@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
@@ -6,16 +6,10 @@
6
6
  * @file Tokenizer.tsx
7
7
  * @input Uses React, BaseTypeahead, Field, Token, useAnnounce,
8
8
  * useAdaptivePresentation, and TokenizerBottomSheet (lazy)
9
- * @output Exports Tokenizer multi-select typeahead component, and the
10
- * internal TokenizerWithPresentation signature the `internal/tokenizer-presentation`
11
- * entry re-exports
9
+ * @output Exports Tokenizer multi-select typeahead component
12
10
  * @position Composed component; forwards DOM ref and exposes focus control via
13
- * handleRef. The sheet presentation — a trigger that opens
14
- * TokenizerBottomSheet — is implemented but not exposed: `TokenizerProps`
15
- * offers no `experimental.presentation` while its user experience is being
16
- * finished (`component:Tokenizer` DEC-3, implementation gap), and only
17
- * Astryx's own packages reach it through the internal entry
18
- * (`architecture:react-component-runtime` INV13).
11
+ * handleRef. The experimental `presentation` option swaps the inline
12
+ * combobox for a trigger that opens TokenizerBottomSheet.
19
13
  *
20
14
  * SYNC: When modified, update:
21
15
  * - /packages/core/src/Tokenizer/index.ts
@@ -84,20 +78,12 @@ registerEnglishFallback(english);
84
78
  */
85
79
 
86
80
  /**
87
- * The presentation options the sheet-capable signature admits. Not public:
88
- * `TokenizerProps` has no `experimental` while the sheet's user experience is
89
- * being finished; Astryx's own packages reach the sheet through
90
- * `@astryxdesign/core/internal/tokenizer-presentation`.
91
- */
92
-
93
- /**
94
- * The props of the sheet-capable signature: `TokenizerProps` plus the
95
- * presentation options and a `ref` that also accepts the sheet presentation's
96
- * trigger button, the control it stands for there. Not public: reached only
97
- * as `TokenizerWithPresentation` through the internal entry, so the released
98
- * `TokenizerProps` — an interface, so `interface X extends TokenizerProps<T>`,
99
- * `Omit<TokenizerProps<T>, …>` and `ComponentProps<typeof Tokenizer>` keep
100
- * their released shapes — names no presentation.
81
+ * The props the experimental opt-in admits. `experimental` is present, and
82
+ * `ref` also accepts the sheet presentation's trigger button, the control it
83
+ * stands for there. Only the overload below reaches this type. `TokenizerProps`
84
+ * stays the component's declared props type: it is an interface, so
85
+ * `interface X extends TokenizerProps<T>`, `Omit<TokenizerProps<T>, …>` and
86
+ * `ComponentProps<typeof Tokenizer>` keep their released shapes.
101
87
  */
102
88
 
103
89
  // =============================================================================
@@ -394,10 +380,10 @@ function EndLane({
394
380
  });
395
381
  }
396
382
 
397
- // The public signature names no presentation: `ComponentProps<typeof
398
- // Tokenizer>` and every public call resolve against `TokenizerProps`. The
399
- // implementation also reads the presentation options, reached only through
400
- // `TokenizerWithPresentation` below.
383
+ // Keep this overload first. TypeScript resolves `ComponentProps<typeof
384
+ // Tokenizer>` against the last overload, so that type stays the stable props.
385
+ // A call that passes `experimental` matches this one and may pass the wider
386
+ // `ref`.
401
387
 
