@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,274 +0,0 @@
|
|
|
1
|
-
import { useCallback, useContext, useEffect, useId, useRef, useState } from 'react';
|
|
2
|
-
import { DashFormContext, useEngineVisibility } from '@dashforge/ui-core';
|
|
3
|
-
import type { DashFormBridge, FieldRegistration } from '@dashforge/ui-core';
|
|
4
|
-
import { useDashFieldMeta } from '@dashforge/forms';
|
|
5
|
-
import {
|
|
6
|
-
formatTime,
|
|
7
|
-
generateTimeOptions,
|
|
8
|
-
timeStringToMinutes,
|
|
9
|
-
} from '@dashforge/calendar-core';
|
|
10
|
-
import { cn } from '../../utils/cn.js';
|
|
11
|
-
import { useAccessState } from '../../hooks/useAccessState.js';
|
|
12
|
-
import { resolveValidationState } from '../_shared/resolveValidationState.js';
|
|
13
|
-
import { Popover } from '../Popover/Popover.js';
|
|
14
|
-
import { timePickerVariants } from './timePicker.variants.js';
|
|
15
|
-
import type { TimePickerProps } from './timePicker.types.js';
|
|
16
|
-
|
|
17
|
-
// Inline 16×16 stroke clock glyph — no icon dependency (tw convention).
|
|
18
|
-
function ClockIcon() {
|
|
19
|
-
return (
|
|
20
|
-
<svg width="1em" height="1em" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
21
|
-
<circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="1.5" />
|
|
22
|
-
<path
|
|
23
|
-
d="M8 4.5V8l2.4 1.4"
|
|
24
|
-
stroke="currentColor"
|
|
25
|
-
strokeWidth="1.5"
|
|
26
|
-
strokeLinecap="round"
|
|
27
|
-
strokeLinejoin="round"
|
|
28
|
-
/>
|
|
29
|
-
</svg>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Dashforge TW `<TimePicker>` — a form-bound time-of-day field.
|
|
35
|
-
*
|
|
36
|
-
* A read-only trigger button paired with a time-list popover (Radix
|
|
37
|
-
* Popover). Integrates with the Dashforge form bridge + RBAC.
|
|
38
|
-
*
|
|
39
|
-
* Storage contract: a canonical 24-hour `"HH:mm"` string, or `null` —
|
|
40
|
-
* shared with the MUI `@dashforge/ui` `TimePicker`. `hour12` is display-only.
|
|
41
|
-
*/
|
|
42
|
-
export function TimePicker(props: TimePickerProps) {
|
|
43
|
-
const {
|
|
44
|
-
name,
|
|
45
|
-
rules,
|
|
46
|
-
label,
|
|
47
|
-
helperText,
|
|
48
|
-
error,
|
|
49
|
-
required,
|
|
50
|
-
disabled,
|
|
51
|
-
placeholder,
|
|
52
|
-
layout = 'stacked',
|
|
53
|
-
visibleWhen,
|
|
54
|
-
access,
|
|
55
|
-
value: explicitValue,
|
|
56
|
-
defaultValue,
|
|
57
|
-
onChange,
|
|
58
|
-
minTime,
|
|
59
|
-
maxTime,
|
|
60
|
-
stepMinutes,
|
|
61
|
-
hour12 = false,
|
|
62
|
-
fullWidth,
|
|
63
|
-
sx,
|
|
64
|
-
slotProps,
|
|
65
|
-
testId,
|
|
66
|
-
} = props;
|
|
67
|
-
|
|
68
|
-
const bridge = useContext(DashFormContext) as DashFormBridge | null;
|
|
69
|
-
const isVisible = useEngineVisibility(bridge?.engine, visibleWhen);
|
|
70
|
-
const fieldMeta = useDashFieldMeta(name);
|
|
71
|
-
const accessState = useAccessState(access);
|
|
72
|
-
|
|
73
|
-
const fieldId = useId();
|
|
74
|
-
const helperId = `${fieldId}-help`;
|
|
75
|
-
|
|
76
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
77
|
-
const [internalValue, setInternalValue] = useState<string | null>(
|
|
78
|
-
defaultValue ?? null,
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
const unregisterRef = useRef({ bridge, name });
|
|
82
|
-
unregisterRef.current = { bridge, name };
|
|
83
|
-
const isMountedRef = useRef(false);
|
|
84
|
-
useEffect(() => {
|
|
85
|
-
isMountedRef.current = true;
|
|
86
|
-
return () => {
|
|
87
|
-
isMountedRef.current = false;
|
|
88
|
-
const { bridge: cap, name: capName } = unregisterRef.current;
|
|
89
|
-
queueMicrotask(() => {
|
|
90
|
-
if (!isMountedRef.current) cap?.unregister?.(capName);
|
|
91
|
-
});
|
|
92
|
-
};
|
|
93
|
-
}, []);
|
|
94
|
-
|
|
95
|
-
const effectiveDisabled = Boolean(disabled) || accessState.disabled;
|
|
96
|
-
const isInteractive = !effectiveDisabled && !accessState.readonly;
|
|
97
|
-
const isFormMode = Boolean(bridge?.register);
|
|
98
|
-
|
|
99
|
-
let resolvedError = error;
|
|
100
|
-
let resolvedHelperText: typeof helperText = helperText;
|
|
101
|
-
let registration: FieldRegistration | null = null;
|
|
102
|
-
let resolvedValue: string | null;
|
|
103
|
-
|
|
104
|
-
if (isFormMode && bridge) {
|
|
105
|
-
registration = bridge.register(name, rules);
|
|
106
|
-
const validation = resolveValidationState(name, bridge, error, helperText);
|
|
107
|
-
resolvedError = validation.error;
|
|
108
|
-
resolvedHelperText = validation.helperText;
|
|
109
|
-
if (explicitValue !== undefined) {
|
|
110
|
-
resolvedValue = explicitValue;
|
|
111
|
-
} else {
|
|
112
|
-
const bv = fieldMeta.value;
|
|
113
|
-
resolvedValue = bv == null ? null : String(bv);
|
|
114
|
-
}
|
|
115
|
-
} else if (explicitValue !== undefined) {
|
|
116
|
-
resolvedValue = explicitValue;
|
|
117
|
-
} else {
|
|
118
|
-
resolvedValue = internalValue;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const registrationRefFn = registration?.ref;
|
|
122
|
-
const triggerRef = useCallback(
|
|
123
|
-
(instance: HTMLButtonElement | null) => {
|
|
124
|
-
if (typeof registrationRefFn === 'function') {
|
|
125
|
-
registrationRefFn(instance);
|
|
126
|
-
}
|
|
127
|
-
},
|
|
128
|
-
[registrationRefFn],
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
if (!isVisible) return null;
|
|
132
|
-
if (!accessState.visible) return null;
|
|
133
|
-
|
|
134
|
-
const v = timePickerVariants({ layout, error: resolvedError, fullWidth });
|
|
135
|
-
const displayValue =
|
|
136
|
-
resolvedValue != null && resolvedValue !== ''
|
|
137
|
-
? formatTime(resolvedValue, { hour12 })
|
|
138
|
-
: '';
|
|
139
|
-
|
|
140
|
-
const options = generateTimeOptions({
|
|
141
|
-
...(minTime !== undefined && { start: minTime }),
|
|
142
|
-
...(maxTime !== undefined && { end: maxTime }),
|
|
143
|
-
...(stepMinutes !== undefined && { stepMinutes }),
|
|
144
|
-
});
|
|
145
|
-
const minMinutes = timeStringToMinutes(minTime ?? '00:00') ?? 0;
|
|
146
|
-
const maxMinutes = timeStringToMinutes(maxTime ?? '23:59') ?? 1439;
|
|
147
|
-
const isTimeDisabled = (time: string): boolean => {
|
|
148
|
-
const minutes = timeStringToMinutes(time);
|
|
149
|
-
return minutes === null || minutes < minMinutes || minutes > maxMinutes;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
const commitValue = (next: string | null) => {
|
|
153
|
-
if (isFormMode && bridge) {
|
|
154
|
-
bridge.setValue?.(name, next);
|
|
155
|
-
void registration?.onChange?.({
|
|
156
|
-
target: { name, value: next ?? '' },
|
|
157
|
-
type: 'change',
|
|
158
|
-
});
|
|
159
|
-
} else if (explicitValue === undefined) {
|
|
160
|
-
setInternalValue(next);
|
|
161
|
-
}
|
|
162
|
-
onChange?.(next);
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
const markTouched = () => {
|
|
166
|
-
if (isFormMode && bridge) {
|
|
167
|
-
const committed = bridge.getValue(name);
|
|
168
|
-
void registration?.onBlur?.({
|
|
169
|
-
target: { name, value: committed == null ? '' : String(committed) },
|
|
170
|
-
type: 'blur',
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
const handleOpenChange = (next: boolean) => {
|
|
176
|
-
if (next && !isInteractive) {
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
setIsOpen(next);
|
|
180
|
-
if (!next) {
|
|
181
|
-
markTouched();
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
const handleSelect = (time: string) => {
|
|
186
|
-
if (isTimeDisabled(time)) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
commitValue(time);
|
|
190
|
-
setIsOpen(false);
|
|
191
|
-
markTouched();
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
return (
|
|
195
|
-
<div
|
|
196
|
-
data-testid={testId}
|
|
197
|
-
className={cn(v.root(), sx, slotProps?.root?.className)}
|
|
198
|
-
>
|
|
199
|
-
{label && (
|
|
200
|
-
<label
|
|
201
|
-
htmlFor={fieldId}
|
|
202
|
-
className={cn(v.label(), slotProps?.label?.className)}
|
|
203
|
-
>
|
|
204
|
-
{label}
|
|
205
|
-
{required && (
|
|
206
|
-
<span
|
|
207
|
-
aria-hidden="true"
|
|
208
|
-
className={cn(v.requiredMark(), slotProps?.requiredMark?.className)}
|
|
209
|
-
>
|
|
210
|
-
*
|
|
211
|
-
</span>
|
|
212
|
-
)}
|
|
213
|
-
</label>
|
|
214
|
-
)}
|
|
215
|
-
|
|
216
|
-
<Popover
|
|
217
|
-
open={isOpen}
|
|
218
|
-
onOpenChange={handleOpenChange}
|
|
219
|
-
side="bottom"
|
|
220
|
-
align="start"
|
|
221
|
-
content={
|
|
222
|
-
<div role="listbox" aria-label="Time options" className={v.list()}>
|
|
223
|
-
{options.map((time) => (
|
|
224
|
-
<button
|
|
225
|
-
key={time}
|
|
226
|
-
type="button"
|
|
227
|
-
role="option"
|
|
228
|
-
aria-selected={time === resolvedValue}
|
|
229
|
-
aria-disabled={isTimeDisabled(time)}
|
|
230
|
-
className={v.option()}
|
|
231
|
-
onClick={() => {
|
|
232
|
-
handleSelect(time);
|
|
233
|
-
}}
|
|
234
|
-
>
|
|
235
|
-
{formatTime(time, { hour12 })}
|
|
236
|
-
</button>
|
|
237
|
-
))}
|
|
238
|
-
</div>
|
|
239
|
-
}
|
|
240
|
-
>
|
|
241
|
-
<button
|
|
242
|
-
type="button"
|
|
243
|
-
id={fieldId}
|
|
244
|
-
ref={triggerRef}
|
|
245
|
-
disabled={effectiveDisabled}
|
|
246
|
-
aria-invalid={resolvedError ? true : undefined}
|
|
247
|
-
aria-describedby={resolvedHelperText ? helperId : undefined}
|
|
248
|
-
className={cn(v.trigger(), slotProps?.trigger?.className)}
|
|
249
|
-
>
|
|
250
|
-
<span className={displayValue ? v.value() : v.placeholder()}>
|
|
251
|
-
{displayValue || placeholder || 'Select a time'}
|
|
252
|
-
</span>
|
|
253
|
-
<span className={v.icon()}>
|
|
254
|
-
<ClockIcon />
|
|
255
|
-
</span>
|
|
256
|
-
</button>
|
|
257
|
-
</Popover>
|
|
258
|
-
|
|
259
|
-
{resolvedHelperText && (
|
|
260
|
-
<p
|
|
261
|
-
id={helperId}
|
|
262
|
-
className={cn(
|
|
263
|
-
resolvedError ? v.errorText() : v.helperText(),
|
|
264
|
-
resolvedError
|
|
265
|
-
? slotProps?.errorText?.className
|
|
266
|
-
: slotProps?.helperText?.className,
|
|
267
|
-
)}
|
|
268
|
-
>
|
|
269
|
-
{resolvedHelperText}
|
|
270
|
-
</p>
|
|
271
|
-
)}
|
|
272
|
-
</div>
|
|
273
|
-
);
|
|
274
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import type { Engine } from '@dashforge/ui-core';
|
|
3
|
-
import type { AccessRequirement } from '@dashforge/rbac';
|
|
4
|
-
|
|
5
|
-
/** Per-slot `className` overrides for `<TimePicker>`. */
|
|
6
|
-
export interface TimePickerSlotProps {
|
|
7
|
-
root?: { className?: string };
|
|
8
|
-
label?: { className?: string };
|
|
9
|
-
requiredMark?: { className?: string };
|
|
10
|
-
trigger?: { className?: string };
|
|
11
|
-
helperText?: { className?: string };
|
|
12
|
-
errorText?: { className?: string };
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Props for the `<TimePicker>` form field (Tailwind skin).
|
|
17
|
-
*
|
|
18
|
-
* A read-only trigger paired with a `<Calendar>`-style time-list popover.
|
|
19
|
-
* The stored value is a canonical 24-hour `"HH:mm"` string, or `null`.
|
|
20
|
-
* 12-hour notation (`hour12`) is display-only. No date, no timezone.
|
|
21
|
-
*
|
|
22
|
-
* The prop surface mirrors the MUI `@dashforge/ui` `TimePicker`.
|
|
23
|
-
*/
|
|
24
|
-
export interface TimePickerProps {
|
|
25
|
-
/** Field name — the bridge registration key. Required. */
|
|
26
|
-
name: string;
|
|
27
|
-
/** Validation rules forwarded to the form bridge. */
|
|
28
|
-
rules?: unknown;
|
|
29
|
-
/** Field label. */
|
|
30
|
-
label?: ReactNode;
|
|
31
|
-
/** Helper text below the control (overrides a bridge error message). */
|
|
32
|
-
helperText?: ReactNode;
|
|
33
|
-
/** Explicit error state (overrides the bridge's auto error). */
|
|
34
|
-
error?: boolean;
|
|
35
|
-
/** Marks the field required (adds the label asterisk). */
|
|
36
|
-
required?: boolean;
|
|
37
|
-
/** Disables the field. */
|
|
38
|
-
disabled?: boolean;
|
|
39
|
-
/** Placeholder shown when no time is selected. */
|
|
40
|
-
placeholder?: string;
|
|
41
|
-
/** Label/control layout. */
|
|
42
|
-
layout?: 'stacked' | 'inline';
|
|
43
|
-
/** Reactive visibility predicate evaluated against the form engine. */
|
|
44
|
-
visibleWhen?: (engine: Engine) => boolean;
|
|
45
|
-
/** RBAC access requirement. */
|
|
46
|
-
access?: AccessRequirement;
|
|
47
|
-
/** Controlled value — `"HH:mm"` (24-hour) or `null`. */
|
|
48
|
-
value?: string | null;
|
|
49
|
-
/** Uncontrolled initial value. */
|
|
50
|
-
defaultValue?: string | null;
|
|
51
|
-
/** Fired with the new time (or `null` when cleared). */
|
|
52
|
-
onChange?: (value: string | null) => void;
|
|
53
|
-
/** Earliest selectable time, `"HH:mm"`. Default `"00:00"`. */
|
|
54
|
-
minTime?: string;
|
|
55
|
-
/** Latest selectable time, `"HH:mm"`. Default `"23:30"`. */
|
|
56
|
-
maxTime?: string;
|
|
57
|
-
/** Step between time-list options, in minutes. Default `30`. */
|
|
58
|
-
stepMinutes?: number;
|
|
59
|
-
/** Render the time list in 12-hour notation. Default `false`. */
|
|
60
|
-
hour12?: boolean;
|
|
61
|
-
/** Stretches the field to its container width. */
|
|
62
|
-
fullWidth?: boolean;
|
|
63
|
-
/** Root-level Tailwind class override. */
|
|
64
|
-
sx?: string;
|
|
65
|
-
/** Per-slot `className` overrides. */
|
|
66
|
-
slotProps?: TimePickerSlotProps;
|
|
67
|
-
/** Test id applied to the field root. */
|
|
68
|
-
testId?: string;
|
|
69
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { tv } from 'tailwind-variants';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Slots for `<TimePicker>` — a bridge-integrated time field whose trigger
|
|
5
|
-
* is a `<button>` styled as an input, opening a time-list popover.
|
|
6
|
-
*
|
|
7
|
-
* Theme identity: bare neutral / brand token-backed classes only — no
|
|
8
|
-
* `dark:` variants on the neutral palette (the preset CSS-var swap
|
|
9
|
-
* auto-inverts). See `_shared/themeIdentity.test.ts`.
|
|
10
|
-
*/
|
|
11
|
-
export const timePickerVariants = tv({
|
|
12
|
-
slots: {
|
|
13
|
-
root: 'flex flex-col',
|
|
14
|
-
label: 'block text-sm font-medium text-neutral-900 mb-1',
|
|
15
|
-
requiredMark: 'text-danger-500 ml-0.5',
|
|
16
|
-
trigger:
|
|
17
|
-
'flex items-center gap-2 h-10 min-w-[10rem] rounded-md border border-neutral-300 bg-neutral-50 px-3 text-base text-neutral-900 cursor-pointer transition-colors hover:border-neutral-400 focus-visible:outline-none focus-visible:border-primary-500 focus-visible:ring-2 focus-visible:ring-primary-500/30 disabled:cursor-not-allowed disabled:opacity-60 disabled:bg-neutral-200',
|
|
18
|
-
value: 'flex-1 truncate text-left',
|
|
19
|
-
placeholder: 'flex-1 truncate text-left text-neutral-400',
|
|
20
|
-
icon: 'shrink-0 text-[1rem] text-neutral-500',
|
|
21
|
-
list: 'flex max-h-64 min-w-[8rem] flex-col gap-0.5 overflow-y-auto p-1',
|
|
22
|
-
option:
|
|
23
|
-
'flex w-full cursor-pointer items-center rounded px-2.5 py-1.5 text-sm text-neutral-900 transition-colors hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-500 aria-selected:bg-primary-600 aria-selected:text-white aria-selected:hover:bg-primary-600 aria-disabled:cursor-default aria-disabled:text-neutral-300 aria-disabled:opacity-60 aria-disabled:hover:bg-transparent',
|
|
24
|
-
helperText: 'mt-1 text-sm text-neutral-600',
|
|
25
|
-
errorText: 'mt-1 text-sm text-danger-600',
|
|
26
|
-
},
|
|
27
|
-
variants: {
|
|
28
|
-
layout: {
|
|
29
|
-
stacked: {},
|
|
30
|
-
inline: {
|
|
31
|
-
root: 'flex-row items-start gap-3',
|
|
32
|
-
label: 'mb-0 pt-2.5 whitespace-nowrap shrink-0',
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
error: {
|
|
36
|
-
true: {
|
|
37
|
-
trigger:
|
|
38
|
-
'border-danger-500 hover:border-danger-500 focus-visible:border-danger-500 focus-visible:ring-danger-500/30',
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
fullWidth: {
|
|
42
|
-
true: {
|
|
43
|
-
root: 'w-full',
|
|
44
|
-
trigger: 'w-full min-w-0',
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
defaultVariants: {
|
|
49
|
-
layout: 'stacked',
|
|
50
|
-
error: false,
|
|
51
|
-
fullWidth: false,
|
|
52
|
-
},
|
|
53
|
-
});
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { describe, it, expect, afterEach, beforeAll } from 'vitest';
|
|
4
|
-
import { render, screen, cleanup } from '@testing-library/react';
|
|
5
|
-
import { Tooltip } from './Tooltip.js';
|
|
6
|
-
|
|
7
|
-
void React;
|
|
8
|
-
afterEach(() => cleanup());
|
|
9
|
-
|
|
10
|
-
// jsdom doesn't implement ResizeObserver — Radix Floating UI requires it.
|
|
11
|
-
// Shim with a noop before any test mounts a Tooltip.
|
|
12
|
-
beforeAll(() => {
|
|
13
|
-
if (typeof globalThis.ResizeObserver === 'undefined') {
|
|
14
|
-
(globalThis as unknown as { ResizeObserver: unknown }).ResizeObserver = class {
|
|
15
|
-
observe() {}
|
|
16
|
-
unobserve() {}
|
|
17
|
-
disconnect() {}
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
if (typeof globalThis.DOMRect === 'undefined') {
|
|
21
|
-
(globalThis as unknown as { DOMRect: unknown }).DOMRect = class {
|
|
22
|
-
static fromRect(r?: DOMRectInit) {
|
|
23
|
-
return new (globalThis as unknown as { DOMRect: new (x: number, y: number, w: number, h: number) => unknown }).DOMRect(
|
|
24
|
-
r?.x ?? 0, r?.y ?? 0, r?.width ?? 0, r?.height ?? 0
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
constructor(public x = 0, public y = 0, public width = 0, public height = 0) {}
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe('Tooltip — rendering', () => {
|
|
33
|
-
it('renders the trigger (children) always', () => {
|
|
34
|
-
render(
|
|
35
|
-
<Tooltip content="Tip text">
|
|
36
|
-
<button>Trigger</button>
|
|
37
|
-
</Tooltip>
|
|
38
|
-
);
|
|
39
|
-
expect(screen.queryByRole('button', { name: 'Trigger' })).not.toBeNull();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('renders content when controlled open=true', () => {
|
|
43
|
-
render(
|
|
44
|
-
<Tooltip content="Tip text" open onOpenChange={() => {}}>
|
|
45
|
-
<button>Trigger</button>
|
|
46
|
-
</Tooltip>
|
|
47
|
-
);
|
|
48
|
-
expect(screen.queryAllByText('Tip text').length).toBeGreaterThan(0);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('does not render content when controlled open=false', () => {
|
|
52
|
-
render(
|
|
53
|
-
<Tooltip content="Tip text" open={false} onOpenChange={() => {}}>
|
|
54
|
-
<button>Trigger</button>
|
|
55
|
-
</Tooltip>
|
|
56
|
-
);
|
|
57
|
-
expect(screen.queryByText('Tip text')).toBeNull();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe('Tooltip — placement props', () => {
|
|
62
|
-
it.each(['top', 'right', 'bottom', 'left'] as const)(
|
|
63
|
-
'renders side=%s without crashing',
|
|
64
|
-
(side) => {
|
|
65
|
-
render(
|
|
66
|
-
<Tooltip content="Tip" open side={side} onOpenChange={() => {}}>
|
|
67
|
-
<button>Trigger</button>
|
|
68
|
-
</Tooltip>
|
|
69
|
-
);
|
|
70
|
-
expect(screen.queryByRole('button', { name: 'Trigger' })).not.toBeNull();
|
|
71
|
-
}
|
|
72
|
-
);
|
|
73
|
-
});
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import * as RadixTooltip from '@radix-ui/react-tooltip';
|
|
2
|
-
import { cn } from '../../utils/cn.js';
|
|
3
|
-
import { tooltipVariants } from './tooltip.variants.js';
|
|
4
|
-
import type { TooltipProps } from './tooltip.types.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Dashforge TW `<Tooltip>` — hoverable / focusable tooltip.
|
|
8
|
-
*
|
|
9
|
-
* Built on `@radix-ui/react-tooltip`:
|
|
10
|
-
* - APG tooltip pattern: `role="tooltip"`, `aria-describedby` wired
|
|
11
|
-
* to the trigger automatically (Radix manages the id linkage).
|
|
12
|
-
* - Shows on hover OR keyboard focus.
|
|
13
|
-
* - Dismissed on Escape or pointer leave.
|
|
14
|
-
*
|
|
15
|
-
* Wrap any single React node — it becomes the trigger via Radix's
|
|
16
|
-
* `asChild` slot. The trigger inherits `aria-describedby` so screen
|
|
17
|
-
* readers announce the tooltip content along with the trigger.
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```tsx
|
|
21
|
-
* <Tooltip content="Delete this item">
|
|
22
|
-
* <Button variant="ghost">
|
|
23
|
-
* <TrashIcon />
|
|
24
|
-
* </Button>
|
|
25
|
-
* </Tooltip>
|
|
26
|
-
* ```
|
|
27
|
-
*
|
|
28
|
-
* Each consumer can also wrap the entire app once in
|
|
29
|
-
* `<RadixTooltip.Provider>` to share delay/skip configuration; we
|
|
30
|
-
* include a per-component provider here for ease-of-use.
|
|
31
|
-
*/
|
|
32
|
-
export function Tooltip(props: TooltipProps) {
|
|
33
|
-
const {
|
|
34
|
-
children,
|
|
35
|
-
content,
|
|
36
|
-
side = 'top',
|
|
37
|
-
align = 'center',
|
|
38
|
-
hideArrow = false,
|
|
39
|
-
delayDuration = 200,
|
|
40
|
-
open,
|
|
41
|
-
onOpenChange,
|
|
42
|
-
sideOffset = 4,
|
|
43
|
-
slotProps,
|
|
44
|
-
} = props;
|
|
45
|
-
|
|
46
|
-
const v = tooltipVariants();
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<RadixTooltip.Provider delayDuration={delayDuration}>
|
|
50
|
-
<RadixTooltip.Root open={open} onOpenChange={onOpenChange}>
|
|
51
|
-
<RadixTooltip.Trigger asChild>{children}</RadixTooltip.Trigger>
|
|
52
|
-
<RadixTooltip.Portal>
|
|
53
|
-
<RadixTooltip.Content
|
|
54
|
-
side={side}
|
|
55
|
-
align={align}
|
|
56
|
-
sideOffset={sideOffset}
|
|
57
|
-
className={cn(v.content(), slotProps?.content?.className)}
|
|
58
|
-
>
|
|
59
|
-
{content}
|
|
60
|
-
{!hideArrow && (
|
|
61
|
-
<RadixTooltip.Arrow
|
|
62
|
-
className={cn(v.arrow(), slotProps?.arrow?.className)}
|
|
63
|
-
/>
|
|
64
|
-
)}
|
|
65
|
-
</RadixTooltip.Content>
|
|
66
|
-
</RadixTooltip.Portal>
|
|
67
|
-
</RadixTooltip.Root>
|
|
68
|
-
</RadixTooltip.Provider>
|
|
69
|
-
);
|
|
70
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
export interface TooltipSlotProps {
|
|
4
|
-
content?: { className?: string };
|
|
5
|
-
arrow?: { className?: string };
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Props for `<Tooltip>`.
|
|
10
|
-
*
|
|
11
|
-
* Built on `@radix-ui/react-tooltip`. Wrap any element with a tooltip
|
|
12
|
-
* that follows APG semantics (`role="tooltip"`, `aria-describedby`
|
|
13
|
-
* wired to the trigger).
|
|
14
|
-
*
|
|
15
|
-
* Renders an arrow by default. Three side options
|
|
16
|
-
* (top / right / bottom / left) with 'top' as default. Delay
|
|
17
|
-
* configurable via `delayDuration` (forwarded to Radix Provider).
|
|
18
|
-
*/
|
|
19
|
-
export interface TooltipProps {
|
|
20
|
-
/** The element that, when hovered/focused, shows the tooltip. */
|
|
21
|
-
children: ReactNode;
|
|
22
|
-
/** Tooltip body content. */
|
|
23
|
-
content: ReactNode;
|
|
24
|
-
/** Side of the trigger to show the tooltip on. @default 'top' */
|
|
25
|
-
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
26
|
-
/** Alignment along the perpendicular axis. @default 'center' */
|
|
27
|
-
align?: 'start' | 'center' | 'end';
|
|
28
|
-
/** Hide the arrow indicator. @default false (arrow shown) */
|
|
29
|
-
hideArrow?: boolean;
|
|
30
|
-
/** Delay before the tooltip shows on hover (ms). @default 200 */
|
|
31
|
-
delayDuration?: number;
|
|
32
|
-
/**
|
|
33
|
-
* Controlled open state. Use when the tooltip should be programmatic
|
|
34
|
-
* (e.g. revealed on a manual button press). Omit for default
|
|
35
|
-
* hover / focus behavior.
|
|
36
|
-
*/
|
|
37
|
-
open?: boolean;
|
|
38
|
-
/** Called when the tooltip's open state changes. */
|
|
39
|
-
onOpenChange?: (open: boolean) => void;
|
|
40
|
-
/** Side offset in pixels from the trigger. @default 4 */
|
|
41
|
-
sideOffset?: number;
|
|
42
|
-
/** Per-slot overrides. */
|
|
43
|
-
slotProps?: TooltipSlotProps;
|
|
44
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { tv, type VariantProps } from 'tailwind-variants';
|
|
2
|
-
|
|
3
|
-
export const tooltipVariants = tv({
|
|
4
|
-
slots: {
|
|
5
|
-
content: [
|
|
6
|
-
'z-50 max-w-xs rounded-md px-3 py-1.5 text-xs font-medium',
|
|
7
|
-
// Auto-invert via the dashforgePreset() CSS-var swap:
|
|
8
|
-
// - Light mode: `bg-neutral-900` = #171717 (dark surface) +
|
|
9
|
-
// `text-neutral-50` = #fafafa (light text) — DARK tooltip
|
|
10
|
-
// on the light page (high contrast).
|
|
11
|
-
// - Dark mode: `bg-neutral-900` flips to #f5f5f5 (light) +
|
|
12
|
-
// `text-neutral-50` flips to #0a0a0a (dark text) — LIGHT
|
|
13
|
-
// tooltip on the dark page (high contrast against page).
|
|
14
|
-
// Adding `dark:bg-neutral-50 dark:text-neutral-900` (the old
|
|
15
|
-
// pattern) would force the dark-mode tooltip back to a dark
|
|
16
|
-
// surface — invisible against the dark page.
|
|
17
|
-
'bg-neutral-900 text-neutral-50',
|
|
18
|
-
'shadow-md',
|
|
19
|
-
'data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95',
|
|
20
|
-
'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',
|
|
21
|
-
'motion-reduce:transition-none motion-reduce:duration-0',
|
|
22
|
-
],
|
|
23
|
-
// Arrow tracks the content bg — auto-inverts the same way.
|
|
24
|
-
arrow: 'fill-neutral-900',
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
export type TooltipVariants = VariantProps<typeof tooltipVariants>;
|