@astryxdesign/core 0.7.7-canary.c0929c8 → 0.7.7-canary.c19ca12

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 (472) 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 +36 -6
  4. package/dist/AppShell/useCloseMobileDrawerOnActivate.d.ts +13 -0
  5. package/dist/AppShell/useCloseMobileDrawerOnActivate.d.ts.map +1 -0
  6. package/dist/AppShell/useCloseMobileDrawerOnActivate.js +45 -0
  7. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  8. package/dist/BottomSheet/BottomSheet.js +79 -9
  9. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  10. package/dist/BottomSheet/BottomSheetPanel.js +23 -4
  11. package/dist/BottomSheet/bottomSheetStack.d.ts.map +1 -1
  12. package/dist/BottomSheet/bottomSheetStack.js +5 -4
  13. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
  14. package/dist/BottomSheet/useSheetGestures.js +3 -1
  15. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +2 -1
  16. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  17. package/dist/Breadcrumbs/BreadcrumbItem.js +7 -3
  18. package/dist/Button/Button.d.ts.map +1 -1
  19. package/dist/Button/Button.js +47 -3
  20. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  21. package/dist/CheckboxInput/CheckboxInput.js +13 -2
  22. package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
  23. package/dist/CheckboxList/CheckboxList.js +7 -1
  24. package/dist/CheckboxList/CheckboxListContext.d.ts +6 -0
  25. package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
  26. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  27. package/dist/CheckboxList/CheckboxListItem.js +10 -2
  28. package/dist/ComplexSelector/ComplexSelector.d.ts +4 -1
  29. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  30. package/dist/ComplexSelector/ComplexSelector.js +14 -4
  31. package/dist/ContextMenu/ContextMenu.js +2 -2
  32. package/dist/DateInput/DateInput.d.ts.map +1 -1
  33. package/dist/DateInput/DateInput.js +5 -2
  34. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  35. package/dist/DateInput/MonthScroller.js +13 -27
  36. package/dist/DateInput/Wheel.d.ts.map +1 -1
  37. package/dist/DateInput/Wheel.js +22 -41
  38. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  39. package/dist/DateTimeInput/DateTimeInput.js +5 -2
  40. package/dist/Dialog/Dialog.d.ts.map +1 -1
  41. package/dist/Dialog/Dialog.js +23 -45
  42. package/dist/Drawer/Drawer.d.ts.map +1 -1
  43. package/dist/Drawer/Drawer.js +15 -11
  44. package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
  45. package/dist/Drawer/useDrawerDialogPresence.js +5 -1
  46. package/dist/Field/Field.js +2 -2
  47. package/dist/Field/PanelSearchInput.d.ts +9 -1
  48. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  49. package/dist/Field/PanelSearchInput.js +3 -1
  50. package/dist/HoverCard/HoverCard.d.ts +4 -3
  51. package/dist/HoverCard/HoverCard.d.ts.map +1 -1
  52. package/dist/HoverCard/HoverCard.js +27 -2
  53. package/dist/HoverCard/useHoverCard.d.ts +5 -4
  54. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  55. package/dist/HoverCard/useHoverCard.js +17 -31
  56. package/dist/Icon/Icon.d.ts +5 -1
  57. package/dist/Icon/Icon.d.ts.map +1 -1
  58. package/dist/Icon/Icon.js +5 -2
  59. package/dist/InfoTip/InfoTip.d.ts +63 -0
  60. package/dist/InfoTip/InfoTip.d.ts.map +1 -0
  61. package/dist/InfoTip/InfoTip.js +126 -0
  62. package/dist/InfoTip/index.d.ts +10 -0
  63. package/dist/InfoTip/index.d.ts.map +1 -0
  64. package/dist/InfoTip/index.js +12 -0
  65. package/dist/Layer/layerAnimations.stylex.d.ts +7 -8
  66. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  67. package/dist/Layer/layerAnimations.stylex.js +25 -20
  68. package/dist/Layer/useBackdropPress.d.ts +27 -0
  69. package/dist/Layer/useBackdropPress.d.ts.map +1 -0
  70. package/dist/Layer/useBackdropPress.js +53 -0
  71. package/dist/Layer/usePressPin.d.ts +20 -10
  72. package/dist/Layer/usePressPin.d.ts.map +1 -1
  73. package/dist/Layer/usePressPin.js +66 -18
  74. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  75. package/dist/Lightbox/Lightbox.js +18 -0
  76. package/dist/MobileNav/MobileNav.js +0 -1
  77. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  78. package/dist/MultiSelector/hooks.js +2 -4
  79. package/dist/Outline/Outline.d.ts +2 -4
  80. package/dist/Outline/Outline.d.ts.map +1 -1
  81. package/dist/Outline/Outline.js +4 -52
  82. package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
  83. package/dist/Outline/useOutlineFromMarkdown.js +1 -0
  84. package/dist/Outline/useScrollSpy.js +3 -3
  85. package/dist/PowerSearch/PowerSearch.d.ts +36 -3
  86. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  87. package/dist/PowerSearch/PowerSearch.js +571 -302
  88. package/dist/PowerSearch/PowerSearchBottomSheet.d.ts +100 -0
  89. package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +1 -0
  90. package/dist/PowerSearch/PowerSearchBottomSheet.js +1913 -0
  91. package/dist/PowerSearch/PowerSearchEditPopover.d.ts +32 -1
  92. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  93. package/dist/PowerSearch/PowerSearchEditPopover.js +17 -6
  94. package/dist/PowerSearch/PowerSearchValueEditor.d.ts +38 -3
  95. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  96. package/dist/PowerSearch/PowerSearchValueEditor.js +170 -61
  97. package/dist/PowerSearch/formatFilterValue.d.ts +7 -0
  98. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  99. package/dist/PowerSearch/formatFilterValue.js +11 -1
  100. package/dist/PowerSearch/formatTokenValue.d.ts +28 -0
  101. package/dist/PowerSearch/formatTokenValue.d.ts.map +1 -0
  102. package/dist/PowerSearch/formatTokenValue.js +160 -0
  103. package/dist/PowerSearch/powerSearchSheetUtils.d.ts +65 -0
  104. package/dist/PowerSearch/powerSearchSheetUtils.d.ts.map +1 -0
  105. package/dist/PowerSearch/powerSearchSheetUtils.js +168 -0
  106. package/dist/RadioList/RadioList.d.ts.map +1 -1
  107. package/dist/RadioList/RadioList.js +8 -2
  108. package/dist/RadioList/RadioListItem.d.ts +1 -1
  109. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  110. package/dist/RadioList/RadioListItem.js +5 -3
  111. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  112. package/dist/Resizable/ResizeHandle.js +118 -260
  113. package/dist/Resizable/resizeGesture.d.ts +91 -0
  114. package/dist/Resizable/resizeGesture.d.ts.map +1 -0
  115. package/dist/Resizable/resizeGesture.js +251 -0
  116. package/dist/SegmentedControl/SegmentedControl.d.ts +3 -1
  117. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  118. package/dist/SegmentedControl/SegmentedControl.js +115 -8
  119. package/dist/SegmentedControl/SegmentedControlContext.d.ts +6 -0
  120. package/dist/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
  121. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -0
  122. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  123. package/dist/SegmentedControl/SegmentedControlItem.js +8 -1
  124. package/dist/SegmentedControl/useSegmentedSelectionMotion.d.ts +357 -0
  125. package/dist/SegmentedControl/useSegmentedSelectionMotion.d.ts.map +1 -0
  126. package/dist/SegmentedControl/useSegmentedSelectionMotion.js +1349 -0
  127. package/dist/SegmentedControl/useSegmentedTouchTracking.d.ts +70 -0
  128. package/dist/SegmentedControl/useSegmentedTouchTracking.d.ts.map +1 -0
  129. package/dist/SegmentedControl/useSegmentedTouchTracking.js +264 -0
  130. package/dist/Selector/Selector.d.ts.map +1 -1
  131. package/dist/Selector/Selector.js +96 -67
  132. package/dist/Selector/optionShape.d.ts +24 -0
  133. package/dist/Selector/optionShape.d.ts.map +1 -0
  134. package/dist/Selector/optionShape.js +48 -0
  135. package/dist/Selector/selectableOptionEntries.d.ts +20 -0
  136. package/dist/Selector/selectableOptionEntries.d.ts.map +1 -0
  137. package/dist/Selector/selectableOptionEntries.js +38 -0
  138. package/dist/Selector/utils.d.ts +2 -17
  139. package/dist/Selector/utils.d.ts.map +1 -1
  140. package/dist/Selector/utils.js +3 -51
  141. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  142. package/dist/SideNav/SideNavItem.js +3 -9
  143. package/dist/Slider/sliderTouchController.js +2 -2
  144. package/dist/Spinner/Spinner.d.ts +1 -1
  145. package/dist/Spinner/Spinner.d.ts.map +1 -1
  146. package/dist/Spinner/Spinner.js +60 -58
  147. package/dist/Switch/switchTouch.d.ts +0 -7
  148. package/dist/Switch/switchTouch.d.ts.map +1 -1
  149. package/dist/Switch/switchTouch.js +2 -10
  150. package/dist/Switch/useSwitchTouch.d.ts +2 -11
  151. package/dist/Switch/useSwitchTouch.d.ts.map +1 -1
  152. package/dist/Switch/useSwitchTouch.js +35 -93
  153. package/dist/Table/BaseTable.d.ts.map +1 -1
  154. package/dist/Table/BaseTable.js +29 -8
  155. package/dist/TextInput/TextInput.d.ts +2 -2
  156. package/dist/TextInput/TextInput.d.ts.map +1 -1
  157. package/dist/TextInput/TextInput.js +10 -7
  158. package/dist/Toast/Toast.d.ts +11 -1
  159. package/dist/Toast/Toast.d.ts.map +1 -1
  160. package/dist/Toast/Toast.js +30 -15
  161. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  162. package/dist/Toast/ToastViewport.js +94 -34
  163. package/dist/Toast/types.d.ts +9 -3
  164. package/dist/Toast/types.d.ts.map +1 -1
  165. package/dist/Token/Token.d.ts +2 -2
  166. package/dist/Token/Token.d.ts.map +1 -1
  167. package/dist/Token/Token.js +13 -4
  168. package/dist/Token/TokenNamingContext.d.ts +14 -0
  169. package/dist/Token/TokenNamingContext.d.ts.map +1 -0
  170. package/dist/Token/TokenNamingContext.js +23 -0
  171. package/dist/Tokenizer/Tokenizer.d.ts +46 -59
  172. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  173. package/dist/Tokenizer/Tokenizer.js +40 -57
  174. package/dist/Tokenizer/TokenizerBottomSheet.d.ts +25 -28
  175. package/dist/Tokenizer/TokenizerBottomSheet.d.ts.map +1 -1
  176. package/dist/Tokenizer/TokenizerBottomSheet.js +157 -54
  177. package/dist/Tokenizer/TokenizerItemRemovableContext.d.ts +3 -0
  178. package/dist/Tokenizer/TokenizerItemRemovableContext.d.ts.map +1 -0
  179. package/dist/Tokenizer/TokenizerItemRemovableContext.js +19 -0
  180. package/dist/Tooltip/Tooltip.d.ts +25 -30
  181. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  182. package/dist/Tooltip/Tooltip.js +24 -5
  183. package/dist/Tooltip/index.d.ts +1 -1
  184. package/dist/Tooltip/index.d.ts.map +1 -1
  185. package/dist/Tooltip/useTooltip.d.ts +45 -28
  186. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  187. package/dist/Tooltip/useTooltip.js +52 -59
  188. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  189. package/dist/TopNav/TopNavItem.js +4 -7
  190. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  191. package/dist/TopNav/TopNavMegaMenuItem.js +4 -7
  192. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  193. package/dist/TopNav/TopNavMenu.js +4 -7
  194. package/dist/Typeahead/TypeaheadItem.d.ts +2 -1
  195. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  196. package/dist/animator/createAnimator.d.ts +98 -0
  197. package/dist/animator/createAnimator.d.ts.map +1 -0
  198. package/dist/animator/createAnimator.js +259 -0
  199. package/dist/astryx.css +96 -7
  200. package/dist/gestures/GestureHost.d.ts +27 -1
  201. package/dist/gestures/GestureHost.d.ts.map +1 -1
  202. package/dist/gestures/GestureHost.js +157 -21
  203. package/dist/gestures/PressTracker.d.ts.map +1 -1
  204. package/dist/gestures/PressTracker.js +4 -3
  205. package/dist/hooks/actionGroupTracker.d.ts +7 -4
  206. package/dist/hooks/actionGroupTracker.d.ts.map +1 -1
  207. package/dist/hooks/actionGroupTracker.js +19 -56
  208. package/dist/hooks/index.d.ts +1 -0
  209. package/dist/hooks/index.d.ts.map +1 -1
  210. package/dist/hooks/index.js +1 -0
  211. package/dist/hooks/pressGroupContext.d.ts +6 -0
  212. package/dist/hooks/pressGroupContext.d.ts.map +1 -0
  213. package/dist/hooks/pressGroupContext.js +20 -0
  214. package/dist/hooks/useActionGroupTracking.d.ts +53 -0
  215. package/dist/hooks/useActionGroupTracking.d.ts.map +1 -0
  216. package/dist/hooks/useActionGroupTracking.js +174 -0
  217. package/dist/hooks/useAnimator.d.ts +41 -0
  218. package/dist/hooks/useAnimator.d.ts.map +1 -0
  219. package/dist/hooks/useAnimator.js +70 -0
  220. package/dist/hooks/useAttachment.d.ts +1 -1
  221. package/dist/hooks/useAttachment.js +1 -1
  222. package/dist/hooks/useHighlightedOptionScroll.d.ts +11 -1
  223. package/dist/hooks/useHighlightedOptionScroll.d.ts.map +1 -1
  224. package/dist/hooks/useHighlightedOptionScroll.js +112 -11
  225. package/dist/hooks/useInputStatusIcon.d.ts +1 -1
  226. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
  227. package/dist/hooks/useInputStatusIcon.js +2 -2
  228. package/dist/hooks/useLongPress.d.ts +6 -2
  229. package/dist/hooks/useLongPress.d.ts.map +1 -1
  230. package/dist/hooks/useLongPress.js +95 -15
  231. package/dist/hooks/useMediaQuery.d.ts +2 -1
  232. package/dist/hooks/useMediaQuery.d.ts.map +1 -1
  233. package/dist/hooks/useMediaQuery.js +7 -4
  234. package/dist/hooks/useMenuPress.d.ts.map +1 -1
  235. package/dist/hooks/useMenuPress.js +4 -2
  236. package/dist/i18n/generated-english/InfoTip/InfoTip.generated.d.ts +8 -0
  237. package/dist/i18n/generated-english/InfoTip/InfoTip.generated.d.ts.map +1 -0
  238. package/dist/i18n/generated-english/InfoTip/InfoTip.generated.js +12 -0
  239. package/dist/i18n/generated-english/PowerSearch/PowerSearch.generated.d.ts.map +1 -1
  240. package/dist/i18n/generated-english/PowerSearch/PowerSearch.generated.js +1 -0
  241. package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts +8 -0
  242. package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts.map +1 -0
  243. package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.js +42 -0
  244. package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.d.ts.map +1 -1
  245. package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.js +6 -0
  246. package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts +8 -0
  247. package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts.map +1 -0
  248. package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.js +14 -0
  249. package/dist/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.d.ts.map +1 -1
  250. package/dist/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.js +7 -1
  251. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  252. package/dist/i18n/generated-locales/en.generated.js +33 -1
  253. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  254. package/dist/i18n/generated-locales/pseudo.generated.js +33 -1
  255. package/dist/index.d.ts +2 -0
  256. package/dist/index.d.ts.map +1 -1
  257. package/dist/index.js +5 -0
  258. package/dist/internal/SheetConfirmation.d.ts +11 -0
  259. package/dist/internal/SheetConfirmation.d.ts.map +1 -0
  260. package/dist/internal/SheetConfirmation.js +92 -0
  261. package/dist/internal/indicatorPress.stylex.d.ts +20 -0
  262. package/dist/internal/indicatorPress.stylex.d.ts.map +1 -0
  263. package/dist/internal/indicatorPress.stylex.js +26 -0
  264. package/dist/internal/sheetDraft.d.ts +35 -0
  265. package/dist/internal/sheetDraft.d.ts.map +1 -0
  266. package/dist/internal/sheetDraft.js +65 -0
  267. package/dist/internal/touch-sheet.d.ts +21 -0
  268. package/dist/internal/touch-sheet.d.ts.map +1 -0
  269. package/dist/internal/touch-sheet.js +19 -0
  270. package/dist/internal/useDismissSearchOnTouchDrag.d.ts +24 -0
  271. package/dist/internal/useDismissSearchOnTouchDrag.d.ts.map +1 -0
  272. package/dist/internal/useDismissSearchOnTouchDrag.js +56 -0
  273. package/dist/motion/animator.d.ts +14 -14
  274. package/dist/motion/animator.d.ts.map +1 -1
  275. package/dist/motion/animator.js +41 -18
  276. package/dist/motion/reducedMotion.d.ts +24 -0
  277. package/dist/motion/reducedMotion.d.ts.map +1 -1
  278. package/dist/motion/reducedMotion.js +78 -1
  279. package/dist/motion/roles.d.ts +7 -1
  280. package/dist/motion/roles.d.ts.map +1 -1
  281. package/dist/motion/roles.js +20 -1
  282. package/dist/motion/uikit/alert.d.ts +41 -0
  283. package/dist/motion/uikit/alert.d.ts.map +1 -0
  284. package/dist/motion/uikit/alert.js +43 -0
  285. package/dist/motion/uikit/index.d.ts +6 -5
  286. package/dist/motion/uikit/index.d.ts.map +1 -1
  287. package/dist/motion/uikit/index.js +6 -5
  288. package/dist/motion/uikit/segmented.d.ts +55 -0
  289. package/dist/motion/uikit/segmented.d.ts.map +1 -0
  290. package/dist/motion/uikit/segmented.js +77 -0
  291. package/dist/motion/uikit/springs.d.ts +0 -18
  292. package/dist/motion/uikit/springs.d.ts.map +1 -1
  293. package/dist/motion/uikit/springs.js +5 -21
  294. package/dist/privateAttributes/pressGroupItem.stylex.d.ts +15 -0
  295. package/dist/privateAttributes/pressGroupItem.stylex.d.ts.map +1 -0
  296. package/dist/privateAttributes/pressGroupItem.stylex.js +23 -0
  297. package/dist/privateAttributes/segmentTitle.stylex.d.ts +5 -0
  298. package/dist/privateAttributes/segmentTitle.stylex.d.ts.map +1 -0
  299. package/dist/privateAttributes/segmentTitle.stylex.js +22 -0
  300. package/dist/utils/browserClickWait.d.ts +35 -0
  301. package/dist/utils/browserClickWait.d.ts.map +1 -0
  302. package/dist/utils/browserClickWait.js +123 -0
  303. package/dist/utils/clickGuard.d.ts +14 -1
  304. package/dist/utils/clickGuard.d.ts.map +1 -1
  305. package/dist/utils/clickGuard.js +46 -1
  306. package/dist/utils/dateParser.d.ts.map +1 -1
  307. package/dist/utils/dateParser.js +12 -0
  308. package/dist/utils/focusReturn.d.ts +15 -0
  309. package/dist/utils/focusReturn.d.ts.map +1 -1
  310. package/dist/utils/focusReturn.js +28 -0
  311. package/dist/utils/interactionOverlay.stylex.d.ts +3 -2
  312. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  313. package/dist/utils/interactionOverlay.stylex.js +3 -2
  314. package/dist/utils/pressFeedback.d.ts.map +1 -1
  315. package/dist/utils/pressFeedback.js +19 -6
  316. package/dist/utils/triggerFocus.d.ts +36 -0
  317. package/dist/utils/triggerFocus.d.ts.map +1 -0
  318. package/dist/utils/triggerFocus.js +65 -0
  319. package/locales/en.json +128 -0
  320. package/locales/pseudo.json +96 -0
  321. package/package.json +18 -8
  322. package/src/AlertDialog/AlertDialog.doc.mjs +2 -2
  323. package/src/AlertDialog/AlertDialog.tsx +37 -5
  324. package/src/AppShell/useCloseMobileDrawerOnActivate.ts +52 -0
  325. package/src/BottomSheet/BottomSheet.tsx +95 -10
  326. package/src/BottomSheet/BottomSheetPanel.tsx +40 -5
  327. package/src/BottomSheet/bottomSheetStack.ts +8 -4
  328. package/src/BottomSheet/useSheetGestures.ts +3 -1
  329. package/src/Breadcrumbs/BreadcrumbItem.tsx +13 -3
  330. package/src/Button/Button.tsx +63 -5
  331. package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -0
  332. package/src/CheckboxInput/CheckboxInput.tsx +36 -9
  333. package/src/CheckboxList/CheckboxList.doc.mjs +4 -2
  334. package/src/CheckboxList/CheckboxList.tsx +6 -0
  335. package/src/CheckboxList/CheckboxListContext.tsx +6 -0
  336. package/src/CheckboxList/CheckboxListItem.tsx +11 -2
  337. package/src/ComplexSelector/ComplexSelector.tsx +20 -5
  338. package/src/ContextMenu/ContextMenu.tsx +2 -2
  339. package/src/DateInput/DateInput.tsx +8 -2
  340. package/src/DateInput/MonthScroller.tsx +18 -22
  341. package/src/DateInput/Wheel.tsx +30 -32
  342. package/src/DateTimeInput/DateTimeInput.tsx +8 -2
  343. package/src/Dialog/Dialog.tsx +54 -45
  344. package/src/Drawer/Drawer.tsx +28 -11
  345. package/src/Drawer/useDrawerDialogPresence.ts +5 -1
  346. package/src/Field/Field.tsx +2 -2
  347. package/src/Field/PanelSearchInput.tsx +11 -0
  348. package/src/HoverCard/HoverCard.doc.mjs +4 -2
  349. package/src/HoverCard/HoverCard.tsx +35 -4
  350. package/src/HoverCard/useHoverCard.doc.mjs +178 -36
  351. package/src/HoverCard/useHoverCard.tsx +46 -52
  352. package/src/Icon/Icon.doc.mjs +49 -8
  353. package/src/Icon/Icon.tsx +15 -7
  354. package/src/InfoTip/InfoTip.doc.mjs +192 -0
  355. package/src/InfoTip/InfoTip.tsx +186 -0
  356. package/src/InfoTip/index.ts +14 -0
  357. package/src/Layer/layerAnimations.stylex.ts +24 -16
  358. package/src/Layer/useBackdropPress.ts +81 -0
  359. package/src/Layer/usePressPin.ts +86 -26
  360. package/src/Lightbox/Lightbox.tsx +18 -0
  361. package/src/MobileNav/MobileNav.tsx +1 -1
  362. package/src/MultiSelector/hooks.ts +2 -4
  363. package/src/Outline/Outline.doc.mjs +177 -51
  364. package/src/Outline/Outline.tsx +5 -57
  365. package/src/Outline/useOutlineFromMarkdown.doc.mjs +157 -0
  366. package/src/Outline/useOutlineFromMarkdown.ts +1 -0
  367. package/src/Outline/useScrollSpy.ts +3 -3
  368. package/src/PowerSearch/PowerSearch.doc.mjs +55 -6
  369. package/src/PowerSearch/PowerSearch.tsx +798 -324
  370. package/src/PowerSearch/PowerSearchBottomSheet.tsx +2515 -0
  371. package/src/PowerSearch/PowerSearchEditPopover.tsx +28 -6
  372. package/src/PowerSearch/PowerSearchValueEditor.tsx +203 -38
  373. package/src/PowerSearch/formatFilterValue.ts +18 -1
  374. package/src/PowerSearch/formatTokenValue.ts +215 -0
  375. package/src/PowerSearch/powerSearchSheetUtils.ts +224 -0
  376. package/src/RadioList/RadioList.doc.mjs +4 -2
  377. package/src/RadioList/RadioList.tsx +7 -2
  378. package/src/RadioList/RadioListItem.tsx +5 -3
  379. package/src/Resizable/ResizeHandle.tsx +133 -328
  380. package/src/Resizable/resizeGesture.ts +368 -0
  381. package/src/SegmentedControl/SegmentedControl.doc.mjs +3 -3
  382. package/src/SegmentedControl/SegmentedControl.tsx +179 -5
  383. package/src/SegmentedControl/SegmentedControlContext.ts +6 -0
  384. package/src/SegmentedControl/SegmentedControlItem.tsx +12 -1
  385. package/src/SegmentedControl/useSegmentedSelectionMotion.ts +1640 -0
  386. package/src/SegmentedControl/useSegmentedTouchTracking.ts +308 -0
  387. package/src/Selector/Selector.tsx +136 -89
  388. package/src/Selector/optionShape.ts +64 -0
  389. package/src/Selector/selectableOptionEntries.ts +39 -0
  390. package/src/Selector/utils.ts +9 -68
  391. package/src/SideNav/SideNavItem.tsx +3 -7
  392. package/src/Slider/sliderTouchController.ts +2 -2
  393. package/src/Spinner/Spinner.tsx +77 -63
  394. package/src/Switch/switchTouch.ts +2 -10
  395. package/src/Switch/useSwitchTouch.ts +38 -104
  396. package/src/Table/BaseTable.tsx +46 -12
  397. package/src/TextInput/TextInput.tsx +11 -10
  398. package/src/Toast/Toast.doc.mjs +4 -3
  399. package/src/Toast/Toast.tsx +57 -32
  400. package/src/Toast/ToastViewport.tsx +121 -35
  401. package/src/Toast/types.ts +9 -3
  402. package/src/Token/Token.tsx +15 -4
  403. package/src/Token/TokenNamingContext.ts +28 -0
  404. package/src/Tokenizer/Tokenizer.doc.mjs +16 -0
  405. package/src/Tokenizer/Tokenizer.tsx +89 -85
  406. package/src/Tokenizer/TokenizerBottomSheet.tsx +219 -93
  407. package/src/Tokenizer/TokenizerItemRemovableContext.ts +24 -0
  408. package/src/Tooltip/Tooltip.doc.mjs +123 -54
  409. package/src/Tooltip/Tooltip.tsx +36 -39
  410. package/src/Tooltip/index.ts +0 -1
  411. package/src/Tooltip/useTooltip.doc.mjs +171 -33
  412. package/src/Tooltip/useTooltip.tsx +98 -86
  413. package/src/TopNav/TopNavItem.tsx +6 -5
  414. package/src/TopNav/TopNavMegaMenuItem.tsx +6 -5
  415. package/src/TopNav/TopNavMenu.tsx +6 -5
  416. package/src/Typeahead/TypeaheadItem.doc.mjs +6 -3
  417. package/src/Typeahead/TypeaheadItem.tsx +2 -1
  418. package/src/animator/createAnimator.doc.mjs +153 -0
  419. package/src/animator/createAnimator.ts +324 -0
  420. package/src/gestures/GestureHost.ts +198 -20
  421. package/src/gestures/PressTracker.ts +4 -3
  422. package/src/gestures/README.md +7 -1
  423. package/src/hooks/actionGroupTracker.ts +32 -61
  424. package/src/hooks/index.ts +2 -0
  425. package/src/hooks/pressGroupContext.ts +21 -0
  426. package/src/hooks/useActionGroupTracking.ts +224 -0
  427. package/src/hooks/useAnimator.doc.mjs +109 -0
  428. package/src/hooks/useAnimator.ts +67 -0
  429. package/src/hooks/useAttachment.ts +1 -1
  430. package/src/hooks/useHighlightedOptionScroll.ts +123 -15
  431. package/src/hooks/useInputStatusIcon.tsx +3 -2
  432. package/src/hooks/useLongPress.doc.mjs +2 -2
  433. package/src/hooks/useLongPress.ts +136 -15
  434. package/src/hooks/useMediaQuery.doc.mjs +2 -2
  435. package/src/hooks/useMediaQuery.ts +13 -4
  436. package/src/hooks/useMenuPress.ts +8 -2
  437. package/src/i18n/generated-english/InfoTip/InfoTip.generated.ts +13 -0
  438. package/src/i18n/generated-english/PowerSearch/PowerSearch.generated.ts +1 -0
  439. package/src/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.ts +43 -0
  440. package/src/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.ts +6 -0
  441. package/src/i18n/generated-english/PowerSearch/formatTokenValue.generated.ts +15 -0
  442. package/src/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.ts +7 -1
  443. package/src/i18n/generated-locales/en.generated.ts +43 -0
  444. package/src/i18n/generated-locales/pseudo.generated.ts +44 -0
  445. package/src/index.ts +14 -0
  446. package/src/internal/SheetConfirmation.tsx +101 -0
  447. package/src/internal/indicatorPress.stylex.ts +24 -0
  448. package/src/internal/sheetDraft.ts +80 -0
  449. package/src/internal/touch-sheet.ts +21 -0
  450. package/src/internal/useDismissSearchOnTouchDrag.ts +69 -0
  451. package/src/motion/MEASUREMENTS.md +7 -0
  452. package/src/motion/README.md +9 -5
  453. package/src/motion/animator.ts +61 -29
  454. package/src/motion/reducedMotion.ts +79 -1
  455. package/src/motion/roles.ts +20 -1
  456. package/src/motion/uikit/alert.ts +43 -0
  457. package/src/motion/uikit/index.ts +5 -5
  458. package/src/motion/uikit/segmented.ts +74 -0
  459. package/src/motion/uikit/springs.ts +5 -21
  460. package/src/privateAttributes/pressGroupItem.stylex.ts +23 -0
  461. package/src/privateAttributes/segmentTitle.stylex.ts +22 -0
  462. package/src/utils/browserClickWait.ts +133 -0
  463. package/src/utils/clickGuard.ts +64 -1
  464. package/src/utils/dateParser.ts +16 -0
  465. package/src/utils/focusReturn.ts +30 -0
  466. package/src/utils/interactionOverlay.stylex.ts +3 -2
  467. package/src/utils/pressFeedback.ts +19 -6
  468. package/src/utils/triggerFocus.ts +80 -0
  469. package/dist/internal/tokenizer-presentation.d.ts +0 -21
  470. package/dist/internal/tokenizer-presentation.d.ts.map +0 -1
  471. package/dist/internal/tokenizer-presentation.js +0 -21
  472. package/src/internal/tokenizer-presentation.ts +0 -25
