@astryxdesign/core 0.7.5 → 0.7.6-canary.0ef60dd

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 (559) hide show
  1. package/dist/AlertDialog/AlertDialog.d.ts +1 -1
  2. package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
  3. package/dist/AlertDialog/AlertDialog.js +5 -5
  4. package/dist/Avatar/Avatar.d.ts.map +1 -1
  5. package/dist/Avatar/Avatar.js +12 -3
  6. package/dist/Badge/Badge.d.ts.map +1 -1
  7. package/dist/Badge/Badge.js +7 -1
  8. package/dist/BottomSheet/BottomSheet.js +1 -1
  9. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  10. package/dist/BottomSheet/BottomSheetPanel.js +2 -1
  11. package/dist/BottomSheet/useSheetGestures.d.ts +12 -0
  12. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  13. package/dist/BottomSheet/useSheetGestures.js +30 -3
  14. package/dist/Button/Button.js +4 -4
  15. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  16. package/dist/CheckboxInput/CheckboxInput.js +6 -5
  17. package/dist/ClickableCard/ClickableCard.d.ts.map +1 -1
  18. package/dist/ClickableCard/ClickableCard.js +37 -4
  19. package/dist/DateInput/DateInput.d.ts.map +1 -1
  20. package/dist/DateInput/DateInput.js +12 -4
  21. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  22. package/dist/DateInput/MonthScroller.js +101 -15
  23. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  24. package/dist/DateInput/TouchDateField.js +8 -3
  25. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  26. package/dist/DateRangeInput/DateRangeInput.js +1 -1
  27. package/dist/DateTimeInput/DateTimeInput.d.ts +5 -2
  28. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  29. package/dist/DateTimeInput/DateTimeInput.js +23 -12
  30. package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -1
  31. package/dist/DateTimeInput/NativeTimeSegment.js +5 -4
  32. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
  33. package/dist/DateTimeInput/TouchDateTimeField.js +4 -3
  34. package/dist/Dialog/Dialog.d.ts.map +1 -1
  35. package/dist/Dialog/Dialog.js +34 -9
  36. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  37. package/dist/Dialog/DialogHeader.js +5 -4
  38. package/dist/Divider/Divider.d.ts.map +1 -1
  39. package/dist/Divider/Divider.js +2 -1
  40. package/dist/Drawer/Drawer.d.ts +1 -0
  41. package/dist/Drawer/Drawer.d.ts.map +1 -1
  42. package/dist/Drawer/Drawer.js +7 -2
  43. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  44. package/dist/DropdownMenu/DropdownMenu.js +7 -3
  45. package/dist/DropdownMenu/MenuBottomSheetActionList.d.ts.map +1 -1
  46. package/dist/DropdownMenu/MenuBottomSheetActionList.js +6 -5
  47. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts +20 -2
  48. package/dist/DropdownMenu/lazyMenuBottomSheet.d.ts.map +1 -1
  49. package/dist/DropdownMenu/lazyMenuBottomSheet.js +31 -3
  50. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  51. package/dist/DropdownMenu/renderDropdownItems.js +21 -16
  52. package/dist/EmptyState/EmptyState.d.ts.map +1 -1
  53. package/dist/EmptyState/EmptyState.js +2 -1
  54. package/dist/Field/FieldLabel.d.ts +1 -1
  55. package/dist/Field/FieldLabel.d.ts.map +1 -1
  56. package/dist/Field/FieldLabel.js +4 -4
  57. package/dist/Field/InputClearButton.js +3 -3
  58. package/dist/Field/PanelSearchInput.js +2 -2
  59. package/dist/FieldStatus/FieldStatus.js +2 -2
  60. package/dist/FileInput/FileInput.d.ts.map +1 -1
  61. package/dist/FileInput/FileInput.js +7 -1
  62. package/dist/Heading/Heading.js +1 -1
  63. package/dist/Icon/Icon.js +1 -1
  64. package/dist/Indicator/CheckIndicator.d.ts.map +1 -1
  65. package/dist/Indicator/CheckIndicator.js +2 -1
  66. package/dist/Indicator/CheckboxIndicator.d.ts.map +1 -1
  67. package/dist/Indicator/CheckboxIndicator.js +3 -1
  68. package/dist/Indicator/RadioIndicator.d.ts.map +1 -1
  69. package/dist/Indicator/RadioIndicator.js +3 -1
  70. package/dist/Item/Item.d.ts.map +1 -1
  71. package/dist/Item/Item.js +2 -1
  72. package/dist/Item/ItemSwipeLayer.js +1 -1
  73. package/dist/Layer/popoverOperations.d.ts +27 -0
  74. package/dist/Layer/popoverOperations.d.ts.map +1 -0
  75. package/dist/Layer/popoverOperations.js +159 -0
  76. package/dist/Layer/useLayer.d.ts +1 -1
  77. package/dist/Layer/useLayer.d.ts.map +1 -1
  78. package/dist/Layer/useLayer.js +93 -59
  79. package/dist/Layout/Layout.js +1 -1
  80. package/dist/Layout/LayoutContent.js +1 -1
  81. package/dist/Layout/LayoutFooter.js +1 -1
  82. package/dist/Layout/LayoutHeader.js +1 -1
  83. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  84. package/dist/Lightbox/Lightbox.js +5 -0
  85. package/dist/Lightbox/LightboxViewport.a11y.browser.spec.js +5 -4
  86. package/dist/List/List.js +1 -1
  87. package/dist/List/ListItem.js +3 -3
  88. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  89. package/dist/MobileNav/MobileNav.js +7 -2
  90. package/dist/MultiSelector/CreateRow.a11y.chromium.spec.js +7 -6
  91. package/dist/MultiSelector/MultiSelector.d.ts +1 -1
  92. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  93. package/dist/MultiSelector/MultiSelector.js +26 -10
  94. package/dist/NumberInput/NumberInput.d.ts +3 -1
  95. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  96. package/dist/NumberInput/NumberInput.js +3 -3
  97. package/dist/NumberInput/numberParser.d.ts +3 -0
  98. package/dist/NumberInput/numberParser.d.ts.map +1 -1
  99. package/dist/NumberInput/numberParser.js +7 -44
  100. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  101. package/dist/ProgressBar/ProgressBar.js +16 -12
  102. package/dist/Resizable/useResizable.d.ts.map +1 -1
  103. package/dist/Resizable/useResizable.js +28 -2
  104. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  105. package/dist/SegmentedControl/SegmentedControlItem.js +4 -1
  106. package/dist/Selector/useSelectorPresentation.d.ts +8 -1
  107. package/dist/Selector/useSelectorPresentation.d.ts.map +1 -1
  108. package/dist/Selector/useSelectorPresentation.js +20 -4
  109. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  110. package/dist/Skeleton/Skeleton.js +1 -1
  111. package/dist/Slider/Slider.d.ts.map +1 -1
  112. package/dist/Slider/Slider.js +10 -2
  113. package/dist/Spinner/Spinner.d.ts.map +1 -1
  114. package/dist/Spinner/Spinner.js +3 -3
  115. package/dist/Stack/Stack.js +1 -1
  116. package/dist/Stack/StackItem.js +1 -1
  117. package/dist/TabList/TabList.d.ts.map +1 -1
  118. package/dist/TabList/TabList.js +16 -1
  119. package/dist/Table/plugins/columnResize/useTableColumnResize.d.ts.map +1 -1
  120. package/dist/Table/plugins/columnResize/useTableColumnResize.js +9 -1
  121. package/dist/Text/Text.js +1 -1
  122. package/dist/Text/useTruncation.d.ts.map +1 -1
  123. package/dist/Text/useTruncation.js +23 -5
  124. package/dist/TextArea/TextArea.d.ts +1 -1
  125. package/dist/TextArea/TextArea.d.ts.map +1 -1
  126. package/dist/TextArea/TextArea.js +13 -2
  127. package/dist/TextInput/TextInput.d.ts.map +1 -1
  128. package/dist/TextInput/TextInput.js +3 -3
  129. package/dist/TimeInput/TimeInput.d.ts +6 -2
  130. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  131. package/dist/TimeInput/TimeInput.js +21 -14
  132. package/dist/TimeInput/TouchTimeField.d.ts.map +1 -1
  133. package/dist/TimeInput/TouchTimeField.js +5 -4
  134. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  135. package/dist/Timestamp/Timestamp.js +2 -2
  136. package/dist/Timestamp/TimestampHoverCard.js +4 -4
  137. package/dist/Toast/Toast.d.ts.map +1 -1
  138. package/dist/Toast/Toast.js +60 -20
  139. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  140. package/dist/Toast/ToastViewport.js +82 -51
  141. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  142. package/dist/Tokenizer/Tokenizer.js +13 -2
  143. package/dist/Tokenizer/TokenizerBottomSheet.js +3 -3
  144. package/dist/Toolbar/Toolbar.d.ts.map +1 -1
  145. package/dist/Toolbar/Toolbar.js +2 -1
  146. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  147. package/dist/TopNav/TopNavMegaMenu.js +3 -0
  148. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  149. package/dist/TopNav/TopNavMenu.js +1 -0
  150. package/dist/Typeahead/Typeahead.d.ts +1 -1
  151. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  152. package/dist/Typeahead/Typeahead.js +9 -1
  153. package/dist/astryx.css +20 -4
  154. package/dist/gestures/GestureArena.d.ts +6 -0
  155. package/dist/gestures/GestureArena.d.ts.map +1 -1
  156. package/dist/gestures/GestureArena.js +39 -0
  157. package/dist/gestures/GestureHost.d.ts +352 -0
  158. package/dist/gestures/GestureHost.d.ts.map +1 -0
  159. package/dist/gestures/GestureHost.js +1773 -0
  160. package/dist/gestures/GestureRecognizer.d.ts +10 -0
  161. package/dist/gestures/GestureRecognizer.d.ts.map +1 -1
  162. package/dist/gestures/GestureRecognizer.js +16 -0
  163. package/dist/gestures/LongPressGestureRecognizer.d.ts +1 -0
  164. package/dist/gestures/LongPressGestureRecognizer.d.ts.map +1 -1
  165. package/dist/gestures/LongPressGestureRecognizer.js +3 -0
  166. package/dist/gestures/PanGestureRecognizer.d.ts +1 -0
  167. package/dist/gestures/PanGestureRecognizer.d.ts.map +1 -1
  168. package/dist/gestures/PanGestureRecognizer.js +3 -0
  169. package/dist/gestures/PinchGestureRecognizer.d.ts +31 -0
  170. package/dist/gestures/PinchGestureRecognizer.d.ts.map +1 -0
  171. package/dist/gestures/PinchGestureRecognizer.js +128 -0
  172. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts +71 -0
  173. package/dist/gestures/ScreenEdgePanGestureRecognizer.d.ts.map +1 -0
  174. package/dist/gestures/ScreenEdgePanGestureRecognizer.js +223 -0
  175. package/dist/gestures/SwipeGestureRecognizer.d.ts +37 -0
  176. package/dist/gestures/SwipeGestureRecognizer.d.ts.map +1 -0
  177. package/dist/gestures/SwipeGestureRecognizer.js +148 -0
  178. package/dist/gestures/TapGestureRecognizer.d.ts +1 -0
  179. package/dist/gestures/TapGestureRecognizer.d.ts.map +1 -1
  180. package/dist/gestures/TapGestureRecognizer.js +3 -0
  181. package/dist/gestures/VelocityTracker.d.ts +6 -2
  182. package/dist/gestures/VelocityTracker.d.ts.map +1 -1
  183. package/dist/gestures/VelocityTracker.js +7 -3
  184. package/dist/gestures/haptics.d.ts +65 -0
  185. package/dist/gestures/haptics.d.ts.map +1 -0
  186. package/dist/gestures/haptics.js +182 -0
  187. package/dist/gestures/nativeScroll.d.ts +42 -0
  188. package/dist/gestures/nativeScroll.d.ts.map +1 -0
  189. package/dist/gestures/nativeScroll.js +228 -0
  190. package/dist/gestures/touchAction.d.ts +60 -0
  191. package/dist/gestures/touchAction.d.ts.map +1 -0
  192. package/dist/gestures/touchAction.js +157 -0
  193. package/dist/gestures/touchActionRule.d.ts +34 -0
  194. package/dist/gestures/touchActionRule.d.ts.map +1 -0
  195. package/dist/gestures/touchActionRule.js +140 -0
  196. package/dist/gestures/types.d.ts +18 -7
  197. package/dist/gestures/types.d.ts.map +1 -1
  198. package/dist/gestures/types.js +22 -2
  199. package/dist/hooks/index.d.ts +1 -1
  200. package/dist/hooks/index.d.ts.map +1 -1
  201. package/dist/hooks/modalAnnounce.d.ts.map +1 -1
  202. package/dist/hooks/modalAnnounce.js +107 -61
  203. package/dist/hooks/useAdaptivePresentation.d.ts.map +1 -1
  204. package/dist/hooks/useAdaptivePresentation.js +4 -1
  205. package/dist/hooks/useAnnounce.d.ts +101 -42
  206. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  207. package/dist/hooks/useAnnounce.js +161 -75
  208. package/dist/hooks/useAnnounceRenderedText.d.ts +11 -3
  209. package/dist/hooks/useAnnounceRenderedText.d.ts.map +1 -1
  210. package/dist/hooks/useAnnounceRenderedText.js +5 -3
  211. package/dist/hooks/useBusyAnnouncement.d.ts.map +1 -1
  212. package/dist/hooks/useBusyAnnouncement.js +6 -12
  213. package/dist/hooks/useMenuHover.d.ts.map +1 -1
  214. package/dist/hooks/useMenuHover.js +12 -1
  215. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  216. package/dist/i18n/generated-locales/en.generated.js +5 -0
  217. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  218. package/dist/i18n/generated-locales/pseudo.generated.js +5 -0
  219. package/dist/motion/animator.d.ts +7 -1
  220. package/dist/motion/animator.d.ts.map +1 -1
  221. package/dist/motion/animator.js +119 -27
  222. package/dist/theme/defineTheme.d.ts +19 -5
  223. package/dist/theme/defineTheme.d.ts.map +1 -1
  224. package/dist/theme/defineTheme.js +64 -4
  225. package/dist/theme/domainTokens/domainTokenDefaults.d.ts +3 -0
  226. package/dist/theme/domainTokens/domainTokenDefaults.d.ts.map +1 -0
  227. package/dist/theme/domainTokens/domainTokenDefaults.js +19 -0
  228. package/dist/theme/domainTokens/index.d.ts +5 -4
  229. package/dist/theme/domainTokens/index.d.ts.map +1 -1
  230. package/dist/theme/domainTokens/index.js +5 -9
  231. package/dist/theme/index.d.ts +1 -0
  232. package/dist/theme/index.d.ts.map +1 -1
  233. package/dist/theme/motionKnobs.d.ts +56 -0
  234. package/dist/theme/motionKnobs.d.ts.map +1 -0
  235. package/dist/theme/motionKnobs.js +48 -0
  236. package/dist/theme/resolveThemeValues.d.ts +11 -4
  237. package/dist/theme/resolveThemeValues.d.ts.map +1 -1
  238. package/dist/theme/resolveThemeValues.js +40 -4
  239. package/dist/theme/themeAdaptations.d.ts +7 -3
  240. package/dist/theme/themeAdaptations.d.ts.map +1 -1
  241. package/dist/theme/themeAdaptations.js +36 -7
  242. package/dist/theme/themeMotion.d.ts +96 -0
  243. package/dist/theme/themeMotion.d.ts.map +1 -0
  244. package/dist/theme/themeMotion.js +177 -0
  245. package/dist/theme/tokenReferences.d.ts +31 -0
  246. package/dist/theme/tokenReferences.d.ts.map +1 -0
  247. package/dist/theme/tokenReferences.js +132 -0
  248. package/dist/theme/tokens.d.ts +1 -0
  249. package/dist/theme/tokens.d.ts.map +1 -1
  250. package/dist/theme/tokens.js +9 -129
  251. package/dist/theme/tokens.stylex.d.ts +12 -0
  252. package/dist/theme/tokens.stylex.d.ts.map +1 -1
  253. package/dist/theme/tokens.stylex.js +12 -0
  254. package/dist/utils/focusReturn.d.ts +17 -1
  255. package/dist/utils/focusReturn.d.ts.map +1 -1
  256. package/dist/utils/focusReturn.js +11 -4
  257. package/dist/utils/getNodeText.d.ts +8 -0
  258. package/dist/utils/getNodeText.d.ts.map +1 -0
  259. package/dist/utils/getNodeText.js +37 -0
  260. package/dist/utils/interactionModality.d.ts +11 -2
  261. package/dist/utils/interactionModality.d.ts.map +1 -1
  262. package/dist/utils/interactionModality.js +58 -5
  263. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  264. package/dist/utils/interactionOverlay.stylex.js +17 -8
  265. package/dist/utils/plainDate.d.ts +2 -0
  266. package/dist/utils/plainDate.d.ts.map +1 -1
  267. package/dist/utils/plainDate.js +46 -3
  268. package/dist/utils/presentation.d.ts +50 -0
  269. package/dist/utils/presentation.d.ts.map +1 -0
  270. package/dist/utils/presentation.js +125 -0
  271. package/dist/utils/pressFeedback.d.ts.map +1 -1
  272. package/dist/utils/pressFeedback.js +20 -1
  273. package/dist/utils/primaryClick.d.ts +11 -0
  274. package/dist/utils/primaryClick.d.ts.map +1 -0
  275. package/dist/utils/primaryClick.js +25 -0
  276. package/dist/utils/timeFormat.d.ts +47 -0
  277. package/dist/utils/timeFormat.d.ts.map +1 -0
  278. package/dist/utils/timeFormat.js +240 -0
  279. package/dist/utils/touchPresentation.d.ts.map +1 -1
  280. package/dist/utils/touchPresentation.js +5 -3
  281. package/dist/utils/touchPresentation.stylex.d.ts +15 -0
  282. package/dist/utils/touchPresentation.stylex.d.ts.map +1 -0
  283. package/dist/utils/touchPresentation.stylex.js +33 -0
  284. package/dist/utils/unicodeDigits.d.ts +20 -0
  285. package/dist/utils/unicodeDigits.d.ts.map +1 -0
  286. package/dist/utils/unicodeDigits.js +70 -0
  287. package/locales/en.json +23 -3
  288. package/locales/pseudo.json +15 -0
  289. package/package.json +5 -4
  290. package/src/AlertDialog/AlertDialog.tsx +6 -5
  291. package/src/AlertDialog/__tests__/AlertDialog.a11y.chromium.spec.ts +18 -6
  292. package/src/Avatar/Avatar.spec.md +22 -22
  293. package/src/Avatar/Avatar.tsx +18 -1
  294. package/src/Avatar/__tests__/AvatarForcedColors.a11y.chromium.spec.ts +126 -0
  295. package/src/Badge/Badge.doc.mjs +1 -1
  296. package/src/Badge/Badge.tsx +19 -2
  297. package/src/Badge/__tests__/BadgeLargerText.a11y.chromium.spec.ts +260 -0
  298. package/src/BottomSheet/BottomSheet.test.tsx +46 -0
  299. package/src/BottomSheet/BottomSheet.tsx +1 -1
  300. package/src/BottomSheet/BottomSheetPanel.tsx +2 -1
  301. package/src/BottomSheet/useSheetGestures.test.ts +52 -0
  302. package/src/BottomSheet/useSheetGestures.ts +37 -6
  303. package/src/Breadcrumbs/__tests__/Breadcrumbs.a11y.chromium.spec.ts +18 -6
  304. package/src/Button/Button.tsx +4 -4
  305. package/src/Calendar/Calendar.spec.md +87 -48
  306. package/src/Calendar/__tests__/Calendar.a11y.chromium.spec.ts +21 -7
  307. package/src/Carousel/__tests__/Carousel.a11y.chromium.spec.ts +21 -7
  308. package/src/CheckboxInput/CheckboxInput.tsx +6 -5
  309. package/src/ClickableCard/ClickableCard.test.tsx +96 -0
  310. package/src/ClickableCard/ClickableCard.tsx +48 -4
  311. package/src/Collapsible/Collapsible.spec.md +2 -0
  312. package/src/Collapsible/CollapsibleGroup.spec.md +57 -29
  313. package/src/Collapsible/__tests__/Collapsible.a11y.chromium.spec.ts +18 -7
  314. package/src/Collapsible/__tests__/CollapsibleGroupAccordion.a11y.chromium.spec.ts +18 -6
  315. package/src/ComplexSelector/ComplexSelector.test.tsx +37 -0
  316. package/src/ContextMenu/ContextMenu.test.tsx +35 -0
  317. package/src/DateInput/DateInput.test.tsx +115 -3
  318. package/src/DateInput/DateInput.tsx +29 -14
  319. package/src/DateInput/DateInputTouch.test.tsx +76 -0
  320. package/src/DateInput/MonthScroller.tsx +106 -20
  321. package/src/DateInput/MonthScrollerSettle.test.tsx +165 -0
  322. package/src/DateInput/TouchDateField.tsx +14 -3
  323. package/src/DateInput/__tests__/MonthScrollerSteps.interaction.browser.spec.ts +312 -0
  324. package/src/DateRangeInput/DateRangeInput.test.tsx +46 -3
  325. package/src/DateRangeInput/DateRangeInput.tsx +16 -12
  326. package/src/DateTimeInput/DateTimeInput.doc.mjs +10 -8
  327. package/src/DateTimeInput/DateTimeInput.spec.md +75 -51
  328. package/src/DateTimeInput/DateTimeInput.test.tsx +81 -0
  329. package/src/DateTimeInput/DateTimeInput.tsx +46 -24
  330. package/src/DateTimeInput/NativeTimeSegment.tsx +4 -6
  331. package/src/DateTimeInput/TouchDateTimeField.tsx +3 -7
  332. package/src/Dialog/Dialog.test.tsx +216 -2
  333. package/src/Dialog/Dialog.tsx +42 -9
  334. package/src/Dialog/DialogHeader.tsx +5 -4
  335. package/src/Dialog/__tests__/DialogSecondDocument.a11y.browser.spec.ts +202 -0
  336. package/src/Divider/Divider.tsx +2 -1
  337. package/src/Drawer/Drawer.spec.md +111 -80
  338. package/src/Drawer/Drawer.test.tsx +35 -0
  339. package/src/Drawer/Drawer.tsx +13 -2
  340. package/src/Drawer/DrawerHeader.spec.md +181 -0
  341. package/src/Drawer/__tests__/DrawerNonModalPageScroll.a11y.chromium.spec.ts +267 -0
  342. package/src/DropdownMenu/DropdownMenu.test.tsx +41 -0
  343. package/src/DropdownMenu/DropdownMenu.tsx +10 -3
  344. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +34 -0
  345. package/src/DropdownMenu/MenuBottomSheetActionList.tsx +6 -5
  346. package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +19 -7
  347. package/src/DropdownMenu/__tests__/MenuButton.a11y.chromium.spec.ts +21 -9
  348. package/src/DropdownMenu/lazyMenuBottomSheet.test.ts +60 -0
  349. package/src/DropdownMenu/lazyMenuBottomSheet.ts +36 -7
  350. package/src/DropdownMenu/renderDropdownItems.tsx +24 -19
  351. package/src/EmptyState/EmptyState.tsx +2 -1
  352. package/src/Field/FieldLabel.tsx +5 -4
  353. package/src/Field/InputClearButton.tsx +3 -3
  354. package/src/Field/PanelSearchInput.tsx +2 -2
  355. package/src/FieldStatus/FieldStatus.tsx +2 -2
  356. package/src/FileInput/FileInput.test.tsx +21 -0
  357. package/src/FileInput/FileInput.tsx +4 -1
  358. package/src/FormLayout/FormLayout.spec.md +7 -8
  359. package/src/Heading/Heading.tsx +1 -1
  360. package/src/Icon/Icon.tsx +1 -1
  361. package/src/Indicator/CheckIndicator.spec.md +47 -42
  362. package/src/Indicator/CheckIndicator.tsx +2 -1
  363. package/src/Indicator/CheckboxIndicator.spec.md +40 -37
  364. package/src/Indicator/CheckboxIndicator.tsx +3 -1
  365. package/src/Indicator/Indicator.spec.md +188 -0
  366. package/src/Indicator/RadioIndicator.tsx +3 -1
  367. package/src/Item/Item.tsx +2 -1
  368. package/src/Item/ItemSwipeLayer.tsx +1 -1
  369. package/src/Kbd/Kbd.spec.md +81 -38
  370. package/src/Layer/__tests__/LayerBrowserHide.a11y.chromium.spec.ts +126 -0
  371. package/src/Layer/popoverOperations.test.ts +205 -0
  372. package/src/Layer/popoverOperations.ts +172 -0
  373. package/src/Layer/useLayer.test.tsx +348 -1
  374. package/src/Layer/useLayer.tsx +118 -71
  375. package/src/Layout/Layout.spec.md +127 -131
  376. package/src/Layout/Layout.tsx +1 -1
  377. package/src/Layout/LayoutContent.spec.md +205 -0
  378. package/src/Layout/LayoutContent.tsx +1 -1
  379. package/src/Layout/LayoutFooter.spec.md +190 -0
  380. package/src/Layout/LayoutFooter.tsx +1 -1
  381. package/src/Layout/LayoutHeader.spec.md +193 -0
  382. package/src/Layout/LayoutHeader.tsx +1 -1
  383. package/src/Layout/LayoutPanel.spec.md +194 -0
  384. package/src/Layout/__tests__/Layout.a11y.chromium.spec.ts +18 -6
  385. package/src/Lightbox/Lightbox.test.tsx +18 -0
  386. package/src/Lightbox/Lightbox.tsx +5 -0
  387. package/src/Lightbox/LightboxViewport.a11y.browser.spec.ts +8 -4
  388. package/src/Link/__tests__/Link.a11y.chromium.spec.ts +18 -8
  389. package/src/List/List.tsx +1 -1
  390. package/src/List/ListItem.spec.md +205 -0
  391. package/src/List/ListItem.tsx +3 -3
  392. package/src/MetadataList/MetadataList.spec.md +187 -0
  393. package/src/MetadataList/MetadataListItem.spec.md +165 -0
  394. package/src/MobileNav/MobileNav.test.tsx +15 -0
  395. package/src/MobileNav/MobileNav.tsx +9 -1
  396. package/src/MobileNav/__tests__/MobileNavHeader.a11y.chromium.spec.ts +89 -0
  397. package/src/MoreMenu/MoreMenu.test.tsx +11 -0
  398. package/src/MultiSelector/CreateRow.a11y.chromium.spec.ts +7 -8
  399. package/src/MultiSelector/MultiSelector.spec.md +7 -4
  400. package/src/MultiSelector/MultiSelector.test.tsx +270 -1
  401. package/src/MultiSelector/MultiSelector.tsx +25 -10
  402. package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +8 -1
  403. package/src/NavMenu/NavHeadingMenu.spec.md +1 -5
  404. package/src/NumberInput/NumberInput.doc.mjs +13 -7
  405. package/src/NumberInput/NumberInput.spec.md +59 -37
  406. package/src/NumberInput/NumberInput.tsx +13 -3
  407. package/src/NumberInput/__tests__/NumberInput.coarse-pointer.a11y.chromium.spec.ts +102 -0
  408. package/src/NumberInput/numberParser.ts +7 -45
  409. package/src/ProgressBar/ProgressBar.test.tsx +108 -32
  410. package/src/ProgressBar/ProgressBar.tsx +58 -10
  411. package/src/ProgressBar/__tests__/ProgressBar.a11y.chromium.spec.ts +21 -9
  412. package/src/ProgressBar/__tests__/ProgressBarMotion.a11y.chromium.spec.ts +831 -0
  413. package/src/Resizable/__tests__/ResizeHandle.a11y.chromium.spec.ts +21 -14
  414. package/src/Resizable/useResizable.test.ts +43 -0
  415. package/src/Resizable/useResizable.ts +32 -9
  416. package/src/SegmentedControl/SegmentedControl.test.tsx +84 -0
  417. package/src/SegmentedControl/SegmentedControlItem.tsx +11 -5
  418. package/src/Selector/Selector.test.tsx +90 -1
  419. package/src/Selector/__tests__/Selector.combobox.a11y.test.tsx +8 -1
  420. package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +8 -1
  421. package/src/Selector/useSelectorPresentation.ts +31 -3
  422. package/src/SideNav/SideNav.test.tsx +27 -0
  423. package/src/SideNav/__tests__/SideNavRailMotion.interaction.browser.spec.ts +176 -51
  424. package/src/Skeleton/Skeleton.tsx +3 -1
  425. package/src/Slider/Slider.test.tsx +31 -0
  426. package/src/Slider/Slider.tsx +8 -3
  427. package/src/Slider/__tests__/Slider.a11y.chromium.spec.ts +19 -7
  428. package/src/Spinner/Spinner.tsx +5 -3
  429. package/src/Stack/Stack.tsx +1 -1
  430. package/src/Stack/StackItem.tsx +1 -1
  431. package/src/TabList/TabList.test.tsx +58 -4
  432. package/src/TabList/TabList.tsx +16 -1
  433. package/src/TabList/__tests__/TabPressPointer.interaction.browser.spec.ts +163 -0
  434. package/src/Table/__tests__/Table.a11y.chromium.spec.ts +18 -6
  435. package/src/Table/plugins/columnResize/useTableColumnResize.test.tsx +22 -0
  436. package/src/Table/plugins/columnResize/useTableColumnResize.tsx +8 -4
  437. package/src/Text/Text.tsx +1 -1
  438. package/src/Text/useTruncation.test.tsx +128 -1
  439. package/src/Text/useTruncation.ts +23 -5
  440. package/src/TextArea/TextArea.spec.md +10 -13
  441. package/src/TextArea/TextArea.test.tsx +60 -0
  442. package/src/TextArea/TextArea.tsx +15 -1
  443. package/src/TextInput/TextInput.test.tsx +21 -0
  444. package/src/TextInput/TextInput.tsx +3 -1
  445. package/src/TimeInput/NativeTimeInput.test.tsx +17 -0
  446. package/src/TimeInput/Presentation.test.tsx +21 -0
  447. package/src/TimeInput/TimeInput.doc.mjs +8 -8
  448. package/src/TimeInput/TimeInput.spec.md +45 -48
  449. package/src/TimeInput/TimeInput.test.tsx +76 -0
  450. package/src/TimeInput/TimeInput.tsx +36 -18
  451. package/src/TimeInput/TouchTimeField.tsx +4 -6
  452. package/src/Timestamp/Timestamp.spec.md +6 -12
  453. package/src/Timestamp/Timestamp.test.tsx +30 -5
  454. package/src/Timestamp/Timestamp.tsx +6 -2
  455. package/src/Timestamp/TimestampHoverCard.tsx +4 -4
  456. package/src/Toast/Toast.spec.md +14 -20
  457. package/src/Toast/Toast.tsx +104 -36
  458. package/src/Toast/ToastViewport.test.tsx +719 -1
  459. package/src/Toast/ToastViewport.tsx +100 -50
  460. package/src/Tokenizer/Tokenizer.spec.md +5 -3
  461. package/src/Tokenizer/Tokenizer.test.tsx +68 -0
  462. package/src/Tokenizer/Tokenizer.tsx +14 -2
  463. package/src/Tokenizer/TokenizerBottomSheet.test.tsx +15 -4
  464. package/src/Tokenizer/TokenizerBottomSheet.tsx +3 -3
  465. package/src/Toolbar/Toolbar.spec.md +5 -6
  466. package/src/Toolbar/Toolbar.test.tsx +30 -0
  467. package/src/Toolbar/Toolbar.tsx +2 -1
  468. package/src/Toolbar/__tests__/Toolbar.a11y.chromium.spec.ts +18 -6
  469. package/src/Tooltip/__tests__/Tooltip.a11y.chromium.spec.ts +18 -7
  470. package/src/TopNav/TopNav.test.tsx +27 -0
  471. package/src/TopNav/TopNavMegaMenu.test.tsx +21 -0
  472. package/src/TopNav/TopNavMegaMenu.tsx +4 -1
  473. package/src/TopNav/TopNavMenu.test.tsx +17 -0
  474. package/src/TopNav/TopNavMenu.tsx +1 -0
  475. package/src/Typeahead/Typeahead.test.tsx +40 -0
  476. package/src/Typeahead/Typeahead.tsx +12 -1
  477. package/src/__tests__/pressState.ts +8 -4
  478. package/src/gestures/GestureArena.ts +35 -0
  479. package/src/gestures/GestureHost.ts +2065 -0
  480. package/src/gestures/GestureRecognizer.ts +18 -0
  481. package/src/gestures/LongPressGestureRecognizer.ts +4 -0
  482. package/src/gestures/PanGestureRecognizer.ts +4 -0
  483. package/src/gestures/PinchGestureRecognizer.ts +148 -0
  484. package/src/gestures/ScreenEdgePanGestureRecognizer.ts +256 -0
  485. package/src/gestures/SwipeGestureRecognizer.ts +197 -0
  486. package/src/gestures/TapGestureRecognizer.ts +4 -0
  487. package/src/gestures/VelocityTracker.ts +10 -3
  488. package/src/gestures/__tests__/GestureHost.test.ts +2087 -0
  489. package/src/gestures/__tests__/PanGestureRecognizer.test.ts +4 -4
  490. package/src/gestures/__tests__/PinchGestureRecognizer.test.ts +74 -0
  491. package/src/gestures/__tests__/ScreenEdgePanGestureRecognizer.test.ts +498 -0
  492. package/src/gestures/__tests__/SwipeGestureRecognizer.test.ts +108 -0
  493. package/src/gestures/__tests__/arena.test.ts +5 -0
  494. package/src/gestures/__tests__/arenaPinchSwipeEdge.test.ts +193 -0
  495. package/src/gestures/__tests__/browser/build-fixture.mjs +46 -0
  496. package/src/gestures/__tests__/browser/fixture.ts +307 -0
  497. package/src/gestures/__tests__/browser/gestures.interaction.browser.spec.ts +1137 -0
  498. package/src/gestures/__tests__/browserNegotiation.test.ts +293 -0
  499. package/src/gestures/__tests__/haptics.test.ts +187 -0
  500. package/src/gestures/__tests__/harness.ts +21 -2
  501. package/src/gestures/__tests__/recognizerKind.test.ts +78 -0
  502. package/src/gestures/__tests__/touchActionRule.test.ts +54 -0
  503. package/src/gestures/haptics.ts +203 -0
  504. package/src/gestures/nativeScroll.ts +277 -0
  505. package/src/gestures/touchAction.ts +191 -0
  506. package/src/gestures/touchActionRule.ts +157 -0
  507. package/src/gestures/types.ts +30 -9
  508. package/src/hooks/index.ts +5 -1
  509. package/src/hooks/modalAnnounce.ts +129 -72
  510. package/src/hooks/useAdaptivePresentation.ts +4 -1
  511. package/src/hooks/useAnnounce.doc.mjs +35 -3
  512. package/src/hooks/useAnnounce.replace.test.tsx +516 -0
  513. package/src/hooks/useAnnounce.ts +209 -102
  514. package/src/hooks/useAnnounceRenderedText.adopters.test.tsx +10 -1
  515. package/src/hooks/useAnnounceRenderedText.ts +17 -3
  516. package/src/hooks/useBusyAnnouncement.ts +7 -10
  517. package/src/hooks/useMenuHover.ts +15 -1
  518. package/src/i18n/generated-locales/en.generated.ts +6 -0
  519. package/src/i18n/generated-locales/pseudo.generated.ts +6 -0
  520. package/src/motion/README.md +11 -1
  521. package/src/motion/animator.test.ts +151 -3
  522. package/src/motion/animator.ts +149 -33
  523. package/src/theme/Theme.doc.mjs +1 -1
  524. package/src/theme/defineTheme.ts +117 -8
  525. package/src/theme/derivedVarRegistry.test.ts +4 -0
  526. package/src/theme/domainTokens/domainTokenDefaults.ts +19 -0
  527. package/src/theme/domainTokens/index.ts +6 -10
  528. package/src/theme/expandMotionScale.test.ts +1 -1
  529. package/src/theme/index.ts +5 -0
  530. package/src/theme/motionKnobs.ts +82 -0
  531. package/src/theme/resolveThemeValues.ts +68 -6
  532. package/src/theme/themeAdaptations.ts +52 -12
  533. package/src/theme/themeMotion.test.ts +620 -0
  534. package/src/theme/themeMotion.ts +221 -0
  535. package/src/theme/tokenReferences.ts +149 -0
  536. package/src/theme/tokens.stylex.ts +10 -0
  537. package/src/theme/tokens.ts +15 -158
  538. package/src/utils/focusReturn.ts +17 -6
  539. package/src/utils/getNodeText.test.ts +24 -0
  540. package/src/utils/getNodeText.ts +37 -0
  541. package/src/utils/interactionModality.test.ts +45 -1
  542. package/src/utils/interactionModality.ts +64 -5
  543. package/src/utils/interactionOverlay.stylex.ts +12 -3
  544. package/src/utils/plainDate.test.ts +90 -0
  545. package/src/utils/plainDate.ts +58 -3
  546. package/src/utils/presentation.test.ts +380 -0
  547. package/src/utils/presentation.ts +180 -0
  548. package/src/utils/pressFeedback.test.ts +138 -0
  549. package/src/utils/pressFeedback.ts +34 -11
  550. package/src/utils/pressPaintPriority.test.ts +80 -0
  551. package/src/utils/primaryClick.test.ts +38 -0
  552. package/src/utils/primaryClick.ts +28 -0
  553. package/src/utils/timeFormat.test.ts +204 -0
  554. package/src/utils/timeFormat.ts +314 -0
  555. package/src/utils/touchPresentation.stylex.ts +43 -0
  556. package/src/utils/touchPresentation.test.ts +140 -1
  557. package/src/utils/touchPresentation.ts +5 -3
  558. package/src/utils/unicodeDigits.test.ts +44 -0
  559. package/src/utils/unicodeDigits.ts +71 -0
