@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.
Files changed (585) hide show
  1. package/dist/AppShell/observeMainOverflow.d.ts.map +1 -1
  2. package/dist/AppShell/observeMainOverflow.js +9 -6
  3. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  4. package/dist/BottomSheet/BottomSheet.js +37 -3
  5. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  6. package/dist/BottomSheet/BottomSheetPanel.js +40 -8
  7. package/dist/BottomSheet/bottomSheetStack.d.ts.map +1 -1
  8. package/dist/BottomSheet/bottomSheetStack.js +4 -3
  9. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  10. package/dist/BottomSheet/useSheetGestures.js +61 -21
  11. package/dist/Calendar/Calendar.d.ts +14 -2
  12. package/dist/Calendar/Calendar.d.ts.map +1 -1
  13. package/dist/Calendar/Calendar.js +63 -74
  14. package/dist/Calendar/getInitialFocusDate.d.ts +4 -1
  15. package/dist/Calendar/getInitialFocusDate.d.ts.map +1 -1
  16. package/dist/Calendar/getInitialFocusDate.js +7 -5
  17. package/dist/Calendar/hooks/useCalendarDays.d.ts +19 -2
  18. package/dist/Calendar/hooks/useCalendarDays.d.ts.map +1 -1
  19. package/dist/Calendar/hooks/useCalendarDays.js +57 -64
  20. package/dist/Calendar/hooks/useCalendarNavigation.d.ts +28 -3
  21. package/dist/Calendar/hooks/useCalendarNavigation.d.ts.map +1 -1
  22. package/dist/Calendar/hooks/useCalendarNavigation.js +33 -22
  23. package/dist/Calendar/styles.d.ts +1 -1
  24. package/dist/CheckboxInput/CheckboxInput.d.ts +2 -1
  25. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  26. package/dist/CheckboxInput/CheckboxInput.js +74 -18
  27. package/dist/CheckboxInput/CheckboxRowPressContext.d.ts +2 -0
  28. package/dist/CheckboxInput/CheckboxRowPressContext.d.ts.map +1 -0
  29. package/dist/CheckboxInput/CheckboxRowPressContext.js +20 -0
  30. package/dist/CheckboxList/CheckboxListItem.d.ts +2 -1
  31. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  32. package/dist/CheckboxList/CheckboxListItem.js +40 -14
  33. package/dist/ClickableCard/ClickableCard.d.ts +1 -1
  34. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  35. package/dist/ClickableCard/ClickableCard.js +5 -1
  36. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  37. package/dist/ContextMenu/ContextMenu.js +2 -0
  38. package/dist/DateInput/DateInput.d.ts +37 -6
  39. package/dist/DateInput/DateInput.d.ts.map +1 -1
  40. package/dist/DateInput/DateInput.js +97 -124
  41. package/dist/DateInput/MonthScroller.d.ts +5 -2
  42. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  43. package/dist/DateInput/MonthScroller.js +26 -29
  44. package/dist/DateInput/MonthYearWheels.d.ts +10 -1
  45. package/dist/DateInput/MonthYearWheels.d.ts.map +1 -1
  46. package/dist/DateInput/MonthYearWheels.js +54 -42
  47. package/dist/DateInput/PickerWheel.d.ts.map +1 -1
  48. package/dist/DateInput/PickerWheel.js +7 -1
  49. package/dist/DateInput/TouchDateField.d.ts +1 -1
  50. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  51. package/dist/DateInput/TouchDateField.js +26 -21
  52. package/dist/DateInput/monthGeometry.d.ts +42 -8
  53. package/dist/DateInput/monthGeometry.d.ts.map +1 -1
  54. package/dist/DateInput/monthGeometry.js +81 -7
  55. package/dist/DateInput/useCalendarPresentation.d.ts +10 -0
  56. package/dist/DateInput/useCalendarPresentation.d.ts.map +1 -0
  57. package/dist/DateInput/useCalendarPresentation.js +32 -0
  58. package/dist/DateInput/useTypedDate.d.ts +92 -0
  59. package/dist/DateInput/useTypedDate.d.ts.map +1 -0
  60. package/dist/DateInput/useTypedDate.js +269 -0
  61. package/dist/DateInput/wheelStrip.js +2 -2
  62. package/dist/DateRangeInput/DateRangeInput.d.ts +17 -1
  63. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  64. package/dist/DateRangeInput/DateRangeInput.js +15 -8
  65. package/dist/DateTimeInput/DateTimeInput.d.ts +26 -3
  66. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  67. package/dist/DateTimeInput/DateTimeInput.js +92 -88
  68. package/dist/DateTimeInput/TouchDateTimeField.d.ts +1 -1
  69. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
  70. package/dist/DateTimeInput/TouchDateTimeField.js +26 -20
  71. package/dist/Dialog/Dialog.d.ts +2 -1
  72. package/dist/Dialog/Dialog.d.ts.map +1 -1
  73. package/dist/Dialog/Dialog.js +14 -3
  74. package/dist/Drawer/useDrawerDialogPresence.d.ts +2 -1
  75. package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
  76. package/dist/Drawer/useDrawerDialogPresence.js +11 -2
  77. package/dist/DropdownMenu/DropdownMenu.d.ts +9 -1
  78. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  79. package/dist/DropdownMenu/DropdownMenu.js +11 -8
  80. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  81. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +3 -2
  82. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  83. package/dist/DropdownMenu/DropdownMenuItem.js +3 -2
  84. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  85. package/dist/DropdownMenu/DropdownMenuRadioItem.js +3 -2
  86. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -1
  87. package/dist/DropdownMenu/DropdownMenuSubMenu.js +3 -2
  88. package/dist/Field/inputDisabledFocus.d.ts +4 -4
  89. package/dist/Field/inputStyles.stylex.d.ts +1 -1
  90. package/dist/FileInput/FileInput.d.ts.map +1 -1
  91. package/dist/FileInput/FileInput.js +16 -2
  92. package/dist/HoverCard/useHoverCard.d.ts +3 -1
  93. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  94. package/dist/Icon/Icon.d.ts +1 -1
  95. package/dist/InfoTip/InfoTip.d.ts +1 -0
  96. package/dist/InfoTip/InfoTip.d.ts.map +1 -1
  97. package/dist/InfoTip/InfoTip.js +6 -18
  98. package/dist/InputGroup/InputGroup.d.ts +4 -3
  99. package/dist/InputGroup/InputGroup.d.ts.map +1 -1
  100. package/dist/InputGroup/InputGroup.js +2 -2
  101. package/dist/InputGroup/InputGroupText.d.ts +2 -1
  102. package/dist/InputGroup/InputGroupText.d.ts.map +1 -1
  103. package/dist/InputGroup/InputGroupText.js +2 -1
  104. package/dist/InputGroup/groupStyles.d.ts +1 -1
  105. package/dist/InputGroup/groupStyles.d.ts.map +1 -1
  106. package/dist/InputGroup/groupStyles.js +1 -1
  107. package/dist/Item/Item.d.ts +20 -1
  108. package/dist/Item/Item.d.ts.map +1 -1
  109. package/dist/Item/Item.js +97 -29
  110. package/dist/Item/ItemListRowContext.d.ts +2 -0
  111. package/dist/Item/ItemListRowContext.d.ts.map +1 -0
  112. package/dist/Item/ItemListRowContext.js +16 -0
  113. package/dist/Layer/holdEntranceInput.d.ts +24 -0
  114. package/dist/Layer/holdEntranceInput.d.ts.map +1 -0
  115. package/dist/Layer/holdEntranceInput.js +65 -0
  116. package/dist/Layer/inputHold.d.ts +49 -0
  117. package/dist/Layer/inputHold.d.ts.map +1 -0
  118. package/dist/Layer/inputHold.js +636 -0
  119. package/dist/Layer/outsidePress.d.ts +4 -0
  120. package/dist/Layer/outsidePress.d.ts.map +1 -1
  121. package/dist/Layer/outsidePress.js +18 -1
  122. package/dist/Layer/preserveAnimations.d.ts +1 -5
  123. package/dist/Layer/preserveAnimations.d.ts.map +1 -1
  124. package/dist/Layer/preserveAnimations.js +12 -214
  125. package/dist/Layer/useBackdropPress.d.ts +8 -0
  126. package/dist/Layer/useBackdropPress.d.ts.map +1 -1
  127. package/dist/Layer/useBackdropPress.js +31 -2
  128. package/dist/Layer/useLayer.d.ts +3 -1
  129. package/dist/Layer/useLayer.d.ts.map +1 -1
  130. package/dist/Layer/useLayer.js +64 -4
  131. package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
  132. package/dist/Layer/useTouchTrigger.js +4 -0
  133. package/dist/Layout/LayoutContent.d.ts +3 -1
  134. package/dist/Layout/LayoutContent.d.ts.map +1 -1
  135. package/dist/Layout/LayoutContent.js +12 -4
  136. package/dist/Layout/LayoutPanel.d.ts +13 -10
  137. package/dist/Layout/LayoutPanel.d.ts.map +1 -1
  138. package/dist/Layout/LayoutPanel.js +81 -11
  139. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  140. package/dist/Lightbox/Lightbox.js +4 -0
  141. package/dist/List/List.d.ts.map +1 -1
  142. package/dist/List/List.js +1 -0
  143. package/dist/List/ListItem.d.ts +5 -4
  144. package/dist/List/ListItem.d.ts.map +1 -1
  145. package/dist/List/ListItem.js +45 -9
  146. package/dist/Markdown/parser.d.ts.map +1 -1
  147. package/dist/Markdown/parser.js +56 -39
  148. package/dist/MetadataList/MetadataList.js +1 -1
  149. package/dist/MobileNav/MobileNav.d.ts +11 -1
  150. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  151. package/dist/MobileNav/MobileNav.js +39 -1
  152. package/dist/MoreMenu/MoreMenu.d.ts +5 -3
  153. package/dist/MoreMenu/MoreMenu.d.ts.map +1 -1
  154. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  155. package/dist/MultiSelector/MultiSelector.js +6 -9
  156. package/dist/NumberInput/NumberInput.d.ts +4 -2
  157. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  158. package/dist/NumberInput/NumberInput.js +244 -11
  159. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  160. package/dist/OverflowList/OverflowList.js +7 -2
  161. package/dist/Popover/usePopover.d.ts +1 -0
  162. package/dist/Popover/usePopover.d.ts.map +1 -1
  163. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  164. package/dist/PowerSearch/PowerSearch.js +12 -5
  165. package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +1 -1
  166. package/dist/PowerSearch/PowerSearchBottomSheet.js +4 -2
  167. package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
  168. package/dist/PowerSearch/PowerSearchToken.js +3 -1
  169. package/dist/PowerSearch/formatFilterValue.d.ts +9 -3
  170. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  171. package/dist/PowerSearch/formatFilterValue.js +14 -11
  172. package/dist/PowerSearch/formatTokenValue.d.ts +6 -2
  173. package/dist/PowerSearch/formatTokenValue.d.ts.map +1 -1
  174. package/dist/PowerSearch/formatTokenValue.js +6 -3
  175. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  176. package/dist/RadioList/RadioListItem.js +16 -3
  177. package/dist/Resizable/ResizeHandle.d.ts +5 -5
  178. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  179. package/dist/Resizable/ResizeHandle.js +44 -5
  180. package/dist/Resizable/resizablePane.d.ts +58 -0
  181. package/dist/Resizable/resizablePane.d.ts.map +1 -0
  182. package/dist/Resizable/resizablePane.js +137 -0
  183. package/dist/Resizable/useResizable.d.ts +7 -0
  184. package/dist/Resizable/useResizable.d.ts.map +1 -1
  185. package/dist/Resizable/useResizable.js +13 -0
  186. package/dist/SegmentedControl/useSegmentedSelectionMotion.js +3 -3
  187. package/dist/SelectableCard/SelectableCard.d.ts +1 -1
  188. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  189. package/dist/SelectableCard/SelectableCard.js +5 -1
  190. package/dist/Selector/Selector.d.ts.map +1 -1
  191. package/dist/Selector/Selector.js +51 -10
  192. package/dist/SideNav/SideNav.d.ts +9 -3
  193. package/dist/SideNav/SideNav.d.ts.map +1 -1
  194. package/dist/SideNav/SideNav.js +45 -10
  195. package/dist/Slider/sliderTouchController.js +2 -2
  196. package/dist/Spinner/Spinner.d.ts.map +1 -1
  197. package/dist/Spinner/Spinner.js +14 -71
  198. package/dist/Spinner/index.d.ts +1 -1
  199. package/dist/Spinner/index.d.ts.map +1 -1
  200. package/dist/Spinner/spinnerRotor.d.ts +28 -0
  201. package/dist/Spinner/spinnerRotor.d.ts.map +1 -0
  202. package/dist/Spinner/spinnerRotor.js +98 -0
  203. package/dist/Stack/StackItem.d.ts +8 -4
  204. package/dist/Stack/StackItem.d.ts.map +1 -1
  205. package/dist/Stack/StackItem.js +17 -4
  206. package/dist/Switch/Switch.d.ts.map +1 -1
  207. package/dist/Switch/Switch.js +13 -10
  208. package/dist/Switch/useSwitchTouch.js +4 -4
  209. package/dist/TabList/Tab.d.ts.map +1 -1
  210. package/dist/TabList/Tab.js +5 -1
  211. package/dist/Table/plugins/sortable/useTableSortable.js +1 -1
  212. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  213. package/dist/Timestamp/Timestamp.js +14 -8
  214. package/dist/Timestamp/formatInstant.d.ts +10 -1
  215. package/dist/Timestamp/formatInstant.d.ts.map +1 -1
  216. package/dist/Timestamp/formatInstant.js +13 -27
  217. package/dist/Timestamp/tooltipEntries.d.ts +5 -3
  218. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -1
  219. package/dist/Timestamp/tooltipEntries.js +6 -4
  220. package/dist/Token/Token.d.ts.map +1 -1
  221. package/dist/Token/Token.js +9 -0
  222. package/dist/Token/TokenLink.d.ts +1 -1
  223. package/dist/Token/TokenLink.d.ts.map +1 -1
  224. package/dist/Token/TokenLink.js +4 -1
  225. package/dist/Tokenizer/Tokenizer.d.ts +14 -10
  226. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  227. package/dist/Tokenizer/Tokenizer.js +189 -89
  228. package/dist/Tooltip/useTooltip.d.ts +3 -1
  229. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  230. package/dist/Tooltip/useTooltip.js +164 -59
  231. package/dist/TreeList/TreeListItem.d.ts +2 -1
  232. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  233. package/dist/TreeList/TreeListItem.js +27 -3
  234. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  235. package/dist/Typeahead/BaseTypeahead.js +2 -1
  236. package/dist/animator/createAnimator.js +2 -2
  237. package/dist/astryx.css +362 -325
  238. package/dist/gestures/GestureHost.d.ts +2 -2
  239. package/dist/gestures/GestureHost.d.ts.map +1 -1
  240. package/dist/gestures/GestureHost.js +21 -6
  241. package/dist/gestures/PanGestureRecognizer.d.ts +11 -1
  242. package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
  243. package/dist/gestures/PanGestureRecognizer.js +15 -1
  244. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +6 -1
  245. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -1
  246. package/dist/gestures/nativeScroll.d.ts +3 -6
  247. package/dist/gestures/nativeScroll.d.ts.map +1 -1
  248. package/dist/gestures/nativeScroll.js +7 -52
  249. package/dist/gestures/wheelSegmenter.d.ts +68 -1
  250. package/dist/gestures/wheelSegmenter.d.ts.map +1 -1
  251. package/dist/gestures/wheelSegmenter.js +199 -10
  252. package/dist/hooks/StackItemScrollRegion.d.ts +31 -0
  253. package/dist/hooks/StackItemScrollRegion.d.ts.map +1 -0
  254. package/dist/hooks/StackItemScrollRegion.js +40 -0
  255. package/dist/hooks/computeOverflow.d.ts +2 -0
  256. package/dist/hooks/computeOverflow.d.ts.map +1 -1
  257. package/dist/hooks/computeOverflow.js +1 -1
  258. package/dist/hooks/menuPressGesture.d.ts +133 -21
  259. package/dist/hooks/menuPressGesture.d.ts.map +1 -1
  260. package/dist/hooks/menuPressGesture.js +155 -30
  261. package/dist/hooks/menuPressValues.d.ts +16 -0
  262. package/dist/hooks/menuPressValues.d.ts.map +1 -0
  263. package/dist/hooks/menuPressValues.js +18 -0
  264. package/dist/hooks/useClickableContainer.d.ts +36 -7
  265. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  266. package/dist/hooks/useClickableContainer.js +63 -14
  267. package/dist/hooks/useFocusTrap.d.ts +10 -0
  268. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  269. package/dist/hooks/useFocusTrap.js +225 -132
  270. package/dist/hooks/useKeyboardHighlight.d.ts +17 -0
  271. package/dist/hooks/useKeyboardHighlight.d.ts.map +1 -0
  272. package/dist/hooks/useKeyboardHighlight.js +38 -0
  273. package/dist/hooks/useMediaQuery.d.ts +2 -1
  274. package/dist/hooks/useMediaQuery.d.ts.map +1 -1
  275. package/dist/hooks/useMediaQuery.js +37 -12
  276. package/dist/hooks/useMenuPress.d.ts +34 -1
  277. package/dist/hooks/useMenuPress.d.ts.map +1 -1
  278. package/dist/hooks/useMenuPress.js +93 -5
  279. package/dist/hooks/useOverflow.d.ts +10 -0
  280. package/dist/hooks/useOverflow.d.ts.map +1 -1
  281. package/dist/hooks/useOverflow.js +214 -23
  282. package/dist/hooks/usePressFeedback.d.ts +6 -6
  283. package/dist/hooks/usePressFeedback.js +6 -6
  284. package/dist/hooks/useScrollRegionProps.d.ts +35 -0
  285. package/dist/hooks/useScrollRegionProps.d.ts.map +1 -0
  286. package/dist/hooks/useScrollRegionProps.js +51 -0
  287. package/dist/i18n/InternationalizationContext.d.ts +6 -0
  288. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  289. package/dist/i18n/InternationalizationProvider.d.ts +23 -3
  290. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  291. package/dist/i18n/InternationalizationProvider.js +8 -3
  292. package/dist/i18n/generated-english/DateInput/DateInput.generated.d.ts.map +1 -1
  293. package/dist/i18n/generated-english/DateInput/DateInput.generated.js +0 -1
  294. package/dist/i18n/generated-english/DateInput/useTypedDate.generated.d.ts +8 -0
  295. package/dist/i18n/generated-english/DateInput/useTypedDate.generated.d.ts.map +1 -0
  296. package/dist/i18n/generated-english/DateInput/useTypedDate.generated.js +16 -0
  297. package/dist/i18n/generated-english/DateTimeInput/DateTimeInput.generated.d.ts.map +1 -1
  298. package/dist/i18n/generated-english/DateTimeInput/DateTimeInput.generated.js +0 -1
  299. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.d.ts +8 -0
  300. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.d.ts.map +1 -0
  301. package/dist/i18n/generated-english/hooks/useScrollRegionProps.generated.js +12 -0
  302. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  303. package/dist/i18n/generated-locales/en.generated.js +5 -0
  304. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  305. package/dist/i18n/generated-locales/pseudo.generated.js +5 -0
  306. package/dist/i18n/index.d.ts +2 -0
  307. package/dist/i18n/index.d.ts.map +1 -1
  308. package/dist/i18n/index.js +1 -0
  309. package/dist/i18n/useCalendarSystem.d.ts +19 -0
  310. package/dist/i18n/useCalendarSystem.d.ts.map +1 -0
  311. package/dist/i18n/useCalendarSystem.js +61 -0
  312. package/dist/internal/calendar-system.d.ts +18 -0
  313. package/dist/internal/calendar-system.d.ts.map +1 -0
  314. package/dist/internal/calendar-system.js +19 -0
  315. package/dist/internal/spinner-rotor.d.ts +16 -0
  316. package/dist/internal/spinner-rotor.d.ts.map +1 -0
  317. package/dist/internal/spinner-rotor.js +16 -0
  318. package/dist/internal/touch.d.ts +20 -2
  319. package/dist/internal/touch.d.ts.map +1 -1
  320. package/dist/internal/touch.js +29 -3
  321. package/dist/motion/animator.d.ts +5 -5
  322. package/dist/motion/animator.d.ts.map +1 -1
  323. package/dist/motion/animator.js +7 -6
  324. package/dist/motion/carryAnimations.d.ts +58 -0
  325. package/dist/motion/carryAnimations.d.ts.map +1 -0
  326. package/dist/motion/carryAnimations.js +305 -0
  327. package/dist/motion/transientCopy.d.ts +4 -2
  328. package/dist/motion/transientCopy.d.ts.map +1 -1
  329. package/dist/motion/transientCopy.js +34 -5
  330. package/dist/motion/uikit/gestures.d.ts +41 -0
  331. package/dist/motion/uikit/gestures.d.ts.map +1 -1
  332. package/dist/motion/uikit/gestures.js +25 -0
  333. package/dist/motion/uikit/index.d.ts +1 -1
  334. package/dist/motion/uikit/index.d.ts.map +1 -1
  335. package/dist/motion/uikit/index.js +1 -1
  336. package/dist/motion/uikit/timing.d.ts +14 -10
  337. package/dist/motion/uikit/timing.d.ts.map +1 -1
  338. package/dist/motion/uikit/timing.js +7 -5
  339. package/dist/privateAttributes/menuPressLit.stylex.d.ts +52 -0
  340. package/dist/privateAttributes/menuPressLit.stylex.d.ts.map +1 -0
  341. package/dist/privateAttributes/menuPressLit.stylex.js +99 -0
  342. package/dist/privateAttributes/press.stylex.d.ts +142 -0
  343. package/dist/privateAttributes/press.stylex.d.ts.map +1 -0
  344. package/dist/privateAttributes/press.stylex.js +101 -0
  345. package/dist/theme/themeMotion.d.ts +3 -2
  346. package/dist/theme/themeMotion.d.ts.map +1 -1
  347. package/dist/theme/themeMotion.js +3 -2
  348. package/dist/theme/tokens.stylex.d.ts +2 -2
  349. package/dist/theme/tokens.stylex.js +1 -1
  350. package/dist/utils/calendarDateParser.d.ts +110 -0
  351. package/dist/utils/calendarDateParser.d.ts.map +1 -0
  352. package/dist/utils/calendarDateParser.js +1225 -0
  353. package/dist/utils/calendarSystem.d.ts +176 -0
  354. package/dist/utils/calendarSystem.d.ts.map +1 -0
  355. package/dist/utils/calendarSystem.js +569 -0
  356. package/dist/utils/coarsePointer.d.ts +5 -0
  357. package/dist/utils/coarsePointer.d.ts.map +1 -1
  358. package/dist/utils/coarsePointer.js +22 -13
  359. package/dist/utils/flatTree.d.ts +6 -3
  360. package/dist/utils/flatTree.d.ts.map +1 -1
  361. package/dist/utils/flatTree.js +13 -3
  362. package/dist/utils/focusReturn.d.ts +34 -13
  363. package/dist/utils/focusReturn.d.ts.map +1 -1
  364. package/dist/utils/focusReturn.js +64 -17
  365. package/dist/utils/hitArea.d.ts +8 -1
  366. package/dist/utils/hitArea.d.ts.map +1 -1
  367. package/dist/utils/hitArea.js +99 -9
  368. package/dist/utils/inputPresentation.d.ts +9 -1
  369. package/dist/utils/inputPresentation.d.ts.map +1 -1
  370. package/dist/utils/inputPresentation.js +15 -1
  371. package/dist/utils/inputStream.d.ts +14 -1
  372. package/dist/utils/inputStream.d.ts.map +1 -1
  373. package/dist/utils/inputStream.js +40 -9
  374. package/dist/utils/interactionOverlay.stylex.d.ts +5 -9
  375. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  376. package/dist/utils/interactionOverlay.stylex.js +29 -31
  377. package/dist/utils/plainDate.d.ts +38 -7
  378. package/dist/utils/plainDate.d.ts.map +1 -1
  379. package/dist/utils/plainDate.js +92 -18
  380. package/dist/utils/pressFeedback.d.ts +10 -2
  381. package/dist/utils/pressFeedback.d.ts.map +1 -1
  382. package/dist/utils/pressFeedback.js +40 -15
  383. package/dist/utils/pressGesture.d.ts +12 -6
  384. package/dist/utils/pressGesture.d.ts.map +1 -1
  385. package/dist/utils/pressGesture.js +26 -8
  386. package/dist/utils/scrollView.d.ts +25 -0
  387. package/dist/utils/scrollView.d.ts.map +1 -0
  388. package/dist/utils/scrollView.js +108 -0
  389. package/dist/utils/selectionLock.d.ts.map +1 -1
  390. package/dist/utils/selectionLock.js +1 -10
  391. package/dist/utils/touchHitArea.d.ts +30 -0
  392. package/dist/utils/touchHitArea.d.ts.map +1 -0
  393. package/dist/utils/touchHitArea.js +167 -0
  394. package/dist/utils/touchHitArea.stylex.d.ts +38 -0
  395. package/dist/utils/touchHitArea.stylex.d.ts.map +1 -0
  396. package/dist/utils/touchHitArea.stylex.js +48 -0
  397. package/dist/utils/triggerFocus.d.ts +5 -0
  398. package/dist/utils/triggerFocus.d.ts.map +1 -1
  399. package/dist/utils/triggerFocus.js +9 -2
  400. package/locales/en.json +21 -1
  401. package/locales/pseudo.json +15 -0
  402. package/package.json +15 -4
  403. package/src/AppShell/observeMainOverflow.ts +9 -6
  404. package/src/BottomSheet/BottomSheet.tsx +45 -3
  405. package/src/BottomSheet/BottomSheetPanel.tsx +64 -7
  406. package/src/BottomSheet/bottomSheetStack.ts +4 -3
  407. package/src/BottomSheet/useSheetGestures.ts +83 -20
  408. package/src/Calendar/Calendar.doc.mjs +76 -6
  409. package/src/Calendar/Calendar.tsx +123 -104
  410. package/src/Calendar/getInitialFocusDate.ts +22 -8
  411. package/src/Calendar/hooks/useCalendarDays.ts +89 -63
  412. package/src/Calendar/hooks/useCalendarNavigation.ts +68 -26
  413. package/src/CheckboxInput/CheckboxInput.doc.mjs +5 -4
  414. package/src/CheckboxInput/CheckboxInput.tsx +105 -20
  415. package/src/CheckboxInput/CheckboxRowPressContext.ts +22 -0
  416. package/src/CheckboxList/CheckboxList.doc.mjs +9 -0
  417. package/src/CheckboxList/CheckboxListItem.doc.mjs +3 -3
  418. package/src/CheckboxList/CheckboxListItem.tsx +35 -14
  419. package/src/ClickableCard/ClickableCard.tsx +8 -1
  420. package/src/ContextMenu/ContextMenu.tsx +2 -0
  421. package/src/DateInput/DateInput.doc.mjs +45 -12
  422. package/src/DateInput/DateInput.tsx +165 -179
  423. package/src/DateInput/MonthScroller.tsx +39 -37
  424. package/src/DateInput/MonthYearWheels.tsx +68 -47
  425. package/src/DateInput/PickerWheel.tsx +7 -2
  426. package/src/DateInput/TouchDateField.tsx +45 -17
  427. package/src/DateInput/monthGeometry.ts +110 -8
  428. package/src/DateInput/useCalendarPresentation.ts +64 -0
  429. package/src/DateInput/useTypedDate.ts +469 -0
  430. package/src/DateInput/wheelStrip.ts +2 -2
  431. package/src/DateRangeInput/DateRangeInput.doc.mjs +9 -0
  432. package/src/DateRangeInput/DateRangeInput.tsx +43 -9
  433. package/src/DateTimeInput/DateTimeInput.doc.mjs +42 -9
  434. package/src/DateTimeInput/DateTimeInput.tsx +138 -148
  435. package/src/DateTimeInput/TouchDateTimeField.tsx +31 -16
  436. package/src/Dialog/Dialog.doc.mjs +1 -1
  437. package/src/Dialog/Dialog.tsx +14 -2
  438. package/src/Drawer/Drawer.doc.mjs +1 -1
  439. package/src/Drawer/useDrawerDialogPresence.ts +9 -2
  440. package/src/DropdownMenu/DropdownMenu.doc.mjs +1 -2
  441. package/src/DropdownMenu/DropdownMenu.tsx +31 -7
  442. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +5 -1
  443. package/src/DropdownMenu/DropdownMenuItem.tsx +8 -4
  444. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +5 -1
  445. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +5 -1
  446. package/src/FileInput/FileInput.tsx +16 -2
  447. package/src/HoverCard/useHoverCard.tsx +3 -1
  448. package/src/Icon/useIcon.doc.mjs +94 -0
  449. package/src/InfoTip/InfoTip.doc.mjs +26 -2
  450. package/src/InfoTip/InfoTip.tsx +6 -27
  451. package/src/InputGroup/InputGroup.doc.mjs +4 -3
  452. package/src/InputGroup/InputGroup.tsx +4 -3
  453. package/src/InputGroup/InputGroupText.doc.mjs +45 -3
  454. package/src/InputGroup/InputGroupText.tsx +2 -1
  455. package/src/InputGroup/groupStyles.ts +3 -1
  456. package/src/Item/Item.tsx +139 -35
  457. package/src/Item/ItemListRowContext.tsx +18 -0
  458. package/src/Layer/holdEntranceInput.ts +84 -0
  459. package/src/Layer/inputHold.ts +734 -0
  460. package/src/Layer/outsidePress.ts +18 -1
  461. package/src/Layer/preserveAnimations.ts +12 -275
  462. package/src/Layer/useBackdropPress.ts +41 -1
  463. package/src/Layer/useLayer.tsx +77 -4
  464. package/src/Layer/useTouchTrigger.ts +4 -0
  465. package/src/Layout/LayoutContent.doc.mjs +6 -3
  466. package/src/Layout/LayoutContent.tsx +10 -4
  467. package/src/Layout/LayoutPanel.doc.mjs +14 -11
  468. package/src/Layout/LayoutPanel.tsx +113 -16
  469. package/src/Lightbox/Lightbox.tsx +4 -0
  470. package/src/List/List.doc.mjs +10 -1
  471. package/src/List/List.tsx +5 -0
  472. package/src/List/ListItem.tsx +63 -8
  473. package/src/Markdown/parser.ts +65 -42
  474. package/src/MetadataList/MetadataList.tsx +1 -1
  475. package/src/MobileNav/MobileNav.doc.mjs +3 -3
  476. package/src/MobileNav/MobileNav.tsx +39 -1
  477. package/src/MoreMenu/MoreMenu.doc.mjs +2 -4
  478. package/src/MoreMenu/MoreMenu.tsx +5 -3
  479. package/src/MultiSelector/MultiSelector.tsx +7 -17
  480. package/src/NumberInput/NumberInput.doc.mjs +1 -1
  481. package/src/NumberInput/NumberInput.tsx +259 -11
  482. package/src/OverflowList/OverflowList.tsx +15 -9
  483. package/src/Popover/usePopover.tsx +1 -0
  484. package/src/PowerSearch/PowerSearch.doc.mjs +3 -3
  485. package/src/PowerSearch/PowerSearch.tsx +20 -3
  486. package/src/PowerSearch/PowerSearchBottomSheet.tsx +4 -1
  487. package/src/PowerSearch/PowerSearchToken.tsx +3 -0
  488. package/src/PowerSearch/formatFilterValue.ts +21 -11
  489. package/src/PowerSearch/formatTokenValue.ts +7 -1
  490. package/src/RadioList/RadioListItem.doc.mjs +3 -2
  491. package/src/RadioList/RadioListItem.tsx +16 -6
  492. package/src/Resizable/Resizable.doc.mjs +40 -12
  493. package/src/Resizable/ResizeHandle.tsx +68 -6
  494. package/src/Resizable/resizablePane.ts +179 -0
  495. package/src/Resizable/useResizable.ts +15 -0
  496. package/src/SegmentedControl/useSegmentedSelectionMotion.ts +3 -3
  497. package/src/SelectableCard/SelectableCard.tsx +8 -1
  498. package/src/Selector/Selector.tsx +83 -8
  499. package/src/SideNav/SideNav.doc.mjs +2 -2
  500. package/src/SideNav/SideNav.tsx +87 -12
  501. package/src/Slider/sliderTouchController.ts +2 -2
  502. package/src/Spinner/Spinner.tsx +7 -89
  503. package/src/Spinner/index.ts +1 -5
  504. package/src/Spinner/spinnerRotor.ts +113 -0
  505. package/src/Stack/Stack.doc.mjs +1 -1
  506. package/src/Stack/StackItem.tsx +27 -13
  507. package/src/Switch/Switch.tsx +7 -6
  508. package/src/Switch/useSwitchTouch.ts +4 -4
  509. package/src/TabList/Tab.tsx +5 -1
  510. package/src/Table/plugins/sortable/useTableSortable.tsx +1 -1
  511. package/src/Timestamp/Timestamp.doc.mjs +3 -3
  512. package/src/Timestamp/Timestamp.tsx +13 -8
  513. package/src/Timestamp/formatInstant.ts +49 -28
  514. package/src/Timestamp/tooltipEntries.ts +7 -3
  515. package/src/Token/Token.tsx +18 -1
  516. package/src/Token/TokenLink.tsx +7 -1
  517. package/src/Tokenizer/Tokenizer.doc.mjs +3 -3
  518. package/src/Tokenizer/Tokenizer.tsx +252 -115
  519. package/src/Tooltip/useTooltip.tsx +180 -80
  520. package/src/TreeList/TreeListItem.tsx +36 -2
  521. package/src/Typeahead/BaseTypeahead.tsx +2 -0
  522. package/src/animator/createAnimator.ts +3 -3
  523. package/src/gestures/GestureHost.ts +21 -5
  524. package/src/gestures/PanGestureRecognizer.ts +19 -2
  525. package/src/gestures/README.md +14 -5
  526. package/src/gestures/ScreenEdgePanGestureRecognizer.ts +6 -1
  527. package/src/gestures/nativeScroll.ts +12 -68
  528. package/src/gestures/wheelSegmenter.ts +243 -10
  529. package/src/hooks/StackItemScrollRegion.tsx +57 -0
  530. package/src/hooks/computeOverflow.ts +1 -1
  531. package/src/hooks/menuPressGesture.ts +244 -38
  532. package/src/hooks/menuPressValues.ts +18 -0
  533. package/src/hooks/useClickableContainer.doc.mjs +8 -2
  534. package/src/hooks/useClickableContainer.ts +93 -15
  535. package/src/hooks/useFocusTrap.ts +268 -151
  536. package/src/hooks/useKeyboardHighlight.ts +71 -0
  537. package/src/hooks/useMediaQuery.ts +41 -12
  538. package/src/hooks/useMenuPress.ts +118 -11
  539. package/src/hooks/useOverflow.ts +321 -75
  540. package/src/hooks/usePressFeedback.doc.mjs +3 -3
  541. package/src/hooks/usePressFeedback.ts +6 -6
  542. package/src/hooks/useScrollRegionProps.ts +76 -0
  543. package/src/i18n/InternationalizationContext.ts +6 -0
  544. package/src/i18n/InternationalizationProvider.doc.mjs +29 -1
  545. package/src/i18n/InternationalizationProvider.tsx +35 -3
  546. package/src/i18n/generated-english/DateInput/DateInput.generated.ts +0 -1
  547. package/src/i18n/generated-english/DateInput/useTypedDate.generated.ts +17 -0
  548. package/src/i18n/generated-english/DateTimeInput/DateTimeInput.generated.ts +0 -1
  549. package/src/i18n/generated-english/hooks/useScrollRegionProps.generated.ts +13 -0
  550. package/src/i18n/generated-locales/en.generated.ts +7 -0
  551. package/src/i18n/generated-locales/pseudo.generated.ts +7 -0
  552. package/src/i18n/index.ts +2 -0
  553. package/src/i18n/useCalendarSystem.ts +95 -0
  554. package/src/internal/calendar-system.ts +26 -0
  555. package/src/internal/spinner-rotor.ts +20 -0
  556. package/src/internal/touch.ts +43 -2
  557. package/src/motion/MEASUREMENTS.md +11 -0
  558. package/src/motion/README.md +3 -3
  559. package/src/motion/animator.ts +7 -7
  560. package/src/motion/carryAnimations.ts +389 -0
  561. package/src/motion/transientCopy.ts +45 -5
  562. package/src/motion/uikit/gestures.ts +22 -0
  563. package/src/motion/uikit/index.ts +1 -0
  564. package/src/motion/uikit/timing.ts +7 -5
  565. package/src/privateAttributes/menuPressLit.stylex.ts +104 -0
  566. package/src/privateAttributes/press.stylex.ts +261 -0
  567. package/src/theme/themeMotion.ts +3 -2
  568. package/src/theme/tokens.stylex.ts +1 -1
  569. package/src/utils/calendarDateParser.ts +1385 -0
  570. package/src/utils/calendarSystem.ts +832 -0
  571. package/src/utils/coarsePointer.ts +27 -14
  572. package/src/utils/flatTree.ts +15 -3
  573. package/src/utils/focusReturn.ts +78 -18
  574. package/src/utils/hitArea.ts +138 -9
  575. package/src/utils/inputPresentation.ts +21 -1
  576. package/src/utils/inputStream.ts +47 -10
  577. package/src/utils/interactionOverlay.stylex.ts +19 -22
  578. package/src/utils/plainDate.ts +130 -19
  579. package/src/utils/pressFeedback.ts +46 -14
  580. package/src/utils/pressGesture.ts +35 -9
  581. package/src/utils/scrollView.ts +135 -0
  582. package/src/utils/selectionLock.ts +5 -10
  583. package/src/utils/touchHitArea.stylex.ts +56 -0
  584. package/src/utils/touchHitArea.ts +177 -0
  585. package/src/utils/triggerFocus.ts +17 -4
