@astryxdesign/core 0.7.7 → 0.7.8-canary.36cde5e

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 (581) hide show
  1. package/dist/AlertDialog/AlertDialog.d.ts +4 -1
  2. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  3. package/dist/AlertDialog/AlertDialog.js +46 -6
  4. package/dist/AppShell/AppShell.d.ts.map +1 -1
  5. package/dist/AppShell/AppShell.js +5 -0
  6. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  7. package/dist/BottomSheet/BottomSheet.js +1 -0
  8. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  9. package/dist/BottomSheet/BottomSheetPanel.js +25 -4
  10. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
  11. package/dist/BottomSheet/BottomSheetSwitcher.js +5 -0
  12. package/dist/BottomSheet/useMobileKeyboard.d.ts.map +1 -1
  13. package/dist/BottomSheet/useMobileKeyboard.js +6 -0
  14. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  15. package/dist/BottomSheet/useSheetGestures.js +12 -1
  16. package/dist/Button/Button.d.ts.map +1 -1
  17. package/dist/Button/Button.js +17 -1
  18. package/dist/Calendar/Calendar.d.ts.map +1 -1
  19. package/dist/Calendar/Calendar.js +15 -16
  20. package/dist/Carousel/Carousel.d.ts.map +1 -1
  21. package/dist/Carousel/Carousel.js +2 -0
  22. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  23. package/dist/Chat/ChatComposerInput.js +4 -0
  24. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  25. package/dist/Chat/ChatMessageList.js +2 -1
  26. package/dist/Chat/useChatDictation.d.ts.map +1 -1
  27. package/dist/Chat/useChatDictation.js +2 -0
  28. package/dist/Chat/useChatNewMessages.js +1 -1
  29. package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
  30. package/dist/Chat/useChatStreamScroll.js +2 -0
  31. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  32. package/dist/Chat/useSpeechRecognition.js +3 -0
  33. package/dist/Chat/useTriggerMenu.js +1 -1
  34. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  35. package/dist/CheckboxInput/CheckboxInput.js +17 -12
  36. package/dist/CodeBlock/CodeBlock.d.ts +10 -1
  37. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  38. package/dist/CodeBlock/CodeBlock.js +28 -11
  39. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  40. package/dist/CommandPalette/CommandPalette.js +2 -0
  41. package/dist/CommandPalette/CommandPaletteItem.d.ts.map +1 -1
  42. package/dist/CommandPalette/CommandPaletteItem.js +2 -0
  43. package/dist/ComplexSelector/ComplexSelector.d.ts +4 -1
  44. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  45. package/dist/ComplexSelector/ComplexSelector.js +14 -4
  46. package/dist/ContextMenu/ContextMenu.js +2 -2
  47. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  48. package/dist/DateInput/MonthScroller.js +5 -2
  49. package/dist/DateInput/PickerWheel.d.ts +19 -0
  50. package/dist/DateInput/PickerWheel.d.ts.map +1 -0
  51. package/dist/DateInput/PickerWheel.js +625 -0
  52. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  53. package/dist/DateInput/TouchDateField.js +1 -0
  54. package/dist/DateInput/Wheel.d.ts +18 -37
  55. package/dist/DateInput/Wheel.d.ts.map +1 -1
  56. package/dist/DateInput/Wheel.js +84 -113
  57. package/dist/DateInput/useOwnScrollGesture.d.ts +10 -0
  58. package/dist/DateInput/useOwnScrollGesture.d.ts.map +1 -1
  59. package/dist/DateInput/useOwnScrollGesture.js +16 -3
  60. package/dist/DateInput/usePointerDragScroll.d.ts.map +1 -1
  61. package/dist/DateInput/usePointerDragScroll.js +2 -0
  62. package/dist/DateInput/useScrollSettle.d.ts.map +1 -1
  63. package/dist/DateInput/useScrollSettle.js +3 -0
  64. package/dist/DateInput/useWheelListbox.d.ts +59 -0
  65. package/dist/DateInput/useWheelListbox.d.ts.map +1 -0
  66. package/dist/DateInput/useWheelListbox.js +88 -0
  67. package/dist/DateInput/wheelOptions.d.ts +74 -0
  68. package/dist/DateInput/wheelOptions.d.ts.map +1 -0
  69. package/dist/DateInput/wheelOptions.js +98 -0
  70. package/dist/DateInput/wheelPhysics.d.ts +127 -0
  71. package/dist/DateInput/wheelPhysics.d.ts.map +1 -0
  72. package/dist/DateInput/wheelPhysics.js +341 -0
  73. package/dist/DateInput/wheelStrip.d.ts +92 -0
  74. package/dist/DateInput/wheelStrip.d.ts.map +1 -0
  75. package/dist/DateInput/wheelStrip.js +258 -0
  76. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
  77. package/dist/DateTimeInput/TouchDateTimeField.js +2 -0
  78. package/dist/Dialog/Dialog.d.ts.map +1 -1
  79. package/dist/Dialog/Dialog.js +9 -32
  80. package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
  81. package/dist/Drawer/useDrawerDialogPresence.js +3 -0
  82. package/dist/DropdownMenu/useMenuOverflow.d.ts.map +1 -1
  83. package/dist/DropdownMenu/useMenuOverflow.js +5 -0
  84. package/dist/Field/Field.js +2 -2
  85. package/dist/FieldStatus/useFieldStatusAnnouncement.d.ts.map +1 -1
  86. package/dist/FieldStatus/useFieldStatusAnnouncement.js +1 -0
  87. package/dist/FormLayout/FormLayout.d.ts +5 -1
  88. package/dist/FormLayout/FormLayout.d.ts.map +1 -1
  89. package/dist/HoverCard/HoverCard.d.ts +6 -4
  90. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  91. package/dist/HoverCard/HoverCard.js +48 -3
  92. package/dist/HoverCard/useHoverCard.d.ts +5 -4
  93. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  94. package/dist/HoverCard/useHoverCard.js +20 -33
  95. package/dist/Icon/Icon.d.ts +5 -1
  96. package/dist/Icon/Icon.d.ts.map +1 -1
  97. package/dist/Icon/Icon.js +5 -2
  98. package/dist/Item/useSwipeAction.d.ts.map +1 -1
  99. package/dist/Item/useSwipeAction.js +3 -0
  100. package/dist/Layer/modalOutlet.d.ts.map +1 -1
  101. package/dist/Layer/modalOutlet.js +2 -0
  102. package/dist/Layer/outsidePress.d.ts.map +1 -1
  103. package/dist/Layer/outsidePress.js +1 -0
  104. package/dist/Layer/useLayer.d.ts.map +1 -1
  105. package/dist/Layer/useLayer.js +3 -0
  106. package/dist/Layer/useLayerDismissal.d.ts.map +1 -1
  107. package/dist/Layer/useLayerDismissal.js +3 -0
  108. package/dist/Layer/usePressPin.d.ts +17 -5
  109. package/dist/Layer/usePressPin.d.ts.map +1 -1
  110. package/dist/Layer/usePressPin.js +62 -12
  111. package/dist/Layer/useTouchTrigger.d.ts.map +1 -1
  112. package/dist/Layer/useTouchTrigger.js +3 -0
  113. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  114. package/dist/Lightbox/Lightbox.js +19 -0
  115. package/dist/MobileNav/MobileNav.d.ts +3 -2
  116. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  117. package/dist/MobileNav/MobileNav.js +9 -25
  118. package/dist/Outline/useOutlineFromDOM.d.ts.map +1 -1
  119. package/dist/Outline/useOutlineFromDOM.js +3 -0
  120. package/dist/Outline/useScrollSpy.d.ts.map +1 -1
  121. package/dist/Outline/useScrollSpy.js +3 -0
  122. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  123. package/dist/OverflowList/OverflowList.js +3 -0
  124. package/dist/Popover/Popover.d.ts.map +1 -1
  125. package/dist/Popover/Popover.js +6 -0
  126. package/dist/PowerSearch/PowerSearch.d.ts +43 -4
  127. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  128. package/dist/PowerSearch/PowerSearch.js +445 -134
  129. package/dist/PowerSearch/PowerSearchBottomSheet.d.ts +102 -0
  130. package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +1 -0
  131. package/dist/PowerSearch/PowerSearchBottomSheet.js +1919 -0
  132. package/dist/PowerSearch/PowerSearchEditPopover.d.ts +35 -2
  133. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  134. package/dist/PowerSearch/PowerSearchEditPopover.js +25 -6
  135. package/dist/PowerSearch/PowerSearchFilterEditor.d.ts +1 -1
  136. package/dist/PowerSearch/PowerSearchFilterEditor.d.ts.map +1 -1
  137. package/dist/PowerSearch/PowerSearchFilterEditor.js +4 -2
  138. package/dist/PowerSearch/PowerSearchToken.d.ts +1 -1
  139. package/dist/PowerSearch/PowerSearchToken.d.ts.map +1 -1
  140. package/dist/PowerSearch/PowerSearchToken.js +7 -2
  141. package/dist/PowerSearch/PowerSearchValueEditor.d.ts +38 -3
  142. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  143. package/dist/PowerSearch/PowerSearchValueEditor.js +193 -83
  144. package/dist/PowerSearch/formatFilterValue.d.ts +18 -6
  145. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  146. package/dist/PowerSearch/formatFilterValue.js +33 -12
  147. package/dist/PowerSearch/formatTokenValue.d.ts +28 -0
  148. package/dist/PowerSearch/formatTokenValue.d.ts.map +1 -0
  149. package/dist/PowerSearch/formatTokenValue.js +162 -0
  150. package/dist/PowerSearch/powerSearchDateZone.d.ts +21 -0
  151. package/dist/PowerSearch/powerSearchDateZone.d.ts.map +1 -0
  152. package/dist/PowerSearch/powerSearchDateZone.js +37 -0
  153. package/dist/PowerSearch/powerSearchSheetUtils.d.ts +65 -0
  154. package/dist/PowerSearch/powerSearchSheetUtils.d.ts.map +1 -0
  155. package/dist/PowerSearch/powerSearchSheetUtils.js +168 -0
  156. package/dist/PowerSearch/types.d.ts +2 -0
  157. package/dist/PowerSearch/types.d.ts.map +1 -1
  158. package/dist/ProgressBar/ProgressBarTouch.d.ts.map +1 -1
  159. package/dist/ProgressBar/ProgressBarTouch.js +2 -0
  160. package/dist/RadioList/RadioList.d.ts.map +1 -1
  161. package/dist/RadioList/RadioList.js +3 -2
  162. package/dist/RadioList/RadioListItem.d.ts +1 -1
  163. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  164. package/dist/RadioList/RadioListItem.js +5 -3
  165. package/dist/Resizable/ResizeHandle.d.ts +2 -1
  166. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  167. package/dist/Resizable/ResizeHandle.js +101 -77
  168. package/dist/Resizable/createResizable.d.ts +145 -0
  169. package/dist/Resizable/createResizable.d.ts.map +1 -0
  170. package/dist/Resizable/createResizable.js +575 -0
  171. package/dist/Resizable/useResizable.d.ts +3 -3
  172. package/dist/Resizable/useResizable.d.ts.map +1 -1
  173. package/dist/Resizable/useResizable.js +252 -459
  174. package/dist/SegmentedControl/useSegmentedSelectionMotion.d.ts.map +1 -1
  175. package/dist/SegmentedControl/useSegmentedSelectionMotion.js +3 -3
  176. package/dist/SelectableCard/SelectableCard.d.ts +2 -0
  177. package/dist/SelectableCard/SelectableCard.d.ts.map +1 -1
  178. package/dist/SelectableCard/SelectableCard.js +36 -11
  179. package/dist/SelectableCard/selectableCardInput.d.ts +12 -0
  180. package/dist/SelectableCard/selectableCardInput.d.ts.map +1 -0
  181. package/dist/SelectableCard/selectableCardInput.js +20 -0
  182. package/dist/Selector/Selector.d.ts.map +1 -1
  183. package/dist/Selector/Selector.js +5 -8
  184. package/dist/Slider/sliderTouchController.js +2 -2
  185. package/dist/Spinner/Spinner.d.ts +1 -1
  186. package/dist/Spinner/Spinner.d.ts.map +1 -1
  187. package/dist/Spinner/Spinner.js +60 -58
  188. package/dist/Switch/Switch.d.ts.map +1 -1
  189. package/dist/Switch/Switch.js +4 -10
  190. package/dist/Switch/useSwitchTouch.js +4 -4
  191. package/dist/Table/BaseTable.d.ts.map +1 -1
  192. package/dist/Table/BaseTable.js +29 -8
  193. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  194. package/dist/Table/plugins/columnResize/useTableColumnResize.js +3 -1
  195. package/dist/Table/plugins/filtering/useTableFiltering.d.ts.map +1 -1
  196. package/dist/Table/plugins/filtering/useTableFiltering.js +2 -1
  197. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  198. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +4 -0
  199. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  200. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +2 -0
  201. package/dist/TextInput/TextInput.d.ts +2 -2
  202. package/dist/TextInput/TextInput.d.ts.map +1 -1
  203. package/dist/TextInput/TextInput.js +10 -7
  204. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  205. package/dist/TimeInput/TimeInput.js +2 -0
  206. package/dist/TimeInput/TouchTimeField.d.ts.map +1 -1
  207. package/dist/TimeInput/TouchTimeField.js +2 -0
  208. package/dist/Timer/Timer.d.ts.map +1 -1
  209. package/dist/Timer/Timer.js +2 -0
  210. package/dist/Timestamp/Timestamp.js +1 -1
  211. package/dist/Toast/Toast.d.ts +11 -1
  212. package/dist/Toast/Toast.d.ts.map +1 -1
  213. package/dist/Toast/Toast.js +25 -15
  214. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  215. package/dist/Toast/ToastViewport.js +97 -34
  216. package/dist/Toast/types.d.ts +9 -3
  217. package/dist/Toast/types.d.ts.map +1 -1
  218. package/dist/Toast/useToast.d.ts.map +1 -1
  219. package/dist/Toast/useToast.js +1 -0
  220. package/dist/Tokenizer/Tokenizer.d.ts +49 -37
  221. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  222. package/dist/Tokenizer/Tokenizer.js +22 -19
  223. package/dist/Tokenizer/TokenizerBottomSheet.d.ts +1 -1
  224. package/dist/Tokenizer/TokenizerBottomSheet.js +1 -1
  225. package/dist/Tokenizer/index.d.ts +1 -1
  226. package/dist/Tokenizer/index.d.ts.map +1 -1
  227. package/dist/Tooltip/useTooltip.d.ts +19 -1
  228. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  229. package/dist/Tooltip/useTooltip.js +34 -53
  230. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  231. package/dist/Typeahead/BaseTypeahead.js +27 -18
  232. package/dist/Typeahead/TypeaheadItem.d.ts +2 -1
  233. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  234. package/dist/animator/createAnimator.d.ts +98 -0
  235. package/dist/animator/createAnimator.d.ts.map +1 -0
  236. package/dist/animator/createAnimator.js +259 -0
  237. package/dist/astryx.css +39 -6
  238. package/dist/gestures/GestureHost.d.ts +16 -1
  239. package/dist/gestures/GestureHost.d.ts.map +1 -1
  240. package/dist/gestures/GestureHost.js +1 -1
  241. package/dist/gestures/PressTracker.d.ts.map +1 -1
  242. package/dist/gestures/PressTracker.js +4 -3
  243. package/dist/hooks/ModalAnnounceProvider.d.ts.map +1 -1
  244. package/dist/hooks/ModalAnnounceProvider.js +1 -0
  245. package/dist/hooks/actionGroupTracker.d.ts +4 -1
  246. package/dist/hooks/actionGroupTracker.d.ts.map +1 -1
  247. package/dist/hooks/actionGroupTracker.js +13 -3
  248. package/dist/hooks/index.d.ts +1 -0
  249. package/dist/hooks/index.d.ts.map +1 -1
  250. package/dist/hooks/index.js +1 -0
  251. package/dist/hooks/longPressDetector.d.ts +66 -0
  252. package/dist/hooks/longPressDetector.d.ts.map +1 -0
  253. package/dist/hooks/longPressDetector.js +200 -0
  254. package/dist/hooks/pressGroupContext.d.ts +6 -0
  255. package/dist/hooks/pressGroupContext.d.ts.map +1 -0
  256. package/dist/hooks/pressGroupContext.js +20 -0
  257. package/dist/hooks/rootScrollStyles.d.ts +48 -0
  258. package/dist/hooks/rootScrollStyles.d.ts.map +1 -0
  259. package/dist/hooks/rootScrollStyles.js +207 -0
  260. package/dist/hooks/scrollLockTouchGuard.d.ts +13 -0
  261. package/dist/hooks/scrollLockTouchGuard.d.ts.map +1 -0
  262. package/dist/hooks/scrollLockTouchGuard.js +134 -0
  263. package/dist/hooks/scrollbarGutter.d.ts +4 -4
  264. package/dist/hooks/scrollbarGutter.d.ts.map +1 -1
  265. package/dist/hooks/scrollbarGutter.js +36 -23
  266. package/dist/hooks/useActionGroupTracking.d.ts +53 -0
  267. package/dist/hooks/useActionGroupTracking.d.ts.map +1 -0
  268. package/dist/hooks/useActionGroupTracking.js +174 -0
  269. package/dist/hooks/useAnimator.d.ts +41 -0
  270. package/dist/hooks/useAnimator.d.ts.map +1 -0
  271. package/dist/hooks/useAnimator.js +70 -0
  272. package/dist/hooks/useAnnounceRenderedText.d.ts.map +1 -1
  273. package/dist/hooks/useAnnounceRenderedText.js +1 -0
  274. package/dist/hooks/useAttachment.d.ts +1 -1
  275. package/dist/hooks/useAttachment.js +1 -1
  276. package/dist/hooks/useAutoMediaMode.d.ts.map +1 -1
  277. package/dist/hooks/useAutoMediaMode.js +1 -0
  278. package/dist/hooks/useBusyAnnouncement.d.ts.map +1 -1
  279. package/dist/hooks/useBusyAnnouncement.js +2 -0
  280. package/dist/hooks/useDevWarning.d.ts.map +1 -1
  281. package/dist/hooks/useDevWarning.js +2 -0
  282. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  283. package/dist/hooks/useFocusTrap.js +2 -0
  284. package/dist/hooks/useGridFocus.d.ts +8 -5
  285. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  286. package/dist/hooks/useGridFocus.js +4 -3
  287. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  288. package/dist/hooks/useHotkeys.js +3 -0
  289. package/dist/hooks/useImageMode.d.ts.map +1 -1
  290. package/dist/hooks/useImageMode.js +3 -0
  291. package/dist/hooks/useInputStatusIcon.d.ts +1 -1
  292. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
  293. package/dist/hooks/useInputStatusIcon.js +2 -2
  294. package/dist/hooks/useKeyboardHint.js +1 -1
  295. package/dist/hooks/useLongPress.d.ts +8 -9
  296. package/dist/hooks/useLongPress.d.ts.map +1 -1
  297. package/dist/hooks/useLongPress.js +23 -106
  298. package/dist/hooks/useMenuHover.d.ts.map +1 -1
  299. package/dist/hooks/useMenuHover.js +2 -0
  300. package/dist/hooks/useMenuPress.d.ts.map +1 -1
  301. package/dist/hooks/useMenuPress.js +3 -0
  302. package/dist/hooks/useOverflow.d.ts.map +1 -1
  303. package/dist/hooks/useOverflow.js +2 -1
  304. package/dist/hooks/usePressFeedback.d.ts.map +1 -1
  305. package/dist/hooks/usePressFeedback.js +1 -0
  306. package/dist/hooks/useResolvedRequired.d.ts +3 -0
  307. package/dist/hooks/useResolvedRequired.d.ts.map +1 -1
  308. package/dist/hooks/useResolvedRequired.js +3 -0
  309. package/dist/hooks/useScrollLock.d.ts +7 -9
  310. package/dist/hooks/useScrollLock.d.ts.map +1 -1
  311. package/dist/hooks/useScrollLock.js +55 -48
  312. package/dist/hooks/useScrollableArea.d.ts.map +1 -1
  313. package/dist/hooks/useScrollableArea.js +5 -0
  314. package/dist/hooks/useStreamingText.d.ts.map +1 -1
  315. package/dist/hooks/useStreamingText.js +3 -0
  316. package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts +8 -0
  317. package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts.map +1 -0
  318. package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.js +42 -0
  319. package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.d.ts.map +1 -1
  320. package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.js +6 -0
  321. package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts +8 -0
  322. package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts.map +1 -0
  323. package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.js +14 -0
  324. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  325. package/dist/i18n/generated-locales/en.generated.js +30 -0
  326. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  327. package/dist/i18n/generated-locales/pseudo.generated.js +30 -0
  328. package/dist/index.d.ts +1 -0
  329. package/dist/index.d.ts.map +1 -1
  330. package/dist/index.js +4 -0
  331. package/dist/internal/indicatorPress.stylex.d.ts +20 -0
  332. package/dist/internal/indicatorPress.stylex.d.ts.map +1 -0
  333. package/dist/internal/indicatorPress.stylex.js +26 -0
  334. package/dist/internal/selectable-card.d.ts +21 -0
  335. package/dist/internal/selectable-card.d.ts.map +1 -0
  336. package/dist/internal/selectable-card.js +20 -0
  337. package/dist/internal/sheetDraft.d.ts +2 -2
  338. package/dist/internal/sheetDraft.js +2 -2
  339. package/dist/motion/animatedLayout.d.ts.map +1 -1
  340. package/dist/motion/animatedLayout.js +7 -7
  341. package/dist/motion/animator.d.ts +14 -14
  342. package/dist/motion/animator.d.ts.map +1 -1
  343. package/dist/motion/animator.js +45 -20
  344. package/dist/motion/progress.d.ts +88 -0
  345. package/dist/motion/progress.d.ts.map +1 -0
  346. package/dist/motion/progress.js +128 -0
  347. package/dist/motion/reducedMotion.d.ts.map +1 -1
  348. package/dist/motion/reducedMotion.js +3 -1
  349. package/dist/motion/uikit/alert.d.ts +41 -0
  350. package/dist/motion/uikit/alert.d.ts.map +1 -0
  351. package/dist/motion/uikit/alert.js +43 -0
  352. package/dist/motion/uikit/index.d.ts +4 -3
  353. package/dist/motion/uikit/index.d.ts.map +1 -1
  354. package/dist/motion/uikit/index.js +4 -3
  355. package/dist/motion/uikit/picker.d.ts +96 -0
  356. package/dist/motion/uikit/picker.d.ts.map +1 -0
  357. package/dist/motion/uikit/picker.js +117 -0
  358. package/dist/privateAttributes/pressGroupItem.stylex.d.ts +22 -0
  359. package/dist/privateAttributes/pressGroupItem.stylex.d.ts.map +1 -0
  360. package/dist/privateAttributes/pressGroupItem.stylex.js +36 -0
  361. package/dist/privateAttributes/reducedMotion.stylex.d.ts +23 -0
  362. package/dist/privateAttributes/reducedMotion.stylex.d.ts.map +1 -0
  363. package/dist/privateAttributes/reducedMotion.stylex.js +40 -0
  364. package/dist/theme/Theme.d.ts.map +1 -1
  365. package/dist/theme/Theme.js +29 -4
  366. package/dist/theme/motionKnobs.d.ts +4 -3
  367. package/dist/theme/motionKnobs.d.ts.map +1 -1
  368. package/dist/theme/motionKnobs.js +3 -2
  369. package/dist/theme/themeMotion.d.ts +6 -0
  370. package/dist/theme/themeMotion.d.ts.map +1 -1
  371. package/dist/theme/themeMotion.js +7 -0
  372. package/dist/utils/dateParser.d.ts.map +1 -1
  373. package/dist/utils/dateParser.js +12 -0
  374. package/dist/utils/focusReturn.d.ts +15 -0
  375. package/dist/utils/focusReturn.d.ts.map +1 -1
  376. package/dist/utils/focusReturn.js +28 -0
  377. package/dist/utils/interactionModality.d.ts.map +1 -1
  378. package/dist/utils/interactionModality.js +4 -0
  379. package/dist/utils/interactionOverlay.stylex.d.ts +3 -2
  380. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  381. package/dist/utils/interactionOverlay.stylex.js +3 -2
  382. package/dist/utils/plainDate.d.ts +8 -0
  383. package/dist/utils/plainDate.d.ts.map +1 -1
  384. package/dist/utils/plainDate.js +19 -0
  385. package/dist/utils/pressFeedback.d.ts.map +1 -1
  386. package/dist/utils/pressFeedback.js +20 -6
  387. package/dist/utils/triggerFocus.d.ts +36 -0
  388. package/dist/utils/triggerFocus.d.ts.map +1 -0
  389. package/dist/utils/triggerFocus.js +65 -0
  390. package/locales/en.json +120 -0
  391. package/locales/pseudo.json +90 -0
  392. package/package.json +14 -9
  393. package/src/AlertDialog/AlertDialog.doc.mjs +2 -2
  394. package/src/AlertDialog/AlertDialog.tsx +46 -5
  395. package/src/AppShell/AppShell.tsx +4 -0
  396. package/src/BottomSheet/BottomSheet.tsx +1 -0
  397. package/src/BottomSheet/BottomSheetPanel.tsx +39 -3
  398. package/src/BottomSheet/BottomSheetSwitcher.tsx +5 -0
  399. package/src/BottomSheet/useMobileKeyboard.ts +4 -0
  400. package/src/BottomSheet/useSheetGestures.ts +10 -1
  401. package/src/Button/Button.tsx +26 -4
  402. package/src/Calendar/Calendar.tsx +36 -25
  403. package/src/Carousel/Carousel.tsx +1 -0
  404. package/src/Chat/ChatComposerInput.tsx +2 -0
  405. package/src/Chat/ChatMessageList.tsx +2 -1
  406. package/src/Chat/useChatDictation.ts +1 -0
  407. package/src/Chat/useChatNewMessages.ts +1 -1
  408. package/src/Chat/useChatStreamScroll.ts +2 -0
  409. package/src/Chat/useSpeechRecognition.ts +2 -0
  410. package/src/Chat/useTriggerMenu.tsx +1 -1
  411. package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -0
  412. package/src/CheckboxInput/CheckboxInput.tsx +38 -15
  413. package/src/CodeBlock/CodeBlock.doc.mjs +9 -1
  414. package/src/CodeBlock/CodeBlock.tsx +41 -4
  415. package/src/CommandPalette/CommandPalette.tsx +1 -0
  416. package/src/CommandPalette/CommandPaletteItem.tsx +1 -0
  417. package/src/ComplexSelector/ComplexSelector.tsx +20 -5
  418. package/src/ContextMenu/ContextMenu.tsx +2 -2
  419. package/src/DateInput/MonthScroller.tsx +8 -2
  420. package/src/DateInput/PickerWheel.tsx +765 -0
  421. package/src/DateInput/TouchDateField.tsx +1 -0
  422. package/src/DateInput/Wheel.tsx +94 -150
  423. package/src/DateInput/useOwnScrollGesture.ts +25 -3
  424. package/src/DateInput/usePointerDragScroll.ts +1 -0
  425. package/src/DateInput/useScrollSettle.ts +2 -0
  426. package/src/DateInput/useWheelListbox.ts +112 -0
  427. package/src/DateInput/wheelOptions.ts +155 -0
  428. package/src/DateInput/wheelPhysics.ts +406 -0
  429. package/src/DateInput/wheelStrip.ts +341 -0
  430. package/src/DateTimeInput/TouchDateTimeField.tsx +2 -0
  431. package/src/Dialog/Dialog.tsx +12 -32
  432. package/src/Drawer/useDrawerDialogPresence.ts +2 -0
  433. package/src/DropdownMenu/useMenuOverflow.ts +3 -0
  434. package/src/Field/Field.tsx +2 -2
  435. package/src/FieldStatus/useFieldStatusAnnouncement.ts +1 -0
  436. package/src/FormLayout/FormLayout.doc.mjs +181 -46
  437. package/src/FormLayout/FormLayout.tsx +5 -1
  438. package/src/HoverCard/HoverCard.doc.mjs +10 -8
  439. package/src/HoverCard/HoverCard.tsx +58 -6
  440. package/src/HoverCard/useHoverCard.doc.mjs +178 -36
  441. package/src/HoverCard/useHoverCard.tsx +49 -54
  442. package/src/Icon/Icon.doc.mjs +49 -8
  443. package/src/Icon/Icon.tsx +15 -7
  444. package/src/IconButton/IconButton.doc.mjs +141 -21
  445. package/src/Item/useSwipeAction.ts +2 -0
  446. package/src/Layer/modalOutlet.ts +2 -0
  447. package/src/Layer/outsidePress.ts +1 -0
  448. package/src/Layer/useLayer.tsx +2 -0
  449. package/src/Layer/useLayerDismissal.ts +2 -0
  450. package/src/Layer/usePressPin.ts +81 -15
  451. package/src/Layer/useTouchTrigger.ts +2 -0
  452. package/src/Lightbox/Lightbox.tsx +19 -0
  453. package/src/MobileNav/MobileNav.tsx +9 -30
  454. package/src/Outline/useOutlineFromDOM.ts +2 -0
  455. package/src/Outline/useScrollSpy.ts +2 -0
  456. package/src/OverflowList/OverflowList.tsx +2 -0
  457. package/src/Popover/Popover.tsx +4 -0
  458. package/src/PowerSearch/PowerSearch.doc.mjs +60 -8
  459. package/src/PowerSearch/PowerSearch.tsx +627 -157
  460. package/src/PowerSearch/PowerSearchBottomSheet.tsx +2525 -0
  461. package/src/PowerSearch/PowerSearchEditPopover.tsx +39 -6
  462. package/src/PowerSearch/PowerSearchFilterEditor.tsx +2 -0
  463. package/src/PowerSearch/PowerSearchToken.tsx +7 -0
  464. package/src/PowerSearch/PowerSearchValueEditor.tsx +244 -58
  465. package/src/PowerSearch/formatFilterValue.ts +55 -17
  466. package/src/PowerSearch/formatTokenValue.ts +222 -0
  467. package/src/PowerSearch/powerSearchDateZone.ts +64 -0
  468. package/src/PowerSearch/powerSearchSheetUtils.ts +224 -0
  469. package/src/PowerSearch/types.ts +2 -0
  470. package/src/ProgressBar/ProgressBarTouch.ts +2 -0
  471. package/src/RadioList/RadioList.tsx +3 -2
  472. package/src/RadioList/RadioListItem.tsx +5 -3
  473. package/src/Resizable/Resizable.doc.mjs +5 -4
  474. package/src/Resizable/ResizeHandle.tsx +169 -109
  475. package/src/Resizable/createResizable.ts +831 -0
  476. package/src/Resizable/useResizable.ts +292 -623
  477. package/src/SegmentedControl/useSegmentedSelectionMotion.ts +6 -3
  478. package/src/SelectableCard/SelectableCard.tsx +39 -10
  479. package/src/SelectableCard/selectableCardInput.ts +30 -0
  480. package/src/Selector/Selector.tsx +5 -12
  481. package/src/Slider/sliderTouchController.ts +2 -2
  482. package/src/Spinner/Spinner.tsx +77 -63
  483. package/src/Switch/Switch.tsx +2 -6
  484. package/src/Switch/useSwitchTouch.ts +4 -4
  485. package/src/Table/BaseTable.tsx +46 -12
  486. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +2 -1
  487. package/src/Table/plugins/filtering/useTableFiltering.tsx +1 -0
  488. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +4 -0
  489. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +2 -0
  490. package/src/TextInput/TextInput.tsx +11 -10
  491. package/src/TimeInput/TimeInput.tsx +2 -0
  492. package/src/TimeInput/TouchTimeField.tsx +2 -0
  493. package/src/Timer/Timer.tsx +1 -0
  494. package/src/Timestamp/Timestamp.tsx +1 -1
  495. package/src/Toast/Toast.doc.mjs +4 -3
  496. package/src/Toast/Toast.tsx +52 -32
  497. package/src/Toast/ToastViewport.tsx +123 -35
  498. package/src/Toast/types.ts +9 -3
  499. package/src/Toast/useToast.tsx +1 -0
  500. package/src/Tokenizer/Tokenizer.doc.mjs +19 -3
  501. package/src/Tokenizer/Tokenizer.tsx +73 -51
  502. package/src/Tokenizer/TokenizerBottomSheet.tsx +1 -1
  503. package/src/Tokenizer/index.ts +1 -0
  504. package/src/Tooltip/useTooltip.doc.mjs +24 -0
  505. package/src/Tooltip/useTooltip.tsx +61 -56
  506. package/src/Typeahead/BaseTypeahead.tsx +27 -17
  507. package/src/Typeahead/TypeaheadItem.doc.mjs +6 -3
  508. package/src/Typeahead/TypeaheadItem.tsx +2 -1
  509. package/src/animator/createAnimator.doc.mjs +153 -0
  510. package/src/animator/createAnimator.ts +324 -0
  511. package/src/gestures/GestureHost.ts +1 -1
  512. package/src/gestures/PressTracker.ts +4 -3
  513. package/src/gestures/README.md +10 -4
  514. package/src/hooks/ModalAnnounceProvider.tsx +1 -0
  515. package/src/hooks/actionGroupTracker.ts +20 -5
  516. package/src/hooks/index.ts +2 -0
  517. package/src/hooks/longPressDetector.ts +273 -0
  518. package/src/hooks/pressGroupContext.ts +21 -0
  519. package/src/hooks/rootScrollStyles.ts +247 -0
  520. package/src/hooks/scrollLockTouchGuard.ts +182 -0
  521. package/src/hooks/scrollbarGutter.ts +41 -26
  522. package/src/hooks/useActionGroupTracking.ts +224 -0
  523. package/src/hooks/useAnimator.doc.mjs +109 -0
  524. package/src/hooks/useAnimator.ts +67 -0
  525. package/src/hooks/useAnnounceRenderedText.ts +1 -0
  526. package/src/hooks/useAttachment.ts +1 -1
  527. package/src/hooks/useAutoMediaMode.ts +1 -0
  528. package/src/hooks/useBusyAnnouncement.ts +2 -0
  529. package/src/hooks/useDevWarning.ts +2 -0
  530. package/src/hooks/useFocusTrap.ts +2 -0
  531. package/src/hooks/useGridFocus.doc.mjs +6 -6
  532. package/src/hooks/useGridFocus.ts +10 -7
  533. package/src/hooks/useHotkeys.ts +2 -0
  534. package/src/hooks/useImageMode.ts +2 -0
  535. package/src/hooks/useInputStatusIcon.tsx +3 -2
  536. package/src/hooks/useKeyboardHint.tsx +1 -1
  537. package/src/hooks/useLongPress.doc.mjs +2 -2
  538. package/src/hooks/useLongPress.ts +32 -122
  539. package/src/hooks/useMenuHover.ts +1 -0
  540. package/src/hooks/useMenuPress.ts +2 -0
  541. package/src/hooks/useOverflow.ts +2 -1
  542. package/src/hooks/usePressFeedback.ts +1 -0
  543. package/src/hooks/useResolvedRequired.ts +3 -0
  544. package/src/hooks/useScrollLock.doc.mjs +51 -12
  545. package/src/hooks/useScrollLock.ts +57 -60
  546. package/src/hooks/useScrollableArea.ts +4 -0
  547. package/src/hooks/useStreamingText.ts +2 -0
  548. package/src/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.ts +43 -0
  549. package/src/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.ts +6 -0
  550. package/src/i18n/generated-english/PowerSearch/formatTokenValue.generated.ts +15 -0
  551. package/src/i18n/generated-locales/en.generated.ts +41 -0
  552. package/src/i18n/generated-locales/pseudo.generated.ts +42 -0
  553. package/src/index.ts +13 -0
  554. package/src/internal/indicatorPress.stylex.ts +24 -0
  555. package/src/internal/selectable-card.ts +21 -0
  556. package/src/internal/sheetDraft.ts +2 -2
  557. package/src/motion/MEASUREMENTS.md +18 -0
  558. package/src/motion/README.md +10 -5
  559. package/src/motion/animatedLayout.ts +10 -5
  560. package/src/motion/animator.ts +66 -31
  561. package/src/motion/progress.ts +155 -0
  562. package/src/motion/reducedMotion.ts +3 -1
  563. package/src/motion/uikit/alert.ts +43 -0
  564. package/src/motion/uikit/index.ts +4 -3
  565. package/src/motion/uikit/picker.ts +116 -0
  566. package/src/privateAttributes/pressGroupItem.stylex.ts +44 -0
  567. package/src/privateAttributes/reducedMotion.stylex.ts +45 -0
  568. package/src/theme/Theme.tsx +37 -3
  569. package/src/theme/motionKnobs.ts +4 -3
  570. package/src/theme/themeMotion.ts +7 -0
  571. package/src/utils/dateParser.ts +16 -0
  572. package/src/utils/focusReturn.ts +30 -0
  573. package/src/utils/interactionModality.ts +4 -0
  574. package/src/utils/interactionOverlay.stylex.ts +3 -2
  575. package/src/utils/plainDate.ts +21 -0
  576. package/src/utils/pressFeedback.ts +24 -6
  577. package/src/utils/triggerFocus.ts +80 -0
  578. package/dist/internal/touch-sheet.d.ts +0 -21
  579. package/dist/internal/touch-sheet.d.ts.map +0 -1
  580. package/dist/internal/touch-sheet.js +0 -19
  581. package/src/internal/touch-sheet.ts +0 -21