@@ -142,9 +142,20 @@ export const MANIPULATION: NativeTouchBehavior = {
142
142
  doubleTapZoom: false,
143
143
  };
144
144
 
145
+ /**
146
+ * What a recognizer is. The gesture code tells the family apart by it, never
147
+ * by `instanceof` (`architecture:react-component-runtime` INV13); a
148
+ * screen-edge pan is its own kind, though it is built on the pan.
149
+ */
150
+ export type RecognizerKind =
151
+ 'tap' | 'longPress' | 'pan' | 'screenEdgePan' | 'swipe' | 'pinch';
152
+
145
153
  let nextRecognizerId = 1;
146
154
 
147
155
  export abstract class GestureRecognizer {
156
+ /** What this recognizer is (see RecognizerKind). */
157
+ abstract get kind(): RecognizerKind;
158
+
148
159
  /** Stable id, for ordering and debugging. */
149
160
  readonly id = nextRecognizerId++;
150
161
  name: string;
@@ -568,12 +579,19 @@ export abstract class GestureRecognizer {
568
579
  }
569
580
  }
570
581
 
582
+ /** @internal The host's hook: listeners follow whether anything is enabled. */
583
+ onEnabledChange: (() => void) | null = null;
584
+
571
585
  /**
572
586
  * UIKit's `isEnabled` setter: turning a recognizer off mid-gesture cancels
573
587
  * the gesture (an active one) or fails it (a possible one).
574
588
  */