@@ -0,0 +1,1225 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file calendarDateParser.ts
5
+ * @input Date text, locale, calendar; Intl, calendarSystem, unicodeDigits
6
+ * @output Cached per-locale lexicons, a typed-date parser with distinct rejection
7
+ * kinds, committed display text, the format hint, and calendar display names
8
+ * @position Core utility; used by DateInput and DateTimeInput through useTypedDate
9
+ *
10
+ * SYNC: When modified, update:
11
+ * - /packages/core/src/utils/calendarDateParser.test.ts
12
+ * - /packages/core/src/utils/calendarDateParser.roundtrip.test.ts
13
+ */
14
+
15
+ import { calendarDateFromFields, calendarMonthOf, calendarMonthsInYear, formatCalendarDate, isCalendarSystemAvailable, isGregorianAligned } from "./calendarSystem.js";
16
+ import { SHARED_DATE_FORMAT_OPTIONS, formatSharedDate, getDaysInMonth, plainDateAddDays, plainDateDiffDays, plainDateFormat, plainDateFormatToParts, plainDateToday } from "./plainDate.js";
17
+ import { INVISIBLE_CHARS, toAsciiDigits } from "./unicodeDigits.js";
18
+
19
+ /** How a typed text reads in a calendar. */
20
+
21
+ /** What a locale writes for one calendar, learned from Intl. */
22
+
23
+ const NUMERIC = {
24
+ year: 'numeric',
25
+ month: 'numeric',
26
+ day: 'numeric'
27
+ };
28
+ const LONG = SHARED_DATE_FORMAT_OPTIONS.date_long;
29
+ const YEAR_ONLY = {
30
+ year: 'numeric'
31
+ };
32
+ const ERA_AND_YEAR = {
33
+ era: 'short',
34
+ year: 'numeric'
35
+ };
36
+ const LONG_WITH_ERA = {
37
+ ...LONG,
38
+ era: 'long'
39
+ };
40
+ const ERA_WIDTHS = {
41
+ long: {
42
+ era: 'long',
43
+ year: 'numeric'
44
+ },
45
+ short: ERA_AND_YEAR,
46
+ narrow: {
47
+ era: 'narrow',
48
+ year: 'numeric'
49
+ }
50
+ };
51
+ const WEEKDAY_FORMATS = [{
52
+ weekday: 'long'
53
+ }, {
54
+ weekday: 'short'
55
+ }, {
56
+ ...LONG,
57
+ weekday: 'long'
58
+ }, {
59
+ ...LONG,
60
+ weekday: 'short'
61
+ }];
62
+ const LONG_WITH_WEEKDAY = {
63
+ ...LONG,
64
+ weekday: 'short'
65
+ };
66
+ // Built at runtime: the Babel copy in a Next.js source build rejects a
67
+ // `\p{...}` regex literal.
68
+ const LETTER = new RegExp('[\\p{L}\\p{M}]', 'u');
69
+ const SEPARATOR = new RegExp('[\\p{P}\\p{S}]', 'u');
70
+ const ONLY_SEPARATORS = new RegExp('^[\\p{P}\\p{S}]+$', 'u');
71
+ const NOT_WORDS = new RegExp('[\\d\\p{P}\\p{S}]+', 'gu');
72
+ const LATIN_MARKS = new RegExp('(\\p{Script=Latin})\\p{Mn}+', 'gu');
73
+ // Scripts written without spaces between words: a name may run into the
74
+ // next word, so a name match there needs no word boundary.
75
+ const SPACELESS = new RegExp('[\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}\\p{Script=Thai}\\p{Script=Lao}\\p{Script=Khmer}\\p{Script=Myanmar}]', 'u');
76
+ const LUNISOLAR = new Set(['chinese', 'dangi']);
77
+ const WITHOUT_ERA = new Set(['gregory', 'iso8601', 'chinese', 'dangi']);
78
+
79
+ /**
80
+ * One ISO date inside each era of a calendar. Intl supplies the names; the
81
+ * era codes are the Temporal and ECMA-402 identifiers.
82
+ */
83
+ const ERA_SAMPLES = {
84
+ gregory: {
85
+ ce: '2000-06-15',
86
+ bce: '-000100-06-15'
87
+ },
88
+ japanese: {
89
+ meiji: '1900-06-15',
90
+ taisho: '1920-06-15',
91
+ showa: '1950-06-15',
92
+ heisei: '2000-06-15',
93
+ reiwa: '2026-06-15'
94
+ },
95
+ roc: {
96
+ roc: '2026-06-15',
97
+ broc: '1900-06-15'
98
+ },
99
+ buddhist: {
100
+ be: '2026-06-15'
101
+ },
102
+ ethiopic: {
103
+ am: '2026-06-15',
104
+ aa: '-005600-06-15'
105
+ },
106
+ ethioaa: {
107
+ aa: '2026-06-15'
108
+ },
109
+ coptic: {
110
+ am: '2026-06-15'
111
+ },
112
+ persian: {
113
+ ap: '2026-06-15'
114
+ },
115
+ hebrew: {
116
+ am: '2026-06-15'
117
+ },
118
+ indian: {
119
+ shaka: '2026-06-15'
120
+ },
121
+ 'islamic-umalqura': {
122
+ ah: '2026-06-15'
123
+ },
124
+ 'islamic-civil': {
125
+ ah: '2026-06-15'
126
+ },
127
+ 'islamic-tbla': {
128
+ ah: '2026-06-15'
129
+ }
130
+ };
131
+
132
+ /** The calendar a text field reads and writes. `iso8601` writes as Gregorian. */
133
+ function textCalendar(calendar) {
134
+ if (calendar === 'iso8601' || !isCalendarSystemAvailable(calendar)) {
135
+ return 'gregory';
136
+ }
137
+ return calendar;
138
+ }
139
+
140
+ // =============================================================================
141
+ // Intl access
142
+ // =============================================================================
143
+
144
+ /** Part types such as `relatedYear` and `yearName` are absent from older TS libs. */
145
+ function partType(part) {
146
+ return part.type;
147
+ }
148
+ function isoToPlainDate(iso) {
149
+ const match = /^(-?\d+)-(\d+)-(\d+)$/.exec(iso);
150
+ if (match == null) {
151
+ throw new RangeError(`Bad sample date ${iso}`);
152
+ }
153
+ return {
154
+ year: +match[1],
155
+ month: +match[2],
156
+ day: +match[3]
157
+ };
158
+ }
159
+ function partsOf(locale, calendar, options, pd) {
160
+ return plainDateFormatToParts(pd, {
161
+ ...options,
162
+ calendar
163
+ }, locale);
164
+ }
165
+
166
+ // =============================================================================
167
+ // Normalization
168
+ // =============================================================================
169
+
170
+ /** Text in one comparable form: ASCII digits, lower case, no Latin accents. */
171
+ export function normalizeDateText(text, locale) {
172
+ // Most typed text is printable ASCII; skip the Unicode passes it does not need.
173
+ if (/^[\u0020-\u007e]*$/.test(text)) {
174
+ const ascii = text.replaceAll('`', "'");
175
+ return /[A-Z]/.test(ascii) ? ascii.toLocaleLowerCase(locale) : ascii;
176
+ }
177
+ const folded = text.normalize('NFKC').replace(INVISIBLE_CHARS, '')
178
+ // Pasted text can carry bidi embeddings.
179
+ .replace(/[\u202a-\u202e]/g, '')
180
+ // People type an ASCII apostrophe or quote for Hebrew geresh and
181
+ // gershayim, and for the ʻ of Islamic month names such as Dhuʻl-Hijjah.
182
+ .replace(/[\u05f3\u2018\u2019\u02bb\u02bc\u02bf`]/g, "'").replace(/[\u05f4\u201c\u201d]/g, '"');
183
+ let result = (toAsciiDigits(folded) ?? folded).toLocaleLowerCase(locale);
184
+ if (/[\u00c0-\u024f\u1e00-\u1eff]/.test(result)) {
185
+ // Fold Latin accents only: in other scripts a mark is part of the letter.
186
+ result = result.normalize('NFD').replace(LATIN_MARKS, '$1').normalize('NFC');
187
+ }
188
+ return result;
189
+ }
190
+
191
+ // =============================================================================
192
+ // Lexicon
193
+ // =============================================================================
194
+
195
+ const lexicons = new Map();
196
+
197
+ /**
198
+ * The lexicon for a locale and calendar, built on first use and cached.
199
+ * Building one formats a few hundred dates; call it when a field gains focus.
200
+ */
201
+ export function getCalendarDateLexicon(locale, calendar) {
202
+ const resolved = textCalendar(calendar);
203
+ const key = `${locale}|${resolved}`;
204
+ let lexicon = lexicons.get(key);
205
+ if (lexicon == null) {
206
+ lexicon = buildLexicon(locale, resolved);
207
+ lexicons.set(key, lexicon);
208
+ }
209
+ return lexicon;
210
+ }
211
+ /** Months to learn names from: a few calendar years, so leap months appear. */
212
+ function sampleMonths(calendar) {
213
+ if (isGregorianAligned(calendar)) {
214
+ return Array.from({
215
+ length: 12
216
+ }, (_, i) => ({
217
+ code: `M${String(i + 1).padStart(2, '0')}`,
218
+ ordinal: i + 1,
219
+ mid: {
220
+ year: 2026,
221
+ month: i + 1,
222
+ day: 15
223
+ },
224
+ monthsInYear: 12
225
+ }));
226
+ }
227
+ const reference = calendarYearOf(calendar, {
228
+ year: 2026,
229
+ month: 6,
230
+ day: 15
231
+ });
232
+ const sampled = [];
233
+ for (let year = reference - 1; year <= reference + 3; year++) {
234
+ const starts = [];
235
+ for (let n = 1; n <= 13; n++) {
236
+ for (const leap of ['', 'L']) {
237
+ const code = `M${String(n).padStart(2, '0')}${leap}`;
238
+ const start = calendarDateFromFields(calendar, {
239
+ year,
240
+ monthCode: code,
241
+ day: 1
242
+ });
243
+ if (start != null) {
244
+ starts.push({
245
+ code,
246
+ start
247
+ });
248
+ }
249
+ }
250
+ }
251
+ starts.sort((a, b) => plainDateDiffDays(b.start, a.start));
252
+ starts.forEach(({
253
+ code,
254
+ start
255
+ }, i) => {
256
+ const month = calendarMonthOf(calendar, start);
257
+ sampled.push({
258
+ code,
259
+ ordinal: i + 1,
260
+ mid: plainDateAddDays(month.start, Math.floor(month.length / 2)),
261
+ monthsInYear: starts.length
262
+ });
263
+ });
264
+ }
265
+ return sampled;
266
+ }
267
+
268
+ /** The calendar's year number of a Gregorian date, read from Intl. */
269
+ function calendarYearOf(calendar, pd) {
270
+ const parts = partsOf('en', calendar, YEAR_ONLY, pd);
271
+ const year = parts.find(p => partType(p) === 'relatedYear' || p.type === 'year');
272
+ return Number(normalizeDateText(year?.value ?? '', 'en'));
273
+ }
274
+ function fieldOrder(parts) {
275
+ const order = [];
276
+ for (const part of parts) {
277
+ const type = partType(part) === 'relatedYear' ? 'year' : part.type;
278
+ if ((type === 'year' || type === 'month' || type === 'day') && !order.includes(type)) {
279
+ order.push(type);
280
+ }
281
+ }
282
+ return order;
283
+ }
284
+ function buildLexicon(locale, calendar) {
285
+ const locales = locale === 'en' ? ['en'] : [locale, 'en'];
286
+ const norm = text => normalizeDateText(text, locale).trim();
287
+ const months = new Map();
288
+ const templates = new Map();
289
+ const leapMarkers = new Set();
290
+ const eras = new Map();
291
+ const yearAliases = new Map();
292
+ const skip = new Set();
293
+ const trailers = new Set();
294
+ const yearMarkers = new Set();
295
+ const separators = new Set();
296
+ const weekdays = new Set();
297
+ const addSkip = (text, words = skip) => {
298
+ for (const word of norm(text).replace(NOT_WORDS, ' ').split(/\s+/)) {
299
+ if (word) {
300
+ words.add(word);
301
+ }
302
+ }
303
+ };
304
+ const addMonth = (text, {
305
+ code,
306
+ ordinal
307
+ }) => {
308
+ const name = norm(text);
309
+ // A month number with affixes: "11月", "9:e mån", "윤6", "6bis". A name
310
+ // can also hold another number: Hungarian "Réb. 1" is the third month.
311
+ const match = /^(\D*)(\d+)(\D*)$/.exec(name);
312
+ const isOwnNumber = [ordinal, Number(code.slice(1, 3))].includes(Number(match?.[2]));
313
+ if (!name || /\d/.test(name) && (!LETTER.test(name) || isOwnNumber)) {
314
+ if (match != null && (match[1] || match[3])) {
315
+ templates.set(`${match[1]}#${match[3]}`, {
316
+ pre: match[1],
317
+ post: match[3],
318
+ isLeap: code.endsWith('L')
319
+ });
320
+ }
321
+ return;
322
+ }
323
+ let codes = months.get(name);
324
+ if (codes == null) {
325
+ codes = new Set();
326
+ months.set(name, codes);
327
+ }
328
+ codes.add(code);
329
+ };
330
+ const sampled = sampleMonths(calendar);
331
+ const monthWidths = [LONG, {
332
+ year: 'numeric',
333
+ month: 'short',
334
+ day: 'numeric'
335
+ }, NUMERIC, {
336
+ month: 'long'
337
+ }, {
338
+ month: 'short'
339
+ }];
340
+ const baseText = new Map();
341
+ for (const month of sampled) {
342
+ for (const loc of locales) {
343
+ monthWidths.forEach((options, width) => {
344
+ const text = partsOf(loc, calendar, options, month.mid).find(p => p.type === 'month')?.value;
345
+ if (text == null) {
346
+ return;
347
+ }
348
+ const baseKey = `${loc}|${width}|${month.code.slice(0, 3)}`;
349
+ if (month.code.endsWith('L')) {
350
+ // A leap month written as its common month plus a marker ("闰六月").
351
+ const base = baseText.get(baseKey);
352
+ if (base != null && text.includes(base) && !/\d/.test(base)) {
353
+ const marker = norm(text.replace(base, ''));
354
+ if (marker) {
355
+ leapMarkers.add(marker);
356
+ return;
357
+ }
358
+ }
359
+ } else {
360
+ baseText.set(baseKey, text);
361
+ }
362
+ addMonth(text, month);
363
+ });
364
+ }
365
+ }
366
+ const literalFormats = [];
367
+ for (const options of [NUMERIC, LONG, SHARED_DATE_FORMAT_OPTIONS.date, SHARED_DATE_FORMAT_OPTIONS.date_weekday, LONG_WITH_WEEKDAY]) {
368
+ literalFormats.push(options, displayOptions(locale, calendar, options));
369
+ }
370
+ const literalDates = sampled.slice(0, 14).map(m => m.mid);
371
+ for (const loc of locales) {
372
+ for (const options of literalFormats) {
373
+ for (const pd of literalDates) {
374
+ const parts = partsOf(loc, calendar, options, pd);
375
+ for (const [k, part] of parts.entries()) {
376
+ if (part.type === 'literal' || partType(part) === 'yearName') {
377
+ addSkip(part.value);
378
+ }
379
+ if (part.type === 'literal' && parts[k - 1]?.type === 'year') {
380
+ addSkip(part.value, yearMarkers);
381
+ }
382
+ }
383
+ if (loc === locale) {
384
+ const tail = parts.at(-1);
385
+ if (tail?.type === 'literal') {
386
+ const trailer = norm(tail.value).replace(/\s+/g, '');
387
+ if (ONLY_SEPARATORS.test(trailer)) {
388
+ trailers.add(trailer);
389
+ }
390
+ }
391
+ }
392
+ }
393
+ }
394
+ for (let day = 0; day < 7; day++) {
395
+ const pd = {
396
+ year: 2026,
397
+ month: 11,
398
+ day: 1 + day
399
+ };
400
+ for (const options of WEEKDAY_FORMATS) {
401
+ const text = partsOf(loc, calendar, options, pd).find(p => p.type === 'weekday')?.value;
402
+ if (text != null) {
403
+ addSkip(text);
404
+ addSkip(text, weekdays);
405
+ // Vietnamese writes a weekday as a word and a number: "Thứ 2".
406
+ if (/\d/.test(norm(text))) {
407
+ skip.add(norm(text));
408
+ }
409
+ }
410
+ }
411
+ }
412
+ }
413
+ const hint = displayOptions(locale, calendar, NUMERIC);
414
+ for (const part of partsOf(locale, calendar, hint, literalDates[0])) {
415
+ const separator = norm(part.value).replace(/\s+/g, '');
416
+ if (part.type === 'literal' && separator) {
417
+ separators.add(separator);
418
+ }
419
+ }
420
+ if (LUNISOLAR.has(calendar)) {
421
+ // Year names cycle every 60 years.
422
+ for (let year = 1996; year < 2057; year++) {
423
+ for (const loc of locales) {
424
+ for (const part of partsOf(loc, calendar, LONG, {
425
+ year,
426
+ month: 6,
427
+ day: 15
428
+ })) {
429
+ if (partType(part) === 'yearName') {
430
+ addSkip(part.value);
431
+ }
432
+ }
433
+ }
434
+ }
435
+ }
436
+ const eraArithmetic = new Map();
437
+ const eraWidths = calendar === 'japanese' ? ['long', 'short', 'narrow'] : ['long', 'short'];
438
+ for (const [code, iso] of Object.entries(ERA_SAMPLES[calendar] ?? {})) {
439
+ const sample = isoToPlainDate(iso);
440
+ for (const loc of locales) {
441
+ // A full date can spell the era differently, such as French "EB".
442
+ for (const options of [...eraWidths.map(width => ERA_WIDTHS[width]), ...literalFormats]) {
443
+ const text = partsOf(loc, calendar, options, sample).find(p => p.type === 'era')?.value;
444
+ if (text != null && norm(text)) {
445
+ eras.set(norm(text), code);
446
+ }
447
+ }
448
+ }
449
+ const eraYear = pd => calendarEraYear('en', calendar, pd).year;
450
+ const year = eraYear(sample);
451
+ const isForward = eraYear({
452
+ ...sample,
453
+ year: sample.year + 1
454
+ }) > year;
455
+ const base = isForward ? sample.year - year : sample.year + year;
456
+ eraArithmetic.set(code, {
457
+ base,
458
+ isForward
459
+ });
460
+ const firstYear = {
461
+ year: isForward ? base + 1 : base - 1,
462
+ month: 12,
463
+ day: 31
464
+ };
465
+ // Some locales write era year 1 as a word, such as Japanese 元.
466
+ if (isGregorianAligned(calendar) && firstYear.year > 0) {
467
+ const text = partsOf(locale, calendar, LONG_WITH_ERA, firstYear).find(p => p.type === 'year')?.value;
468
+ if (text != null && !/\d/.test(norm(text))) {
469
+ yearAliases.set(norm(text), '1');
470
+ }
471
+ }
472
+ }
473
+ if (calendar === 'japanese') {
474
+ eraArithmetic.set('ce', {
475
+ base: 0,
476
+ isForward: true
477
+ });
478
+ }
479
+ for (const marker of leapMarkers) {
480
+ skip.delete(marker);
481
+ }
482
+ for (const word of [...months.keys(), ...eras.keys(), ...yearAliases.keys()]) {
483
+ skip.delete(word);
484
+ }
485
+
486
+ // Whether a typed month number is the month's position in its year (Hebrew)
487
+ // or its code number (Chinese). Probed with a locale that writes numbers.
488
+ let isNumericMonthOrdinal = false;
489
+ const shifted = sampled.find(m => m.ordinal !== Number(m.code.slice(1, 3)));
490
+ if (shifted != null) {
491
+ const text = partsOf('sv', calendar, NUMERIC, shifted.mid).find(p => p.type === 'month')?.value;
492
+ isNumericMonthOrdinal = Number(normalizeDateText(text ?? '', 'sv').replace(/\D+/g, '')) === shifted.ordinal;
493
+ }
494
+ const vocabularySet = new Set([...months.keys(), ...eras.keys(), ...skip, ...leapMarkers, ...yearAliases.keys()]);
495
+ const sample = {
496
+ year: 2026,
497
+ month: 11,
498
+ day: 2
499
+ };
500
+ return {
501
+ locale,
502
+ calendar,
503
+ order: fieldOrder(partsOf(locale, calendar, NUMERIC, sample)),
504
+ nameOrder: fieldOrder(partsOf(locale, calendar, LONG, sample)),
505
+ months,
506
+ monthTemplates: [...templates.values()].sort((a, b) => b.pre.length + b.post.length - (a.pre.length + a.post.length)),
507
+ leapMarkers,
508
+ eras,
509
+ yearAliases,
510
+ trailers,
511
+ yearMarkers,
512
+ separators,
513
+ weekdays,
514
+ vocabulary: [...vocabularySet].sort((a, b) => b.length - a.length),
515
+ vocabularySet,
516
+ isNumericMonthOrdinal,
517
+ eraArithmetic
518
+ };
519
+ }
520
+
521
+ /** The era name and era year Intl writes for a date. */
522
+ function calendarEraYear(locale, calendar, pd) {
523
+ const parts = partsOf(locale, calendar, ERA_AND_YEAR, pd);
524
+ return {
525
+ era: parts.find(p => p.type === 'era')?.value ?? '',
526
+ year: Number(normalizeDateText(parts.find(p => p.type === 'year' || partType(p) === 'relatedYear')?.value ?? '', locale))
527
+ };
528
+ }
529
+
530
+ // =============================================================================
531
+ // Tokens
532
+ // =============================================================================
533
+
534
+ function tokenize(s, lex, isDigitNameRead = true) {
535
+ const out = [];
536
+ let hasDigitName = false;
537
+ let i = 0;
538
+ const end = s.trimEnd().length;
539
+ while (i < end) {
540
+ const ch = s[i];
541
+ if (/\s/.test(ch)) {
542
+ i++;
543
+ continue;
544
+ }
545
+ const template = matchTemplate(s, i, lex);
546
+ if (template != null) {
547
+ out.push(template.token);
548
+ i = template.end;
549
+ continue;
550
+ }
551
+ const digitName = isDigitNameRead && /\d/.test(ch) && matchWord(s, i, lex);
552
+ if (digitName) {
553
+ out.push(wordToken(digitName, lex));
554
+ hasDigitName = true;
555
+ i += digitName.length;
556
+ continue;
557
+ }
558
+ if (/\d/.test(ch)) {
559
+ let j = i;
560
+ while (j < s.length && /\d/.test(s[j])) {
561
+ j++;
562
+ }
563
+ out.push({
564
+ t: 'num',
565
+ v: s.slice(i, j)
566
+ });
567
+ i = j;
568
+ continue;
569
+ }
570
+ const word = matchWord(s, i, lex);
571
+ if (word != null) {
572
+ out.push(wordToken(word, lex));
573
+ i += word.length;
574
+ continue;
575
+ }
576
+ if (SEPARATOR.test(ch)) {
577
+ let j = i;
578
+ while (j < end && (SEPARATOR.test(s[j]) || /\s/.test(s[j]))) {
579
+ j++;
580
+ }
581
+ out.push({
582
+ t: 'sep',
583
+ v: s.slice(i, j).replace(/\s+/g, '')
584
+ });
585
+ i = j;
586
+ continue;
587
+ }
588
+ let j = i;
589
+ while (j < end && LETTER.test(s[j])) {
590
+ j++;
591
+ }
592
+ const run = s.slice(i, j);
593
+ const joined = matchJoinedWord(s, i, lex);
594
+ if (joined != null) {
595
+ out.push(wordToken(joined, lex));
596
+ i += joined.length;
597
+ continue;
598
+ }
599
+ const monthCodes = monthByPrefix(run, lex);
600
+ if (monthCodes != null) {
601
+ out.push({
602
+ t: 'month',
603
+ codes: monthCodes
604
+ });
605
+ i = j;
606
+ continue;
607
+ }
608
+ if (j >= end && run && lex.vocabulary.some(w => w.startsWith(run))) {
609
+ return 'incomplete';
610
+ }
611
+ return 'unreadable';
612
+ }
613
+ // Latvian "1. adars" is a month, and also day 1 of "adars". It is the day
614
+ // when no other number can be the day. A number before the year word, as in
615
+ // "26. g.", is the year.
616
+ const canBeDay = (token, k) => {
617
+ const next = out.slice(k + 1).find(t => t.t !== 'sep');
618
+ const isYear = next?.t === 'word' && next.isYearMarker === true;
619
+ return token.t === 'num' && Number(token.v) <= 31 && !isYear;
620
+ };
621
+ if (hasDigitName && !out.some(canBeDay)) {
622
+ return tokenize(s, lex, false);
623
+ }
624
+ return out;
625
+ }
626
+ function matchTemplate(s, i, lex) {
627
+ for (const template of lex.monthTemplates) {
628
+ if (!s.startsWith(template.pre, i)) {
629
+ continue;
630
+ }
631
+ const digits = /^\d+/.exec(s.slice(i + template.pre.length));
632
+ if (digits == null) {
633
+ continue;
634
+ }
635
+ const after = i + template.pre.length + digits[0].length;
636
+ if (template.post && !s.startsWith(template.post, after)) {
637
+ continue;
638
+ }
639
+ if (!template.post && !template.pre) {
640
+ continue;
641
+ }
642
+ return {
643
+ token: {
644
+ t: 'monthNum',
645
+ v: digits[0],
646
+ isLeap: template.isLeap
647
+ },
648
+ end: after + template.post.length
649
+ };
650
+ }
651
+ return null;
652
+ }
653
+
654
+ /** The longest known word at `i` that ends where a word may end. */
655
+ function matchWord(s, i, lex) {
656
+ for (const word of lex.vocabulary) {
657
+ if (!s.startsWith(word, i)) {
658
+ continue;
659
+ }
660
+ const next = s[i + word.length] ?? '';
661
+ const last = word[word.length - 1];
662
+ if (!LETTER.test(next) || SPACELESS.test(next) || SPACELESS.test(last) || !LETTER.test(last)) {
663
+ return word;
664
+ }
665
+ }
666
+ return null;
667
+ }
668
+
669
+ /**
670
+ * A known word joined to the next one with no space, such as Hebrew ב before
671
+ * a month name or a leap marker after it ("Eighth Monthbis").
672
+ */
673
+ function matchJoinedWord(s, i, lex) {
674
+ for (const word of lex.vocabulary) {
675
+ if (!s.startsWith(word, i)) {
676
+ continue;
677
+ }
678
+ const next = i + word.length;
679
+ if (lex.vocabulary.some(w => s.startsWith(w, next))) {
680
+ return word;
681
+ }
682
+ }
683
+ return null;
684
+ }
685
+ function wordToken(word, lex) {
686
+ const isWeekday = lex.weekdays.has(word.replace(NOT_WORDS, ''));
687
+ const codes = lex.months.get(word);
688
+ if (codes != null) {
689
+ return {
690
+ t: 'month',
691
+ codes,
692
+ isWeekday
693
+ };
694
+ }
695
+ const era = lex.eras.get(word);
696
+ if (era != null) {
697
+ return {
698
+ t: 'era',
699
+ code: era,
700
+ isWeekday
701
+ };
702
+ }
703
+ if (lex.leapMarkers.has(word)) {
704
+ return {
705
+ t: 'leap'
706
+ };
707
+ }
708
+ const alias = lex.yearAliases.get(word);
709
+ if (alias != null) {
710
+ return {
711
+ t: 'num',
712
+ v: alias,
713
+ isAlias: true
714
+ };
715
+ }
716
+ return {
717
+ t: 'word',
718
+ isYearMarker: lex.yearMarkers.has(word)
719
+ };
720
+ }
721
+
722
+ /** The month a typed abbreviation names when it starts only one month name. */
723
+ function monthByPrefix(run, lex) {
724
+ if (run.length < 3) {
725
+ return null;
726
+ }
727
+ let found = null;
728
+ for (const [name, codes] of lex.months) {
729
+ if (name.startsWith(run)) {
730
+ if (found != null && !sameCodes(found, codes)) {
731
+ return null;
732
+ }
733
+ found = codes;
734
+ }
735
+ }
736
+ return found;
737
+ }
738
+
739
+ /**
740
+ * A weekday word can also be a month or era name, such as French "mar.". When
741
+ * the text has another month or era, the first such word is the weekday.
742
+ */
743
+ function weekdaysAsWords(tokens) {
744
+ let out = tokens;
745
+ for (const kinds of [['month', 'monthNum'], ['era']]) {
746
+ const named = out.filter(t => kinds.includes(t.t));
747
+ const weekday = named.find(t => 'isWeekday' in t && t.isWeekday);
748
+ if (named.length > 1 && weekday != null) {
749
+ out = out.map(t => t === weekday ? {
750
+ t: 'word'
751
+ } : t);
752
+ }
753
+ }
754
+ return out;
755
+ }
756
+ function sameCodes(a, b) {
757
+ return a.size === b.size && [...a].every(code => b.has(code));
758
+ }
759
+
760
+ // =============================================================================
761
+ // Parsing
762
+ // =============================================================================
763
+
764
+ const INCOMPLETE = {
765
+ kind: 'incomplete'
766
+ };
767
+ const UNREADABLE = {
768
+ kind: 'unreadable'
769
+ };
770
+ const EMPTY = {
771
+ kind: 'empty'
772
+ };
773
+ /**
774
+ * Reads typed text as a date in the lexicon's calendar. Values are Gregorian.
775
+ * The result tells an empty field, part of a date, unreadable text, a date the
776
+ * calendar does not have, a date out of range, and a date apart.
777
+ */
778
+ export function parseCalendarDate(text, lex, options = {}) {
779
+ const s = normalizeDateText(text, lex.locale).trim();
780
+ if (!s) {
781
+ return EMPTY;
782
+ }
783
+ const {
784
+ isDateDisabled,
785
+ isoIsGregorian = false
786
+ } = options;
787
+ if (isoIsGregorian) {
788
+ const iso = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(s);
789
+ if (iso != null) {
790
+ return finish(gregorianDate(+iso[1], +iso[2], +iso[3]), true, isDateDisabled);
791
+ }
792
+ }
793
+ const read = tokenize(s, lex);
794
+ if (read === 'incomplete' || read === 'unreadable') {
795
+ return read === 'incomplete' ? INCOMPLETE : UNREADABLE;
796
+ }
797
+ const tokens = weekdaysAsWords(read);
798
+ const nums = tokens.filter(token => token.t === 'num');
799
+ const monthTokens = tokens.filter(token => token.t === 'month' || token.t === 'monthNum');
800
+ const eraCodes = new Set(tokens.flatMap(token => token.t === 'era' ? [token.code] : []));
801
+ const isLeap = tokens.some(token => token.t === 'leap' || token.t === 'monthNum' && token.isLeap);
802
+ if (monthTokens.length > 1 || eraCodes.size > 1) {
803
+ return UNREADABLE;
804
+ }
805
+ if (nums.length === 0 && monthTokens.length === 0) {
806
+ return eraCodes.size > 0 ? INCOMPLETE : UNREADABLE;
807
+ }
808
+ const typedEra = eraCodes.size === 1 ? [...eraCodes][0] : undefined;
809
+ const assigned = new Map();
810
+ let monthCode;
811
+ let monthOrdinal;
812
+ const monthToken = monthTokens[0];
813
+ if (monthToken != null) {
814
+ if (monthToken.t === 'month') {
815
+ if (monthToken.codes.size !== 1) {
816
+ return UNREADABLE;
817
+ }
818
+ monthCode = [...monthToken.codes][0];
819
+ } else if (lex.isNumericMonthOrdinal) {
820
+ monthOrdinal = Number(monthToken.v);
821
+ } else {
822
+ monthCode = `M${monthToken.v.padStart(2, '0')}`;
823
+ }
824
+ if (nums.length === 0 || nums.length > 2) {
825
+ return nums.length === 0 ? INCOMPLETE : UNREADABLE;
826
+ }
827
+ let rest = lex.nameOrder.filter(field => field !== 'month');
828
+ const long = nums.filter(n => n.v.length >= 3 && !n.isAlias);
829
+ if (nums.length === 1) {
830
+ rest = long.length === 1 ? ['year'] : ['day'];
831
+ } else if (long.length === 1) {
832
+ // With a month name, a number of three or more digits is the year.
833
+ rest = nums[0] === long[0] ? ['year', 'day'] : ['day', 'year'];
834
+ }
835
+ nums.forEach((n, k) => assigned.set(n, rest[k]));
836
+ } else {
837
+ if (nums.length < 2) {
838
+ return INCOMPLETE;
839
+ }
840
+ if (nums.length > 3 || !sameSeparators(tokens, lex)) {
841
+ return UNREADABLE;
842
+ }
843
+ let order = nums.length === 2 ? lex.order.filter(field => field !== 'year') : lex.order;
844
+ if (nums.length === 3 && order[0] !== 'year' && nums[0].v.length >= 3) {
845
+ // ISO-shaped text: a leading long number is the year.
846
+ order = ['year', 'month', 'day'];
847
+ }
848
+ if (nums.length === 2 && nums.some(n => n.v.length >= 3)) {
849
+ return INCOMPLETE;
850
+ }
851
+ nums.forEach((n, k) => assigned.set(n, order[k]));
852
+ }
853
+ const tokenOf = field => nums.find(n => assigned.get(n) === field);
854
+ const dayToken = tokenOf('day');
855
+ const yearToken = tokenOf('year');
856
+ const monthNumToken = tokenOf('month');
857
+ if (dayToken == null) {
858
+ return INCOMPLETE;
859
+ }
860
+ if (monthNumToken != null) {
861
+ if (lex.isNumericMonthOrdinal) {
862
+ monthOrdinal = Number(monthNumToken.v);
863
+ } else {
864
+ monthCode = `M${String(Number(monthNumToken.v)).padStart(2, '0')}`;
865
+ }
866
+ }
867
+ if (monthCode != null && isLeap && !monthCode.endsWith('L')) {
868
+ monthCode += 'L';
869
+ }
870
+ const day = Number(dayToken.v);
871
+ const monthNumber = monthOrdinal ?? Number(monthCode?.slice(1, 3) ?? 0);
872
+ if (day < 1 || day > 31 || monthNumber < 1 || monthNumber > 13) {
873
+ // A lone 0 starts a two-digit day or month such as 07.
874
+ const startsField = [dayToken, monthNumToken].some(t => t?.v === '0');
875
+ return startsField ? INCOMPLETE : UNREADABLE;
876
+ }
877
+ const today = options.today ?? plainDateToday();
878
+ const dateFields = {
879
+ day
880
+ };
881
+ if (monthCode != null) {
882
+ dateFields.monthCode = monthCode;
883
+ } else {
884
+ dateFields.month = monthOrdinal;
885
+ }
886
+ let isYearComplete = false;
887
+ if (yearToken == null) {
888
+ applyDefaultYear(dateFields, lex, today);
889
+ } else {
890
+ const digits = yearToken.isAlias ? 1 : yearToken.v.length;
891
+ const year = Number(yearToken.v);
892
+ const isYearLast = lastNumber(tokens) === yearToken;
893
+ const {
894
+ calendar
895
+ } = lex;
896
+ if (typedEra != null) {
897
+ dateFields.era = typedEra;
898
+ dateFields.eraYear = year;
899
+ isYearComplete = true;
900
+ } else if (calendar === 'japanese' && digits <= 2) {
901
+ const era = currentEra(lex, today);
902
+ if (era == null) {
903
+ return UNREADABLE;
904
+ }
905
+ dateFields.era = era;
906
+ dateFields.eraYear = year;
907
+ isYearComplete = !isYearLast;
908
+ } else if (calendar === 'japanese' && digits === 4) {
909
+ dateFields.era = 'ce';
910
+ dateFields.eraYear = year;
911
+ isYearComplete = true;
912
+ } else if (calendar === 'roc') {
913
+ dateFields.era = 'roc';
914
+ dateFields.eraYear = year;
915
+ isYearComplete = digits >= 4 || !isYearLast;
916
+ } else if (digits === 2) {
917
+ dateFields.year = windowedYear(year, calendarYearOf(calendar, today));
918
+ } else if (digits >= 4) {
919
+ dateFields.year = year;
920
+ isYearComplete = true;
921
+ } else {
922
+ return INCOMPLETE;
923
+ }
924
+ }
925
+ const date = resolveDate(lex, dateFields);
926
+ const isComplete = yearToken != null && isYearComplete && isLastFieldClosed(tokens, lex, assigned, date);
927
+ return finish(date, isComplete, isDateDisabled);
928
+ }
929
+ function finish(date, isComplete, isDateDisabled) {
930
+ if (date == null) {
931
+ return {
932
+ kind: 'nonexistent',
933
+ isComplete
934
+ };
935
+ }
936
+ if (isDateDisabled?.(date)) {
937
+ return {
938
+ kind: 'outOfRange',
939
+ date,
940
+ isComplete
941
+ };
942
+ }
943
+ return {
944
+ kind: 'value',
945
+ date,
946
+ isComplete
947
+ };
948
+ }
949
+
950
+ /**
951
+ * Whether the numbers share one separator. Two separators of the locale's own
952
+ * numeric pattern also match, such as Hindi Buddhist "1/1`/2443".
953
+ */
954
+ function sameSeparators(tokens, lex) {
955
+ let previous = null;
956
+ let seenNumber = false;
957
+ let pending = null;
958
+ for (const token of tokens) {
959
+ if (token.t === 'num') {
960
+ if (seenNumber) {
961
+ const separator = pending ?? '';
962
+ if (previous != null && separator !== previous && !(lex.separators.has(separator) && lex.separators.has(previous))) {
963
+ return false;
964
+ }
965
+ previous = separator;
966
+ }
967
+ seenNumber = true;
968
+ pending = null;
969
+ } else if (token.t === 'sep') {
970
+ pending = token.v;
971
+ } else {
972
+ pending = null;
973
+ seenNumber = false;
974
+ previous = null;
975
+ }
976
+ }
977
+ return true;
978
+ }
979
+ function lastNumber(tokens) {
980
+ const last = tokens.filter(token => token.t !== 'sep').at(-1);
981
+ return last?.t === 'num' ? last : undefined;
982
+ }
983
+
984
+ /**
985
+ * Whether the text has stopped growing: no separator trails it, and its last
986
+ * field cannot take another digit.
987
+ */
988
+ function isLastFieldClosed(tokens, lex, assigned, date) {
989
+ const last = tokens.at(-1);
990
+ if (last == null) {
991
+ return false;
992
+ }
993
+ if (last.t === 'sep') {
994
+ return lex.trailers.has(last.v);
995
+ }
996
+ if (last.t !== 'num') {
997
+ return true;
998
+ }
999
+ const field = assigned.get(last);
1000
+ if (field === 'year' || last.v.length >= 2) {
1001
+ return true;
1002
+ }
1003
+ const value = Number(last.v);
1004
+ if (field === 'day') {
1005
+ // Not the month's own length: a 3 can start a 30 that the month lacks,
1006
+ // and the field must then report that day, not the 3rd.
1007
+ return value * 10 > 31;
1008
+ }
1009
+ const monthsInYear = date == null ? 13 : calendarMonthsInYear(lex.calendar, date);
1010
+ return value * 10 > monthsInYear;
1011
+ }
1012
+
1013
+ /**
1014
+ * Resolves a two-digit year to the century that puts it at most 80 years
1015
+ * before and 19 years after the current year.
1016
+ */
1017
+ function windowedYear(twoDigits, current) {
1018
+ let year = current - current % 100 + twoDigits;
1019
+ if (year > current + 19) {
1020
+ year -= 100;
1021
+ } else if (year < current - 80) {
1022
+ year += 100;
1023
+ }
1024
+ return year;
1025
+ }
1026
+ function currentEra(lex, today) {
1027
+ const {
1028
+ era
1029
+ } = calendarEraYear('en', lex.calendar, today);
1030
+ return lex.eras.get(normalizeDateText(era, lex.locale).trim());
1031
+ }
1032
+ function applyDefaultYear(fields, lex, today) {
1033
+ if (lex.eraArithmetic.size > 0 && !WITHOUT_ERA.has(lex.calendar)) {
1034
+ const {
1035
+ era,
1036
+ year
1037
+ } = calendarEraYear('en', lex.calendar, today);
1038
+ const code = lex.eras.get(normalizeDateText(era, lex.locale).trim());
1039
+ if (code != null) {
1040
+ fields.era = code;
1041
+ fields.eraYear = year;
1042
+ return;
1043
+ }
1044
+ }
1045
+ fields.year = calendarYearOf(lex.calendar, today);
1046
+ }
1047
+ function gregorianDate(year, month, day) {
1048
+ if (year < 1 || year > 9999 || month < 1 || month > 12 || day < 1 || day > getDaysInMonth(year, month)) {
1049
+ return null;
1050
+ }
1051
+ return {
1052
+ year,
1053
+ month,
1054
+ day
1055
+ };
1056
+ }
1057
+
1058
+ /** The Gregorian date for calendar fields, or null when it does not exist. */
1059
+ function resolveDate(lex, fields) {
1060
+ const {
1061
+ calendar
1062
+ } = lex;
1063
+ if (!isGregorianAligned(calendar)) {
1064
+ const defined = Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined));
1065
+ const date = calendarDateFromFields(calendar, defined);
1066
+ return date != null && date.year >= 1 && date.year <= 9999 ? date : null;
1067
+ }
1068
+ if (fields.monthCode?.endsWith('L')) {
1069
+ return null;
1070
+ }
1071
+ const month = fields.month ?? Number(fields.monthCode?.slice(1, 3));
1072
+ let gregorianYear;
1073
+ if (fields.era != null) {
1074
+ const arithmetic = lex.eraArithmetic.get(fields.era);
1075
+ if (arithmetic == null || fields.eraYear == null || fields.eraYear < 1) {
1076
+ return null;
1077
+ }
1078
+ gregorianYear = arithmetic.isForward ? arithmetic.base + fields.eraYear : arithmetic.base - fields.eraYear;
1079
+ } else {
1080
+ const defaultEra = calendar === 'buddhist' ? 'be' : 'ce';
1081
+ const arithmetic = lex.eraArithmetic.get(defaultEra);
1082
+ gregorianYear = (arithmetic?.base ?? 0) + (fields.year ?? 0);
1083
+ }
1084
+ const date = gregorianDate(gregorianYear, month, fields.day);
1085
+ if (date == null || calendar !== 'japanese' || fields.era === 'ce') {
1086
+ return date;
1087
+ }
1088
+ // Each Japanese era ends on a set day; a year past it is not in that era.
1089
+ const written = calendarEraYear('en', calendar, date);
1090
+ const era = lex.eras.get(normalizeDateText(written.era, lex.locale).trim());
1091
+ return era === fields.era && written.year === fields.eraYear ? date : null;
1092
+ }
1093
+
1094
+ // =============================================================================
1095
+ // Display
1096
+ // =============================================================================
1097
+
1098
+ const displayOptionCache = new WeakMap();
1099
+ const eraChangeCache = new Map();
1100
+
1101
+ /**
1102
+ * Whether the era changes between 1900 and 2100. Only then can a year without
1103
+ * its era read as two dates.
1104
+ */
1105
+ function hasEraChange(calendar) {
1106
+ let result = eraChangeCache.get(calendar);
1107
+ if (result == null) {
1108
+ const eraOf = date => calendarEraYear('en', calendar, date).era;
1109
+ result = eraOf({
1110
+ year: 1900,
1111
+ month: 1,
1112
+ day: 1
1113
+ }) !== eraOf({
1114
+ year: 2100,
1115
+ month: 12,
1116
+ day: 31
1117
+ });
1118
+ eraChangeCache.set(calendar, result);
1119
+ }
1120
+ return result;
1121
+ }
1122
+
1123
+ /**
1124
+ * Adds the era to a format that omits it, so a year never reads as a
1125
+ * Gregorian year. Keeps the locale's own pattern when the era would reorder
1126
+ * the fields. Where the era changes, it uses a narrow era that keeps the
1127
+ * order instead, such as Amharic Japanese "1/1/8 R".
1128
+ */
1129
+ function displayOptions(locale, calendar, options) {
1130
+ if (WITHOUT_ERA.has(calendar)) {
1131
+ return options;
1132
+ }
1133
+ let byLocale = displayOptionCache.get(options);
1134
+ if (byLocale == null) {
1135
+ byLocale = new Map();
1136
+ displayOptionCache.set(options, byLocale);
1137
+ }
1138
+ const key = `${locale}|${calendar}`;
1139
+ let result = byLocale.get(key);
1140
+ if (result == null) {
1141
+ const sample = {
1142
+ year: 2026,
1143
+ month: 11,
1144
+ day: 2
1145
+ };
1146
+ const parts = partsOf(locale, calendar, options, sample);
1147
+ result = options;
1148
+ const order = fieldOrder(parts).join();
1149
+ if (!parts.some(p => p.type === 'era')) {
1150
+ const widths = hasEraChange(calendar) ? ['short', 'narrow'] : ['short'];
1151
+ for (const era of widths) {
1152
+ const withEra = {
1153
+ ...options,
1154
+ era
1155
+ };
1156
+ const eraParts = partsOf(locale, calendar, withEra, sample);
1157
+ if (fieldOrder(eraParts).join() === order) {
1158
+ result = withEra;
1159
+ break;
1160
+ }
1161
+ }
1162
+ }
1163
+ byLocale.set(key, result);
1164
+ }
1165
+ return result;
1166
+ }
1167
+ function formatInCalendar(pd, options, locale, calendar) {
1168
+ if (LUNISOLAR.has(calendar)) {
1169
+ return formatCalendarDate(calendar, pd, options, locale, {
1170
+ relatedYear: true
1171
+ });
1172
+ }
1173
+ const display = displayOptions(locale, calendar, options);
1174
+ const text = plainDateFormat(pd, {
1175
+ ...display,
1176
+ calendar
1177
+ }, locale);
1178
+ // When every era width reorders the fields, such as the Amharic short-month
1179
+ // date, the text has no era. Text without an era reads in the latest era.
1180
+ // So a date of an earlier era adds the era. It goes at the start or the
1181
+ // end, as in the era format.
1182
+ const eraOf = date => calendarEraYear('en', calendar, date).era;
1183
+ if (!hasEraChange(calendar) || eraOf(pd) === eraOf({
1184
+ year: 9999,
1185
+ month: 12,
1186
+ day: 31
1187
+ }) || partsOf(locale, calendar, display, pd).some(p => p.type === 'era')) {
1188
+ return text;
1189
+ }
1190
+ const withEra = partsOf(locale, calendar, {
1191
+ ...options,
1192
+ era: 'short'
1193
+ }, pd);
1194
+ const at = withEra.findIndex(p => p.type === 'era');
1195
+ const era = withEra.slice(at === 0 ? 0 : at - 1, at === 0 ? 2 : at + 1).map(p => p.value).join('');
1196
+ return at === 0 ? era + text : text + era;
1197
+ }
1198
+
1199
+ /**
1200
+ * The committed text of a date field in a calendar. Gregorian text is the
1201
+ * shared Timestamp date text; `system_date` is always the ISO date.
1202
+ */
1203
+ export function formatCalendarDateText(pd, format, locale, calendar) {
1204
+ const resolved = textCalendar(calendar);
1205
+ if (format === 'system_date' || resolved === 'gregory') {
1206
+ return formatSharedDate(pd, format, locale);
1207
+ }
1208
+ return formatInCalendar(pd, SHARED_DATE_FORMAT_OPTIONS[format], locale, resolved);
1209
+ }
1210
+
1211
+ /** An example date in the calendar's numeric pattern, with its era. */
1212
+ export function formatCalendarDateHint(pd, locale, calendar) {
1213
+ return formatInCalendar(pd, NUMERIC, locale, textCalendar(calendar));
1214
+ }
1215
+
1216
+ /** The calendar's name in the locale, such as "Persian Calendar". */
1217
+ export function calendarDisplayName(calendar, locale) {
1218
+ try {
1219
+ return new Intl.DisplayNames(locale, {
1220
+ type: 'calendar'
1221
+ }).of(calendar) ?? calendar;
1222
+ } catch {
1223
+ return calendar;
1224
+ }
1225
+ }