@astryxdesign/core 0.7.5 → 0.7.6-canary.5cd7a15
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/AlertDialog/AlertDialog.d.ts +1 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +5 -5
- package/dist/Avatar/Avatar.d.ts.map +1 -1
- package/dist/Avatar/Avatar.js +12 -3
- package/dist/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +7 -1
- package/dist/BottomSheet/BottomSheet.js +1 -1
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +2 -1
- package/dist/BottomSheet/useSheetGestures.d.ts +12 -0
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +30 -3
- package/dist/Button/Button.js +4 -4
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +6 -5
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +12 -4
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +101 -15
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +8 -3
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +1 -1
- package/dist/DateTimeInput/DateTimeInput.d.ts +5 -2
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +23 -12
- package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -1
- package/dist/DateTimeInput/NativeTimeSegment.js +5 -4
- package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
- package/dist/DateTimeInput/TouchDateTimeField.js +4 -3
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +34 -9
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +5 -4
- package/dist/Divider/Divider.d.ts.map +1 -1
- package/dist/Divider/Divider.js +2 -1
- package/dist/Drawer/Drawer.d.ts +1 -0
- package/dist/Drawer/Drawer.d.ts.map +1 -1
- package/dist/Drawer/Drawer.js +7 -2
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +4 -1
- package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -1
- package/dist/DropdownMenu/MenuBottomSheetActionList.js +6 -5
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +10 -1
- package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -1
- package/dist/DropdownMenu/lazyMenuBottomSheet.js +16 -2
- package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
- package/dist/DropdownMenu/renderDropdownItems.js +21 -16
- package/dist/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/EmptyState/EmptyState.js +2 -1
- package/dist/Field/FieldLabel.d.ts +1 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +4 -4
- package/dist/Field/InputClearButton.js +3 -3
- package/dist/Field/PanelSearchInput.js +2 -2
- package/dist/FieldStatus/FieldStatus.js +2 -2
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +7 -1
- package/dist/Heading/Heading.js +1 -1
- package/dist/Icon/Icon.js +1 -1
- package/dist/Indicator/CheckIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckIndicator.js +2 -1
- package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
- package/dist/Indicator/CheckboxIndicator.js +3 -1
- package/dist/Indicator/RadioIndicator.d.ts.map +1 -1
- package/dist/Indicator/RadioIndicator.js +3 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +2 -1
- package/dist/Item/ItemSwipeLayer.js +1 -1
- package/dist/Layout/Layout.js +1 -1
- package/dist/Layout/LayoutContent.js +1 -1
- package/dist/Layout/LayoutFooter.js +1 -1
- package/dist/Layout/LayoutHeader.js +1 -1
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +5 -0
- package/dist/Lightbox/LightboxViewport.a11y.browser.spec.js +5 -4
- package/dist/List/List.js +1 -1
- package/dist/List/ListItem.js +3 -3
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +7 -2
- package/dist/MultiSelector/MultiSelector.d.ts +1 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +5 -2
- package/dist/NumberInput/NumberInput.d.ts +3 -1
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +3 -3
- package/dist/NumberInput/numberParser.d.ts +3 -0
- package/dist/NumberInput/numberParser.d.ts.map +1 -1
- package/dist/NumberInput/numberParser.js +7 -44
- package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar/ProgressBar.js +16 -12
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +28 -2
- package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
- package/dist/SegmentedControl/SegmentedControlItem.js +4 -1
- package/dist/Selector/useSelectorPresentation.d.ts +8 -1
- package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
- package/dist/Selector/useSelectorPresentation.js +20 -4
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +7 -1
- package/dist/Spinner/Spinner.js +2 -2
- package/dist/Stack/Stack.js +1 -1
- package/dist/Stack/StackItem.js +1 -1
- package/dist/TabList/TabList.d.ts.map +1 -1
- package/dist/TabList/TabList.js +16 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
- package/dist/Table/plugins/columnResize/useTableColumnResize.js +9 -1
- package/dist/Text/Text.js +1 -1
- package/dist/Text/useTruncation.d.ts.map +1 -1
- package/dist/Text/useTruncation.js +23 -5
- package/dist/TextArea/TextArea.d.ts +1 -1
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +13 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +3 -3
- package/dist/TimeInput/TimeInput.d.ts +6 -2
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +21 -14
- package/dist/TimeInput/TouchTimeField.d.ts.map +1 -1
- package/dist/TimeInput/TouchTimeField.js +5 -4
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +2 -2
- package/dist/Timestamp/TimestampHoverCard.js +4 -4
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +60 -20
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +82 -51
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +13 -2
- package/dist/Tokenizer/TokenizerBottomSheet.js +3 -3
- package/dist/Toolbar/Toolbar.d.ts.map +1 -1
- package/dist/Toolbar/Toolbar.js +2 -1
- package/dist/Typeahead/Typeahead.d.ts +1 -1
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +9 -1
- package/dist/astryx.css +15 -1
- package/dist/gestures/GestureArena.d.ts +6 -0
- package/dist/gestures/GestureArena.d.ts.map +1 -1
- package/dist/gestures/GestureArena.js +39 -0
- package/dist/gestures/GestureHost.d.ts +352 -0
- package/dist/gestures/GestureHost.d.ts.map +1 -0
- package/dist/gestures/GestureHost.js +1773 -0
- package/dist/gestures/GestureRecognizer.d.ts +10 -0
- package/dist/gestures/GestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/GestureRecognizer.js +16 -0
- package/dist/gestures/LongPressGestureRecognizer.d.ts +1 -0
- package/dist/gestures/LongPressGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/LongPressGestureRecognizer.js +3 -0
- package/dist/gestures/PanGestureRecognizer.d.ts +1 -0
- package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/PanGestureRecognizer.js +3 -0
- package/dist/gestures/PinchGestureRecognizer.d.ts +31 -0
- package/dist/gestures/PinchGestureRecognizer.d.ts.map +1 -0
- package/dist/gestures/PinchGestureRecognizer.js +128 -0
- package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +71 -0
- package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -0
- package/dist/gestures/ScreenEdgePanGestureRecognizer.js +223 -0
- package/dist/gestures/SwipeGestureRecognizer.d.ts +37 -0
- package/dist/gestures/SwipeGestureRecognizer.d.ts.map +1 -0
- package/dist/gestures/SwipeGestureRecognizer.js +148 -0
- package/dist/gestures/TapGestureRecognizer.d.ts +1 -0
- package/dist/gestures/TapGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/TapGestureRecognizer.js +3 -0
- package/dist/gestures/VelocityTracker.d.ts +6 -2
- package/dist/gestures/VelocityTracker.d.ts.map +1 -1
- package/dist/gestures/VelocityTracker.js +7 -3
- package/dist/gestures/haptics.d.ts +65 -0
- package/dist/gestures/haptics.d.ts.map +1 -0
- package/dist/gestures/haptics.js +182 -0
- package/dist/gestures/nativeScroll.d.ts +42 -0
- package/dist/gestures/nativeScroll.d.ts.map +1 -0
- package/dist/gestures/nativeScroll.js +228 -0
- package/dist/gestures/touchAction.d.ts +60 -0
- package/dist/gestures/touchAction.d.ts.map +1 -0
- package/dist/gestures/touchAction.js +157 -0
- package/dist/gestures/touchActionRule.d.ts +34 -0
- package/dist/gestures/touchActionRule.d.ts.map +1 -0
- package/dist/gestures/touchActionRule.js +140 -0
- package/dist/gestures/types.d.ts +18 -7
- package/dist/gestures/types.d.ts.map +1 -1
- package/dist/gestures/types.js +22 -2
- package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -1
- package/dist/hooks/useAdaptivePresentation.js +4 -1
- package/dist/hooks/useMenuHover.d.ts.map +1 -1
- package/dist/hooks/useMenuHover.js +12 -1
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +3 -0
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +3 -0
- package/dist/motion/animator.d.ts +7 -1
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +119 -27
- package/dist/theme/defineTheme.js +1 -1
- package/dist/theme/domainTokens/domainTokenDefaults.d.ts +3 -0
- package/dist/theme/domainTokens/domainTokenDefaults.d.ts.map +1 -0
- package/dist/theme/domainTokens/domainTokenDefaults.js +19 -0
- package/dist/theme/domainTokens/index.d.ts +5 -4
- package/dist/theme/domainTokens/index.d.ts.map +1 -1
- package/dist/theme/domainTokens/index.js +5 -9
- package/dist/utils/focusReturn.d.ts +17 -1
- package/dist/utils/focusReturn.d.ts.map +1 -1
- package/dist/utils/focusReturn.js +11 -4
- package/dist/utils/getNodeText.d.ts +8 -0
- package/dist/utils/getNodeText.d.ts.map +1 -0
- package/dist/utils/getNodeText.js +37 -0
- package/dist/utils/interactionModality.d.ts +11 -2
- package/dist/utils/interactionModality.d.ts.map +1 -1
- package/dist/utils/interactionModality.js +58 -5
- package/dist/utils/plainDate.d.ts +2 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +46 -3
- package/dist/utils/presentation.d.ts +50 -0
- package/dist/utils/presentation.d.ts.map +1 -0
- package/dist/utils/presentation.js +125 -0
- package/dist/utils/primaryClick.d.ts +11 -0
- package/dist/utils/primaryClick.d.ts.map +1 -0
- package/dist/utils/primaryClick.js +25 -0
- package/dist/utils/timeFormat.d.ts +47 -0
- package/dist/utils/timeFormat.d.ts.map +1 -0
- package/dist/utils/timeFormat.js +240 -0
- package/dist/utils/touchPresentation.d.ts.map +1 -1
- package/dist/utils/touchPresentation.js +5 -3
- package/dist/utils/touchPresentation.stylex.d.ts +15 -0
- package/dist/utils/touchPresentation.stylex.d.ts.map +1 -0
- package/dist/utils/touchPresentation.stylex.js +33 -0
- package/dist/utils/unicodeDigits.d.ts +20 -0
- package/dist/utils/unicodeDigits.d.ts.map +1 -0
- package/dist/utils/unicodeDigits.js +70 -0
- package/locales/en.json +15 -3
- package/locales/pseudo.json +9 -0
- package/package.json +5 -4
- package/src/AlertDialog/AlertDialog.tsx +6 -5
- package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +18 -6
- package/src/Avatar/Avatar.spec.md +22 -22
- package/src/Avatar/Avatar.tsx +18 -1
- package/src/Avatar/__tests__/AvatarForcedColors.a11y.chromium.spec.ts +126 -0
- package/src/Badge/Badge.doc.mjs +1 -1
- package/src/Badge/Badge.tsx +19 -2
- package/src/Badge/__tests__/BadgeLargerText.a11y.chromium.spec.ts +260 -0
- package/src/BottomSheet/BottomSheet.test.tsx +46 -0
- package/src/BottomSheet/BottomSheet.tsx +1 -1
- package/src/BottomSheet/BottomSheetPanel.tsx +2 -1
- package/src/BottomSheet/useSheetGestures.test.ts +52 -0
- package/src/BottomSheet/useSheetGestures.ts +37 -6
- package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.chromium.spec.ts +18 -6
- package/src/Button/Button.tsx +4 -4
- package/src/Calendar/Calendar.spec.md +87 -48
- package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +21 -7
- package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +21 -7
- package/src/CheckboxInput/CheckboxInput.tsx +6 -5
- package/src/Collapsible/Collapsible.spec.md +2 -0
- package/src/Collapsible/CollapsibleGroup.spec.md +57 -29
- package/src/Collapsible/__tests__/Collapsible.a11y.chromium.spec.ts +18 -7
- package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +18 -6
- package/src/ComplexSelector/ComplexSelector.test.tsx +37 -0
- package/src/ContextMenu/ContextMenu.test.tsx +35 -0
- package/src/DateInput/DateInput.test.tsx +115 -3
- package/src/DateInput/DateInput.tsx +29 -14
- package/src/DateInput/DateInputTouch.test.tsx +76 -0
- package/src/DateInput/MonthScroller.tsx +106 -20
- package/src/DateInput/MonthScrollerSettle.test.tsx +165 -0
- package/src/DateInput/TouchDateField.tsx +14 -3
- package/src/DateInput/__tests__/MonthScrollerSteps.interaction.browser.spec.ts +312 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +46 -3
- package/src/DateRangeInput/DateRangeInput.tsx +16 -12
- package/src/DateTimeInput/DateTimeInput.doc.mjs +10 -8
- package/src/DateTimeInput/DateTimeInput.spec.md +75 -51
- package/src/DateTimeInput/DateTimeInput.test.tsx +81 -0
- package/src/DateTimeInput/DateTimeInput.tsx +46 -24
- package/src/DateTimeInput/NativeTimeSegment.tsx +4 -6
- package/src/DateTimeInput/TouchDateTimeField.tsx +3 -7
- package/src/Dialog/Dialog.test.tsx +216 -2
- package/src/Dialog/Dialog.tsx +42 -9
- package/src/Dialog/DialogHeader.tsx +5 -4
- package/src/Dialog/__tests__/DialogSecondDocument.a11y.browser.spec.ts +202 -0
- package/src/Divider/Divider.tsx +2 -1
- package/src/Drawer/Drawer.spec.md +111 -80
- package/src/Drawer/Drawer.test.tsx +35 -0
- package/src/Drawer/Drawer.tsx +13 -2
- package/src/Drawer/DrawerHeader.spec.md +181 -0
- package/src/Drawer/__tests__/DrawerNonModalPageScroll.a11y.chromium.spec.ts +267 -0
- package/src/DropdownMenu/DropdownMenu.test.tsx +41 -0
- package/src/DropdownMenu/DropdownMenu.tsx +7 -1
- package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +34 -0
- package/src/DropdownMenu/MenuBottomSheetActionList.tsx +6 -5
- package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +19 -7
- package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +21 -9
- package/src/DropdownMenu/lazyMenuBottomSheet.test.ts +53 -0
- package/src/DropdownMenu/lazyMenuBottomSheet.ts +23 -6
- package/src/DropdownMenu/renderDropdownItems.tsx +24 -19
- package/src/EmptyState/EmptyState.tsx +2 -1
- package/src/Field/FieldLabel.tsx +5 -4
- package/src/Field/InputClearButton.tsx +3 -3
- package/src/Field/PanelSearchInput.tsx +2 -2
- package/src/FieldStatus/FieldStatus.tsx +2 -2
- package/src/FileInput/FileInput.test.tsx +21 -0
- package/src/FileInput/FileInput.tsx +4 -1
- package/src/FormLayout/FormLayout.spec.md +7 -8
- package/src/Heading/Heading.tsx +1 -1
- package/src/Icon/Icon.tsx +1 -1
- package/src/Indicator/CheckIndicator.spec.md +47 -42
- package/src/Indicator/CheckIndicator.tsx +2 -1
- package/src/Indicator/CheckboxIndicator.spec.md +40 -37
- package/src/Indicator/CheckboxIndicator.tsx +3 -1
- package/src/Indicator/Indicator.spec.md +188 -0
- package/src/Indicator/RadioIndicator.tsx +3 -1
- package/src/Item/Item.tsx +2 -1
- package/src/Item/ItemSwipeLayer.tsx +1 -1
- package/src/Layout/Layout.spec.md +127 -131
- package/src/Layout/Layout.tsx +1 -1
- package/src/Layout/LayoutContent.spec.md +205 -0
- package/src/Layout/LayoutContent.tsx +1 -1
- package/src/Layout/LayoutFooter.spec.md +190 -0
- package/src/Layout/LayoutFooter.tsx +1 -1
- package/src/Layout/LayoutHeader.spec.md +193 -0
- package/src/Layout/LayoutHeader.tsx +1 -1
- package/src/Layout/LayoutPanel.spec.md +194 -0
- package/src/Layout/__tests__/Layout.a11y.chromium.spec.ts +18 -6
- package/src/Lightbox/Lightbox.test.tsx +18 -0
- package/src/Lightbox/Lightbox.tsx +5 -0
- package/src/Lightbox/LightboxViewport.a11y.browser.spec.ts +8 -4
- package/src/Link/__tests__/Link.a11y.chromium.spec.ts +18 -8
- package/src/List/List.tsx +1 -1
- package/src/List/ListItem.spec.md +205 -0
- package/src/List/ListItem.tsx +3 -3
- package/src/MobileNav/MobileNav.test.tsx +15 -0
- package/src/MobileNav/MobileNav.tsx +9 -1
- package/src/MobileNav/__tests__/MobileNavHeader.a11y.chromium.spec.ts +89 -0
- package/src/MoreMenu/MoreMenu.test.tsx +11 -0
- package/src/MultiSelector/MultiSelector.spec.md +7 -4
- package/src/MultiSelector/MultiSelector.test.tsx +118 -1
- package/src/MultiSelector/MultiSelector.tsx +6 -2
- package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +8 -1
- package/src/NavMenu/NavHeadingMenu.spec.md +1 -5
- package/src/NumberInput/NumberInput.doc.mjs +13 -7
- package/src/NumberInput/NumberInput.spec.md +59 -37
- package/src/NumberInput/NumberInput.tsx +13 -3
- package/src/NumberInput/__tests__/NumberInput.coarse-pointer.a11y.chromium.spec.ts +102 -0
- package/src/NumberInput/numberParser.ts +7 -45
- package/src/ProgressBar/ProgressBar.test.tsx +108 -32
- package/src/ProgressBar/ProgressBar.tsx +58 -10
- package/src/ProgressBar/__tests__/ProgressBar.a11y.chromium.spec.ts +21 -9
- package/src/ProgressBar/__tests__/ProgressBarMotion.a11y.chromium.spec.ts +831 -0
- package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +21 -14
- package/src/Resizable/useResizable.test.ts +43 -0
- package/src/Resizable/useResizable.ts +32 -9
- package/src/SegmentedControl/SegmentedControl.test.tsx +84 -0
- package/src/SegmentedControl/SegmentedControlItem.tsx +11 -5
- package/src/Selector/Selector.test.tsx +90 -1
- package/src/Selector/__tests__/Selector.combobox.a11y.test.tsx +8 -1
- package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +8 -1
- package/src/Selector/useSelectorPresentation.ts +31 -3
- package/src/SideNav/SideNav.test.tsx +27 -0
- package/src/SideNav/__tests__/SideNavRailMotion.interaction.browser.spec.ts +176 -51
- package/src/Slider/Slider.test.tsx +12 -0
- package/src/Slider/Slider.tsx +4 -1
- package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +19 -7
- package/src/Spinner/Spinner.tsx +2 -2
- package/src/Stack/Stack.tsx +1 -1
- package/src/Stack/StackItem.tsx +1 -1
- package/src/TabList/TabList.test.tsx +58 -4
- package/src/TabList/TabList.tsx +16 -1
- package/src/TabList/__tests__/TabPressPointer.interaction.browser.spec.ts +163 -0
- package/src/Table/__tests__/Table.a11y.chromium.spec.ts +18 -6
- package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +22 -0
- package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -4
- package/src/Text/Text.tsx +1 -1
- package/src/Text/useTruncation.test.tsx +128 -1
- package/src/Text/useTruncation.ts +23 -5
- package/src/TextArea/TextArea.spec.md +10 -13
- package/src/TextArea/TextArea.test.tsx +60 -0
- package/src/TextArea/TextArea.tsx +15 -1
- package/src/TextInput/TextInput.test.tsx +21 -0
- package/src/TextInput/TextInput.tsx +3 -1
- package/src/TimeInput/NativeTimeInput.test.tsx +17 -0
- package/src/TimeInput/Presentation.test.tsx +21 -0
- package/src/TimeInput/TimeInput.doc.mjs +8 -8
- package/src/TimeInput/TimeInput.spec.md +45 -48
- package/src/TimeInput/TimeInput.test.tsx +76 -0
- package/src/TimeInput/TimeInput.tsx +36 -18
- package/src/TimeInput/TouchTimeField.tsx +4 -6
- package/src/Timestamp/Timestamp.spec.md +6 -12
- package/src/Timestamp/Timestamp.test.tsx +30 -5
- package/src/Timestamp/Timestamp.tsx +6 -2
- package/src/Timestamp/TimestampHoverCard.tsx +4 -4
- package/src/Toast/Toast.spec.md +14 -20
- package/src/Toast/Toast.tsx +104 -36
- package/src/Toast/ToastViewport.test.tsx +719 -1
- package/src/Toast/ToastViewport.tsx +100 -50
- package/src/Tokenizer/Tokenizer.spec.md +5 -3
- package/src/Tokenizer/Tokenizer.test.tsx +68 -0
- package/src/Tokenizer/Tokenizer.tsx +14 -2
- package/src/Tokenizer/TokenizerBottomSheet.test.tsx +15 -4
- package/src/Tokenizer/TokenizerBottomSheet.tsx +3 -3
- package/src/Toolbar/Toolbar.spec.md +5 -6
- package/src/Toolbar/Toolbar.test.tsx +30 -0
- package/src/Toolbar/Toolbar.tsx +2 -1
- package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +18 -6
- package/src/Tooltip/__tests__/Tooltip.a11y.chromium.spec.ts +18 -7
- package/src/TopNav/TopNav.test.tsx +27 -0
- package/src/Typeahead/Typeahead.test.tsx +40 -0
- package/src/Typeahead/Typeahead.tsx +12 -1
- package/src/gestures/GestureArena.ts +35 -0
- package/src/gestures/GestureHost.ts +2065 -0
- package/src/gestures/GestureRecognizer.ts +18 -0
- package/src/gestures/LongPressGestureRecognizer.ts +4 -0
- package/src/gestures/PanGestureRecognizer.ts +4 -0
- package/src/gestures/PinchGestureRecognizer.ts +148 -0
- package/src/gestures/ScreenEdgePanGestureRecognizer.ts +256 -0
- package/src/gestures/SwipeGestureRecognizer.ts +197 -0
- package/src/gestures/TapGestureRecognizer.ts +4 -0
- package/src/gestures/VelocityTracker.ts +10 -3
- package/src/gestures/__tests__/GestureHost.test.ts +2087 -0
- package/src/gestures/__tests__/PanGestureRecognizer.test.ts +4 -4
- package/src/gestures/__tests__/PinchGestureRecognizer.test.ts +74 -0
- package/src/gestures/__tests__/ScreenEdgePanGestureRecognizer.test.ts +498 -0
- package/src/gestures/__tests__/SwipeGestureRecognizer.test.ts +108 -0
- package/src/gestures/__tests__/arena.test.ts +5 -0
- package/src/gestures/__tests__/arenaPinchSwipeEdge.test.ts +193 -0
- package/src/gestures/__tests__/browser/build-fixture.mjs +46 -0
- package/src/gestures/__tests__/browser/fixture.ts +307 -0
- package/src/gestures/__tests__/browser/gestures.interaction.browser.spec.ts +1137 -0
- package/src/gestures/__tests__/browserNegotiation.test.ts +293 -0
- package/src/gestures/__tests__/haptics.test.ts +187 -0
- package/src/gestures/__tests__/harness.ts +21 -2
- package/src/gestures/__tests__/recognizerKind.test.ts +78 -0
- package/src/gestures/__tests__/touchActionRule.test.ts +54 -0
- package/src/gestures/haptics.ts +203 -0
- package/src/gestures/nativeScroll.ts +277 -0
- package/src/gestures/touchAction.ts +191 -0
- package/src/gestures/touchActionRule.ts +157 -0
- package/src/gestures/types.ts +30 -9
- package/src/hooks/useAdaptivePresentation.ts +4 -1
- package/src/hooks/useMenuHover.ts +15 -1
- package/src/i18n/generated-locales/en.generated.ts +4 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +4 -0
- package/src/motion/README.md +11 -1
- package/src/motion/animator.test.ts +151 -3
- package/src/motion/animator.ts +149 -33
- package/src/theme/defineTheme.ts +1 -1
- package/src/theme/derivedVarRegistry.test.ts +4 -0
- package/src/theme/domainTokens/domainTokenDefaults.ts +19 -0
- package/src/theme/domainTokens/index.ts +6 -10
- package/src/utils/focusReturn.ts +17 -6
- package/src/utils/getNodeText.test.ts +24 -0
- package/src/utils/getNodeText.ts +37 -0
- package/src/utils/interactionModality.test.ts +45 -1
- package/src/utils/interactionModality.ts +64 -5
- package/src/utils/plainDate.test.ts +90 -0
- package/src/utils/plainDate.ts +58 -3
- package/src/utils/presentation.test.ts +380 -0
- package/src/utils/presentation.ts +180 -0
- package/src/utils/pressPaintPriority.test.ts +80 -0
- package/src/utils/primaryClick.test.ts +38 -0
- package/src/utils/primaryClick.ts +28 -0
- package/src/utils/timeFormat.test.ts +204 -0
- package/src/utils/timeFormat.ts +314 -0
- package/src/utils/touchPresentation.stylex.ts +43 -0
- package/src/utils/touchPresentation.test.ts +140 -1
- package/src/utils/touchPresentation.ts +5 -3
- package/src/utils/unicodeDigits.test.ts +44 -0
- package/src/utils/unicodeDigits.ts +71 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file presentation.ts
|
|
7
|
+
* @input A component's `presentation` prop (a caller's value, or omitted),
|
|
8
|
+
* what the component does when it is omitted, and the touch presentation
|
|
9
|
+
* (utils/touchPresentation.ts)
|
|
10
|
+
* @output usePresentation and readPresentation (and the pure
|
|
11
|
+
* resolvePresentation): the surface to render and whether the component's
|
|
12
|
+
* touch input modes apply
|
|
13
|
+
* @position Internal resolver for stable components that, under a finger,
|
|
14
|
+
* present a different surface or switch how an open surface follows input
|
|
15
|
+
* (architecture:public-component-api INV16)
|
|
16
|
+
*
|
|
17
|
+
* A caller's explicit `presentation` always wins over the touch default:
|
|
18
|
+
*
|
|
19
|
+
* - `'popover'`: the fine-pointer surface AND input modes, on every device;
|
|
20
|
+
* - `'bottom-sheet'`: the sheet everywhere, with touch input modes under a
|
|
21
|
+
* finger;
|
|
22
|
+
* - `'adaptive'`: the sheet on a compact touch screen and the popover
|
|
23
|
+
* elsewhere, with touch input modes under a finger;
|
|
24
|
+
* - omitted: the component's default. `whenOmitted: 'popover'` answers as
|
|
25
|
+
* `'popover'` (today's components). `whenOmitted: 'touch'` keeps the
|
|
26
|
+
* popover surface and turns the component's touch input modes on under a
|
|
27
|
+
* finger, as UIMenu tracks a finger in an anchored menu. Making `'touch'`
|
|
28
|
+
* a released component's default is a functional default change
|
|
29
|
+
* (`spec:AST-017` FR3) whose Changeset names `presentation="popover"`.
|
|
30
|
+
*
|
|
31
|
+
* One touch model on every touch device: the modes depend on the pointer,
|
|
32
|
+
* never on the platform. Touch styling (press paint, the text-size floor)
|
|
33
|
+
* and touch-only behavior that a component's own record defines (a row
|
|
34
|
+
* swipe, a slider's thumb) do not read this: they keep the touch
|
|
35
|
+
* presentation.
|
|
36
|
+
*
|
|
37
|
+
* CSS: a style that implements a touch surface or input mode is applied with
|
|
38
|
+
* `touchModes` (`stylex.props(touchModes && styles.touchMode)`), never as a
|
|
39
|
+
* bare media key on a base style, so a pinned `'popover'` keeps none of it.
|
|
40
|
+
* A rule inside it that needs the touch query uses the touch presentation's
|
|
41
|
+
* touch key; the iOS `@supports` gate is only for the one style iOS WebKit
|
|
42
|
+
* itself requires (the 16px text-size floor), never for a touch mode. On the
|
|
43
|
+
* server and while hydrating, `touchModes` is false and `'adaptive'` is the
|
|
44
|
+
* popover: a touch surface or mode opens only after hydration
|
|
45
|
+
* (`spec:AST-094` FR13), and no hint changes that. usePresentation listens
|
|
46
|
+
* only to the queries a request reads (`architecture:react-component-runtime`
|
|
47
|
+
* INV5): none for a pinned `'popover'`.
|
|
48
|
+
*
|
|
49
|
+
* SYNC: When modified, update presentation.test.ts.
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
import {useCallback, useMemo, useSyncExternalStore} from 'react';
|
|
53
|
+
import type {AdaptivePresentation} from '../hooks/useAdaptivePresentation';
|
|
54
|
+
import type {CompactDefinition} from '../theme/themeAdaptations';
|
|
55
|
+
import {
|
|
56
|
+
readTouchPresentation,
|
|
57
|
+
TOUCH_QUERY,
|
|
58
|
+
useCompactDefinition,
|
|
59
|
+
type TouchPresentation,
|
|
60
|
+
} from './touchPresentation';
|
|
61
|
+
|
|
62
|
+
/** What a component does when the caller omits `presentation`. */
|
|
63
|
+
export type PresentationDefault = 'popover' | 'touch';
|
|
64
|
+
|
|
65
|
+
export interface ResolvedPresentation {
|
|
66
|
+
/** The surface to render. */
|
|
67
|
+
readonly surface: 'popover' | 'bottom-sheet';
|
|
68
|
+
/**
|
|
69
|
+
* The component's touch input modes apply: a finger, and `presentation`
|
|
70
|
+
* not pinned to `'popover'`.
|
|
71
|
+
*/
|
|
72
|
+
readonly touchModes: boolean;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface PresentationOptions {
|
|
76
|
+
/** What an omitted `presentation` means. @default 'popover' */
|
|
77
|
+
readonly whenOmitted?: PresentationDefault;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* usePresentation's options. There is no server hint: the server and
|
|
82
|
+
* hydrating render never present touch modes (`spec:AST-094` FR13).
|
|
83
|
+
*/
|
|
84
|
+
export type UsePresentationOptions = PresentationOptions;
|
|
85
|
+
|
|
86
|
+
export interface ReadPresentationOptions extends PresentationOptions {
|
|
87
|
+
/** The window to read; the global one by default. */
|
|
88
|
+
readonly view?: Window | null;
|
|
89
|
+
/**
|
|
90
|
+
* The active theme's compact definition (`useCompactDefinition()`, read
|
|
91
|
+
* while rendering), so a theme that moves `md` moves the sheet too
|
|
92
|
+
* (`spec:AST-012` FR9).
|
|
93
|
+
*/
|
|
94
|
+
readonly compact: CompactDefinition;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** The decision, from a presentation request and a touch presentation. */
|
|
98
|
+
export function resolvePresentation(
|
|
99
|
+
presentation: AdaptivePresentation | undefined,
|
|
100
|
+
touch: TouchPresentation,
|
|
101
|
+
whenOmitted: PresentationDefault = 'popover',
|
|
102
|
+
): ResolvedPresentation {
|
|
103
|
+
const request = presentation ?? whenOmitted;
|
|
104
|
+
const surface =
|
|
105
|
+
request === 'bottom-sheet' ||
|
|
106
|
+
(request === 'adaptive' && touch.isTouch && touch.isCompact)
|
|
107
|
+
? 'bottom-sheet'
|
|
108
|
+
: 'popover';
|
|
109
|
+
const touchModes = request !== 'popover' && touch.isTouch;
|
|
110
|
+
return {surface, touchModes};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const noSubscription = () => () => {};
|
|
114
|
+
/** The server and hydrating render match no query (`spec:AST-094` FR13). */
|
|
115
|
+
const matchesNothing = () => false;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* A media query's match, subscribed only while `query` is given
|
|
119
|
+
* (`architecture:react-component-runtime` INV5); false on the server and
|
|
120
|
+
* while hydrating (`spec:AST-094` FR13).
|
|
121
|
+
*/
|
|
122
|
+
function useMatchWhileRead(query: string | null): boolean {
|
|
123
|
+
const subscribe = useCallback(
|
|
124
|
+
(onStoreChange: () => void) => {
|
|
125
|
+
if (query == null) {
|
|
126
|
+
return noSubscription();
|
|
127
|
+
}
|
|
128
|
+
const mql = window.matchMedia(query);
|
|
129
|
+
mql.addEventListener('change', onStoreChange);
|
|
130
|
+
return () => mql.removeEventListener('change', onStoreChange);
|
|
131
|
+
},
|
|
132
|
+
[query],
|
|
133
|
+
);
|
|
134
|
+
const getSnapshot = useCallback(
|
|
135
|
+
() => query != null && window.matchMedia(query).matches,
|
|
136
|
+
[query],
|
|
137
|
+
);
|
|
138
|
+
return useSyncExternalStore(subscribe, getSnapshot, matchesNothing);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* The presentation now, following the pointer and the size as they change
|
|
143
|
+
* (a tablet docking a trackpad). SSR-safe: renders the server default (not
|
|
144
|
+
* touch, not compact) until hydrated (`spec:AST-094` FR13). It subscribes
|
|
145
|
+
* only to what the request reads: a pinned `'popover'` to neither query,
|
|
146
|
+
* `'bottom-sheet'` and the omitted `'touch'` default to the pointer, and
|
|
147
|
+
* `'adaptive'` to the pointer and the compact size.
|
|
148
|
+
*/
|
|
149
|
+
export function usePresentation(
|
|
150
|
+
presentation: AdaptivePresentation | undefined,
|
|
151
|
+
{whenOmitted = 'popover'}: UsePresentationOptions = {},
|
|
152
|
+
): ResolvedPresentation {
|
|
153
|
+
const request = presentation ?? whenOmitted;
|
|
154
|
+
const compact = useCompactDefinition();
|
|
155
|
+
const isTouch = useMatchWhileRead(request === 'popover' ? null : TOUCH_QUERY);
|
|
156
|
+
const isCompact = useMatchWhileRead(
|
|
157
|
+
request === 'adaptive' ? compact.query : null,
|
|
158
|
+
);
|
|
159
|
+
return useMemo(
|
|
160
|
+
() => resolvePresentation(presentation, {isTouch, isCompact}, whenOmitted),
|
|
161
|
+
[presentation, isTouch, isCompact, whenOmitted],
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* The presentation at this moment, for a decision taken once (a menu
|
|
167
|
+
* deciding how it follows the finger that opened it).
|
|
168
|
+
*/
|
|
169
|
+
export function readPresentation(
|
|
170
|
+
presentation: AdaptivePresentation | undefined,
|
|
171
|
+
{whenOmitted = 'popover', view, compact}: ReadPresentationOptions,
|
|
172
|
+
): ResolvedPresentation {
|
|
173
|
+
const target =
|
|
174
|
+
view === undefined ? (typeof window === 'undefined' ? null : window) : view;
|
|
175
|
+
return resolvePresentation(
|
|
176
|
+
presentation,
|
|
177
|
+
readTouchPresentation(target, compact),
|
|
178
|
+
whenOmitted,
|
|
179
|
+
);
|
|
180
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file pressPaintPriority.test.ts
|
|
5
|
+
* @input Uses vitest, Babel with the StyleX plugin (the repository's shared
|
|
6
|
+
* module resolution) and interactionOverlay.stylex.ts
|
|
7
|
+
* @output Checks, in the compiled CSS, that the press paint outranks the
|
|
8
|
+
* coarse-pointer `:active` reset of the overlay
|
|
9
|
+
* @position Regression test for the cascade order of the press overlay
|
|
10
|
+
*
|
|
11
|
+
* WebKit applies `:active` during a touch. Under a coarse pointer the overlay
|
|
12
|
+
* turns the bare `:active` image off, and the press paint
|
|
13
|
+
* (`[data-astryx-press="on"]`) must still win: its rule has to sit in a
|
|
14
|
+
* higher StyleX priority than the reset. The order is a property of how
|
|
15
|
+
* each key is spelled: an imported `defineConsts` key compiles to a higher
|
|
16
|
+
* priority than the same literal, which put the reset above the paint and
|
|
17
|
+
* erased the touch-down frame.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import fs from 'node:fs';
|
|
21
|
+
import {createRequire} from 'node:module';
|
|
22
|
+
import path from 'node:path';
|
|
23
|
+
import {describe, expect, it} from 'vitest';
|
|
24
|
+
import stylexResolution from '../../../../scripts/stylex-module-resolution.cjs';
|
|
25
|
+
|
|
26
|
+
type Rule = [string, {ltr: string}, number];
|
|
27
|
+
|
|
28
|
+
// Babel's types are not part of core's typecheck; type the one call used.
|
|
29
|
+
const {transformSync} = createRequire(import.meta.url)('@babel/core') as {
|
|
30
|
+
transformSync: (
|
|
31
|
+
code: string,
|
|
32
|
+
options: Record<string, unknown>,
|
|
33
|
+
) => {metadata?: unknown} | null;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function compiledRules(file: string): Rule[] {
|
|
37
|
+
const output = transformSync(fs.readFileSync(file, 'utf8'), {
|
|
38
|
+
filename: file,
|
|
39
|
+
babelrc: false,
|
|
40
|
+
configFile: false,
|
|
41
|
+
parserOpts: {plugins: ['typescript', 'jsx']},
|
|
42
|
+
plugins: [
|
|
43
|
+
[
|
|
44
|
+
'@stylexjs/babel-plugin',
|
|
45
|
+
{
|
|
46
|
+
dev: false,
|
|
47
|
+
runtimeInjection: false,
|
|
48
|
+
genConditionalClasses: true,
|
|
49
|
+
treeshakeCompensation: true,
|
|
50
|
+
unstable_moduleResolution: stylexResolution.stylexModuleResolution,
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
],
|
|
54
|
+
});
|
|
55
|
+
return (output?.metadata as {stylex?: Rule[]}).stylex ?? [];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
describe('press overlay cascade', () => {
|
|
59
|
+
it('ranks the press paint above the coarse-pointer :active reset', () => {
|
|
60
|
+
const rules = compiledRules(
|
|
61
|
+
path.resolve(__dirname, 'interactionOverlay.stylex.ts'),
|
|
62
|
+
);
|
|
63
|
+
const resets = rules.filter(
|
|
64
|
+
// Matched without its condition's text: an imported key compiles to a
|
|
65
|
+
// placeholder until the bundle step.
|
|
66
|
+
([, {ltr}]) =>
|
|
67
|
+
ltr.includes(':active') && ltr.includes('background-image:none'),
|
|
68
|
+
);
|
|
69
|
+
const paints = rules.filter(
|
|
70
|
+
([, {ltr}]) =>
|
|
71
|
+
ltr.includes('[data-astryx-press="on"]') &&
|
|
72
|
+
ltr.includes('background-image:'),
|
|
73
|
+
);
|
|
74
|
+
expect(resets.length).toBeGreaterThan(0);
|
|
75
|
+
expect(paints.length).toBeGreaterThan(0);
|
|
76
|
+
const highestReset = Math.max(...resets.map(([, , priority]) => priority));
|
|
77
|
+
const lowestPaint = Math.min(...paints.map(([, , priority]) => priority));
|
|
78
|
+
expect(highestReset).toBeLessThan(lowestPaint);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file primaryClick.test.ts
|
|
5
|
+
* @input isPrimaryClick over button presses on Apple and other platforms
|
|
6
|
+
* @output Tests that only the main button, and not a ctrl-click on macOS,
|
|
7
|
+
* is a primary click (spec:AST-094 FR43)
|
|
8
|
+
* @position Unit tests of packages/core/src/utils/primaryClick.ts
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {afterEach, describe, expect, it, vi} from 'vitest';
|
|
12
|
+
import {isPrimaryClick} from './primaryClick';
|
|
13
|
+
|
|
14
|
+
function onPlatform(platform: string) {
|
|
15
|
+
vi.spyOn(navigator, 'platform', 'get').mockReturnValue(platform);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
vi.restoreAllMocks();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('isPrimaryClick (spec:AST-094 FR43)', () => {
|
|
23
|
+
it('takes the main button, and no right click or pen barrel button', () => {
|
|
24
|
+
onPlatform('Win32');
|
|
25
|
+
expect(isPrimaryClick({button: 0, ctrlKey: false})).toBe(true);
|
|
26
|
+
expect(isPrimaryClick({button: 2, ctrlKey: false})).toBe(false);
|
|
27
|
+
expect(isPrimaryClick({button: 1, ctrlKey: false})).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("takes no ctrl-click on macOS, that platform's context click, and a ctrl-click elsewhere", () => {
|
|
31
|
+
onPlatform('MacIntel');
|
|
32
|
+
expect(isPrimaryClick({button: 0, ctrlKey: true})).toBe(false);
|
|
33
|
+
expect(isPrimaryClick({button: 0, ctrlKey: false})).toBe(true);
|
|
34
|
+
vi.restoreAllMocks();
|
|
35
|
+
onPlatform('Win32');
|
|
36
|
+
expect(isPrimaryClick({button: 0, ctrlKey: true})).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file primaryClick.ts
|
|
5
|
+
* @input A mouse or pen button press: its `button` and `ctrlKey`
|
|
6
|
+
* @output Exports isPrimaryClick
|
|
7
|
+
* @position Internal util, the one primary-click rule: the gesture host
|
|
8
|
+
* starts a press only for one, and the press controller paints only one;
|
|
9
|
+
* platform detection is utils/isApplePlatform.ts
|
|
10
|
+
*
|
|
11
|
+
* Deliberately absent from utils/index.ts: packages/core/src/index.ts does
|
|
12
|
+
* `export * from './utils'`, so naming it there would publish it as API.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {isApplePlatform} from './isApplePlatform';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Whether a button press is a primary click: the main button, and not a
|
|
19
|
+
* ctrl-click on macOS or iPadOS, which is that platform's context click
|
|
20
|
+
* (`spec:AST-094` FR43). A right click, a pen's barrel button and a macOS
|
|
21
|
+
* ctrl-click start no press.
|
|
22
|
+
*/
|
|
23
|
+
export function isPrimaryClick(event: {
|
|
24
|
+
readonly button: number;
|
|
25
|
+
readonly ctrlKey: boolean;
|
|
26
|
+
}): boolean {
|
|
27
|
+
return event.button === 0 && !(event.ctrlKey && isApplePlatform());
|
|
28
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file timeFormat.test.ts
|
|
5
|
+
* @input Uses vitest and the timeFormat helpers
|
|
6
|
+
* @output Unit tests for locale hour cycles, locale time text, and parsing it back
|
|
7
|
+
* @position Testing; validates utils/timeFormat.ts
|
|
8
|
+
*
|
|
9
|
+
* SYNC: When timeFormat.ts changes, update tests to match new behavior
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {describe, expect, it} from 'vitest';
|
|
13
|
+
import {
|
|
14
|
+
formatLocaleTime,
|
|
15
|
+
parseLocaleTime,
|
|
16
|
+
resolveHourFormat,
|
|
17
|
+
type HourFormat,
|
|
18
|
+
} from './timeFormat';
|
|
19
|
+
import {parseTimeInput, type ISOTimeString} from './timeParser';
|
|
20
|
+
|
|
21
|
+
const iso = (time: string) => time as ISOTimeString;
|
|
22
|
+
|
|
23
|
+
describe('resolveHourFormat', () => {
|
|
24
|
+
it.each([
|
|
25
|
+
['en', '12h'],
|
|
26
|
+
['en-US', '12h'],
|
|
27
|
+
['ko-KR', '12h'],
|
|
28
|
+
['en-GB', '24h'],
|
|
29
|
+
['de-DE', '24h'],
|
|
30
|
+
['vi-VN', '24h'],
|
|
31
|
+
['fr-FR', '24h'],
|
|
32
|
+
] as const)('reads the hour cycle of %s as %s', (locale, expected) => {
|
|
33
|
+
expect(resolveHourFormat(locale)).toBe(expected);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('honors a -u-hc- preference carried on the locale tag', () => {
|
|
37
|
+
expect(resolveHourFormat('en-US-u-hc-h23')).toBe('24h');
|
|
38
|
+
expect(resolveHourFormat('de-DE-u-hc-h12')).toBe('12h');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('lets an explicit hour format win over the locale', () => {
|
|
42
|
+
expect(resolveHourFormat('de-DE', '12h')).toBe('12h');
|
|
43
|
+
expect(resolveHourFormat('en-US', '24h')).toBe('24h');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('falls back to twelve-hour for a malformed tag', () => {
|
|
47
|
+
expect(resolveHourFormat('not a locale')).toBe('12h');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
describe('formatLocaleTime', () => {
|
|
52
|
+
it('keeps the released English text exactly, with a plain space', () => {
|
|
53
|
+
expect(formatLocaleTime(iso('14:30'), 'en', '12h')).toBe('2:30 PM');
|
|
54
|
+
expect(formatLocaleTime(iso('00:05'), 'en', '12h')).toBe('12:05 AM');
|
|
55
|
+
expect(formatLocaleTime(iso('14:30:05'), 'en', '12h', true)).toBe(
|
|
56
|
+
'2:30:05 PM',
|
|
57
|
+
);
|
|
58
|
+
expect(formatLocaleTime(iso('09:05'), 'en', '24h')).toBe('09:05');
|
|
59
|
+
expect(formatLocaleTime(iso('09:05:07'), 'en', '24h', true)).toBe(
|
|
60
|
+
'09:05:07',
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("uses the locale's day-period words and their position", () => {
|
|
65
|
+
expect(formatLocaleTime(iso('14:30'), 'ko-KR', '12h')).toBe('오후 2:30');
|
|
66
|
+
expect(formatLocaleTime(iso('09:05'), 'zh-CN', '12h')).toBe('上午9:05');
|
|
67
|
+
expect(formatLocaleTime(iso('14:30'), 'es-ES', '12h')).toBe('2:30 p. m.');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('writes noon as 12 in a twelve-hour reading, not 0', () => {
|
|
71
|
+
expect(formatLocaleTime(iso('12:30'), 'ja-JP', '12h')).toBe('午後12:30');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('writes English twelve-hour text when the locale would drop the day period', () => {
|
|
75
|
+
// fr-CM's twelve-hour reading writes 02:30 and 14:30 both as "2:30".
|
|
76
|
+
expect(formatLocaleTime(iso('14:30'), 'fr-CM', '12h')).toBe('2:30 PM');
|
|
77
|
+
expect(formatLocaleTime(iso('02:30'), 'fr-CM', '12h')).toBe('2:30 AM');
|
|
78
|
+
expect(formatLocaleTime(iso('14:30'), 'fr-CM', '24h')).toBe('14:30');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("uses the locale's separator and digits", () => {
|
|
82
|
+
expect(formatLocaleTime(iso('14:30'), 'fi-FI', '24h')).toBe('14.30');
|
|
83
|
+
expect(formatLocaleTime(iso('14:30'), 'ar-EG', '12h')).toBe('٢:٣٠ م');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('returns empty text for an empty or malformed time', () => {
|
|
87
|
+
expect(formatLocaleTime(undefined, 'en', '12h')).toBe('');
|
|
88
|
+
expect(formatLocaleTime(iso('25:00'), 'en', '12h')).toBe('');
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('parseLocaleTime', () => {
|
|
93
|
+
const LOCALES = [
|
|
94
|
+
'en-US',
|
|
95
|
+
'en-GB',
|
|
96
|
+
'de-DE',
|
|
97
|
+
'fi-FI',
|
|
98
|
+
'fr-CA',
|
|
99
|
+
'es-ES',
|
|
100
|
+
'sv-SE',
|
|
101
|
+
'vi-VN',
|
|
102
|
+
'ja-JP',
|
|
103
|
+
'ko-KR',
|
|
104
|
+
'zh-TW',
|
|
105
|
+
'ar-EG',
|
|
106
|
+
'fa-IR',
|
|
107
|
+
'he-IL',
|
|
108
|
+
// Twelve-hour readings whose separators or surrounding words differ from
|
|
109
|
+
// the twenty-four-hour reading: a dot (as, nds), "h" (oc), a word between
|
|
110
|
+
// the day period and the hour (brx, ee), a word before the hour (dz, nds,
|
|
111
|
+
// tok), and Tibetan digits (dz).
|
|
112
|
+
'as',
|
|
113
|
+
'brx',
|
|
114
|
+
'dz',
|
|
115
|
+
'ee',
|
|
116
|
+
'nds',
|
|
117
|
+
'oc',
|
|
118
|
+
'tok',
|
|
119
|
+
// A one-letter day period that English input contains ("m" in "pm").
|
|
120
|
+
'gd',
|
|
121
|
+
// A twelve-hour reading with no day period at all.
|
|
122
|
+
'fr-CM',
|
|
123
|
+
];
|
|
124
|
+
const TIMES = ['00:00', '00:30', '09:05', '11:59', '12:00', '12:30', '23:45'];
|
|
125
|
+
const FORMATS: HourFormat[] = ['12h', '24h'];
|
|
126
|
+
|
|
127
|
+
it.each(LOCALES)('reads back every time %s writes', locale => {
|
|
128
|
+
for (const hourFormat of FORMATS) {
|
|
129
|
+
for (const time of TIMES) {
|
|
130
|
+
const text = formatLocaleTime(iso(time), locale, hourFormat);
|
|
131
|
+
expect(
|
|
132
|
+
parseLocaleTime(text, locale),
|
|
133
|
+
`${locale} ${hourFormat} "${text}"`,
|
|
134
|
+
).toBe(time);
|
|
135
|
+
}
|
|
136
|
+
const withSeconds = formatLocaleTime(
|
|
137
|
+
iso('14:30:05'),
|
|
138
|
+
locale,
|
|
139
|
+
hourFormat,
|
|
140
|
+
true,
|
|
141
|
+
);
|
|
142
|
+
expect(parseLocaleTime(withSeconds, locale, true)).toBe('14:30:05');
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('reads a spaced day period as the half of the day it names', () => {
|
|
147
|
+
// Previously parsed as 02:30: the English matcher missed "p. m.".
|
|
148
|
+
expect(parseLocaleTime('2:30 p. m.', 'es-ES')).toBe('14:30');
|
|
149
|
+
expect(parseLocaleTime('午後2:30', 'ja-JP')).toBe('14:30');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('reads twelve-hour text whose pattern differs from the 24-hour one', () => {
|
|
153
|
+
expect(parseLocaleTime('অপৰাহ্ন ২.৩০', 'as')).toBe('14:30');
|
|
154
|
+
expect(parseLocaleTime('ɣetrɔ ga 2:30', 'ee')).toBe('14:30');
|
|
155
|
+
expect(parseLocaleTime('Klock 2.30:05 PM', 'nds', true)).toBe('14:30:05');
|
|
156
|
+
expect(parseLocaleTime('2h30:05 PM', 'oc', true)).toBe('14:30:05');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it("reads the locale's separator", () => {
|
|
160
|
+
// Previously "14.30" read only its "14" prefix.
|
|
161
|
+
expect(parseLocaleTime('14.30', 'fi-FI')).toBe('14:30');
|
|
162
|
+
expect(parseLocaleTime('14 h 30', 'fr-CA')).toBe('14:30');
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('does not read a day-period word out of the middle of an English word', () => {
|
|
166
|
+
// gd writes the morning as "m": the "m" of "pm" is not that word.
|
|
167
|
+
expect(parseLocaleTime('2:30 PM', 'gd')).toBe('14:30');
|
|
168
|
+
expect(parseLocaleTime('12:00 PM', 'gd')).toBe('12:00');
|
|
169
|
+
expect(parseLocaleTime('2pm', 'gd')).toBe('14:00');
|
|
170
|
+
expect(parseLocaleTime('2:30 p.m', 'gd')).toBe('14:30');
|
|
171
|
+
expect(parseLocaleTime('12:00 p.m', 'gd')).toBe('12:00');
|
|
172
|
+
expect(parseLocaleTime('2 p.m', 'gd')).toBe('14:00');
|
|
173
|
+
expect(parseLocaleTime('11 a.m', 'gd')).toBe('11:00');
|
|
174
|
+
expect(parseLocaleTime('2:30m', 'gd')).toBe('02:30');
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('still reads English input in every locale exactly as before', () => {
|
|
178
|
+
const inputs = [
|
|
179
|
+
'2:30 PM',
|
|
180
|
+
'2:30 p.m',
|
|
181
|
+
'2:30 p.m.',
|
|
182
|
+
'12:00 PM',
|
|
183
|
+
'12:00 AM',
|
|
184
|
+
'2pm',
|
|
185
|
+
'2 p.m',
|
|
186
|
+
'11 a.m',
|
|
187
|
+
'14:30',
|
|
188
|
+
'1430',
|
|
189
|
+
];
|
|
190
|
+
for (const locale of LOCALES) {
|
|
191
|
+
for (const input of inputs) {
|
|
192
|
+
expect(parseLocaleTime(input, locale), `${locale} "${input}"`).toBe(
|
|
193
|
+
parseTimeInput(input),
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('rejects text no reading fits', () => {
|
|
200
|
+
expect(parseLocaleTime('', 'en-US')).toBeNull();
|
|
201
|
+
expect(parseLocaleTime('25:99', 'de-DE')).toBeNull();
|
|
202
|
+
expect(parseLocaleTime('午後14:30', 'ja-JP')).toBeNull();
|
|
203
|
+
});
|
|
204
|
+
});
|