@deftui/react 0.2.5 → 0.3.1
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/README.md +2 -2
- package/dist/index.d.mts +7 -5
- package/dist/index.mjs +4 -4
- package/dist/styles.css +3 -0
- package/dist/vendor/README.md +10 -9
- package/dist/vendor/coss/calendar.d.mts +4 -0
- package/dist/vendor/coss/calendar.mjs +70 -0
- package/dist/vendor/coss/card.d.mts +23 -0
- package/dist/vendor/coss/card.mjs +160 -0
- package/dist/vendor/coss/dialog.d.mts +1 -1
- package/dist/vendor/coss/dialog.mjs +1 -1
- package/dist/vendor/coss/table.d.mts +15 -0
- package/dist/vendor/coss/table.mjs +73 -0
- package/dist/vendor/reui.io/cascader/cascader-async.d.mts +20 -0
- package/dist/vendor/reui.io/cascader/cascader-async.mjs +578 -0
- package/dist/vendor/reui.io/cascader/cascader-context.d.mts +12 -0
- package/dist/vendor/reui.io/cascader/cascader-context.mjs +56 -0
- package/dist/vendor/reui.io/cascader/cascader-footer.d.mts +60 -0
- package/dist/vendor/reui.io/cascader/cascader-footer.mjs +445 -0
- package/dist/vendor/reui.io/cascader/cascader-i18n.mjs +64 -0
- package/dist/vendor/reui.io/cascader/cascader-item.d.mts +92 -0
- package/dist/vendor/reui.io/cascader/cascader-item.mjs +533 -0
- package/dist/vendor/reui.io/cascader/cascader-lib.d.mts +3 -0
- package/dist/vendor/reui.io/cascader/cascader-lib.mjs +688 -0
- package/dist/vendor/reui.io/cascader/cascader-nav.d.mts +56 -0
- package/dist/vendor/reui.io/cascader/cascader-nav.mjs +310 -0
- package/dist/vendor/reui.io/cascader/cascader-types.d.mts +140 -0
- package/dist/vendor/reui.io/cascader/cascader-virtual.d.mts +18 -0
- package/dist/vendor/reui.io/cascader/cascader-virtual.mjs +159 -0
- package/dist/vendor/reui.io/cascader/cascader.d.mts +299 -0
- package/dist/vendor/reui.io/cascader/cascader.mjs +1470 -0
- package/dist/vendor/reui.io/timeline.d.mts +21 -0
- package/dist/vendor/reui.io/timeline.mjs +127 -0
- package/dist/vendor/tailored/lightbox.d.mts +1 -1
- package/dist/vendor/tailored/lightbox.mjs +1 -1
- package/dist/widgets/datetime.d.mts +1 -1
- package/dist/widgets/datetime.mjs +6 -1
- package/dist/widgets/export.d.mts +28 -0
- package/dist/widgets/index.d.mts +69 -20
- package/dist/widgets/index.mjs +61 -11
- package/package.json +2 -2
- package/dist/vendor/shadcn/calendar.d.mts +0 -10
- package/dist/vendor/shadcn/calendar.mjs +0 -107
- package/dist/vendor/shadcn/card.d.mts +0 -11
- package/dist/vendor/shadcn/card.mjs +0 -55
- package/dist/vendor/shadcn/table.d.mts +0 -9
- package/dist/vendor/shadcn/table.mjs +0 -59
- package/dist/vendor/tailored/file-tree.d.mts +0 -21
- package/dist/vendor/tailored/file-tree.mjs +0 -146
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCascaderActions, useCascaderHighlight, useCascaderState } from "./cascader-context.mjs";
|
|
3
|
+
import { CascaderItem, CascaderItems, getCascaderMoreProps } from "./cascader-item.mjs";
|
|
4
|
+
import * as React$1 from "react";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { defaultRangeExtractor, useVirtualizer } from "@tanstack/react-virtual";
|
|
7
|
+
// src/vendor/reui.io/cascader/cascader-virtual.tsx
|
|
8
|
+
/**
|
|
9
|
+
* The cascader's virtualizer: TanStack plus the highlight pinning and
|
|
10
|
+
* scroll-into-view a combobox list needs. `activeIndex` is clamped here, not by
|
|
11
|
+
* the caller: emitted from a layout effect, it can be one commit ahead of a
|
|
12
|
+
* level that just shrank and would otherwise scroll to a row that is gone.
|
|
13
|
+
*/
|
|
14
|
+
function useCascaderVirtualizer({ count, getScrollElement, estimateSize = 32, overscan = 8, getItemKey, activeIndex = -1 }) {
|
|
15
|
+
const active = activeIndex >= 0 && activeIndex < count ? activeIndex : -1;
|
|
16
|
+
const rangeExtractor = React$1.useCallback((range) => {
|
|
17
|
+
const indices = new Set(defaultRangeExtractor(range));
|
|
18
|
+
if (active !== -1) indices.add(active);
|
|
19
|
+
return Array.from(indices).sort((a, b) => a - b);
|
|
20
|
+
}, [active]);
|
|
21
|
+
const measureEstimate = React$1.useCallback(() => estimateSize, [estimateSize]);
|
|
22
|
+
const virtualizer = useVirtualizer({
|
|
23
|
+
count,
|
|
24
|
+
getScrollElement,
|
|
25
|
+
estimateSize: measureEstimate,
|
|
26
|
+
overscan,
|
|
27
|
+
getItemKey,
|
|
28
|
+
rangeExtractor
|
|
29
|
+
});
|
|
30
|
+
React$1.useEffect(() => {
|
|
31
|
+
if (active === -1) return;
|
|
32
|
+
virtualizer.scrollToIndex(active, { align: "auto" });
|
|
33
|
+
}, [
|
|
34
|
+
active,
|
|
35
|
+
count,
|
|
36
|
+
virtualizer
|
|
37
|
+
]);
|
|
38
|
+
return virtualizer;
|
|
39
|
+
}
|
|
40
|
+
const NO_GUTTER = {
|
|
41
|
+
block: 0,
|
|
42
|
+
inline: 0
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* The ROWS' BOX's own padding, never the scrollport's (separate element, reads
|
|
46
|
+
* a flat zero). Measured because every style sets its own: a windowed row is
|
|
47
|
+
* positioned against this box's PADDING box while the scroll-height spacer is
|
|
48
|
+
* an in-flow child of its CONTENT box, so without it rows sit flush.
|
|
49
|
+
*/
|
|
50
|
+
function useCascaderVirtualGutter(contentElement) {
|
|
51
|
+
const [gutter, setGutter] = React$1.useState(NO_GUTTER);
|
|
52
|
+
React$1.useLayoutEffect(() => {
|
|
53
|
+
if (!contentElement) return;
|
|
54
|
+
const styles = getComputedStyle(contentElement);
|
|
55
|
+
const block = Number.parseFloat(styles.paddingTop) || 0;
|
|
56
|
+
const inline = Number.parseFloat(styles.paddingInlineStart || styles.paddingLeft) || 0;
|
|
57
|
+
setGutter((previous) => previous.block === block && previous.inline === inline ? previous : {
|
|
58
|
+
block,
|
|
59
|
+
inline
|
|
60
|
+
});
|
|
61
|
+
}, [contentElement]);
|
|
62
|
+
return gutter;
|
|
63
|
+
}
|
|
64
|
+
/** Logical insets, not `left` / `width`, so RTL needs no second code path. */
|
|
65
|
+
function cascaderVirtualRowStyle(start, gutter) {
|
|
66
|
+
return {
|
|
67
|
+
position: "absolute",
|
|
68
|
+
top: 0,
|
|
69
|
+
insetInlineStart: gutter.inline,
|
|
70
|
+
insetInlineEnd: gutter.inline,
|
|
71
|
+
transform: `translateY(${start + gutter.block}px)`
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The element that actually SCROLLS: the `ScrollArea` viewport above the rows'
|
|
76
|
+
* box, not the rows' box itself, which never overflows, so a virtualizer aimed
|
|
77
|
+
* at it would read a full `clientHeight` and render every row. `closest` rather
|
|
78
|
+
* than `parentElement`, plus a fallback to the content element, keeps a
|
|
79
|
+
* hand-written `overflow-y-auto` container working.
|
|
80
|
+
*/
|
|
81
|
+
function cascaderScrollElement(content) {
|
|
82
|
+
if (!content) return null;
|
|
83
|
+
return content.closest("[data-slot=\"scroll-area-viewport\"]") ?? content;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* `role="presentation"` keeps the listbox owning nothing but options, and this
|
|
87
|
+
* node's parent IS the rows' box, saving a ref threaded through `CascaderList`.
|
|
88
|
+
*/
|
|
89
|
+
function CascaderVirtualSpacer({ height, onContentElement }) {
|
|
90
|
+
return /* @__PURE__ */ jsx("div", {
|
|
91
|
+
ref: (node) => onContentElement(node?.parentElement ?? null),
|
|
92
|
+
role: "presentation",
|
|
93
|
+
"data-slot": "cascader-virtual-spacer",
|
|
94
|
+
style: { height }
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Windowed replacement for `CascaderItems`, dropped inside `CascaderList`. The
|
|
99
|
+
* registration is a LAYOUT effect because the root derives `virtualized` from
|
|
100
|
+
* it and the flip has to land before the browser paints. Until the root has
|
|
101
|
+
* seen it, this renders exactly what `CascaderItems` does, so no frame carries
|
|
102
|
+
* indexed rows while Base UI still owns the composite list.
|
|
103
|
+
*/
|
|
104
|
+
function CascaderVirtualItems(props) {
|
|
105
|
+
const { virtualized, registerVirtualRenderer } = useCascaderActions();
|
|
106
|
+
React$1.useLayoutEffect(() => registerVirtualRenderer(), [registerVirtualRenderer]);
|
|
107
|
+
if (!virtualized) return /* @__PURE__ */ jsx(CascaderItems, {});
|
|
108
|
+
return /* @__PURE__ */ jsx(CascaderVirtualRows, { ...props });
|
|
109
|
+
}
|
|
110
|
+
function CascaderVirtualRows({ estimateSize, overscan }) {
|
|
111
|
+
"use no memo";
|
|
112
|
+
const { estimateRowSize, overscan: rootOverscan, mode, isBranch, isSelectable, isSelected, isIndeterminate } = useCascaderActions();
|
|
113
|
+
const { renderedItems, treeRows, deepResults, loadStates } = useCascaderState();
|
|
114
|
+
const highlight = useCascaderHighlight();
|
|
115
|
+
const [contentElement, setContentElement] = React$1.useState(null);
|
|
116
|
+
const gutter = useCascaderVirtualGutter(contentElement);
|
|
117
|
+
const tree = mode === "tree";
|
|
118
|
+
const count = tree ? treeRows.length : renderedItems.length;
|
|
119
|
+
const showPath = !tree && deepResults !== null;
|
|
120
|
+
const getItemKey = React$1.useCallback((index) => (tree ? treeRows[index]?.node.value : renderedItems[index]?.value) ?? index, [
|
|
121
|
+
tree,
|
|
122
|
+
treeRows,
|
|
123
|
+
renderedItems
|
|
124
|
+
]);
|
|
125
|
+
const virtualizer = useCascaderVirtualizer({
|
|
126
|
+
count,
|
|
127
|
+
getScrollElement: () => cascaderScrollElement(contentElement),
|
|
128
|
+
estimateSize: estimateSize ?? estimateRowSize,
|
|
129
|
+
overscan: overscan ?? rootOverscan,
|
|
130
|
+
getItemKey,
|
|
131
|
+
activeIndex: highlight.index
|
|
132
|
+
});
|
|
133
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(CascaderVirtualSpacer, {
|
|
134
|
+
height: virtualizer.getTotalSize(),
|
|
135
|
+
onContentElement: setContentElement
|
|
136
|
+
}), virtualizer.getVirtualItems().map((row) => {
|
|
137
|
+
const flat = tree ? treeRows[row.index] : void 0;
|
|
138
|
+
const node = tree ? flat?.node : renderedItems[row.index];
|
|
139
|
+
if (!node) return null;
|
|
140
|
+
return /* @__PURE__ */ jsx(CascaderItem, {
|
|
141
|
+
ref: virtualizer.measureElement,
|
|
142
|
+
"data-index": row.index,
|
|
143
|
+
style: cascaderVirtualRowStyle(row.start, gutter),
|
|
144
|
+
node,
|
|
145
|
+
index: row.index,
|
|
146
|
+
depth: flat?.depth,
|
|
147
|
+
expanded: flat?.expanded,
|
|
148
|
+
branch: flat ? flat.branch : isBranch(node),
|
|
149
|
+
selectable: isSelectable(node),
|
|
150
|
+
selected: isSelected(node),
|
|
151
|
+
indeterminate: isIndeterminate(node),
|
|
152
|
+
...getCascaderMoreProps(node, loadStates),
|
|
153
|
+
showPath,
|
|
154
|
+
"aria-setsize": flat ? flat.setSize : count,
|
|
155
|
+
"aria-posinset": flat ? flat.posInSet : row.index + 1
|
|
156
|
+
}, row.key);
|
|
157
|
+
})] });
|
|
158
|
+
}
|
|
159
|
+
export { CascaderVirtualItems, useCascaderVirtualizer };
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { CascaderGetChildren, CascaderOnSearch, CascaderResolveValue } from "./cascader-async.mjs";
|
|
2
|
+
import { CascaderItemState } from "./cascader-context.mjs";
|
|
3
|
+
import { CascaderCheckedStrategy } from "./cascader-lib.mjs";
|
|
4
|
+
import { CascaderActionItem, CascaderChangeDetails, CascaderLabels, CascaderMode, CascaderNode, CascaderSearchScope, CascaderSelectable } from "./cascader-types.mjs";
|
|
5
|
+
import * as React$1 from "react";
|
|
6
|
+
import { useRender } from "@base-ui/react/use-render";
|
|
7
|
+
import { Combobox } from "@base-ui/react";
|
|
8
|
+
/**
|
|
9
|
+
* Why the navigation path changed.
|
|
10
|
+
* - `"drill"`: a branch was entered (row press, level arrow, search hit).
|
|
11
|
+
* - `"back"`: one level up (back control, Backspace on an empty query).
|
|
12
|
+
* - `"breadcrumb"`: a jump to an exact depth in the trail.
|
|
13
|
+
* - `"reveal"`: the reopen navigated to the level holding the selection.
|
|
14
|
+
* - `"external"`: `setPath` called from outside the primitive's own flows.
|
|
15
|
+
*/
|
|
16
|
+
export type CascaderPathChangeReason = "drill" | "back" | "breadcrumb" | "reveal" | "external";
|
|
17
|
+
/** Everything independent of the selection mode; the rest is on the two arms. */
|
|
18
|
+
export interface CascaderBaseProps<T = unknown> {
|
|
19
|
+
/** Nested tree, or a flat list when `getParent` is supplied. */
|
|
20
|
+
items: CascaderNode<T>[];
|
|
21
|
+
/** Opt in to flat adjacency input by returning each node's parent value. */
|
|
22
|
+
getParent?: (node: CascaderNode<T>) => string | null | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Fetches one level on demand; `node` is `null` for the root, and only
|
|
25
|
+
* `{ value, label: value }` for a level on screen whose node has not loaded
|
|
26
|
+
* (a deep link, or a page-loaded level after a `loadKey` change). Return an
|
|
27
|
+
* array, or a `CascaderLoadResult` when the level pages. Pages cache apart
|
|
28
|
+
* from `items`; mark unfetched branches `hasChildren` or they read as leaves.
|
|
29
|
+
*/
|
|
30
|
+
getChildren?: CascaderGetChildren<T>;
|
|
31
|
+
/**
|
|
32
|
+
* Server-side search, debounced by `searchDebounce`; replaces the local scan
|
|
33
|
+
* while the query is set. Results are detached: resolvable by value, in no
|
|
34
|
+
* level. Ignored in `mode="tree"`, where a hit belongs to no visible branch.
|
|
35
|
+
*/
|
|
36
|
+
onSearch?: CascaderOnSearch<T>;
|
|
37
|
+
/** Milliseconds of quiet before `onSearch` fires. */
|
|
38
|
+
searchDebounce?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Resolves a value the loader has never seen into its ancestor chain, root
|
|
41
|
+
* first, so the trigger can path a server-supplied selection. Runs with the
|
|
42
|
+
* popup closed too. Does NOT mark those levels loaded: opening one still
|
|
43
|
+
* fetches, and lists the node after its rows while it has pages left.
|
|
44
|
+
*/
|
|
45
|
+
resolveValue?: CascaderResolveValue<T>;
|
|
46
|
+
/** Cache key. Changing it drops every page and aborts anything in flight. */
|
|
47
|
+
loadKey?: unknown;
|
|
48
|
+
/** Prefetch a highlighted branch's children after a pause. Off by default. */
|
|
49
|
+
prefetch?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Called when a load fails. `context.parent` is the level (`null` for root);
|
|
52
|
+
* `context.reason` is `"level"`, `"more"`, `"retry"`, `"prefetch"`,
|
|
53
|
+
* `"search"` or `"resolve"`. Never for an aborted or superseded request.
|
|
54
|
+
*/
|
|
55
|
+
onLoadError?: (error: unknown, context: {
|
|
56
|
+
parent: string | null;
|
|
57
|
+
reason: string;
|
|
58
|
+
}) => void;
|
|
59
|
+
/** Which nodes may be committed. Defaults to leaves only. */
|
|
60
|
+
selectable?: CascaderSelectable<T>;
|
|
61
|
+
/**
|
|
62
|
+
* Whether the built-in SINGLE-SELECT check is drawn. Defaults to true.
|
|
63
|
+
* `false` also gives back the inline-end gutter every style reserves for it;
|
|
64
|
+
* `data-selected` and `aria-selected` stay. A no-op under `multiple`, where
|
|
65
|
+
* the checkbox is the selection CONTROL rather than a decoration.
|
|
66
|
+
*/
|
|
67
|
+
indicator?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Footer ACTIONS: commands pinned below the list, never rows in it, and never
|
|
70
|
+
* touching the data tree. A childless `<CascaderFooter />` draws these; an
|
|
71
|
+
* action with `items` opens a side-anchored flyout rather than firing.
|
|
72
|
+
*/
|
|
73
|
+
actions?: CascaderActionItem[];
|
|
74
|
+
/**
|
|
75
|
+
* Parent/child cascading. Multi-select only, off by default, and it needs
|
|
76
|
+
* committable branches (`selectable="any"` or a predicate). A commit selects
|
|
77
|
+
* or deselects every SELECTABLE node in the KNOWN subtree (loaded, or on a
|
|
78
|
+
* resolved chain) and reconciles ancestors. KNOWN is the semantic, not a
|
|
79
|
+
* hedge: a commit must not fan out into a request per level, so children
|
|
80
|
+
* arriving later arrive unchecked.
|
|
81
|
+
*/
|
|
82
|
+
cascade?: boolean;
|
|
83
|
+
mode?: CascaderMode;
|
|
84
|
+
/** How a branch opens from the pointer in columns mode's ACTIVE column.
|
|
85
|
+
* `"click"` is the default, and neither value ever commits a selection. */
|
|
86
|
+
expandTrigger?: "click" | "hover";
|
|
87
|
+
path?: string[];
|
|
88
|
+
defaultPath?: string[];
|
|
89
|
+
/** The second argument says WHY. An existing `(path) => void` still works. */
|
|
90
|
+
onPathChange?: (path: string[], details: {
|
|
91
|
+
reason: CascaderPathChangeReason;
|
|
92
|
+
}) => void;
|
|
93
|
+
expanded?: string[];
|
|
94
|
+
defaultExpanded?: string[];
|
|
95
|
+
onExpandedChange?: (expanded: string[]) => void;
|
|
96
|
+
open?: boolean;
|
|
97
|
+
defaultOpen?: boolean;
|
|
98
|
+
/** Forwards Base UI's reason; a leaf commit's close says `"item-press"`. */
|
|
99
|
+
onOpenChange?: (open: boolean, details: {
|
|
100
|
+
reason: string;
|
|
101
|
+
}) => void;
|
|
102
|
+
/**
|
|
103
|
+
* Whether a SINGLE-SELECT leaf commit closes the popup. Defaults to true.
|
|
104
|
+
* `false` is for a compare-and-repick flow; Escape, outside press and the
|
|
105
|
+
* trigger still close. Ignored under `multiple`, which never closes.
|
|
106
|
+
*/
|
|
107
|
+
closeOnSelect?: boolean;
|
|
108
|
+
inputValue?: string;
|
|
109
|
+
defaultInputValue?: string;
|
|
110
|
+
onInputValueChange?: (value: string) => void;
|
|
111
|
+
/**
|
|
112
|
+
* `"level"` (default) filters the level on screen, `"deep"` also searches
|
|
113
|
+
* below it, `"global"` searches the whole tree from any level.
|
|
114
|
+
*/
|
|
115
|
+
searchScope?: CascaderSearchScope;
|
|
116
|
+
/** Custom matcher, replacing label + keywords substring matching. */
|
|
117
|
+
filter?: (node: CascaderNode<T>, normalizedQuery: string) => boolean;
|
|
118
|
+
/** On open, navigate to the level holding the selection. Default true.
|
|
119
|
+
* Not in `mode="tree"`, which has no levels to navigate. */
|
|
120
|
+
revealSelected?: boolean;
|
|
121
|
+
maxHeight?: number | string;
|
|
122
|
+
/**
|
|
123
|
+
* Window the rendered rows. `undefined` decides per level from
|
|
124
|
+
* `virtualizeThreshold`; `true`/`false` force it. Also opt-in at the markup
|
|
125
|
+
* level, so the base install pulls in no virtualization library.
|
|
126
|
+
*/
|
|
127
|
+
virtualize?: boolean;
|
|
128
|
+
/** Row count at which windowing turns itself on. */
|
|
129
|
+
virtualizeThreshold?: number;
|
|
130
|
+
/** Row height handed to the virtualizer before a row has been measured. */
|
|
131
|
+
estimateRowSize?: number;
|
|
132
|
+
/** Rows rendered beyond each edge of the viewport. */
|
|
133
|
+
overscan?: number;
|
|
134
|
+
labels?: Partial<CascaderLabels>;
|
|
135
|
+
/** Replaces the entire row, affordances included. */
|
|
136
|
+
renderItem?: (node: CascaderNode<T>, state: CascaderItemState<T>) => React$1.ReactNode;
|
|
137
|
+
/** Replaces only the label block; icon, count, chevron and check stay. */
|
|
138
|
+
renderLabel?: (node: CascaderNode<T>, state: CascaderItemState<T>) => React$1.ReactNode;
|
|
139
|
+
disabled?: boolean;
|
|
140
|
+
/** Native form field name. Submits the selected value(s). */
|
|
141
|
+
name?: string;
|
|
142
|
+
/** Id of the owning form, for a cascader rendered outside it. */
|
|
143
|
+
form?: string;
|
|
144
|
+
/** Id of the control. Pairs the field with a `<label htmlFor>`. */
|
|
145
|
+
id?: string;
|
|
146
|
+
/** Marks the field required for native form validation. */
|
|
147
|
+
required?: boolean;
|
|
148
|
+
/** The value can be read and submitted, but not changed. */
|
|
149
|
+
readOnly?: boolean;
|
|
150
|
+
/** Marks the field invalid: `aria-invalid` and `data-invalid` on the trigger,
|
|
151
|
+
* the chips and the input, which every style's error treatment reads. */
|
|
152
|
+
invalid?: boolean;
|
|
153
|
+
/** Ref to the hidden input Base UI submits with, for form-library focus. */
|
|
154
|
+
inputRef?: React$1.Ref<HTMLInputElement>;
|
|
155
|
+
/** Renders without a floating popup, for an embedded `CascaderPanel`. */
|
|
156
|
+
inline?: boolean;
|
|
157
|
+
children?: React$1.ReactNode;
|
|
158
|
+
}
|
|
159
|
+
export interface CascaderSingleProps<T = unknown> extends CascaderBaseProps<T> {
|
|
160
|
+
multiple?: false;
|
|
161
|
+
value?: string;
|
|
162
|
+
defaultValue?: string;
|
|
163
|
+
onValueChange?: (value: string, details: CascaderChangeDetails<T>) => void;
|
|
164
|
+
/** `never` so passing it is a compile error, not a silent no-op. */
|
|
165
|
+
max?: never;
|
|
166
|
+
}
|
|
167
|
+
/** Multi-select props. Enables checkbox rows and chip display. */
|
|
168
|
+
export interface CascaderMultipleProps<T = unknown> extends CascaderBaseProps<T> {
|
|
169
|
+
multiple: true;
|
|
170
|
+
value?: string[];
|
|
171
|
+
defaultValue?: string[];
|
|
172
|
+
onValueChange?: (value: string[], details: CascaderChangeDetails<T>) => void;
|
|
173
|
+
/** Cap on selections. Further picks are refused, the existing ones survive. */
|
|
174
|
+
max?: number;
|
|
175
|
+
}
|
|
176
|
+
/** `multiple` discriminates: `value`, `onValueChange` and `max` narrow with it. */
|
|
177
|
+
export type CascaderProps<T = unknown> = CascaderSingleProps<T> | CascaderMultipleProps<T>;
|
|
178
|
+
/** No default on `T`: inferred from `items`, so `node.data` arrives typed. */
|
|
179
|
+
declare function Cascader<T>({ items, getParent, getChildren, onSearch, searchDebounce, resolveValue, loadKey, prefetch, onLoadError, value: valueProp, defaultValue, onValueChange: onValueChangeProp, multiple, selectable, indicator, actions, cascade, max, mode, expandTrigger, path: pathProp, defaultPath, onPathChange, expanded: expandedProp, defaultExpanded, onExpandedChange, open: openProp, defaultOpen, onOpenChange, closeOnSelect, inputValue: inputValueProp, defaultInputValue, onInputValueChange, searchScope, filter, revealSelected, maxHeight, virtualize, virtualizeThreshold, estimateRowSize, overscan, labels: labelsProp, renderItem, renderLabel, disabled, name, form, id, required, readOnly, invalid, inputRef, inline, children }: CascaderProps<T>): React$1.JSX.Element;
|
|
180
|
+
/** `Trigger.Props` stops short of `ref`, so it is intersected in, as the
|
|
181
|
+
* shadcn combobox wrapper also does: a form library needs a ref here, and
|
|
182
|
+
* `onBlur`, the "touched" signal, lands here too. */
|
|
183
|
+
export interface CascaderTriggerProps extends Combobox.Trigger.Props, Pick<React$1.ComponentPropsWithRef<"button">, "ref"> {
|
|
184
|
+
/** Hides the trailing chevron, for a trigger that supplies its own. */
|
|
185
|
+
showIcon?: boolean;
|
|
186
|
+
}
|
|
187
|
+
declare function CascaderTrigger({ className, children, showIcon, ref, ...props }: CascaderTriggerProps): React$1.JSX.Element;
|
|
188
|
+
export interface CascaderChipsProps extends Omit<Combobox.Chips.Props, "children">, Pick<React$1.ComponentPropsWithRef<"div">, "ref"> {
|
|
189
|
+
/** Shown in place of the chips when nothing is selected. */
|
|
190
|
+
placeholder?: React$1.ReactNode;
|
|
191
|
+
/**
|
|
192
|
+
* How a `cascade` selection is condensed into chips. DISPLAY ONLY: the
|
|
193
|
+
* stored value stays the full closure, which keeps a row's checked state an
|
|
194
|
+
* O(1) lookup. `"all"` (default) is one chip per value, `"parent"` collapses
|
|
195
|
+
* a fully selected branch, `"child"` chips only the deepest frontier.
|
|
196
|
+
* Removing a condensed chip removes its whole closure and reconciles.
|
|
197
|
+
*/
|
|
198
|
+
strategy?: CascaderCheckedStrategy;
|
|
199
|
+
/** Replaces the chip list, receiving the resolved selection IN SELECTION
|
|
200
|
+
* ORDER. Keep that order: Base UI removes a chip by sibling position. */
|
|
201
|
+
children?: React$1.ReactNode | ((nodes: CascaderNode[]) => React$1.ReactNode);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* The multi-select trigger surface: one removable chip per selection, where
|
|
205
|
+
* `CascaderValue` would collapse to "3 selected". A component rather than a
|
|
206
|
+
* recipe because of three easy misses: the popup anchored to the chips, an
|
|
207
|
+
* accessible name on every remove button, and labels that disambiguate when
|
|
208
|
+
* two branches use the same one.
|
|
209
|
+
*
|
|
210
|
+
* ```tsx
|
|
211
|
+
* const anchor = useCascaderAnchor()
|
|
212
|
+
* <Cascader multiple items={items}>
|
|
213
|
+
* <CascaderChips ref={anchor} placeholder="Select attributes" />
|
|
214
|
+
* <CascaderContent anchor={anchor}>...</CascaderContent>
|
|
215
|
+
* </Cascader>
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
declare function CascaderChips({ className, children, placeholder, strategy, ...props }: CascaderChipsProps): React$1.JSX.Element;
|
|
219
|
+
export interface CascaderChipProps extends Omit<Combobox.Chip.Props, "children"> {
|
|
220
|
+
node: CascaderNode;
|
|
221
|
+
/** Prefix the label with its ancestor trail. */
|
|
222
|
+
showPath?: boolean;
|
|
223
|
+
/** Trail segments to show, the node itself included. */
|
|
224
|
+
maxSegments?: number;
|
|
225
|
+
/** Hides the remove button, for a read-only chip. */
|
|
226
|
+
showRemove?: boolean;
|
|
227
|
+
/** Replaces Base UI's positional removal for this chip (remove button and
|
|
228
|
+
* Backspace/Delete). Supplied for a `strategy`-condensed chip, whose
|
|
229
|
+
* position no longer maps onto the stored array. */
|
|
230
|
+
onRemove?: () => void;
|
|
231
|
+
/** Replaces the chip's label. The remove button is still rendered. */
|
|
232
|
+
children?: React$1.ReactNode;
|
|
233
|
+
}
|
|
234
|
+
/** One chip. Removal goes through Base UI's `ChipRemove`, which reports the
|
|
235
|
+
* shortened selection to the root, so it lands in the same `setSelection` as
|
|
236
|
+
* every other deselection and `cascade` applies to it. */
|
|
237
|
+
declare function CascaderChip({ className, node, showPath, maxSegments, showRemove, onRemove, children, ...props }: CascaderChipProps): React$1.JSX.Element;
|
|
238
|
+
export interface CascaderContentProps extends Combobox.Popup.Props,
|
|
239
|
+
/** Positioner surface forwarded as-is, so an unusual anchor does not force
|
|
240
|
+
* a rebuild of the content stack. No `trackAnchor`: Base UI 1.5.0 has
|
|
241
|
+
* none. */
|
|
242
|
+
Pick<Combobox.Positioner.Props, "side" | "align" | "sideOffset" | "alignOffset" | "anchor" | "collisionBoundary" | "collisionPadding" | "sticky" | "positionMethod">,
|
|
243
|
+
/** Where the portal mounts, for a shadow root or a scoped stacking context. */
|
|
244
|
+
Pick<Combobox.Portal.Props, "container"> {}
|
|
245
|
+
/** Portal + Positioner + floating panel. Unlike shadcn's `ComboboxContent` it
|
|
246
|
+
* does NOT clamp the popup to the anchor width (a cascader panel is routinely
|
|
247
|
+
* wider), but it keeps `group/combobox-content`, which `CascaderEmpty` needs. */
|
|
248
|
+
declare function CascaderContent({ className, side, sideOffset, align, alignOffset, anchor, collisionBoundary, collisionPadding, sticky, positionMethod, container, ref, ...props }: CascaderContentProps): React$1.JSX.Element;
|
|
249
|
+
export type CascaderPanelProps = useRender.ComponentProps<"div">;
|
|
250
|
+
/**
|
|
251
|
+
* The nav + list(s) + footer container, with no positioning of its own: inside
|
|
252
|
+
* `CascaderContent` for the popup case, alone for the embedded one.
|
|
253
|
+
*
|
|
254
|
+
* `min-h-0` and `max-h-full` are load-bearing. A flex child without `min-h-0`
|
|
255
|
+
* refuses to shrink below its content, which is the usual reason a scroll area
|
|
256
|
+
* never scrolls - worst embedded, where no positioner publishes
|
|
257
|
+
* `--available-height`. It also owns the panel's TAB ORDER: the scroll area
|
|
258
|
+
* makes itself a tab stop whenever the level overflows, stranding the footer,
|
|
259
|
+
* and the panel is the only ancestor of both ends of that move in BOTH shapes.
|
|
260
|
+
*/
|
|
261
|
+
declare function CascaderPanel({ className, ...props }: CascaderPanelProps): React$1.ReactElement<unknown, string | React$1.JSXElementConstructor<any>>;
|
|
262
|
+
export interface CascaderListProps extends Omit<Combobox.List.Props, "style"> {
|
|
263
|
+
/** Applied to the OUTER shell, which owns the height, so an inline
|
|
264
|
+
* `--cascader-max-height` lands where the bound can read it. Narrowed from
|
|
265
|
+
* Base UI's `style`: the shell is a plain `<div>` with no list state. */
|
|
266
|
+
style?: React$1.CSSProperties;
|
|
267
|
+
/** Caps this level's height; the panel still shrinks to fit. Default 24rem. */
|
|
268
|
+
maxHeight?: number | string;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Scroll container for one level: pattern 3 of the house scroll reference,
|
|
272
|
+
* viewport-bounded popup scroll. The height is `min()` of `--available-height`
|
|
273
|
+
* (the positioner's space between anchor and viewport edge) and `maxHeight`,
|
|
274
|
+
* so neither can be ignored; a fixed pixel cap alone still reserved 288px for
|
|
275
|
+
* a panel opened 200px above the fold and spilled off screen, and wasted room
|
|
276
|
+
* in a tall window. The four classes are shared with `CascaderColumns` and
|
|
277
|
+
* live in `cascader-lib.tsx`.
|
|
278
|
+
*/
|
|
279
|
+
declare function CascaderList({ className, style, maxHeight: maxHeightProp, ...props }: CascaderListProps): React$1.JSX.Element;
|
|
280
|
+
export interface CascaderEmptyProps extends Combobox.Empty.Props {
|
|
281
|
+
/** @deprecated Ignored: the loading surface no longer draws skeletons. They
|
|
282
|
+
* promised a shape the level might not have and cost a second layout; the
|
|
283
|
+
* progress lives on the branch row instead. Kept so call sites compile. */
|
|
284
|
+
skeletonRows?: number;
|
|
285
|
+
}
|
|
286
|
+
/** The empty, loading and error surface, in ONE element that never unmounts.
|
|
287
|
+
* `Combobox.Empty` renders whenever `filteredItems.length === 0`, as true of a
|
|
288
|
+
* fetching level as of an empty one, so swapping siblings would announce "No
|
|
289
|
+
* results found." over every async level. Swap the CHILDREN. */
|
|
290
|
+
declare function CascaderEmpty({ className, children, skeletonRows, ...props }: CascaderEmptyProps): React$1.JSX.Element;
|
|
291
|
+
export type CascaderStatusProps = Combobox.Status.Props;
|
|
292
|
+
/**
|
|
293
|
+
* Polite live region for the current level and result count, which drill-down
|
|
294
|
+
* otherwise hides in a visual breadcrumb. Built on `Combobox.Status` for its
|
|
295
|
+
* initial-mutation marker: Safari and VoiceOver need a text change ~200ms
|
|
296
|
+
* after mount before reading a polite region at all.
|
|
297
|
+
*/
|
|
298
|
+
declare function CascaderStatus({ className, children, ...props }: CascaderStatusProps): React$1.JSX.Element;
|
|
299
|
+
export { Cascader, CascaderChip, CascaderChips, CascaderContent, CascaderEmpty, type CascaderItemState, CascaderList, CascaderPanel, CascaderStatus, CascaderTrigger };
|