@astryxdesign/core 0.7.7-canary.f9ac85f → 0.7.7

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 (198) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/dist/AppShell/useCloseMobileDrawerOnActivate.d.ts +13 -0
  3. package/dist/AppShell/useCloseMobileDrawerOnActivate.d.ts.map +1 -0
  4. package/dist/AppShell/useCloseMobileDrawerOnActivate.js +45 -0
  5. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  6. package/dist/BottomSheet/BottomSheet.js +79 -9
  7. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  8. package/dist/BottomSheet/BottomSheetPanel.js +1 -1
  9. package/dist/BottomSheet/bottomSheetStack.d.ts.map +1 -1
  10. package/dist/BottomSheet/bottomSheetStack.js +5 -4
  11. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +2 -1
  12. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  13. package/dist/Breadcrumbs/BreadcrumbItem.js +7 -3
  14. package/dist/Button/Button.d.ts.map +1 -1
  15. package/dist/Button/Button.js +30 -2
  16. package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
  17. package/dist/CheckboxList/CheckboxList.js +7 -1
  18. package/dist/CheckboxList/CheckboxListContext.d.ts +6 -0
  19. package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
  20. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  21. package/dist/CheckboxList/CheckboxListItem.js +10 -2
  22. package/dist/DateInput/DateInput.d.ts.map +1 -1
  23. package/dist/DateInput/DateInput.js +5 -2
  24. package/dist/DateInput/MonthScroller.d.ts.map +1 -1
  25. package/dist/DateInput/MonthScroller.js +13 -27
  26. package/dist/DateInput/Wheel.d.ts.map +1 -1
  27. package/dist/DateInput/Wheel.js +22 -41
  28. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  29. package/dist/DateTimeInput/DateTimeInput.js +5 -2
  30. package/dist/Dialog/Dialog.d.ts.map +1 -1
  31. package/dist/Dialog/Dialog.js +4 -3
  32. package/dist/Drawer/Drawer.js +0 -1
  33. package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
  34. package/dist/Drawer/useDrawerDialogPresence.js +5 -1
  35. package/dist/Field/PanelSearchInput.d.ts +9 -1
  36. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  37. package/dist/Field/PanelSearchInput.js +3 -1
  38. package/dist/InfoTip/InfoTip.d.ts +2 -2
  39. package/dist/InfoTip/InfoTip.js +4 -4
  40. package/dist/Layer/layerAnimations.stylex.d.ts +7 -8
  41. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  42. package/dist/Layer/layerAnimations.stylex.js +25 -20
  43. package/dist/Layer/usePressPin.d.ts +3 -5
  44. package/dist/Layer/usePressPin.d.ts.map +1 -1
  45. package/dist/Layer/usePressPin.js +4 -6
  46. package/dist/MobileNav/MobileNav.js +0 -1
  47. package/dist/MultiSelector/hooks.d.ts.map +1 -1
  48. package/dist/MultiSelector/hooks.js +2 -4
  49. package/dist/Outline/Outline.d.ts +2 -4
  50. package/dist/Outline/Outline.d.ts.map +1 -1
  51. package/dist/Outline/Outline.js +4 -52
  52. package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
  53. package/dist/Outline/useOutlineFromMarkdown.js +1 -0
  54. package/dist/Outline/useScrollSpy.js +3 -3
  55. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  56. package/dist/PowerSearch/PowerSearch.js +134 -179
  57. package/dist/RadioList/RadioList.d.ts.map +1 -1
  58. package/dist/RadioList/RadioList.js +5 -0
  59. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  60. package/dist/Resizable/ResizeHandle.js +118 -260
  61. package/dist/Resizable/resizeGesture.d.ts +91 -0
  62. package/dist/Resizable/resizeGesture.d.ts.map +1 -0
  63. package/dist/Resizable/resizeGesture.js +251 -0
  64. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  65. package/dist/SideNav/SideNavItem.js +3 -9
  66. package/dist/Token/Token.d.ts +2 -2
  67. package/dist/Token/Token.d.ts.map +1 -1
  68. package/dist/Token/Token.js +12 -4
  69. package/dist/Token/TokenNamingContext.d.ts +14 -0
  70. package/dist/Token/TokenNamingContext.d.ts.map +1 -0
  71. package/dist/Token/TokenNamingContext.js +23 -0
  72. package/dist/Tokenizer/Tokenizer.d.ts +46 -59
  73. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  74. package/dist/Tokenizer/Tokenizer.js +35 -58
  75. package/dist/Tokenizer/TokenizerBottomSheet.d.ts +25 -28
  76. package/dist/Tokenizer/TokenizerBottomSheet.d.ts.map +1 -1
  77. package/dist/Tokenizer/TokenizerBottomSheet.js +157 -54
  78. package/dist/Tokenizer/TokenizerItemRemovableContext.d.ts.map +1 -1
  79. package/dist/Tokenizer/TokenizerItemRemovableContext.js +5 -3
  80. package/dist/Tooltip/Tooltip.d.ts +25 -30
  81. package/dist/Tooltip/Tooltip.d.ts.map +1 -1
  82. package/dist/Tooltip/Tooltip.js +24 -5
  83. package/dist/Tooltip/index.d.ts +1 -1
  84. package/dist/Tooltip/index.d.ts.map +1 -1
  85. package/dist/Tooltip/useTooltip.d.ts +28 -29
  86. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  87. package/dist/Tooltip/useTooltip.js +20 -8
  88. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  89. package/dist/TopNav/TopNavItem.js +4 -7
  90. package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
  91. package/dist/TopNav/TopNavMegaMenuItem.js +4 -7
  92. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  93. package/dist/TopNav/TopNavMenu.js +4 -7
  94. package/dist/astryx.css +5 -5
  95. package/dist/gestures/GestureHost.d.ts +27 -1
  96. package/dist/gestures/GestureHost.d.ts.map +1 -1
  97. package/dist/gestures/GestureHost.js +90 -8
  98. package/dist/hooks/useHighlightedOptionScroll.d.ts +11 -1
  99. package/dist/hooks/useHighlightedOptionScroll.d.ts.map +1 -1
  100. package/dist/hooks/useHighlightedOptionScroll.js +103 -5
  101. package/dist/hooks/useMenuPress.d.ts.map +1 -1
  102. package/dist/hooks/useMenuPress.js +4 -2
  103. package/dist/i18n/generated-english/PowerSearch/PowerSearch.generated.d.ts.map +1 -1
  104. package/dist/i18n/generated-english/PowerSearch/PowerSearch.generated.js +1 -0
  105. package/dist/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.d.ts.map +1 -1
  106. package/dist/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.js +7 -1
  107. package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
  108. package/dist/i18n/generated-locales/en.generated.js +1 -0
  109. package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
  110. package/dist/i18n/generated-locales/pseudo.generated.js +1 -0
  111. package/dist/internal/SheetConfirmation.d.ts +11 -0
  112. package/dist/internal/SheetConfirmation.d.ts.map +1 -0
  113. package/dist/internal/SheetConfirmation.js +92 -0
  114. package/dist/internal/sheetDraft.d.ts +35 -0
  115. package/dist/internal/sheetDraft.d.ts.map +1 -0
  116. package/dist/internal/sheetDraft.js +65 -0
  117. package/dist/internal/touch-sheet.d.ts +21 -0
  118. package/dist/internal/touch-sheet.d.ts.map +1 -0
  119. package/dist/internal/touch-sheet.js +19 -0
  120. package/dist/internal/useDismissSearchOnTouchDrag.d.ts +24 -0
  121. package/dist/internal/useDismissSearchOnTouchDrag.d.ts.map +1 -0
  122. package/dist/internal/useDismissSearchOnTouchDrag.js +56 -0
  123. package/dist/motion/reducedMotion.d.ts +24 -0
  124. package/dist/motion/reducedMotion.d.ts.map +1 -1
  125. package/dist/motion/reducedMotion.js +78 -1
  126. package/dist/utils/clickGuard.d.ts +8 -1
  127. package/dist/utils/clickGuard.d.ts.map +1 -1
  128. package/dist/utils/clickGuard.js +24 -1
  129. package/locales/en.json +4 -0
  130. package/locales/pseudo.json +3 -0
  131. package/package.json +9 -9
  132. package/src/AppShell/useCloseMobileDrawerOnActivate.ts +52 -0
  133. package/src/BottomSheet/BottomSheet.tsx +95 -10
  134. package/src/BottomSheet/BottomSheetPanel.tsx +7 -2
  135. package/src/BottomSheet/bottomSheetStack.ts +8 -4
  136. package/src/Breadcrumbs/BreadcrumbItem.tsx +13 -3
  137. package/src/Button/Button.tsx +37 -1
  138. package/src/CheckboxList/CheckboxList.doc.mjs +4 -2
  139. package/src/CheckboxList/CheckboxList.tsx +6 -0
  140. package/src/CheckboxList/CheckboxListContext.tsx +6 -0
  141. package/src/CheckboxList/CheckboxListItem.tsx +11 -2
  142. package/src/DateInput/DateInput.tsx +8 -2
  143. package/src/DateInput/MonthScroller.tsx +18 -22
  144. package/src/DateInput/Wheel.tsx +30 -32
  145. package/src/DateTimeInput/DateTimeInput.tsx +8 -2
  146. package/src/Dialog/Dialog.tsx +19 -4
  147. package/src/Drawer/Drawer.tsx +1 -1
  148. package/src/Drawer/useDrawerDialogPresence.ts +5 -1
  149. package/src/Field/PanelSearchInput.tsx +11 -0
  150. package/src/InfoTip/InfoTip.doc.mjs +3 -3
  151. package/src/InfoTip/InfoTip.tsx +5 -5
  152. package/src/Layer/layerAnimations.stylex.ts +24 -16
  153. package/src/Layer/usePressPin.ts +5 -11
  154. package/src/MobileNav/MobileNav.tsx +1 -1
  155. package/src/MultiSelector/hooks.ts +2 -4
  156. package/src/Outline/Outline.doc.mjs +177 -51
  157. package/src/Outline/Outline.tsx +5 -57
  158. package/src/Outline/useOutlineFromMarkdown.doc.mjs +157 -0
  159. package/src/Outline/useOutlineFromMarkdown.ts +1 -0
  160. package/src/Outline/useScrollSpy.ts +3 -3
  161. package/src/PowerSearch/PowerSearch.doc.mjs +3 -3
  162. package/src/PowerSearch/PowerSearch.tsx +196 -183
  163. package/src/RadioList/RadioList.doc.mjs +4 -2
  164. package/src/RadioList/RadioList.tsx +4 -0
  165. package/src/Resizable/ResizeHandle.tsx +133 -328
  166. package/src/Resizable/resizeGesture.ts +368 -0
  167. package/src/SideNav/SideNavItem.tsx +3 -7
  168. package/src/Token/Token.tsx +13 -4
  169. package/src/Token/TokenNamingContext.ts +28 -0
  170. package/src/Tokenizer/Tokenizer.doc.mjs +16 -0
  171. package/src/Tokenizer/Tokenizer.tsx +81 -86
  172. package/src/Tokenizer/TokenizerBottomSheet.tsx +219 -93
  173. package/src/Tokenizer/TokenizerItemRemovableContext.ts +5 -3
  174. package/src/Tooltip/Tooltip.doc.mjs +123 -54
  175. package/src/Tooltip/Tooltip.tsx +36 -39
  176. package/src/Tooltip/index.ts +0 -1
  177. package/src/Tooltip/useTooltip.doc.mjs +147 -33
  178. package/src/Tooltip/useTooltip.tsx +39 -32
  179. package/src/TopNav/TopNavItem.tsx +6 -5
  180. package/src/TopNav/TopNavMegaMenuItem.tsx +6 -5
  181. package/src/TopNav/TopNavMenu.tsx +6 -5
  182. package/src/gestures/GestureHost.ts +105 -10
  183. package/src/hooks/useHighlightedOptionScroll.ts +113 -9
  184. package/src/hooks/useMenuPress.ts +8 -2
  185. package/src/i18n/generated-english/PowerSearch/PowerSearch.generated.ts +1 -0
  186. package/src/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.ts +7 -1
  187. package/src/i18n/generated-locales/en.generated.ts +1 -0
  188. package/src/i18n/generated-locales/pseudo.generated.ts +1 -0
  189. package/src/internal/SheetConfirmation.tsx +101 -0
  190. package/src/internal/sheetDraft.ts +80 -0
  191. package/src/internal/touch-sheet.ts +21 -0
  192. package/src/internal/useDismissSearchOnTouchDrag.ts +69 -0
  193. package/src/motion/reducedMotion.ts +79 -1
  194. package/src/utils/clickGuard.ts +37 -1
  195. package/dist/internal/tokenizer-presentation.d.ts +0 -21
  196. package/dist/internal/tokenizer-presentation.d.ts.map +0 -1
  197. package/dist/internal/tokenizer-presentation.js +0 -21
  198. package/src/internal/tokenizer-presentation.ts +0 -25
