@box/metadata-taxonomy-picker 2.18.0
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/LICENSE +379 -0
- package/README.md +57 -0
- package/dist/chunks/empty-state.js +22 -0
- package/dist/chunks/error-state.js +41 -0
- package/dist/chunks/load-more-error-row.js +53 -0
- package/dist/chunks/load-more-loading-row.js +17 -0
- package/dist/chunks/loading-state.js +17 -0
- package/dist/chunks/metadata-taxonomy-picker-shell.js +278 -0
- package/dist/chunks/taxonomy-ancestor-breadcrumb.js +115 -0
- package/dist/chunks/taxonomy-items-list.js +114 -0
- package/dist/chunks/taxonomy-level-filter.js +47 -0
- package/dist/chunks/taxonomy-menu-item.js +99 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/lib/components/metadata-taxonomy-picker-shell/index.js +2 -0
- package/dist/esm/lib/components/metadata-taxonomy-picker-shell/messages.js +24 -0
- package/dist/esm/lib/components/metadata-taxonomy-picker-shell/metadata-taxonomy-picker-shell.js +2 -0
- package/dist/esm/lib/components/taxonomy-ancestor-breadcrumb/index.js +2 -0
- package/dist/esm/lib/components/taxonomy-ancestor-breadcrumb/taxonomy-ancestor-breadcrumb.js +2 -0
- package/dist/esm/lib/components/taxonomy-items-list/empty-state/empty-state.js +2 -0
- package/dist/esm/lib/components/taxonomy-items-list/empty-state/index.js +2 -0
- package/dist/esm/lib/components/taxonomy-items-list/error-state/error-state.js +2 -0
- package/dist/esm/lib/components/taxonomy-items-list/error-state/index.js +2 -0
- package/dist/esm/lib/components/taxonomy-items-list/index.js +6 -0
- package/dist/esm/lib/components/taxonomy-items-list/load-more-feedback/index.js +3 -0
- package/dist/esm/lib/components/taxonomy-items-list/load-more-feedback/load-more-error-row.js +2 -0
- package/dist/esm/lib/components/taxonomy-items-list/load-more-feedback/load-more-loading-row.js +2 -0
- package/dist/esm/lib/components/taxonomy-items-list/load-more-feedback/messages.js +20 -0
- package/dist/esm/lib/components/taxonomy-items-list/loading-state/index.js +2 -0
- package/dist/esm/lib/components/taxonomy-items-list/loading-state/loading-state.js +2 -0
- package/dist/esm/lib/components/taxonomy-items-list/messages.js +36 -0
- package/dist/esm/lib/components/taxonomy-items-list/taxonomy-items-list.js +2 -0
- package/dist/esm/lib/components/taxonomy-level-filter/index.js +2 -0
- package/dist/esm/lib/components/taxonomy-level-filter/messages.js +6 -0
- package/dist/esm/lib/components/taxonomy-level-filter/taxonomy-level-filter.js +2 -0
- package/dist/esm/lib/components/taxonomy-menu-item/index.js +2 -0
- package/dist/esm/lib/components/taxonomy-menu-item/messages.js +6 -0
- package/dist/esm/lib/components/taxonomy-menu-item/taxonomy-menu-item.js +2 -0
- package/dist/esm/lib/components/taxonomy-menu-item/use-taxonomy-menu-item-keyboard.js +100 -0
- package/dist/esm/lib/constants.js +2 -0
- package/dist/esm/lib/hooks/messages.js +16 -0
- package/dist/esm/lib/hooks/use-taxonomy-picker-controller.js +261 -0
- package/dist/esm/lib/metadata-taxonomy-picker.js +10 -0
- package/dist/esm/lib/state/reducer.js +147 -0
- package/dist/esm/lib/state/transitions.js +22 -0
- package/dist/i18n/bn-IN.js +24 -0
- package/dist/i18n/bn-IN.properties +44 -0
- package/dist/i18n/da-DK.js +24 -0
- package/dist/i18n/da-DK.properties +44 -0
- package/dist/i18n/de-DE.js +24 -0
- package/dist/i18n/de-DE.properties +44 -0
- package/dist/i18n/en-AU.js +24 -0
- package/dist/i18n/en-AU.properties +44 -0
- package/dist/i18n/en-CA.js +24 -0
- package/dist/i18n/en-CA.properties +44 -0
- package/dist/i18n/en-GB.js +24 -0
- package/dist/i18n/en-GB.properties +44 -0
- package/dist/i18n/en-US.js +24 -0
- package/dist/i18n/en-US.properties +44 -0
- package/dist/i18n/en-x-pseudo.js +24 -0
- package/dist/i18n/en-x-pseudo.properties +44 -0
- package/dist/i18n/es-419.js +24 -0
- package/dist/i18n/es-419.properties +44 -0
- package/dist/i18n/es-ES.js +24 -0
- package/dist/i18n/es-ES.properties +44 -0
- package/dist/i18n/fi-FI.js +24 -0
- package/dist/i18n/fi-FI.properties +44 -0
- package/dist/i18n/fr-CA.js +24 -0
- package/dist/i18n/fr-CA.properties +44 -0
- package/dist/i18n/fr-FR.js +24 -0
- package/dist/i18n/fr-FR.properties +44 -0
- package/dist/i18n/hi-IN.js +24 -0
- package/dist/i18n/hi-IN.properties +44 -0
- package/dist/i18n/it-IT.js +24 -0
- package/dist/i18n/it-IT.properties +44 -0
- package/dist/i18n/ja-JP.js +24 -0
- package/dist/i18n/ja-JP.properties +44 -0
- package/dist/i18n/json/src/lib/components/metadata-taxonomy-picker-shell/messages.json +1 -0
- package/dist/i18n/json/src/lib/components/taxonomy-items-list/load-more-feedback/messages.json +1 -0
- package/dist/i18n/json/src/lib/components/taxonomy-items-list/messages.json +1 -0
- package/dist/i18n/json/src/lib/components/taxonomy-level-filter/messages.json +1 -0
- package/dist/i18n/json/src/lib/components/taxonomy-menu-item/messages.json +1 -0
- package/dist/i18n/json/src/lib/hooks/messages.json +1 -0
- package/dist/i18n/ko-KR.js +24 -0
- package/dist/i18n/ko-KR.properties +44 -0
- package/dist/i18n/nb-NO.js +24 -0
- package/dist/i18n/nb-NO.properties +44 -0
- package/dist/i18n/nl-NL.js +24 -0
- package/dist/i18n/nl-NL.properties +44 -0
- package/dist/i18n/pl-PL.js +24 -0
- package/dist/i18n/pl-PL.properties +44 -0
- package/dist/i18n/pt-BR.js +24 -0
- package/dist/i18n/pt-BR.properties +44 -0
- package/dist/i18n/ru-RU.js +24 -0
- package/dist/i18n/ru-RU.properties +44 -0
- package/dist/i18n/sv-SE.js +24 -0
- package/dist/i18n/sv-SE.properties +44 -0
- package/dist/i18n/tr-TR.js +24 -0
- package/dist/i18n/tr-TR.properties +44 -0
- package/dist/i18n/zh-CN.js +24 -0
- package/dist/i18n/zh-CN.properties +44 -0
- package/dist/i18n/zh-TW.js +24 -0
- package/dist/i18n/zh-TW.properties +44 -0
- package/dist/styles/empty-state.css +1 -0
- package/dist/styles/error-state.css +1 -0
- package/dist/styles/load-more-error-row.css +1 -0
- package/dist/styles/load-more-loading-row.css +1 -0
- package/dist/styles/loading-state.css +1 -0
- package/dist/styles/metadata-taxonomy-picker-shell.css +1 -0
- package/dist/styles/taxonomy-ancestor-breadcrumb.css +1 -0
- package/dist/styles/taxonomy-items-list.css +1 -0
- package/dist/styles/taxonomy-level-filter.css +1 -0
- package/dist/styles/taxonomy-menu-item.css +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/lib/components/metadata-taxonomy-picker-shell/index.d.ts +1 -0
- package/dist/types/lib/components/metadata-taxonomy-picker-shell/messages.d.ts +27 -0
- package/dist/types/lib/components/metadata-taxonomy-picker-shell/metadata-taxonomy-picker-shell.d.ts +2 -0
- package/dist/types/lib/components/taxonomy-ancestor-breadcrumb/index.d.ts +1 -0
- package/dist/types/lib/components/taxonomy-ancestor-breadcrumb/taxonomy-ancestor-breadcrumb.d.ts +16 -0
- package/dist/types/lib/components/taxonomy-items-list/empty-state/empty-state.d.ts +10 -0
- package/dist/types/lib/components/taxonomy-items-list/empty-state/index.d.ts +1 -0
- package/dist/types/lib/components/taxonomy-items-list/error-state/error-state.d.ts +9 -0
- package/dist/types/lib/components/taxonomy-items-list/error-state/index.d.ts +1 -0
- package/dist/types/lib/components/taxonomy-items-list/index.d.ts +5 -0
- package/dist/types/lib/components/taxonomy-items-list/load-more-feedback/index.d.ts +2 -0
- package/dist/types/lib/components/taxonomy-items-list/load-more-feedback/load-more-error-row.d.ts +10 -0
- package/dist/types/lib/components/taxonomy-items-list/load-more-feedback/load-more-loading-row.d.ts +7 -0
- package/dist/types/lib/components/taxonomy-items-list/load-more-feedback/messages.d.ts +22 -0
- package/dist/types/lib/components/taxonomy-items-list/loading-state/index.d.ts +1 -0
- package/dist/types/lib/components/taxonomy-items-list/loading-state/loading-state.d.ts +6 -0
- package/dist/types/lib/components/taxonomy-items-list/messages.d.ts +42 -0
- package/dist/types/lib/components/taxonomy-items-list/taxonomy-items-list.d.ts +82 -0
- package/dist/types/lib/components/taxonomy-level-filter/index.d.ts +1 -0
- package/dist/types/lib/components/taxonomy-level-filter/messages.d.ts +7 -0
- package/dist/types/lib/components/taxonomy-level-filter/taxonomy-level-filter.d.ts +11 -0
- package/dist/types/lib/components/taxonomy-menu-item/index.d.ts +1 -0
- package/dist/types/lib/components/taxonomy-menu-item/messages.d.ts +7 -0
- package/dist/types/lib/components/taxonomy-menu-item/taxonomy-menu-item.d.ts +20 -0
- package/dist/types/lib/components/taxonomy-menu-item/use-taxonomy-menu-item-keyboard.d.ts +47 -0
- package/dist/types/lib/constants.d.ts +49 -0
- package/dist/types/lib/hooks/messages.d.ts +17 -0
- package/dist/types/lib/hooks/use-taxonomy-picker-controller.d.ts +22 -0
- package/dist/types/lib/metadata-taxonomy-picker.d.ts +8 -0
- package/dist/types/lib/state/reducer.d.ts +180 -0
- package/dist/types/lib/state/transitions.d.ts +4 -0
- package/dist/types/lib/stories/metadata-taxonomy-picker.stories.d.ts +136 -0
- package/dist/types/lib/stories/shared/build-taxonomy-items.d.ts +10 -0
- package/dist/types/lib/stories/shared/create-mock-items-service.d.ts +35 -0
- package/dist/types/lib/stories/shared/generate-deep-nodes.d.ts +39 -0
- package/dist/types/lib/stories/shared/generate-hierarchical-nodes.d.ts +3 -0
- package/dist/types/lib/stories/shared/generate-nodes.d.ts +2 -0
- package/dist/types/lib/stories/shared/generate-search-results.d.ts +10 -0
- package/dist/types/lib/stories/shared/story-container.d.ts +5 -0
- package/dist/types/lib/stories/shared/taxonomy-items-list-fixtures.d.ts +7 -0
- package/dist/types/lib/stories/taxonomy-ancestor-breadcrumb.stories.d.ts +28 -0
- package/dist/types/lib/stories/taxonomy-items-list.stories.d.ts +77 -0
- package/dist/types/lib/stories/taxonomy-menu-item.stories.d.ts +67 -0
- package/dist/types/lib/stories/tests/breadcrumb-navigation.interaction-tests.stories.d.ts +78 -0
- package/dist/types/lib/stories/tests/error-handling.interaction-tests.stories.d.ts +50 -0
- package/dist/types/lib/stories/tests/interaction-tests.stories.d.ts +47 -0
- package/dist/types/lib/stories/tests/level-filter-interaction-tests.stories.d.ts +99 -0
- package/dist/types/lib/stories/tests/level-transitions.interaction-tests.stories.d.ts +60 -0
- package/dist/types/lib/stories/tests/pagination.interaction-tests.stories.d.ts +90 -0
- package/dist/types/lib/stories/tests/portal-and-ref.interaction-tests.stories.d.ts +39 -0
- package/dist/types/lib/stories/tests/search-interaction-tests.stories.d.ts +124 -0
- package/dist/types/lib/stories/tests/shell-selection.interaction-tests.stories.d.ts +56 -0
- package/dist/types/lib/stories/tests/single-level-mode.interaction-tests.stories.d.ts +50 -0
- package/dist/types/lib/stories/tests/taxonomy-menu-item.interaction-tests.stories.d.ts +70 -0
- package/dist/types/lib/stories/tests/visual-regression-tests.stories.d.ts +38 -0
- package/dist/types/lib/types.d.ts +105 -0
- package/package.json +51 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { TaxonomyMenuItemProps } from '../taxonomy-menu-item';
|
|
2
|
+
export interface TaxonomyItemsListProps {
|
|
3
|
+
items: TaxonomyMenuItemProps[];
|
|
4
|
+
multiSelect: boolean;
|
|
5
|
+
selectedValue: string;
|
|
6
|
+
estimatedRowHeight?: number;
|
|
7
|
+
/**
|
|
8
|
+
* When `true`, each row is measured at runtime via `ResizeObserver` +
|
|
9
|
+
* `getBoundingClientRect()` so the virtualizer can position rows of
|
|
10
|
+
* varying height (e.g. search/ancestor rows whose breadcrumb may wrap).
|
|
11
|
+
*
|
|
12
|
+
* Browse rows are CSS-locked to a fixed height, so leaving this `false`
|
|
13
|
+
* (the default) avoids per-row layout reads during scroll.
|
|
14
|
+
*/
|
|
15
|
+
hasVariableRowHeight?: boolean;
|
|
16
|
+
/** When `true`, the empty state renders "No results found" instead of "No subnodes". */
|
|
17
|
+
isSearchMode?: boolean;
|
|
18
|
+
isFetching: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Initial-load error for the list. When set, the entire list area is replaced
|
|
21
|
+
* by a full-area `ErrorState` with a retry button. Mutually exclusive with
|
|
22
|
+
* `items` — the controller clears items when this is set.
|
|
23
|
+
*/
|
|
24
|
+
error: string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Inline "load more" error for the active list. When set, an inline error row
|
|
27
|
+
* is rendered at the bottom of the existing items (already-loaded items remain
|
|
28
|
+
* visible) and the scroll-near-bottom auto-trigger is suppressed until the
|
|
29
|
+
* user retries.
|
|
30
|
+
*/
|
|
31
|
+
loadMoreError?: string | null;
|
|
32
|
+
/**
|
|
33
|
+
* Called when the user activates the retry control on either error surface
|
|
34
|
+
* (full-area initial load error or the inline load-more error row). The
|
|
35
|
+
* controller decides which operation to re-run via `lastFailedOp`.
|
|
36
|
+
*/
|
|
37
|
+
onRetry: () => void;
|
|
38
|
+
/**
|
|
39
|
+
* Applied as the `id` of the scroll container (`role="listbox"`), satisfying
|
|
40
|
+
* the `aria-controls` reference set on the combobox input in the shell.
|
|
41
|
+
* Must match the `listboxId` threaded down from `MetadataTaxonomyPickerShell`.
|
|
42
|
+
*/
|
|
43
|
+
listboxId?: string;
|
|
44
|
+
/** Called when the user Shift+Tabs from the first row to return focus to the main input. */
|
|
45
|
+
onFocusExit?: () => void;
|
|
46
|
+
/**
|
|
47
|
+
* `true` when another page of items is available to be loaded.
|
|
48
|
+
* Required (alongside no in-flight fetch) for the scroll-near-bottom
|
|
49
|
+
* handler to fire `onLoadMore`.
|
|
50
|
+
*/
|
|
51
|
+
hasMore?: boolean;
|
|
52
|
+
/** `true` while a "load more" page request is in flight (drives the inline ghost rows). */
|
|
53
|
+
isFetchingMore?: boolean;
|
|
54
|
+
/** Called when the user has scrolled within `LOAD_MORE_ROOT_MARGIN_PX` of the bottom of the list. */
|
|
55
|
+
onLoadMore?: () => void;
|
|
56
|
+
}
|
|
57
|
+
/** Imperative handle exposed via `ref` for scroll position save/restore. */
|
|
58
|
+
export interface TaxonomyItemsListRef {
|
|
59
|
+
getScrollTop: () => number;
|
|
60
|
+
scrollTo: (top: number) => void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Virtualized list of taxonomy rows.
|
|
64
|
+
*
|
|
65
|
+
* Renders only the visible window of `TaxonomyMenuItem`s plus an overscan
|
|
66
|
+
* buffer, so very large datasets stay smooth. The list owns the scroll
|
|
67
|
+
* container and renders one of three non-list states (loading, error, empty)
|
|
68
|
+
* when applicable; otherwise it renders the virtualized rows.
|
|
69
|
+
*
|
|
70
|
+
* The scroll container carries `role="listbox"` (+ `id={listboxId}`) to
|
|
71
|
+
* satisfy the ARIA combobox contract — the shell's `aria-controls` points
|
|
72
|
+
* here. In single-select mode the `Radio.Group` lives inside the listbox
|
|
73
|
+
* (not around it) so the hierarchy is `listbox > radiogroup > options`.
|
|
74
|
+
*
|
|
75
|
+
* Browse rows are CSS-locked to a fixed height; search/ancestor rows can
|
|
76
|
+
* vary, in which case `hasVariableRowHeight` opts into per-row measurement.
|
|
77
|
+
*
|
|
78
|
+
* The component exposes a `TaxonomyItemsListRef` imperative handle for
|
|
79
|
+
* saving and restoring the scroll position when toggling between browse
|
|
80
|
+
* and search modes.
|
|
81
|
+
*/
|
|
82
|
+
export declare const TaxonomyItemsList: import('react').ForwardRefExoticComponent<TaxonomyItemsListProps & import('react').RefAttributes<TaxonomyItemsListRef>>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { TaxonomyLevelFilter, type TaxonomyLevelFilterProps } from './taxonomy-level-filter';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { TaxonomyLevel } from '../../types';
|
|
2
|
+
export interface TaxonomyLevelFilterProps {
|
|
3
|
+
availableLevels: readonly TaxonomyLevel[];
|
|
4
|
+
levelFilter: number | null;
|
|
5
|
+
onLevelFilterChange: (level: number | null) => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Dropdown above the search results that scopes search to a single taxonomy
|
|
9
|
+
* level. "All levels" clears the filter.
|
|
10
|
+
*/
|
|
11
|
+
export declare function TaxonomyLevelFilter({ availableLevels, levelFilter, onLevelFilterChange }: TaxonomyLevelFilterProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { TaxonomyMenuItem, type TaxonomyMenuItemProps } from './taxonomy-menu-item';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TaxonomyAncestor } from '../../types';
|
|
2
|
+
export interface TaxonomyMenuItemProps {
|
|
3
|
+
id: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
isSearchMode?: boolean;
|
|
6
|
+
selectable: boolean;
|
|
7
|
+
multiSelect: boolean;
|
|
8
|
+
isSelected: boolean;
|
|
9
|
+
showDrillDown: boolean;
|
|
10
|
+
ancestors?: TaxonomyAncestor[];
|
|
11
|
+
onSelect: (id: string, closeAfterSelect?: boolean) => void;
|
|
12
|
+
onDrillDown?: (id: string) => void;
|
|
13
|
+
/** Called when Shift+Tab is pressed while this is the first row, to return focus to the main input. */
|
|
14
|
+
onFocusExit?: () => void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Row component for browse and search lists.
|
|
18
|
+
* Keyboard model is documented in useTaxonomyMenuItemKeyboard.
|
|
19
|
+
*/
|
|
20
|
+
export declare const TaxonomyMenuItem: import('react').NamedExoticComponent<TaxonomyMenuItemProps>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { KeyboardEvent } from 'react';
|
|
2
|
+
export interface UseTaxonomyMenuItemKeyboardOptions {
|
|
3
|
+
id: string;
|
|
4
|
+
multiSelect: boolean;
|
|
5
|
+
onSelect: (id: string, closeAfterSelect?: boolean) => void;
|
|
6
|
+
/** Called when focus exits the top of the list (e.g. Shift+Tab on the first row). */
|
|
7
|
+
onFocusExit?: () => void;
|
|
8
|
+
rowRef: React.RefObject<HTMLButtonElement>;
|
|
9
|
+
selectionControlRef: React.RefObject<HTMLButtonElement>;
|
|
10
|
+
drillDownRef: React.RefObject<HTMLButtonElement>;
|
|
11
|
+
}
|
|
12
|
+
export interface UseTaxonomyMenuItemKeyboardResult {
|
|
13
|
+
/** Redirect focus to the row when the radio receives it without our code asking. */
|
|
14
|
+
handleSelectionControlFocus: () => void;
|
|
15
|
+
/** Bubble-phase handler on the CompositeItem row div. */
|
|
16
|
+
handleRowKeyDown: (event: KeyboardEvent<HTMLButtonElement>) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Capture-phase handler on the CompositeItem row div. Intercepts all arrow
|
|
19
|
+
* keys originating from the selection control before Radix's RadioGroup
|
|
20
|
+
* navigation (merged via Slot/asChild into the radio button's own onKeyDown)
|
|
21
|
+
* can process them.
|
|
22
|
+
*/
|
|
23
|
+
handleRowKeyDownCapture: (event: KeyboardEvent<HTMLButtonElement>) => void;
|
|
24
|
+
/** Bubble-phase handler on the checkbox / radio button. */
|
|
25
|
+
handleSelectionControlKeyDown: (event: KeyboardEvent<HTMLButtonElement>) => void;
|
|
26
|
+
/** Bubble-phase handler on the drill-down IconButton. */
|
|
27
|
+
handleDrillDownKeyDown: (event: KeyboardEvent<HTMLButtonElement>) => void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Encapsulates all keyboard (and radio-focus-redirect) logic for a single
|
|
31
|
+
* TaxonomyMenuItem row.
|
|
32
|
+
*
|
|
33
|
+
* Keyboard model (requires an ancestor CompositeProvider + Composite):
|
|
34
|
+
* - Tab / Shift+Tab anywhere in the row → next / previous row.
|
|
35
|
+
* At a list boundary Tab exits the popup naturally.
|
|
36
|
+
* - ArrowUp / ArrowDown anywhere in the row → next / previous row.
|
|
37
|
+
* - ArrowLeft from row → selection control.
|
|
38
|
+
* - ArrowRight from row → drill-down.
|
|
39
|
+
* - ArrowLeft from selection control → row.
|
|
40
|
+
* - ArrowRight from selection control → drill-down.
|
|
41
|
+
* - ArrowLeft from drill-down → selection control (or row if none).
|
|
42
|
+
* - Enter on radio → select (Radix blocks the native Enter event on buttons).
|
|
43
|
+
* - Enter / Space on drill-down → drill-down action.
|
|
44
|
+
* - Arrow keys from the selection control are intercepted in the capture phase
|
|
45
|
+
* so Radix's RovingFocusGroup never navigates between radios.
|
|
46
|
+
*/
|
|
47
|
+
export declare function useTaxonomyMenuItemKeyboard({ id, multiSelect, onSelect, onFocusExit, rowRef, selectionControlRef, drillDownRef, }: UseTaxonomyMenuItemKeyboardOptions): UseTaxonomyMenuItemKeyboardResult;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Single-line browse rows — matches `--bp-size-090` (36px) in taxonomy-menu-item styles. */
|
|
2
|
+
export declare const ESTIMATED_BROWSE_ROW_HEIGHT = 36;
|
|
3
|
+
/**
|
|
4
|
+
* Two-line search/ancestor rows — display name + breadcrumb line.
|
|
5
|
+
* ~20px body-default-bold + ~16px xsmall breadcrumb + 2 × 4px vertical padding ≈ 44px.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ESTIMATED_SEARCH_ROW_HEIGHT = 44;
|
|
8
|
+
/**
|
|
9
|
+
* How many off-screen rows the virtualizer renders above and below the
|
|
10
|
+
* viewport. Higher values reduce the chance of fast scroll outrunning
|
|
11
|
+
* the renderer at the cost of slightly more DOM work; rows are memoized,
|
|
12
|
+
* so the trade-off favors a generous cushion.
|
|
13
|
+
*/
|
|
14
|
+
export declare const OVERSCAN_COUNT = 20;
|
|
15
|
+
/** Skeleton rows shown during initial load. Sized to fill the stable 21rem popover area. */
|
|
16
|
+
export declare const SKELETON_ROW_COUNT = 9;
|
|
17
|
+
/** Height (px) of each skeleton row Ghost placeholder. */
|
|
18
|
+
export declare const SKELETON_ROW_HEIGHT = 16;
|
|
19
|
+
/** Number of ghost rows shown at the bottom of the list while a "load more" page is in flight. */
|
|
20
|
+
export declare const LOAD_MORE_GHOST_ROW_COUNT = 3;
|
|
21
|
+
/** Height (px) of each ghost row shown during "load more". */
|
|
22
|
+
export declare const LOAD_MORE_GHOST_ROW_HEIGHT = 16;
|
|
23
|
+
/** Total height (px) of the inline "load more" ghost block: padding(12×2) + 3×16 + 2×gap(20) = 112. */
|
|
24
|
+
export declare const LOAD_MORE_GHOST_BLOCK_HEIGHT = 112;
|
|
25
|
+
/** Distance (px) from the bottom of the list at which the next page is pre-fetched. */
|
|
26
|
+
export declare const LOAD_MORE_ROOT_MARGIN_PX = 200;
|
|
27
|
+
/** Minimum time the load-more loading slot stays visible before yielding to the inline error row. */
|
|
28
|
+
export declare const LOAD_MORE_ERROR_MIN_VISIBLE_MS = 400;
|
|
29
|
+
/** Separator string rendered between breadcrumb segments. */
|
|
30
|
+
export declare const BREADCRUMB_SEPARATOR = " / ";
|
|
31
|
+
/** Maximum number of lines the breadcrumb trail may occupy before collapsing to `first / icon / last`. */
|
|
32
|
+
export declare const BREADCRUMB_MAX_LINES = 2;
|
|
33
|
+
/**
|
|
34
|
+
* Sub-pixel tolerance for breadcrumb overflow detection.
|
|
35
|
+
* Browsers can report ~1px diffs even when content visually fits.
|
|
36
|
+
*/
|
|
37
|
+
export declare const BREADCRUMB_OVERFLOW_THRESHOLD_PX = 2;
|
|
38
|
+
/** Unicode ellipsis character used when trimming overflowed breadcrumb segments. */
|
|
39
|
+
export declare const BREADCRUMB_ELLIPSIS_CHAR = "\u2026";
|
|
40
|
+
/** Default page size for taxonomy node fetch requests. */
|
|
41
|
+
export declare const DEFAULT_PAGE_LIMIT = 100;
|
|
42
|
+
/** Stale-after threshold for cached levels; older entries are evicted on read. */
|
|
43
|
+
export declare const CACHE_TTL_MS: number;
|
|
44
|
+
/** Cache key used for the root level (parentId === null). */
|
|
45
|
+
export declare const ROOT_CACHE_KEY = "__root__";
|
|
46
|
+
/** Sentinel `Crumb.id` for the synthetic root entry; mapped back to `null` parentId by the shell. */
|
|
47
|
+
export declare const BREADCRUMB_ROOT_ID = "__breadcrumb_root__";
|
|
48
|
+
/** Debounce time for search input changes. */
|
|
49
|
+
export declare const SEARCH_DEBOUNCE_MS = 500;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const messages: {
|
|
2
|
+
initialLoadErrorFallback: {
|
|
3
|
+
defaultMessage: string;
|
|
4
|
+
description: string;
|
|
5
|
+
id: string;
|
|
6
|
+
};
|
|
7
|
+
searchErrorFallback: {
|
|
8
|
+
defaultMessage: string;
|
|
9
|
+
description: string;
|
|
10
|
+
id: string;
|
|
11
|
+
};
|
|
12
|
+
loadMoreErrorFallback: {
|
|
13
|
+
defaultMessage: string;
|
|
14
|
+
description: string;
|
|
15
|
+
id: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { PickerState } from '../state/reducer';
|
|
2
|
+
import { DrillDownTarget, TaxonomyItemsService, TaxonomyLevel, TaxonomyPickerEventService } from '../types';
|
|
3
|
+
/** Forces a fixed search scope, bypassing the level-filter and drill-down scoping. */
|
|
4
|
+
export interface SearchScopeOverride {
|
|
5
|
+
parentId: string | null;
|
|
6
|
+
levelFilter: number | null;
|
|
7
|
+
}
|
|
8
|
+
export declare function useTaxonomyPickerController(itemsService: TaxonomyItemsService, levels?: readonly TaxonomyLevel[], eventService?: TaxonomyPickerEventService): {
|
|
9
|
+
state: PickerState;
|
|
10
|
+
isOpen: boolean;
|
|
11
|
+
handleOpenChange: (open: boolean) => void;
|
|
12
|
+
handleInputValueChange: (inputValue: string) => void;
|
|
13
|
+
actions: {
|
|
14
|
+
drillDown: (target: DrillDownTarget) => void;
|
|
15
|
+
navigateBack: (targetParentId: string | null) => void;
|
|
16
|
+
loadMore: () => Promise<void>;
|
|
17
|
+
searchLoadMore: () => Promise<void>;
|
|
18
|
+
setLevelFilter: (level: number | null) => void;
|
|
19
|
+
retry: () => void;
|
|
20
|
+
setSearchScopeOverride: (next: SearchScopeOverride | undefined) => void;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MetadataTaxonomyPickerProps } from './types';
|
|
2
|
+
export type { MetadataTaxonomyPickerProps } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Forwards the ref to the picker's trigger input so consumers can manage
|
|
5
|
+
* focus or other imperative interactions on the input element directly.
|
|
6
|
+
*/
|
|
7
|
+
export declare const MetadataTaxonomyPicker: import('react').ForwardRefExoticComponent<MetadataTaxonomyPickerProps & import('react').RefAttributes<HTMLInputElement>>;
|
|
8
|
+
export default MetadataTaxonomyPicker;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { BreadcrumbEntry, TaxonomyLevel, TaxonomyNode, TaxonomySearchResult } from '../types';
|
|
2
|
+
export declare enum FailedOp {
|
|
3
|
+
Browse = "browse",
|
|
4
|
+
BrowseMore = "browse-more",
|
|
5
|
+
Search = "search",
|
|
6
|
+
SearchMore = "search-more"
|
|
7
|
+
}
|
|
8
|
+
export declare enum PickerActionType {
|
|
9
|
+
/** Initial fetch for the current level started — shows the skeleton. */
|
|
10
|
+
FetchStart = "FETCH_START",
|
|
11
|
+
/** Initial fetch succeeded; carries `forParentId` so stale responses can be dropped. */
|
|
12
|
+
FetchSuccess = "FETCH_SUCCESS",
|
|
13
|
+
/** Initial fetch failed; sets `lastFailedOp = 'browse'` so retry knows what to re-run. */
|
|
14
|
+
FetchError = "FETCH_ERROR",
|
|
15
|
+
/** User navigated deeper into a node — atomically transitions to a new level. */
|
|
16
|
+
DrillDown = "DRILL_DOWN",
|
|
17
|
+
/** User navigated back to a level whose snapshot is still cached — no skeleton. */
|
|
18
|
+
NavigateBack = "NAVIGATE_BACK",
|
|
19
|
+
/** User navigated back to a level whose cache was evicted — re-fetch with skeleton. */
|
|
20
|
+
NavigateBackRefetch = "NAVIGATE_BACK_REFETCH",
|
|
21
|
+
/** Hard reset to `initialState` (e.g. popover closed). */
|
|
22
|
+
Reset = "RESET",
|
|
23
|
+
/** "Load more" page fetch for the current browse list started. */
|
|
24
|
+
LoadMoreStart = "LOAD_MORE_START",
|
|
25
|
+
/** "Load more" page appended to `items`; advances `itemsNextMarker`. */
|
|
26
|
+
LoadMoreSuccess = "LOAD_MORE_SUCCESS",
|
|
27
|
+
/**
|
|
28
|
+
* "Load more" page failed; sets `loadMoreError` so the inline error row is shown,
|
|
29
|
+
* and `lastFailedOp = 'browse-more'` so retry knows what to re-run from the
|
|
30
|
+
* current marker.
|
|
31
|
+
*/
|
|
32
|
+
LoadMoreError = "LOAD_MORE_ERROR",
|
|
33
|
+
/** Search input changed — updates the raw `searchInputValue` on every keystroke. */
|
|
34
|
+
SearchInputChange = "SEARCH_INPUT_CHANGE",
|
|
35
|
+
/** Debounced search committed — promotes `searchInputValue` to `searchQuery` and fires the request. */
|
|
36
|
+
SearchFetchStart = "SEARCH_FETCH_START",
|
|
37
|
+
/** Search results arrived; carries `forQuery` so stale responses can be dropped. */
|
|
38
|
+
SearchFetchSuccess = "SEARCH_FETCH_SUCCESS",
|
|
39
|
+
/** Search request failed; sets `lastFailedOp = 'search'`. */
|
|
40
|
+
SearchFetchError = "SEARCH_FETCH_ERROR",
|
|
41
|
+
/** Search input cleared — wipes the search slice and returns to the browse view. */
|
|
42
|
+
SearchClear = "SEARCH_CLEAR",
|
|
43
|
+
/** "Load more" page fetch for the current search results started. */
|
|
44
|
+
SearchLoadMoreStart = "SEARCH_LOAD_MORE_START",
|
|
45
|
+
/** "Load more" page appended to `searchResults`; advances `searchNextMarker`. */
|
|
46
|
+
SearchLoadMoreSuccess = "SEARCH_LOAD_MORE_SUCCESS",
|
|
47
|
+
/**
|
|
48
|
+
* "Load more" page for search failed; sets `searchLoadMoreError` so the inline
|
|
49
|
+
* error row is shown and `lastFailedOp = 'search-more'` so retry re-runs the
|
|
50
|
+
* load-more from the current marker against the active query.
|
|
51
|
+
*/
|
|
52
|
+
SearchLoadMoreError = "SEARCH_LOAD_MORE_ERROR",
|
|
53
|
+
/** User picked a level filter for the global (root-level) search. */
|
|
54
|
+
SetLevelFilter = "SET_LEVEL_FILTER"
|
|
55
|
+
}
|
|
56
|
+
export type PickerAction = {
|
|
57
|
+
type: PickerActionType.FetchStart;
|
|
58
|
+
} | {
|
|
59
|
+
type: PickerActionType.FetchSuccess;
|
|
60
|
+
entries: TaxonomyNode[];
|
|
61
|
+
nextMarker: string | undefined;
|
|
62
|
+
forParentId: string | null;
|
|
63
|
+
} | {
|
|
64
|
+
type: PickerActionType.FetchError;
|
|
65
|
+
error: string;
|
|
66
|
+
forParentId: string | null;
|
|
67
|
+
} | {
|
|
68
|
+
type: PickerActionType.DrillDown;
|
|
69
|
+
targetParentId: string;
|
|
70
|
+
levelStack: BreadcrumbEntry[];
|
|
71
|
+
} | {
|
|
72
|
+
type: PickerActionType.NavigateBack;
|
|
73
|
+
targetParentId: string | null;
|
|
74
|
+
levelStack: BreadcrumbEntry[];
|
|
75
|
+
cached: {
|
|
76
|
+
items: TaxonomyNode[];
|
|
77
|
+
nextMarker: string | undefined;
|
|
78
|
+
};
|
|
79
|
+
} | {
|
|
80
|
+
type: PickerActionType.NavigateBackRefetch;
|
|
81
|
+
targetParentId: string | null;
|
|
82
|
+
levelStack: BreadcrumbEntry[];
|
|
83
|
+
} | {
|
|
84
|
+
type: PickerActionType.Reset;
|
|
85
|
+
} | {
|
|
86
|
+
type: PickerActionType.LoadMoreStart;
|
|
87
|
+
} | {
|
|
88
|
+
type: PickerActionType.LoadMoreSuccess;
|
|
89
|
+
entries: TaxonomyNode[];
|
|
90
|
+
nextMarker: string | undefined;
|
|
91
|
+
} | {
|
|
92
|
+
type: PickerActionType.LoadMoreError;
|
|
93
|
+
error: string;
|
|
94
|
+
} | {
|
|
95
|
+
type: PickerActionType.SearchInputChange;
|
|
96
|
+
value: string;
|
|
97
|
+
availableLevels: readonly TaxonomyLevel[];
|
|
98
|
+
} | {
|
|
99
|
+
type: PickerActionType.SearchFetchStart;
|
|
100
|
+
query: string;
|
|
101
|
+
} | {
|
|
102
|
+
type: PickerActionType.SearchFetchSuccess;
|
|
103
|
+
results: TaxonomySearchResult[];
|
|
104
|
+
nextMarker: string | undefined;
|
|
105
|
+
forQuery: string;
|
|
106
|
+
} | {
|
|
107
|
+
type: PickerActionType.SearchFetchError;
|
|
108
|
+
error: string;
|
|
109
|
+
} | {
|
|
110
|
+
type: PickerActionType.SearchClear;
|
|
111
|
+
} | {
|
|
112
|
+
type: PickerActionType.SearchLoadMoreStart;
|
|
113
|
+
} | {
|
|
114
|
+
type: PickerActionType.SearchLoadMoreSuccess;
|
|
115
|
+
entries: TaxonomySearchResult[];
|
|
116
|
+
nextMarker: string | undefined;
|
|
117
|
+
forQuery: string;
|
|
118
|
+
} | {
|
|
119
|
+
type: PickerActionType.SearchLoadMoreError;
|
|
120
|
+
error: string;
|
|
121
|
+
forQuery: string;
|
|
122
|
+
} | {
|
|
123
|
+
type: PickerActionType.SetLevelFilter;
|
|
124
|
+
level: number | null;
|
|
125
|
+
};
|
|
126
|
+
export interface PickerState {
|
|
127
|
+
/** Breadcrumb trail of ancestors leading to `currentParentId`; empty at root. */
|
|
128
|
+
levelStack: BreadcrumbEntry[];
|
|
129
|
+
/** Parent node currently being browsed; `null` is the root level. */
|
|
130
|
+
currentParentId: string | null;
|
|
131
|
+
/** Children of `currentParentId` rendered in the browse list. */
|
|
132
|
+
items: TaxonomyNode[];
|
|
133
|
+
/** Pagination cursor for the next `items` page; `undefined` when no more pages. */
|
|
134
|
+
itemsNextMarker: string | undefined;
|
|
135
|
+
/** Initial fetch for the current level is in flight — drives the skeleton. */
|
|
136
|
+
isFetching: boolean;
|
|
137
|
+
/** "Load more" page for the current level is in flight — drives the inline spinner. */
|
|
138
|
+
isFetchingMore: boolean;
|
|
139
|
+
/** Initial fetch error for the current level; mutually exclusive with `items`. */
|
|
140
|
+
initialLoadError: string | null;
|
|
141
|
+
/**
|
|
142
|
+
* "Load more" page error for the current level. When set, an inline error row
|
|
143
|
+
* is rendered at the bottom of the existing list (already-loaded items remain
|
|
144
|
+
* visible). Cleared when a retry begins or the level changes.
|
|
145
|
+
*/
|
|
146
|
+
loadMoreError: string | null;
|
|
147
|
+
/** Raw search input value — updated on every keystroke (pre-debounce). */
|
|
148
|
+
searchInputValue: string;
|
|
149
|
+
/** Debounced/committed query the active search request was fired against; used to race-guard `SearchFetchSuccess`. */
|
|
150
|
+
searchQuery: string;
|
|
151
|
+
/** Results for the active `searchQuery`. */
|
|
152
|
+
searchResults: TaxonomySearchResult[];
|
|
153
|
+
/** Pagination cursor for the next `searchResults` page. */
|
|
154
|
+
searchNextMarker: string | undefined;
|
|
155
|
+
/** Initial search fetch is in flight. */
|
|
156
|
+
isFetchingSearch: boolean;
|
|
157
|
+
/** "Load more" page for search results is in flight. */
|
|
158
|
+
isFetchingSearchMore: boolean;
|
|
159
|
+
/** Initial search request error; mutually exclusive with `searchResults`. */
|
|
160
|
+
searchError: string | null;
|
|
161
|
+
/**
|
|
162
|
+
* "Load more" page error for the active search query. When set, an inline
|
|
163
|
+
* error row is rendered at the bottom of the search results list. Cleared
|
|
164
|
+
* when a retry begins or the search query changes / clears.
|
|
165
|
+
*/
|
|
166
|
+
searchLoadMoreError: string | null;
|
|
167
|
+
/** Optional level filter applied to the global (root-level) search; `null` means "all levels". */
|
|
168
|
+
levelFilter: number | null;
|
|
169
|
+
/** Levels available in the current taxonomy (drives the level-filter dropdown and single-level scoping). */
|
|
170
|
+
availableLevels: TaxonomyLevel[];
|
|
171
|
+
/**
|
|
172
|
+
* Which operation failed most recently, so `retry()` knows which one to re-run
|
|
173
|
+
* without having to infer it from other state. Cleared on success or when a
|
|
174
|
+
* new operation begins. Covers all four failure cases: initial browse, browse
|
|
175
|
+
* load-more, initial search, and search load-more.
|
|
176
|
+
*/
|
|
177
|
+
lastFailedOp: FailedOp | null;
|
|
178
|
+
}
|
|
179
|
+
export declare const initialState: PickerState;
|
|
180
|
+
export declare function pickerReducer(state: PickerState, action: PickerAction): PickerState;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { BreadcrumbEntry } from '../types';
|
|
2
|
+
import { PickerState } from './reducer';
|
|
3
|
+
/** Atomic move to a new level: empties items, shows skeleton, wipes search slice. */
|
|
4
|
+
export declare const transitionToLevel: (state: PickerState, targetParentId: string | null, levelStack: BreadcrumbEntry[]) => PickerState;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { MetadataTaxonomyPicker } from '../../index';
|
|
3
|
+
import { MetadataTaxonomyPickerProps, TaxonomyPickerMode, TaxonomyValue } from '../types';
|
|
4
|
+
declare const _default: {
|
|
5
|
+
title: string;
|
|
6
|
+
component: import('react').ForwardRefExoticComponent<MetadataTaxonomyPickerProps & import('react').RefAttributes<HTMLInputElement>>;
|
|
7
|
+
decorators: ((Story: import('storybook/internal/csf').PartialStoryFn<import('@storybook/react').ReactRenderer, {
|
|
8
|
+
mode: TaxonomyPickerMode;
|
|
9
|
+
multiSelect: boolean;
|
|
10
|
+
value: TaxonomyValue[];
|
|
11
|
+
onValueChange: (values: TaxonomyValue[]) => void;
|
|
12
|
+
itemsService: import('../types').TaxonomyItemsService;
|
|
13
|
+
eventService?: import('../types').TaxonomyPickerEventService | undefined;
|
|
14
|
+
levels?: import('../types').TaxonomyLevel[] | undefined;
|
|
15
|
+
placeholder?: string | undefined;
|
|
16
|
+
disabled?: boolean | undefined;
|
|
17
|
+
label?: string | undefined;
|
|
18
|
+
containerClassName?: string | undefined;
|
|
19
|
+
portalElement?: (HTMLElement | (() => HTMLElement | null) | null) | undefined;
|
|
20
|
+
ref?: import('react').LegacyRef<HTMLInputElement> | undefined;
|
|
21
|
+
key?: import('react').Key | null | undefined;
|
|
22
|
+
}>) => import("react/jsx-runtime").JSX.Element)[];
|
|
23
|
+
parameters: {
|
|
24
|
+
docs: {
|
|
25
|
+
description: {
|
|
26
|
+
component: string;
|
|
27
|
+
};
|
|
28
|
+
page: () => import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
};
|
|
30
|
+
modernizedComponents: boolean;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export default _default;
|
|
34
|
+
type Story = StoryObj<typeof MetadataTaxonomyPicker>;
|
|
35
|
+
/** The popover shows the initial data when the initial fetch is successful. */
|
|
36
|
+
export declare const InitialData: Story;
|
|
37
|
+
/**
|
|
38
|
+
* The popover shows a skeleton loading state while the initial fetch is in progress.
|
|
39
|
+
*/
|
|
40
|
+
export declare const LoadingState: Story;
|
|
41
|
+
/**
|
|
42
|
+
* The popover shows an empty state when there is no data after loading completes.
|
|
43
|
+
*/
|
|
44
|
+
export declare const EmptyState: Story;
|
|
45
|
+
/** 1 000 items rendered in a virtualized list — validates performance at scale. */
|
|
46
|
+
export declare const LargeDataset: Story;
|
|
47
|
+
/** 1 000 items in multi-select mode — checkboxes with large dataset. */
|
|
48
|
+
export declare const LargeDatasetMultiSelect: Story;
|
|
49
|
+
/** Error state — the fetch fails and a retry button is shown. */
|
|
50
|
+
export declare const ErrorState: Story;
|
|
51
|
+
/**
|
|
52
|
+
* Disabled state — the trigger cannot be interacted with.
|
|
53
|
+
*/
|
|
54
|
+
export declare const Disabled: Story;
|
|
55
|
+
/**
|
|
56
|
+
* No selection — only the placeholder text is visible inside the trigger.
|
|
57
|
+
*/
|
|
58
|
+
export declare const NoSelection: Story;
|
|
59
|
+
/**
|
|
60
|
+
* A single chip is shown inside the trigger when one value is selected.
|
|
61
|
+
*/
|
|
62
|
+
export declare const SingleChip: Story;
|
|
63
|
+
/**
|
|
64
|
+
* Multiple chips are shown when several values are selected.
|
|
65
|
+
*/
|
|
66
|
+
export declare const MultipleChips: Story;
|
|
67
|
+
/**
|
|
68
|
+
* When many values are selected the chips wrap across multiple lines inside the trigger.
|
|
69
|
+
*/
|
|
70
|
+
export declare const OverflowChips: Story;
|
|
71
|
+
/** Click a row's chevron (or press Right Arrow on a focused row) to drill in. */
|
|
72
|
+
export declare const DrillDownNavigation: Story;
|
|
73
|
+
/**
|
|
74
|
+
* Eight-level hierarchy (Region → Block) with four siblings per level. Drill all
|
|
75
|
+
* the way down to see the Blueprint Breadcrumb collapse the older ancestors into
|
|
76
|
+
* the folder-tree dropdown while keeping the last few levels and the current
|
|
77
|
+
* page visible.
|
|
78
|
+
*/
|
|
79
|
+
export declare const DeepDrillDownNavigation: Story;
|
|
80
|
+
/**
|
|
81
|
+
* Six-level hierarchy with intentionally long display names, rendered in a
|
|
82
|
+
* narrow popover. Forces the folder-tree truncation to engage early so the
|
|
83
|
+
* breadcrumb dropdown trigger is visible even mid-way through the trail.
|
|
84
|
+
*/
|
|
85
|
+
export declare const DeepDrillDownNavigationWithLongLabels: Story;
|
|
86
|
+
/**
|
|
87
|
+
* Picker with real search filtering: typing a substring shows all matching
|
|
88
|
+
* nodes with their ancestor breadcrumbs. Try `region`, `country`, `state`, or
|
|
89
|
+
* `01` to see results across all levels. Use the level filter dropdown to
|
|
90
|
+
* restrict results to a specific level.
|
|
91
|
+
*/
|
|
92
|
+
export declare const WithSearch: Story;
|
|
93
|
+
/**
|
|
94
|
+
* Disabled state with selected values — chips are visible but not interactive (no dismiss button).
|
|
95
|
+
*/
|
|
96
|
+
export declare const DisabledWithChips: Story;
|
|
97
|
+
/**
|
|
98
|
+
* Cursor-paginated browse list (450 items, page size 100). Scroll near the bottom
|
|
99
|
+
* to auto-fetch the next page: ghost rows appear while the request is in flight
|
|
100
|
+
* and new rows append below the already-loaded ones, preserving scroll position.
|
|
101
|
+
*/
|
|
102
|
+
export declare const Pagination: Story;
|
|
103
|
+
/**
|
|
104
|
+
* Pagination + drill-down: scroll through several pages at the root, drill into
|
|
105
|
+
* a node, then navigate back. All pages loaded before drilling down are restored
|
|
106
|
+
* from cache, so the user lands back at the same scroll-loaded state without
|
|
107
|
+
* having to re-scroll or re-fetch.
|
|
108
|
+
*/
|
|
109
|
+
export declare const PaginationWithDrillDownCacheRestore: Story;
|
|
110
|
+
/** Multi-level × multi-select: drill down at every level, pick many values across levels. */
|
|
111
|
+
export declare const MultiLevelMultiSelect: Story;
|
|
112
|
+
/** Multi-level × single-select: drill down, pick one value; popover closes on selection. */
|
|
113
|
+
export declare const MultiLevelSingleSelect: Story;
|
|
114
|
+
/**
|
|
115
|
+
* Single-level × multi-select with non-selectable parents. Drill through
|
|
116
|
+
* Country → State (no radios) to reach selectable Cities; search is locked
|
|
117
|
+
* to the City level regardless of browse position.
|
|
118
|
+
*/
|
|
119
|
+
export declare const SingleLevelMultiSelectWithNonSelectableParents: Story;
|
|
120
|
+
/** Single-level × single-select with non-selectable parents — closes on City pick. */
|
|
121
|
+
export declare const SingleLevelSingleSelectWithNonSelectableParents: Story;
|
|
122
|
+
/**
|
|
123
|
+
* Browse load-more error: the first page loads successfully, but the next page
|
|
124
|
+
* (triggered by scrolling to the bottom) fails. Already-loaded items stay
|
|
125
|
+
* visible and an inline "Loading failed" row with a Reload action appears at
|
|
126
|
+
* the bottom of the list. Clicking Reload re-attempts from the current marker.
|
|
127
|
+
*/
|
|
128
|
+
export declare const LoadMoreError: Story;
|
|
129
|
+
/**
|
|
130
|
+
* Search error: the initial search request fails, replacing the result area
|
|
131
|
+
* with the full-area error and retry button. Clicking retry re-runs the last
|
|
132
|
+
* committed query.
|
|
133
|
+
*/
|
|
134
|
+
export declare const SearchErrorState: Story;
|
|
135
|
+
export declare const PortalElementInScrollableContainer: Story;
|
|
136
|
+
export declare const ForwardedRefFocus: Story;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { TaxonomyMenuItemProps } from '../../components/taxonomy-menu-item';
|
|
2
|
+
interface BuildOptions extends Partial<TaxonomyMenuItemProps> {
|
|
3
|
+
onSelect: TaxonomyMenuItemProps['onSelect'];
|
|
4
|
+
onDrillDown: TaxonomyMenuItemProps['onDrillDown'];
|
|
5
|
+
}
|
|
6
|
+
/** Browse-mode items: single-line rows, no ancestors, drill-down enabled. */
|
|
7
|
+
export declare function buildBrowseItems(count: number, options: BuildOptions): TaxonomyMenuItemProps[];
|
|
8
|
+
/** Search-mode items: rows with ancestor breadcrumbs of varying depth. */
|
|
9
|
+
export declare function buildSearchItems(count: number, options: BuildOptions): TaxonomyMenuItemProps[];
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { TaxonomyItemsService, TaxonomyLevel, TaxonomyNode, TaxonomySearchResult } from '../../types';
|
|
2
|
+
declare const ROOT_KEY = "__root__";
|
|
3
|
+
export interface MockServiceConfig {
|
|
4
|
+
/** Flat fixture; ignored when `nodesByParent` is set. */
|
|
5
|
+
nodes?: TaxonomyNode[];
|
|
6
|
+
/** Children indexed by parent id; use `ROOT_KEY` for the root level. */
|
|
7
|
+
nodesByParent?: Record<string, TaxonomyNode[]>;
|
|
8
|
+
/**
|
|
9
|
+
* Pre-defined search results returned verbatim regardless of the query.
|
|
10
|
+
* Ignored when `filterSearchByQuery` is `true`.
|
|
11
|
+
*/
|
|
12
|
+
searchResults?: TaxonomySearchResult[];
|
|
13
|
+
/**
|
|
14
|
+
* When `true` and `nodesByParent` is provided, `searchNodes` performs a
|
|
15
|
+
* real case-insensitive substring match against every node's display name
|
|
16
|
+
* and returns results with full ancestor chains — useful for interactive
|
|
17
|
+
* search stories.
|
|
18
|
+
*/
|
|
19
|
+
filterSearchByQuery?: boolean;
|
|
20
|
+
/** Optional fixture levels; accepted for parity with the picker's `levels` prop. */
|
|
21
|
+
levels?: TaxonomyLevel[];
|
|
22
|
+
delay?: number;
|
|
23
|
+
/** Override the response delay for `searchNodes` only. Defaults to `delay`. */
|
|
24
|
+
searchDelay?: number;
|
|
25
|
+
shouldError?: boolean;
|
|
26
|
+
errorMessage?: string;
|
|
27
|
+
/**
|
|
28
|
+
* When set, `getNodes` / `searchNodes` honor `params.limit` + `params.marker`
|
|
29
|
+
* for true cursor pagination over the fixture. When unset, the full fixture
|
|
30
|
+
* is returned in one page (legacy behavior used by non-pagination stories).
|
|
31
|
+
*/
|
|
32
|
+
paginate?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export declare function createMockItemsService(config?: MockServiceConfig): TaxonomyItemsService;
|
|
35
|
+
export { ROOT_KEY };
|