@@ -0,0 +1,765 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file PickerWheel.tsx
7
+ * @input Wheel's props (wheelOptions.ts): options, value and change callback
8
+ * @output PickerWheel: one picker column that moves like UIPickerView
9
+ * @position Internal component; the Wheel under a finger (Wheel.tsx picks it)
10
+ *
11
+ * It moves on the gesture system and the shared animator, not on a native
12
+ * scroller. One strip holds the rows and is the only element that moves.
13
+ *
14
+ * SYNC: When modified, update PickerWheel.test.tsx, Wheel.tsx,
15
+ * DateInputTouch.test.tsx, DateInput.doc.mjs and TimeInput.doc.mjs.
16
+ */
17
+
18
+ import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
19
+ import * as stylex from '@stylexjs/stylex';
20
+ import {scrollTypeOf} from '../gestures/GestureHost';
21
+ import {PanGestureRecognizer} from '../gestures/PanGestureRecognizer';
22
+ import {TapGestureRecognizer} from '../gestures/TapGestureRecognizer';
23
+ import {useGestureRecognizer} from '../gestures/useGestureRecognizer';
24
+ import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect';
25
+ import {rubberBandInverse} from '../motion/rubberBand';
26
+ import {resolveMotion} from '../motion/resolveMotion';
27
+ import {picker, registerPickerTable} from '../motion/uikit/picker';
28
+ import {registerScrollTable, scroll} from '../motion/uikit/scroll';
29
+ import {registerTimingTable, timing} from '../motion/uikit/timing';
30
+ import {
31
+ colorVars,
32
+ fontWeightVars,
33
+ radiusVars,
34
+ spacingVars,
35
+ typeScaleVars,
36
+ } from '../theme/tokens.stylex';
37
+ import {focusOutlineStyles} from '../utils/focusOutline.stylex';
38
+ import {lockSelection} from '../gestures/selectionLock';
39
+ import {dateInputTouchGeometry, dateInputTouchSizes} from './tokens.stylex';
40
+ import {useOwnScrollGesture} from './useOwnScrollGesture';
41
+ import {useWheelListbox} from './useWheelListbox';
42
+ import {createWheelStrip, type PlayOptions} from './wheelStrip';
43
+ import {
44
+ dragOffset,
45
+ nearestIndex,
46
+ offsetBounds,
47
+ planRelease,
48
+ spinCurve,
49
+ type WheelCurve,
50
+ type WheelLayout,
51
+ } from './wheelPhysics';
52
+ import {
53
+ endIndex,
54
+ nearestEnabledIndex,
55
+ steppedIndex,
56
+ WHEEL_ROW_HEIGHT,
57
+ type WheelProps,
58
+ } from './wheelOptions';
59
+
60
+ /** Row pitch, px: the touch column keeps the scrolling column's pitch. */
61
+ const ROW_HEIGHT = WHEEL_ROW_HEIGHT;
62
+ /** UIKit's picker measures scaled to that pitch (UIKit's row is 32 pt). */
63
+ const UIKIT_SCALE = ROW_HEIGHT / picker.geometry.rowHeight;
64
+ /** UIKit's rubber band dimension for the picker's table, at that pitch. */
65
+ const RUBBER_BAND_DIMENSION = picker.geometry.rubberBandDimension * UIKIT_SCALE;
66
+
67
+ const styles = stylex.create({
68
+ // The scrolling column's box, band and rows (Wheel.tsx), moved by the
69
+ // gesture system and the compositor instead of a native scroller.
70
+ column: {
71
+ position: 'relative',
72
+ flex: '1 1 0',
73
+ minInlineSize: 0,
74
+ blockSize: dateInputTouchGeometry.paneBlockSize,
75
+ overflow: 'hidden',
76
+ outline: 'none',
77
+ WebkitTapHighlightColor: 'transparent',
78
+ },
79
+ // The rows fade toward the column's edges, from the scrolling column's 0.3
80
+ // to fully opaque at the band and back. The scrolling column fades them the
81
+ // same way under reduced motion. A static mask: nothing paints it again as
82
+ // the strip moves. It sits inside the column, so it never clips the
83
+ // column's focus ring.
84
+ fade: {
85
+ position: 'absolute',
86
+ inset: 0,
87
+ pointerEvents: 'none',
88
+ maskImage:
89
+ 'linear-gradient(to bottom, rgb(0 0 0 / 0.3), rgb(0 0 0) 50%, rgb(0 0 0 / 0.3))',
90
+ },
91
+ /**
92
+ * The selection band: a centred row-height plate behind the rows.
93
+ * Decorative: the committed value is announced by `aria-selected`.
94
+ */
95
+ band: {
96
+ position: 'absolute',
97
+ insetInline: 0,
98
+ insetBlockStart: `calc(50% - (${dateInputTouchSizes.wheelItemSize} / 2))`,
99
+ blockSize: dateInputTouchSizes.wheelItemSize,
100
+ borderRadius: radiusVars['--radius-element'],
101
+ backgroundColor: colorVars['--color-neutral'],
102
+ pointerEvents: 'none',
103
+ },
104
+ /**
105
+ * The strip holds the rows at their places along the wheel, with its top on
106
+ * the band's row. It moves by minus the wheel's offset, and the animator
107
+ * writes its `translate`. Also what a reduced-motion cross-fade fades.
108
+ */
109
+ strip: {
110
+ position: 'absolute',
111
+ insetInline: 0,
112
+ insetBlockStart: `calc(50% - (${dateInputTouchSizes.wheelItemSize} / 2))`,
113
+ pointerEvents: 'none',
114
+ },
115
+ /** One row: an option at its place along the strip, flat. */
116
+ row: {
117
+ position: 'absolute',
118
+ insetInline: 0,
119
+ blockSize: dateInputTouchSizes.wheelItemSize,
120
+ display: 'flex',
121
+ alignItems: 'center',
122
+ justifyContent: 'center',
123
+ paddingInline: spacingVars['--spacing-2'],
124
+ boxSizing: 'border-box',
125
+ fontSize: typeScaleVars['--text-large-size'],
126
+ fontWeight: fontWeightVars['--font-weight-normal'],
127
+ color: colorVars['--color-text-primary'],
128
+ whiteSpace: 'nowrap',
129
+ overflow: 'hidden',
130
+ textOverflow: 'ellipsis',
131
+ userSelect: 'none',
132
+ // The mark has no transition, unlike the scrolling column's. A colour or
133
+ // weight that animates lays out and paints every frame on the main thread.
134
+ // A mark set as a drag lets go would do so through the coast.
135
+ },
136
+ /** The row under the band, as the scrolling column marks it. */
137
+ rowActive: {
138
+ color: colorVars['--color-text-accent'],
139
+ fontWeight: fontWeightVars['--font-weight-semibold'],
140
+ },
141
+ rowDisabled: {
142
+ color: colorVars['--color-text-disabled'],
143
+ },
144
+ /** A row at its place along the strip. */
145
+ rowAt: (top: string) => ({insetBlockStart: top}),
146
+ });
147
+
148
+ /**
149
+ * The motion tables the wheel resolves internal roles from: the timing curve,
150
+ * the scroll bounce and the picker's tap spin. Nothing registers on import
151
+ * (motion/roles.ts) and each register is idempotent, so the wheel calls this
152
+ * right before it resolves a role.
153
+ */
154
+ function registerWheelTables(): void {
155
+ registerTimingTable();
156
+ registerScrollTable();
157
+ registerPickerTable();
158
+ }
159
+
160
+ /**
161
+ * A turn onto `to` on the picker's tap spin: its duration and its curve, as
162
+ * resolved under `column` when the turn starts.
163
+ */
164
+ function turnCurve(
165
+ column: Element | null,
166
+ from: number,
167
+ to: number,
168
+ ): WheelCurve {
169
+ registerWheelTables();
170
+ return spinCurve(
171
+ from,
172
+ to,
173
+ resolveMotion(column, picker.tapSpin, 'durationMs') / 1000,
174
+ resolveMotion(column, timing.curves.move),
175
+ );
176
+ }
177
+
178
+ interface DragState {
179
+ /** The finger's offset at the pan's start, before any rubber band. */
180
+ readonly start: number;
181
+ }
182
+
183
+ /**
184
+ * One UIPickerView column: the Wheel under a finger. It does not scroll
185
+ * natively. WebKit gives every scroll-snapping scroller the fast deceleration
186
+ * rate, and a scroller's momentum cannot be caught or measured. A busy main
187
+ * thread does not stop or jump a motion here. Under Reduce Motion a throw's
188
+ * momentum still plays, as iOS scrolling does. Every other motion
189
+ * cross-fades onto its row.
190
+ *
191
+ * @example
192
+ * ```
193
+ * <PickerWheel label="Month" options={monthOptions} value={month} onChange={setMonth} />
194
+ * ```
195
+ */
196
+ export function PickerWheel({
197
+ label,
198
+ options,
199
+ value,
200
+ onChange,
201
+ isActive = true,
202
+ }: WheelProps) {
203
+ const columnRef = useRef<HTMLDivElement | null>(null);
204
+ const rowsRef = useRef<HTMLDivElement | null>(null);
205
+ const rowCount = options.length;
206
+ const layout = useMemo<WheelLayout>(
207
+ () => ({rowHeight: ROW_HEIGHT, rowCount}),
208
+ [rowCount],
209
+ );
210
+ const [motion] = useState(() => createWheelStrip(layout));
211
+ const selectedIndex = Math.max(
212
+ 0,
213
+ options.findIndex(option => option.value === value),
214
+ );
215
+ const dragRef = useRef<DragState | null>(null);
216
+ /** A finger landed on a moving wheel and stopped it. */
217
+ const caughtRef = useRef(false);
218
+
219
+ // The latest props, for the motion's and the gesture listeners' callbacks,
220
+ // which are attached once and outlive a render.
221
+ const latestRef = useRef({options, value, onChange, layout});
222
+ useIsomorphicLayoutEffect(() => {
223
+ latestRef.current = {options, value, onChange, layout};
224
+ });
225
+
226
+ // The row under the band is marked as the scrolling column marks it. At rest
227
+ // that is the committed row, styled in render. While a finger drags the
228
+ // wheel, the row reaching the band is painted directly, so marking it never
229
+ // re-renders. A motion unmarks every row as it starts and marks the row it
230
+ // stops or ends on. The compositor then plays it with no layout or paint per
231
+ // frame, and no mark rides away from the band.
232
+ const paintedRef = useRef<Set<HTMLElement>>(new Set());
233
+ const paintRow = useCallback((position: number | null) => {
234
+ const container = rowsRef.current;
235
+ if (container == null || container.children.length === 0) {
236
+ return;
237
+ }
238
+ const rows = container.children;
239
+ const {options: currentOptions, value: currentValue} = latestRef.current;
240
+ const active =
241
+ position == null
242
+ ? null
243
+ : ((rows[position] as HTMLElement | undefined) ?? null);
244
+ const painted = paintedRef.current;
245
+ for (const row of painted) {
246
+ row.style.removeProperty('color');
247
+ row.style.removeProperty('font-weight');
248
+ }
249
+ painted.clear();
250
+ const selected = currentOptions.findIndex(
251
+ option => option.value === currentValue,
252
+ );
253
+ if (rows[selected] != null && rows[selected] !== active) {
254
+ // The committed row's own mark gives way while another row is under
255
+ // the band.
256
+ const row = rows[selected] as HTMLElement;
257
+ row.style.color = currentOptions[selected]?.isDisabled
258
+ ? colorVars['--color-text-disabled']
259
+ : colorVars['--color-text-primary'];
260
+ row.style.fontWeight = fontWeightVars['--font-weight-normal'];
261
+ painted.add(row);
262
+ }
263
+ if (active == null || position == null) {
264
+ return;
265
+ }
266
+ active.style.color = currentOptions[position]?.isDisabled
267
+ ? colorVars['--color-text-disabled']
268
+ : colorVars['--color-text-accent'];
269
+ active.style.fontWeight = fontWeightVars['--font-weight-semibold'];
270
+ painted.add(active);
271
+ }, []);
272
+
273
+ // Every motion the wheel starts. Under Reduce Motion a transition lands
274
+ // without travel: the animator cross-fades the strip onto its row. The
275
+ // momentum that continues a throw is not a transition, so it plays as is.
276
+ const move = useCallback(
277
+ (curve: WheelCurve, options: PlayOptions = {}) => {
278
+ paintRow(null);
279
+ // The mark comes back from the row the motion reports nearest when it
280
+ // ends, even the row it began on.
281
+ motion.forgetNearest();
282
+ motion.play(curve, options);
283
+ },
284
+ [motion, paintRow],
285
+ );
286
+
287
+ // The wheel came to rest at `offset`: commit, or turn on to the row the
288
+ // rest rule names first.
289
+ const arrive = useCallback(
290
+ (offset: number) => {
291
+ const current = latestRef.current;
292
+ const row = nearestIndex(offset, current.layout);
293
+ const committed = current.options.findIndex(
294
+ option => option.value === current.value,
295
+ );
296
+ // A rest on the committed row is not a stop to correct. A committed value
297
+ // outside the bounds stays until a person moves the wheel off it, as in
298
+ // the scrolling column.
299
+ let step = 0;
300
+ if (row !== committed) {
301
+ step =
302
+ nearestEnabledIndex(current.options, row, Math.max(0, committed)) -
303
+ row;
304
+ }
305
+ if (step !== 0) {
306
+ const target = row + step;
307
+ move(turnCurve(columnRef.current, offset, target * ROW_HEIGHT), {
308
+ onEnd: (outcome, end) => {
309
+ if (outcome === 'arrived') {
310
+ arrive(end);
311
+ }
312
+ },
313
+ });
314
+ return;
315
+ }
316
+ const option = current.options[row];
317
+ if (
318
+ option != null &&
319
+ !option.isDisabled &&
320
+ option.value !== current.value
321
+ ) {
322
+ current.onChange(option.value);
323
+ }
324
+ },
325
+ [move],
326
+ );
327
+
328
+ const onEnd = useCallback(
329
+ (outcome: 'arrived' | 'stopped', offset: number) => {
330
+ if (outcome === 'arrived') {
331
+ arrive(offset);
332
+ }
333
+ },
334
+ [arrive],
335
+ );
336
+
337
+ // The animator holds the strip while it is attached, and lets it go as it
338
+ // detaches or is replaced.
339
+ const attachStrip = useCallback(
340
+ (strip: HTMLDivElement) => {
341
+ rowsRef.current = strip;
342
+ motion.attach(strip);
343
+ return () => {
344
+ rowsRef.current = null;
345
+ motion.attach(null);
346
+ };
347
+ },
348
+ [motion],
349
+ );
350
+
351
+ // The motion's layout follows the rows.
352
+ useIsomorphicLayoutEffect(() => {
353
+ motion.setLayout(layout);
354
+ }, [motion, layout]);
355
+
356
+ // The band's mark follows the row the motion reports nearest the band.
357
+ useIsomorphicLayoutEffect(() => {
358
+ motion.onNearestChange(paintRow);
359
+ return () => motion.onNearestChange(null);
360
+ }, [motion, paintRow]);
361
+ // At rest on the committed row, render's own mark takes over again.
362
+ useIsomorphicLayoutEffect(() => {
363
+ if (
364
+ motion.isMoving() ||
365
+ dragRef.current != null ||
366
+ nearestIndex(motion.offset(), layout) !== selectedIndex
367
+ ) {
368
+ return;
369
+ }
370
+ for (const row of paintedRef.current) {
371
+ row.style.removeProperty('color');
372
+ row.style.removeProperty('font-weight');
373
+ }
374
+ paintedRef.current.clear();
375
+ });
376
+
377
+ // The motion's animations and timers end with the wheel.
378
+ useEffect(() => () => motion.dispose(), [motion]);
379
+
380
+ // Park the committed row under the band when the wheel is shown, at once. A
381
+ // value that changes from outside while the wheel is shown turns the wheel
382
+ // onto its row instead. UIDatePicker turns onto its maximum the same way, and
383
+ // never jumps there. For example, a bound clamps the time after another wheel
384
+ // turned, or the calendar moved to another month. A second change during that
385
+ // turn turns on from where the wheel is drawn. Never while a finger or a
386
+ // motion of its own owns the wheel.
387
+ const parkedRef = useRef(false);
388
+ const parkTurnRef = useRef<object | null>(null);
389
+ useIsomorphicLayoutEffect(() => {
390
+ if (!isActive) {
391
+ parkedRef.current = false;
392
+ return;
393
+ }
394
+ if (
395
+ dragRef.current != null ||
396
+ (motion.isMoving() && parkTurnRef.current == null)
397
+ ) {
398
+ return;
399
+ }
400
+ const target = selectedIndex * ROW_HEIGHT;
401
+ const shown = motion.isMoving() ? motion.stop() : motion.offset();
402
+ const isAway = Math.abs(shown - target) > 0.01;
403
+ if (isAway && parkedRef.current) {
404
+ // The turn's own end paints the band's row.
405
+ const turn = {};
406
+ parkTurnRef.current = turn;
407
+ move(turnCurve(columnRef.current, shown, target), {
408
+ onEnd: () => {
409
+ if (parkTurnRef.current === turn) {
410
+ parkTurnRef.current = null;
411
+ }
412
+ },
413
+ });
414
+ return;
415
+ }
416
+ if (isAway) {
417
+ motion.setOffset(target);
418
+ }
419
+ parkedRef.current = true;
420
+ }, [isActive, selectedIndex, motion, move]);
421
+
422
+ // A hidden wheel keeps no motion running and holds no drag. Hiding it
423
+ // mid-drag ends the pan without calling its listener, because the toggle's
424
+ // owner owns that end. So the drag is dropped here, uncommitted. Shown again,
425
+ // the wheel parks the committed row.
426
+ useEffect(() => {
427
+ if (!isActive) {
428
+ dragRef.current = null;
429
+ motion.stop();
430
+ }
431
+ }, [isActive, motion]);
432
+
433
+ // A finger lands: a moving wheel stops where it is on screen.
434
+ const onTouchDown = useCallback(
435
+ (time: number) => {
436
+ caughtRef.current = motion.isMoving();
437
+ if (caughtRef.current) {
438
+ motion.stop(time);
439
+ }
440
+ },
441
+ [motion],
442
+ );
443
+
444
+ // The latest touch-down handler, for the gesture listener attached once.
445
+ const onTouchDownRef = useRef(onTouchDown);
446
+ useIsomorphicLayoutEffect(() => {
447
+ onTouchDownRef.current = onTouchDown;
448
+ });
449
+
450
+ const release = useCallback(
451
+ (velocity: number) => {
452
+ registerWheelTables();
453
+ const plan = planRelease(
454
+ motion.offset(),
455
+ velocity,
456
+ latestRef.current.layout,
457
+ resolveMotion(columnRef.current, scroll.bounce),
458
+ );
459
+ move(plan.curve, {
460
+ ticks: true,
461
+ onEnd,
462
+ touchRelease: true,
463
+ momentum: plan.kind === 'coast' || plan.kind === 'edge',
464
+ });
465
+ },
466
+ [motion, move, onEnd],
467
+ );
468
+
469
+ const pan = useGestureRecognizer(
470
+ columnRef,
471
+ () =>
472
+ new PanGestureRecognizer({
473
+ name: 'wheel-pan',
474
+ direction: 'vertical',
475
+ // A trackpad's two-finger scroll drives the pan as a finger does. The
476
+ // rows follow, coast on at the lift with the fingers' last speed, and
477
+ // rest by the rest rule. A mouse wheel's notches never reach the pan.
478
+ allowedScrollTypes: ['continuous'],
479
+ // A held finger on the wheel never starts text selection or the
480
+ // callout.
481
+ selectionLock: lockSelection,
482
+ shouldReceiveTouch: (_pan, touch) => {
483
+ onTouchDownRef.current(touch.time);
484
+ return true;
485
+ },
486
+ }),
487
+ recognizer => {
488
+ const {layout: currentLayout} = latestRef.current;
489
+ switch (recognizer.state) {
490
+ case 'began': {
491
+ const shown = motion.isMoving() ? motion.stop() : motion.offset();
492
+ dragRef.current = {start: fingerOffset(shown, currentLayout)};
493
+ motion.resetDrag();
494
+ motion.setOffset(
495
+ dragOffset(
496
+ dragRef.current.start - recognizer.translation().y,
497
+ currentLayout,
498
+ ),
499
+ {ticks: true},
500
+ );
501
+ break;
502
+ }
503
+ case 'changed': {
504
+ const drag = dragRef.current;
505
+ if (drag == null) {
506
+ break;
507
+ }
508
+ motion.setOffset(
509
+ dragOffset(drag.start - recognizer.translation().y, currentLayout),
510
+ {ticks: true},
511
+ );
512
+ break;
513
+ }
514
+ case 'ended': {
515
+ const drag = dragRef.current;
516
+ dragRef.current = null;
517
+ // A scroll view's release velocity (the pan's last two, blended as
518
+ // UIPickerView's); the rows move against the finger.
519
+ release(drag == null ? 0 : -recognizer.scrollVelocity().y);
520
+ break;
521
+ }
522
+ case 'cancelled': {
523
+ dragRef.current = null;
524
+ release(0);
525
+ break;
526
+ }
527
+ case 'possible':
528
+ case 'failed':
529
+ break;
530
+ }
531
+ },
532
+ {isEnabled: isActive},
533
+ );
534
+
535
+ // A touch that stopped a moving wheel and lifted without dragging: the
536
+ // wheel eases onto the nearest row, as a release without velocity does.
537
+ useEffect(
538
+ () =>
539
+ pan.addTransitionListener((_pan, _from, to) => {
540
+ // The flag stays up until the next touch lands. The tap recognizer may
541
+ // hear of this lift after the pan does, and must not read it as a tap
542
+ // on a row.
543
+ if (to === 'failed' && caughtRef.current && !motion.isMoving()) {
544
+ release(0);
545
+ }
546
+ }),
547
+ [pan, motion, release],
548
+ );
549
+
550
+ useGestureRecognizer(
551
+ columnRef,
552
+ () => new TapGestureRecognizer({name: 'wheel-tap'}),
553
+ recognizer => {
554
+ if (recognizer.state !== 'ended' || caughtRef.current) {
555
+ return;
556
+ }
557
+ const column = columnRef.current;
558
+ if (column == null) {
559
+ return;
560
+ }
561
+ const box = column.getBoundingClientRect();
562
+ const {y} = recognizer.location();
563
+ const offset = motion.offset();
564
+ const currentLayout = latestRef.current.layout;
565
+ const target = rowAtPoint(
566
+ y - (box.top + box.height / 2),
567
+ offset,
568
+ currentLayout,
569
+ );
570
+ if (target == null || target === nearestIndex(offset, currentLayout)) {
571
+ return;
572
+ }
573
+ move(turnCurve(columnRef.current, offset, target * ROW_HEIGHT), {
574
+ onEnd,
575
+ });
576
+ },
577
+ {isEnabled: isActive},
578
+ );
579
+
580
+ // Keep the finger, and the pointer it lands with: inside a BottomSheet the
581
+ // sheet would otherwise read a downward drag here as swipe-to-dismiss. This
582
+ // wheel pans through the gesture system, which never cancels the pointer
583
+ // the sheet armed on (see useOwnScrollGesture).
584
+ useOwnScrollGesture(columnRef, 'all', {
585
+ isEnabled: isActive,
586
+ isPointerKept: true,
587
+ });
588
+
589
+ // A key commits the row at `position` at once and turns the wheel there
590
+ // from `offset`.
591
+ const turnToPosition = useCallback(
592
+ (position: number, offset: number) => {
593
+ const current = latestRef.current;
594
+ const option = current.options[position];
595
+ if (option.value !== current.value) {
596
+ current.onChange(option.value);
597
+ }
598
+ move(turnCurve(columnRef.current, offset, position * ROW_HEIGHT));
599
+ },
600
+ [move],
601
+ );
602
+
603
+ const moveBy = useCallback(
604
+ (delta: number) => {
605
+ const current = latestRef.current;
606
+ if (current.options.length === 0 || delta === 0) {
607
+ return;
608
+ }
609
+ // Keys step from the row the wheel is heading to, not the one it is
610
+ // passing: two quick presses move two rows. A key with nowhere to go
611
+ // leaves a turn in flight to finish on its row.
612
+ const row = steppedIndex(
613
+ current.options,
614
+ nearestIndex(motion.target(), current.layout),
615
+ delta,
616
+ );
617
+ if (row == null) {
618
+ return;
619
+ }
620
+ const offset = motion.isMoving() ? motion.stop() : motion.offset();
621
+ turnToPosition(row, offset);
622
+ },
623
+ [motion, turnToPosition],
624
+ );
625
+
626
+ // A mouse wheel's notch turns the wheel one row, as an arrow key does, with
627
+ // no coast. The gesture host leaves a notch to what is under the pointer,
628
+ // which is this wheel. A wheel the pan took arrives here already prevented.
629
+ // A ctrl-wheel stays the page's zoom, and a sideways scroll stays the
630
+ // page's.
631
+ useEffect(() => {
632
+ const column = columnRef.current;
633
+ if (column == null || !isActive) {
634
+ return undefined;
635
+ }
636
+ const onWheel = (event: WheelEvent) => {
637
+ if (
638
+ event.defaultPrevented ||
639
+ event.ctrlKey ||
640
+ event.shiftKey ||
641
+ event.deltaY === 0 ||
642
+ Math.abs(event.deltaX) > Math.abs(event.deltaY) ||
643
+ scrollTypeOf(event) !== 'discrete'
644
+ ) {
645
+ return;
646
+ }
647
+ event.preventDefault();
648
+ moveBy(Math.sign(event.deltaY));
649
+ };
650
+ column.addEventListener('wheel', onWheel, {passive: false});
651
+ return () => column.removeEventListener('wheel', onWheel);
652
+ }, [isActive, moveBy]);
653
+
654
+ // Home and End: the first and the last enabled row.
655
+ const moveToEnd = useCallback(
656
+ (end: 'first' | 'last') => {
657
+ const row = endIndex(latestRef.current.options, end);
658
+ if (row == null) {
659
+ return;
660
+ }
661
+ const offset = motion.isMoving() ? motion.stop() : motion.offset();
662
+ turnToPosition(row, offset);
663
+ },
664
+ [motion, turnToPosition],
665
+ );
666
+
667
+ // A click on a row commits it at once and turns the wheel there, as the arrow
668
+ // keys do. The click comes from assistive technology, a keyboard, a test, or
669
+ // a mouse the tap recognizer did not take. A finger's tap is the tap
670
+ // recognizer's, and the click it would produce is swallowed by the gesture
671
+ // system.
672
+ const activateRow = useCallback(
673
+ (row: number) => {
674
+ const current = latestRef.current;
675
+ const option = current.options[row];
676
+ if (option == null || option.isDisabled) {
677
+ return;
678
+ }
679
+ const offset = motion.isMoving() ? motion.stop() : motion.offset();
680
+ if (option.value !== current.value) {
681
+ current.onChange(option.value);
682
+ }
683
+ move(turnCurve(columnRef.current, offset, row * ROW_HEIGHT));
684
+ },
685
+ [motion, move],
686
+ );
687
+
688
+ const {listboxProps, optionProps} = useWheelListbox({
689
+ label,
690
+ options,
691
+ value,
692
+ // The committed row: a value set from outside shows in the same render.
693
+ activeIndex: selectedIndex,
694
+ stepBy: moveBy,
695
+ toEnd: moveToEnd,
696
+ activate: activateRow,
697
+ });
698
+
699
+ return (
700
+ <div
701
+ ref={columnRef}
702
+ {...listboxProps}
703
+ data-wheel=""
704
+ {...stylex.props(styles.column, focusOutlineStyles.focusVisible)}>
705
+ <div data-wheel-fade="" {...stylex.props(styles.fade)}>
706
+ <div aria-hidden="true" {...stylex.props(styles.band)} />
707
+ <div
708
+ ref={attachStrip}
709
+ data-wheel-strip=""
710
+ {...stylex.props(styles.strip)}>
711
+ {options.map((option, index) => (
712
+ <div
713
+ key={option.value}
714
+ {...optionProps(option, index)}
715
+ data-wheel-row=""
716
+ data-label={option.label}
717
+ {...stylex.props(
718
+ styles.row,
719
+ styles.rowAt(`${index * ROW_HEIGHT}px`),
720
+ index === selectedIndex && styles.rowActive,
721
+ option.isDisabled && styles.rowDisabled,
722
+ )}>
723
+ {option.label}
724
+ </div>
725
+ ))}
726
+ </div>
727
+ </div>
728
+ </div>
729
+ );
730
+ }
731
+
732
+ PickerWheel.displayName = 'PickerWheel';
733
+
734
+ /**
735
+ * The row under a point `dy` px below the band's centre, or null past either
736
+ * end of the list.
737
+ */
738
+ function rowAtPoint(
739
+ dy: number,
740
+ offset: number,
741
+ layout: WheelLayout,
742
+ ): number | null {
743
+ const position = Math.round((offset + dy) / layout.rowHeight);
744
+ if (position < 0 || position >= layout.rowCount) {
745
+ return null;
746
+ }
747
+ return position;
748
+ }
749
+
750
+ /**
751
+ * The finger's offset for a shown one. Past an end, it is the travel that the
752
+ * rubber band shows as `shown`. So a drag that starts in a bounce continues
753
+ * without a jump.
754
+ */
755
+ function fingerOffset(shown: number, layout: WheelLayout): number {
756
+ const {min, max} = offsetBounds(layout);
757
+ const dimension = RUBBER_BAND_DIMENSION;
758
+ if (shown < min) {
759
+ return min + rubberBandInverse(shown - min, dimension);
760
+ }
761
+ if (shown > max) {
762
+ return max + rubberBandInverse(shown - max, dimension);
763
+ }
764
+ return shown;
765
+ }