@financedistrict/apps-ui 0.1.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 +19 -0
- package/README.md +119 -0
- package/dist/Radio-BYWz1n7p.d.cts +32 -0
- package/dist/Radio-BYWz1n7p.d.ts +32 -0
- package/dist/SelectTrigger-By0iPBI3.d.cts +78 -0
- package/dist/SelectTrigger-By0iPBI3.d.ts +78 -0
- package/dist/accordion.cjs +322 -0
- package/dist/accordion.d.cts +156 -0
- package/dist/accordion.d.ts +156 -0
- package/dist/accordion.js +2 -0
- package/dist/apps-ui.umd.js +1 -0
- package/dist/button.cjs +366 -0
- package/dist/button.d.cts +52 -0
- package/dist/button.d.ts +52 -0
- package/dist/button.js +3 -0
- package/dist/checkbox.cjs +74 -0
- package/dist/checkbox.d.cts +63 -0
- package/dist/checkbox.d.ts +63 -0
- package/dist/checkbox.js +2 -0
- package/dist/chunk-3RU7JMFE.js +27 -0
- package/dist/chunk-5TWRK4NW.js +783 -0
- package/dist/chunk-7EOSDFS3.js +9 -0
- package/dist/chunk-AIQ4UOGK.js +142 -0
- package/dist/chunk-B3MMGTPV.js +200 -0
- package/dist/chunk-DAHQYLUI.js +146 -0
- package/dist/chunk-DGBXADSS.js +1 -0
- package/dist/chunk-E6KPNTWW.js +295 -0
- package/dist/chunk-EOAB6G2D.js +149 -0
- package/dist/chunk-FAOVKDVM.js +32 -0
- package/dist/chunk-FV76Z4Z2.js +78 -0
- package/dist/chunk-GLTLBUZ7.js +285 -0
- package/dist/chunk-GTZFV43T.js +154 -0
- package/dist/chunk-HRGZNL4A.js +88 -0
- package/dist/chunk-IEVN3J2F.js +98 -0
- package/dist/chunk-IRS3T6LF.js +352 -0
- package/dist/chunk-IYYHCQXG.js +146 -0
- package/dist/chunk-JIXW3455.js +89 -0
- package/dist/chunk-N4VAP2GB.js +77 -0
- package/dist/chunk-SJ2ZRYVV.js +167 -0
- package/dist/chunk-SNU4YXOR.js +66 -0
- package/dist/chunk-TT6JQATV.js +99 -0
- package/dist/chunk-UPQ3ZPCO.js +66 -0
- package/dist/chunk-UVUSVFOH.js +264 -0
- package/dist/chunk-WJFPGGJB.js +255 -0
- package/dist/chunk-WXEBQA7A.js +371 -0
- package/dist/chunk-Y2O4YYZQ.js +184 -0
- package/dist/cut-corner.cjs +111 -0
- package/dist/cut-corner.d.cts +49 -0
- package/dist/cut-corner.d.ts +49 -0
- package/dist/cut-corner.js +1 -0
- package/dist/dialog.cjs +441 -0
- package/dist/dialog.d.cts +240 -0
- package/dist/dialog.d.ts +240 -0
- package/dist/dialog.js +3 -0
- package/dist/feature-card.cjs +182 -0
- package/dist/feature-card.d.cts +54 -0
- package/dist/feature-card.d.ts +54 -0
- package/dist/feature-card.js +2 -0
- package/dist/filter.cjs +873 -0
- package/dist/filter.d.cts +129 -0
- package/dist/filter.d.ts +129 -0
- package/dist/filter.js +6 -0
- package/dist/index.cjs +4583 -0
- package/dist/index.d.cts +29 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +27 -0
- package/dist/inline-select.cjs +856 -0
- package/dist/inline-select.d.cts +92 -0
- package/dist/inline-select.d.ts +92 -0
- package/dist/inline-select.js +6 -0
- package/dist/input.cjs +263 -0
- package/dist/input.d.cts +157 -0
- package/dist/input.d.ts +157 -0
- package/dist/input.js +4 -0
- package/dist/panel.cjs +185 -0
- package/dist/panel.d.cts +103 -0
- package/dist/panel.d.ts +103 -0
- package/dist/panel.js +2 -0
- package/dist/property-grid.cjs +110 -0
- package/dist/property-grid.d.cts +56 -0
- package/dist/property-grid.d.ts +56 -0
- package/dist/property-grid.js +2 -0
- package/dist/radio.cjs +74 -0
- package/dist/radio.d.cts +39 -0
- package/dist/radio.d.ts +39 -0
- package/dist/radio.js +2 -0
- package/dist/scrollbar.cjs +34 -0
- package/dist/scrollbar.d.cts +35 -0
- package/dist/scrollbar.d.ts +35 -0
- package/dist/scrollbar.js +1 -0
- package/dist/search-bar.cjs +408 -0
- package/dist/search-bar.d.cts +42 -0
- package/dist/search-bar.d.ts +42 -0
- package/dist/search-bar.js +4 -0
- package/dist/select.cjs +998 -0
- package/dist/select.d.cts +357 -0
- package/dist/select.d.ts +357 -0
- package/dist/select.js +5 -0
- package/dist/selectable-feature-card.cjs +159 -0
- package/dist/selectable-feature-card.d.cts +74 -0
- package/dist/selectable-feature-card.d.ts +74 -0
- package/dist/selectable-feature-card.js +3 -0
- package/dist/sidebar-item.cjs +175 -0
- package/dist/sidebar-item.d.cts +75 -0
- package/dist/sidebar-item.d.ts +75 -0
- package/dist/sidebar-item.js +2 -0
- package/dist/switch.cjs +86 -0
- package/dist/switch.d.cts +72 -0
- package/dist/switch.d.ts +72 -0
- package/dist/switch.js +2 -0
- package/dist/table-cell.cjs +196 -0
- package/dist/table-cell.d.cts +76 -0
- package/dist/table-cell.d.ts +76 -0
- package/dist/table-cell.js +2 -0
- package/dist/table-title.cjs +34 -0
- package/dist/table-title.d.cts +16 -0
- package/dist/table-title.d.ts +16 -0
- package/dist/table-title.js +2 -0
- package/dist/tabs.cjs +299 -0
- package/dist/tabs.d.cts +116 -0
- package/dist/tabs.d.ts +116 -0
- package/dist/tabs.js +2 -0
- package/dist/toast.cjs +87 -0
- package/dist/toast.d.cts +48 -0
- package/dist/toast.d.ts +48 -0
- package/dist/toast.js +2 -0
- package/dist/token-input.cjs +415 -0
- package/dist/token-input.d.cts +90 -0
- package/dist/token-input.d.ts +90 -0
- package/dist/token-input.js +3 -0
- package/dist/tooltip.cjs +384 -0
- package/dist/tooltip.d.cts +142 -0
- package/dist/tooltip.d.ts +142 -0
- package/dist/tooltip.js +2 -0
- package/package.json +200 -0
- package/src/fonts.css +33 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { S as SelectOption } from './SelectTrigger-By0iPBI3.cjs';
|
|
2
|
+
export { a as SelectTrigger, b as SelectTriggerProps, s as selectTriggerLabel } from './SelectTrigger-By0iPBI3.cjs';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
5
|
+
import { VariantProps } from 'class-variance-authority';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Find the next enabled option index moving `dir` (1 = down, -1 = up) from
|
|
9
|
+
* `from`, skipping `disabled` rows and clamping at the ends (no wrap). If no
|
|
10
|
+
* enabled row exists in that direction, `from` is returned unchanged. Pure —
|
|
11
|
+
* unit-testable in isolation.
|
|
12
|
+
*/
|
|
13
|
+
declare function nextEnabledIndex(options: SelectOption[], from: number, dir: 1 | -1): number;
|
|
14
|
+
/** Options for {@link useSelectListbox}. Trigger-agnostic — any button-shaped
|
|
15
|
+
* trigger (field, line, inline) can drive the same listbox orchestration. */
|
|
16
|
+
interface UseSelectListboxOptions {
|
|
17
|
+
/** The options to choose from (array-of-data API). */
|
|
18
|
+
options: SelectOption[];
|
|
19
|
+
/** Controlled selection. `string` in single mode, `string[]` in multi. */
|
|
20
|
+
value?: string | string[];
|
|
21
|
+
/** Uncontrolled initial selection. */
|
|
22
|
+
defaultValue?: string | string[];
|
|
23
|
+
/** Fires with the next selection — `string` (single) or `string[]` (multi). */
|
|
24
|
+
onValueChange?: (value: string | string[]) => void;
|
|
25
|
+
/** Single (default) vs multi select. */
|
|
26
|
+
multiple?: boolean;
|
|
27
|
+
/** Disabled — the trigger won't open and keys are ignored. */
|
|
28
|
+
disabled?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Whether a single-select pick closes the listbox. Default `true` (Select /
|
|
31
|
+
* InlineSelect behaviour, unchanged). When `false`, single-select does NOT
|
|
32
|
+
* close on pick — it stays open like multi, keeping the active row on the
|
|
33
|
+
* chosen option. Multi never closes on pick regardless of this flag. Filter
|
|
34
|
+
* passes `false` (its dropdown persists so several picks / a Reset are
|
|
35
|
+
* possible without reopening).
|
|
36
|
+
*/
|
|
37
|
+
closeOnSelect?: boolean;
|
|
38
|
+
/** Base id for the widget (trigger id); the listbox id derives from it. */
|
|
39
|
+
id: string;
|
|
40
|
+
/** Consumer's forwarded ref to the trigger button (merged with the internal ref). */
|
|
41
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The ARIA popup + activedescendant attributes a trigger button must spread.
|
|
45
|
+
* `role` is intentionally NOT included — a field trigger uses `role="combobox"`
|
|
46
|
+
* to legitimize `aria-activedescendant`/`aria-controls` (ADR-0013 #3), which it
|
|
47
|
+
* sets itself; these attributes are the shared wiring both triggers need.
|
|
48
|
+
*/
|
|
49
|
+
interface SelectTriggerAriaProps {
|
|
50
|
+
onClick: () => void;
|
|
51
|
+
onKeyDown: (event: React.KeyboardEvent<HTMLButtonElement>) => void;
|
|
52
|
+
"aria-haspopup": "listbox";
|
|
53
|
+
"aria-expanded": boolean;
|
|
54
|
+
"aria-controls": string | undefined;
|
|
55
|
+
"aria-activedescendant": string | undefined;
|
|
56
|
+
}
|
|
57
|
+
/** The props a trigger passes straight to `<SelectListbox>` (minus the a11y name). */
|
|
58
|
+
interface SelectListboxOwnProps {
|
|
59
|
+
id: string;
|
|
60
|
+
options: SelectOption[];
|
|
61
|
+
selected: string[];
|
|
62
|
+
multiple: boolean;
|
|
63
|
+
activeIndex: number;
|
|
64
|
+
anchorRect: DOMRect | null;
|
|
65
|
+
onSelect: (value: string) => void;
|
|
66
|
+
onActiveChange: (index: number) => void;
|
|
67
|
+
}
|
|
68
|
+
/** Everything a trigger + `<SelectListbox>` need to render a select. */
|
|
69
|
+
interface UseSelectListboxResult {
|
|
70
|
+
/** Currently selected values (normalized to an array for both modes). */
|
|
71
|
+
selected: string[];
|
|
72
|
+
/** Whether the listbox is open (flips the trigger caret + `aria-expanded`). */
|
|
73
|
+
open: boolean;
|
|
74
|
+
/** Callback ref for the trigger button (merges the consumer's ref + internal). */
|
|
75
|
+
setTriggerRef: (node: HTMLButtonElement | null) => void;
|
|
76
|
+
/** id of the listbox element (the trigger's `aria-controls` target). */
|
|
77
|
+
listboxId: string;
|
|
78
|
+
/** id of the active `aria-activedescendant` row, or undefined when none. */
|
|
79
|
+
activeId: string | undefined;
|
|
80
|
+
/** ARIA + handler props to spread on the trigger button. */
|
|
81
|
+
triggerProps: SelectTriggerAriaProps;
|
|
82
|
+
/** Props to spread on `<SelectListbox>` (supply the a11y name separately). */
|
|
83
|
+
listboxProps: SelectListboxOwnProps;
|
|
84
|
+
/** Close the listbox; `restoreFocus` returns focus to the trigger. */
|
|
85
|
+
closeListbox: (restoreFocus: boolean) => void;
|
|
86
|
+
/** Resolved display text for the trigger (from `selectTriggerLabel`). */
|
|
87
|
+
text: string;
|
|
88
|
+
/** Whether `text` is the placeholder (muted) vs a real value. */
|
|
89
|
+
isPlaceholder: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Clear the selection, committing the empty value through the same
|
|
92
|
+
* controlled/uncontrolled + `onValueChange` path as a normal pick (single →
|
|
93
|
+
* `""`, multi → `[]`). Does NOT close the listbox — the caller decides. Used
|
|
94
|
+
* by Filter's Reset footer.
|
|
95
|
+
*/
|
|
96
|
+
reset: () => void;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Trigger-agnostic orchestration for a select-style listbox widget — extracted
|
|
100
|
+
* from `Select` so alternate triggers (`InlineSelect`) reuse the exact same
|
|
101
|
+
* behavior. Owns:
|
|
102
|
+
*
|
|
103
|
+
* - selection state (controlled via `value`, uncontrolled via `defaultValue`),
|
|
104
|
+
* - `open` / `activeIndex` / `anchorRect`, the merged trigger ref,
|
|
105
|
+
* - the type-ahead buffer, reposition-on-scroll/resize, outside-`pointerdown`
|
|
106
|
+
* close, the full keydown model (↑/↓/Home/End/Enter/Space/Escape/Tab +
|
|
107
|
+
* type-ahead, disabled-skip, no-wrap clamp), and the select/click handlers.
|
|
108
|
+
*
|
|
109
|
+
* Focus stays on the trigger; the roving highlight lives in the portaled
|
|
110
|
+
* listbox via `aria-activedescendant` (ADR-0013 #2). The consumer supplies a
|
|
111
|
+
* `placeholder` to `selectTriggerLabel` itself if it needs the resolved text —
|
|
112
|
+
* this hook exposes the raw pieces; `text`/`isPlaceholder` are computed against
|
|
113
|
+
* the passed `placeholder` below.
|
|
114
|
+
*/
|
|
115
|
+
declare function useSelectListbox(options: UseSelectListboxOptions & {
|
|
116
|
+
placeholder?: string;
|
|
117
|
+
}): UseSelectListboxResult;
|
|
118
|
+
|
|
119
|
+
interface SelectProps extends Omit<React.ComponentProps<"button">, "value" | "defaultValue" | "onChange"> {
|
|
120
|
+
/** The options to choose from (array-of-data API, not compound children). */
|
|
121
|
+
options: SelectOption[];
|
|
122
|
+
/** Controlled selection. `string` in single mode, `string[]` in multi. */
|
|
123
|
+
value?: string | string[];
|
|
124
|
+
/** Uncontrolled initial selection. */
|
|
125
|
+
defaultValue?: string | string[];
|
|
126
|
+
/** Fires with the next selection — `string` (single) or `string[]` (multi). */
|
|
127
|
+
onValueChange?: (value: string | string[]) => void;
|
|
128
|
+
/** Single (default) vs multi select. */
|
|
129
|
+
multiple?: boolean;
|
|
130
|
+
/** `field` (bordered box, default) | `line` (bottom border only). */
|
|
131
|
+
variation?: "field" | "line";
|
|
132
|
+
/** Shown when nothing is selected. */
|
|
133
|
+
placeholder?: string;
|
|
134
|
+
/** Uppercase label above the field. */
|
|
135
|
+
label?: React.ReactNode;
|
|
136
|
+
/** Error state — destructive border/label/hint. */
|
|
137
|
+
error?: boolean;
|
|
138
|
+
/** Helper text below the field; destructive when `error`. */
|
|
139
|
+
hint?: React.ReactNode;
|
|
140
|
+
/** Leading adornment in the trigger (decorative). */
|
|
141
|
+
leadingSlot?: React.ReactNode;
|
|
142
|
+
/**
|
|
143
|
+
* Toggles the resting visibility of the bottom line on the **`line`**
|
|
144
|
+
* variation only (mirrors `Input`). Default `true` (line visible at rest).
|
|
145
|
+
* When `false`, the bottom line is hidden at rest (transparent) but still
|
|
146
|
+
* appears on focus (accent) and on error (destructive); the 1px `border-b` is
|
|
147
|
+
* kept in all cases so there is no layout shift. Has NO effect on the `field`
|
|
148
|
+
* variation.
|
|
149
|
+
*/
|
|
150
|
+
showBottomLine?: boolean;
|
|
151
|
+
/** Class names for the outer wrapper (the label/field/hint stack). */
|
|
152
|
+
wrapperClassName?: string;
|
|
153
|
+
/** Class names for the trigger field row. */
|
|
154
|
+
fieldClassName?: string;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Select — a shared base select with a custom, portaled dropdown. Single and
|
|
158
|
+
* multi in one component; two visual variations (`field` / `line`); one `lg`
|
|
159
|
+
* size. Uncontrolled by default (`defaultValue`) with a controlled escape hatch
|
|
160
|
+
* (`value` + `onValueChange`).
|
|
161
|
+
*
|
|
162
|
+
* The trigger is a `<button>` styled as an input field (reusing `inputVariants`
|
|
163
|
+
* — the Figma Select field IS the base-input field). The dropdown is a portaled
|
|
164
|
+
* `role="listbox"` positioned from the trigger's rect, flipping above when short
|
|
165
|
+
* on room and repositioning on scroll/resize. Focus stays on the trigger via
|
|
166
|
+
* `aria-activedescendant` (no focus trap): ↑/↓/Home/End move the active row,
|
|
167
|
+
* Enter/Space toggle, Escape closes and restores focus, type-ahead jumps to a
|
|
168
|
+
* matching label, and disabled rows are skipped. `ref` is a normal React 19
|
|
169
|
+
* prop, forwarded to the trigger button.
|
|
170
|
+
*
|
|
171
|
+
* The trigger-agnostic orchestration (selection state, open/active/anchor, the
|
|
172
|
+
* keyboard model, type-ahead, reposition + outside-click) lives in the shared
|
|
173
|
+
* `useSelectListbox` hook; this component wires the hook to the field trigger +
|
|
174
|
+
* portaled listbox.
|
|
175
|
+
*/
|
|
176
|
+
declare function Select({ options, value: valueProp, defaultValue, onValueChange, multiple, variation, placeholder, label, error, hint, leadingSlot, showBottomLine, disabled, id: idProp, className, wrapperClassName, fieldClassName, ref, ...props }: SelectProps): React.JSX.Element;
|
|
177
|
+
|
|
178
|
+
/** How the portaled panel is sized horizontally (see {@link computeListboxHorizontal}). */
|
|
179
|
+
type ListboxWidthMode = "trigger" | "auto";
|
|
180
|
+
/**
|
|
181
|
+
* Pure placement math for the portaled panel. Given the trigger's rect, the
|
|
182
|
+
* measured panel height, and the viewport height, decide whether the panel goes
|
|
183
|
+
* below (default) or flips above, and return the absolute `top`/`left`/`width`
|
|
184
|
+
* (in document coordinates the caller offsets by scroll).
|
|
185
|
+
*
|
|
186
|
+
* Flips above only when there is no room below AND there is room above — so a
|
|
187
|
+
* panel taller than either side stays below (then scrolls). Kept free of the
|
|
188
|
+
* DOM/React so the branch is unit-testable.
|
|
189
|
+
*/
|
|
190
|
+
declare function computeListboxPosition(anchor: DOMRect, listboxHeight: number, viewportHeight: number): {
|
|
191
|
+
top: number;
|
|
192
|
+
left: number;
|
|
193
|
+
width: number;
|
|
194
|
+
placement: "top" | "bottom";
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* Pure horizontal-sizing math for the portaled panel — the width/left half of
|
|
198
|
+
* placement, split out from {@link computeListboxPosition} (which owns the
|
|
199
|
+
* vertical top/flip) so each branch is unit-testable and Select's behaviour is
|
|
200
|
+
* provably untouched.
|
|
201
|
+
*
|
|
202
|
+
* - `"trigger"` (Select, default): the panel matches the trigger exactly — a
|
|
203
|
+
* fixed pixel `width` = `anchor.width` at `left` = `anchor.left`. Byte-for-byte
|
|
204
|
+
* what Select produced before this helper existed.
|
|
205
|
+
* - `"auto"` (InlineSelect): the panel sizes to its content. `width` is left
|
|
206
|
+
* undefined (the caller applies `width: "max-content"` in the style), bounded
|
|
207
|
+
* by `minWidth` = `anchor.width` (never narrower than the trigger) and
|
|
208
|
+
* `maxWidth` = viewport − 2×margin (never wider than the viewport). `left` is
|
|
209
|
+
* clamped into `[margin, viewportWidth − margin − measuredWidth]` so the
|
|
210
|
+
* measured panel never overflows either edge; the lower bound wins if the
|
|
211
|
+
* viewport is narrower than the panel (clamp collapses to `margin`).
|
|
212
|
+
*/
|
|
213
|
+
declare function computeListboxHorizontal(anchor: DOMRect, widthMode: ListboxWidthMode, measuredWidth: number, viewportWidth: number, margin: number): {
|
|
214
|
+
left: number;
|
|
215
|
+
width?: number;
|
|
216
|
+
minWidth?: number;
|
|
217
|
+
maxWidth?: number;
|
|
218
|
+
};
|
|
219
|
+
interface SelectListboxProps {
|
|
220
|
+
/** id of the listbox element (the trigger's `aria-controls` target). */
|
|
221
|
+
id: string;
|
|
222
|
+
options: SelectOption[];
|
|
223
|
+
/** Currently selected values (normalized to an array for both modes). */
|
|
224
|
+
selected: string[];
|
|
225
|
+
/** Multi-select: rows show a leading checkbox + `aria-multiselectable`. */
|
|
226
|
+
multiple: boolean;
|
|
227
|
+
/** Index of the roving `aria-activedescendant` highlight (-1 = none). */
|
|
228
|
+
activeIndex: number;
|
|
229
|
+
/** The trigger's rect, captured on open + scroll/resize (null → not placed). */
|
|
230
|
+
anchorRect: DOMRect | null;
|
|
231
|
+
/**
|
|
232
|
+
* How the panel is sized horizontally. `"trigger"` (default) matches the
|
|
233
|
+
* trigger's width/left (Select). `"auto"` sizes to content, never narrower
|
|
234
|
+
* than the trigger nor wider than the viewport, clamped inside the viewport
|
|
235
|
+
* (InlineSelect). See {@link computeListboxHorizontal}.
|
|
236
|
+
*/
|
|
237
|
+
widthMode?: ListboxWidthMode;
|
|
238
|
+
/** Toggle/choose a value (single closes upstream; multi stays open). */
|
|
239
|
+
onSelect: (value: string) => void;
|
|
240
|
+
/** Move the active highlight (pointer hover keeps keyboard + mouse in sync). */
|
|
241
|
+
onActiveChange: (index: number) => void;
|
|
242
|
+
/**
|
|
243
|
+
* Optional content pinned BELOW the scrollable list (e.g. Filter's Reset
|
|
244
|
+
* button). When `undefined` the panel renders EXACTLY as before — the `<ul>`
|
|
245
|
+
* IS the portaled/positioned card (no DOM or class change for Select /
|
|
246
|
+
* InlineSelect). When provided, the card chrome moves to a wrapping panel
|
|
247
|
+
* `<div>` (a flex column): the scrolling `role="listbox"` on top and this
|
|
248
|
+
* footer pinned below, staying visible while the list scrolls under the
|
|
249
|
+
* `max-height` cap. The footer is outside the `role="listbox"` (it is not an
|
|
250
|
+
* option), so it must supply its own semantics/labels.
|
|
251
|
+
*/
|
|
252
|
+
footer?: React.ReactNode;
|
|
253
|
+
/** Accessible name for the listbox (mirrors the trigger's name). */
|
|
254
|
+
"aria-label"?: string;
|
|
255
|
+
"aria-labelledby"?: string;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* The portaled dropdown panel. Renders through `createPortal` into
|
|
259
|
+
* `document.body` (so it escapes any `overflow:hidden`/stacking ancestor),
|
|
260
|
+
* absolutely positioned from the trigger's rect via `computeListboxPosition`
|
|
261
|
+
* (matched width, below by default, flips above when short on room), capped at
|
|
262
|
+
* `LISTBOX_MAX_HEIGHT` with internal scroll.
|
|
263
|
+
*
|
|
264
|
+
* Selection semantics live on the `role="option"` rows (`aria-selected`); the
|
|
265
|
+
* multi-select checkbox is a *visual mirror* only — kept out of the tab/AT flow
|
|
266
|
+
* (`tabIndex=-1`, `aria-hidden`) so the option is the single source of truth for
|
|
267
|
+
* assistive tech. Focus never enters the panel (activedescendant pattern), so
|
|
268
|
+
* rows are chosen via `onMouseDown` (before the trigger's outside-click
|
|
269
|
+
* `pointerdown` can fire) rather than a focus-stealing click.
|
|
270
|
+
*/
|
|
271
|
+
declare function SelectListbox({ id, options, selected, multiple, activeIndex, anchorRect, widthMode, onSelect, onActiveChange, footer, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, }: SelectListboxProps): React.ReactPortal;
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Select styling — the parts of the Select that are NOT already solved by
|
|
275
|
+
* `inputVariants`. Binds ONLY to the semantic token layer (never primitives,
|
|
276
|
+
* never arbitrary values); theme switching is automatic via the `.dark` class,
|
|
277
|
+
* so no `dark:` variants are needed.
|
|
278
|
+
*
|
|
279
|
+
* The trigger's field-row styling (field/line × focus-border × error) is reused
|
|
280
|
+
* verbatim from `../input/inputVariants` — the Figma Select field IS the
|
|
281
|
+
* base-input field — so it is NOT re-declared here. This file owns only:
|
|
282
|
+
*
|
|
283
|
+
* - `selectListboxVariants` — the portaled dropdown panel (card surface).
|
|
284
|
+
* - `selectOptionVariants` — the option rows (resting / active / selected /
|
|
285
|
+
* disabled), where "active" is the roving `aria-activedescendant` highlight
|
|
286
|
+
* (keyboard/pointer), NOT the browser `:focus` (focus never leaves the
|
|
287
|
+
* trigger in the activedescendant pattern).
|
|
288
|
+
*/
|
|
289
|
+
/**
|
|
290
|
+
* The portaled dropdown surface. A card: white background, 1px card border,
|
|
291
|
+
* 4px radius (`radius/sm`, matching the `field` trigger), and the Figma
|
|
292
|
+
* `shadow/s` drop shadow. Vertical padding gives the first/last rows breathing
|
|
293
|
+
* room; `max-height` + `overflow-y-auto` cap the list and scroll internally
|
|
294
|
+
* (the pixel cap is applied inline in `SelectListbox` alongside the measured
|
|
295
|
+
* position, since it is layout- not token-driven).
|
|
296
|
+
*/
|
|
297
|
+
declare const selectListboxVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
298
|
+
type SelectListboxVariantsProps = VariantProps<typeof selectListboxVariants>;
|
|
299
|
+
/**
|
|
300
|
+
* Footer-mode panel chrome. When `<SelectListbox>` gets a `footer` slot the
|
|
301
|
+
* card surface (background/border/radius/shadow) moves from the `<ul>` to a
|
|
302
|
+
* wrapping panel `<div>`, so the footer can pin BELOW the scrollable list while
|
|
303
|
+
* the list scrolls under the `max-height` cap. The `<ul>` inside then carries
|
|
304
|
+
* ONLY its scroll + `py-1` inset (see `selectListboxScrollVariants`), never the
|
|
305
|
+
* chrome — keeping the no-footer path (the `<ul>` as the panel) byte-identical.
|
|
306
|
+
*
|
|
307
|
+
* The panel itself is a flex COLUMN clipping to its rounded corners
|
|
308
|
+
* (`overflow-hidden`) so the footer's top border and the list's scroll both sit
|
|
309
|
+
* inside the radius; `min-h-0` lets the `<ul>` shrink and scroll rather than
|
|
310
|
+
* push the footer out of the capped panel.
|
|
311
|
+
*/
|
|
312
|
+
declare const selectListboxPanelVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
313
|
+
/**
|
|
314
|
+
* The scrolling `<ul>` when it lives INSIDE a footer panel: it owns the scroll
|
|
315
|
+
* and the `py-1` inset (moved off the panel chrome above), and `min-h-0` +
|
|
316
|
+
* `flex-1` so it takes the remaining height and scrolls under the cap while the
|
|
317
|
+
* footer stays pinned. No card chrome here — the panel owns it.
|
|
318
|
+
*/
|
|
319
|
+
declare const selectListboxScrollVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
320
|
+
/**
|
|
321
|
+
* The pinned footer region under the list (Filter's Reset row). A top divider
|
|
322
|
+
* (`border-t-card-border`) separates it from the scrolling list; it never
|
|
323
|
+
* scrolls. Horizontal padding matches an option row's inset (`px-3`) so the
|
|
324
|
+
* footer's content left-aligns with the option labels.
|
|
325
|
+
*/
|
|
326
|
+
declare const selectListboxFooterVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
327
|
+
/**
|
|
328
|
+
* An option row. Layout is a horizontal flex row (leading checkbox in multi);
|
|
329
|
+
* typography is `body-03` (Archivo 14/20). Colours bind to the Figma
|
|
330
|
+
* `selectable-list-item` (node 4921:8203) tokens — the **card/neutral** family
|
|
331
|
+
* (this is content on a card surface), NOT the `input-*` family the trigger
|
|
332
|
+
* borrows: resting text `text-foreground`, disabled text `text-foreground-muted`
|
|
333
|
+
* (the row is also skipped by keyboard nav in `Select`). The `active` state is
|
|
334
|
+
* the keyboard/pointer highlight driven by `aria-activedescendant` — it fills
|
|
335
|
+
* with `bg-card-accent` (Figma `card/neutral/normal/accent`) so the highlight
|
|
336
|
+
* reads as "this row is targeted".
|
|
337
|
+
*
|
|
338
|
+
* `selected` differs by mode (`multiple`):
|
|
339
|
+
* - **single**: the single-select selected state — a brand-tinted row
|
|
340
|
+
* (`bg-card-brand-accent`), a 3px left accent bar
|
|
341
|
+
* (`border-l-3 border-l-card-brand-border-accent`), and brand foreground text
|
|
342
|
+
* (`text-card-brand-foreground`). NO trailing check — the fill + bar are the
|
|
343
|
+
* affordance. This wins over the neutral `active` highlight so a selected row
|
|
344
|
+
* stays branded on hover.
|
|
345
|
+
* - **multi**: no row tint — the leading checkbox carries the selected look
|
|
346
|
+
* (matching the Figma multiselect/selected state), and the neutral `active`
|
|
347
|
+
* highlight still applies on hover.
|
|
348
|
+
*/
|
|
349
|
+
declare const selectOptionVariants: (props?: ({
|
|
350
|
+
active?: boolean | null | undefined;
|
|
351
|
+
selected?: boolean | null | undefined;
|
|
352
|
+
multiple?: boolean | null | undefined;
|
|
353
|
+
disabled?: boolean | null | undefined;
|
|
354
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
355
|
+
type SelectOptionVariantsProps = VariantProps<typeof selectOptionVariants>;
|
|
356
|
+
|
|
357
|
+
export { type ListboxWidthMode, Select, SelectListbox, type SelectListboxOwnProps, type SelectListboxProps, type SelectListboxVariantsProps, SelectOption, type SelectOptionVariantsProps, type SelectProps, type SelectTriggerAriaProps, type UseSelectListboxOptions, type UseSelectListboxResult, computeListboxHorizontal, computeListboxPosition, nextEnabledIndex, selectListboxFooterVariants, selectListboxPanelVariants, selectListboxScrollVariants, selectListboxVariants, selectOptionVariants, useSelectListbox };
|