@dashforge/tw 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +134 -1
- package/README.md +45 -0
- package/dist/index.esm.js +3986 -477
- package/dist/src/components/Accordion/Accordion.d.ts.map +1 -1
- package/dist/src/components/Accordion/accordion.types.d.ts +7 -0
- package/dist/src/components/Accordion/accordion.types.d.ts.map +1 -1
- package/dist/src/components/Alert/Alert.d.ts +1 -1
- package/dist/src/components/Alert/Alert.d.ts.map +1 -1
- package/dist/src/components/Alert/alert.types.d.ts +17 -0
- package/dist/src/components/Alert/alert.types.d.ts.map +1 -1
- package/dist/src/components/AppShell/AppShell.d.ts.map +1 -1
- package/dist/src/components/AppShell/appShell.types.d.ts +7 -0
- package/dist/src/components/AppShell/appShell.types.d.ts.map +1 -1
- package/dist/src/components/Autocomplete/Autocomplete.d.ts.map +1 -1
- package/dist/src/components/Autocomplete/autocomplete.types.d.ts +47 -1
- package/dist/src/components/Autocomplete/autocomplete.types.d.ts.map +1 -1
- package/dist/src/components/Avatar/Avatar.d.ts.map +1 -1
- package/dist/src/components/Avatar/avatar.types.d.ts +17 -1
- package/dist/src/components/Avatar/avatar.types.d.ts.map +1 -1
- package/dist/src/components/Badge/Badge.d.ts.map +1 -1
- package/dist/src/components/Badge/badge.types.d.ts +27 -2
- package/dist/src/components/Badge/badge.types.d.ts.map +1 -1
- package/dist/src/components/Box/Box.d.ts.map +1 -1
- package/dist/src/components/Box/box.types.d.ts +64 -1
- package/dist/src/components/Box/box.types.d.ts.map +1 -1
- package/dist/src/components/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
- package/dist/src/components/Breadcrumbs/breadcrumbs.types.d.ts +26 -1
- package/dist/src/components/Breadcrumbs/breadcrumbs.types.d.ts.map +1 -1
- package/dist/src/components/Button/Button.d.ts.map +1 -1
- package/dist/src/components/Button/button.types.d.ts +53 -1
- package/dist/src/components/Button/button.types.d.ts.map +1 -1
- package/dist/src/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/src/components/Calendar/calendar.types.d.ts +16 -0
- package/dist/src/components/Calendar/calendar.types.d.ts.map +1 -1
- package/dist/src/components/Card/Card.d.ts.map +1 -1
- package/dist/src/components/Card/card.types.d.ts +17 -0
- package/dist/src/components/Card/card.types.d.ts.map +1 -1
- package/dist/src/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/src/components/Checkbox/checkbox.types.d.ts +19 -1
- package/dist/src/components/Checkbox/checkbox.types.d.ts.map +1 -1
- package/dist/src/components/Chip/Chip.d.ts.map +1 -1
- package/dist/src/components/Chip/chip.types.d.ts +40 -1
- package/dist/src/components/Chip/chip.types.d.ts.map +1 -1
- package/dist/src/components/ConfirmDialog/ConfirmDialog.d.ts.map +1 -1
- package/dist/src/components/ConfirmDialog/confirmDialog.types.d.ts +30 -2
- package/dist/src/components/ConfirmDialog/confirmDialog.types.d.ts.map +1 -1
- package/dist/src/components/Container/Container.d.ts.map +1 -1
- package/dist/src/components/Container/container.types.d.ts +29 -1
- package/dist/src/components/Container/container.types.d.ts.map +1 -1
- package/dist/src/components/DataGrid/DataGrid.d.ts +1 -1
- package/dist/src/components/DataGrid/DataGrid.d.ts.map +1 -1
- package/dist/src/components/DataGrid/dataGrid.types.d.ts +124 -10
- package/dist/src/components/DataGrid/dataGrid.types.d.ts.map +1 -1
- package/dist/src/components/DatePicker/DatePicker.d.ts +1 -1
- package/dist/src/components/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist/src/components/DatePicker/datePicker.types.d.ts +18 -0
- package/dist/src/components/DatePicker/datePicker.types.d.ts.map +1 -1
- package/dist/src/components/DateRangePicker/DateRangePicker.d.ts +1 -1
- package/dist/src/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
- package/dist/src/components/DateRangePicker/dateRangePicker.types.d.ts +18 -0
- package/dist/src/components/DateRangePicker/dateRangePicker.types.d.ts.map +1 -1
- package/dist/src/components/DateTimePicker/DateTimePicker.d.ts +1 -1
- package/dist/src/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
- package/dist/src/components/DateTimePicker/dateTimePicker.types.d.ts +20 -0
- package/dist/src/components/DateTimePicker/dateTimePicker.types.d.ts.map +1 -1
- package/dist/src/components/Dialog/Dialog.d.ts.map +1 -1
- package/dist/src/components/Dialog/dialog.types.d.ts +25 -1
- package/dist/src/components/Dialog/dialog.types.d.ts.map +1 -1
- package/dist/src/components/Divider/Divider.d.ts.map +1 -1
- package/dist/src/components/Divider/divider.types.d.ts +37 -1
- package/dist/src/components/Divider/divider.types.d.ts.map +1 -1
- package/dist/src/components/Drawer/Drawer.d.ts +21 -0
- package/dist/src/components/Drawer/Drawer.d.ts.map +1 -0
- package/dist/src/components/Drawer/drawer.types.d.ts +311 -0
- package/dist/src/components/Drawer/drawer.types.d.ts.map +1 -0
- package/dist/src/components/Drawer/drawer.variants.d.ts +177 -0
- package/dist/src/components/Drawer/drawer.variants.d.ts.map +1 -0
- package/dist/src/components/Grid/Grid.d.ts.map +1 -1
- package/dist/src/components/Grid/grid.types.d.ts +16 -0
- package/dist/src/components/Grid/grid.types.d.ts.map +1 -1
- package/dist/src/components/IconButton/IconButton.d.ts.map +1 -1
- package/dist/src/components/IconButton/iconButton.types.d.ts +40 -1
- package/dist/src/components/IconButton/iconButton.types.d.ts.map +1 -1
- package/dist/src/components/LeftNav/LeftNav.d.ts.map +1 -1
- package/dist/src/components/LeftNav/leftNav.types.d.ts +26 -6
- package/dist/src/components/LeftNav/leftNav.types.d.ts.map +1 -1
- package/dist/src/components/Link/Link.d.ts +15 -0
- package/dist/src/components/Link/Link.d.ts.map +1 -0
- package/dist/src/components/Link/link.types.d.ts +169 -0
- package/dist/src/components/Link/link.types.d.ts.map +1 -0
- package/dist/src/components/Link/link.variants.d.ts +107 -0
- package/dist/src/components/Link/link.variants.d.ts.map +1 -0
- package/dist/src/components/Menu/Menu.d.ts +1 -1
- package/dist/src/components/Menu/Menu.d.ts.map +1 -1
- package/dist/src/components/Menu/menu.types.d.ts +20 -0
- package/dist/src/components/Menu/menu.types.d.ts.map +1 -1
- package/dist/src/components/NumberField/NumberField.d.ts.map +1 -1
- package/dist/src/components/NumberField/numberField.types.d.ts +47 -1
- package/dist/src/components/NumberField/numberField.types.d.ts.map +1 -1
- package/dist/src/components/OTPField/OTPField.d.ts.map +1 -1
- package/dist/src/components/OTPField/otpField.types.d.ts +35 -1
- package/dist/src/components/OTPField/otpField.types.d.ts.map +1 -1
- package/dist/src/components/Pagination/Pagination.d.ts.map +1 -1
- package/dist/src/components/Pagination/pagination.types.d.ts +26 -1
- package/dist/src/components/Pagination/pagination.types.d.ts.map +1 -1
- package/dist/src/components/Popover/Popover.d.ts.map +1 -1
- package/dist/src/components/Popover/popover.types.d.ts +29 -0
- package/dist/src/components/Popover/popover.types.d.ts.map +1 -1
- package/dist/src/components/Progress/Progress.d.ts +20 -0
- package/dist/src/components/Progress/Progress.d.ts.map +1 -0
- package/dist/src/components/Progress/progress.types.d.ts +200 -0
- package/dist/src/components/Progress/progress.types.d.ts.map +1 -0
- package/dist/src/components/Progress/progress.variants.d.ts +224 -0
- package/dist/src/components/Progress/progress.variants.d.ts.map +1 -0
- package/dist/src/components/RadioGroup/RadioGroup.d.ts.map +1 -1
- package/dist/src/components/RadioGroup/radioGroup.types.d.ts +25 -1
- package/dist/src/components/RadioGroup/radioGroup.types.d.ts.map +1 -1
- package/dist/src/components/Select/Select.d.ts +14 -0
- package/dist/src/components/Select/Select.d.ts.map +1 -0
- package/dist/src/components/Select/select.types.d.ts +272 -0
- package/dist/src/components/Select/select.types.d.ts.map +1 -0
- package/dist/src/components/Select/select.variants.d.ts +204 -0
- package/dist/src/components/Select/select.variants.d.ts.map +1 -0
- package/dist/src/components/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/src/components/Skeleton/skeleton.types.d.ts +25 -1
- package/dist/src/components/Skeleton/skeleton.types.d.ts.map +1 -1
- package/dist/src/components/Slider/Slider.d.ts +15 -0
- package/dist/src/components/Slider/Slider.d.ts.map +1 -0
- package/dist/src/components/Slider/slider.types.d.ts +268 -0
- package/dist/src/components/Slider/slider.types.d.ts.map +1 -0
- package/dist/src/components/Slider/slider.variants.d.ts +313 -0
- package/dist/src/components/Slider/slider.variants.d.ts.map +1 -0
- package/dist/src/components/Snackbar/Snackbar.d.ts.map +1 -1
- package/dist/src/components/Snackbar/snackbar.types.d.ts +29 -5
- package/dist/src/components/Snackbar/snackbar.types.d.ts.map +1 -1
- package/dist/src/components/Spinner/Spinner.d.ts.map +1 -1
- package/dist/src/components/Spinner/spinner.types.d.ts +22 -2
- package/dist/src/components/Spinner/spinner.types.d.ts.map +1 -1
- package/dist/src/components/Stack/Stack.d.ts.map +1 -1
- package/dist/src/components/Stack/stack.types.d.ts +53 -2
- package/dist/src/components/Stack/stack.types.d.ts.map +1 -1
- package/dist/src/components/Stack/stack.variants.d.ts +23 -0
- package/dist/src/components/Stack/stack.variants.d.ts.map +1 -1
- package/dist/src/components/Stepper/Step.d.ts +30 -0
- package/dist/src/components/Stepper/Step.d.ts.map +1 -0
- package/dist/src/components/Stepper/Stepper.d.ts +15 -0
- package/dist/src/components/Stepper/Stepper.d.ts.map +1 -0
- package/dist/src/components/Stepper/StepperContext.d.ts +8 -0
- package/dist/src/components/Stepper/StepperContext.d.ts.map +1 -0
- package/dist/src/components/Stepper/stepper.types.d.ts +358 -0
- package/dist/src/components/Stepper/stepper.types.d.ts.map +1 -0
- package/dist/src/components/Stepper/stepper.variants.d.ts +253 -0
- package/dist/src/components/Stepper/stepper.variants.d.ts.map +1 -0
- package/dist/src/components/Stepper/useStep.d.ts +53 -0
- package/dist/src/components/Stepper/useStep.d.ts.map +1 -0
- package/dist/src/components/Switch/Switch.d.ts.map +1 -1
- package/dist/src/components/Switch/switch.types.d.ts +44 -1
- package/dist/src/components/Switch/switch.types.d.ts.map +1 -1
- package/dist/src/components/Table/Table.d.ts +1 -1
- package/dist/src/components/Table/Table.d.ts.map +1 -1
- package/dist/src/components/Table/table.types.d.ts +103 -8
- package/dist/src/components/Table/table.types.d.ts.map +1 -1
- package/dist/src/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/src/components/Tabs/tabs.types.d.ts +26 -1
- package/dist/src/components/Tabs/tabs.types.d.ts.map +1 -1
- package/dist/src/components/TextField/TextField.d.ts.map +1 -1
- package/dist/src/components/TextField/textField.types.d.ts +30 -1
- package/dist/src/components/TextField/textField.types.d.ts.map +1 -1
- package/dist/src/components/Textarea/Textarea.d.ts.map +1 -1
- package/dist/src/components/Textarea/textarea.types.d.ts +51 -1
- package/dist/src/components/Textarea/textarea.types.d.ts.map +1 -1
- package/dist/src/components/TimePicker/TimePicker.d.ts +1 -1
- package/dist/src/components/TimePicker/TimePicker.d.ts.map +1 -1
- package/dist/src/components/TimePicker/timePicker.types.d.ts +18 -0
- package/dist/src/components/TimePicker/timePicker.types.d.ts.map +1 -1
- package/dist/src/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/src/components/Tooltip/tooltip.types.d.ts +30 -0
- package/dist/src/components/Tooltip/tooltip.types.d.ts.map +1 -1
- package/dist/src/components/TopBar/TopBar.d.ts.map +1 -1
- package/dist/src/components/TopBar/topBar.types.d.ts +25 -1
- package/dist/src/components/TopBar/topBar.types.d.ts.map +1 -1
- package/dist/src/components/Typography/Typography.d.ts.map +1 -1
- package/dist/src/components/Typography/typography.types.d.ts +47 -1
- package/dist/src/components/Typography/typography.types.d.ts.map +1 -1
- package/dist/src/components/Typography/typography.variants.d.ts +2 -2
- package/dist/src/components/Typography/typography.variants.d.ts.map +1 -1
- package/dist/src/hooks/useStandaloneFieldWarning.d.ts +38 -0
- package/dist/src/hooks/useStandaloneFieldWarning.d.ts.map +1 -0
- package/dist/src/index.d.ts +62 -42
- package/dist/src/index.d.ts.map +1 -1
- package/package.json +11 -5
- 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,49 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import type { AppShellVariants } from './appShell.variants.js';
|
|
3
|
-
|
|
4
|
-
export interface AppShellSlotProps {
|
|
5
|
-
root?: { className?: string };
|
|
6
|
-
header?: { className?: string };
|
|
7
|
-
nav?: { className?: string };
|
|
8
|
-
navMobile?: { className?: string };
|
|
9
|
-
main?: { className?: string };
|
|
10
|
-
footer?: { className?: string };
|
|
11
|
-
backdrop?: { className?: string };
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Props for `<AppShell>`.
|
|
16
|
-
*
|
|
17
|
-
* Top-level layout orchestrator with 4 named slots:
|
|
18
|
-
*
|
|
19
|
-
* - `header` (top, sticky)
|
|
20
|
-
* - `nav` (left side, fixed-width on desktop, drawer on mobile)
|
|
21
|
-
* - `footer` (bottom, non-sticky)
|
|
22
|
-
* - `children` (main content, scrolls independently)
|
|
23
|
-
*
|
|
24
|
-
* Responsive behavior:
|
|
25
|
-
* - **≥ md (768px)**: nav is rendered inline at the left.
|
|
26
|
-
* - **< md**: nav slides in as an overlay drawer when
|
|
27
|
-
* `navOpen={true}` (controlled).
|
|
28
|
-
*
|
|
29
|
-
* The shell is router-agnostic — pass any nav/header content. Typical
|
|
30
|
-
* pairing is `<LeftNav>` + `<TopBar>` (with a hamburger button in
|
|
31
|
-
* `TopBar.start` that flips `navOpen`).
|
|
32
|
-
*/
|
|
33
|
-
export interface AppShellProps extends AppShellVariants {
|
|
34
|
-
header?: ReactNode;
|
|
35
|
-
nav?: ReactNode;
|
|
36
|
-
footer?: ReactNode;
|
|
37
|
-
children?: ReactNode;
|
|
38
|
-
/**
|
|
39
|
-
* Mobile drawer open state. Controlled — provide
|
|
40
|
-
* `onNavOpenChange` to update. When `undefined`, the mobile drawer
|
|
41
|
-
* is always closed (consumer hasn't wired up the toggle yet).
|
|
42
|
-
*/
|
|
43
|
-
navOpen?: boolean;
|
|
44
|
-
onNavOpenChange?: (open: boolean) => void;
|
|
45
|
-
/** Root className shortcut. */
|
|
46
|
-
sx?: string;
|
|
47
|
-
/** Per-slot className overrides. */
|
|
48
|
-
slotProps?: AppShellSlotProps;
|
|
49
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { tv, type VariantProps } from 'tailwind-variants';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Tailwind-variants recipe for `<AppShell>`.
|
|
5
|
-
*
|
|
6
|
-
* Slots:
|
|
7
|
-
* - `root` — outer flex column (full viewport)
|
|
8
|
-
* - `header` — top region
|
|
9
|
-
* - `body` — flex row holding nav + main
|
|
10
|
-
* - `nav` — desktop nav rail (md+)
|
|
11
|
-
* - `navMobile` — mobile drawer (slide-in)
|
|
12
|
-
* - `main` — scrollable content area
|
|
13
|
-
* - `footer` — bottom region
|
|
14
|
-
* - `backdrop` — semi-opaque overlay behind the mobile drawer
|
|
15
|
-
*/
|
|
16
|
-
export const appShellVariants = tv({
|
|
17
|
-
slots: {
|
|
18
|
-
root: 'flex flex-col min-h-screen bg-neutral-100',
|
|
19
|
-
header: 'shrink-0',
|
|
20
|
-
body: 'flex flex-1 min-h-0',
|
|
21
|
-
nav: 'hidden md:flex shrink-0',
|
|
22
|
-
navMobile: [
|
|
23
|
-
'flex md:hidden fixed inset-y-0 left-0 z-40',
|
|
24
|
-
// Drawer slide-in is the most prominent motion in AppShell and
|
|
25
|
-
// a clear WCAG 2.3.3 candidate. Gate the transition on
|
|
26
|
-
// `prefers-reduced-motion: no-preference`; the data-driven
|
|
27
|
-
// `-translate-x-full` / `translate-x-0` still applies, just
|
|
28
|
-
// without the smooth slide.
|
|
29
|
-
'transition-transform duration-200 ease-out motion-reduce:transition-none motion-reduce:duration-0',
|
|
30
|
-
'-translate-x-full',
|
|
31
|
-
],
|
|
32
|
-
main: 'flex-1 min-w-0 overflow-y-auto',
|
|
33
|
-
footer: 'shrink-0',
|
|
34
|
-
backdrop: [
|
|
35
|
-
'md:hidden fixed inset-0 z-30 bg-black/40',
|
|
36
|
-
// Backdrop opacity fade — micro motion, gated for consistency.
|
|
37
|
-
'transition-opacity duration-200 motion-reduce:transition-none motion-reduce:duration-0',
|
|
38
|
-
'opacity-0 pointer-events-none',
|
|
39
|
-
],
|
|
40
|
-
},
|
|
41
|
-
variants: {
|
|
42
|
-
navOpen: {
|
|
43
|
-
true: {
|
|
44
|
-
navMobile: 'translate-x-0',
|
|
45
|
-
backdrop: 'opacity-100 pointer-events-auto',
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
defaultVariants: {
|
|
50
|
-
navOpen: false,
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
export type AppShellVariants = VariantProps<typeof appShellVariants>;
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { describe, it, expect } from 'vitest';
|
|
3
|
-
import { render } from '@testing-library/react';
|
|
4
|
-
import { AspectRatio } from './AspectRatio.js';
|
|
5
|
-
|
|
6
|
-
describe('<AspectRatio>', () => {
|
|
7
|
-
// ─── Default rendering ──────────────────────────────────────────────
|
|
8
|
-
describe('default rendering', () => {
|
|
9
|
-
it('renders a <div> by default', () => {
|
|
10
|
-
const { container } = render(<AspectRatio>x</AspectRatio>);
|
|
11
|
-
expect(container.firstElementChild?.tagName).toBe('DIV');
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it('default ratio is 1 (square)', () => {
|
|
15
|
-
const { container } = render(<AspectRatio>x</AspectRatio>);
|
|
16
|
-
const el = container.firstElementChild as HTMLElement;
|
|
17
|
-
expect(el.style.aspectRatio).toBe('1 / 1');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('always has w-full baseline', () => {
|
|
21
|
-
const { container } = render(<AspectRatio>x</AspectRatio>);
|
|
22
|
-
expect(container.firstElementChild?.className).toContain('w-full');
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
// ─── ratio prop ─────────────────────────────────────────────────────
|
|
27
|
-
describe('ratio', () => {
|
|
28
|
-
it('numeric ratio 16/9 → "1.7777… / 1"', () => {
|
|
29
|
-
const { container } = render(<AspectRatio ratio={16 / 9}>x</AspectRatio>);
|
|
30
|
-
const el = container.firstElementChild as HTMLElement;
|
|
31
|
-
// 16/9 ≈ 1.7777, formatted as "<number> / 1"
|
|
32
|
-
expect(el.style.aspectRatio).toMatch(/^1\.\d+ \/ 1$/);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('numeric ratio 4/3', () => {
|
|
36
|
-
const { container } = render(<AspectRatio ratio={4 / 3}>x</AspectRatio>);
|
|
37
|
-
const el = container.firstElementChild as HTMLElement;
|
|
38
|
-
expect(el.style.aspectRatio).toMatch(/^1\.\d+ \/ 1$/);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('string ratio "16 / 9" passes through', () => {
|
|
42
|
-
const { container } = render(<AspectRatio ratio="16 / 9">x</AspectRatio>);
|
|
43
|
-
const el = container.firstElementChild as HTMLElement;
|
|
44
|
-
expect(el.style.aspectRatio).toBe('16 / 9');
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('string ratio "21/9" passes through (ultrawide)', () => {
|
|
48
|
-
const { container } = render(<AspectRatio ratio="21/9">x</AspectRatio>);
|
|
49
|
-
const el = container.firstElementChild as HTMLElement;
|
|
50
|
-
expect(el.style.aspectRatio).toBe('21/9');
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// ─── Override ───────────────────────────────────────────────────────
|
|
55
|
-
describe('override', () => {
|
|
56
|
-
it('sx adds utility classes', () => {
|
|
57
|
-
const { container } = render(
|
|
58
|
-
<AspectRatio ratio={16 / 9} sx="rounded-xl overflow-hidden">
|
|
59
|
-
x
|
|
60
|
-
</AspectRatio>,
|
|
61
|
-
);
|
|
62
|
-
const cls = container.firstElementChild?.className ?? '';
|
|
63
|
-
expect(cls).toContain('rounded-xl');
|
|
64
|
-
expect(cls).toContain('overflow-hidden');
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('user style merges with aspect-ratio', () => {
|
|
68
|
-
const { container } = render(
|
|
69
|
-
<AspectRatio ratio={1} style={{ backgroundColor: 'red' }}>x</AspectRatio>,
|
|
70
|
-
);
|
|
71
|
-
const el = container.firstElementChild as HTMLElement;
|
|
72
|
-
expect(el.style.backgroundColor).toBe('red');
|
|
73
|
-
expect(el.style.aspectRatio).toBe('1 / 1');
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('user style aspect-ratio overrides the prop (last wins)', () => {
|
|
77
|
-
const { container } = render(
|
|
78
|
-
<AspectRatio ratio={1} style={{ aspectRatio: '2 / 1' }}>x</AspectRatio>,
|
|
79
|
-
);
|
|
80
|
-
const el = container.firstElementChild as HTMLElement;
|
|
81
|
-
// Inline style merge — user's later spread wins
|
|
82
|
-
expect(el.style.aspectRatio).toBe('2 / 1');
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// ─── Polymorphism ───────────────────────────────────────────────────
|
|
87
|
-
describe('polymorphism', () => {
|
|
88
|
-
it('as="figure" renders <figure>', () => {
|
|
89
|
-
const { container } = render(
|
|
90
|
-
<AspectRatio as="figure" ratio={1}>x</AspectRatio>,
|
|
91
|
-
);
|
|
92
|
-
expect(container.firstElementChild?.tagName).toBe('FIGURE');
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('as="picture" works for responsive image markup', () => {
|
|
96
|
-
const { container } = render(
|
|
97
|
-
<AspectRatio as="picture" ratio={16 / 9}>
|
|
98
|
-
<img src="x.jpg" alt="" />
|
|
99
|
-
</AspectRatio>,
|
|
100
|
-
);
|
|
101
|
-
expect(container.firstElementChild?.tagName).toBe('PICTURE');
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// ─── Child rendering ────────────────────────────────────────────────
|
|
106
|
-
describe('child rendering', () => {
|
|
107
|
-
it('renders an <img> child', () => {
|
|
108
|
-
const { container } = render(
|
|
109
|
-
<AspectRatio ratio={16 / 9}>
|
|
110
|
-
<img src="hero.jpg" alt="hero" className="w-full h-full object-cover" />
|
|
111
|
-
</AspectRatio>,
|
|
112
|
-
);
|
|
113
|
-
const img = container.querySelector('img');
|
|
114
|
-
expect(img?.getAttribute('src')).toBe('hero.jpg');
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('renders multiple children (e.g. overlay pattern)', () => {
|
|
118
|
-
const { container } = render(
|
|
119
|
-
<AspectRatio ratio={16 / 9}>
|
|
120
|
-
<img src="hero.jpg" alt="hero" />
|
|
121
|
-
<div className="absolute inset-0 bg-black/40" />
|
|
122
|
-
</AspectRatio>,
|
|
123
|
-
);
|
|
124
|
-
expect(container.firstElementChild?.children.length).toBe(2);
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
// ─── Pass-through ───────────────────────────────────────────────────
|
|
129
|
-
it('forwards data-* + aria-*', () => {
|
|
130
|
-
const { container } = render(
|
|
131
|
-
<AspectRatio data-testid="ar" aria-label="hero">x</AspectRatio>,
|
|
132
|
-
);
|
|
133
|
-
const el = container.firstElementChild;
|
|
134
|
-
expect(el?.getAttribute('data-testid')).toBe('ar');
|
|
135
|
-
expect(el?.getAttribute('aria-label')).toBe('hero');
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// ─── F11-bis edge cases ─────────────────────────────────────────────
|
|
139
|
-
describe('extreme ratio values', () => {
|
|
140
|
-
it('ratio="21 / 9" (ultrawide cinema) passes through verbatim', () => {
|
|
141
|
-
const { container } = render(<AspectRatio ratio="21 / 9">x</AspectRatio>);
|
|
142
|
-
expect((container.firstElementChild as HTMLElement).style.aspectRatio).toBe('21 / 9');
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('ratio="9 / 16" (portrait video) passes through verbatim', () => {
|
|
146
|
-
const { container } = render(<AspectRatio ratio="9 / 16">x</AspectRatio>);
|
|
147
|
-
expect((container.firstElementChild as HTMLElement).style.aspectRatio).toBe('9 / 16');
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('numeric tiny ratio (0.5) formats as "0.5 / 1"', () => {
|
|
151
|
-
const { container } = render(<AspectRatio ratio={0.5}>x</AspectRatio>);
|
|
152
|
-
expect((container.firstElementChild as HTMLElement).style.aspectRatio).toBe('0.5 / 1');
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('numeric large ratio (3) formats as "3 / 1"', () => {
|
|
156
|
-
const { container } = render(<AspectRatio ratio={3}>x</AspectRatio>);
|
|
157
|
-
expect((container.firstElementChild as HTMLElement).style.aspectRatio).toBe('3 / 1');
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describe('rounded clipped media pattern (the #1 doc gotcha)', () => {
|
|
162
|
-
it('rounded + overflow-hidden both end up on the className', () => {
|
|
163
|
-
const { container } = render(
|
|
164
|
-
<AspectRatio ratio={16 / 9} sx="rounded-2xl overflow-hidden">
|
|
165
|
-
<img src="x.jpg" alt="" className="w-full h-full object-cover" />
|
|
166
|
-
</AspectRatio>,
|
|
167
|
-
);
|
|
168
|
-
const cls = container.firstElementChild?.className ?? '';
|
|
169
|
-
expect(cls).toContain('rounded-2xl');
|
|
170
|
-
expect(cls).toContain('overflow-hidden');
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
});
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { forwardRef, type CSSProperties, type ElementType } from 'react';
|
|
2
|
-
import { cn } from '../../utils/cn.js';
|
|
3
|
-
import type { AspectRatioProps } from './aspectRatio.types.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* `<AspectRatio>` — locks the aspect ratio of its child container,
|
|
7
|
-
* regardless of width. The classic use is responsive images and
|
|
8
|
-
* embedded media: an `<img>` that takes 100% of the available width
|
|
9
|
-
* but always renders at 16:9 (or 1:1, or whatever the source ratio is)
|
|
10
|
-
* — no jumping layouts during image load, no whitespace below the
|
|
11
|
-
* media, no JS measurement.
|
|
12
|
-
*
|
|
13
|
-
* Implementation: native CSS `aspect-ratio` property. Supported in
|
|
14
|
-
* every browser shipped from 2021 onward (Chrome 88, Firefox 89,
|
|
15
|
-
* Safari 15, Edge 88). No padding-bottom hack — that workaround
|
|
16
|
-
* predates the native property and brings ugly absolute-positioning
|
|
17
|
-
* requirements on the child.
|
|
18
|
-
*
|
|
19
|
-
* Why a component if it's "just one CSS property"?
|
|
20
|
-
* Two reasons:
|
|
21
|
-
* 1. Discoverability — `<AspectRatio ratio={16/9}>` documents the
|
|
22
|
-
* intent at the call site. `style={{ aspectRatio: '16/9' }}` is
|
|
23
|
-
* the same thing functionally, but harder to spot in a 200-line
|
|
24
|
-
* component file.
|
|
25
|
-
* 2. Composition — pairs naturally with `sx="rounded-xl overflow-hidden"`
|
|
26
|
-
* for the canonical "rounded clipped media" pattern. Forgetting
|
|
27
|
-
* the `overflow-hidden` is the #1 mistake we want to prevent
|
|
28
|
-
* through documentation (it's in this component's MDX, at the
|
|
29
|
-
* top of the Notes).
|
|
30
|
-
*
|
|
31
|
-
* Child contract:
|
|
32
|
-
* The single child is expected to fill the container — typically
|
|
33
|
-
* `<img>` / `<video>` with `className="w-full h-full object-cover"`.
|
|
34
|
-
* We don't force this via CSS (the consumer might want a centered
|
|
35
|
-
* icon instead of a filling image) — but it's the 99% case, and the
|
|
36
|
-
* docs show it first.
|
|
37
|
-
*/
|
|
38
|
-
export const AspectRatio = forwardRef<HTMLElement, AspectRatioProps>(
|
|
39
|
-
function AspectRatio(props, ref) {
|
|
40
|
-
const {
|
|
41
|
-
ratio = 1,
|
|
42
|
-
as,
|
|
43
|
-
sx,
|
|
44
|
-
style,
|
|
45
|
-
children,
|
|
46
|
-
...rest
|
|
47
|
-
} = props;
|
|
48
|
-
|
|
49
|
-
/*
|
|
50
|
-
* Normalise to a CSS `aspect-ratio` string. The CSS property
|
|
51
|
-
* accepts both `16/9` and `16 / 9` (with spaces), but for safety
|
|
52
|
-
* we convert numbers to the canonical `N / 1` form — `aspectRatio: 1.7777`
|
|
53
|
-
* works too, but produces an arbitrary-looking value in DevTools.
|
|
54
|
-
*/
|
|
55
|
-
const aspectRatioValue = typeof ratio === 'number' ? `${ratio} / 1` : ratio;
|
|
56
|
-
|
|
57
|
-
const mergedStyle: CSSProperties = {
|
|
58
|
-
aspectRatio: aspectRatioValue,
|
|
59
|
-
...style,
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const classes = cn('w-full', sx);
|
|
63
|
-
const Tag = (as ?? 'div') as ElementType;
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<Tag ref={ref as never} className={classes} style={mergedStyle} {...rest}>
|
|
67
|
-
{children}
|
|
68
|
-
</Tag>
|
|
69
|
-
);
|
|
70
|
-
},
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
AspectRatio.displayName = 'AspectRatio';
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { ElementType, HTMLAttributes, ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Props for `<AspectRatio>` — content-shape primitive that locks the
|
|
5
|
-
* aspect ratio of its child regardless of width.
|
|
6
|
-
*
|
|
7
|
-
* Implementation: uses the native CSS `aspect-ratio` property
|
|
8
|
-
* (supported in all current browsers since 2021 — Chrome 88+, Firefox 89+,
|
|
9
|
-
* Safari 15+, Edge 88+). No padding-bottom hack, no JS measurement.
|
|
10
|
-
*
|
|
11
|
-
* `ratio` accepts:
|
|
12
|
-
* • A number — width / height. `16/9` is 1.7777…, `1` is square,
|
|
13
|
-
* `4/3` is 1.333…, `21/9` is ultrawide cinema.
|
|
14
|
-
* • A string with the CSS `aspect-ratio` syntax, e.g. `'16 / 9'`,
|
|
15
|
-
* `'4 / 3'`. Useful when you want the source ratio to read clearly
|
|
16
|
-
* in the JSX (`ratio="16 / 9"` is more legible than `ratio={16/9}`).
|
|
17
|
-
*
|
|
18
|
-
* The component renders a single element with `aspect-ratio: X` and
|
|
19
|
-
* `width: 100%`. The child is expected to fill it — typically an
|
|
20
|
-
* `<img>` or `<video>` with `className="w-full h-full object-cover"`.
|
|
21
|
-
*
|
|
22
|
-
* Why not a TV recipe?
|
|
23
|
-
* The ratio is arbitrary (`16/9`, `1`, `2.35`, anything). Tailwind
|
|
24
|
-
* has `aspect-square` / `aspect-video` / `aspect-[16/9]` arbitrary
|
|
25
|
-
* values, but enumerating every conceivable ratio in TV would be
|
|
26
|
-
* pointless. We set `style={{ aspectRatio }}` directly — pure CSS
|
|
27
|
-
* property, no class purge concerns.
|
|
28
|
-
*/
|
|
29
|
-
export interface AspectRatioProps
|
|
30
|
-
extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {
|
|
31
|
-
/**
|
|
32
|
-
* Aspect ratio as width/height. Number (`16/9`) or CSS string
|
|
33
|
-
* (`'16 / 9'`). Default `1` (square).
|
|
34
|
-
*/
|
|
35
|
-
ratio?: number | string;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The child that fills the locked-ratio container. Typically an
|
|
39
|
-
* `<img>` or `<video>` with `className="w-full h-full object-cover"`.
|
|
40
|
-
*/
|
|
41
|
-
children?: ReactNode;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Override the rendered HTML tag. Defaults to `'div'`.
|
|
45
|
-
*/
|
|
46
|
-
as?: ElementType;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Utility classes appended to the base. Resolved via `tailwind-merge`.
|
|
50
|
-
* Common overrides: `sx="rounded-xl overflow-hidden"` to clip the
|
|
51
|
-
* child's overflow (image bleeds otherwise).
|
|
52
|
-
*/
|
|
53
|
-
sx?: string;
|
|
54
|
-
}
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
/**
|
|
3
|
-
* Performance + re-render budget tests for `<Autocomplete>`.
|
|
4
|
-
*
|
|
5
|
-
* These are NOT "is X fast" benchmarks — they're guardrails against
|
|
6
|
-
* regressions in the things that matter for a 1000+ option combobox:
|
|
7
|
-
*
|
|
8
|
-
* 1. **Filter memoization**: `filteredOptions` must be reference-stable
|
|
9
|
-
* when its inputs (options + filter text + selection state) don't
|
|
10
|
-
* change. A stable reference means downstream lists don't re-mount.
|
|
11
|
-
*
|
|
12
|
-
* 2. **Render budget**: typing N characters must cause O(N) renders
|
|
13
|
-
* of the component, not O(N²) or worse. With our internals there
|
|
14
|
-
* are 2 renders per keystroke (one for `inputValue`, one for the
|
|
15
|
-
* popover opening on first keystroke), so the budget is `2N + k`
|
|
16
|
-
* for a small constant `k`.
|
|
17
|
-
*
|
|
18
|
-
* 3. **Initial render time** with a large option list must finish
|
|
19
|
-
* within a generous wall-clock budget. This catches a future
|
|
20
|
-
* refactor that, say, accidentally calls `getOptionLabel` 1000²
|
|
21
|
-
* times during mount.
|
|
22
|
-
*/
|
|
23
|
-
import { describe, it, expect } from 'vitest';
|
|
24
|
-
import { useEffect, useRef } from 'react';
|
|
25
|
-
import { render, fireEvent, screen } from '@testing-library/react';
|
|
26
|
-
import { Autocomplete } from './Autocomplete.js';
|
|
27
|
-
import type { AutocompleteOption } from './autocomplete.types.js';
|
|
28
|
-
|
|
29
|
-
// Generate `n` deterministic options.
|
|
30
|
-
function makeOptions(n: number): AutocompleteOption[] {
|
|
31
|
-
return Array.from({ length: n }, (_, i) => ({
|
|
32
|
-
value: `o-${i}`,
|
|
33
|
-
label: `Option ${i}`,
|
|
34
|
-
}));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Wrap a component and expose a render-counter ref so tests can assert
|
|
39
|
-
* how many times React re-rendered the wrapped subtree.
|
|
40
|
-
*/
|
|
41
|
-
function withRenderCounter<P>(
|
|
42
|
-
Component: React.ComponentType<P>,
|
|
43
|
-
counterRef: { count: number }
|
|
44
|
-
): React.FC<P> {
|
|
45
|
-
return function Counted(props: P) {
|
|
46
|
-
counterRef.count++;
|
|
47
|
-
return <Component {...(props as P & object)} />;
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
describe('<Autocomplete> performance', () => {
|
|
52
|
-
it('mounts a 1000-option list well under 500ms', () => {
|
|
53
|
-
const options = makeOptions(1000);
|
|
54
|
-
const t0 = performance.now();
|
|
55
|
-
render(<Autocomplete name="x" options={options} label="X" />);
|
|
56
|
-
const t1 = performance.now();
|
|
57
|
-
expect(t1 - t0).toBeLessThan(500);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('filters a 1000-option list well under 100ms per keystroke', () => {
|
|
61
|
-
const options = makeOptions(1000);
|
|
62
|
-
render(<Autocomplete name="x" options={options} label="X" />);
|
|
63
|
-
const input = screen.getByRole('combobox') as HTMLInputElement;
|
|
64
|
-
const t0 = performance.now();
|
|
65
|
-
fireEvent.change(input, { target: { value: '9' } });
|
|
66
|
-
const t1 = performance.now();
|
|
67
|
-
expect(t1 - t0).toBeLessThan(100);
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
describe('<Autocomplete> re-render budget', () => {
|
|
72
|
-
it('renders at most 2 times on mount (StrictMode-free path)', () => {
|
|
73
|
-
const counter = { count: 0 };
|
|
74
|
-
const Counted = withRenderCounter(Autocomplete, counter);
|
|
75
|
-
render(<Counted name="x" options={makeOptions(20)} label="X" />);
|
|
76
|
-
// 1 initial render — and we tolerate up to 2 to account for the
|
|
77
|
-
// synchronous useState callbacks that schedule a follow-up commit.
|
|
78
|
-
expect(counter.count).toBeLessThanOrEqual(2);
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('keeps renders linear in keystrokes (≤ 3 renders per char)', () => {
|
|
82
|
-
const counter = { count: 0 };
|
|
83
|
-
const Counted = withRenderCounter(Autocomplete, counter);
|
|
84
|
-
const { container } = render(
|
|
85
|
-
<Counted name="x" options={makeOptions(50)} label="X" />
|
|
86
|
-
);
|
|
87
|
-
const baseline = counter.count;
|
|
88
|
-
const input = container.querySelector(
|
|
89
|
-
'input[role="combobox"]'
|
|
90
|
-
) as HTMLInputElement;
|
|
91
|
-
const N = 10;
|
|
92
|
-
for (let i = 0; i < N; i++) {
|
|
93
|
-
fireEvent.change(input, { target: { value: 'a'.repeat(i + 1) } });
|
|
94
|
-
}
|
|
95
|
-
const perChar = (counter.count - baseline) / N;
|
|
96
|
-
// 1-2 renders per keystroke is the design budget; allow some slack
|
|
97
|
-
// for popover-open transitions on the first keystroke and the
|
|
98
|
-
// highlight reset useState call.
|
|
99
|
-
expect(perChar).toBeLessThanOrEqual(3);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('does NOT re-render an unrelated sibling on each keystroke', () => {
|
|
103
|
-
// Critical perf property: typing into one Autocomplete must not
|
|
104
|
-
// cause sibling components in the same tree to re-render. We check
|
|
105
|
-
// this by mounting a sibling whose render count we count directly.
|
|
106
|
-
const sibCount = { count: 0 };
|
|
107
|
-
const Sibling = () => {
|
|
108
|
-
sibCount.count++;
|
|
109
|
-
return <div data-testid="sib" />;
|
|
110
|
-
};
|
|
111
|
-
render(
|
|
112
|
-
<div>
|
|
113
|
-
<Autocomplete name="x" options={makeOptions(50)} label="X" />
|
|
114
|
-
<Sibling />
|
|
115
|
-
</div>
|
|
116
|
-
);
|
|
117
|
-
const before = sibCount.count;
|
|
118
|
-
const input = screen.getByRole('combobox') as HTMLInputElement;
|
|
119
|
-
for (let i = 0; i < 5; i++) {
|
|
120
|
-
fireEvent.change(input, { target: { value: 'a'.repeat(i + 1) } });
|
|
121
|
-
}
|
|
122
|
-
// No state in the parent changes ⇒ sibling never re-renders.
|
|
123
|
-
expect(sibCount.count).toBe(before);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('filteredOptions reference is stable across unrelated re-renders', () => {
|
|
127
|
-
// Functional contract: if the deps (options, filter text, selection)
|
|
128
|
-
// don't change, `useMemo` should return the same array reference.
|
|
129
|
-
// We verify by triggering a parent re-render with no relevant input
|
|
130
|
-
// change and asserting the `<li>` DOM elements are reused (same id
|
|
131
|
-
// identities ⇒ React reused the keys).
|
|
132
|
-
const options = makeOptions(20);
|
|
133
|
-
const seenIds = new Set<string>();
|
|
134
|
-
const { rerender } = render(
|
|
135
|
-
<Autocomplete name="x" options={options} label="X" />
|
|
136
|
-
);
|
|
137
|
-
const input = screen.getByRole('combobox') as HTMLInputElement;
|
|
138
|
-
fireEvent.focus(input); // open popover so the list renders
|
|
139
|
-
const lis1 = Array.from(
|
|
140
|
-
document.querySelectorAll('[role="option"]')
|
|
141
|
-
).map((el) => el.id);
|
|
142
|
-
lis1.forEach((id) => seenIds.add(id));
|
|
143
|
-
|
|
144
|
-
// Trigger an unrelated re-render: same options ref, same input
|
|
145
|
-
// value, same selection.
|
|
146
|
-
rerender(<Autocomplete name="x" options={options} label="X" />);
|
|
147
|
-
const lis2 = Array.from(
|
|
148
|
-
document.querySelectorAll('[role="option"]')
|
|
149
|
-
).map((el) => el.id);
|
|
150
|
-
|
|
151
|
-
// Same ids ⇒ React keyed reuse held; list DOM was not torn down.
|
|
152
|
-
expect(lis2).toEqual(lis1);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('captures number of options accessor calls during one filter cycle', () => {
|
|
156
|
-
// Implementation detail with strong perf relevance: filtering 1000
|
|
157
|
-
// options must call `getOptionLabel` at most O(N) times per filter
|
|
158
|
-
// (NOT O(N²) or anything weirdly memoized that re-computes per
|
|
159
|
-
// child).
|
|
160
|
-
let labelCalls = 0;
|
|
161
|
-
let valueCalls = 0;
|
|
162
|
-
const N = 200;
|
|
163
|
-
const options: AutocompleteOption[] = makeOptions(N);
|
|
164
|
-
render(
|
|
165
|
-
<Autocomplete
|
|
166
|
-
name="x"
|
|
167
|
-
options={options}
|
|
168
|
-
label="X"
|
|
169
|
-
getOptionLabel={(o) => {
|
|
170
|
-
labelCalls++;
|
|
171
|
-
return o.label;
|
|
172
|
-
}}
|
|
173
|
-
getOptionValue={(o) => {
|
|
174
|
-
valueCalls++;
|
|
175
|
-
return o.value;
|
|
176
|
-
}}
|
|
177
|
-
/>
|
|
178
|
-
);
|
|
179
|
-
const input = screen.getByRole('combobox') as HTMLInputElement;
|
|
180
|
-
labelCalls = 0;
|
|
181
|
-
valueCalls = 0;
|
|
182
|
-
fireEvent.change(input, { target: { value: '5' } });
|
|
183
|
-
// Budget: O(N) on both. Allow 4x N to cover the filter pass plus
|
|
184
|
-
// the popover-open render's per-option `getOptionValue` for ids
|
|
185
|
-
// and `getOptionLabel` for the rendered <li> body.
|
|
186
|
-
expect(labelCalls).toBeLessThanOrEqual(4 * N);
|
|
187
|
-
expect(valueCalls).toBeLessThanOrEqual(4 * N);
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
describe('<Autocomplete> async + perf interaction', () => {
|
|
192
|
-
it('debounces loadOptions so 5 rapid keystrokes ⇒ 1 fetch', async () => {
|
|
193
|
-
const calls: string[] = [];
|
|
194
|
-
const load = (q: string) => {
|
|
195
|
-
calls.push(q);
|
|
196
|
-
return Promise.resolve<AutocompleteOption[]>([]);
|
|
197
|
-
};
|
|
198
|
-
render(
|
|
199
|
-
<Autocomplete
|
|
200
|
-
name="x"
|
|
201
|
-
options={[]}
|
|
202
|
-
loadOptions={load}
|
|
203
|
-
loadDebounceMs={50}
|
|
204
|
-
/>
|
|
205
|
-
);
|
|
206
|
-
const input = screen.getByRole('combobox') as HTMLInputElement;
|
|
207
|
-
// Type 5 chars in quick succession (synchronous).
|
|
208
|
-
for (let i = 0; i < 5; i++) {
|
|
209
|
-
fireEvent.change(input, { target: { value: 'abcde'.slice(0, i + 1) } });
|
|
210
|
-
}
|
|
211
|
-
// Before debounce expires, no call yet.
|
|
212
|
-
expect(calls.length).toBe(0);
|
|
213
|
-
// Wait past debounce window.
|
|
214
|
-
await new Promise((r) => setTimeout(r, 80));
|
|
215
|
-
// Exactly ONE call lands, with the LAST typed value.
|
|
216
|
-
expect(calls).toEqual(['abcde']);
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Module-level useEffect import sanity (suppresses "useRef declared but
|
|
222
|
-
* not used" if a test runner tree-shake removes some perf tests in CI).
|
|
223
|
-
*/
|
|
224
|
-
void useRef;
|
|
225
|
-
void useEffect;
|