@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,144 +0,0 @@
|
|
|
1
|
-
import { useCallback, useRef, useState, type DragEvent } from 'react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Native HTML5 drag-and-drop reorder for DataGrid column headers.
|
|
5
|
-
*
|
|
6
|
-
* Zero new runtime deps — uses the browser's built-in drag events.
|
|
7
|
-
* The hook returns handler factories you wire onto each `<th>` plus
|
|
8
|
-
* a `dropTarget` state used to render the visual indicator (a left
|
|
9
|
-
* or right border on the hovered column).
|
|
10
|
-
*
|
|
11
|
-
* - `dragStart(field)` → onDragStart; stashes source field in a ref
|
|
12
|
-
* + sets `dataTransfer.effectAllowed = 'move'`.
|
|
13
|
-
* - `dragOver(field)` → onDragOver; preventDefault + computes
|
|
14
|
-
* whether the cursor is over the LEFT or RIGHT half of the
|
|
15
|
-
* target → updates dropTarget so the indicator renders.
|
|
16
|
-
* - `drop(field)` → onDrop; computes the new order array via
|
|
17
|
-
* `moveColumn(source, target, side)` and commits it.
|
|
18
|
-
* - `dragEnd()` → onDragEnd; clears state.
|
|
19
|
-
*
|
|
20
|
-
* Reorder math: when dropping `source` onto the LEFT half of
|
|
21
|
-
* `target`, the source is inserted BEFORE the target's position
|
|
22
|
-
* in the order list. RIGHT half → AFTER.
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
export interface UseColumnReorderArgs {
|
|
26
|
-
/** The current order. */
|
|
27
|
-
order: string[];
|
|
28
|
-
/** Commit a new order. */
|
|
29
|
-
onChange: (next: string[]) => void;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface DropTarget {
|
|
33
|
-
field: string;
|
|
34
|
-
side: 'left' | 'right';
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface ColumnReorderHandlers {
|
|
38
|
-
/** Current drop target (used by the renderer to show the indicator). */
|
|
39
|
-
dropTarget: DropTarget | null;
|
|
40
|
-
/** Field currently being dragged (used to dim the source header). */
|
|
41
|
-
draggingField: string | null;
|
|
42
|
-
dragStart: (field: string) => (e: DragEvent<HTMLElement>) => void;
|
|
43
|
-
dragOver: (field: string) => (e: DragEvent<HTMLElement>) => void;
|
|
44
|
-
drop: (field: string) => (e: DragEvent<HTMLElement>) => void;
|
|
45
|
-
dragEnd: () => void;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function useColumnReorder(
|
|
49
|
-
args: UseColumnReorderArgs,
|
|
50
|
-
): ColumnReorderHandlers {
|
|
51
|
-
const { order, onChange } = args;
|
|
52
|
-
const sourceRef = useRef<string | null>(null);
|
|
53
|
-
const [dropTarget, setDropTarget] = useState<DropTarget | null>(null);
|
|
54
|
-
const [draggingField, setDraggingField] = useState<string | null>(null);
|
|
55
|
-
|
|
56
|
-
const dragStart = useCallback(
|
|
57
|
-
(field: string) => (e: DragEvent<HTMLElement>) => {
|
|
58
|
-
sourceRef.current = field;
|
|
59
|
-
setDraggingField(field);
|
|
60
|
-
try {
|
|
61
|
-
e.dataTransfer.effectAllowed = 'move';
|
|
62
|
-
// Some browsers refuse to start a drag if no data is set.
|
|
63
|
-
e.dataTransfer.setData('text/plain', field);
|
|
64
|
-
} catch {
|
|
65
|
-
/* noop — jsdom doesn't implement dataTransfer fully. */
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
[],
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
const dragOver = useCallback(
|
|
72
|
-
(field: string) => (e: DragEvent<HTMLElement>) => {
|
|
73
|
-
if (sourceRef.current == null) return;
|
|
74
|
-
if (field === sourceRef.current) return;
|
|
75
|
-
e.preventDefault();
|
|
76
|
-
e.dataTransfer.dropEffect = 'move';
|
|
77
|
-
// Determine LEFT vs RIGHT half of the target.
|
|
78
|
-
const rect = e.currentTarget.getBoundingClientRect();
|
|
79
|
-
const midpoint = rect.left + rect.width / 2;
|
|
80
|
-
const side: 'left' | 'right' = e.clientX < midpoint ? 'left' : 'right';
|
|
81
|
-
setDropTarget((prev) =>
|
|
82
|
-
prev && prev.field === field && prev.side === side
|
|
83
|
-
? prev
|
|
84
|
-
: { field, side },
|
|
85
|
-
);
|
|
86
|
-
},
|
|
87
|
-
[],
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
const drop = useCallback(
|
|
91
|
-
(field: string) => (e: DragEvent<HTMLElement>) => {
|
|
92
|
-
e.preventDefault();
|
|
93
|
-
const source = sourceRef.current;
|
|
94
|
-
sourceRef.current = null;
|
|
95
|
-
setDraggingField(null);
|
|
96
|
-
const target = dropTarget;
|
|
97
|
-
setDropTarget(null);
|
|
98
|
-
if (!source || source === field) return;
|
|
99
|
-
const side = target?.field === field ? target.side : 'right';
|
|
100
|
-
const next = moveColumn(order, source, field, side);
|
|
101
|
-
if (!arraysEqual(next, order)) onChange(next);
|
|
102
|
-
},
|
|
103
|
-
[order, onChange, dropTarget],
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
const dragEnd = useCallback(() => {
|
|
107
|
-
sourceRef.current = null;
|
|
108
|
-
setDraggingField(null);
|
|
109
|
-
setDropTarget(null);
|
|
110
|
-
}, []);
|
|
111
|
-
|
|
112
|
-
return { dropTarget, draggingField, dragStart, dragOver, drop, dragEnd };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Move `source` next to `target` in the `order` list.
|
|
117
|
-
* `side='left'` inserts before; `side='right'` inserts after.
|
|
118
|
-
* Exposed for unit testing.
|
|
119
|
-
*/
|
|
120
|
-
export function moveColumn(
|
|
121
|
-
order: string[],
|
|
122
|
-
source: string,
|
|
123
|
-
target: string,
|
|
124
|
-
side: 'left' | 'right',
|
|
125
|
-
): string[] {
|
|
126
|
-
const withoutSource = order.filter((f) => f !== source);
|
|
127
|
-
const targetIndex = withoutSource.indexOf(target);
|
|
128
|
-
if (targetIndex === -1) return order;
|
|
129
|
-
const insertAt = side === 'left' ? targetIndex : targetIndex + 1;
|
|
130
|
-
return [
|
|
131
|
-
...withoutSource.slice(0, insertAt),
|
|
132
|
-
source,
|
|
133
|
-
...withoutSource.slice(insertAt),
|
|
134
|
-
];
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function arraysEqual(a: string[], b: string[]): boolean {
|
|
138
|
-
if (a === b) return true;
|
|
139
|
-
if (a.length !== b.length) return false;
|
|
140
|
-
for (let i = 0; i < a.length; i++) {
|
|
141
|
-
if (a[i] !== b[i]) return false;
|
|
142
|
-
}
|
|
143
|
-
return true;
|
|
144
|
-
}
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
/**
|
|
3
|
-
* Unit tests for `useColumnResize` — the pointer-drag + keyboard
|
|
4
|
-
* column-resize hook (Sprint 4.2-bis, keyboard `nudge` added in
|
|
5
|
-
* Sprint 6 P2). Sprint 6 P4 — direct coverage of the clamp logic
|
|
6
|
-
* and the drag commit path.
|
|
7
|
-
*/
|
|
8
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
9
|
-
import { renderHook } from '@testing-library/react';
|
|
10
|
-
import { useColumnResize } from './useColumnResize.js';
|
|
11
|
-
|
|
12
|
-
describe('useColumnResize — nudge (keyboard path)', () => {
|
|
13
|
-
it('commits currentWidth + delta', () => {
|
|
14
|
-
const onChange = vi.fn();
|
|
15
|
-
const { result } = renderHook(() =>
|
|
16
|
-
useColumnResize({ widths: { a: 100 }, onChange }),
|
|
17
|
-
);
|
|
18
|
-
result.current.nudge('a', 100, 16, 40, 400);
|
|
19
|
-
expect(onChange).toHaveBeenCalledWith({ a: 116 });
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('clamps to the effective minimum', () => {
|
|
23
|
-
const onChange = vi.fn();
|
|
24
|
-
const { result } = renderHook(() =>
|
|
25
|
-
useColumnResize({ widths: { a: 50 }, onChange }),
|
|
26
|
-
);
|
|
27
|
-
// currentWidth 50, delta -64 → 14, clamped up to min 40.
|
|
28
|
-
result.current.nudge('a', 50, -64, 40, 400);
|
|
29
|
-
expect(onChange).toHaveBeenCalledWith({ a: 40 });
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('clamps to the effective maximum', () => {
|
|
33
|
-
const onChange = vi.fn();
|
|
34
|
-
const { result } = renderHook(() =>
|
|
35
|
-
useColumnResize({ widths: { a: 380 }, onChange }),
|
|
36
|
-
);
|
|
37
|
-
// currentWidth 380, delta +64 → 444, clamped down to max 400.
|
|
38
|
-
result.current.nudge('a', 380, 64, 40, 400);
|
|
39
|
-
expect(onChange).toHaveBeenCalledWith({ a: 400 });
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('honors the hook-level minWidth/maxWidth floor/ceiling', () => {
|
|
43
|
-
const onChange = vi.fn();
|
|
44
|
-
const { result } = renderHook(() =>
|
|
45
|
-
useColumnResize({
|
|
46
|
-
widths: {},
|
|
47
|
-
onChange,
|
|
48
|
-
minWidth: 80,
|
|
49
|
-
maxWidth: 200,
|
|
50
|
-
}),
|
|
51
|
-
);
|
|
52
|
-
// clampMin 40 < hook min 80 → effective min is 80.
|
|
53
|
-
result.current.nudge('a', 100, -64, 40, 1000);
|
|
54
|
-
expect(onChange).toHaveBeenCalledWith({ a: 80 });
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('preserves the other columns in the width map', () => {
|
|
58
|
-
const onChange = vi.fn();
|
|
59
|
-
const { result } = renderHook(() =>
|
|
60
|
-
useColumnResize({ widths: { a: 100, b: 200 }, onChange }),
|
|
61
|
-
);
|
|
62
|
-
result.current.nudge('a', 100, 16, 40, 400);
|
|
63
|
-
expect(onChange).toHaveBeenCalledWith({ a: 116, b: 200 });
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
describe('useColumnResize — startResize (pointer-drag path)', () => {
|
|
68
|
-
it('returns an event handler from the factory', () => {
|
|
69
|
-
const { result } = renderHook(() =>
|
|
70
|
-
useColumnResize({ widths: {}, onChange: () => {} }),
|
|
71
|
-
);
|
|
72
|
-
const handler = result.current.startResize('a', 100, 40, 400);
|
|
73
|
-
expect(typeof handler).toBe('function');
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('a pointer drag commits a clamped new width via pointermove', () => {
|
|
77
|
-
const onChange = vi.fn();
|
|
78
|
-
const { result } = renderHook(() =>
|
|
79
|
-
useColumnResize({ widths: { a: 100 }, onChange }),
|
|
80
|
-
);
|
|
81
|
-
const el = document.createElement('span');
|
|
82
|
-
document.body.appendChild(el);
|
|
83
|
-
|
|
84
|
-
// Synthetic pointerdown — shape mirrors React's PointerEvent.
|
|
85
|
-
const downEvent = {
|
|
86
|
-
pointerType: 'mouse',
|
|
87
|
-
button: 0,
|
|
88
|
-
clientX: 500,
|
|
89
|
-
pointerId: 1,
|
|
90
|
-
currentTarget: el,
|
|
91
|
-
preventDefault: () => {},
|
|
92
|
-
stopPropagation: () => {},
|
|
93
|
-
} as unknown as React.PointerEvent<HTMLElement>;
|
|
94
|
-
|
|
95
|
-
result.current.startResize('a', 100, 40, 400)(downEvent);
|
|
96
|
-
|
|
97
|
-
// Drag 30px to the right → 100 + 30 = 130.
|
|
98
|
-
const move = new Event('pointermove') as Event & { clientX: number };
|
|
99
|
-
move.clientX = 530;
|
|
100
|
-
el.dispatchEvent(move);
|
|
101
|
-
expect(onChange).toHaveBeenLastCalledWith({ a: 130 });
|
|
102
|
-
|
|
103
|
-
// Drag far left → clamps to min 40.
|
|
104
|
-
const move2 = new Event('pointermove') as Event & { clientX: number };
|
|
105
|
-
move2.clientX = 0;
|
|
106
|
-
el.dispatchEvent(move2);
|
|
107
|
-
expect(onChange).toHaveBeenLastCalledWith({ a: 40 });
|
|
108
|
-
|
|
109
|
-
// pointerup tears the listeners down — a later move is a no-op.
|
|
110
|
-
const up = new Event('pointerup') as Event & { pointerId: number };
|
|
111
|
-
up.pointerId = 1;
|
|
112
|
-
el.dispatchEvent(up);
|
|
113
|
-
onChange.mockClear();
|
|
114
|
-
const move3 = new Event('pointermove') as Event & { clientX: number };
|
|
115
|
-
move3.clientX = 999;
|
|
116
|
-
el.dispatchEvent(move3);
|
|
117
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
118
|
-
|
|
119
|
-
document.body.removeChild(el);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it('ignores a non-primary mouse button', () => {
|
|
123
|
-
const onChange = vi.fn();
|
|
124
|
-
const { result } = renderHook(() =>
|
|
125
|
-
useColumnResize({ widths: {}, onChange }),
|
|
126
|
-
);
|
|
127
|
-
const el = document.createElement('span');
|
|
128
|
-
const downEvent = {
|
|
129
|
-
pointerType: 'mouse',
|
|
130
|
-
button: 2, // right-click
|
|
131
|
-
clientX: 0,
|
|
132
|
-
pointerId: 1,
|
|
133
|
-
currentTarget: el,
|
|
134
|
-
preventDefault: () => {},
|
|
135
|
-
stopPropagation: () => {},
|
|
136
|
-
} as unknown as React.PointerEvent<HTMLElement>;
|
|
137
|
-
result.current.startResize('a', 100, 40, 400)(downEvent);
|
|
138
|
-
const move = new Event('pointermove') as Event & { clientX: number };
|
|
139
|
-
move.clientX = 200;
|
|
140
|
-
el.dispatchEvent(move);
|
|
141
|
-
// No listener was attached → no commit.
|
|
142
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
143
|
-
});
|
|
144
|
-
});
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import { useCallback, useRef, type PointerEvent as RPointerEvent } from 'react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Native column-resize behavior for DataGrid (and Table later if
|
|
5
|
-
* promoted to `_shared`).
|
|
6
|
-
*
|
|
7
|
-
* The returned `startResize` is wired to a `pointerdown` handler on a
|
|
8
|
-
* thin grabber positioned at the right edge of a `<th>`. We capture
|
|
9
|
-
* the pointer on the target element so `pointermove` / `pointerup`
|
|
10
|
-
* keep flowing even if the cursor leaves the grabber.
|
|
11
|
-
*
|
|
12
|
-
* Why native pointer events vs a drag library:
|
|
13
|
-
* - Zero new runtime deps (sprint constraint)
|
|
14
|
-
* - Pointer events normalize mouse/touch/pen out of the box
|
|
15
|
-
* - Pointer capture means we don't have to track the global
|
|
16
|
-
* `mousemove` / `mouseup` — the browser routes events to our
|
|
17
|
-
* listener until release.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
export interface UseColumnResizeArgs {
|
|
21
|
-
/** Current column widths (Record<field, px>). */
|
|
22
|
-
widths: Record<string, number>;
|
|
23
|
-
/** Commit a new width map. */
|
|
24
|
-
onChange: (next: Record<string, number>) => void;
|
|
25
|
-
/** Hard floor for any column (px). @default 40 */
|
|
26
|
-
minWidth?: number;
|
|
27
|
-
/** Hard ceiling for any column (px). @default 1200 */
|
|
28
|
-
maxWidth?: number;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface ColumnResizeHandlers {
|
|
32
|
-
startResize: (
|
|
33
|
-
field: string,
|
|
34
|
-
startWidth: number,
|
|
35
|
-
clampMin: number,
|
|
36
|
-
clampMax: number,
|
|
37
|
-
) => (e: RPointerEvent<HTMLElement>) => void;
|
|
38
|
-
/**
|
|
39
|
-
* Commit a single clamped width delta — the keyboard-resize path.
|
|
40
|
-
* Wired to ArrowLeft/ArrowRight on the focused resize handle so the
|
|
41
|
-
* feature is reachable without a pointer (WCAG 2.1 — keyboard
|
|
42
|
-
* operability). Same clamping as the drag path.
|
|
43
|
-
*/
|
|
44
|
-
nudge: (
|
|
45
|
-
field: string,
|
|
46
|
-
currentWidth: number,
|
|
47
|
-
delta: number,
|
|
48
|
-
clampMin: number,
|
|
49
|
-
clampMax: number,
|
|
50
|
-
) => void;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function useColumnResize(args: UseColumnResizeArgs): ColumnResizeHandlers {
|
|
54
|
-
const { widths, onChange, minWidth = 40, maxWidth = 1200 } = args;
|
|
55
|
-
|
|
56
|
-
// We need the LATEST widths inside the pointermove closure. Stick
|
|
57
|
-
// them in a ref so the closure captured at pointerdown stays valid
|
|
58
|
-
// for the duration of the drag.
|
|
59
|
-
const widthsRef = useRef(widths);
|
|
60
|
-
widthsRef.current = widths;
|
|
61
|
-
|
|
62
|
-
const startResize = useCallback(
|
|
63
|
-
(
|
|
64
|
-
field: string,
|
|
65
|
-
startWidth: number,
|
|
66
|
-
clampMin: number,
|
|
67
|
-
clampMax: number,
|
|
68
|
-
) => {
|
|
69
|
-
return (e: RPointerEvent<HTMLElement>) => {
|
|
70
|
-
// Only respond to the primary mouse button (or touch / pen).
|
|
71
|
-
if (e.pointerType === 'mouse' && e.button !== 0) return;
|
|
72
|
-
|
|
73
|
-
e.preventDefault();
|
|
74
|
-
e.stopPropagation();
|
|
75
|
-
|
|
76
|
-
const startX = e.clientX;
|
|
77
|
-
const target = e.currentTarget;
|
|
78
|
-
try {
|
|
79
|
-
target.setPointerCapture(e.pointerId);
|
|
80
|
-
} catch {
|
|
81
|
-
// jsdom or older browsers — fine to fall back to global listeners.
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const effectiveMin = Math.max(minWidth, clampMin);
|
|
85
|
-
const effectiveMax = Math.min(maxWidth, clampMax);
|
|
86
|
-
|
|
87
|
-
const handleMove = (ev: PointerEvent) => {
|
|
88
|
-
const delta = ev.clientX - startX;
|
|
89
|
-
const next = clamp(startWidth + delta, effectiveMin, effectiveMax);
|
|
90
|
-
onChange({ ...widthsRef.current, [field]: next });
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const handleEnd = (ev: PointerEvent) => {
|
|
94
|
-
try {
|
|
95
|
-
target.releasePointerCapture(ev.pointerId);
|
|
96
|
-
} catch {
|
|
97
|
-
/* noop */
|
|
98
|
-
}
|
|
99
|
-
target.removeEventListener('pointermove', handleMove);
|
|
100
|
-
target.removeEventListener('pointerup', handleEnd);
|
|
101
|
-
target.removeEventListener('pointercancel', handleEnd);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
target.addEventListener('pointermove', handleMove);
|
|
105
|
-
target.addEventListener('pointerup', handleEnd);
|
|
106
|
-
target.addEventListener('pointercancel', handleEnd);
|
|
107
|
-
};
|
|
108
|
-
},
|
|
109
|
-
[onChange, minWidth, maxWidth],
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
const nudge = useCallback(
|
|
113
|
-
(
|
|
114
|
-
field: string,
|
|
115
|
-
currentWidth: number,
|
|
116
|
-
delta: number,
|
|
117
|
-
clampMin: number,
|
|
118
|
-
clampMax: number,
|
|
119
|
-
) => {
|
|
120
|
-
const effectiveMin = Math.max(minWidth, clampMin);
|
|
121
|
-
const effectiveMax = Math.min(maxWidth, clampMax);
|
|
122
|
-
const next = clamp(currentWidth + delta, effectiveMin, effectiveMax);
|
|
123
|
-
onChange({ ...widthsRef.current, [field]: next });
|
|
124
|
-
},
|
|
125
|
-
[onChange, minWidth, maxWidth],
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
return { startResize, nudge };
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function clamp(n: number, min: number, max: number): number {
|
|
132
|
-
if (n < min) return min;
|
|
133
|
-
if (n > max) return max;
|
|
134
|
-
return n;
|
|
135
|
-
}
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import { useState, type ReactNode } from 'react';
|
|
2
|
-
import { Popover } from '../../Popover/Popover.js';
|
|
3
|
-
import { cn } from '../../../utils/cn.js';
|
|
4
|
-
import type { TableColumn } from '../../Table/table.types.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Column visibility menu for DataGrid.
|
|
8
|
-
*
|
|
9
|
-
* Renders a toolbar button (the trigger) that opens a `<Popover>`
|
|
10
|
-
* with one checkbox per `hideable` column. Auto-commits on every
|
|
11
|
-
* toggle — there's no draft / commit step. Outside-click and Esc
|
|
12
|
-
* close the popover (Radix-managed).
|
|
13
|
-
*
|
|
14
|
-
* UX rationale for Popover-over-Dialog:
|
|
15
|
-
* - Lightweight, non-modal: the user can keep referring to the grid
|
|
16
|
-
* while picking columns. A modal Dialog would interrupt the flow.
|
|
17
|
-
* - Auto-commit reads as a "settings panel" rather than a
|
|
18
|
-
* "configuration form" — matches AG-Grid / MUI DataGrid v6 /
|
|
19
|
-
* TanStack examples.
|
|
20
|
-
* - No focus trap on the rest of the page; the user can scroll the
|
|
21
|
-
* grid or click the column resize handles without dismissing the
|
|
22
|
-
* panel first.
|
|
23
|
-
*
|
|
24
|
-
* Columns with `hideable: false` are NEVER shown in the menu —
|
|
25
|
-
* those are considered structurally required (e.g. an ID column).
|
|
26
|
-
*
|
|
27
|
-
* RBAC-hidden columns (`access.onUnauthorized === 'hide'`) are also
|
|
28
|
-
* excluded — they're already removed from `visibleCols` upstream.
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
export interface ColumnVisibilityLabels {
|
|
32
|
-
columnsButton?: string;
|
|
33
|
-
columnsTitle?: string;
|
|
34
|
-
/**
|
|
35
|
-
* Accessible label for the tri-state master checkbox that
|
|
36
|
-
* shows/hides every hideable column at once. Not shown as visible
|
|
37
|
-
* text — surfaced to assistive tech via `aria-label`.
|
|
38
|
-
*/
|
|
39
|
-
columnsToggleAll?: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const DEFAULT_VISIBILITY_LABELS: Required<ColumnVisibilityLabels> = {
|
|
43
|
-
columnsButton: 'Columns',
|
|
44
|
-
columnsTitle: 'Toggle columns',
|
|
45
|
-
columnsToggleAll: 'Toggle all columns',
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export interface ColumnVisibilityTriggerProps<T extends object> {
|
|
49
|
-
cols: TableColumn<T>[];
|
|
50
|
-
hiddenColumns: string[];
|
|
51
|
-
onChange: (next: string[]) => void;
|
|
52
|
-
disabled?: boolean;
|
|
53
|
-
labels?: ColumnVisibilityLabels;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function ColumnVisibilityTrigger<T extends object>(
|
|
57
|
-
props: ColumnVisibilityTriggerProps<T>,
|
|
58
|
-
) {
|
|
59
|
-
const { cols, hiddenColumns, onChange, disabled, labels: labelsProp } = props;
|
|
60
|
-
const labels = { ...DEFAULT_VISIBILITY_LABELS, ...labelsProp };
|
|
61
|
-
const [open, setOpen] = useState(false);
|
|
62
|
-
|
|
63
|
-
// Hideable cols are the only ones the user can toggle. `hideable`
|
|
64
|
-
// defaults to `true` — a column is hideable unless explicitly opted
|
|
65
|
-
// out with `hideable: false` (structurally required column).
|
|
66
|
-
const hideableCols = cols.filter((c) => c.hideable !== false);
|
|
67
|
-
|
|
68
|
-
const toggle = (field: string) => {
|
|
69
|
-
onChange(
|
|
70
|
-
hiddenColumns.includes(field)
|
|
71
|
-
? hiddenColumns.filter((f) => f !== field)
|
|
72
|
-
: [...hiddenColumns, field],
|
|
73
|
-
);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// Tri-state master: checked = every hideable column visible,
|
|
77
|
-
// unchecked = every one hidden, indeterminate = mixed.
|
|
78
|
-
const allVisible = hideableCols.every(
|
|
79
|
-
(c) => !hiddenColumns.includes(c.field as string),
|
|
80
|
-
);
|
|
81
|
-
const allHidden =
|
|
82
|
-
hideableCols.length > 0 &&
|
|
83
|
-
hideableCols.every((c) => hiddenColumns.includes(c.field as string));
|
|
84
|
-
const someHidden = !allVisible && !allHidden;
|
|
85
|
-
|
|
86
|
-
// Standard select-all semantics: when everything is visible the
|
|
87
|
-
// master hides all; otherwise it shows all.
|
|
88
|
-
const toggleAll = () => {
|
|
89
|
-
onChange(allVisible ? hideableCols.map((c) => c.field as string) : []);
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
return (
|
|
93
|
-
<Popover
|
|
94
|
-
open={open}
|
|
95
|
-
onOpenChange={setOpen}
|
|
96
|
-
side="bottom"
|
|
97
|
-
align="end"
|
|
98
|
-
content={
|
|
99
|
-
<div className="flex flex-col gap-1 min-w-[220px]">
|
|
100
|
-
{/*
|
|
101
|
-
Header row — the tri-state master checkbox + the title.
|
|
102
|
-
The master replaces the old "Show all · Hide all" text
|
|
103
|
-
links: one control, no extra copy, consistent with the
|
|
104
|
-
DataGrid row select-all checkbox. The title is a heading
|
|
105
|
-
(not part of the checkbox label) and stays consumer-
|
|
106
|
-
customizable via `labels.columnsTitle`.
|
|
107
|
-
*/}
|
|
108
|
-
<div className="flex items-center gap-2 px-1 pb-2 mb-1 border-b border-neutral-200">
|
|
109
|
-
<input
|
|
110
|
-
type="checkbox"
|
|
111
|
-
aria-label={labels.columnsToggleAll}
|
|
112
|
-
checked={allVisible}
|
|
113
|
-
ref={(el) => {
|
|
114
|
-
if (el) el.indeterminate = someHidden;
|
|
115
|
-
}}
|
|
116
|
-
onChange={toggleAll}
|
|
117
|
-
className="cursor-pointer"
|
|
118
|
-
/>
|
|
119
|
-
<span className="text-xs font-semibold text-neutral-700 uppercase tracking-wide">
|
|
120
|
-
{labels.columnsTitle}
|
|
121
|
-
</span>
|
|
122
|
-
</div>
|
|
123
|
-
<ul className="flex flex-col gap-0.5 max-h-72 overflow-auto list-none pl-0 m-0">
|
|
124
|
-
{hideableCols.map((col) => {
|
|
125
|
-
const field = col.field as string;
|
|
126
|
-
const hidden = hiddenColumns.includes(field);
|
|
127
|
-
const header =
|
|
128
|
-
typeof col.header === 'function' ? col.header() : col.header;
|
|
129
|
-
return (
|
|
130
|
-
<li key={field}>
|
|
131
|
-
<label className="flex items-center gap-2 cursor-pointer py-1 px-1 rounded hover:bg-neutral-100">
|
|
132
|
-
<input
|
|
133
|
-
type="checkbox"
|
|
134
|
-
checked={!hidden}
|
|
135
|
-
onChange={() => toggle(field)}
|
|
136
|
-
className="cursor-pointer"
|
|
137
|
-
/>
|
|
138
|
-
<span className="text-sm text-neutral-900">{header}</span>
|
|
139
|
-
</label>
|
|
140
|
-
</li>
|
|
141
|
-
);
|
|
142
|
-
})}
|
|
143
|
-
</ul>
|
|
144
|
-
</div>
|
|
145
|
-
}
|
|
146
|
-
>
|
|
147
|
-
<button
|
|
148
|
-
type="button"
|
|
149
|
-
disabled={disabled}
|
|
150
|
-
className={cn(
|
|
151
|
-
'inline-flex items-center gap-1.5 px-2.5 py-1.5 rounded-md',
|
|
152
|
-
'text-sm text-neutral-700 hover:text-neutral-900',
|
|
153
|
-
'border border-neutral-300 bg-neutral-50 hover:bg-neutral-100',
|
|
154
|
-
'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
|
|
155
|
-
'transition-colors motion-reduce:transition-none',
|
|
156
|
-
'disabled:opacity-50 disabled:cursor-not-allowed',
|
|
157
|
-
)}
|
|
158
|
-
>
|
|
159
|
-
<ColumnsIcon />
|
|
160
|
-
<span>{labels.columnsButton}</span>
|
|
161
|
-
</button>
|
|
162
|
-
</Popover>
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// ───── Icon ─────
|
|
167
|
-
|
|
168
|
-
function ColumnsIcon(): ReactNode {
|
|
169
|
-
return (
|
|
170
|
-
<svg
|
|
171
|
-
width="0.875em"
|
|
172
|
-
height="0.875em"
|
|
173
|
-
viewBox="0 0 16 16"
|
|
174
|
-
fill="none"
|
|
175
|
-
stroke="currentColor"
|
|
176
|
-
strokeWidth="1.5"
|
|
177
|
-
strokeLinecap="round"
|
|
178
|
-
strokeLinejoin="round"
|
|
179
|
-
aria-hidden="true"
|
|
180
|
-
>
|
|
181
|
-
<rect x="2" y="3" width="3.5" height="10" rx="0.5" />
|
|
182
|
-
<rect x="6.25" y="3" width="3.5" height="10" rx="0.5" />
|
|
183
|
-
<rect x="10.5" y="3" width="3.5" height="10" rx="0.5" />
|
|
184
|
-
</svg>
|
|
185
|
-
);
|
|
186
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { describe, it, expect, vi, beforeAll } from 'vitest';
|
|
3
|
-
import { render, screen, fireEvent } from '@testing-library/react';
|
|
4
|
-
|
|
5
|
-
import { DatePicker } from './DatePicker.js';
|
|
6
|
-
|
|
7
|
-
beforeAll(() => {
|
|
8
|
-
// Radix Popover (Floating UI) needs ResizeObserver — jsdom lacks it.
|
|
9
|
-
if (!('ResizeObserver' in globalThis)) {
|
|
10
|
-
class ResizeObserverStub {
|
|
11
|
-
observe(): void {
|
|
12
|
-
/* no-op */
|
|
13
|
-
}
|
|
14
|
-
unobserve(): void {
|
|
15
|
-
/* no-op */
|
|
16
|
-
}
|
|
17
|
-
disconnect(): void {
|
|
18
|
-
/* no-op */
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
(globalThis as { ResizeObserver?: unknown }).ResizeObserver =
|
|
22
|
-
ResizeObserverStub;
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
describe('DatePicker', () => {
|
|
27
|
-
it('renders a labelled trigger with the placeholder', () => {
|
|
28
|
-
render(
|
|
29
|
-
<DatePicker name="birthday" label="Birthday" placeholder="Pick one" />,
|
|
30
|
-
);
|
|
31
|
-
expect(screen.queryByText('Birthday')).not.toBeNull();
|
|
32
|
-
expect(screen.getByRole('button').textContent).toContain('Pick one');
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('shows a localized controlled value', () => {
|
|
36
|
-
render(<DatePicker name="d" value="2026-05-20" />);
|
|
37
|
-
expect(screen.getByRole('button').textContent).toContain('May 20, 2026');
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('opens and toggles the calendar popover from the trigger', () => {
|
|
41
|
-
render(<DatePicker name="d" defaultValue="2026-05-20" />);
|
|
42
|
-
const trigger = screen.getByRole('button');
|
|
43
|
-
expect(screen.queryByRole('dialog')).toBeNull();
|
|
44
|
-
fireEvent.click(trigger);
|
|
45
|
-
expect(screen.queryByRole('dialog')).not.toBeNull();
|
|
46
|
-
fireEvent.click(trigger);
|
|
47
|
-
expect(screen.queryByRole('dialog')).toBeNull();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('selects a date from the popover, updates the trigger and closes', () => {
|
|
51
|
-
const onChange = vi.fn();
|
|
52
|
-
render(
|
|
53
|
-
<DatePicker name="d" defaultValue="2026-05-20" onChange={onChange} />,
|
|
54
|
-
);
|
|
55
|
-
fireEvent.click(screen.getByRole('button'));
|
|
56
|
-
fireEvent.click(screen.getByRole('button', { name: /May 15, 2026/ }));
|
|
57
|
-
expect(onChange).toHaveBeenCalledWith('2026-05-15');
|
|
58
|
-
expect(screen.queryByRole('dialog')).toBeNull();
|
|
59
|
-
expect(screen.getByRole('button').textContent).toContain('May 15, 2026');
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('keeps a controlled value fixed but still reports the change', () => {
|
|
63
|
-
const onChange = vi.fn();
|
|
64
|
-
render(<DatePicker name="d" value="2026-05-20" onChange={onChange} />);
|
|
65
|
-
fireEvent.click(screen.getByRole('button'));
|
|
66
|
-
fireEvent.click(screen.getByRole('button', { name: /May 15, 2026/ }));
|
|
67
|
-
expect(onChange).toHaveBeenCalledWith('2026-05-15');
|
|
68
|
-
expect(screen.getByRole('button').textContent).toContain('May 20, 2026');
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('does not open the popover when disabled', () => {
|
|
72
|
-
render(<DatePicker name="d" disabled />);
|
|
73
|
-
fireEvent.click(screen.getByRole('button'));
|
|
74
|
-
expect(screen.queryByRole('dialog')).toBeNull();
|
|
75
|
-
});
|
|
76
|
-
});
|