@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,173 @@
|
|
|
1
|
+
import { tv, type VariantProps } from 'tailwind-variants';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tailwind-variants recipe for `<Chip>` — promoted from the internal
|
|
5
|
+
* `Table/cells/RenderChip` (Sprint 4.4). The visual treatment is
|
|
6
|
+
* preserved byte-identical: the same 3 × 7 compound matrix
|
|
7
|
+
* (variant × color) emitted by RenderChip is now the single source
|
|
8
|
+
* of truth, consumed by both the public `<Chip>` and (via thin
|
|
9
|
+
* wrapper) the legacy `RenderChip` internal.
|
|
10
|
+
*
|
|
11
|
+
* Slots (only `root` slot used by the public Chip; sub-slots
|
|
12
|
+
* surfaced via separate inline classes in `Chip.tsx`):
|
|
13
|
+
* - `root` — outer chip surface
|
|
14
|
+
*
|
|
15
|
+
* Variants axis (3 × 7, plus orthogonal `size`):
|
|
16
|
+
* - `color`: 7 intents (`neutral / primary / secondary / success /
|
|
17
|
+
* warning / danger / info`)
|
|
18
|
+
* - `variant`: `soft` (default) / `solid` / `outline`
|
|
19
|
+
* - `size`: `sm` (default) / `md`
|
|
20
|
+
*
|
|
21
|
+
* Token-driven: every Tailwind utility resolves through
|
|
22
|
+
* `dashforgePreset()` → CSS variables. No hardcoded hex.
|
|
23
|
+
*
|
|
24
|
+
* `dark:` variants on color palettes (lines 49-77 of legacy
|
|
25
|
+
* RenderChip, preserved here) are INTENTIONAL — color palettes do not
|
|
26
|
+
* auto-invert via the CSS-var swap (only the `neutral` palette does),
|
|
27
|
+
* so the `dark:` shift is a deliberate design choice (darker bg +
|
|
28
|
+
* lighter text in dark mode for visual cohesion). `dark:` on the
|
|
29
|
+
* `neutral` row is AVOIDED — that would double-invert.
|
|
30
|
+
*/
|
|
31
|
+
export const chipVariants = tv({
|
|
32
|
+
base: [
|
|
33
|
+
'inline-flex items-center gap-1 rounded-full font-medium',
|
|
34
|
+
'whitespace-nowrap',
|
|
35
|
+
// Smooth transitions for clickable / selected state changes.
|
|
36
|
+
'transition-colors',
|
|
37
|
+
'motion-reduce:transition-none',
|
|
38
|
+
],
|
|
39
|
+
variants: {
|
|
40
|
+
color: {
|
|
41
|
+
neutral: '',
|
|
42
|
+
primary: '',
|
|
43
|
+
secondary: '',
|
|
44
|
+
success: '',
|
|
45
|
+
warning: '',
|
|
46
|
+
danger: '',
|
|
47
|
+
info: '',
|
|
48
|
+
},
|
|
49
|
+
variant: {
|
|
50
|
+
soft: '',
|
|
51
|
+
solid: '',
|
|
52
|
+
outline: '',
|
|
53
|
+
},
|
|
54
|
+
size: {
|
|
55
|
+
sm: 'h-5 px-2 text-xs',
|
|
56
|
+
md: 'h-6 px-2.5 text-xs',
|
|
57
|
+
},
|
|
58
|
+
/**
|
|
59
|
+
* Clickable state — adds focus ring + hover transition. Applied
|
|
60
|
+
* when the chip renders as `<button>` (i.e. `onClick` or
|
|
61
|
+
* explicit `clickable` is set).
|
|
62
|
+
*/
|
|
63
|
+
clickable: {
|
|
64
|
+
true: [
|
|
65
|
+
'cursor-pointer select-none',
|
|
66
|
+
'outline-none focus-visible:ring-2 focus-visible:ring-offset-1',
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
/**
|
|
70
|
+
* Selected state — used on filter chips to indicate active
|
|
71
|
+
* selection. Visually shifts the chip to a heavier emphasis
|
|
72
|
+
* (one step up the elevation ladder of its current variant).
|
|
73
|
+
* Compound rules below apply the actual shift per (variant, color)
|
|
74
|
+
* cell.
|
|
75
|
+
*/
|
|
76
|
+
selected: {
|
|
77
|
+
true: 'ring-2 ring-offset-1',
|
|
78
|
+
},
|
|
79
|
+
/** Disabled state for clickable chips. */
|
|
80
|
+
disabled: {
|
|
81
|
+
true: 'opacity-50 cursor-not-allowed pointer-events-none',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
compoundVariants: [
|
|
85
|
+
// ─── soft × color ──────────────────────────────────────────────
|
|
86
|
+
// Subtle bg + readable text. Neutral row uses NO `dark:` (auto-
|
|
87
|
+
// inverts via the dashforgePreset CSS-var swap). Color rows KEEP
|
|
88
|
+
// `dark:` (color palettes don't auto-invert).
|
|
89
|
+
{ variant: 'soft', color: 'neutral', class: 'bg-neutral-100 text-neutral-700' },
|
|
90
|
+
{ variant: 'soft', color: 'primary', class: 'bg-primary-100 dark:bg-primary-950 text-primary-700 dark:text-primary-300' },
|
|
91
|
+
{ variant: 'soft', color: 'secondary', class: 'bg-secondary-100 dark:bg-secondary-950 text-secondary-700 dark:text-secondary-300' },
|
|
92
|
+
{ variant: 'soft', color: 'success', class: 'bg-success-100 dark:bg-success-950 text-success-700 dark:text-success-300' },
|
|
93
|
+
{ variant: 'soft', color: 'warning', class: 'bg-warning-100 dark:bg-warning-950 text-warning-700 dark:text-warning-300' },
|
|
94
|
+
{ variant: 'soft', color: 'danger', class: 'bg-danger-100 dark:bg-danger-950 text-danger-700 dark:text-danger-300' },
|
|
95
|
+
{ variant: 'soft', color: 'info', class: 'bg-info-100 dark:bg-info-950 text-info-700 dark:text-info-300' },
|
|
96
|
+
// ─── solid × color ─────────────────────────────────────────────
|
|
97
|
+
// Full bg + contrasting text. Solid neutral uses neutral-700/50
|
|
98
|
+
// (both on neutral palette → auto-invert together).
|
|
99
|
+
// `text-white` is deliberately NOT used: white does not auto-invert,
|
|
100
|
+
// which would flip the contrast in dark mode for the neutral row.
|
|
101
|
+
{ variant: 'solid', color: 'neutral', class: 'bg-neutral-700 text-neutral-50' },
|
|
102
|
+
{ variant: 'solid', color: 'primary', class: 'bg-primary-500 text-white' },
|
|
103
|
+
{ variant: 'solid', color: 'secondary', class: 'bg-secondary-500 text-white' },
|
|
104
|
+
{ variant: 'solid', color: 'success', class: 'bg-success-500 text-white' },
|
|
105
|
+
{ variant: 'solid', color: 'warning', class: 'bg-warning-500 text-white' },
|
|
106
|
+
{ variant: 'solid', color: 'danger', class: 'bg-danger-500 text-white' },
|
|
107
|
+
{ variant: 'solid', color: 'info', class: 'bg-info-500 text-white' },
|
|
108
|
+
// ─── outline × color ───────────────────────────────────────────
|
|
109
|
+
// Border + colored text. Outline neutral: both auto-invert via
|
|
110
|
+
// CSS-var swap. Color rows: `dark:text-*-300` for legibility in
|
|
111
|
+
// dark mode on a transparent background.
|
|
112
|
+
{ variant: 'outline', color: 'neutral', class: 'border border-neutral-300 text-neutral-700' },
|
|
113
|
+
{ variant: 'outline', color: 'primary', class: 'border border-primary-500 text-primary-700 dark:text-primary-300' },
|
|
114
|
+
{ variant: 'outline', color: 'secondary', class: 'border border-secondary-500 text-secondary-700 dark:text-secondary-300' },
|
|
115
|
+
{ variant: 'outline', color: 'success', class: 'border border-success-500 text-success-700 dark:text-success-300' },
|
|
116
|
+
{ variant: 'outline', color: 'warning', class: 'border border-warning-500 text-warning-700 dark:text-warning-300' },
|
|
117
|
+
{ variant: 'outline', color: 'danger', class: 'border border-danger-500 text-danger-700 dark:text-danger-300' },
|
|
118
|
+
{ variant: 'outline', color: 'info', class: 'border border-info-500 text-info-700 dark:text-info-300' },
|
|
119
|
+
// ─── clickable × color hover (subtle bg shift) ─────────────────
|
|
120
|
+
// Hover state on clickable chips. Each (variant, color) hover
|
|
121
|
+
// emits a one-tier deeper bg tint, working across both modes via
|
|
122
|
+
// the same auto-invert logic as the base compound.
|
|
123
|
+
{ clickable: true, variant: 'soft', color: 'neutral', class: 'hover:bg-neutral-200' },
|
|
124
|
+
{ clickable: true, variant: 'soft', color: 'primary', class: 'hover:bg-primary-200 dark:hover:bg-primary-900' },
|
|
125
|
+
{ clickable: true, variant: 'soft', color: 'secondary', class: 'hover:bg-secondary-200 dark:hover:bg-secondary-900' },
|
|
126
|
+
{ clickable: true, variant: 'soft', color: 'success', class: 'hover:bg-success-200 dark:hover:bg-success-900' },
|
|
127
|
+
{ clickable: true, variant: 'soft', color: 'warning', class: 'hover:bg-warning-200 dark:hover:bg-warning-900' },
|
|
128
|
+
{ clickable: true, variant: 'soft', color: 'danger', class: 'hover:bg-danger-200 dark:hover:bg-danger-900' },
|
|
129
|
+
{ clickable: true, variant: 'soft', color: 'info', class: 'hover:bg-info-200 dark:hover:bg-info-900' },
|
|
130
|
+
// Solid hover → one tone darker
|
|
131
|
+
{ clickable: true, variant: 'solid', color: 'neutral', class: 'hover:bg-neutral-800' },
|
|
132
|
+
{ clickable: true, variant: 'solid', color: 'primary', class: 'hover:bg-primary-600' },
|
|
133
|
+
{ clickable: true, variant: 'solid', color: 'secondary', class: 'hover:bg-secondary-600' },
|
|
134
|
+
{ clickable: true, variant: 'solid', color: 'success', class: 'hover:bg-success-600' },
|
|
135
|
+
{ clickable: true, variant: 'solid', color: 'warning', class: 'hover:bg-warning-600' },
|
|
136
|
+
{ clickable: true, variant: 'solid', color: 'danger', class: 'hover:bg-danger-600' },
|
|
137
|
+
{ clickable: true, variant: 'solid', color: 'info', class: 'hover:bg-info-600' },
|
|
138
|
+
// Outline hover → tinted bg appears (transparent → light tint)
|
|
139
|
+
{ clickable: true, variant: 'outline', color: 'neutral', class: 'hover:bg-neutral-100' },
|
|
140
|
+
{ clickable: true, variant: 'outline', color: 'primary', class: 'hover:bg-primary-50 dark:hover:bg-primary-950' },
|
|
141
|
+
{ clickable: true, variant: 'outline', color: 'secondary', class: 'hover:bg-secondary-50 dark:hover:bg-secondary-950' },
|
|
142
|
+
{ clickable: true, variant: 'outline', color: 'success', class: 'hover:bg-success-50 dark:hover:bg-success-950' },
|
|
143
|
+
{ clickable: true, variant: 'outline', color: 'warning', class: 'hover:bg-warning-50 dark:hover:bg-warning-950' },
|
|
144
|
+
{ clickable: true, variant: 'outline', color: 'danger', class: 'hover:bg-danger-50 dark:hover:bg-danger-950' },
|
|
145
|
+
{ clickable: true, variant: 'outline', color: 'info', class: 'hover:bg-info-50 dark:hover:bg-info-950' },
|
|
146
|
+
// ─── selected × color (focus ring tone) ────────────────────────
|
|
147
|
+
// When selected, the ring color matches the chip's intent.
|
|
148
|
+
{ selected: true, color: 'neutral', class: 'ring-neutral-400' },
|
|
149
|
+
{ selected: true, color: 'primary', class: 'ring-primary-500' },
|
|
150
|
+
{ selected: true, color: 'secondary', class: 'ring-secondary-500' },
|
|
151
|
+
{ selected: true, color: 'success', class: 'ring-success-500' },
|
|
152
|
+
{ selected: true, color: 'warning', class: 'ring-warning-500' },
|
|
153
|
+
{ selected: true, color: 'danger', class: 'ring-danger-500' },
|
|
154
|
+
{ selected: true, color: 'info', class: 'ring-info-500' },
|
|
155
|
+
// ─── clickable × color (focus ring tone) ───────────────────────
|
|
156
|
+
// Tab-focused ring tone matches the chip color (same intent as
|
|
157
|
+
// selected but only when keyboard-focused, via focus-visible).
|
|
158
|
+
{ clickable: true, color: 'neutral', class: 'focus-visible:ring-neutral-400' },
|
|
159
|
+
{ clickable: true, color: 'primary', class: 'focus-visible:ring-primary-500' },
|
|
160
|
+
{ clickable: true, color: 'secondary', class: 'focus-visible:ring-secondary-500' },
|
|
161
|
+
{ clickable: true, color: 'success', class: 'focus-visible:ring-success-500' },
|
|
162
|
+
{ clickable: true, color: 'warning', class: 'focus-visible:ring-warning-500' },
|
|
163
|
+
{ clickable: true, color: 'danger', class: 'focus-visible:ring-danger-500' },
|
|
164
|
+
{ clickable: true, color: 'info', class: 'focus-visible:ring-info-500' },
|
|
165
|
+
],
|
|
166
|
+
defaultVariants: {
|
|
167
|
+
color: 'neutral',
|
|
168
|
+
variant: 'soft',
|
|
169
|
+
size: 'sm',
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
export type ChipVariants = VariantProps<typeof chipVariants>;
|
|
@@ -120,7 +120,7 @@ export function ColumnVisibilityTrigger<T extends object>(
|
|
|
120
120
|
{labels.columnsTitle}
|
|
121
121
|
</span>
|
|
122
122
|
</div>
|
|
123
|
-
<ul className="flex flex-col gap-0.5 max-h-72 overflow-auto">
|
|
123
|
+
<ul className="flex flex-col gap-0.5 max-h-72 overflow-auto list-none pl-0 m-0">
|
|
124
124
|
{hideableCols.map((col) => {
|
|
125
125
|
const field = col.field as string;
|
|
126
126
|
const hidden = hiddenColumns.includes(field);
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
4
|
+
import { render, screen, fireEvent, cleanup } from '@testing-library/react';
|
|
5
|
+
import { RbacProvider } from '@dashforge/rbac';
|
|
6
|
+
import type { RbacPolicy, Subject } from '@dashforge/rbac';
|
|
7
|
+
import { IconButton } from './IconButton.js';
|
|
8
|
+
|
|
9
|
+
void React;
|
|
10
|
+
afterEach(() => cleanup());
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* `<IconButton>` unit tests. Covers:
|
|
14
|
+
* - icon rendering, required aria-label, base layout primitives
|
|
15
|
+
* - variant × color × size matrix (5 variants × 5 colors × 3 sizes)
|
|
16
|
+
* — sampled, not exhaustive (the full matrix is covered by
|
|
17
|
+
* `<Button>`'s tests since IconButton reuses `buttonVariants`)
|
|
18
|
+
* - square geometry via SIZE_OVERRIDES + aspect-square
|
|
19
|
+
* - asChild polymorphism via Radix Slot
|
|
20
|
+
* - loading state (spinner + aria-busy + disabled)
|
|
21
|
+
* - disabled state (explicit + access.disabled + access.readonly)
|
|
22
|
+
* - access RBAC: hide / disable
|
|
23
|
+
* - click handler firing semantics
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const TestIcon = () => (
|
|
27
|
+
<svg data-testid="test-icon" width={20} height={20} viewBox="0 0 20 20">
|
|
28
|
+
<circle cx="10" cy="10" r="8" />
|
|
29
|
+
</svg>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const FULL_ACCESS_POLICY: RbacPolicy = {
|
|
33
|
+
roles: [
|
|
34
|
+
{
|
|
35
|
+
name: 'admin',
|
|
36
|
+
permissions: [{ resource: '*', action: '*', effect: 'allow' }],
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
const NO_ACCESS_POLICY: RbacPolicy = {
|
|
41
|
+
roles: [
|
|
42
|
+
{ name: 'guest', permissions: [] },
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
const adminSubject: Subject = { id: 'a', roles: ['admin'] };
|
|
46
|
+
const guestSubject: Subject = { id: 'g', roles: ['guest'] };
|
|
47
|
+
|
|
48
|
+
describe('<IconButton>', () => {
|
|
49
|
+
describe('rendering', () => {
|
|
50
|
+
it('renders the icon child', () => {
|
|
51
|
+
render(
|
|
52
|
+
<IconButton aria-label="x">
|
|
53
|
+
<TestIcon />
|
|
54
|
+
</IconButton>
|
|
55
|
+
);
|
|
56
|
+
expect(screen.getByTestId('test-icon')).toBeTruthy();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('applies the aria-label to the button element', () => {
|
|
60
|
+
render(
|
|
61
|
+
<IconButton aria-label="Open settings">
|
|
62
|
+
<TestIcon />
|
|
63
|
+
</IconButton>
|
|
64
|
+
);
|
|
65
|
+
expect(screen.getByRole('button', { name: /open settings/i })).toBeTruthy();
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('renders as type="button" by default', () => {
|
|
69
|
+
render(
|
|
70
|
+
<IconButton aria-label="x">
|
|
71
|
+
<TestIcon />
|
|
72
|
+
</IconButton>
|
|
73
|
+
);
|
|
74
|
+
const btn = screen.getByRole('button') as HTMLButtonElement;
|
|
75
|
+
expect(btn.type).toBe('button');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('respects an explicit type prop', () => {
|
|
79
|
+
render(
|
|
80
|
+
<IconButton aria-label="x" type="submit">
|
|
81
|
+
<TestIcon />
|
|
82
|
+
</IconButton>
|
|
83
|
+
);
|
|
84
|
+
const btn = screen.getByRole('button') as HTMLButtonElement;
|
|
85
|
+
expect(btn.type).toBe('submit');
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe('layout primitives — square geometry', () => {
|
|
90
|
+
it('always applies aspect-square + inline-flex (layout base)', () => {
|
|
91
|
+
const { container } = render(
|
|
92
|
+
<IconButton aria-label="x">
|
|
93
|
+
<TestIcon />
|
|
94
|
+
</IconButton>
|
|
95
|
+
);
|
|
96
|
+
const btn = container.querySelector('button')!;
|
|
97
|
+
expect(btn.className).toContain('aspect-square');
|
|
98
|
+
expect(btn.className).toContain('inline-flex');
|
|
99
|
+
expect(btn.className).toContain('items-center');
|
|
100
|
+
expect(btn.className).toContain('justify-center');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('applies SIZE_OVERRIDES (w-N + px-0) for sm', () => {
|
|
104
|
+
const { container } = render(
|
|
105
|
+
<IconButton aria-label="x" size="sm">
|
|
106
|
+
<TestIcon />
|
|
107
|
+
</IconButton>
|
|
108
|
+
);
|
|
109
|
+
const btn = container.querySelector('button')!;
|
|
110
|
+
expect(btn.className).toContain('w-8');
|
|
111
|
+
expect(btn.className).toContain('px-0');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('applies SIZE_OVERRIDES for md (default)', () => {
|
|
115
|
+
const { container } = render(
|
|
116
|
+
<IconButton aria-label="x">
|
|
117
|
+
<TestIcon />
|
|
118
|
+
</IconButton>
|
|
119
|
+
);
|
|
120
|
+
const btn = container.querySelector('button')!;
|
|
121
|
+
expect(btn.className).toContain('w-10');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('applies SIZE_OVERRIDES for lg', () => {
|
|
125
|
+
const { container } = render(
|
|
126
|
+
<IconButton aria-label="x" size="lg">
|
|
127
|
+
<TestIcon />
|
|
128
|
+
</IconButton>
|
|
129
|
+
);
|
|
130
|
+
const btn = container.querySelector('button')!;
|
|
131
|
+
expect(btn.className).toContain('w-12');
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('variant × color (inherits buttonVariants)', () => {
|
|
136
|
+
it('renders solid + primary (token-driven, no hardcoded hex)', () => {
|
|
137
|
+
const { container } = render(
|
|
138
|
+
<IconButton aria-label="x" variant="solid" color="primary">
|
|
139
|
+
<TestIcon />
|
|
140
|
+
</IconButton>
|
|
141
|
+
);
|
|
142
|
+
const btn = container.querySelector('button')!;
|
|
143
|
+
expect(btn.className).toContain('bg-primary-500');
|
|
144
|
+
expect(btn.className).not.toMatch(/#[0-9a-fA-F]{3,8}/);
|
|
145
|
+
expect(btn.className).not.toMatch(/\bdark:/);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it('renders outline + danger (border color comes through)', () => {
|
|
149
|
+
const { container } = render(
|
|
150
|
+
<IconButton aria-label="x" variant="outline" color="danger">
|
|
151
|
+
<TestIcon />
|
|
152
|
+
</IconButton>
|
|
153
|
+
);
|
|
154
|
+
const btn = container.querySelector('button')!;
|
|
155
|
+
expect(btn.className).toContain('border');
|
|
156
|
+
expect(btn.className).toContain('danger');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('ghost variant uses bg-transparent', () => {
|
|
160
|
+
const { container } = render(
|
|
161
|
+
<IconButton aria-label="x" variant="ghost">
|
|
162
|
+
<TestIcon />
|
|
163
|
+
</IconButton>
|
|
164
|
+
);
|
|
165
|
+
const btn = container.querySelector('button')!;
|
|
166
|
+
expect(btn.className).toContain('bg-transparent');
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe('asChild polymorphism', () => {
|
|
171
|
+
it('renders the child via Radix Slot when asChild=true', () => {
|
|
172
|
+
const { container } = render(
|
|
173
|
+
<IconButton asChild aria-label="Open">
|
|
174
|
+
<a href="/open" data-testid="anchor-child">
|
|
175
|
+
<TestIcon />
|
|
176
|
+
</a>
|
|
177
|
+
</IconButton>
|
|
178
|
+
);
|
|
179
|
+
// Should be an <a>, not a <button>
|
|
180
|
+
const anchor = container.querySelector('a[data-testid="anchor-child"]');
|
|
181
|
+
expect(anchor).toBeTruthy();
|
|
182
|
+
expect(container.querySelector('button')).toBeNull();
|
|
183
|
+
// Anchor carries the IconButton className
|
|
184
|
+
expect(anchor!.className).toContain('aspect-square');
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('loading state', () => {
|
|
189
|
+
it('swaps the icon with a spinner', () => {
|
|
190
|
+
const { container } = render(
|
|
191
|
+
<IconButton aria-label="x" loading>
|
|
192
|
+
<TestIcon />
|
|
193
|
+
</IconButton>
|
|
194
|
+
);
|
|
195
|
+
// Icon child gone, replaced by Spinner (animate-spin is on the
|
|
196
|
+
// Spinner's outer <span> wrapper now, since Sprint 4.4 refactor
|
|
197
|
+
// delegated to the public <Spinner> component).
|
|
198
|
+
expect(screen.queryByTestId('test-icon')).toBeNull();
|
|
199
|
+
const spinner = container.querySelector('[class*="animate-spin"]');
|
|
200
|
+
expect(spinner).toBeTruthy();
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('sets aria-busy=true while loading', () => {
|
|
204
|
+
render(
|
|
205
|
+
<IconButton aria-label="x" loading>
|
|
206
|
+
<TestIcon />
|
|
207
|
+
</IconButton>
|
|
208
|
+
);
|
|
209
|
+
const btn = screen.getByRole('button');
|
|
210
|
+
expect(btn.getAttribute('aria-busy')).toBe('true');
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('is disabled while loading', () => {
|
|
214
|
+
render(
|
|
215
|
+
<IconButton aria-label="x" loading>
|
|
216
|
+
<TestIcon />
|
|
217
|
+
</IconButton>
|
|
218
|
+
);
|
|
219
|
+
const btn = screen.getByRole('button') as HTMLButtonElement;
|
|
220
|
+
expect(btn.disabled).toBe(true);
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
describe('disabled state', () => {
|
|
225
|
+
it('respects the explicit disabled prop', () => {
|
|
226
|
+
render(
|
|
227
|
+
<IconButton aria-label="x" disabled>
|
|
228
|
+
<TestIcon />
|
|
229
|
+
</IconButton>
|
|
230
|
+
);
|
|
231
|
+
const btn = screen.getByRole('button') as HTMLButtonElement;
|
|
232
|
+
expect(btn.disabled).toBe(true);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it('does not fire onClick when disabled', () => {
|
|
236
|
+
const onClick = vi.fn();
|
|
237
|
+
render(
|
|
238
|
+
<IconButton aria-label="x" disabled onClick={onClick}>
|
|
239
|
+
<TestIcon />
|
|
240
|
+
</IconButton>
|
|
241
|
+
);
|
|
242
|
+
fireEvent.click(screen.getByRole('button'));
|
|
243
|
+
expect(onClick).not.toHaveBeenCalled();
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
describe('access RBAC integration', () => {
|
|
248
|
+
it('hides the button when access.onUnauthorized=hide and subject lacks permission', () => {
|
|
249
|
+
const { container } = render(
|
|
250
|
+
<RbacProvider policy={NO_ACCESS_POLICY} subject={guestSubject}>
|
|
251
|
+
<IconButton
|
|
252
|
+
aria-label="x"
|
|
253
|
+
access={{
|
|
254
|
+
resource: 'article',
|
|
255
|
+
action: 'publish',
|
|
256
|
+
onUnauthorized: 'hide',
|
|
257
|
+
}}
|
|
258
|
+
>
|
|
259
|
+
<TestIcon />
|
|
260
|
+
</IconButton>
|
|
261
|
+
</RbacProvider>
|
|
262
|
+
);
|
|
263
|
+
expect(container.querySelector('button')).toBeNull();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('disables the button when access.onUnauthorized=disable and subject lacks permission', () => {
|
|
267
|
+
render(
|
|
268
|
+
<RbacProvider policy={NO_ACCESS_POLICY} subject={guestSubject}>
|
|
269
|
+
<IconButton
|
|
270
|
+
aria-label="x"
|
|
271
|
+
access={{
|
|
272
|
+
resource: 'article',
|
|
273
|
+
action: 'publish',
|
|
274
|
+
onUnauthorized: 'disable',
|
|
275
|
+
}}
|
|
276
|
+
>
|
|
277
|
+
<TestIcon />
|
|
278
|
+
</IconButton>
|
|
279
|
+
</RbacProvider>
|
|
280
|
+
);
|
|
281
|
+
const btn = screen.getByRole('button') as HTMLButtonElement;
|
|
282
|
+
expect(btn.disabled).toBe(true);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it('renders normally for an admin subject', () => {
|
|
286
|
+
render(
|
|
287
|
+
<RbacProvider policy={FULL_ACCESS_POLICY} subject={adminSubject}>
|
|
288
|
+
<IconButton
|
|
289
|
+
aria-label="x"
|
|
290
|
+
access={{
|
|
291
|
+
resource: 'article',
|
|
292
|
+
action: 'publish',
|
|
293
|
+
onUnauthorized: 'hide',
|
|
294
|
+
}}
|
|
295
|
+
>
|
|
296
|
+
<TestIcon />
|
|
297
|
+
</IconButton>
|
|
298
|
+
</RbacProvider>
|
|
299
|
+
);
|
|
300
|
+
expect(screen.getByRole('button')).toBeTruthy();
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
describe('click handler', () => {
|
|
305
|
+
it('fires onClick when clicked', () => {
|
|
306
|
+
const onClick = vi.fn();
|
|
307
|
+
render(
|
|
308
|
+
<IconButton aria-label="x" onClick={onClick}>
|
|
309
|
+
<TestIcon />
|
|
310
|
+
</IconButton>
|
|
311
|
+
);
|
|
312
|
+
fireEvent.click(screen.getByRole('button'));
|
|
313
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
describe('visibleWhen (engine-reactive, Sprint 4.4)', () => {
|
|
318
|
+
it('renders when visibleWhen returns true', () => {
|
|
319
|
+
const { container } = render(
|
|
320
|
+
<IconButton aria-label="x" visibleWhen={() => true}>
|
|
321
|
+
<TestIcon />
|
|
322
|
+
</IconButton>
|
|
323
|
+
);
|
|
324
|
+
expect(container.firstChild).toBeTruthy();
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('returns null when visibleWhen returns false', () => {
|
|
328
|
+
const { container } = render(
|
|
329
|
+
<IconButton aria-label="x" visibleWhen={() => false}>
|
|
330
|
+
<TestIcon />
|
|
331
|
+
</IconButton>
|
|
332
|
+
);
|
|
333
|
+
expect(container.firstChild).toBeNull();
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
it('renders normally when visibleWhen is omitted', () => {
|
|
337
|
+
const { container } = render(
|
|
338
|
+
<IconButton aria-label="x">
|
|
339
|
+
<TestIcon />
|
|
340
|
+
</IconButton>
|
|
341
|
+
);
|
|
342
|
+
expect(container.firstChild).toBeTruthy();
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
describe('overrides — sx + className', () => {
|
|
347
|
+
it('appends sx to the root className', () => {
|
|
348
|
+
const { container } = render(
|
|
349
|
+
<IconButton aria-label="x" sx="ring-2 ring-purple-500">
|
|
350
|
+
<TestIcon />
|
|
351
|
+
</IconButton>
|
|
352
|
+
);
|
|
353
|
+
const btn = container.querySelector('button')!;
|
|
354
|
+
expect(btn.className).toContain('ring-purple-500');
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
it('appends className to the root', () => {
|
|
358
|
+
const { container } = render(
|
|
359
|
+
<IconButton aria-label="x" className="my-custom-icon-btn">
|
|
360
|
+
<TestIcon />
|
|
361
|
+
</IconButton>
|
|
362
|
+
);
|
|
363
|
+
const btn = container.querySelector('button')!;
|
|
364
|
+
expect(btn.className).toContain('my-custom-icon-btn');
|
|
365
|
+
});
|
|
366
|
+
});
|
|
367
|
+
});
|