@dashforge/tw 1.0.0 → 1.1.0
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/CHANGELOG.md +221 -0
- package/README.md +74 -15
- package/dashforge-tw-1.0.0.tgz +0 -0
- package/dist/index.d.ts +1 -146
- package/dist/index.esm.js +3127 -748
- package/dist/src/components/Alert/Alert.d.ts +65 -0
- package/dist/src/components/Alert/Alert.d.ts.map +1 -0
- package/dist/src/components/Alert/alert.types.d.ts +130 -0
- package/dist/src/components/Alert/alert.types.d.ts.map +1 -0
- package/dist/src/components/Alert/alert.variants.d.ts +85 -0
- package/dist/src/components/Alert/alert.variants.d.ts.map +1 -0
- package/dist/src/components/Avatar/Avatar.d.ts +48 -0
- package/dist/src/components/Avatar/Avatar.d.ts.map +1 -0
- package/dist/src/components/Avatar/avatar.types.d.ts +162 -0
- package/dist/src/components/Avatar/avatar.types.d.ts.map +1 -0
- package/dist/src/components/Avatar/avatar.variants.d.ts +208 -0
- package/dist/src/components/Avatar/avatar.variants.d.ts.map +1 -0
- package/dist/src/components/Badge/Badge.d.ts +63 -0
- package/dist/src/components/Badge/Badge.d.ts.map +1 -0
- package/dist/src/components/Badge/badge.types.d.ts +124 -0
- package/dist/src/components/Badge/badge.types.d.ts.map +1 -0
- package/dist/src/components/Badge/badge.variants.d.ts +262 -0
- package/dist/src/components/Badge/badge.variants.d.ts.map +1 -0
- package/dist/src/components/Box/Box.d.ts.map +1 -1
- package/dist/src/components/Box/box.types.d.ts +53 -0
- package/dist/src/components/Box/box.types.d.ts.map +1 -1
- package/dist/src/components/Button/Button.d.ts.map +1 -1
- package/dist/src/components/Button/button.types.d.ts +35 -0
- package/dist/src/components/Button/button.types.d.ts.map +1 -1
- package/dist/src/components/Card/Card.d.ts +107 -0
- package/dist/src/components/Card/Card.d.ts.map +1 -0
- package/dist/src/components/Card/card.types.d.ts +119 -0
- package/dist/src/components/Card/card.types.d.ts.map +1 -0
- package/dist/src/components/Chip/Chip.d.ts +67 -0
- package/dist/src/components/Chip/Chip.d.ts.map +1 -0
- package/dist/src/components/Chip/chip.types.d.ts +113 -0
- package/dist/src/components/Chip/chip.types.d.ts.map +1 -0
- package/dist/src/components/Chip/chip.variants.d.ts +155 -0
- package/dist/src/components/Chip/chip.variants.d.ts.map +1 -0
- package/dist/src/components/IconButton/IconButton.d.ts +57 -0
- package/dist/src/components/IconButton/IconButton.d.ts.map +1 -0
- package/dist/src/components/IconButton/iconButton.types.d.ts +96 -0
- package/dist/src/components/IconButton/iconButton.types.d.ts.map +1 -0
- package/dist/src/components/IconButton/iconButton.variants.d.ts +26 -0
- package/dist/src/components/IconButton/iconButton.variants.d.ts.map +1 -0
- package/dist/src/components/Menu/Menu.d.ts +118 -0
- package/dist/src/components/Menu/Menu.d.ts.map +1 -0
- package/dist/src/components/Menu/menu.types.d.ts +179 -0
- package/dist/src/components/Menu/menu.types.d.ts.map +1 -0
- package/dist/src/components/Menu/menu.variants.d.ts +129 -0
- package/dist/src/components/Menu/menu.variants.d.ts.map +1 -0
- package/dist/src/components/Snackbar/Snackbar.d.ts.map +1 -1
- package/dist/src/components/Snackbar/snackbar.types.d.ts +40 -3
- package/dist/src/components/Snackbar/snackbar.types.d.ts.map +1 -1
- package/dist/src/components/Snackbar/snackbar.variants.d.ts +12 -57
- package/dist/src/components/Snackbar/snackbar.variants.d.ts.map +1 -1
- package/dist/src/components/Spinner/Spinner.d.ts +44 -0
- package/dist/src/components/Spinner/Spinner.d.ts.map +1 -0
- package/dist/src/components/Spinner/spinner.types.d.ts +89 -0
- package/dist/src/components/Spinner/spinner.types.d.ts.map +1 -0
- package/dist/src/components/Spinner/spinner.variants.d.ts +111 -0
- package/dist/src/components/Spinner/spinner.variants.d.ts.map +1 -0
- package/dist/src/components/Table/cells/RenderChip.d.ts +15 -72
- package/dist/src/components/Table/cells/RenderChip.d.ts.map +1 -1
- package/dist/src/components/_shared/severity/index.d.ts +21 -0
- package/dist/src/components/_shared/severity/index.d.ts.map +1 -0
- package/dist/src/components/_shared/severity/severity.types.d.ts +48 -0
- package/dist/src/components/_shared/severity/severity.types.d.ts.map +1 -0
- package/dist/src/components/_shared/severity/severityIcons.d.ts +45 -0
- package/dist/src/components/_shared/severity/severityIcons.d.ts.map +1 -0
- package/dist/src/components/_shared/severity/severityVariants.d.ts +22 -0
- package/dist/src/components/_shared/severity/severityVariants.d.ts.map +1 -0
- package/dist/src/index.d.ts +27 -2
- package/dist/src/index.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/components/Alert/Alert.test.tsx +302 -0
- package/src/components/Alert/Alert.tsx +186 -0
- package/src/components/Alert/alert.types.ts +144 -0
- package/src/components/Alert/alert.variants.ts +71 -0
- package/src/components/Autocomplete/autocomplete.variants.ts +1 -1
- package/src/components/Avatar/Avatar.test.tsx +287 -0
- package/src/components/Avatar/Avatar.tsx +304 -0
- package/src/components/Avatar/avatar.types.ts +205 -0
- package/src/components/Avatar/avatar.variants.ts +194 -0
- package/src/components/Badge/Badge.test.tsx +385 -0
- package/src/components/Badge/Badge.tsx +174 -0
- package/src/components/Badge/badge.types.ts +154 -0
- package/src/components/Badge/badge.variants.ts +161 -0
- package/src/components/Box/Box.test.tsx +21 -0
- package/src/components/Box/Box.tsx +32 -3
- package/src/components/Box/box.types.ts +55 -0
- package/src/components/Button/Button.test.tsx +21 -0
- package/src/components/Button/Button.tsx +28 -27
- package/src/components/Button/button.types.ts +36 -0
- package/src/components/Card/Card.test.tsx +291 -0
- package/src/components/Card/Card.tsx +241 -0
- package/src/components/Card/card.types.ts +132 -0
- package/src/components/Chip/Chip.test.tsx +316 -0
- package/src/components/Chip/Chip.tsx +224 -0
- package/src/components/Chip/chip.types.ts +128 -0
- package/src/components/Chip/chip.variants.ts +173 -0
- package/src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx +1 -1
- package/src/components/IconButton/IconButton.test.tsx +367 -0
- package/src/components/IconButton/IconButton.tsx +159 -0
- package/src/components/IconButton/iconButton.types.ts +106 -0
- package/src/components/IconButton/iconButton.variants.ts +31 -0
- package/src/components/LeftNav/leftNav.variants.ts +2 -2
- package/src/components/Menu/Menu.test.tsx +408 -0
- package/src/components/Menu/Menu.tsx +335 -0
- package/src/components/Menu/menu.types.ts +221 -0
- package/src/components/Menu/menu.variants.ts +132 -0
- package/src/components/Pagination/pagination.variants.ts +1 -1
- package/src/components/Snackbar/Snackbar.tsx +46 -28
- package/src/components/Snackbar/snackbar.types.ts +47 -3
- package/src/components/Snackbar/snackbar.variants.ts +29 -22
- package/src/components/Spinner/Spinner.test.tsx +199 -0
- package/src/components/Spinner/Spinner.tsx +158 -0
- package/src/components/Spinner/spinner.types.ts +113 -0
- package/src/components/Spinner/spinner.variants.ts +83 -0
- package/src/components/Table/cells/RenderChip.tsx +24 -87
- package/src/components/Table/cells/RowActionsMenu.tsx +1 -1
- package/src/components/_shared/severity/index.ts +33 -0
- package/src/components/_shared/severity/severity.types.ts +50 -0
- package/src/components/_shared/severity/severityIcons.tsx +104 -0
- package/src/components/_shared/severity/severityVariants.test.ts +136 -0
- package/src/components/_shared/severity/severityVariants.ts +115 -0
- package/src/index.ts +163 -1
- package/LICENSE +0 -21
- package/dist/components/Accordion/Accordion.d.ts +0 -21
- package/dist/components/Accordion/Accordion.d.ts.map +0 -1
- package/dist/components/Accordion/accordion.types.d.ts +0 -74
- package/dist/components/Accordion/accordion.types.d.ts.map +0 -1
- package/dist/components/Accordion/accordion.variants.d.ts +0 -58
- package/dist/components/Accordion/accordion.variants.d.ts.map +0 -1
- package/dist/components/AppShell/AppShell.d.ts +0 -46
- package/dist/components/AppShell/AppShell.d.ts.map +0 -1
- package/dist/components/AppShell/appShell.types.d.ts +0 -62
- package/dist/components/AppShell/appShell.types.d.ts.map +0 -1
- package/dist/components/AppShell/appShell.variants.d.ts +0 -65
- package/dist/components/AppShell/appShell.variants.d.ts.map +0 -1
- package/dist/components/AspectRatio/AspectRatio.d.ts +0 -36
- package/dist/components/AspectRatio/AspectRatio.d.ts.map +0 -1
- package/dist/components/AspectRatio/aspectRatio.types.d.ts +0 -50
- package/dist/components/AspectRatio/aspectRatio.types.d.ts.map +0 -1
- package/dist/components/Autocomplete/Autocomplete.d.ts +0 -32
- package/dist/components/Autocomplete/Autocomplete.d.ts.map +0 -1
- package/dist/components/Autocomplete/autocomplete.types.d.ts +0 -214
- package/dist/components/Autocomplete/autocomplete.types.d.ts.map +0 -1
- package/dist/components/Autocomplete/autocomplete.variants.d.ts +0 -214
- package/dist/components/Autocomplete/autocomplete.variants.d.ts.map +0 -1
- package/dist/components/Box/Box.d.ts +0 -36
- package/dist/components/Box/Box.d.ts.map +0 -1
- package/dist/components/Box/box.types.d.ts +0 -54
- package/dist/components/Box/box.types.d.ts.map +0 -1
- package/dist/components/Box/box.variants.d.ts +0 -402
- package/dist/components/Box/box.variants.d.ts.map +0 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +0 -23
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts.map +0 -1
- package/dist/components/Breadcrumbs/breadcrumbs.types.d.ts +0 -98
- package/dist/components/Breadcrumbs/breadcrumbs.types.d.ts.map +0 -1
- package/dist/components/Breadcrumbs/breadcrumbs.variants.d.ts +0 -85
- package/dist/components/Breadcrumbs/breadcrumbs.variants.d.ts.map +0 -1
- package/dist/components/Button/Button.d.ts +0 -44
- package/dist/components/Button/Button.d.ts.map +0 -1
- package/dist/components/Button/button.types.d.ts +0 -66
- package/dist/components/Button/button.types.d.ts.map +0 -1
- package/dist/components/Button/button.variants.d.ts +0 -104
- package/dist/components/Button/button.variants.d.ts.map +0 -1
- package/dist/components/Calendar/Calendar.d.ts +0 -14
- package/dist/components/Calendar/Calendar.d.ts.map +0 -1
- package/dist/components/Calendar/calendar.types.d.ts +0 -72
- package/dist/components/Calendar/calendar.types.d.ts.map +0 -1
- package/dist/components/Calendar/calendar.variants.d.ts +0 -99
- package/dist/components/Calendar/calendar.variants.d.ts.map +0 -1
- package/dist/components/Checkbox/Checkbox.d.ts +0 -31
- package/dist/components/Checkbox/Checkbox.d.ts.map +0 -1
- package/dist/components/Checkbox/checkbox.types.d.ts +0 -86
- package/dist/components/Checkbox/checkbox.types.d.ts.map +0 -1
- package/dist/components/Checkbox/checkbox.variants.d.ts +0 -109
- package/dist/components/Checkbox/checkbox.variants.d.ts.map +0 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +0 -38
- package/dist/components/ConfirmDialog/ConfirmDialog.d.ts.map +0 -1
- package/dist/components/ConfirmDialog/confirmDialog.types.d.ts +0 -80
- package/dist/components/ConfirmDialog/confirmDialog.types.d.ts.map +0 -1
- package/dist/components/ConfirmDialog/confirmDialog.variants.d.ts +0 -90
- package/dist/components/ConfirmDialog/confirmDialog.variants.d.ts.map +0 -1
- package/dist/components/Container/Container.d.ts +0 -35
- package/dist/components/Container/Container.d.ts.map +0 -1
- package/dist/components/Container/container.types.d.ts +0 -41
- package/dist/components/Container/container.types.d.ts.map +0 -1
- package/dist/components/Container/container.variants.d.ts +0 -93
- package/dist/components/Container/container.variants.d.ts.map +0 -1
- package/dist/components/DataGrid/DataGrid.d.ts +0 -29
- package/dist/components/DataGrid/DataGrid.d.ts.map +0 -1
- package/dist/components/DataGrid/dataGrid.types.d.ts +0 -214
- package/dist/components/DataGrid/dataGrid.types.d.ts.map +0 -1
- package/dist/components/DataGrid/dataGrid.variants.d.ts +0 -222
- package/dist/components/DataGrid/dataGrid.variants.d.ts.map +0 -1
- package/dist/components/DataGrid/filters/ColumnFilters.d.ts +0 -23
- package/dist/components/DataGrid/filters/ColumnFilters.d.ts.map +0 -1
- package/dist/components/DataGrid/reorder/useColumnReorder.d.ts +0 -50
- package/dist/components/DataGrid/reorder/useColumnReorder.d.ts.map +0 -1
- package/dist/components/DataGrid/resize/useColumnResize.d.ts +0 -39
- package/dist/components/DataGrid/resize/useColumnResize.d.ts.map +0 -1
- package/dist/components/DataGrid/visibility/ColumnVisibilityMenu.d.ts +0 -44
- package/dist/components/DataGrid/visibility/ColumnVisibilityMenu.d.ts.map +0 -1
- package/dist/components/DatePicker/DatePicker.d.ts +0 -14
- package/dist/components/DatePicker/DatePicker.d.ts.map +0 -1
- package/dist/components/DatePicker/datePicker.types.d.ts +0 -88
- package/dist/components/DatePicker/datePicker.types.d.ts.map +0 -1
- package/dist/components/DatePicker/datePicker.variants.d.ts +0 -97
- package/dist/components/DatePicker/datePicker.variants.d.ts.map +0 -1
- package/dist/components/DateRangePicker/DateRangePicker.d.ts +0 -13
- package/dist/components/DateRangePicker/DateRangePicker.d.ts.map +0 -1
- package/dist/components/DateRangePicker/dateRangePicker.types.d.ts +0 -85
- package/dist/components/DateRangePicker/dateRangePicker.types.d.ts.map +0 -1
- package/dist/components/DateRangePicker/dateRangePicker.variants.d.ts +0 -183
- package/dist/components/DateRangePicker/dateRangePicker.variants.d.ts.map +0 -1
- package/dist/components/DateTimePicker/DateTimePicker.d.ts +0 -13
- package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +0 -1
- package/dist/components/DateTimePicker/dateTimePicker.types.d.ts +0 -90
- package/dist/components/DateTimePicker/dateTimePicker.types.d.ts.map +0 -1
- package/dist/components/DateTimePicker/dateTimePicker.variants.d.ts +0 -107
- package/dist/components/DateTimePicker/dateTimePicker.variants.d.ts.map +0 -1
- package/dist/components/Dialog/Dialog.d.ts +0 -17
- package/dist/components/Dialog/Dialog.d.ts.map +0 -1
- package/dist/components/Dialog/dialog.types.d.ts +0 -75
- package/dist/components/Dialog/dialog.types.d.ts.map +0 -1
- package/dist/components/Dialog/dialog.variants.d.ts +0 -80
- package/dist/components/Dialog/dialog.variants.d.ts.map +0 -1
- package/dist/components/Divider/Divider.d.ts +0 -50
- package/dist/components/Divider/Divider.d.ts.map +0 -1
- package/dist/components/Divider/divider.types.d.ts +0 -47
- package/dist/components/Divider/divider.types.d.ts.map +0 -1
- package/dist/components/Divider/divider.variants.d.ts +0 -129
- package/dist/components/Divider/divider.variants.d.ts.map +0 -1
- package/dist/components/Grid/Grid.d.ts +0 -32
- package/dist/components/Grid/Grid.d.ts.map +0 -1
- package/dist/components/Grid/grid.types.d.ts +0 -103
- package/dist/components/Grid/grid.types.d.ts.map +0 -1
- package/dist/components/Grid/grid.variants.d.ts +0 -453
- package/dist/components/Grid/grid.variants.d.ts.map +0 -1
- package/dist/components/LeftNav/LeftNav.d.ts +0 -34
- package/dist/components/LeftNav/LeftNav.d.ts.map +0 -1
- package/dist/components/LeftNav/leftNav.types.d.ts +0 -136
- package/dist/components/LeftNav/leftNav.types.d.ts.map +0 -1
- package/dist/components/LeftNav/leftNav.variants.d.ts +0 -143
- package/dist/components/LeftNav/leftNav.variants.d.ts.map +0 -1
- package/dist/components/NumberField/NumberField.d.ts +0 -18
- package/dist/components/NumberField/NumberField.d.ts.map +0 -1
- package/dist/components/NumberField/numberField.types.d.ts +0 -79
- package/dist/components/NumberField/numberField.types.d.ts.map +0 -1
- package/dist/components/NumberField/numberField.variants.d.ts +0 -169
- package/dist/components/NumberField/numberField.variants.d.ts.map +0 -1
- package/dist/components/OTPField/OTPField.d.ts +0 -25
- package/dist/components/OTPField/OTPField.d.ts.map +0 -1
- package/dist/components/OTPField/otpField.types.d.ts +0 -74
- package/dist/components/OTPField/otpField.types.d.ts.map +0 -1
- package/dist/components/OTPField/otpField.variants.d.ts +0 -105
- package/dist/components/OTPField/otpField.variants.d.ts.map +0 -1
- package/dist/components/Pagination/Pagination.d.ts +0 -32
- package/dist/components/Pagination/Pagination.d.ts.map +0 -1
- package/dist/components/Pagination/pagination.helpers.d.ts +0 -23
- package/dist/components/Pagination/pagination.helpers.d.ts.map +0 -1
- package/dist/components/Pagination/pagination.types.d.ts +0 -120
- package/dist/components/Pagination/pagination.types.d.ts.map +0 -1
- package/dist/components/Pagination/pagination.variants.d.ts +0 -150
- package/dist/components/Pagination/pagination.variants.d.ts.map +0 -1
- package/dist/components/Popover/Popover.d.ts +0 -15
- package/dist/components/Popover/Popover.d.ts.map +0 -1
- package/dist/components/Popover/popover.types.d.ts +0 -45
- package/dist/components/Popover/popover.types.d.ts.map +0 -1
- package/dist/components/Popover/popover.variants.d.ts +0 -34
- package/dist/components/Popover/popover.variants.d.ts.map +0 -1
- package/dist/components/RadioGroup/RadioGroup.d.ts +0 -35
- package/dist/components/RadioGroup/RadioGroup.d.ts.map +0 -1
- package/dist/components/RadioGroup/radioGroup.types.d.ts +0 -103
- package/dist/components/RadioGroup/radioGroup.types.d.ts.map +0 -1
- package/dist/components/RadioGroup/radioGroup.variants.d.ts +0 -166
- package/dist/components/RadioGroup/radioGroup.variants.d.ts.map +0 -1
- package/dist/components/Skeleton/Skeleton.d.ts +0 -23
- package/dist/components/Skeleton/Skeleton.d.ts.map +0 -1
- package/dist/components/Skeleton/skeleton.types.d.ts +0 -56
- package/dist/components/Skeleton/skeleton.types.d.ts.map +0 -1
- package/dist/components/Skeleton/skeleton.variants.d.ts +0 -110
- package/dist/components/Skeleton/skeleton.variants.d.ts.map +0 -1
- package/dist/components/Snackbar/Snackbar.d.ts +0 -37
- package/dist/components/Snackbar/Snackbar.d.ts.map +0 -1
- package/dist/components/Snackbar/snackbar.types.d.ts +0 -86
- package/dist/components/Snackbar/snackbar.types.d.ts.map +0 -1
- package/dist/components/Snackbar/snackbar.variants.d.ts +0 -153
- package/dist/components/Snackbar/snackbar.variants.d.ts.map +0 -1
- package/dist/components/Stack/Stack.d.ts +0 -24
- package/dist/components/Stack/Stack.d.ts.map +0 -1
- package/dist/components/Stack/stack.types.d.ts +0 -61
- package/dist/components/Stack/stack.types.d.ts.map +0 -1
- package/dist/components/Stack/stack.variants.d.ts +0 -163
- package/dist/components/Stack/stack.variants.d.ts.map +0 -1
- package/dist/components/Switch/Switch.d.ts +0 -15
- package/dist/components/Switch/Switch.d.ts.map +0 -1
- package/dist/components/Switch/switch.types.d.ts +0 -47
- package/dist/components/Switch/switch.types.d.ts.map +0 -1
- package/dist/components/Switch/switch.variants.d.ts +0 -105
- package/dist/components/Switch/switch.variants.d.ts.map +0 -1
- package/dist/components/Table/Table.d.ts +0 -24
- package/dist/components/Table/Table.d.ts.map +0 -1
- package/dist/components/Table/cells/RenderButton.d.ts +0 -13
- package/dist/components/Table/cells/RenderButton.d.ts.map +0 -1
- package/dist/components/Table/cells/RenderChip.d.ts +0 -80
- package/dist/components/Table/cells/RenderChip.d.ts.map +0 -1
- package/dist/components/Table/cells/RenderText.d.ts +0 -21
- package/dist/components/Table/cells/RenderText.d.ts.map +0 -1
- package/dist/components/Table/cells/RenderTwoLine.d.ts +0 -20
- package/dist/components/Table/cells/RenderTwoLine.d.ts.map +0 -1
- package/dist/components/Table/cells/RowActionsMenu.d.ts +0 -36
- package/dist/components/Table/cells/RowActionsMenu.d.ts.map +0 -1
- package/dist/components/Table/cells/index.d.ts +0 -11
- package/dist/components/Table/cells/index.d.ts.map +0 -1
- package/dist/components/Table/table.types.d.ts +0 -399
- package/dist/components/Table/table.types.d.ts.map +0 -1
- package/dist/components/Table/table.variants.d.ts +0 -285
- package/dist/components/Table/table.variants.d.ts.map +0 -1
- package/dist/components/Tabs/Tabs.d.ts +0 -19
- package/dist/components/Tabs/Tabs.d.ts.map +0 -1
- package/dist/components/Tabs/tabs.types.d.ts +0 -61
- package/dist/components/Tabs/tabs.types.d.ts.map +0 -1
- package/dist/components/Tabs/tabs.variants.d.ts +0 -82
- package/dist/components/Tabs/tabs.variants.d.ts.map +0 -1
- package/dist/components/Tabs/useTabs.d.ts +0 -55
- package/dist/components/Tabs/useTabs.d.ts.map +0 -1
- package/dist/components/TextField/TextField.d.ts +0 -25
- package/dist/components/TextField/TextField.d.ts.map +0 -1
- package/dist/components/TextField/textField.types.d.ts +0 -98
- package/dist/components/TextField/textField.types.d.ts.map +0 -1
- package/dist/components/TextField/textField.variants.d.ts +0 -166
- package/dist/components/TextField/textField.variants.d.ts.map +0 -1
- package/dist/components/Textarea/Textarea.d.ts +0 -16
- package/dist/components/Textarea/Textarea.d.ts.map +0 -1
- package/dist/components/Textarea/textarea.types.d.ts +0 -63
- package/dist/components/Textarea/textarea.types.d.ts.map +0 -1
- package/dist/components/Textarea/textarea.variants.d.ts +0 -197
- package/dist/components/Textarea/textarea.variants.d.ts.map +0 -1
- package/dist/components/TimePicker/TimePicker.d.ts +0 -12
- package/dist/components/TimePicker/TimePicker.d.ts.map +0 -1
- package/dist/components/TimePicker/timePicker.types.d.ts +0 -80
- package/dist/components/TimePicker/timePicker.types.d.ts.map +0 -1
- package/dist/components/TimePicker/timePicker.variants.d.ts +0 -103
- package/dist/components/TimePicker/timePicker.variants.d.ts.map +0 -1
- package/dist/components/Tooltip/Tooltip.d.ts +0 -29
- package/dist/components/Tooltip/Tooltip.d.ts.map +0 -1
- package/dist/components/Tooltip/tooltip.types.d.ts +0 -47
- package/dist/components/Tooltip/tooltip.types.d.ts.map +0 -1
- package/dist/components/Tooltip/tooltip.variants.d.ts +0 -34
- package/dist/components/Tooltip/tooltip.variants.d.ts.map +0 -1
- package/dist/components/TopBar/TopBar.d.ts +0 -33
- package/dist/components/TopBar/TopBar.d.ts.map +0 -1
- package/dist/components/TopBar/topBar.types.d.ts +0 -49
- package/dist/components/TopBar/topBar.types.d.ts.map +0 -1
- package/dist/components/TopBar/topBar.variants.d.ts +0 -79
- package/dist/components/TopBar/topBar.variants.d.ts.map +0 -1
- package/dist/components/Typography/Typography.d.ts +0 -42
- package/dist/components/Typography/Typography.d.ts.map +0 -1
- package/dist/components/Typography/typography.types.d.ts +0 -61
- package/dist/components/Typography/typography.types.d.ts.map +0 -1
- package/dist/components/Typography/typography.variants.d.ts +0 -167
- package/dist/components/Typography/typography.variants.d.ts.map +0 -1
- package/dist/components/VisuallyHidden/VisuallyHidden.d.ts +0 -42
- package/dist/components/VisuallyHidden/VisuallyHidden.d.ts.map +0 -1
- package/dist/components/VisuallyHidden/visuallyHidden.types.d.ts +0 -42
- package/dist/components/VisuallyHidden/visuallyHidden.types.d.ts.map +0 -1
- package/dist/components/_shared/data/getNestedValue.d.ts +0 -20
- package/dist/components/_shared/data/getNestedValue.d.ts.map +0 -1
- package/dist/components/_shared/data/useColumnAutoDetect.d.ts +0 -45
- package/dist/components/_shared/data/useColumnAutoDetect.d.ts.map +0 -1
- package/dist/components/_shared/data/useControllableState.d.ts +0 -23
- package/dist/components/_shared/data/useControllableState.d.ts.map +0 -1
- package/dist/components/_shared/data/useDebouncedValue.d.ts +0 -10
- package/dist/components/_shared/data/useDebouncedValue.d.ts.map +0 -1
- package/dist/components/_shared/data/useTableFilter.d.ts +0 -36
- package/dist/components/_shared/data/useTableFilter.d.ts.map +0 -1
- package/dist/components/_shared/data/useTableSearch.d.ts +0 -23
- package/dist/components/_shared/data/useTableSearch.d.ts.map +0 -1
- package/dist/components/_shared/data/useTableSelection.d.ts +0 -25
- package/dist/components/_shared/data/useTableSelection.d.ts.map +0 -1
- package/dist/components/_shared/data/useTableSort.d.ts +0 -20
- package/dist/components/_shared/data/useTableSort.d.ts.map +0 -1
- package/dist/components/_shared/data/useVirtualizer.d.ts +0 -107
- package/dist/components/_shared/data/useVirtualizer.d.ts.map +0 -1
- package/dist/components/_shared/resolveValidationState.d.ts +0 -42
- package/dist/components/_shared/resolveValidationState.d.ts.map +0 -1
- package/dist/hooks/useAccessState.d.ts +0 -37
- package/dist/hooks/useAccessState.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/tsconfig.lib.tsbuildinfo +0 -1
- package/dist/utils/cn.d.ts +0 -26
- package/dist/utils/cn.d.ts.map +0 -1
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { ClassValue } from 'tailwind-variants';
|
|
3
|
+
import type { Engine } from '@dashforge/ui-core';
|
|
4
|
+
import type { AccessRequirement } from '@dashforge/rbac';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Intent color — drives the badge background. Default is `danger`
|
|
8
|
+
* because the most common notification UX expects a red dot/count
|
|
9
|
+
* for "needs attention" affordance.
|
|
10
|
+
*/
|
|
11
|
+
export type BadgeColor =
|
|
12
|
+
| 'neutral'
|
|
13
|
+
| 'primary'
|
|
14
|
+
| 'secondary'
|
|
15
|
+
| 'success'
|
|
16
|
+
| 'warning'
|
|
17
|
+
| 'danger'
|
|
18
|
+
| 'info';
|
|
19
|
+
|
|
20
|
+
/** 4 corner positions for the floating badge. */
|
|
21
|
+
export type BadgePlacement =
|
|
22
|
+
| 'top-right'
|
|
23
|
+
| 'top-left'
|
|
24
|
+
| 'bottom-right'
|
|
25
|
+
| 'bottom-left';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Anchor shape:
|
|
29
|
+
* - `'rectangular'` (default) — badge sits at the bounding-box
|
|
30
|
+
* corner. Use for square-ish anchors like IconButton, Card.
|
|
31
|
+
* - `'circular'` — badge offset to align with the circular edge.
|
|
32
|
+
* Use for round anchors like Avatar.
|
|
33
|
+
*/
|
|
34
|
+
export type BadgeOverlap = 'rectangular' | 'circular';
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Per-slot className overrides for `<Badge>`.
|
|
38
|
+
*/
|
|
39
|
+
export interface BadgeSlotProps {
|
|
40
|
+
/** Outer wrapper (relative-positioned, contains the anchor + badge). */
|
|
41
|
+
root?: { className?: string };
|
|
42
|
+
/** The floating badge pill / dot itself. */
|
|
43
|
+
badge?: { className?: string };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Props for `<Badge>` — anchored indicator (count / dot / short text).
|
|
48
|
+
*
|
|
49
|
+
* Wrapper-only mode: `<Badge>` always wraps an anchor element passed
|
|
50
|
+
* as `children`. For standalone inline pills (status labels, tags),
|
|
51
|
+
* use `<Chip>` — Badge and Chip are complementary, not interchangeable.
|
|
52
|
+
*
|
|
53
|
+
* Relationship with Chip:
|
|
54
|
+
* - `<Chip>` = inline pill (interactive — `onClick`, `onDelete`,
|
|
55
|
+
* `selected`). Standalone, no anchor.
|
|
56
|
+
* - `<Badge>` = anchored indicator (passive — small count / dot
|
|
57
|
+
* overlaid on top of another element).
|
|
58
|
+
*/
|
|
59
|
+
export interface BadgeProps {
|
|
60
|
+
// ─── Required ──────────────────────────────────────────────────
|
|
61
|
+
/** The anchor element (Avatar / IconButton / button / Card / custom). */
|
|
62
|
+
children: ReactNode;
|
|
63
|
+
|
|
64
|
+
// ─── Content ───────────────────────────────────────────────────
|
|
65
|
+
/**
|
|
66
|
+
* Numeric or string content to display inside the badge.
|
|
67
|
+
* - `number` → formatted via `max` (overflow renders as `"N+"`)
|
|
68
|
+
* - `string` → rendered verbatim (e.g., `"NEW"`)
|
|
69
|
+
* - omitted + `dot=false` → no badge rendered (or only at zero if
|
|
70
|
+
* `showZero=true`)
|
|
71
|
+
*/
|
|
72
|
+
content?: number | string;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Dot-only mode — small circle without content. When `true`,
|
|
76
|
+
* `content` and `max` are ignored.
|
|
77
|
+
*/
|
|
78
|
+
dot?: boolean;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Overflow threshold for numeric `content`. Values above render
|
|
82
|
+
* as `{max}+`. Set to `-1` to disable overflow (always raw number).
|
|
83
|
+
* @default 99
|
|
84
|
+
*/
|
|
85
|
+
max?: number;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Whether to render the badge when numeric `content` is `0`.
|
|
89
|
+
* Hidden by default — the typical notification UX is "no badge =
|
|
90
|
+
* nothing to see".
|
|
91
|
+
* @default false
|
|
92
|
+
*/
|
|
93
|
+
showZero?: boolean;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Imperative hide — keeps the badge in the DOM but applies
|
|
97
|
+
* `display: none`. Use for opacity/scale fade animations without
|
|
98
|
+
* unmounting.
|
|
99
|
+
* @default false
|
|
100
|
+
*/
|
|
101
|
+
invisible?: boolean;
|
|
102
|
+
|
|
103
|
+
// ─── Visual ────────────────────────────────────────────────────
|
|
104
|
+
/** @default 'danger' — typical "needs attention" notification color. */
|
|
105
|
+
color?: BadgeColor;
|
|
106
|
+
|
|
107
|
+
/** @default 'top-right' */
|
|
108
|
+
placement?: BadgePlacement;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Anchor shape — controls badge offset.
|
|
112
|
+
* - `'rectangular'` (default) sits at the bounding-box corner
|
|
113
|
+
* - `'circular'` offsets to align with the circular anchor edge
|
|
114
|
+
* (use with `<Avatar shape="circle">`)
|
|
115
|
+
* @default 'rectangular'
|
|
116
|
+
*/
|
|
117
|
+
overlap?: BadgeOverlap;
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* White/neutral ring around the badge — visually separates from
|
|
121
|
+
* the anchor surface. Token-driven via `ring-neutral-50` which
|
|
122
|
+
* auto-inverts via the dashforgePreset CSS-var swap (no `dark:`
|
|
123
|
+
* needed).
|
|
124
|
+
* @default true
|
|
125
|
+
*/
|
|
126
|
+
withRing?: boolean;
|
|
127
|
+
|
|
128
|
+
// ─── Bridge integration (Sprint 4.4) ───────────────────────────
|
|
129
|
+
/**
|
|
130
|
+
* RBAC requirement — hides the badge for unauthorized subjects.
|
|
131
|
+
* The wrapped anchor element remains visible (use Box `access`
|
|
132
|
+
* to gate the anchor too).
|
|
133
|
+
*
|
|
134
|
+
* Use case: admin-only notification count, role-gated indicators.
|
|
135
|
+
*/
|
|
136
|
+
access?: AccessRequirement;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Reactive visibility predicate. When `false`, the badge dot/count
|
|
140
|
+
* is not rendered (children always render). Use for state-driven
|
|
141
|
+
* indicators tied to engine values.
|
|
142
|
+
*/
|
|
143
|
+
visibleWhen?: (engine: Engine) => boolean;
|
|
144
|
+
|
|
145
|
+
// ─── Override ──────────────────────────────────────────────────
|
|
146
|
+
/** Root-element class shortcut. */
|
|
147
|
+
sx?: ClassValue;
|
|
148
|
+
|
|
149
|
+
/** Standard className — appended to the root via `cn()`. */
|
|
150
|
+
className?: string;
|
|
151
|
+
|
|
152
|
+
/** Per-slot overrides — root + badge. */
|
|
153
|
+
slotProps?: BadgeSlotProps;
|
|
154
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { tv, type VariantProps } from 'tailwind-variants';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tailwind-variants recipe for `<Badge>`.
|
|
5
|
+
*
|
|
6
|
+
* Slot layout:
|
|
7
|
+
* - `root` — outer span (relative-positioned wrapper around the
|
|
8
|
+
* anchor). `inline-flex` so the wrapper shrinks to fit
|
|
9
|
+
* the anchor element.
|
|
10
|
+
* - `badge` — the floating absolute-positioned pill / dot. Two
|
|
11
|
+
* variants (`dot=true` → tiny circle, `dot=false` →
|
|
12
|
+
* pill with min-width to fit content).
|
|
13
|
+
*
|
|
14
|
+
* Color axis emits the `badge` background + text classes. The 7
|
|
15
|
+
* intents map to:
|
|
16
|
+
* - solid bg: `bg-{intent}-500` (vivid, attention-grabbing for
|
|
17
|
+
* notifications — different from Chip which uses 600 for solid
|
|
18
|
+
* because chip surface is larger; small badge needs the brighter
|
|
19
|
+
* mid-tone)
|
|
20
|
+
* - text: `text-white` for primary/secondary/success/warning/danger/
|
|
21
|
+
* info; `text-neutral-50` for neutral (auto-inverts via CSS-var
|
|
22
|
+
* swap, no `dark:` needed)
|
|
23
|
+
*
|
|
24
|
+
* Placement axis emits absolute-position + translate utilities:
|
|
25
|
+
* - top-right (default): `top-0 right-0 -translate-y-1/2 translate-x-1/2`
|
|
26
|
+
* - top-left: `top-0 left-0 -translate-y-1/2 -translate-x-1/2`
|
|
27
|
+
* - bottom-right: `bottom-0 right-0 translate-y-1/2 translate-x-1/2`
|
|
28
|
+
* - bottom-left: `bottom-0 left-0 translate-y-1/2 -translate-x-1/2`
|
|
29
|
+
*
|
|
30
|
+
* Overlap axis adds an extra inset for circular anchors so the
|
|
31
|
+
* badge sits along the round edge instead of the bounding box corner.
|
|
32
|
+
*/
|
|
33
|
+
export const badgeVariants = tv({
|
|
34
|
+
slots: {
|
|
35
|
+
root: 'relative inline-flex shrink-0',
|
|
36
|
+
badge: [
|
|
37
|
+
// Absolute positioning is owned by the placement compound rules.
|
|
38
|
+
'absolute z-10',
|
|
39
|
+
// Layout / typography — pill defaults; dot mode overrides
|
|
40
|
+
// dimensions below.
|
|
41
|
+
'inline-flex items-center justify-center',
|
|
42
|
+
'rounded-full',
|
|
43
|
+
'text-[10px] font-medium leading-none',
|
|
44
|
+
'pointer-events-none select-none',
|
|
45
|
+
// Smooth show/hide for `invisible` toggle (consumer-side
|
|
46
|
+
// animation hook). Gated on motion-reduce per WCAG 2.3.3.
|
|
47
|
+
'transition-transform duration-150 motion-reduce:transition-none motion-reduce:duration-0',
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
variants: {
|
|
51
|
+
/**
|
|
52
|
+
* `dot=true` → tiny circle (8px), no content. The badge slot
|
|
53
|
+
* collapses to a fixed-size circle without the pill min-width.
|
|
54
|
+
*/
|
|
55
|
+
dot: {
|
|
56
|
+
true: {
|
|
57
|
+
badge: 'w-2 h-2 p-0',
|
|
58
|
+
},
|
|
59
|
+
false: {
|
|
60
|
+
// Content pill — 16px tall, padded inline, min-width so
|
|
61
|
+
// single-digit counts still read centered.
|
|
62
|
+
badge: 'min-w-4 h-4 px-1',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
/** Whether the floating badge is hidden via `display: none`. */
|
|
66
|
+
invisible: {
|
|
67
|
+
true: {
|
|
68
|
+
badge: 'hidden',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
/** Halo ring for visual separation from the anchor surface. */
|
|
72
|
+
withRing: {
|
|
73
|
+
true: {
|
|
74
|
+
// ring-neutral-50 auto-inverts via dashforgePreset CSS var
|
|
75
|
+
// swap (no `dark:` needed for the neutral palette).
|
|
76
|
+
badge: 'ring-2 ring-neutral-50',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
/** 7 intents — drives the badge background + text colour. */
|
|
80
|
+
color: {
|
|
81
|
+
neutral: {
|
|
82
|
+
// Both classes on the neutral palette — auto-invert via CSS
|
|
83
|
+
// var swap. No `dark:` variants needed.
|
|
84
|
+
badge: 'bg-neutral-700 text-neutral-50',
|
|
85
|
+
},
|
|
86
|
+
primary: { badge: 'bg-primary-500 text-white' },
|
|
87
|
+
secondary: { badge: 'bg-secondary-500 text-white' },
|
|
88
|
+
success: { badge: 'bg-success-500 text-white' },
|
|
89
|
+
warning: { badge: 'bg-warning-500 text-white' },
|
|
90
|
+
danger: { badge: 'bg-danger-500 text-white' },
|
|
91
|
+
info: { badge: 'bg-info-500 text-white' },
|
|
92
|
+
},
|
|
93
|
+
placement: {
|
|
94
|
+
'top-right': {
|
|
95
|
+
badge: 'top-0 right-0 -translate-y-1/2 translate-x-1/2',
|
|
96
|
+
},
|
|
97
|
+
'top-left': {
|
|
98
|
+
badge: 'top-0 left-0 -translate-y-1/2 -translate-x-1/2',
|
|
99
|
+
},
|
|
100
|
+
'bottom-right': {
|
|
101
|
+
badge: 'bottom-0 right-0 translate-y-1/2 translate-x-1/2',
|
|
102
|
+
},
|
|
103
|
+
'bottom-left': {
|
|
104
|
+
badge: 'bottom-0 left-0 translate-y-1/2 -translate-x-1/2',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
/**
|
|
108
|
+
* `overlap='circular'` adds an inward inset so the badge sits
|
|
109
|
+
* along the circular anchor edge instead of the bounding-box
|
|
110
|
+
* corner. The 14% offset is empirically tuned to match the
|
|
111
|
+
* standard avatar / round-button geometry (matches MUI's value).
|
|
112
|
+
*/
|
|
113
|
+
overlap: {
|
|
114
|
+
rectangular: {},
|
|
115
|
+
circular: {},
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
compoundVariants: [
|
|
119
|
+
// ─── overlap='circular' × placement — additional inset ─────────
|
|
120
|
+
// The inward shift is in addition to the placement translate,
|
|
121
|
+
// achieved via an extra `-{translate-corner}` adjustment.
|
|
122
|
+
{
|
|
123
|
+
overlap: 'circular',
|
|
124
|
+
placement: 'top-right',
|
|
125
|
+
class: {
|
|
126
|
+
badge: 'top-[14%] right-[14%] translate-x-1/2 -translate-y-1/2',
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
overlap: 'circular',
|
|
131
|
+
placement: 'top-left',
|
|
132
|
+
class: {
|
|
133
|
+
badge: 'top-[14%] left-[14%] -translate-x-1/2 -translate-y-1/2',
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
overlap: 'circular',
|
|
138
|
+
placement: 'bottom-right',
|
|
139
|
+
class: {
|
|
140
|
+
badge: 'bottom-[14%] right-[14%] translate-x-1/2 translate-y-1/2',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
overlap: 'circular',
|
|
145
|
+
placement: 'bottom-left',
|
|
146
|
+
class: {
|
|
147
|
+
badge: 'bottom-[14%] left-[14%] -translate-x-1/2 translate-y-1/2',
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
defaultVariants: {
|
|
152
|
+
dot: false,
|
|
153
|
+
invisible: false,
|
|
154
|
+
withRing: true,
|
|
155
|
+
color: 'danger',
|
|
156
|
+
placement: 'top-right',
|
|
157
|
+
overlap: 'rectangular',
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
export type BadgeVariants = VariantProps<typeof badgeVariants>;
|
|
@@ -367,4 +367,25 @@ describe('<Box>', () => {
|
|
|
367
367
|
expect(container.firstElementChild?.className).toContain('rounded-none');
|
|
368
368
|
});
|
|
369
369
|
});
|
|
370
|
+
|
|
371
|
+
describe('bridge integration — visibleWhen (Sprint 4.4 surface alignment)', () => {
|
|
372
|
+
it('renders when visibleWhen returns true', () => {
|
|
373
|
+
const { container } = render(
|
|
374
|
+
<Box visibleWhen={() => true}>shown</Box>
|
|
375
|
+
);
|
|
376
|
+
expect(container.firstChild).toBeTruthy();
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
it('returns null when visibleWhen returns false', () => {
|
|
380
|
+
const { container } = render(
|
|
381
|
+
<Box visibleWhen={() => false}>hidden</Box>
|
|
382
|
+
);
|
|
383
|
+
expect(container.firstChild).toBeNull();
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
it('renders normally when visibleWhen is omitted', () => {
|
|
387
|
+
const { container } = render(<Box>always</Box>);
|
|
388
|
+
expect(container.firstChild).toBeTruthy();
|
|
389
|
+
});
|
|
390
|
+
});
|
|
370
391
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { forwardRef, type ElementType, type ReactElement } from 'react';
|
|
1
|
+
import { forwardRef, useContext, type ElementType, type ReactElement } from 'react';
|
|
2
2
|
import { Slot } from '@radix-ui/react-slot';
|
|
3
|
+
import { DashFormContext, useEngineVisibility } from '@dashforge/ui-core';
|
|
3
4
|
import { cn } from '../../utils/cn.js';
|
|
5
|
+
import { useAccessState } from '../../hooks/useAccessState.js';
|
|
4
6
|
import { boxVariants } from './box.variants.js';
|
|
5
7
|
import type { BoxProps } from './box.types.js';
|
|
6
8
|
|
|
@@ -50,22 +52,49 @@ export const Box = forwardRef<HTMLElement, BoxProps>(
|
|
|
50
52
|
as,
|
|
51
53
|
asChild = false,
|
|
52
54
|
sx,
|
|
55
|
+
visibleWhen,
|
|
56
|
+
access,
|
|
53
57
|
children,
|
|
54
58
|
...rest
|
|
55
59
|
} = props;
|
|
56
60
|
|
|
61
|
+
// Bridge — hooks called unconditionally (rules-of-hooks).
|
|
62
|
+
// `useEngineVisibility` subscribes to engine state inside a
|
|
63
|
+
// `<DashForm>` and re-evaluates the predicate reactively; outside
|
|
64
|
+
// a form, it evaluates the predicate as a plain closure.
|
|
65
|
+
// `useAccessState` consults the @dashforge/rbac policy engine.
|
|
66
|
+
// Both default to no-op when the corresponding prop is omitted.
|
|
67
|
+
const bridge = useContext(DashFormContext);
|
|
68
|
+
const isVisible = useEngineVisibility(bridge?.engine, visibleWhen);
|
|
69
|
+
const accessState = useAccessState(access);
|
|
70
|
+
|
|
71
|
+
// Early return — predicate false OR RBAC denies visibility.
|
|
72
|
+
if (!isVisible || !accessState.visible) return null;
|
|
73
|
+
|
|
57
74
|
const classes = cn(
|
|
58
75
|
boxVariants({
|
|
59
76
|
variant, color, elevation, rounded,
|
|
60
77
|
p, px, py, m, mx, my,
|
|
61
78
|
fullWidth, fullHeight,
|
|
62
79
|
}),
|
|
80
|
+
// RBAC-disabled / readonly surfaces dim visually + carry
|
|
81
|
+
// semantic ARIA attributes (assigned below) so descendants and
|
|
82
|
+
// assistive tech can react.
|
|
83
|
+
accessState.disabled && 'opacity-60',
|
|
84
|
+
accessState.readonly && 'opacity-80',
|
|
63
85
|
sx,
|
|
64
86
|
);
|
|
65
87
|
|
|
88
|
+
const ariaProps = {
|
|
89
|
+
'aria-disabled': accessState.disabled || undefined,
|
|
90
|
+
'aria-readonly': accessState.readonly || undefined,
|
|
91
|
+
'data-disabled': accessState.disabled || undefined,
|
|
92
|
+
'data-readonly': accessState.readonly || undefined,
|
|
93
|
+
};
|
|
94
|
+
|
|
66
95
|
if (asChild) {
|
|
67
96
|
return (
|
|
68
|
-
<Slot ref={ref} className={classes} {...rest}>
|
|
97
|
+
<Slot ref={ref} className={classes} {...ariaProps} {...rest}>
|
|
69
98
|
{children as ReactElement}
|
|
70
99
|
</Slot>
|
|
71
100
|
);
|
|
@@ -73,7 +102,7 @@ export const Box = forwardRef<HTMLElement, BoxProps>(
|
|
|
73
102
|
|
|
74
103
|
const Tag = (as ?? 'div') as ElementType;
|
|
75
104
|
return (
|
|
76
|
-
<Tag ref={ref as never} className={classes} {...rest}>
|
|
105
|
+
<Tag ref={ref as never} className={classes} {...ariaProps} {...rest}>
|
|
77
106
|
{children}
|
|
78
107
|
</Tag>
|
|
79
108
|
);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { ElementType, HTMLAttributes } from 'react';
|
|
2
|
+
import type { Engine } from '@dashforge/ui-core';
|
|
3
|
+
import type { AccessRequirement } from '@dashforge/rbac';
|
|
2
4
|
import type { BoxVariants } from './box.variants.js';
|
|
3
5
|
|
|
4
6
|
/**
|
|
@@ -58,4 +60,57 @@ export interface BoxProps
|
|
|
58
60
|
* position, animation, etc.).
|
|
59
61
|
*/
|
|
60
62
|
sx?: string;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Reactive visibility predicate — added in 1.1.0 (Sprint 4.4
|
|
66
|
+
* surface alignment). When the predicate returns `false`, the
|
|
67
|
+
* component renders `null`. Inside a `<DashForm>` it subscribes
|
|
68
|
+
* reactively to engine state changes; outside a form, it's
|
|
69
|
+
* evaluated as a plain closure.
|
|
70
|
+
*
|
|
71
|
+
* Use for state-driven hiding of dashboard cards, conditional
|
|
72
|
+
* sections, gated content, etc. **For permission-driven hiding,
|
|
73
|
+
* prefer `access` with `onUnauthorized: 'hide'`** — it's semantically
|
|
74
|
+
* the correct path and surfaces better in RBAC dev tools.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```tsx
|
|
78
|
+
* // Dashboard card visible only when there are pending shipments
|
|
79
|
+
* <Box variant="outlined" rounded="lg" p={4}
|
|
80
|
+
* visibleWhen={() => pendingCount > 0}>
|
|
81
|
+
* <Typography variant="h3">{pendingCount} pending</Typography>
|
|
82
|
+
* </Box>
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
visibleWhen?: (engine: Engine) => boolean;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* RBAC requirement — added in 1.1.0 (Sprint 4.4 surface alignment).
|
|
89
|
+
* Controls Box visibility / disabled-state via the centralized
|
|
90
|
+
* `@dashforge/rbac` policy engine.
|
|
91
|
+
*
|
|
92
|
+
* - `onUnauthorized: 'hide'` → Box does not render
|
|
93
|
+
* - `onUnauthorized: 'disable'` → adds `aria-disabled` + dimmed
|
|
94
|
+
* visual; interactive children should derive their disabled state
|
|
95
|
+
* from `data-disabled` on the Box or pass their own `access`
|
|
96
|
+
* - `onUnauthorized: 'readonly'` → adds `aria-readonly`; mostly used
|
|
97
|
+
* when Box wraps form sections that propagate readonly to children
|
|
98
|
+
*
|
|
99
|
+
* Use for permission-gated dashboard cards, admin-only sections,
|
|
100
|
+
* tenant-aware layouts. The hide path is the common case.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```tsx
|
|
104
|
+
* // Revenue card visible only to users with billing:read permission
|
|
105
|
+
* <Box variant="elevated" rounded="lg" elevation={2} p={4}
|
|
106
|
+
* access={{
|
|
107
|
+
* resource: 'billing',
|
|
108
|
+
* action: 'read',
|
|
109
|
+
* onUnauthorized: 'hide'
|
|
110
|
+
* }}>
|
|
111
|
+
* <Typography variant="h3">Q3 Revenue</Typography>
|
|
112
|
+
* </Box>
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
access?: AccessRequirement;
|
|
61
116
|
}
|
|
@@ -181,3 +181,24 @@ describe('Button — asChild polymorphism', () => {
|
|
|
181
181
|
expect(node.getAttribute('aria-disabled')).toBe('true');
|
|
182
182
|
});
|
|
183
183
|
});
|
|
184
|
+
|
|
185
|
+
describe('Button — visibleWhen (engine-reactive visibility, Sprint 4.4)', () => {
|
|
186
|
+
it('renders when visibleWhen returns true (no DashForm context)', () => {
|
|
187
|
+
const { container } = render(
|
|
188
|
+
<Button visibleWhen={() => true}>shown</Button>
|
|
189
|
+
);
|
|
190
|
+
expect(container.firstChild).toBeTruthy();
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('returns null when visibleWhen returns false', () => {
|
|
194
|
+
const { container } = render(
|
|
195
|
+
<Button visibleWhen={() => false}>hidden</Button>
|
|
196
|
+
);
|
|
197
|
+
expect(container.firstChild).toBeNull();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('renders normally when visibleWhen is omitted', () => {
|
|
201
|
+
const { container } = render(<Button>always</Button>);
|
|
202
|
+
expect(container.firstChild).toBeTruthy();
|
|
203
|
+
});
|
|
204
|
+
});
|
|
@@ -1,36 +1,22 @@
|
|
|
1
|
-
import { forwardRef } from 'react';
|
|
1
|
+
import { forwardRef, useContext } from 'react';
|
|
2
2
|
import { Slot } from '@radix-ui/react-slot';
|
|
3
|
+
import { DashFormContext, useEngineVisibility } from '@dashforge/ui-core';
|
|
3
4
|
import { cn } from '../../utils/cn.js';
|
|
4
5
|
import { useAccessState } from '../../hooks/useAccessState.js';
|
|
6
|
+
import { Spinner } from '../Spinner/Spinner.js';
|
|
7
|
+
import type { SpinnerSize } from '../Spinner/spinner.types.js';
|
|
5
8
|
import { buttonVariants } from './button.variants.js';
|
|
6
9
|
import type { ButtonProps } from './button.types.js';
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
12
|
+
* Map Button size to Spinner size. Button has 3 sizes (sm/md/lg);
|
|
13
|
+
* Spinner has 5 (xs/sm/md/lg/xl). Picking the closest match keeps
|
|
14
|
+
* the spinner visually proportional to the button label.
|
|
11
15
|
*
|
|
12
16
|
* @internal
|
|
13
17
|
*/
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
<svg
|
|
18
|
-
aria-hidden="true"
|
|
19
|
-
width={dim}
|
|
20
|
-
height={dim}
|
|
21
|
-
viewBox="0 0 24 24"
|
|
22
|
-
fill="none"
|
|
23
|
-
className="animate-spin"
|
|
24
|
-
>
|
|
25
|
-
<circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2.5" strokeOpacity="0.25" />
|
|
26
|
-
<path
|
|
27
|
-
d="M21 12a9 9 0 0 0-9-9"
|
|
28
|
-
stroke="currentColor"
|
|
29
|
-
strokeWidth="2.5"
|
|
30
|
-
strokeLinecap="round"
|
|
31
|
-
/>
|
|
32
|
-
</svg>
|
|
33
|
-
);
|
|
18
|
+
function buttonSizeToSpinnerSize(size: 'sm' | 'md' | 'lg'): SpinnerSize {
|
|
19
|
+
return size === 'sm' ? 'xs' : size === 'lg' ? 'md' : 'sm';
|
|
34
20
|
}
|
|
35
21
|
|
|
36
22
|
/**
|
|
@@ -80,6 +66,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button
|
|
|
80
66
|
) {
|
|
81
67
|
const {
|
|
82
68
|
access,
|
|
69
|
+
visibleWhen,
|
|
83
70
|
disabled,
|
|
84
71
|
variant,
|
|
85
72
|
color,
|
|
@@ -92,11 +79,18 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button
|
|
|
92
79
|
...rest
|
|
93
80
|
} = props;
|
|
94
81
|
|
|
95
|
-
//
|
|
82
|
+
// Bridge — both hooks called unconditionally (rules-of-hooks).
|
|
83
|
+
// Inside a `<DashForm>`, `useEngineVisibility` subscribes to engine
|
|
84
|
+
// state and re-evaluates the predicate on changes; outside a form,
|
|
85
|
+
// the predicate is called with `null` engine (consumer captures
|
|
86
|
+
// external state in the closure).
|
|
87
|
+
const bridge = useContext(DashFormContext);
|
|
88
|
+
const isVisible = useEngineVisibility(bridge?.engine, visibleWhen);
|
|
96
89
|
const accessState = useAccessState(access);
|
|
97
90
|
|
|
98
|
-
// Early return for hidden state
|
|
99
|
-
|
|
91
|
+
// Early return for hidden state — either RBAC denies visibility or
|
|
92
|
+
// the engine-reactive predicate returned false.
|
|
93
|
+
if (!isVisible || !accessState.visible) return null;
|
|
100
94
|
|
|
101
95
|
// Effective disabled = explicit OR RBAC-disabled OR RBAC-readonly OR loading.
|
|
102
96
|
// Buttons do not support a true readonly state — RBAC readonly is mapped
|
|
@@ -143,7 +137,14 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button
|
|
|
143
137
|
className={classes}
|
|
144
138
|
{...rest}
|
|
145
139
|
>
|
|
146
|
-
{loading &&
|
|
140
|
+
{loading && (
|
|
141
|
+
<Spinner
|
|
142
|
+
size={buttonSizeToSpinnerSize(size ?? 'md')}
|
|
143
|
+
thickness="thick"
|
|
144
|
+
withTrack
|
|
145
|
+
label=""
|
|
146
|
+
/>
|
|
147
|
+
)}
|
|
147
148
|
{children}
|
|
148
149
|
</button>
|
|
149
150
|
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ButtonHTMLAttributes } from 'react';
|
|
2
|
+
import type { Engine } from '@dashforge/ui-core';
|
|
2
3
|
import type { AccessRequirement } from '@dashforge/rbac';
|
|
3
4
|
import type { ButtonVariants } from './button.variants.js';
|
|
4
5
|
|
|
@@ -45,6 +46,41 @@ export interface ButtonProps
|
|
|
45
46
|
*/
|
|
46
47
|
access?: AccessRequirement;
|
|
47
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Reactive visibility predicate. Re-evaluated on every engine state
|
|
51
|
+
* change when the button is mounted inside a `<DashForm>`; outside
|
|
52
|
+
* a form, evaluated as a plain predicate (the consumer captures
|
|
53
|
+
* any external state in the closure).
|
|
54
|
+
*
|
|
55
|
+
* When the predicate returns `false`, the component renders `null`.
|
|
56
|
+
*
|
|
57
|
+
* **Added in 1.1.0 (Sprint 4.4 alignment)** — extends the
|
|
58
|
+
* engine-reactive visibility pattern previously available only on
|
|
59
|
+
* form fields + `<Alert>` to every interactive component in the
|
|
60
|
+
* Dashforge TW catalog (Button, IconButton, Chip, …).
|
|
61
|
+
*
|
|
62
|
+
* Note: `visibleWhen` is for **state-driven** hide. For
|
|
63
|
+
* **permission-driven** hide, use `access` with
|
|
64
|
+
* `onUnauthorized: 'hide'` — it's the semantically correct path
|
|
65
|
+
* and provides better error messages in RBAC dev tools.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* // Inside a DashForm — reactive on engine state
|
|
70
|
+
* <Button
|
|
71
|
+
* visibleWhen={(engine) =>
|
|
72
|
+
* engine.getNode('plan')?.value === 'premium'
|
|
73
|
+
* }
|
|
74
|
+
* >
|
|
75
|
+
* Upgrade extras
|
|
76
|
+
* </Button>
|
|
77
|
+
*
|
|
78
|
+
* // Outside a form — closure over external React state
|
|
79
|
+
* <Button visibleWhen={() => itemCount > 0}>Bulk delete</Button>
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
visibleWhen?: (engine: Engine) => boolean;
|
|
83
|
+
|
|
48
84
|
/**
|
|
49
85
|
* When `true`, the immediate child element is rendered with the
|
|
50
86
|
* Button's classes merged in (via `@radix-ui/react-slot`). The
|