@astryxdesign/core 0.7.8 → 0.7.9-canary.0200dfe
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AppShell/observeMainOverflow.d.ts.map +1 -1
- package/dist/AppShell/observeMainOverflow.js +9 -6
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +37 -3
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +40 -8
- package/dist/BottomSheet/bottomSheetStack.d.ts.map +1 -1
- package/dist/BottomSheet/bottomSheetStack.js +4 -3
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +61 -21
- package/dist/Calendar/Calendar.d.ts +14 -2
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +63 -74
- package/dist/Calendar/getInitialFocusDate.d.ts +4 -1
- package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -1
- package/dist/Calendar/getInitialFocusDate.js +7 -5
- package/dist/Calendar/hooks/useCalendarDays.d.ts +19 -2
- package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarDays.js +57 -64
- package/dist/Calendar/hooks/useCalendarNavigation.d.ts +28 -3
- package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarNavigation.js +33 -22
- package/dist/Calendar/styles.d.ts +1 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts +2 -1
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +74 -18
- package/dist/CheckboxInput/CheckboxRowPressContext.d.ts +2 -0
- package/dist/CheckboxInput/CheckboxRowPressContext.d.ts.map +1 -0
- package/dist/CheckboxInput/CheckboxRowPressContext.js +20 -0
- package/dist/CheckboxList/CheckboxListItem.d.ts +2 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +40 -14
- package/dist/ClickableCard/ClickableCard.d.ts +1 -1
- package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
- package/dist/ClickableCard/ClickableCard.js +5 -1
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +2 -0
- package/dist/DateInput/DateInput.d.ts +37 -6
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +97 -124
- package/dist/DateInput/MonthScroller.d.ts +5 -2
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +26 -29
- package/dist/DateInput/MonthYearWheels.d.ts +10 -1
- package/dist/DateInput/MonthYearWheels.d.ts.map +1 -1
- package/dist/DateInput/MonthYearWheels.js +54 -42
- package/dist/DateInput/PickerWheel.d.ts.map +1 -1
- package/dist/DateInput/PickerWheel.js +7 -1
- package/dist/DateInput/TouchDateField.d.ts +1 -1
- package/dist/DateInput/TouchDateField.d.ts.map +1 -1
- package/dist/DateInput/TouchDateField.js +26 -21
- package/dist/DateInput/monthGeometry.d.ts +42 -8
- package/dist/DateInput/monthGeometry.d.ts.map +1 -1
- package/dist/DateInput/monthGeometry.js +81 -7
- package/dist/DateInput/useCalendarPresentation.d.ts +10 -0
- package/dist/DateInput/useCalendarPresentation.d.ts.map +1 -0
- package/dist/DateInput/useCalendarPresentation.js +32 -0
- package/dist/DateInput/useTypedDate.d.ts +92 -0
- package/dist/DateInput/useTypedDate.d.ts.map +1 -0
- package/dist/DateInput/useTypedDate.js +269 -0
- package/dist/DateInput/wheelStrip.js +2 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts +17 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +15 -8
- package/dist/DateTimeInput/DateTimeInput.d.ts +26 -3
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +92 -88
- package/dist/DateTimeInput/TouchDateTimeField.d.ts +1 -1
- package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
- package/dist/DateTimeInput/TouchDateTimeField.js +26 -20
- package/dist/Dialog/Dialog.d.ts +2 -1
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +14 -3
- package/dist/Drawer/useDrawerDialogPresence.d.ts +2 -1
- package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
- package/dist/Drawer/useDrawerDialogPresence.js +11 -2
- package/dist/DropdownMenu/DropdownMenu.d.ts +9 -1
- package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenu.js +11 -8
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +3 -2
- package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuItem.js +3 -2
- package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioItem.js +3 -2
- package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuSubMenu.js +3 -2
- package/dist/Field/inputDisabledFocus.d.ts +4 -4
- package/dist/Field/inputStyles.stylex.d.ts +1 -1
- package/dist/FileInput/FileInput.d.ts.map +1 -1
- package/dist/FileInput/FileInput.js +16 -2
- package/dist/HoverCard/useHoverCard.d.ts +3 -1
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/Icon/Icon.d.ts +1 -1
- package/dist/InfoTip/InfoTip.d.ts +1 -0
- package/dist/InfoTip/InfoTip.d.ts.map +1 -1
- package/dist/InfoTip/InfoTip.js +6 -18
- package/dist/InputGroup/InputGroup.d.ts +4 -3
- package/dist/InputGroup/InputGroup.d.ts.map +1 -1
- package/dist/InputGroup/InputGroup.js +2 -2
- package/dist/InputGroup/InputGroupText.d.ts +2 -1
- package/dist/InputGroup/InputGroupText.d.ts.map +1 -1
- package/dist/InputGroup/InputGroupText.js +2 -1
- package/dist/InputGroup/groupStyles.d.ts +1 -1
- package/dist/InputGroup/groupStyles.d.ts.map +1 -1
- package/dist/InputGroup/groupStyles.js +1 -1
- package/dist/Item/Item.d.ts +20 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +97 -29
- package/dist/Item/ItemListRowContext.d.ts +2 -0
- package/dist/Item/ItemListRowContext.d.ts.map +1 -0
- package/dist/Item/ItemListRowContext.js +16 -0
- package/dist/Layer/holdEntranceInput.d.ts +24 -0
- package/dist/Layer/holdEntranceInput.d.ts.map +1 -0
- package/dist/Layer/holdEntranceInput.js +65 -0
- package/dist/Layer/inputHold.d.ts +49 -0
- package/dist/Layer/inputHold.d.ts.map +1 -0
- package/dist/Layer/inputHold.js +636 -0
- package/dist/Layer/outsidePress.d.ts +4 -0
- package/dist/Layer/outsidePress.d.ts.map +1 -1
- package/dist/Layer/outsidePress.js +18 -1
- package/dist/Layer/preserveAnimations.d.ts +1 -5
- package/dist/Layer/preserveAnimations.d.ts.map +1 -1
- package/dist/Layer/preserveAnimations.js +12 -214
- package/dist/Layer/useBackdropPress.d.ts +8 -0
- package/dist/Layer/useBackdropPress.d.ts.map +1 -1
- package/dist/Layer/useBackdropPress.js +31 -2
- package/dist/Layer/useLayer.d.ts +3 -1
- package/dist/Layer/useLayer.d.ts.map +1 -1
- package/dist/Layer/useLayer.js +64 -4
- package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
- package/dist/Layer/useTouchTrigger.js +4 -0
- package/dist/Layout/LayoutContent.d.ts +3 -1
- package/dist/Layout/LayoutContent.d.ts.map +1 -1
- package/dist/Layout/LayoutContent.js +12 -4
- package/dist/Layout/LayoutPanel.d.ts +13 -10
- package/dist/Layout/LayoutPanel.d.ts.map +1 -1
- package/dist/Layout/LayoutPanel.js +81 -11
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +4 -0
- package/dist/List/List.d.ts.map +1 -1
- package/dist/List/List.js +1 -0
- package/dist/List/ListItem.d.ts +5 -4
- package/dist/List/ListItem.d.ts.map +1 -1
- package/dist/List/ListItem.js +45 -9
- package/dist/Markdown/parser.d.ts.map +1 -1
- package/dist/Markdown/parser.js +56 -39
- package/dist/MetadataList/MetadataList.js +1 -1
- package/dist/MobileNav/MobileNav.d.ts +11 -1
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +39 -1
- package/dist/MoreMenu/MoreMenu.d.ts +5 -3
- package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +6 -9
- package/dist/NumberInput/NumberInput.d.ts +4 -2
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +244 -11
- package/dist/OverflowList/OverflowList.d.ts.map +1 -1
- package/dist/OverflowList/OverflowList.js +7 -2
- package/dist/Popover/usePopover.d.ts +1 -0
- package/dist/Popover/usePopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +12 -5
- package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchBottomSheet.js +4 -2
- package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchToken.js +3 -1
- package/dist/PowerSearch/formatFilterValue.d.ts +9 -3
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +14 -11
- package/dist/PowerSearch/formatTokenValue.d.ts +6 -2
- package/dist/PowerSearch/formatTokenValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatTokenValue.js +6 -3
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +16 -3
- package/dist/Resizable/ResizeHandle.d.ts +5 -5
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +44 -5
- package/dist/Resizable/resizablePane.d.ts +58 -0
- package/dist/Resizable/resizablePane.d.ts.map +1 -0
- package/dist/Resizable/resizablePane.js +137 -0
- package/dist/Resizable/useResizable.d.ts +7 -0
- package/dist/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +13 -0
- package/dist/SegmentedControl/useSegmentedSelectionMotion.js +3 -3
- package/dist/SelectableCard/SelectableCard.d.ts +1 -1
- package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
- package/dist/SelectableCard/SelectableCard.js +5 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +51 -10
- package/dist/SideNav/SideNav.d.ts +9 -3
- package/dist/SideNav/SideNav.d.ts.map +1 -1
- package/dist/SideNav/SideNav.js +45 -10
- package/dist/Slider/sliderTouchController.js +2 -2
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +14 -71
- package/dist/Spinner/index.d.ts +1 -1
- package/dist/Spinner/index.d.ts.map +1 -1
- package/dist/Spinner/spinnerRotor.d.ts +28 -0
- package/dist/Spinner/spinnerRotor.d.ts.map +1 -0
- package/dist/Spinner/spinnerRotor.js +98 -0
- package/dist/Stack/StackItem.d.ts +8 -4
- package/dist/Stack/StackItem.d.ts.map +1 -1
- package/dist/Stack/StackItem.js +17 -4
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +13 -10
- package/dist/Switch/useSwitchTouch.js +4 -4
- package/dist/TabList/Tab.d.ts.map +1 -1
- package/dist/TabList/Tab.js +5 -1
- package/dist/Table/plugins/sortable/useTableSortable.js +1 -1
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +14 -8
- package/dist/Timestamp/formatInstant.d.ts +10 -1
- package/dist/Timestamp/formatInstant.d.ts.map +1 -1
- package/dist/Timestamp/formatInstant.js +13 -27
- package/dist/Timestamp/tooltipEntries.d.ts +5 -3
- package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
- package/dist/Timestamp/tooltipEntries.js +6 -4
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +9 -0
- package/dist/Token/TokenLink.d.ts +1 -1
- package/dist/Token/TokenLink.d.ts.map +1 -1
- package/dist/Token/TokenLink.js +4 -1
- package/dist/Tokenizer/Tokenizer.d.ts +14 -10
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +189 -89
- package/dist/Tooltip/useTooltip.d.ts +3 -1
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +164 -59
- package/dist/TreeList/TreeListItem.d.ts +2 -1
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +27 -3
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +2 -1
- package/dist/animator/createAnimator.js +2 -2
- package/dist/astryx.css +362 -325
- package/dist/gestures/GestureHost.d.ts +2 -2
- package/dist/gestures/GestureHost.d.ts.map +1 -1
- package/dist/gestures/GestureHost.js +21 -6
- package/dist/gestures/PanGestureRecognizer.d.ts +11 -1
- package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/PanGestureRecognizer.js +15 -1
- package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +6 -1
- package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -1
- package/dist/gestures/nativeScroll.d.ts +3 -6
- package/dist/gestures/nativeScroll.d.ts.map +1 -1
- package/dist/gestures/nativeScroll.js +7 -52
- package/dist/gestures/wheelSegmenter.d.ts +68 -1
- package/dist/gestures/wheelSegmenter.d.ts.map +1 -1
- package/dist/gestures/wheelSegmenter.js +199 -10
- package/dist/hooks/StackItemScrollRegion.d.ts +31 -0
- package/dist/hooks/StackItemScrollRegion.d.ts.map +1 -0
- package/dist/hooks/StackItemScrollRegion.js +40 -0
- package/dist/hooks/computeOverflow.d.ts +2 -0
- package/dist/hooks/computeOverflow.d.ts.map +1 -1
- package/dist/hooks/computeOverflow.js +1 -1
- package/dist/hooks/menuPressGesture.d.ts +133 -21
- package/dist/hooks/menuPressGesture.d.ts.map +1 -1
- package/dist/hooks/menuPressGesture.js +155 -30
- package/dist/hooks/menuPressValues.d.ts +16 -0
- package/dist/hooks/menuPressValues.d.ts.map +1 -0
- package/dist/hooks/menuPressValues.js +18 -0
- package/dist/hooks/useClickableContainer.d.ts +36 -7
- package/dist/hooks/useClickableContainer.d.ts.map +1 -1
- package/dist/hooks/useClickableContainer.js +63 -14
- package/dist/hooks/useFocusTrap.d.ts +10 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +225 -132
- package/dist/hooks/useKeyboardHighlight.d.ts +17 -0
- package/dist/hooks/useKeyboardHighlight.d.ts.map +1 -0
- package/dist/hooks/useKeyboardHighlight.js +38 -0
- package/dist/hooks/useMediaQuery.d.ts +2 -1
- package/dist/hooks/useMediaQuery.d.ts.map +1 -1
- package/dist/hooks/useMediaQuery.js +37 -12
- package/dist/hooks/useMenuPress.d.ts +34 -1
- package/dist/hooks/useMenuPress.d.ts.map +1 -1
- package/dist/hooks/useMenuPress.js +93 -5
- package/dist/hooks/useOverflow.d.ts +10 -0
- package/dist/hooks/useOverflow.d.ts.map +1 -1
- package/dist/hooks/useOverflow.js +214 -23
- package/dist/hooks/usePressFeedback.d.ts +6 -6
- package/dist/hooks/usePressFeedback.js +6 -6
- package/dist/hooks/useScrollRegionProps.d.ts +35 -0
- package/dist/hooks/useScrollRegionProps.d.ts.map +1 -0
- package/dist/hooks/useScrollRegionProps.js +51 -0
- package/dist/i18n/InternationalizationContext.d.ts +6 -0
- package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.d.ts +23 -3
- package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
- package/dist/i18n/InternationalizationProvider.js +8 -3
- package/dist/i18n/generated-english/DateInput/DateInput.generated.d.ts.map +1 -1
- package/dist/i18n/generated-english/DateInput/DateInput.generated.js +0 -1
- package/dist/i18n/generated-english/DateInput/useTypedDate.generated.d.ts +8 -0
- package/dist/i18n/generated-english/DateInput/useTypedDate.generated.d.ts.map +1 -0
- package/dist/i18n/generated-english/DateInput/useTypedDate.generated.js +16 -0
- package/dist/i18n/generated-english/DateTimeInput/DateTimeInput.generated.d.ts.map +1 -1
- package/dist/i18n/generated-english/DateTimeInput/DateTimeInput.generated.js +0 -1
- package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.d.ts +8 -0
- package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.d.ts.map +1 -0
- package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.js +12 -0
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +5 -0
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +5 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +1 -0
- package/dist/i18n/useCalendarSystem.d.ts +19 -0
- package/dist/i18n/useCalendarSystem.d.ts.map +1 -0
- package/dist/i18n/useCalendarSystem.js +61 -0
- package/dist/internal/calendar-system.d.ts +18 -0
- package/dist/internal/calendar-system.d.ts.map +1 -0
- package/dist/internal/calendar-system.js +19 -0
- package/dist/internal/spinner-rotor.d.ts +16 -0
- package/dist/internal/spinner-rotor.d.ts.map +1 -0
- package/dist/internal/spinner-rotor.js +16 -0
- package/dist/internal/touch.d.ts +20 -2
- package/dist/internal/touch.d.ts.map +1 -1
- package/dist/internal/touch.js +29 -3
- package/dist/motion/animator.d.ts +5 -5
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +7 -6
- package/dist/motion/carryAnimations.d.ts +58 -0
- package/dist/motion/carryAnimations.d.ts.map +1 -0
- package/dist/motion/carryAnimations.js +305 -0
- package/dist/motion/transientCopy.d.ts +4 -2
- package/dist/motion/transientCopy.d.ts.map +1 -1
- package/dist/motion/transientCopy.js +34 -5
- package/dist/motion/uikit/gestures.d.ts +41 -0
- package/dist/motion/uikit/gestures.d.ts.map +1 -1
- package/dist/motion/uikit/gestures.js +25 -0
- package/dist/motion/uikit/index.d.ts +1 -1
- package/dist/motion/uikit/index.d.ts.map +1 -1
- package/dist/motion/uikit/index.js +1 -1
- package/dist/motion/uikit/timing.d.ts +14 -10
- package/dist/motion/uikit/timing.d.ts.map +1 -1
- package/dist/motion/uikit/timing.js +7 -5
- package/dist/privateAttributes/menuPressLit.stylex.d.ts +52 -0
- package/dist/privateAttributes/menuPressLit.stylex.d.ts.map +1 -0
- package/dist/privateAttributes/menuPressLit.stylex.js +99 -0
- package/dist/privateAttributes/press.stylex.d.ts +142 -0
- package/dist/privateAttributes/press.stylex.d.ts.map +1 -0
- package/dist/privateAttributes/press.stylex.js +101 -0
- package/dist/theme/themeMotion.d.ts +3 -2
- package/dist/theme/themeMotion.d.ts.map +1 -1
- package/dist/theme/themeMotion.js +3 -2
- package/dist/theme/tokens.stylex.d.ts +2 -2
- package/dist/theme/tokens.stylex.js +1 -1
- package/dist/utils/calendarDateParser.d.ts +110 -0
- package/dist/utils/calendarDateParser.d.ts.map +1 -0
- package/dist/utils/calendarDateParser.js +1225 -0
- package/dist/utils/calendarSystem.d.ts +176 -0
- package/dist/utils/calendarSystem.d.ts.map +1 -0
- package/dist/utils/calendarSystem.js +569 -0
- package/dist/utils/coarsePointer.d.ts +5 -0
- package/dist/utils/coarsePointer.d.ts.map +1 -1
- package/dist/utils/coarsePointer.js +22 -13
- package/dist/utils/flatTree.d.ts +6 -3
- package/dist/utils/flatTree.d.ts.map +1 -1
- package/dist/utils/flatTree.js +13 -3
- package/dist/utils/focusReturn.d.ts +34 -13
- package/dist/utils/focusReturn.d.ts.map +1 -1
- package/dist/utils/focusReturn.js +64 -17
- package/dist/utils/hitArea.d.ts +8 -1
- package/dist/utils/hitArea.d.ts.map +1 -1
- package/dist/utils/hitArea.js +99 -9
- package/dist/utils/inputPresentation.d.ts +9 -1
- package/dist/utils/inputPresentation.d.ts.map +1 -1
- package/dist/utils/inputPresentation.js +15 -1
- package/dist/utils/inputStream.d.ts +14 -1
- package/dist/utils/inputStream.d.ts.map +1 -1
- package/dist/utils/inputStream.js +40 -9
- package/dist/utils/interactionOverlay.stylex.d.ts +5 -9
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
- package/dist/utils/interactionOverlay.stylex.js +29 -31
- package/dist/utils/plainDate.d.ts +38 -7
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +92 -18
- package/dist/utils/pressFeedback.d.ts +10 -2
- package/dist/utils/pressFeedback.d.ts.map +1 -1
- package/dist/utils/pressFeedback.js +40 -15
- package/dist/utils/pressGesture.d.ts +12 -6
- package/dist/utils/pressGesture.d.ts.map +1 -1
- package/dist/utils/pressGesture.js +26 -8
- package/dist/utils/scrollView.d.ts +25 -0
- package/dist/utils/scrollView.d.ts.map +1 -0
- package/dist/utils/scrollView.js +108 -0
- package/dist/utils/selectionLock.d.ts.map +1 -1
- package/dist/utils/selectionLock.js +1 -10
- package/dist/utils/touchHitArea.d.ts +30 -0
- package/dist/utils/touchHitArea.d.ts.map +1 -0
- package/dist/utils/touchHitArea.js +167 -0
- package/dist/utils/touchHitArea.stylex.d.ts +38 -0
- package/dist/utils/touchHitArea.stylex.d.ts.map +1 -0
- package/dist/utils/touchHitArea.stylex.js +48 -0
- package/dist/utils/triggerFocus.d.ts +5 -0
- package/dist/utils/triggerFocus.d.ts.map +1 -1
- package/dist/utils/triggerFocus.js +9 -2
- package/locales/en.json +21 -1
- package/locales/pseudo.json +15 -0
- package/package.json +15 -4
- package/src/AppShell/observeMainOverflow.ts +9 -6
- package/src/BottomSheet/BottomSheet.tsx +45 -3
- package/src/BottomSheet/BottomSheetPanel.tsx +64 -7
- package/src/BottomSheet/bottomSheetStack.ts +4 -3
- package/src/BottomSheet/useSheetGestures.ts +83 -20
- package/src/Calendar/Calendar.doc.mjs +76 -6
- package/src/Calendar/Calendar.tsx +123 -104
- package/src/Calendar/getInitialFocusDate.ts +22 -8
- package/src/Calendar/hooks/useCalendarDays.ts +89 -63
- package/src/Calendar/hooks/useCalendarNavigation.ts +68 -26
- package/src/CheckboxInput/CheckboxInput.doc.mjs +5 -4
- package/src/CheckboxInput/CheckboxInput.tsx +105 -20
- package/src/CheckboxInput/CheckboxRowPressContext.ts +22 -0
- package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
- package/src/CheckboxList/CheckboxListItem.doc.mjs +3 -3
- package/src/CheckboxList/CheckboxListItem.tsx +35 -14
- package/src/ClickableCard/ClickableCard.tsx +8 -1
- package/src/ContextMenu/ContextMenu.tsx +2 -0
- package/src/DateInput/DateInput.doc.mjs +45 -12
- package/src/DateInput/DateInput.tsx +165 -179
- package/src/DateInput/MonthScroller.tsx +39 -37
- package/src/DateInput/MonthYearWheels.tsx +68 -47
- package/src/DateInput/PickerWheel.tsx +7 -2
- package/src/DateInput/TouchDateField.tsx +45 -17
- package/src/DateInput/monthGeometry.ts +110 -8
- package/src/DateInput/useCalendarPresentation.ts +64 -0
- package/src/DateInput/useTypedDate.ts +469 -0
- package/src/DateInput/wheelStrip.ts +2 -2
- package/src/DateRangeInput/DateRangeInput.doc.mjs +9 -0
- package/src/DateRangeInput/DateRangeInput.tsx +43 -9
- package/src/DateTimeInput/DateTimeInput.doc.mjs +42 -9
- package/src/DateTimeInput/DateTimeInput.tsx +138 -148
- package/src/DateTimeInput/TouchDateTimeField.tsx +31 -16
- package/src/Dialog/Dialog.doc.mjs +1 -1
- package/src/Dialog/Dialog.tsx +14 -2
- package/src/Drawer/Drawer.doc.mjs +1 -1
- package/src/Drawer/useDrawerDialogPresence.ts +9 -2
- package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -2
- package/src/DropdownMenu/DropdownMenu.tsx +31 -7
- package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +5 -1
- package/src/DropdownMenu/DropdownMenuItem.tsx +8 -4
- package/src/DropdownMenu/DropdownMenuRadioItem.tsx +5 -1
- package/src/DropdownMenu/DropdownMenuSubMenu.tsx +5 -1
- package/src/FileInput/FileInput.tsx +16 -2
- package/src/HoverCard/useHoverCard.tsx +3 -1
- package/src/Icon/useIcon.doc.mjs +94 -0
- package/src/InfoTip/InfoTip.doc.mjs +26 -2
- package/src/InfoTip/InfoTip.tsx +6 -27
- package/src/InputGroup/InputGroup.doc.mjs +4 -3
- package/src/InputGroup/InputGroup.tsx +4 -3
- package/src/InputGroup/InputGroupText.doc.mjs +45 -3
- package/src/InputGroup/InputGroupText.tsx +2 -1
- package/src/InputGroup/groupStyles.ts +3 -1
- package/src/Item/Item.tsx +139 -35
- package/src/Item/ItemListRowContext.tsx +18 -0
- package/src/Layer/holdEntranceInput.ts +84 -0
- package/src/Layer/inputHold.ts +734 -0
- package/src/Layer/outsidePress.ts +18 -1
- package/src/Layer/preserveAnimations.ts +12 -275
- package/src/Layer/useBackdropPress.ts +41 -1
- package/src/Layer/useLayer.tsx +77 -4
- package/src/Layer/useTouchTrigger.ts +4 -0
- package/src/Layout/LayoutContent.doc.mjs +6 -3
- package/src/Layout/LayoutContent.tsx +10 -4
- package/src/Layout/LayoutPanel.doc.mjs +14 -11
- package/src/Layout/LayoutPanel.tsx +113 -16
- package/src/Lightbox/Lightbox.tsx +4 -0
- package/src/List/List.doc.mjs +10 -1
- package/src/List/List.tsx +5 -0
- package/src/List/ListItem.tsx +63 -8
- package/src/Markdown/parser.ts +65 -42
- package/src/MetadataList/MetadataList.tsx +1 -1
- package/src/MobileNav/MobileNav.doc.mjs +3 -3
- package/src/MobileNav/MobileNav.tsx +39 -1
- package/src/MoreMenu/MoreMenu.doc.mjs +2 -4
- package/src/MoreMenu/MoreMenu.tsx +5 -3
- package/src/MultiSelector/MultiSelector.tsx +7 -17
- package/src/NumberInput/NumberInput.doc.mjs +1 -1
- package/src/NumberInput/NumberInput.tsx +259 -11
- package/src/OverflowList/OverflowList.tsx +15 -9
- package/src/Popover/usePopover.tsx +1 -0
- package/src/PowerSearch/PowerSearch.doc.mjs +3 -3
- package/src/PowerSearch/PowerSearch.tsx +20 -3
- package/src/PowerSearch/PowerSearchBottomSheet.tsx +4 -1
- package/src/PowerSearch/PowerSearchToken.tsx +3 -0
- package/src/PowerSearch/formatFilterValue.ts +21 -11
- package/src/PowerSearch/formatTokenValue.ts +7 -1
- package/src/RadioList/RadioListItem.doc.mjs +3 -2
- package/src/RadioList/RadioListItem.tsx +16 -6
- package/src/Resizable/Resizable.doc.mjs +40 -12
- package/src/Resizable/ResizeHandle.tsx +68 -6
- package/src/Resizable/resizablePane.ts +179 -0
- package/src/Resizable/useResizable.ts +15 -0
- package/src/SegmentedControl/useSegmentedSelectionMotion.ts +3 -3
- package/src/SelectableCard/SelectableCard.tsx +8 -1
- package/src/Selector/Selector.tsx +83 -8
- package/src/SideNav/SideNav.doc.mjs +2 -2
- package/src/SideNav/SideNav.tsx +87 -12
- package/src/Slider/sliderTouchController.ts +2 -2
- package/src/Spinner/Spinner.tsx +7 -89
- package/src/Spinner/index.ts +1 -5
- package/src/Spinner/spinnerRotor.ts +113 -0
- package/src/Stack/Stack.doc.mjs +1 -1
- package/src/Stack/StackItem.tsx +27 -13
- package/src/Switch/Switch.tsx +7 -6
- package/src/Switch/useSwitchTouch.ts +4 -4
- package/src/TabList/Tab.tsx +5 -1
- package/src/Table/plugins/sortable/useTableSortable.tsx +1 -1
- package/src/Timestamp/Timestamp.doc.mjs +3 -3
- package/src/Timestamp/Timestamp.tsx +13 -8
- package/src/Timestamp/formatInstant.ts +49 -28
- package/src/Timestamp/tooltipEntries.ts +7 -3
- package/src/Token/Token.tsx +18 -1
- package/src/Token/TokenLink.tsx +7 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +3 -3
- package/src/Tokenizer/Tokenizer.tsx +252 -115
- package/src/Tooltip/useTooltip.tsx +180 -80
- package/src/TreeList/TreeListItem.tsx +36 -2
- package/src/Typeahead/BaseTypeahead.tsx +2 -0
- package/src/animator/createAnimator.ts +3 -3
- package/src/gestures/GestureHost.ts +21 -5
- package/src/gestures/PanGestureRecognizer.ts +19 -2
- package/src/gestures/README.md +14 -5
- package/src/gestures/ScreenEdgePanGestureRecognizer.ts +6 -1
- package/src/gestures/nativeScroll.ts +12 -68
- package/src/gestures/wheelSegmenter.ts +243 -10
- package/src/hooks/StackItemScrollRegion.tsx +57 -0
- package/src/hooks/computeOverflow.ts +1 -1
- package/src/hooks/menuPressGesture.ts +244 -38
- package/src/hooks/menuPressValues.ts +18 -0
- package/src/hooks/useClickableContainer.doc.mjs +8 -2
- package/src/hooks/useClickableContainer.ts +93 -15
- package/src/hooks/useFocusTrap.ts +268 -151
- package/src/hooks/useKeyboardHighlight.ts +71 -0
- package/src/hooks/useMediaQuery.ts +41 -12
- package/src/hooks/useMenuPress.ts +118 -11
- package/src/hooks/useOverflow.ts +321 -75
- package/src/hooks/usePressFeedback.doc.mjs +3 -3
- package/src/hooks/usePressFeedback.ts +6 -6
- package/src/hooks/useScrollRegionProps.ts +76 -0
- package/src/i18n/InternationalizationContext.ts +6 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +29 -1
- package/src/i18n/InternationalizationProvider.tsx +35 -3
- package/src/i18n/generated-english/DateInput/DateInput.generated.ts +0 -1
- package/src/i18n/generated-english/DateInput/useTypedDate.generated.ts +17 -0
- package/src/i18n/generated-english/DateTimeInput/DateTimeInput.generated.ts +0 -1
- package/src/i18n/generated-english/hooks/useScrollRegionProps.generated.ts +13 -0
- package/src/i18n/generated-locales/en.generated.ts +7 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +7 -0
- package/src/i18n/index.ts +2 -0
- package/src/i18n/useCalendarSystem.ts +95 -0
- package/src/internal/calendar-system.ts +26 -0
- package/src/internal/spinner-rotor.ts +20 -0
- package/src/internal/touch.ts +43 -2
- package/src/motion/MEASUREMENTS.md +11 -0
- package/src/motion/README.md +3 -3
- package/src/motion/animator.ts +7 -7
- package/src/motion/carryAnimations.ts +389 -0
- package/src/motion/transientCopy.ts +45 -5
- package/src/motion/uikit/gestures.ts +22 -0
- package/src/motion/uikit/index.ts +1 -0
- package/src/motion/uikit/timing.ts +7 -5
- package/src/privateAttributes/menuPressLit.stylex.ts +104 -0
- package/src/privateAttributes/press.stylex.ts +261 -0
- package/src/theme/themeMotion.ts +3 -2
- package/src/theme/tokens.stylex.ts +1 -1
- package/src/utils/calendarDateParser.ts +1385 -0
- package/src/utils/calendarSystem.ts +832 -0
- package/src/utils/coarsePointer.ts +27 -14
- package/src/utils/flatTree.ts +15 -3
- package/src/utils/focusReturn.ts +78 -18
- package/src/utils/hitArea.ts +138 -9
- package/src/utils/inputPresentation.ts +21 -1
- package/src/utils/inputStream.ts +47 -10
- package/src/utils/interactionOverlay.stylex.ts +19 -22
- package/src/utils/plainDate.ts +130 -19
- package/src/utils/pressFeedback.ts +46 -14
- package/src/utils/pressGesture.ts +35 -9
- package/src/utils/scrollView.ts +135 -0
- package/src/utils/selectionLock.ts +5 -10
- package/src/utils/touchHitArea.stylex.ts +56 -0
- package/src/utils/touchHitArea.ts +177 -0
- package/src/utils/triggerFocus.ts +17 -4
|
@@ -0,0 +1,832 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file calendarSystem.ts
|
|
5
|
+
* @input A calendar identifier and Gregorian PlainDates
|
|
6
|
+
* @output Calendar months located by their Gregorian days, their year and
|
|
7
|
+
* month numbers, month and year steps, dates from calendar fields,
|
|
8
|
+
* availability of each calendar, and calendar labels and digits
|
|
9
|
+
* @position Shared date utility; read by the i18n calendar resolution, by
|
|
10
|
+
* the date components, and by Calendar's public hooks. Values stay Gregorian PlainDates. Temporal owns the arithmetic of
|
|
11
|
+
* every calendar whose months are not Gregorian.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type {Locale} from '../i18n/types';
|
|
15
|
+
import type {PlainDate} from './dateTypes';
|
|
16
|
+
import {
|
|
17
|
+
DATE_FORMAT_MONTH_ONLY,
|
|
18
|
+
dateTimeFormatAtCall,
|
|
19
|
+
dateTimeFormatFor,
|
|
20
|
+
plainDateAddDays,
|
|
21
|
+
plainDateAddMonths,
|
|
22
|
+
plainDateFormatDayNumber,
|
|
23
|
+
plainDateFormatStandaloneMonthYear,
|
|
24
|
+
plainDateFormatToParts,
|
|
25
|
+
plainDateFromDate,
|
|
26
|
+
plainDateFromInstant,
|
|
27
|
+
plainDateIsInRange,
|
|
28
|
+
getDaysInMonth,
|
|
29
|
+
} from './plainDate';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A calendar system that date components can show: the calendars that
|
|
33
|
+
* ECMA-402 and Temporal require. Values stay Gregorian ISO dates in every
|
|
34
|
+
* calendar.
|
|
35
|
+
*/
|
|
36
|
+
export type CalendarSystem =
|
|
37
|
+
| 'gregory'
|
|
38
|
+
| 'iso8601'
|
|
39
|
+
| 'buddhist'
|
|
40
|
+
| 'roc'
|
|
41
|
+
| 'japanese'
|
|
42
|
+
| 'persian'
|
|
43
|
+
| 'indian'
|
|
44
|
+
| 'hebrew'
|
|
45
|
+
| 'chinese'
|
|
46
|
+
| 'dangi'
|
|
47
|
+
| 'coptic'
|
|
48
|
+
| 'ethiopic'
|
|
49
|
+
| 'ethioaa'
|
|
50
|
+
| 'islamic-civil'
|
|
51
|
+
| 'islamic-tbla'
|
|
52
|
+
| 'islamic-umalqura';
|
|
53
|
+
|
|
54
|
+
// A record, so the compiler checks that it lists every calendar exactly once.
|
|
55
|
+
const KNOWN_CALENDARS: Readonly<Record<CalendarSystem, true>> = {
|
|
56
|
+
gregory: true,
|
|
57
|
+
iso8601: true,
|
|
58
|
+
buddhist: true,
|
|
59
|
+
roc: true,
|
|
60
|
+
japanese: true,
|
|
61
|
+
persian: true,
|
|
62
|
+
indian: true,
|
|
63
|
+
hebrew: true,
|
|
64
|
+
chinese: true,
|
|
65
|
+
dangi: true,
|
|
66
|
+
coptic: true,
|
|
67
|
+
ethiopic: true,
|
|
68
|
+
ethioaa: true,
|
|
69
|
+
'islamic-civil': true,
|
|
70
|
+
'islamic-tbla': true,
|
|
71
|
+
'islamic-umalqura': true,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const CALENDAR_SYSTEMS = Object.keys(
|
|
75
|
+
KNOWN_CALENDARS,
|
|
76
|
+
) as ReadonlyArray<CalendarSystem>;
|
|
77
|
+
|
|
78
|
+
const GREGORIAN_ALIGNED: ReadonlySet<CalendarSystem> = new Set([
|
|
79
|
+
'gregory',
|
|
80
|
+
'iso8601',
|
|
81
|
+
'buddhist',
|
|
82
|
+
'roc',
|
|
83
|
+
'japanese',
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Whether `<input type="date">` can show the calendar. The native control is
|
|
88
|
+
* Gregorian by specification, so only `gregory` and `iso8601` qualify.
|
|
89
|
+
*/
|
|
90
|
+
export function isGregorianCalendar(calendar: CalendarSystem): boolean {
|
|
91
|
+
return calendar === 'gregory' || calendar === 'iso8601';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Whether the calendar's months and days are the Gregorian ones. */
|
|
95
|
+
export function isGregorianAligned(calendar: CalendarSystem): boolean {
|
|
96
|
+
return GREGORIAN_ALIGNED.has(calendar);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function isCalendarSystem(value: string): value is CalendarSystem {
|
|
100
|
+
return Object.hasOwn(KNOWN_CALENDARS, value);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// The published types must not need the `esnext.temporal` library.
|
|
104
|
+
// This module declares only the Temporal members it reads.
|
|
105
|
+
interface TemporalPlainDate {
|
|
106
|
+
readonly year: number;
|
|
107
|
+
readonly month: number;
|
|
108
|
+
readonly day: number;
|
|
109
|
+
readonly daysInMonth: number;
|
|
110
|
+
readonly monthsInYear: number;
|
|
111
|
+
with(fields: {year?: number; month?: number; day: number}): TemporalPlainDate;
|
|
112
|
+
add(duration: {months?: number; years?: number}): TemporalPlainDate;
|
|
113
|
+
until(
|
|
114
|
+
other: TemporalPlainDate,
|
|
115
|
+
options: {largestUnit: 'months'},
|
|
116
|
+
): {readonly months: number};
|
|
117
|
+
withCalendar(calendar: 'iso8601'): TemporalPlainDate;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface TemporalPlainDateConstructor {
|
|
121
|
+
new (
|
|
122
|
+
isoYear: number,
|
|
123
|
+
isoMonth: number,
|
|
124
|
+
isoDay: number,
|
|
125
|
+
calendar: string,
|
|
126
|
+
): TemporalPlainDate;
|
|
127
|
+
from(
|
|
128
|
+
fields: CalendarDateFields & {calendar: string},
|
|
129
|
+
options: {overflow: 'reject'},
|
|
130
|
+
): TemporalPlainDate;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
interface TemporalNamespace {
|
|
134
|
+
PlainDate: TemporalPlainDateConstructor;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function getTemporal(): TemporalNamespace | undefined {
|
|
138
|
+
const temporal = (globalThis as {Temporal?: Partial<TemporalNamespace>})
|
|
139
|
+
.Temporal;
|
|
140
|
+
return typeof temporal?.PlainDate === 'function'
|
|
141
|
+
? (temporal as TemporalNamespace)
|
|
142
|
+
: undefined;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// The key is the Temporal object, so a polyfill that loads later gets its
|
|
146
|
+
// own probe.
|
|
147
|
+
const supportedCalendars = new WeakMap<object, Map<CalendarSystem, boolean>>();
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Whether this runtime can show the calendar. Gregorian-aligned calendars
|
|
151
|
+
* always can. The others need a `Temporal` that knows the calendar: a
|
|
152
|
+
* polyfill build without non-ISO calendars throws for them.
|
|
153
|
+
*/
|
|
154
|
+
export function isCalendarSystemAvailable(calendar: CalendarSystem): boolean {
|
|
155
|
+
if (isGregorianAligned(calendar)) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
const temporal = getTemporal();
|
|
159
|
+
if (temporal == null) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
let known = supportedCalendars.get(temporal);
|
|
163
|
+
if (known == null) {
|
|
164
|
+
known = new Map();
|
|
165
|
+
supportedCalendars.set(temporal, known);
|
|
166
|
+
}
|
|
167
|
+
let isSupported = known.get(calendar);
|
|
168
|
+
if (isSupported == null) {
|
|
169
|
+
try {
|
|
170
|
+
new temporal.PlainDate(2000, 1, 1, calendar);
|
|
171
|
+
isSupported = true;
|
|
172
|
+
} catch {
|
|
173
|
+
isSupported = false;
|
|
174
|
+
}
|
|
175
|
+
known.set(calendar, isSupported);
|
|
176
|
+
}
|
|
177
|
+
return isSupported;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function inCalendar(
|
|
181
|
+
calendar: CalendarSystem,
|
|
182
|
+
pd: PlainDate,
|
|
183
|
+
): TemporalPlainDate {
|
|
184
|
+
const temporal = getTemporal();
|
|
185
|
+
if (temporal == null) {
|
|
186
|
+
throw new Error(`The "${calendar}" calendar needs Temporal.`);
|
|
187
|
+
}
|
|
188
|
+
return new temporal.PlainDate(pd.year, pd.month, pd.day, calendar);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function toGregorian(date: TemporalPlainDate): PlainDate {
|
|
192
|
+
const iso = date.withCalendar('iso8601');
|
|
193
|
+
return {year: iso.year, month: iso.month, day: iso.day};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** A month of a calendar, located by its first and last Gregorian days. */
|
|
197
|
+
export interface CalendarMonth {
|
|
198
|
+
readonly start: PlainDate;
|
|
199
|
+
readonly end: PlainDate;
|
|
200
|
+
readonly length: number;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function makeMonth(start: PlainDate, length: number): CalendarMonth {
|
|
204
|
+
return {start, end: plainDateAddDays(start, length - 1), length};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function gregorianMonth(year: number, month: number): CalendarMonth {
|
|
208
|
+
return makeMonth({year, month, day: 1}, getDaysInMonth(year, month));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function temporalMonth(firstDay: TemporalPlainDate): CalendarMonth {
|
|
212
|
+
return makeMonth(toGregorian(firstDay), firstDay.daysInMonth);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** The day of the calendar month that a Gregorian date falls on. */
|
|
216
|
+
export function calendarDayOfMonth(
|
|
217
|
+
calendar: CalendarSystem,
|
|
218
|
+
pd: PlainDate,
|
|
219
|
+
): number {
|
|
220
|
+
return isGregorianAligned(calendar) ? pd.day : inCalendar(calendar, pd).day;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/** The calendar month that contains a Gregorian date. */
|
|
224
|
+
export function calendarMonthOf(
|
|
225
|
+
calendar: CalendarSystem,
|
|
226
|
+
pd: PlainDate,
|
|
227
|
+
): CalendarMonth {
|
|
228
|
+
if (isGregorianAligned(calendar)) {
|
|
229
|
+
return gregorianMonth(pd.year, pd.month);
|
|
230
|
+
}
|
|
231
|
+
return temporalMonth(inCalendar(calendar, pd).with({day: 1}));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* A calendar month by its year and its position in that year, as
|
|
236
|
+
* `Temporal.PlainDate` numbers them: month 13 exists in a Hebrew leap year.
|
|
237
|
+
*/
|
|
238
|
+
export interface CalendarYearMonth {
|
|
239
|
+
readonly year: number;
|
|
240
|
+
readonly month: number;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Temporal counts the years of these Gregorian-aligned calendars from another
|
|
244
|
+
// epoch: 2026 is 2569 in `buddhist` and 115 in `roc`.
|
|
245
|
+
const GREGORIAN_YEAR_OFFSETS: Partial<Record<CalendarSystem, number>> = {
|
|
246
|
+
buddhist: 543,
|
|
247
|
+
roc: -1911,
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
/** The year and month numbers of a calendar month. */
|
|
251
|
+
export function calendarYearMonthOf(
|
|
252
|
+
calendar: CalendarSystem,
|
|
253
|
+
month: CalendarMonth,
|
|
254
|
+
): CalendarYearMonth {
|
|
255
|
+
if (isGregorianAligned(calendar)) {
|
|
256
|
+
return {
|
|
257
|
+
year: month.start.year + (GREGORIAN_YEAR_OFFSETS[calendar] ?? 0),
|
|
258
|
+
month: month.start.month,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
const {year, month: monthOfYear} = inCalendar(calendar, month.start);
|
|
262
|
+
return {year, month: monthOfYear};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* The calendar month with these year and month numbers. A month past the end
|
|
267
|
+
* of its year becomes the last month of that year, as Temporal constrains it.
|
|
268
|
+
*/
|
|
269
|
+
export function calendarMonthFromYearMonth(
|
|
270
|
+
calendar: CalendarSystem,
|
|
271
|
+
{year, month}: CalendarYearMonth,
|
|
272
|
+
): CalendarMonth {
|
|
273
|
+
if (isGregorianAligned(calendar)) {
|
|
274
|
+
return gregorianMonth(
|
|
275
|
+
year - (GREGORIAN_YEAR_OFFSETS[calendar] ?? 0),
|
|
276
|
+
month,
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
// `with` replaces the year and month of any date in the calendar.
|
|
280
|
+
return temporalMonth(
|
|
281
|
+
inCalendar(calendar, {year: 2000, month: 1, day: 1}).with({
|
|
282
|
+
year,
|
|
283
|
+
month,
|
|
284
|
+
day: 1,
|
|
285
|
+
}),
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** The calendar month `n` months after `month`, or before it when negative. */
|
|
290
|
+
export function calendarAddMonths(
|
|
291
|
+
calendar: CalendarSystem,
|
|
292
|
+
month: CalendarMonth,
|
|
293
|
+
n: number,
|
|
294
|
+
): CalendarMonth {
|
|
295
|
+
if (n === 0) {
|
|
296
|
+
return month;
|
|
297
|
+
}
|
|
298
|
+
if (isGregorianAligned(calendar)) {
|
|
299
|
+
const {year, month: monthOfYear} = plainDateAddMonths(month.start, n);
|
|
300
|
+
return gregorianMonth(year, monthOfYear);
|
|
301
|
+
}
|
|
302
|
+
return temporalMonth(inCalendar(calendar, month.start).add({months: n}));
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Moves a date by `n` calendar months. It keeps the day of the month and
|
|
307
|
+
* clamps it to the length of the target month.
|
|
308
|
+
*/
|
|
309
|
+
export function calendarShiftMonths(
|
|
310
|
+
calendar: CalendarSystem,
|
|
311
|
+
pd: PlainDate,
|
|
312
|
+
n: number,
|
|
313
|
+
): PlainDate {
|
|
314
|
+
if (isGregorianAligned(calendar)) {
|
|
315
|
+
return plainDateAddMonths(pd, n);
|
|
316
|
+
}
|
|
317
|
+
return toGregorian(inCalendar(calendar, pd).add({months: n}));
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Moves a date by `n` calendar years, to the same month of the target year.
|
|
322
|
+
* It clamps the day of the month. A leap month that the target year does not
|
|
323
|
+
* have becomes its common counterpart, because Temporal keeps the month code
|
|
324
|
+
* and constrains it.
|
|
325
|
+
*/
|
|
326
|
+
export function calendarShiftYears(
|
|
327
|
+
calendar: CalendarSystem,
|
|
328
|
+
pd: PlainDate,
|
|
329
|
+
n: number,
|
|
330
|
+
): PlainDate {
|
|
331
|
+
if (isGregorianAligned(calendar)) {
|
|
332
|
+
return plainDateAddMonths(pd, n * 12);
|
|
333
|
+
}
|
|
334
|
+
return toGregorian(inCalendar(calendar, pd).add({years: n}));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** Whether a Gregorian date falls inside a calendar month. */
|
|
338
|
+
export function isInCalendarMonth(
|
|
339
|
+
pd: PlainDate,
|
|
340
|
+
month: CalendarMonth,
|
|
341
|
+
): boolean {
|
|
342
|
+
return plainDateIsInRange(pd, [month.start, month.end]);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* The day that names a calendar month: its middle day. In the Japanese
|
|
347
|
+
* calendar an era can start inside a month, and most days of that month then
|
|
348
|
+
* belong to the era of its middle day.
|
|
349
|
+
*/
|
|
350
|
+
export function calendarMonthLabelDay(month: CalendarMonth): PlainDate {
|
|
351
|
+
return plainDateAddDays(month.start, Math.floor(month.length / 2));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* The stand-alone month and year label of a calendar month, such as
|
|
356
|
+
* "Aban 1405 AP", named by `calendarMonthLabelDay`. When `day` is given and the
|
|
357
|
+
* month spans an era change, it formats that day instead, clamped to the
|
|
358
|
+
* month, so January 1989 reads 昭和64年1月 on the 3rd and 平成元年1月 on the
|
|
359
|
+
* 22nd.
|
|
360
|
+
*/
|
|
361
|
+
export function formatCalendarMonthLabel(
|
|
362
|
+
calendar: CalendarSystem,
|
|
363
|
+
month: CalendarMonth,
|
|
364
|
+
locale: Locale,
|
|
365
|
+
day?: number,
|
|
366
|
+
): string {
|
|
367
|
+
const labelDay =
|
|
368
|
+
day != null && calendarMonthSpansEras(calendar, month, locale)
|
|
369
|
+
? plainDateAddDays(
|
|
370
|
+
month.start,
|
|
371
|
+
Math.min(Math.max(day, 1), month.length) - 1,
|
|
372
|
+
)
|
|
373
|
+
: calendarMonthLabelDay(month);
|
|
374
|
+
return plainDateFormatStandaloneMonthYear(
|
|
375
|
+
labelDay,
|
|
376
|
+
locale,
|
|
377
|
+
labelCalendar(calendar),
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/** Whether the first and last days of a calendar month fall in different eras. */
|
|
382
|
+
function calendarMonthSpansEras(
|
|
383
|
+
calendar: CalendarSystem,
|
|
384
|
+
month: CalendarMonth,
|
|
385
|
+
locale: Locale,
|
|
386
|
+
): boolean {
|
|
387
|
+
return (
|
|
388
|
+
!isGregorianCalendar(calendar) &&
|
|
389
|
+
eraYearAt(calendar, month.start, locale).era !==
|
|
390
|
+
eraYearAt(calendar, month.end, locale).era
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Intl has no month names for `iso8601`. Labels use `gregory`, which has the
|
|
395
|
+
// same months and days.
|
|
396
|
+
function labelCalendar(calendar: CalendarSystem): CalendarSystem {
|
|
397
|
+
return calendar === 'iso8601' ? 'gregory' : calendar;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function formatToParts(
|
|
401
|
+
calendar: CalendarSystem,
|
|
402
|
+
pd: PlainDate,
|
|
403
|
+
options: Intl.DateTimeFormatOptions,
|
|
404
|
+
locale: Locale,
|
|
405
|
+
): Intl.DateTimeFormatPart[] {
|
|
406
|
+
return plainDateFormatToParts(pd, {...options, calendar}, locale);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const MONTH_PART_TYPES: ReadonlySet<string> = new Set([
|
|
410
|
+
'era',
|
|
411
|
+
'year',
|
|
412
|
+
'relatedYear',
|
|
413
|
+
'yearName',
|
|
414
|
+
'month',
|
|
415
|
+
]);
|
|
416
|
+
|
|
417
|
+
function monthPartsKey(parts: Intl.DateTimeFormatPart[]): string {
|
|
418
|
+
return parts
|
|
419
|
+
.filter(part => MONTH_PART_TYPES.has(part.type))
|
|
420
|
+
.map(part => part.value)
|
|
421
|
+
.join('|');
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Formats a Gregorian date in the calendar, such as "Friday, Aban 8, 1405 AP".
|
|
426
|
+
* The label always names the month and day that the grid shows. Intl and the
|
|
427
|
+
* runtime's Temporal can disagree on where a month of the Chinese or Dangi
|
|
428
|
+
* calendar starts; the label then takes its month and year from the middle of
|
|
429
|
+
* the Temporal month, and its day from Temporal. With `relatedYear`, a
|
|
430
|
+
* Chinese or Dangi year that the locale names only by its place in the 60-year
|
|
431
|
+
* cycle becomes the related Gregorian year.
|
|
432
|
+
*/
|
|
433
|
+
export function formatCalendarDate(
|
|
434
|
+
calendar: CalendarSystem,
|
|
435
|
+
pd: PlainDate,
|
|
436
|
+
options: Intl.DateTimeFormatOptions,
|
|
437
|
+
locale: Locale,
|
|
438
|
+
labelOptions?: {readonly relatedYear?: boolean},
|
|
439
|
+
): string {
|
|
440
|
+
return joinParts(
|
|
441
|
+
formatCalendarDateToParts(calendar, pd, options, locale, labelOptions),
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/** The parts of `formatCalendarDate`'s label. */
|
|
446
|
+
export function formatCalendarDateToParts(
|
|
447
|
+
calendar: CalendarSystem,
|
|
448
|
+
pd: PlainDate,
|
|
449
|
+
options: Intl.DateTimeFormatOptions,
|
|
450
|
+
locale: Locale,
|
|
451
|
+
{relatedYear = false}: {readonly relatedYear?: boolean} = {},
|
|
452
|
+
): Intl.DateTimeFormatPart[] {
|
|
453
|
+
const parts = formatToParts(labelCalendar(calendar), pd, options, locale);
|
|
454
|
+
const fixed = withTemporalDay(calendar, pd, parts, options, locale);
|
|
455
|
+
return relatedYear
|
|
456
|
+
? withRelatedYear(calendar, pd, fixed, options, locale)
|
|
457
|
+
: fixed;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
function withRelatedYear(
|
|
461
|
+
calendar: CalendarSystem,
|
|
462
|
+
pd: PlainDate,
|
|
463
|
+
parts: Intl.DateTimeFormatPart[],
|
|
464
|
+
options: Intl.DateTimeFormatOptions,
|
|
465
|
+
locale: Locale,
|
|
466
|
+
): Intl.DateTimeFormatPart[] {
|
|
467
|
+
if (
|
|
468
|
+
(calendar !== 'chinese' && calendar !== 'dangi') ||
|
|
469
|
+
!isCalendarSystemAvailable(calendar) ||
|
|
470
|
+
parts.some(part => (part.type as string) === 'relatedYear')
|
|
471
|
+
) {
|
|
472
|
+
return parts;
|
|
473
|
+
}
|
|
474
|
+
const {numberingSystem} = dateTimeFormatFor(locale, {
|
|
475
|
+
...options,
|
|
476
|
+
calendar,
|
|
477
|
+
timeZone: 'UTC',
|
|
478
|
+
}).resolvedOptions();
|
|
479
|
+
const {year} = inCalendar(calendar, pd);
|
|
480
|
+
const value = plainDateFormatDayNumber(year, locale, numberingSystem);
|
|
481
|
+
return parts.map(part =>
|
|
482
|
+
/^year(Name)?$/.test(part.type) ? {...part, value} : part,
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// Returns `parts` itself where Intl already names Temporal's month and day.
|
|
487
|
+
function withTemporalDay(
|
|
488
|
+
calendar: CalendarSystem,
|
|
489
|
+
pd: PlainDate,
|
|
490
|
+
parts: Intl.DateTimeFormatPart[],
|
|
491
|
+
options: Intl.DateTimeFormatOptions,
|
|
492
|
+
locale: Locale,
|
|
493
|
+
): Intl.DateTimeFormatPart[] {
|
|
494
|
+
if (isGregorianAligned(calendar) || !isCalendarSystemAvailable(calendar)) {
|
|
495
|
+
return parts;
|
|
496
|
+
}
|
|
497
|
+
const date = inCalendar(calendar, pd);
|
|
498
|
+
const middle = plainDateAddDays(
|
|
499
|
+
pd,
|
|
500
|
+
Math.floor(date.daysInMonth / 2) - (date.day - 1),
|
|
501
|
+
);
|
|
502
|
+
const middleParts = formatToParts(calendar, middle, options, locale);
|
|
503
|
+
const intlDay = formatToParts(
|
|
504
|
+
calendar,
|
|
505
|
+
pd,
|
|
506
|
+
{day: 'numeric'},
|
|
507
|
+
'en-u-nu-latn',
|
|
508
|
+
).find(part => part.type === 'day')?.value;
|
|
509
|
+
if (
|
|
510
|
+
Number(intlDay) === date.day &&
|
|
511
|
+
monthPartsKey(parts) === monthPartsKey(middleParts)
|
|
512
|
+
) {
|
|
513
|
+
return parts;
|
|
514
|
+
}
|
|
515
|
+
const {numberingSystem} = dateTimeFormatFor(locale, {
|
|
516
|
+
...options,
|
|
517
|
+
calendar,
|
|
518
|
+
timeZone: 'UTC',
|
|
519
|
+
}).resolvedOptions();
|
|
520
|
+
const middleValues = new Map(
|
|
521
|
+
middleParts.map(part => [part.type, part.value]),
|
|
522
|
+
);
|
|
523
|
+
return parts.map(part =>
|
|
524
|
+
part.type === 'day'
|
|
525
|
+
? {
|
|
526
|
+
...part,
|
|
527
|
+
value: plainDateFormatDayNumber(date.day, locale, numberingSystem),
|
|
528
|
+
}
|
|
529
|
+
: MONTH_PART_TYPES.has(part.type)
|
|
530
|
+
? {...part, value: middleValues.get(part.type) ?? part.value}
|
|
531
|
+
: part,
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Formats an instant as `formatCalendarDate` formats the day it falls on in
|
|
537
|
+
* `timeZone`, the host's zone when omitted. Intl writes any time of day that
|
|
538
|
+
* `options` asks for.
|
|
539
|
+
*/
|
|
540
|
+
export function formatCalendarInstant(
|
|
541
|
+
calendar: CalendarSystem,
|
|
542
|
+
instant: Date,
|
|
543
|
+
options: Intl.DateTimeFormatOptions,
|
|
544
|
+
locale: Locale,
|
|
545
|
+
timeZone?: string,
|
|
546
|
+
): string {
|
|
547
|
+
return instantLabel(calendar, instant, options, locale, timeZone).text;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Formats the range between two instants. Intl writes the fields that both
|
|
552
|
+
* ends share once. Where Intl names another month or day than Temporal at
|
|
553
|
+
* either end, the range writes each end in full.
|
|
554
|
+
*/
|
|
555
|
+
export function formatCalendarInstantRange(
|
|
556
|
+
calendar: CalendarSystem,
|
|
557
|
+
start: Date,
|
|
558
|
+
end: Date,
|
|
559
|
+
options: Intl.DateTimeFormatOptions,
|
|
560
|
+
locale: Locale,
|
|
561
|
+
timeZone?: string,
|
|
562
|
+
): string {
|
|
563
|
+
const ends = [start, end].map(instant =>
|
|
564
|
+
instantLabel(calendar, instant, options, locale, timeZone),
|
|
565
|
+
);
|
|
566
|
+
const {format} = ends[0];
|
|
567
|
+
if (ends.every(({isIntl}) => isIntl)) {
|
|
568
|
+
return format.formatRange(start, end);
|
|
569
|
+
}
|
|
570
|
+
// Intl writes a range of different years as two full dates around its
|
|
571
|
+
// separator, which gives the separator to put between the two full ends.
|
|
572
|
+
const far = new Date(start.getTime() + 400 * 86_400_000);
|
|
573
|
+
const both = format.formatRange(start, far);
|
|
574
|
+
const [from, to] = [format.format(start), format.format(far)];
|
|
575
|
+
const separator =
|
|
576
|
+
both.startsWith(from) && both.endsWith(to)
|
|
577
|
+
? both.slice(from.length, both.length - to.length)
|
|
578
|
+
: ' – ';
|
|
579
|
+
const [first, last] = ends.map(({text}) => text);
|
|
580
|
+
return first === last ? first : `${first}${separator}${last}`;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
function instantLabel(
|
|
584
|
+
calendar: CalendarSystem,
|
|
585
|
+
instant: Date,
|
|
586
|
+
options: Intl.DateTimeFormatOptions,
|
|
587
|
+
locale: Locale,
|
|
588
|
+
timeZone: string | undefined,
|
|
589
|
+
) {
|
|
590
|
+
const format = dateTimeFormatAtCall(locale, {
|
|
591
|
+
...options,
|
|
592
|
+
...(timeZone === undefined ? {} : {timeZone}),
|
|
593
|
+
calendar: labelCalendar(calendar),
|
|
594
|
+
});
|
|
595
|
+
const parts = format.formatToParts(instant);
|
|
596
|
+
const day =
|
|
597
|
+
timeZone === undefined
|
|
598
|
+
? plainDateFromDate(instant)
|
|
599
|
+
: plainDateFromInstant(instant.getTime(), timeZone);
|
|
600
|
+
const fixed = withTemporalDay(calendar, day, parts, options, locale);
|
|
601
|
+
const isIntl = fixed === parts;
|
|
602
|
+
return {
|
|
603
|
+
format,
|
|
604
|
+
isIntl,
|
|
605
|
+
text: isIntl ? format.format(instant) : joinParts(fixed),
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
function joinParts(parts: Intl.DateTimeFormatPart[]): string {
|
|
610
|
+
return parts.map(part => part.value).join('');
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* The fields of a date written in a calendar. A field gives either `year` or
|
|
615
|
+
* `era` with `eraYear`, and either `monthCode` (such as `M05L` for a leap
|
|
616
|
+
* month) or `month`, the month's position in its year.
|
|
617
|
+
*/
|
|
618
|
+
export interface CalendarDateFields {
|
|
619
|
+
readonly year?: number;
|
|
620
|
+
readonly era?: string;
|
|
621
|
+
readonly eraYear?: number;
|
|
622
|
+
readonly monthCode?: string;
|
|
623
|
+
readonly month?: number;
|
|
624
|
+
readonly day: number;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* The Gregorian date for fields written in a calendar that needs Temporal,
|
|
629
|
+
* or null when the calendar does not have that date. Temporal validates the
|
|
630
|
+
* fields and never adjusts them: 30 Esfand in a common Persian year is null.
|
|
631
|
+
*/
|
|
632
|
+
export function calendarDateFromFields(
|
|
633
|
+
calendar: CalendarSystem,
|
|
634
|
+
fields: CalendarDateFields,
|
|
635
|
+
): PlainDate | null {
|
|
636
|
+
const temporal = getTemporal();
|
|
637
|
+
if (temporal == null) {
|
|
638
|
+
throw new Error(`The "${calendar}" calendar needs Temporal.`);
|
|
639
|
+
}
|
|
640
|
+
try {
|
|
641
|
+
return toGregorian(
|
|
642
|
+
temporal.PlainDate.from({...fields, calendar}, {overflow: 'reject'}),
|
|
643
|
+
);
|
|
644
|
+
} catch (error) {
|
|
645
|
+
if (error instanceof RangeError || error instanceof TypeError) {
|
|
646
|
+
return null;
|
|
647
|
+
}
|
|
648
|
+
throw error;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/** The number of months in the calendar year that contains a date. */
|
|
653
|
+
export function calendarMonthsInYear(
|
|
654
|
+
calendar: CalendarSystem,
|
|
655
|
+
pd: PlainDate,
|
|
656
|
+
): number {
|
|
657
|
+
return isGregorianAligned(calendar)
|
|
658
|
+
? 12
|
|
659
|
+
: inCalendar(calendar, pd).monthsInYear;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* The number of calendar months from the month `from` to the month `to`:
|
|
664
|
+
* positive when `to` is later.
|
|
665
|
+
*/
|
|
666
|
+
export function calendarMonthsBetween(
|
|
667
|
+
calendar: CalendarSystem,
|
|
668
|
+
from: CalendarMonth,
|
|
669
|
+
to: CalendarMonth,
|
|
670
|
+
): number {
|
|
671
|
+
if (isGregorianAligned(calendar)) {
|
|
672
|
+
return (
|
|
673
|
+
(to.start.year - from.start.year) * 12 +
|
|
674
|
+
(to.start.month - from.start.month)
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
return inCalendar(calendar, from.start).until(
|
|
678
|
+
inCalendar(calendar, to.start),
|
|
679
|
+
{largestUnit: 'months'},
|
|
680
|
+
).months;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* The calendar month at a position in a year of the calendar. A
|
|
685
|
+
* Gregorian-aligned calendar counts Gregorian years here; the others count
|
|
686
|
+
* years as {@link calendarYearMonthOf} does.
|
|
687
|
+
*/
|
|
688
|
+
export function calendarMonthOfYear(
|
|
689
|
+
calendar: CalendarSystem,
|
|
690
|
+
year: number,
|
|
691
|
+
month: number,
|
|
692
|
+
): CalendarMonth {
|
|
693
|
+
return isGregorianAligned(calendar)
|
|
694
|
+
? gregorianMonth(year, month)
|
|
695
|
+
: calendarMonthFromYearMonth(calendar, {year, month});
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/** The number of months in a year of the calendar. */
|
|
699
|
+
export function calendarMonthsInCalendarYear(
|
|
700
|
+
calendar: CalendarSystem,
|
|
701
|
+
year: number,
|
|
702
|
+
): number {
|
|
703
|
+
return isGregorianAligned(calendar)
|
|
704
|
+
? 12
|
|
705
|
+
: calendarMonthsInYear(
|
|
706
|
+
calendar,
|
|
707
|
+
calendarMonthOfYear(calendar, year, 1).start,
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* The name of a calendar month, such as "Adar I". It formats the middle day of
|
|
713
|
+
* the month, for the reason {@link formatCalendarMonthLabel} gives.
|
|
714
|
+
*/
|
|
715
|
+
export function formatCalendarMonthName(
|
|
716
|
+
calendar: CalendarSystem,
|
|
717
|
+
month: CalendarMonth,
|
|
718
|
+
locale: Locale,
|
|
719
|
+
): string {
|
|
720
|
+
return formatCalendarDate(
|
|
721
|
+
calendar,
|
|
722
|
+
plainDateAddDays(month.start, Math.floor(month.length / 2)),
|
|
723
|
+
DATE_FORMAT_MONTH_ONLY,
|
|
724
|
+
locale,
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
const YEAR_PART_TYPES: ReadonlySet<string> = new Set([
|
|
729
|
+
'era',
|
|
730
|
+
'year',
|
|
731
|
+
'relatedYear',
|
|
732
|
+
]);
|
|
733
|
+
|
|
734
|
+
/** The era and year parts of a date, as the locale writes them in a long date. */
|
|
735
|
+
function eraYearAt(
|
|
736
|
+
calendar: CalendarSystem,
|
|
737
|
+
pd: PlainDate,
|
|
738
|
+
locale: Locale,
|
|
739
|
+
): {readonly era: string | undefined; readonly label: string | null} {
|
|
740
|
+
const parts = formatToParts(
|
|
741
|
+
calendar,
|
|
742
|
+
pd,
|
|
743
|
+
{era: 'short', year: 'numeric', month: 'long', day: 'numeric'},
|
|
744
|
+
locale,
|
|
745
|
+
);
|
|
746
|
+
const era = parts.find(part => part.type === 'era')?.value;
|
|
747
|
+
const first = parts.findIndex(part => YEAR_PART_TYPES.has(part.type));
|
|
748
|
+
if (first === -1) {
|
|
749
|
+
return {era, label: null};
|
|
750
|
+
}
|
|
751
|
+
let last = first;
|
|
752
|
+
parts.forEach((part, index) => {
|
|
753
|
+
if (YEAR_PART_TYPES.has(part.type)) {
|
|
754
|
+
last = index;
|
|
755
|
+
}
|
|
756
|
+
});
|
|
757
|
+
const label = parts
|
|
758
|
+
.slice(first, last + 1)
|
|
759
|
+
.filter(part => YEAR_PART_TYPES.has(part.type) || part.type === 'literal')
|
|
760
|
+
.map(part => part.value)
|
|
761
|
+
.join('')
|
|
762
|
+
.replace(/\s+/g, ' ')
|
|
763
|
+
.trim();
|
|
764
|
+
return {era, label};
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Whether the first and last days of a year of the calendar fall in different
|
|
769
|
+
* eras, as the Japanese year 2019 does (Heisei, then Reiwa). Only an era change
|
|
770
|
+
* counts: other parts, such as a Chinese related year, can disagree at the
|
|
771
|
+
* edges of a year when Intl and Temporal place a month start one day apart.
|
|
772
|
+
*/
|
|
773
|
+
export function calendarYearSpansEras(
|
|
774
|
+
calendar: CalendarSystem,
|
|
775
|
+
year: number,
|
|
776
|
+
locale: Locale,
|
|
777
|
+
): boolean {
|
|
778
|
+
if (isGregorianCalendar(calendar)) {
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
781
|
+
const months = calendarMonthsInCalendarYear(calendar, year);
|
|
782
|
+
const start = eraYearAt(
|
|
783
|
+
calendar,
|
|
784
|
+
calendarMonthOfYear(calendar, year, 1).start,
|
|
785
|
+
locale,
|
|
786
|
+
);
|
|
787
|
+
const end = eraYearAt(
|
|
788
|
+
calendar,
|
|
789
|
+
calendarMonthOfYear(calendar, year, months).end,
|
|
790
|
+
locale,
|
|
791
|
+
);
|
|
792
|
+
return start.era !== end.era && start.label != null && end.label != null;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* The label of a year of the calendar, with its era where the locale writes
|
|
797
|
+
* one in a date, such as "令和8" in `ja-JP` or "1405 AP" in English. It uses the
|
|
798
|
+
* era and year parts of a long date, in the locale's order and digits, with the
|
|
799
|
+
* text between them. A year that spans an era change takes its era from `at`,
|
|
800
|
+
* a month position and a day clamped to that month, so 2019 reads "平成31" in
|
|
801
|
+
* January and "令和元" in May. Without `at`, and for every other year, the label
|
|
802
|
+
* comes from the middle of the year. Gregorian years are plain numbers.
|
|
803
|
+
*/
|
|
804
|
+
export function formatCalendarYearLabel(
|
|
805
|
+
calendar: CalendarSystem,
|
|
806
|
+
year: number,
|
|
807
|
+
locale: Locale,
|
|
808
|
+
at?: {readonly month: number; readonly day: number},
|
|
809
|
+
): string {
|
|
810
|
+
if (isGregorianCalendar(calendar)) {
|
|
811
|
+
return String(year);
|
|
812
|
+
}
|
|
813
|
+
const months = calendarMonthsInCalendarYear(calendar, year);
|
|
814
|
+
if (at != null && calendarYearSpansEras(calendar, year, locale)) {
|
|
815
|
+
const month = calendarMonthOfYear(
|
|
816
|
+
calendar,
|
|
817
|
+
year,
|
|
818
|
+
Math.min(Math.max(at.month, 1), months),
|
|
819
|
+
);
|
|
820
|
+
const day = Math.min(Math.max(at.day, 1), month.length);
|
|
821
|
+
return (
|
|
822
|
+
eraYearAt(calendar, plainDateAddDays(month.start, day - 1), locale)
|
|
823
|
+
.label ?? String(year)
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
const middle = eraYearAt(
|
|
827
|
+
calendar,
|
|
828
|
+
calendarMonthOfYear(calendar, year, Math.floor(months / 2) + 1).start,
|
|
829
|
+
locale,
|
|
830
|
+
);
|
|
831
|
+
return middle.label ?? String(year);
|
|
832
|
+
}
|