@bfrs/agentic-components 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BFRS_AGENTIC_COMPONENTS.md +359 -14
- package/dist/components/data-display/DataTable/DataTable.types.d.ts +7 -0
- package/dist/components/data-display/DataTable/TableColumnVisibility.d.ts +1 -1
- package/dist/components/data-display/DataTable/TablePagination.d.ts +1 -1
- package/dist/components/data-display/DataTable/TableSaveView.d.ts +44 -0
- package/dist/components/data-display/DataTable/index.d.ts +1 -0
- package/dist/components/ui/feedback/Alert/Alert.d.ts +2 -0
- package/dist/custom-elements.d.ts +8 -0
- package/dist/custom-elements.js +5968 -5647
- package/dist/custom-elements.js.map +1 -1
- package/dist/index.js +4052 -3844
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
|
@@ -36,7 +36,30 @@ import "@bfrs/agentic-components/fonts.css";
|
|
|
36
36
|
Import components by name:
|
|
37
37
|
|
|
38
38
|
```tsx
|
|
39
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
BfrsProvider,
|
|
41
|
+
Button,
|
|
42
|
+
FormField,
|
|
43
|
+
Input,
|
|
44
|
+
Slider,
|
|
45
|
+
ColorPicker,
|
|
46
|
+
ColorSwatchGroup,
|
|
47
|
+
OptionCardGroup,
|
|
48
|
+
SelectableChipGroup,
|
|
49
|
+
NumberStepper,
|
|
50
|
+
SuggestInput,
|
|
51
|
+
FileDropzone,
|
|
52
|
+
RevealField,
|
|
53
|
+
RevealAndCopy,
|
|
54
|
+
Modal,
|
|
55
|
+
DataTable,
|
|
56
|
+
TableColumnVisibility,
|
|
57
|
+
TableSaveView,
|
|
58
|
+
TableToolbar,
|
|
59
|
+
DateRangePicker,
|
|
60
|
+
ToastProvider,
|
|
61
|
+
useToast
|
|
62
|
+
} from "@bfrs/agentic-components";
|
|
40
63
|
```
|
|
41
64
|
|
|
42
65
|
React consumers should wrap BFRS surfaces in `BfrsProvider`; the provider owns `--bfrs-*` variables, color scheme, and portal inheritance.
|
|
@@ -119,7 +142,7 @@ Registered tags cover the documented component surface, including
|
|
|
119
142
|
`bfrs-button-group`, `bfrs-toast-provider`, `bfrs-table-toolbar`,
|
|
120
143
|
`bfrs-table-empty-state`, `bfrs-table-error-state`, `bfrs-table-skeleton`,
|
|
121
144
|
`bfrs-table-row-actions`, `bfrs-table-bulk-actions`, and
|
|
122
|
-
`bfrs-table-column-visibility` in addition to the existing component tags.
|
|
145
|
+
`bfrs-table-column-visibility`, and `bfrs-table-save-view` in addition to the existing component tags.
|
|
123
146
|
Existing form and pattern tags include `bfrs-date-range-picker`,
|
|
124
147
|
`bfrs-multi-select`, `bfrs-step-progress-card`, `bfrs-data-table`,
|
|
125
148
|
`bfrs-modal`, `bfrs-tabs`, and the rest of the documented `bfrs-*` surface.
|
|
@@ -164,7 +187,7 @@ Use attributes for simple props: `variant`, `size`, `tone`, `label`, `loading`,
|
|
|
164
187
|
|
|
165
188
|
Common component events: `(value-change)`, `(checked-change)`, `(open-change)`, `(reveal-change)`, `(copy)`, `(copy-error)`, `(close)`, `(confirm)`, `(cancel)`, `(cell-action)`, `(cell-event)`, `(row-click)`, `(sort-change)`, `(page-change)`, `(page-size-change)`, `(action-select)`, `(dropdown-select)`, `(date-range-change)`, `(search-change)`, `(open-filters)`, `(apply)`, `(reset)`, and `(submit)`. Payloads are available on `$event.detail`.
|
|
166
189
|
|
|
167
|
-
For validated forms, keep client validation, API validation, and submit side effects in the consuming app. In React, pass field errors through `
|
|
190
|
+
For validated forms, keep client validation, API validation, and submit side effects in the consuming app. In React, wrap controls in `FormField`, pass field errors through `errorText`, and set the control's `error` prop when supported. In Angular, wrap controls that do not render their own label in `bfrs-form-field`; pass `error-text` and `helper-text` there, listen to the control's `(value-change)`, and manage success/failure notifications with `bfrs-toast-manager`.
|
|
168
191
|
|
|
169
192
|
```html
|
|
170
193
|
<bfrs-select
|
|
@@ -398,7 +421,7 @@ Square button for icon-only actions. Always provide `aria-label`.
|
|
|
398
421
|
|
|
399
422
|
### Forms
|
|
400
423
|
|
|
401
|
-
> **Rule:** Always wrap form controls in `FormField` — it handles label, helper text, error text, and aria wiring automatically.
|
|
424
|
+
> **Rule:** Always wrap form controls in `FormField` — it handles label, helper text, error text, consistent spacing, and aria wiring automatically.
|
|
402
425
|
|
|
403
426
|
---
|
|
404
427
|
|
|
@@ -406,6 +429,8 @@ Square button for icon-only actions. Always provide `aria-label`.
|
|
|
406
429
|
|
|
407
430
|
Wraps any form control with label, helper, and error text. Connects them via `aria-describedby`.
|
|
408
431
|
|
|
432
|
+
The label always renders on its own block row with a `6px` vertical gap before the control. This applies consistently to full-width controls such as `Input` and inline controls such as `NumberStepper`; do not add manual margins between the label and control.
|
|
433
|
+
|
|
409
434
|
```tsx
|
|
410
435
|
<FormField
|
|
411
436
|
label="Email address"
|
|
@@ -415,6 +440,28 @@ Wraps any form control with label, helper, and error text. Connects them via `ar
|
|
|
415
440
|
>
|
|
416
441
|
<Input type="email" value={email} onChange={…} />
|
|
417
442
|
</FormField>
|
|
443
|
+
|
|
444
|
+
<FormField label="Quantity">
|
|
445
|
+
<NumberStepper
|
|
446
|
+
value={quantity}
|
|
447
|
+
min={1}
|
|
448
|
+
max={10}
|
|
449
|
+
onValueChange={setQuantity}
|
|
450
|
+
/>
|
|
451
|
+
</FormField>
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
Angular / Custom Elements:
|
|
455
|
+
|
|
456
|
+
```html
|
|
457
|
+
<bfrs-form-field label="Quantity" helper-text="Choose between 1 and 10 items.">
|
|
458
|
+
<bfrs-number-stepper
|
|
459
|
+
[value]="quantity"
|
|
460
|
+
min="1"
|
|
461
|
+
max="10"
|
|
462
|
+
(value-change)="quantity = $event.detail.value">
|
|
463
|
+
</bfrs-number-stepper>
|
|
464
|
+
</bfrs-form-field>
|
|
418
465
|
```
|
|
419
466
|
|
|
420
467
|
| Prop | Type | Default |
|
|
@@ -548,6 +595,7 @@ const [range, setRange] = useState<DateRangeValue>({
|
|
|
548
595
|
| `maxRangeDays` | `number` | — |
|
|
549
596
|
| `months` | `1 \| 2` | `2` |
|
|
550
597
|
| `open` / `onOpenChange` | controlled popover state | — |
|
|
598
|
+
| `defaultOpen` | `boolean` | `false` |
|
|
551
599
|
|
|
552
600
|
Keep API date formatting, route updates, and business limits in the consuming app.
|
|
553
601
|
|
|
@@ -580,6 +628,7 @@ Combobox with search. Use when options list is long (10+).
|
|
|
580
628
|
| `disabled` | `boolean` | `false` |
|
|
581
629
|
| `error` | `boolean` | `false` |
|
|
582
630
|
| `clearable` | `boolean` | `true` |
|
|
631
|
+
| `size` | `"sm" \| "md" \| "lg"` | `"md"` |
|
|
583
632
|
|
|
584
633
|
---
|
|
585
634
|
|
|
@@ -621,6 +670,7 @@ Angular custom element:
|
|
|
621
670
|
| `error` | `boolean` | `false` |
|
|
622
671
|
| `clearable` | `boolean` | `true` |
|
|
623
672
|
| `maxVisibleValues` | `number` | `2` |
|
|
673
|
+
| `size` | `"sm" \| "md" \| "lg"` | `"md"` |
|
|
624
674
|
|
|
625
675
|
---
|
|
626
676
|
|
|
@@ -657,25 +707,73 @@ Angular: `<bfrs-selectable-chip-group multiple [props]="{ options, value }" (val
|
|
|
657
707
|
|
|
658
708
|
#### `NumberStepper`
|
|
659
709
|
|
|
660
|
-
Quantity input rendered as decrement, value, increment controls.
|
|
710
|
+
Quantity input rendered as decrement, value, increment controls. It is an inline-width control, so use `FormField` for its visible label and consistent label-to-control spacing.
|
|
661
711
|
|
|
662
712
|
```tsx
|
|
663
|
-
<
|
|
713
|
+
<FormField label="Quantity">
|
|
714
|
+
<NumberStepper
|
|
715
|
+
value={quantity}
|
|
716
|
+
min={1}
|
|
717
|
+
max={10}
|
|
718
|
+
step={1}
|
|
719
|
+
onValueChange={setQuantity}
|
|
720
|
+
/>
|
|
721
|
+
</FormField>
|
|
664
722
|
```
|
|
665
723
|
|
|
666
|
-
|
|
724
|
+
| Prop | Type | Default |
|
|
725
|
+
|------|------|---------|
|
|
726
|
+
| `value` | `number` | — |
|
|
727
|
+
| `defaultValue` | `number` | `0` |
|
|
728
|
+
| `onValueChange` | `(value: number) => void` | — |
|
|
729
|
+
| `min` | `number` | — |
|
|
730
|
+
| `max` | `number` | — |
|
|
731
|
+
| `step` | `number` | `1` |
|
|
732
|
+
| `size` | `"sm" \| "md"` | `"md"` |
|
|
733
|
+
| `error` | `boolean` | `false` |
|
|
734
|
+
| `disabled` | `boolean` | `false` |
|
|
735
|
+
|
|
736
|
+
Angular:
|
|
737
|
+
|
|
738
|
+
```html
|
|
739
|
+
<bfrs-form-field label="Quantity">
|
|
740
|
+
<bfrs-number-stepper
|
|
741
|
+
[value]="quantity"
|
|
742
|
+
min="1"
|
|
743
|
+
max="10"
|
|
744
|
+
step="1"
|
|
745
|
+
(value-change)="quantity = $event.detail.value">
|
|
746
|
+
</bfrs-number-stepper>
|
|
747
|
+
</bfrs-form-field>
|
|
748
|
+
```
|
|
667
749
|
|
|
668
750
|
---
|
|
669
751
|
|
|
670
752
|
#### `SuggestInput`
|
|
671
753
|
|
|
672
|
-
Free-text input with async-friendly suggestions dropdown. Use when the user may type arbitrary text; use `SearchableSelect` when the final value must be from a bounded option list.
|
|
754
|
+
Free-text input with async-friendly suggestions dropdown. Use when the user may type arbitrary text; use `SearchableSelect` when the final value must be from a bounded option list. Wrap it in `FormField` when it needs a visible label, helper text, or validation message.
|
|
673
755
|
|
|
674
756
|
```tsx
|
|
675
|
-
<
|
|
757
|
+
<FormField label="City">
|
|
758
|
+
<SuggestInput
|
|
759
|
+
value={city}
|
|
760
|
+
suggestions={citySuggestions}
|
|
761
|
+
onValueChange={setCity}
|
|
762
|
+
onSuggestionSelect={setSelectedCity}
|
|
763
|
+
/>
|
|
764
|
+
</FormField>
|
|
676
765
|
```
|
|
677
766
|
|
|
678
|
-
Angular:
|
|
767
|
+
Angular:
|
|
768
|
+
|
|
769
|
+
```html
|
|
770
|
+
<bfrs-form-field label="City">
|
|
771
|
+
<bfrs-suggest-input
|
|
772
|
+
[props]="{ suggestions: citySuggestions, value: city }"
|
|
773
|
+
(value-change)="city = $event.detail.value">
|
|
774
|
+
</bfrs-suggest-input>
|
|
775
|
+
</bfrs-form-field>
|
|
776
|
+
```
|
|
679
777
|
|
|
680
778
|
---
|
|
681
779
|
|
|
@@ -703,6 +801,82 @@ Angular: `<bfrs-reveal-field label="Phone" value="9876543210"></bfrs-reveal-fiel
|
|
|
703
801
|
|
|
704
802
|
---
|
|
705
803
|
|
|
804
|
+
#### Additional form controls composition
|
|
805
|
+
|
|
806
|
+
Use `FormField` around controls that do not own a label. This keeps Quantity and City aligned in the same grid and preserves the standard `6px` label-to-control gap without demo-specific margins.
|
|
807
|
+
|
|
808
|
+
```tsx
|
|
809
|
+
<Stack gap={5}>
|
|
810
|
+
<OptionCardGroup
|
|
811
|
+
value={fulfillmentMode}
|
|
812
|
+
onValueChange={setFulfillmentMode}
|
|
813
|
+
options={fulfillmentOptions}
|
|
814
|
+
/>
|
|
815
|
+
|
|
816
|
+
<SelectableChipGroup
|
|
817
|
+
multiple
|
|
818
|
+
value={channels}
|
|
819
|
+
options={channelOptions}
|
|
820
|
+
addAction={{ label: "Add" }}
|
|
821
|
+
onValueChange={setChannels}
|
|
822
|
+
/>
|
|
823
|
+
|
|
824
|
+
<Grid columns={2} gap={4}>
|
|
825
|
+
<FormField label="Quantity">
|
|
826
|
+
<NumberStepper
|
|
827
|
+
value={quantity}
|
|
828
|
+
min={1}
|
|
829
|
+
max={10}
|
|
830
|
+
onValueChange={setQuantity}
|
|
831
|
+
/>
|
|
832
|
+
</FormField>
|
|
833
|
+
|
|
834
|
+
<FormField label="City">
|
|
835
|
+
<SuggestInput
|
|
836
|
+
value={city}
|
|
837
|
+
suggestions={citySuggestions}
|
|
838
|
+
onValueChange={setCity}
|
|
839
|
+
/>
|
|
840
|
+
</FormField>
|
|
841
|
+
</Grid>
|
|
842
|
+
|
|
843
|
+
<FileDropzone
|
|
844
|
+
title="Upload invoice"
|
|
845
|
+
onFilesChange={setFiles}
|
|
846
|
+
/>
|
|
847
|
+
|
|
848
|
+
<RevealField
|
|
849
|
+
label="Masked account field"
|
|
850
|
+
value="9876543210"
|
|
851
|
+
allowCopy
|
|
852
|
+
/>
|
|
853
|
+
</Stack>
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
Angular / Custom Elements:
|
|
857
|
+
|
|
858
|
+
```html
|
|
859
|
+
<bfrs-grid columns="2" gap="4">
|
|
860
|
+
<bfrs-form-field label="Quantity">
|
|
861
|
+
<bfrs-number-stepper
|
|
862
|
+
[value]="quantity"
|
|
863
|
+
min="1"
|
|
864
|
+
max="10"
|
|
865
|
+
(value-change)="quantity = $event.detail.value">
|
|
866
|
+
</bfrs-number-stepper>
|
|
867
|
+
</bfrs-form-field>
|
|
868
|
+
|
|
869
|
+
<bfrs-form-field label="City">
|
|
870
|
+
<bfrs-suggest-input
|
|
871
|
+
[props]="{ suggestions: citySuggestions, value: city }"
|
|
872
|
+
(value-change)="city = $event.detail.value">
|
|
873
|
+
</bfrs-suggest-input>
|
|
874
|
+
</bfrs-form-field>
|
|
875
|
+
</bfrs-grid>
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
---
|
|
879
|
+
|
|
706
880
|
#### `Slider`
|
|
707
881
|
|
|
708
882
|
Controlled numeric range control. Use instead of raw `<input type="range">`.
|
|
@@ -915,6 +1089,12 @@ Small inline status label.
|
|
|
915
1089
|
<Badge tone="warning">Pending</Badge>
|
|
916
1090
|
<Badge tone="danger">Blocked</Badge>
|
|
917
1091
|
<Badge count={3} aria-label="3 active filters" />
|
|
1092
|
+
|
|
1093
|
+
{/* Sizes: xs | sm (default) | md | lg */}
|
|
1094
|
+
<Badge size="xs" tone="success">xs</Badge>
|
|
1095
|
+
<Badge size="sm" tone="success">sm</Badge>
|
|
1096
|
+
<Badge size="md" tone="success">md</Badge>
|
|
1097
|
+
<Badge size="lg" tone="success">lg</Badge>
|
|
918
1098
|
```
|
|
919
1099
|
|
|
920
1100
|
| Prop | Type | Default |
|
|
@@ -941,6 +1121,12 @@ Removable tag. Use in filter bars and multi-select UIs.
|
|
|
941
1121
|
>
|
|
942
1122
|
Status: Active
|
|
943
1123
|
</Chip>
|
|
1124
|
+
|
|
1125
|
+
{/* Sizes: xs | sm (default) | md | lg */}
|
|
1126
|
+
<Chip size="xs" tone="primary">xs</Chip>
|
|
1127
|
+
<Chip size="sm" tone="primary">sm</Chip>
|
|
1128
|
+
<Chip size="md" tone="primary">md</Chip>
|
|
1129
|
+
<Chip size="lg" tone="primary">lg</Chip>
|
|
944
1130
|
```
|
|
945
1131
|
|
|
946
1132
|
| Prop | Type | Default |
|
|
@@ -949,10 +1135,13 @@ Removable tag. Use in filter bars and multi-select UIs.
|
|
|
949
1135
|
| `tone` | `"neutral" \| "primary" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` |
|
|
950
1136
|
| `size` | `"xs" \| "sm" \| "md" \| "lg"` | `"sm"` |
|
|
951
1137
|
| `leftIcon` | `ReactNode` | — |
|
|
1138
|
+
| `rightIcon` | `ReactNode` | — |
|
|
952
1139
|
| `removable` | `boolean` | `false` |
|
|
953
1140
|
| `onRemove` | `() => void` | — |
|
|
954
1141
|
| `removeLabel` | `string` | `"Remove"` |
|
|
955
1142
|
|
|
1143
|
+
Angular: use `left-icon="package"` / `right-icon="arrow-right"` for named Phosphor icons, or use named slots `<span slot="left-icon">…</span>`.
|
|
1144
|
+
|
|
956
1145
|
---
|
|
957
1146
|
|
|
958
1147
|
#### `Alert`
|
|
@@ -967,11 +1156,18 @@ Contextual message banner. Auto-selects an icon based on tone.
|
|
|
967
1156
|
>
|
|
968
1157
|
Upgrade to keep access to all features.
|
|
969
1158
|
</Alert>
|
|
1159
|
+
|
|
1160
|
+
{/* Sizes: xs | sm | md (default) | lg */}
|
|
1161
|
+
<Alert size="xs" tone="info" title="XSmall">Ultra-compact inline alert.</Alert>
|
|
1162
|
+
<Alert size="sm" tone="info" title="Small">Compact alert for dense layouts.</Alert>
|
|
1163
|
+
<Alert size="md" tone="info" title="Medium">Default alert size.</Alert>
|
|
1164
|
+
<Alert size="lg" tone="info" title="Large">Spacious alert for prominent messages.</Alert>
|
|
970
1165
|
```
|
|
971
1166
|
|
|
972
1167
|
| Prop | Type | Default |
|
|
973
1168
|
|------|------|---------|
|
|
974
1169
|
| `tone` | `"info" \| "success" \| "warning" \| "danger"` | `"info"` |
|
|
1170
|
+
| `size` | `"xs" \| "sm" \| "md" \| "lg"` | `"md"` |
|
|
975
1171
|
| `title` | `ReactNode` | — |
|
|
976
1172
|
| `action` | `ReactNode` | — |
|
|
977
1173
|
| `icon` | `ReactNode` | auto (from tone) |
|
|
@@ -1130,6 +1326,11 @@ Centered modal. Use for confirmations, forms, and focused tasks.
|
|
|
1130
1326
|
| `size` | `"sm" \| "md" \| "lg" \| "xl" \| "full"` | `"md"` |
|
|
1131
1327
|
| `open` | `boolean` | — |
|
|
1132
1328
|
| `onOpenChange` | `(open: boolean) => void` | — |
|
|
1329
|
+
| `contentClassName` | `string` | — |
|
|
1330
|
+
| `headerClassName` | `string` | — |
|
|
1331
|
+
| `footerClassName` | `string` | — |
|
|
1332
|
+
|
|
1333
|
+
Angular: `content-class-name`, `header-class-name`, `footer-class-name` attributes.
|
|
1133
1334
|
|
|
1134
1335
|
`Dialog` is a deprecated compatibility alias. Use `Modal` in new code.
|
|
1135
1336
|
|
|
@@ -1160,6 +1361,11 @@ Slide-out panel. Use for detail views, settings, and secondary flows.
|
|
|
1160
1361
|
| `description` | `ReactNode` | — |
|
|
1161
1362
|
| `open` | `boolean` | — |
|
|
1162
1363
|
| `onOpenChange` | `(open: boolean) => void` | — |
|
|
1364
|
+
| `contentClassName` | `string` | — |
|
|
1365
|
+
| `headerClassName` | `string` | — |
|
|
1366
|
+
| `footerClassName` | `string` | — |
|
|
1367
|
+
|
|
1368
|
+
Angular: `content-class-name`, `header-class-name`, `footer-class-name` attributes.
|
|
1163
1369
|
|
|
1164
1370
|
---
|
|
1165
1371
|
|
|
@@ -1204,6 +1410,7 @@ Floating label on hover. Provide `content` as the tooltip text.
|
|
|
1204
1410
|
| `children` | `ReactNode` | **required** |
|
|
1205
1411
|
| `side` | `"top" \| "right" \| "bottom" \| "left"` | `"top"` |
|
|
1206
1412
|
| `delayDuration` | `number` | `350` |
|
|
1413
|
+
| `disabled` | `boolean` | `false` |
|
|
1207
1414
|
|
|
1208
1415
|
---
|
|
1209
1416
|
|
|
@@ -1228,6 +1435,43 @@ Floating content panel. Use for filters, pickers, and inline forms.
|
|
|
1228
1435
|
|
|
1229
1436
|
---
|
|
1230
1437
|
|
|
1438
|
+
#### `FilterDrawer`
|
|
1439
|
+
|
|
1440
|
+
Slide-out drawer pre-wired for filter forms. Manages its own Apply / Reset footer; the consumer owns filter state and the apply logic.
|
|
1441
|
+
|
|
1442
|
+
```tsx
|
|
1443
|
+
<FilterDrawer
|
|
1444
|
+
title="Filter shipments"
|
|
1445
|
+
open={filtersOpen}
|
|
1446
|
+
onOpenChange={setFiltersOpen}
|
|
1447
|
+
onApply={handleApply}
|
|
1448
|
+
onReset={handleReset}
|
|
1449
|
+
activeFiltersCount={activeCount}
|
|
1450
|
+
footerActions={<Button variant="ghost">Save as preset</Button>}
|
|
1451
|
+
>
|
|
1452
|
+
<StatusFilter />
|
|
1453
|
+
<DateFilter />
|
|
1454
|
+
</FilterDrawer>
|
|
1455
|
+
```
|
|
1456
|
+
|
|
1457
|
+
| Prop | Type | Default |
|
|
1458
|
+
|------|------|---------|
|
|
1459
|
+
| `open` | `boolean` | — |
|
|
1460
|
+
| `onOpenChange` | `(open: boolean) => void` | — |
|
|
1461
|
+
| `onApply` | `() => void` | — |
|
|
1462
|
+
| `onReset` | `() => void` | — |
|
|
1463
|
+
| `title` | `ReactNode` | `"Filters"` |
|
|
1464
|
+
| `description` | `ReactNode` | — |
|
|
1465
|
+
| `applyLabel` | `ReactNode` | `"Apply filters"` |
|
|
1466
|
+
| `resetLabel` | `ReactNode` | `"Reset all"` |
|
|
1467
|
+
| `activeFiltersCount` | `number` | `0` |
|
|
1468
|
+
| `applying` | `boolean` | `false` |
|
|
1469
|
+
| `footerActions` | `ReactNode` | — |
|
|
1470
|
+
|
|
1471
|
+
Angular: `(apply)`, `(reset)`, `(close)` events; `<span slot="footer-actions">…</span>` for extra footer content.
|
|
1472
|
+
|
|
1473
|
+
---
|
|
1474
|
+
|
|
1231
1475
|
### Data Display
|
|
1232
1476
|
|
|
1233
1477
|
---
|
|
@@ -1259,12 +1503,13 @@ User avatar with image, initials fallback, and online status.
|
|
|
1259
1503
|
|
|
1260
1504
|
#### `TablePagination`
|
|
1261
1505
|
|
|
1262
|
-
Table page navigation. Handles ellipsis, edge pages,
|
|
1506
|
+
Table page navigation. Handles ellipsis, edge pages, optional page-size controls, and two navigation variants: `indexed` (Prev, page indexes like `1 2 3 ... 10`, Next) and `simple` (Prev / Next only).
|
|
1263
1507
|
|
|
1264
1508
|
```tsx
|
|
1265
1509
|
<TablePagination
|
|
1266
1510
|
page={currentPage}
|
|
1267
1511
|
totalPages={totalPages}
|
|
1512
|
+
variant="indexed"
|
|
1268
1513
|
pageSize={pageSize}
|
|
1269
1514
|
onPageChange={setCurrentPage}
|
|
1270
1515
|
onPageSizeChange={setPageSize}
|
|
@@ -1276,8 +1521,14 @@ Table page navigation. Handles ellipsis, edge pages, and optional page-size cont
|
|
|
1276
1521
|
| `page` | `number` | **required** |
|
|
1277
1522
|
| `totalPages` | `number` | **required** |
|
|
1278
1523
|
| `onPageChange` | `(page: number) => void` | **required** |
|
|
1524
|
+
| `variant` | `"indexed" \| "simple"` | `"indexed"` |
|
|
1279
1525
|
| `pageSize` | `number` | — |
|
|
1280
1526
|
| `onPageSizeChange` | `(pageSize: number) => void` | — |
|
|
1527
|
+
| `itemsPerPageLabel` | `string` | `"Items per page:"` |
|
|
1528
|
+
|
|
1529
|
+
Angular: `items-per-page-label` attribute.
|
|
1530
|
+
|
|
1531
|
+
> Pass `pagination={{ page, totalPages, variant: "simple", onPageChange }}` to `DataTable` when the built-in footer should show only Prev and Next.
|
|
1281
1532
|
|
|
1282
1533
|
---
|
|
1283
1534
|
|
|
@@ -1320,6 +1571,11 @@ Generic data table with sorting, loading skeleton, row actions, selection, pagin
|
|
|
1320
1571
|
| `density` | `"compact" \| "default" \| "comfortable"` | `"default"` |
|
|
1321
1572
|
| `emptyTitle` | `ReactNode` | `"No records found"` |
|
|
1322
1573
|
| `emptyDescription` | `ReactNode` | — |
|
|
1574
|
+
| `defaultSorting` | `{ columnId: string; direction: "asc" \| "desc" } \| null` | `null` |
|
|
1575
|
+
| `maxHeight` | `number \| string` | — |
|
|
1576
|
+
| `stickyHeader` | `boolean` | `true` |
|
|
1577
|
+
|
|
1578
|
+
Angular: pass `sorting` as JSON attribute `[sorting]='{"columnId":"name","direction":"asc"}'`; `default-sorting`, `max-height`, `sticky-header` attributes are fully supported. `show-all-label` and `(show-all)` event are supported on `bfrs-table-column-visibility`.
|
|
1323
1579
|
|
|
1324
1580
|
`DataTableColumn<T>`:
|
|
1325
1581
|
```ts
|
|
@@ -1337,6 +1593,33 @@ Generic data table with sorting, loading skeleton, row actions, selection, pagin
|
|
|
1337
1593
|
|
|
1338
1594
|
When `loading` is true, `DataTable` renders built-in table-row skeleton placeholders rather than a spinner. The consumer app only owns the loading boolean.
|
|
1339
1595
|
|
|
1596
|
+
Use `TableSaveView` with `TableColumnVisibility` when the user changes columns or filters and needs to save the draft as a named view. It opens the "Save this view" modal, collects the view name, summarizes settings like hidden columns, and calls `onSave({ name, visibleColumnIds, hiddenColumnCount, filtersCount, appliedSettingLabels })`; persistence remains app-owned.
|
|
1597
|
+
|
|
1598
|
+
```tsx
|
|
1599
|
+
<TableToolbar
|
|
1600
|
+
title="Orders"
|
|
1601
|
+
actions={
|
|
1602
|
+
<div className="bfrs-flex bfrs-items-center bfrs-gap-2">
|
|
1603
|
+
{dirty && (
|
|
1604
|
+
<TableSaveView
|
|
1605
|
+
columns={visibilityColumns}
|
|
1606
|
+
visibleColumnIds={visibleColumnIds}
|
|
1607
|
+
onSave={({ visibleColumnIds: nextSavedIds }) => setSavedColumnIds(nextSavedIds)}
|
|
1608
|
+
/>
|
|
1609
|
+
)}
|
|
1610
|
+
<TableColumnVisibility
|
|
1611
|
+
columns={visibilityColumns}
|
|
1612
|
+
visibleColumnIds={visibleColumnIds}
|
|
1613
|
+
onVisibleColumnIdsChange={setVisibleColumnIds}
|
|
1614
|
+
onReset={() => setVisibleColumnIds(savedColumnIds)}
|
|
1615
|
+
/>
|
|
1616
|
+
</div>
|
|
1617
|
+
}
|
|
1618
|
+
/>
|
|
1619
|
+
```
|
|
1620
|
+
|
|
1621
|
+
Angular custom-element consumers can use `<bfrs-table-save-view>` and listen for `(save-view)` with the same payload.
|
|
1622
|
+
|
|
1340
1623
|
Custom-element DataTable action cells must be declarative because Angular/HTML cannot pass React `cell` functions through JSON. Use `cellType: "button"` for one inline button, `cellType: "buttons"` for multiple inline buttons, or `cellType: "actions"` for an action menu. Action clicks emit `cell-action` with `{ actionId, columnId, row, rowId, rowIndex }` and do not trigger `row-click`.
|
|
1341
1624
|
|
|
1342
1625
|
```html
|
|
@@ -1429,6 +1712,68 @@ not rendered. Listed custom-element events are re-emitted as `cell-event` with
|
|
|
1429
1712
|
|
|
1430
1713
|
---
|
|
1431
1714
|
|
|
1715
|
+
#### `TableColumnVisibility`
|
|
1716
|
+
|
|
1717
|
+
Column show/hide control used inside `TableToolbar`. Emits `visible-column-ids-change` and exposes a "Show all" reset button.
|
|
1718
|
+
|
|
1719
|
+
```tsx
|
|
1720
|
+
<TableColumnVisibility
|
|
1721
|
+
columns={visibilityColumns}
|
|
1722
|
+
visibleColumnIds={visibleColumnIds}
|
|
1723
|
+
onVisibleColumnIdsChange={setVisibleColumnIds}
|
|
1724
|
+
onReset={() => setVisibleColumnIds(savedColumnIds)}
|
|
1725
|
+
showAllLabel="Show all columns"
|
|
1726
|
+
/>
|
|
1727
|
+
```
|
|
1728
|
+
|
|
1729
|
+
| Prop | Type | Default |
|
|
1730
|
+
|------|------|---------|
|
|
1731
|
+
| `columns` | `{ id: string; label: string }[]` | **required** |
|
|
1732
|
+
| `visibleColumnIds` | `string[]` | — |
|
|
1733
|
+
| `onVisibleColumnIdsChange` | `(ids: string[]) => void` | — |
|
|
1734
|
+
| `onReset` | `() => void` | — |
|
|
1735
|
+
| `onShowAll` | `() => void` | — |
|
|
1736
|
+
| `showAllLabel` | `string` | `"Show all"` |
|
|
1737
|
+
| `resetLabel` | `string` | `"Reset"` |
|
|
1738
|
+
| `label` | `ReactNode` | `"Columns"` |
|
|
1739
|
+
|
|
1740
|
+
Angular: `show-all-label` attribute; `(show-all)` event.
|
|
1741
|
+
|
|
1742
|
+
---
|
|
1743
|
+
|
|
1744
|
+
#### `MetricCard`
|
|
1745
|
+
|
|
1746
|
+
KPI display card with trend indicator, optional subtitle, description, icon slot, and action slot.
|
|
1747
|
+
|
|
1748
|
+
```tsx
|
|
1749
|
+
<MetricCard
|
|
1750
|
+
title="Total shipments"
|
|
1751
|
+
value="12,480"
|
|
1752
|
+
trendValue="+8.2%"
|
|
1753
|
+
trendDirection="up"
|
|
1754
|
+
subtitle="vs last month"
|
|
1755
|
+
icon={<Icon icon={Package} />}
|
|
1756
|
+
action={<Button size="sm" variant="ghost">View all</Button>}
|
|
1757
|
+
/>
|
|
1758
|
+
```
|
|
1759
|
+
|
|
1760
|
+
| Prop | Type | Default |
|
|
1761
|
+
|------|------|---------|
|
|
1762
|
+
| `title` | `ReactNode` | `"Metric"` |
|
|
1763
|
+
| `value` | `ReactNode` | — |
|
|
1764
|
+
| `subtitle` | `ReactNode` | — |
|
|
1765
|
+
| `description` | `ReactNode` | — |
|
|
1766
|
+
| `trendValue` | `ReactNode` | — |
|
|
1767
|
+
| `trendDirection` | `"up" \| "down" \| "neutral"` | `"neutral"` |
|
|
1768
|
+
| `icon` | `ReactNode` | — |
|
|
1769
|
+
| `action` | `ReactNode` | — |
|
|
1770
|
+
| `loading` | `boolean` | `false` |
|
|
1771
|
+
| `compact` | `boolean` | `false` |
|
|
1772
|
+
|
|
1773
|
+
Angular: `icon="package"` for a named Phosphor icon; use `<span slot="action">…</span>` for the action slot.
|
|
1774
|
+
|
|
1775
|
+
---
|
|
1776
|
+
|
|
1432
1777
|
### Navigation
|
|
1433
1778
|
|
|
1434
1779
|
---
|
|
@@ -1742,7 +2087,7 @@ Grouped expandable sections. Use `type="single"` (default) to keep one panel ope
|
|
|
1742
2087
|
|
|
1743
2088
|
For `type="single"`, `value`/`defaultValue`/`onValueChange` use a string; for `type="multiple"` they use a string array.
|
|
1744
2089
|
|
|
1745
|
-
Angular: `<bfrs-accordion type="single" [props]="{ items: sections }" (value-change)="openSection = $event.detail.value"></bfrs-accordion>`. Pass each item's `content` as a string in custom-element usage.
|
|
2090
|
+
Angular: `<bfrs-accordion type="single" value="pickup" [props]="{ items: sections }" (value-change)="openSection = $event.detail.value"></bfrs-accordion>`. The `value` attribute supports controlled mode; use a JSON array string for `type="multiple"`. Pass each item's `content` as a string in custom-element usage.
|
|
1746
2091
|
|
|
1747
2092
|
---
|
|
1748
2093
|
|
|
@@ -1954,7 +2299,7 @@ Step-by-step progress indicator. Calculates `done` / `active` / `pending` state
|
|
|
1954
2299
|
loading={isLoading}
|
|
1955
2300
|
sorting={sorting}
|
|
1956
2301
|
onSortingChange={setSorting}
|
|
1957
|
-
pagination={{ page, totalPages, onPageChange: setPage }}
|
|
2302
|
+
pagination={{ page, totalPages, variant: "indexed", onPageChange: setPage }}
|
|
1958
2303
|
/>
|
|
1959
2304
|
</Card>
|
|
1960
2305
|
</Container>
|
|
@@ -2002,6 +2347,6 @@ Step-by-step progress indicator. Calculates `done` / `active` / `pending` state
|
|
|
2002
2347
|
|
|
2003
2348
|
- Do not use raw Tailwind classes for spacing, color, or typography — use `Stack`, `Text`, and component props instead
|
|
2004
2349
|
- Do not build custom modals, drawers, or dropdowns — use `Modal`, `ConfirmDialog`, `Drawer`, and `ActionMenu`
|
|
2005
|
-
- Do not render form labels manually — use `FormField
|
|
2350
|
+
- Do not render form labels or add label margins manually — use `FormField`, which keeps labels on their own row, applies the standard gap, and wires aria attributes automatically
|
|
2006
2351
|
- Do not use `<h1>`–`<h6>` or `<p>` directly — use `<Text variant="h1">` etc.
|
|
2007
2352
|
- Do not add `loading` spinners manually — all interactive components accept a `loading` prop
|
|
@@ -3,6 +3,7 @@ import { ActionMenuItem } from '../../navigation/ActionMenu';
|
|
|
3
3
|
export type SortDirection = "asc" | "desc";
|
|
4
4
|
export type TableDensity = "compact" | "default" | "comfortable";
|
|
5
5
|
export type TableAlign = "left" | "center" | "right";
|
|
6
|
+
export type TablePaginationVariant = "indexed" | "simple";
|
|
6
7
|
export type DataTableSorting = {
|
|
7
8
|
columnId: string;
|
|
8
9
|
direction: SortDirection;
|
|
@@ -45,6 +46,8 @@ export type DataTableLeadingColumn<Row> = {
|
|
|
45
46
|
export type DataTablePagination = {
|
|
46
47
|
page: number;
|
|
47
48
|
totalPages: number;
|
|
49
|
+
/** "indexed" shows Prev, page numbers, and Next. "simple" shows only Prev and Next. */
|
|
50
|
+
variant?: TablePaginationVariant;
|
|
48
51
|
pageSize?: number;
|
|
49
52
|
totalItems?: number;
|
|
50
53
|
pageSizeOptions?: number[];
|
|
@@ -169,5 +172,9 @@ export type TableColumnVisibilityProps = {
|
|
|
169
172
|
label?: ReactNode;
|
|
170
173
|
resetLabel?: ReactNode;
|
|
171
174
|
onReset?: () => void;
|
|
175
|
+
/** Label for the "Show all" footer button. Defaults to "Show all". */
|
|
176
|
+
showAllLabel?: ReactNode;
|
|
177
|
+
/** Override the "Show all" action. Defaults to making every column visible. */
|
|
178
|
+
onShowAll?: () => void;
|
|
172
179
|
className?: string;
|
|
173
180
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { TableColumnVisibilityProps } from './DataTable.types';
|
|
2
|
-
export declare function TableColumnVisibility({ columns, visibleColumnIds, onVisibleColumnIdsChange, label, resetLabel, onReset, className }: TableColumnVisibilityProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function TableColumnVisibility({ columns, visibleColumnIds, onVisibleColumnIdsChange, label, resetLabel, onReset, showAllLabel, onShowAll, className }: TableColumnVisibilityProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { TablePaginationProps } from './DataTable.types';
|
|
2
|
-
export declare function TablePagination({ page, totalPages, pageSize, totalItems, pageSizeOptions, onPageChange, onPageSizeChange, itemLabel, itemsPerPageLabel, className, pageSizeControl, showPageNavigation }: TablePaginationProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function TablePagination({ page, totalPages, variant, pageSize, totalItems, pageSizeOptions, onPageChange, onPageSizeChange, itemLabel, itemsPerPageLabel, className, pageSizeControl, showPageNavigation }: TablePaginationProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { TableColumnVisibilityColumn } from './DataTable.types';
|
|
3
|
+
export type TableSaveViewPayload = {
|
|
4
|
+
name: string;
|
|
5
|
+
visibleColumnIds: string[];
|
|
6
|
+
hiddenColumnCount: number;
|
|
7
|
+
filtersCount: number;
|
|
8
|
+
appliedSettingLabels: string[];
|
|
9
|
+
};
|
|
10
|
+
export type TableSaveViewProps = {
|
|
11
|
+
open?: boolean;
|
|
12
|
+
defaultOpen?: boolean;
|
|
13
|
+
onOpenChange?: (open: boolean) => void;
|
|
14
|
+
onClose?: () => void;
|
|
15
|
+
trigger?: ReactNode;
|
|
16
|
+
triggerLabel?: ReactNode;
|
|
17
|
+
title?: ReactNode;
|
|
18
|
+
description?: ReactNode;
|
|
19
|
+
viewName?: string;
|
|
20
|
+
defaultViewName?: string;
|
|
21
|
+
onViewNameChange?: (viewName: string) => void;
|
|
22
|
+
viewNameLabel?: ReactNode;
|
|
23
|
+
viewNamePlaceholder?: string;
|
|
24
|
+
appliedLabel?: ReactNode;
|
|
25
|
+
appliedSettings?: ReactNode;
|
|
26
|
+
appliedSettingLabels?: string[];
|
|
27
|
+
columns?: TableColumnVisibilityColumn[];
|
|
28
|
+
visibleColumnIds?: string[];
|
|
29
|
+
hiddenColumnCount?: number;
|
|
30
|
+
filtersCount?: number;
|
|
31
|
+
cancelLabel?: ReactNode;
|
|
32
|
+
saveLabel?: ReactNode;
|
|
33
|
+
onCancel?: () => void;
|
|
34
|
+
onSave?: (payload: TableSaveViewPayload) => void | Promise<void>;
|
|
35
|
+
loading?: boolean;
|
|
36
|
+
disabled?: boolean;
|
|
37
|
+
closeOnSave?: boolean;
|
|
38
|
+
closeOnOverlayClick?: boolean;
|
|
39
|
+
closeOnEscape?: boolean;
|
|
40
|
+
preventClose?: boolean;
|
|
41
|
+
className?: string;
|
|
42
|
+
triggerClassName?: string;
|
|
43
|
+
};
|
|
44
|
+
export declare function TableSaveView({ open, defaultOpen, onOpenChange, onClose, trigger, triggerLabel, title, description, viewName, defaultViewName, onViewNameChange, viewNameLabel, viewNamePlaceholder, appliedLabel, appliedSettings, appliedSettingLabels, columns, visibleColumnIds, hiddenColumnCount, filtersCount, cancelLabel, saveLabel, onCancel, onSave, loading, disabled, closeOnSave, closeOnOverlayClick, closeOnEscape, preventClose, className, triggerClassName }: TableSaveViewProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,6 +2,7 @@ import { HTMLAttributes, ReactNode } from 'react';
|
|
|
2
2
|
import { VariantProps } from 'class-variance-authority';
|
|
3
3
|
declare const alertVariants: (props?: ({
|
|
4
4
|
tone?: "success" | "warning" | "danger" | "info" | null | undefined;
|
|
5
|
+
size?: "xs" | "sm" | "md" | "lg" | null | undefined;
|
|
5
6
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
6
7
|
export type AlertProps = Omit<HTMLAttributes<HTMLDivElement>, "title"> & VariantProps<typeof alertVariants> & {
|
|
7
8
|
title?: ReactNode;
|
|
@@ -10,6 +11,7 @@ export type AlertProps = Omit<HTMLAttributes<HTMLDivElement>, "title"> & Variant
|
|
|
10
11
|
};
|
|
11
12
|
export declare const Alert: import('react').ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "title"> & VariantProps<(props?: ({
|
|
12
13
|
tone?: "success" | "warning" | "danger" | "info" | null | undefined;
|
|
14
|
+
size?: "xs" | "sm" | "md" | "lg" | null | undefined;
|
|
13
15
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string> & {
|
|
14
16
|
title?: ReactNode;
|
|
15
17
|
action?: ReactNode;
|