@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,110 +0,0 @@
|
|
|
1
|
-
import type { ButtonHTMLAttributes } from 'react';
|
|
2
|
-
import type { Engine } from '@dashforge/ui-core';
|
|
3
|
-
import type { AccessRequirement } from '@dashforge/rbac';
|
|
4
|
-
import type { ButtonVariants } from './button.variants.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Props for the Dashforge TW `<Button>` component.
|
|
8
|
-
*
|
|
9
|
-
* Extends the native `<button>` attributes (so `onClick`, `type`,
|
|
10
|
-
* `aria-*`, `data-*` etc. all flow through), narrowed in two places:
|
|
11
|
-
*
|
|
12
|
-
* - `disabled` is kept (combines with RBAC + loading via OR)
|
|
13
|
-
* - `className` is omitted — use `sx` instead. This keeps the
|
|
14
|
-
* override path **single and explicit**: `sx` is the escape hatch
|
|
15
|
-
* for adding utility classes, and `tailwind-merge` (via `cn()`)
|
|
16
|
-
* guarantees it wins over any conflicting variant class.
|
|
17
|
-
*
|
|
18
|
-
* Plus the variant axes from `tailwind-variants` and Dashforge-specific
|
|
19
|
-
* additions:
|
|
20
|
-
*
|
|
21
|
-
* - `access` — RBAC requirement (hide / disable / readonly)
|
|
22
|
-
* - `asChild` — Radix Slot polymorphism: when `true`, renders the
|
|
23
|
-
* immediate child element with the Button's class merged in, so
|
|
24
|
-
* `<Button asChild><a href="/x">Go</a></Button>` produces a styled
|
|
25
|
-
* `<a>` with no extra wrapper DOM
|
|
26
|
-
*/
|
|
27
|
-
export interface ButtonProps
|
|
28
|
-
// `color` is omitted from the native `<button>` attributes because
|
|
29
|
-
// HTML's legacy `color` attribute (string) collides with our variant
|
|
30
|
-
// axis (`'primary' | 'secondary' | …`). The Picked variant version
|
|
31
|
-
// is the canonical one.
|
|
32
|
-
extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'color'>,
|
|
33
|
-
Pick<ButtonVariants, 'variant' | 'color' | 'size' | 'fullWidth' | 'loading'> {
|
|
34
|
-
/**
|
|
35
|
-
* RBAC access control requirement.
|
|
36
|
-
*
|
|
37
|
-
* Controls button visibility and interaction based on user
|
|
38
|
-
* permissions:
|
|
39
|
-
* - `onUnauthorized: 'hide'` → button does not render
|
|
40
|
-
* - `onUnauthorized: 'disable'` → button renders disabled
|
|
41
|
-
* - `onUnauthorized: 'readonly'` → button renders disabled
|
|
42
|
-
* (buttons do not support true readonly semantics; disabled is
|
|
43
|
-
* used as fallback)
|
|
44
|
-
*
|
|
45
|
-
* Combines with `disabled` and `loading` props via OR logic.
|
|
46
|
-
*/
|
|
47
|
-
access?: AccessRequirement;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Reactive visibility predicate. Re-evaluated on every engine state
|
|
51
|
-
* change when the button is mounted inside a `<DashForm>`; outside
|
|
52
|
-
* a form, evaluated as a plain predicate (the consumer captures
|
|
53
|
-
* any external state in the closure).
|
|
54
|
-
*
|
|
55
|
-
* When the predicate returns `false`, the component renders `null`.
|
|
56
|
-
*
|
|
57
|
-
* **Added in 1.1.0 (Sprint 4.4 alignment)** — extends the
|
|
58
|
-
* engine-reactive visibility pattern previously available only on
|
|
59
|
-
* form fields + `<Alert>` to every interactive component in the
|
|
60
|
-
* Dashforge TW catalog (Button, IconButton, Chip, …).
|
|
61
|
-
*
|
|
62
|
-
* Note: `visibleWhen` is for **state-driven** hide. For
|
|
63
|
-
* **permission-driven** hide, use `access` with
|
|
64
|
-
* `onUnauthorized: 'hide'` — it's the semantically correct path
|
|
65
|
-
* and provides better error messages in RBAC dev tools.
|
|
66
|
-
*
|
|
67
|
-
* @example
|
|
68
|
-
* ```tsx
|
|
69
|
-
* // Inside a DashForm — reactive on engine state
|
|
70
|
-
* <Button
|
|
71
|
-
* visibleWhen={(engine) =>
|
|
72
|
-
* engine.getNode('plan')?.value === 'premium'
|
|
73
|
-
* }
|
|
74
|
-
* >
|
|
75
|
-
* Upgrade extras
|
|
76
|
-
* </Button>
|
|
77
|
-
*
|
|
78
|
-
* // Outside a form — closure over external React state
|
|
79
|
-
* <Button visibleWhen={() => itemCount > 0}>Bulk delete</Button>
|
|
80
|
-
* ```
|
|
81
|
-
*/
|
|
82
|
-
visibleWhen?: (engine: Engine) => boolean;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* When `true`, the immediate child element is rendered with the
|
|
86
|
-
* Button's classes merged in (via `@radix-ui/react-slot`). The
|
|
87
|
-
* Button DOM element is not emitted.
|
|
88
|
-
*
|
|
89
|
-
* Common pattern: render a router `Link` with Button styling.
|
|
90
|
-
*
|
|
91
|
-
* @example
|
|
92
|
-
* ```tsx
|
|
93
|
-
* <Button asChild variant="solid">
|
|
94
|
-
* <Link to="/dashboard">Dashboard</Link>
|
|
95
|
-
* </Button>
|
|
96
|
-
* ```
|
|
97
|
-
*/
|
|
98
|
-
asChild?: boolean;
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Tailwind utility classes appended **after** the variant classes,
|
|
102
|
-
* so they win on any conflict via `tailwind-merge`.
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* ```tsx
|
|
106
|
-
* <Button sx="md:w-1/2 shadow-xl">Save</Button>
|
|
107
|
-
* ```
|
|
108
|
-
*/
|
|
109
|
-
sx?: string;
|
|
110
|
-
}
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { tv, type VariantProps } from 'tailwind-variants';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Tailwind-variants recipe for `<Button>`.
|
|
5
|
-
*
|
|
6
|
-
* Three independent axes plus two booleans:
|
|
7
|
-
* - `variant`: visual treatment (solid / outline / ghost / link)
|
|
8
|
-
* - `color`: semantic intent role (primary / secondary / success /
|
|
9
|
-
* warning / danger)
|
|
10
|
-
* - `size`: sm / md / lg
|
|
11
|
-
* - `fullWidth`: stretches to container width
|
|
12
|
-
* - `loading`: visually + functionally disabled, used together with
|
|
13
|
-
* an inline spinner rendered by the component
|
|
14
|
-
*
|
|
15
|
-
* Color × variant combinations are expressed via `compoundVariants` so
|
|
16
|
-
* each pair owns its bg / text / border / hover / focus quartet without
|
|
17
|
-
* a `dark:` variant explosion. Dark mode swap is delegated entirely to
|
|
18
|
-
* the runtime CSS-vars from `@dashforge/tw-theme` — the same class
|
|
19
|
-
* resolves to a different value when `data-dash-tw-theme="dark"` flips.
|
|
20
|
-
*
|
|
21
|
-
* Token references:
|
|
22
|
-
* - Surface bg / border / text → `*-primary-*`, `*-danger-*`, etc.
|
|
23
|
-
* (resolved via `dashforgePreset()`)
|
|
24
|
-
* - Hover / focus / active states→ one tone deeper on the same scale
|
|
25
|
-
* (`primary-600` from `primary-500`)
|
|
26
|
-
* - Disabled → opacity drop + no pointer-events
|
|
27
|
-
*/
|
|
28
|
-
export const buttonVariants = tv({
|
|
29
|
-
base: [
|
|
30
|
-
'inline-flex items-center justify-center gap-2',
|
|
31
|
-
'font-medium',
|
|
32
|
-
'rounded-md',
|
|
33
|
-
'select-none whitespace-nowrap',
|
|
34
|
-
'transition-colors',
|
|
35
|
-
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',
|
|
36
|
-
'disabled:opacity-50 disabled:pointer-events-none',
|
|
37
|
-
],
|
|
38
|
-
variants: {
|
|
39
|
-
variant: {
|
|
40
|
-
solid: 'border border-transparent text-white',
|
|
41
|
-
outline: 'bg-transparent border',
|
|
42
|
-
ghost: 'bg-transparent border border-transparent',
|
|
43
|
-
link: 'bg-transparent border-0 underline-offset-4 hover:underline px-0',
|
|
44
|
-
},
|
|
45
|
-
color: {
|
|
46
|
-
primary: '',
|
|
47
|
-
secondary: '',
|
|
48
|
-
success: '',
|
|
49
|
-
warning: '',
|
|
50
|
-
danger: '',
|
|
51
|
-
},
|
|
52
|
-
size: {
|
|
53
|
-
sm: 'h-8 px-3 text-sm',
|
|
54
|
-
md: 'h-10 px-4 text-base',
|
|
55
|
-
lg: 'h-12 px-6 text-lg',
|
|
56
|
-
},
|
|
57
|
-
fullWidth: {
|
|
58
|
-
true: 'w-full',
|
|
59
|
-
},
|
|
60
|
-
loading: {
|
|
61
|
-
true: 'cursor-wait',
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
compoundVariants: [
|
|
65
|
-
// ───── solid × color ─────
|
|
66
|
-
{
|
|
67
|
-
variant: 'solid',
|
|
68
|
-
color: 'primary',
|
|
69
|
-
class: 'bg-primary-500 hover:bg-primary-600 active:bg-primary-700 focus-visible:ring-primary-500',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
variant: 'solid',
|
|
73
|
-
color: 'secondary',
|
|
74
|
-
class: 'bg-secondary-500 hover:bg-secondary-600 active:bg-secondary-700 focus-visible:ring-secondary-500',
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
variant: 'solid',
|
|
78
|
-
color: 'success',
|
|
79
|
-
class: 'bg-success-500 hover:bg-success-600 active:bg-success-700 focus-visible:ring-success-500',
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
variant: 'solid',
|
|
83
|
-
color: 'warning',
|
|
84
|
-
class: 'bg-warning-500 hover:bg-warning-600 active:bg-warning-700 focus-visible:ring-warning-500',
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
variant: 'solid',
|
|
88
|
-
color: 'danger',
|
|
89
|
-
class: 'bg-danger-500 hover:bg-danger-600 active:bg-danger-700 focus-visible:ring-danger-500',
|
|
90
|
-
},
|
|
91
|
-
// ───── outline × color ─────
|
|
92
|
-
{
|
|
93
|
-
variant: 'outline',
|
|
94
|
-
color: 'primary',
|
|
95
|
-
class: 'border-primary-500 text-primary-700 hover:bg-primary-50 focus-visible:ring-primary-500',
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
variant: 'outline',
|
|
99
|
-
color: 'secondary',
|
|
100
|
-
class: 'border-secondary-500 text-secondary-700 hover:bg-secondary-50 focus-visible:ring-secondary-500',
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
variant: 'outline',
|
|
104
|
-
color: 'success',
|
|
105
|
-
class: 'border-success-500 text-success-700 hover:bg-success-50 focus-visible:ring-success-500',
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
variant: 'outline',
|
|
109
|
-
color: 'warning',
|
|
110
|
-
class: 'border-warning-500 text-warning-700 hover:bg-warning-50 focus-visible:ring-warning-500',
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
variant: 'outline',
|
|
114
|
-
color: 'danger',
|
|
115
|
-
class: 'border-danger-500 text-danger-700 hover:bg-danger-50 focus-visible:ring-danger-500',
|
|
116
|
-
},
|
|
117
|
-
// ───── ghost × color ─────
|
|
118
|
-
{
|
|
119
|
-
variant: 'ghost',
|
|
120
|
-
color: 'primary',
|
|
121
|
-
class: 'text-primary-700 hover:bg-primary-50 focus-visible:ring-primary-500',
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
variant: 'ghost',
|
|
125
|
-
color: 'secondary',
|
|
126
|
-
class: 'text-secondary-700 hover:bg-secondary-50 focus-visible:ring-secondary-500',
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
variant: 'ghost',
|
|
130
|
-
color: 'success',
|
|
131
|
-
class: 'text-success-700 hover:bg-success-50 focus-visible:ring-success-500',
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
variant: 'ghost',
|
|
135
|
-
color: 'warning',
|
|
136
|
-
class: 'text-warning-700 hover:bg-warning-50 focus-visible:ring-warning-500',
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
variant: 'ghost',
|
|
140
|
-
color: 'danger',
|
|
141
|
-
class: 'text-danger-700 hover:bg-danger-50 focus-visible:ring-danger-500',
|
|
142
|
-
},
|
|
143
|
-
// ───── link × color ─────
|
|
144
|
-
{ variant: 'link', color: 'primary', class: 'text-primary-700 hover:text-primary-800' },
|
|
145
|
-
{ variant: 'link', color: 'secondary', class: 'text-secondary-700 hover:text-secondary-800' },
|
|
146
|
-
{ variant: 'link', color: 'success', class: 'text-success-700 hover:text-success-800' },
|
|
147
|
-
{ variant: 'link', color: 'warning', class: 'text-warning-700 hover:text-warning-800' },
|
|
148
|
-
{ variant: 'link', color: 'danger', class: 'text-danger-700 hover:text-danger-800' },
|
|
149
|
-
],
|
|
150
|
-
defaultVariants: {
|
|
151
|
-
variant: 'solid',
|
|
152
|
-
color: 'primary',
|
|
153
|
-
size: 'md',
|
|
154
|
-
fullWidth: false,
|
|
155
|
-
loading: false,
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
export type ButtonVariants = VariantProps<typeof buttonVariants>;
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
3
|
-
import { render, screen, fireEvent } from '@testing-library/react';
|
|
4
|
-
|
|
5
|
-
import { Calendar } from './Calendar.js';
|
|
6
|
-
|
|
7
|
-
describe('Calendar', () => {
|
|
8
|
-
it('renders a labelled month grid', () => {
|
|
9
|
-
render(<Calendar today="2026-05-20" />);
|
|
10
|
-
expect(screen.queryByRole('grid', { name: 'Calendar' })).not.toBeNull();
|
|
11
|
-
expect(screen.queryByText('May 2026')).not.toBeNull();
|
|
12
|
-
expect(screen.getAllByRole('columnheader')).toHaveLength(7);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('renders a fixed 42-cell grid', () => {
|
|
16
|
-
render(<Calendar today="2026-05-20" />);
|
|
17
|
-
expect(screen.getAllByRole('gridcell')).toHaveLength(42);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('fires onChange when a day is clicked', () => {
|
|
21
|
-
const onChange = vi.fn();
|
|
22
|
-
render(<Calendar today="2026-05-20" onChange={onChange} />);
|
|
23
|
-
fireEvent.click(screen.getByRole('button', { name: /May 15, 2026/ }));
|
|
24
|
-
expect(onChange).toHaveBeenCalledWith('2026-05-15');
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('marks the controlled selected day as pressed', () => {
|
|
28
|
-
render(<Calendar today="2026-05-20" value="2026-05-10" />);
|
|
29
|
-
expect(
|
|
30
|
-
screen
|
|
31
|
-
.getByRole('button', { name: /May 10, 2026/ })
|
|
32
|
-
.getAttribute('aria-pressed'),
|
|
33
|
-
).toBe('true');
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('navigates to the next and previous month', () => {
|
|
37
|
-
render(<Calendar today="2026-05-20" />);
|
|
38
|
-
fireEvent.click(screen.getByRole('button', { name: 'Next month' }));
|
|
39
|
-
expect(screen.queryByText('June 2026')).not.toBeNull();
|
|
40
|
-
fireEvent.click(screen.getByRole('button', { name: 'Previous month' }));
|
|
41
|
-
expect(screen.queryByText('May 2026')).not.toBeNull();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('moves roving focus with the arrow keys', () => {
|
|
45
|
-
render(<Calendar today="2026-05-20" />);
|
|
46
|
-
const grid = screen.getByRole('grid');
|
|
47
|
-
expect(
|
|
48
|
-
screen
|
|
49
|
-
.getByRole('button', { name: /May 20, 2026/ })
|
|
50
|
-
.getAttribute('tabindex'),
|
|
51
|
-
).toBe('0');
|
|
52
|
-
fireEvent.keyDown(grid, { key: 'ArrowRight' });
|
|
53
|
-
expect(
|
|
54
|
-
screen
|
|
55
|
-
.getByRole('button', { name: /May 21, 2026/ })
|
|
56
|
-
.getAttribute('tabindex'),
|
|
57
|
-
).toBe('0');
|
|
58
|
-
expect(
|
|
59
|
-
screen
|
|
60
|
-
.getByRole('button', { name: /May 20, 2026/ })
|
|
61
|
-
.getAttribute('tabindex'),
|
|
62
|
-
).toBe('-1');
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('does not select a disabled date', () => {
|
|
66
|
-
const onChange = vi.fn();
|
|
67
|
-
render(
|
|
68
|
-
<Calendar today="2026-05-20" minDate="2026-05-15" onChange={onChange} />,
|
|
69
|
-
);
|
|
70
|
-
const blocked = screen.getByRole('button', { name: /May 10, 2026/ });
|
|
71
|
-
expect(blocked.getAttribute('aria-disabled')).toBe('true');
|
|
72
|
-
fireEvent.click(blocked);
|
|
73
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
74
|
-
});
|
|
75
|
-
});
|
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import type { KeyboardEvent } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
formatLongDate,
|
|
5
|
-
resolveCalendarKey,
|
|
6
|
-
useCalendar,
|
|
7
|
-
} from '@dashforge/calendar-core';
|
|
8
|
-
import type { ISODate } from '@dashforge/calendar-core';
|
|
9
|
-
import { cn } from '../../utils/cn.js';
|
|
10
|
-
import { calendarDayVariants, calendarVariants } from './calendar.variants.js';
|
|
11
|
-
import type { CalendarProps } from './calendar.types.js';
|
|
12
|
-
|
|
13
|
-
// Inline 16×16 stroke chevrons — no icon dependency (tw convention).
|
|
14
|
-
function ChevronLeftIcon() {
|
|
15
|
-
return (
|
|
16
|
-
<svg
|
|
17
|
-
width="1em"
|
|
18
|
-
height="1em"
|
|
19
|
-
viewBox="0 0 16 16"
|
|
20
|
-
fill="none"
|
|
21
|
-
aria-hidden="true"
|
|
22
|
-
>
|
|
23
|
-
<path
|
|
24
|
-
d="M10 4 6 8l4 4"
|
|
25
|
-
stroke="currentColor"
|
|
26
|
-
strokeWidth="1.5"
|
|
27
|
-
strokeLinecap="round"
|
|
28
|
-
strokeLinejoin="round"
|
|
29
|
-
/>
|
|
30
|
-
</svg>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function ChevronRightIcon() {
|
|
35
|
-
return (
|
|
36
|
-
<svg
|
|
37
|
-
width="1em"
|
|
38
|
-
height="1em"
|
|
39
|
-
viewBox="0 0 16 16"
|
|
40
|
-
fill="none"
|
|
41
|
-
aria-hidden="true"
|
|
42
|
-
>
|
|
43
|
-
<path
|
|
44
|
-
d="m6 4 4 4-4 4"
|
|
45
|
-
stroke="currentColor"
|
|
46
|
-
strokeWidth="1.5"
|
|
47
|
-
strokeLinecap="round"
|
|
48
|
-
strokeLinejoin="round"
|
|
49
|
-
/>
|
|
50
|
-
</svg>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* `<Calendar>` — a standalone, inline month-grid date picker.
|
|
56
|
-
*
|
|
57
|
-
* The Tailwind presentation layer over the headless `useCalendar` engine
|
|
58
|
-
* from `@dashforge/calendar-core` (the same engine the MUI `@dashforge/ui`
|
|
59
|
-
* calendar consumes — only the skin differs). Implements the WCAG grid
|
|
60
|
-
* pattern with roving tab-index focus.
|
|
61
|
-
*
|
|
62
|
-
* It is a primitive: no form-bridge / RBAC integration — use `<DatePicker>`
|
|
63
|
-
* for a form-bound date field.
|
|
64
|
-
*/
|
|
65
|
-
export function Calendar(props: CalendarProps) {
|
|
66
|
-
const {
|
|
67
|
-
value,
|
|
68
|
-
defaultValue,
|
|
69
|
-
onChange,
|
|
70
|
-
month,
|
|
71
|
-
year,
|
|
72
|
-
defaultMonth,
|
|
73
|
-
defaultYear,
|
|
74
|
-
onMonthChange,
|
|
75
|
-
minDate,
|
|
76
|
-
maxDate,
|
|
77
|
-
disabledDates,
|
|
78
|
-
isDateDisabled,
|
|
79
|
-
weekStartDay,
|
|
80
|
-
locale,
|
|
81
|
-
today,
|
|
82
|
-
disabled = false,
|
|
83
|
-
autoFocus = false,
|
|
84
|
-
sx,
|
|
85
|
-
slotProps,
|
|
86
|
-
testId,
|
|
87
|
-
'aria-label': ariaLabel = 'Calendar',
|
|
88
|
-
} = props;
|
|
89
|
-
|
|
90
|
-
const isValueControlled = value !== undefined;
|
|
91
|
-
const [internalValue, setInternalValue] = useState<ISODate | null>(
|
|
92
|
-
defaultValue ?? null,
|
|
93
|
-
);
|
|
94
|
-
const selectedValue: ISODate | null = isValueControlled
|
|
95
|
-
? value
|
|
96
|
-
: internalValue;
|
|
97
|
-
|
|
98
|
-
const handleSelect = useCallback(
|
|
99
|
-
(iso: ISODate) => {
|
|
100
|
-
if (!isValueControlled) {
|
|
101
|
-
setInternalValue(iso);
|
|
102
|
-
}
|
|
103
|
-
onChange?.(iso);
|
|
104
|
-
},
|
|
105
|
-
[isValueControlled, onChange],
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
const calendar = useCalendar({
|
|
109
|
-
selected: selectedValue,
|
|
110
|
-
month,
|
|
111
|
-
year,
|
|
112
|
-
defaultMonth,
|
|
113
|
-
defaultYear,
|
|
114
|
-
onMonthChange,
|
|
115
|
-
minDate,
|
|
116
|
-
maxDate,
|
|
117
|
-
disabledDates,
|
|
118
|
-
isDateDisabled,
|
|
119
|
-
weekStartDay,
|
|
120
|
-
locale,
|
|
121
|
-
today,
|
|
122
|
-
onSelect: handleSelect,
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
// Roving focus: the active day cell holds DOM focus; it is moved only
|
|
126
|
-
// after a keyboard interaction (or on mount when `autoFocus`). `focus`
|
|
127
|
-
// uses `preventScroll` so opening the calendar inside a popup never
|
|
128
|
-
// scroll-jumps the page before the popup is positioned.
|
|
129
|
-
const focusedCellRef = useRef<HTMLButtonElement | null>(null);
|
|
130
|
-
const shouldFocusRef = useRef(autoFocus);
|
|
131
|
-
|
|
132
|
-
useEffect(() => {
|
|
133
|
-
if (shouldFocusRef.current && focusedCellRef.current) {
|
|
134
|
-
focusedCellRef.current.focus({ preventScroll: true });
|
|
135
|
-
shouldFocusRef.current = false;
|
|
136
|
-
}
|
|
137
|
-
}, [calendar.focusedDate]);
|
|
138
|
-
|
|
139
|
-
const handleKeyDown = useCallback(
|
|
140
|
-
(event: KeyboardEvent<HTMLDivElement>) => {
|
|
141
|
-
if (disabled) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
const action = resolveCalendarKey(event.key);
|
|
145
|
-
if (action === null) {
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
event.preventDefault();
|
|
149
|
-
shouldFocusRef.current = true;
|
|
150
|
-
switch (action) {
|
|
151
|
-
case 'select':
|
|
152
|
-
calendar.selectDate(calendar.focusedDate);
|
|
153
|
-
break;
|
|
154
|
-
case 'monthForward':
|
|
155
|
-
calendar.goToNextMonth();
|
|
156
|
-
break;
|
|
157
|
-
case 'monthBackward':
|
|
158
|
-
calendar.goToPreviousMonth();
|
|
159
|
-
break;
|
|
160
|
-
default:
|
|
161
|
-
calendar.navigate(action);
|
|
162
|
-
}
|
|
163
|
-
},
|
|
164
|
-
[disabled, calendar],
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
const resolvedLocale = locale ?? 'en-US';
|
|
168
|
-
const v = calendarVariants({ disabled });
|
|
169
|
-
|
|
170
|
-
return (
|
|
171
|
-
<div
|
|
172
|
-
data-testid={testId}
|
|
173
|
-
className={cn(v.root(), sx, slotProps?.root?.className)}
|
|
174
|
-
>
|
|
175
|
-
{/* Header: month navigation + label */}
|
|
176
|
-
<div className={cn(v.header(), slotProps?.header?.className)}>
|
|
177
|
-
<button
|
|
178
|
-
type="button"
|
|
179
|
-
className={v.navButton()}
|
|
180
|
-
disabled={disabled}
|
|
181
|
-
aria-label="Previous month"
|
|
182
|
-
onClick={() => {
|
|
183
|
-
calendar.goToPreviousMonth();
|
|
184
|
-
}}
|
|
185
|
-
>
|
|
186
|
-
<ChevronLeftIcon />
|
|
187
|
-
</button>
|
|
188
|
-
<span aria-live="polite" className={v.monthLabel()}>
|
|
189
|
-
{calendar.monthLabel}
|
|
190
|
-
</span>
|
|
191
|
-
<button
|
|
192
|
-
type="button"
|
|
193
|
-
className={v.navButton()}
|
|
194
|
-
disabled={disabled}
|
|
195
|
-
aria-label="Next month"
|
|
196
|
-
onClick={() => {
|
|
197
|
-
calendar.goToNextMonth();
|
|
198
|
-
}}
|
|
199
|
-
>
|
|
200
|
-
<ChevronRightIcon />
|
|
201
|
-
</button>
|
|
202
|
-
</div>
|
|
203
|
-
|
|
204
|
-
{/* Grid */}
|
|
205
|
-
<div
|
|
206
|
-
role="grid"
|
|
207
|
-
aria-label={ariaLabel}
|
|
208
|
-
onKeyDown={handleKeyDown}
|
|
209
|
-
className={cn(v.grid(), slotProps?.grid?.className)}
|
|
210
|
-
>
|
|
211
|
-
<div role="row" className={v.weekdayRow()}>
|
|
212
|
-
{calendar.weekdayNames.map((dayName, index) => (
|
|
213
|
-
<span
|
|
214
|
-
key={`weekday-${String(index)}`}
|
|
215
|
-
role="columnheader"
|
|
216
|
-
className={v.weekday()}
|
|
217
|
-
>
|
|
218
|
-
{dayName}
|
|
219
|
-
</span>
|
|
220
|
-
))}
|
|
221
|
-
</div>
|
|
222
|
-
|
|
223
|
-
{calendar.weeks.map((week) => (
|
|
224
|
-
<div key={week.key} role="row" className={v.weekRow()}>
|
|
225
|
-
{week.days.map((day) => {
|
|
226
|
-
const isActiveCell = day.iso === calendar.focusedDate;
|
|
227
|
-
return (
|
|
228
|
-
<span key={day.iso} role="gridcell" className="flex">
|
|
229
|
-
<button
|
|
230
|
-
type="button"
|
|
231
|
-
ref={isActiveCell ? focusedCellRef : null}
|
|
232
|
-
tabIndex={isActiveCell ? 0 : -1}
|
|
233
|
-
disabled={disabled}
|
|
234
|
-
aria-label={formatLongDate(
|
|
235
|
-
{ year: day.year, month: day.month, day: day.day },
|
|
236
|
-
resolvedLocale,
|
|
237
|
-
)}
|
|
238
|
-
aria-current={day.isToday ? 'date' : undefined}
|
|
239
|
-
aria-pressed={day.isSelected}
|
|
240
|
-
aria-disabled={day.isDisabled}
|
|
241
|
-
onClick={() => {
|
|
242
|
-
calendar.selectDate(day.iso);
|
|
243
|
-
}}
|
|
244
|
-
className={cn(
|
|
245
|
-
calendarDayVariants({
|
|
246
|
-
siblingMonth: day.isSiblingMonth,
|
|
247
|
-
today: day.isToday,
|
|
248
|
-
selected: day.isSelected,
|
|
249
|
-
disabled: day.isDisabled,
|
|
250
|
-
}),
|
|
251
|
-
slotProps?.day?.className,
|
|
252
|
-
)}
|
|
253
|
-
>
|
|
254
|
-
{day.day}
|
|
255
|
-
</button>
|
|
256
|
-
</span>
|
|
257
|
-
);
|
|
258
|
-
})}
|
|
259
|
-
</div>
|
|
260
|
-
))}
|
|
261
|
-
</div>
|
|
262
|
-
</div>
|
|
263
|
-
);
|
|
264
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import type { ISODate, WeekDay } from '@dashforge/calendar-core';
|
|
2
|
-
|
|
3
|
-
/** Per-slot `className` overrides for `<Calendar>`. */
|
|
4
|
-
export interface CalendarSlotProps {
|
|
5
|
-
root?: { className?: string };
|
|
6
|
-
header?: { className?: string };
|
|
7
|
-
grid?: { className?: string };
|
|
8
|
-
/** Applied to every day-cell button. */
|
|
9
|
-
day?: { className?: string };
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Props for the `<Calendar>` primitive — a standalone, inline month grid.
|
|
14
|
-
*
|
|
15
|
-
* `Calendar` is NOT a form field (no bridge / RBAC integration). It is the
|
|
16
|
-
* low-level building block used inside `<DatePicker>`. For a form-bound date
|
|
17
|
-
* input use `<DatePicker>`.
|
|
18
|
-
*
|
|
19
|
-
* Dates are ISO `YYYY-MM-DD` strings throughout. The headless date engine is
|
|
20
|
-
* `@dashforge/calendar-core` — shared with the MUI `@dashforge/ui` calendar.
|
|
21
|
-
*/
|
|
22
|
-
export interface CalendarProps {
|
|
23
|
-
/** Selected date (controlled). */
|
|
24
|
-
value?: ISODate | null;
|
|
25
|
-
/** Initial selected date (uncontrolled). */
|
|
26
|
-
defaultValue?: ISODate | null;
|
|
27
|
-
/** Fired when a day is chosen. */
|
|
28
|
-
onChange?: (value: ISODate) => void;
|
|
29
|
-
/** Controlled displayed month (1-indexed). Pair with `year`. */
|
|
30
|
-
month?: number;
|
|
31
|
-
/** Controlled displayed year. Pair with `month`. */
|
|
32
|
-
year?: number;
|
|
33
|
-
/** Initial displayed month (1-indexed, uncontrolled). */
|
|
34
|
-
defaultMonth?: number;
|
|
35
|
-
/** Initial displayed year (uncontrolled). */
|
|
36
|
-
defaultYear?: number;
|
|
37
|
-
/** Fired when the displayed month changes. */
|
|
38
|
-
onMonthChange?: (month: number, year: number) => void;
|
|
39
|
-
/** Earliest selectable date (inclusive). */
|
|
40
|
-
minDate?: ISODate;
|
|
41
|
-
/** Latest selectable date (inclusive). */
|
|
42
|
-
maxDate?: ISODate;
|
|
43
|
-
/** Explicit list of disabled dates. */
|
|
44
|
-
disabledDates?: readonly ISODate[];
|
|
45
|
-
/** Predicate marking arbitrary dates disabled. */
|
|
46
|
-
isDateDisabled?: (date: ISODate) => boolean;
|
|
47
|
-
/** Weekday of the grid's first column (`0` = Sunday). Default `0`. */
|
|
48
|
-
weekStartDay?: WeekDay;
|
|
49
|
-
/** BCP-47 locale for month/weekday names. Default `"en-US"`. */
|
|
50
|
-
locale?: string;
|
|
51
|
-
/** Overrides "today" (ISO `YYYY-MM-DD`), mainly for testing. */
|
|
52
|
-
today?: ISODate;
|
|
53
|
-
/** Disables the whole calendar. */
|
|
54
|
-
disabled?: boolean;
|
|
55
|
-
/** Moves DOM focus to the active day cell on mount. */
|
|
56
|
-
autoFocus?: boolean;
|
|
57
|
-
/** Accessible label for the grid. Default `"Calendar"`. */
|
|
58
|
-
'aria-label'?: string;
|
|
59
|
-
/** Root-level Tailwind class override. */
|
|
60
|
-
sx?: string;
|
|
61
|
-
/** Per-slot `className` overrides. */
|
|
62
|
-
slotProps?: CalendarSlotProps;
|
|
63
|
-
/** Test id applied to the root element. */
|
|
64
|
-
testId?: string;
|
|
65
|
-
}
|