575
589
  setEnabled(value: boolean): void {
590
+ const changed = this.isEnabled !== value;
576
591
  this.isEnabled = value;
592
+ if (changed) {
593
+ this.onEnabledChange?.();
594
+ }
577
595
  if (!value && (this.state !== 'possible' || this.isInvolved())) {
578
596
  this.cancel();
579
597
  }
@@ -41,6 +41,10 @@ export interface LongPressGestureRecognizerOptions extends GestureRecognizerOpti
41
41
  }
42
42
 
43
43
  export class LongPressGestureRecognizer extends GestureRecognizer {
44
+ override get kind(): GestureRecognizer['kind'] {
45
+ return 'longPress';
46
+ }
47
+
44
48
  minimumPressDuration: number;
45
49
  allowableMovement: number;
46
50
  numberOfTapsRequired: number;
@@ -87,6 +87,10 @@ const DIRECTION_VECTORS: Partial<Record<PanDirection, Point>> = {
87
87
  };
88
88
 
89
89
  export class PanGestureRecognizer extends GestureRecognizer {
90
+ override get kind(): GestureRecognizer['kind'] {
91
+ return 'pan';
92
+ }
93
+
90
94
  minimumNumberOfTouches: number;
91
95
  maximumNumberOfTouches: number;
92
96
  hysteresis: number;
@@ -0,0 +1,148 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file PinchGestureRecognizer.ts
5
+ * @input Touches from a GestureArena
6
+ * @output Exports PinchGestureRecognizer (UIPinchGestureRecognizer) and its
7
+ * options
8
+ * @position Continuous two-finger recognizer of packages/core/src/gestures
9
+ *
10
+ * Tracks the first two fingers; more are ignored. Begins once the distance
11
+ * between them has changed by `hysteresis` px. As in UIKit, `scale` is then
12
+ * the current distance over the starting distance moved by the hysteresis
13
+ * toward the pinch, so it does not jump (settable to re-base it); `velocity`
14
+ * is scale per second. Lifting either finger ends an
15
+ * active pinch and fails a possible one.
16
+ *
17
+ * A host gives every element WITHOUT a pinch recognizer `pinch-zoom` in its
18
+ * `touch-action`, so the page stays zoomable (WCAG 1.4.4); attaching one
19
+ * takes the two-finger gesture for this element only.
20
+ */
21
+
22
+ import {UIKIT_PINCH} from '../motion/uikit/gestures';
23
+ import {centroid, distance} from './geometry';
24
+ import {
25
+ GestureRecognizer,
26
+ isActive,
27
+ type GestureRecognizerOptions,
28
+ type NativeTouchBehavior,
29
+ } from './GestureRecognizer';
30
+ import type {GestureEventContext, GestureTouch, Point} from './types';
31
+ import {VelocityTracker} from './VelocityTracker';
32
+
33
+ export interface PinchGestureRecognizerOptions extends GestureRecognizerOptions<PinchGestureRecognizer> {
34
+ hysteresis?: number;
35
+ }
36
+
37
+ export class PinchGestureRecognizer extends GestureRecognizer {
38
+ override get kind(): GestureRecognizer['kind'] {
39
+ return 'pinch';
40
+ }
41
+
42
+ hysteresis: number;
43
+ private initialSpan = 0;
44
+ private scaleValue = 1;
45
+ private readonly tracker = new VelocityTracker();
46
+ private lastTime = 0;
47
+
48
+ constructor(options: PinchGestureRecognizerOptions = {}) {
49
+ super(options);
50
+ this.hysteresis = options.hysteresis ?? UIKIT_PINCH.hysteresis.value;
51
+ }
52
+
53
+ /** Current span over the span the fingers started at. */
54
+ get scale(): number {
55
+ return this.scaleValue;
56
+ }
57
+
58
+ /** Re-base: from now on the scale reads `value` at the current span. */
59
+ set scale(value: number) {
60
+ const span = this.span();
61
+ if (span > 0 && value > 0) {
62
+ this.initialSpan = span / value;
63
+ this.scaleValue = value;
64
+ // The velocity continues from the re-based value, without a jump.
65
+ this.tracker.reset();
66
+ this.tracker.add(value, 0, this.lastTime);
67
+ }
68
+ }
69
+
70
+ /** Scale per second (UIKit's filter; measured for pans, assumed here). */
71
+ get velocity(): number {
72
+ return this.tracker.velocity().x;
73
+ }
74
+
75
+ /** The midpoint between the two fingers. */
76
+ focalPoint(): Point {
77
+ return centroid(this.touches.values());
78
+ }
79
+
80
+ /** Two fingers on this view are this recognizer's, not the browser's zoom. */
81
+ override get nativeTouchBehavior(): NativeTouchBehavior {
82
+ return {panX: true, panY: true, pinchZoom: false, doubleTapZoom: false};
83
+ }
84
+
85
+ protected override acceptsTouch(touch: GestureTouch): boolean {
86
+ return this.numberOfTouches < 2 && super.acceptsTouch(touch);
87
+ }
88
+
89
+ protected override touchesBegan(
90
+ _touches: ReadonlyArray<GestureTouch>,
91
+ event: GestureEventContext,
92
+ ): void {
93
+ this.lastTime = event.time;
94
+ if (this.numberOfTouches === 2) {
95
+ this.initialSpan = this.span();
96
+ this.scaleValue = 1;
97
+ this.tracker.reset();
98
+ this.tracker.add(1, 0, event.time);
99
+ }
100
+ }
101
+
102
+ protected override touchesMoved(
103
+ _touches: ReadonlyArray<GestureTouch>,
104
+ event: GestureEventContext,
105
+ ): void {
106
+ if (this.numberOfTouches < 2 || this.initialSpan <= 0) {
107
+ return;
108
+ }
109
+ this.lastTime = event.time;
110
+ const span = this.span();
111
+ // Once recognized, a pinch waiting on a recognizer it requires to fail
112
+ // keeps its re-based start: its moves only follow the fingers.
113
+ if (this.state === 'possible' && this.pending == null) {
114
+ if (Math.abs(span - this.initialSpan) >= this.hysteresis) {
115
+ // UIKit measures from the start moved by the hysteresis, and its
116
+ // first velocity spans from the touch-down (scale 1) to here.
117
+ this.initialSpan +=
118
+ Math.sign(span - this.initialSpan) * this.hysteresis;
119
+ this.scaleValue = span / this.initialSpan;
120
+ this.tracker.add(this.scaleValue, 0, event.time);
121
+ this.setState('began');
122
+ }
123
+ return;
124
+ }
125
+ this.scaleValue = span / this.initialSpan;
126
+ // Every move of the fingers is a sample: a span that holds while they
127
+ // move reads as no change, so the velocity never goes stale.
128
+ this.tracker.add(this.scaleValue, 0, event.time, {isMotion: true});
129
+ if (isActive(this.state)) {
130
+ this.setState('changed');
131
+ }
132
+ }
133
+
134
+ protected override touchesEnded(): void {
135
+ this.setState(isActive(this.state) ? 'ended' : 'failed');
136
+ }
137
+
138
+ protected override reset(): void {
139
+ this.initialSpan = 0;
140
+ this.scaleValue = 1;
141
+ this.tracker.reset();
142
+ }
143
+
144
+ private span(): number {
145
+ const [a, b] = this.trackedTouches;
146
+ return a == null || b == null ? 0 : distance(a, b);
147
+ }
148
+ }
@@ -0,0 +1,256 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file ScreenEdgePanGestureRecognizer.ts
5
+ * @input Touches from a GestureArena; the viewport size and writing
6
+ * direction from its environment
7
+ * @output Exports ScreenEdgePanGestureRecognizer
8
+ * (UIScreenEdgePanGestureRecognizer), its options and edge type
9
+ * @position Continuous recognizer of packages/core/src/gestures, a pan that
10
+ * only starts from a band at the edge of the viewport
11
+ *
12
+ * A touch that lands outside every requested band fails at once, so a
13
+ * recognizer that requires this one to fail is not held up by a touch in the
14
+ * middle of the screen. Inside a band, the pan begins on movement away from
15
+ * that edge. `leading` and `trailing` resolve against the view's writing
16
+ * direction: under RTL the leading edge is the right one, as the
17
+ * interactive pop gesture's is.
18
+ *
19
+ * Attach it to the edge zone: an element that lies within the band at its
20
+ * edge. There the pan takes the horizontal axis from the browser, which has
21
+ * nothing to scroll in so thin a band, so a touch in the band decides at
22
+ * UIKit's 15 px screen-edge hysteresis. On any other view, whose
23
+ * `touch-action` cannot claim per touch, it leaves the browser every touch
24
+ * behavior, so the author's scrolling there is untouched, and a touch in the
25
+ * band decides at FR19's 10 px like every other claim (spec:AST-094 FR18,
26
+ * DEC-22). The edges' physical sides and the edge zone are measured once,
27
+ * together, and serve both the element's `touch-action` and the touch-down
28
+ * decision; the host reports a layout change (layoutChanged), and a changed
29
+ * answer is announced (onTouchBehaviorChange) so `touch-action` follows it
30
+ * (FR19). The writing direction is read again at each touch-down: a view
31
+ * switched to RTL in place, with no resize, is measured again there and the
32
+ * change announced, so a `leading` back swipe follows the new leading edge
33
+ * (`design:bidirectionality` DR13). That touch landed under the touch-action
34
+ * from before, so it decides at FR19's 10 px unless that one claimed the
35
+ * axis.
36
+ */
37
+
38
+ import {UIKIT_PAN, UIKIT_SCREEN_EDGE_PAN} from '../motion/uikit/gestures';
39
+ import {ALL_NATIVE_TOUCH, type NativeTouchBehavior} from './GestureRecognizer';
40
+ import {
41
+ PanGestureRecognizer,
42
+ type PanGestureRecognizerOptions,
43
+ } from './PanGestureRecognizer';
44
+ import type {GestureEventContext, GestureTouch} from './types';
45
+
46
+ /**
47
+ * How far past `edgeRegion` a view still counts as the edge zone, px: layout
48
+ * snaps sizes to 1/64 px, so a strip authored at the region measures a hair
49
+ * wider; half a pixel takes that and nothing a pixel wider.
50
+ */
51
+ const EDGE_ZONE_TOLERANCE = 0.5;
52
+
53
+ /**
54
+ * An edge by writing direction: under RTL the leading edge is the right one.
55
+ * Top and bottom edges land with their first user.
56
+ */
57
+ export type ScreenEdge = 'leading' | 'trailing';
58
+
59
+ /** A physical horizontal edge of the viewport. */
60
+ type PhysicalEdge = 'left' | 'right';
61
+
62
+ /**
63
+ * What the pan measures of its view, once until a layout change: the
64
+ * writing direction it read, the physical sides its edges resolve to under
65
+ * that direction, and the sides whose band the view lies within.
66
+ */
67
+ interface EdgeLayout {
68
+ readonly isRtl: boolean;
69
+ readonly watched: ReadonlyArray<PhysicalEdge>;
70
+ readonly zone: ReadonlySet<PhysicalEdge>;
71
+ }
72
+
73
+ /**
74
+ * A screen-edge pan is a finger's: it takes no `allowedPointerTypes`
75
+ * (`spec:AST-094` FR43).
76
+ */
77
+ export interface ScreenEdgePanGestureRecognizerOptions extends Omit<
78
+ PanGestureRecognizerOptions,
79
+ 'direction' | 'allowedPointerTypes'
80
+ > {
81
+ /** The edges a touch may start from. @default ['leading'] */
82
+ edges?: ReadonlyArray<ScreenEdge>;
83
+ /** Width of the band at each edge, px. */
84
+ edgeRegion?: number;
85
+ }
86
+
87
+ export class ScreenEdgePanGestureRecognizer extends PanGestureRecognizer {
88
+ override get kind(): PanGestureRecognizer['kind'] {
89
+ return 'screenEdgePan';
90
+ }
91
+
92
+ edges: ReadonlyArray<ScreenEdge>;
93
+ edgeRegion: number;
94
+ /** The physical edge the current gesture started from. */
95
+ activeEdge: PhysicalEdge | null = null;
96
+ /**
97
+ * @internal Set by the host while attached: called when the edge-zone
98
+ * answer changes, so the element's `touch-action` follows it
99
+ * (spec:AST-094 FR19, DEC-22).
100
+ */
101
+ onTouchBehaviorChange: (() => void) | null = null;
102
+ /** The hysteresis where the pan takes its axis (UIKit's 15 px). */
103
+ private readonly edgeHysteresis: number;
104
+ /** What the pan measured of its view (see EdgeLayout), until a layout change. */
105
+ private layout: EdgeLayout | null = null;
106
+
107
+ constructor(options: ScreenEdgePanGestureRecognizerOptions = {}) {
108
+ super({
109
+ maximumNumberOfTouches: 1,
110
+ hysteresis: UIKIT_SCREEN_EDGE_PAN.hysteresis.value,
111
+ ...options,
112
+ // A finger's only: under a mouse, a trackpad or a pen the screen-edge
113
+ // pan stays off (`spec:AST-094` FR43), whatever a caller passes.
114
+ allowedPointerTypes: ['touch'],
115
+ });
116
+ this.edges = options.edges ?? ['leading'];
117
+ this.edgeRegion =
118
+ options.edgeRegion ?? UIKIT_SCREEN_EDGE_PAN.edgeRegion.value;
119
+ this.edgeHysteresis = this.hysteresis;
120
+ }
121
+
122
+ /**
123
+ * The pan takes the horizontal axis only in its edge zone, a view within
124
+ * the band of an edge it watches; elsewhere it leaves the browser every
125
+ * touch behavior, so the author's scrolling is untouched (spec:AST-094
126
+ * FR18), never claiming across a whole wider element.
127
+ */
128
+ override get nativeTouchBehavior(): NativeTouchBehavior {
129
+ const {watched, zone} = this.measured();
130
+ if (!watched.some(edge => zone.has(edge))) {
131
+ return ALL_NATIVE_TOUCH;
132
+ }
133
+ return {
134
+ panX: false,
135
+ panY: true,
136
+ pinchZoom: true,
137
+ doubleTapZoom: false,
138
+ };
139
+ }
140
+
141
+ /**
142
+ * @internal Whether the edge zone depends on the viewport's width: the pan
143
+ * watches the right side, whose band moves with the viewport, so the host
144
+ * reports a viewport resize to it as well as its own box's (FR19, FR24).
145
+ */
146
+ get watchesViewport(): boolean {
147
+ return this.measured().watched.includes('right');
148
+ }
149
+
150
+ /**
151
+ * @internal The view's box may have changed (a resize): its edges' sides
152
+ * and the edge zone are measured again, and a changed answer calls
153
+ * onTouchBehaviorChange.
154
+ */
155
+ layoutChanged(): void {
156
+ const before = this.layout;
157
+ this.layout = null;
158
+ const after = this.measured();
159
+ if (
160
+ before == null ||
161
+ before.watched.join() !== after.watched.join() ||
162
+ before.zone.size !== after.zone.size ||
163
+ [...after.zone].some(edge => !before.zone.has(edge))
164
+ ) {
165
+ this.onTouchBehaviorChange?.();
166
+ }
167
+ }
168
+
169
+ protected override touchesBegan(
170
+ touches: ReadonlyArray<GestureTouch>,
171
+ event: GestureEventContext,
172
+ ): void {
173
+ if (this.numberOfTouches === touches.length) {
174
+ // The touch-action the browser applies to this touch was derived from
175
+ // the layout in force as it landed: whether that claimed the axis.
176
+ const inForce = this.measured();
177
+ const claimedAxis = inForce.watched.some(side => inForce.zone.has(side));
178
+ // A direction switched in place (no resize) moves the leading edge:
179
+ // measure again, and announce it so touch-action follows for the next
180
+ // touch (DR13).
181
+ if (inForce.isRtl !== this.environment.isRtl(this.view)) {
182
+ this.layoutChanged();
183
+ }
184
+ const edge = this.edgeAt(touches[0]);
185
+ if (edge == null) {
186
+ this.setState('failed');
187
+ return;
188
+ }
189
+ this.activeEdge = edge;
190
+ // On an element within the band, which takes the axis across the edge,
191
+ // a touch decides at UIKit's 15 px; on any other, which leaves the
192
+ // browser that axis, at FR19's 10 px, before the browser commits to a
193
+ // scroll (spec:AST-094 FR18, DEC-22). The answer is the one this
194
+ // touch's touch-action was derived from: a touch that measured again
195
+ // decides at 10 px unless the layout in force claimed the axis.
196
+ const offZone = !claimedAxis || !this.measured().zone.has(edge);
197
+ this.hysteresis = offZone
198
+ ? Math.min(this.edgeHysteresis, UIKIT_PAN.hysteresis.value)
199
+ : this.edgeHysteresis;
200
+ this.direction = edge === 'left' ? 'right' : 'left';
201
+ }
202
+ super.touchesBegan(touches, event);
203
+ }
204
+
205
+ /**
206
+ * The physical sides the pan's edges resolve to under the view's writing
207
+ * direction, and the sides whose band the view lies within, measured
208
+ * together once until a layout change: the view starts at that side and
209
+ * reaches no farther than `edgeRegion` from it, within layout's rounding
210
+ * (a strip authored at the 40.2 px region lays out at 40.203 px, on
211
+ * 1/64 px). A view that cannot be measured lies within none.
212
+ */
213
+ private measured(): EdgeLayout {
214
+ if (this.layout != null) {
215
+ return this.layout;
216
+ }
217
+ const isRtl = this.environment.isRtl(this.view);
218
+ const watched = this.edges.map(edge =>
219
+ (edge === 'leading') !== isRtl ? 'left' : 'right',
220
+ );
221
+ const zone = new Set<PhysicalEdge>();
222
+ const rect = this.environment.viewRect?.(this.view);
223
+ if (rect != null && rect.width > 0) {
224
+ const {width} = this.environment.viewportSize();
225
+ const right = rect.left + rect.width;
226
+ const band = this.edgeRegion + EDGE_ZONE_TOLERANCE;
227
+ if (rect.left >= -EDGE_ZONE_TOLERANCE && right <= band) {
228
+ zone.add('left');
229
+ }
230
+ if (rect.left >= width - band && right <= width + EDGE_ZONE_TOLERANCE) {
231
+ zone.add('right');
232
+ }
233
+ }
234
+ this.layout = {isRtl, watched, zone};
235
+ return this.layout;
236
+ }
237
+
238
+ protected override reset(): void {
239
+ super.reset();
240
+ this.activeEdge = null;
241
+ }
242
+
243
+ private edgeAt(touch: GestureTouch): PhysicalEdge | null {
244
+ const {width} = this.environment.viewportSize();
245
+ for (const physical of this.measured().watched) {
246
+ const inBand =
247
+ physical === 'left'
248
+ ? touch.startX <= this.edgeRegion
249
+ : touch.startX >= width - this.edgeRegion;
250
+ if (inBand) {
251
+ return physical;
252
+ }
253
+ }
254
+ return null;
255
+ }
256
+ }
@@ -0,0 +1,197 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file SwipeGestureRecognizer.ts
5
+ * @input Touches from a GestureArena
6
+ * @output Exports SwipeGestureRecognizer (UISwipeGestureRecognizer), its
7
+ * options and direction type
8
+ * @position Discrete recognizer of packages/core/src/gestures
9
+ *
10
+ * Recognized WHILE the fingers move, as UIKit's is: as soon as the centroid
11
+ * has travelled `minimumDistance` along an allowed direction, within
12
+ * `maximumDuration` of touch-down, with off-axis travel no more than
13
+ * `maximumSecondaryMovement` px across it. Off-axis travel past that
14
+ * allowance, or the distance travelled the wrong way, rules a direction out;
15
+ * the swipe fails once every allowed direction is ruled out, as it does for
16
+ * too many fingers, the duration running out, and a lift before it was
17
+ * recognized.
18
+ */
19
+
20
+ import {UIKIT_SWIPE} from '../motion/uikit/gestures';
21
+ import {centroid} from './geometry';
22
+ import {
23
+ GestureRecognizer,
24
+ type GestureRecognizerOptions,
25
+ type NativeTouchBehavior,
26
+ } from './GestureRecognizer';
27
+ import type {GestureEventContext, GestureTouch, Point} from './types';
28
+
29
+ export type SwipeDirection = 'left' | 'right' | 'up' | 'down';
30
+
31
+ export interface SwipeGestureRecognizerOptions extends GestureRecognizerOptions<SwipeGestureRecognizer> {
32
+ /** @default ['right'] */
33
+ direction?: SwipeDirection | ReadonlyArray<SwipeDirection>;
34
+ /** @default 1 */
35
+ numberOfTouchesRequired?: number;
36
+ minimumDistance?: number;
37
+ maximumDuration?: number;
38
+ maximumSecondaryMovement?: number;
39
+ }
40
+
41
+ const SWIPE = UIKIT_SWIPE;
42
+
43
+ export class SwipeGestureRecognizer extends GestureRecognizer {
44
+ override get kind(): GestureRecognizer['kind'] {
45
+ return 'swipe';
46
+ }
47
+
48
+ directions: ReadonlyArray<SwipeDirection>;
49
+ numberOfTouchesRequired: number;
50
+ minimumDistance: number;
51
+ maximumDuration: number;
52
+ maximumSecondaryMovement: number;
53
+ /** The direction of the recognized swipe. */
54
+ recognizedDirection: SwipeDirection | null = null;
55
+
56
+ private origin: Point = {x: 0, y: 0};
57
+ /** Directions this touch's path has ruled out. */
58
+ private readonly ruledOut = new Set<SwipeDirection>();
59
+ /** The centroid at the previous move. */
60
+ private last: Point | null = null;
61
+
62
+ constructor(options: SwipeGestureRecognizerOptions = {}) {
63
+ super(options);
64
+ const direction = options.direction ?? ['right'];
65
+ this.directions = typeof direction === 'string' ? [direction] : direction;
66
+ this.numberOfTouchesRequired = options.numberOfTouchesRequired ?? 1;
67
+ this.minimumDistance =
68
+ options.minimumDistance ?? SWIPE.minimumDistance.value;
69
+ this.maximumDuration =
70
+ options.maximumDuration ?? SWIPE.maximumDuration.value;
71
+ this.maximumSecondaryMovement =
72
+ options.maximumSecondaryMovement ?? SWIPE.maximumSecondaryMovement.value;
73
+ }
74
+
75
+ override get isDiscrete(): boolean {
76
+ return true;
77
+ }
78
+
79
+ override get nativeTouchBehavior(): NativeTouchBehavior {
80
+ const horizontal = this.directions.some(
81
+ direction => direction === 'left' || direction === 'right',
82
+ );
83
+ const vertical = this.directions.some(
84
+ direction => direction === 'up' || direction === 'down',
85
+ );
86
+ return {
87
+ panX: !horizontal,
88
+ panY: !vertical,
89
+ pinchZoom: true,
90
+ doubleTapZoom: false,
91
+ };
92
+ }
93
+
94
+ protected override touchesBegan(
95
+ touches: ReadonlyArray<GestureTouch>,
96
+ event: GestureEventContext,
97
+ ): void {
98
+ if (this.numberOfTouches > this.numberOfTouchesRequired) {
99
+ this.setState('failed');
100
+ return;
101
+ }
102
+ if (this.numberOfTouches === touches.length) {
103
+ this.setTimer(event.time + this.maximumDuration, () => {
104
+ // A swipe already recognized, waiting on a recognizer it requires to
105
+ // fail, holds its recognition (spec:AST-094 FR15).
106
+ if (this.pending == null) {
107
+ this.setState('failed');
108
+ }
109
+ });
110
+ }
111
+ // Measure from where every required finger is down.
112
+ this.origin = centroid(this.touches.values());
113
+ this.last = null;
114
+ }
115
+
116
+ protected override touchesMoved(): void {
117
+ if (
118
+ this.pending != null ||
119
+ this.numberOfTouches !== this.numberOfTouchesRequired
120
+ ) {
121
+ return;
122
+ }
123
+ const current = centroid(this.touches.values());
124
+ const from = this.last ?? this.origin;
125
+ this.last = current;
126
+ for (const direction of this.directions) {
127
+ if (this.ruledOut.has(direction)) {
128
+ continue;
129
+ }
130
+ // Along and across this direction at the start and the end of the
131
+ // move. The path between two events is read as a straight segment, so
132
+ // the verdict does not depend on how far apart the events were.
133
+ const [along0, across0] = this.project(direction, from);
134
+ const [along1, across1] = this.project(direction, current);
135
+ const reaches = segmentCrossing(along0, along1, this.minimumDistance);
136
+ const strays = Math.max(
137
+ segmentCrossing(across0, across1, this.maximumSecondaryMovement),
138
+ segmentCrossing(-across0, -across1, this.maximumSecondaryMovement),
139
+ );
140
+ const strayAt = strays < 0 ? Infinity : strays;
141
+ if (reaches >= 0 && reaches <= strayAt) {
142
+ this.recognizedDirection = direction;
143
+ this.setState('ended');
144
+ return;
145
+ }
146
+ // Off-axis travel past the allowance, or the distance the wrong way,
147
+ // rules a direction out for good.
148
+ if (strays >= 0 || along1 <= -this.minimumDistance) {
149
+ this.ruledOut.add(direction);
150
+ }
151
+ }
152
+ if (this.directions.every(direction => this.ruledOut.has(direction))) {
153
+ this.setState('failed');
154
+ }
155
+ }
156
+
157
+ /** Travel along and across `direction` from the origin to `point`. */
158
+ private project(direction: SwipeDirection, point: Point): [number, number] {
159
+ const dx = point.x - this.origin.x;
160
+ const dy = point.y - this.origin.y;
161
+ return direction === 'left'
162
+ ? [-dx, dy]
163
+ : direction === 'right'
164
+ ? [dx, dy]
165
+ : direction === 'up'
166
+ ? [-dy, dx]
167
+ : [dy, dx];
168
+ }
169
+
170
+ protected override touchesEnded(): void {
171
+ // Recognized and waiting, it holds past the lift (FR15).
172
+ if (this.pending == null) {
173
+ this.setState('failed');
174
+ }
175
+ }
176
+
177
+ protected override reset(): void {
178
+ this.recognizedDirection = null;
179
+ this.ruledOut.clear();
180
+ this.last = null;
181
+ this.origin = {x: 0, y: 0};
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Where on the segment from `start` to `end` (0 to 1) the value first
187
+ * reaches `limit`; 0 when it starts there, -1 when it never does.
188
+ */
189
+ function segmentCrossing(start: number, end: number, limit: number): number {
190
+ if (start >= limit) {
191
+ return 0;
192
+ }
193
+ if (end < limit) {
194
+ return -1;
195
+ }
196
+ return (limit - start) / (end - start);
197
+ }
@@ -43,6 +43,10 @@ export interface TapGestureRecognizerOptions extends GestureRecognizerOptions<Ta
43
43
  const TAP = UIKIT_TAP;
44
44
 
45
45
  export class TapGestureRecognizer extends GestureRecognizer {
46
+ override get kind(): GestureRecognizer['kind'] {
47
+ return 'tap';
48
+ }
49
+
46
50
  numberOfTapsRequired: number;
47
51
  numberOfTouchesRequired: number;
48
52
  allowableMovement: number;