402
388
  export function Tokenizer({
403
389
  label,
@@ -514,6 +500,14 @@ export function Tokenizer({
514
500
  sheetQueryRef.current = query;
515
501
  onChangeQuery?.(query);
516
502
  }, [onChangeQuery]);
503
+ // Save's one report. The sheet announced each edit as it happened, so
504
+ // nothing is announced here; a field that is disabled at Save reports
505
+ // nothing.
506
+ const handleSheetCommit = useCallback((items, change) => {
507
+ if (!isDisabled) {
508
+ onChange(items, change);
509
+ }
510
+ }, [isDisabled, onChange]);
517
511
  // Set around a focus move the field makes itself — a presentation swap
518
512
  // handing focus from one control to the other — so the receiving control
519
513
  // does not report it as focus entering from outside.
@@ -646,16 +640,15 @@ export function Tokenizer({
646
640
  // `endContent`, a clear button, or all three — so its width is measured
647
641
  // rather than assumed, and the input reserves it.
648
642
  const [laneRef, laneReserve] = useEndLaneReserve(END_LANE_INSET);
649
- // A composing component can lock tokens (PowerSearch's read-only field).
650
- // Backspace and the token remove controls skip a locked token. Clear all
651
- // does not check it.
643
+ // A composing component can lock tokens (PowerSearch's read-only filters
644
+ // and read-only field). No remove path removes a locked token.
652
645
  const isItemRemovable = use(TokenizerItemRemovableContext);
653
646
  const canRemoveItem = useCallback(item => isItemRemovable?.(item) ?? true, [isItemRemovable]);
654
647
  // The half of the lane's contents this component knows about. The busy half
655
648
  // is the leaf's own business — folding it in here would mean reading the
656
649
  // busy state during this render, which is exactly the re-render the store
657
650
  // exists to avoid.
658
- const hasClearButton = hasClear && value.length > 0 && !isDisabled;
651
+ const hasClearButton = hasClear && !isDisabled && value.some(canRemoveItem);
659
652
  const hasStaticEndLane = Boolean(endContent || hasClearButton);
660
653
  const [isFocusedWithin, setIsFocusedWithin] = useState(false);
661
654
  const isTruncated = !isFocusedWithin && tokenOverflowBehavior !== 'none' && value.length > 0;
@@ -875,18 +868,18 @@ export function Tokenizer({
875
868
  return true;
876
869
  }, [value, onChange, isDisabled, canRemoveItem, announce, t]);
877
870
 
878
- // Handle clearing all items
879
871
  // A composing component that words its own Clear all (PowerSearch) provides
880
872
  // its words; otherwise the field's own (component:Tokenizer AR7).
881
873
  const clearAllMessage = use(TokenizerClearAllMessageContext) ?? t('@astryx.tokenizer.allRemoved');
882
874
  const handleClearAll = useCallback(options => {
883
- if (isDisabled || value.length === 0) {
875
+ const removedItems = value.filter(canRemoveItem);
876
+ if (isDisabled || removedItems.length === 0) {
884
877
  return;
885
878
  }
886
- // Report the last item as removed (convention)
887
- const lastItem = value[value.length - 1];
888
- onChange([], {
889
- item: lastItem,
879
+ // onChange names one item. Clear all names the last one it removes.
880
+ const lastRemovedItem = removedItems[removedItems.length - 1];
881
+ onChange(value.filter(item => !canRemoveItem(item)), {
882
+ item: lastRemovedItem,
890
883
  type: 'remove'
891
884
  });
892
885
  // Focus moves to the input, so the emptied selection is announced, in
@@ -895,7 +888,7 @@ export function Tokenizer({
895
888
  announce(clearAllMessage);
896
889
  }
897
890
  inputRef.current?.focus();
898
- }, [value, onChange, isDisabled, announce, clearAllMessage]);
891
+ }, [value, onChange, isDisabled, canRemoveItem, announce, clearAllMessage]);
899
892
 
900
893
  // Handle backspace on empty input — remove last token
901
894
  const handleKeyDown = useCallback(e => {
@@ -938,7 +931,7 @@ export function Tokenizer({
938
931
  return /*#__PURE__*/_jsx(Token, {
939
932
  label: item.label,
940
933
  size: size,
941
- onRemove: isDisabled ? undefined : onRemoveItem,
934
+ onRemove: isDisabled || !canRemoveItem(item) ? undefined : onRemoveItem,
942
935
  isDisabled: isDisabled,
943
936
  xstyle: styles.token
944
937
  }, item.id);
@@ -1203,17 +1196,13 @@ export function Tokenizer({
1203
1196
  label: label,
1204
1197
  searchSource: searchSource,
1205
1198
  value: value,
1206
- isAtMax: isAtMax,
1199
+ maxEntries: maxEntries,
1207
1200
  hasCreate: hasCreate,
1208
1201
  maxMenuItems: maxMenuItems ?? 10,
1209
1202
  minQueryLength: minQueryLength ?? 1,
1210
1203
  debounceMs: debounceMs ?? 150,
1211
1204
  emptySearchText: emptySearchText,
1212
- onAdd: handleAdd,
1213
- onRemove: handleRemove,
1214
- onClearAll: () => handleClearAll({
1215
- silent: true
1216
- }),
1205
+ onCommit: handleSheetCommit,
1217
1206
  onChangeQuery: handleSheetQueryChange
1218
1207
  })]
1219
1208
  });
@@ -1280,16 +1269,4 @@ export function Tokenizer({
1280
1269
  children: [tokenizerContent, showsDisabledMessage && disabledMessageTooltip.renderTooltip(disabledMessage)]
1281
1270
  });
1282
1271
  }
1283
- Tokenizer.displayName = 'Tokenizer';
1284
-
1285
- /**
1286
- * The same component with the sheet presentation reachable: `experimental`
1287
- * (`presentation: 'popover' | 'bottom-sheet' | 'adaptive'`) and a `ref` that
1288
- * also takes the trigger button. Not public — re-exported only by
1289
- * `@astryxdesign/core/internal/tokenizer-presentation`, the entry reserved
1290
- * for Astryx's own packages (`architecture:react-component-runtime` INV13),
1291
- * while the sheet's user experience is being finished (`component:Tokenizer`
1292
- * DEC-3). The public `Tokenizer` renders the popover presentation for every
1293
- * field.
1294
- */
1295
- export const TokenizerWithPresentation = Tokenizer;
1272
+ Tokenizer.displayName = 'Tokenizer';
@@ -22,13 +22,17 @@
22
22
  * - /docs/specs/components/Tokenizer/Tokenizer.spec.md (FR16–FR24, AR6, PR6)
23
23
  */
24
24
  import { type ReactNode, type RefObject } from 'react';
25
+ import { type SheetDraftChange } from '../internal/sheetDraft.js';
25
26
  import type { SearchableItem, SearchSource } from '../Typeahead/types.js';
26
27
  /** Rows rendered per batch while a long list scrolls (`component:Tokenizer` FR21). */
27
28
  export declare const LIST_RENDER_BATCH_SIZE = 50;
28
29
  export interface TokenizerBottomSheetProps<T extends SearchableItem> {
29
30
  /** Whether the sheet is open. */
30
31
  isOpen: boolean;
31
- /** Called with `false` when the sheet dismisses or Done is pressed. */
32
+ /**
33
+ * Called with `false` when the sheet closes: Save, a clean dismissal, or a
34
+ * confirmed discard.
35
+ */
32
36
  onOpenChange: (isOpen: boolean) => void;
33
37
  /** The trigger, which takes focus back after the sheet closes. */
34
38
  finalFocusRef: RefObject<HTMLElement | null>;
@@ -44,10 +48,10 @@ export interface TokenizerBottomSheetProps<T extends SearchableItem> {
44
48
  /** The field label; names the sheet, the search field, and the list. */
45
49
  label: string;
46
50
  searchSource: SearchSource<T>;
47
- /** The committed selection. */
51
+ /** The committed selection; the draft the sheet edits starts from it. */
48
52
  value: T[];
49
- /** Whether `maxEntries` is reached. */
50
- isAtMax: boolean;
53
+ /** The selection limit, enforced on the draft. */
54
+ maxEntries: number | undefined;
51
55
  hasCreate: boolean;
52
56
  maxMenuItems: number;
53
57
  minQueryLength: number;
@@ -55,41 +59,34 @@ export interface TokenizerBottomSheetProps<T extends SearchableItem> {
55
59
  /** The no-results message; a string becomes the empty state's title. */
56
60
  emptySearchText: ReactNode;
57
61
  /**
58
- * Tokenizer's add path — duplicate checks and the create sentinel — asked
59
- * to stay silent: the sheet announces the change itself, from inside its
60
- * dialog, where `useAnnounce` routes it (`spec:AST-086` FR14). Returns
61
- * whether the item was added.
62
+ * Save's one report: the whole draft and the last edit that still holds.
63
+ * The sheet announces each edit itself when it happens, from inside its
64
+ * dialog, where `useAnnounce` routes it; nothing is announced on Save.
62
65
  */
63
- onAdd: (item: T, options: {
64
- silent: true;
65
- }) => boolean;
66
- /** Tokenizer's remove path, silent for the same reason. */
67
- onRemove: (item: T, options: {
68
- silent: true;
69
- }) => boolean;
70
- /** Tokenizer's clear-all path. */
71
- onClearAll: () => void;
66
+ onCommit: (items: T[], change: SheetDraftChange<T>) => void;
72
67
  onChangeQuery?: (query: string) => void;
73
68
  }
74
69
  /**
75
70
  * The touch surface of Tokenizer's `bottom-sheet` presentation.
76
71
  *
77
- * Rows keep their position while the sheet is open: the items selected when it
78
- * opened lead, in `value` order, then selected items the results do not carry,
79
- * then the results. Toggling a row changes its checkbox and nothing else; the
80
- * next open takes a fresh snapshot and regroups selected-first.
81
- */
82
- /**
83
- * The sheet: BottomSheet around the content. Split in two so the content —
72
+ * One open sheet edits one draft that starts as `value`; rows, the create row
73
+ * and Clear all change the draft, and Save reports it once. Rows keep their
74
+ * position while the sheet is open: the items selected when it opened lead,
75
+ * in `value` order, then draft-selected items the results do not carry, then
76
+ * the results; the next open takes a fresh snapshot and regroups
77
+ * selected-first.
78
+ *
79
+ * The sheet is BottomSheet around the content, split in two so the content —
84
80
  * search, rows, footer, and every announcement about them — is rendered
85
81
  * inside the sheet's dialog, where `useAnnounce` routes into it while it is
86
- * open (`spec:AST-086` FR14): a component that renders a modal and announces
87
- * about its content is inside that modal only when the announcing code is.
82
+ * open: a component that renders a modal and announces about its content is
83
+ * inside that modal only when the announcing code is.
88
84
  *
89
85
  * The outer part also tells the content how a close came about: a close the
90
- * person made (Done, swipe, scrim, Escape) clears the query so the next open
86
+ * person made (Save, swipe, scrim, Escape) clears the query so the next open
91
87
  * lists the bootstrap set, while a close the field forced (becoming disabled
92
- * while open) keeps it (`component:Tokenizer` FR18).
88
+ * while open) keeps it. A swipe, scrim or Escape close of a changed draft is
89
+ * routed to the content first, which asks before discarding.
93
90
  */
94
91
  export declare function TokenizerBottomSheet<T extends SearchableItem>({ isOpen, onOpenChange, finalFocusRef, label, ...content }: TokenizerBottomSheetProps<T>): import("react").JSX.Element;
95
92
  export declare namespace TokenizerBottomSheet {
@@ -1 +1 @@
1
- {"version":3,"file":"TokenizerBottomSheet.d.ts","sourceRoot":"","sources":["../../src/Tokenizer/TokenizerBottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAML,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAiBf,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAgBrE,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAyHzC,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,cAAc;IACjE,iCAAiC;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,uEAAuE;IACvE,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,kEAAkE;IAClE,aAAa,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7C;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9B,+BAA+B;IAC/B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,eAAe,EAAE,SAAS,CAAC;IAC3B;;;;;OAKG;IACH,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;QAAC,MAAM,EAAE,IAAI,CAAA;KAAC,KAAK,OAAO,CAAC;IACrD,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;QAAC,MAAM,EAAE,IAAI,CAAA;KAAC,KAAK,OAAO,CAAC;IACxD,kCAAkC;IAClC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED;;;;;;;GAOG;AACH;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,cAAc,EAAE,EAC7D,MAAM,EACN,YAAY,EACZ,aAAa,EACb,KAAK,EACL,GAAG,OAAO,EACX,EAAE,yBAAyB,CAAC,CAAC,CAAC,+BAgC9B;yBAtCe,oBAAoB"}
1
+ {"version":3,"file":"TokenizerBottomSheet.d.ts","sourceRoot":"","sources":["../../src/Tokenizer/TokenizerBottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAML,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAgBf,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAqBrE,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAyHzC,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,cAAc;IACjE,iCAAiC;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,kEAAkE;IAClE,aAAa,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7C;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9B,yEAAyE;IACzE,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,kDAAkD;IAClD,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,eAAe,EAAE,SAAS,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAC5D,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,cAAc,EAAE,EAC7D,MAAM,EACN,YAAY,EACZ,aAAa,EACb,KAAK,EACL,GAAG,OAAO,EACX,EAAE,yBAAyB,CAAC,CAAC,CAAC,+BAqC9B;yBA3Ce,oBAAoB"}