@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.
- package/CHANGELOG.md +104 -0
- package/dist/AppShell/useCloseMobileDrawerOnActivate.d.ts +13 -0
- package/dist/AppShell/useCloseMobileDrawerOnActivate.d.ts.map +1 -0
- package/dist/AppShell/useCloseMobileDrawerOnActivate.js +45 -0
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +79 -9
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +1 -1
- package/dist/BottomSheet/bottomSheetStack.d.ts.map +1 -1
- package/dist/BottomSheet/bottomSheetStack.js +5 -4
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts +2 -1
- package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
- package/dist/Breadcrumbs/BreadcrumbItem.js +7 -3
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +30 -2
- package/dist/CheckboxList/CheckboxList.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxList.js +7 -1
- package/dist/CheckboxList/CheckboxListContext.d.ts +6 -0
- package/dist/CheckboxList/CheckboxListContext.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +10 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +5 -2
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +13 -27
- package/dist/DateInput/Wheel.d.ts.map +1 -1
- package/dist/DateInput/Wheel.js +22 -41
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +5 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +4 -3
- package/dist/Drawer/Drawer.js +0 -1
- package/dist/Drawer/useDrawerDialogPresence.d.ts.map +1 -1
- package/dist/Drawer/useDrawerDialogPresence.js +5 -1
- package/dist/Field/PanelSearchInput.d.ts +9 -1
- package/dist/Field/PanelSearchInput.d.ts.map +1 -1
- package/dist/Field/PanelSearchInput.js +3 -1
- package/dist/InfoTip/InfoTip.d.ts +2 -2
- package/dist/InfoTip/InfoTip.js +4 -4
- package/dist/Layer/layerAnimations.stylex.d.ts +7 -8
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +25 -20
- package/dist/Layer/usePressPin.d.ts +3 -5
- package/dist/Layer/usePressPin.d.ts.map +1 -1
- package/dist/Layer/usePressPin.js +4 -6
- package/dist/MobileNav/MobileNav.js +0 -1
- package/dist/MultiSelector/hooks.d.ts.map +1 -1
- package/dist/MultiSelector/hooks.js +2 -4
- package/dist/Outline/Outline.d.ts +2 -4
- package/dist/Outline/Outline.d.ts.map +1 -1
- package/dist/Outline/Outline.js +4 -52
- package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
- package/dist/Outline/useOutlineFromMarkdown.js +1 -0
- package/dist/Outline/useScrollSpy.js +3 -3
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +134 -179
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +5 -0
- package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
- package/dist/Resizable/ResizeHandle.js +118 -260
- package/dist/Resizable/resizeGesture.d.ts +91 -0
- package/dist/Resizable/resizeGesture.d.ts.map +1 -0
- package/dist/Resizable/resizeGesture.js +251 -0
- package/dist/SideNav/SideNavItem.d.ts.map +1 -1
- package/dist/SideNav/SideNavItem.js +3 -9
- package/dist/Token/Token.d.ts +2 -2
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +12 -4
- package/dist/Token/TokenNamingContext.d.ts +14 -0
- package/dist/Token/TokenNamingContext.d.ts.map +1 -0
- package/dist/Token/TokenNamingContext.js +23 -0
- package/dist/Tokenizer/Tokenizer.d.ts +46 -59
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +35 -58
- package/dist/Tokenizer/TokenizerBottomSheet.d.ts +25 -28
- package/dist/Tokenizer/TokenizerBottomSheet.d.ts.map +1 -1
- package/dist/Tokenizer/TokenizerBottomSheet.js +157 -54
- package/dist/Tokenizer/TokenizerItemRemovableContext.d.ts.map +1 -1
- package/dist/Tokenizer/TokenizerItemRemovableContext.js +5 -3
- package/dist/Tooltip/Tooltip.d.ts +25 -30
- package/dist/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip/Tooltip.js +24 -5
- package/dist/Tooltip/index.d.ts +1 -1
- package/dist/Tooltip/index.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.d.ts +28 -29
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +20 -8
- package/dist/TopNav/TopNavItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavItem.js +4 -7
- package/dist/TopNav/TopNavMegaMenuItem.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuItem.js +4 -7
- package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
- package/dist/TopNav/TopNavMenu.js +4 -7
- package/dist/astryx.css +5 -5
- package/dist/gestures/GestureHost.d.ts +27 -1
- package/dist/gestures/GestureHost.d.ts.map +1 -1
- package/dist/gestures/GestureHost.js +90 -8
- package/dist/hooks/useHighlightedOptionScroll.d.ts +11 -1
- package/dist/hooks/useHighlightedOptionScroll.d.ts.map +1 -1
- package/dist/hooks/useHighlightedOptionScroll.js +103 -5
- package/dist/hooks/useMenuPress.d.ts.map +1 -1
- package/dist/hooks/useMenuPress.js +4 -2
- package/dist/i18n/generated-english/PowerSearch/PowerSearch.generated.d.ts.map +1 -1
- package/dist/i18n/generated-english/PowerSearch/PowerSearch.generated.js +1 -0
- package/dist/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.d.ts.map +1 -1
- package/dist/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.js +7 -1
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +1 -0
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +1 -0
- package/dist/internal/SheetConfirmation.d.ts +11 -0
- package/dist/internal/SheetConfirmation.d.ts.map +1 -0
- package/dist/internal/SheetConfirmation.js +92 -0
- package/dist/internal/sheetDraft.d.ts +35 -0
- package/dist/internal/sheetDraft.d.ts.map +1 -0
- package/dist/internal/sheetDraft.js +65 -0
- package/dist/internal/touch-sheet.d.ts +21 -0
- package/dist/internal/touch-sheet.d.ts.map +1 -0
- package/dist/internal/touch-sheet.js +19 -0
- package/dist/internal/useDismissSearchOnTouchDrag.d.ts +24 -0
- package/dist/internal/useDismissSearchOnTouchDrag.d.ts.map +1 -0
- package/dist/internal/useDismissSearchOnTouchDrag.js +56 -0
- package/dist/motion/reducedMotion.d.ts +24 -0
- package/dist/motion/reducedMotion.d.ts.map +1 -1
- package/dist/motion/reducedMotion.js +78 -1
- package/dist/utils/clickGuard.d.ts +8 -1
- package/dist/utils/clickGuard.d.ts.map +1 -1
- package/dist/utils/clickGuard.js +24 -1
- package/locales/en.json +4 -0
- package/locales/pseudo.json +3 -0
- package/package.json +9 -9
- package/src/AppShell/useCloseMobileDrawerOnActivate.ts +52 -0
- package/src/BottomSheet/BottomSheet.tsx +95 -10
- package/src/BottomSheet/BottomSheetPanel.tsx +7 -2
- package/src/BottomSheet/bottomSheetStack.ts +8 -4
- package/src/Breadcrumbs/BreadcrumbItem.tsx +13 -3
- package/src/Button/Button.tsx +37 -1
- package/src/CheckboxList/CheckboxList.doc.mjs +4 -2
- package/src/CheckboxList/CheckboxList.tsx +6 -0
- package/src/CheckboxList/CheckboxListContext.tsx +6 -0
- package/src/CheckboxList/CheckboxListItem.tsx +11 -2
- package/src/DateInput/DateInput.tsx +8 -2
- package/src/DateInput/MonthScroller.tsx +18 -22
- package/src/DateInput/Wheel.tsx +30 -32
- package/src/DateTimeInput/DateTimeInput.tsx +8 -2
- package/src/Dialog/Dialog.tsx +19 -4
- package/src/Drawer/Drawer.tsx +1 -1
- package/src/Drawer/useDrawerDialogPresence.ts +5 -1
- package/src/Field/PanelSearchInput.tsx +11 -0
- package/src/InfoTip/InfoTip.doc.mjs +3 -3
- package/src/InfoTip/InfoTip.tsx +5 -5
- package/src/Layer/layerAnimations.stylex.ts +24 -16
- package/src/Layer/usePressPin.ts +5 -11
- package/src/MobileNav/MobileNav.tsx +1 -1
- package/src/MultiSelector/hooks.ts +2 -4
- package/src/Outline/Outline.doc.mjs +177 -51
- package/src/Outline/Outline.tsx +5 -57
- package/src/Outline/useOutlineFromMarkdown.doc.mjs +157 -0
- package/src/Outline/useOutlineFromMarkdown.ts +1 -0
- package/src/Outline/useScrollSpy.ts +3 -3
- package/src/PowerSearch/PowerSearch.doc.mjs +3 -3
- package/src/PowerSearch/PowerSearch.tsx +196 -183
- package/src/RadioList/RadioList.doc.mjs +4 -2
- package/src/RadioList/RadioList.tsx +4 -0
- package/src/Resizable/ResizeHandle.tsx +133 -328
- package/src/Resizable/resizeGesture.ts +368 -0
- package/src/SideNav/SideNavItem.tsx +3 -7
- package/src/Token/Token.tsx +13 -4
- package/src/Token/TokenNamingContext.ts +28 -0
- package/src/Tokenizer/Tokenizer.doc.mjs +16 -0
- package/src/Tokenizer/Tokenizer.tsx +81 -86
- package/src/Tokenizer/TokenizerBottomSheet.tsx +219 -93
- package/src/Tokenizer/TokenizerItemRemovableContext.ts +5 -3
- package/src/Tooltip/Tooltip.doc.mjs +123 -54
- package/src/Tooltip/Tooltip.tsx +36 -39
- package/src/Tooltip/index.ts +0 -1
- package/src/Tooltip/useTooltip.doc.mjs +147 -33
- package/src/Tooltip/useTooltip.tsx +39 -32
- package/src/TopNav/TopNavItem.tsx +6 -5
- package/src/TopNav/TopNavMegaMenuItem.tsx +6 -5
- package/src/TopNav/TopNavMenu.tsx +6 -5
- package/src/gestures/GestureHost.ts +105 -10
- package/src/hooks/useHighlightedOptionScroll.ts +113 -9
- package/src/hooks/useMenuPress.ts +8 -2
- package/src/i18n/generated-english/PowerSearch/PowerSearch.generated.ts +1 -0
- package/src/i18n/generated-english/Tokenizer/TokenizerBottomSheet.generated.ts +7 -1
- package/src/i18n/generated-locales/en.generated.ts +1 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +1 -0
- package/src/internal/SheetConfirmation.tsx +101 -0
- package/src/internal/sheetDraft.ts +80 -0
- package/src/internal/touch-sheet.ts +21 -0
- package/src/internal/useDismissSearchOnTouchDrag.ts +69 -0
- package/src/motion/reducedMotion.ts +79 -1
- package/src/utils/clickGuard.ts +37 -1
- package/dist/internal/tokenizer-presentation.d.ts +0 -21
- package/dist/internal/tokenizer-presentation.d.ts.map +0 -1
- package/dist/internal/tokenizer-presentation.js +0 -21
- 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
|
|
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
|
|
14
|
-
*
|
|
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
|
|
@@ -96,6 +90,7 @@ import {composeEventHandlers, mergeProps} from '../utils';
|
|
|
96
90
|
import {joinAriaIDs} from '../utils/inputAria';
|
|
97
91
|
import {isFocusDetached} from '../utils/focusReturn';
|
|
98
92
|
import {themeProps} from '../utils/themeProps';
|
|
93
|
+
import type {SheetDraftChange} from '../internal/sheetDraft';
|
|
99
94
|
import type {TokenizerBottomSheetProps} from './TokenizerBottomSheet';
|
|
100
95
|
import {useResolvedRequired} from '../hooks/useResolvedRequired';
|
|
101
96
|
import type {FieldStatusPlacement} from '../Field/fieldStatusPlacement';
|
|
@@ -148,36 +143,6 @@ export interface TokenizerHandle {
|
|
|
148
143
|
blur(): void;
|
|
149
144
|
}
|
|
150
145
|
|
|
151
|
-
/**
|
|
152
|
-
* The presentation options the sheet-capable signature admits. Not public:
|
|
153
|
-
* `TokenizerProps` has no `experimental` while the sheet's user experience is
|
|
154
|
-
* being finished; Astryx's own packages reach the sheet through
|
|
155
|
-
* `@astryxdesign/core/internal/tokenizer-presentation`.
|
|
156
|
-
*/
|
|
157
|
-
export interface TokenizerPresentationOptions {
|
|
158
|
-
/**
|
|
159
|
-
* How the field presents its choices.
|
|
160
|
-
* - `'popover'`: the inline combobox with its anchored suggestion menu —
|
|
161
|
-
* the stable behavior.
|
|
162
|
-
* - `'bottom-sheet'`: a trigger showing the selected tokens that opens one
|
|
163
|
-
* tall modal sheet: a search row on top, full-width checkbox rows that
|
|
164
|
-
* keep their place while the sheet is open, a create row with
|
|
165
|
-
* `hasCreate`, and a footer with a confirmed Clear all and Done. Suited
|
|
166
|
-
* to compact touch screens, where the inline combobox competes with the
|
|
167
|
-
* software keyboard.
|
|
168
|
-
* - `'adaptive'`: the bottom sheet on compact coarse-pointer screens,
|
|
169
|
-
* otherwise the popover — the same resolution Selector uses.
|
|
170
|
-
*
|
|
171
|
-
* In the sheet presentation the trigger is the control: `ref`, `id`,
|
|
172
|
-
* `aria-*`, and `data-*` reach it. `renderItem`, `renderToken`,
|
|
173
|
-
* `endContent`, `hasClear`, `hasEntriesOnFocus`, `menuWidth`,
|
|
174
|
-
* `tokenOverflowBehavior`, and `hasAutoFocus` have no surface to act on
|
|
175
|
-
* and warn once in development.
|
|
176
|
-
* @default 'popover'
|
|
177
|
-
*/
|
|
178
|
-
presentation?: 'popover' | 'bottom-sheet' | 'adaptive';
|
|
179
|
-
}
|
|
180
|
-
|
|
181
146
|
export interface TokenizerProps<T extends SearchableItem> extends Omit<
|
|
182
147
|
FieldInputBaseProps<HTMLInputElement>,
|
|
183
148
|
'onChange' | 'onFocus' | 'onBlur' | 'onKeyDown'
|
|
@@ -335,26 +300,58 @@ export interface TokenizerProps<T extends SearchableItem> extends Omit<
|
|
|
335
300
|
ref?: React.Ref<HTMLInputElement>;
|
|
336
301
|
/** Imperative handle ref for focus/blur control. */
|
|
337
302
|
handleRef?: React.Ref<TokenizerHandle>;
|
|
303
|
+
/**
|
|
304
|
+
* Experimental options, outside the stable compatibility promise: anything
|
|
305
|
+
* in this object may change or be removed in a patch release. Omit it for
|
|
306
|
+
* the stable behavior.
|
|
307
|
+
* @experimental
|
|
308
|
+
*/
|
|
309
|
+
experimental?: {
|
|
310
|
+
/**
|
|
311
|
+
* How the field presents its choices.
|
|
312
|
+
* - `'popover'`: the inline combobox with its anchored suggestion menu —
|
|
313
|
+
* the stable behavior.
|
|
314
|
+
* - `'bottom-sheet'`: a trigger showing the selected tokens that opens one
|
|
315
|
+
* tall modal sheet: a search row on top, full-width checkbox rows that
|
|
316
|
+
* keep their place while the sheet is open, a create row with
|
|
317
|
+
* `hasCreate`, and a footer pinned in every state with a confirmed Clear
|
|
318
|
+
* all and Save. The sheet edits a draft: `onChange` fires once, when Save
|
|
319
|
+
* commits it, and a swipe, scrim or Escape close of a changed draft asks
|
|
320
|
+
* before discarding. Suited to compact touch screens, where the inline
|
|
321
|
+
* combobox competes with the software keyboard.
|
|
322
|
+
* - `'adaptive'`: the bottom sheet on compact coarse-pointer screens,
|
|
323
|
+
* otherwise the popover — the same resolution Selector uses.
|
|
324
|
+
*
|
|
325
|
+
* In the sheet presentation the trigger is the control: `ref`, `id`,
|
|
326
|
+
* `aria-*`, and `data-*` reach it. `renderItem`, `renderToken`,
|
|
327
|
+
* `endContent`, `hasClear`, `hasEntriesOnFocus`, `menuWidth`,
|
|
328
|
+
* `tokenOverflowBehavior`, and `hasAutoFocus` have no surface to act on
|
|
329
|
+
* and warn once in development.
|
|
330
|
+
* @experimental
|
|
331
|
+
* @default 'popover'
|
|
332
|
+
*/
|
|
333
|
+
presentation?: 'popover' | 'bottom-sheet' | 'adaptive';
|
|
334
|
+
};
|
|
338
335
|
}
|
|
339
336
|
|
|
340
337
|
/**
|
|
341
|
-
* The props
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
* `
|
|
346
|
-
* `
|
|
347
|
-
* their released shapes — names no presentation.
|
|
338
|
+
* The props the experimental opt-in admits. `experimental` is present, and
|
|
339
|
+
* `ref` also accepts the sheet presentation's trigger button, the control it
|
|
340
|
+
* stands for there. Only the overload below reaches this type. `TokenizerProps`
|
|
341
|
+
* stays the component's declared props type: it is an interface, so
|
|
342
|
+
* `interface X extends TokenizerProps<T>`, `Omit<TokenizerProps<T>, …>` and
|
|
343
|
+
* `ComponentProps<typeof Tokenizer>` keep their released shapes.
|
|
348
344
|
*/
|
|
349
|
-
|
|
345
|
+
type TokenizerExperimentalProps<T extends SearchableItem> = Omit<
|
|
350
346
|
TokenizerProps<T>,
|
|
351
|
-
'ref'
|
|
347
|
+
'ref' | 'experimental'
|
|
352
348
|
> & {
|
|
353
|
-
/**
|
|
354
|
-
experimental
|
|
349
|
+
/** @experimental */
|
|
350
|
+
experimental: NonNullable<TokenizerProps<T>['experimental']>;
|
|
355
351
|
/**
|
|
356
352
|
* Ref forwarded to the control: the combobox input in the popover
|
|
357
353
|
* presentation, the trigger button in the sheet presentation.
|
|
354
|
+
* @experimental
|
|
358
355
|
*/
|
|
359
356
|
ref?: React.Ref<HTMLInputElement | HTMLButtonElement>;
|
|
360
357
|
};
|
|
@@ -724,10 +721,13 @@ function EndLane({
|
|
|
724
721
|
);
|
|
725
722
|
}
|
|
726
723
|
|
|
727
|
-
//
|
|
728
|
-
// Tokenizer>`
|
|
729
|
-
//
|
|
730
|
-
// `
|
|
724
|
+
// Keep this overload first. TypeScript resolves `ComponentProps<typeof
|
|
725
|
+
// Tokenizer>` against the last overload, so that type stays the stable props.
|
|
726
|
+
// A call that passes `experimental` matches this one and may pass the wider
|
|
727
|
+
// `ref`.
|
|
728
|
+
export function Tokenizer<T extends SearchableItem>(
|
|
729
|
+
props: TokenizerExperimentalProps<T>,
|
|
730
|
+
): React.JSX.Element;
|
|
731
731
|
export function Tokenizer<T extends SearchableItem>(
|
|
732
732
|
props: TokenizerProps<T>,
|
|
733
733
|
): React.JSX.Element;
|
|
@@ -781,7 +781,7 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
781
781
|
'aria-describedby': ariaDescribedByProp,
|
|
782
782
|
'aria-labelledby': ariaLabelledByProp,
|
|
783
783
|
...restProps
|
|
784
|
-
}:
|
|
784
|
+
}: TokenizerProps<T> | TokenizerExperimentalProps<T>): React.JSX.Element {
|
|
785
785
|
const isEffectivelyRequired = useResolvedRequired({isRequired, isOptional});
|
|
786
786
|
const {rest, container} = useFieldInputStyling('Tokenizer', restProps, {
|
|
787
787
|
containerXstyle,
|
|
@@ -844,6 +844,17 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
844
844
|
},
|
|
845
845
|
[onChangeQuery],
|
|
846
846
|
);
|
|
847
|
+
// Save's one report. The sheet announced each edit as it happened, so
|
|
848
|
+
// nothing is announced here; a field that is disabled at Save reports
|
|
849
|
+
// nothing.
|
|
850
|
+
const handleSheetCommit = useCallback(
|
|
851
|
+
(items: T[], change: SheetDraftChange<T>) => {
|
|
852
|
+
if (!isDisabled) {
|
|
853
|
+
onChange(items, change);
|
|
854
|
+
}
|
|
855
|
+
},
|
|
856
|
+
[isDisabled, onChange],
|
|
857
|
+
);
|
|
847
858
|
// Set around a focus move the field makes itself — a presentation swap
|
|
848
859
|
// handing focus from one control to the other — so the receiving control
|
|
849
860
|
// does not report it as focus entering from outside.
|
|
@@ -1009,9 +1020,8 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
1009
1020
|
// `endContent`, a clear button, or all three — so its width is measured
|
|
1010
1021
|
// rather than assumed, and the input reserves it.
|
|
1011
1022
|
const [laneRef, laneReserve] = useEndLaneReserve(END_LANE_INSET);
|
|
1012
|
-
// A composing component can lock tokens (PowerSearch's read-only
|
|
1013
|
-
//
|
|
1014
|
-
// does not check it.
|
|
1023
|
+
// A composing component can lock tokens (PowerSearch's read-only filters
|
|
1024
|
+
// and read-only field). No remove path removes a locked token.
|
|
1015
1025
|
const isItemRemovable = use(TokenizerItemRemovableContext);
|
|
1016
1026
|
const canRemoveItem = useCallback(
|
|
1017
1027
|
(item: T) => isItemRemovable?.(item) ?? true,
|
|
@@ -1021,7 +1031,7 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
1021
1031
|
// is the leaf's own business — folding it in here would mean reading the
|
|
1022
1032
|
// busy state during this render, which is exactly the re-render the store
|
|
1023
1033
|
// exists to avoid.
|
|
1024
|
-
const hasClearButton = hasClear &&
|
|
1034
|
+
const hasClearButton = hasClear && !isDisabled && value.some(canRemoveItem);
|
|
1025
1035
|
const hasStaticEndLane = Boolean(endContent || hasClearButton);
|
|
1026
1036
|
const [isFocusedWithin, setIsFocusedWithin] = useState(false);
|
|
1027
1037
|
const isTruncated =
|
|
@@ -1287,19 +1297,22 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
1287
1297
|
[value, onChange, isDisabled, canRemoveItem, announce, t],
|
|
1288
1298
|
);
|
|
1289
1299
|
|
|
1290
|
-
// Handle clearing all items
|
|
1291
1300
|
// A composing component that words its own Clear all (PowerSearch) provides
|
|
1292
1301
|
// its words; otherwise the field's own (component:Tokenizer AR7).
|
|
1293
1302
|
const clearAllMessage =
|
|
1294
1303
|
use(TokenizerClearAllMessageContext) ?? t('@astryx.tokenizer.allRemoved');
|
|
1295
1304
|
const handleClearAll = useCallback(
|
|
1296
1305
|
(options?: {silent?: boolean}) => {
|
|
1297
|
-
|
|
1306
|
+
const removedItems = value.filter(canRemoveItem);
|
|
1307
|
+
if (isDisabled || removedItems.length === 0) {
|
|
1298
1308
|
return;
|
|
1299
1309
|
}
|
|
1300
|
-
//
|
|
1301
|
-
const
|
|
1302
|
-
onChange(
|
|
1310
|
+
// onChange names one item. Clear all names the last one it removes.
|
|
1311
|
+
const lastRemovedItem = removedItems[removedItems.length - 1];
|
|
1312
|
+
onChange(
|
|
1313
|
+
value.filter(item => !canRemoveItem(item)),
|
|
1314
|
+
{item: lastRemovedItem, type: 'remove'},
|
|
1315
|
+
);
|
|
1303
1316
|
// Focus moves to the input, so the emptied selection is announced, in
|
|
1304
1317
|
// the sheet's words (WCAG 4.1.3). The sheet announces its own Clear all.
|
|
1305
1318
|
if (!options?.silent) {
|
|
@@ -1307,7 +1320,7 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
1307
1320
|
}
|
|
1308
1321
|
inputRef.current?.focus();
|
|
1309
1322
|
},
|
|
1310
|
-
[value, onChange, isDisabled, announce, clearAllMessage],
|
|
1323
|
+
[value, onChange, isDisabled, canRemoveItem, announce, clearAllMessage],
|
|
1311
1324
|
);
|
|
1312
1325
|
|
|
1313
1326
|
// Handle backspace on empty input — remove last token
|
|
@@ -1370,7 +1383,7 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
1370
1383
|
key={item.id}
|
|
1371
1384
|
label={item.label}
|
|
1372
1385
|
size={size}
|
|
1373
|
-
onRemove={isDisabled ? undefined : onRemoveItem}
|
|
1386
|
+
onRemove={isDisabled || !canRemoveItem(item) ? undefined : onRemoveItem}
|
|
1374
1387
|
isDisabled={isDisabled}
|
|
1375
1388
|
xstyle={styles.token}
|
|
1376
1389
|
/>
|
|
@@ -1715,15 +1728,13 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
1715
1728
|
label={label}
|
|
1716
1729
|
searchSource={searchSource}
|
|
1717
1730
|
value={value}
|
|
1718
|
-
|
|
1731
|
+
maxEntries={maxEntries}
|
|
1719
1732
|
hasCreate={hasCreate}
|
|
1720
1733
|
maxMenuItems={maxMenuItems ?? 10}
|
|
1721
1734
|
minQueryLength={minQueryLength ?? 1}
|
|
1722
1735
|
debounceMs={debounceMs ?? 150}
|
|
1723
1736
|
emptySearchText={emptySearchText}
|
|
1724
|
-
|
|
1725
|
-
onRemove={handleRemove}
|
|
1726
|
-
onClearAll={() => handleClearAll({silent: true})}
|
|
1737
|
+
onCommit={handleSheetCommit}
|
|
1727
1738
|
onChangeQuery={handleSheetQueryChange}
|
|
1728
1739
|
/>
|
|
1729
1740
|
)}
|
|
@@ -1830,19 +1841,3 @@ export function Tokenizer<T extends SearchableItem>({
|
|
|
1830
1841
|
}
|
|
1831
1842
|
|
|
1832
1843
|
Tokenizer.displayName = 'Tokenizer';
|
|
1833
|
-
|
|
1834
|
-
/**
|
|
1835
|
-
* The same component with the sheet presentation reachable: `experimental`
|
|
1836
|
-
* (`presentation: 'popover' | 'bottom-sheet' | 'adaptive'`) and a `ref` that
|
|
1837
|
-
* also takes the trigger button. Not public — re-exported only by
|
|
1838
|
-
* `@astryxdesign/core/internal/tokenizer-presentation`, the entry reserved
|
|
1839
|
-
* for Astryx's own packages (`architecture:react-component-runtime` INV13),
|
|
1840
|
-
* while the sheet's user experience is being finished (`component:Tokenizer`
|
|
1841
|
-
* DEC-3). The public `Tokenizer` renders the popover presentation for every
|
|
1842
|
-
* field.
|
|
1843
|
-
*/
|
|
1844
|
-
export const TokenizerWithPresentation = Tokenizer as <
|
|
1845
|
-
T extends SearchableItem,
|
|
1846
|
-
>(
|
|
1847
|
-
props: TokenizerWithPresentationProps<T>,
|
|
1848
|
-
) => React.JSX.Element;
|