@astryxdesign/core 0.7.6-canary.f73623d → 0.7.6-canary.f899313
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/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +2 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +8 -2
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +17 -18
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +8 -4
- package/dist/DropdownMenu/DropdownMenuGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuGroup.js +2 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +27 -2
- package/dist/FieldStatus/FieldStatus.d.ts +3 -0
- package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
- package/dist/FieldStatus/FieldStatus.js +1 -0
- package/dist/FileInput/FileInput.d.ts +3 -0
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +59 -33
- package/dist/Layer/useTouchTrigger.d.ts +9 -0
- package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
- package/dist/Layer/useTouchTrigger.js +1 -1
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +10 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +19 -9
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +11 -15
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +9 -6
- package/dist/Selector/hooks.js +2 -2
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +82 -10
- 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.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +16 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +10 -3
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +36 -10
- package/dist/astryx.css +1 -1
- 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/package.json +18 -5
- package/src/Badge/Badge.tsx +2 -1
- package/src/Chat/ChatMessage.spec.md +64 -65
- package/src/Citation/Citation.spec.md +60 -47
- package/src/ComplexSelector/ComplexSelector.tsx +19 -2
- package/src/DateInput/DateInput.spec.md +74 -57
- package/src/DateInput/MonthScroller.tsx +15 -17
- package/src/DateRangeInput/DateRangeInput.tsx +18 -3
- package/src/DropdownMenu/DropdownMenuGroup.tsx +2 -1
- package/src/Field/Field.doc.mjs +2 -1
- package/src/Field/FieldLabel.doc.mjs +4 -2
- package/src/Field/FieldLabel.spec.md +30 -21
- package/src/Field/FieldLabel.tsx +37 -3
- package/src/FieldStatus/FieldStatus.tsx +7 -0
- package/src/FileInput/FileInput.tsx +69 -28
- package/src/FormLayout/FormLayout.spec.md +11 -19
- package/src/Layer/useTouchTrigger.ts +1 -1
- package/src/Lightbox/Lightbox.spec.md +249 -61
- package/src/Link/Link.tsx +9 -2
- package/src/MultiSelector/MultiSelector.spec.md +121 -114
- package/src/MultiSelector/MultiSelector.tsx +19 -5
- package/src/NumberInput/NumberInput.tsx +11 -18
- package/src/ProgressBar/ProgressBar.spec.md +143 -119
- package/src/Selector/Selector.tsx +16 -6
- package/src/Selector/hooks.ts +2 -2
- package/src/Slider/Slider.spec.md +18 -16
- package/src/Slider/Slider.tsx +101 -9
- package/src/Token/Token.spec.md +24 -23
- package/src/Token/Token.tsx +15 -0
- package/src/Tokenizer/Tokenizer.tsx +10 -0
- package/src/Typeahead/BaseTypeahead.tsx +18 -2
- package/src/Typeahead/Typeahead.tsx +40 -9
- package/src/i18n/useListFormatter.ts +42 -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.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.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.test.tsx +0 -398
- package/src/AspectRatio/__tests__/AspectRatioFitLayers.a11y.browser.spec.ts +0 -158
- package/src/Avatar/Avatar.test.tsx +0 -867
- package/src/Avatar/AvatarStatusDot.test.tsx +0 -306
- package/src/Avatar/__tests__/AvatarForcedColors.a11y.chromium.spec.ts +0 -126
- package/src/AvatarGroup/AvatarGroup.test.tsx +0 -313
- package/src/AvatarGroup/AvatarGroupOverflow.test.tsx +0 -263
- package/src/Badge/Badge.test.tsx +0 -125
- package/src/Badge/__tests__/BadgeLargerText.a11y.chromium.spec.ts +0 -260
- package/src/Banner/Banner.test.tsx +0 -879
- package/src/Blockquote/Blockquote.test.tsx +0 -121
- 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.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/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.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.test.tsx +0 -1025
- 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.test.tsx +0 -202
- 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.test.tsx +0 -406
- package/src/Chat/ChatComposer.test.tsx +0 -364
- package/src/Chat/ChatComposerDrawer.test.tsx +0 -130
- package/src/Chat/ChatComposerInput.test.tsx +0 -2136
- package/src/Chat/ChatComposerTokenElement.test.tsx +0 -85
- package/src/Chat/ChatDictationButton.test.tsx +0 -108
- package/src/Chat/ChatLayout.test.tsx +0 -311
- package/src/Chat/ChatLayoutScrollButton.test.tsx +0 -99
- package/src/Chat/ChatMessage.test.tsx +0 -344
- package/src/Chat/ChatMessageBubble.test.tsx +0 -294
- package/src/Chat/ChatMessageList.test.tsx +0 -198
- package/src/Chat/ChatMessageMetadata.test.tsx +0 -66
- package/src/Chat/ChatPastedTextToken.test.tsx +0 -71
- package/src/Chat/ChatSendButton.test.tsx +0 -309
- package/src/Chat/ChatSystemMessage.test.tsx +0 -189
- package/src/Chat/ChatTokenizedText.test.tsx +0 -163
- 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.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.test.tsx +0 -1159
- package/src/CheckboxList/__tests__/CheckboxList.a11y.chromium.spec.ts +0 -1998
- package/src/Citation/Citation.test.tsx +0 -361
- package/src/ClickableCard/ClickableCard.test.tsx +0 -382
- package/src/Code/Code.test.tsx +0 -75
- package/src/CodeBlock/CodeBlock.highlightStyles.test.tsx +0 -87
- 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.test.tsx +0 -620
- 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.test.tsx +0 -750
- 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.test.tsx +0 -539
- package/src/CommandPalette/CommandPaletteItem.test.tsx +0 -417
- 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.test.tsx +0 -1171
- package/src/ComplexSelector/__tests__/ComplexSelector.a11y.chromium.spec.ts +0 -965
- package/src/ContextMenu/ContextMenu.test.tsx +0 -1617
- package/src/ContextMenu/ContextMenu.triggerProps.test.tsx +0 -54
- 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.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.test.tsx +0 -1151
- package/src/DateTimeInput/DateTimeInput.fr10.test.tsx +0 -319
- 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.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/useImperativeDialog.test.tsx +0 -78
- package/src/Divider/Divider.test.tsx +0 -155
- package/src/Drawer/Drawer.test.tsx +0 -1335
- package/src/Drawer/DrawerDirection.test.tsx +0 -127
- 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.ssr.test.tsx +0 -93
- package/src/DropdownMenu/DropdownMenu.test.tsx +0 -4498
- package/src/DropdownMenu/DropdownMenuContext.public.test.ts +0 -22
- package/src/DropdownMenu/DropdownMenuLazySheet.test.tsx +0 -126
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +0 -635
- package/src/DropdownMenu/DropdownMenuSheetFirstOpen.test.tsx +0 -72
- 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/EmptyState/EmptyState.announce.test.tsx +0 -227
- package/src/EmptyState/EmptyState.test.tsx +0 -284
- package/src/Field/Field.test.tsx +0 -800
- 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.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.test.tsx +0 -1291
- package/src/FormLayout/FormLayout.test.tsx +0 -444
- package/src/FormLayout/__snapshots__/FormLayout.test.tsx.snap +0 -46
- package/src/Grid/Grid.test.tsx +0 -509
- package/src/HStack/HStack.test.tsx +0 -129
- package/src/Heading/Heading.test.tsx +0 -328
- package/src/HoverCard/HoverCard.test.tsx +0 -1339
- package/src/Icon/Icon.test.tsx +0 -990
- package/src/Icon/globalIconRegistry.test.tsx +0 -613
- package/src/IconButton/IconButton.test.tsx +0 -156
- package/src/Indicator/Indicator.test.tsx +0 -389
- package/src/Indicator/indicatorRegistry.test.tsx +0 -106
- package/src/InputGroup/InputGroup.test.tsx +0 -502
- package/src/InteractiveRoleContext/InteractiveRoleContext.test.tsx +0 -185
- package/src/Item/Item.source-build.test.mjs +0 -88
- 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.test.tsx +0 -299
- 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.test.tsx +0 -375
- 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.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.test.tsx +0 -457
- 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.test.tsx +0 -1052
- package/src/List/ListItem.source-build.test.mjs +0 -41
- 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.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/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.test.tsx +0 -383
- 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.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.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.test.tsx +0 -41
- 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.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.test.tsx +0 -1134
- package/src/Outline/OutlineFocus.a11y.chromium.spec.ts +0 -551
- package/src/Outline/parseOutlineFromMarkdown.test.ts +0 -104
- package/src/OverflowList/OverflowList.test.tsx +0 -1073
- package/src/Overlay/Overlay.test.tsx +0 -424
- package/src/Pagination/Pagination.test.tsx +0 -1754
- 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.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.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.test.tsx +0 -1051
- package/src/RadioList/RadioListItem.press.source-build.test.mjs +0 -80
- 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/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.test.tsx +0 -304
- package/src/Section/Section.test.tsx +0 -376
- package/src/SegmentedControl/SegmentedControl.test.tsx +0 -981
- 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.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.test.tsx +0 -4275
- package/src/SideNav/SideNavRailMotion.test.tsx +0 -620
- package/src/SideNav/__tests__/SideNavRailMotion.interaction.browser.spec.ts +0 -542
- package/src/SizeContext/SizeContext.test.tsx +0 -226
- package/src/Skeleton/Skeleton.test.tsx +0 -148
- package/src/Slider/Slider.fr10.test.tsx +0 -93
- 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.test.tsx +0 -484
- package/src/Stack/Stack.test.tsx +0 -473
- package/src/Stack/StackItem.test.tsx +0 -105
- package/src/StatusDot/StatusDot.test.tsx +0 -213
- package/src/Stepper/Stepper.public.test.ts +0 -91
- package/src/Stepper/Stepper.test.tsx +0 -2130
- package/src/Switch/Switch.focusRing.source-build.test.mjs +0 -81
- 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/TabList.test.tsx +0 -1755
- 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.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/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/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.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/tableContextMenu.test.tsx +0 -208
- 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.test.tsx +0 -1317
- package/src/TextInput/TextInput.fr10.test.tsx +0 -21
- 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.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.test.tsx +0 -907
- package/src/Timer/Timer.test.tsx +0 -302
- package/src/Timestamp/Timestamp.test.tsx +0 -1661
- package/src/Timestamp/tooltipEntries.test.ts +0 -566
- 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.test.tsx +0 -1000
- 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.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.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.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.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.test.tsx +0 -863
- package/src/TopNav/TopNavMegaMenu.reduced-motion.source-build.test.mjs +0 -83
- package/src/TopNav/TopNavMegaMenu.test.tsx +0 -1153
- package/src/TopNav/TopNavMenu.test.tsx +0 -502
- package/src/TopNav/__tests__/TopNavMobileLongHeading.a11y.chromium.spec.ts +0 -75
- 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.test.tsx +0 -553
- package/src/Typeahead/Typeahead.fr10.test.tsx +0 -28
- 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.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/__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,1661 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file Slider.test.tsx
|
|
5
|
-
* @input Uses vitest, @testing-library/react, userEvent, Slider component
|
|
6
|
-
* @output Unit tests for Slider behavior and modifier-only focus-ring suppression
|
|
7
|
-
* @position Testing; validates Slider.tsx implementation
|
|
8
|
-
*
|
|
9
|
-
* SYNC: When Slider.tsx changes, update tests to match new behavior
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import {InternationalizationProvider} from '../i18n';
|
|
13
|
-
import {useState} from 'react';
|
|
14
|
-
import {describe, it, expect, vi, beforeEach} from 'vitest';
|
|
15
|
-
import {render, screen, act, fireEvent, waitFor} from '@testing-library/react';
|
|
16
|
-
import userEvent from '@testing-library/user-event';
|
|
17
|
-
import {
|
|
18
|
-
declaresPressedOverlay,
|
|
19
|
-
rulesDeclaredFor,
|
|
20
|
-
} from '../__tests__/pressState';
|
|
21
|
-
import * as stylex from '@stylexjs/stylex';
|
|
22
|
-
import {Slider} from './Slider';
|
|
23
|
-
import {FormLayout} from '../FormLayout';
|
|
24
|
-
import {focusOutlineStyles} from '../utils/focusOutline.stylex';
|
|
25
|
-
import {
|
|
26
|
-
__resetInteractionModalityForTest,
|
|
27
|
-
getInteractionModality,
|
|
28
|
-
} from '../utils/interactionModality';
|
|
29
|
-
|
|
30
|
-
// Mock showPopover/hidePopover (not implemented in jsdom) so the tooltip layer
|
|
31
|
-
// reflects its open state via a `popover-open` attribute the tests can assert.
|
|
32
|
-
beforeEach(() => {
|
|
33
|
-
HTMLElement.prototype.showPopover = vi.fn(function (this: HTMLElement) {
|
|
34
|
-
this.setAttribute('popover-open', '');
|
|
35
|
-
const event = new Event('toggle', {bubbles: false});
|
|
36
|
-
Object.defineProperty(event, 'newState', {value: 'open'});
|
|
37
|
-
this.dispatchEvent(event);
|
|
38
|
-
});
|
|
39
|
-
HTMLElement.prototype.hidePopover = vi.fn(function (this: HTMLElement) {
|
|
40
|
-
this.removeAttribute('popover-open');
|
|
41
|
-
const event = new Event('toggle', {bubbles: false});
|
|
42
|
-
Object.defineProperty(event, 'newState', {value: 'closed'});
|
|
43
|
-
this.dispatchEvent(event);
|
|
44
|
-
});
|
|
45
|
-
const originalMatches = HTMLElement.prototype.matches;
|
|
46
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
47
|
-
(HTMLElement.prototype as any).matches = function (
|
|
48
|
-
selector: string,
|
|
49
|
-
): boolean {
|
|
50
|
-
if (selector === ':popover-open') {
|
|
51
|
-
return this.hasAttribute('popover-open');
|
|
52
|
-
}
|
|
53
|
-
// jsdom does not derive :focus-visible from keyboard focus for a
|
|
54
|
-
// div[role="slider"] thumb; treat the focused thumb as focus-visible so the
|
|
55
|
-
// disabled-reason tooltip's keyboard-focus path can be exercised.
|
|
56
|
-
if (selector === ':focus-visible') {
|
|
57
|
-
return this === document.activeElement;
|
|
58
|
-
}
|
|
59
|
-
return originalMatches.call(this, selector);
|
|
60
|
-
};
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe('Slider', () => {
|
|
64
|
-
// --- Aria labels ---
|
|
65
|
-
|
|
66
|
-
it('single thumb takes its accessible name from the label', () => {
|
|
67
|
-
render(<Slider label="Volume" value={50} />);
|
|
68
|
-
const slider = screen.getByRole('slider');
|
|
69
|
-
expect(slider).toHaveAccessibleName('Volume');
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('range thumbs have individual names composing with the group label', () => {
|
|
73
|
-
render(<Slider label="Price range" value={[20, 80] as [number, number]} />);
|
|
74
|
-
const sliders = screen.getAllByRole('slider');
|
|
75
|
-
expect(sliders[0]).toHaveAccessibleName('Minimum value');
|
|
76
|
-
expect(sliders[1]).toHaveAccessibleName('Maximum value');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('translates the range thumb names under another locale', () => {
|
|
80
|
-
render(
|
|
81
|
-
<InternationalizationProvider
|
|
82
|
-
locale="fr"
|
|
83
|
-
overrides={{
|
|
84
|
-
fr: {
|
|
85
|
-
'@astryx.slider.minimumThumb': 'Valeur minimale',
|
|
86
|
-
'@astryx.slider.maximumThumb': 'Valeur maximale',
|
|
87
|
-
},
|
|
88
|
-
}}>
|
|
89
|
-
<Slider label="Prix" value={[20, 80] as [number, number]} />
|
|
90
|
-
</InternationalizationProvider>,
|
|
91
|
-
);
|
|
92
|
-
const sliders = screen.getAllByRole('slider');
|
|
93
|
-
expect(sliders[0]).toHaveAccessibleName('Valeur minimale');
|
|
94
|
-
expect(sliders[1]).toHaveAccessibleName('Valeur maximale');
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('sets aria-valuetext with formatValue', () => {
|
|
98
|
-
render(
|
|
99
|
-
<Slider label="Temperature" value={72} formatValue={v => `${v}°F`} />,
|
|
100
|
-
);
|
|
101
|
-
const slider = screen.getByRole('slider');
|
|
102
|
-
expect(slider).toHaveAttribute('aria-valuetext', '72°F');
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('uses custom min and max', () => {
|
|
106
|
-
render(<Slider label="Temperature" value={72} min={60} max={90} />);
|
|
107
|
-
const slider = screen.getByRole('slider');
|
|
108
|
-
expect(slider).toHaveAttribute('aria-valuemin', '60');
|
|
109
|
-
expect(slider).toHaveAttribute('aria-valuemax', '90');
|
|
110
|
-
expect(slider).toHaveAttribute('aria-valuenow', '72');
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it.each([
|
|
114
|
-
{value: 150, expectedValue: 100, expectedPosition: 'calc(100% - 10px)'},
|
|
115
|
-
{value: -50, expectedValue: 0, expectedPosition: 'calc(0% + 10px)'},
|
|
116
|
-
])(
|
|
117
|
-
'clamps a controlled value of $value to $expectedValue',
|
|
118
|
-
({value, expectedValue, expectedPosition}) => {
|
|
119
|
-
render(<Slider label="Volume" value={value} min={0} max={100} />);
|
|
120
|
-
const slider = screen.getByRole('slider');
|
|
121
|
-
expect(slider).toHaveAttribute('aria-valuenow', String(expectedValue));
|
|
122
|
-
// Thumb positions via the logical `inset-inline-start` so it mirrors
|
|
123
|
-
// under RTL (see RTL Phase 4), offset by half a thumb so the extremes
|
|
124
|
-
// stay inside the component box.
|
|
125
|
-
expect(slider).toHaveStyle({insetInlineStart: expectedPosition});
|
|
126
|
-
},
|
|
127
|
-
);
|
|
128
|
-
|
|
129
|
-
// Regression: #5050 — at min/max the thumb centred on the container edge,
|
|
130
|
-
// so half of it (10px of a 20px thumb) hung outside the component.
|
|
131
|
-
it.each([
|
|
132
|
-
{value: 0, position: 'calc(0% + 10px)'},
|
|
133
|
-
{value: 50, position: 'calc(50% + 0px)'},
|
|
134
|
-
{value: 100, position: 'calc(100% - 10px)'},
|
|
135
|
-
])(
|
|
136
|
-
'insets the thumb at value $value so it stays in bounds',
|
|
137
|
-
({value, position}) => {
|
|
138
|
-
render(<Slider label="Volume" value={value} min={0} max={100} />);
|
|
139
|
-
expect(screen.getByRole('slider')).toHaveStyle({
|
|
140
|
-
insetInlineStart: position,
|
|
141
|
-
});
|
|
142
|
-
},
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
it.each([
|
|
146
|
-
{value: 0, position: 'calc(0% + 10px)'},
|
|
147
|
-
{value: 100, position: 'calc(100% - 10px)'},
|
|
148
|
-
])(
|
|
149
|
-
'insets a vertical thumb at value $value so it stays in bounds',
|
|
150
|
-
({value, position}) => {
|
|
151
|
-
render(
|
|
152
|
-
<Slider
|
|
153
|
-
label="Volume"
|
|
154
|
-
value={value}
|
|
155
|
-
min={0}
|
|
156
|
-
max={100}
|
|
157
|
-
orientation="vertical"
|
|
158
|
-
/>,
|
|
159
|
-
);
|
|
160
|
-
expect(screen.getByRole('slider')).toHaveStyle({bottom: position});
|
|
161
|
-
},
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
it('reflects orientation and disabled state on the interactive control target', () => {
|
|
165
|
-
render(
|
|
166
|
-
<Slider
|
|
167
|
-
label="Volume"
|
|
168
|
-
value={50}
|
|
169
|
-
orientation="vertical"
|
|
170
|
-
valueDisplay="text"
|
|
171
|
-
isDisabled
|
|
172
|
-
/>,
|
|
173
|
-
);
|
|
174
|
-
const control = screen.getByRole('slider').parentElement;
|
|
175
|
-
expect(control).not.toBeNull();
|
|
176
|
-
expect(control).toHaveClass('astryx-slider-control');
|
|
177
|
-
expect(control).toHaveAttribute('data-orientation', 'vertical');
|
|
178
|
-
expect(control).toHaveAttribute('data-disabled', 'disabled');
|
|
179
|
-
expect(control).not.toContainElement(screen.getByText('50'));
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('range mode sets correct aria values on both thumbs', () => {
|
|
183
|
-
render(
|
|
184
|
-
<Slider
|
|
185
|
-
label="Range"
|
|
186
|
-
value={[25, 75] as [number, number]}
|
|
187
|
-
min={0}
|
|
188
|
-
max={100}
|
|
189
|
-
/>,
|
|
190
|
-
);
|
|
191
|
-
const sliders = screen.getAllByRole('slider');
|
|
192
|
-
expect(sliders[0]).toHaveAttribute('aria-valuenow', '25');
|
|
193
|
-
expect(sliders[1]).toHaveAttribute('aria-valuenow', '75');
|
|
194
|
-
// Per the APG multi-thumb pattern, each thumb's bounds are constrained by
|
|
195
|
-
// its sibling: the lower thumb can't exceed the upper thumb's value and
|
|
196
|
-
// the upper thumb can't go below the lower thumb's value.
|
|
197
|
-
expect(sliders[0]).toHaveAttribute('aria-valuemin', '0');
|
|
198
|
-
expect(sliders[0]).toHaveAttribute('aria-valuemax', '75');
|
|
199
|
-
expect(sliders[1]).toHaveAttribute('aria-valuemin', '25');
|
|
200
|
-
expect(sliders[1]).toHaveAttribute('aria-valuemax', '100');
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('range thumb bounds update after moving a thumb', async () => {
|
|
204
|
-
const user = userEvent.setup();
|
|
205
|
-
function ControlledRange() {
|
|
206
|
-
const [value, setValue] = useState<[number, number]>([25, 75]);
|
|
207
|
-
return (
|
|
208
|
-
<Slider
|
|
209
|
-
label="Range"
|
|
210
|
-
value={value}
|
|
211
|
-
onChange={setValue}
|
|
212
|
-
min={0}
|
|
213
|
-
max={100}
|
|
214
|
-
/>
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
render(<ControlledRange />);
|
|
218
|
-
const sliders = screen.getAllByRole('slider');
|
|
219
|
-
act(() => {
|
|
220
|
-
sliders[0].focus();
|
|
221
|
-
});
|
|
222
|
-
await user.keyboard('{ArrowRight}');
|
|
223
|
-
expect(sliders[0]).toHaveAttribute('aria-valuenow', '26');
|
|
224
|
-
// The upper thumb's floor tracks the lower thumb's new value.
|
|
225
|
-
expect(sliders[1]).toHaveAttribute('aria-valuemin', '26');
|
|
226
|
-
expect(sliders[0]).toHaveAttribute('aria-valuemax', '75');
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it('range thumb bounds include the minStepsBetweenThumbs gap', () => {
|
|
230
|
-
render(
|
|
231
|
-
<Slider
|
|
232
|
-
label="Range"
|
|
233
|
-
value={[20, 80] as [number, number]}
|
|
234
|
-
min={0}
|
|
235
|
-
max={100}
|
|
236
|
-
step={5}
|
|
237
|
-
minStepsBetweenThumbs={2}
|
|
238
|
-
/>,
|
|
239
|
-
);
|
|
240
|
-
const sliders = screen.getAllByRole('slider');
|
|
241
|
-
// minGap = 2 steps * 5 = 10
|
|
242
|
-
expect(sliders[0]).toHaveAttribute('aria-valuemax', '70');
|
|
243
|
-
expect(sliders[1]).toHaveAttribute('aria-valuemin', '30');
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
// --- Label association ---
|
|
247
|
-
|
|
248
|
-
// A <label htmlFor> must point at an existing form-associated element;
|
|
249
|
-
// div[role="slider"] is not labelable, so the Slider label must render as a
|
|
250
|
-
// group label instead (WCAG 1.3.1).
|
|
251
|
-
const LABELABLE_TAGS = new Set([
|
|
252
|
-
'BUTTON',
|
|
253
|
-
'INPUT',
|
|
254
|
-
'METER',
|
|
255
|
-
'OUTPUT',
|
|
256
|
-
'PROGRESS',
|
|
257
|
-
'SELECT',
|
|
258
|
-
'TEXTAREA',
|
|
259
|
-
]);
|
|
260
|
-
|
|
261
|
-
function expectNoOrphanedLabels(container: HTMLElement) {
|
|
262
|
-
for (const labelEl of container.querySelectorAll('label[for]')) {
|
|
263
|
-
const target = document.getElementById(labelEl.getAttribute('for')!);
|
|
264
|
-
expect(target).not.toBeNull();
|
|
265
|
-
expect(LABELABLE_TAGS.has(target!.tagName)).toBe(true);
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
it('single mode renders the label as a group label naming the thumb', () => {
|
|
270
|
-
const {container} = render(<Slider label="Volume" value={50} />);
|
|
271
|
-
expectNoOrphanedLabels(container);
|
|
272
|
-
const slider = screen.getByRole('slider');
|
|
273
|
-
const labelledBy = slider.getAttribute('aria-labelledby');
|
|
274
|
-
expect(labelledBy).toBeTruthy();
|
|
275
|
-
expect(document.getElementById(labelledBy!)).toHaveTextContent('Volume');
|
|
276
|
-
expect(slider).toHaveAccessibleName('Volume');
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
it('range mode labels the slider group via aria-labelledby', () => {
|
|
280
|
-
const {container} = render(
|
|
281
|
-
<Slider label="Price range" value={[20, 80] as [number, number]} />,
|
|
282
|
-
);
|
|
283
|
-
expectNoOrphanedLabels(container);
|
|
284
|
-
const group = screen.getByRole('group', {name: 'Price range'});
|
|
285
|
-
const labelledBy = group.getAttribute('aria-labelledby');
|
|
286
|
-
expect(labelledBy).toBeTruthy();
|
|
287
|
-
expect(document.getElementById(labelledBy!)).toHaveTextContent(
|
|
288
|
-
'Price range',
|
|
289
|
-
);
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
it('sets aria-orientation for vertical', () => {
|
|
293
|
-
render(<Slider label="Volume" value={50} orientation="vertical" />);
|
|
294
|
-
const slider = screen.getByRole('slider');
|
|
295
|
-
expect(slider).toHaveAttribute('aria-orientation', 'vertical');
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
it('sets aria-invalid when status type is error', () => {
|
|
299
|
-
render(
|
|
300
|
-
<Slider
|
|
301
|
-
label="Volume"
|
|
302
|
-
value={50}
|
|
303
|
-
status={{type: 'error', message: 'Value too high'}}
|
|
304
|
-
/>,
|
|
305
|
-
);
|
|
306
|
-
const slider = screen.getByRole('slider');
|
|
307
|
-
expect(slider).toHaveAttribute('aria-invalid', 'true');
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
it('associates description via aria-describedby', () => {
|
|
311
|
-
render(
|
|
312
|
-
<Slider
|
|
313
|
-
label="Volume"
|
|
314
|
-
value={50}
|
|
315
|
-
description="Adjust the volume level"
|
|
316
|
-
/>,
|
|
317
|
-
);
|
|
318
|
-
const slider = screen.getByRole('slider');
|
|
319
|
-
const describedby = slider.getAttribute('aria-describedby');
|
|
320
|
-
expect(describedby).toBeTruthy();
|
|
321
|
-
const descEl = document.getElementById(describedby!.split(' ')[0]);
|
|
322
|
-
expect(descEl).toHaveTextContent('Adjust the volume level');
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
it('associates status message via aria-describedby', () => {
|
|
326
|
-
render(
|
|
327
|
-
<Slider
|
|
328
|
-
label="Volume"
|
|
329
|
-
value={50}
|
|
330
|
-
description="Adjust the volume level"
|
|
331
|
-
status={{type: 'error', message: 'Too loud'}}
|
|
332
|
-
/>,
|
|
333
|
-
);
|
|
334
|
-
const slider = screen.getByRole('slider');
|
|
335
|
-
const describedby = slider.getAttribute('aria-describedby');
|
|
336
|
-
expect(describedby).toBeTruthy();
|
|
337
|
-
// Should have at least two IDs (description + status message)
|
|
338
|
-
const ids = describedby!.split(' ');
|
|
339
|
-
expect(ids.length).toBeGreaterThanOrEqual(2);
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
it('decorative track elements have aria-hidden', () => {
|
|
343
|
-
const {container} = render(<Slider label="Volume" value={50} />);
|
|
344
|
-
const ariaHidden = container.querySelectorAll('[aria-hidden="true"]');
|
|
345
|
-
expect(ariaHidden.length).toBeGreaterThanOrEqual(2);
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
// --- Required state ---
|
|
349
|
-
|
|
350
|
-
it('conveys required state through the accessible description', () => {
|
|
351
|
-
render(<Slider label="Volume" value={50} isRequired />);
|
|
352
|
-
const slider = screen.getByRole('slider');
|
|
353
|
-
expect(slider).toHaveAccessibleDescription(/Required/);
|
|
354
|
-
// aria-required is not a supported property of role="slider" in
|
|
355
|
-
// WAI-ARIA 1.2, so it must never appear on the thumb.
|
|
356
|
-
expect(slider).not.toHaveAttribute('aria-required');
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
it('conveys required state under FormLayout defaultOptionality="required" unless isOptional (FormLayout FR5)', () => {
|
|
360
|
-
render(
|
|
361
|
-
<FormLayout defaultOptionality="required">
|
|
362
|
-
<Slider label="Volume" value={50} />
|
|
363
|
-
<Slider label="Balance" value={50} isOptional />
|
|
364
|
-
</FormLayout>,
|
|
365
|
-
);
|
|
366
|
-
const [volume, balance] = screen.getAllByRole('slider');
|
|
367
|
-
expect(volume).toHaveAccessibleDescription(/Required/);
|
|
368
|
-
expect(balance).not.toHaveAccessibleDescription(/Required/);
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
it('conveys required state on both thumbs of a range slider', () => {
|
|
372
|
-
render(
|
|
373
|
-
<Slider
|
|
374
|
-
label="Price range"
|
|
375
|
-
value={[20, 80] as [number, number]}
|
|
376
|
-
isRequired
|
|
377
|
-
/>,
|
|
378
|
-
);
|
|
379
|
-
const sliders = screen.getAllByRole('slider');
|
|
380
|
-
expect(sliders).toHaveLength(2);
|
|
381
|
-
for (const thumb of sliders) {
|
|
382
|
-
expect(thumb).toHaveAccessibleDescription(/Required/);
|
|
383
|
-
expect(thumb).not.toHaveAttribute('aria-required');
|
|
384
|
-
}
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
it('combines required with other describedby parts in the description', () => {
|
|
388
|
-
render(
|
|
389
|
-
<Slider
|
|
390
|
-
label="Volume"
|
|
391
|
-
value={50}
|
|
392
|
-
description="Adjust the volume level"
|
|
393
|
-
isRequired
|
|
394
|
-
/>,
|
|
395
|
-
);
|
|
396
|
-
const slider = screen.getByRole('slider');
|
|
397
|
-
expect(slider).toHaveAccessibleDescription(/Adjust the volume level/);
|
|
398
|
-
expect(slider).toHaveAccessibleDescription(/Required/);
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
it('does not mention required without isRequired', () => {
|
|
402
|
-
render(
|
|
403
|
-
<Slider
|
|
404
|
-
label="Volume"
|
|
405
|
-
value={50}
|
|
406
|
-
description="Adjust the volume level"
|
|
407
|
-
/>,
|
|
408
|
-
);
|
|
409
|
-
const slider = screen.getByRole('slider');
|
|
410
|
-
expect(slider).not.toHaveAccessibleDescription(/Required/);
|
|
411
|
-
expect(slider).not.toHaveAttribute('aria-required');
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
// --- Disabled guards ---
|
|
415
|
-
|
|
416
|
-
it('disables thumbs when isDisabled is true', () => {
|
|
417
|
-
render(<Slider label="Volume" value={50} isDisabled />);
|
|
418
|
-
const slider = screen.getByRole('slider');
|
|
419
|
-
expect(slider).toHaveAttribute('aria-disabled', 'true');
|
|
420
|
-
expect(slider).toHaveAttribute('tabIndex', '0');
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
it('does not fire onChange on pointer down when disabled', () => {
|
|
424
|
-
const handleChange = vi.fn();
|
|
425
|
-
render(
|
|
426
|
-
<Slider
|
|
427
|
-
label="Volume"
|
|
428
|
-
value={50}
|
|
429
|
-
min={0}
|
|
430
|
-
max={100}
|
|
431
|
-
onChange={handleChange}
|
|
432
|
-
isDisabled
|
|
433
|
-
/>,
|
|
434
|
-
);
|
|
435
|
-
const slider = screen.getByRole('slider');
|
|
436
|
-
const trackContainer = slider.parentElement!;
|
|
437
|
-
|
|
438
|
-
trackContainer.getBoundingClientRect = () => ({
|
|
439
|
-
left: 0,
|
|
440
|
-
top: 0,
|
|
441
|
-
right: 200,
|
|
442
|
-
bottom: 20,
|
|
443
|
-
width: 200,
|
|
444
|
-
height: 20,
|
|
445
|
-
x: 0,
|
|
446
|
-
y: 0,
|
|
447
|
-
toJSON: () => {},
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
fireEvent.pointerDown(trackContainer, {
|
|
451
|
-
clientX: 100,
|
|
452
|
-
clientY: 10,
|
|
453
|
-
pointerId: 1,
|
|
454
|
-
});
|
|
455
|
-
|
|
456
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
it('does not fire onChange on keyboard when disabled', () => {
|
|
460
|
-
const handleChange = vi.fn();
|
|
461
|
-
render(
|
|
462
|
-
<Slider label="Volume" value={50} onChange={handleChange} isDisabled />,
|
|
463
|
-
);
|
|
464
|
-
const slider = screen.getByRole('slider');
|
|
465
|
-
fireEvent.keyDown(slider, {key: 'ArrowRight'});
|
|
466
|
-
expect(handleChange).not.toHaveBeenCalled();
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
// --- onChangeEnd on keyboard ---
|
|
470
|
-
|
|
471
|
-
it('fires onChangeEnd on keyboard ArrowRight', async () => {
|
|
472
|
-
const user = userEvent.setup();
|
|
473
|
-
const handleChange = vi.fn();
|
|
474
|
-
const handleChangeEnd = vi.fn();
|
|
475
|
-
render(
|
|
476
|
-
<Slider
|
|
477
|
-
label="Volume"
|
|
478
|
-
value={50}
|
|
479
|
-
step={5}
|
|
480
|
-
onChange={handleChange}
|
|
481
|
-
onChangeEnd={handleChangeEnd}
|
|
482
|
-
/>,
|
|
483
|
-
);
|
|
484
|
-
const slider = screen.getByRole('slider');
|
|
485
|
-
act(() => {
|
|
486
|
-
slider.focus();
|
|
487
|
-
});
|
|
488
|
-
await user.keyboard('{ArrowRight}');
|
|
489
|
-
expect(handleChange).toHaveBeenCalledWith(55);
|
|
490
|
-
expect(handleChangeEnd).toHaveBeenCalledWith(55);
|
|
491
|
-
});
|
|
492
|
-
|
|
493
|
-
// --- Fractional step precision ---
|
|
494
|
-
|
|
495
|
-
it('emits exact decimal values for fractional steps on keyboard', async () => {
|
|
496
|
-
const user = userEvent.setup();
|
|
497
|
-
const handleChange = vi.fn();
|
|
498
|
-
const handleChangeEnd = vi.fn();
|
|
499
|
-
render(
|
|
500
|
-
<Slider
|
|
501
|
-
label="Opacity"
|
|
502
|
-
value={0.2}
|
|
503
|
-
min={0}
|
|
504
|
-
max={1}
|
|
505
|
-
step={0.1}
|
|
506
|
-
onChange={handleChange}
|
|
507
|
-
onChangeEnd={handleChangeEnd}
|
|
508
|
-
/>,
|
|
509
|
-
);
|
|
510
|
-
const slider = screen.getByRole('slider');
|
|
511
|
-
act(() => {
|
|
512
|
-
slider.focus();
|
|
513
|
-
});
|
|
514
|
-
await user.keyboard('{ArrowRight}');
|
|
515
|
-
// 0.2 + 0.1 must not surface binary float error (0.30000000000000004)
|
|
516
|
-
expect(handleChange).toHaveBeenCalledWith(0.3);
|
|
517
|
-
expect(handleChangeEnd).toHaveBeenCalledWith(0.3);
|
|
518
|
-
});
|
|
519
|
-
|
|
520
|
-
it('emits exact decimal values for fractional steps in range mode', async () => {
|
|
521
|
-
const user = userEvent.setup();
|
|
522
|
-
const handleChange = vi.fn();
|
|
523
|
-
const handleChangeEnd = vi.fn();
|
|
524
|
-
render(
|
|
525
|
-
<Slider
|
|
526
|
-
label="Range"
|
|
527
|
-
value={[0.2, 0.6] as [number, number]}
|
|
528
|
-
min={0}
|
|
529
|
-
max={1}
|
|
530
|
-
step={0.1}
|
|
531
|
-
onChange={handleChange}
|
|
532
|
-
onChangeEnd={handleChangeEnd}
|
|
533
|
-
/>,
|
|
534
|
-
);
|
|
535
|
-
const sliders = screen.getAllByRole('slider');
|
|
536
|
-
act(() => {
|
|
537
|
-
sliders[1].focus();
|
|
538
|
-
});
|
|
539
|
-
await user.keyboard('{ArrowRight}');
|
|
540
|
-
// 0.6 + 0.1 snaps to 7 * 0.1, which is 0.7000000000000001 without rounding
|
|
541
|
-
expect(handleChange).toHaveBeenCalledWith([0.2, 0.7]);
|
|
542
|
-
expect(handleChangeEnd).toHaveBeenCalledWith([0.2, 0.7]);
|
|
543
|
-
});
|
|
544
|
-
|
|
545
|
-
it('End reaches an off-grid max from a non-zero min, and Home still reaches min', async () => {
|
|
546
|
-
const user = userEvent.setup();
|
|
547
|
-
const onChange = vi.fn();
|
|
548
|
-
const onChangeEnd = vi.fn();
|
|
549
|
-
// From min 1 with step 3 the grid is 1, 4, …, 100; max 101 is off it.
|
|
550
|
-
render(
|
|
551
|
-
<Slider
|
|
552
|
-
label="Zoom"
|
|
553
|
-
min={1}
|
|
554
|
-
max={101}
|
|
555
|
-
step={3}
|
|
556
|
-
value={49}
|
|
557
|
-
onChange={onChange}
|
|
558
|
-
onChangeEnd={onChangeEnd}
|
|
559
|
-
/>,
|
|
560
|
-
);
|
|
561
|
-
const thumb = screen.getByRole('slider');
|
|
562
|
-
thumb.focus();
|
|
563
|
-
|
|
564
|
-
await user.keyboard('{End}');
|
|
565
|
-
expect(onChange).toHaveBeenLastCalledWith(101);
|
|
566
|
-
expect(onChangeEnd).toHaveBeenLastCalledWith(101);
|
|
567
|
-
|
|
568
|
-
await user.keyboard('{Home}');
|
|
569
|
-
expect(onChange).toHaveBeenLastCalledWith(1);
|
|
570
|
-
expect(onChangeEnd).toHaveBeenLastCalledWith(1);
|
|
571
|
-
});
|
|
572
|
-
|
|
573
|
-
it('End lands on max when max is off the step grid, while arrows still snap', async () => {
|
|
574
|
-
const user = userEvent.setup();
|
|
575
|
-
const onChange = vi.fn();
|
|
576
|
-
function Owner() {
|
|
577
|
-
const [value, setValue] = useState(48);
|
|
578
|
-
return (
|
|
579
|
-
<Slider
|
|
580
|
-
label="Zoom"
|
|
581
|
-
min={0}
|
|
582
|
-
max={100}
|
|
583
|
-
step={3}
|
|
584
|
-
value={value}
|
|
585
|
-
onChange={(next: number) => {
|
|
586
|
-
onChange(next);
|
|
587
|
-
setValue(next);
|
|
588
|
-
}}
|
|
589
|
-
/>
|
|
590
|
-
);
|
|
591
|
-
}
|
|
592
|
-
render(<Owner />);
|
|
593
|
-
const thumb = screen.getByRole('slider');
|
|
594
|
-
thumb.focus();
|
|
595
|
-
|
|
596
|
-
await user.keyboard('{End}');
|
|
597
|
-
expect(onChange).toHaveBeenLastCalledWith(100);
|
|
598
|
-
|
|
599
|
-
// ORD1 for arrows and Page keys is unchanged: from max (100, off the
|
|
600
|
-
// grid) ArrowLeft targets 97 and snaps to 96; from 96 PageUp targets 126
|
|
601
|
-
// and clamps to 100, the bound.
|
|
602
|
-
await user.keyboard('{ArrowLeft}');
|
|
603
|
-
expect(onChange).toHaveBeenLastCalledWith(96);
|
|
604
|
-
await user.keyboard('{PageUp}');
|
|
605
|
-
expect(onChange).toHaveBeenLastCalledWith(100);
|
|
606
|
-
});
|
|
607
|
-
|
|
608
|
-
it('fires onChangeEnd on keyboard Home/End with correct value', async () => {
|
|
609
|
-
const user = userEvent.setup();
|
|
610
|
-
const handleChangeEnd = vi.fn();
|
|
611
|
-
render(
|
|
612
|
-
<Slider
|
|
613
|
-
label="Volume"
|
|
614
|
-
value={50}
|
|
615
|
-
min={0}
|
|
616
|
-
max={100}
|
|
617
|
-
onChange={vi.fn()}
|
|
618
|
-
onChangeEnd={handleChangeEnd}
|
|
619
|
-
/>,
|
|
620
|
-
);
|
|
621
|
-
const slider = screen.getByRole('slider');
|
|
622
|
-
act(() => {
|
|
623
|
-
slider.focus();
|
|
624
|
-
});
|
|
625
|
-
await user.keyboard('{Home}');
|
|
626
|
-
expect(handleChangeEnd).toHaveBeenCalledWith(0);
|
|
627
|
-
});
|
|
628
|
-
|
|
629
|
-
it('fires onChangeEnd with correct value for range mode on keyboard', async () => {
|
|
630
|
-
const user = userEvent.setup();
|
|
631
|
-
const handleChangeEnd = vi.fn();
|
|
632
|
-
render(
|
|
633
|
-
<Slider
|
|
634
|
-
label="Range"
|
|
635
|
-
value={[20, 80] as [number, number]}
|
|
636
|
-
min={0}
|
|
637
|
-
max={100}
|
|
638
|
-
step={5}
|
|
639
|
-
onChange={vi.fn()}
|
|
640
|
-
onChangeEnd={handleChangeEnd}
|
|
641
|
-
/>,
|
|
642
|
-
);
|
|
643
|
-
const sliders = screen.getAllByRole('slider');
|
|
644
|
-
act(() => {
|
|
645
|
-
sliders[0].focus();
|
|
646
|
-
});
|
|
647
|
-
await user.keyboard('{ArrowRight}');
|
|
648
|
-
expect(handleChangeEnd).toHaveBeenCalledWith([25, 80]);
|
|
649
|
-
});
|
|
650
|
-
|
|
651
|
-
// --- Pointer handling ---
|
|
652
|
-
|
|
653
|
-
it('fires onChangeEnd on pointer up after pointer down', () => {
|
|
654
|
-
const handleChange = vi.fn();
|
|
655
|
-
const handleChangeEnd = vi.fn();
|
|
656
|
-
render(
|
|
657
|
-
<Slider
|
|
658
|
-
label="Volume"
|
|
659
|
-
value={50}
|
|
660
|
-
min={0}
|
|
661
|
-
max={100}
|
|
662
|
-
onChange={handleChange}
|
|
663
|
-
onChangeEnd={handleChangeEnd}
|
|
664
|
-
/>,
|
|
665
|
-
);
|
|
666
|
-
const slider = screen.getByRole('slider');
|
|
667
|
-
const trackContainer = slider.parentElement!;
|
|
668
|
-
|
|
669
|
-
trackContainer.getBoundingClientRect = () => ({
|
|
670
|
-
left: 0,
|
|
671
|
-
top: 0,
|
|
672
|
-
right: 200,
|
|
673
|
-
bottom: 20,
|
|
674
|
-
width: 200,
|
|
675
|
-
height: 20,
|
|
676
|
-
x: 0,
|
|
677
|
-
y: 0,
|
|
678
|
-
toJSON: () => {},
|
|
679
|
-
});
|
|
680
|
-
|
|
681
|
-
fireEvent.pointerDown(trackContainer, {
|
|
682
|
-
clientX: 100,
|
|
683
|
-
clientY: 10,
|
|
684
|
-
pointerId: 1,
|
|
685
|
-
});
|
|
686
|
-
fireEvent.pointerUp(trackContainer, {
|
|
687
|
-
clientX: 100,
|
|
688
|
-
clientY: 10,
|
|
689
|
-
pointerId: 1,
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
expect(handleChangeEnd).toHaveBeenCalledTimes(1);
|
|
693
|
-
});
|
|
694
|
-
|
|
695
|
-
it('focuses closest thumb on track click', () => {
|
|
696
|
-
render(
|
|
697
|
-
<Slider label="Volume" value={50} min={0} max={100} onChange={vi.fn()} />,
|
|
698
|
-
);
|
|
699
|
-
const slider = screen.getByRole('slider');
|
|
700
|
-
const trackContainer = slider.parentElement!;
|
|
701
|
-
|
|
702
|
-
trackContainer.getBoundingClientRect = () => ({
|
|
703
|
-
left: 0,
|
|
704
|
-
top: 0,
|
|
705
|
-
right: 200,
|
|
706
|
-
bottom: 20,
|
|
707
|
-
width: 200,
|
|
708
|
-
height: 20,
|
|
709
|
-
x: 0,
|
|
710
|
-
y: 0,
|
|
711
|
-
toJSON: () => {},
|
|
712
|
-
});
|
|
713
|
-
|
|
714
|
-
fireEvent.pointerDown(trackContainer, {
|
|
715
|
-
clientX: 100,
|
|
716
|
-
clientY: 10,
|
|
717
|
-
pointerId: 1,
|
|
718
|
-
});
|
|
719
|
-
|
|
720
|
-
expect(document.activeElement).toBe(slider);
|
|
721
|
-
});
|
|
722
|
-
|
|
723
|
-
// --- RTL pointer value mapping (RTL Phase 4) ---
|
|
724
|
-
// Contract: the inline-start edge (value = min) is the RIGHT edge under RTL,
|
|
725
|
-
// so the same physical click maps to the mirrored value relative to LTR.
|
|
726
|
-
// `valueDisplay="none"` keeps the thumb a direct child of the track element
|
|
727
|
-
// (no Tooltip wrapper) so the mocked rect lands on trackRef.
|
|
728
|
-
|
|
729
|
-
it('maps a track click to the LTR value in the default direction', () => {
|
|
730
|
-
const handleChange = vi.fn();
|
|
731
|
-
render(
|
|
732
|
-
<Slider
|
|
733
|
-
label="Volume"
|
|
734
|
-
value={0}
|
|
735
|
-
min={0}
|
|
736
|
-
max={100}
|
|
737
|
-
valueDisplay="none"
|
|
738
|
-
onChange={handleChange}
|
|
739
|
-
/>,
|
|
740
|
-
);
|
|
741
|
-
const track = screen.getByRole('slider').parentElement!;
|
|
742
|
-
track.getBoundingClientRect = () => ({
|
|
743
|
-
left: 0,
|
|
744
|
-
top: 0,
|
|
745
|
-
right: 200,
|
|
746
|
-
bottom: 20,
|
|
747
|
-
width: 200,
|
|
748
|
-
height: 20,
|
|
749
|
-
x: 0,
|
|
750
|
-
y: 0,
|
|
751
|
-
toJSON: () => {},
|
|
752
|
-
});
|
|
753
|
-
|
|
754
|
-
// Click at x=50 of a 200px track. The thumb's travel is the track minus
|
|
755
|
-
// half a thumb at each end (180px from x=10), so the fraction is
|
|
756
|
-
// (50 - 10) / 180 → value 22.
|
|
757
|
-
fireEvent.pointerDown(track, {clientX: 50, clientY: 10, pointerId: 1});
|
|
758
|
-
expect(handleChange).toHaveBeenLastCalledWith(22);
|
|
759
|
-
});
|
|
760
|
-
|
|
761
|
-
it('mirrors a track click to the RTL value when the track is rtl', () => {
|
|
762
|
-
const handleChange = vi.fn();
|
|
763
|
-
render(
|
|
764
|
-
<Slider
|
|
765
|
-
label="Volume"
|
|
766
|
-
value={0}
|
|
767
|
-
min={0}
|
|
768
|
-
max={100}
|
|
769
|
-
valueDisplay="none"
|
|
770
|
-
onChange={handleChange}
|
|
771
|
-
/>,
|
|
772
|
-
);
|
|
773
|
-
const track = screen.getByRole('slider').parentElement!;
|
|
774
|
-
track.getBoundingClientRect = () => ({
|
|
775
|
-
left: 0,
|
|
776
|
-
top: 0,
|
|
777
|
-
right: 200,
|
|
778
|
-
bottom: 20,
|
|
779
|
-
width: 200,
|
|
780
|
-
height: 20,
|
|
781
|
-
x: 0,
|
|
782
|
-
y: 0,
|
|
783
|
-
toJSON: () => {},
|
|
784
|
-
});
|
|
785
|
-
|
|
786
|
-
// Force the track's computed direction to rtl (isRtlElement reads this).
|
|
787
|
-
const realGetComputedStyle = window.getComputedStyle;
|
|
788
|
-
const gcsSpy = vi
|
|
789
|
-
.spyOn(window, 'getComputedStyle')
|
|
790
|
-
.mockImplementation((el: Element, pseudo?: string | null) => {
|
|
791
|
-
if (el === track) {
|
|
792
|
-
return {direction: 'rtl'} as CSSStyleDeclaration;
|
|
793
|
-
}
|
|
794
|
-
return realGetComputedStyle(el, pseudo ?? undefined);
|
|
795
|
-
});
|
|
796
|
-
|
|
797
|
-
// Same physical click at x=50. Under RTL the inline start is the right
|
|
798
|
-
// edge, so the fraction is (right - 10 - x) / 180 = 140/180 → value 78
|
|
799
|
-
// (the mirror of the LTR value 22).
|
|
800
|
-
fireEvent.pointerDown(track, {clientX: 50, clientY: 10, pointerId: 1});
|
|
801
|
-
expect(handleChange).toHaveBeenLastCalledWith(78);
|
|
802
|
-
|
|
803
|
-
gcsSpy.mockRestore();
|
|
804
|
-
});
|
|
805
|
-
|
|
806
|
-
it('follows the mirrored track under RTL: ArrowLeft increases, ArrowRight decreases, Up/Down unchanged', () => {
|
|
807
|
-
const handleChange = vi.fn();
|
|
808
|
-
render(
|
|
809
|
-
<Slider
|
|
810
|
-
label="Volume"
|
|
811
|
-
value={50}
|
|
812
|
-
min={0}
|
|
813
|
-
max={100}
|
|
814
|
-
step={1}
|
|
815
|
-
valueDisplay="none"
|
|
816
|
-
onChange={handleChange}
|
|
817
|
-
/>,
|
|
818
|
-
);
|
|
819
|
-
const thumb = screen.getByRole('slider');
|
|
820
|
-
const track = thumb.parentElement!;
|
|
821
|
-
const realGetComputedStyle = window.getComputedStyle;
|
|
822
|
-
const gcsSpy = vi
|
|
823
|
-
.spyOn(window, 'getComputedStyle')
|
|
824
|
-
.mockImplementation((el: Element, pseudo?: string | null) => {
|
|
825
|
-
if (el === track) {
|
|
826
|
-
return {direction: 'rtl'} as CSSStyleDeclaration;
|
|
827
|
-
}
|
|
828
|
-
return realGetComputedStyle(el, pseudo ?? undefined);
|
|
829
|
-
});
|
|
830
|
-
|
|
831
|
-
fireEvent.keyDown(thumb, {key: 'ArrowLeft'});
|
|
832
|
-
expect(handleChange).toHaveBeenLastCalledWith(51);
|
|
833
|
-
fireEvent.keyDown(thumb, {key: 'ArrowRight'});
|
|
834
|
-
expect(handleChange).toHaveBeenLastCalledWith(49);
|
|
835
|
-
fireEvent.keyDown(thumb, {key: 'ArrowUp'});
|
|
836
|
-
expect(handleChange).toHaveBeenLastCalledWith(51);
|
|
837
|
-
fireEvent.keyDown(thumb, {key: 'ArrowDown'});
|
|
838
|
-
expect(handleChange).toHaveBeenLastCalledWith(49);
|
|
839
|
-
|
|
840
|
-
gcsSpy.mockRestore();
|
|
841
|
-
});
|
|
842
|
-
|
|
843
|
-
it('keeps ArrowLeft decreasing on a vertical track under RTL', () => {
|
|
844
|
-
const handleChange = vi.fn();
|
|
845
|
-
render(
|
|
846
|
-
<Slider
|
|
847
|
-
label="Volume"
|
|
848
|
-
value={50}
|
|
849
|
-
min={0}
|
|
850
|
-
max={100}
|
|
851
|
-
step={1}
|
|
852
|
-
orientation="vertical"
|
|
853
|
-
valueDisplay="none"
|
|
854
|
-
onChange={handleChange}
|
|
855
|
-
/>,
|
|
856
|
-
);
|
|
857
|
-
const thumb = screen.getByRole('slider');
|
|
858
|
-
const track = thumb.parentElement!;
|
|
859
|
-
const realGetComputedStyle = window.getComputedStyle;
|
|
860
|
-
const gcsSpy = vi
|
|
861
|
-
.spyOn(window, 'getComputedStyle')
|
|
862
|
-
.mockImplementation((el: Element, pseudo?: string | null) => {
|
|
863
|
-
if (el === track) {
|
|
864
|
-
return {direction: 'rtl'} as CSSStyleDeclaration;
|
|
865
|
-
}
|
|
866
|
-
return realGetComputedStyle(el, pseudo ?? undefined);
|
|
867
|
-
});
|
|
868
|
-
|
|
869
|
-
fireEvent.keyDown(thumb, {key: 'ArrowLeft'});
|
|
870
|
-
expect(handleChange).toHaveBeenLastCalledWith(49);
|
|
871
|
-
fireEvent.keyDown(thumb, {key: 'ArrowRight'});
|
|
872
|
-
expect(handleChange).toHaveBeenLastCalledWith(51);
|
|
873
|
-
|
|
874
|
-
gcsSpy.mockRestore();
|
|
875
|
-
});
|
|
876
|
-
|
|
877
|
-
// --- Mark label click snapping ---
|
|
878
|
-
|
|
879
|
-
it('clicking a mark label snaps to that mark value, not pointer position', () => {
|
|
880
|
-
const handleChange = vi.fn();
|
|
881
|
-
render(
|
|
882
|
-
<Slider
|
|
883
|
-
label="Volume"
|
|
884
|
-
value={50}
|
|
885
|
-
min={0}
|
|
886
|
-
max={100}
|
|
887
|
-
onChange={handleChange}
|
|
888
|
-
marks={[{value: 100, label: '100'}]}
|
|
889
|
-
/>,
|
|
890
|
-
);
|
|
891
|
-
const markLabel = screen.getByTestId('slider-mark-label');
|
|
892
|
-
|
|
893
|
-
// Simulate a click on the left edge of the "100" label — pointer X would
|
|
894
|
-
// map to ~99 if calculated from position, but should snap to 100.
|
|
895
|
-
fireEvent.pointerDown(markLabel, {clientX: 1, clientY: 10, pointerId: 1});
|
|
896
|
-
|
|
897
|
-
expect(handleChange).toHaveBeenCalledWith(100);
|
|
898
|
-
});
|
|
899
|
-
|
|
900
|
-
// --- Marks color ---
|
|
901
|
-
|
|
902
|
-
/** Whether the element has an unconditional rule painting a token. */
|
|
903
|
-
function declaresColorToken(el: Element, token: string): boolean {
|
|
904
|
-
return rulesDeclaredFor(el).some(rule => {
|
|
905
|
-
const selector = rule
|
|
906
|
-
.slice(0, rule.indexOf('{'))
|
|
907
|
-
.replaceAll(':not(#\\#)', '');
|
|
908
|
-
return !selector.includes(':') && rule.includes(`var(${token})`);
|
|
909
|
-
});
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
it('uses the track color for unfilled marks and the accent for filled marks', () => {
|
|
913
|
-
render(
|
|
914
|
-
<Slider
|
|
915
|
-
label="Volume"
|
|
916
|
-
value={50}
|
|
917
|
-
min={0}
|
|
918
|
-
max={100}
|
|
919
|
-
marks={[{value: 25}, {value: 75}]}
|
|
920
|
-
/>,
|
|
921
|
-
);
|
|
922
|
-
const marks = screen.getAllByTestId('slider-mark');
|
|
923
|
-
|
|
924
|
-
expect(marks).toHaveLength(2);
|
|
925
|
-
expect(declaresColorToken(marks[0], '--color-track')).toBe(false);
|
|
926
|
-
expect(declaresColorToken(marks[0], '--color-accent')).toBe(true);
|
|
927
|
-
expect(declaresColorToken(marks[1], '--color-track')).toBe(true);
|
|
928
|
-
expect(declaresColorToken(marks[1], '--color-accent')).toBe(false);
|
|
929
|
-
});
|
|
930
|
-
|
|
931
|
-
function declaresFillColor(el: Element): boolean {
|
|
932
|
-
return declaresColorToken(el, '--color-accent');
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
it('colors marks at or behind the thumb with the fill color', () => {
|
|
936
|
-
render(
|
|
937
|
-
<Slider
|
|
938
|
-
label="Volume"
|
|
939
|
-
value={50}
|
|
940
|
-
min={0}
|
|
941
|
-
max={100}
|
|
942
|
-
marks={[
|
|
943
|
-
{value: 0},
|
|
944
|
-
{value: 25},
|
|
945
|
-
{value: 50},
|
|
946
|
-
{value: 75},
|
|
947
|
-
{value: 100},
|
|
948
|
-
]}
|
|
949
|
-
/>,
|
|
950
|
-
);
|
|
951
|
-
const marks = screen.getAllByTestId('slider-mark');
|
|
952
|
-
expect(marks).toHaveLength(5);
|
|
953
|
-
// Marks at 0, 25, and 50 sit at or behind the thumb: fill color.
|
|
954
|
-
expect(declaresFillColor(marks[0])).toBe(true);
|
|
955
|
-
expect(declaresFillColor(marks[1])).toBe(true);
|
|
956
|
-
expect(declaresFillColor(marks[2])).toBe(true);
|
|
957
|
-
// Marks at 75 and 100 sit ahead of the thumb: default mark color.
|
|
958
|
-
expect(declaresFillColor(marks[3])).toBe(false);
|
|
959
|
-
expect(declaresFillColor(marks[4])).toBe(false);
|
|
960
|
-
});
|
|
961
|
-
|
|
962
|
-
it('colors marks between the thumbs with the fill color in range mode', () => {
|
|
963
|
-
render(
|
|
964
|
-
<Slider
|
|
965
|
-
label="Price range"
|
|
966
|
-
value={[20, 80] as [number, number]}
|
|
967
|
-
min={0}
|
|
968
|
-
max={100}
|
|
969
|
-
marks={[
|
|
970
|
-
{value: 0},
|
|
971
|
-
{value: 20},
|
|
972
|
-
{value: 50},
|
|
973
|
-
{value: 80},
|
|
974
|
-
{value: 100},
|
|
975
|
-
]}
|
|
976
|
-
/>,
|
|
977
|
-
);
|
|
978
|
-
const marks = screen.getAllByTestId('slider-mark');
|
|
979
|
-
expect(marks).toHaveLength(5);
|
|
980
|
-
// The mark at 0 sits before the range: default mark color.
|
|
981
|
-
expect(declaresFillColor(marks[0])).toBe(false);
|
|
982
|
-
// Marks at 20, 50, and 80 sit between (or at) the thumbs: fill color.
|
|
983
|
-
expect(declaresFillColor(marks[1])).toBe(true);
|
|
984
|
-
expect(declaresFillColor(marks[2])).toBe(true);
|
|
985
|
-
expect(declaresFillColor(marks[3])).toBe(true);
|
|
986
|
-
// The mark at 100 sits after the range: default mark color.
|
|
987
|
-
expect(declaresFillColor(marks[4])).toBe(false);
|
|
988
|
-
});
|
|
989
|
-
|
|
990
|
-
// --- Boundary clamping ---
|
|
991
|
-
|
|
992
|
-
it('clamps value at max boundary', async () => {
|
|
993
|
-
const user = userEvent.setup();
|
|
994
|
-
const handleChange = vi.fn();
|
|
995
|
-
render(
|
|
996
|
-
<Slider
|
|
997
|
-
label="Volume"
|
|
998
|
-
value={99}
|
|
999
|
-
min={0}
|
|
1000
|
-
max={100}
|
|
1001
|
-
step={5}
|
|
1002
|
-
onChange={handleChange}
|
|
1003
|
-
/>,
|
|
1004
|
-
);
|
|
1005
|
-
const slider = screen.getByRole('slider');
|
|
1006
|
-
act(() => {
|
|
1007
|
-
slider.focus();
|
|
1008
|
-
});
|
|
1009
|
-
await user.keyboard('{ArrowRight}');
|
|
1010
|
-
expect(handleChange).toHaveBeenCalledWith(100);
|
|
1011
|
-
});
|
|
1012
|
-
|
|
1013
|
-
it('clamps value at min boundary', async () => {
|
|
1014
|
-
const user = userEvent.setup();
|
|
1015
|
-
const handleChange = vi.fn();
|
|
1016
|
-
render(
|
|
1017
|
-
<Slider
|
|
1018
|
-
label="Volume"
|
|
1019
|
-
value={1}
|
|
1020
|
-
min={0}
|
|
1021
|
-
max={100}
|
|
1022
|
-
step={5}
|
|
1023
|
-
onChange={handleChange}
|
|
1024
|
-
/>,
|
|
1025
|
-
);
|
|
1026
|
-
const slider = screen.getByRole('slider');
|
|
1027
|
-
act(() => {
|
|
1028
|
-
slider.focus();
|
|
1029
|
-
});
|
|
1030
|
-
await user.keyboard('{ArrowLeft}');
|
|
1031
|
-
expect(handleChange).toHaveBeenCalledWith(0);
|
|
1032
|
-
});
|
|
1033
|
-
|
|
1034
|
-
describe('disabledMessage', () => {
|
|
1035
|
-
const h = {hidden: true} as const;
|
|
1036
|
-
|
|
1037
|
-
function getTrack(): HTMLElement {
|
|
1038
|
-
return screen.getByRole('slider').parentElement!;
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
it('shows the reason tooltip on hover when disabled with a reason', async () => {
|
|
1042
|
-
render(
|
|
1043
|
-
<Slider
|
|
1044
|
-
label="Volume"
|
|
1045
|
-
value={50}
|
|
1046
|
-
valueDisplay="none"
|
|
1047
|
-
isDisabled
|
|
1048
|
-
disabledMessage="Volume is locked while sharing your screen"
|
|
1049
|
-
/>,
|
|
1050
|
-
);
|
|
1051
|
-
const tooltip = screen.getByRole('tooltip', h);
|
|
1052
|
-
expect(tooltip).toHaveTextContent(
|
|
1053
|
-
'Volume is locked while sharing your screen',
|
|
1054
|
-
);
|
|
1055
|
-
fireEvent.mouseEnter(getTrack());
|
|
1056
|
-
await waitFor(() => expect(tooltip).toHaveAttribute('popover-open'));
|
|
1057
|
-
fireEvent.mouseLeave(getTrack());
|
|
1058
|
-
await waitFor(() => expect(tooltip).not.toHaveAttribute('popover-open'));
|
|
1059
|
-
});
|
|
1060
|
-
|
|
1061
|
-
it('shows the reason tooltip on keyboard focus', async () => {
|
|
1062
|
-
const user = userEvent.setup();
|
|
1063
|
-
render(
|
|
1064
|
-
<Slider
|
|
1065
|
-
label="Volume"
|
|
1066
|
-
value={50}
|
|
1067
|
-
valueDisplay="none"
|
|
1068
|
-
isDisabled
|
|
1069
|
-
disabledMessage="Volume is locked while sharing your screen"
|
|
1070
|
-
/>,
|
|
1071
|
-
);
|
|
1072
|
-
const tooltip = screen.getByRole('tooltip', h);
|
|
1073
|
-
await user.tab();
|
|
1074
|
-
expect(screen.getByRole('slider')).toHaveFocus();
|
|
1075
|
-
await waitFor(() => expect(tooltip).toHaveAttribute('popover-open'));
|
|
1076
|
-
});
|
|
1077
|
-
|
|
1078
|
-
it('does not render a tooltip when not disabled', () => {
|
|
1079
|
-
render(
|
|
1080
|
-
<Slider
|
|
1081
|
-
label="Volume"
|
|
1082
|
-
value={50}
|
|
1083
|
-
valueDisplay="none"
|
|
1084
|
-
disabledMessage="Volume is locked while sharing your screen"
|
|
1085
|
-
/>,
|
|
1086
|
-
);
|
|
1087
|
-
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
1088
|
-
});
|
|
1089
|
-
|
|
1090
|
-
it('does not render a tooltip when disabled without a reason', () => {
|
|
1091
|
-
render(
|
|
1092
|
-
<Slider label="Volume" value={50} valueDisplay="none" isDisabled />,
|
|
1093
|
-
);
|
|
1094
|
-
expect(screen.queryByRole('tooltip', h)).not.toBeInTheDocument();
|
|
1095
|
-
});
|
|
1096
|
-
|
|
1097
|
-
it('keeps the thumb focusable via aria-disabled when a reason is provided', () => {
|
|
1098
|
-
render(
|
|
1099
|
-
<Slider
|
|
1100
|
-
label="Volume"
|
|
1101
|
-
value={50}
|
|
1102
|
-
valueDisplay="none"
|
|
1103
|
-
isDisabled
|
|
1104
|
-
disabledMessage="Volume is locked while sharing your screen"
|
|
1105
|
-
/>,
|
|
1106
|
-
);
|
|
1107
|
-
const thumb = screen.getByRole('slider');
|
|
1108
|
-
expect(thumb).toHaveAttribute('aria-disabled', 'true');
|
|
1109
|
-
expect(thumb).toHaveAttribute('tabindex', '0');
|
|
1110
|
-
});
|
|
1111
|
-
|
|
1112
|
-
it('links the reason tooltip via aria-describedby', () => {
|
|
1113
|
-
render(
|
|
1114
|
-
<Slider
|
|
1115
|
-
label="Volume"
|
|
1116
|
-
value={50}
|
|
1117
|
-
valueDisplay="none"
|
|
1118
|
-
isDisabled
|
|
1119
|
-
disabledMessage="Volume is locked while sharing your screen"
|
|
1120
|
-
/>,
|
|
1121
|
-
);
|
|
1122
|
-
const thumb = screen.getByRole('slider');
|
|
1123
|
-
const tooltip = screen.getByRole('tooltip', h);
|
|
1124
|
-
expect(thumb.getAttribute('aria-describedby')).toContain(tooltip.id);
|
|
1125
|
-
});
|
|
1126
|
-
|
|
1127
|
-
it('blocks value changes while focusable-disabled', async () => {
|
|
1128
|
-
const user = userEvent.setup();
|
|
1129
|
-
const onChange = vi.fn();
|
|
1130
|
-
render(
|
|
1131
|
-
<Slider
|
|
1132
|
-
label="Volume"
|
|
1133
|
-
value={50}
|
|
1134
|
-
valueDisplay="none"
|
|
1135
|
-
onChange={onChange}
|
|
1136
|
-
isDisabled
|
|
1137
|
-
disabledMessage="Volume is locked while sharing your screen"
|
|
1138
|
-
/>,
|
|
1139
|
-
);
|
|
1140
|
-
const thumb = screen.getByRole('slider');
|
|
1141
|
-
act(() => thumb.focus());
|
|
1142
|
-
await user.keyboard('{ArrowRight}');
|
|
1143
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
1144
|
-
});
|
|
1145
|
-
|
|
1146
|
-
it('stays focusable when disabled without a reason', () => {
|
|
1147
|
-
render(
|
|
1148
|
-
<Slider label="Volume" value={50} valueDisplay="none" isDisabled />,
|
|
1149
|
-
);
|
|
1150
|
-
expect(screen.getByRole('slider')).toHaveAttribute('tabindex', '0');
|
|
1151
|
-
});
|
|
1152
|
-
});
|
|
1153
|
-
describe('form participation', () => {
|
|
1154
|
-
it('submits the value under htmlName', () => {
|
|
1155
|
-
const {container} = render(
|
|
1156
|
-
<form>
|
|
1157
|
-
<Slider label="Volume" htmlName="volume" value={50} />
|
|
1158
|
-
</form>,
|
|
1159
|
-
);
|
|
1160
|
-
const data = new FormData(container.querySelector('form')!);
|
|
1161
|
-
expect(data.get('volume')).toBe('50');
|
|
1162
|
-
});
|
|
1163
|
-
|
|
1164
|
-
it('submits both range values under the same name', () => {
|
|
1165
|
-
const {container} = render(
|
|
1166
|
-
<form>
|
|
1167
|
-
<Slider
|
|
1168
|
-
label="Price"
|
|
1169
|
-
htmlName="price"
|
|
1170
|
-
value={[20, 80] as [number, number]}
|
|
1171
|
-
/>
|
|
1172
|
-
</form>,
|
|
1173
|
-
);
|
|
1174
|
-
const data = new FormData(container.querySelector('form')!);
|
|
1175
|
-
expect(data.getAll('price')).toEqual(['20', '80']);
|
|
1176
|
-
});
|
|
1177
|
-
|
|
1178
|
-
it('is excluded from form data when disabled', () => {
|
|
1179
|
-
const {container} = render(
|
|
1180
|
-
<form>
|
|
1181
|
-
<Slider label="Volume" htmlName="volume" value={50} isDisabled />
|
|
1182
|
-
</form>,
|
|
1183
|
-
);
|
|
1184
|
-
expect([
|
|
1185
|
-
...new FormData(container.querySelector('form')!).keys(),
|
|
1186
|
-
]).toEqual([]);
|
|
1187
|
-
});
|
|
1188
|
-
});
|
|
1189
|
-
|
|
1190
|
-
describe('focus ring modality', () => {
|
|
1191
|
-
beforeEach(() => {
|
|
1192
|
-
__resetInteractionModalityForTest();
|
|
1193
|
-
});
|
|
1194
|
-
|
|
1195
|
-
// The ring is a stylex class, so derive it from the same source the
|
|
1196
|
-
// component applies rather than hardcoding a hash.
|
|
1197
|
-
const RING = stylex
|
|
1198
|
-
.props(focusOutlineStyles.focusVisible)
|
|
1199
|
-
.className!.split(' ');
|
|
1200
|
-
const isRinged = (el: HTMLElement) =>
|
|
1201
|
-
RING.every(c => el.classList.contains(c));
|
|
1202
|
-
|
|
1203
|
-
// The track has no layout in jsdom; pointer maths needs a real rect.
|
|
1204
|
-
const grabTrack = (thumb: HTMLElement) => {
|
|
1205
|
-
const track = thumb.parentElement!;
|
|
1206
|
-
track.getBoundingClientRect = () => ({
|
|
1207
|
-
left: 0,
|
|
1208
|
-
top: 0,
|
|
1209
|
-
right: 200,
|
|
1210
|
-
bottom: 20,
|
|
1211
|
-
width: 200,
|
|
1212
|
-
height: 20,
|
|
1213
|
-
x: 0,
|
|
1214
|
-
y: 0,
|
|
1215
|
-
toJSON: () => {},
|
|
1216
|
-
});
|
|
1217
|
-
fireEvent.pointerDown(track, {clientX: 100, clientY: 10, pointerId: 1});
|
|
1218
|
-
};
|
|
1219
|
-
|
|
1220
|
-
it('rings when the thumb is reached with the keyboard', async () => {
|
|
1221
|
-
const user = userEvent.setup();
|
|
1222
|
-
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
1223
|
-
await user.tab();
|
|
1224
|
-
expect(isRinged(screen.getByRole('slider'))).toBe(true);
|
|
1225
|
-
});
|
|
1226
|
-
|
|
1227
|
-
it('does not ring when the thumb is grabbed with the mouse', () => {
|
|
1228
|
-
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
1229
|
-
const thumb = screen.getByRole('slider');
|
|
1230
|
-
grabTrack(thumb);
|
|
1231
|
-
expect(thumb).toHaveFocus();
|
|
1232
|
-
expect(isRinged(thumb)).toBe(false);
|
|
1233
|
-
});
|
|
1234
|
-
|
|
1235
|
-
it('drops the ring when the mouse grabs a thumb that already had it', async () => {
|
|
1236
|
-
const user = userEvent.setup();
|
|
1237
|
-
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
1238
|
-
await user.tab();
|
|
1239
|
-
const thumb = screen.getByRole('slider');
|
|
1240
|
-
expect(isRinged(thumb)).toBe(true);
|
|
1241
|
-
// Already focused, so focus() fires no focus event.
|
|
1242
|
-
grabTrack(thumb);
|
|
1243
|
-
expect(isRinged(thumb)).toBe(false);
|
|
1244
|
-
});
|
|
1245
|
-
|
|
1246
|
-
it('brings the ring back when an arrow key follows a mouse drag', () => {
|
|
1247
|
-
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
1248
|
-
const thumb = screen.getByRole('slider');
|
|
1249
|
-
grabTrack(thumb);
|
|
1250
|
-
expect(isRinged(thumb)).toBe(false);
|
|
1251
|
-
fireEvent.keyDown(thumb, {key: 'ArrowRight'});
|
|
1252
|
-
expect(isRinged(thumb)).toBe(true);
|
|
1253
|
-
});
|
|
1254
|
-
|
|
1255
|
-
it('leaves the ring off for a modifier chord after a mouse drag', () => {
|
|
1256
|
-
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
1257
|
-
const thumb = screen.getByRole('slider');
|
|
1258
|
-
grabTrack(thumb);
|
|
1259
|
-
// Copying or reloading is not navigation, and the mouse is still on it.
|
|
1260
|
-
fireEvent.keyDown(thumb, {key: 'c', metaKey: true});
|
|
1261
|
-
expect(isRinged(thumb)).toBe(false);
|
|
1262
|
-
});
|
|
1263
|
-
|
|
1264
|
-
it('leaves the ring off for a bare Shift press after a mouse drag', () => {
|
|
1265
|
-
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
1266
|
-
const thumb = screen.getByRole('slider');
|
|
1267
|
-
grabTrack(thumb);
|
|
1268
|
-
fireEvent.keyDown(thumb, {key: 'Shift', shiftKey: true});
|
|
1269
|
-
expect(getInteractionModality()).toBe('keyboard');
|
|
1270
|
-
expect(isRinged(thumb)).toBe(false);
|
|
1271
|
-
});
|
|
1272
|
-
|
|
1273
|
-
it.each([
|
|
1274
|
-
['Meta', {metaKey: true}],
|
|
1275
|
-
['Alt', {altKey: true}],
|
|
1276
|
-
['Control', {ctrlKey: true}],
|
|
1277
|
-
])(
|
|
1278
|
-
'leaves the ring off for %s and its chord after bare Shift',
|
|
1279
|
-
(key, flags) => {
|
|
1280
|
-
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
1281
|
-
const thumb = screen.getByRole('slider');
|
|
1282
|
-
grabTrack(thumb);
|
|
1283
|
-
fireEvent.keyDown(thumb, {key: 'Shift', shiftKey: true});
|
|
1284
|
-
fireEvent.keyUp(thumb, {key: 'Shift'});
|
|
1285
|
-
fireEvent.keyDown(thumb, {key, ...flags});
|
|
1286
|
-
expect(isRinged(thumb)).toBe(false);
|
|
1287
|
-
fireEvent.keyDown(thumb, {key: 'c', ...flags});
|
|
1288
|
-
expect(getInteractionModality()).toBe('keyboard');
|
|
1289
|
-
expect(isRinged(thumb)).toBe(false);
|
|
1290
|
-
},
|
|
1291
|
-
);
|
|
1292
|
-
|
|
1293
|
-
it('restores the ring and changes value for Shift+Arrow after bare Shift', () => {
|
|
1294
|
-
const onChange = vi.fn();
|
|
1295
|
-
render(<Slider label="Volume" value={50} onChange={onChange} />);
|
|
1296
|
-
const thumb = screen.getByRole('slider');
|
|
1297
|
-
grabTrack(thumb);
|
|
1298
|
-
onChange.mockClear();
|
|
1299
|
-
fireEvent.keyDown(thumb, {key: 'Shift', shiftKey: true});
|
|
1300
|
-
expect(isRinged(thumb)).toBe(false);
|
|
1301
|
-
expect(onChange).not.toHaveBeenCalled();
|
|
1302
|
-
|
|
1303
|
-
fireEvent.keyDown(thumb, {key: 'ArrowRight', shiftKey: true});
|
|
1304
|
-
expect(isRinged(thumb)).toBe(true);
|
|
1305
|
-
expect(onChange).toHaveBeenCalledWith(51);
|
|
1306
|
-
});
|
|
1307
|
-
|
|
1308
|
-
it('preserves an existing keyboard ring when Shift is pressed', async () => {
|
|
1309
|
-
const user = userEvent.setup();
|
|
1310
|
-
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
1311
|
-
await user.tab();
|
|
1312
|
-
const thumb = screen.getByRole('slider');
|
|
1313
|
-
|
|
1314
|
-
fireEvent.keyDown(thumb, {key: 'Shift', shiftKey: true});
|
|
1315
|
-
expect(isRinged(thumb)).toBe(true);
|
|
1316
|
-
});
|
|
1317
|
-
|
|
1318
|
-
it('rings when Shift+Tab returns to a mouse-focused thumb', async () => {
|
|
1319
|
-
const user = userEvent.setup();
|
|
1320
|
-
render(
|
|
1321
|
-
<>
|
|
1322
|
-
<Slider label="Volume" value={50} onChange={vi.fn()} />
|
|
1323
|
-
<button type="button">After slider</button>
|
|
1324
|
-
</>,
|
|
1325
|
-
);
|
|
1326
|
-
const thumb = screen.getByRole('slider');
|
|
1327
|
-
grabTrack(thumb);
|
|
1328
|
-
expect(isRinged(thumb)).toBe(false);
|
|
1329
|
-
await user.click(screen.getByRole('button', {name: 'After slider'}));
|
|
1330
|
-
|
|
1331
|
-
await user.tab({shift: true});
|
|
1332
|
-
expect(thumb).toHaveFocus();
|
|
1333
|
-
expect(isRinged(thumb)).toBe(true);
|
|
1334
|
-
});
|
|
1335
|
-
|
|
1336
|
-
it('drops the ring on blur', async () => {
|
|
1337
|
-
const user = userEvent.setup();
|
|
1338
|
-
render(<Slider label="Volume" value={50} onChange={vi.fn()} />);
|
|
1339
|
-
await user.tab();
|
|
1340
|
-
const thumb = screen.getByRole('slider');
|
|
1341
|
-
expect(isRinged(thumb)).toBe(true);
|
|
1342
|
-
act(() => thumb.blur());
|
|
1343
|
-
expect(isRinged(thumb)).toBe(false);
|
|
1344
|
-
});
|
|
1345
|
-
|
|
1346
|
-
it('rings the range thumb the keyboard reached, not its sibling', async () => {
|
|
1347
|
-
const user = userEvent.setup();
|
|
1348
|
-
render(
|
|
1349
|
-
<Slider
|
|
1350
|
-
label="Price"
|
|
1351
|
-
value={[20, 80] as [number, number]}
|
|
1352
|
-
onChange={vi.fn()}
|
|
1353
|
-
/>,
|
|
1354
|
-
);
|
|
1355
|
-
await user.tab();
|
|
1356
|
-
await user.tab();
|
|
1357
|
-
const thumbs = screen.getAllByRole('slider');
|
|
1358
|
-
expect(thumbs[1]).toHaveFocus();
|
|
1359
|
-
expect(isRinged(thumbs[1])).toBe(true);
|
|
1360
|
-
expect(isRinged(thumbs[0])).toBe(false);
|
|
1361
|
-
});
|
|
1362
|
-
});
|
|
1363
|
-
});
|
|
1364
|
-
|
|
1365
|
-
describe('one pointer per drag', () => {
|
|
1366
|
-
// valueDisplay="none" keeps the thumb a direct child of the track, so the
|
|
1367
|
-
// mocked rect lands on it: 200 px wide, thumbs travel 10 px (0) to 190 px
|
|
1368
|
-
// (100), value = (x - 10) / 1.8.
|
|
1369
|
-
function ControlledSlider({
|
|
1370
|
-
id,
|
|
1371
|
-
onChangeEnd,
|
|
1372
|
-
}: {
|
|
1373
|
-
id: string;
|
|
1374
|
-
onChangeEnd?: (value: number) => void;
|
|
1375
|
-
}) {
|
|
1376
|
-
const [value, setValue] = useState(50);
|
|
1377
|
-
return (
|
|
1378
|
-
<Slider
|
|
1379
|
-
label={id}
|
|
1380
|
-
value={value}
|
|
1381
|
-
min={0}
|
|
1382
|
-
max={100}
|
|
1383
|
-
valueDisplay="none"
|
|
1384
|
-
onChange={setValue}
|
|
1385
|
-
onChangeEnd={onChangeEnd}
|
|
1386
|
-
/>
|
|
1387
|
-
);
|
|
1388
|
-
}
|
|
1389
|
-
|
|
1390
|
-
function trackOf(thumb: HTMLElement): HTMLElement {
|
|
1391
|
-
const track = thumb.parentElement!;
|
|
1392
|
-
track.getBoundingClientRect = () => ({
|
|
1393
|
-
left: 0,
|
|
1394
|
-
top: 0,
|
|
1395
|
-
right: 200,
|
|
1396
|
-
bottom: 20,
|
|
1397
|
-
width: 200,
|
|
1398
|
-
height: 20,
|
|
1399
|
-
x: 0,
|
|
1400
|
-
y: 0,
|
|
1401
|
-
toJSON: () => {},
|
|
1402
|
-
});
|
|
1403
|
-
return track;
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
it('ignores a second finger that lands, moves or lifts during a drag', () => {
|
|
1407
|
-
const onChangeEnd = vi.fn();
|
|
1408
|
-
render(<ControlledSlider id="Volume" onChangeEnd={onChangeEnd} />);
|
|
1409
|
-
const thumb = screen.getByRole('slider');
|
|
1410
|
-
const track = trackOf(thumb);
|
|
1411
|
-
|
|
1412
|
-
fireEvent.pointerDown(track, {clientX: 100, clientY: 10, pointerId: 1});
|
|
1413
|
-
fireEvent.pointerDown(track, {clientX: 28, clientY: 10, pointerId: 2});
|
|
1414
|
-
expect(thumb).toHaveAttribute('aria-valuenow', '50');
|
|
1415
|
-
|
|
1416
|
-
fireEvent.pointerMove(track, {clientX: 136, clientY: 10, pointerId: 1});
|
|
1417
|
-
fireEvent.pointerMove(track, {clientX: 46, clientY: 10, pointerId: 2});
|
|
1418
|
-
expect(thumb).toHaveAttribute('aria-valuenow', '70');
|
|
1419
|
-
|
|
1420
|
-
// The second finger lifting does not end the first finger's drag.
|
|
1421
|
-
fireEvent.pointerUp(track, {clientX: 46, clientY: 10, pointerId: 2});
|
|
1422
|
-
expect(onChangeEnd).not.toHaveBeenCalled();
|
|
1423
|
-
expect(declaresPressedOverlay(thumb)).toBe(true);
|
|
1424
|
-
|
|
1425
|
-
fireEvent.pointerMove(track, {clientX: 154, clientY: 10, pointerId: 1});
|
|
1426
|
-
fireEvent.pointerUp(track, {clientX: 154, clientY: 10, pointerId: 1});
|
|
1427
|
-
expect(thumb).toHaveAttribute('aria-valuenow', '80');
|
|
1428
|
-
expect(onChangeEnd).toHaveBeenCalledOnce();
|
|
1429
|
-
expect(onChangeEnd).toHaveBeenCalledWith(80);
|
|
1430
|
-
expect(declaresPressedOverlay(thumb)).toBe(false);
|
|
1431
|
-
});
|
|
1432
|
-
|
|
1433
|
-
it('ends the drag when its pointer capture is lost without an up', () => {
|
|
1434
|
-
const onChangeEnd = vi.fn();
|
|
1435
|
-
render(<ControlledSlider id="Volume" onChangeEnd={onChangeEnd} />);
|
|
1436
|
-
const thumb = screen.getByRole('slider');
|
|
1437
|
-
const track = trackOf(thumb);
|
|
1438
|
-
|
|
1439
|
-
fireEvent.pointerDown(track, {clientX: 136, clientY: 10, pointerId: 1});
|
|
1440
|
-
fireEvent.lostPointerCapture(track, {pointerId: 1});
|
|
1441
|
-
expect(onChangeEnd).toHaveBeenCalledOnce();
|
|
1442
|
-
expect(onChangeEnd).toHaveBeenCalledWith(70);
|
|
1443
|
-
expect(declaresPressedOverlay(thumb)).toBe(false);
|
|
1444
|
-
|
|
1445
|
-
// The slider answers the next press.
|
|
1446
|
-
fireEvent.pointerDown(track, {clientX: 28, clientY: 10, pointerId: 3});
|
|
1447
|
-
expect(thumb).toHaveAttribute('aria-valuenow', '10');
|
|
1448
|
-
});
|
|
1449
|
-
|
|
1450
|
-
it('ends the drag when its control node is replaced mid-drag and the capture is lost', () => {
|
|
1451
|
-
// A FormLayout direction change re-renders the field in another layout,
|
|
1452
|
-
// replacing the control node while the drag holds it. The browser then
|
|
1453
|
-
// fires lostpointercapture at the document, not at the removed node.
|
|
1454
|
-
const onChangeEnd = vi.fn();
|
|
1455
|
-
function InLayout({
|
|
1456
|
-
direction,
|
|
1457
|
-
}: {
|
|
1458
|
-
direction: 'vertical' | 'horizontal-labels';
|
|
1459
|
-
}) {
|
|
1460
|
-
return (
|
|
1461
|
-
<FormLayout direction={direction}>
|
|
1462
|
-
<ControlledSlider id="Volume" onChangeEnd={onChangeEnd} />
|
|
1463
|
-
</FormLayout>
|
|
1464
|
-
);
|
|
1465
|
-
}
|
|
1466
|
-
const {rerender} = render(<InLayout direction="vertical" />);
|
|
1467
|
-
const before = trackOf(screen.getByRole('slider'));
|
|
1468
|
-
fireEvent.pointerDown(before, {clientX: 136, clientY: 10, pointerId: 1});
|
|
1469
|
-
|
|
1470
|
-
rerender(<InLayout direction="horizontal-labels" />);
|
|
1471
|
-
fireEvent.lostPointerCapture(document, {pointerId: 1});
|
|
1472
|
-
expect(onChangeEnd).toHaveBeenCalledOnce();
|
|
1473
|
-
|
|
1474
|
-
// The slider answers the next press on whichever node it renders now.
|
|
1475
|
-
const thumb = screen.getByRole('slider');
|
|
1476
|
-
const after = trackOf(thumb);
|
|
1477
|
-
fireEvent.pointerDown(after, {clientX: 28, clientY: 10, pointerId: 3});
|
|
1478
|
-
expect(thumb).toHaveAttribute('aria-valuenow', '10');
|
|
1479
|
-
});
|
|
1480
|
-
|
|
1481
|
-
it('holds a document listener only while a drag is in progress', () => {
|
|
1482
|
-
const add = vi.spyOn(document, 'addEventListener');
|
|
1483
|
-
const remove = vi.spyOn(document, 'removeEventListener');
|
|
1484
|
-
const lostCapture = (spy: typeof add) =>
|
|
1485
|
-
spy.mock.calls.filter(([type]) => type === 'lostpointercapture');
|
|
1486
|
-
const {unmount} = render(<ControlledSlider id="Volume" />);
|
|
1487
|
-
const track = trackOf(screen.getByRole('slider'));
|
|
1488
|
-
// Idle: no document listener.
|
|
1489
|
-
expect(lostCapture(add)).toHaveLength(0);
|
|
1490
|
-
|
|
1491
|
-
fireEvent.pointerDown(track, {clientX: 136, clientY: 10, pointerId: 1});
|
|
1492
|
-
expect(lostCapture(add)).toHaveLength(1);
|
|
1493
|
-
const listener = lostCapture(add)[0][1];
|
|
1494
|
-
fireEvent.pointerUp(track, {clientX: 136, clientY: 10, pointerId: 1});
|
|
1495
|
-
expect(lostCapture(remove).map(([, fn]) => fn)).toEqual([listener]);
|
|
1496
|
-
|
|
1497
|
-
// A slider unmounted mid-drag removes its listener too.
|
|
1498
|
-
fireEvent.pointerDown(track, {clientX: 28, clientY: 10, pointerId: 2});
|
|
1499
|
-
const second = lostCapture(add)[1][1];
|
|
1500
|
-
unmount();
|
|
1501
|
-
expect(lostCapture(remove).map(([, fn]) => fn)).toEqual([listener, second]);
|
|
1502
|
-
add.mockRestore();
|
|
1503
|
-
remove.mockRestore();
|
|
1504
|
-
});
|
|
1505
|
-
|
|
1506
|
-
it('lets two fingers drag two sliders at once', () => {
|
|
1507
|
-
render(
|
|
1508
|
-
<>
|
|
1509
|
-
<ControlledSlider id="Treble" />
|
|
1510
|
-
<ControlledSlider id="Bass" />
|
|
1511
|
-
</>,
|
|
1512
|
-
);
|
|
1513
|
-
const treble = screen.getByRole('slider', {name: 'Treble'});
|
|
1514
|
-
const bass = screen.getByRole('slider', {name: 'Bass'});
|
|
1515
|
-
const trebleTrack = trackOf(treble);
|
|
1516
|
-
const bassTrack = trackOf(bass);
|
|
1517
|
-
|
|
1518
|
-
fireEvent.pointerDown(trebleTrack, {
|
|
1519
|
-
clientX: 100,
|
|
1520
|
-
clientY: 10,
|
|
1521
|
-
pointerId: 1,
|
|
1522
|
-
});
|
|
1523
|
-
fireEvent.pointerDown(bassTrack, {clientX: 100, clientY: 10, pointerId: 2});
|
|
1524
|
-
fireEvent.pointerMove(trebleTrack, {
|
|
1525
|
-
clientX: 154,
|
|
1526
|
-
clientY: 10,
|
|
1527
|
-
pointerId: 1,
|
|
1528
|
-
});
|
|
1529
|
-
fireEvent.pointerMove(bassTrack, {clientX: 28, clientY: 10, pointerId: 2});
|
|
1530
|
-
|
|
1531
|
-
expect(treble).toHaveAttribute('aria-valuenow', '80');
|
|
1532
|
-
expect(bass).toHaveAttribute('aria-valuenow', '10');
|
|
1533
|
-
});
|
|
1534
|
-
});
|
|
1535
|
-
|
|
1536
|
-
describe('pressed state', () => {
|
|
1537
|
-
it('paints the pressed overlay on the thumb for as long as it is dragged, from wherever the press lands', () => {
|
|
1538
|
-
render(
|
|
1539
|
-
<Slider label="Volume" value={50} min={0} max={100} onChange={vi.fn()} />,
|
|
1540
|
-
);
|
|
1541
|
-
const thumb = screen.getByRole('slider');
|
|
1542
|
-
const trackContainer = thumb.parentElement!;
|
|
1543
|
-
trackContainer.getBoundingClientRect = () => ({
|
|
1544
|
-
left: 0,
|
|
1545
|
-
top: 0,
|
|
1546
|
-
right: 200,
|
|
1547
|
-
bottom: 20,
|
|
1548
|
-
width: 200,
|
|
1549
|
-
height: 20,
|
|
1550
|
-
x: 0,
|
|
1551
|
-
y: 0,
|
|
1552
|
-
toJSON: () => {},
|
|
1553
|
-
});
|
|
1554
|
-
|
|
1555
|
-
expect(declaresPressedOverlay(thumb)).toBe(false);
|
|
1556
|
-
// A slider is a drag: the press lands on the track, not the thumb, and
|
|
1557
|
-
// the thumb follows it. The pressed paint follows the drag.
|
|
1558
|
-
fireEvent.pointerDown(trackContainer, {
|
|
1559
|
-
clientX: 20,
|
|
1560
|
-
clientY: 10,
|
|
1561
|
-
pointerId: 1,
|
|
1562
|
-
});
|
|
1563
|
-
expect(declaresPressedOverlay(thumb)).toBe(true);
|
|
1564
|
-
fireEvent.pointerMove(trackContainer, {
|
|
1565
|
-
clientX: 120,
|
|
1566
|
-
clientY: 10,
|
|
1567
|
-
pointerId: 1,
|
|
1568
|
-
});
|
|
1569
|
-
expect(declaresPressedOverlay(thumb)).toBe(true);
|
|
1570
|
-
fireEvent.pointerUp(trackContainer, {
|
|
1571
|
-
clientX: 120,
|
|
1572
|
-
clientY: 10,
|
|
1573
|
-
pointerId: 1,
|
|
1574
|
-
});
|
|
1575
|
-
expect(declaresPressedOverlay(thumb)).toBe(false);
|
|
1576
|
-
});
|
|
1577
|
-
|
|
1578
|
-
it('paints only the thumb being dragged in a range slider', () => {
|
|
1579
|
-
render(
|
|
1580
|
-
<Slider
|
|
1581
|
-
label="Price"
|
|
1582
|
-
value={[20, 80] as [number, number]}
|
|
1583
|
-
min={0}
|
|
1584
|
-
max={100}
|
|
1585
|
-
onChange={vi.fn()}
|
|
1586
|
-
/>,
|
|
1587
|
-
);
|
|
1588
|
-
const [start, end] = screen.getAllByRole('slider');
|
|
1589
|
-
// In range mode the control is the group; each thumb sits in its own
|
|
1590
|
-
// value-tooltip wrapper.
|
|
1591
|
-
const trackContainer = screen.getByRole('group');
|
|
1592
|
-
trackContainer.getBoundingClientRect = () => ({
|
|
1593
|
-
left: 0,
|
|
1594
|
-
top: 0,
|
|
1595
|
-
right: 200,
|
|
1596
|
-
bottom: 20,
|
|
1597
|
-
width: 200,
|
|
1598
|
-
height: 20,
|
|
1599
|
-
x: 0,
|
|
1600
|
-
y: 0,
|
|
1601
|
-
toJSON: () => {},
|
|
1602
|
-
});
|
|
1603
|
-
fireEvent.pointerDown(trackContainer, {
|
|
1604
|
-
clientX: 170,
|
|
1605
|
-
clientY: 10,
|
|
1606
|
-
pointerId: 1,
|
|
1607
|
-
});
|
|
1608
|
-
expect(declaresPressedOverlay(end)).toBe(true);
|
|
1609
|
-
expect(declaresPressedOverlay(start)).toBe(false);
|
|
1610
|
-
fireEvent.pointerUp(trackContainer, {
|
|
1611
|
-
clientX: 170,
|
|
1612
|
-
clientY: 10,
|
|
1613
|
-
pointerId: 1,
|
|
1614
|
-
});
|
|
1615
|
-
expect(declaresPressedOverlay(end)).toBe(false);
|
|
1616
|
-
});
|
|
1617
|
-
|
|
1618
|
-
it('keeps a direct press on the visible upper thumb when range values coincide', () => {
|
|
1619
|
-
render(
|
|
1620
|
-
<Slider
|
|
1621
|
-
label="Price"
|
|
1622
|
-
value={[50, 50] as [number, number]}
|
|
1623
|
-
min={0}
|
|
1624
|
-
max={100}
|
|
1625
|
-
onChange={vi.fn()}
|
|
1626
|
-
/>,
|
|
1627
|
-
);
|
|
1628
|
-
const [start, end] = screen.getAllByRole('slider');
|
|
1629
|
-
const trackContainer = screen.getByRole('group');
|
|
1630
|
-
trackContainer.getBoundingClientRect = () => ({
|
|
1631
|
-
left: 0,
|
|
1632
|
-
top: 0,
|
|
1633
|
-
right: 200,
|
|
1634
|
-
bottom: 20,
|
|
1635
|
-
width: 200,
|
|
1636
|
-
height: 20,
|
|
1637
|
-
x: 0,
|
|
1638
|
-
y: 0,
|
|
1639
|
-
toJSON: () => {},
|
|
1640
|
-
});
|
|
1641
|
-
|
|
1642
|
-
fireEvent.pointerDown(end, {
|
|
1643
|
-
clientX: 100,
|
|
1644
|
-
clientY: 10,
|
|
1645
|
-
pointerId: 1,
|
|
1646
|
-
});
|
|
1647
|
-
expect(declaresPressedOverlay(end)).toBe(true);
|
|
1648
|
-
expect(declaresPressedOverlay(start)).toBe(false);
|
|
1649
|
-
});
|
|
1650
|
-
|
|
1651
|
-
it('does not press a disabled slider', () => {
|
|
1652
|
-
render(<Slider label="Volume" value={50} isDisabled onChange={vi.fn()} />);
|
|
1653
|
-
const thumb = screen.getByRole('slider');
|
|
1654
|
-
fireEvent.pointerDown(thumb.parentElement!, {
|
|
1655
|
-
clientX: 20,
|
|
1656
|
-
clientY: 10,
|
|
1657
|
-
pointerId: 1,
|
|
1658
|
-
});
|
|
1659
|
-
expect(declaresPressedOverlay(thumb)).toBe(false);
|
|
1660
|
-
});
|
|
1661
|
-
});
|