@@ -37,6 +37,12 @@ export interface CheckboxListContextValue {
37
37
  */
38
38
  disabledMessageID?: string;
39
39
  isReadOnly: boolean;
40
+ /**
41
+ * True when the list has an error `status`. Each checkbox is then
42
+ * `aria-invalid`. Some screen readers skip a group's invalid state when a
43
+ * checkbox takes focus.
44
+ */
45
+ isInvalid?: boolean;
40
46
  /**
41
47
  * Values of the items whose `changeAction` is pending. Each matching item
42
48
  * renders an in-checkbox spinner and blocks re-toggling; the list is empty
@@ -24,6 +24,7 @@ import {colorVars} from '../theme/tokens.stylex';
24
24
  import type {BaseProps} from '../BaseProps';
25
25
  import {CheckboxInput} from '../CheckboxInput/CheckboxInput';
26
26
  import type {CheckboxInputProps} from '../CheckboxInput/CheckboxInput';
27
+ import type {InputStatus} from '../Field/types';
27
28
  import {ListItem} from '../List/ListItem';
28
29
  import {ListContext} from '../List/ListContext';
29
30
  import {CheckboxListContext} from './CheckboxListContext';
@@ -149,6 +150,8 @@ export interface CheckboxListItemProps extends BaseProps<HTMLLIElement> {
149
150
  // Component
150
151
  // =============================================================================
151
152
 
153
+ const ERROR_STATUS: InputStatus = {type: 'error'};
154
+
152
155
  /**
153
156
  * The row's visible description is the checkbox's accessible description. Item
154
157
  * renders that element and owns its id, and publishes the id through
@@ -167,11 +170,17 @@ function DescribedCheckboxInput(
167
170
  props: Omit<CheckboxInputProps, 'aria-describedby'>,
168
171
  ) {
169
172
  const describedBy = use(ItemDescriptionContext);
170
- const reasonID = use(CheckboxListContext)?.disabledMessageID;
173
+ const listContext = use(CheckboxListContext);
171
174
  return (
172
175
  <CheckboxInput
173
176
  {...props}
174
- aria-describedby={joinAriaIDs(describedBy ?? undefined, reasonID)}
177
+ aria-describedby={joinAriaIDs(
178
+ describedBy ?? undefined,
179
+ listContext?.disabledMessageID,
180
+ )}
181
+ // The status has no message, so CheckboxInput renders nothing. The list
182
+ // renders the message.
183
+ status={listContext?.isInvalid ? ERROR_STATUS : undefined}
175
184
  />
176
185
  );
177
186
  }
@@ -35,6 +35,7 @@ import {
35
35
  } from '../Field/fieldParts';
36
36
  import {useDevWarning} from '../hooks/useDevWarning';
37
37
  import {mergeRefs} from '../utils/mergeRefs';
38
+ import {isFocusLost} from '../utils/focusReturn';
38
39
  import {useMergedRefs} from '../hooks/useMergedRefs';
39
40
  import {useBusyAnnouncement} from '../hooks/useBusyAnnouncement';
40
41
  import {Field, inputWrapperStyles} from '../Field';
@@ -347,7 +348,10 @@ export interface ComplexSelectorRenderState {
347
348
  export interface ComplexSelectorHandle {
348
349
  /** Open the selector surface. No-op when disabled or already open. */
349
350
  open(): void;
350
- /** Close the selector surface. Restores focus to the trigger. */
351
+ /**
352
+ * Close the selector surface. Focus returns to the trigger only when it
353
+ * would otherwise be lost; a caller-rendered trigger always gets it back.
354
+ */
351
355
  close(): void;
352
356
  /** Toggle the selector surface open or closed. */
353
357
  toggle(): void;
@@ -630,12 +634,22 @@ export function ComplexSelector<Value>({
630
634
  onOpenChange?.(true);
631
635
  }, [onOpenChange]);
632
636
 
637
+ // The popup's content element, read when it closes.
638
+ const popupContentRef = useRef<HTMLElement | null>(null);
639
+ const hasCallerTrigger = renderTrigger != null;
633
640
  const handlePopoverHide = useCallback(() => {
634
- // Focus is restored first so a consumer that moves focus elsewhere from
635
- // the callback wins, instead of being overwritten a line later.
636
- triggerRef.current?.focus();
641
+ const trigger = triggerRef.current;
642
+ // A press that moved focus to another control keeps it there. A caller's
643
+ // control always gets focus back. Focus moves before the callback, so a
644
+ // consumer that moves it from the callback wins.
645
+ if (
646
+ hasCallerTrigger ||
647
+ isFocusLost(popupContentRef.current, trigger?.ownerDocument)
648
+ ) {
649
+ trigger?.focus();
650
+ }
637
651
  onOpenChange?.(false);
638
- }, [onOpenChange]);
652
+ }, [hasCallerTrigger, onOpenChange]);
639
653
 