@@ -9,6 +9,12 @@ interface UseHighlightedOptionScrollOptions {
9
9
  */
10
10
  itemCount?: number;
11
11
  }
12
+ /**
13
+ * Highlights the hovered option at `index`. `onHighlight` runs when the hover
14
+ * takes effect: at once, or after the pointer moves or presses when a
15
+ * keyboard move holds the highlight.
16
+ */
17
+ export type HighlightFromHover = (index: number, onHighlight?: () => void) => void;
12
18
  /**
13
19
  * Keep the highlighted option visible during keyboard navigation — but not for
14
20
  * hover highlights. Hover must highlight only: scrollIntoView moves the next
@@ -16,7 +22,11 @@ interface UseHighlightedOptionScrollOptions {
16
22
  * scrolls again — a runaway auto-scroll loop with no user input.
17
23
  * Keyboard paths call the raw setter directly and keep their scrolling; hover
18
24
  * paths call the returned callback.
25
+ *
26
+ * A keyboard move holds the highlight. A key that scrolls the list moves rows
27
+ * under a still mouse, and the browser reports the row under it as entered;
28
+ * that row takes the highlight only once the pointer moves or presses.
19
29
  */
20
- export declare function useHighlightedOptionScroll({ isOpen, highlightedIndex, setHighlightedIndex, getOptionId, itemCount, }: UseHighlightedOptionScrollOptions): (index: number) => void;
30
+ export declare function useHighlightedOptionScroll({ isOpen, highlightedIndex, setHighlightedIndex, getOptionId, itemCount, }: UseHighlightedOptionScrollOptions): HighlightFromHover;
21
31
  export {};
