@astryxdesign/core 0.7.6-canary.f73623d → 0.7.6-canary.f77aaf2
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/dist/AppShell/AppShell.d.ts.map +1 -1
- package/dist/AppShell/AppShell.js +0 -6
- package/dist/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +2 -1
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +6 -2
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +36 -9
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts +1 -1
- package/dist/BottomSheet/BottomSheetSwitcher.js +1 -1
- package/dist/BottomSheet/useMobileKeyboard.d.ts.map +1 -1
- package/dist/BottomSheet/useMobileKeyboard.js +44 -8
- package/dist/BottomSheet/useSheetGestures.d.ts +36 -6
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +67 -10
- package/dist/Breadcrumbs/BreadcrumbItem.js +4 -2
- package/dist/Center/Center.d.ts +1 -1
- package/dist/Center/Center.js +1 -1
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +10 -5
- package/dist/Chat/ChatComposerDrawer.d.ts +1 -1
- package/dist/Chat/ChatComposerDrawer.js +1 -1
- package/dist/Chat/ChatComposerInput.d.ts +1 -1
- package/dist/Chat/ChatComposerInput.js +1 -1
- package/dist/Chat/ChatLayout.d.ts.map +1 -1
- package/dist/Chat/ChatLayout.js +1 -1
- package/dist/Chat/ChatMessageList.d.ts.map +1 -1
- package/dist/Chat/ChatMessageList.js +3 -1
- package/dist/Chat/ChatPastedTextToken.d.ts.map +1 -1
- package/dist/Chat/ChatPastedTextToken.js +15 -4
- package/dist/Chat/ChatSystemMessage.d.ts.map +1 -1
- package/dist/Chat/ChatSystemMessage.js +2 -1
- package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +5 -2
- package/dist/CheckboxList/CheckboxListContext.d.ts +8 -0
- package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +5 -2
- package/dist/Code/Code.d.ts +1 -1
- package/dist/Code/Code.js +1 -1
- package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteInput.js +8 -5
- package/dist/ComplexSelector/ComplexSelector.d.ts +2 -2
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +7 -2
- package/dist/DateInput/DateInput.d.ts +3 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +17 -18
- package/dist/DateRangeInput/DateRangeInput.d.ts +3 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +8 -4
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +10 -15
- package/dist/Drawer/Drawer.d.ts +1 -1
- package/dist/Drawer/Drawer.js +1 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +19 -8
- package/dist/DropdownMenu/DropdownMenuGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuGroup.js +2 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +1 -1
- package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -1
- package/dist/DropdownMenu/MenuBottomSheetActionList.js +9 -3
- package/dist/Field/Field.d.ts +2 -2
- package/dist/Field/Field.d.ts.map +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +19 -2
- package/dist/Field/PanelSearchInput.d.ts.map +1 -1
- package/dist/Field/PanelSearchInput.js +10 -5
- package/dist/Field/fieldStatusPlacement.d.ts +15 -0
- package/dist/Field/fieldStatusPlacement.d.ts.map +1 -0
- package/dist/Field/fieldStatusPlacement.js +1 -0
- package/dist/FieldStatus/FieldStatus.d.ts +16 -28
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +25 -3
- package/dist/FieldStatus/index.d.ts +7 -0
- package/dist/FieldStatus/index.d.ts.map +1 -1
- package/dist/FileInput/FileInput.d.ts +10 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +86 -35
- package/dist/Item/Item.js +5 -5
- package/dist/Item/ItemSwipeLayer.d.ts.map +1 -1
- package/dist/Item/ItemSwipeLayer.js +8 -2
- package/dist/Layer/useTouchTrigger.d.ts +35 -3
- package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
- package/dist/Layer/useTouchTrigger.js +80 -11
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +10 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +1 -0
- package/dist/MetadataList/MetadataList.d.ts.map +1 -1
- package/dist/MetadataList/MetadataList.js +2 -1
- package/dist/MetadataList/MetadataListItem.d.ts.map +1 -1
- package/dist/MetadataList/MetadataListItem.js +2 -1
- package/dist/MultiSelector/MultiSelector.d.ts +2 -2
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +35 -25
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +4 -2
- package/dist/NumberInput/NumberInput.d.ts +3 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +11 -15
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +2 -1
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Popover/Popover.js +2 -2
- package/dist/Popover/usePopover.d.ts +7 -1
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +8 -2
- package/dist/PowerSearch/PowerSearch.d.ts +3 -2
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +4 -2
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +7 -2
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +8 -2
- package/dist/RadioList/RadioListReasonContext.d.ts +2 -0
- package/dist/RadioList/RadioListReasonContext.d.ts.map +1 -0
- package/dist/RadioList/RadioListReasonContext.js +22 -0
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +53 -10
- package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControl.js +22 -5
- package/dist/SegmentedControl/SegmentedControlContext.d.ts +6 -0
- package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +16 -3
- package/dist/Selector/Selector.d.ts +3 -3
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +14 -8
- package/dist/Selector/hooks.js +2 -2
- package/dist/Selector/useSelectorPresentation.d.ts +7 -1
- package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
- package/dist/Selector/useSelectorPresentation.js +2 -1
- package/dist/SideNav/railMotion.d.ts +5 -5
- package/dist/SideNav/railMotion.d.ts.map +1 -1
- package/dist/SideNav/railMotion.js +69 -177
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +100 -17
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +7 -6
- package/dist/Table/glidingDivider.d.ts +8 -1
- package/dist/Table/glidingDivider.d.ts.map +1 -1
- package/dist/Table/glidingDivider.js +8 -3
- package/dist/Table/plugins/sortable/useTableSortable.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +1 -2
- package/dist/TextArea/TextArea.d.ts +2 -2
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextInput/TextInput.d.ts +3 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.d.ts +3 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/Timer/Timer.js +1 -1
- package/dist/Toast/useToast.d.ts.map +1 -1
- package/dist/Toast/useToast.js +8 -2
- package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButton.js +11 -3
- package/dist/Token/Token.d.ts +1 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +15 -0
- package/dist/Tokenizer/Tokenizer.d.ts +3 -2
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +73 -50
- package/dist/Tokenizer/TokenizerBottomSheet.d.ts +1 -1
- package/dist/Tokenizer/TokenizerBottomSheet.d.ts.map +1 -1
- package/dist/Tokenizer/TokenizerBottomSheet.js +9 -15
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +4 -3
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +6 -3
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +4 -3
- package/dist/Typeahead/BaseTypeahead.d.ts +4 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +262 -43
- package/dist/Typeahead/Typeahead.d.ts +3 -2
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +36 -10
- package/dist/Typeahead/index.d.ts +1 -1
- package/dist/Typeahead/index.d.ts.map +1 -1
- package/dist/Typeahead/types.d.ts +26 -3
- package/dist/Typeahead/types.d.ts.map +1 -1
- package/dist/astryx.css +1 -2
- package/dist/gestures/haptics.d.ts.map +1 -1
- package/dist/gestures/haptics.js +1 -5
- package/dist/hooks/menuPressMarker.d.ts +13 -0
- package/dist/hooks/menuPressMarker.d.ts.map +1 -0
- package/dist/hooks/menuPressMarker.js +15 -0
- package/dist/hooks/useClickableContainer.d.ts +24 -4
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +41 -14
- package/dist/hooks/useFocusReturnVisibility.d.ts +8 -1
- package/dist/hooks/useFocusReturnVisibility.d.ts.map +1 -1
- package/dist/hooks/useFocusReturnVisibility.js +14 -8
- package/dist/hooks/useInputStatusIcon.d.ts +2 -2
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
- package/dist/hooks/useInputStatusIcon.js +1 -2
- package/dist/hooks/useListFocus.d.ts +19 -0
- package/dist/hooks/useListFocus.d.ts.map +1 -1
- package/dist/hooks/useListFocus.js +26 -1
- package/dist/hooks/useMenuPress.d.ts +2 -2
- package/dist/hooks/useMenuPress.d.ts.map +1 -1
- package/dist/hooks/useMenuPress.js +5 -6
- package/dist/hooks/useTreeFocus.d.ts.map +1 -1
- package/dist/hooks/useTreeFocus.js +13 -5
- package/dist/hooks/useTypeahead.d.ts +3 -1
- package/dist/hooks/useTypeahead.d.ts.map +1 -1
- package/dist/hooks/useTypeahead.js +21 -15
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +6 -0
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +6 -0
- package/dist/i18n/useListFormatter.d.ts +9 -0
- package/dist/i18n/useListFormatter.d.ts.map +1 -0
- package/dist/i18n/useListFormatter.js +41 -0
- package/dist/motion/animatedLayout.d.ts +130 -5
- package/dist/motion/animatedLayout.d.ts.map +1 -1
- package/dist/motion/animatedLayout.js +771 -44
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +38 -2
- package/dist/privateAttributes/segmentDisabled.stylex.d.ts +5 -0
- package/dist/privateAttributes/segmentDisabled.stylex.d.ts.map +1 -0
- package/dist/privateAttributes/segmentDisabled.stylex.js +28 -0
- package/dist/theme/Theme.d.ts +10 -0
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +8 -4
- package/dist/theme/useTheme.d.ts.map +1 -1
- package/dist/theme/useTheme.js +7 -1
- package/dist/utils/focusReturn.d.ts +5 -3
- package/dist/utils/focusReturn.d.ts.map +1 -1
- package/dist/utils/focusReturn.js +6 -4
- package/dist/utils/getNodeText.d.ts.map +1 -1
- package/dist/utils/getNodeText.js +2 -1
- package/dist/utils/interactionModality.d.ts +78 -7
- package/dist/utils/interactionModality.d.ts.map +1 -1
- package/dist/utils/interactionModality.js +125 -42
- package/dist/utils/pressDisabled.d.ts +21 -0
- package/dist/utils/pressDisabled.d.ts.map +1 -0
- package/dist/utils/pressDisabled.js +32 -0
- package/dist/utils/pressFeedback.d.ts.map +1 -1
- package/dist/utils/pressFeedback.js +5 -3
- package/dist/utils/typeaheadMatch.d.ts +24 -0
- package/dist/utils/typeaheadMatch.d.ts.map +1 -0
- package/dist/utils/typeaheadMatch.js +112 -0
- package/locales/en.json +25 -1
- package/locales/pseudo.json +18 -0
- package/package.json +19 -5
- package/src/AppShell/AppShell.tsx +0 -9
- package/src/Badge/Badge.tsx +2 -1
- package/src/BottomSheet/BottomSheet.tsx +4 -2
- package/src/BottomSheet/BottomSheetPanel.tsx +39 -8
- package/src/BottomSheet/BottomSheetSwitcher.tsx +1 -1
- package/src/BottomSheet/useMobileKeyboard.ts +51 -10
- package/src/BottomSheet/useSheetGestures.ts +92 -15
- package/src/Breadcrumbs/BreadcrumbItem.tsx +2 -1
- package/src/Center/Center.tsx +1 -1
- package/src/Chat/ChatComposer.tsx +7 -10
- package/src/Chat/ChatComposerDrawer.tsx +1 -1
- package/src/Chat/ChatComposerInput.tsx +1 -1
- package/src/Chat/ChatLayout.tsx +1 -6
- package/src/Chat/ChatMessageList.tsx +1 -0
- package/src/Chat/ChatPastedTextToken.tsx +14 -4
- package/src/Chat/ChatSystemMessage.tsx +4 -1
- package/src/Chat/ChatToolCalls.tsx +5 -0
- package/src/CheckboxList/CheckboxList.tsx +7 -1
- package/src/CheckboxList/CheckboxListContext.tsx +8 -0
- package/src/CheckboxList/CheckboxListItem.tsx +8 -2
- package/src/Code/Code.tsx +1 -1
- package/src/CommandPalette/CommandPaletteInput.tsx +5 -8
- package/src/ComplexSelector/ComplexSelector.tsx +22 -4
- package/src/DateInput/DateInput.tsx +2 -2
- package/src/DateInput/MonthScroller.tsx +15 -17
- package/src/DateRangeInput/DateRangeInput.tsx +20 -5
- package/src/Dialog/Dialog.tsx +9 -25
- package/src/Drawer/Drawer.tsx +1 -1
- package/src/DropdownMenu/DropdownMenu.tsx +24 -9
- package/src/DropdownMenu/DropdownMenuGroup.tsx +2 -1
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +3 -1
- package/src/DropdownMenu/MenuBottomSheetActionList.tsx +6 -3
- package/src/Field/Field.doc.mjs +2 -1
- package/src/Field/Field.tsx +2 -2
- package/src/Field/FieldLabel.doc.mjs +4 -2
- package/src/Field/FieldLabel.tsx +18 -2
- package/src/Field/PanelSearchInput.tsx +7 -8
- package/src/Field/fieldStatusPlacement.ts +18 -0
- package/src/FieldStatus/FieldStatus.tsx +33 -3
- package/src/FieldStatus/index.ts +7 -0
- package/src/FileInput/FileInput.doc.mjs +3 -3
- package/src/FileInput/FileInput.tsx +103 -36
- package/src/HoverCard/HoverCard.doc.mjs +3 -3
- package/src/HoverCard/useHoverCard.doc.mjs +1 -1
- package/src/Item/Item.tsx +5 -5
- package/src/Item/ItemSwipeLayer.tsx +8 -1
- package/src/Layer/useTouchTrigger.ts +107 -18
- package/src/Link/Link.tsx +9 -2
- package/src/Markdown/Markdown.tsx +1 -0
- package/src/MetadataList/MetadataList.tsx +4 -2
- package/src/MetadataList/MetadataListItem.tsx +2 -1
- package/src/MultiSelector/MultiSelector.tsx +57 -36
- package/src/MultiSelector/hooks.ts +7 -5
- package/src/NumberInput/NumberInput.tsx +13 -20
- package/src/OverflowList/OverflowList.tsx +2 -1
- package/src/Pagination/Pagination.tsx +1 -0
- package/src/Popover/Popover.tsx +2 -2
- package/src/Popover/usePopover.tsx +7 -2
- package/src/PowerSearch/PowerSearch.tsx +4 -2
- package/src/RadioList/RadioList.tsx +13 -2
- package/src/RadioList/RadioListItem.tsx +9 -1
- package/src/RadioList/RadioListReasonContext.ts +25 -0
- package/src/Resizable/useResizable.ts +50 -7
- package/src/SegmentedControl/SegmentedControl.tsx +43 -8
- package/src/SegmentedControl/SegmentedControlContext.ts +6 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +12 -1
- package/src/Selector/Selector.tsx +23 -9
- package/src/Selector/hooks.ts +2 -2
- package/src/Selector/useSelectorPresentation.ts +8 -1
- package/src/SideNav/railMotion.ts +73 -179
- package/src/Slider/Slider.tsx +116 -19
- package/src/Table/BaseTable.tsx +10 -6
- package/src/Table/glidingDivider.ts +8 -3
- package/src/Table/plugins/sortable/useTableSortable.tsx +2 -0
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
- package/src/TextArea/TextArea.tsx +3 -2
- package/src/TextInput/TextInput.tsx +2 -2
- package/src/TimeInput/TimeInput.tsx +2 -2
- package/src/Timer/Timer.tsx +1 -1
- package/src/Toast/useToast.tsx +8 -3
- package/src/ToggleButton/ToggleButton.tsx +10 -3
- package/src/Token/Token.tsx +15 -0
- package/src/Tokenizer/Tokenizer.doc.mjs +12 -8
- package/src/Tokenizer/Tokenizer.tsx +81 -53
- package/src/Tokenizer/TokenizerBottomSheet.tsx +9 -15
- package/src/Tooltip/Tooltip.doc.mjs +3 -3
- package/src/Tooltip/useTooltip.doc.mjs +1 -1
- package/src/TopNav/TopNavMegaMenu.tsx +4 -3
- package/src/TreeList/TreeList.tsx +6 -3
- package/src/TreeList/TreeListItem.tsx +5 -3
- package/src/Typeahead/BaseTypeahead.doc.mjs +7 -4
- package/src/Typeahead/BaseTypeahead.tsx +314 -40
- package/src/Typeahead/Typeahead.doc.mjs +21 -4
- package/src/Typeahead/Typeahead.tsx +42 -11
- package/src/Typeahead/TypeaheadItem.doc.mjs +6 -3
- package/src/Typeahead/index.ts +1 -1
- package/src/Typeahead/types.ts +27 -3
- package/src/gestures/haptics.ts +1 -8
- package/src/hooks/menuPressMarker.ts +15 -0
- package/src/hooks/useClickableContainer.ts +48 -17
- package/src/hooks/useFocusReturnVisibility.ts +15 -12
- package/src/hooks/useInputStatusIcon.tsx +2 -2
- package/src/hooks/useListFocus.ts +38 -1
- package/src/hooks/useMenuPress.ts +5 -5
- package/src/hooks/useTreeFocus.doc.mjs +2 -2
- package/src/hooks/useTreeFocus.ts +16 -10
- package/src/hooks/useTypeahead.doc.mjs +2 -2
- package/src/hooks/useTypeahead.ts +21 -20
- package/src/i18n/generated-locales/en.generated.ts +8 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +8 -0
- package/src/i18n/useListFormatter.ts +42 -0
- package/src/motion/animatedLayout.ts +977 -45
- package/src/motion/animator.ts +55 -2
- package/src/privateAttributes/segmentDisabled.stylex.ts +28 -0
- package/src/theme/Theme.tsx +8 -4
- package/src/theme/useTheme.ts +6 -1
- package/src/utils/focusReturn.ts +6 -4
- package/src/utils/getNodeText.ts +2 -1
- package/src/utils/interactionModality.ts +165 -44
- package/src/utils/pressDisabled.ts +32 -0
- package/src/utils/pressFeedback.ts +5 -3
- package/src/utils/typeaheadMatch.ts +141 -0
- package/dist/Item/ItemMarkerColumns.a11y.chromium.spec.d.ts +0 -2
- package/dist/Item/ItemMarkerColumns.a11y.chromium.spec.js +0 -132
- package/dist/Lightbox/LightboxKeyboard.a11y.browser.spec.d.ts +0 -2
- package/dist/Lightbox/LightboxKeyboard.a11y.browser.spec.js +0 -78
- package/dist/Lightbox/LightboxViewport.a11y.browser.spec.d.ts +0 -2
- package/dist/Lightbox/LightboxViewport.a11y.browser.spec.js +0 -66
- package/dist/List/ListMarkers.a11y.chromium.spec.d.ts +0 -2
- package/dist/List/ListMarkers.a11y.chromium.spec.js +0 -677
- package/dist/Markdown/Markdown.fr23.bench.d.ts +0 -2
- package/dist/Markdown/Markdown.fr23.bench.d.ts.map +0 -1
- package/dist/Markdown/Markdown.fr23.bench.js +0 -152
- package/dist/Markdown/MarkdownTable.a11y.chromium.spec.d.ts +0 -2
- package/dist/Markdown/MarkdownTable.a11y.chromium.spec.js +0 -590
- package/dist/Markdown/plugins/headingLinks.a11y.chromium.spec.d.ts +0 -2
- package/dist/Markdown/plugins/headingLinks.a11y.chromium.spec.js +0 -657
- package/dist/MobileNav/MobileNavPinchZoom.a11y.chromium.spec.d.ts +0 -2
- package/dist/MobileNav/MobileNavPinchZoom.a11y.chromium.spec.js +0 -153
- package/dist/MultiSelector/CreateRow.a11y.chromium.spec.d.ts +0 -2
- package/dist/MultiSelector/CreateRow.a11y.chromium.spec.js +0 -117
- package/dist/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.d.ts +0 -2
- package/dist/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.js +0 -49
- package/dist/MultiSelector/OptionActions.a11y.chromium.spec.d.ts +0 -2
- package/dist/MultiSelector/OptionActions.a11y.chromium.spec.js +0 -273
- package/dist/Outline/OutlineFocus.a11y.chromium.spec.d.ts +0 -2
- package/dist/Outline/OutlineFocus.a11y.chromium.spec.js +0 -421
- package/dist/Typeahead/BaseTypeahead.emptyState.a11y.chromium.spec.d.ts +0 -2
- package/dist/Typeahead/BaseTypeahead.emptyState.a11y.chromium.spec.js +0 -118
- package/dist/reset.a11y.chromium.spec.d.ts +0 -2
- package/dist/reset.a11y.chromium.spec.js +0 -231
- package/dist/reset.until-found.a11y.browser.spec.d.ts +0 -2
- package/dist/reset.until-found.a11y.browser.spec.js +0 -72
- package/src/AlertDialog/AlertDialog.spec.md +0 -259
- package/src/AlertDialog/AlertDialog.test.tsx +0 -519
- package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +0 -128
- package/src/AlertDialog/__tests__/AlertDialog.a11y.renders.tsx +0 -52
- package/src/AlertDialog/__tests__/AlertDialog.a11y.states.ts +0 -68
- package/src/AlertDialog/__tests__/AlertDialog.a11y.test.tsx +0 -144
- package/src/AlertDialog/useImperativeAlertDialog.test.tsx +0 -163
- package/src/AppShell/AppShell.spec.md +0 -331
- package/src/AppShell/AppShell.test.tsx +0 -1310
- package/src/AppShell/__tests__/AppShellMainKeyboard.a11y.browser.spec.ts +0 -534
- package/src/AppShell/observeMainOverflow.test.ts +0 -173
- package/src/AspectRatio/AspectRatio.spec.md +0 -179
- package/src/AspectRatio/AspectRatio.test.tsx +0 -398
- package/src/AspectRatio/__tests__/AspectRatioFitLayers.a11y.browser.spec.ts +0 -158
- package/src/Avatar/Avatar.spec.md +0 -253
- package/src/Avatar/Avatar.test.tsx +0 -867
- package/src/Avatar/AvatarStatusDot.spec.md +0 -208
- package/src/Avatar/AvatarStatusDot.test.tsx +0 -306
- package/src/Avatar/__tests__/AvatarForcedColors.a11y.chromium.spec.ts +0 -126
- package/src/AvatarGroup/AvatarGroup.spec.md +0 -205
- package/src/AvatarGroup/AvatarGroup.test.tsx +0 -313
- package/src/AvatarGroup/AvatarGroupOverflow.spec.md +0 -210
- package/src/AvatarGroup/AvatarGroupOverflow.test.tsx +0 -263
- package/src/Badge/Badge.spec.md +0 -207
- package/src/Badge/Badge.test.tsx +0 -125
- package/src/Badge/__tests__/BadgeLargerText.a11y.chromium.spec.ts +0 -260
- package/src/Banner/Banner.spec.md +0 -282
- package/src/Banner/Banner.test.tsx +0 -879
- package/src/Blockquote/Blockquote.spec.md +0 -171
- package/src/Blockquote/Blockquote.test.tsx +0 -121
- package/src/BottomSheet/BottomSheet.spec.md +0 -457
- package/src/BottomSheet/BottomSheet.test.tsx +0 -3154
- package/src/BottomSheet/BottomSheetEdgeTint.test.tsx +0 -248
- package/src/BottomSheet/BottomSheetKeyboard.test.tsx +0 -195
- package/src/BottomSheet/BottomSheetPanel.test.tsx +0 -549
- package/src/BottomSheet/BottomSheetReplace.test.tsx +0 -1638
- package/src/BottomSheet/BottomSheetStacking.announce.test.tsx +0 -246
- package/src/BottomSheet/BottomSheetStacking.test.tsx +0 -3184
- package/src/BottomSheet/BottomSheetSwitcher.spec.md +0 -367
- package/src/BottomSheet/BottomSheetSwitcher.test.tsx +0 -2010
- package/src/BottomSheet/__tests__/BottomSheetDrag.a11y.chromium.spec.ts +0 -129
- package/src/BottomSheet/__tests__/BottomSheetFocusReturn.a11y.browser.spec.ts +0 -97
- package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +0 -415
- package/src/BottomSheet/__tests__/BottomSheetNativeModal.a11y.browser.spec.ts +0 -462
- package/src/BottomSheet/__tests__/BottomSheetPinchZoom.a11y.chromium.spec.ts +0 -247
- package/src/BottomSheet/__tests__/BottomSheetToastOutlet.a11y.chromium.spec.ts +0 -83
- package/src/BottomSheet/snapOffsets.test.ts +0 -254
- package/src/BottomSheet/useSheetGestures.test.ts +0 -1690
- package/src/Breadcrumbs/BreadcrumbItem.spec.md +0 -269
- package/src/Breadcrumbs/Breadcrumbs.spec.md +0 -165
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +0 -921
- package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.chromium.spec.ts +0 -132
- package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.renders.tsx +0 -45
- package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.states.ts +0 -81
- package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.test.tsx +0 -125
- package/src/Button/Button.spec.md +0 -322
- package/src/Button/Button.test.tsx +0 -864
- package/src/Button/__tests__/Button.a11y.chromium.spec.ts +0 -355
- package/src/Button/__tests__/Button.a11y.harnesses.tsx +0 -47
- package/src/Button/__tests__/Button.a11y.known-failures.ts +0 -25
- package/src/Button/__tests__/Button.a11y.renders.tsx +0 -139
- package/src/Button/__tests__/Button.a11y.states.ts +0 -317
- package/src/Button/__tests__/Button.a11y.test.tsx +0 -187
- package/src/ButtonGroup/ButtonGroup.spec.md +0 -220
- package/src/ButtonGroup/ButtonGroup.test.tsx +0 -1025
- package/src/Calendar/Calendar.spec.md +0 -248
- package/src/Calendar/Calendar.test.tsx +0 -2186
- package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +0 -141
- package/src/Calendar/__tests__/Calendar.a11y.known-failures.ts +0 -12
- package/src/Calendar/__tests__/Calendar.a11y.renders.tsx +0 -57
- package/src/Calendar/__tests__/Calendar.a11y.states.ts +0 -139
- package/src/Calendar/__tests__/Calendar.a11y.test.tsx +0 -137
- package/src/Calendar/dayCellUtils.test.ts +0 -520
- package/src/Calendar/getInitialFocusDate.test.ts +0 -94
- package/src/Calendar/getStandaloneShortWeekdayNames.test.ts +0 -54
- package/src/Calendar/hooks/useCalendarConstraints.test.ts +0 -153
- package/src/Calendar/hooks/useCalendarDays.test.ts +0 -265
- package/src/Calendar/hooks/useCalendarNavigation.test.ts +0 -252
- package/src/Card/Card.spec.md +0 -205
- package/src/Card/Card.test.tsx +0 -202
- package/src/Carousel/Carousel.spec.md +0 -146
- package/src/Carousel/Carousel.test.tsx +0 -1036
- package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +0 -207
- package/src/Carousel/__tests__/Carousel.a11y.known-failures.ts +0 -12
- package/src/Carousel/__tests__/Carousel.a11y.renders.tsx +0 -39
- package/src/Carousel/__tests__/Carousel.a11y.states.ts +0 -139
- package/src/Carousel/__tests__/Carousel.a11y.test.tsx +0 -127
- package/src/Center/Center.spec.md +0 -205
- package/src/Center/Center.test.tsx +0 -406
- package/src/Chat/ChatComposer.spec.md +0 -246
- package/src/Chat/ChatComposer.test.tsx +0 -364
- package/src/Chat/ChatComposerDrawer.spec.md +0 -267
- package/src/Chat/ChatComposerDrawer.test.tsx +0 -130
- package/src/Chat/ChatComposerInput.spec.md +0 -224
- package/src/Chat/ChatComposerInput.test.tsx +0 -2136
- package/src/Chat/ChatComposerTokenElement.spec.md +0 -164
- package/src/Chat/ChatComposerTokenElement.test.tsx +0 -85
- package/src/Chat/ChatDictationButton.spec.md +0 -205
- package/src/Chat/ChatDictationButton.test.tsx +0 -108
- package/src/Chat/ChatLayout.spec.md +0 -276
- package/src/Chat/ChatLayout.test.tsx +0 -311
- package/src/Chat/ChatLayoutScrollButton.spec.md +0 -322
- package/src/Chat/ChatLayoutScrollButton.test.tsx +0 -99
- package/src/Chat/ChatMessage.spec.md +0 -265
- package/src/Chat/ChatMessage.test.tsx +0 -344
- package/src/Chat/ChatMessageBubble.spec.md +0 -263
- package/src/Chat/ChatMessageBubble.test.tsx +0 -294
- package/src/Chat/ChatMessageList.spec.md +0 -222
- package/src/Chat/ChatMessageList.test.tsx +0 -198
- package/src/Chat/ChatMessageMetadata.spec.md +0 -220
- package/src/Chat/ChatMessageMetadata.test.tsx +0 -66
- package/src/Chat/ChatPastedTextToken.test.tsx +0 -71
- package/src/Chat/ChatSendButton.spec.md +0 -238
- package/src/Chat/ChatSendButton.test.tsx +0 -309
- package/src/Chat/ChatSystemMessage.spec.md +0 -224
- package/src/Chat/ChatSystemMessage.test.tsx +0 -189
- package/src/Chat/ChatTokenizedText.spec.md +0 -190
- package/src/Chat/ChatTokenizedText.test.tsx +0 -163
- package/src/Chat/ChatToolCalls.spec.md +0 -194
- package/src/Chat/ChatToolCalls.test.tsx +0 -413
- package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +0 -577
- package/src/Chat/__tests__/ChatLayoutScrollButtonSurface.a11y.chromium.spec.ts +0 -740
- package/src/Chat/__tests__/ChatMessageBubble.a11y.chromium.spec.ts +0 -457
- package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.test.ts +0 -91
- package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.ts +0 -91
- package/src/Chat/__tests__/ChatMessageList.a11y.chromium.spec.ts +0 -465
- package/src/Chat/__tests__/ChatMessageMetadata.a11y.chromium.spec.ts +0 -416
- package/src/Chat/__tests__/ChatSendButton.a11y.chromium.spec.ts +0 -1523
- package/src/Chat/__tests__/ChatSystemMessage.a11y.chromium.spec.ts +0 -1004
- package/src/Chat/__tests__/ChatTokenizedText.a11y.chromium.spec.ts +0 -574
- package/src/Chat/__tests__/useChatStreamScroll.a11y.chromium.spec.ts +0 -263
- package/src/Chat/__tests__/useChatStreamScroll.fixture.tsx +0 -61
- package/src/Chat/useChatDictation.test.tsx +0 -369
- package/src/Chat/useChatNewMessages.test.tsx +0 -209
- package/src/Chat/useChatPasteAsToken.test.ts +0 -191
- package/src/Chat/useChatStreamScroll.test.tsx +0 -381
- package/src/Chat/useTriggerMenu.test.tsx +0 -994
- package/src/CheckboxInput/CheckboxInput.spec.md +0 -218
- package/src/CheckboxInput/CheckboxInput.test.tsx +0 -926
- package/src/CheckboxInput/__tests__/Checkbox.a11y.chromium.spec.ts +0 -354
- package/src/CheckboxInput/__tests__/Checkbox.a11y.known-failures.ts +0 -54
- package/src/CheckboxInput/__tests__/Checkbox.a11y.renders.tsx +0 -310
- package/src/CheckboxInput/__tests__/Checkbox.a11y.states.ts +0 -404
- package/src/CheckboxInput/__tests__/Checkbox.a11y.test.tsx +0 -128
- package/src/CheckboxList/CheckboxList.fr10.test.tsx +0 -51
- package/src/CheckboxList/CheckboxList.spec.md +0 -332
- package/src/CheckboxList/CheckboxList.test.tsx +0 -1159
- package/src/CheckboxList/CheckboxListItem.spec.md +0 -302
- package/src/CheckboxList/__tests__/CheckboxList.a11y.chromium.spec.ts +0 -1998
- package/src/Citation/Citation.spec.md +0 -179
- package/src/Citation/Citation.test.tsx +0 -361
- package/src/ClickableCard/ClickableCard.spec.md +0 -241
- package/src/ClickableCard/ClickableCard.test.tsx +0 -382
- package/src/Code/Code.spec.md +0 -170
- package/src/Code/Code.test.tsx +0 -75
- package/src/CodeBlock/CodeBlock.highlightStyles.test.tsx +0 -87
- package/src/CodeBlock/CodeBlock.spec.md +0 -243
- package/src/CodeBlock/CodeBlock.test.tsx +0 -752
- package/src/CodeBlock/CodeLanguage.test.tsx +0 -173
- package/src/CodeBlock/__tests__/CodeBlockCopyClearance.a11y.chromium.spec.ts +0 -325
- package/src/CodeBlock/__tests__/CodeBlockLanguages.a11y.chromium.spec.ts +0 -64
- package/src/CodeBlock/__tests__/CodeBlockOverflowStop.a11y.chromium.spec.ts +0 -126
- package/src/CodeBlock/__tests__/DiffRowPaint.a11y.chromium.spec.ts +0 -94
- package/src/CodeBlock/highlightRanges.test.ts +0 -253
- package/src/CodeBlock/languages.test.ts +0 -402
- package/src/CodeBlock/tokenizer.test.ts +0 -280
- package/src/CodeBlock/tokenizerBudget.test.ts +0 -112
- package/src/Collapsible/Collapsible.spec.md +0 -247
- package/src/Collapsible/Collapsible.test.tsx +0 -620
- package/src/Collapsible/CollapsibleGroup.spec.md +0 -229
- package/src/Collapsible/CollapsibleGroup.test.tsx +0 -656
- package/src/Collapsible/__tests__/Collapsible.a11y.chromium.spec.ts +0 -194
- package/src/Collapsible/__tests__/Collapsible.a11y.states.ts +0 -117
- package/src/Collapsible/__tests__/Collapsible.a11y.test.tsx +0 -140
- package/src/Collapsible/__tests__/CollapsibleGroup.a11y.chromium.spec.ts +0 -559
- package/src/Collapsible/__tests__/CollapsibleGroup.a11y.renders.tsx +0 -45
- package/src/Collapsible/__tests__/CollapsibleGroup.a11y.states.ts +0 -139
- package/src/Collapsible/__tests__/CollapsibleGroup.a11y.test.tsx +0 -135
- package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +0 -141
- package/src/Collapsible/useCollapsible.test.tsx +0 -236
- package/src/CommandPalette/CommandPalette.perf.test.ts +0 -100
- package/src/CommandPalette/CommandPalette.spec.md +0 -278
- package/src/CommandPalette/CommandPalette.test.tsx +0 -750
- package/src/CommandPalette/CommandPaletteEmpty.spec.md +0 -190
- package/src/CommandPalette/CommandPaletteEmpty.test.tsx +0 -101
- package/src/CommandPalette/CommandPaletteFooter.test.tsx +0 -122
- package/src/CommandPalette/CommandPaletteGroup.test.tsx +0 -129
- package/src/CommandPalette/CommandPaletteInput.spec.md +0 -215
- package/src/CommandPalette/CommandPaletteInput.test.tsx +0 -539
- package/src/CommandPalette/CommandPaletteItem.spec.md +0 -223
- package/src/CommandPalette/CommandPaletteItem.test.tsx +0 -417
- package/src/CommandPalette/CommandPaletteList.spec.md +0 -194
- package/src/CommandPalette/CommandPaletteList.test.tsx +0 -184
- package/src/CommandPalette/__tests__/CommandPalette.a11y.chromium.spec.ts +0 -600
- package/src/CommandPalette/__tests__/CommandPaletteEmptyAudit.a11y.chromium.spec.ts +0 -715
- package/src/CommandPalette/__tests__/CommandPaletteFooter.a11y.chromium.spec.ts +0 -582
- package/src/CommandPalette/__tests__/CommandPaletteInputAudit.a11y.chromium.spec.ts +0 -336
- package/src/CommandPalette/__tests__/CommandPaletteItemAudit.a11y.chromium.spec.ts +0 -523
- package/src/ComplexSelector/ComplexSelector.focusableDisabled.test.tsx +0 -76
- package/src/ComplexSelector/ComplexSelector.fr10.test.tsx +0 -262
- package/src/ComplexSelector/ComplexSelector.spec.md +0 -266
- package/src/ComplexSelector/ComplexSelector.test.tsx +0 -1171
- package/src/ComplexSelector/__tests__/ComplexSelector.a11y.chromium.spec.ts +0 -965
- package/src/ContextMenu/ContextMenu.spec.md +0 -279
- package/src/ContextMenu/ContextMenu.test.tsx +0 -1617
- package/src/ContextMenu/ContextMenu.triggerProps.test.tsx +0 -54
- package/src/ContextMenu/ContextMenuItem.spec.md +0 -132
- package/src/ContextMenu/__tests__/ContextMenuAudit.a11y.chromium.spec.ts +0 -439
- package/src/ContextMenu/__tests__/ContextMenuCursorAnchor.a11y.browser.spec.ts +0 -154
- package/src/ContextMenu/__tests__/ContextMenuLongPress.a11y.chromium.spec.ts +0 -117
- package/src/DateInput/DateInput.fr10.test.tsx +0 -283
- package/src/DateInput/DateInput.spec.md +0 -319
- package/src/DateInput/DateInput.test.tsx +0 -1571
- package/src/DateInput/DateInputTouch.test.tsx +0 -2948
- package/src/DateInput/MonthScrollerSettle.test.tsx +0 -165
- package/src/DateInput/NativeDateField.test.tsx +0 -741
- package/src/DateInput/Presentation.test.tsx +0 -121
- package/src/DateInput/__tests__/DateInputAudit.a11y.chromium.spec.ts +0 -577
- package/src/DateInput/__tests__/MonthScrollerSteps.interaction.browser.spec.ts +0 -312
- package/src/DateInput/__tests__/WheelPinchZoom.a11y.chromium.spec.ts +0 -171
- package/src/DateRangeInput/DateRangeInput.fr10.test.tsx +0 -165
- package/src/DateRangeInput/DateRangeInput.spec.md +0 -203
- package/src/DateRangeInput/DateRangeInput.test.tsx +0 -1151
- package/src/DateTimeInput/DateTimeInput.fr10.test.tsx +0 -319
- package/src/DateTimeInput/DateTimeInput.spec.md +0 -270
- package/src/DateTimeInput/DateTimeInput.test.tsx +0 -2656
- package/src/DateTimeInput/DateTimeInputTouch.test.tsx +0 -1071
- package/src/DateTimeInput/NativePickerSegments.test.tsx +0 -657
- package/src/DateTimeInput/Presentation.test.tsx +0 -89
- package/src/Dialog/Dialog.source-build.test.mjs +0 -43
- package/src/Dialog/Dialog.spec.md +0 -189
- package/src/Dialog/Dialog.test.tsx +0 -1599
- package/src/Dialog/DialogHeader.test.tsx +0 -477
- package/src/Dialog/__tests__/Dialog.a11y.browser.spec.ts +0 -111
- package/src/Dialog/__tests__/Dialog.a11y.chromium.spec.ts +0 -218
- package/src/Dialog/__tests__/Dialog.a11y.known-failures.ts +0 -28
- package/src/Dialog/__tests__/Dialog.a11y.renders.tsx +0 -107
- package/src/Dialog/__tests__/Dialog.a11y.states.ts +0 -104
- package/src/Dialog/__tests__/Dialog.a11y.test.tsx +0 -102
- package/src/Dialog/__tests__/Dialog.reduced-motion.a11y.browser.spec.ts +0 -252
- package/src/Dialog/__tests__/DialogSecondDocument.a11y.browser.spec.ts +0 -202
- package/src/Dialog/modules/DialogHeader.spec.md +0 -211
- package/src/Dialog/useImperativeDialog.test.tsx +0 -78
- package/src/Divider/Divider.spec.md +0 -252
- package/src/Divider/Divider.test.tsx +0 -155
- package/src/Drawer/Drawer.spec.md +0 -388
- package/src/Drawer/Drawer.test.tsx +0 -1335
- package/src/Drawer/DrawerDirection.test.tsx +0 -127
- package/src/Drawer/DrawerHeader.spec.md +0 -181
- package/src/Drawer/DrawerHeader.test.tsx +0 -102
- package/src/Drawer/__tests__/DrawerAudit.a11y.chromium.spec.ts +0 -402
- package/src/Drawer/__tests__/DrawerHeaderAudit.a11y.chromium.spec.ts +0 -298
- package/src/Drawer/__tests__/DrawerNonModalPageScroll.a11y.chromium.spec.ts +0 -267
- package/src/DropdownMenu/DropdownMenu.spec.md +0 -562
- package/src/DropdownMenu/DropdownMenu.ssr.test.tsx +0 -93
- package/src/DropdownMenu/DropdownMenu.test.tsx +0 -4498
- package/src/DropdownMenu/DropdownMenuCheckboxItem.spec.md +0 -192
- package/src/DropdownMenu/DropdownMenuContext.public.test.ts +0 -22
- package/src/DropdownMenu/DropdownMenuDivider.spec.md +0 -186
- package/src/DropdownMenu/DropdownMenuGroup.spec.md +0 -145
- package/src/DropdownMenu/DropdownMenuItem.spec.md +0 -215
- package/src/DropdownMenu/DropdownMenuLazySheet.test.tsx +0 -126
- package/src/DropdownMenu/DropdownMenuRadioGroup.spec.md +0 -187
- package/src/DropdownMenu/DropdownMenuRadioItem.spec.md +0 -227
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +0 -635
- package/src/DropdownMenu/DropdownMenuSheetFirstOpen.test.tsx +0 -72
- package/src/DropdownMenu/DropdownMenuSubMenu.spec.md +0 -231
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +0 -2442
- package/src/DropdownMenu/__tests__/DropdownMenuDividerAudit.a11y.chromium.spec.ts +0 -281
- package/src/DropdownMenu/__tests__/DropdownMenuDrillIn.a11y.chromium.spec.ts +0 -175
- package/src/DropdownMenu/__tests__/DropdownMenuFocusReturn.a11y.browser.spec.ts +0 -74
- package/src/DropdownMenu/__tests__/DropdownMenuGroupAudit.a11y.chromium.spec.ts +0 -335
- package/src/DropdownMenu/__tests__/DropdownMenuItemAudit.a11y.chromium.spec.ts +0 -367
- package/src/DropdownMenu/__tests__/DropdownMenuRadioGroupAudit.a11y.chromium.spec.ts +0 -328
- package/src/DropdownMenu/__tests__/DropdownMenuRadioItemAudit.a11y.chromium.spec.ts +0 -540
- package/src/DropdownMenu/__tests__/DropdownMenuSubMenuAudit.a11y.chromium.spec.ts +0 -671
- package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +0 -158
- package/src/DropdownMenu/__tests__/Menu.a11y.known-failures.ts +0 -26
- package/src/DropdownMenu/__tests__/Menu.a11y.renders.tsx +0 -65
- package/src/DropdownMenu/__tests__/Menu.a11y.states.ts +0 -138
- package/src/DropdownMenu/__tests__/Menu.a11y.test.tsx +0 -136
- package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +0 -149
- package/src/DropdownMenu/__tests__/MenuButton.a11y.known-failures.ts +0 -12
- package/src/DropdownMenu/__tests__/MenuButton.a11y.renders.tsx +0 -67
- package/src/DropdownMenu/__tests__/MenuButton.a11y.states.ts +0 -141
- package/src/DropdownMenu/__tests__/MenuButton.a11y.test.tsx +0 -138
- package/src/DropdownMenu/__tests__/MenuHeaderFooter.a11y.chromium.spec.ts +0 -231
- package/src/DropdownMenu/__tests__/MenuHoverFocus.a11y.chromium.spec.ts +0 -238
- package/src/DropdownMenu/__tests__/MenuPinchZoom.a11y.chromium.spec.ts +0 -173
- package/src/DropdownMenu/__tests__/MenuPress.a11y.chromium.spec.ts +0 -503
- package/src/DropdownMenu/__tests__/SubMenuHeaderFooter.a11y.chromium.spec.ts +0 -268
- package/src/DropdownMenu/__tests__/warmMenuBottomSheet.tsx +0 -43
- package/src/DropdownMenu/lazyMenuBottomSheet.test.ts +0 -60
- package/src/DropdownMenu/modules/useMenuHover.spec.md +0 -283
- package/src/DropdownMenu/modules/useMenuPress.spec.md +0 -348
- package/src/EmptyState/EmptyState.announce.test.tsx +0 -227
- package/src/EmptyState/EmptyState.spec.md +0 -203
- package/src/EmptyState/EmptyState.test.tsx +0 -284
- package/src/Field/Field.spec.md +0 -226
- package/src/Field/Field.test.tsx +0 -800
- package/src/Field/FieldLabel.spec.md +0 -183
- package/src/Field/FieldLabel.test.tsx +0 -244
- package/src/Field/InputClearButton.test.tsx +0 -395
- package/src/Field/__tests__/FieldLabelAudit.a11y.chromium.spec.ts +0 -297
- package/src/Field/fieldInputFamily.test.tsx +0 -160
- package/src/FieldStatus/FieldStatus.spec.md +0 -224
- package/src/FieldStatus/FieldStatus.test.tsx +0 -482
- package/src/FieldStatus/__tests__/StatusMessage.a11y.chromium.spec.ts +0 -206
- package/src/FieldStatus/__tests__/StatusMessage.a11y.known-failures.ts +0 -13
- package/src/FieldStatus/__tests__/StatusMessage.a11y.renders.tsx +0 -287
- package/src/FieldStatus/__tests__/StatusMessage.a11y.states.ts +0 -302
- package/src/FieldStatus/__tests__/StatusMessage.a11y.test.tsx +0 -154
- package/src/FileInput/FileInput.fr10.test.tsx +0 -21
- package/src/FileInput/FileInput.spec.md +0 -199
- package/src/FileInput/FileInput.test.tsx +0 -1291
- package/src/FormLayout/FormLayout.spec.md +0 -209
- package/src/FormLayout/FormLayout.test.tsx +0 -444
- package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +0 -46
- package/src/Grid/Grid.spec.md +0 -193
- package/src/Grid/Grid.test.tsx +0 -509
- package/src/Grid/GridSpan.spec.md +0 -158
- package/src/HStack/HStack.test.tsx +0 -129
- package/src/Heading/Heading.spec.md +0 -198
- package/src/Heading/Heading.test.tsx +0 -328
- package/src/HoverCard/HoverCard.spec.md +0 -244
- package/src/HoverCard/HoverCard.test.tsx +0 -1339
- package/src/Icon/Icon.spec.md +0 -244
- package/src/Icon/Icon.test.tsx +0 -990
- package/src/Icon/globalIconRegistry.test.tsx +0 -613
- package/src/IconButton/IconButton.spec.md +0 -197
- package/src/IconButton/IconButton.test.tsx +0 -156
- package/src/Indicator/CheckIndicator.spec.md +0 -164
- package/src/Indicator/CheckboxIndicator.spec.md +0 -164
- package/src/Indicator/Indicator.spec.md +0 -188
- package/src/Indicator/Indicator.test.tsx +0 -389
- package/src/Indicator/indicatorRegistry.test.tsx +0 -106
- package/src/InputGroup/InputGroup.spec.md +0 -199
- package/src/InputGroup/InputGroup.test.tsx +0 -502
- package/src/InputGroup/InputGroupText.spec.md +0 -139
- package/src/InteractiveRoleContext/InteractiveRoleContext.test.tsx +0 -185
- package/src/Item/Item.source-build.test.mjs +0 -88
- package/src/Item/Item.spec.md +0 -226
- package/src/Item/Item.swipeLayer.test.tsx +0 -74
- package/src/Item/Item.test.tsx +0 -1515
- package/src/Item/ItemMarkerColumns.a11y.chromium.spec.ts +0 -211
- package/src/Item/__tests__/ItemSwipeActions.a11y.chromium.spec.ts +0 -337
- package/src/Item/__tests__/ItemSwipePinchZoom.a11y.chromium.spec.ts +0 -186
- package/src/Kbd/Kbd.spec.md +0 -185
- package/src/Kbd/Kbd.test.tsx +0 -299
- package/src/Layer/LayerProvider.spec.md +0 -149
- package/src/Layer/LayerProvider.test.tsx +0 -143
- package/src/Layer/__tests__/LayerBrowserHide.a11y.chromium.spec.ts +0 -126
- package/src/Layer/__tests__/LayerReducedMotion.a11y.chromium.spec.ts +0 -176
- package/src/Layer/__tests__/TouchTrigger.a11y.chromium.spec.ts +0 -200
- package/src/Layer/anchorName.test.ts +0 -146
- package/src/Layer/layerDismissalFamilies.test.tsx +0 -487
- package/src/Layer/layerDismissalInvariants.test.tsx +0 -501
- package/src/Layer/layerHost.test.ts +0 -117
- package/src/Layer/layerScopedContext.test.tsx +0 -499
- package/src/Layer/layerViewportInset.source-build.test.mjs +0 -90
- package/src/Layer/layerViewportInset.test.ts +0 -120
- package/src/Layer/popoverOperations.test.ts +0 -205
- package/src/Layer/useLayer.test.tsx +0 -2845
- package/src/Layer/useLayerDismissal.test.tsx +0 -580
- package/src/Layer/useTouchTrigger.test.ts +0 -70
- package/src/Layout/Layout.spec.md +0 -243
- package/src/Layout/Layout.test.tsx +0 -375
- package/src/Layout/LayoutContent.spec.md +0 -205
- package/src/Layout/LayoutFooter.spec.md +0 -190
- package/src/Layout/LayoutHeader.spec.md +0 -193
- package/src/Layout/LayoutPanel.spec.md +0 -194
- package/src/Layout/LayoutSlots.test.tsx +0 -376
- package/src/Layout/__tests__/Layout.a11y.chromium.spec.ts +0 -134
- package/src/Layout/__tests__/Layout.a11y.renders.tsx +0 -110
- package/src/Layout/__tests__/Layout.a11y.states.ts +0 -93
- package/src/Layout/__tests__/Layout.a11y.test.tsx +0 -142
- package/src/Layout/__tests__/childrenAsContent.test.tsx +0 -59
- package/src/Layout/__tests__/contentWidth.test.tsx +0 -303
- package/src/Layout/__tests__/edgeCompensation.test.tsx +0 -191
- package/src/Layout/__tests__/nestedPadding.test.tsx +0 -264
- package/src/Layout/overlayPaddingReset.test.tsx +0 -224
- package/src/Lightbox/Lightbox.spec.md +0 -199
- package/src/Lightbox/Lightbox.test.tsx +0 -837
- package/src/Lightbox/LightboxKeyboard.a11y.browser.spec.ts +0 -78
- package/src/Lightbox/LightboxViewport.a11y.browser.spec.ts +0 -74
- package/src/Lightbox/useLightbox.test.tsx +0 -263
- package/src/Link/Link.spec.md +0 -230
- package/src/Link/Link.test.tsx +0 -457
- package/src/Link/LinkProvider.spec.md +0 -167
- package/src/Link/__tests__/Link.a11y.chromium.spec.ts +0 -153
- package/src/Link/__tests__/Link.a11y.renders.tsx +0 -97
- package/src/Link/__tests__/Link.a11y.states.ts +0 -104
- package/src/Link/__tests__/Link.a11y.test.tsx +0 -127
- package/src/Link/__tests__/Link.navigation.a11y.chromium.spec.ts +0 -262
- package/src/Link/__tests__/Link.truncation.a11y.chromium.spec.ts +0 -58
- package/src/Link/useLinkComponent.test.tsx +0 -572
- package/src/Link/useLinkify.test.tsx +0 -146
- package/src/List/List.spec.md +0 -336
- package/src/List/List.test.tsx +0 -1052
- package/src/List/ListItem.source-build.test.mjs +0 -41
- package/src/List/ListItem.spec.md +0 -205
- package/src/List/ListMarkers.a11y.chromium.spec.ts +0 -904
- package/src/Markdown/Markdown.codeLanguages.test.tsx +0 -137
- package/src/Markdown/Markdown.fr23.bench.ts +0 -176
- package/src/Markdown/Markdown.fr23.perf.test.ts +0 -484
- package/src/Markdown/Markdown.helpers.perf.test.ts +0 -495
- package/src/Markdown/Markdown.public.test.ts +0 -309
- package/src/Markdown/Markdown.renderBoundary.test.tsx +0 -72
- package/src/Markdown/Markdown.rerender.test.tsx +0 -143
- package/src/Markdown/Markdown.spec.md +0 -595
- package/src/Markdown/Markdown.test.tsx +0 -1383
- package/src/Markdown/MarkdownTable.a11y.chromium.spec.ts +0 -727
- package/src/Markdown/__tests__/MarkdownNesting.a11y.chromium.spec.ts +0 -102
- package/src/Markdown/angleDestinations.test.tsx +0 -104
- package/src/Markdown/ast.test.ts +0 -374
- package/src/Markdown/atxHeadingIndentation.test.tsx +0 -53
- package/src/Markdown/blockNesting.test.tsx +0 -124
- package/src/Markdown/blockquoteMarkers.test.tsx +0 -69
- package/src/Markdown/characterReferences.test.ts +0 -47
- package/src/Markdown/codeSpans.test.tsx +0 -65
- package/src/Markdown/emphasis.test.tsx +0 -214
- package/src/Markdown/fenceInfo.test.tsx +0 -47
- package/src/Markdown/imageAlt.test.tsx +0 -84
- package/src/Markdown/incremental.test.ts +0 -1198
- package/src/Markdown/incrementalIndentation.test.tsx +0 -36
- package/src/Markdown/indentedFences.test.tsx +0 -374
- package/src/Markdown/indentedTables.test.tsx +0 -53
- package/src/Markdown/linkBrackets.test.tsx +0 -116
- package/src/Markdown/linkDestinationLinear.test.tsx +0 -54
- package/src/Markdown/linkDestinations.test.tsx +0 -127
- package/src/Markdown/linkTextCode.test.tsx +0 -65
- package/src/Markdown/listBullets.test.tsx +0 -55
- package/src/Markdown/listContinuation.test.tsx +0 -94
- package/src/Markdown/listThematicBreak.test.tsx +0 -49
- package/src/Markdown/longLinkLabels.test.tsx +0 -49
- package/src/Markdown/modules/headingLinks.spec.md +0 -262
- package/src/Markdown/modules/remark.spec.md +0 -269
- package/src/Markdown/modules/softBreaks.spec.md +0 -137
- package/src/Markdown/modules/sourceLines.spec.md +0 -162
- package/src/Markdown/openFenceFinalNewline.test.tsx +0 -85
- package/src/Markdown/parser.perf.test.ts +0 -398
- package/src/Markdown/parser.public.test.ts +0 -144
- package/src/Markdown/parser.test.ts +0 -1925
- package/src/Markdown/plugin-renderer/MarkdownPluginNodeRenderer.test.tsx +0 -300
- package/src/Markdown/plugins/frontmatter.test.tsx +0 -150
- package/src/Markdown/plugins/headingLinks.a11y.chromium.spec.ts +0 -856
- package/src/Markdown/plugins/headingLinks.ssr.test.tsx +0 -143
- package/src/Markdown/plugins/headingLinks.test.tsx +0 -637
- package/src/Markdown/plugins/protocol.test.tsx +0 -1083
- package/src/Markdown/plugins/semanticFence.test.tsx +0 -655
- package/src/Markdown/plugins/softBreaks.test.tsx +0 -172
- package/src/Markdown/plugins/sourceDecoration.test.tsx +0 -799
- package/src/Markdown/plugins/sourceLines.test.tsx +0 -715
- package/src/Markdown/plugins/textTransform.test.ts +0 -467
- package/src/Markdown/remark.test.tsx +0 -1877
- package/src/Markdown/streaming.test.ts +0 -148
- package/src/Markdown/streamingListShapes.test.tsx +0 -93
- package/src/Markdown/trailingSpaces.test.tsx +0 -45
- package/src/MetadataList/MetadataList.spec.md +0 -187
- package/src/MetadataList/MetadataList.test.tsx +0 -383
- package/src/MetadataList/MetadataListItem.spec.md +0 -165
- package/src/MobileNav/MobileNav.spec.md +0 -306
- package/src/MobileNav/MobileNav.test.tsx +0 -296
- package/src/MobileNav/MobileNavCloseEdgeCases.test.tsx +0 -584
- package/src/MobileNav/MobileNavCloseTiming.test.ts +0 -58
- package/src/MobileNav/MobileNavCloseVisibility.test.tsx +0 -172
- package/src/MobileNav/MobileNavEntryAnimation.test.tsx +0 -212
- package/src/MobileNav/MobileNavFocus.test.tsx +0 -553
- package/src/MobileNav/MobileNavPinchZoom.a11y.chromium.spec.ts +0 -147
- package/src/MobileNav/MobileNavReopen.test.tsx +0 -118
- package/src/MobileNav/MobileNavScrollbarGutter.test.tsx +0 -109
- package/src/MobileNav/MobileNavToggle.test.tsx +0 -179
- package/src/MobileNav/__tests__/MobileNavHeader.a11y.chromium.spec.ts +0 -89
- package/src/MobileNav/__tests__/MobileNavWidth.a11y.chromium.spec.ts +0 -103
- package/src/MoreMenu/MoreMenu.spec.md +0 -268
- package/src/MoreMenu/MoreMenu.test.tsx +0 -367
- package/src/MultiSelector/CreateRow.a11y.chromium.spec.ts +0 -148
- package/src/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.ts +0 -72
- package/src/MultiSelector/MultiSelector.focusableDisabled.test.tsx +0 -121
- package/src/MultiSelector/MultiSelector.fr10.test.tsx +0 -221
- package/src/MultiSelector/MultiSelector.spec.md +0 -357
- package/src/MultiSelector/MultiSelector.test.tsx +0 -4971
- package/src/MultiSelector/OptionActions.a11y.chromium.spec.ts +0 -310
- package/src/MultiSelector/__tests__/MultiSelector.a11y.chromium.spec.ts +0 -46
- package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +0 -135
- package/src/NavIcon/NavIcon.spec.md +0 -158
- package/src/NavIcon/NavIcon.test.tsx +0 -41
- package/src/NavMenu/NavHeadingMenu.spec.md +0 -264
- package/src/NavMenu/NavHeadingMenu.test.tsx +0 -714
- package/src/NavMenu/__tests__/NavMenusSlideSelection.a11y.chromium.spec.ts +0 -137
- package/src/NumberInput/NumberInput.fr10.test.tsx +0 -21
- package/src/NumberInput/NumberInput.spec.md +0 -270
- package/src/NumberInput/NumberInput.test.tsx +0 -2697
- package/src/NumberInput/__tests__/NumberInput.a11y.chromium.spec.ts +0 -124
- package/src/NumberInput/__tests__/NumberInput.a11y.known-failures.ts +0 -26
- package/src/NumberInput/__tests__/NumberInput.a11y.renders.tsx +0 -77
- package/src/NumberInput/__tests__/NumberInput.a11y.states.ts +0 -116
- package/src/NumberInput/__tests__/NumberInput.a11y.test.tsx +0 -154
- package/src/NumberInput/__tests__/NumberInput.coarse-pointer.a11y.chromium.spec.ts +0 -102
- package/src/NumberInput/numberInputCommit.test.ts +0 -72
- package/src/NumberInput/numberParser.docblock.test.ts +0 -234
- package/src/NumberInput/numberParser.test.ts +0 -222
- package/src/Outline/Outline.spec.md +0 -258
- package/src/Outline/Outline.test.tsx +0 -1134
- package/src/Outline/OutlineFocus.a11y.chromium.spec.ts +0 -551
- package/src/Outline/modules/parseOutlineFromMarkdown.spec.md +0 -150
- package/src/Outline/parseOutlineFromMarkdown.test.ts +0 -104
- package/src/OverflowList/OverflowList.spec.md +0 -204
- package/src/OverflowList/OverflowList.test.tsx +0 -1073
- package/src/Overlay/Overlay.spec.md +0 -304
- package/src/Overlay/Overlay.test.tsx +0 -424
- package/src/Pagination/Pagination.spec.md +0 -300
- package/src/Pagination/Pagination.test.tsx +0 -1754
- package/src/Popover/Popover.spec.md +0 -525
- package/src/Popover/Popover.test.tsx +0 -1508
- package/src/Popover/PopoverPresentation.test.tsx +0 -952
- package/src/Popover/__tests__/PopoverSecondDocument.a11y.chromium.spec.ts +0 -267
- package/src/PowerSearch/PowerSearch.spec.md +0 -661
- package/src/PowerSearch/PowerSearch.test.tsx +0 -1027
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +0 -1190
- package/src/PowerSearch/PowerSearchFilterEditor.test.tsx +0 -377
- package/src/PowerSearch/PowerSearchToken.test.tsx +0 -230
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +0 -754
- package/src/PowerSearch/formatFilterValue.test.ts +0 -339
- package/src/PowerSearch/resolveDateTimeRangePart.test.ts +0 -40
- package/src/PowerSearch/usePowerSearchConfig.test.ts +0 -832
- package/src/PowerSearch/usePowerSearchSource.test.ts +0 -621
- package/src/ProgressBar/ProgressBar.spec.md +0 -261
- package/src/ProgressBar/ProgressBar.test.tsx +0 -928
- package/src/ProgressBar/__tests__/ProgressBar.a11y.chromium.spec.ts +0 -127
- package/src/ProgressBar/__tests__/ProgressBar.a11y.known-failures.ts +0 -12
- package/src/ProgressBar/__tests__/ProgressBar.a11y.renders.tsx +0 -38
- package/src/ProgressBar/__tests__/ProgressBar.a11y.states.ts +0 -123
- package/src/ProgressBar/__tests__/ProgressBar.a11y.test.tsx +0 -107
- package/src/ProgressBar/__tests__/ProgressBarMotion.a11y.chromium.spec.ts +0 -831
- package/src/RadioList/RadioList.fr10.test.tsx +0 -67
- package/src/RadioList/RadioList.spec.md +0 -227
- package/src/RadioList/RadioList.test.tsx +0 -1051
- package/src/RadioList/RadioListItem.press.source-build.test.mjs +0 -80
- package/src/RadioList/RadioListItem.spec.md +0 -223
- package/src/RadioList/__tests__/RadioGroup.a11y.chromium.spec.ts +0 -274
- package/src/RadioList/__tests__/RadioGroup.a11y.known-failures.ts +0 -12
- package/src/RadioList/__tests__/RadioGroup.a11y.renders.tsx +0 -232
- package/src/RadioList/__tests__/RadioGroup.a11y.states.ts +0 -503
- package/src/RadioList/__tests__/RadioGroup.a11y.test.tsx +0 -217
- package/src/Resizable/Resizable.spec.md +0 -298
- package/src/Resizable/ResizeHandle.test.tsx +0 -1067
- package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +0 -127
- package/src/Resizable/__tests__/ResizeHandle.a11y.known-failures.ts +0 -39
- package/src/Resizable/__tests__/ResizeHandle.a11y.renders.tsx +0 -80
- package/src/Resizable/__tests__/ResizeHandle.a11y.states.ts +0 -197
- package/src/Resizable/__tests__/ResizeHandle.a11y.test.tsx +0 -123
- package/src/Resizable/shippedDirections.test.ts +0 -462
- package/src/Resizable/useResizable.test.ts +0 -1725
- package/src/Resizable/utils.test.ts +0 -74
- package/src/ScrollableArea/ScrollableArea.spec.md +0 -190
- package/src/ScrollableArea/ScrollableArea.test.tsx +0 -304
- package/src/ScrollableArea/modules/useScrollableArea.spec.md +0 -149
- package/src/Section/Section.spec.md +0 -197
- package/src/Section/Section.test.tsx +0 -376
- package/src/SegmentedControl/SegmentedControl.spec.md +0 -261
- package/src/SegmentedControl/SegmentedControl.test.tsx +0 -981
- package/src/SegmentedControl/SegmentedControlItem.spec.md +0 -206
- package/src/SelectableCard/SelectableCard.spec.md +0 -230
- package/src/SelectableCard/SelectableCard.test.tsx +0 -216
- package/src/Selector/Selector.focusableDisabled.test.tsx +0 -127
- package/src/Selector/Selector.fr10.test.tsx +0 -149
- package/src/Selector/Selector.sheetActiveDescendant.test.tsx +0 -95
- package/src/Selector/Selector.source-build.test.mjs +0 -79
- package/src/Selector/Selector.spec.md +0 -379
- package/src/Selector/Selector.test.tsx +0 -5117
- package/src/Selector/__tests__/Combobox.a11y.known-failures.ts +0 -27
- package/src/Selector/__tests__/Combobox.a11y.states.ts +0 -145
- package/src/Selector/__tests__/ComboboxField.a11y.chromium.spec.ts +0 -458
- package/src/Selector/__tests__/EmptyStateAnnouncement.a11y.chromium.spec.ts +0 -91
- package/src/Selector/__tests__/Listbox.a11y.chromium.spec.ts +0 -131
- package/src/Selector/__tests__/Listbox.a11y.dom.ts +0 -38
- package/src/Selector/__tests__/Listbox.a11y.inventory.test.ts +0 -63
- package/src/Selector/__tests__/Listbox.a11y.known-failures.ts +0 -12
- package/src/Selector/__tests__/Listbox.a11y.states.ts +0 -232
- package/src/Selector/__tests__/Selector.a11y.chromium.spec.ts +0 -46
- package/src/Selector/__tests__/Selector.combobox.a11y.chromium.spec.ts +0 -109
- package/src/Selector/__tests__/Selector.combobox.a11y.test.tsx +0 -133
- package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +0 -128
- package/src/Selector/useCombobox.public.test.tsx +0 -89
- package/src/Selector/useCombobox.test.tsx +0 -444
- package/src/SideNav/SideNav.spec.md +0 -247
- package/src/SideNav/SideNav.test.tsx +0 -4275
- package/src/SideNav/SideNavCollapseButton.spec.md +0 -161
- package/src/SideNav/SideNavHeading.spec.md +0 -226
- package/src/SideNav/SideNavItem.spec.md +0 -236
- package/src/SideNav/SideNavRailMotion.test.tsx +0 -620
- package/src/SideNav/SideNavSection.spec.md +0 -153
- package/src/SideNav/__tests__/SideNavRailMotion.interaction.browser.spec.ts +0 -542
- package/src/SizeContext/SizeContext.test.tsx +0 -226
- package/src/Skeleton/Skeleton.spec.md +0 -184
- package/src/Skeleton/Skeleton.test.tsx +0 -148
- package/src/Slider/Slider.fr10.test.tsx +0 -93
- package/src/Slider/Slider.spec.md +0 -285
- package/src/Slider/Slider.test.tsx +0 -1661
- package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +0 -125
- package/src/Slider/__tests__/Slider.a11y.known-failures.ts +0 -12
- package/src/Slider/__tests__/Slider.a11y.renders.tsx +0 -42
- package/src/Slider/__tests__/Slider.a11y.states.ts +0 -106
- package/src/Slider/__tests__/Slider.a11y.test.tsx +0 -105
- package/src/Spinner/Spinner.spec.md +0 -231
- package/src/Spinner/Spinner.test.tsx +0 -484
- package/src/Stack/Stack.spec.md +0 -203
- package/src/Stack/Stack.test.tsx +0 -473
- package/src/Stack/StackItem.test.tsx +0 -105
- package/src/StatusDot/StatusDot.spec.md +0 -224
- package/src/StatusDot/StatusDot.test.tsx +0 -213
- package/src/Stepper/Step.spec.md +0 -200
- package/src/Stepper/Stepper.public.test.ts +0 -91
- package/src/Stepper/Stepper.spec.md +0 -327
- package/src/Stepper/Stepper.test.tsx +0 -2130
- package/src/Switch/Switch.focusRing.source-build.test.mjs +0 -81
- package/src/Switch/Switch.spec.md +0 -277
- package/src/Switch/Switch.test.tsx +0 -1136
- package/src/Switch/__tests__/Switch.a11y.chromium.spec.ts +0 -211
- package/src/Switch/__tests__/Switch.a11y.known-failures.ts +0 -28
- package/src/Switch/__tests__/Switch.a11y.states.ts +0 -275
- package/src/Switch/__tests__/Switch.a11y.test.tsx +0 -144
- package/src/TabList/Tab.spec.md +0 -201
- package/src/TabList/TabList.spec.md +0 -217
- package/src/TabList/TabList.test.tsx +0 -1755
- package/src/TabList/TabMenu.spec.md +0 -198
- package/src/TabList/__tests__/TabListOverflow.interaction.browser.spec.ts +0 -99
- package/src/TabList/__tests__/TabPressPointer.interaction.browser.spec.ts +0 -163
- package/src/TabList/__tests__/Tabs.a11y.chromium.spec.ts +0 -199
- package/src/TabList/__tests__/Tabs.a11y.known-failures.ts +0 -12
- package/src/TabList/__tests__/Tabs.a11y.renders.tsx +0 -92
- package/src/TabList/__tests__/Tabs.a11y.states.ts +0 -247
- package/src/TabList/__tests__/Tabs.a11y.test.tsx +0 -153
- package/src/Table/Table.perf.test.tsx +0 -569
- package/src/Table/Table.spec.md +0 -395
- package/src/Table/Table.test.tsx +0 -1883
- package/src/Table/TableHeaderCell.test.tsx +0 -291
- package/src/Table/TableSelectionToolbar.test.tsx +0 -109
- package/src/Table/__tests__/Table.a11y.chromium.spec.ts +0 -141
- package/src/Table/__tests__/Table.a11y.contracts.ts +0 -35
- package/src/Table/__tests__/Table.a11y.renders.tsx +0 -112
- package/src/Table/__tests__/Table.a11y.states.ts +0 -136
- package/src/Table/__tests__/Table.a11y.test.tsx +0 -198
- package/src/Table/__tests__/TableMinWidth.a11y.chromium.spec.ts +0 -75
- package/src/Table/__tests__/TableRowGlide.a11y.browser.spec.ts +0 -382
- package/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts +0 -138
- package/src/Table/__tests__/TableStickyDividers.a11y.browser.spec.ts +0 -560
- package/src/Table/plugins/activation/useTableActivation.spec.md +0 -254
- package/src/Table/plugins/columnResize/useTableColumnResize.spec.md +0 -373
- package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +0 -941
- package/src/Table/plugins/columnSettings/useTableColumnSettings.test.tsx +0 -175
- package/src/Table/plugins/columnSettings/useTableColumnSettingsState.test.tsx +0 -296
- package/src/Table/plugins/filtering/useTableFilterState.test.tsx +0 -143
- package/src/Table/plugins/filtering/useTableFiltering.test.tsx +0 -357
- package/src/Table/plugins/groupedRows/useTableGroupedRows-perf.test.tsx +0 -112
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +0 -409
- package/src/Table/plugins/infiniteScroll/useTableInfiniteScroll.spec.md +0 -244
- package/src/Table/plugins/pagination/useTablePagination-perf.test.tsx +0 -232
- package/src/Table/plugins/pagination/useTablePagination.test.tsx +0 -666
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.glide.test.tsx +0 -280
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +0 -681
- package/src/Table/plugins/rowIndex/useTableRowIndex.test.tsx +0 -132
- package/src/Table/plugins/rowStatus/useTableRowStatus.public.test.ts +0 -92
- package/src/Table/plugins/rowStatus/useTableRowStatus.spec.md +0 -355
- package/src/Table/plugins/rowStatus/useTableRowStatus.test.tsx +0 -519
- package/src/Table/plugins/selection/useTableSelection-perf.test.tsx +0 -258
- package/src/Table/plugins/selection/useTableSelection.test.tsx +0 -424
- package/src/Table/plugins/selection/useTableSelectionState.test.tsx +0 -451
- package/src/Table/plugins/sortable/__tests__/useTableSortable.a11y.test.tsx +0 -174
- package/src/Table/plugins/sortable/__tests__/useTableSortable.a11y.ts +0 -86
- package/src/Table/plugins/sortable/useTableSortable.test.tsx +0 -786
- package/src/Table/plugins/sortable/useTableSortableState.test.tsx +0 -580
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.test.tsx +0 -334
- package/src/Table/plugins/tree/useTableTreeData-perf.test.tsx +0 -163
- package/src/Table/plugins/tree/useTableTreeData.test.tsx +0 -992
- package/src/Table/plugins/tree/useTableTreeState.test.tsx +0 -740
- package/src/Table/plugins/virtualization/useTableVirtualization.spec.md +0 -266
- package/src/Table/tableContextMenu.test.tsx +0 -208
- package/src/Text/Text.spec.md +0 -193
- package/src/Text/Text.test.tsx +0 -405
- package/src/Text/useTruncation.test.tsx +0 -196
- package/src/TextArea/TextArea.fr10.test.tsx +0 -21
- package/src/TextArea/TextArea.spec.md +0 -300
- package/src/TextArea/TextArea.test.tsx +0 -1317
- package/src/TextInput/TextInput.fr10.test.tsx +0 -21
- package/src/TextInput/TextInput.spec.md +0 -260
- package/src/TextInput/TextInput.test.tsx +0 -1280
- package/src/TextInput/__tests__/TextInput.a11y.chromium.spec.ts +0 -214
- package/src/TextInput/__tests__/TextInput.a11y.known-failures.ts +0 -40
- package/src/TextInput/__tests__/TextInput.a11y.renders.tsx +0 -202
- package/src/TextInput/__tests__/TextInput.a11y.states.ts +0 -384
- package/src/TextInput/__tests__/TextInput.a11y.test.tsx +0 -130
- package/src/Thumbnail/Thumbnail.spec.md +0 -244
- package/src/Thumbnail/Thumbnail.test.tsx +0 -384
- package/src/TimeInput/NativeTimeInput.test.tsx +0 -343
- package/src/TimeInput/Presentation.test.tsx +0 -192
- package/src/TimeInput/TimeInput.fr10.test.tsx +0 -312
- package/src/TimeInput/TimeInput.spec.md +0 -270
- package/src/TimeInput/TimeInput.test.tsx +0 -907
- package/src/Timer/Timer.spec.md +0 -215
- package/src/Timer/Timer.test.tsx +0 -302
- package/src/Timestamp/Timestamp.spec.md +0 -246
- package/src/Timestamp/Timestamp.test.tsx +0 -1661
- package/src/Timestamp/tooltipEntries.test.ts +0 -566
- package/src/Toast/Toast.spec.md +0 -291
- package/src/Toast/ToastViewport.modalHost.test.tsx +0 -891
- package/src/Toast/ToastViewport.test.tsx +0 -3130
- package/src/Toast/useToast.test.tsx +0 -258
- package/src/ToggleButton/ToggleButton.spec.md +0 -256
- package/src/ToggleButton/ToggleButton.test.tsx +0 -1000
- package/src/ToggleButton/ToggleButtonGroup.spec.md +0 -195
- package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +0 -177
- package/src/ToggleButton/__tests__/ToggleButton.a11y.renders.tsx +0 -133
- package/src/ToggleButton/__tests__/ToggleButton.a11y.states.ts +0 -167
- package/src/ToggleButton/__tests__/ToggleButton.a11y.test.tsx +0 -103
- package/src/Token/Token.spec.md +0 -261
- package/src/Token/Token.test.tsx +0 -707
- package/src/Token/__tests__/TokenRemoveTarget.a11y.chromium.spec.ts +0 -87
- package/src/Tokenizer/Tokenizer.fr10.test.tsx +0 -28
- package/src/Tokenizer/Tokenizer.props-type.test.tsx +0 -126
- package/src/Tokenizer/Tokenizer.spec.md +0 -615
- package/src/Tokenizer/Tokenizer.ssr.test.tsx +0 -196
- package/src/Tokenizer/Tokenizer.test.tsx +0 -2216
- package/src/Tokenizer/TokenizerBottomSheet.test.tsx +0 -2738
- package/src/Tokenizer/__tests__/TokenizerEndLane.a11y.chromium.spec.ts +0 -505
- package/src/Toolbar/Toolbar.spec.md +0 -227
- package/src/Toolbar/Toolbar.test.tsx +0 -600
- package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +0 -176
- package/src/Toolbar/__tests__/Toolbar.a11y.renders.tsx +0 -63
- package/src/Toolbar/__tests__/Toolbar.a11y.states.ts +0 -142
- package/src/Toolbar/__tests__/Toolbar.a11y.test.tsx +0 -126
- package/src/Tooltip/Tooltip.spec.md +0 -267
- package/src/Tooltip/Tooltip.test.tsx +0 -819
- package/src/Tooltip/__tests__/Tooltip.a11y.chromium.spec.ts +0 -141
- package/src/Tooltip/__tests__/Tooltip.a11y.renders.tsx +0 -86
- package/src/Tooltip/__tests__/Tooltip.a11y.states.ts +0 -132
- package/src/Tooltip/__tests__/Tooltip.a11y.test.tsx +0 -126
- package/src/Tooltip/__tests__/TooltipFocusReturn.a11y.chromium.spec.ts +0 -130
- package/src/Tooltip/__tests__/TooltipHoverBridge.a11y.chromium.spec.ts +0 -75
- package/src/Tooltip/__tests__/TooltipTallContent.a11y.browser.spec.ts +0 -673
- package/src/Tooltip/__tests__/TooltipTallContentTracking.a11y.browser.spec.ts +0 -1162
- package/src/Tooltip/useTooltip.test.tsx +0 -483
- package/src/TopNav/TopNav.spec.md +0 -190
- package/src/TopNav/TopNav.test.tsx +0 -863
- package/src/TopNav/TopNavHeading.spec.md +0 -211
- package/src/TopNav/TopNavItem.spec.md +0 -189
- package/src/TopNav/TopNavMegaMenu.reduced-motion.source-build.test.mjs +0 -83
- package/src/TopNav/TopNavMegaMenu.spec.md +0 -190
- package/src/TopNav/TopNavMegaMenu.test.tsx +0 -1153
- package/src/TopNav/TopNavMegaMenuFeaturedCard.spec.md +0 -150
- package/src/TopNav/TopNavMegaMenuItem.spec.md +0 -155
- package/src/TopNav/TopNavMenu.spec.md +0 -202
- package/src/TopNav/TopNavMenu.test.tsx +0 -502
- package/src/TopNav/__tests__/TopNavMobileLongHeading.a11y.chromium.spec.ts +0 -75
- package/src/TreeList/TreeList.spec.md +0 -328
- package/src/TreeList/TreeList.test.tsx +0 -1737
- package/src/TreeList/__tests__/TreeList.a11y.chromium.spec.ts +0 -138
- package/src/TreeList/__tests__/TreeList.a11y.renders.tsx +0 -44
- package/src/TreeList/__tests__/TreeList.a11y.states.ts +0 -164
- package/src/TreeList/__tests__/TreeList.a11y.test.tsx +0 -138
- package/src/TreeList/__tests__/TreeListGuideAlignment.interaction.browser.spec.ts +0 -127
- package/src/TreeList/__tests__/TreeListRowNames.a11y.chromium.spec.ts +0 -83
- package/src/Typeahead/BaseTypeahead.emptyState.a11y.chromium.spec.ts +0 -138
- package/src/Typeahead/BaseTypeahead.spec.md +0 -270
- package/src/Typeahead/BaseTypeahead.test.tsx +0 -553
- package/src/Typeahead/Typeahead.fr10.test.tsx +0 -28
- package/src/Typeahead/Typeahead.spec.md +0 -257
- package/src/Typeahead/Typeahead.test.tsx +0 -2984
- package/src/Typeahead/TypeaheadItem.test.tsx +0 -134
- package/src/VStack/VStack.test.tsx +0 -128
- package/src/VisuallyHidden/VisuallyHidden.spec.md +0 -170
- package/src/VisuallyHidden/VisuallyHidden.test.tsx +0 -115
- package/src/__tests__/BusyOwnerAnnouncement.test.tsx +0 -853
- package/src/__tests__/CardPress.a11y.chromium.spec.ts +0 -353
- package/src/__tests__/DisabledTriggerFocus.a11y.chromium.spec.ts +0 -87
- package/src/__tests__/PressModality.a11y.chromium.spec.ts +0 -392
- package/src/__tests__/PressedState.a11y.chromium.spec.ts +0 -814
- package/src/__tests__/TestIcon.tsx +0 -26
- package/src/__tests__/babelPluginAddExtensions.test.ts +0 -190
- package/src/__tests__/fastRoleQueries.ts +0 -66
- package/src/__tests__/forcedColors.ts +0 -60
- package/src/__tests__/internalModulesNotExperimental.test.ts +0 -88
- package/src/__tests__/pressState.ts +0 -216
- package/src/__tests__/stubMatchMedia.test.ts +0 -79
- package/src/__tests__/stubMatchMedia.ts +0 -95
- package/src/__tests__/stylexDeclarations.ts +0 -51
- package/src/__tests__/unthemedLength.ts +0 -34
- package/src/docPropLiterals.test.ts +0 -964
- package/src/docPropReferences.test.ts +0 -178
- package/src/docs-script.test.mjs +0 -55
- package/src/gestures/__tests__/GestureHost.test.ts +0 -2136
- package/src/gestures/__tests__/LongPressGestureRecognizer.test.ts +0 -141
- package/src/gestures/__tests__/PanGestureRecognizer.test.ts +0 -327
- package/src/gestures/__tests__/PinchGestureRecognizer.test.ts +0 -74
- package/src/gestures/__tests__/PressTracker.test.ts +0 -275
- package/src/gestures/__tests__/ScreenEdgePanGestureRecognizer.test.ts +0 -498
- package/src/gestures/__tests__/SwipeGestureRecognizer.test.ts +0 -108
- package/src/gestures/__tests__/TapGestureRecognizer.test.ts +0 -154
- package/src/gestures/__tests__/VelocityTracker.streams.test.ts +0 -243
- package/src/gestures/__tests__/VelocityTracker.test.ts +0 -261
- package/src/gestures/__tests__/arena.test.ts +0 -864
- package/src/gestures/__tests__/arenaContinuous.test.ts +0 -207
- package/src/gestures/__tests__/arenaPinchSwipeEdge.test.ts +0 -193
- package/src/gestures/__tests__/arenaTapLongPress.test.ts +0 -211
- package/src/gestures/__tests__/browser/build-fixture.mjs +0 -46
- package/src/gestures/__tests__/browser/fixture.ts +0 -307
- package/src/gestures/__tests__/browser/gestures.interaction.browser.spec.ts +0 -1137
- package/src/gestures/__tests__/browserNegotiation.test.ts +0 -293
- package/src/gestures/__tests__/fixtures/pointer-streams/README.md +0 -82
- package/src/gestures/__tests__/fixtures/pointer-streams/android-chromium-fling.json +0 -130
- package/src/gestures/__tests__/fixtures/pointer-streams/android-chromium-slow.json +0 -860
- package/src/gestures/__tests__/fixtures/pointer-streams/android-chromium-stop-release.json +0 -357
- package/src/gestures/__tests__/fixtures/pointer-streams/android-firefox-fling.json +0 -66
- package/src/gestures/__tests__/fixtures/pointer-streams/android-firefox-slow.json +0 -268
- package/src/gestures/__tests__/fixtures/pointer-streams/android-firefox-stop-release.json +0 -128
- package/src/gestures/__tests__/fixtures/pointer-streams/capture.html +0 -123
- package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-mouse-fling.json +0 -64
- package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-mouse-slow.json +0 -268
- package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-mouse-stop-release.json +0 -124
- package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-pen-fling.json +0 -64
- package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-pen-slow.json +0 -268
- package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-pen-stop-release.json +0 -124
- package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-touch-fling.json +0 -84
- package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-touch-slow.json +0 -381
- package/src/gestures/__tests__/fixtures/pointer-streams/desktop-chromium-touch-stop-release.json +0 -171
- package/src/gestures/__tests__/fixtures/pointer-streams/ios-safari-fling.json +0 -45
- package/src/gestures/__tests__/fixtures/pointer-streams/ios-safari-slow.json +0 -101
- package/src/gestures/__tests__/fixtures/pointer-streams/ios-safari-stop-release.json +0 -130
- package/src/gestures/__tests__/haptics.test.ts +0 -187
- package/src/gestures/__tests__/harness.ts +0 -252
- package/src/gestures/__tests__/pressTrackerFactory.test.ts +0 -59
- package/src/gestures/__tests__/recognizerKind.test.ts +0 -78
- package/src/gestures/__tests__/touchActionRule.test.ts +0 -54
- package/src/gestures/__tests__/useGestureRecognizer.test.tsx +0 -570
- package/src/hooks/__tests__/MenuPressShadowRoot.a11y.chromium.spec.ts +0 -144
- package/src/hooks/__tests__/menuLinkClicks.ts +0 -71
- package/src/hooks/actionGroupTracker.exports.test.ts +0 -28
- package/src/hooks/actionGroupTracker.test.ts +0 -510
- package/src/hooks/computeOverflow.test.ts +0 -422
- package/src/hooks/deprecatedApis.public.test.ts +0 -33
- package/src/hooks/menuPressGesture.test.ts +0 -253
- package/src/hooks/scrollKeyboardDelegation.test.ts +0 -188
- package/src/hooks/scrollbarGutter.test.ts +0 -167
- package/src/hooks/useAnnounce.modal.test.tsx +0 -1291
- package/src/hooks/useAnnounce.replace.test.tsx +0 -516
- package/src/hooks/useAnnounce.test.tsx +0 -293
- package/src/hooks/useAnnounceRenderedText.adopters.test.tsx +0 -235
- package/src/hooks/useAutoMediaMode.test.ts +0 -109
- package/src/hooks/useBusyAnnouncement.adopters.test.tsx +0 -69
- package/src/hooks/useBusyAnnouncement.test.tsx +0 -112
- package/src/hooks/useClickableContainer.test.tsx +0 -236
- package/src/hooks/useClipboard.test.tsx +0 -151
- package/src/hooks/useContainerReveal.test.tsx +0 -163
- package/src/hooks/useDevWarning.test.tsx +0 -45
- package/src/hooks/useEntryAnimation.ssr.test.tsx +0 -143
- package/src/hooks/useFocusTrap.test.tsx +0 -635
- package/src/hooks/useFocusTrapEscapeShim.test.tsx +0 -166
- package/src/hooks/useGridFocus.test.tsx +0 -165
- package/src/hooks/useHotkeys.test.ts +0 -265
- package/src/hooks/useImageMode.test.ts +0 -133
- package/src/hooks/useInputContainer.test.tsx +0 -180
- package/src/hooks/useInputStatusIcon.test.tsx +0 -240
- package/src/hooks/useIsHydrating.test.tsx +0 -70
- package/src/hooks/useKeyboardHint.test.tsx +0 -92
- package/src/hooks/useListFocus.test.tsx +0 -664
- package/src/hooks/useLongPress.test.tsx +0 -152
- package/src/hooks/useMediaQuery.test.ts +0 -165
- package/src/hooks/useMenuHover.test.tsx +0 -536
- package/src/hooks/useMenuPress.test.tsx +0 -565
- package/src/hooks/useMergedRefs.test.tsx +0 -62
- package/src/hooks/useOverflow.test.ts +0 -504
- package/src/hooks/useRenamedProp.test.tsx +0 -95
- package/src/hooks/useScrollLock.test.ts +0 -248
- package/src/hooks/useScrollOverflow.test.tsx +0 -323
- package/src/hooks/useScrollableArea.test.tsx +0 -836
- package/src/hooks/useStreamingText.test.ts +0 -237
- package/src/hooks/useTreeFocus.test.tsx +0 -351
- package/src/hooks/useTypeahead.test.tsx +0 -351
- package/src/i18n/InternationalizationProvider.spec.md +0 -252
- package/src/i18n/__tests__/InternationalizationProvider.test.tsx +0 -128
- package/src/i18n/__tests__/e2e-pagination.test.tsx +0 -172
- package/src/i18n/__tests__/e2e-powersearch.test.tsx +0 -166
- package/src/i18n/__tests__/getLocaleDirection.test.ts +0 -40
- package/src/i18n/__tests__/resolve.test.ts +0 -325
- package/src/i18n/__tests__/useCollator.test.tsx +0 -115
- package/src/i18n/__tests__/useDirection.test.tsx +0 -66
- package/src/i18n/__tests__/useLocale.test.tsx +0 -52
- package/src/i18n/useTranslator.test.tsx +0 -267
- package/src/inputFontFloor.test.ts +0 -106
- package/src/internal/tokenizer-presentation.test.ts +0 -29
- package/src/internal/touch.test.ts +0 -44
- package/src/motion/__tests__/animatedLayout.interaction.browser.spec.ts +0 -1613
- package/src/motion/__tests__/animatedLayoutAdopters.interaction.browser.spec.ts +0 -217
- package/src/motion/__tests__/animatedLayoutBundle.ts +0 -17
- package/src/motion/__tests__/animator.interaction.browser.spec.ts +0 -843
- package/src/motion/__tests__/motionBundle.ts +0 -14
- package/src/motion/animatedLayout.boundary.test.ts +0 -155
- package/src/motion/animatedLayout.swap.test.ts +0 -827
- package/src/motion/animatedLayout.test.ts +0 -1154
- package/src/motion/animatedLayoutAdopters.test.tsx +0 -500
- package/src/motion/animator.test.ts +0 -3746
- package/src/motion/bezier.test.ts +0 -52
- package/src/motion/coast.test.ts +0 -99
- package/src/motion/decay.test.ts +0 -120
- package/src/motion/projection.test.ts +0 -107
- package/src/motion/reducedMotion.test.ts +0 -129
- package/src/motion/reducedMotionPlan.test.ts +0 -208
- package/src/motion/resolveMotion.test.ts +0 -123
- package/src/motion/resolveSnapPoint.test.ts +0 -189
- package/src/motion/roles.test.ts +0 -273
- package/src/motion/rubberBand.test.ts +0 -88
- package/src/motion/selectPage.test.ts +0 -31
- package/src/motion/spring.test.ts +0 -650
- package/src/motion/uikit/gestures.test.ts +0 -89
- package/src/motion/uikit/springRows.test.ts +0 -71
- package/src/motion/uikit/tableImports.test.ts +0 -293
- package/src/motion/uikit/uikit.test.ts +0 -364
- package/src/motion/uikit/values.test.ts +0 -121
- package/src/naming.test.ts +0 -44
- package/src/postinstall.test.mjs +0 -216
- package/src/reset.a11y.chromium.spec.ts +0 -238
- package/src/reset.test.ts +0 -205
- package/src/reset.until-found.a11y.browser.spec.ts +0 -76
- package/src/reset.until-found.test.ts +0 -32
- package/src/serverSafeComponents.test.ts +0 -675
- package/src/stylexValidation.source-build.test.mjs +0 -42
- package/src/tailwind-theme.test.ts +0 -153
- package/src/theme/MediaTheme.dom.test.tsx +0 -97
- package/src/theme/Theme.test.tsx +0 -337
- package/src/theme/__tests__/SpacingRootFontSize.a11y.chromium.spec.ts +0 -199
- package/src/theme/contrast.test.ts +0 -94
- package/src/theme/declarationBoundary.test.ts +0 -126
- package/src/theme/defineTheme.test.ts +0 -2028
- package/src/theme/derivedVarRegistry.test.ts +0 -592
- package/src/theme/expandColorScale.test.ts +0 -651
- package/src/theme/expandMotionScale.test.ts +0 -145
- package/src/theme/expandRadiusScale.test.ts +0 -59
- package/src/theme/expandTypeScale.test.ts +0 -351
- package/src/theme/extensibleAxes.test.ts +0 -432
- package/src/theme/generateThemeRules.test.ts +0 -1870
- package/src/theme/hct.test.ts +0 -93
- package/src/theme/onMediaTokens.test.ts +0 -431
- package/src/theme/publicThemeHelperContract.test.ts +0 -67
- package/src/theme/syntax/defineSyntaxTheme.diff.test.ts +0 -91
- package/src/theme/syntax/serverSafeSyntax.test.ts +0 -68
- package/src/theme/syntax/useSyntaxTheme.diff.test.tsx +0 -40
- package/src/theme/themeAdaptations.test.ts +0 -1795
- package/src/theme/themeMotion.test.ts +0 -620
- package/src/theme/themeRegistry.test.ts +0 -59
- package/src/theme/themingTargets.test.ts +0 -589
- package/src/theme/tokenValueCompat.test.ts +0 -204
- package/src/theme/tokens.test.ts +0 -441
- package/src/theme/useTheme.test.tsx +0 -322
- package/src/unicodePropertyEscapes.source-build.test.mjs +0 -69
- package/src/utils/chainEventHandlers.test.ts +0 -39
- package/src/utils/characters.test.ts +0 -141
- package/src/utils/color.test.ts +0 -233
- package/src/utils/composeEventHandlers.test.ts +0 -71
- package/src/utils/customPropertyArmLayering.test.ts +0 -131
- package/src/utils/dateParser.test.ts +0 -402
- package/src/utils/dateTypes.test.ts +0 -40
- package/src/utils/devWarning.test.ts +0 -56
- package/src/utils/edgeAutoscroll.test.ts +0 -192
- package/src/utils/focusReturn.test.ts +0 -119
- package/src/utils/getKey.test.ts +0 -25
- package/src/utils/getNodeText.test.ts +0 -24
- package/src/utils/hitArea.test.ts +0 -628
- package/src/utils/ime.test.ts +0 -32
- package/src/utils/inputAria.test.ts +0 -39
- package/src/utils/interactionModality.test.ts +0 -144
- package/src/utils/isApplePlatform.test.ts +0 -61
- package/src/utils/mergeProps.test.ts +0 -166
- package/src/utils/mergeRefs.test.ts +0 -48
- package/src/utils/parseStyleKey.test.ts +0 -56
- package/src/utils/plainDate.test.ts +0 -938
- package/src/utils/presentation.test.ts +0 -380
- package/src/utils/pressFeedback.test.ts +0 -1012
- package/src/utils/pressGesture.test.ts +0 -332
- package/src/utils/pressPaintPriority.test.ts +0 -80
- package/src/utils/pressPaintSource.test.ts +0 -65
- package/src/utils/pressableCoverage.test.ts +0 -192
- package/src/utils/primaryClick.test.ts +0 -38
- package/src/utils/safeUrl.test.ts +0 -101
- package/src/utils/sharedMutationObserver.test.ts +0 -106
- package/src/utils/sharedResizeObserver.test.ts +0 -283
- package/src/utils/themeProps.test.ts +0 -62
- package/src/utils/timeFormat.test.ts +0 -204
- package/src/utils/timeParser.test.ts +0 -295
- package/src/utils/touchPresentation.test.ts +0 -462
- package/src/utils/unicodeDigits.test.ts +0 -44
|
@@ -1,2697 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file NumberInput.test.tsx
|
|
5
|
-
* @input Uses vitest, @testing-library/react, NumberInput component
|
|
6
|
-
* @output Unit tests for NumberInput component behavior
|
|
7
|
-
* @position Testing; validates NumberInput.tsx implementation
|
|
8
|
-
*
|
|
9
|
-
* SYNC: When NumberInput.tsx changes, update tests to match new behavior
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
|
|
13
|
-
import {act, useState} from 'react';
|
|
14
|
-
import {render, screen, fireEvent, waitFor} from '@testing-library/react';
|
|
15
|
-
import userEvent from '@testing-library/user-event';
|
|
16
|
-
import * as stylex from '@stylexjs/stylex';
|
|
17
|
-
import {colorVars} from '../theme/tokens.stylex';
|
|
18
|
-
import {TestIcon} from '../__tests__/TestIcon';
|
|
19
|
-
import {InternationalizationProvider} from '../i18n';
|
|
20
|
-
import {registerIcons, resetIcons} from '../Icon';
|
|
21
|
-
import {InputGroup} from '../InputGroup';
|
|
22
|
-
import {NumberInput} from './NumberInput';
|
|
23
|
-
import {defineTheme} from '../theme/defineTheme';
|
|
24
|
-
import {generateThemeCSS} from '../theme/generateThemeRules';
|
|
25
|
-
import {__resetLiveRegionsForTest} from '../hooks/useAnnounce';
|
|
26
|
-
|
|
27
|
-
// jsdom cannot match `:focus-visible`: compare the ring's StyleX class hash.
|
|
28
|
-
const RING = stylex
|
|
29
|
-
.props(
|
|
30
|
-
stylex.create({
|
|
31
|
-
ring: {
|
|
32
|
-
boxShadow: {
|
|
33
|
-
default: null,
|
|
34
|
-
':has(> [aria-disabled="true"]:focus-visible)': `inset 0px 0px 0px 2px ${colorVars['--color-accent-muted']}`,
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
}).ring,
|
|
38
|
-
)
|
|
39
|
-
.className!.split(' ')
|
|
40
|
-
.pop()!;
|
|
41
|
-
|
|
42
|
-
// FieldStatus announces status messages through the persistent useAnnounce
|
|
43
|
-
// singletons; remove them between tests so role/aria-live queries in this
|
|
44
|
-
// file never match a leftover region.
|
|
45
|
-
afterEach(() => {
|
|
46
|
-
__resetLiveRegionsForTest();
|
|
47
|
-
resetIcons();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// Mock showPopover/hidePopover since jsdom does not implement them. Used by the
|
|
51
|
-
// disabledMessage tooltip.
|
|
52
|
-
beforeEach(() => {
|
|
53
|
-
HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
|
|
54
|
-
this.setAttribute('popover-open', '');
|
|
55
|
-
const event = new Event('toggle', {bubbles: false});
|
|
56
|
-
Object.defineProperty(event, 'newState', {value: 'open'});
|
|
57
|
-
this.dispatchEvent(event);
|
|
58
|
-
});
|
|
59
|
-
HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
|
|
60
|
-
this.removeAttribute('popover-open');
|
|
61
|
-
const event = new Event('toggle', {bubbles: false});
|
|
62
|
-
Object.defineProperty(event, 'newState', {value: 'closed'});
|
|
63
|
-
this.dispatchEvent(event);
|
|
64
|
-
});
|
|
65
|
-
const originalMatches = HTMLElement.prototype.matches;
|
|
66
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
-
(HTMLElement.prototype as any).matches = function (
|
|
68
|
-
selector: string,
|
|
69
|
-
): boolean {
|
|
70
|
-
if (selector === ':popover-open') {
|
|
71
|
-
return this.hasAttribute('popover-open');
|
|
72
|
-
}
|
|
73
|
-
return originalMatches.call(this, selector);
|
|
74
|
-
};
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
// jsdom popover content is in the DOM but may not be "visible" in the
|
|
78
|
-
// accessibility tree. Use hidden: true to find it.
|
|
79
|
-
const h = {hidden: true} as const;
|
|
80
|
-
|
|
81
|
-
describe('NumberInput', () => {
|
|
82
|
-
it('renders with label', () => {
|
|
83
|
-
render(<NumberInput label="Quantity" value={null} onChange={() => {}} />);
|
|
84
|
-
expect(screen.getByLabelText('Quantity')).toBeInTheDocument();
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('renders with placeholder', () => {
|
|
88
|
-
render(
|
|
89
|
-
<NumberInput
|
|
90
|
-
label="Quantity"
|
|
91
|
-
value={null}
|
|
92
|
-
onChange={() => {}}
|
|
93
|
-
placeholder="Enter number"
|
|
94
|
-
/>,
|
|
95
|
-
);
|
|
96
|
-
expect(screen.getByPlaceholderText('Enter number')).toBeInTheDocument();
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
it('displays the controlled value as editable text', () => {
|
|
100
|
-
render(<NumberInput label="Quantity" value={456} onChange={() => {}} />);
|
|
101
|
-
expect(screen.getByRole('spinbutton')).toHaveValue('456');
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('displays an empty string for a null value', () => {
|
|
105
|
-
render(<NumberInput label="Quantity" value={null} onChange={() => {}} />);
|
|
106
|
-
expect(screen.getByRole('spinbutton')).toHaveValue('');
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('displays an empty string for an undefined value', () => {
|
|
110
|
-
render(
|
|
111
|
-
<NumberInput label="Quantity" value={undefined} onChange={() => {}} />,
|
|
112
|
-
);
|
|
113
|
-
expect(screen.getByRole('spinbutton')).toHaveValue('');
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('forwards ref correctly', () => {
|
|
117
|
-
const ref = vi.fn();
|
|
118
|
-
render(
|
|
119
|
-
<NumberInput
|
|
120
|
-
ref={ref}
|
|
121
|
-
label="Quantity"
|
|
122
|
-
value={null}
|
|
123
|
-
onChange={() => {}}
|
|
124
|
-
/>,
|
|
125
|
-
);
|
|
126
|
-
expect(ref).toHaveBeenCalledWith(expect.any(HTMLInputElement));
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it('visually hides label when isLabelHidden is true', () => {
|
|
130
|
-
render(
|
|
131
|
-
<NumberInput
|
|
132
|
-
label="Quantity"
|
|
133
|
-
isLabelHidden
|
|
134
|
-
value={null}
|
|
135
|
-
onChange={() => {}}
|
|
136
|
-
/>,
|
|
137
|
-
);
|
|
138
|
-
const label = screen.getByText('Quantity');
|
|
139
|
-
expect(label).toBeInTheDocument();
|
|
140
|
-
expect(screen.getByLabelText('Quantity')).toBeInTheDocument();
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('shows label visually by default', () => {
|
|
144
|
-
render(<NumberInput label="Amount" value={null} onChange={() => {}} />);
|
|
145
|
-
const label = screen.getByText('Amount');
|
|
146
|
-
expect(label).toBeVisible();
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
it('sets aria-required when isRequired is true', () => {
|
|
150
|
-
render(
|
|
151
|
-
<NumberInput
|
|
152
|
-
label="Quantity"
|
|
153
|
-
isRequired
|
|
154
|
-
value={null}
|
|
155
|
-
onChange={() => {}}
|
|
156
|
-
/>,
|
|
157
|
-
);
|
|
158
|
-
expect(screen.getByRole('spinbutton')).toHaveAttribute(
|
|
159
|
-
'aria-required',
|
|
160
|
-
'true',
|
|
161
|
-
);
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it('does not set aria-required when isRequired is false', () => {
|
|
165
|
-
render(<NumberInput label="Quantity" value={null} onChange={() => {}} />);
|
|
166
|
-
expect(screen.getByRole('spinbutton')).not.toHaveAttribute('aria-required');
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it('exposes aria-disabled, not native disabled, when isDisabled is true (spec:AST-085)', () => {
|
|
170
|
-
render(
|
|
171
|
-
<NumberInput
|
|
172
|
-
label="Quantity"
|
|
173
|
-
isDisabled
|
|
174
|
-
value={null}
|
|
175
|
-
onChange={() => {}}
|
|
176
|
-
/>,
|
|
177
|
-
);
|
|
178
|
-
expect(screen.getByRole('spinbutton')).toHaveAttribute(
|
|
179
|
-
'aria-disabled',
|
|
180
|
-
'true',
|
|
181
|
-
);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it('keeps a disabled input in the tab order and rings it (spec:AST-085 FR1, FR6)', async () => {
|
|
185
|
-
const user = userEvent.setup();
|
|
186
|
-
render(
|
|
187
|
-
<>
|
|
188
|
-
<NumberInput label="First" value={1} onChange={() => {}} />
|
|
189
|
-
<NumberInput label="Second" value={2} onChange={() => {}} isDisabled />
|
|
190
|
-
</>,
|
|
191
|
-
);
|
|
192
|
-
await user.tab();
|
|
193
|
-
await user.tab();
|
|
194
|
-
const input = screen.getByRole('spinbutton', {name: 'Second'});
|
|
195
|
-
expect(input).toHaveFocus();
|
|
196
|
-
expect(input.parentElement).toHaveClass(RING);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
it('runs no caller handler, steps nothing and submits no form while disabled (spec:AST-085 FR2)', async () => {
|
|
200
|
-
const user = userEvent.setup();
|
|
201
|
-
const handlers = {
|
|
202
|
-
onChange: vi.fn(),
|
|
203
|
-
onEnter: vi.fn(),
|
|
204
|
-
onKeyDown: vi.fn(),
|
|
205
|
-
onPaste: vi.fn(),
|
|
206
|
-
};
|
|
207
|
-
const onSubmit = vi.fn((e: React.FormEvent) => e.preventDefault());
|
|
208
|
-
render(
|
|
209
|
-
<form onSubmit={onSubmit}>
|
|
210
|
-
<NumberInput
|
|
211
|
-
label="Quantity"
|
|
212
|
-
value={5}
|
|
213
|
-
isDisabled
|
|
214
|
-
hasNumberSteppers
|
|
215
|
-
{...handlers}
|
|
216
|
-
/>
|
|
217
|
-
</form>,
|
|
218
|
-
);
|
|
219
|
-
await user.click(screen.getByRole('spinbutton'));
|
|
220
|
-
await user.keyboard('{ArrowUp}{ArrowDown}{Enter}');
|
|
221
|
-
await user.paste('9');
|
|
222
|
-
await user.click(screen.getByRole('button', {name: 'Increment Quantity'}));
|
|
223
|
-
for (const handler of [...Object.values(handlers), onSubmit]) {
|
|
224
|
-
expect(handler).not.toHaveBeenCalled();
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
it('commits nothing when a field disabled mid-entry loses focus (spec:AST-085 FR2)', async () => {
|
|
229
|
-
const user = userEvent.setup();
|
|
230
|
-
const onChange = vi.fn();
|
|
231
|
-
const field = (isDisabled: boolean) => (
|
|
232
|
-
<NumberInput
|
|
233
|
-
label="Quantity"
|
|
234
|
-
value={5}
|
|
235
|
-
onChange={onChange}
|
|
236
|
-
isDisabled={isDisabled}
|
|
237
|
-
/>
|
|
238
|
-
);
|
|
239
|
-
const {rerender} = render(field(false));
|
|
240
|
-
const input = screen.getByRole('spinbutton');
|
|
241
|
-
await user.clear(input);
|
|
242
|
-
await user.type(input, '8');
|
|
243
|
-
onChange.mockClear();
|
|
244
|
-
rerender(field(true));
|
|
245
|
-
await user.tab();
|
|
246
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
247
|
-
expect(input).toHaveValue('5');
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('does not fire onChange when disabled', async () => {
|
|
251
|
-
const user = userEvent.setup();
|
|
252
|
-
const handleChange = vi.fn();
|
|
253
|
-
render(
|
|
254
|
-
<NumberInput
|
|
255
|
-
label="Quantity"
|
|
256
|
-
isDisabled
|
|
257
|
-
value={null}
|
|
258
|
-
onChange={handleChange}
|
|
259
|
-
/>,
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
const input = screen.getByRole('spinbutton');
|
|
263
|
-
await user.type(input, '123');
|
|
264
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('is not disabled by default', () => {
|
|
268
|
-
render(<NumberInput label="Quantity" value={null} onChange={() => {}} />);
|
|
269
|
-
expect(screen.getByRole('spinbutton')).not.toBeDisabled();
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it('renders with startIcon', () => {
|
|
273
|
-
render(
|
|
274
|
-
<NumberInput
|
|
275
|
-
label="Count"
|
|
276
|
-
value={null}
|
|
277
|
-
onChange={() => {}}
|
|
278
|
-
startIcon={TestIcon}
|
|
279
|
-
/>,
|
|
280
|
-
);
|
|
281
|
-
expect(screen.getByRole('spinbutton')).toBeInTheDocument();
|
|
282
|
-
const svg = document.querySelector('svg');
|
|
283
|
-
expect(svg).toBeInTheDocument();
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
it('renders without icon wrapper when startIcon is not provided', () => {
|
|
287
|
-
const {container} = render(
|
|
288
|
-
<NumberInput label="Quantity" value={null} onChange={() => {}} />,
|
|
289
|
-
);
|
|
290
|
-
expect(container.querySelector('svg')).not.toBeInTheDocument();
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
describe('text-backed spinbutton attributes', () => {
|
|
294
|
-
it('uses a text input with decimal input mode by default', () => {
|
|
295
|
-
render(<NumberInput label="Price" value={5} onChange={() => {}} />);
|
|
296
|
-
const input = screen.getByRole('spinbutton');
|
|
297
|
-
expect(input).toHaveAttribute('type', 'text');
|
|
298
|
-
expect(input).toHaveAttribute('inputmode', 'decimal');
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
it('uses numeric input mode for integer-only values', () => {
|
|
302
|
-
render(
|
|
303
|
-
<NumberInput
|
|
304
|
-
label="Count"
|
|
305
|
-
value={5}
|
|
306
|
-
onChange={() => {}}
|
|
307
|
-
isIntegerOnly
|
|
308
|
-
/>,
|
|
309
|
-
);
|
|
310
|
-
expect(screen.getByRole('spinbutton')).toHaveAttribute(
|
|
311
|
-
'inputmode',
|
|
312
|
-
'numeric',
|
|
313
|
-
);
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
it('exposes the minimum through spinbutton ARIA', () => {
|
|
317
|
-
render(
|
|
318
|
-
<NumberInput label="Age" value={null} onChange={() => {}} min={0} />,
|
|
319
|
-
);
|
|
320
|
-
expect(screen.getByRole('spinbutton')).toHaveAttribute(
|
|
321
|
-
'aria-valuemin',
|
|
322
|
-
'0',
|
|
323
|
-
);
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
it('exposes the maximum through spinbutton ARIA', () => {
|
|
327
|
-
render(
|
|
328
|
-
<NumberInput label="Age" value={null} onChange={() => {}} max={120} />,
|
|
329
|
-
);
|
|
330
|
-
expect(screen.getByRole('spinbutton')).toHaveAttribute(
|
|
331
|
-
'aria-valuemax',
|
|
332
|
-
'120',
|
|
333
|
-
);
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
it('exposes the current value through spinbutton ARIA', () => {
|
|
337
|
-
render(<NumberInput label="Age" value={42} onChange={() => {}} />);
|
|
338
|
-
expect(screen.getByRole('spinbutton')).toHaveAttribute(
|
|
339
|
-
'aria-valuenow',
|
|
340
|
-
'42',
|
|
341
|
-
);
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
describe('formatted display values', () => {
|
|
346
|
-
it('shows the formatted value at rest and exposes it to assistive technology', () => {
|
|
347
|
-
render(
|
|
348
|
-
<NumberInput
|
|
349
|
-
label="Revenue"
|
|
350
|
-
value={1234}
|
|
351
|
-
onChange={() => {}}
|
|
352
|
-
formatValue={number => `$${number.toLocaleString('en-US')}`}
|
|
353
|
-
/>,
|
|
354
|
-
);
|
|
355
|
-
const input = screen.getByRole('spinbutton');
|
|
356
|
-
expect(input).toHaveValue('$1,234');
|
|
357
|
-
expect(input).toHaveAttribute('aria-valuetext', '$1,234');
|
|
358
|
-
expect(input).toHaveAttribute('aria-valuenow', '1234');
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
it('keeps the whole text selected when focus arrives with it selected, as Tab does', () => {
|
|
362
|
-
render(
|
|
363
|
-
<NumberInput
|
|
364
|
-
label="Amount"
|
|
365
|
-
value={1500000}
|
|
366
|
-
onChange={() => {}}
|
|
367
|
-
formatValue={number => number.toLocaleString('en-US')}
|
|
368
|
-
/>,
|
|
369
|
-
);
|
|
370
|
-
const input = screen.getByRole<HTMLInputElement>('spinbutton');
|
|
371
|
-
expect(input).toHaveValue('1,500,000');
|
|
372
|
-
|
|
373
|
-
// Tab into a text field selects its text before the focus event.
|
|
374
|
-
input.focus();
|
|
375
|
-
input.setSelectionRange(0, input.value.length);
|
|
376
|
-
fireEvent.focus(input);
|
|
377
|
-
|
|
378
|
-
// The editable text replaces the formatted text, and stays selected.
|
|
379
|
-
expect(input).toHaveValue('1500000');
|
|
380
|
-
expect(input.selectionStart).toBe(0);
|
|
381
|
-
expect(input.selectionEnd).toBe('1500000'.length);
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
it('does not swallow keystrokes when focus swaps no text', async () => {
|
|
385
|
-
const user = userEvent.setup();
|
|
386
|
-
function Controlled() {
|
|
387
|
-
const [value, setValue] = useState<number | null>(1);
|
|
388
|
-
return <NumberInput label="Amount" value={value} onChange={setValue} />;
|
|
389
|
-
}
|
|
390
|
-
render(
|
|
391
|
-
<>
|
|
392
|
-
<button type="button">Before</button>
|
|
393
|
-
<Controlled />
|
|
394
|
-
</>,
|
|
395
|
-
);
|
|
396
|
-
const input = screen.getByRole<HTMLInputElement>('spinbutton');
|
|
397
|
-
// Tab into the field with its text selected, as a browser does. The
|
|
398
|
-
// text is the same at rest and focused, so nothing is swapped.
|
|
399
|
-
input.focus();
|
|
400
|
-
input.setSelectionRange(0, input.value.length);
|
|
401
|
-
fireEvent.focus(input);
|
|
402
|
-
await user.keyboard('75');
|
|
403
|
-
expect(input).toHaveValue('75');
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
it('leaves the caret where a click put it', () => {
|
|
407
|
-
render(
|
|
408
|
-
<NumberInput
|
|
409
|
-
label="Amount"
|
|
410
|
-
value={1500000}
|
|
411
|
-
onChange={() => {}}
|
|
412
|
-
formatValue={number => number.toLocaleString('en-US')}
|
|
413
|
-
/>,
|
|
414
|
-
);
|
|
415
|
-
const input = screen.getByRole<HTMLInputElement>('spinbutton');
|
|
416
|
-
input.focus();
|
|
417
|
-
input.setSelectionRange(3, 3);
|
|
418
|
-
fireEvent.focus(input);
|
|
419
|
-
expect(input.selectionStart).toBe(input.selectionEnd);
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
it('keeps ARIA value text on the committed value while an edit is pending', () => {
|
|
423
|
-
function ControlledNumberInput() {
|
|
424
|
-
const [controlledValue, setControlledValue] = useState(1234);
|
|
425
|
-
return (
|
|
426
|
-
<NumberInput
|
|
427
|
-
label="Revenue"
|
|
428
|
-
value={controlledValue}
|
|
429
|
-
onChange={setControlledValue}
|
|
430
|
-
formatValue={number => `$${number.toLocaleString('en-US')}`}
|
|
431
|
-
/>
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
render(<ControlledNumberInput />);
|
|
435
|
-
const input = screen.getByRole('spinbutton');
|
|
436
|
-
fireEvent.focus(input);
|
|
437
|
-
fireEvent.input(input, {target: {value: '4200'}});
|
|
438
|
-
|
|
439
|
-
expect(input).toHaveAttribute('aria-valuenow', '1234');
|
|
440
|
-
expect(input).toHaveAttribute('aria-valuetext', '$1,234');
|
|
441
|
-
|
|
442
|
-
fireEvent.blur(input);
|
|
443
|
-
expect(input).toHaveAttribute('aria-valuenow', '4200');
|
|
444
|
-
expect(input).toHaveAttribute('aria-valuetext', '$4,200');
|
|
445
|
-
});
|
|
446
|
-
|
|
447
|
-
it('shows the raw numeric value while focused and restores formatting on blur', () => {
|
|
448
|
-
render(
|
|
449
|
-
<NumberInput
|
|
450
|
-
label="Revenue"
|
|
451
|
-
value={1234}
|
|
452
|
-
onChange={() => {}}
|
|
453
|
-
formatValue={number => `$${number.toLocaleString('en-US')}`}
|
|
454
|
-
/>,
|
|
455
|
-
);
|
|
456
|
-
const input = screen.getByRole('spinbutton');
|
|
457
|
-
|
|
458
|
-
fireEvent.focus(input);
|
|
459
|
-
expect(input).toHaveValue('1234');
|
|
460
|
-
|
|
461
|
-
fireEvent.blur(input);
|
|
462
|
-
expect(input).toHaveValue('$1,234');
|
|
463
|
-
});
|
|
464
|
-
|
|
465
|
-
it('preserves invalid pending text while focused, then restores the formatted true value', () => {
|
|
466
|
-
const onChange = vi.fn();
|
|
467
|
-
render(
|
|
468
|
-
<NumberInput
|
|
469
|
-
label="Quantity"
|
|
470
|
-
value={3}
|
|
471
|
-
onChange={onChange}
|
|
472
|
-
isIntegerOnly
|
|
473
|
-
formatValue={number => `${number} items`}
|
|
474
|
-
/>,
|
|
475
|
-
);
|
|
476
|
-
const input = screen.getByRole('spinbutton');
|
|
477
|
-
|
|
478
|
-
fireEvent.focus(input);
|
|
479
|
-
fireEvent.change(input, {target: {value: '3.5'}});
|
|
480
|
-
expect(input).toHaveValue('3.5');
|
|
481
|
-
expect(input).toHaveAttribute('aria-invalid', 'true');
|
|
482
|
-
expect(onChange).not.toHaveBeenCalledWith(3.5);
|
|
483
|
-
|
|
484
|
-
fireEvent.blur(input);
|
|
485
|
-
expect(input).toHaveValue('3 items');
|
|
486
|
-
});
|
|
487
|
-
|
|
488
|
-
it('does not call the formatter for an empty value', () => {
|
|
489
|
-
const formatValue = vi.fn((number: number) => String(number));
|
|
490
|
-
render(
|
|
491
|
-
<NumberInput
|
|
492
|
-
label="Quantity"
|
|
493
|
-
value={null}
|
|
494
|
-
onChange={() => {}}
|
|
495
|
-
formatValue={formatValue}
|
|
496
|
-
/>,
|
|
497
|
-
);
|
|
498
|
-
expect(screen.getByRole('spinbutton')).toHaveValue('');
|
|
499
|
-
expect(formatValue).not.toHaveBeenCalled();
|
|
500
|
-
});
|
|
501
|
-
});
|
|
502
|
-
|
|
503
|
-
describe('onChange validation', () => {
|
|
504
|
-
it('commits a valid number on blur', async () => {
|
|
505
|
-
const user = userEvent.setup();
|
|
506
|
-
const handleChange = vi.fn();
|
|
507
|
-
render(
|
|
508
|
-
<NumberInput label="Quantity" value={null} onChange={handleChange} />,
|
|
509
|
-
);
|
|
510
|
-
|
|
511
|
-
const input = screen.getByRole('spinbutton');
|
|
512
|
-
await user.click(input);
|
|
513
|
-
await user.type(input, '42');
|
|
514
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
515
|
-
|
|
516
|
-
await user.tab();
|
|
517
|
-
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
518
|
-
expect(handleChange).toHaveBeenCalledWith(42);
|
|
519
|
-
});
|
|
520
|
-
|
|
521
|
-
it('does not call onChange when value exceeds max', async () => {
|
|
522
|
-
const user = userEvent.setup();
|
|
523
|
-
const handleChange = vi.fn();
|
|
524
|
-
render(
|
|
525
|
-
<NumberInput
|
|
526
|
-
label="Rating"
|
|
527
|
-
value={null}
|
|
528
|
-
onChange={handleChange}
|
|
529
|
-
max={5}
|
|
530
|
-
/>,
|
|
531
|
-
);
|
|
532
|
-
|
|
533
|
-
const input = screen.getByRole('spinbutton');
|
|
534
|
-
await user.click(input);
|
|
535
|
-
await user.type(input, '10');
|
|
536
|
-
|
|
537
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
it('does not call onChange when value is below min', async () => {
|
|
541
|
-
const user = userEvent.setup();
|
|
542
|
-
const handleChange = vi.fn();
|
|
543
|
-
render(
|
|
544
|
-
<NumberInput
|
|
545
|
-
label="Age"
|
|
546
|
-
value={null}
|
|
547
|
-
onChange={handleChange}
|
|
548
|
-
min={0}
|
|
549
|
-
/>,
|
|
550
|
-
);
|
|
551
|
-
|
|
552
|
-
const input = screen.getByRole('spinbutton');
|
|
553
|
-
await user.click(input);
|
|
554
|
-
await user.type(input, '-5');
|
|
555
|
-
|
|
556
|
-
// Neither -5 nor any partial input is valid with min=0
|
|
557
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
558
|
-
});
|
|
559
|
-
|
|
560
|
-
it('does not call onChange for decimal when isIntegerOnly is true', async () => {
|
|
561
|
-
const user = userEvent.setup();
|
|
562
|
-
const handleChange = vi.fn();
|
|
563
|
-
render(
|
|
564
|
-
<NumberInput
|
|
565
|
-
label="Count"
|
|
566
|
-
value={null}
|
|
567
|
-
onChange={handleChange}
|
|
568
|
-
isIntegerOnly
|
|
569
|
-
/>,
|
|
570
|
-
);
|
|
571
|
-
|
|
572
|
-
const input = screen.getByRole('spinbutton');
|
|
573
|
-
await user.click(input);
|
|
574
|
-
await user.type(input, '3.5');
|
|
575
|
-
|
|
576
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
it('calls onChange for decimal when isIntegerOnly is false', async () => {
|
|
580
|
-
const user = userEvent.setup();
|
|
581
|
-
const handleChange = vi.fn();
|
|
582
|
-
render(
|
|
583
|
-
<NumberInput label="Price" value={null} onChange={handleChange} />,
|
|
584
|
-
);
|
|
585
|
-
|
|
586
|
-
const input = screen.getByRole('spinbutton');
|
|
587
|
-
await user.click(input);
|
|
588
|
-
await user.type(input, '3.5');
|
|
589
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
590
|
-
|
|
591
|
-
await user.tab();
|
|
592
|
-
expect(handleChange).toHaveBeenCalledWith(3.5);
|
|
593
|
-
});
|
|
594
|
-
});
|
|
595
|
-
|
|
596
|
-
describe('invalid draft commit policy', () => {
|
|
597
|
-
function ControlledNumberInput({
|
|
598
|
-
initialValue = 7,
|
|
599
|
-
locale = 'en-US',
|
|
600
|
-
}: {
|
|
601
|
-
initialValue?: number | null;
|
|
602
|
-
locale?: 'en-US' | 'de-DE';
|
|
603
|
-
}) {
|
|
604
|
-
const [controlledValue, setControlledValue] = useState<number | null>(
|
|
605
|
-
initialValue,
|
|
606
|
-
);
|
|
607
|
-
return (
|
|
608
|
-
<InternationalizationProvider locale={locale}>
|
|
609
|
-
<NumberInput
|
|
610
|
-
label="Quantity"
|
|
611
|
-
value={controlledValue}
|
|
612
|
-
onChange={setControlledValue}
|
|
613
|
-
/>
|
|
614
|
-
<output data-testid="committed">{String(controlledValue)}</output>
|
|
615
|
-
</InternationalizationProvider>
|
|
616
|
-
);
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
async function exerciseInvalidDraft(
|
|
620
|
-
entry: 'typing' | 'input',
|
|
621
|
-
commit: 'blur' | 'Enter',
|
|
622
|
-
) {
|
|
623
|
-
const user = userEvent.setup();
|
|
624
|
-
render(<ControlledNumberInput />);
|
|
625
|
-
const input = screen.getByRole('spinbutton');
|
|
626
|
-
await user.click(input);
|
|
627
|
-
await user.clear(input);
|
|
628
|
-
if (entry === 'typing') {
|
|
629
|
-
await user.type(input, '1·234·567');
|
|
630
|
-
} else {
|
|
631
|
-
fireEvent.input(input, {target: {value: '1·234·567'}});
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
expect(input).toHaveValue('1·234·567');
|
|
635
|
-
expect(input).toHaveAttribute('aria-invalid', 'true');
|
|
636
|
-
expect(screen.getByTestId('committed')).toHaveTextContent('7');
|
|
637
|
-
|
|
638
|
-
if (commit === 'blur') {
|
|
639
|
-
await user.tab();
|
|
640
|
-
expect(input).toHaveValue('7');
|
|
641
|
-
expect(input).not.toHaveAttribute('aria-invalid');
|
|
642
|
-
} else {
|
|
643
|
-
await user.keyboard('{Enter}');
|
|
644
|
-
expect(input).toHaveValue('1·234·567');
|
|
645
|
-
expect(input).toHaveAttribute('aria-invalid', 'true');
|
|
646
|
-
}
|
|
647
|
-
expect(screen.getByTestId('committed')).toHaveTextContent('7');
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
it('rejects a sequentially typed invalid draft on blur', async () => {
|
|
651
|
-
await exerciseInvalidDraft('typing', 'blur');
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
it('rejects a one-shot invalid draft on blur', async () => {
|
|
655
|
-
await exerciseInvalidDraft('input', 'blur');
|
|
656
|
-
});
|
|
657
|
-
|
|
658
|
-
it('rejects a sequentially typed invalid draft on Enter', async () => {
|
|
659
|
-
await exerciseInvalidDraft('typing', 'Enter');
|
|
660
|
-
});
|
|
661
|
-
|
|
662
|
-
it('rejects a one-shot invalid draft on Enter', async () => {
|
|
663
|
-
await exerciseInvalidDraft('input', 'Enter');
|
|
664
|
-
});
|
|
665
|
-
|
|
666
|
-
it('commits a valid localized grouped number as one edit', async () => {
|
|
667
|
-
const user = userEvent.setup();
|
|
668
|
-
render(<ControlledNumberInput locale="de-DE" />);
|
|
669
|
-
const input = screen.getByRole('spinbutton');
|
|
670
|
-
await user.click(input);
|
|
671
|
-
await user.clear(input);
|
|
672
|
-
await user.type(input, '1.234.567');
|
|
673
|
-
|
|
674
|
-
expect(screen.getByTestId('committed')).toHaveTextContent('7');
|
|
675
|
-
await user.tab();
|
|
676
|
-
expect(screen.getByTestId('committed')).toHaveTextContent('1234567');
|
|
677
|
-
expect(input).toHaveValue('1234567');
|
|
678
|
-
});
|
|
679
|
-
|
|
680
|
-
it('keeps a controlled update behind an invalid focused draft', () => {
|
|
681
|
-
const onChange = vi.fn();
|
|
682
|
-
const {rerender} = render(
|
|
683
|
-
<NumberInput label="Quantity" value={7} onChange={onChange} />,
|
|
684
|
-
);
|
|
685
|
-
const input = screen.getByRole('spinbutton');
|
|
686
|
-
fireEvent.focus(input);
|
|
687
|
-
fireEvent.input(input, {target: {value: '1·234·567'}});
|
|
688
|
-
|
|
689
|
-
rerender(<NumberInput label="Quantity" value={9} onChange={onChange} />);
|
|
690
|
-
expect(input).toHaveValue('1·234·567');
|
|
691
|
-
fireEvent.blur(input);
|
|
692
|
-
|
|
693
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
694
|
-
expect(input).toHaveValue('9');
|
|
695
|
-
});
|
|
696
|
-
|
|
697
|
-
it('waits for IME composition to finish before committing', () => {
|
|
698
|
-
const onChange = vi.fn();
|
|
699
|
-
render(<NumberInput label="Quantity" value={7} onChange={onChange} />);
|
|
700
|
-
const input = screen.getByRole('spinbutton');
|
|
701
|
-
fireEvent.focus(input);
|
|
702
|
-
fireEvent.input(input, {target: {value: '42'}});
|
|
703
|
-
fireEvent.keyDown(input, {key: 'Enter', isComposing: true});
|
|
704
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
705
|
-
|
|
706
|
-
fireEvent.keyDown(input, {key: 'Enter'});
|
|
707
|
-
expect(onChange).toHaveBeenCalledTimes(1);
|
|
708
|
-
expect(onChange).toHaveBeenCalledWith(42);
|
|
709
|
-
});
|
|
710
|
-
|
|
711
|
-
it('steps from the committed value when the draft is invalid', () => {
|
|
712
|
-
const onChange = vi.fn();
|
|
713
|
-
render(<NumberInput label="Quantity" value={7} onChange={onChange} />);
|
|
714
|
-
const input = screen.getByRole('spinbutton');
|
|
715
|
-
fireEvent.focus(input);
|
|
716
|
-
fireEvent.input(input, {target: {value: '1·234·567'}});
|
|
717
|
-
fireEvent.keyDown(input, {key: 'ArrowUp'});
|
|
718
|
-
|
|
719
|
-
expect(onChange).toHaveBeenCalledTimes(1);
|
|
720
|
-
expect(onChange).toHaveBeenCalledWith(8);
|
|
721
|
-
expect(input).toHaveValue('7');
|
|
722
|
-
});
|
|
723
|
-
});
|
|
724
|
-
|
|
725
|
-
describe('units prop', () => {
|
|
726
|
-
it('renders units text when provided', () => {
|
|
727
|
-
render(
|
|
728
|
-
<NumberInput
|
|
729
|
-
label="Discount"
|
|
730
|
-
value={10}
|
|
731
|
-
onChange={() => {}}
|
|
732
|
-
units="%"
|
|
733
|
-
/>,
|
|
734
|
-
);
|
|
735
|
-
expect(screen.getByText('%')).toBeInTheDocument();
|
|
736
|
-
});
|
|
737
|
-
|
|
738
|
-
it('does not render units when not provided', () => {
|
|
739
|
-
render(<NumberInput label="Amount" value={100} onChange={() => {}} />);
|
|
740
|
-
expect(screen.queryByText('%')).not.toBeInTheDocument();
|
|
741
|
-
expect(screen.queryByText('GB')).not.toBeInTheDocument();
|
|
742
|
-
});
|
|
743
|
-
|
|
744
|
-
it('includes the units text in the accessible description (WCAG 1.3.1)', () => {
|
|
745
|
-
render(
|
|
746
|
-
<NumberInput
|
|
747
|
-
label="Storage"
|
|
748
|
-
value={50}
|
|
749
|
-
onChange={() => {}}
|
|
750
|
-
units="GB"
|
|
751
|
-
/>,
|
|
752
|
-
);
|
|
753
|
-
expect(screen.getByRole('spinbutton')).toHaveAccessibleDescription(/GB/);
|
|
754
|
-
});
|
|
755
|
-
|
|
756
|
-
it('combines units with the description in the accessible description', () => {
|
|
757
|
-
render(
|
|
758
|
-
<NumberInput
|
|
759
|
-
label="Discount"
|
|
760
|
-
value={10}
|
|
761
|
-
onChange={() => {}}
|
|
762
|
-
description="Applied at checkout"
|
|
763
|
-
units="%"
|
|
764
|
-
/>,
|
|
765
|
-
);
|
|
766
|
-
const input = screen.getByRole('spinbutton');
|
|
767
|
-
expect(input).toHaveAccessibleDescription(/Applied at checkout/);
|
|
768
|
-
expect(input).toHaveAccessibleDescription(/%/);
|
|
769
|
-
});
|
|
770
|
-
});
|
|
771
|
-
|
|
772
|
-
describe('event callbacks', () => {
|
|
773
|
-
it('calls onFocus when input receives focus', async () => {
|
|
774
|
-
const user = userEvent.setup();
|
|
775
|
-
const handleFocus = vi.fn();
|
|
776
|
-
render(
|
|
777
|
-
<NumberInput
|
|
778
|
-
label="Quantity"
|
|
779
|
-
value={null}
|
|
780
|
-
onChange={() => {}}
|
|
781
|
-
onFocus={handleFocus}
|
|
782
|
-
/>,
|
|
783
|
-
);
|
|
784
|
-
|
|
785
|
-
await user.click(screen.getByRole('spinbutton'));
|
|
786
|
-
expect(handleFocus).toHaveBeenCalledTimes(1);
|
|
787
|
-
});
|
|
788
|
-
|
|
789
|
-
it('calls onBlur when input loses focus', async () => {
|
|
790
|
-
const user = userEvent.setup();
|
|
791
|
-
const handleBlur = vi.fn();
|
|
792
|
-
render(
|
|
793
|
-
<NumberInput
|
|
794
|
-
label="Quantity"
|
|
795
|
-
value={null}
|
|
796
|
-
onChange={() => {}}
|
|
797
|
-
onBlur={handleBlur}
|
|
798
|
-
/>,
|
|
799
|
-
);
|
|
800
|
-
|
|
801
|
-
const input = screen.getByRole('spinbutton');
|
|
802
|
-
await user.click(input);
|
|
803
|
-
await user.tab();
|
|
804
|
-
expect(handleBlur).toHaveBeenCalledTimes(1);
|
|
805
|
-
});
|
|
806
|
-
|
|
807
|
-
it('calls onEnter when Enter key is pressed', async () => {
|
|
808
|
-
const user = userEvent.setup();
|
|
809
|
-
const handleEnter = vi.fn();
|
|
810
|
-
render(
|
|
811
|
-
<NumberInput
|
|
812
|
-
label="Quantity"
|
|
813
|
-
value={null}
|
|
814
|
-
onChange={() => {}}
|
|
815
|
-
onEnter={handleEnter}
|
|
816
|
-
/>,
|
|
817
|
-
);
|
|
818
|
-
|
|
819
|
-
const input = screen.getByRole('spinbutton');
|
|
820
|
-
await user.click(input);
|
|
821
|
-
await user.keyboard('{Enter}');
|
|
822
|
-
expect(handleEnter).toHaveBeenCalledTimes(1);
|
|
823
|
-
});
|
|
824
|
-
|
|
825
|
-
it('commits valid value on Enter key', async () => {
|
|
826
|
-
const user = userEvent.setup();
|
|
827
|
-
const handleChange = vi.fn();
|
|
828
|
-
const handleEnter = vi.fn();
|
|
829
|
-
render(
|
|
830
|
-
<NumberInput
|
|
831
|
-
label="Quantity"
|
|
832
|
-
value={null}
|
|
833
|
-
onChange={handleChange}
|
|
834
|
-
onEnter={handleEnter}
|
|
835
|
-
/>,
|
|
836
|
-
);
|
|
837
|
-
|
|
838
|
-
const input = screen.getByRole('spinbutton');
|
|
839
|
-
await user.click(input);
|
|
840
|
-
await user.type(input, '42');
|
|
841
|
-
handleChange.mockClear();
|
|
842
|
-
await user.keyboard('{Enter}');
|
|
843
|
-
|
|
844
|
-
expect(handleEnter).toHaveBeenCalledTimes(1);
|
|
845
|
-
});
|
|
846
|
-
});
|
|
847
|
-
|
|
848
|
-
describe('range clamping on commit', () => {
|
|
849
|
-
it('commits an over-max entry at max on blur', async () => {
|
|
850
|
-
const user = userEvent.setup();
|
|
851
|
-
const handleChange = vi.fn();
|
|
852
|
-
render(
|
|
853
|
-
<NumberInput
|
|
854
|
-
label="Page"
|
|
855
|
-
value={null}
|
|
856
|
-
onChange={handleChange}
|
|
857
|
-
min={1}
|
|
858
|
-
max={2}
|
|
859
|
-
isIntegerOnly
|
|
860
|
-
/>,
|
|
861
|
-
);
|
|
862
|
-
|
|
863
|
-
const input = screen.getByRole('spinbutton');
|
|
864
|
-
await user.click(input);
|
|
865
|
-
await user.type(input, '100');
|
|
866
|
-
handleChange.mockClear();
|
|
867
|
-
await user.tab();
|
|
868
|
-
|
|
869
|
-
expect(handleChange).toHaveBeenCalledWith(2);
|
|
870
|
-
});
|
|
871
|
-
|
|
872
|
-
it('commits an over-max entry at max on Enter', async () => {
|
|
873
|
-
const user = userEvent.setup();
|
|
874
|
-
const handleChange = vi.fn();
|
|
875
|
-
render(
|
|
876
|
-
<NumberInput
|
|
877
|
-
label="Rating"
|
|
878
|
-
value={null}
|
|
879
|
-
onChange={handleChange}
|
|
880
|
-
max={5}
|
|
881
|
-
/>,
|
|
882
|
-
);
|
|
883
|
-
|
|
884
|
-
const input = screen.getByRole('spinbutton');
|
|
885
|
-
await user.click(input);
|
|
886
|
-
await user.type(input, '10');
|
|
887
|
-
handleChange.mockClear();
|
|
888
|
-
await user.keyboard('{Enter}');
|
|
889
|
-
|
|
890
|
-
expect(handleChange).toHaveBeenCalledWith(5);
|
|
891
|
-
});
|
|
892
|
-
|
|
893
|
-
it('commits a below-min entry at min', async () => {
|
|
894
|
-
const user = userEvent.setup();
|
|
895
|
-
const handleChange = vi.fn();
|
|
896
|
-
render(
|
|
897
|
-
<NumberInput
|
|
898
|
-
label="Age"
|
|
899
|
-
value={null}
|
|
900
|
-
onChange={handleChange}
|
|
901
|
-
min={0}
|
|
902
|
-
/>,
|
|
903
|
-
);
|
|
904
|
-
|
|
905
|
-
const input = screen.getByRole('spinbutton');
|
|
906
|
-
await user.click(input);
|
|
907
|
-
await user.type(input, '-5');
|
|
908
|
-
await user.tab();
|
|
909
|
-
|
|
910
|
-
expect(handleChange).toHaveBeenCalledWith(0);
|
|
911
|
-
});
|
|
912
|
-
|
|
913
|
-
it('does not clamp while typing', async () => {
|
|
914
|
-
const user = userEvent.setup();
|
|
915
|
-
const handleChange = vi.fn();
|
|
916
|
-
render(
|
|
917
|
-
<NumberInput
|
|
918
|
-
label="Rating"
|
|
919
|
-
value={null}
|
|
920
|
-
onChange={handleChange}
|
|
921
|
-
max={5}
|
|
922
|
-
/>,
|
|
923
|
-
);
|
|
924
|
-
|
|
925
|
-
const input = screen.getByRole('spinbutton');
|
|
926
|
-
await user.click(input);
|
|
927
|
-
await user.type(input, '10');
|
|
928
|
-
|
|
929
|
-
// The entry stays exactly as typed until it is committed.
|
|
930
|
-
expect(input).toHaveValue('10');
|
|
931
|
-
expect(handleChange).not.toHaveBeenCalledWith(5);
|
|
932
|
-
});
|
|
933
|
-
|
|
934
|
-
it('displays the clamped value after commit', async () => {
|
|
935
|
-
const user = userEvent.setup();
|
|
936
|
-
function ControlledNumberInput() {
|
|
937
|
-
const [value, setValue] = useState<number>(1);
|
|
938
|
-
return (
|
|
939
|
-
<NumberInput
|
|
940
|
-
label="Page"
|
|
941
|
-
value={value}
|
|
942
|
-
onChange={setValue}
|
|
943
|
-
min={1}
|
|
944
|
-
max={2}
|
|
945
|
-
isIntegerOnly
|
|
946
|
-
/>
|
|
947
|
-
);
|
|
948
|
-
}
|
|
949
|
-
render(<ControlledNumberInput />);
|
|
950
|
-
|
|
951
|
-
const input = screen.getByRole('spinbutton');
|
|
952
|
-
await user.click(input);
|
|
953
|
-
await user.clear(input);
|
|
954
|
-
await user.type(input, '100');
|
|
955
|
-
await user.tab();
|
|
956
|
-
|
|
957
|
-
expect(input).toHaveValue('2');
|
|
958
|
-
});
|
|
959
|
-
|
|
960
|
-
it('shows the clamped value in the field after Enter', async () => {
|
|
961
|
-
const user = userEvent.setup();
|
|
962
|
-
function ControlledNumberInput() {
|
|
963
|
-
const [value, setValue] = useState<number | null>(null);
|
|
964
|
-
return (
|
|
965
|
-
<NumberInput
|
|
966
|
-
label="Rating"
|
|
967
|
-
value={value}
|
|
968
|
-
onChange={setValue}
|
|
969
|
-
min={1}
|
|
970
|
-
max={5}
|
|
971
|
-
/>
|
|
972
|
-
);
|
|
973
|
-
}
|
|
974
|
-
render(<ControlledNumberInput />);
|
|
975
|
-
|
|
976
|
-
const input = screen.getByRole('spinbutton');
|
|
977
|
-
await user.click(input);
|
|
978
|
-
await user.type(input, '10{Enter}');
|
|
979
|
-
|
|
980
|
-
// Still focused: the field must not keep showing the rejected entry.
|
|
981
|
-
expect(input).toHaveValue('5');
|
|
982
|
-
});
|
|
983
|
-
|
|
984
|
-
it('reverts an entry that is not a usable number', async () => {
|
|
985
|
-
const user = userEvent.setup();
|
|
986
|
-
const handleChange = vi.fn();
|
|
987
|
-
render(
|
|
988
|
-
<NumberInput
|
|
989
|
-
label="Count"
|
|
990
|
-
value={null}
|
|
991
|
-
onChange={handleChange}
|
|
992
|
-
max={10}
|
|
993
|
-
isIntegerOnly
|
|
994
|
-
/>,
|
|
995
|
-
);
|
|
996
|
-
|
|
997
|
-
const input = screen.getByRole('spinbutton');
|
|
998
|
-
await user.click(input);
|
|
999
|
-
await user.type(input, '12.5');
|
|
1000
|
-
handleChange.mockClear();
|
|
1001
|
-
await user.tab();
|
|
1002
|
-
|
|
1003
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
1004
|
-
expect(input).toHaveValue('');
|
|
1005
|
-
});
|
|
1006
|
-
|
|
1007
|
-
it('rounds a fractional max inwards for an integer-only field', async () => {
|
|
1008
|
-
const user = userEvent.setup();
|
|
1009
|
-
const handleChange = vi.fn();
|
|
1010
|
-
render(
|
|
1011
|
-
<NumberInput
|
|
1012
|
-
label="Count"
|
|
1013
|
-
value={null}
|
|
1014
|
-
onChange={handleChange}
|
|
1015
|
-
max={9.5}
|
|
1016
|
-
isIntegerOnly
|
|
1017
|
-
/>,
|
|
1018
|
-
);
|
|
1019
|
-
|
|
1020
|
-
const input = screen.getByRole('spinbutton');
|
|
1021
|
-
await user.click(input);
|
|
1022
|
-
await user.type(input, '20');
|
|
1023
|
-
handleChange.mockClear();
|
|
1024
|
-
await user.tab();
|
|
1025
|
-
|
|
1026
|
-
expect(handleChange).toHaveBeenCalledWith(9);
|
|
1027
|
-
});
|
|
1028
|
-
|
|
1029
|
-
it('rounds a fractional min inwards for an integer-only field', async () => {
|
|
1030
|
-
const user = userEvent.setup();
|
|
1031
|
-
const handleChange = vi.fn();
|
|
1032
|
-
render(
|
|
1033
|
-
<NumberInput
|
|
1034
|
-
label="Count"
|
|
1035
|
-
value={null}
|
|
1036
|
-
onChange={handleChange}
|
|
1037
|
-
min={0.5}
|
|
1038
|
-
isIntegerOnly
|
|
1039
|
-
/>,
|
|
1040
|
-
);
|
|
1041
|
-
|
|
1042
|
-
const input = screen.getByRole('spinbutton');
|
|
1043
|
-
await user.click(input);
|
|
1044
|
-
await user.type(input, '0');
|
|
1045
|
-
handleChange.mockClear();
|
|
1046
|
-
await user.tab();
|
|
1047
|
-
|
|
1048
|
-
expect(handleChange).toHaveBeenCalledWith(1);
|
|
1049
|
-
});
|
|
1050
|
-
|
|
1051
|
-
it('does not clamp when no value can satisfy both bounds', async () => {
|
|
1052
|
-
const user = userEvent.setup();
|
|
1053
|
-
const handleChange = vi.fn();
|
|
1054
|
-
render(
|
|
1055
|
-
<NumberInput
|
|
1056
|
-
label="Count"
|
|
1057
|
-
value={null}
|
|
1058
|
-
onChange={handleChange}
|
|
1059
|
-
min={5}
|
|
1060
|
-
max={2}
|
|
1061
|
-
/>,
|
|
1062
|
-
);
|
|
1063
|
-
|
|
1064
|
-
const input = screen.getByRole('spinbutton');
|
|
1065
|
-
await user.click(input);
|
|
1066
|
-
await user.type(input, '10');
|
|
1067
|
-
handleChange.mockClear();
|
|
1068
|
-
await user.tab();
|
|
1069
|
-
|
|
1070
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
1071
|
-
expect(input).toHaveValue('');
|
|
1072
|
-
});
|
|
1073
|
-
});
|
|
1074
|
-
|
|
1075
|
-
describe('status prop', () => {
|
|
1076
|
-
it('renders with error status icon', () => {
|
|
1077
|
-
const {container} = render(
|
|
1078
|
-
<NumberInput
|
|
1079
|
-
label="Amount"
|
|
1080
|
-
value={null}
|
|
1081
|
-
onChange={() => {}}
|
|
1082
|
-
status={{type: 'error'}}
|
|
1083
|
-
/>,
|
|
1084
|
-
);
|
|
1085
|
-
expect(container.querySelector('svg')).toBeInTheDocument();
|
|
1086
|
-
});
|
|
1087
|
-
|
|
1088
|
-
it('renders with warning status icon', () => {
|
|
1089
|
-
const {container} = render(
|
|
1090
|
-
<NumberInput
|
|
1091
|
-
label="Amount"
|
|
1092
|
-
value={null}
|
|
1093
|
-
onChange={() => {}}
|
|
1094
|
-
status={{type: 'warning'}}
|
|
1095
|
-
/>,
|
|
1096
|
-
);
|
|
1097
|
-
expect(container.querySelector('svg')).toBeInTheDocument();
|
|
1098
|
-
});
|
|
1099
|
-
|
|
1100
|
-
it('renders with success status icon', () => {
|
|
1101
|
-
const {container} = render(
|
|
1102
|
-
<NumberInput
|
|
1103
|
-
label="Amount"
|
|
1104
|
-
value={null}
|
|
1105
|
-
onChange={() => {}}
|
|
1106
|
-
status={{type: 'success'}}
|
|
1107
|
-
/>,
|
|
1108
|
-
);
|
|
1109
|
-
expect(container.querySelector('svg')).toBeInTheDocument();
|
|
1110
|
-
});
|
|
1111
|
-
|
|
1112
|
-
it('renders status message when provided', () => {
|
|
1113
|
-
render(
|
|
1114
|
-
<NumberInput
|
|
1115
|
-
label="Amount"
|
|
1116
|
-
value={null}
|
|
1117
|
-
onChange={() => {}}
|
|
1118
|
-
status={{type: 'error', message: 'Value must be positive'}}
|
|
1119
|
-
/>,
|
|
1120
|
-
);
|
|
1121
|
-
expect(screen.getByText('Value must be positive')).toBeInTheDocument();
|
|
1122
|
-
});
|
|
1123
|
-
|
|
1124
|
-
it('has no dangling aria-describedby ids inside InputGroup (WCAG 1.3.1)', () => {
|
|
1125
|
-
// Inside an InputGroup no Field renders, so the status message element
|
|
1126
|
-
// does not exist; aria-describedby must not reference its id.
|
|
1127
|
-
render(
|
|
1128
|
-
<InputGroup label="Price">
|
|
1129
|
-
<NumberInput
|
|
1130
|
-
label="Amount"
|
|
1131
|
-
value={null}
|
|
1132
|
-
onChange={() => {}}
|
|
1133
|
-
status={{type: 'error', message: 'Value must be positive'}}
|
|
1134
|
-
/>
|
|
1135
|
-
</InputGroup>,
|
|
1136
|
-
);
|
|
1137
|
-
const input = screen.getByRole('spinbutton');
|
|
1138
|
-
const describedBy = input.getAttribute('aria-describedby') ?? '';
|
|
1139
|
-
for (const idToken of describedBy.split(/\s+/).filter(Boolean)) {
|
|
1140
|
-
expect(document.getElementById(idToken)).not.toBeNull();
|
|
1141
|
-
}
|
|
1142
|
-
});
|
|
1143
|
-
|
|
1144
|
-
it('names the input by its label and a caller aria-labelledby', () => {
|
|
1145
|
-
render(
|
|
1146
|
-
<>
|
|
1147
|
-
<span id="shipping-heading">Shipping</span>
|
|
1148
|
-
<NumberInput
|
|
1149
|
-
label="Amount"
|
|
1150
|
-
value={null}
|
|
1151
|
-
onChange={() => {}}
|
|
1152
|
-
aria-labelledby="shipping-heading"
|
|
1153
|
-
/>
|
|
1154
|
-
</>,
|
|
1155
|
-
);
|
|
1156
|
-
const input = screen.getByRole('spinbutton', {name: 'Amount Shipping'});
|
|
1157
|
-
expect(input.getAttribute('aria-labelledby')?.split(' ')).toContain(
|
|
1158
|
-
'shipping-heading',
|
|
1159
|
-
);
|
|
1160
|
-
});
|
|
1161
|
-
|
|
1162
|
-
it('names a grouped input by the group, its label, and a caller aria-labelledby', () => {
|
|
1163
|
-
render(
|
|
1164
|
-
<>
|
|
1165
|
-
<span id="shipping-heading">Shipping</span>
|
|
1166
|
-
<InputGroup label="Price">
|
|
1167
|
-
<NumberInput
|
|
1168
|
-
label="Amount"
|
|
1169
|
-
value={null}
|
|
1170
|
-
onChange={() => {}}
|
|
1171
|
-
aria-labelledby="shipping-heading"
|
|
1172
|
-
/>
|
|
1173
|
-
</InputGroup>
|
|
1174
|
-
</>,
|
|
1175
|
-
);
|
|
1176
|
-
expect(
|
|
1177
|
-
screen.getByRole('spinbutton', {name: 'Price Amount Shipping'}),
|
|
1178
|
-
).toBeInTheDocument();
|
|
1179
|
-
});
|
|
1180
|
-
|
|
1181
|
-
it('leaves a standalone input named by its label element without a caller aria-labelledby', () => {
|
|
1182
|
-
render(<NumberInput label="Amount" value={null} onChange={() => {}} />);
|
|
1183
|
-
const input = screen.getByRole('spinbutton', {name: 'Amount'});
|
|
1184
|
-
expect(input).not.toHaveAttribute('aria-labelledby');
|
|
1185
|
-
});
|
|
1186
|
-
|
|
1187
|
-
it('does not render status message when not provided', () => {
|
|
1188
|
-
render(
|
|
1189
|
-
<NumberInput
|
|
1190
|
-
label="Amount"
|
|
1191
|
-
value={null}
|
|
1192
|
-
onChange={() => {}}
|
|
1193
|
-
status={{type: 'error'}}
|
|
1194
|
-
/>,
|
|
1195
|
-
);
|
|
1196
|
-
expect(screen.queryByText(/positive/i)).not.toBeInTheDocument();
|
|
1197
|
-
});
|
|
1198
|
-
|
|
1199
|
-
it('sets aria-invalid when status type is error', () => {
|
|
1200
|
-
render(
|
|
1201
|
-
<NumberInput
|
|
1202
|
-
label="Amount"
|
|
1203
|
-
value={null}
|
|
1204
|
-
onChange={() => {}}
|
|
1205
|
-
status={{type: 'error'}}
|
|
1206
|
-
/>,
|
|
1207
|
-
);
|
|
1208
|
-
expect(screen.getByRole('spinbutton')).toHaveAttribute(
|
|
1209
|
-
'aria-invalid',
|
|
1210
|
-
'true',
|
|
1211
|
-
);
|
|
1212
|
-
});
|
|
1213
|
-
|
|
1214
|
-
it('does not set aria-invalid for warning status', () => {
|
|
1215
|
-
render(
|
|
1216
|
-
<NumberInput
|
|
1217
|
-
label="Amount"
|
|
1218
|
-
value={null}
|
|
1219
|
-
onChange={() => {}}
|
|
1220
|
-
status={{type: 'warning'}}
|
|
1221
|
-
/>,
|
|
1222
|
-
);
|
|
1223
|
-
expect(screen.getByRole('spinbutton')).not.toHaveAttribute(
|
|
1224
|
-
'aria-invalid',
|
|
1225
|
-
);
|
|
1226
|
-
});
|
|
1227
|
-
|
|
1228
|
-
it('does not set aria-invalid for success status', () => {
|
|
1229
|
-
render(
|
|
1230
|
-
<NumberInput
|
|
1231
|
-
label="Amount"
|
|
1232
|
-
value={null}
|
|
1233
|
-
onChange={() => {}}
|
|
1234
|
-
status={{type: 'success'}}
|
|
1235
|
-
/>,
|
|
1236
|
-
);
|
|
1237
|
-
expect(screen.getByRole('spinbutton')).not.toHaveAttribute(
|
|
1238
|
-
'aria-invalid',
|
|
1239
|
-
);
|
|
1240
|
-
});
|
|
1241
|
-
});
|
|
1242
|
-
|
|
1243
|
-
describe('invalid typed input feedback (WCAG 3.3.1)', () => {
|
|
1244
|
-
it('sets aria-invalid="true" when typed input is unparseable', async () => {
|
|
1245
|
-
const user = userEvent.setup();
|
|
1246
|
-
render(
|
|
1247
|
-
<NumberInput
|
|
1248
|
-
label="Count"
|
|
1249
|
-
value={null}
|
|
1250
|
-
onChange={() => {}}
|
|
1251
|
-
isIntegerOnly
|
|
1252
|
-
/>,
|
|
1253
|
-
);
|
|
1254
|
-
|
|
1255
|
-
const input = screen.getByRole('spinbutton');
|
|
1256
|
-
await user.click(input);
|
|
1257
|
-
// "3.5" is invalid when isIntegerOnly is set
|
|
1258
|
-
await user.type(input, '3.5');
|
|
1259
|
-
|
|
1260
|
-
expect(input).toHaveAttribute('aria-invalid', 'true');
|
|
1261
|
-
});
|
|
1262
|
-
|
|
1263
|
-
it('does not set aria-invalid when typed input is valid', async () => {
|
|
1264
|
-
const user = userEvent.setup();
|
|
1265
|
-
render(<NumberInput label="Count" value={null} onChange={() => {}} />);
|
|
1266
|
-
|
|
1267
|
-
const input = screen.getByRole('spinbutton');
|
|
1268
|
-
await user.click(input);
|
|
1269
|
-
await user.type(input, '42');
|
|
1270
|
-
|
|
1271
|
-
expect(input).not.toHaveAttribute('aria-invalid');
|
|
1272
|
-
});
|
|
1273
|
-
|
|
1274
|
-
it('announces an alert message when typed input is invalid', async () => {
|
|
1275
|
-
const user = userEvent.setup();
|
|
1276
|
-
render(
|
|
1277
|
-
<NumberInput
|
|
1278
|
-
label="Count"
|
|
1279
|
-
value={null}
|
|
1280
|
-
onChange={() => {}}
|
|
1281
|
-
isIntegerOnly
|
|
1282
|
-
/>,
|
|
1283
|
-
);
|
|
1284
|
-
|
|
1285
|
-
const input = screen.getByRole('spinbutton');
|
|
1286
|
-
await user.click(input);
|
|
1287
|
-
await user.type(input, '3.5');
|
|
1288
|
-
|
|
1289
|
-
expect(screen.getByRole('alert')).toHaveTextContent('Invalid number');
|
|
1290
|
-
});
|
|
1291
|
-
|
|
1292
|
-
it('resolves the invalid-number announcement from the i18n catalog', async () => {
|
|
1293
|
-
const user = userEvent.setup();
|
|
1294
|
-
render(
|
|
1295
|
-
<InternationalizationProvider
|
|
1296
|
-
locale="ar-SA"
|
|
1297
|
-
overrides={{
|
|
1298
|
-
'ar-SA': {'@astryx.numberInput.invalidNumber': 'رقم غير صالح'},
|
|
1299
|
-
}}>
|
|
1300
|
-
<NumberInput
|
|
1301
|
-
label="Count"
|
|
1302
|
-
value={null}
|
|
1303
|
-
onChange={() => {}}
|
|
1304
|
-
isIntegerOnly
|
|
1305
|
-
/>
|
|
1306
|
-
</InternationalizationProvider>,
|
|
1307
|
-
);
|
|
1308
|
-
|
|
1309
|
-
const input = screen.getByRole('spinbutton');
|
|
1310
|
-
await user.click(input);
|
|
1311
|
-
await user.type(input, '3.5');
|
|
1312
|
-
|
|
1313
|
-
expect(screen.getByRole('alert')).toHaveTextContent('رقم غير صالح');
|
|
1314
|
-
});
|
|
1315
|
-
|
|
1316
|
-
it('does not announce an alert message when input is valid', async () => {
|
|
1317
|
-
const user = userEvent.setup();
|
|
1318
|
-
render(<NumberInput label="Count" value={null} onChange={() => {}} />);
|
|
1319
|
-
|
|
1320
|
-
const input = screen.getByRole('spinbutton');
|
|
1321
|
-
await user.click(input);
|
|
1322
|
-
await user.type(input, '42');
|
|
1323
|
-
|
|
1324
|
-
expect(screen.getByRole('alert')).toHaveTextContent('');
|
|
1325
|
-
expect(screen.queryByText('Invalid number')).not.toBeInTheDocument();
|
|
1326
|
-
});
|
|
1327
|
-
});
|
|
1328
|
-
|
|
1329
|
-
it('renders tooltip info icon when labelTooltip is provided', () => {
|
|
1330
|
-
render(
|
|
1331
|
-
<NumberInput
|
|
1332
|
-
label="Help"
|
|
1333
|
-
value={null}
|
|
1334
|
-
onChange={() => {}}
|
|
1335
|
-
labelTooltip="Helpful info"
|
|
1336
|
-
/>,
|
|
1337
|
-
);
|
|
1338
|
-
expect(document.querySelector('svg')).toBeInTheDocument();
|
|
1339
|
-
});
|
|
1340
|
-
|
|
1341
|
-
it('does not render tooltip icon when labelTooltip is not provided', () => {
|
|
1342
|
-
render(<NumberInput label="Quantity" value={null} onChange={() => {}} />);
|
|
1343
|
-
expect(document.querySelector('svg')).not.toBeInTheDocument();
|
|
1344
|
-
});
|
|
1345
|
-
|
|
1346
|
-
describe('hasAutoFocus prop', () => {
|
|
1347
|
-
it('focuses the input when hasAutoFocus is true', () => {
|
|
1348
|
-
render(
|
|
1349
|
-
<NumberInput
|
|
1350
|
-
label="Quantity"
|
|
1351
|
-
value={null}
|
|
1352
|
-
onChange={() => {}}
|
|
1353
|
-
hasAutoFocus
|
|
1354
|
-
/>,
|
|
1355
|
-
);
|
|
1356
|
-
expect(screen.getByRole('spinbutton')).toHaveFocus();
|
|
1357
|
-
});
|
|
1358
|
-
|
|
1359
|
-
it('does not focus when hasAutoFocus is false', () => {
|
|
1360
|
-
render(<NumberInput label="Quantity" value={null} onChange={() => {}} />);
|
|
1361
|
-
expect(screen.getByRole('spinbutton')).not.toHaveFocus();
|
|
1362
|
-
});
|
|
1363
|
-
});
|
|
1364
|
-
|
|
1365
|
-
describe('htmlName prop', () => {
|
|
1366
|
-
it('sets name attribute when htmlName is provided', () => {
|
|
1367
|
-
render(
|
|
1368
|
-
<NumberInput
|
|
1369
|
-
label="Quantity"
|
|
1370
|
-
value={null}
|
|
1371
|
-
onChange={() => {}}
|
|
1372
|
-
htmlName="quantity"
|
|
1373
|
-
/>,
|
|
1374
|
-
);
|
|
1375
|
-
expect(screen.getByRole('spinbutton')).toHaveAttribute(
|
|
1376
|
-
'name',
|
|
1377
|
-
'quantity',
|
|
1378
|
-
);
|
|
1379
|
-
});
|
|
1380
|
-
|
|
1381
|
-
it('does not set name attribute when htmlName is not provided', () => {
|
|
1382
|
-
render(<NumberInput label="Quantity" value={null} onChange={() => {}} />);
|
|
1383
|
-
expect(screen.getByRole('spinbutton')).not.toHaveAttribute('name');
|
|
1384
|
-
});
|
|
1385
|
-
});
|
|
1386
|
-
|
|
1387
|
-
describe('form participation', () => {
|
|
1388
|
-
it('submits the value under htmlName', () => {
|
|
1389
|
-
const {container} = render(
|
|
1390
|
-
<form>
|
|
1391
|
-
<NumberInput
|
|
1392
|
-
label="Quantity"
|
|
1393
|
-
htmlName="quantity"
|
|
1394
|
-
value={42}
|
|
1395
|
-
onChange={() => {}}
|
|
1396
|
-
/>
|
|
1397
|
-
</form>,
|
|
1398
|
-
);
|
|
1399
|
-
const data = new FormData(container.querySelector('form')!);
|
|
1400
|
-
expect(data.get('quantity')).toBe('42');
|
|
1401
|
-
});
|
|
1402
|
-
|
|
1403
|
-
it('submits the raw number instead of the formatted display value', () => {
|
|
1404
|
-
const {container} = render(
|
|
1405
|
-
<form>
|
|
1406
|
-
<NumberInput
|
|
1407
|
-
label="Revenue"
|
|
1408
|
-
htmlName="revenue"
|
|
1409
|
-
value={1234}
|
|
1410
|
-
onChange={() => {}}
|
|
1411
|
-
formatValue={number => `$${number.toLocaleString('en-US')}`}
|
|
1412
|
-
/>
|
|
1413
|
-
</form>,
|
|
1414
|
-
);
|
|
1415
|
-
const data = new FormData(container.querySelector('form')!);
|
|
1416
|
-
expect(data.get('revenue')).toBe('1234');
|
|
1417
|
-
});
|
|
1418
|
-
|
|
1419
|
-
it('submits the committed value in formatted mode until an edit commits', () => {
|
|
1420
|
-
function ControlledForm() {
|
|
1421
|
-
const [controlledValue, setControlledValue] = useState(7);
|
|
1422
|
-
return (
|
|
1423
|
-
<form>
|
|
1424
|
-
<NumberInput
|
|
1425
|
-
label="Quantity"
|
|
1426
|
-
htmlName="quantity"
|
|
1427
|
-
value={controlledValue}
|
|
1428
|
-
onChange={setControlledValue}
|
|
1429
|
-
formatValue={String}
|
|
1430
|
-
/>
|
|
1431
|
-
</form>
|
|
1432
|
-
);
|
|
1433
|
-
}
|
|
1434
|
-
const {container} = render(<ControlledForm />);
|
|
1435
|
-
const form = container.querySelector('form')!;
|
|
1436
|
-
const input = screen.getByRole('spinbutton');
|
|
1437
|
-
fireEvent.focus(input);
|
|
1438
|
-
fireEvent.input(input, {target: {value: '42'}});
|
|
1439
|
-
|
|
1440
|
-
expect(new FormData(form).get('quantity')).toBe('7');
|
|
1441
|
-
fireEvent.blur(input);
|
|
1442
|
-
expect(new FormData(form).get('quantity')).toBe('42');
|
|
1443
|
-
});
|
|
1444
|
-
|
|
1445
|
-
it('is excluded from form data when disabled', () => {
|
|
1446
|
-
const {container} = render(
|
|
1447
|
-
<form>
|
|
1448
|
-
<NumberInput
|
|
1449
|
-
label="Quantity"
|
|
1450
|
-
htmlName="quantity"
|
|
1451
|
-
value={42}
|
|
1452
|
-
onChange={() => {}}
|
|
1453
|
-
isDisabled
|
|
1454
|
-
/>
|
|
1455
|
-
</form>,
|
|
1456
|
-
);
|
|
1457
|
-
expect([
|
|
1458
|
-
...new FormData(container.querySelector('form')!).keys(),
|
|
1459
|
-
]).toEqual([]);
|
|
1460
|
-
});
|
|
1461
|
-
|
|
1462
|
-
// Regression: a disabledMessage swaps the native `disabled` attribute for
|
|
1463
|
-
// aria-disabled + readOnly so the reason stays focus-discoverable, but
|
|
1464
|
-
// read-only fields still submit — the name has to be withheld too.
|
|
1465
|
-
it('is excluded from form data when disabled, even with a disabledMessage', () => {
|
|
1466
|
-
const {container} = render(
|
|
1467
|
-
<form>
|
|
1468
|
-
<NumberInput
|
|
1469
|
-
label="Quantity"
|
|
1470
|
-
htmlName="quantity"
|
|
1471
|
-
value={42}
|
|
1472
|
-
onChange={() => {}}
|
|
1473
|
-
isDisabled
|
|
1474
|
-
disabledMessage="Quantity is fixed by the contract"
|
|
1475
|
-
/>
|
|
1476
|
-
</form>,
|
|
1477
|
-
);
|
|
1478
|
-
expect([
|
|
1479
|
-
...new FormData(container.querySelector('form')!).keys(),
|
|
1480
|
-
]).toEqual([]);
|
|
1481
|
-
});
|
|
1482
|
-
});
|
|
1483
|
-
|
|
1484
|
-
describe('isReadOnly', () => {
|
|
1485
|
-
it('marks the input read-only', () => {
|
|
1486
|
-
render(
|
|
1487
|
-
<NumberInput
|
|
1488
|
-
label="Quantity"
|
|
1489
|
-
value={42}
|
|
1490
|
-
onChange={() => {}}
|
|
1491
|
-
isReadOnly
|
|
1492
|
-
/>,
|
|
1493
|
-
);
|
|
1494
|
-
expect(screen.getByRole('spinbutton')).toHaveAttribute('readonly');
|
|
1495
|
-
});
|
|
1496
|
-
|
|
1497
|
-
it('still submits its value with the form', () => {
|
|
1498
|
-
const {container} = render(
|
|
1499
|
-
<form>
|
|
1500
|
-
<NumberInput
|
|
1501
|
-
label="Quantity"
|
|
1502
|
-
htmlName="quantity"
|
|
1503
|
-
value={42}
|
|
1504
|
-
onChange={() => {}}
|
|
1505
|
-
isReadOnly
|
|
1506
|
-
/>
|
|
1507
|
-
</form>,
|
|
1508
|
-
);
|
|
1509
|
-
expect(
|
|
1510
|
-
new FormData(container.querySelector('form')!).get('quantity'),
|
|
1511
|
-
).toBe('42');
|
|
1512
|
-
});
|
|
1513
|
-
|
|
1514
|
-
it('does not call onChange when the user types', async () => {
|
|
1515
|
-
const user = userEvent.setup();
|
|
1516
|
-
const handleChange = vi.fn();
|
|
1517
|
-
render(
|
|
1518
|
-
<NumberInput
|
|
1519
|
-
label="Quantity"
|
|
1520
|
-
value={42}
|
|
1521
|
-
onChange={handleChange}
|
|
1522
|
-
isReadOnly
|
|
1523
|
-
/>,
|
|
1524
|
-
);
|
|
1525
|
-
await user.type(screen.getByRole('spinbutton'), '7');
|
|
1526
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
1527
|
-
});
|
|
1528
|
-
|
|
1529
|
-
it('stays focusable and is not disabled', async () => {
|
|
1530
|
-
const user = userEvent.setup();
|
|
1531
|
-
render(
|
|
1532
|
-
<NumberInput
|
|
1533
|
-
label="Quantity"
|
|
1534
|
-
value={42}
|
|
1535
|
-
onChange={() => {}}
|
|
1536
|
-
isReadOnly
|
|
1537
|
-
/>,
|
|
1538
|
-
);
|
|
1539
|
-
const input = screen.getByRole('spinbutton');
|
|
1540
|
-
expect(input).not.toBeDisabled();
|
|
1541
|
-
await user.tab();
|
|
1542
|
-
expect(input).toHaveFocus();
|
|
1543
|
-
});
|
|
1544
|
-
|
|
1545
|
-
it('hides the clear button', () => {
|
|
1546
|
-
render(
|
|
1547
|
-
<NumberInput
|
|
1548
|
-
label="Quantity"
|
|
1549
|
-
value={42}
|
|
1550
|
-
onChange={() => {}}
|
|
1551
|
-
hasClear
|
|
1552
|
-
isReadOnly
|
|
1553
|
-
/>,
|
|
1554
|
-
);
|
|
1555
|
-
expect(screen.queryByRole('button')).not.toBeInTheDocument();
|
|
1556
|
-
});
|
|
1557
|
-
|
|
1558
|
-
it('does not step on ArrowUp or ArrowDown', async () => {
|
|
1559
|
-
const user = userEvent.setup();
|
|
1560
|
-
const handleChange = vi.fn();
|
|
1561
|
-
render(
|
|
1562
|
-
<NumberInput
|
|
1563
|
-
label="Quantity"
|
|
1564
|
-
value={42}
|
|
1565
|
-
onChange={handleChange}
|
|
1566
|
-
isReadOnly
|
|
1567
|
-
/>,
|
|
1568
|
-
);
|
|
1569
|
-
const input = screen.getByRole<HTMLInputElement>('spinbutton');
|
|
1570
|
-
input.focus();
|
|
1571
|
-
await user.keyboard('{ArrowUp}{ArrowDown}');
|
|
1572
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
1573
|
-
expect(input).toHaveValue('42');
|
|
1574
|
-
});
|
|
1575
|
-
|
|
1576
|
-
it('leaves wheel scrolling to the page instead of stepping', () => {
|
|
1577
|
-
const onScrollableWheel = vi.fn();
|
|
1578
|
-
const handleChange = vi.fn();
|
|
1579
|
-
render(
|
|
1580
|
-
<div onWheel={onScrollableWheel}>
|
|
1581
|
-
<NumberInput
|
|
1582
|
-
label="Quantity"
|
|
1583
|
-
value={42}
|
|
1584
|
-
onChange={handleChange}
|
|
1585
|
-
isReadOnly
|
|
1586
|
-
/>
|
|
1587
|
-
</div>,
|
|
1588
|
-
);
|
|
1589
|
-
const input = screen.getByRole<HTMLInputElement>('spinbutton');
|
|
1590
|
-
input.focus();
|
|
1591
|
-
const event = new WheelEvent('wheel', {
|
|
1592
|
-
bubbles: true,
|
|
1593
|
-
cancelable: true,
|
|
1594
|
-
deltaY: -100,
|
|
1595
|
-
});
|
|
1596
|
-
fireEvent(input, event);
|
|
1597
|
-
|
|
1598
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
1599
|
-
expect(event.defaultPrevented).toBe(false);
|
|
1600
|
-
expect(onScrollableWheel).toHaveBeenCalledTimes(1);
|
|
1601
|
-
});
|
|
1602
|
-
|
|
1603
|
-
it('disables both number steppers', () => {
|
|
1604
|
-
const handleChange = vi.fn();
|
|
1605
|
-
render(
|
|
1606
|
-
<NumberInput
|
|
1607
|
-
label="Quantity"
|
|
1608
|
-
value={42}
|
|
1609
|
-
onChange={handleChange}
|
|
1610
|
-
hasNumberSteppers
|
|
1611
|
-
isReadOnly
|
|
1612
|
-
/>,
|
|
1613
|
-
);
|
|
1614
|
-
const increment = screen.getByRole('button', {
|
|
1615
|
-
name: 'Increment Quantity',
|
|
1616
|
-
});
|
|
1617
|
-
expect(increment).toHaveAttribute('aria-disabled', 'true');
|
|
1618
|
-
expect(
|
|
1619
|
-
screen.getByRole('button', {name: 'Decrement Quantity'}),
|
|
1620
|
-
).toHaveAttribute('aria-disabled', 'true');
|
|
1621
|
-
|
|
1622
|
-
fireEvent.click(increment);
|
|
1623
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
1624
|
-
});
|
|
1625
|
-
|
|
1626
|
-
it('lets isDisabled win when both are set', () => {
|
|
1627
|
-
const {container} = render(
|
|
1628
|
-
<form>
|
|
1629
|
-
<NumberInput
|
|
1630
|
-
label="Quantity"
|
|
1631
|
-
htmlName="quantity"
|
|
1632
|
-
value={42}
|
|
1633
|
-
onChange={() => {}}
|
|
1634
|
-
isReadOnly
|
|
1635
|
-
isDisabled
|
|
1636
|
-
/>
|
|
1637
|
-
</form>,
|
|
1638
|
-
);
|
|
1639
|
-
expect(screen.getByRole('spinbutton')).toHaveAttribute(
|
|
1640
|
-
'aria-disabled',
|
|
1641
|
-
'true',
|
|
1642
|
-
);
|
|
1643
|
-
expect([
|
|
1644
|
-
...new FormData(container.querySelector('form')!).keys(),
|
|
1645
|
-
]).toEqual([]);
|
|
1646
|
-
});
|
|
1647
|
-
});
|
|
1648
|
-
|
|
1649
|
-
describe('autoComplete prop', () => {
|
|
1650
|
-
it('sets autocomplete attribute when autoComplete is provided', () => {
|
|
1651
|
-
render(
|
|
1652
|
-
<NumberInput
|
|
1653
|
-
label="Age"
|
|
1654
|
-
value={null}
|
|
1655
|
-
onChange={() => {}}
|
|
1656
|
-
autoComplete="off"
|
|
1657
|
-
/>,
|
|
1658
|
-
);
|
|
1659
|
-
expect(screen.getByRole('spinbutton')).toHaveAttribute(
|
|
1660
|
-
'autocomplete',
|
|
1661
|
-
'off',
|
|
1662
|
-
);
|
|
1663
|
-
});
|
|
1664
|
-
});
|
|
1665
|
-
|
|
1666
|
-
describe('hasClear', () => {
|
|
1667
|
-
it('shows clear button when hasClear is true and value exists', () => {
|
|
1668
|
-
render(
|
|
1669
|
-
<NumberInput label="Qty" value={5} onChange={() => {}} hasClear />,
|
|
1670
|
-
);
|
|
1671
|
-
expect(
|
|
1672
|
-
screen.getByRole('button', {name: 'Clear Qty'}),
|
|
1673
|
-
).toBeInTheDocument();
|
|
1674
|
-
});
|
|
1675
|
-
|
|
1676
|
-
it('focuses the field inside the tap that clears it, without scrolling', () => {
|
|
1677
|
-
// iOS Safari brings up its keyboard only for a focus made while
|
|
1678
|
-
// handling the touch.
|
|
1679
|
-
const onChange = vi.fn();
|
|
1680
|
-
const focusSpy = vi.spyOn(HTMLElement.prototype, 'focus');
|
|
1681
|
-
render(
|
|
1682
|
-
<NumberInput label="Qty" value={5} onChange={onChange} hasClear />,
|
|
1683
|
-
);
|
|
1684
|
-
const input = screen.getByRole('spinbutton');
|
|
1685
|
-
fireEvent.click(screen.getByRole('button', {name: 'Clear Qty'}), {
|
|
1686
|
-
detail: 1,
|
|
1687
|
-
});
|
|
1688
|
-
expect(onChange).toHaveBeenCalledWith(null);
|
|
1689
|
-
expect(document.activeElement).toBe(input);
|
|
1690
|
-
expect(focusSpy).toHaveBeenLastCalledWith({preventScroll: true});
|
|
1691
|
-
focusSpy.mockRestore();
|
|
1692
|
-
});
|
|
1693
|
-
|
|
1694
|
-
it('does not show clear button when value is null', () => {
|
|
1695
|
-
render(
|
|
1696
|
-
<NumberInput label="Qty" value={null} onChange={() => {}} hasClear />,
|
|
1697
|
-
);
|
|
1698
|
-
expect(
|
|
1699
|
-
screen.queryByRole('button', {name: 'Clear Qty'}),
|
|
1700
|
-
).not.toBeInTheDocument();
|
|
1701
|
-
});
|
|
1702
|
-
|
|
1703
|
-
it('keeps Tab moving forward when an empty field has an invalid draft', async () => {
|
|
1704
|
-
const user = userEvent.setup();
|
|
1705
|
-
render(
|
|
1706
|
-
<>
|
|
1707
|
-
<NumberInput label="Qty" value={null} onChange={() => {}} hasClear />
|
|
1708
|
-
<button type="button">Next field</button>
|
|
1709
|
-
</>,
|
|
1710
|
-
);
|
|
1711
|
-
const input = screen.getByRole('spinbutton');
|
|
1712
|
-
await user.click(input);
|
|
1713
|
-
await user.type(input, 'invalid');
|
|
1714
|
-
expect(
|
|
1715
|
-
screen.queryByRole('button', {name: 'Clear Qty'}),
|
|
1716
|
-
).not.toBeInTheDocument();
|
|
1717
|
-
|
|
1718
|
-
await user.tab();
|
|
1719
|
-
expect(screen.getByRole('button', {name: 'Next field'})).toHaveFocus();
|
|
1720
|
-
});
|
|
1721
|
-
|
|
1722
|
-
it('does not show clear button when hasClear is false', () => {
|
|
1723
|
-
render(<NumberInput label="Qty" value={5} onChange={() => {}} />);
|
|
1724
|
-
expect(
|
|
1725
|
-
screen.queryByRole('button', {name: 'Clear Qty'}),
|
|
1726
|
-
).not.toBeInTheDocument();
|
|
1727
|
-
});
|
|
1728
|
-
|
|
1729
|
-
it('does not show clear button when disabled', () => {
|
|
1730
|
-
render(
|
|
1731
|
-
<NumberInput
|
|
1732
|
-
label="Qty"
|
|
1733
|
-
value={5}
|
|
1734
|
-
onChange={() => {}}
|
|
1735
|
-
hasClear
|
|
1736
|
-
isDisabled
|
|
1737
|
-
/>,
|
|
1738
|
-
);
|
|
1739
|
-
expect(
|
|
1740
|
-
screen.queryByRole('button', {name: 'Clear Qty'}),
|
|
1741
|
-
).not.toBeInTheDocument();
|
|
1742
|
-
});
|
|
1743
|
-
|
|
1744
|
-
it('calls onChange with null when clear is clicked', async () => {
|
|
1745
|
-
const user = userEvent.setup();
|
|
1746
|
-
const onChange = vi.fn();
|
|
1747
|
-
render(
|
|
1748
|
-
<NumberInput label="Qty" value={5} onChange={onChange} hasClear />,
|
|
1749
|
-
);
|
|
1750
|
-
await user.click(screen.getByRole('button', {name: 'Clear Qty'}));
|
|
1751
|
-
expect(onChange).toHaveBeenCalledWith(null);
|
|
1752
|
-
});
|
|
1753
|
-
});
|
|
1754
|
-
|
|
1755
|
-
describe('click-to-focus', () => {
|
|
1756
|
-
it('focuses input when clicking the start icon', () => {
|
|
1757
|
-
render(
|
|
1758
|
-
<NumberInput
|
|
1759
|
-
label="Qty"
|
|
1760
|
-
value={0}
|
|
1761
|
-
onChange={() => {}}
|
|
1762
|
-
startIcon={<TestIcon />}
|
|
1763
|
-
/>,
|
|
1764
|
-
);
|
|
1765
|
-
|
|
1766
|
-
const input = screen.getByRole('spinbutton');
|
|
1767
|
-
const wrapper = input.parentElement!;
|
|
1768
|
-
const iconElement = wrapper.querySelector('svg')!;
|
|
1769
|
-
|
|
1770
|
-
fireEvent.click(iconElement);
|
|
1771
|
-
expect(input).toHaveFocus();
|
|
1772
|
-
});
|
|
1773
|
-
|
|
1774
|
-
it('focuses input when clicking the wrapper padding', () => {
|
|
1775
|
-
render(<NumberInput label="Qty" value={0} onChange={() => {}} />);
|
|
1776
|
-
|
|
1777
|
-
const input = screen.getByRole('spinbutton');
|
|
1778
|
-
const wrapper = input.parentElement!;
|
|
1779
|
-
|
|
1780
|
-
fireEvent.click(wrapper);
|
|
1781
|
-
expect(input).toHaveFocus();
|
|
1782
|
-
});
|
|
1783
|
-
});
|
|
1784
|
-
|
|
1785
|
-
describe('disabledMessage', () => {
|
|
1786
|
-
it('shows the reason tooltip on hover when disabled with a reason', async () => {
|
|
1787
|
-
render(
|
|
1788
|
-
<NumberInput
|
|
1789
|
-
label="Quantity"
|
|
1790
|
-
value={5}
|
|
1791
|
-
onChange={() => {}}
|
|
1792
|
-
isDisabled
|
|
1793
|
-
disabledMessage="You need the Editor role"
|
|
1794
|
-
/>,
|
|
1795
|
-
);
|
|
1796
|
-
|
|
1797
|
-
const input = screen.getByRole('spinbutton');
|
|
1798
|
-
const container = input.parentElement as HTMLElement;
|
|
1799
|
-
const tooltip = screen.getByRole('tooltip', h);
|
|
1800
|
-
expect(tooltip).toHaveTextContent('You need the Editor role');
|
|
1801
|
-
|
|
1802
|
-
fireEvent.mouseEnter(container);
|
|
1803
|
-
await waitFor(() => {
|
|
1804
|
-
expect(tooltip).toHaveAttribute('popover-open');
|
|
1805
|
-
});
|
|
1806
|
-
|
|
1807
|
-
fireEvent.mouseLeave(container);
|
|
1808
|
-
await waitFor(() => {
|
|
1809
|
-
expect(tooltip).not.toHaveAttribute('popover-open');
|
|
1810
|
-
});
|
|
1811
|
-
});
|
|
1812
|
-
|
|
1813
|
-
it('shows the reason tooltip on keyboard focus', async () => {
|
|
1814
|
-
const user = userEvent.setup();
|
|
1815
|
-
render(
|
|
1816
|
-
<NumberInput
|
|
1817
|
-
label="Quantity"
|
|
1818
|
-
value={5}
|
|
1819
|
-
onChange={() => {}}
|
|
1820
|
-
isDisabled
|
|
1821
|
-
disabledMessage="You need the Editor role"
|
|
1822
|
-
/>,
|
|
1823
|
-
);
|
|
1824
|
-
|
|
1825
|
-
const tooltip = screen.getByRole('tooltip', h);
|
|
1826
|
-
await user.tab();
|
|
1827
|
-
expect(screen.getByRole('spinbutton')).toHaveFocus();
|
|
1828
|
-
await waitFor(() => {
|
|
1829
|
-
expect(tooltip).toHaveAttribute('popover-open');
|
|
1830
|
-
});
|
|
1831
|
-
});
|
|
1832
|
-
|
|
1833
|
-
it('does not render a tooltip when not disabled', () => {
|
|
1834
|
-
render(
|
|
1835
|
-
<NumberInput
|
|
1836
|
-
label="Quantity"
|
|
1837
|
-
value={5}
|
|
1838
|
-
onChange={() => {}}
|
|
1839
|
-
disabledMessage="You need the Editor role"
|
|
1840
|
-
/>,
|
|
1841
|
-
);
|
|
1842
|
-
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
1843
|
-
});
|
|
1844
|
-
|
|
1845
|
-
it('does not render a tooltip when disabled without a reason', () => {
|
|
1846
|
-
render(
|
|
1847
|
-
<NumberInput
|
|
1848
|
-
label="Quantity"
|
|
1849
|
-
value={5}
|
|
1850
|
-
onChange={() => {}}
|
|
1851
|
-
isDisabled
|
|
1852
|
-
/>,
|
|
1853
|
-
);
|
|
1854
|
-
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
1855
|
-
});
|
|
1856
|
-
|
|
1857
|
-
it('keeps the input focusable via aria-disabled when a reason is provided', () => {
|
|
1858
|
-
render(
|
|
1859
|
-
<NumberInput
|
|
1860
|
-
label="Quantity"
|
|
1861
|
-
value={5}
|
|
1862
|
-
onChange={() => {}}
|
|
1863
|
-
isDisabled
|
|
1864
|
-
disabledMessage="You need the Editor role"
|
|
1865
|
-
/>,
|
|
1866
|
-
);
|
|
1867
|
-
const input = screen.getByRole('spinbutton');
|
|
1868
|
-
expect(input).not.toBeDisabled();
|
|
1869
|
-
expect(input).toHaveAttribute('aria-disabled', 'true');
|
|
1870
|
-
expect(input).toHaveAttribute('readonly');
|
|
1871
|
-
});
|
|
1872
|
-
|
|
1873
|
-
it('links the reason tooltip from the input via aria-describedby', () => {
|
|
1874
|
-
render(
|
|
1875
|
-
<NumberInput
|
|
1876
|
-
label="Quantity"
|
|
1877
|
-
value={5}
|
|
1878
|
-
onChange={() => {}}
|
|
1879
|
-
isDisabled
|
|
1880
|
-
disabledMessage="You need the Editor role"
|
|
1881
|
-
/>,
|
|
1882
|
-
);
|
|
1883
|
-
const input = screen.getByRole('spinbutton');
|
|
1884
|
-
const tooltip = screen.getByRole('tooltip', h);
|
|
1885
|
-
expect(input.getAttribute('aria-describedby')).toContain(tooltip.id);
|
|
1886
|
-
});
|
|
1887
|
-
|
|
1888
|
-
it('blocks value changes while focusable-disabled', async () => {
|
|
1889
|
-
const user = userEvent.setup();
|
|
1890
|
-
const onChange = vi.fn();
|
|
1891
|
-
render(
|
|
1892
|
-
<NumberInput
|
|
1893
|
-
label="Quantity"
|
|
1894
|
-
value={5}
|
|
1895
|
-
onChange={onChange}
|
|
1896
|
-
isDisabled
|
|
1897
|
-
disabledMessage="You need the Editor role"
|
|
1898
|
-
/>,
|
|
1899
|
-
);
|
|
1900
|
-
|
|
1901
|
-
const input = screen.getByRole('spinbutton');
|
|
1902
|
-
await user.click(input);
|
|
1903
|
-
await user.keyboard('9');
|
|
1904
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
1905
|
-
});
|
|
1906
|
-
|
|
1907
|
-
it('stays focusable when disabled without a reason', () => {
|
|
1908
|
-
render(
|
|
1909
|
-
<NumberInput
|
|
1910
|
-
label="Quantity"
|
|
1911
|
-
value={5}
|
|
1912
|
-
onChange={() => {}}
|
|
1913
|
-
isDisabled
|
|
1914
|
-
/>,
|
|
1915
|
-
);
|
|
1916
|
-
const input = screen.getByRole('spinbutton');
|
|
1917
|
-
expect(input).not.toBeDisabled();
|
|
1918
|
-
expect(input).toHaveAttribute('aria-disabled', 'true');
|
|
1919
|
-
});
|
|
1920
|
-
});
|
|
1921
|
-
});
|
|
1922
|
-
|
|
1923
|
-
describe('keyboard clearing with hasClear (#3599)', () => {
|
|
1924
|
-
it('commits null when the input is emptied and blurred', () => {
|
|
1925
|
-
const onChange = vi.fn();
|
|
1926
|
-
render(<NumberInput label="Qty" hasClear value={42} onChange={onChange} />);
|
|
1927
|
-
const input = screen.getByLabelText('Qty');
|
|
1928
|
-
fireEvent.change(input, {target: {value: ''}});
|
|
1929
|
-
fireEvent.blur(input);
|
|
1930
|
-
expect(onChange).toHaveBeenCalledWith(null);
|
|
1931
|
-
});
|
|
1932
|
-
|
|
1933
|
-
it('commits null when the input is emptied and Enter is pressed', () => {
|
|
1934
|
-
const onChange = vi.fn();
|
|
1935
|
-
render(<NumberInput label="Qty" hasClear value={42} onChange={onChange} />);
|
|
1936
|
-
const input = screen.getByLabelText('Qty');
|
|
1937
|
-
fireEvent.change(input, {target: {value: ''}});
|
|
1938
|
-
fireEvent.keyDown(input, {key: 'Enter'});
|
|
1939
|
-
expect(onChange).toHaveBeenCalledWith(null);
|
|
1940
|
-
});
|
|
1941
|
-
|
|
1942
|
-
it('does not fire when emptied and blurred with no prior value', () => {
|
|
1943
|
-
const onChange = vi.fn();
|
|
1944
|
-
render(
|
|
1945
|
-
<NumberInput label="Qty" hasClear value={null} onChange={onChange} />,
|
|
1946
|
-
);
|
|
1947
|
-
const input = screen.getByLabelText('Qty');
|
|
1948
|
-
fireEvent.change(input, {target: {value: ''}});
|
|
1949
|
-
fireEvent.blur(input);
|
|
1950
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
1951
|
-
});
|
|
1952
|
-
|
|
1953
|
-
it('still reverts on blur when hasClear is not set', () => {
|
|
1954
|
-
const onChange = vi.fn();
|
|
1955
|
-
render(<NumberInput label="Qty" value={42} onChange={onChange} />);
|
|
1956
|
-
const input = screen.getByLabelText('Qty');
|
|
1957
|
-
fireEvent.change(input, {target: {value: ''}});
|
|
1958
|
-
fireEvent.blur(input);
|
|
1959
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
1960
|
-
expect((input as HTMLInputElement).value).toBe('42');
|
|
1961
|
-
});
|
|
1962
|
-
});
|
|
1963
|
-
|
|
1964
|
-
describe('NumberInput statusVariant forwarding', () => {
|
|
1965
|
-
it('defaults to attached (status renders with data-variant="attached")', () => {
|
|
1966
|
-
const {container} = render(
|
|
1967
|
-
<NumberInput
|
|
1968
|
-
label="Amount"
|
|
1969
|
-
value={null}
|
|
1970
|
-
onChange={() => {}}
|
|
1971
|
-
status={{type: 'error', message: 'Must be positive'}}
|
|
1972
|
-
/>,
|
|
1973
|
-
);
|
|
1974
|
-
expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
|
|
1975
|
-
'data-variant',
|
|
1976
|
-
'attached',
|
|
1977
|
-
);
|
|
1978
|
-
});
|
|
1979
|
-
|
|
1980
|
-
it('forwards statusVariant="detached" to the underlying Field status', () => {
|
|
1981
|
-
const {container} = render(
|
|
1982
|
-
<NumberInput
|
|
1983
|
-
label="Amount"
|
|
1984
|
-
value={null}
|
|
1985
|
-
onChange={() => {}}
|
|
1986
|
-
status={{type: 'error', message: 'Must be positive'}}
|
|
1987
|
-
statusVariant="detached"
|
|
1988
|
-
/>,
|
|
1989
|
-
);
|
|
1990
|
-
expect(container.querySelector('.astryx-field-status')).toHaveAttribute(
|
|
1991
|
-
'data-variant',
|
|
1992
|
-
'detached',
|
|
1993
|
-
);
|
|
1994
|
-
});
|
|
1995
|
-
});
|
|
1996
|
-
|
|
1997
|
-
describe('NumberInput stepping', () => {
|
|
1998
|
-
const stepInteractions = [
|
|
1999
|
-
[
|
|
2000
|
-
'keyboard',
|
|
2001
|
-
(input: HTMLElement, direction: 'up' | 'down') =>
|
|
2002
|
-
fireEvent.keyDown(input, {
|
|
2003
|
-
key: direction === 'up' ? 'ArrowUp' : 'ArrowDown',
|
|
2004
|
-
}),
|
|
2005
|
-
],
|
|
2006
|
-
[
|
|
2007
|
-
'wheel',
|
|
2008
|
-
(input: HTMLElement, direction: 'up' | 'down') => {
|
|
2009
|
-
input.focus();
|
|
2010
|
-
act(() => {
|
|
2011
|
-
fireEvent.wheel(input, {deltaY: direction === 'up' ? -100 : 100});
|
|
2012
|
-
});
|
|
2013
|
-
},
|
|
2014
|
-
],
|
|
2015
|
-
[
|
|
2016
|
-
'number stepper',
|
|
2017
|
-
(_input: HTMLElement, direction: 'up' | 'down') =>
|
|
2018
|
-
fireEvent.click(
|
|
2019
|
-
screen.getByRole('button', {
|
|
2020
|
-
name: direction === 'up' ? 'Increment Amount' : 'Decrement Amount',
|
|
2021
|
-
}),
|
|
2022
|
-
),
|
|
2023
|
-
],
|
|
2024
|
-
] as const;
|
|
2025
|
-
|
|
2026
|
-
it('increments with ArrowUp and decrements with ArrowDown', () => {
|
|
2027
|
-
const onChange = vi.fn();
|
|
2028
|
-
render(<NumberInput label="Amount" value={5} onChange={onChange} />);
|
|
2029
|
-
const input = screen.getByRole('spinbutton');
|
|
2030
|
-
|
|
2031
|
-
fireEvent.keyDown(input, {key: 'ArrowUp'});
|
|
2032
|
-
expect(onChange).toHaveBeenLastCalledWith(6);
|
|
2033
|
-
|
|
2034
|
-
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
2035
|
-
expect(onChange).toHaveBeenLastCalledWith(4);
|
|
2036
|
-
});
|
|
2037
|
-
|
|
2038
|
-
it('does not step or commit on a composing keydown (IME)', () => {
|
|
2039
|
-
const onChange = vi.fn();
|
|
2040
|
-
render(<NumberInput label="Amount" value={5} onChange={onChange} />);
|
|
2041
|
-
const input = screen.getByRole('spinbutton');
|
|
2042
|
-
|
|
2043
|
-
// The field is type="text", so an IME composes into it. Enter commits the
|
|
2044
|
-
// candidate and the arrows walk the candidate window; neither should reach
|
|
2045
|
-
// the stepping or commit paths. Both signals a browser may report.
|
|
2046
|
-
fireEvent.keyDown(input, {key: 'ArrowUp', isComposing: true});
|
|
2047
|
-
fireEvent.keyDown(input, {key: 'ArrowDown', keyCode: 229});
|
|
2048
|
-
fireEvent.keyDown(input, {key: 'Enter', isComposing: true});
|
|
2049
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
2050
|
-
|
|
2051
|
-
// A real, non-composing ArrowUp still steps.
|
|
2052
|
-
fireEvent.keyDown(input, {key: 'ArrowUp'});
|
|
2053
|
-
expect(onChange).toHaveBeenLastCalledWith(6);
|
|
2054
|
-
});
|
|
2055
|
-
|
|
2056
|
-
it('lets onKeyDown cancel keyboard stepping', () => {
|
|
2057
|
-
const onChange = vi.fn();
|
|
2058
|
-
const onKeyDown = vi.fn((event: React.KeyboardEvent<HTMLInputElement>) =>
|
|
2059
|
-
event.preventDefault(),
|
|
2060
|
-
);
|
|
2061
|
-
render(
|
|
2062
|
-
<NumberInput
|
|
2063
|
-
label="Amount"
|
|
2064
|
-
value={5}
|
|
2065
|
-
onChange={onChange}
|
|
2066
|
-
onKeyDown={onKeyDown}
|
|
2067
|
-
/>,
|
|
2068
|
-
);
|
|
2069
|
-
fireEvent.keyDown(screen.getByRole('spinbutton'), {key: 'ArrowUp'});
|
|
2070
|
-
|
|
2071
|
-
expect(onKeyDown).toHaveBeenCalledTimes(1);
|
|
2072
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
2073
|
-
});
|
|
2074
|
-
|
|
2075
|
-
it('uses decimal-safe step arithmetic', () => {
|
|
2076
|
-
const onChange = vi.fn();
|
|
2077
|
-
render(
|
|
2078
|
-
<NumberInput label="Amount" value={0.2} onChange={onChange} step={0.1} />,
|
|
2079
|
-
);
|
|
2080
|
-
fireEvent.keyDown(screen.getByRole('spinbutton'), {key: 'ArrowUp'});
|
|
2081
|
-
expect(onChange).toHaveBeenCalledWith(0.3);
|
|
2082
|
-
});
|
|
2083
|
-
|
|
2084
|
-
it('aligns an off-step value in the requested direction', () => {
|
|
2085
|
-
const onChange = vi.fn();
|
|
2086
|
-
render(
|
|
2087
|
-
<NumberInput
|
|
2088
|
-
label="Amount"
|
|
2089
|
-
value={0.25}
|
|
2090
|
-
onChange={onChange}
|
|
2091
|
-
step={0.1}
|
|
2092
|
-
/>,
|
|
2093
|
-
);
|
|
2094
|
-
const input = screen.getByRole('spinbutton');
|
|
2095
|
-
|
|
2096
|
-
fireEvent.keyDown(input, {key: 'ArrowUp'});
|
|
2097
|
-
expect(onChange).toHaveBeenLastCalledWith(0.3);
|
|
2098
|
-
|
|
2099
|
-
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
2100
|
-
expect(onChange).toHaveBeenLastCalledWith(0.2);
|
|
2101
|
-
});
|
|
2102
|
-
|
|
2103
|
-
it('starts an empty value at the relevant boundary', () => {
|
|
2104
|
-
const onChange = vi.fn();
|
|
2105
|
-
const {rerender} = render(
|
|
2106
|
-
<NumberInput label="Amount" value={null} onChange={onChange} min={2} />,
|
|
2107
|
-
);
|
|
2108
|
-
fireEvent.keyDown(screen.getByRole('spinbutton'), {key: 'ArrowUp'});
|
|
2109
|
-
expect(onChange).toHaveBeenLastCalledWith(2);
|
|
2110
|
-
|
|
2111
|
-
rerender(
|
|
2112
|
-
<NumberInput label="Amount" value={null} onChange={onChange} max={8} />,
|
|
2113
|
-
);
|
|
2114
|
-
fireEvent.keyDown(screen.getByRole('spinbutton'), {key: 'ArrowDown'});
|
|
2115
|
-
expect(onChange).toHaveBeenLastCalledWith(8);
|
|
2116
|
-
});
|
|
2117
|
-
|
|
2118
|
-
it('keeps generated values integral when isIntegerOnly is set', () => {
|
|
2119
|
-
const onChange = vi.fn();
|
|
2120
|
-
render(
|
|
2121
|
-
<NumberInput
|
|
2122
|
-
label="Amount"
|
|
2123
|
-
value={null}
|
|
2124
|
-
onChange={onChange}
|
|
2125
|
-
min={2.5}
|
|
2126
|
-
isIntegerOnly
|
|
2127
|
-
/>,
|
|
2128
|
-
);
|
|
2129
|
-
fireEvent.keyDown(screen.getByRole('spinbutton'), {key: 'ArrowUp'});
|
|
2130
|
-
expect(onChange).toHaveBeenCalledWith(3);
|
|
2131
|
-
});
|
|
2132
|
-
|
|
2133
|
-
it('does not step past min or max', () => {
|
|
2134
|
-
const onChange = vi.fn();
|
|
2135
|
-
const {rerender} = render(
|
|
2136
|
-
<NumberInput
|
|
2137
|
-
label="Amount"
|
|
2138
|
-
value={10}
|
|
2139
|
-
onChange={onChange}
|
|
2140
|
-
min={0}
|
|
2141
|
-
max={10}
|
|
2142
|
-
/>,
|
|
2143
|
-
);
|
|
2144
|
-
fireEvent.keyDown(screen.getByRole('spinbutton'), {key: 'ArrowUp'});
|
|
2145
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
2146
|
-
|
|
2147
|
-
rerender(
|
|
2148
|
-
<NumberInput
|
|
2149
|
-
label="Amount"
|
|
2150
|
-
value={0}
|
|
2151
|
-
onChange={onChange}
|
|
2152
|
-
min={0}
|
|
2153
|
-
max={10}
|
|
2154
|
-
/>,
|
|
2155
|
-
);
|
|
2156
|
-
fireEvent.keyDown(screen.getByRole('spinbutton'), {key: 'ArrowDown'});
|
|
2157
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
2158
|
-
});
|
|
2159
|
-
|
|
2160
|
-
it.each(stepInteractions)(
|
|
2161
|
-
'clamps at a fractional max after rounding via the %s',
|
|
2162
|
-
(_name, interact) => {
|
|
2163
|
-
const onChange = vi.fn();
|
|
2164
|
-
render(
|
|
2165
|
-
<NumberInput
|
|
2166
|
-
label="Amount"
|
|
2167
|
-
value={99}
|
|
2168
|
-
onChange={onChange}
|
|
2169
|
-
max={99.99}
|
|
2170
|
-
hasNumberSteppers
|
|
2171
|
-
/>,
|
|
2172
|
-
);
|
|
2173
|
-
|
|
2174
|
-
interact(screen.getByRole('spinbutton'), 'up');
|
|
2175
|
-
|
|
2176
|
-
expect(onChange).toHaveBeenCalledWith(99.99);
|
|
2177
|
-
expect(onChange).not.toHaveBeenCalledWith(100);
|
|
2178
|
-
},
|
|
2179
|
-
);
|
|
2180
|
-
|
|
2181
|
-
it.each(stepInteractions)(
|
|
2182
|
-
'clamps at a fractional min after rounding via the %s',
|
|
2183
|
-
(_name, interact) => {
|
|
2184
|
-
const onChange = vi.fn();
|
|
2185
|
-
const min = 4e-13;
|
|
2186
|
-
render(
|
|
2187
|
-
<NumberInput
|
|
2188
|
-
label="Amount"
|
|
2189
|
-
value={0.5}
|
|
2190
|
-
onChange={onChange}
|
|
2191
|
-
min={min}
|
|
2192
|
-
hasNumberSteppers
|
|
2193
|
-
/>,
|
|
2194
|
-
);
|
|
2195
|
-
|
|
2196
|
-
interact(screen.getByRole('spinbutton'), 'down');
|
|
2197
|
-
|
|
2198
|
-
expect(onChange).toHaveBeenCalledWith(min);
|
|
2199
|
-
expect(onChange).not.toHaveBeenCalledWith(0);
|
|
2200
|
-
},
|
|
2201
|
-
);
|
|
2202
|
-
|
|
2203
|
-
it('reflects a reached fractional max in the spinbutton and stepper state', () => {
|
|
2204
|
-
function ControlledNumberInput() {
|
|
2205
|
-
const [value, setValue] = useState(99);
|
|
2206
|
-
return (
|
|
2207
|
-
<NumberInput
|
|
2208
|
-
label="Amount"
|
|
2209
|
-
value={value}
|
|
2210
|
-
onChange={setValue}
|
|
2211
|
-
max={99.99}
|
|
2212
|
-
hasNumberSteppers
|
|
2213
|
-
/>
|
|
2214
|
-
);
|
|
2215
|
-
}
|
|
2216
|
-
render(<ControlledNumberInput />);
|
|
2217
|
-
|
|
2218
|
-
const input = screen.getByRole('spinbutton');
|
|
2219
|
-
const increment = screen.getByRole('button', {name: 'Increment Amount'});
|
|
2220
|
-
expect(increment).not.toHaveAttribute('aria-disabled');
|
|
2221
|
-
|
|
2222
|
-
fireEvent.click(increment);
|
|
2223
|
-
|
|
2224
|
-
expect(input).toHaveValue('99.99');
|
|
2225
|
-
expect(input).toHaveAttribute('aria-valuenow', '99.99');
|
|
2226
|
-
expect(input).not.toHaveAttribute('aria-invalid');
|
|
2227
|
-
expect(increment).toHaveAttribute('aria-disabled', 'true');
|
|
2228
|
-
});
|
|
2229
|
-
|
|
2230
|
-
it('allows wheel stepping by default and consumes the focused gesture', () => {
|
|
2231
|
-
const onScrollableWheel = vi.fn();
|
|
2232
|
-
const onChange = vi.fn();
|
|
2233
|
-
render(
|
|
2234
|
-
<div onWheel={onScrollableWheel}>
|
|
2235
|
-
<NumberInput label="Amount" value={5} onChange={onChange} />
|
|
2236
|
-
</div>,
|
|
2237
|
-
);
|
|
2238
|
-
const input = screen.getByRole<HTMLInputElement>('spinbutton');
|
|
2239
|
-
input.focus();
|
|
2240
|
-
const event = new WheelEvent('wheel', {
|
|
2241
|
-
bubbles: true,
|
|
2242
|
-
cancelable: true,
|
|
2243
|
-
deltaY: -100,
|
|
2244
|
-
});
|
|
2245
|
-
fireEvent(input, event);
|
|
2246
|
-
|
|
2247
|
-
expect(onChange).toHaveBeenCalledWith(6);
|
|
2248
|
-
expect(event.defaultPrevented).toBe(true);
|
|
2249
|
-
expect(onScrollableWheel).not.toHaveBeenCalled();
|
|
2250
|
-
});
|
|
2251
|
-
|
|
2252
|
-
it('leaves wheel scrolling alone when isWheelEnabled is false', () => {
|
|
2253
|
-
const onScrollableWheel = vi.fn();
|
|
2254
|
-
const onChange = vi.fn();
|
|
2255
|
-
render(
|
|
2256
|
-
<div onWheel={onScrollableWheel}>
|
|
2257
|
-
<NumberInput
|
|
2258
|
-
label="Amount"
|
|
2259
|
-
value={5}
|
|
2260
|
-
onChange={onChange}
|
|
2261
|
-
isWheelEnabled={false}
|
|
2262
|
-
/>
|
|
2263
|
-
</div>,
|
|
2264
|
-
);
|
|
2265
|
-
const input = screen.getByRole<HTMLInputElement>('spinbutton');
|
|
2266
|
-
input.focus();
|
|
2267
|
-
const event = new WheelEvent('wheel', {
|
|
2268
|
-
bubbles: true,
|
|
2269
|
-
cancelable: true,
|
|
2270
|
-
deltaY: -100,
|
|
2271
|
-
});
|
|
2272
|
-
fireEvent(input, event);
|
|
2273
|
-
|
|
2274
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
2275
|
-
expect(event.defaultPrevented).toBe(false);
|
|
2276
|
-
expect(onScrollableWheel).toHaveBeenCalledTimes(1);
|
|
2277
|
-
});
|
|
2278
|
-
|
|
2279
|
-
it('updates the wheel listener when isWheelEnabled changes', () => {
|
|
2280
|
-
const onScrollableWheel = vi.fn();
|
|
2281
|
-
const onChange = vi.fn();
|
|
2282
|
-
const {rerender} = render(
|
|
2283
|
-
<div onWheel={onScrollableWheel}>
|
|
2284
|
-
<NumberInput
|
|
2285
|
-
label="Amount"
|
|
2286
|
-
value={5}
|
|
2287
|
-
onChange={onChange}
|
|
2288
|
-
isWheelEnabled={false}
|
|
2289
|
-
/>
|
|
2290
|
-
</div>,
|
|
2291
|
-
);
|
|
2292
|
-
const input = screen.getByRole<HTMLInputElement>('spinbutton');
|
|
2293
|
-
input.focus();
|
|
2294
|
-
|
|
2295
|
-
rerender(
|
|
2296
|
-
<div onWheel={onScrollableWheel}>
|
|
2297
|
-
<NumberInput
|
|
2298
|
-
label="Amount"
|
|
2299
|
-
value={5}
|
|
2300
|
-
onChange={onChange}
|
|
2301
|
-
isWheelEnabled
|
|
2302
|
-
/>
|
|
2303
|
-
</div>,
|
|
2304
|
-
);
|
|
2305
|
-
fireEvent.wheel(input, {deltaY: -100});
|
|
2306
|
-
expect(onChange).toHaveBeenCalledWith(6);
|
|
2307
|
-
expect(onScrollableWheel).not.toHaveBeenCalled();
|
|
2308
|
-
|
|
2309
|
-
onChange.mockClear();
|
|
2310
|
-
rerender(
|
|
2311
|
-
<div onWheel={onScrollableWheel}>
|
|
2312
|
-
<NumberInput
|
|
2313
|
-
label="Amount"
|
|
2314
|
-
value={5}
|
|
2315
|
-
onChange={onChange}
|
|
2316
|
-
isWheelEnabled={false}
|
|
2317
|
-
/>
|
|
2318
|
-
</div>,
|
|
2319
|
-
);
|
|
2320
|
-
fireEvent.wheel(input, {deltaY: -100});
|
|
2321
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
2322
|
-
expect(onScrollableWheel).toHaveBeenCalledTimes(1);
|
|
2323
|
-
});
|
|
2324
|
-
|
|
2325
|
-
it('leaves wheel scrolling alone when the input is not focused', () => {
|
|
2326
|
-
const onScrollableWheel = vi.fn();
|
|
2327
|
-
const onChange = vi.fn();
|
|
2328
|
-
render(
|
|
2329
|
-
<div onWheel={onScrollableWheel}>
|
|
2330
|
-
<NumberInput label="Amount" value={5} onChange={onChange} />
|
|
2331
|
-
</div>,
|
|
2332
|
-
);
|
|
2333
|
-
const input = screen.getByRole('spinbutton');
|
|
2334
|
-
const event = new WheelEvent('wheel', {
|
|
2335
|
-
bubbles: true,
|
|
2336
|
-
cancelable: true,
|
|
2337
|
-
deltaY: 100,
|
|
2338
|
-
});
|
|
2339
|
-
fireEvent(input, event);
|
|
2340
|
-
|
|
2341
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
2342
|
-
expect(event.defaultPrevented).toBe(false);
|
|
2343
|
-
expect(onScrollableWheel).toHaveBeenCalledTimes(1);
|
|
2344
|
-
});
|
|
2345
|
-
|
|
2346
|
-
it('leaves modified wheel gestures alone', () => {
|
|
2347
|
-
const onScrollableWheel = vi.fn();
|
|
2348
|
-
const onChange = vi.fn();
|
|
2349
|
-
render(
|
|
2350
|
-
<div onWheel={onScrollableWheel}>
|
|
2351
|
-
<NumberInput label="Amount" value={5} onChange={onChange} />
|
|
2352
|
-
</div>,
|
|
2353
|
-
);
|
|
2354
|
-
const input = screen.getByRole<HTMLInputElement>('spinbutton');
|
|
2355
|
-
input.focus();
|
|
2356
|
-
fireEvent.wheel(input, {deltaY: -100, ctrlKey: true});
|
|
2357
|
-
|
|
2358
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
2359
|
-
expect(onScrollableWheel).toHaveBeenCalledTimes(1);
|
|
2360
|
-
});
|
|
2361
|
-
|
|
2362
|
-
it('leaves wheel scrolling alone when the input is aria-disabled', () => {
|
|
2363
|
-
const onScrollableWheel = vi.fn();
|
|
2364
|
-
const onChange = vi.fn();
|
|
2365
|
-
render(
|
|
2366
|
-
<div onWheel={onScrollableWheel}>
|
|
2367
|
-
<NumberInput
|
|
2368
|
-
label="Amount"
|
|
2369
|
-
value={5}
|
|
2370
|
-
onChange={onChange}
|
|
2371
|
-
isDisabled
|
|
2372
|
-
disabledMessage="This value is locked"
|
|
2373
|
-
/>
|
|
2374
|
-
</div>,
|
|
2375
|
-
);
|
|
2376
|
-
const input = screen.getByRole<HTMLInputElement>('spinbutton');
|
|
2377
|
-
input.focus();
|
|
2378
|
-
fireEvent.wheel(input, {deltaY: -100});
|
|
2379
|
-
|
|
2380
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
2381
|
-
expect(onScrollableWheel).toHaveBeenCalledTimes(1);
|
|
2382
|
-
});
|
|
2383
|
-
|
|
2384
|
-
describe('hasNumberSteppers', () => {
|
|
2385
|
-
it('does not show stepper buttons by default', () => {
|
|
2386
|
-
render(<NumberInput label="Quantity" value={5} onChange={() => {}} />);
|
|
2387
|
-
expect(
|
|
2388
|
-
screen.queryByRole('button', {name: 'Increment Quantity'}),
|
|
2389
|
-
).not.toBeInTheDocument();
|
|
2390
|
-
expect(
|
|
2391
|
-
screen.queryByRole('button', {name: 'Decrement Quantity'}),
|
|
2392
|
-
).not.toBeInTheDocument();
|
|
2393
|
-
});
|
|
2394
|
-
|
|
2395
|
-
it('shows localized increment and decrement buttons when enabled', () => {
|
|
2396
|
-
render(
|
|
2397
|
-
<NumberInput
|
|
2398
|
-
label="Quantity"
|
|
2399
|
-
value={5}
|
|
2400
|
-
onChange={() => {}}
|
|
2401
|
-
hasNumberSteppers
|
|
2402
|
-
/>,
|
|
2403
|
-
);
|
|
2404
|
-
expect(
|
|
2405
|
-
screen.getByRole('button', {name: 'Increment Quantity'}),
|
|
2406
|
-
).toHaveAttribute('tabindex', '-1');
|
|
2407
|
-
expect(
|
|
2408
|
-
screen.getByRole('button', {name: 'Decrement Quantity'}),
|
|
2409
|
-
).toHaveAttribute('tabindex', '-1');
|
|
2410
|
-
});
|
|
2411
|
-
|
|
2412
|
-
it('uses the NumberInput extension icon for both stepper buttons', () => {
|
|
2413
|
-
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
2414
|
-
registerIcons({
|
|
2415
|
-
chevronDown: <svg data-testid="generic-chevron-down" />,
|
|
2416
|
-
'numberInput:stepperDown': <svg data-testid="number-stepper-down" />,
|
|
2417
|
-
});
|
|
2418
|
-
|
|
2419
|
-
render(
|
|
2420
|
-
<NumberInput
|
|
2421
|
-
label="Quantity"
|
|
2422
|
-
value={5}
|
|
2423
|
-
onChange={() => {}}
|
|
2424
|
-
hasNumberSteppers
|
|
2425
|
-
/>,
|
|
2426
|
-
);
|
|
2427
|
-
|
|
2428
|
-
const stepperIcons = screen.getAllByTestId('number-stepper-down');
|
|
2429
|
-
expect(stepperIcons).toHaveLength(2);
|
|
2430
|
-
for (const icon of stepperIcons) {
|
|
2431
|
-
expect(icon.parentElement).toHaveAttribute('data-size', 'xsm');
|
|
2432
|
-
}
|
|
2433
|
-
expect(
|
|
2434
|
-
screen.queryByTestId('generic-chevron-down'),
|
|
2435
|
-
).not.toBeInTheDocument();
|
|
2436
|
-
warnSpy.mockRestore();
|
|
2437
|
-
});
|
|
2438
|
-
|
|
2439
|
-
it('steps the value and returns focus to the input', () => {
|
|
2440
|
-
const onChange = vi.fn();
|
|
2441
|
-
render(
|
|
2442
|
-
<NumberInput
|
|
2443
|
-
label="Quantity"
|
|
2444
|
-
value={5}
|
|
2445
|
-
onChange={onChange}
|
|
2446
|
-
hasNumberSteppers
|
|
2447
|
-
/>,
|
|
2448
|
-
);
|
|
2449
|
-
const input = screen.getByRole('spinbutton');
|
|
2450
|
-
|
|
2451
|
-
fireEvent.click(screen.getByRole('button', {name: 'Increment Quantity'}));
|
|
2452
|
-
expect(onChange).toHaveBeenLastCalledWith(6);
|
|
2453
|
-
expect(input).toHaveFocus();
|
|
2454
|
-
|
|
2455
|
-
fireEvent.click(screen.getByRole('button', {name: 'Decrement Quantity'}));
|
|
2456
|
-
expect(onChange).toHaveBeenLastCalledWith(4);
|
|
2457
|
-
expect(input).toHaveFocus();
|
|
2458
|
-
});
|
|
2459
|
-
|
|
2460
|
-
it('disables only the stepper at the reached boundary', () => {
|
|
2461
|
-
render(
|
|
2462
|
-
<NumberInput
|
|
2463
|
-
label="Quantity"
|
|
2464
|
-
value={10}
|
|
2465
|
-
onChange={() => {}}
|
|
2466
|
-
min={0}
|
|
2467
|
-
max={10}
|
|
2468
|
-
hasNumberSteppers
|
|
2469
|
-
/>,
|
|
2470
|
-
);
|
|
2471
|
-
expect(
|
|
2472
|
-
screen.getByRole('button', {name: 'Increment Quantity'}),
|
|
2473
|
-
).toHaveAttribute('aria-disabled', 'true');
|
|
2474
|
-
expect(
|
|
2475
|
-
screen.getByRole('button', {name: 'Decrement Quantity'}),
|
|
2476
|
-
).not.toHaveAttribute('aria-disabled');
|
|
2477
|
-
});
|
|
2478
|
-
|
|
2479
|
-
it('commits nothing from a click on the stepper at the reached boundary (spec:AST-085 FR2)', async () => {
|
|
2480
|
-
const user = userEvent.setup();
|
|
2481
|
-
const onChange = vi.fn();
|
|
2482
|
-
render(
|
|
2483
|
-
<NumberInput
|
|
2484
|
-
label="Quantity"
|
|
2485
|
-
value={5}
|
|
2486
|
-
onChange={onChange}
|
|
2487
|
-
min={0}
|
|
2488
|
-
max={10}
|
|
2489
|
-
hasNumberSteppers
|
|
2490
|
-
/>,
|
|
2491
|
-
);
|
|
2492
|
-
const input = screen.getByRole('spinbutton');
|
|
2493
|
-
await user.clear(input);
|
|
2494
|
-
await user.type(input, '10');
|
|
2495
|
-
onChange.mockClear();
|
|
2496
|
-
await user.click(
|
|
2497
|
-
screen.getByRole('button', {name: 'Increment Quantity'}),
|
|
2498
|
-
);
|
|
2499
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
2500
|
-
});
|
|
2501
|
-
|
|
2502
|
-
it('disables both steppers with the input', () => {
|
|
2503
|
-
render(
|
|
2504
|
-
<NumberInput
|
|
2505
|
-
label="Quantity"
|
|
2506
|
-
value={5}
|
|
2507
|
-
onChange={() => {}}
|
|
2508
|
-
hasNumberSteppers
|
|
2509
|
-
isDisabled
|
|
2510
|
-
/>,
|
|
2511
|
-
);
|
|
2512
|
-
expect(
|
|
2513
|
-
screen.getByRole('button', {name: 'Increment Quantity'}),
|
|
2514
|
-
).toHaveAttribute('aria-disabled', 'true');
|
|
2515
|
-
expect(
|
|
2516
|
-
screen.getByRole('button', {name: 'Decrement Quantity'}),
|
|
2517
|
-
).toHaveAttribute('aria-disabled', 'true');
|
|
2518
|
-
});
|
|
2519
|
-
});
|
|
2520
|
-
});
|
|
2521
|
-
|
|
2522
|
-
describe('NumberInput disabled theme state', () => {
|
|
2523
|
-
it('reflects disabled on the root target so themes can gate paint on it', () => {
|
|
2524
|
-
const {container} = render(
|
|
2525
|
-
<NumberInput
|
|
2526
|
-
label="Quantity"
|
|
2527
|
-
value={null}
|
|
2528
|
-
onChange={() => {}}
|
|
2529
|
-
isDisabled
|
|
2530
|
-
/>,
|
|
2531
|
-
);
|
|
2532
|
-
const root = container.querySelector('.astryx-number-input');
|
|
2533
|
-
expect(root).toHaveAttribute('data-disabled', 'disabled');
|
|
2534
|
-
});
|
|
2535
|
-
|
|
2536
|
-
it('omits data-disabled when enabled, like status does', () => {
|
|
2537
|
-
const {container} = render(
|
|
2538
|
-
<NumberInput label="Quantity" value={null} onChange={() => {}} />,
|
|
2539
|
-
);
|
|
2540
|
-
const root = container.querySelector('.astryx-number-input');
|
|
2541
|
-
expect(root).not.toHaveAttribute('data-disabled');
|
|
2542
|
-
});
|
|
2543
|
-
});
|
|
2544
|
-
|
|
2545
|
-
describe('NumberInput readonly theme state', () => {
|
|
2546
|
-
it('reflects readonly on the root target so themes can gate paint on it', () => {
|
|
2547
|
-
const {container} = render(
|
|
2548
|
-
<NumberInput label="Qty" value={1} onChange={() => {}} isReadOnly />,
|
|
2549
|
-
);
|
|
2550
|
-
const root = container.querySelector('.astryx-number-input');
|
|
2551
|
-
expect(root).toHaveAttribute('data-readonly', 'readonly');
|
|
2552
|
-
});
|
|
2553
|
-
|
|
2554
|
-
it('omits data-readonly when editable', () => {
|
|
2555
|
-
const {container} = render(
|
|
2556
|
-
<NumberInput label="Qty" value={1} onChange={() => {}} />,
|
|
2557
|
-
);
|
|
2558
|
-
const root = container.querySelector('.astryx-number-input');
|
|
2559
|
-
expect(root).not.toHaveAttribute('data-readonly');
|
|
2560
|
-
});
|
|
2561
|
-
});
|
|
2562
|
-
|
|
2563
|
-
describe('NumberInput stepper padding coupling', () => {
|
|
2564
|
-
function generateThemeTestCSS(theme: Parameters<typeof generateThemeCSS>[0]) {
|
|
2565
|
-
const {prose, component} = generateThemeCSS(theme);
|
|
2566
|
-
return [prose, component].filter(Boolean).join('\n\n');
|
|
2567
|
-
}
|
|
2568
|
-
|
|
2569
|
-
// The chains the wrapper and the stepper column both read. Spelled out here
|
|
2570
|
-
// rather than imported so the test pins the actual token names a theme sets:
|
|
2571
|
-
// if the chain is renamed or a level is dropped, this fails.
|
|
2572
|
-
const BLOCK_START =
|
|
2573
|
-
'var(--astryx-number-input-padding-block-start, var(--astryx-number-input-padding, var(--spacing-1)))';
|
|
2574
|
-
const BLOCK_END =
|
|
2575
|
-
'var(--astryx-number-input-padding-block-end, var(--astryx-number-input-padding, var(--spacing-1)))';
|
|
2576
|
-
|
|
2577
|
-
// jsdom re-serializes a var() chain without the spaces after its commas.
|
|
2578
|
-
const noSpace = (value: string) => value.replace(/\s+/g, '');
|
|
2579
|
-
|
|
2580
|
-
it('reads its padding from the public number-input padding tokens', () => {
|
|
2581
|
-
const {container} = render(
|
|
2582
|
-
<NumberInput
|
|
2583
|
-
label="Quantity"
|
|
2584
|
-
value={5}
|
|
2585
|
-
onChange={() => {}}
|
|
2586
|
-
hasNumberSteppers
|
|
2587
|
-
/>,
|
|
2588
|
-
);
|
|
2589
|
-
const root = container.querySelector('.astryx-number-input') as HTMLElement;
|
|
2590
|
-
// Read as physical properties: StyleX compiles the block-axis logical
|
|
2591
|
-
// properties to `padding-top`/`padding-bottom` (identical in every
|
|
2592
|
-
// horizontal writing mode). Per side, not through the shared field base's
|
|
2593
|
-
// `paddingBlock` shorthand, so each edge can be cancelled on its own.
|
|
2594
|
-
const wrapper = getComputedStyle(root);
|
|
2595
|
-
expect(noSpace(wrapper.paddingTop)).toBe(noSpace(BLOCK_START));
|
|
2596
|
-
expect(noSpace(wrapper.paddingBottom)).toBe(noSpace(BLOCK_END));
|
|
2597
|
-
|
|
2598
|
-
// The column cancels the wrapper's block padding by reading the same
|
|
2599
|
-
// tokens — not a hardcoded default — so it stays flush when a theme
|
|
2600
|
-
// changes the padding. The column is the stepper buttons' direct parent.
|
|
2601
|
-
const steppers = container.querySelector(
|
|
2602
|
-
'button[aria-label="Increment Quantity"]',
|
|
2603
|
-
)?.parentElement as HTMLElement;
|
|
2604
|
-
const column = getComputedStyle(steppers);
|
|
2605
|
-
expect(noSpace(column.marginTop)).toBe(
|
|
2606
|
-
noSpace(`calc(-1 * ${BLOCK_START})`),
|
|
2607
|
-
);
|
|
2608
|
-
expect(noSpace(column.marginBottom)).toBe(
|
|
2609
|
-
noSpace(`calc(-1 * ${BLOCK_END})`),
|
|
2610
|
-
);
|
|
2611
|
-
});
|
|
2612
|
-
|
|
2613
|
-
// jsdom cannot resolve the @layer cascade, so the generated CSS is the
|
|
2614
|
-
// proof. Each case is a spelling of the SAME declaration: the column has to
|
|
2615
|
-
// track all of them, not just the one the component happened to name.
|
|
2616
|
-
describe('a themed padding reaches the steppers in every spelling', () => {
|
|
2617
|
-
it.each([
|
|
2618
|
-
[
|
|
2619
|
-
'the padding shorthand, two values',
|
|
2620
|
-
{padding: '14px 20px'},
|
|
2621
|
-
[
|
|
2622
|
-
'--astryx-number-input-padding-block-start: 14px',
|
|
2623
|
-
'--astryx-number-input-padding-block-end: 14px',
|
|
2624
|
-
'--astryx-number-input-padding-inline: 20px',
|
|
2625
|
-
],
|
|
2626
|
-
],
|
|
2627
|
-
[
|
|
2628
|
-
'the padding shorthand, one value',
|
|
2629
|
-
{padding: '10px'},
|
|
2630
|
-
['--astryx-number-input-padding: 10px'],
|
|
2631
|
-
],
|
|
2632
|
-
[
|
|
2633
|
-
'the block/inline longhands',
|
|
2634
|
-
{paddingBlock: '10px', paddingInline: '20px'},
|
|
2635
|
-
[
|
|
2636
|
-
'--astryx-number-input-padding-block-start: 10px',
|
|
2637
|
-
'--astryx-number-input-padding-block-end: 10px',
|
|
2638
|
-
'--astryx-number-input-padding-inline: 20px',
|
|
2639
|
-
],
|
|
2640
|
-
],
|
|
2641
|
-
[
|
|
2642
|
-
'a single edge longhand',
|
|
2643
|
-
{paddingBlockStart: '12px'},
|
|
2644
|
-
['--astryx-number-input-padding-block-start: 12px'],
|
|
2645
|
-
],
|
|
2646
|
-
[
|
|
2647
|
-
// A single var carrying "4px 12px" would make the column's
|
|
2648
|
-
// calc(-1 * …) invalid and drop the margin outright; the expansion
|
|
2649
|
-
// splits the two values into their own edges instead.
|
|
2650
|
-
'an asymmetric block padding',
|
|
2651
|
-
{paddingBlock: '4px 12px'},
|
|
2652
|
-
[
|
|
2653
|
-
'--astryx-number-input-padding-block-start: 4px',
|
|
2654
|
-
'--astryx-number-input-padding-block-end: 12px',
|
|
2655
|
-
],
|
|
2656
|
-
],
|
|
2657
|
-
[
|
|
2658
|
-
// `paddingTop` is `paddingBlockStart` in every horizontal writing
|
|
2659
|
-
// mode, so it normalizes onto the same tokens. The physical inline
|
|
2660
|
-
// pair is deliberately not mapped — see generateThemeRules.
|
|
2661
|
-
'the physical block longhands',
|
|
2662
|
-
{paddingTop: '14px', paddingBottom: '6px'},
|
|
2663
|
-
[
|
|
2664
|
-
'--astryx-number-input-padding-block-start: 14px',
|
|
2665
|
-
'--astryx-number-input-padding-block-end: 6px',
|
|
2666
|
-
],
|
|
2667
|
-
],
|
|
2668
|
-
])('%s', (_label, base, expected) => {
|
|
2669
|
-
const theme = defineTheme({
|
|
2670
|
-
name: 'number-input-padding-spelling-test',
|
|
2671
|
-
components: {'number-input': {base}},
|
|
2672
|
-
});
|
|
2673
|
-
const css = generateThemeTestCSS(theme);
|
|
2674
|
-
for (const declaration of expected) {
|
|
2675
|
-
expect(css).toContain(declaration);
|
|
2676
|
-
}
|
|
2677
|
-
// The expansion consumes the padding: a raw declaration left on the
|
|
2678
|
-
// wrapper is padding the column cannot see, which is the gap itself.
|
|
2679
|
-
expect(css).not.toMatch(
|
|
2680
|
-
/^\s*padding(-block|-inline|-top|-bottom)?(-start|-end)?:/m,
|
|
2681
|
-
);
|
|
2682
|
-
});
|
|
2683
|
-
});
|
|
2684
|
-
|
|
2685
|
-
it('carries a themed border radius to the stepper column corners', () => {
|
|
2686
|
-
// The column's outer corners read --_field-radius. Emitting only
|
|
2687
|
-
// `border-radius` on the wrapper rounds the field and leaves the steppers
|
|
2688
|
-
// at the default radius, which is visible wherever the two differ.
|
|
2689
|
-
const theme = defineTheme({
|
|
2690
|
-
name: 'number-input-radius-test',
|
|
2691
|
-
components: {'number-input': {base: {borderRadius: '2px'}}},
|
|
2692
|
-
});
|
|
2693
|
-
const css = generateThemeTestCSS(theme);
|
|
2694
|
-
expect(css).toContain('--_field-radius: 2px');
|
|
2695
|
-
expect(css).toContain('border-radius: 2px');
|
|
2696
|
-
});
|
|
2697
|
-
});
|