@dashforge/tw 1.1.0 → 1.1.1
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 +21 -1
- package/dist/index.esm.js +1 -1
- package/dist/src/index.d.ts +1 -1
- package/package.json +8 -3
- package/.swcrc +0 -29
- package/A11Y.md +0 -130
- package/CONSUMER-VALIDATION.md +0 -130
- package/COVERAGE.md +0 -63
- package/PARITY.md +0 -481
- package/PERFORMANCE.md +0 -227
- package/REFINEMENT-NOTES.md +0 -50
- package/THEME-AUDIT.md +0 -174
- package/dashforge-tw-1.0.0.tgz +0 -0
- package/eslint.config.mjs +0 -62
- package/project.json +0 -15
- package/rollup.config.cjs +0 -16
- package/src/components/Accordion/Accordion.test.tsx +0 -95
- package/src/components/Accordion/Accordion.tsx +0 -97
- package/src/components/Accordion/accordion.types.ts +0 -66
- package/src/components/Accordion/accordion.variants.ts +0 -32
- package/src/components/Alert/Alert.test.tsx +0 -302
- package/src/components/Alert/Alert.tsx +0 -186
- package/src/components/Alert/alert.types.ts +0 -144
- package/src/components/Alert/alert.variants.ts +0 -71
- package/src/components/AppShell/AppShell.test.tsx +0 -223
- package/src/components/AppShell/AppShell.tsx +0 -239
- package/src/components/AppShell/appShell.types.ts +0 -49
- package/src/components/AppShell/appShell.variants.ts +0 -54
- package/src/components/AspectRatio/AspectRatio.test.tsx +0 -173
- package/src/components/AspectRatio/AspectRatio.tsx +0 -73
- package/src/components/AspectRatio/aspectRatio.types.ts +0 -54
- package/src/components/Autocomplete/Autocomplete.perf.test.tsx +0 -225
- package/src/components/Autocomplete/Autocomplete.test.tsx +0 -556
- package/src/components/Autocomplete/Autocomplete.tsx +0 -1069
- package/src/components/Autocomplete/autocomplete.types.ts +0 -198
- package/src/components/Autocomplete/autocomplete.variants.ts +0 -141
- package/src/components/Avatar/Avatar.test.tsx +0 -287
- package/src/components/Avatar/Avatar.tsx +0 -304
- package/src/components/Avatar/avatar.types.ts +0 -205
- package/src/components/Avatar/avatar.variants.ts +0 -194
- package/src/components/Badge/Badge.test.tsx +0 -385
- package/src/components/Badge/Badge.tsx +0 -174
- package/src/components/Badge/badge.types.ts +0 -154
- package/src/components/Badge/badge.variants.ts +0 -161
- package/src/components/Box/Box.test.tsx +0 -391
- package/src/components/Box/Box.tsx +0 -112
- package/src/components/Box/box.types.ts +0 -116
- package/src/components/Box/box.variants.ts +0 -230
- package/src/components/Breadcrumbs/Breadcrumbs.perf.test.tsx +0 -128
- package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +0 -231
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +0 -203
- package/src/components/Breadcrumbs/breadcrumbs.types.ts +0 -87
- package/src/components/Breadcrumbs/breadcrumbs.variants.ts +0 -54
- package/src/components/Button/Button.test.tsx +0 -204
- package/src/components/Button/Button.tsx +0 -151
- package/src/components/Button/button.types.ts +0 -110
- package/src/components/Button/button.variants.ts +0 -159
- package/src/components/Calendar/Calendar.test.tsx +0 -75
- package/src/components/Calendar/Calendar.tsx +0 -264
- package/src/components/Calendar/calendar.types.ts +0 -65
- package/src/components/Calendar/calendar.variants.ts +0 -64
- package/src/components/Card/Card.test.tsx +0 -291
- package/src/components/Card/Card.tsx +0 -241
- package/src/components/Card/card.types.ts +0 -132
- package/src/components/Checkbox/Checkbox.test.tsx +0 -146
- package/src/components/Checkbox/Checkbox.tsx +0 -286
- package/src/components/Checkbox/checkbox.types.ts +0 -88
- package/src/components/Checkbox/checkbox.variants.ts +0 -68
- package/src/components/Chip/Chip.test.tsx +0 -316
- package/src/components/Chip/Chip.tsx +0 -224
- package/src/components/Chip/chip.types.ts +0 -128
- package/src/components/Chip/chip.variants.ts +0 -173
- package/src/components/ConfirmDialog/ConfirmDialog.perf.test.tsx +0 -172
- package/src/components/ConfirmDialog/ConfirmDialog.test.tsx +0 -311
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +0 -252
- package/src/components/ConfirmDialog/confirmDialog.types.ts +0 -70
- package/src/components/ConfirmDialog/confirmDialog.variants.ts +0 -76
- package/src/components/Container/Container.test.tsx +0 -209
- package/src/components/Container/Container.tsx +0 -74
- package/src/components/Container/container.types.ts +0 -45
- package/src/components/Container/container.variants.ts +0 -81
- package/src/components/DataGrid/DataGrid.perf.test.tsx +0 -114
- package/src/components/DataGrid/DataGrid.test.tsx +0 -1153
- package/src/components/DataGrid/DataGrid.tsx +0 -1282
- package/src/components/DataGrid/dataGrid.types.ts +0 -238
- package/src/components/DataGrid/dataGrid.variants.ts +0 -152
- package/src/components/DataGrid/filters/ColumnFilters.test.tsx +0 -330
- package/src/components/DataGrid/filters/ColumnFilters.tsx +0 -456
- package/src/components/DataGrid/reorder/useColumnReorder.test.ts +0 -130
- package/src/components/DataGrid/reorder/useColumnReorder.ts +0 -144
- package/src/components/DataGrid/resize/useColumnResize.test.ts +0 -144
- package/src/components/DataGrid/resize/useColumnResize.ts +0 -135
- package/src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx +0 -186
- package/src/components/DatePicker/DatePicker.test.tsx +0 -76
- package/src/components/DatePicker/DatePicker.tsx +0 -305
- package/src/components/DatePicker/datePicker.types.ts +0 -77
- package/src/components/DatePicker/datePicker.variants.ts +0 -50
- package/src/components/DateRangePicker/DateRangePicker.test.tsx +0 -92
- package/src/components/DateRangePicker/DateRangePicker.tsx +0 -510
- package/src/components/DateRangePicker/dateRangePicker.types.ts +0 -74
- package/src/components/DateRangePicker/dateRangePicker.variants.ts +0 -101
- package/src/components/DateTimePicker/DateTimePicker.test.tsx +0 -78
- package/src/components/DateTimePicker/DateTimePicker.tsx +0 -347
- package/src/components/DateTimePicker/dateTimePicker.types.ts +0 -79
- package/src/components/DateTimePicker/dateTimePicker.variants.ts +0 -55
- package/src/components/Dialog/Dialog.test.tsx +0 -96
- package/src/components/Dialog/Dialog.tsx +0 -102
- package/src/components/Dialog/dialog.types.ts +0 -62
- package/src/components/Dialog/dialog.variants.ts +0 -66
- package/src/components/Divider/Divider.test.tsx +0 -243
- package/src/components/Divider/Divider.tsx +0 -140
- package/src/components/Divider/divider.types.ts +0 -52
- package/src/components/Divider/divider.variants.ts +0 -116
- package/src/components/Grid/Grid.test.tsx +0 -321
- package/src/components/Grid/Grid.tsx +0 -148
- package/src/components/Grid/grid.types.ts +0 -112
- package/src/components/Grid/grid.variants.ts +0 -133
- package/src/components/IconButton/IconButton.test.tsx +0 -367
- package/src/components/IconButton/IconButton.tsx +0 -159
- package/src/components/IconButton/iconButton.types.ts +0 -106
- package/src/components/IconButton/iconButton.variants.ts +0 -31
- package/src/components/LeftNav/LeftNav.perf.test.tsx +0 -172
- package/src/components/LeftNav/LeftNav.test.tsx +0 -302
- package/src/components/LeftNav/LeftNav.tsx +0 -330
- package/src/components/LeftNav/leftNav.types.ts +0 -120
- package/src/components/LeftNav/leftNav.variants.ts +0 -107
- package/src/components/Menu/Menu.test.tsx +0 -408
- package/src/components/Menu/Menu.tsx +0 -335
- package/src/components/Menu/menu.types.ts +0 -221
- package/src/components/Menu/menu.variants.ts +0 -132
- package/src/components/NumberField/NumberField.test.tsx +0 -83
- package/src/components/NumberField/NumberField.tsx +0 -321
- package/src/components/NumberField/numberField.types.ts +0 -72
- package/src/components/NumberField/numberField.variants.ts +0 -94
- package/src/components/OTPField/OTPField.test.tsx +0 -121
- package/src/components/OTPField/OTPField.tsx +0 -250
- package/src/components/OTPField/otpField.types.ts +0 -58
- package/src/components/OTPField/otpField.variants.ts +0 -72
- package/src/components/Pagination/Pagination.test.tsx +0 -314
- package/src/components/Pagination/Pagination.tsx +0 -277
- package/src/components/Pagination/pagination.helpers.ts +0 -102
- package/src/components/Pagination/pagination.types.ts +0 -117
- package/src/components/Pagination/pagination.variants.ts +0 -117
- package/src/components/Popover/Popover.test.tsx +0 -72
- package/src/components/Popover/Popover.tsx +0 -55
- package/src/components/Popover/popover.types.ts +0 -42
- package/src/components/Popover/popover.variants.ts +0 -24
- package/src/components/RadioGroup/RadioGroup.test.tsx +0 -140
- package/src/components/RadioGroup/RadioGroup.tsx +0 -283
- package/src/components/RadioGroup/radioGroup.types.ts +0 -85
- package/src/components/RadioGroup/radioGroup.variants.ts +0 -87
- package/src/components/Skeleton/Skeleton.test.tsx +0 -127
- package/src/components/Skeleton/Skeleton.tsx +0 -49
- package/src/components/Skeleton/skeleton.types.ts +0 -59
- package/src/components/Skeleton/skeleton.variants.ts +0 -87
- package/src/components/Snackbar/Snackbar.perf.test.tsx +0 -144
- package/src/components/Snackbar/Snackbar.test.tsx +0 -327
- package/src/components/Snackbar/Snackbar.tsx +0 -316
- package/src/components/Snackbar/snackbar.types.ts +0 -127
- package/src/components/Snackbar/snackbar.variants.ts +0 -81
- package/src/components/Spinner/Spinner.test.tsx +0 -199
- package/src/components/Spinner/Spinner.tsx +0 -158
- package/src/components/Spinner/spinner.types.ts +0 -113
- package/src/components/Spinner/spinner.variants.ts +0 -83
- package/src/components/Stack/Stack.test.tsx +0 -309
- package/src/components/Stack/Stack.tsx +0 -115
- package/src/components/Stack/stack.types.ts +0 -68
- package/src/components/Stack/stack.variants.ts +0 -80
- package/src/components/Switch/Switch.test.tsx +0 -131
- package/src/components/Switch/Switch.tsx +0 -158
- package/src/components/Switch/switch.types.ts +0 -36
- package/src/components/Switch/switch.variants.ts +0 -70
- package/src/components/Table/Table.perf.test.tsx +0 -81
- package/src/components/Table/Table.test.tsx +0 -674
- package/src/components/Table/Table.tsx +0 -863
- package/src/components/Table/cells/RenderButton.tsx +0 -23
- package/src/components/Table/cells/RenderChip.tsx +0 -37
- package/src/components/Table/cells/RenderText.tsx +0 -37
- package/src/components/Table/cells/RenderTwoLine.tsx +0 -34
- package/src/components/Table/cells/RowActionsMenu.tsx +0 -147
- package/src/components/Table/cells/cells.test.tsx +0 -247
- package/src/components/Table/cells/index.ts +0 -14
- package/src/components/Table/table.types.ts +0 -438
- package/src/components/Table/table.variants.ts +0 -207
- package/src/components/Tabs/Tabs.test.tsx +0 -145
- package/src/components/Tabs/Tabs.tsx +0 -77
- package/src/components/Tabs/tabs.types.ts +0 -55
- package/src/components/Tabs/tabs.variants.ts +0 -69
- package/src/components/Tabs/useTabs.ts +0 -167
- package/src/components/TextField/TextField.test.tsx +0 -198
- package/src/components/TextField/TextField.tsx +0 -245
- package/src/components/TextField/textField.types.ts +0 -90
- package/src/components/TextField/textField.variants.ts +0 -105
- package/src/components/Textarea/Textarea.test.tsx +0 -75
- package/src/components/Textarea/Textarea.tsx +0 -190
- package/src/components/Textarea/textarea.types.ts +0 -60
- package/src/components/Textarea/textarea.variants.ts +0 -85
- package/src/components/TimePicker/TimePicker.test.tsx +0 -65
- package/src/components/TimePicker/TimePicker.tsx +0 -274
- package/src/components/TimePicker/timePicker.types.ts +0 -69
- package/src/components/TimePicker/timePicker.variants.ts +0 -53
- package/src/components/Tooltip/Tooltip.test.tsx +0 -73
- package/src/components/Tooltip/Tooltip.tsx +0 -70
- package/src/components/Tooltip/tooltip.types.ts +0 -44
- package/src/components/Tooltip/tooltip.variants.ts +0 -28
- package/src/components/TopBar/TopBar.test.tsx +0 -129
- package/src/components/TopBar/TopBar.tsx +0 -66
- package/src/components/TopBar/topBar.types.ts +0 -42
- package/src/components/TopBar/topBar.variants.ts +0 -38
- package/src/components/Typography/Typography.test.tsx +0 -247
- package/src/components/Typography/Typography.tsx +0 -112
- package/src/components/Typography/typography.types.ts +0 -65
- package/src/components/Typography/typography.variants.ts +0 -130
- package/src/components/VisuallyHidden/VisuallyHidden.test.tsx +0 -86
- package/src/components/VisuallyHidden/VisuallyHidden.tsx +0 -59
- package/src/components/VisuallyHidden/visuallyHidden.types.ts +0 -45
- package/src/components/_shared/data/getNestedValue.test.ts +0 -50
- package/src/components/_shared/data/getNestedValue.ts +0 -32
- package/src/components/_shared/data/useColumnAutoDetect.test.ts +0 -123
- package/src/components/_shared/data/useColumnAutoDetect.ts +0 -100
- package/src/components/_shared/data/useControllableState.ts +0 -48
- package/src/components/_shared/data/useDebouncedValue.ts +0 -24
- package/src/components/_shared/data/useTableFilter.test.ts +0 -166
- package/src/components/_shared/data/useTableFilter.ts +0 -118
- package/src/components/_shared/data/useTableSearch.test.ts +0 -115
- package/src/components/_shared/data/useTableSearch.ts +0 -66
- package/src/components/_shared/data/useTableSelection.test.ts +0 -100
- package/src/components/_shared/data/useTableSelection.ts +0 -100
- package/src/components/_shared/data/useTableSort.test.ts +0 -150
- package/src/components/_shared/data/useTableSort.ts +0 -141
- package/src/components/_shared/data/useVirtualizer.test.ts +0 -158
- package/src/components/_shared/data/useVirtualizer.ts +0 -199
- package/src/components/_shared/resolveValidationState.ts +0 -60
- package/src/components/_shared/severity/index.ts +0 -33
- package/src/components/_shared/severity/severity.types.ts +0 -50
- package/src/components/_shared/severity/severityIcons.tsx +0 -104
- package/src/components/_shared/severity/severityVariants.test.ts +0 -136
- package/src/components/_shared/severity/severityVariants.ts +0 -115
- package/src/components/_shared/themeIdentity.test.ts +0 -113
- package/src/hooks/useAccessState.spec.tsx +0 -161
- package/src/hooks/useAccessState.ts +0 -81
- package/src/index.ts +0 -550
- package/src/utils/cn.spec.ts +0 -16
- package/src/utils/cn.ts +0 -29
- package/test-output/vitest/coverage/base.css +0 -224
- package/test-output/vitest/coverage/block-navigation.js +0 -87
- package/test-output/vitest/coverage/clover.xml +0 -2418
- package/test-output/vitest/coverage/coverage-final.json +0 -89
- package/test-output/vitest/coverage/favicon.png +0 -0
- package/test-output/vitest/coverage/index.html +0 -746
- package/test-output/vitest/coverage/prettify.css +0 -1
- package/test-output/vitest/coverage/prettify.js +0 -2
- package/test-output/vitest/coverage/sort-arrow-sprite.png +0 -0
- package/test-output/vitest/coverage/sorter.js +0 -210
- package/test-output/vitest/coverage/src/components/Accordion/Accordion.tsx.html +0 -376
- package/test-output/vitest/coverage/src/components/Accordion/accordion.variants.ts.html +0 -181
- package/test-output/vitest/coverage/src/components/Accordion/index.html +0 -131
- package/test-output/vitest/coverage/src/components/AppShell/AppShell.tsx.html +0 -802
- package/test-output/vitest/coverage/src/components/AppShell/appShell.variants.ts.html +0 -247
- package/test-output/vitest/coverage/src/components/AppShell/index.html +0 -131
- package/test-output/vitest/coverage/src/components/AspectRatio/AspectRatio.tsx.html +0 -304
- package/test-output/vitest/coverage/src/components/AspectRatio/index.html +0 -116
- package/test-output/vitest/coverage/src/components/Autocomplete/Autocomplete.tsx.html +0 -3292
- package/test-output/vitest/coverage/src/components/Autocomplete/autocomplete.variants.ts.html +0 -508
- package/test-output/vitest/coverage/src/components/Autocomplete/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Box/Box.tsx.html +0 -334
- package/test-output/vitest/coverage/src/components/Box/box.variants.ts.html +0 -775
- package/test-output/vitest/coverage/src/components/Box/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Breadcrumbs/Breadcrumbs.tsx.html +0 -694
- package/test-output/vitest/coverage/src/components/Breadcrumbs/breadcrumbs.variants.ts.html +0 -247
- package/test-output/vitest/coverage/src/components/Breadcrumbs/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Button/Button.tsx.html +0 -535
- package/test-output/vitest/coverage/src/components/Button/button.variants.ts.html +0 -562
- package/test-output/vitest/coverage/src/components/Button/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Checkbox/Checkbox.tsx.html +0 -943
- package/test-output/vitest/coverage/src/components/Checkbox/checkbox.variants.ts.html +0 -289
- package/test-output/vitest/coverage/src/components/Checkbox/index.html +0 -131
- package/test-output/vitest/coverage/src/components/ConfirmDialog/ConfirmDialog.tsx.html +0 -841
- package/test-output/vitest/coverage/src/components/ConfirmDialog/confirmDialog.variants.ts.html +0 -313
- package/test-output/vitest/coverage/src/components/ConfirmDialog/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Container/Container.tsx.html +0 -307
- package/test-output/vitest/coverage/src/components/Container/container.variants.ts.html +0 -328
- package/test-output/vitest/coverage/src/components/Container/index.html +0 -131
- package/test-output/vitest/coverage/src/components/DataGrid/DataGrid.tsx.html +0 -3937
- package/test-output/vitest/coverage/src/components/DataGrid/dataGrid.variants.ts.html +0 -541
- package/test-output/vitest/coverage/src/components/DataGrid/filters/ColumnFilters.tsx.html +0 -1453
- package/test-output/vitest/coverage/src/components/DataGrid/filters/index.html +0 -116
- package/test-output/vitest/coverage/src/components/DataGrid/index.html +0 -131
- package/test-output/vitest/coverage/src/components/DataGrid/reorder/index.html +0 -116
- package/test-output/vitest/coverage/src/components/DataGrid/reorder/useColumnReorder.ts.html +0 -517
- package/test-output/vitest/coverage/src/components/DataGrid/resize/index.html +0 -116
- package/test-output/vitest/coverage/src/components/DataGrid/resize/useColumnResize.ts.html +0 -490
- package/test-output/vitest/coverage/src/components/DataGrid/visibility/ColumnVisibilityMenu.tsx.html +0 -592
- package/test-output/vitest/coverage/src/components/DataGrid/visibility/index.html +0 -116
- package/test-output/vitest/coverage/src/components/DateTimePicker/DateTimePicker.tsx.html +0 -1042
- package/test-output/vitest/coverage/src/components/DateTimePicker/dateTimePicker.variants.ts.html +0 -337
- package/test-output/vitest/coverage/src/components/DateTimePicker/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Dialog/Dialog.tsx.html +0 -391
- package/test-output/vitest/coverage/src/components/Dialog/dialog.variants.ts.html +0 -283
- package/test-output/vitest/coverage/src/components/Dialog/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Divider/Divider.tsx.html +0 -505
- package/test-output/vitest/coverage/src/components/Divider/divider.variants.ts.html +0 -433
- package/test-output/vitest/coverage/src/components/Divider/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Grid/Grid.tsx.html +0 -529
- package/test-output/vitest/coverage/src/components/Grid/grid.variants.ts.html +0 -484
- package/test-output/vitest/coverage/src/components/Grid/index.html +0 -131
- package/test-output/vitest/coverage/src/components/LeftNav/LeftNav.tsx.html +0 -1075
- package/test-output/vitest/coverage/src/components/LeftNav/index.html +0 -131
- package/test-output/vitest/coverage/src/components/LeftNav/leftNav.variants.ts.html +0 -406
- package/test-output/vitest/coverage/src/components/NumberField/NumberField.tsx.html +0 -1048
- package/test-output/vitest/coverage/src/components/NumberField/index.html +0 -131
- package/test-output/vitest/coverage/src/components/NumberField/numberField.variants.ts.html +0 -367
- package/test-output/vitest/coverage/src/components/OTPField/OTPField.tsx.html +0 -835
- package/test-output/vitest/coverage/src/components/OTPField/index.html +0 -131
- package/test-output/vitest/coverage/src/components/OTPField/otpField.variants.ts.html +0 -301
- package/test-output/vitest/coverage/src/components/Pagination/Pagination.tsx.html +0 -916
- package/test-output/vitest/coverage/src/components/Pagination/index.html +0 -146
- package/test-output/vitest/coverage/src/components/Pagination/pagination.helpers.ts.html +0 -391
- package/test-output/vitest/coverage/src/components/Pagination/pagination.variants.ts.html +0 -436
- package/test-output/vitest/coverage/src/components/Popover/Popover.tsx.html +0 -250
- package/test-output/vitest/coverage/src/components/Popover/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Popover/popover.variants.ts.html +0 -157
- package/test-output/vitest/coverage/src/components/RadioGroup/RadioGroup.tsx.html +0 -934
- package/test-output/vitest/coverage/src/components/RadioGroup/index.html +0 -131
- package/test-output/vitest/coverage/src/components/RadioGroup/radioGroup.variants.ts.html +0 -346
- package/test-output/vitest/coverage/src/components/Skeleton/Skeleton.tsx.html +0 -232
- package/test-output/vitest/coverage/src/components/Skeleton/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Skeleton/skeleton.variants.ts.html +0 -346
- package/test-output/vitest/coverage/src/components/Snackbar/Snackbar.tsx.html +0 -979
- package/test-output/vitest/coverage/src/components/Snackbar/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Snackbar/snackbar.variants.ts.html +0 -307
- package/test-output/vitest/coverage/src/components/Stack/Stack.tsx.html +0 -430
- package/test-output/vitest/coverage/src/components/Stack/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Stack/stack.variants.ts.html +0 -325
- package/test-output/vitest/coverage/src/components/Switch/Switch.tsx.html +0 -559
- package/test-output/vitest/coverage/src/components/Switch/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Switch/switch.variants.ts.html +0 -295
- package/test-output/vitest/coverage/src/components/Table/Table.tsx.html +0 -2677
- package/test-output/vitest/coverage/src/components/Table/cells/RenderButton.tsx.html +0 -154
- package/test-output/vitest/coverage/src/components/Table/cells/RenderChip.tsx.html +0 -385
- package/test-output/vitest/coverage/src/components/Table/cells/RenderText.tsx.html +0 -196
- package/test-output/vitest/coverage/src/components/Table/cells/RenderTwoLine.tsx.html +0 -187
- package/test-output/vitest/coverage/src/components/Table/cells/RowActionsMenu.tsx.html +0 -526
- package/test-output/vitest/coverage/src/components/Table/cells/index.html +0 -191
- package/test-output/vitest/coverage/src/components/Table/cells/index.ts.html +0 -127
- package/test-output/vitest/coverage/src/components/Table/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Table/table.variants.ts.html +0 -706
- package/test-output/vitest/coverage/src/components/Tabs/Tabs.tsx.html +0 -283
- package/test-output/vitest/coverage/src/components/Tabs/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Tabs/tabs.variants.ts.html +0 -292
- package/test-output/vitest/coverage/src/components/TextField/TextField.tsx.html +0 -820
- package/test-output/vitest/coverage/src/components/TextField/index.html +0 -131
- package/test-output/vitest/coverage/src/components/TextField/textField.variants.ts.html +0 -400
- package/test-output/vitest/coverage/src/components/Textarea/Textarea.tsx.html +0 -655
- package/test-output/vitest/coverage/src/components/Textarea/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Textarea/textarea.variants.ts.html +0 -340
- package/test-output/vitest/coverage/src/components/Tooltip/Tooltip.tsx.html +0 -295
- package/test-output/vitest/coverage/src/components/Tooltip/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Tooltip/tooltip.variants.ts.html +0 -169
- package/test-output/vitest/coverage/src/components/TopBar/TopBar.tsx.html +0 -283
- package/test-output/vitest/coverage/src/components/TopBar/index.html +0 -131
- package/test-output/vitest/coverage/src/components/TopBar/topBar.variants.ts.html +0 -199
- package/test-output/vitest/coverage/src/components/Typography/Typography.tsx.html +0 -421
- package/test-output/vitest/coverage/src/components/Typography/index.html +0 -131
- package/test-output/vitest/coverage/src/components/Typography/typography.variants.ts.html +0 -436
- package/test-output/vitest/coverage/src/components/VisuallyHidden/VisuallyHidden.tsx.html +0 -262
- package/test-output/vitest/coverage/src/components/VisuallyHidden/index.html +0 -116
- package/test-output/vitest/coverage/src/components/_shared/data/getNestedValue.ts.html +0 -181
- package/test-output/vitest/coverage/src/components/_shared/data/index.html +0 -236
- package/test-output/vitest/coverage/src/components/_shared/data/useColumnAutoDetect.ts.html +0 -385
- package/test-output/vitest/coverage/src/components/_shared/data/useControllableState.ts.html +0 -229
- package/test-output/vitest/coverage/src/components/_shared/data/useDebouncedValue.ts.html +0 -157
- package/test-output/vitest/coverage/src/components/_shared/data/useTableFilter.ts.html +0 -439
- package/test-output/vitest/coverage/src/components/_shared/data/useTableSearch.ts.html +0 -283
- package/test-output/vitest/coverage/src/components/_shared/data/useTableSelection.ts.html +0 -385
- package/test-output/vitest/coverage/src/components/_shared/data/useTableSort.ts.html +0 -508
- package/test-output/vitest/coverage/src/components/_shared/data/useVirtualizer.ts.html +0 -682
- package/test-output/vitest/coverage/src/components/_shared/index.html +0 -116
- package/test-output/vitest/coverage/src/components/_shared/resolveValidationState.ts.html +0 -265
- package/test-output/vitest/coverage/src/hooks/index.html +0 -116
- package/test-output/vitest/coverage/src/hooks/useAccessState.ts.html +0 -328
- package/test-output/vitest/coverage/src/index.html +0 -116
- package/test-output/vitest/coverage/src/index.ts.html +0 -1153
- package/test-output/vitest/coverage/src/utils/cn.ts.html +0 -172
- package/test-output/vitest/coverage/src/utils/index.html +0 -116
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -58
- package/tsconfig.spec.json +0 -34
- package/vite.config.ts +0 -33
- package/vitest.config.mts +0 -29
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { tv, type VariantProps } from 'tailwind-variants';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Tailwind-variants recipe for `<Checkbox>` with slots.
|
|
5
|
-
*
|
|
6
|
-
* Slots:
|
|
7
|
-
* - `root` — outer flex wrapper enclosing the control + label
|
|
8
|
-
* - `control` — the visible square (Radix `Checkbox.Root`)
|
|
9
|
-
* - `indicator` — checkmark SVG container (Radix `Checkbox.Indicator`)
|
|
10
|
-
* - `label` — text label associated with the control
|
|
11
|
-
* - `helperText` — descriptive line below
|
|
12
|
-
* - `errorText` — error message line (semantic counterpart of helperText)
|
|
13
|
-
*
|
|
14
|
-
* Variants:
|
|
15
|
-
* - `size` : sm / md / lg (drives control box dimensions + label text size)
|
|
16
|
-
* - `error` : bool — swaps borders + helper-text color to danger tones
|
|
17
|
-
*/
|
|
18
|
-
export const checkboxVariants = tv({
|
|
19
|
-
slots: {
|
|
20
|
-
root: 'inline-flex items-start gap-2',
|
|
21
|
-
control: [
|
|
22
|
-
'inline-flex items-center justify-center shrink-0',
|
|
23
|
-
// bg-neutral-50 inverts — dark-mode aware via the dashforge preset.
|
|
24
|
-
'rounded border bg-neutral-50',
|
|
25
|
-
'border-neutral-300',
|
|
26
|
-
'transition-colors',
|
|
27
|
-
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-primary-500',
|
|
28
|
-
// Radix data-state hooks
|
|
29
|
-
'data-[state=checked]:bg-primary-500 data-[state=checked]:border-primary-500',
|
|
30
|
-
'data-[state=indeterminate]:bg-primary-500 data-[state=indeterminate]:border-primary-500',
|
|
31
|
-
'data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed',
|
|
32
|
-
],
|
|
33
|
-
indicator: 'flex items-center justify-center text-white',
|
|
34
|
-
label: 'select-none cursor-pointer text-neutral-900',
|
|
35
|
-
helperText: 'text-sm text-neutral-600 mt-1',
|
|
36
|
-
errorText: 'text-sm text-danger-600 mt-1',
|
|
37
|
-
},
|
|
38
|
-
variants: {
|
|
39
|
-
size: {
|
|
40
|
-
sm: {
|
|
41
|
-
control: 'h-4 w-4',
|
|
42
|
-
label: 'text-sm',
|
|
43
|
-
indicator: 'h-3 w-3',
|
|
44
|
-
},
|
|
45
|
-
md: {
|
|
46
|
-
control: 'h-5 w-5',
|
|
47
|
-
label: 'text-base',
|
|
48
|
-
indicator: 'h-3.5 w-3.5',
|
|
49
|
-
},
|
|
50
|
-
lg: {
|
|
51
|
-
control: 'h-6 w-6',
|
|
52
|
-
label: 'text-lg',
|
|
53
|
-
indicator: 'h-4 w-4',
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
error: {
|
|
57
|
-
true: {
|
|
58
|
-
control: 'border-danger-500 focus-visible:ring-danger-500',
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
},
|
|
62
|
-
defaultVariants: {
|
|
63
|
-
size: 'md',
|
|
64
|
-
error: false,
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
export type CheckboxVariants = VariantProps<typeof checkboxVariants>;
|
|
@@ -1,316 +0,0 @@
|
|
|
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 { Chip } from './Chip.js';
|
|
8
|
-
|
|
9
|
-
void React;
|
|
10
|
-
afterEach(() => cleanup());
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* `<Chip>` unit tests. Covers:
|
|
14
|
-
* - static vs clickable rendering (span vs button)
|
|
15
|
-
* - sample variant × color cells (token-driven, no hardcoded hex)
|
|
16
|
-
* - icon / avatar leading slots (avatar wins when both set)
|
|
17
|
-
* - onClick (clickable) and onDelete (delete button) — separate
|
|
18
|
-
* event paths, delete button stops propagation
|
|
19
|
-
* - selected → aria-pressed
|
|
20
|
-
* - disabled state (explicit + access.disabled)
|
|
21
|
-
* - access RBAC: hide / disable
|
|
22
|
-
* - className / sx overrides
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
const FULL_ACCESS_POLICY: RbacPolicy = {
|
|
26
|
-
roles: [
|
|
27
|
-
{
|
|
28
|
-
name: 'admin',
|
|
29
|
-
permissions: [{ resource: '*', action: '*', effect: 'allow' }],
|
|
30
|
-
},
|
|
31
|
-
],
|
|
32
|
-
};
|
|
33
|
-
const NO_ACCESS_POLICY: RbacPolicy = {
|
|
34
|
-
roles: [{ name: 'guest', permissions: [] }],
|
|
35
|
-
};
|
|
36
|
-
const adminSubject: Subject = { id: 'a', roles: ['admin'] };
|
|
37
|
-
const guestSubject: Subject = { id: 'g', roles: ['guest'] };
|
|
38
|
-
|
|
39
|
-
describe('<Chip>', () => {
|
|
40
|
-
describe('rendering — root element', () => {
|
|
41
|
-
it('renders as <span> by default (static)', () => {
|
|
42
|
-
const { container } = render(<Chip label="Active" />);
|
|
43
|
-
expect(container.querySelector('span')).toBeTruthy();
|
|
44
|
-
expect(container.querySelector('button')).toBeNull();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('renders as <button> when clickable=true', () => {
|
|
48
|
-
render(<Chip label="Filter" clickable />);
|
|
49
|
-
expect(screen.getByRole('button', { name: /filter/i })).toBeTruthy();
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('renders as <button> when onClick is provided (implicit clickable)', () => {
|
|
53
|
-
render(<Chip label="Click me" onClick={() => {}} />);
|
|
54
|
-
expect(screen.getByRole('button', { name: /click me/i })).toBeTruthy();
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('renders the label content', () => {
|
|
58
|
-
render(<Chip label="Active" />);
|
|
59
|
-
expect(screen.getByText('Active')).toBeTruthy();
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe('variant × color matrix (sample, token-driven)', () => {
|
|
64
|
-
it('renders soft + primary with token classes (no hardcoded hex)', () => {
|
|
65
|
-
const { container } = render(
|
|
66
|
-
<Chip label="x" variant="soft" color="primary" />
|
|
67
|
-
);
|
|
68
|
-
const root = container.firstChild as HTMLElement;
|
|
69
|
-
expect(root.className).toContain('bg-primary-100');
|
|
70
|
-
expect(root.className).toContain('text-primary-700');
|
|
71
|
-
expect(root.className).not.toMatch(/#[0-9a-fA-F]{3,8}/);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('renders solid + danger with full bg', () => {
|
|
75
|
-
const { container } = render(
|
|
76
|
-
<Chip label="x" variant="solid" color="danger" />
|
|
77
|
-
);
|
|
78
|
-
const root = container.firstChild as HTMLElement;
|
|
79
|
-
expect(root.className).toContain('bg-danger-500');
|
|
80
|
-
expect(root.className).toContain('text-white');
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('renders outline + info with border', () => {
|
|
84
|
-
const { container } = render(
|
|
85
|
-
<Chip label="x" variant="outline" color="info" />
|
|
86
|
-
);
|
|
87
|
-
const root = container.firstChild as HTMLElement;
|
|
88
|
-
expect(root.className).toContain('border-info-500');
|
|
89
|
-
expect(root.className).toContain('text-info-700');
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it('defaults to soft + neutral when omitted', () => {
|
|
93
|
-
const { container } = render(<Chip label="x" />);
|
|
94
|
-
const root = container.firstChild as HTMLElement;
|
|
95
|
-
expect(root.className).toContain('bg-neutral-100');
|
|
96
|
-
expect(root.className).toContain('text-neutral-700');
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
describe('size axis', () => {
|
|
101
|
-
it('applies h-5 + text-xs for size="sm" (default)', () => {
|
|
102
|
-
const { container } = render(<Chip label="x" />);
|
|
103
|
-
const root = container.firstChild as HTMLElement;
|
|
104
|
-
expect(root.className).toContain('h-5');
|
|
105
|
-
expect(root.className).toContain('text-xs');
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('applies h-6 for size="md"', () => {
|
|
109
|
-
const { container } = render(<Chip label="x" size="md" />);
|
|
110
|
-
const root = container.firstChild as HTMLElement;
|
|
111
|
-
expect(root.className).toContain('h-6');
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
describe('leading slots — icon / avatar', () => {
|
|
116
|
-
it('renders icon when provided', () => {
|
|
117
|
-
render(
|
|
118
|
-
<Chip label="x" icon={<span data-testid="icon">i</span>} />
|
|
119
|
-
);
|
|
120
|
-
expect(screen.getByTestId('icon')).toBeTruthy();
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('renders avatar when provided', () => {
|
|
124
|
-
render(
|
|
125
|
-
<Chip label="x" avatar={<span data-testid="avatar">A</span>} />
|
|
126
|
-
);
|
|
127
|
-
expect(screen.getByTestId('avatar')).toBeTruthy();
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('avatar wins over icon when both set (MUI parity)', () => {
|
|
131
|
-
render(
|
|
132
|
-
<Chip
|
|
133
|
-
label="x"
|
|
134
|
-
icon={<span data-testid="icon">i</span>}
|
|
135
|
-
avatar={<span data-testid="avatar">A</span>}
|
|
136
|
-
/>
|
|
137
|
-
);
|
|
138
|
-
expect(screen.getByTestId('avatar')).toBeTruthy();
|
|
139
|
-
expect(screen.queryByTestId('icon')).toBeNull();
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
describe('onClick (clickable chip)', () => {
|
|
144
|
-
it('fires onClick when clicked', () => {
|
|
145
|
-
const onClick = vi.fn();
|
|
146
|
-
render(<Chip label="x" onClick={onClick} />);
|
|
147
|
-
fireEvent.click(screen.getByRole('button'));
|
|
148
|
-
expect(onClick).toHaveBeenCalledTimes(1);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('does NOT fire onClick when disabled', () => {
|
|
152
|
-
const onClick = vi.fn();
|
|
153
|
-
render(<Chip label="x" onClick={onClick} disabled />);
|
|
154
|
-
fireEvent.click(screen.getByRole('button'));
|
|
155
|
-
expect(onClick).not.toHaveBeenCalled();
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
describe('onDelete (delete button)', () => {
|
|
160
|
-
it('renders a delete button when onDelete is provided', () => {
|
|
161
|
-
render(<Chip label="tag" onDelete={() => {}} />);
|
|
162
|
-
expect(screen.getByRole('button', { name: /^remove$/i })).toBeTruthy();
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('does NOT render a delete button when onDelete is omitted', () => {
|
|
166
|
-
render(<Chip label="tag" />);
|
|
167
|
-
expect(screen.queryByRole('button', { name: /^remove$/i })).toBeNull();
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it('respects custom deleteLabel for aria-label', () => {
|
|
171
|
-
render(<Chip label="tag" onDelete={() => {}} deleteLabel="Detach tag" />);
|
|
172
|
-
expect(screen.getByRole('button', { name: /detach tag/i })).toBeTruthy();
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it('fires onDelete when delete button clicked', () => {
|
|
176
|
-
const onDelete = vi.fn();
|
|
177
|
-
render(<Chip label="tag" onDelete={onDelete} />);
|
|
178
|
-
fireEvent.click(screen.getByRole('button', { name: /remove/i }));
|
|
179
|
-
expect(onDelete).toHaveBeenCalledTimes(1);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('delete button does NOT trigger chip onClick (stopPropagation)', () => {
|
|
183
|
-
const onClick = vi.fn();
|
|
184
|
-
const onDelete = vi.fn();
|
|
185
|
-
render(
|
|
186
|
-
<Chip label="tag" onClick={onClick} onDelete={onDelete} />
|
|
187
|
-
);
|
|
188
|
-
// Click on the delete button
|
|
189
|
-
fireEvent.click(screen.getByRole('button', { name: /remove/i }));
|
|
190
|
-
expect(onDelete).toHaveBeenCalledTimes(1);
|
|
191
|
-
expect(onClick).not.toHaveBeenCalled();
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
describe('selected state', () => {
|
|
196
|
-
it('applies aria-pressed=true when selected on a clickable chip', () => {
|
|
197
|
-
render(<Chip label="x" clickable selected />);
|
|
198
|
-
const btn = screen.getByRole('button');
|
|
199
|
-
expect(btn.getAttribute('aria-pressed')).toBe('true');
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it('applies the selected ring class', () => {
|
|
203
|
-
const { container } = render(<Chip label="x" clickable selected />);
|
|
204
|
-
const root = container.firstChild as HTMLElement;
|
|
205
|
-
expect(root.className).toContain('ring-2');
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('does NOT set aria-pressed when not selected', () => {
|
|
209
|
-
render(<Chip label="x" clickable />);
|
|
210
|
-
const btn = screen.getByRole('button');
|
|
211
|
-
expect(btn.getAttribute('aria-pressed')).toBeNull();
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
describe('disabled state', () => {
|
|
216
|
-
it('respects the explicit disabled prop on clickable chip', () => {
|
|
217
|
-
render(<Chip label="x" clickable disabled />);
|
|
218
|
-
const btn = screen.getByRole('button') as HTMLButtonElement;
|
|
219
|
-
expect(btn.disabled).toBe(true);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('applies opacity-50 + cursor-not-allowed to root when disabled', () => {
|
|
223
|
-
const { container } = render(<Chip label="x" disabled />);
|
|
224
|
-
const root = container.firstChild as HTMLElement;
|
|
225
|
-
expect(root.className).toContain('opacity-50');
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
describe('access RBAC integration', () => {
|
|
230
|
-
it('hides the chip when access.onUnauthorized=hide and subject lacks permission', () => {
|
|
231
|
-
const { container } = render(
|
|
232
|
-
<RbacProvider policy={NO_ACCESS_POLICY} subject={guestSubject}>
|
|
233
|
-
<Chip
|
|
234
|
-
label="x"
|
|
235
|
-
access={{
|
|
236
|
-
resource: 'admin-panel',
|
|
237
|
-
action: 'read',
|
|
238
|
-
onUnauthorized: 'hide',
|
|
239
|
-
}}
|
|
240
|
-
/>
|
|
241
|
-
</RbacProvider>
|
|
242
|
-
);
|
|
243
|
-
expect(container.firstChild).toBeNull();
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
it('disables a clickable chip when access.onUnauthorized=disable', () => {
|
|
247
|
-
render(
|
|
248
|
-
<RbacProvider policy={NO_ACCESS_POLICY} subject={guestSubject}>
|
|
249
|
-
<Chip
|
|
250
|
-
label="x"
|
|
251
|
-
clickable
|
|
252
|
-
access={{
|
|
253
|
-
resource: 'admin-panel',
|
|
254
|
-
action: 'read',
|
|
255
|
-
onUnauthorized: 'disable',
|
|
256
|
-
}}
|
|
257
|
-
/>
|
|
258
|
-
</RbacProvider>
|
|
259
|
-
);
|
|
260
|
-
const btn = screen.getByRole('button') as HTMLButtonElement;
|
|
261
|
-
expect(btn.disabled).toBe(true);
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
it('renders normally for admin subject', () => {
|
|
265
|
-
render(
|
|
266
|
-
<RbacProvider policy={FULL_ACCESS_POLICY} subject={adminSubject}>
|
|
267
|
-
<Chip
|
|
268
|
-
label="visible"
|
|
269
|
-
access={{
|
|
270
|
-
resource: 'admin-panel',
|
|
271
|
-
action: 'read',
|
|
272
|
-
onUnauthorized: 'hide',
|
|
273
|
-
}}
|
|
274
|
-
/>
|
|
275
|
-
</RbacProvider>
|
|
276
|
-
);
|
|
277
|
-
expect(screen.getByText('visible')).toBeTruthy();
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
describe('bridge integration — visibleWhen', () => {
|
|
282
|
-
it('renders when visibleWhen returns true (no DashForm context)', () => {
|
|
283
|
-
const { container } = render(
|
|
284
|
-
<Chip label="shown" visibleWhen={() => true} />
|
|
285
|
-
);
|
|
286
|
-
expect(container.firstChild).toBeTruthy();
|
|
287
|
-
expect(screen.getByText('shown')).toBeTruthy();
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
it('returns null when visibleWhen returns false', () => {
|
|
291
|
-
const { container } = render(
|
|
292
|
-
<Chip label="hidden" visibleWhen={() => false} />
|
|
293
|
-
);
|
|
294
|
-
expect(container.firstChild).toBeNull();
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
it('renders normally when visibleWhen is omitted', () => {
|
|
298
|
-
const { container } = render(<Chip label="always" />);
|
|
299
|
-
expect(container.firstChild).toBeTruthy();
|
|
300
|
-
});
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
describe('overrides — sx + className', () => {
|
|
304
|
-
it('appends sx to the root className', () => {
|
|
305
|
-
const { container } = render(<Chip label="x" sx="ring-2 ring-purple-500" />);
|
|
306
|
-
const root = container.firstChild as HTMLElement;
|
|
307
|
-
expect(root.className).toContain('ring-purple-500');
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
it('appends className to the root', () => {
|
|
311
|
-
const { container } = render(<Chip label="x" className="my-custom-chip" />);
|
|
312
|
-
const root = container.firstChild as HTMLElement;
|
|
313
|
-
expect(root.className).toContain('my-custom-chip');
|
|
314
|
-
});
|
|
315
|
-
});
|
|
316
|
-
});
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
import { forwardRef, useContext, type KeyboardEvent, type MouseEvent } from 'react';
|
|
2
|
-
import { DashFormContext, useEngineVisibility } from '@dashforge/ui-core';
|
|
3
|
-
import { cn } from '../../utils/cn.js';
|
|
4
|
-
import { useAccessState } from '../../hooks/useAccessState.js';
|
|
5
|
-
import { chipVariants } from './chip.variants.js';
|
|
6
|
-
import type { ChipProps } from './chip.types.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Default delete-button glyph — inline stroke SVG. Inherits the
|
|
10
|
-
* chip's text colour via `currentColor`. No icon-library dep.
|
|
11
|
-
*
|
|
12
|
-
* @internal
|
|
13
|
-
*/
|
|
14
|
-
function DefaultDeleteIcon() {
|
|
15
|
-
return (
|
|
16
|
-
<svg
|
|
17
|
-
width="0.875em"
|
|
18
|
-
height="0.875em"
|
|
19
|
-
viewBox="0 0 14 14"
|
|
20
|
-
fill="none"
|
|
21
|
-
stroke="currentColor"
|
|
22
|
-
strokeWidth={1.75}
|
|
23
|
-
strokeLinecap="round"
|
|
24
|
-
strokeLinejoin="round"
|
|
25
|
-
aria-hidden="true"
|
|
26
|
-
>
|
|
27
|
-
<path d="m4 4 6 6M10 4l-6 6" />
|
|
28
|
-
</svg>
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Dashforge TW Chip — status / filter / tag pill.
|
|
34
|
-
*
|
|
35
|
-
* Promoted from the internal `Table/cells/RenderChip` (Sprint 4.4):
|
|
36
|
-
* preserves the 3 × 7 variant × color matrix byte-identical and adds
|
|
37
|
-
* the public API (label, icon, avatar, clickable, onClick, onDelete,
|
|
38
|
-
* selected, access).
|
|
39
|
-
*
|
|
40
|
-
* **Rendering modes** (chosen at runtime from props):
|
|
41
|
-
* - **Static** (default) → `<span>`. Pure display.
|
|
42
|
-
* - **Clickable** (`clickable` true OR `onClick` provided) →
|
|
43
|
-
* `<button type="button">` with focus ring + hover state.
|
|
44
|
-
* - **Deletable** (`onDelete` provided) → root + trailing `<button>`
|
|
45
|
-
* for the delete glyph. Static or clickable root depending on
|
|
46
|
-
* whether `onClick` is also set.
|
|
47
|
-
*
|
|
48
|
-
* **Variant axis** is `soft | solid | outline` (Dashforge chip
|
|
49
|
-
* vocabulary, default `'soft'`). Distinct from Button's
|
|
50
|
-
* (`solid | outline | ghost | link`) and Alert's
|
|
51
|
-
* (`standard | filled | outlined`) by design — see CHANGELOG.
|
|
52
|
-
*
|
|
53
|
-
* **A11y**:
|
|
54
|
-
* - Static chip → no role (it's a `<span>`).
|
|
55
|
-
* - Clickable chip → native `<button>` semantics.
|
|
56
|
-
* - `selected` → `aria-pressed="true"` (so it announces as a toggle
|
|
57
|
-
* button in pressed state).
|
|
58
|
-
* - Delete button → its own `<button>` with `aria-label`
|
|
59
|
-
* (defaults to `'Remove'`).
|
|
60
|
-
*
|
|
61
|
-
* @example
|
|
62
|
-
* ```tsx
|
|
63
|
-
* // Static status chip
|
|
64
|
-
* <Chip label="Active" color="success" />
|
|
65
|
-
*
|
|
66
|
-
* // With icon
|
|
67
|
-
* import { CheckIcon } from 'lucide-react';
|
|
68
|
-
* <Chip label="Verified" color="success" icon={<CheckIcon size={14} />} />
|
|
69
|
-
*
|
|
70
|
-
* // Filter chip (clickable + toggle via selected)
|
|
71
|
-
* <Chip
|
|
72
|
-
* label="Last 7 days"
|
|
73
|
-
* color="primary"
|
|
74
|
-
* clickable
|
|
75
|
-
* selected={range === '7d'}
|
|
76
|
-
* onClick={() => setRange('7d')}
|
|
77
|
-
* />
|
|
78
|
-
*
|
|
79
|
-
* // Removable tag
|
|
80
|
-
* <Chip
|
|
81
|
-
* label="design-system"
|
|
82
|
-
* color="info"
|
|
83
|
-
* variant="outline"
|
|
84
|
-
* onDelete={() => removeTag('design-system')}
|
|
85
|
-
* />
|
|
86
|
-
*
|
|
87
|
-
* // RBAC-gated admin chip
|
|
88
|
-
* <Chip
|
|
89
|
-
* label="Admin"
|
|
90
|
-
* color="danger"
|
|
91
|
-
* variant="solid"
|
|
92
|
-
* access={{ resource: 'role', action: 'read', onUnauthorized: 'hide' }}
|
|
93
|
-
* />
|
|
94
|
-
* ```
|
|
95
|
-
*/
|
|
96
|
-
export const Chip = forwardRef<HTMLElement, ChipProps>(function Chip(
|
|
97
|
-
props,
|
|
98
|
-
ref
|
|
99
|
-
) {
|
|
100
|
-
const {
|
|
101
|
-
label,
|
|
102
|
-
icon,
|
|
103
|
-
avatar,
|
|
104
|
-
variant,
|
|
105
|
-
color,
|
|
106
|
-
size,
|
|
107
|
-
clickable: clickableProp,
|
|
108
|
-
onClick,
|
|
109
|
-
onDelete,
|
|
110
|
-
deleteIcon,
|
|
111
|
-
deleteLabel = 'Remove',
|
|
112
|
-
selected,
|
|
113
|
-
disabled: disabledProp,
|
|
114
|
-
visibleWhen,
|
|
115
|
-
access,
|
|
116
|
-
sx,
|
|
117
|
-
className,
|
|
118
|
-
} = props;
|
|
119
|
-
|
|
120
|
-
// Bridge — both hooks called unconditionally (rules-of-hooks).
|
|
121
|
-
// Inside a `<DashForm>`, `useEngineVisibility` subscribes to engine
|
|
122
|
-
// state and re-evaluates the predicate on changes; outside a form,
|
|
123
|
-
// the predicate is called with `null` engine (consumer captures
|
|
124
|
-
// external state in the closure).
|
|
125
|
-
const bridge = useContext(DashFormContext);
|
|
126
|
-
const isVisible = useEngineVisibility(bridge?.engine, visibleWhen);
|
|
127
|
-
const accessState = useAccessState(access);
|
|
128
|
-
|
|
129
|
-
if (!isVisible || !accessState.visible) return null;
|
|
130
|
-
|
|
131
|
-
// Effective interactivity / disabled — mirrors Button semantics.
|
|
132
|
-
const isClickable = Boolean(clickableProp ?? onClick);
|
|
133
|
-
const isDisabled =
|
|
134
|
-
Boolean(disabledProp) || accessState.disabled || accessState.readonly;
|
|
135
|
-
|
|
136
|
-
const classes = cn(
|
|
137
|
-
chipVariants({
|
|
138
|
-
color,
|
|
139
|
-
variant,
|
|
140
|
-
size,
|
|
141
|
-
clickable: isClickable || undefined,
|
|
142
|
-
selected: selected || undefined,
|
|
143
|
-
disabled: isDisabled || undefined,
|
|
144
|
-
}),
|
|
145
|
-
sx,
|
|
146
|
-
className
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
// ─── Inner content — leading slot + label + delete ────────────
|
|
150
|
-
// Avatar wins over icon when both provided (MUI parity).
|
|
151
|
-
// Label is rendered as a direct text node (no wrapping span) so
|
|
152
|
-
// the chip DOM stays minimal and consumers that target the root
|
|
153
|
-
// via `getByText(label)` continue working. The root's
|
|
154
|
-
// `inline-flex items-center` provides vertical alignment with
|
|
155
|
-
// any leading / trailing slots.
|
|
156
|
-
const leading = avatar ?? icon;
|
|
157
|
-
const innerContent = (
|
|
158
|
-
<>
|
|
159
|
-
{leading != null && (
|
|
160
|
-
<span className="-ml-0.5 inline-flex items-center shrink-0">
|
|
161
|
-
{leading}
|
|
162
|
-
</span>
|
|
163
|
-
)}
|
|
164
|
-
{label}
|
|
165
|
-
{onDelete != null && (
|
|
166
|
-
<button
|
|
167
|
-
type="button"
|
|
168
|
-
aria-label={deleteLabel}
|
|
169
|
-
onClick={(e: MouseEvent<HTMLButtonElement>) => {
|
|
170
|
-
// Stop propagation so the chip's own onClick doesn't fire
|
|
171
|
-
// when the user clicks the × — MUI matches this behaviour.
|
|
172
|
-
e.stopPropagation();
|
|
173
|
-
if (!isDisabled) onDelete(e);
|
|
174
|
-
}}
|
|
175
|
-
disabled={isDisabled}
|
|
176
|
-
className={cn(
|
|
177
|
-
'ml-0.5 -mr-1 inline-flex items-center justify-center',
|
|
178
|
-
'h-4 w-4 rounded-full opacity-70 hover:opacity-100',
|
|
179
|
-
'outline-none focus-visible:ring-2 focus-visible:ring-current',
|
|
180
|
-
'transition-opacity'
|
|
181
|
-
)}
|
|
182
|
-
>
|
|
183
|
-
{deleteIcon ?? <DefaultDeleteIcon />}
|
|
184
|
-
</button>
|
|
185
|
-
)}
|
|
186
|
-
</>
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
// ─── Interactive root (clickable) ─────────────────────────────
|
|
190
|
-
if (isClickable) {
|
|
191
|
-
return (
|
|
192
|
-
<button
|
|
193
|
-
ref={ref as React.Ref<HTMLButtonElement>}
|
|
194
|
-
type="button"
|
|
195
|
-
className={classes}
|
|
196
|
-
disabled={isDisabled}
|
|
197
|
-
aria-pressed={selected ? true : undefined}
|
|
198
|
-
onClick={(e: MouseEvent<HTMLButtonElement>) => {
|
|
199
|
-
if (isDisabled) return;
|
|
200
|
-
onClick?.(e);
|
|
201
|
-
}}
|
|
202
|
-
onKeyDown={(e: KeyboardEvent<HTMLButtonElement>) => {
|
|
203
|
-
// Native <button> handles Enter + Space already; the keydown
|
|
204
|
-
// is here for future extension (e.g. Delete key to fire
|
|
205
|
-
// onDelete when focused) — currently no-op.
|
|
206
|
-
void e;
|
|
207
|
-
}}
|
|
208
|
-
>
|
|
209
|
-
{innerContent}
|
|
210
|
-
</button>
|
|
211
|
-
);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// ─── Static root (display only) ───────────────────────────────
|
|
215
|
-
return (
|
|
216
|
-
<span
|
|
217
|
-
ref={ref as React.Ref<HTMLSpanElement>}
|
|
218
|
-
className={classes}
|
|
219
|
-
aria-disabled={isDisabled || undefined}
|
|
220
|
-
>
|
|
221
|
-
{innerContent}
|
|
222
|
-
</span>
|
|
223
|
-
);
|
|
224
|
-
});
|