22
32
  //# sourceMappingURL=useHighlightedOptionScroll.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useHighlightedOptionScroll.d.ts","sourceRoot":"","sources":["../../src/hooks/useHighlightedOptionScroll.ts"],"names":[],"mappings":"AAiBA,UAAU,iCAAiC;IACzC,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,MAAM,EACN,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,EACX,SAAS,GACV,EAAE,iCAAiC,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CA+B7D"}
1
+ {"version":3,"file":"useHighlightedOptionScroll.d.ts","sourceRoot":"","sources":["../../src/hooks/useHighlightedOptionScroll.ts"],"names":[],"mappings":"AAkBA,UAAU,iCAAiC;IACzC,MAAM,EAAE,OAAO,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAC/B,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,IAAI,KACrB,IAAI,CAAC;AAOV;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,MAAM,EACN,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,EACX,SAAS,GACV,EAAE,iCAAiC,GAAG,kBAAkB,CAmHxD"}
@@ -8,11 +8,19 @@
8
8
  * option-id resolver for the owning listbox
9
9
  * @output Exports useHighlightedOptionScroll: keeps the highlighted option
10
10
  * scrolled into view for keyboard navigation while hover-driven highlights
11
- * never scroll; the hover callback is stable while `setHighlightedIndex` is
11
+ * never scroll, and a hover after a keyboard move waits for the pointer to
12
+ * move or press; the hover callback is stable while `setHighlightedIndex` is
12
13
  * @position Internal hook; used by useCombobox, useMultiCombobox,
13
14
  * BaseTypeahead, and DateTimeInput — the owners of combobox highlight state
14
15
  */
15
16
  import { useCallback, useEffect, useRef } from 'react';
17
+
18
+ /**
19
+ * Highlights the hovered option at `index`. `onHighlight` runs when the hover
20
+ * takes effect: at once, or after the pointer moves or presses when a
21
+ * keyboard move holds the highlight.
22
+ */
23
+
16
24
  /**
17
25
  * Keep the highlighted option visible during keyboard navigation — but not for
18
26
  * hover highlights. Hover must highlight only: scrollIntoView moves the next
@@ -20,6 +28,10 @@ import { useCallback, useEffect, useRef } from 'react';
20
28
  * scrolls again — a runaway auto-scroll loop with no user input.
21
29
  * Keyboard paths call the raw setter directly and keep their scrolling; hover
22
30
  * paths call the returned callback.
31
+ *
32
+ * A keyboard move holds the highlight. A key that scrolls the list moves rows
33
+ * under a still mouse, and the browser reports the row under it as entered;
34
+ * that row takes the highlight only once the pointer moves or presses.
23
35
  */
