@astryxdesign/core 0.5.0 → 0.5.1-canary.f64186a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +222 -0
- package/dist/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +45 -20
- package/dist/AspectRatio/AspectRatio.d.ts +6 -6
- package/dist/Avatar/Avatar.d.ts +25 -1
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +43 -9
- package/dist/Avatar/index.d.ts +2 -2
- package/dist/Avatar/index.d.ts.map +1 -1
- package/dist/Avatar/index.js +1 -1
- package/dist/AvatarGroup/AvatarGroup.d.ts +9 -2
- package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroup.js +5 -2
- package/dist/AvatarGroup/AvatarGroupContext.d.ts +2 -1
- package/dist/AvatarGroup/AvatarGroupContext.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
- package/dist/AvatarGroup/AvatarGroupOverflow.js +11 -7
- package/dist/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +26 -2
- package/dist/Banner/Banner.d.ts +10 -1
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +11 -2
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +8 -7
- package/dist/Calendar/Calendar.d.ts +4 -2
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +15 -21
- package/dist/Calendar/hooks/useCalendarDays.js +4 -6
- package/dist/Calendar/hooks/useCalendarNavigation.js +4 -6
- package/dist/Calendar/styles.d.ts +5 -20
- package/dist/Calendar/styles.d.ts.map +1 -1
- package/dist/Calendar/styles.js +15 -17
- package/dist/Card/Card.d.ts +12 -12
- package/dist/Card/Card.d.ts.map +1 -1
- package/dist/Card/Card.js +17 -9
- package/dist/Card/index.d.ts +35 -1
- package/dist/Card/index.d.ts.map +1 -1
- package/dist/Card/index.js +21 -1
- package/dist/Carousel/Carousel.d.ts.map +1 -1
- package/dist/Carousel/Carousel.js +108 -7
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +7 -1
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +15 -4
- package/dist/CodeBlock/highlightRanges.js +1 -1
- package/dist/CodeBlock/highlightStyles.js +13 -13
- package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
- package/dist/CommandPalette/CommandPaletteItem.js +2 -7
- package/dist/ComplexSelector/ComplexSelector.d.ts +10 -2
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +14 -7
- package/dist/DateInput/DateInput.d.ts +43 -0
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +22 -5
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +5 -3
- package/dist/DateInput/MonthYearWheels.d.ts.map +1 -1
- package/dist/DateInput/MonthYearWheels.js +6 -4
- package/dist/DateInput/NativeDateField.d.ts +10 -0
- package/dist/DateInput/NativeDateField.d.ts.map +1 -0
- package/dist/DateInput/NativeDateField.js +494 -0
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +52 -25
- package/dist/DateInput/Wheel.d.ts.map +1 -1
- package/dist/DateInput/Wheel.js +1 -0
- package/dist/DateInput/index.d.ts +1 -1
- package/dist/DateInput/index.d.ts.map +1 -1
- package/dist/DateInput/nativeDateSegments.d.ts +22 -0
- package/dist/DateInput/nativeDateSegments.d.ts.map +1 -0
- package/dist/DateInput/nativeDateSegments.js +111 -0
- package/dist/DateRangeInput/DateRangeInput.d.ts +4 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +3 -5
- package/dist/DateTimeInput/DateTimeInput.d.ts +23 -24
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +35 -10
- package/dist/DateTimeInput/TouchDateTimeField.d.ts +6 -0
- package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -0
- package/dist/DateTimeInput/TouchDateTimeField.js +1021 -0
- package/dist/Dialog/Dialog.d.ts +16 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +28 -7
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +4 -13
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +9 -1
- package/dist/Field/InputClearButton.d.ts +9 -3
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +14 -3
- package/dist/Heading/Heading.d.ts.map +1 -1
- package/dist/Heading/Heading.js +0 -1
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +104 -3
- package/dist/HoverCard/useHoverCard.d.ts +14 -2
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +7 -1
- package/dist/Icon/Icon.d.ts +4 -2
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/defaultIcons.d.ts +3 -2
- package/dist/Icon/defaultIcons.d.ts.map +1 -1
- package/dist/Icon/defaultIcons.js +7 -0
- package/dist/Icon/globalIconRegistry.d.ts +13 -0
- package/dist/Icon/globalIconRegistry.d.ts.map +1 -1
- package/dist/Icon/globalIconRegistry.js +34 -6
- package/dist/Icon/index.d.ts +1 -1
- package/dist/Icon/index.d.ts.map +1 -1
- package/dist/Icon/useIcon.d.ts +5 -2
- package/dist/Icon/useIcon.d.ts.map +1 -1
- package/dist/Icon/useIcon.js +3 -0
- package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckboxIndicator.js +6 -2
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +2 -2
- package/dist/Kbd/Kbd.d.ts.map +1 -1
- package/dist/Kbd/Kbd.js +2 -26
- package/dist/Layer/gestureCounter.d.ts +8 -0
- package/dist/Layer/gestureCounter.d.ts.map +1 -0
- package/dist/Layer/gestureCounter.js +53 -0
- package/dist/Layer/useLayer.d.ts +23 -13
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +146 -24
- package/dist/List/List.d.ts +1 -1
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +15 -4
- package/dist/Markdown/Markdown.d.ts +1 -1
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +20 -7
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +5 -3
- package/dist/MetadataList/MetadataListItem.d.ts +1 -1
- package/dist/MetadataList/MetadataListItem.d.ts.map +1 -1
- package/dist/MetadataList/MetadataListItem.js +4 -1
- package/dist/MultiSelector/MultiSelector.d.ts +18 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +58 -11
- package/dist/MultiSelector/hooks.d.ts +7 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +3 -2
- package/dist/NavIcon/NavIcon.d.ts.map +1 -1
- package/dist/NavIcon/NavIcon.js +5 -1
- package/dist/NavItem/navItemStyles.stylex.d.ts +0 -8
- package/dist/NavItem/navItemStyles.stylex.d.ts.map +1 -1
- package/dist/NavItem/navItemStyles.stylex.js +0 -2
- package/dist/NavMenu/NavHeadingMenu.d.ts +1 -1
- package/dist/NavMenu/NavHeadingMenu.d.ts.map +1 -1
- package/dist/NavMenu/NavHeadingMenu.js +7 -4
- package/dist/NumberInput/NumberInput.d.ts +6 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +95 -126
- package/dist/NumberInput/numberInputCommit.d.ts +34 -0
- package/dist/NumberInput/numberInputCommit.d.ts.map +1 -0
- package/dist/NumberInput/numberInputCommit.js +71 -0
- package/dist/NumberInput/numberParser.d.ts +64 -0
- package/dist/NumberInput/numberParser.d.ts.map +1 -0
- package/dist/NumberInput/numberParser.js +350 -0
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +2 -3
- package/dist/OverflowList/OverflowList.d.ts +41 -1
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +43 -2
- package/dist/Popover/Popover.d.ts.map +1 -1
- package/dist/Popover/Popover.js +8 -14
- package/dist/Popover/usePopover.d.ts +15 -41
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/Popover/usePopover.js +26 -7
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +91 -18
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +4 -2
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +18 -5
- package/dist/Resizable/useResizable.d.ts +19 -1
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +104 -38
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +9 -0
- package/dist/Selector/Selector.d.ts +18 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +92 -21
- package/dist/Selector/hooks.d.ts +7 -1
- package/dist/Selector/hooks.d.ts.map +1 -1
- package/dist/Selector/hooks.js +3 -2
- package/dist/SideNav/SideNav.d.ts +6 -1
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +57 -27
- package/dist/SideNav/SideNavHeading.d.ts.map +1 -1
- package/dist/SideNav/SideNavHeading.js +5 -4
- package/dist/SideNav/SideNavItem.d.ts +29 -4
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +75 -20
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +34 -2
- package/dist/Spinner/Spinner.d.ts +3 -1
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +199 -20
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +6 -1
- package/dist/Stepper/Step.d.ts.map +1 -1
- package/dist/Stepper/Step.js +7 -6
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +5 -1
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +6 -1
- package/dist/Table/Table.d.ts.map +1 -1
- package/dist/Table/Table.js +3 -6
- package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
- package/dist/Table/plugins/filtering/useTableFiltering.js +73 -4
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +26 -0
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +34 -3
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Table/plugins/selection/useTableSelection.js +25 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
- package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +3 -4
- package/dist/Text/Text.d.ts.map +1 -1
- package/dist/Text/Text.js +0 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +13 -8
- package/dist/Timestamp/Timestamp.d.ts +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +10 -18
- package/dist/Timestamp/formatInstant.d.ts.map +1 -1
- package/dist/Timestamp/formatInstant.js +10 -5
- package/dist/Toast/Toast.d.ts +17 -2
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +77 -11
- package/dist/Toast/ToastViewport.d.ts +1 -0
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +76 -21
- package/dist/Toast/index.d.ts +1 -1
- package/dist/Toast/index.d.ts.map +1 -1
- package/dist/Toast/types.d.ts +38 -0
- package/dist/Toast/types.d.ts.map +1 -1
- package/dist/Toast/useToastGesture.d.ts +26 -0
- package/dist/Toast/useToastGesture.d.ts.map +1 -0
- package/dist/Toast/useToastGesture.js +223 -0
- package/dist/Token/Token.d.ts +1 -1
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +23 -12
- package/dist/Token/TokenLink.d.ts +1 -1
- package/dist/Token/TokenLink.d.ts.map +1 -1
- package/dist/Token/TokenLink.js +5 -2
- package/dist/Tokenizer/Tokenizer.d.ts +12 -1
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +31 -21
- package/dist/TopNav/TopNavHeading.js +2 -2
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +3 -3
- package/dist/TopNav/TopNavMegaMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenu.js +30 -9
- package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.js +3 -3
- package/dist/TopNav/TopNavMenu.d.ts +1 -1
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +21 -6
- package/dist/TreeList/TreeList.d.ts +1 -1
- package/dist/TreeList/TreeList.d.ts.map +1 -1
- package/dist/TreeList/TreeList.js +7 -2
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +2 -2
- package/dist/Typeahead/BaseTypeahead.d.ts +33 -0
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +51 -8
- package/dist/Typeahead/Typeahead.d.ts +8 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +2 -0
- package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/Typeahead/TypeaheadItem.js +7 -2
- package/dist/astryx.css +87 -22
- package/dist/hooks/useHotkeys.d.ts.map +1 -1
- package/dist/hooks/useHotkeys.js +3 -25
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +14 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/theme/Theme.d.ts.map +1 -1
- package/dist/theme/Theme.js +46 -10
- package/dist/theme/defineTheme.d.ts +9 -3
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/defineTheme.js +5 -0
- package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
- package/dist/theme/derivedVarRegistry.js +24 -4
- package/dist/theme/generateThemeRules.d.ts +21 -0
- package/dist/theme/generateThemeRules.d.ts.map +1 -1
- package/dist/theme/generateThemeRules.js +26 -0
- package/dist/theme/syntax/tokens.d.ts +1 -1
- package/dist/theme/syntax/tokens.d.ts.map +1 -1
- package/dist/theme/syntax/tokens.js +5 -2
- package/dist/theme/useTheme.d.ts.map +1 -1
- package/dist/theme/useTheme.js +6 -7
- package/dist/utils/dateParser.d.ts +5 -8
- package/dist/utils/dateParser.d.ts.map +1 -1
- package/dist/utils/dateParser.js +10 -11
- package/dist/utils/focusOutline.stylex.d.ts +25 -0
- package/dist/utils/focusOutline.stylex.d.ts.map +1 -1
- package/dist/utils/focusOutline.stylex.js +15 -0
- package/dist/utils/interactionOverlay.stylex.d.ts +26 -0
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -0
- package/dist/utils/interactionOverlay.stylex.js +42 -0
- package/dist/utils/isApplePlatform.d.ts +18 -0
- package/dist/utils/isApplePlatform.d.ts.map +1 -0
- package/dist/utils/isApplePlatform.js +37 -0
- package/dist/utils/plainDate.d.ts +11 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +20 -4
- package/locales/af-ZA.json +7 -7
- package/locales/ar-SA.json +7 -7
- package/locales/ca-ES.json +6 -6
- package/locales/cs-CZ.json +7 -7
- package/locales/da-DK.json +7 -7
- package/locales/de-DE.json +7 -7
- package/locales/el-GR.json +7 -7
- package/locales/en.json +178 -6
- package/locales/es-ES.json +6 -6
- package/locales/fi-FI.json +7 -7
- package/locales/fr-FR.json +7 -7
- package/locales/he-IL.json +7 -7
- package/locales/hu-HU.json +7 -7
- package/locales/it-IT.json +7 -7
- package/locales/ja-JP.json +7 -7
- package/locales/ko-KR.json +7 -7
- package/locales/nl-NL.json +7 -7
- package/locales/no-NO.json +7 -7
- package/locales/pl-PL.json +7 -7
- package/locales/pseudo.json +130 -1
- package/locales/pt-BR.json +7 -7
- package/locales/pt-PT.json +7 -7
- package/locales/ro-RO.json +7 -7
- package/locales/ru-RU.json +7 -7
- package/locales/sr-SP.json +7 -7
- package/locales/sv-SE.json +7 -7
- package/locales/tr-TR.json +7 -7
- package/locales/uk-UA.json +7 -7
- package/locales/vi-VN.json +7 -7
- package/locales/zh-CN.json +7 -7
- package/locales/zh-TW.json +7 -7
- package/package.json +4 -5
- package/src/AlertDialog/AlertDialog.doc.mjs +114 -30
- package/src/AlertDialog/AlertDialog.test.tsx +211 -2
- package/src/AlertDialog/AlertDialog.tsx +62 -20
- package/src/AspectRatio/AspectRatio.doc.mjs +3 -3
- package/src/AspectRatio/AspectRatio.tsx +6 -6
- package/src/Avatar/Avatar.doc.mjs +12 -2
- package/src/Avatar/Avatar.test.tsx +80 -0
- package/src/Avatar/Avatar.tsx +64 -14
- package/src/Avatar/index.ts +2 -2
- package/src/AvatarGroup/AvatarGroup.doc.mjs +8 -2
- package/src/AvatarGroup/AvatarGroup.test.tsx +24 -0
- package/src/AvatarGroup/AvatarGroup.tsx +12 -4
- package/src/AvatarGroup/AvatarGroupContext.ts +5 -3
- package/src/AvatarGroup/AvatarGroupOverflow.tsx +12 -12
- package/src/Badge/Badge.doc.mjs +3 -2
- package/src/Badge/Badge.test.tsx +32 -3
- package/src/Badge/Badge.tsx +42 -1
- package/src/Banner/Banner.doc.mjs +9 -0
- package/src/Banner/Banner.test.tsx +76 -11
- package/src/Banner/Banner.tsx +21 -2
- package/src/Button/Button.doc.mjs +2 -1
- package/src/Button/Button.test.tsx +19 -4
- package/src/Button/Button.tsx +9 -29
- package/src/ButtonGroup/ButtonGroup.doc.mjs +2 -2
- package/src/ButtonGroup/ButtonGroup.test.tsx +13 -0
- package/src/Calendar/Calendar.doc.mjs +3 -3
- package/src/Calendar/Calendar.test.tsx +112 -0
- package/src/Calendar/Calendar.tsx +18 -16
- package/src/Calendar/hooks/useCalendarDays.ts +4 -4
- package/src/Calendar/hooks/useCalendarNavigation.ts +4 -4
- package/src/Calendar/styles.ts +48 -42
- package/src/Card/Card.doc.mjs +10 -7
- package/src/Card/Card.test.tsx +113 -19
- package/src/Card/Card.tsx +67 -89
- package/src/Card/index.ts +36 -1
- package/src/Carousel/Carousel.doc.mjs +3 -0
- package/src/Carousel/Carousel.test.tsx +360 -0
- package/src/Carousel/Carousel.tsx +116 -15
- package/src/CheckboxInput/CheckboxInput.doc.mjs +2 -0
- package/src/CheckboxInput/CheckboxInput.test.tsx +15 -0
- package/src/CheckboxInput/CheckboxInput.tsx +5 -0
- package/src/CodeBlock/CodeBlock.doc.mjs +10 -4
- package/src/CodeBlock/CodeBlock.test.tsx +37 -0
- package/src/CodeBlock/CodeBlock.tsx +20 -4
- package/src/CodeBlock/highlightRanges.ts +1 -1
- package/src/CodeBlock/highlightStyles.ts +13 -13
- package/src/CommandPalette/CommandPaletteItem.tsx +2 -12
- package/src/ComplexSelector/ComplexSelector.doc.mjs +7 -0
- package/src/ComplexSelector/ComplexSelector.test.tsx +183 -0
- package/src/ComplexSelector/ComplexSelector.tsx +22 -12
- package/src/DateInput/DateInput.doc.mjs +16 -0
- package/src/DateInput/DateInput.test.tsx +9 -4
- package/src/DateInput/DateInput.tsx +54 -3
- package/src/DateInput/DateInputTouch.test.tsx +146 -32
- package/src/DateInput/MonthScroller.tsx +5 -1
- package/src/DateInput/MonthYearWheels.tsx +7 -4
- package/src/DateInput/NativeDateField.test.tsx +635 -0
- package/src/DateInput/NativeDateField.tsx +641 -0
- package/src/DateInput/TouchDateField.tsx +83 -33
- package/src/DateInput/Wheel.tsx +1 -0
- package/src/DateInput/index.ts +1 -0
- package/src/DateInput/nativeDateSegments.ts +127 -0
- package/src/DateRangeInput/DateRangeInput.doc.mjs +2 -2
- package/src/DateRangeInput/DateRangeInput.test.tsx +46 -0
- package/src/DateRangeInput/DateRangeInput.tsx +8 -13
- package/src/DateTimeInput/DateTimeInput.doc.mjs +38 -21
- package/src/DateTimeInput/DateTimeInput.test.tsx +76 -0
- package/src/DateTimeInput/DateTimeInput.tsx +54 -20
- package/src/DateTimeInput/DateTimeInputTouch.test.tsx +980 -0
- package/src/DateTimeInput/TouchDateTimeField.tsx +1437 -0
- package/src/Dialog/Dialog.test.tsx +185 -18
- package/src/Dialog/Dialog.tsx +35 -11
- package/src/DropdownMenu/DropdownMenu.test.tsx +44 -10
- package/src/DropdownMenu/DropdownMenu.tsx +4 -13
- package/src/Field/FieldLabel.test.tsx +29 -0
- package/src/Field/FieldLabel.tsx +7 -0
- package/src/Field/InputClearButton.test.tsx +15 -1
- package/src/Field/InputClearButton.tsx +28 -4
- package/src/Heading/Heading.tsx +0 -1
- package/src/HoverCard/HoverCard.doc.mjs +8 -2
- package/src/HoverCard/HoverCard.test.tsx +154 -4
- package/src/HoverCard/HoverCard.tsx +137 -3
- package/src/HoverCard/useHoverCard.tsx +23 -3
- package/src/Icon/Icon.test.tsx +55 -1
- package/src/Icon/Icon.tsx +5 -3
- package/src/Icon/defaultIcons.tsx +11 -2
- package/src/Icon/globalIconRegistry.test.tsx +16 -3
- package/src/Icon/globalIconRegistry.tsx +37 -6
- package/src/Icon/index.ts +1 -0
- package/src/Icon/useIcon.ts +9 -2
- package/src/Indicator/CheckboxIndicator.tsx +14 -8
- package/src/Indicator/Indicator.doc.mjs +2 -0
- package/src/Item/Item.tsx +2 -7
- package/src/Kbd/Kbd.test.tsx +0 -17
- package/src/Kbd/Kbd.tsx +2 -26
- package/src/Layer/gestureCounter.ts +57 -0
- package/src/Layer/useLayer.test.tsx +368 -16
- package/src/Layer/useLayer.tsx +208 -35
- package/src/Layout/__tests__/edgeCompensation.test.tsx +1 -1
- package/src/List/List.test.tsx +38 -0
- package/src/List/List.tsx +8 -1
- package/src/Markdown/Markdown.test.tsx +37 -0
- package/src/Markdown/Markdown.tsx +16 -5
- package/src/Markdown/parser.test.ts +33 -0
- package/src/Markdown/parser.ts +9 -3
- package/src/MetadataList/MetadataList.test.tsx +75 -2
- package/src/MetadataList/MetadataListItem.tsx +5 -2
- package/src/MultiSelector/MultiSelector.doc.mjs +22 -1
- package/src/MultiSelector/MultiSelector.test.tsx +205 -0
- package/src/MultiSelector/MultiSelector.tsx +103 -16
- package/src/MultiSelector/hooks.ts +9 -2
- package/src/NavIcon/NavIcon.doc.mjs +8 -2
- package/src/NavIcon/NavIcon.test.tsx +9 -0
- package/src/NavIcon/NavIcon.tsx +5 -1
- package/src/NavItem/navItemStyles.stylex.ts +0 -8
- package/src/NavMenu/NavHeadingMenu.test.tsx +30 -0
- package/src/NavMenu/NavHeadingMenu.tsx +7 -4
- package/src/NumberInput/NumberInput.doc.mjs +26 -7
- package/src/NumberInput/NumberInput.test.tsx +563 -8
- package/src/NumberInput/NumberInput.tsx +77 -131
- package/src/NumberInput/numberInputCommit.test.ts +72 -0
- package/src/NumberInput/numberInputCommit.ts +103 -0
- package/src/NumberInput/numberParser.docblock.test.ts +234 -0
- package/src/NumberInput/numberParser.test.ts +222 -0
- package/src/NumberInput/numberParser.ts +403 -0
- package/src/Outline/Outline.tsx +2 -4
- package/src/OverflowList/OverflowList.doc.mjs +102 -21
- package/src/OverflowList/OverflowList.test.tsx +550 -4
- package/src/OverflowList/OverflowList.tsx +100 -2
- package/src/Pagination/Pagination.test.tsx +3 -2
- package/src/Popover/Popover.doc.mjs +2 -2
- package/src/Popover/Popover.test.tsx +38 -0
- package/src/Popover/Popover.tsx +28 -66
- package/src/Popover/usePopover.tsx +44 -5
- package/src/PowerSearch/PowerSearchEditPopover.test.tsx +87 -0
- package/src/PowerSearch/PowerSearchValueEditor.test.tsx +64 -0
- package/src/PowerSearch/PowerSearchValueEditor.tsx +109 -10
- package/src/PowerSearch/formatFilterValue.test.ts +16 -1
- package/src/PowerSearch/formatFilterValue.ts +2 -0
- package/src/ProgressBar/ProgressBar.doc.mjs +42 -6
- package/src/ProgressBar/ProgressBar.test.tsx +24 -0
- package/src/ProgressBar/ProgressBar.tsx +28 -8
- package/src/Resizable/Resizable.doc.mjs +2 -2
- package/src/Resizable/useResizable.doc.mjs +21 -2
- package/src/Resizable/useResizable.test.ts +421 -0
- package/src/Resizable/useResizable.ts +133 -48
- package/src/SelectableCard/SelectableCard.doc.mjs +3 -0
- package/src/SelectableCard/SelectableCard.tsx +16 -0
- package/src/Selector/Selector.doc.mjs +14 -0
- package/src/Selector/Selector.source-build.test.mjs +65 -0
- package/src/Selector/Selector.test.tsx +301 -0
- package/src/Selector/Selector.tsx +145 -32
- package/src/Selector/hooks.ts +17 -2
- package/src/SideNav/SideNav.doc.mjs +2 -2
- package/src/SideNav/SideNav.test.tsx +1069 -6
- package/src/SideNav/SideNav.tsx +109 -38
- package/src/SideNav/SideNavHeading.tsx +5 -2
- package/src/SideNav/SideNavItem.doc.mjs +24 -3
- package/src/SideNav/SideNavItem.tsx +134 -44
- package/src/Slider/Slider.test.tsx +106 -1
- package/src/Slider/Slider.tsx +52 -1
- package/src/Spinner/Spinner.doc.mjs +17 -5
- package/src/Spinner/Spinner.test.tsx +164 -0
- package/src/Spinner/Spinner.tsx +252 -22
- package/src/StatusDot/StatusDot.doc.mjs +8 -2
- package/src/StatusDot/StatusDot.test.tsx +9 -0
- package/src/StatusDot/StatusDot.tsx +7 -1
- package/src/Stepper/Step.doc.mjs +1 -1
- package/src/Stepper/Step.tsx +7 -14
- package/src/Switch/Switch.doc.mjs +2 -0
- package/src/Switch/Switch.test.tsx +10 -0
- package/src/Switch/Switch.tsx +3 -0
- package/src/Table/BaseTable.tsx +6 -1
- package/src/Table/Table.doc.mjs +5 -3
- package/src/Table/Table.tsx +3 -8
- package/src/Table/TableBody.doc.mjs +2 -2
- package/src/Table/TableFooter.doc.mjs +1 -1
- package/src/Table/TableHeader.doc.mjs +1 -1
- package/src/Table/plugins/filtering/useTableFiltering.test.tsx +44 -6
- package/src/Table/plugins/filtering/useTableFiltering.tsx +100 -4
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +50 -4
- package/src/Table/plugins/selection/useTableSelection.test.tsx +62 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +25 -2
- package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -2
- package/src/Table/useTableGroupedRows.doc.mjs +3 -3
- package/src/Table/useTablePagination.doc.mjs +1 -1
- package/src/Table/useTableSelection.doc.mjs +1 -1
- package/src/Text/Text.test.tsx +44 -0
- package/src/Text/Text.tsx +0 -1
- package/src/TextArea/TextArea.doc.mjs +12 -2
- package/src/TextArea/TextArea.test.tsx +11 -0
- package/src/TextArea/TextArea.tsx +34 -22
- package/src/Timestamp/Timestamp.test.tsx +89 -0
- package/src/Timestamp/Timestamp.tsx +8 -8
- package/src/Timestamp/formatInstant.ts +5 -0
- package/src/Toast/Toast.doc.mjs +213 -44
- package/src/Toast/Toast.tsx +118 -23
- package/src/Toast/ToastViewport.test.tsx +1434 -8
- package/src/Toast/ToastViewport.tsx +85 -14
- package/src/Toast/index.ts +2 -0
- package/src/Toast/types.ts +43 -5
- package/src/Toast/useToastGesture.ts +361 -0
- package/src/Token/Token.test.tsx +95 -0
- package/src/Token/Token.tsx +19 -17
- package/src/Token/TokenLink.tsx +12 -3
- package/src/Tokenizer/Tokenizer.doc.mjs +16 -3
- package/src/Tokenizer/Tokenizer.test.tsx +161 -0
- package/src/Tokenizer/Tokenizer.tsx +49 -24
- package/src/TopNav/TopNavHeading.tsx +2 -2
- package/src/TopNav/TopNavItem.tsx +3 -7
- package/src/TopNav/TopNavMegaMenu.test.tsx +104 -0
- package/src/TopNav/TopNavMegaMenu.tsx +47 -4
- package/src/TopNav/TopNavMegaMenuItem.tsx +10 -9
- package/src/TopNav/TopNavMenu.test.tsx +133 -1
- package/src/TopNav/TopNavMenu.tsx +38 -5
- package/src/TreeList/TreeList.test.tsx +49 -0
- package/src/TreeList/TreeList.tsx +7 -2
- package/src/TreeList/TreeListItem.tsx +2 -7
- package/src/Typeahead/BaseTypeahead.doc.mjs +13 -0
- package/src/Typeahead/BaseTypeahead.tsx +96 -6
- package/src/Typeahead/Typeahead.doc.mjs +6 -0
- package/src/Typeahead/Typeahead.test.tsx +154 -0
- package/src/Typeahead/Typeahead.tsx +9 -0
- package/src/Typeahead/TypeaheadItem.test.tsx +43 -0
- package/src/Typeahead/TypeaheadItem.tsx +8 -1
- package/src/hooks/useAnnounce.doc.mjs +96 -0
- package/src/hooks/useDevWarning.doc.mjs +96 -0
- package/src/hooks/useHotkeys.test.ts +0 -18
- package/src/hooks/useHotkeys.ts +3 -25
- package/src/hooks/useIndicatorFocusRing.doc.mjs +104 -0
- package/src/hooks/useInputStatusIcon.doc.mjs +142 -0
- package/src/hooks/useInteractiveRole.doc.mjs +119 -0
- package/src/hooks/useLongPress.doc.mjs +123 -0
- package/src/hooks/useOverflow.doc.mjs +58 -17
- package/src/hooks/useOverflow.ts +16 -4
- package/src/hooks/useTypeahead.doc.mjs +153 -0
- package/src/index.ts +2 -0
- package/src/raw-import.d.ts +14 -0
- package/src/theme/Theme.test.tsx +104 -2
- package/src/theme/Theme.tsx +49 -14
- package/src/theme/defineTheme.test.ts +23 -0
- package/src/theme/defineTheme.ts +12 -3
- package/src/theme/derivedVarRegistry.test.ts +87 -3
- package/src/theme/derivedVarRegistry.ts +23 -4
- package/src/theme/generateThemeRules.test.ts +99 -1
- package/src/theme/generateThemeRules.ts +28 -0
- package/src/theme/syntax/tokens.ts +5 -2
- package/src/theme/useTheme.test.tsx +10 -0
- package/src/theme/useTheme.ts +16 -10
- package/src/utils/dateParser.test.ts +34 -2
- package/src/utils/dateParser.ts +11 -14
- package/src/utils/focusOutline.stylex.ts +50 -0
- package/src/utils/interactionOverlay.stylex.ts +74 -0
- package/src/utils/isApplePlatform.test.ts +61 -0
- package/src/utils/isApplePlatform.ts +37 -0
- package/src/utils/plainDate.test.ts +46 -0
- package/src/utils/plainDate.ts +18 -3
|
@@ -97,6 +97,19 @@ export interface BaseTypeaheadProps<T extends SearchableItem> extends Omit<
|
|
|
97
97
|
/** Fixed dropdown width in pixels. Never shrinks below the anchor width. */
|
|
98
98
|
menuWidth?: number;
|
|
99
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Minimum query length before the search source is queried. Below it no
|
|
102
|
+
* search runs and the menu stays closed, so a remote source is not asked
|
|
103
|
+
* for a result set that cannot be meaningful yet — and the user does not
|
|
104
|
+
* see "no results" for a query that was never searched.
|
|
105
|
+
*
|
|
106
|
+
* Measured with `String.length` (UTF-16 code units), like every other
|
|
107
|
+
* length check in the library.
|
|
108
|
+
*
|
|
109
|
+
* @default 1 — every non-empty query is searched.
|
|
110
|
+
*/
|
|
111
|
+
minQueryLength?: number;
|
|
112
|
+
|
|
100
113
|
/**
|
|
101
114
|
* Text shown when no results found.
|
|
102
115
|
* @default 'No results found'
|
|
@@ -135,6 +148,28 @@ export interface BaseTypeaheadProps<T extends SearchableItem> extends Omit<
|
|
|
135
148
|
*/
|
|
136
149
|
onOpenChange?: (isOpen: boolean) => void;
|
|
137
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Entries derived from the query text rather than fetched for it — today,
|
|
153
|
+
* Tokenizer's "Create ...".
|
|
154
|
+
*
|
|
155
|
+
* They are appended to whatever the search returned, and they are offered
|
|
156
|
+
* whatever `minQueryLength` says: that threshold exists to avoid a fetch
|
|
157
|
+
* that is too broad to be worth making, and these cost no fetch. A field
|
|
158
|
+
* that can create `QA` should not stop being able to just because a search
|
|
159
|
+
* for `QA` would match too much.
|
|
160
|
+
*
|
|
161
|
+
* Receives the results they will be appended to, so a caller can decline to
|
|
162
|
+
* offer an entry that duplicates one.
|
|
163
|
+
*
|
|
164
|
+
* Underscored and `@internal`: `BaseTypeaheadProps` is re-exported from the
|
|
165
|
+
* package entry point, so anything named on it ships as public API at the
|
|
166
|
+
* next cut. This is a wiring detail between Tokenizer and the base — the
|
|
167
|
+
* same reason `DefinedTheme.__inputTokens` carries its prefix.
|
|
168
|
+
*
|
|
169
|
+
* @internal
|
|
170
|
+
*/
|
|
171
|
+
__queryEntries?: (query: string, results: T[]) => T[];
|
|
172
|
+
|
|
138
173
|
/**
|
|
139
174
|
* Debounce delay in ms before triggering search after typing.
|
|
140
175
|
* Set to 0 for synchronous/local search sources that don't need debouncing.
|
|
@@ -301,6 +336,19 @@ const itemSizeStyles = stylex.create({
|
|
|
301
336
|
},
|
|
302
337
|
});
|
|
303
338
|
|
|
339
|
+
// =============================================================================
|
|
340
|
+
// Helpers
|
|
341
|
+
// =============================================================================
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* A query that has been typed but is still shorter than the caller's
|
|
345
|
+
* threshold. An empty query is not "below the minimum" — it is the
|
|
346
|
+
* untouched state, and `hasEntriesOnFocus` owns what happens there.
|
|
347
|
+
*/
|
|
348
|
+
function isBelowMinQueryLength(query: string, minQueryLength: number): boolean {
|
|
349
|
+
return query.length > 0 && query.length < minQueryLength;
|
|
350
|
+
}
|
|
351
|
+
|
|
304
352
|
// =============================================================================
|
|
305
353
|
// Component
|
|
306
354
|
// =============================================================================
|
|
@@ -333,12 +381,14 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
333
381
|
hasEntriesOnFocus = false,
|
|
334
382
|
maxMenuItems = 10,
|
|
335
383
|
menuWidth,
|
|
384
|
+
minQueryLength = 1,
|
|
336
385
|
emptySearchResultsText: emptySearchResultsTextFromProps,
|
|
337
386
|
isDisabled = false,
|
|
338
387
|
isFocusableDisabled = false,
|
|
339
388
|
hasAutoFocus = false,
|
|
340
389
|
onChangeQuery,
|
|
341
390
|
onOpenChange,
|
|
391
|
+
__queryEntries,
|
|
342
392
|
inputId: externalInputId,
|
|
343
393
|
ariaDescribedBy,
|
|
344
394
|
ariaLabelledBy,
|
|
@@ -457,7 +507,11 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
457
507
|
return;
|
|
458
508
|
}
|
|
459
509
|
resultsGenRef.current = gen;
|
|
460
|
-
const
|
|
510
|
+
const fetched = searchResults.slice(0, maxMenuItems);
|
|
511
|
+
const shown = [
|
|
512
|
+
...fetched,
|
|
513
|
+
...(__queryEntries?.(searchQuery, fetched) ?? []),
|
|
514
|
+
];
|
|
461
515
|
setResults(shown);
|
|
462
516
|
setHighlightedIndex(shown.length > 0 ? 0 : -1);
|
|
463
517
|
if (searchResults.length > 0 || searchQuery.length > 0) {
|
|
@@ -490,6 +544,7 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
490
544
|
showLayer,
|
|
491
545
|
announce,
|
|
492
546
|
emptySearchResultsText,
|
|
547
|
+
__queryEntries,
|
|
493
548
|
t,
|
|
494
549
|
],
|
|
495
550
|
);
|
|
@@ -532,14 +587,35 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
532
587
|
clearTimeout(searchTimeoutRef.current);
|
|
533
588
|
}
|
|
534
589
|
|
|
535
|
-
|
|
590
|
+
// Nothing to search: either the field was emptied, or the query is
|
|
591
|
+
// still shorter than `minQueryLength`. Both drop stale results and
|
|
592
|
+
// close the menu — showing the empty state for a query that was never
|
|
593
|
+
// searched would report "no results" that nobody looked for.
|
|
594
|
+
if (
|
|
595
|
+
(newQuery.length === 0 && !hasEntriesOnFocus) ||
|
|
596
|
+
isBelowMinQueryLength(newQuery, minQueryLength)
|
|
597
|
+
) {
|
|
536
598
|
searchGenRef.current++;
|
|
537
599
|
searchSource.cancel?.();
|
|
538
|
-
|
|
600
|
+
// A query too short to search can still carry entries derived from
|
|
601
|
+
// the text itself. `hasSearched` stays false either way, so the menu
|
|
602
|
+
// never reports "no results" for a query nobody looked for.
|
|
603
|
+
const derived = __queryEntries?.(newQuery, []) ?? [];
|
|
604
|
+
setResults(derived);
|
|
605
|
+
setHighlightedIndex(derived.length > 0 ? 0 : -1);
|
|
539
606
|
setHasSearched(false);
|
|
607
|
+
// Bumping the generation abandons any in-flight search, which means
|
|
608
|
+
// its own `finally` will decline to clear this — so clear it here or
|
|
609
|
+
// the field spins forever. Backspacing below the threshold on a remote
|
|
610
|
+
// source is the everyday way to hit that.
|
|
611
|
+
setIsLoading(false);
|
|
540
612
|
// Clear any lingering result-count / no-results announcement.
|
|
541
613
|
announce('');
|
|
542
|
-
|
|
614
|
+
if (derived.length > 0) {
|
|
615
|
+
showLayer();
|
|
616
|
+
} else {
|
|
617
|
+
popover.hide();
|
|
618
|
+
}
|
|
543
619
|
return;
|
|
544
620
|
}
|
|
545
621
|
|
|
@@ -560,6 +636,9 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
560
636
|
[
|
|
561
637
|
onChangeQuery,
|
|
562
638
|
hasEntriesOnFocus,
|
|
639
|
+
minQueryLength,
|
|
640
|
+
__queryEntries,
|
|
641
|
+
showLayer,
|
|
563
642
|
performSearch,
|
|
564
643
|
performBootstrap,
|
|
565
644
|
popover,
|
|
@@ -591,6 +670,10 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
591
670
|
setQuery('');
|
|
592
671
|
setResults([]);
|
|
593
672
|
setHasSearched(false);
|
|
673
|
+
// Same reason as in handleQueryChange: the invalidated search will not
|
|
674
|
+
// clear this itself. Selecting a stale result while the next search is
|
|
675
|
+
// still in flight would otherwise leave the field spinning.
|
|
676
|
+
setIsLoading(false);
|
|
594
677
|
popover.hide();
|
|
595
678
|
inputRef.current?.focus();
|
|
596
679
|
},
|
|
@@ -674,7 +757,13 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
674
757
|
if (results.length > 0) {
|
|
675
758
|
popover.show();
|
|
676
759
|
setHighlightedIndex(0);
|
|
677
|
-
} else if (
|
|
760
|
+
} else if (
|
|
761
|
+
hasEntriesOnFocus &&
|
|
762
|
+
// A below-threshold query was never searched; falling back to the
|
|
763
|
+
// bootstrap entries here would open a menu of suggestions that
|
|
764
|
+
// ignore what the user has already typed.
|
|
765
|
+
!isBelowMinQueryLength(query, minQueryLength)
|
|
766
|
+
) {
|
|
678
767
|
void performBootstrap();
|
|
679
768
|
}
|
|
680
769
|
}
|
|
@@ -740,7 +829,8 @@ export const BaseTypeahead = function BaseTypeahead<T extends SearchableItem>({
|
|
|
740
829
|
highlightedIndex,
|
|
741
830
|
handleSelect,
|
|
742
831
|
hasEntriesOnFocus,
|
|
743
|
-
query
|
|
832
|
+
query,
|
|
833
|
+
minQueryLength,
|
|
744
834
|
performBootstrap,
|
|
745
835
|
externalOnKeyDown,
|
|
746
836
|
],
|
|
@@ -83,6 +83,12 @@ export const docs = {
|
|
|
83
83
|
description: 'Maximum number of dropdown items to display.',
|
|
84
84
|
default: '10',
|
|
85
85
|
},
|
|
86
|
+
{
|
|
87
|
+
name: 'minQueryLength',
|
|
88
|
+
type: 'number',
|
|
89
|
+
description: 'Minimum query length before the search source is queried. Below it no search runs and the menu stays closed.',
|
|
90
|
+
default: '1',
|
|
91
|
+
},
|
|
86
92
|
{
|
|
87
93
|
name: 'status',
|
|
88
94
|
type: "{type: 'warning' | 'error' | 'success', message?: string}",
|
|
@@ -778,6 +778,160 @@ describe('BaseTypeahead hasEntriesOnFocus', () => {
|
|
|
778
778
|
});
|
|
779
779
|
});
|
|
780
780
|
|
|
781
|
+
describe('BaseTypeahead minQueryLength', () => {
|
|
782
|
+
it('does not search or open the menu below the threshold', async () => {
|
|
783
|
+
const search = vi.fn((query: string) =>
|
|
784
|
+
fruits.filter(f => f.label.toLowerCase().includes(query.toLowerCase())),
|
|
785
|
+
);
|
|
786
|
+
render(
|
|
787
|
+
<BaseTypeahead
|
|
788
|
+
searchSource={{search, bootstrap: () => []}}
|
|
789
|
+
value={null}
|
|
790
|
+
onChange={() => {}}
|
|
791
|
+
minQueryLength={3}
|
|
792
|
+
debounceMs={0}
|
|
793
|
+
/>,
|
|
794
|
+
);
|
|
795
|
+
const input = screen.getByRole('combobox');
|
|
796
|
+
|
|
797
|
+
fireEvent.change(input, {target: {value: 'Ap'}});
|
|
798
|
+
await act(async () => {
|
|
799
|
+
await Promise.resolve();
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
expect(search).not.toHaveBeenCalled();
|
|
803
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
804
|
+
|
|
805
|
+
// Positive control: the third character crosses the threshold, so the
|
|
806
|
+
// same harness does see the search and the open menu.
|
|
807
|
+
fireEvent.change(input, {target: {value: 'App'}});
|
|
808
|
+
await waitFor(() => {
|
|
809
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
810
|
+
});
|
|
811
|
+
expect(search).toHaveBeenCalledExactlyOnceWith('App');
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
it('closes the menu again when the query falls back below the threshold', async () => {
|
|
815
|
+
render(
|
|
816
|
+
<BaseTypeahead
|
|
817
|
+
searchSource={fruitSource}
|
|
818
|
+
value={null}
|
|
819
|
+
onChange={() => {}}
|
|
820
|
+
minQueryLength={3}
|
|
821
|
+
debounceMs={0}
|
|
822
|
+
/>,
|
|
823
|
+
);
|
|
824
|
+
const input = screen.getByRole('combobox');
|
|
825
|
+
|
|
826
|
+
fireEvent.change(input, {target: {value: 'App'}});
|
|
827
|
+
await waitFor(() => {
|
|
828
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
fireEvent.change(input, {target: {value: 'Ap'}});
|
|
832
|
+
await waitFor(() => {
|
|
833
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
834
|
+
});
|
|
835
|
+
});
|
|
836
|
+
|
|
837
|
+
it('does not fall back to bootstrap entries on ArrowDown below the threshold', async () => {
|
|
838
|
+
const bootstrap = vi.fn(() => fruits.slice(0, 3));
|
|
839
|
+
render(
|
|
840
|
+
<BaseTypeahead
|
|
841
|
+
searchSource={{search: () => [], bootstrap}}
|
|
842
|
+
value={null}
|
|
843
|
+
onChange={() => {}}
|
|
844
|
+
hasEntriesOnFocus
|
|
845
|
+
minQueryLength={3}
|
|
846
|
+
debounceMs={0}
|
|
847
|
+
/>,
|
|
848
|
+
);
|
|
849
|
+
const input = screen.getByRole('combobox');
|
|
850
|
+
|
|
851
|
+
fireEvent.focus(input);
|
|
852
|
+
await waitFor(() => {
|
|
853
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
854
|
+
});
|
|
855
|
+
bootstrap.mockClear();
|
|
856
|
+
|
|
857
|
+
// Typing below the threshold closes the bootstrap menu...
|
|
858
|
+
fireEvent.change(input, {target: {value: 'Ap'}});
|
|
859
|
+
await waitFor(() => {
|
|
860
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
// ...and ArrowDown must not re-open it with entries that ignore the
|
|
864
|
+
// two characters already typed.
|
|
865
|
+
fireEvent.keyDown(input, {key: 'ArrowDown'});
|
|
866
|
+
await act(async () => {
|
|
867
|
+
await Promise.resolve();
|
|
868
|
+
});
|
|
869
|
+
expect(bootstrap).not.toHaveBeenCalled();
|
|
870
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
it('searches on the first character when minQueryLength is not set', async () => {
|
|
874
|
+
const search = vi.fn(() => fruits.slice(0, 1));
|
|
875
|
+
render(
|
|
876
|
+
<BaseTypeahead
|
|
877
|
+
searchSource={{search, bootstrap: () => []}}
|
|
878
|
+
value={null}
|
|
879
|
+
onChange={() => {}}
|
|
880
|
+
debounceMs={0}
|
|
881
|
+
/>,
|
|
882
|
+
);
|
|
883
|
+
const input = screen.getByRole('combobox');
|
|
884
|
+
|
|
885
|
+
fireEvent.change(input, {target: {value: 'A'}});
|
|
886
|
+
await waitFor(() => {
|
|
887
|
+
expect(input).toHaveAttribute('aria-expanded', 'true');
|
|
888
|
+
});
|
|
889
|
+
expect(search).toHaveBeenCalledExactlyOnceWith('A');
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
it('stops reporting "Loading" when the query falls below the threshold mid-search', async () => {
|
|
893
|
+
// Falling below the threshold abandons the in-flight search by bumping the
|
|
894
|
+
// search generation, which also makes that search decline to clear the
|
|
895
|
+
// loading flag on its way out. Backspacing from three characters to two on
|
|
896
|
+
// a remote source is the everyday way to hit it, and the field would
|
|
897
|
+
// otherwise report "Loading" to a screen reader until the third character
|
|
898
|
+
// went back in.
|
|
899
|
+
let settle: (items: SearchableItem[]) => void = () => {};
|
|
900
|
+
const search = vi.fn(
|
|
901
|
+
async () =>
|
|
902
|
+
new Promise<SearchableItem[]>(resolve => {
|
|
903
|
+
settle = resolve;
|
|
904
|
+
}),
|
|
905
|
+
);
|
|
906
|
+
render(
|
|
907
|
+
<BaseTypeahead
|
|
908
|
+
searchSource={{search, bootstrap: () => []}}
|
|
909
|
+
value={null}
|
|
910
|
+
onChange={() => {}}
|
|
911
|
+
minQueryLength={3}
|
|
912
|
+
debounceMs={0}
|
|
913
|
+
/>,
|
|
914
|
+
);
|
|
915
|
+
const input = screen.getByRole('combobox');
|
|
916
|
+
|
|
917
|
+
fireEvent.change(input, {target: {value: 'App'}});
|
|
918
|
+
await waitFor(() => {
|
|
919
|
+
expect(screen.getByRole('status', {name: 'Loading'})).toBeInTheDocument();
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
fireEvent.change(input, {target: {value: 'Ap'}});
|
|
923
|
+
await act(async () => {
|
|
924
|
+
settle(fruits.slice(0, 1));
|
|
925
|
+
await Promise.resolve();
|
|
926
|
+
});
|
|
927
|
+
|
|
928
|
+
expect(
|
|
929
|
+
screen.queryByRole('status', {name: 'Loading'}),
|
|
930
|
+
).not.toBeInTheDocument();
|
|
931
|
+
expect(input).toHaveAttribute('aria-expanded', 'false');
|
|
932
|
+
});
|
|
933
|
+
});
|
|
934
|
+
|
|
781
935
|
describe('BaseTypeahead hasSearched reset', () => {
|
|
782
936
|
it('does not show "No results found" after selecting an item and re-entering', async () => {
|
|
783
937
|
const onChange = vi.fn();
|
|
@@ -111,6 +111,13 @@ export interface TypeaheadProps<T extends SearchableItem> extends Omit<
|
|
|
111
111
|
hasEntriesOnFocus?: boolean;
|
|
112
112
|
/** Max dropdown items. @default 10 */
|
|
113
113
|
maxMenuItems?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Minimum query length before the search source is queried. Below it no
|
|
116
|
+
* search runs and the menu stays closed — useful for remote sources where
|
|
117
|
+
* one or two characters match too much to be worth fetching.
|
|
118
|
+
* @default 1
|
|
119
|
+
*/
|
|
120
|
+
minQueryLength?: number;
|
|
114
121
|
/** Text shown when no results found. @default 'No results found' */
|
|
115
122
|
emptySearchResultsText?: string;
|
|
116
123
|
/** Whether the input is disabled. @default false */
|
|
@@ -248,6 +255,7 @@ export function Typeahead<T extends SearchableItem>({
|
|
|
248
255
|
placeholder,
|
|
249
256
|
hasEntriesOnFocus,
|
|
250
257
|
maxMenuItems,
|
|
258
|
+
minQueryLength,
|
|
251
259
|
emptySearchResultsText,
|
|
252
260
|
isDisabled = false,
|
|
253
261
|
disabledMessage,
|
|
@@ -467,6 +475,7 @@ export function Typeahead<T extends SearchableItem>({
|
|
|
467
475
|
placeholder={showToken ? undefined : placeholder}
|
|
468
476
|
hasEntriesOnFocus={hasEntriesOnFocus}
|
|
469
477
|
maxMenuItems={maxMenuItems}
|
|
478
|
+
minQueryLength={minQueryLength}
|
|
470
479
|
emptySearchResultsText={emptySearchResultsText}
|
|
471
480
|
isDisabled={isDisabled}
|
|
472
481
|
hasAutoFocus={hasAutoFocus}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file TypeaheadItem.test.tsx
|
|
5
|
+
* @input Uses vitest, @testing-library/react, TypeaheadItem
|
|
6
|
+
* @output Unit tests for TypeaheadItem
|
|
7
|
+
* @position Testing; validates TypeaheadItem.tsx implementation
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {describe, it, expect} from 'vitest';
|
|
11
|
+
import {render, screen} from '@testing-library/react';
|
|
12
|
+
import {TypeaheadItem} from './TypeaheadItem';
|
|
13
|
+
|
|
14
|
+
describe('TypeaheadItem', () => {
|
|
15
|
+
it('forwards pass-through props to the item element', () => {
|
|
16
|
+
render(
|
|
17
|
+
<TypeaheadItem
|
|
18
|
+
item={{id: '1', label: 'Alice'}}
|
|
19
|
+
aria-label="Alice, engineer"
|
|
20
|
+
id="result-1"
|
|
21
|
+
data-source="directory"
|
|
22
|
+
data-testid="item"
|
|
23
|
+
/>,
|
|
24
|
+
);
|
|
25
|
+
const item = screen.getByTestId('item');
|
|
26
|
+
expect(item).toHaveAttribute('aria-label', 'Alice, engineer');
|
|
27
|
+
expect(item).toHaveAttribute('id', 'result-1');
|
|
28
|
+
expect(item).toHaveAttribute('data-source', 'directory');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('merges a caller className with its own classes', () => {
|
|
32
|
+
render(
|
|
33
|
+
<TypeaheadItem
|
|
34
|
+
item={{id: '1', label: 'Alice'}}
|
|
35
|
+
className="caller-class"
|
|
36
|
+
data-testid="item"
|
|
37
|
+
/>,
|
|
38
|
+
);
|
|
39
|
+
const item = screen.getByTestId('item');
|
|
40
|
+
expect(item.className).toContain('caller-class');
|
|
41
|
+
expect(item.className).toContain('astryx-typeahead-item');
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -132,7 +132,11 @@ export function TypeaheadItem<T extends SearchableItem>({
|
|
|
132
132
|
icon,
|
|
133
133
|
description,
|
|
134
134
|
isDisabled = false,
|
|
135
|
+
group: _group,
|
|
135
136
|
xstyle,
|
|
137
|
+
className,
|
|
138
|
+
style,
|
|
139
|
+
...rest
|
|
136
140
|
}: TypeaheadItemProps<T>) {
|
|
137
141
|
// If item has a pre-rendered element, use it
|
|
138
142
|
if (item.element) {
|
|
@@ -145,7 +149,10 @@ export function TypeaheadItem<T extends SearchableItem>({
|
|
|
145
149
|
{...mergeProps(
|
|
146
150
|
themeProps('typeahead-item'),
|
|
147
151
|
stylex.props(styles.container, isDisabled && styles.disabled, xstyle),
|
|
148
|
-
|
|
152
|
+
className,
|
|
153
|
+
style,
|
|
154
|
+
)}
|
|
155
|
+
{...rest}>
|
|
149
156
|
{icon}
|
|
150
157
|
<div {...stylex.props(styles.content)}>
|
|
151
158
|
<span {...stylex.props(styles.label)}>{item.label}</span>
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').HookDoc} */
|
|
4
|
+
export const docs = {
|
|
5
|
+
name: 'useAnnounce',
|
|
6
|
+
displayName: 'useAnnounce',
|
|
7
|
+
keywords: [
|
|
8
|
+
'announce',
|
|
9
|
+
'live region',
|
|
10
|
+
'aria-live',
|
|
11
|
+
'screen reader',
|
|
12
|
+
'accessibility',
|
|
13
|
+
'a11y',
|
|
14
|
+
'status',
|
|
15
|
+
'alert',
|
|
16
|
+
'polite',
|
|
17
|
+
'assertive',
|
|
18
|
+
'visually hidden',
|
|
19
|
+
'wcag',
|
|
20
|
+
],
|
|
21
|
+
params: [],
|
|
22
|
+
returns: [
|
|
23
|
+
{
|
|
24
|
+
name: 'announce',
|
|
25
|
+
type: '(message: string, politeness?: "polite" | "assertive") => void',
|
|
26
|
+
description:
|
|
27
|
+
'Speaks a message through the shared live region. Politeness defaults to "polite"; an empty message clears any lingering status instead of announcing.',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
usage: {
|
|
31
|
+
description:
|
|
32
|
+
'Imperatively announces a message to screen readers through a visually-hidden live region. Use it for state that is only conveyed visually; search result counts, "no results", loading and saved confirmations, validation errors (WCAG 4.1.3 Status Messages). The polite and assertive regions are created empty on first use and stay mounted, which is what makes announcements reliable: most screen readers ignore a live region that is inserted together with its content. Each message is cleared a couple of seconds after it is announced so stale status does not linger in the accessibility tree.',
|
|
33
|
+
bestPractices: [
|
|
34
|
+
{
|
|
35
|
+
guidance: true,
|
|
36
|
+
description:
|
|
37
|
+
'Reach for this instead of hand-rolling an aria-live div; a region rendered with its content usually does not announce at all.',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
guidance: true,
|
|
41
|
+
description:
|
|
42
|
+
'Keep "polite" for status and result counts; reserve "assertive" for errors and time-sensitive alerts, since it interrupts whatever the screen reader is saying.',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
guidance: true,
|
|
46
|
+
description:
|
|
47
|
+
'Announce the outcome, not the interaction; "12 results" rather than "search ran".',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
guidance: false,
|
|
51
|
+
description:
|
|
52
|
+
'Announce content that is already visible and correctly labeled in the DOM; that doubles up for screen reader users.',
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
relatedComponents: ['VisuallyHidden', 'Toast'],
|
|
57
|
+
relatedHooks: ['useClipboard'],
|
|
58
|
+
importPath: '@astryxdesign/core/hooks',
|
|
59
|
+
category: 'accessibility',
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/** @type {import('@astryxdesign/cli/authoring').HookTranslationDoc} */
|
|
63
|
+
export const docsDense = {
|
|
64
|
+
description:
|
|
65
|
+
'Imperative screen-reader announcements via a visually-hidden live region. Polite + assertive regions created empty on first use + kept mounted, so announcements are reliable (most AT ignore a live region inserted together w/ its content). Messages auto-clear after ~2s.',
|
|
66
|
+
returnDescriptions: {
|
|
67
|
+
announce:
|
|
68
|
+
'speaks message through shared live region. politeness defaults "polite"; empty message clears lingering status.',
|
|
69
|
+
},
|
|
70
|
+
usage: {
|
|
71
|
+
description:
|
|
72
|
+
'Announces visual-only state to screen readers: result counts, "no results", loading / saved confirmations, validation errors (WCAG 4.1.3). Regions mounted empty up front, so updates announce; text auto-clears so stale status does not linger in a11y tree.',
|
|
73
|
+
bestPractices: [
|
|
74
|
+
{
|
|
75
|
+
guidance: true,
|
|
76
|
+
description:
|
|
77
|
+
'Use instead of hand-rolled aria-live div; region rendered w/ its content usually does not announce.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
guidance: true,
|
|
81
|
+
description:
|
|
82
|
+
'"polite" for status / counts; "assertive" only for errors + time-sensitive alerts (it interrupts).',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
guidance: true,
|
|
86
|
+
description:
|
|
87
|
+
'Announce outcome, not interaction; "12 results", not "search ran".',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
guidance: false,
|
|
91
|
+
description:
|
|
92
|
+
'Announce content already visible + labeled in DOM; doubles up for AT users.',
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').HookDoc} */
|
|
4
|
+
export const docs = {
|
|
5
|
+
name: 'useDevWarning',
|
|
6
|
+
displayName: 'useDevWarning',
|
|
7
|
+
keywords: [
|
|
8
|
+
'warning',
|
|
9
|
+
'dev',
|
|
10
|
+
'development',
|
|
11
|
+
'console',
|
|
12
|
+
'guardrail',
|
|
13
|
+
'misuse',
|
|
14
|
+
'invariant',
|
|
15
|
+
'debug',
|
|
16
|
+
'devWarn',
|
|
17
|
+
],
|
|
18
|
+
params: [
|
|
19
|
+
{
|
|
20
|
+
name: 'component',
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'Component or hook name, used as the message prefix.',
|
|
23
|
+
required: true,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'message',
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'What went wrong and how to fix it.',
|
|
29
|
+
required: true,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'condition',
|
|
33
|
+
type: 'boolean',
|
|
34
|
+
description: 'Whether to warn.',
|
|
35
|
+
default: 'true',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
returns: [],
|
|
39
|
+
usage: {
|
|
40
|
+
description:
|
|
41
|
+
'Fires a dev-only "Component: message" console warning once per mount while the condition holds. It is the render-safe way for a component to flag misuse: warning straight from the render body repeats on every render, and gating it with state adds a re-render, so this uses a ref and an effect instead. For a warning outside a component, use the imperative devWarn utility.',
|
|
42
|
+
bestPractices: [
|
|
43
|
+
{
|
|
44
|
+
guidance: true,
|
|
45
|
+
description:
|
|
46
|
+
'Say what is wrong and what the builder should do instead; the message is the whole value of the warning.',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
guidance: true,
|
|
50
|
+
description:
|
|
51
|
+
'Warn about combinations the types cannot express, such as two mutually exclusive props being set together.',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
guidance: false,
|
|
55
|
+
description:
|
|
56
|
+
'Use it for anything a user could see or for runtime error handling; it is stripped from production builds.',
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
relatedComponents: [],
|
|
61
|
+
relatedHooks: [],
|
|
62
|
+
importPath: '@astryxdesign/core/hooks',
|
|
63
|
+
category: 'utility',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/** @type {import('@astryxdesign/cli/authoring').HookTranslationDoc} */
|
|
67
|
+
export const docsDense = {
|
|
68
|
+
description:
|
|
69
|
+
'Dev-only "Component: message" console warning, once per mount while condition holds. Ref + effect, so it never repeats per render nor causes a re-render. Outside a component, use the imperative devWarn utility.',
|
|
70
|
+
paramDescriptions: {
|
|
71
|
+
component: 'component / hook name, used as message prefix.',
|
|
72
|
+
message: 'what went wrong + how to fix it.',
|
|
73
|
+
condition: 'whether to warn.',
|
|
74
|
+
},
|
|
75
|
+
usage: {
|
|
76
|
+
description:
|
|
77
|
+
'Render-safe guardrail warning from inside a component. Stripped from production builds.',
|
|
78
|
+
bestPractices: [
|
|
79
|
+
{
|
|
80
|
+
guidance: true,
|
|
81
|
+
description:
|
|
82
|
+
'Say what is wrong + what to do instead; the message is the value.',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
guidance: true,
|
|
86
|
+
description:
|
|
87
|
+
'Warn about combinations types cannot express (mutually exclusive props set together).',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
guidance: false,
|
|
91
|
+
description:
|
|
92
|
+
'Use for user-visible problems / runtime error handling; it is dev-only.',
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
};
|
|
@@ -67,24 +67,6 @@ describe('useHotkeys', () => {
|
|
|
67
67
|
expect(onPress).toHaveBeenCalledTimes(1);
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
-
it('reads a blank userAgentData.platform as unknown, not as non-Apple', () => {
|
|
71
|
-
// Builds that rewrite their client-hints identity expose the key with an
|
|
72
|
-
// empty value; navigator.platform is the only surface left that answers.
|
|
73
|
-
vi.stubGlobal('navigator', {
|
|
74
|
-
userAgentData: {platform: ''},
|
|
75
|
-
platform: 'MacIntel',
|
|
76
|
-
});
|
|
77
|
-
const onPress = vi.fn();
|
|
78
|
-
renderHook(() => useHotkeys([{keys: 'mod+k', onPress}]));
|
|
79
|
-
|
|
80
|
-
press('k', {ctrlKey: true});
|
|
81
|
-
expect(onPress).not.toHaveBeenCalled();
|
|
82
|
-
|
|
83
|
-
const event = press('k', {metaKey: true});
|
|
84
|
-
expect(onPress).toHaveBeenCalledTimes(1);
|
|
85
|
-
expect(onPress).toHaveBeenCalledWith(event);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
70
|
it('does not fire a bare key when modifiers are held', () => {
|
|
89
71
|
stubApplePlatform();
|
|
90
72
|
const onPress = vi.fn();
|