@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,291 @@
|
|
|
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 { Card, CardContent, CardActionArea } from './Card.js';
|
|
8
|
+
|
|
9
|
+
void React;
|
|
10
|
+
afterEach(() => cleanup());
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Unit tests for the Card family. Covers:
|
|
14
|
+
* - <Card>: thin Box wrapper with restricted variant axis, inherits
|
|
15
|
+
* access + visibleWhen from Box (verified at integration level)
|
|
16
|
+
* - <CardContent>: padded inner box with default p=4 and override
|
|
17
|
+
* - <CardActionArea>: clickable wrapper (button or asChild), focus
|
|
18
|
+
* ring, selected aria-pressed, disabled state, access RBAC,
|
|
19
|
+
* visibleWhen predicate
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const ADMIN_POLICY: RbacPolicy = {
|
|
23
|
+
roles: [
|
|
24
|
+
{
|
|
25
|
+
name: 'admin',
|
|
26
|
+
permissions: [{ resource: '*', action: '*', effect: 'allow' }],
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
const NO_ACCESS_POLICY: RbacPolicy = {
|
|
31
|
+
roles: [{ name: 'guest', permissions: [] }],
|
|
32
|
+
};
|
|
33
|
+
const adminSubject: Subject = { id: 'a', roles: ['admin'] };
|
|
34
|
+
const guestSubject: Subject = { id: 'g', roles: ['guest'] };
|
|
35
|
+
|
|
36
|
+
describe('<Card>', () => {
|
|
37
|
+
describe('rendering', () => {
|
|
38
|
+
it('renders children', () => {
|
|
39
|
+
render(<Card data-testid="card">hello</Card>);
|
|
40
|
+
expect(screen.getByTestId('card')).toBeTruthy();
|
|
41
|
+
expect(screen.getByText('hello')).toBeTruthy();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('applies default outlined variant (border class from Box)', () => {
|
|
45
|
+
const { container } = render(<Card>x</Card>);
|
|
46
|
+
const root = container.firstElementChild!;
|
|
47
|
+
expect(root.className).toContain('border');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('applies default rounded="lg"', () => {
|
|
51
|
+
const { container } = render(<Card>x</Card>);
|
|
52
|
+
const root = container.firstElementChild!;
|
|
53
|
+
expect(root.className).toContain('rounded-lg');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('overrides default variant to elevated', () => {
|
|
57
|
+
const { container } = render(<Card variant="elevated">x</Card>);
|
|
58
|
+
const root = container.firstElementChild!;
|
|
59
|
+
// Elevated variant uses bg-white in light mode
|
|
60
|
+
expect(root.className).toContain('bg-white');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('respects elevation override', () => {
|
|
64
|
+
const { container } = render(<Card elevation={3}>x</Card>);
|
|
65
|
+
const root = container.firstElementChild!;
|
|
66
|
+
expect(root.className).toContain('shadow-md');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('inherits visibleWhen from Box', () => {
|
|
70
|
+
const { container } = render(
|
|
71
|
+
<Card visibleWhen={() => false}>hidden</Card>
|
|
72
|
+
);
|
|
73
|
+
expect(container.firstChild).toBeNull();
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('inherits access from Box (hide mode)', () => {
|
|
77
|
+
const { container } = render(
|
|
78
|
+
<RbacProvider policy={NO_ACCESS_POLICY} subject={guestSubject}>
|
|
79
|
+
<Card
|
|
80
|
+
access={{
|
|
81
|
+
resource: 'admin',
|
|
82
|
+
action: 'read',
|
|
83
|
+
onUnauthorized: 'hide',
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
86
|
+
admin-only
|
|
87
|
+
</Card>
|
|
88
|
+
</RbacProvider>
|
|
89
|
+
);
|
|
90
|
+
expect(container.firstChild).toBeNull();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('inherits access from Box (visible for authorized subject)', () => {
|
|
94
|
+
const { container } = render(
|
|
95
|
+
<RbacProvider policy={ADMIN_POLICY} subject={adminSubject}>
|
|
96
|
+
<Card
|
|
97
|
+
access={{
|
|
98
|
+
resource: 'admin',
|
|
99
|
+
action: 'read',
|
|
100
|
+
onUnauthorized: 'hide',
|
|
101
|
+
}}
|
|
102
|
+
>
|
|
103
|
+
shown
|
|
104
|
+
</Card>
|
|
105
|
+
</RbacProvider>
|
|
106
|
+
);
|
|
107
|
+
expect(container.firstChild).toBeTruthy();
|
|
108
|
+
expect(screen.getByText('shown')).toBeTruthy();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe('<CardContent>', () => {
|
|
114
|
+
it('renders children inside a Box with default p=4', () => {
|
|
115
|
+
const { container } = render(
|
|
116
|
+
<CardContent>content</CardContent>
|
|
117
|
+
);
|
|
118
|
+
const root = container.firstElementChild!;
|
|
119
|
+
expect(root.className).toContain('p-4');
|
|
120
|
+
expect(screen.getByText('content')).toBeTruthy();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('respects custom p value', () => {
|
|
124
|
+
const { container } = render(
|
|
125
|
+
<CardContent p={6}>spacious</CardContent>
|
|
126
|
+
);
|
|
127
|
+
const root = container.firstElementChild!;
|
|
128
|
+
expect(root.className).toContain('p-6');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('respects p={0} for zero padding', () => {
|
|
132
|
+
const { container } = render(
|
|
133
|
+
<CardContent p={0}>flush</CardContent>
|
|
134
|
+
);
|
|
135
|
+
const root = container.firstElementChild!;
|
|
136
|
+
expect(root.className).toContain('p-0');
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('appends className', () => {
|
|
140
|
+
const { container } = render(
|
|
141
|
+
<CardContent className="my-custom-content">x</CardContent>
|
|
142
|
+
);
|
|
143
|
+
const root = container.firstElementChild!;
|
|
144
|
+
expect(root.className).toContain('my-custom-content');
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
describe('<CardActionArea>', () => {
|
|
149
|
+
describe('rendering', () => {
|
|
150
|
+
it('renders as <button> by default', () => {
|
|
151
|
+
render(<CardActionArea>click me</CardActionArea>);
|
|
152
|
+
expect(screen.getByRole('button', { name: /click me/i })).toBeTruthy();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('renders as the immediate child when asChild=true', () => {
|
|
156
|
+
const { container } = render(
|
|
157
|
+
<CardActionArea asChild>
|
|
158
|
+
<a href="/x" data-testid="anchor-child">link content</a>
|
|
159
|
+
</CardActionArea>
|
|
160
|
+
);
|
|
161
|
+
const anchor = container.querySelector('a[data-testid="anchor-child"]');
|
|
162
|
+
expect(anchor).toBeTruthy();
|
|
163
|
+
expect(container.querySelector('button')).toBeNull();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('applies base layout (block w-full)', () => {
|
|
167
|
+
const { container } = render(<CardActionArea>x</CardActionArea>);
|
|
168
|
+
const root = container.firstElementChild!;
|
|
169
|
+
expect(root.className).toContain('block');
|
|
170
|
+
expect(root.className).toContain('w-full');
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe('selected state', () => {
|
|
175
|
+
it('applies aria-pressed=true when selected', () => {
|
|
176
|
+
render(<CardActionArea selected>x</CardActionArea>);
|
|
177
|
+
expect(screen.getByRole('button').getAttribute('aria-pressed')).toBe('true');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('does NOT set aria-pressed when not selected', () => {
|
|
181
|
+
render(<CardActionArea>x</CardActionArea>);
|
|
182
|
+
expect(screen.getByRole('button').getAttribute('aria-pressed')).toBeNull();
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it('applies primary ring class when selected', () => {
|
|
186
|
+
const { container } = render(<CardActionArea selected>x</CardActionArea>);
|
|
187
|
+
const btn = container.firstElementChild!;
|
|
188
|
+
expect(btn.className).toContain('ring-primary-500');
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
describe('disabled state', () => {
|
|
193
|
+
it('respects explicit disabled prop', () => {
|
|
194
|
+
render(<CardActionArea disabled>x</CardActionArea>);
|
|
195
|
+
const btn = screen.getByRole('button') as HTMLButtonElement;
|
|
196
|
+
expect(btn.disabled).toBe(true);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('does NOT fire onClick when disabled', () => {
|
|
200
|
+
const onClick = vi.fn();
|
|
201
|
+
render(<CardActionArea disabled onClick={onClick}>x</CardActionArea>);
|
|
202
|
+
fireEvent.click(screen.getByRole('button'));
|
|
203
|
+
expect(onClick).not.toHaveBeenCalled();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('applies opacity-50 + cursor-not-allowed when disabled', () => {
|
|
207
|
+
const { container } = render(<CardActionArea disabled>x</CardActionArea>);
|
|
208
|
+
const btn = container.firstElementChild!;
|
|
209
|
+
expect(btn.className).toContain('opacity-50');
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
describe('click handler', () => {
|
|
214
|
+
it('fires onClick when clicked', () => {
|
|
215
|
+
const onClick = vi.fn();
|
|
216
|
+
render(<CardActionArea onClick={onClick}>x</CardActionArea>);
|
|
217
|
+
fireEvent.click(screen.getByRole('button'));
|
|
218
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe('access RBAC', () => {
|
|
223
|
+
it('hides when access.onUnauthorized=hide and subject lacks permission', () => {
|
|
224
|
+
const { container } = render(
|
|
225
|
+
<RbacProvider policy={NO_ACCESS_POLICY} subject={guestSubject}>
|
|
226
|
+
<CardActionArea
|
|
227
|
+
access={{
|
|
228
|
+
resource: 'admin',
|
|
229
|
+
action: 'read',
|
|
230
|
+
onUnauthorized: 'hide',
|
|
231
|
+
}}
|
|
232
|
+
>
|
|
233
|
+
admin-cta
|
|
234
|
+
</CardActionArea>
|
|
235
|
+
</RbacProvider>
|
|
236
|
+
);
|
|
237
|
+
expect(container.firstChild).toBeNull();
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('disables when access.onUnauthorized=disable', () => {
|
|
241
|
+
render(
|
|
242
|
+
<RbacProvider policy={NO_ACCESS_POLICY} subject={guestSubject}>
|
|
243
|
+
<CardActionArea
|
|
244
|
+
access={{
|
|
245
|
+
resource: 'admin',
|
|
246
|
+
action: 'read',
|
|
247
|
+
onUnauthorized: 'disable',
|
|
248
|
+
}}
|
|
249
|
+
>
|
|
250
|
+
disable-cta
|
|
251
|
+
</CardActionArea>
|
|
252
|
+
</RbacProvider>
|
|
253
|
+
);
|
|
254
|
+
const btn = screen.getByRole('button') as HTMLButtonElement;
|
|
255
|
+
expect(btn.disabled).toBe(true);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('renders normally for authorized subject', () => {
|
|
259
|
+
render(
|
|
260
|
+
<RbacProvider policy={ADMIN_POLICY} subject={adminSubject}>
|
|
261
|
+
<CardActionArea
|
|
262
|
+
access={{
|
|
263
|
+
resource: 'admin',
|
|
264
|
+
action: 'read',
|
|
265
|
+
onUnauthorized: 'hide',
|
|
266
|
+
}}
|
|
267
|
+
>
|
|
268
|
+
admin-cta
|
|
269
|
+
</CardActionArea>
|
|
270
|
+
</RbacProvider>
|
|
271
|
+
);
|
|
272
|
+
expect(screen.getByText('admin-cta')).toBeTruthy();
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
describe('visibleWhen', () => {
|
|
277
|
+
it('renders when predicate returns true', () => {
|
|
278
|
+
render(
|
|
279
|
+
<CardActionArea visibleWhen={() => true}>shown</CardActionArea>
|
|
280
|
+
);
|
|
281
|
+
expect(screen.getByText('shown')).toBeTruthy();
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it('returns null when predicate returns false', () => {
|
|
285
|
+
const { container } = render(
|
|
286
|
+
<CardActionArea visibleWhen={() => false}>hidden</CardActionArea>
|
|
287
|
+
);
|
|
288
|
+
expect(container.firstChild).toBeNull();
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
});
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { forwardRef, useContext } from 'react';
|
|
2
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
3
|
+
import { DashFormContext, useEngineVisibility } from '@dashforge/ui-core';
|
|
4
|
+
import { cn } from '../../utils/cn.js';
|
|
5
|
+
import { useAccessState } from '../../hooks/useAccessState.js';
|
|
6
|
+
import { Box } from '../Box/Box.js';
|
|
7
|
+
import type {
|
|
8
|
+
CardActionAreaProps,
|
|
9
|
+
CardContentProps,
|
|
10
|
+
CardProps,
|
|
11
|
+
} from './card.types.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* `<Card>` — opinionated surface preset over `<Box>`.
|
|
15
|
+
*
|
|
16
|
+
* Thin alias that pre-fills card-shaped Box defaults (`outlined`,
|
|
17
|
+
* `rounded='lg'`, `elevation=1`, no padding). Reads as `<Card>` in
|
|
18
|
+
* consumer code while reusing every Box affordance: surface variants,
|
|
19
|
+
* 7 intent colors, spacing scale, polymorphism, and the bridge
|
|
20
|
+
* integration (`access` + `visibleWhen`) retrofitted to Box in 1.1.0.
|
|
21
|
+
*
|
|
22
|
+
* Restricted variant axis: only `'outlined' | 'elevated' | 'plain'`.
|
|
23
|
+
* `'soft'` and `'solid'` are deliberately excluded — they belong to
|
|
24
|
+
* Box (as `<Alert>`-shaped callouts) and to banners, not to cards.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* // Most common — outlined card with content padding via CardContent
|
|
29
|
+
* <Card>
|
|
30
|
+
* <CardContent>
|
|
31
|
+
* <Typography variant="h3">Title</Typography>
|
|
32
|
+
* <Typography variant="body">Body</Typography>
|
|
33
|
+
* </CardContent>
|
|
34
|
+
* </Card>
|
|
35
|
+
*
|
|
36
|
+
* // Elevated, clickable, gated by RBAC (inherits access from Box)
|
|
37
|
+
* <Card
|
|
38
|
+
* variant="elevated"
|
|
39
|
+
* elevation={2}
|
|
40
|
+
* access={{ resource: 'billing', action: 'read', onUnauthorized: 'hide' }}
|
|
41
|
+
* >
|
|
42
|
+
* <CardActionArea onClick={openBilling}>
|
|
43
|
+
* <CardContent>
|
|
44
|
+
* <Typography variant="h3">Revenue</Typography>
|
|
45
|
+
* </CardContent>
|
|
46
|
+
* </CardActionArea>
|
|
47
|
+
* </Card>
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export const Card = forwardRef<HTMLElement, CardProps>(function Card(
|
|
51
|
+
props,
|
|
52
|
+
ref
|
|
53
|
+
) {
|
|
54
|
+
const {
|
|
55
|
+
variant = 'outlined',
|
|
56
|
+
rounded = 'lg',
|
|
57
|
+
elevation = 1,
|
|
58
|
+
p = 0,
|
|
59
|
+
children,
|
|
60
|
+
...rest
|
|
61
|
+
} = props;
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<Box
|
|
65
|
+
ref={ref}
|
|
66
|
+
variant={variant}
|
|
67
|
+
rounded={rounded}
|
|
68
|
+
elevation={elevation}
|
|
69
|
+
p={p}
|
|
70
|
+
{...rest}
|
|
71
|
+
>
|
|
72
|
+
{children}
|
|
73
|
+
</Box>
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
Card.displayName = 'Card';
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* `<CardContent>` — padded inner section of a Card.
|
|
81
|
+
*
|
|
82
|
+
* Semantic alias for an inner `<Box p={4}>`. The default padding step
|
|
83
|
+
* (4) maps to `--df-tw-spacing-4` (1rem) via the dashforgePreset,
|
|
84
|
+
* matching common card-content paddings across MUI / shadcn / Chakra.
|
|
85
|
+
* Override `p` to dial up/down per the spacing token scale.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```tsx
|
|
89
|
+
* <Card>
|
|
90
|
+
* <CardContent p={6}> {/* bigger inner padding *}/}
|
|
91
|
+
* <Typography variant="h3">Spacious card</Typography>
|
|
92
|
+
* </CardContent>
|
|
93
|
+
* </Card>
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export function CardContent({
|
|
97
|
+
p = 4,
|
|
98
|
+
children,
|
|
99
|
+
className,
|
|
100
|
+
sx,
|
|
101
|
+
}: CardContentProps) {
|
|
102
|
+
return (
|
|
103
|
+
<Box p={p} sx={cn(className, sx as string | undefined)}>
|
|
104
|
+
{children}
|
|
105
|
+
</Box>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
CardContent.displayName = 'CardContent';
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* `<CardActionArea>` — clickable wrapper for Card content.
|
|
113
|
+
*
|
|
114
|
+
* Adds focus ring + hover tint + Radix Slot polymorphism. Renders as
|
|
115
|
+
* `<button type="button">` by default, or as the immediate child via
|
|
116
|
+
* `asChild` (typical pattern: wrap a router `<Link>`).
|
|
117
|
+
*
|
|
118
|
+
* Bridge integration is local — CardActionArea is an action trigger
|
|
119
|
+
* (not a surface), so it carries `access` + `visibleWhen` directly
|
|
120
|
+
* (rather than relying on the wrapping Card's props). This lets the
|
|
121
|
+
* consumer differentiate "the card is visible but not clickable" from
|
|
122
|
+
* "the card is not visible at all".
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```tsx
|
|
126
|
+
* // Card-as-CTA
|
|
127
|
+
* <Card>
|
|
128
|
+
* <CardActionArea onClick={navigate}>
|
|
129
|
+
* <CardContent>
|
|
130
|
+
* <Typography variant="h3">Open dashboard</Typography>
|
|
131
|
+
* <Typography variant="body">Hover to see the focus ring.</Typography>
|
|
132
|
+
* </CardContent>
|
|
133
|
+
* </CardActionArea>
|
|
134
|
+
* </Card>
|
|
135
|
+
*
|
|
136
|
+
* // Polymorphic — wrap a router Link
|
|
137
|
+
* <Card>
|
|
138
|
+
* <CardActionArea asChild>
|
|
139
|
+
* <Link to="/billing">
|
|
140
|
+
* <CardContent>
|
|
141
|
+
* <Typography variant="h3">Billing</Typography>
|
|
142
|
+
* </CardContent>
|
|
143
|
+
* </Link>
|
|
144
|
+
* </CardActionArea>
|
|
145
|
+
* </Card>
|
|
146
|
+
*
|
|
147
|
+
* // Selectable card (filter / option pattern)
|
|
148
|
+
* <CardActionArea
|
|
149
|
+
* selected={selected === 'monthly'}
|
|
150
|
+
* onClick={() => setSelected('monthly')}
|
|
151
|
+
* >
|
|
152
|
+
* <CardContent>Monthly plan</CardContent>
|
|
153
|
+
* </CardActionArea>
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export const CardActionArea = forwardRef<HTMLButtonElement, CardActionAreaProps>(
|
|
157
|
+
function CardActionArea(props, ref) {
|
|
158
|
+
const {
|
|
159
|
+
children,
|
|
160
|
+
asChild,
|
|
161
|
+
selected,
|
|
162
|
+
access,
|
|
163
|
+
visibleWhen,
|
|
164
|
+
disabled,
|
|
165
|
+
sx,
|
|
166
|
+
className,
|
|
167
|
+
onClick,
|
|
168
|
+
...rest
|
|
169
|
+
} = props;
|
|
170
|
+
|
|
171
|
+
// Bridge — both hooks called unconditionally (rules-of-hooks).
|
|
172
|
+
const bridge = useContext(DashFormContext);
|
|
173
|
+
const isVisible = useEngineVisibility(bridge?.engine, visibleWhen);
|
|
174
|
+
const accessState = useAccessState(access);
|
|
175
|
+
|
|
176
|
+
if (!isVisible || !accessState.visible) return null;
|
|
177
|
+
|
|
178
|
+
const isDisabled =
|
|
179
|
+
Boolean(disabled) || accessState.disabled || accessState.readonly;
|
|
180
|
+
|
|
181
|
+
// The action area must SPAN the parent Card so the entire surface
|
|
182
|
+
// is clickable. Includes focus ring, hover, and a subtle pressed
|
|
183
|
+
// tint via `data-pressed`. Token-driven via dashforgePreset.
|
|
184
|
+
const classes = cn(
|
|
185
|
+
'block w-full text-left',
|
|
186
|
+
'outline-none rounded-[inherit]',
|
|
187
|
+
'transition-colors',
|
|
188
|
+
// Hover — gentle bg tint on top of the card surface. Uses
|
|
189
|
+
// currentColor with 5% alpha so it composes with any Card
|
|
190
|
+
// variant/color without hardcoding.
|
|
191
|
+
'hover:bg-current/5',
|
|
192
|
+
// Focus ring — keyboard-navigable, primary tone, inset slightly
|
|
193
|
+
// so it traces the card's inherited radius.
|
|
194
|
+
'focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-1',
|
|
195
|
+
// Selected — adds a primary tone ring + soft tint so the card
|
|
196
|
+
// visually reads as "active option" without changing the parent
|
|
197
|
+
// Card's variant.
|
|
198
|
+
selected && 'ring-2 ring-primary-500 ring-offset-1 bg-primary-50/60 dark:bg-primary-950/40',
|
|
199
|
+
// Disabled — dims content and suppresses clicks.
|
|
200
|
+
isDisabled && 'opacity-50 cursor-not-allowed pointer-events-none',
|
|
201
|
+
sx,
|
|
202
|
+
className
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const handleClick: React.MouseEventHandler<HTMLButtonElement> = (e) => {
|
|
206
|
+
if (isDisabled) return;
|
|
207
|
+
onClick?.(e);
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
if (asChild) {
|
|
211
|
+
return (
|
|
212
|
+
<Slot
|
|
213
|
+
ref={ref}
|
|
214
|
+
className={classes}
|
|
215
|
+
data-disabled={isDisabled || undefined}
|
|
216
|
+
aria-disabled={isDisabled || undefined}
|
|
217
|
+
aria-pressed={selected ? true : undefined}
|
|
218
|
+
onClick={handleClick}
|
|
219
|
+
>
|
|
220
|
+
{children}
|
|
221
|
+
</Slot>
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return (
|
|
226
|
+
<button
|
|
227
|
+
ref={ref}
|
|
228
|
+
type="button"
|
|
229
|
+
className={classes}
|
|
230
|
+
disabled={isDisabled}
|
|
231
|
+
aria-pressed={selected ? true : undefined}
|
|
232
|
+
onClick={handleClick}
|
|
233
|
+
{...rest}
|
|
234
|
+
>
|
|
235
|
+
{children}
|
|
236
|
+
</button>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
CardActionArea.displayName = 'CardActionArea';
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef, 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
|
+
import type { BoxProps } from '../Box/box.types.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* `<Card>` — opinionated surface preset over `<Box>`.
|
|
9
|
+
*
|
|
10
|
+
* Architectural note: `<Box>` already implements the full surface
|
|
11
|
+
* vocabulary (variant × color, elevation, rounded, spacing). `<Card>`
|
|
12
|
+
* exists for **two reasons** on top of Box:
|
|
13
|
+
*
|
|
14
|
+
* 1. **MUI mental model** — devs migrating from `@mui/material/Card`
|
|
15
|
+
* reach for `<Card>` reflexively. Having the component (as a
|
|
16
|
+
* thin Box alias with card-shaped defaults) removes adoption
|
|
17
|
+
* friction without duplicating the surface system.
|
|
18
|
+
* 2. **Restricted variant axis** — Card excludes `'soft'` and
|
|
19
|
+
* `'solid'` from Box's 5 variants. A "solid card" is semantically
|
|
20
|
+
* a banner; a "soft card" is a callout (use `<Alert>`). Restricting
|
|
21
|
+
* to `'outlined' | 'elevated' | 'plain'` is opinionated typing
|
|
22
|
+
* that catches misuse at compile time.
|
|
23
|
+
*
|
|
24
|
+
* Card inherits `access` + `visibleWhen` from Box (Sprint 4.4 surface
|
|
25
|
+
* alignment) automatically — no per-component wiring needed.
|
|
26
|
+
*
|
|
27
|
+
* Defaults set by Card (override at the call site):
|
|
28
|
+
* - `variant='outlined'` → soft border + bg tint (most card-like)
|
|
29
|
+
* - `rounded='lg'` → 8px radius
|
|
30
|
+
* - `elevation={1}` → faint shadow for visual weight
|
|
31
|
+
* - `p={0}` → no inner padding (use `<CardContent>`)
|
|
32
|
+
*/
|
|
33
|
+
export interface CardProps
|
|
34
|
+
extends Omit<BoxProps, 'variant'> {
|
|
35
|
+
/**
|
|
36
|
+
* Restricted variant — only the three card-appropriate Box variants.
|
|
37
|
+
* - `'outlined'` (default) — bordered surface with subtle tint.
|
|
38
|
+
* - `'elevated'` — surface with shadow, no border.
|
|
39
|
+
* - `'plain'` — bare surface (background + radius), no border, no
|
|
40
|
+
* shadow. Use when wrapping content that already provides chrome.
|
|
41
|
+
*
|
|
42
|
+
* @default 'outlined'
|
|
43
|
+
*/
|
|
44
|
+
variant?: 'outlined' | 'elevated' | 'plain';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* `<CardContent>` — padded inner section of a Card.
|
|
49
|
+
*
|
|
50
|
+
* A semantic alias for `<Box p={4}>` (or the equivalent spacing
|
|
51
|
+
* step). Reads better in starter-kit code than the equivalent Box
|
|
52
|
+
* call — the consumer expresses "this is the content area of the
|
|
53
|
+
* card" rather than "this is a box with padding-4 inside a card".
|
|
54
|
+
*
|
|
55
|
+
* No surface props — CardContent inherits its background from the
|
|
56
|
+
* parent Card. The only configurable axis is the padding step.
|
|
57
|
+
*/
|
|
58
|
+
export interface CardContentProps {
|
|
59
|
+
/**
|
|
60
|
+
* Inner padding token step (same scale as `<Box p>`).
|
|
61
|
+
* @default 4
|
|
62
|
+
*/
|
|
63
|
+
p?: BoxProps['p'];
|
|
64
|
+
|
|
65
|
+
/** Content of the section. */
|
|
66
|
+
children: ReactNode;
|
|
67
|
+
|
|
68
|
+
/** Standard React `className` — appended to the root via `cn()`. */
|
|
69
|
+
className?: string;
|
|
70
|
+
|
|
71
|
+
/** Root-element class shortcut (string or clsx-compatible value). */
|
|
72
|
+
sx?: ClassValue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* `<CardActionArea>` — clickable wrapper inside (or around) a Card.
|
|
77
|
+
*
|
|
78
|
+
* The single value-add over a raw `<Box>` wrapper: focus ring +
|
|
79
|
+
* hover state + Radix Slot polymorphism so the wrapper can become a
|
|
80
|
+
* router `<Link>` without nesting `<a>` inside `<button>` (a11y
|
|
81
|
+
* violation).
|
|
82
|
+
*
|
|
83
|
+
* Use cases:
|
|
84
|
+
* - "Card-as-CTA" patterns where the whole card surface should be
|
|
85
|
+
* clickable (e.g. "Open dashboard" tile)
|
|
86
|
+
* - Card-shaped router links in dashboards / navigation grids
|
|
87
|
+
* - Selectable cards in galleries (with `selected` + `onClick`)
|
|
88
|
+
*
|
|
89
|
+
* Always renders as `<button>` (or the asChild element) — focusable,
|
|
90
|
+
* keyboard-accessible by default. `aria-pressed` when `selected=true`
|
|
91
|
+
* for the toggle pattern (filter card / option card).
|
|
92
|
+
*/
|
|
93
|
+
export interface CardActionAreaProps
|
|
94
|
+
extends Omit<ComponentPropsWithoutRef<'button'>, 'className' | 'color'> {
|
|
95
|
+
/** The card body / content to wrap. */
|
|
96
|
+
children: ReactNode;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Render-as-child via Radix Slot. The CardActionArea styles paint
|
|
100
|
+
* onto the immediate child element (typically a router `<Link>`).
|
|
101
|
+
* No `<button>` DOM emitted.
|
|
102
|
+
*/
|
|
103
|
+
asChild?: boolean;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Selected state — for toggle / option-card patterns. Adds
|
|
107
|
+
* `aria-pressed="true"` and a primary-toned focus ring even when
|
|
108
|
+
* not focused.
|
|
109
|
+
*/
|
|
110
|
+
selected?: boolean;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* RBAC requirement — controls clickability via the centralized
|
|
114
|
+
* `@dashforge/rbac` policy engine.
|
|
115
|
+
* - `onUnauthorized: 'hide'` → action area does not render
|
|
116
|
+
* - `onUnauthorized: 'disable'` → clicks suppressed + dimmed
|
|
117
|
+
* - `onUnauthorized: 'readonly'` → mapped to disabled
|
|
118
|
+
*/
|
|
119
|
+
access?: AccessRequirement;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Engine-reactive visibility predicate — Sprint 4.4 alignment.
|
|
123
|
+
* When the predicate returns `false`, the action area renders `null`.
|
|
124
|
+
*/
|
|
125
|
+
visibleWhen?: (engine: Engine) => boolean;
|
|
126
|
+
|
|
127
|
+
/** Root-element class shortcut. */
|
|
128
|
+
sx?: ClassValue;
|
|
129
|
+
|
|
130
|
+
/** Standard React className — appended via `cn()`. */
|
|
131
|
+
className?: string;
|
|
132
|
+
}
|