24
36
  export function useHighlightedOptionScroll({
25
37
  isOpen,
@@ -31,10 +43,87 @@ export function useHighlightedOptionScroll({
31
43
  // The callback reads no render state, so memoized rows keep one function.
32
44
  const hoveredIndexRef = useRef(null);
33
45
  const shownIndexRef = useRef(highlightedIndex);
34
- const highlightFromHover = useCallback(index => {
46
+ // The hover that came while a keyboard move held the highlight.
47
+ const waitingHoverRef = useRef(null);
48
+ // Set only while a keyboard move holds the highlight.
49
+ const removeHoldListenersRef = useRef(null);
50
+ const setHighlightedIndexRef = useRef(setHighlightedIndex);
51
+ // The pointer's last screen position a hold saw, kept across holds.
52
+ const lastPointerRef = useRef(null);
53
+ const applyHover = useCallback(hover => {
54
+ hoveredIndexRef.current = hover.index;
55
+ setHighlightedIndexRef.current(hover.index);
56
+ hover.onHighlight?.();
57
+ }, []);
58
+ const endHold = useCallback(() => {
59
+ removeHoldListenersRef.current?.();
60
+ removeHoldListenersRef.current = null;
61
+ }, []);
62
+ const releaseHold = useCallback(() => {
63
+ endHold();
64
+ const waiting = waitingHoverRef.current;
65
+ waitingHoverRef.current = null;
66
+ if (waiting != null) {
67
+ applyHover(waiting);
68
+ }
69
+ }, [applyHover, endHold]);
70
+
71
+ // Holds the highlight until the pointer moves or presses. The listeners
72
+ // live only while the hold does. Movement is read by screen coordinates: a
73
+ // scroll moves the rows, not the pointer. The browser reports a row as
74
+ // entered before the move that reaches it, so the first real move gives
75
+ // that row the highlight. A press releases at once, so a held press lights
76
+ // the pressed row.
77
+ const startHold = useCallback(() => {
78
+ waitingHoverRef.current = null;
79
+ if (removeHoldListenersRef.current != null) {
80
+ return;
81
+ }
82
+ const onPointerMove = event => {
83
+ const last = lastPointerRef.current;
84
+ lastPointerRef.current = {
85
+ x: event.screenX,
86
+ y: event.screenY
87
+ };
88
+ if (last != null && last.x === event.screenX && last.y === event.screenY) {
89
+ return;
90
+ }
91
+ releaseHold();
92
+ };
93
+ const options = {
94
+ capture: true,
95
+ passive: true
96
+ };
97
+ document.addEventListener('pointermove', onPointerMove, options);
98
+ document.addEventListener('pointerdown', releaseHold, options);
99
+ removeHoldListenersRef.current = () => {
100
+ document.removeEventListener('pointermove', onPointerMove, options);
101
+ document.removeEventListener('pointerdown', releaseHold, options);
102
+ };
103
+ }, [releaseHold]);
104
+ const highlightFromHover = useCallback((index, onHighlight) => {
105
+ if (removeHoldListenersRef.current != null) {
106
+ waitingHoverRef.current = {
107
+ index,
108
+ onHighlight
109
+ };
110
+ return;
111
+ }
35
112
  hoveredIndexRef.current = index;
36
113
  setHighlightedIndex(index);
114
+ onHighlight?.();
115
+ }, [setHighlightedIndex]);
116
+
117
+ // Effect: keeps the hold's document listeners calling the current setter.
118
+ useEffect(() => {
119
+ setHighlightedIndexRef.current = setHighlightedIndex;
37
120
  }, [setHighlightedIndex]);
121
+
122
+ // Effect: removes the hold's document listeners on unmount.
123
+ useEffect(() => endHold, [endHold]);
124
+
125
+ // Effect: scrolls the highlighted option into view in the document, and
126
+ // starts or ends the hold on its document listeners.
38
127
  useEffect(() => {
39
128
  // Only a move to the hovered row came from the hover. A hover on the row
40
129
  // already highlighted changes nothing, so a later run for the same row
@@ -43,12 +132,21 @@ export function useHighlightedOptionScroll({
43
132
  shownIndexRef.current = highlightedIndex;
44
133
  const isFromHover = hasMoved && hoveredIndexRef.current === highlightedIndex;
45
134
  hoveredIndexRef.current = null;
46
- if (isFromHover || !isOpen || highlightedIndex < 0) {
135
+ if (isFromHover) {
136
+ return;
137
+ }
138
+ // A cleared highlight, a closed list, or a list that is not shown (a
139
+ // closed CommandPalette reports itself as open) has nothing to hold.
140
+ const option = isOpen && highlightedIndex >= 0 ? document.getElementById(getOptionId(highlightedIndex)) : null;
141
+ if (option == null) {
142
+ waitingHoverRef.current = null;
143
+ endHold();
47
144
  return;
48
145
  }
49
- document.getElementById(getOptionId(highlightedIndex))?.scrollIntoView?.({
146
+ startHold();
147
+ option.scrollIntoView?.({
50
148
  block: 'nearest'
51
149
  });
52
- }, [isOpen, highlightedIndex, getOptionId, itemCount]);
150
+ }, [isOpen, highlightedIndex, getOptionId, itemCount, endHold, startHold]);
53
151
  return highlightFromHover;
54
152
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useMenuPress.d.ts","sourceRoot":"","sources":["../../src/hooks/useMenuPress.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAML,KAAK,oBAAoB,EAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AAiBpD,OAAO,EAAC,iBAAiB,EAAC,CAAC;AAE3B;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,mCAAmC,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,yBAAyB,MAAwB,CAAC;AAC/D,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,MAAyB,CAAC;AAC/D;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAM9C,oFAAoF;AACpF,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAUhD;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED,4DAA4D;AAC5D,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED,MAAM,WAAW,mBAAmB;IAClC,+EAA+E;IAC/E,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACvC,uEAAuE;IACvE,UAAU,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC3C;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,oBAAoB,KAAK,OAAO,CAAC;IAChE;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/D,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IACvC;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;IACnD,mBAAmB;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,SAAS,EAAE;QACT,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAChE,CAAC,iBAAiB,CAAC,EAAE,EAAE,CAAC;KACzB,CAAC;IACF,yEAAyE;IACzE,YAAY,EAAE;QACZ,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAChE,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;KAC/D,CAAC;IACF;;;;OAIG;IACH,uBAAuB,EAAE,MAAM,OAAO,CAAC;IACvC,uEAAuE;IACvE,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AA0DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CAwkB7E"}
1
+ {"version":3,"file":"useMenuPress.d.ts","sourceRoot":"","sources":["../../src/hooks/useMenuPress.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAML,KAAK,oBAAoB,EAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AAiBpD,OAAO,EAAC,iBAAiB,EAAC,CAAC;AAE3B;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,mCAAmC,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,yBAAyB,MAAwB,CAAC;AAC/D,iFAAiF;AACjF,eAAO,MAAM,wBAAwB,MAAyB,CAAC;AAC/D;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAM9C,oFAAoF;AACpF,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAUhD;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED,4DAA4D;AAC5D,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C;AAED,MAAM,WAAW,mBAAmB;IAClC,+EAA+E;IAC/E,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACvC,uEAAuE;IACvE,UAAU,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC3C;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,oBAAoB,KAAK,OAAO,CAAC;IAChE;;;;;OAKG;IACH,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IAChD;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IAC/D,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IACvC;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,GAAG,IAAI,CAAC;IACnD,mBAAmB;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,sEAAsE;IACtE,SAAS,EAAE;QACT,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAChE,CAAC,iBAAiB,CAAC,EAAE,EAAE,CAAC;KACzB,CAAC;IACF,yEAAyE;IACzE,YAAY,EAAE;QACZ,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;QAChE,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;KAC/D,CAAC;IACF;;;;OAIG;IACH,uBAAuB,EAAE,MAAM,OAAO,CAAC;IACvC,uEAAuE;IACvE,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AA0DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CA8kB7E"}
@@ -344,7 +344,8 @@ export function useMenuPress(options) {
344
344
  endGesture();
345
345
  // Once armed, the one swallower stays installed.
346
346
  armClickGuard(doc, {
347
- staysInstalled: true
347
+ staysInstalled: true,
348
+ cancelsTouchEnd: native?.pointerType === 'touch'
348
349
  });
349
350
  if (native != null) {
350
351
  activate(effect.row, native);
@@ -356,7 +357,8 @@ export function useMenuPress(options) {
356
357
  endGesture();
357
358
  if (effect.stray) {
358
359
  armClickGuard(doc, {
359
- staysInstalled: true
360
+ staysInstalled: true,
361
+ cancelsTouchEnd: native?.pointerType === 'touch'
360
362
  });
361
363
  }
362
364
  if (effect.dismiss) {
@@ -1 +1 @@
1
- {"version":3,"file":"PowerSearch.generated.d.ts","sourceRoot":"","sources":["../../../../src/i18n/generated-english/PowerSearch/PowerSearch.generated.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,QAAA,MAAM,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAM7C,CAAC;AAEF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"PowerSearch.generated.d.ts","sourceRoot":"","sources":["../../../../src/i18n/generated-english/PowerSearch/PowerSearch.generated.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,QAAA,MAAM,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAO7C,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -8,6 +8,7 @@
8
8
 
9
9
  const english = {
10
10
  "@astryx.powersearch.allFiltersRemoved": "All filters removed",
11
+ "@astryx.powersearch.editableFiltersRemoved": "Editable filters removed",
11
12
  "@astryx.powersearch.editor.apply": "Apply",
12
13
  "@astryx.powersearch.label": "Search",
13
14
  "@astryx.powersearch.placeholder": "Search…",
@@ -1 +1 @@
1
- {"version":3,"file":"TokenizerBottomSheet.generated.d.ts","sourceRoot":"","sources":["../../../../src/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,QAAA,MAAM,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAoB7C,CAAC;AAEF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"TokenizerBottomSheet.generated.d.ts","sourceRoot":"","sources":["../../../../src/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,QAAA,MAAM,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA0B7C,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -7,6 +7,7 @@
7
7
  */
8
8
 
9
9
  const english = {
10
+ "@astryx.alertDialog.cancel": "Cancel",
10
11
  "@astryx.textInput.clearLabel": "Clear {label}",
11
12
  "@astryx.tokenizer.add": "Add",
12
13
  "@astryx.tokenizer.addValue": "Add {value}",
@@ -16,11 +17,16 @@ const english = {
16
17
  "@astryx.tokenizer.clearAllTitle": "Clear all selected items?",
17
18
  "@astryx.tokenizer.clearSelection": "Clear selection",
18
19
  "@astryx.tokenizer.create": "Create \"{value}\"",
19
- "@astryx.tokenizer.done": "Done",
20
+ "@astryx.tokenizer.discardChanges": "Discard changes",
21
+ "@astryx.tokenizer.discardChangesDescription": "Your changes to {label} haven't been saved.",
22
+ "@astryx.tokenizer.discardChangesTitle": "Discard changes?",
23
+ "@astryx.tokenizer.keepEditing": "Keep editing",
20
24
  "@astryx.tokenizer.noResultsDescription": "Try a different search.",
21
25
  "@astryx.tokenizer.nothingToClear": "Nothing selected",
26
+ "@astryx.tokenizer.save": "Save",
22
27
  "@astryx.tokenizer.search": "Search {label}",
23
28
  "@astryx.tokenizer.searchPlaceholder": "Search…",
29
+ "@astryx.tokenizer.selectionLimit": "Select up to {count, plural, one {# item} other {# items}}",
24
30
  "@astryx.tokenizer.tokenAdded": "Added {label}",
25
31
  "@astryx.tokenizer.tokenRemoved": "Removed {label}",
26
32
  "@astryx.typeahead.emptySearchResults": "No results found",
@@ -1 +1 @@
1
- {"version":3,"file":"en.generated.d.ts","sourceRoot":"","sources":["../../../src/i18n/generated-locales/en.generated.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,QAAA,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAmnBpD,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"en.generated.d.ts","sourceRoot":"","sources":["../../../src/i18n/generated-locales/en.generated.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,QAAA,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAonBpD,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -288,6 +288,7 @@ const runtimeCatalog = {
288
288
  '@astryx.powersearch.label': 'Search',
289
289
  '@astryx.powersearch.placeholder': 'Search…',
290
290
  '@astryx.powersearch.allFiltersRemoved': 'All filters removed',
291
+ '@astryx.powersearch.editableFiltersRemoved': 'Editable filters removed',
291
292
  '@astryx.resizable.collapsed': 'Collapsed',
292
293
  '@astryx.resizable.handle.label': 'Resize handle',
293
294
  '@astryx.selector.placeholder': 'Select…',
@@ -1 +1 @@
1
- {"version":3,"file":"pseudo.generated.d.ts","sourceRoot":"","sources":["../../../src/i18n/generated-locales/pseudo.generated.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,QAAA,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA8nBpD,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"pseudo.generated.d.ts","sourceRoot":"","sources":["../../../src/i18n/generated-locales/pseudo.generated.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,QAAA,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA+nBpD,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -288,6 +288,7 @@ const runtimeCatalog = {
288
288
  '@astryx.powersearch.label': '⟦Šéàřçĥ⟧',
289
289
  '@astryx.powersearch.placeholder': '⟦Šéàřçĥ…⟧',
290
290
  '@astryx.powersearch.allFiltersRemoved': '⟦Àłł ƒíłţéřš řéɱóṽéð⟧',
291
+ '@astryx.powersearch.editableFiltersRemoved': '⟦Éðíţàƀłé ƒíłţéřš řéɱóṽéð⟧',
291
292
  '@astryx.resizable.collapsed': '⟦Çółłàþšéð⟧',
292
293
  '@astryx.resizable.handle.label': '⟦Řéšížé ĥàñðłé⟧',
293
294
  '@astryx.selector.placeholder': '⟦Šéłéçţ…⟧',
@@ -0,0 +1,11 @@
1
+ export interface SheetConfirmationProps {
2
+ isOpen: boolean;
3
+ onOpenChange: (isOpen: boolean) => void;
4
+ title: string;
5
+ description: string;
6
+ cancelLabel: string;
7
+ actionLabel: string;
8
+ onAction: () => void;
9
+ }
10
+ export declare function SheetConfirmation({ isOpen, onOpenChange, title, description, cancelLabel, actionLabel, onAction, }: SheetConfirmationProps): import("react").JSX.Element;
11
+ //# sourceMappingURL=SheetConfirmation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SheetConfirmation.d.ts","sourceRoot":"","sources":["../../src/internal/SheetConfirmation.tsx"],"names":[],"mappings":"AA8BA,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAMD,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,YAAY,EACZ,KAAK,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,QAAQ,GACT,EAAE,sBAAsB,+BAgDxB"}
@@ -0,0 +1,92 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file SheetConfirmation.tsx
7
+ * @input Dialog, Layout, Heading, Text, Button; caller-owned copy
8
+ * @output SheetConfirmation — the confirmation a touch sheet opens over
9
+ * itself for Clear all and for discarding a changed draft
10
+ * @position Core-internal, shared by the Tokenizer sheet and the PowerSearch
11
+ * sheets; not a public export
12
+ *
13
+ * AlertDialog fixes its purpose to form and its safe action to ghost. A touch
14
+ * sheet's confirmation allows scrim dismissal. Its two full-width large
15
+ * actions are stacked and separated: the destructive action first in reading
16
+ * order, the safe action focused first. The alert-dialog theme target stays.
17
+ */
18
+ import { useId } from 'react';
19
+ import * as stylex from '@stylexjs/stylex';
20
+ import { Button } from "../Button/Button.js";
21
+ import { Dialog } from "../Dialog/Dialog.js";
22
+ import { Heading } from "../Heading/Heading.js";
23
+ import { Layout } from "../Layout/Layout.js";
24
+ import { LayoutContent } from "../Layout/LayoutContent.js";
25
+ import { LayoutFooter } from "../Layout/LayoutFooter.js";
26
+ import { Stack } from "../Stack/Stack.js";
27
+ import { Text } from "../Text/Text.js";
28
+ import { themeProps } from "../utils/themeProps.js";
29
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
30
+ const styles = {
31
+ action: {
32
+ kzqmXN: "xh8yej3",
33
+ $$css: true
34
+ }
35
+ };
36
+ export function SheetConfirmation({
37
+ isOpen,
38
+ onOpenChange,
39
+ title,
40
+ description,
41
+ cancelLabel,
42
+ actionLabel,
43
+ onAction
44
+ }) {
45
+ const titleId = useId();
46
+ const descriptionId = useId();
47
+ return /*#__PURE__*/_jsx(Dialog, {
48
+ ...themeProps('alert-dialog'),
49
+ isOpen: isOpen,
50
+ onOpenChange: onOpenChange,
51
+ purpose: "info",
52
+ role: "alertdialog",
53
+ "aria-labelledby": titleId,
54
+ "aria-describedby": descriptionId,
55
+ width: 400,
56
+ children: /*#__PURE__*/_jsx(Layout, {
57
+ content: /*#__PURE__*/_jsxs(LayoutContent, {
58
+ children: [/*#__PURE__*/_jsx(Heading, {
59
+ level: 2,
60
+ id: titleId,
61
+ children: title
62
+ }), /*#__PURE__*/_jsx(Text, {
63
+ type: "body",
64
+ color: "secondary",
65
+ id: descriptionId,
66
+ children: description
67
+ })]
68
+ }),
69
+ footer: /*#__PURE__*/_jsx(LayoutFooter, {
70
+ children: /*#__PURE__*/_jsxs(Stack, {
71
+ direction: "vertical",
72
+ gap: 4,
73
+ hAlign: "stretch",
74
+ children: [/*#__PURE__*/_jsx(Button, {
75
+ label: actionLabel,
76
+ variant: "destructive",
77
+ size: "lg",
78
+ onClick: onAction,
79
+ xstyle: styles.action
80
+ }), /*#__PURE__*/_jsx(Button, {
81
+ label: cancelLabel,
82
+ variant: "secondary",
83
+ size: "lg",
84
+ onClick: () => onOpenChange(false),
85
+ "data-autofocus": true,
86
+ xstyle: styles.action
87
+ })]
88
+ })
89
+ })
90
+ })
91
+ });
92
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @file sheetDraft.ts
3
+ * @input A sheet's selection at open, its draft, and the last edit made
4
+ * @output SheetDraftChange, hasSameSelection, nameSheetDraftChange — the
5
+ * rules a touch sheet's Save and dismissal share
6
+ * @position Core-internal, shared by the Tokenizer sheet and the Lab sheets
7
+ * through `internal/touch-sheet`; not a public export
8
+ *
9
+ * A touch sheet edits a draft and reports it once, on Save, with one change:
10
+ * the last edit that still holds, else the nearest net add or remove. A
11
+ * dismissal asks before discarding only while the draft differs from the
12
+ * selection at open, as a set: a row unchecked and checked again is no change.
13
+ */
14
+ interface SheetDraftItem {
15
+ id: string | number;
16
+ }
17
+ /** An edit of a sheet's draft, and the shape Save reports. */
18
+ export type SheetDraftChange<T> = {
19
+ item: T;
20
+ type: 'add' | 'create' | 'remove';
21
+ };
22
+ /** Whether two selections hold the same items, in any order. */
23
+ export declare function hasSameSelection<T extends SheetDraftItem>(a: ReadonlyArray<T>, b: ReadonlyArray<T>): boolean;
24
+ /**
25
+ * The change Save reports for a draft that differs from the selection at
26
+ * open, or `null` when nothing differs. The last edit names it when it still
27
+ * holds: its item is in the draft and was not selected at open, or was
28
+ * selected at open and is gone. Otherwise, after a removal, a `remove` names
29
+ * an item that is gone; otherwise an `add` (`create` when the last edit
30
+ * created that item) names an item that is new; otherwise a `remove` names
31
+ * an item that is gone.
32
+ */
33
+ export declare function nameSheetDraftChange<T extends SheetDraftItem>(valueAtOpen: ReadonlyArray<T>, draftValue: ReadonlyArray<T>, lastDraftChange: SheetDraftChange<T> | null): SheetDraftChange<T> | null;
34
+ export {};
35
+ //# sourceMappingURL=sheetDraft.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sheetDraft.d.ts","sourceRoot":"","sources":["../../src/internal/sheetDraft.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;GAYG;AAEH,UAAU,cAAc;IACtB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB;AAED,8DAA8D;AAC9D,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;IAChC,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACnC,CAAC;AAEF,gEAAgE;AAChE,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,cAAc,EACvD,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,EACnB,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,GAClB,OAAO,CAMT;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,cAAc,EAC3D,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC,EAC7B,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,EAC5B,eAAe,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,GAC1C,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI,CA6B5B"}
@@ -0,0 +1,65 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ /**
3
+ * @file sheetDraft.ts
4
+ * @input A sheet's selection at open, its draft, and the last edit made
5
+ * @output SheetDraftChange, hasSameSelection, nameSheetDraftChange — the
6
+ * rules a touch sheet's Save and dismissal share
7
+ * @position Core-internal, shared by the Tokenizer sheet and the Lab sheets
8
+ * through `internal/touch-sheet`; not a public export
9
+ *
10
+ * A touch sheet edits a draft and reports it once, on Save, with one change:
11
+ * the last edit that still holds, else the nearest net add or remove. A
12
+ * dismissal asks before discarding only while the draft differs from the
13
+ * selection at open, as a set: a row unchecked and checked again is no change.
14
+ */
15
+
16
+ /** An edit of a sheet's draft, and the shape Save reports. */
17
+
18
+ /** Whether two selections hold the same items, in any order. */
19
+ export function hasSameSelection(a, b) {
20
+ if (a.length !== b.length) {
21
+ return false;
22
+ }
23
+ const ids = new Set(a.map(item => item.id));
24
+ return b.every(item => ids.has(item.id));
25
+ }
26
+
27
+ /**
28
+ * The change Save reports for a draft that differs from the selection at
29
+ * open, or `null` when nothing differs. The last edit names it when it still
30
+ * holds: its item is in the draft and was not selected at open, or was
31
+ * selected at open and is gone. Otherwise, after a removal, a `remove` names
32
+ * an item that is gone; otherwise an `add` (`create` when the last edit
33
+ * created that item) names an item that is new; otherwise a `remove` names
34
+ * an item that is gone.
35
+ */
36
+ export function nameSheetDraftChange(valueAtOpen, draftValue, lastDraftChange) {
37
+ const wasSelected = id => valueAtOpen.some(item => item.id === id);
38
+ const isSelected = id => draftValue.some(item => item.id === id);
39
+ const added = draftValue.find(item => !wasSelected(item.id));
40
+ const removed = valueAtOpen.find(item => !isSelected(item.id));
41
+ const lastChangeIsNet = lastDraftChange != null && (lastDraftChange.type === 'remove' ? wasSelected(lastDraftChange.item.id) && !isSelected(lastDraftChange.item.id) : isSelected(lastDraftChange.item.id) && !wasSelected(lastDraftChange.item.id));
42
+ if (lastChangeIsNet) {
43
+ return lastDraftChange;
44
+ }
45
+ if (lastDraftChange?.type === 'remove' && removed != null) {
46
+ return {
47
+ item: removed,
48
+ type: 'remove'
49
+ };
50
+ }
51
+ if (added != null) {
52
+ const type = lastDraftChange?.item.id === added.id && lastDraftChange.type === 'create' ? 'create' : 'add';
53
+ return {
54
+ item: added,
55
+ type
56
+ };
57
+ }
58
+ if (removed != null) {
59
+ return {
60
+ item: removed,
61
+ type: 'remove'
62
+ };
63
+ }
64
+ return null;
65
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @file touch-sheet.ts
3
+ * @input The touch sheets' shared confirmation, search-drag dismissal and
4
+ * draft rules
5
+ * @output `@astryxdesign/core/internal/touch-sheet`: SheetConfirmation,
6
+ * useDismissSearchOnTouchDrag, hasSameSelection and nameSheetDraftChange,
7
+ * re-exported by name for Lab's sheets
8
+ * @position An internal entry reserved for Astryx's own packages:
9
+ * undocumented, outside the public API and its compatibility promise,
10
+ * versioned in lockstep with Core, and allowed only in Core and Lab by the
11
+ * `@astryx/no-core-internal-import` lint rule. Core components import the
12
+ * same modules by relative path. Named re-exports only.
13
+ *
14
+ * SYNC: When modified, update scripts/sync-exports.js.
15
+ */
16
+ export { SheetConfirmation } from './SheetConfirmation.js';
17
+ export type { SheetConfirmationProps } from './SheetConfirmation.js';
18
+ export { useDismissSearchOnTouchDrag } from './useDismissSearchOnTouchDrag.js';
19
+ export { hasSameSelection, nameSheetDraftChange } from './sheetDraft.js';
20
+ export type { SheetDraftChange } from './sheetDraft.js';
21
+ //# sourceMappingURL=touch-sheet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"touch-sheet.d.ts","sourceRoot":"","sources":["../../src/internal/touch-sheet.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,YAAY,EAAC,sBAAsB,EAAC,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAC,2BAA2B,EAAC,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAC,gBAAgB,EAAE,oBAAoB,EAAC,MAAM,cAAc,CAAC;AACpE,YAAY,EAAC,gBAAgB,EAAC,MAAM,cAAc,CAAC"}
@@ -0,0 +1,19 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ /**
3
+ * @file touch-sheet.ts
4
+ * @input The touch sheets' shared confirmation, search-drag dismissal and
5
+ * draft rules
6
+ * @output `@astryxdesign/core/internal/touch-sheet`: SheetConfirmation,
7
+ * useDismissSearchOnTouchDrag, hasSameSelection and nameSheetDraftChange,
8
+ * re-exported by name for Lab's sheets
9
+ * @position An internal entry reserved for Astryx's own packages:
10
+ * undocumented, outside the public API and its compatibility promise,
11
+ * versioned in lockstep with Core, and allowed only in Core and Lab by the
12
+ * `@astryx/no-core-internal-import` lint rule. Core components import the
13
+ * same modules by relative path. Named re-exports only.
14
+ *
15
+ * SYNC: When modified, update scripts/sync-exports.js.
16
+ */
17
+ export { SheetConfirmation } from "./SheetConfirmation.js";
18
+ export { useDismissSearchOnTouchDrag } from "./useDismissSearchOnTouchDrag.js";
19
+ export { hasSameSelection, nameSheetDraftChange } from "./sheetDraft.js";
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @file useDismissSearchOnTouchDrag.ts
3
+ * @input Caller-owned search inputs, a focus target, and touch events from a
4
+ * separate results list
5
+ * @output useDismissSearchOnTouchDrag — touch handlers for the results list
6
+ * @position Core-internal, shared by the touch sheets; not a public export
7
+ *
8
+ * A direct vertical touch drag on the results moves focus off a focused
9
+ * search input. The on-screen keyboard then leaves and the rows come into
10
+ * view; the query stays. Focus goes to the caller's target (the sheet's
11
+ * panel), never to the page body behind an open modal. Scroll events are not
12
+ * observed: filtering can clamp scrollTop and fire scroll while someone is
13
+ * typing. Small moves, taps and multi-touch gestures leave focus alone.
14
+ */
15
+ import { type TouchEvent } from 'react';
16
+ type SearchInput = HTMLInputElement | null | undefined;
17
+ export declare function useDismissSearchOnTouchDrag(getSearchInputs: () => ReadonlyArray<SearchInput>, getFocusTarget?: () => HTMLElement | null | undefined): {
18
+ onTouchStart: (event: TouchEvent<HTMLElement>) => void;
19
+ onTouchMove: (event: TouchEvent<HTMLElement>) => void;
20
+ onTouchEnd: () => void;
21
+ onTouchCancel: () => void;
22
+ };
23
+ export {};
24
+ //# sourceMappingURL=useDismissSearchOnTouchDrag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDismissSearchOnTouchDrag.d.ts","sourceRoot":"","sources":["../../src/internal/useDismissSearchOnTouchDrag.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAS,KAAK,UAAU,EAAC,MAAM,OAAO,CAAC;AAI9C,KAAK,WAAW,GAAG,gBAAgB,GAAG,IAAI,GAAG,SAAS,CAAC;AAEvD,wBAAgB,2BAA2B,CACzC,eAAe,EAAE,MAAM,aAAa,CAAC,WAAW,CAAC,EACjD,cAAc,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,SAAS;0BAQ7B,UAAU,CAAC,WAAW,CAAC;yBAIxB,UAAU,CAAC,WAAW,CAAC;;;EA6B/C"}
@@ -0,0 +1,56 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file useDismissSearchOnTouchDrag.ts
7
+ * @input Caller-owned search inputs, a focus target, and touch events from a
8
+ * separate results list
9
+ * @output useDismissSearchOnTouchDrag — touch handlers for the results list
10
+ * @position Core-internal, shared by the touch sheets; not a public export
11
+ *
12
+ * A direct vertical touch drag on the results moves focus off a focused
13
+ * search input. The on-screen keyboard then leaves and the rows come into
14
+ * view; the query stays. Focus goes to the caller's target (the sheet's
15
+ * panel), never to the page body behind an open modal. Scroll events are not
16
+ * observed: filtering can clamp scrollTop and fire scroll while someone is
17
+ * typing. Small moves, taps and multi-touch gestures leave focus alone.
18
+ */
19
+ import { useRef } from 'react';
20
+ const DRAG_THRESHOLD_PX = 8;
21
+ export function useDismissSearchOnTouchDrag(getSearchInputs, getFocusTarget) {
22
+ const startYRef = useRef(null);
23
+ const reset = () => {
24
+ startYRef.current = null;
25
+ };
26
+ return {
27
+ onTouchStart: event => {
28
+ startYRef.current = event.touches.length === 1 ? event.touches[0].clientY : null;
29
+ },
30
+ onTouchMove: event => {
31
+ if (event.touches.length !== 1) {
32
+ reset();
33
+ return;
34
+ }
35
+ const startY = startYRef.current;
36
+ if (startY == null || Math.abs(event.touches[0].clientY - startY) < DRAG_THRESHOLD_PX) {
37
+ return;
38
+ }
39
+ reset();
40
+ const focusedSearch = getSearchInputs().find(input => input != null && input === document.activeElement);
41
+ if (focusedSearch == null) {
42
+ return;
43
+ }
44
+ const target = getFocusTarget?.();
45
+ if (target != null) {
46
+ target.focus({
47
+ preventScroll: true
48
+ });
49
+ } else {
50
+ focusedSearch.blur();
51
+ }
52
+ },
53
+ onTouchEnd: reset,
54
+ onTouchCancel: reset
55
+ };
56
+ }