640
654
  const popover = usePopover({
641
655
  dialogLabel: label,
@@ -645,6 +659,7 @@ export function ComplexSelector<Value>({
645
659
  onShow: handlePopoverShow,
646
660
  onHide: handlePopoverHide,
647
661
  });
662
+ popupContentRef.current = popover.contentRef.current;
648
663
 
649
664
  const isOpen = popover.isOpen;
650
665
 
@@ -712,14 +712,14 @@ export function ContextMenu({
712
712
  );
713
713
  const handleTriggerTouchEnd = useCallback(
714
714
  (event: React.TouchEvent<HTMLElement>) => {
715
- handleLongPressTouchEnd();
715
+ handleLongPressTouchEnd(event);
716
716
  onTouchEndProp?.(event);
717
717
  },
718
718
  [handleLongPressTouchEnd, onTouchEndProp],
719
719
  );
720
720
  const handleTriggerTouchCancel = useCallback(
721
721
  (event: React.TouchEvent<HTMLElement>) => {
722
- handleLongPressTouchCancel();
722
+ handleLongPressTouchCancel(event);
723
723
  onTouchCancelProp?.(event);
724
724
  },
725
725
  [handleLongPressTouchCancel, onTouchCancelProp],
@@ -884,12 +884,18 @@ function PointerDateField({
884
884
  if (!isEffectivelyDisabled) {
885
885
  popover.show({skipAutoFocus: true});
886
886
  }
887
- } else if (e.key === 'Enter') {
887
+ } else if (
888
+ e.key === 'Enter' &&
889
+ (pendingInput !== null || isEffectivelyDisabled)
890
+ ) {
891
+ // Typed text holds Enter back, or a form would submit the value from
892
+ // before the commit. A disabled or busy field must not submit its
893
+ // form either. Otherwise Enter keeps its default, as in any text field.
888
894
  e.preventDefault();
889
895
  commitPendingInput();
890
896
  }
891
897
  },
892
- [popover, commitPendingInput, isEffectivelyDisabled],
898
+ [popover, commitPendingInput, isEffectivelyDisabled, pendingInput],
893
899
  );
894
900
 
895
901
  const inputWrapper = (
@@ -38,6 +38,7 @@ import {
38
38
  useRef,
39
39
  useState,
40
40
  } from 'react';
41
+ import {flushSync} from 'react-dom';
41
42
  import * as stylex from '@stylexjs/stylex';
42
43
  import {useCalendarDays} from '../Calendar';
43
44
  import {useDirection, useLocale} from '../i18n';
@@ -62,7 +63,11 @@ import {
62
63
  plainDateToISO,
63
64
  DATE_FORMAT_WITH_WEEKDAY,
64
65
  } from '../utils';
65
- import {reducedMotionFade} from '../motion/reducedMotion';
66
+ import {
67
+ playReducedMotionDip,
68
+ reducedMotionFade,
69
+ type ReducedMotionDip,
70
+ } from '../motion/reducedMotion';
66
71
  import {dateInputTouchSizes, dateInputTouchGeometry} from './tokens.stylex';
67
72
  import {useOwnScrollGesture} from './useOwnScrollGesture';
68
73
  import {useScrollSettle} from './useScrollSettle';
@@ -434,17 +439,12 @@ export function MonthScroller({
434
439
 
435
440
  // The Reduced Motion dip of a step on a touch screen, owned here so a
436
441
  // second step or the unmount clears it.
437
- const dipRef = useRef<{animation: Animation; timer: number} | null>(null);
442
+ const dipRef = useRef<ReducedMotionDip | null>(null);
438
443
  const stopDip = useCallback(() => {
439
- const dip = dipRef.current;
440
- if (dip != null) {
441
- window.clearTimeout(dip.timer);
442
- dip.animation.cancel();
443
- dipRef.current = null;
444
- }
444
+ dipRef.current?.cancel();
445
+ dipRef.current = null;
445
446
  }, []);
446
- // Synchronizes with the dip's timer and animation: neither outlives the
447
- // scroller.
447
+ // Synchronizes with the dip's animations: they do not outlive the scroller.
448
448
  useEffect(() => stopDip, [stopDip]);
449
449
 
450
450
  const scrollToMonth = useCallback(
@@ -505,18 +505,14 @@ export function MonthScroller({
505
505
  land();
506
506
  return;
507
507
  }
508
- // A second step within the dip has replaced the first (above): only
509
- // its scroll lands, at its own dip's middle.
510
- dipRef.current = {
511
- animation: scroller.animate(
512
- [{opacity: 1}, {opacity: 0}, {opacity: 1}],
513
- {duration: fade.duration, easing: fade.easing},
514
- ),
515
- timer: window.setTimeout(() => {
516
- dipRef.current = null;
517
- land();
518
- }, fade.duration / 2),
519
- };
508
+ // A newer step replaces this one: only its scroll lands.
509
+ dipRef.current = playReducedMotionDip(scroller, fade, () => {
510
+ dipRef.current = null;
511
+ // The fade-in starts as soon as this returns. So render now: the
512
+ // scroll lands in the layout effect, before the fade-in.
513
+ // eslint-disable-next-line @eslint-react/dom-no-flush-sync -- the month must change before the dip's fade-in starts
514
+ flushSync(land);
515
+ });
520
516
  return;
521
517
  }
522
518
  steeredRowRef.current = row;
@@ -49,7 +49,11 @@ import {
49
49
  durationVars,
50
50
  } from '../theme/tokens.stylex';
51
51
  import {focusOutlineStyles} from '../utils';
52
- import {reducedMotionFade} from '../motion/reducedMotion';
52
+ import {
53
+ playReducedMotionDip,
54
+ reducedMotionFade,
55
+ type ReducedMotionDip,
56
+ } from '../motion/reducedMotion';
53
57
  import {dateInputTouchSizes, dateInputTouchGeometry} from './tokens.stylex';
54
58
  import {useOwnScrollGesture} from './useOwnScrollGesture';
55
59
  import {usePointerDragScroll} from './usePointerDragScroll';
@@ -331,19 +335,19 @@ export function Wheel({
331
335
  // once on a fine one.
332
336
  const lastPointerRef = useRef<string | null>(null);
333
337
 
334
- // A reduced-motion dip whose rows have not landed yet: its timer and the
335
- // row it lands on. While one is pending the rows stay put for it, so they
336
- // never move at full opacity, and a further step retargets it.
337
- const pendingFadeRef = useRef<{timer: number; top: number} | null>(null);
338
+ // A reduced-motion dip whose rows have not landed yet: the row they land
339
+ // on. While one is pending the rows stay put for it, so they never move at
340
+ // full opacity, and a further step retargets it.
341
+ const pendingFadeRef = useRef<{top: number} | null>(null);
338
342
  // The running dip, so a step during its fade-in starts the next one where
339
343
  // the column is.
340
- const dipRef = useRef<Animation | null>(null);
344
+ const dipRef = useRef<ReducedMotionDip | null>(null);
345
+ // Synchronizes with the dip's animations: an unmounted wheel lands nothing.
341
346
  useEffect(
342
347
  () => () => {
343
- if (pendingFadeRef.current != null) {
344
- window.clearTimeout(pendingFadeRef.current.timer);
345
- pendingFadeRef.current = null;
346
- }
348
+ pendingFadeRef.current = null;
349
+ dipRef.current?.cancel();
350
+ dipRef.current = null;
347
351
  },
348
352
  [],
349
353
  );
@@ -368,19 +372,15 @@ export function Wheel({
368
372
  ? reducedMotionFade(scroller, {touchRelease})
369
373
  : null;
370
374
  const pending = pendingFadeRef.current;
375
+ // A change that lands now replaces a pending landing. Its dip goes on
376
+ // and fades back in.
371
377
  if (fadeTiming == null) {
372
- if (pending != null) {
373
- window.clearTimeout(pending.timer);
374
- pendingFadeRef.current = null;
375
- }
378
+ pendingFadeRef.current = null;
376
379
  scroller.scrollTo({top, behavior});
377
380
  return;
378
381
  }
379
382
  if (fadeTiming.duration === 0 || typeof scroller.animate !== 'function') {
380
- if (pending != null) {
381
- window.clearTimeout(pending.timer);
382
- pendingFadeRef.current = null;
383
- }
383
+ pendingFadeRef.current = null;
384
384
  scroller.scrollTo({top, behavior: 'auto'});
385
385
  return;
386
386
  }
@@ -389,26 +389,24 @@ export function Wheel({
389
389
  pending.top = top;
390
390
  return;
391
391
  }
392
- const {duration, easing} = fadeTiming;
393
392
  // A step during the last dip's fade-in starts the new dip at the
394
393
  // column's current opacity, not at full opacity. A leaving element fades
395
394
  // out from where it is.
396
395
  const shown = Number.parseFloat(getComputedStyle(scroller).opacity);
397
396
  dipRef.current?.cancel();
398
- dipRef.current = scroller.animate(
399
- [
400
- {opacity: Number.isFinite(shown) ? shown : 1, easing},
401
- {opacity: 0, easing},
402
- {opacity: 1},
403
- ],
404
- {duration, easing: 'linear'},
405
- );
406
- const landing = {top, timer: 0};
407
- landing.timer = window.setTimeout(() => {
408
- pendingFadeRef.current = null;
409
- scroller.scrollTo({top: landing.top, behavior: 'auto'});
410
- }, duration / 2);
397
+ const landing = {top};
411
398
  pendingFadeRef.current = landing;
399
+ dipRef.current = playReducedMotionDip(
400
+ scroller,
401
+ fadeTiming,
402
+ () => {
403
+ if (pendingFadeRef.current === landing) {
404
+ pendingFadeRef.current = null;
405
+ scroller.scrollTo({top: landing.top, behavior: 'auto'});
406
+ }
407
+ },
408
+ Number.isFinite(shown) ? shown : 1,
409
+ );
412
410
  },
413
411
  [itemBlockSize],
414
412
  );
@@ -1143,12 +1143,18 @@ function PointerDateTimeField({
1143
1143
  if (!isEffectivelyDisabled) {
1144
1144
  popover.show({skipAutoFocus: true});
1145
1145
  }
1146
- } else if (e.key === 'Enter') {
1146
+ } else if (
1147
+ e.key === 'Enter' &&
1148
+ (datePendingInput !== null || isEffectivelyDisabled)
1149
+ ) {
1150
+ // Typed text holds Enter back, or a form would submit the value from
1151
+ // before the commit. A disabled or busy field must not submit its
1152
+ // form either. Otherwise Enter keeps its default, as in any text field.
1147
1153
  e.preventDefault();
1148
1154
  commitDatePendingInput();
1149
1155
  }
1150
1156
  },
1151
- [popover, commitDatePendingInput, isEffectivelyDisabled],
1157
+ [popover, commitDatePendingInput, isEffectivelyDisabled, datePendingInput],
1152
1158
  );
1153
1159
 
1154
1160
  // --- Time-option popover (#2727) ---
@@ -52,6 +52,7 @@ import {LayerContentBoundary} from '../Layer/layerScopedContext';
52
52
  import {layerClickBoundary} from '../Layer/layerClickBoundary';
53
53
  import {LayerDepthProvider} from '../Layer/LayerDepthContext';
54
54
  import {useLayerDismissal} from '../Layer/useLayerDismissal';
55
+ import {useBackdropPress} from '../Layer/useBackdropPress';
55
56
  import {useModalOutlet} from '../Layer/modalOutlet';
56
57
  import {
57
58
  colorVars,
@@ -80,10 +81,15 @@ import {themeProps} from '../utils/themeProps';
80
81
  import type {DialogVariantMap} from './index';
81
82
  import {focusOutlineProps} from '../utils/focusOutline.stylex';
82
83
  import {useInteractionModalityTracking} from '../utils/interactionModality';
83
- import {focusForLastInput, isFocusLost} from '../utils/focusReturn';
84
+ import {
85
+ focusForLastInput,
86
+ prepareFocusReturnOnRemoval,
87
+ } from '../utils/focusReturn';
84
88
  import {ModalAnnounceProvider} from '../hooks/ModalAnnounceProvider';
85
89
 
86
90
  import {useMergedRefs} from '../hooks/useMergedRefs';
91
+
92
+ type PointerHandler = (event: React.PointerEvent<HTMLDialogElement>) => void;
87
93
  /**
88
94
  * Calculate a directional translate offset for dialog entry animation.
89
95
  * Returns a normalized vector from the trigger element toward the viewport
@@ -186,8 +192,22 @@ const styles = stylex.create({
186
192
  position: 'fixed',
187
193
  margin: 'auto',
188
194
  padding: 0,
189
- borderWidth: 0,
190
- borderStyle: 'none',
195
+ // The backdrop does not blur the page. Forced colors override the
196
+ // backdrop's colour, so a 1px border keeps the modal separate from the
197
+ // page. It is a border, not an outline: the focus ring
198
+ // (focusOutlineProps) owns the outline longhands on this element.
199
+ borderWidth: {
200
+ default: 0,
201
+ '@media (forced-colors: active)': 1,
202
+ },
203
+ borderStyle: {
204
+ default: 'none',
205
+ '@media (forced-colors: active)': 'solid',
206
+ },
207
+ borderColor: {
208
+ default: null,
209
+ '@media (forced-colors: active)': 'CanvasText',
210
+ },
191
211
  backgroundColor: colorVars['--color-background-surface'],
192
212
  '--_dialog-radius': radiusVars['--radius-container'],
193
213
  borderRadius: 'var(--_dialog-radius)',
@@ -233,11 +253,10 @@ const styles = stylex.create({
233
253
  openSettled: {
234
254
  animationName: 'none',
235
255
  },
236
- // Backdrop using ::backdrop pseudo-element
256
+ // No backdrop-filter: a full-viewport blur is costly to repaint.
237
257
  backdrop: {
238
258
  '::backdrop': {
239
259
  backgroundColor: colorVars['--color-overlay'],
240
- backdropFilter: 'blur(2px)',
241
260
  },
242
261
  },
243
262
  fullscreen: {
@@ -246,6 +265,8 @@ const styles = stylex.create({
246
265
  maxWidth: '100dvw',
247
266
  maxHeight: '100dvh',
248
267
  borderRadius: 0,
268
+ // Nothing of the page shows around a full-screen dialog: no edge.
269
+ borderWidth: 0,
249
270
  margin: 0,
250
271
  inset: 0,
251
272
  },
@@ -635,39 +656,15 @@ export function Dialog({
635
656
  }, [isOpen, isInline]);
636
657
 
637
658
  // A dialog that unmounts while open (rendered only while open, or removed
638
- // with the rest of a view) never runs the close branch above, and removing a
639
- // <dialog> does not run the browser's own focus return. Focus left inside
640
- // it, or dropped to the body by the removal, goes back to the opener.
659
+ // with the rest of a view) never runs the close branch above. Focus the
660
+ // removal lost goes back to the opener.
641
661
  useEffect(() => {
642
- if (isInline) {
662
+ const dialog = dialogRef.current;
663
+ if (isInline || dialog == null) {
643
664
  return;
644
665
  }
645
- const dialog = dialogRef.current;
646
- // Read now: a removed iframe's document has no window, so its frame
647
- // element can no longer be found once the dialog is gone.
648
- const host = dialog?.ownerDocument.defaultView?.frameElement ?? null;
649
- return () => {
650
- const trigger = triggerElementRef.current;
651
- if (dialog == null || trigger == null) {
652
- return;
653
- }
654
- // Checked once the commit has finished: StrictMode's simulated unmount
655
- // leaves the dialog in the document, and only a real removal returns
656
- // focus.
657
- queueMicrotask(() => {
658
- if (dialog.isConnected || !trigger.isConnected) {
659
- return;
660
- }
661
- // isFocusLost reads the dialog's own document. For a dialog in an
662
- // iframe, the document that hosts the frame must also have lost focus
663
- // or keep it on that frame, wherever the opener is: a control the
664
- // user pressed outside the frame to remove the dialog, or the frame
665
- // itself, keeps its focus.
666
- if (isFocusLost(dialog) && (host == null || isFocusLost(host))) {
667
- focusForLastInput(trigger);
668
- }
669
- });
670
- };
666
+ const returnFocusOnRemoval = prepareFocusReturnOnRemoval(dialog);
667
+ return () => returnFocusOnRemoval(triggerElementRef.current);
671
668
  }, [isInline]);
672
669
 
673
670
  // Host app-global surfaces (toasts) inside this modal while it is open, so
@@ -723,16 +720,16 @@ export function Dialog({
723
720
  }
724
721
  }, [isOpen, isInline, hasConsumerName, titleId]);
725
722
 
726
- // Handle backdrop click — when the user clicks the ::backdrop pseudo-element,
727
- // the event target is the <dialog> element itself; clicks on child content
728
- // always target the child. This avoids false positives from native browser
723
+ // A press on the ::backdrop targets the <dialog> itself, so native browser
729
724
  // popups (date pickers, selects, color pickers) that render outside the
730
- // dialog's bounding rect.
731
- const handleClick = (event: React.MouseEvent<HTMLDialogElement>) => {
732
- if (event.target === event.currentTarget && allowBackdropClick) {
733
- onOpenChange(false);
734
- }
735
- };
725
+ // dialog's rect never count. The press must start and end there.
726
+ const handleBackdropPress = useCallback(() => {
727
+ onOpenChange(false);
728
+ }, [onOpenChange]);
729
+ const backdropPress = useBackdropPress(
730
+ handleBackdropPress,
731
+ allowBackdropClick,
732
+ );
736
733
 
737
734
  // The native `cancel` event is the browser's own close-watcher firing: an
738
735
  // Android back gesture, or a close request the stack never saw a press for.
@@ -890,8 +887,20 @@ export function Dialog({
890
887
  // written.
891
888
  {...layerClickBoundary({
892
889
  ...safeProps,
893
- onClick: chainEventHandlers(handleClick, onClickProp),
890
+ onClick: chainEventHandlers(backdropPress.onClick, onClickProp),
894
891
  })}
892
+ onPointerDownCapture={chainEventHandlers(
893
+ backdropPress.onPointerDownCapture,
894
+ safeProps.onPointerDownCapture as PointerHandler | undefined,
895
+ )}
896
+ onPointerUpCapture={chainEventHandlers(
897
+ backdropPress.onPointerUpCapture,
898
+ safeProps.onPointerUpCapture as PointerHandler | undefined,
899
+ )}
900
+ onPointerCancelCapture={chainEventHandlers(
901
+ backdropPress.onPointerCancelCapture,
902
+ safeProps.onPointerCancelCapture as PointerHandler | undefined,
903
+ )}
895
904
  onCancel={handleCancel}
896
905
  aria-modal={isHydrating ? undefined : 'true'}
897
906
  // The default aria-labelledby (from a DialogHeader title) is set
@@ -78,9 +78,11 @@ import {layerTextReset} from '../Layer/layerTextReset.stylex';
78
78
  import {layerStructureReset} from '../Layer/layerStructureReset.stylex';
79
79
  import {LayerContentBoundary} from '../Layer/layerScopedContext';
80
80
  import {useModalOutlet} from '../Layer/modalOutlet';
81
+ import {useBackdropPress} from '../Layer/useBackdropPress';
81
82
  import {layerClickBoundary} from '../Layer/layerClickBoundary';
82
83
  import {ModalAnnounceProvider} from '../hooks/ModalAnnounceProvider';
83
84
  import {composeEventHandlers, mergeProps, themeProps} from '../utils';
85
+ import {chainEventHandlers} from '../utils/chainEventHandlers';
84
86
  import {container, overlayPaddingReset} from '../Layout';
85
87
  import {
86
88
  containerPaddingBlockEndVarStyles,
@@ -92,6 +94,8 @@ import {
92
94
  import type {SpacingStep, SpacingToken} from '../Layout';
93
95
  import {useDrawerDialogPresence} from './useDrawerDialogPresence';
94
96
 
97
+ type PointerHandler = (event: React.PointerEvent<HTMLDialogElement>) => void;
98
+
95
99
  // =============================================================================
96
100
  // Styles
97
101
  // =============================================================================
@@ -218,8 +222,8 @@ const styles = stylex.create({
218
222
  // Scrim via the browser's ::backdrop pseudo-element (top layer).
219
223
  scrim: {
220
224
  '::backdrop': {
225
+ // No backdrop-filter: a full-viewport blur is costly to repaint.
221
226
  backgroundColor: colorVars['--color-overlay'],
222
- backdropFilter: 'blur(2px)',
223
227
  opacity: 0,
224
228
  transitionProperty: 'opacity',
225
229
  transitionDuration: durationVars['--duration-medium'],
@@ -543,15 +547,14 @@ export function Drawer({
543
547
  [allowEscape, handleDismiss, shouldDismissOnCloseRequest],
544
548
  );
545
549
 
546
- // Clicks on the ::backdrop target the <dialog> element itself; clicks on
547
- // drawer content always target a child (the content area fills the panel).
548
- const handleClick = useCallback(
549
- (event: React.MouseEvent<HTMLDialogElement>) => {
550
- if (event.target === event.currentTarget && hasScrim && allowScrimClick) {
551
- onOpenChange(false);
552
- }
553
- },
554
- [allowScrimClick, hasScrim, onOpenChange],
550
+ // A press on the ::backdrop targets the <dialog> itself (the content area
551
+ // fills the panel). The press must start and end there.
552
+ const handleScrimPress = useCallback(() => {
553
+ onOpenChange(false);
554
+ }, [onOpenChange]);
555
+ const scrimPress = useBackdropPress(
556
+ handleScrimPress,
557
+ hasScrim && allowScrimClick,
555
558
  );
556
559
 
557
560
  const widthValue = typeof width === 'number' ? `${width}px` : width;
@@ -612,8 +615,22 @@ export function Drawer({
612
615
  // written.
613
616
  {...layerClickBoundary({
614
617
  ...safeProps,
615
- onClick: composeEventHandlers(onClickProp, handleClick),
618
+ onClick: composeEventHandlers(onClickProp, scrimPress.onClick),
616
619
  })}
620
+ // The hook records where the press started first. The caller's capture
621
+ // handler then runs, also when a child prevented default.
622
+ onPointerDownCapture={chainEventHandlers(
623
+ scrimPress.onPointerDownCapture,
624
+ safeProps.onPointerDownCapture as PointerHandler | undefined,
625
+ )}
626
+ onPointerUpCapture={chainEventHandlers(
627
+ scrimPress.onPointerUpCapture,
628
+ safeProps.onPointerUpCapture as PointerHandler | undefined,
629
+ )}
630
+ onPointerCancelCapture={chainEventHandlers(
631
+ scrimPress.onPointerCancelCapture,
632
+ safeProps.onPointerCancelCapture as PointerHandler | undefined,
633
+ )}
617
634
  onKeyDown={onKeyDownProp}
618
635
  onCancel={handleCancel}>
619
636
  <ModalAnnounceProvider dialogRef={dialogRef} isOpen={isOpen && hasScrim}>
@@ -33,6 +33,7 @@ import {
33
33
  } from 'react';
34
34
  import {flushSync} from 'react-dom';
35
35
  import {notifyTopLayerEntry} from '../Layer/modalOutlet';
36
+ import {runPopoverOperation} from '../Layer/popoverOperations';
36
37
 
37
38
  /** Slack past the computed transition before the backstop gives up waiting. */
38
39
  const EXIT_BACKSTOP_BUFFER_MS = 50;
@@ -71,7 +72,10 @@ function showDrawerHost(dialog: HTMLDialogElement, isModal: boolean): void {
71
72
  if (isModal) {
72
73
  dialog.showModal();
73
74
  } else if (typeof dialog.showPopover === 'function') {
74
- dialog.showPopover();
75
+ // The dialog's show focuses its first control. A tooltip on that control
76
+ // then asks to show. The browser refuses a show inside another show.
77
+ // Counting this show makes the tooltip wait until it ends.
78
+ runPopoverOperation(dialog.ownerDocument, () => dialog.showPopover());
75
79
  // The drawer is now the newest top-layer entry: global hosts shown before
76
80
  // it (the toast viewport) re-enter above it, as they do above a modal.
77
81
  notifyTopLayerEntry();
@@ -25,11 +25,11 @@ import {FieldStatus} from '../FieldStatus/FieldStatus';
25
25
  import {useFieldStatusAnnouncement} from '../FieldStatus/useFieldStatusAnnouncement';
26
26
  import {spacingVars, borderVars, sizeVars} from '../theme/tokens.stylex';
27
27
  import type {IconType} from '../Icon';
28
- import {mergeProps} from '../utils';
28
+ import {mergeProps} from '../utils/mergeProps';
29
29
  import {useDevWarning} from '../hooks/useDevWarning';
30
30
  import {FormLayoutContext} from '../FormLayout/FormLayoutContext';
31
31
  import {Text} from '../Text/Text';
32
- import {VisuallyHidden} from '../VisuallyHidden';
32
+ import {VisuallyHidden} from '../VisuallyHidden/VisuallyHidden';
33
33
  import {themeProps} from '../utils/themeProps';
34
34
  import type {FieldStatusPlacement} from './fieldStatusPlacement';
35
35
 
@@ -58,6 +58,7 @@ import {
58
58
  } from '../theme/tokens.stylex';
59
59
  import type {BaseProps} from '../BaseProps';
60
60
  import {textEntryTraitAttributes} from './textEntryTraits';
61
+ import {inputWrapperStyles} from './inputStyles.stylex';
61
62
 
62
63
  const styles = stylex.create({
63
64
  // Gutter only. Matches the option list's own padding so the field below
@@ -185,6 +186,14 @@ export interface PanelSearchInputProps extends Omit<
185
186
  * the field to the same height as its rows.
186
187
  */
187
188
  fieldXstyle?: StyleXStyles;
189
+ /**
190
+ * Draw the field as the shared input box — the input border, accent while
191
+ * focused, surface and radius — instead of the borderless panel row. A
192
+ * touch sheet is a full-width surface, not a bordered panel, so its field
193
+ * reads as a form input.
194
+ * @default false
195
+ */
196
+ hasInputBox?: boolean;
188
197
  }
189
198
 
190
199
  /**
@@ -208,6 +217,7 @@ export function PanelSearchInput({
208
217
  onBlur,
209
218
  onContainerKeyDown,
210
219
  fieldXstyle,
220
+ hasInputBox = false,
211
221
  xstyle,
212
222
  className,
213
223
  style,
@@ -268,6 +278,7 @@ export function PanelSearchInput({
268
278
  {...stylex.props(
269
279
  styles.field,
270
280
  isKeyboardFocus && styles.fieldKeyboardFocus,
281
+ hasInputBox && inputWrapperStyles.base,
271
282
  fieldXstyle,
272
283
  )}>
273
284
  <Icon icon="search" size="sm" color="secondary" xstyle={styles.icon} />