@weichenlin/swell-ui 0.0.0-stage → 0.2.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/README.md +287 -2
- package/dist/index.d.ts +659 -0
- package/dist/index.js +3453 -0
- package/dist/styles.css +6 -0
- package/dist/theme.css +207 -0
- package/dist/themes/warm.css +63 -0
- package/dist/typography.css +12 -0
- package/package.json +74 -3
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,659 @@
|
|
|
1
|
+
import { ClassValue } from "clsx";
|
|
2
|
+
import { VariantProps } from "class-variance-authority";
|
|
3
|
+
import { ComponentProps, MouseEvent, ReactElement, ReactNode } from "react";
|
|
4
|
+
//#region src/components/badge/badge.d.ts
|
|
5
|
+
type BadgeTone = 'neutral' | 'info' | 'success' | 'warning' | 'danger';
|
|
6
|
+
type BadgeVariant = 'subtle' | 'outline' | 'solid';
|
|
7
|
+
type BadgeSize = 'sm' | 'md';
|
|
8
|
+
type BadgeProps = Omit<ComponentProps<'span'>, 'onClick'> & {
|
|
9
|
+
tone?: BadgeTone;
|
|
10
|
+
variant?: BadgeVariant;
|
|
11
|
+
size?: BadgeSize;
|
|
12
|
+
/** Leading, decorative glyph (hidden from assistive tech). Ignored while `busy`. */
|
|
13
|
+
icon?: ReactNode;
|
|
14
|
+
/** In-progress state: swaps the icon for a spinning ring (a static ring under reduced motion). */
|
|
15
|
+
busy?: boolean;
|
|
16
|
+
/** Visually-hidden prefix for screen readers, e.g. "Health" reads as "Health: Unknown". */
|
|
17
|
+
context?: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function Badge({ tone, variant, size, icon, busy, context, className, children, ...props }: BadgeProps): import("react").JSX.Element;
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/components/tooltip.d.ts
|
|
22
|
+
type Side = 'top' | 'bottom' | 'left' | 'right';
|
|
23
|
+
type TriggerProps = {
|
|
24
|
+
'aria-describedby'?: string;
|
|
25
|
+
};
|
|
26
|
+
type TooltipProps = {
|
|
27
|
+
/** Nothing renders (and no aria-describedby is added) when empty. */
|
|
28
|
+
content?: ReactNode;
|
|
29
|
+
/** Preferred side; flips to the opposite one when it doesn't fit the viewport. */
|
|
30
|
+
side?: Side;
|
|
31
|
+
/**
|
|
32
|
+
* Link the tooltip to the trigger via aria-describedby. Turn off when the
|
|
33
|
+
* tooltip only repeats the trigger's accessible name (e.g. icon button labels).
|
|
34
|
+
*/
|
|
35
|
+
describe?: boolean;
|
|
36
|
+
/** Classes for the wrapper that anchors the tooltip. */
|
|
37
|
+
className?: string;
|
|
38
|
+
children: ReactElement<TriggerProps>;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Hover/focus tooltip around any element. The bubble is portaled to `<body>` with
|
|
42
|
+
* fixed positioning, so scroll containers (tables, drawers) never clip it.
|
|
43
|
+
* Events are read on the wrapper, so aria-disabled triggers work; React still
|
|
44
|
+
* treats the portaled bubble as inside the wrapper, so the pointer can rest on it.
|
|
45
|
+
*/
|
|
46
|
+
export declare function Tooltip({ content, side, describe, className, children }: TooltipProps): import("react").JSX.Element;
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/components/button/button.d.ts
|
|
49
|
+
declare const buttonVariants: (props?: ({
|
|
50
|
+
intent?: "surface" | "primary" | "secondary" | "dark" | "ghost" | null | undefined;
|
|
51
|
+
size?: "sm" | "md" | "lg" | null | undefined;
|
|
52
|
+
tone?: "danger" | "default" | null | undefined;
|
|
53
|
+
fullWidth?: boolean | null | undefined;
|
|
54
|
+
square?: boolean | null | undefined;
|
|
55
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
56
|
+
type BaseProps = Omit<ComponentProps<'button'>, 'children'> & Omit<VariantProps<typeof buttonVariants>, 'square'> & {
|
|
57
|
+
/** Shows a spinner, keeps width and focus, blocks activation. */
|
|
58
|
+
loading?: boolean;
|
|
59
|
+
/** Announced through a polite live region while loading. */
|
|
60
|
+
loadingText?: string;
|
|
61
|
+
/** Tooltip explaining why the button is disabled; shown on hover and keyboard focus. */
|
|
62
|
+
disabledReason?: string;
|
|
63
|
+
/** Material-style press ripple; on by default. */
|
|
64
|
+
ripple?: boolean;
|
|
65
|
+
};
|
|
66
|
+
type TextButtonProps = BaseProps & {
|
|
67
|
+
icon?: never;
|
|
68
|
+
iconLeft?: ReactNode;
|
|
69
|
+
iconRight?: ReactNode;
|
|
70
|
+
children?: ReactNode;
|
|
71
|
+
tooltip?: never;
|
|
72
|
+
tooltipSide?: never;
|
|
73
|
+
};
|
|
74
|
+
type IconOnlyButtonProps = Omit<BaseProps, 'aria-label' | 'fullWidth'> & {
|
|
75
|
+
/** Renders a square icon-only button. */
|
|
76
|
+
icon: NonNullable<ReactNode>;
|
|
77
|
+
/** Required: an icon has no text to name the button. */
|
|
78
|
+
'aria-label': string;
|
|
79
|
+
/** Show the label as a tooltip on hover/focus. */
|
|
80
|
+
tooltip?: boolean;
|
|
81
|
+
tooltipSide?: TooltipProps['side'];
|
|
82
|
+
fullWidth?: never;
|
|
83
|
+
children?: never;
|
|
84
|
+
iconLeft?: never;
|
|
85
|
+
iconRight?: never;
|
|
86
|
+
};
|
|
87
|
+
type ButtonProps = TextButtonProps | IconOnlyButtonProps;
|
|
88
|
+
export declare function Button(props: ButtonProps): import("react").JSX.Element;
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region src/components/card/card.d.ts
|
|
91
|
+
type CardElement = 'div' | 'section' | 'article';
|
|
92
|
+
type CardProps = ComponentProps<'div'> & {
|
|
93
|
+
/** `section`/`article` are named by their CardHeader title. */
|
|
94
|
+
as?: CardElement;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Bordered surface for a group of related content. No padding of its own: CardHeader and
|
|
98
|
+
* CardContent add it, so full-bleed rows (lists, tables) can sit edge to edge.
|
|
99
|
+
*/
|
|
100
|
+
export declare function Card({ as: Comp, className, ...props }: CardProps): import("react").JSX.Element;
|
|
101
|
+
type CardHeaderProps = Omit<ComponentProps<'div'>, 'title' | 'children'> & {
|
|
102
|
+
title: ReactNode;
|
|
103
|
+
description?: ReactNode;
|
|
104
|
+
/** Trailing control, e.g. a "View all" link. */
|
|
105
|
+
action?: ReactNode;
|
|
106
|
+
headingLevel?: 2 | 3;
|
|
107
|
+
};
|
|
108
|
+
export declare function CardHeader({ title, description, action, headingLevel, className, ...props }: CardHeaderProps): import("react").JSX.Element;
|
|
109
|
+
export declare function CardContent({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region src/components/checkbox/choice-row.d.ts
|
|
112
|
+
/**
|
|
113
|
+
* Either a visible label, or only an aria-label when the context already names the control
|
|
114
|
+
* (a table row, a toolbar). Same idea as the input family's FieldLabelProps.
|
|
115
|
+
*/
|
|
116
|
+
type ChoiceLabelProps = {
|
|
117
|
+
label: ReactNode;
|
|
118
|
+
'aria-label'?: string;
|
|
119
|
+
} | {
|
|
120
|
+
label?: never;
|
|
121
|
+
'aria-label': string;
|
|
122
|
+
};
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/components/checkbox/checkbox.d.ts
|
|
125
|
+
type NativeCheckboxProps = Omit<ComponentProps<'input'>, 'type' | 'size' | 'children' | 'aria-label'>;
|
|
126
|
+
type CheckboxProps = NativeCheckboxProps & ChoiceLabelProps & {
|
|
127
|
+
/** One muted line under the label, linked with aria-describedby. */
|
|
128
|
+
description?: ReactNode;
|
|
129
|
+
/** Truthy sets aria-invalid; text is shown under the label and linked with aria-describedby. */
|
|
130
|
+
error?: ReactNode;
|
|
131
|
+
/**
|
|
132
|
+
* Partly selected (a "select all" over some rows): drawn as a dash, announced as mixed.
|
|
133
|
+
* A visual state only; the form still submits `checked`. The browser clears it on click, so
|
|
134
|
+
* derive it from the children's state and it stays right after every change.
|
|
135
|
+
*/
|
|
136
|
+
indeterminate?: boolean;
|
|
137
|
+
/** Classes for the `<input>`; `className` goes to the row. */
|
|
138
|
+
inputClassName?: string;
|
|
139
|
+
};
|
|
140
|
+
export declare function Checkbox({ label, description, error, indeterminate, className, inputClassName, ref, checked, 'aria-describedby': describedBy, 'aria-invalid': ariaInvalid, ...props }: CheckboxProps): import("react").JSX.Element;
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/components/checkbox/checkbox-group.d.ts
|
|
143
|
+
type CheckboxGroupProps = Omit<ComponentProps<'fieldset'>, 'children'> & {
|
|
144
|
+
/** Names the group (fieldset legend); title case noun, no trailing colon. */
|
|
145
|
+
legend: ReactNode;
|
|
146
|
+
/** Muted line under the legend, linked to the group with aria-describedby. */
|
|
147
|
+
description?: ReactNode;
|
|
148
|
+
/**
|
|
149
|
+
* Group-level message (e.g. "Pick at least one"), linked with aria-describedby. Not aria-invalid:
|
|
150
|
+
* ARIA 1.2 doesn't support it on the group role. Native `required` can't express "one of", so
|
|
151
|
+
* validate in your submit handler and pass the message here.
|
|
152
|
+
*/
|
|
153
|
+
error?: ReactNode;
|
|
154
|
+
orientation?: 'vertical' | 'horizontal';
|
|
155
|
+
/** Checkbox (or Switch) rows; each keeps its own name/checked. `disabled` reaches them natively. */
|
|
156
|
+
children: ReactNode;
|
|
157
|
+
};
|
|
158
|
+
/** A `<fieldset>` + `<legend>` around related checkboxes; holds no value of its own. */
|
|
159
|
+
export declare function CheckboxGroup({ legend, description, error, orientation, className, 'aria-describedby': describedByProp, children, ...props }: CheckboxGroupProps): import("react").JSX.Element;
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/components/modal/modal-shell.d.ts
|
|
162
|
+
/**
|
|
163
|
+
* Why the modal asks to close. `programmatic` is never sent by the modal itself; it is there for
|
|
164
|
+
* callers that route their own closes (e.g. after a successful submit) through the same handler.
|
|
165
|
+
*/
|
|
166
|
+
type ModalCloseReason = 'escape' | 'backdrop' | 'close-button' | 'programmatic';
|
|
167
|
+
//#endregion
|
|
168
|
+
//#region src/components/dialog/dialog.d.ts
|
|
169
|
+
type DialogSize = 'sm' | 'md' | 'lg';
|
|
170
|
+
/**
|
|
171
|
+
* Why the dialog asks to close. `programmatic` is never sent by the dialog itself; it is there for
|
|
172
|
+
* callers that route their own closes (e.g. after a successful submit) through the same handler.
|
|
173
|
+
*/
|
|
174
|
+
type DialogCloseReason = ModalCloseReason;
|
|
175
|
+
type DialogProps = Omit<ComponentProps<'dialog'>, 'open'> & {
|
|
176
|
+
open: boolean;
|
|
177
|
+
onOpenChange: (open: boolean, reason: DialogCloseReason) => void;
|
|
178
|
+
/** Max width: sm 384px (confirmations), md 480px (default), lg 640px (wide forms). */
|
|
179
|
+
size?: DialogSize;
|
|
180
|
+
/**
|
|
181
|
+
* Destructive confirmation: role="alertdialog", no close button by default, and a backdrop
|
|
182
|
+
* click doesn't close (it bounces instead). Put `autoFocus` on the least destructive button.
|
|
183
|
+
*/
|
|
184
|
+
alert?: boolean;
|
|
185
|
+
/** False blocks Esc, the backdrop and the close button (e.g. while a request is pending). */
|
|
186
|
+
dismissible?: boolean;
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Modal dialog on the native `<dialog>` + showModal() (behavior in ModalShell). Controlled: `open`
|
|
190
|
+
* drives it and every close request goes through `onOpenChange`.
|
|
191
|
+
*/
|
|
192
|
+
export declare function Dialog({ size, className, children, ...props }: DialogProps): import("react").JSX.Element;
|
|
193
|
+
type DialogHeaderProps = Omit<ComponentProps<'div'>, 'title'> & {
|
|
194
|
+
title: ReactNode;
|
|
195
|
+
description?: ReactNode;
|
|
196
|
+
/** Top-right close button. Defaults to on, except for `alert` dialogs (answer with the footer). */
|
|
197
|
+
closeButton?: boolean;
|
|
198
|
+
};
|
|
199
|
+
export declare function DialogHeader({ title, description, closeButton, className, ...props }: DialogHeaderProps): import("react").JSX.Element;
|
|
200
|
+
/** Scrolls when the content is taller than the space left between header and footer. */
|
|
201
|
+
export declare function DialogBody({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
202
|
+
/** Actions, right-aligned: Cancel first, the primary action last (rightmost). */
|
|
203
|
+
export declare function DialogFooter({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
204
|
+
//#endregion
|
|
205
|
+
//#region src/components/drawer/drawer.d.ts
|
|
206
|
+
type DrawerSide = 'left' | 'right';
|
|
207
|
+
type DrawerSize = 'sm' | 'md' | 'lg';
|
|
208
|
+
/** Same reasons as Dialog's; `programmatic` is for callers routing their own closes. */
|
|
209
|
+
type DrawerCloseReason = ModalCloseReason;
|
|
210
|
+
type DrawerProps = Omit<ComponentProps<'dialog'>, 'open'> & {
|
|
211
|
+
open: boolean;
|
|
212
|
+
onOpenChange: (open: boolean, reason: DrawerCloseReason) => void;
|
|
213
|
+
/** Edge it slides out of. Defaults to right (details, filters); navigation passes left. */
|
|
214
|
+
side?: DrawerSide;
|
|
215
|
+
/** Width: sm 280px (navigation), md 384px (default, filters), lg 480px (details, forms). */
|
|
216
|
+
size?: DrawerSize;
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* Modal side panel on the native `<dialog>` (behavior shared with Dialog through ModalShell).
|
|
220
|
+
* Controlled through `open` / `onOpenChange(open, reason)`; Esc, the backdrop, DrawerHeader's close
|
|
221
|
+
* button and DrawerClose all ask through `onOpenChange`. Needs a name: `aria-label` /
|
|
222
|
+
* `aria-labelledby`, or a DrawerHeader title.
|
|
223
|
+
*/
|
|
224
|
+
export declare function Drawer({ side, size, className, children, ref, ...props }: DrawerProps): import("react").JSX.Element;
|
|
225
|
+
type DrawerHeaderProps = Omit<ComponentProps<'div'>, 'title'> & {
|
|
226
|
+
/** Also names the drawer. */
|
|
227
|
+
title: ReactNode;
|
|
228
|
+
description?: ReactNode;
|
|
229
|
+
};
|
|
230
|
+
/** Title, optional description and the close button, pinned above the body. */
|
|
231
|
+
export declare function DrawerHeader({ title, description, className, ...props }: DrawerHeaderProps): import("react").JSX.Element;
|
|
232
|
+
/** Fills the space between header and footer and scrolls on its own; they stay put. */
|
|
233
|
+
export declare function DrawerBody({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
234
|
+
/** Actions, right-aligned: Cancel first, the primary action last (rightmost). */
|
|
235
|
+
export declare function DrawerFooter({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
236
|
+
type DrawerCloseProps = Omit<ComponentProps<'button'>, 'children' | 'type' | 'aria-label' | 'onClick'> & {
|
|
237
|
+
/** Required: the button shows only an icon. */
|
|
238
|
+
'aria-label': string;
|
|
239
|
+
size?: 'sm' | 'md' | 'lg';
|
|
240
|
+
/** Defaults to X. */
|
|
241
|
+
icon?: ReactNode;
|
|
242
|
+
};
|
|
243
|
+
/** A ghost icon button that closes the drawer, for custom headers. */
|
|
244
|
+
export declare function DrawerClose({ size, icon, ...props }: DrawerCloseProps): import("react").JSX.Element;
|
|
245
|
+
//#endregion
|
|
246
|
+
//#region src/components/input/field.d.ts
|
|
247
|
+
type FieldSize = 'sm' | 'md' | 'lg';
|
|
248
|
+
type NativeInputProps = Omit<ComponentProps<'input'>, 'size' | 'children'>;
|
|
249
|
+
/** Props every input in the family shares. */
|
|
250
|
+
type FieldProps = NativeInputProps & {
|
|
251
|
+
/** Visible label, rendered as a real `<label>` above the field. */
|
|
252
|
+
label: string;
|
|
253
|
+
/** Outlined floating label: rests inside the field and moves onto the top border. */
|
|
254
|
+
floating?: boolean;
|
|
255
|
+
helperText?: ReactNode;
|
|
256
|
+
/** Truthy puts the field in the error state; the text replaces helperText. */
|
|
257
|
+
error?: ReactNode;
|
|
258
|
+
size?: FieldSize;
|
|
259
|
+
/** Decorative leading icon (aria-hidden) or plain text prefix such as `https://`. */
|
|
260
|
+
start?: ReactNode;
|
|
261
|
+
/** Decorative trailing icon (aria-hidden) or plain text suffix. */
|
|
262
|
+
end?: ReactNode;
|
|
263
|
+
/** Monospace with spellcheck/autocorrect off, for tags, SHAs and hostnames. */
|
|
264
|
+
mono?: boolean;
|
|
265
|
+
/** Shows a spinner and announces validatingText; the field stays editable. */
|
|
266
|
+
validating?: boolean;
|
|
267
|
+
validatingText?: string;
|
|
268
|
+
/** Classes for the `<input>`; `className` goes to the outer wrapper. */
|
|
269
|
+
inputClassName?: string;
|
|
270
|
+
};
|
|
271
|
+
/**
|
|
272
|
+
* Either a visible label, or only an aria-label when the context already names the field
|
|
273
|
+
* (a table cell, a toolbar filter). Floating needs a visible label.
|
|
274
|
+
*/
|
|
275
|
+
type FieldLabelProps = {
|
|
276
|
+
label: string;
|
|
277
|
+
floating?: boolean;
|
|
278
|
+
} | {
|
|
279
|
+
label?: never;
|
|
280
|
+
floating?: never;
|
|
281
|
+
'aria-label': string;
|
|
282
|
+
};
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region src/components/input/copy-input.d.ts
|
|
285
|
+
type CopyInputProps = Omit<FieldProps, 'type' | 'value' | 'defaultValue' | 'readOnly' | 'onChange'> & {
|
|
286
|
+
value: string;
|
|
287
|
+
};
|
|
288
|
+
export declare function CopyInput({ value, mono, size, onFocus, onClick, ...props }: CopyInputProps): import("react").JSX.Element;
|
|
289
|
+
//#endregion
|
|
290
|
+
//#region src/components/input/input.d.ts
|
|
291
|
+
/**
|
|
292
|
+
* Password and search have dedicated components (PasswordInput, SearchInput).
|
|
293
|
+
* No `number`: its spinners and wheel stepping misfire; use `inputMode="numeric"` instead.
|
|
294
|
+
*/
|
|
295
|
+
type InputType = 'text' | 'email' | 'url' | 'tel';
|
|
296
|
+
type InputProps = Omit<FieldProps, 'type' | 'label' | 'floating'> & FieldLabelProps & {
|
|
297
|
+
type?: InputType;
|
|
298
|
+
};
|
|
299
|
+
export declare function Input({ type, ...props }: InputProps): import("react").JSX.Element;
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region src/components/input/password-input.d.ts
|
|
302
|
+
type PasswordInputProps = Omit<FieldProps, 'type'> & {
|
|
303
|
+
type?: never;
|
|
304
|
+
};
|
|
305
|
+
export declare function PasswordInput({ autoComplete, size, ...props }: PasswordInputProps): import("react").JSX.Element;
|
|
306
|
+
//#endregion
|
|
307
|
+
//#region src/components/input/search-input.d.ts
|
|
308
|
+
type SearchInputProps = Omit<FieldProps, 'type' | 'label' | 'floating' | 'start'> & {
|
|
309
|
+
/** Required: a search field has no visible label. */
|
|
310
|
+
'aria-label': string;
|
|
311
|
+
/** Called after the clear button or Esc empties the field. */
|
|
312
|
+
onClear?: () => void;
|
|
313
|
+
label?: never;
|
|
314
|
+
floating?: never;
|
|
315
|
+
start?: never;
|
|
316
|
+
type?: never;
|
|
317
|
+
};
|
|
318
|
+
export declare function SearchInput({ onClear, onChange, onKeyDown, inputClassName, size, ...props }: SearchInputProps): import("react").JSX.Element;
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region src/components/meter/meter.d.ts
|
|
321
|
+
type MeterTone = BadgeTone;
|
|
322
|
+
type MeterSegment = {
|
|
323
|
+
label: string;
|
|
324
|
+
value: number;
|
|
325
|
+
tone: MeterTone;
|
|
326
|
+
};
|
|
327
|
+
type MeterProps = Omit<ComponentProps<'div'>, 'children'> & {
|
|
328
|
+
label: ReactNode;
|
|
329
|
+
/** Short trailing text on the label row, e.g. "9 of 13 report health". */
|
|
330
|
+
summary?: ReactNode;
|
|
331
|
+
/** Drawn in order; zero values are left out of both the bar and the legend. */
|
|
332
|
+
segments: MeterSegment[];
|
|
333
|
+
};
|
|
334
|
+
/**
|
|
335
|
+
* Stacked proportion bar with a legend. The bar is decorative; the legend list carries the
|
|
336
|
+
* numbers for assistive tech, so nothing is conveyed by color alone.
|
|
337
|
+
*/
|
|
338
|
+
export declare function Meter({ label, summary, segments, className, ...props }: MeterProps): import("react").JSX.Element;
|
|
339
|
+
//#endregion
|
|
340
|
+
//#region src/components/select/select.d.ts
|
|
341
|
+
/** `value` must be non-empty: `''` is reserved for "nothing chosen". */
|
|
342
|
+
type SelectOption = {
|
|
343
|
+
value: string;
|
|
344
|
+
/** Also the option's text, which typeahead and screen readers use. */
|
|
345
|
+
label: string;
|
|
346
|
+
/** Decorative (aria-hidden); shown in the picker and on the trigger while selected. */
|
|
347
|
+
icon?: ReactNode;
|
|
348
|
+
disabled?: boolean;
|
|
349
|
+
};
|
|
350
|
+
type SelectGroup = {
|
|
351
|
+
label: string;
|
|
352
|
+
options: SelectOption[];
|
|
353
|
+
};
|
|
354
|
+
type NativeSelectProps = Omit<ComponentProps<'select'>, 'size' | 'children' | 'multiple' | 'value' | 'defaultValue'>;
|
|
355
|
+
type SelectProps = NativeSelectProps & FieldLabelProps & {
|
|
356
|
+
options: (SelectOption | SelectGroup)[];
|
|
357
|
+
/** `''` means nothing chosen. */
|
|
358
|
+
value?: string;
|
|
359
|
+
defaultValue?: string;
|
|
360
|
+
/** Shown while nothing is chosen. Label-above only: a floating label takes its place (MUI). */
|
|
361
|
+
placeholder?: string;
|
|
362
|
+
helperText?: ReactNode;
|
|
363
|
+
/** Truthy puts the field in the error state; the text replaces helperText. */
|
|
364
|
+
error?: ReactNode;
|
|
365
|
+
size?: FieldSize;
|
|
366
|
+
/** Fixed decorative leading icon; the selected option's own icon wins when it has one. */
|
|
367
|
+
start?: ReactNode;
|
|
368
|
+
mono?: boolean;
|
|
369
|
+
/** Classes for the `<select>`; `className` goes to the outer wrapper. */
|
|
370
|
+
selectClassName?: string;
|
|
371
|
+
/** A native select can't be read-only; use disabled or a read-only Input. */
|
|
372
|
+
readOnly?: never;
|
|
373
|
+
/** Single choice only. */
|
|
374
|
+
multiple?: never;
|
|
375
|
+
/** The trailing slot belongs to the chevron. */
|
|
376
|
+
end?: never;
|
|
377
|
+
};
|
|
378
|
+
/**
|
|
379
|
+
* Single-choice select: a real `<select>` (native keyboard, typeahead, forms, validation and
|
|
380
|
+
* autofill), customized through `appearance: base-select` where supported. Same frame as Input.
|
|
381
|
+
*/
|
|
382
|
+
export declare function Select({ options, placeholder, helperText, error, size, start, mono, className, selectClassName, label, floating, id, required, disabled, value, defaultValue, onChange, ref, 'aria-describedby': describedByProp, 'aria-invalid': ariaInvalid, ...props }: SelectProps): import("react").JSX.Element;
|
|
383
|
+
//#endregion
|
|
384
|
+
//#region src/components/sidebar/sidebar.d.ts
|
|
385
|
+
/**
|
|
386
|
+
* Drawer open state shared by Sidebar and SidebarTrigger, which usually sit in different parts of
|
|
387
|
+
* the app shell. One per sidebar; no shortcuts, no persistence.
|
|
388
|
+
*/
|
|
389
|
+
export declare function SidebarProvider({ children }: {
|
|
390
|
+
children: ReactNode;
|
|
391
|
+
}): import("react").JSX.Element;
|
|
392
|
+
type SidebarLabel = {
|
|
393
|
+
'aria-label': string;
|
|
394
|
+
'aria-labelledby'?: never;
|
|
395
|
+
} | {
|
|
396
|
+
'aria-labelledby': string;
|
|
397
|
+
'aria-label'?: never;
|
|
398
|
+
};
|
|
399
|
+
type SidebarProps = Omit<ComponentProps<'nav'>, 'aria-label' | 'aria-labelledby'> & SidebarLabel;
|
|
400
|
+
/**
|
|
401
|
+
* App navigation. From 960px up it is docked at the start of the layout: 240px, full height, only
|
|
402
|
+
* the body scrolls. Below 960px it is hidden and SidebarTrigger opens the same content in a drawer.
|
|
403
|
+
* Needs a SidebarProvider around both.
|
|
404
|
+
*/
|
|
405
|
+
export declare function Sidebar({ className, children, ...props }: SidebarProps): import("react").JSX.Element;
|
|
406
|
+
type SidebarTriggerProps = Omit<ComponentProps<'button'>, 'children' | 'type' | 'aria-label' | 'aria-expanded' | 'aria-controls'> & {
|
|
407
|
+
'aria-label'?: string;
|
|
408
|
+
size?: 'sm' | 'md' | 'lg';
|
|
409
|
+
};
|
|
410
|
+
/** Menu button that opens the drawer; only shown below 960px. Focus returns here on close. */
|
|
411
|
+
export declare function SidebarTrigger({ 'aria-label': ariaLabel, className, onClick, ...props }: SidebarTriggerProps): import("react").JSX.Element;
|
|
412
|
+
/** Brand row, pinned above the body. In the drawer it also holds the close button. */
|
|
413
|
+
export declare function SidebarHeader({ className, children, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
414
|
+
/** The groups, between header and footer; the only part that scrolls. */
|
|
415
|
+
export declare function SidebarBody({ className, ref, onPointerMove, onPointerLeave, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
416
|
+
/** Pinned below the body. */
|
|
417
|
+
export declare function SidebarFooter({ className, ...props }: ComponentProps<'div'>): import("react").JSX.Element;
|
|
418
|
+
type SidebarGroupProps = ComponentProps<'div'> & {
|
|
419
|
+
/** Short sentence-case label above the items; also names the list for screen readers. */
|
|
420
|
+
label?: ReactNode;
|
|
421
|
+
};
|
|
422
|
+
export declare function SidebarGroup({ label, className, children, ...props }: SidebarGroupProps): import("react").JSX.Element;
|
|
423
|
+
type SidebarItemProps = ComponentProps<'a'> & {
|
|
424
|
+
/**
|
|
425
|
+
* Render the only child (usually a router Link) as the item, merging these props into it. The
|
|
426
|
+
* link sets href and aria-current="page"; the item is styled from them.
|
|
427
|
+
*/
|
|
428
|
+
asChild?: boolean;
|
|
429
|
+
};
|
|
430
|
+
/**
|
|
431
|
+
* A sidebar link. Plain `<a>` by default; with `asChild`, your router's Link. Mark the current one
|
|
432
|
+
* aria-current="page". Inside the drawer, a click the link handles in place (preventDefault, as
|
|
433
|
+
* router links do) closes the drawer; a modified click opens a new tab and leaves it open.
|
|
434
|
+
*/
|
|
435
|
+
export declare function SidebarItem({ asChild, className, children, ...props }: SidebarItemProps): import("react").JSX.Element;
|
|
436
|
+
/** Decorative 16px leading icon for a SidebarItem (hidden from assistive tech); takes the text color. */
|
|
437
|
+
export declare function SidebarIcon({ className, ...props }: ComponentProps<'span'>): import("react").JSX.Element;
|
|
438
|
+
/** Count at the end of a SidebarItem, as a small neutral Badge; part of the name ("Projects 8"). */
|
|
439
|
+
export declare function SidebarBadge({ className, ...props }: BadgeProps): import("react").JSX.Element;
|
|
440
|
+
//#endregion
|
|
441
|
+
//#region src/components/switch/switch.d.ts
|
|
442
|
+
type SwitchSize = 'sm' | 'md';
|
|
443
|
+
type NativeSwitchProps = Omit<ComponentProps<'input'>, 'type' | 'size' | 'children' | 'role' | 'aria-checked' | 'aria-label'>;
|
|
444
|
+
type SwitchProps = NativeSwitchProps & ChoiceLabelProps & {
|
|
445
|
+
/** One muted line under the label (what is true while it's on), linked with aria-describedby. */
|
|
446
|
+
description?: ReactNode;
|
|
447
|
+
/** Truthy sets aria-invalid; text is shown under the label and linked with aria-describedby. */
|
|
448
|
+
error?: ReactNode;
|
|
449
|
+
/** sm 28x14 for dense rows and tables, md 36x20 for settings. */
|
|
450
|
+
size?: SwitchSize;
|
|
451
|
+
/**
|
|
452
|
+
* A spinner in the thumb while the change is being saved: aria-busy, and clicks/Space are
|
|
453
|
+
* swallowed without disabling, so focus stays put.
|
|
454
|
+
*/
|
|
455
|
+
loading?: boolean;
|
|
456
|
+
/** `start`: label first and the switch pushed to the far end, as in a settings row. */
|
|
457
|
+
labelPosition?: 'end' | 'start';
|
|
458
|
+
/** Classes for the `<input>` (the track); `className` goes to the row. */
|
|
459
|
+
inputClassName?: string;
|
|
460
|
+
};
|
|
461
|
+
export declare function Switch({ label, description, error, size, loading, labelPosition, className, inputClassName, disabled, onChange, 'aria-describedby': describedBy, 'aria-invalid': ariaInvalid, ...props }: SwitchProps): import("react").JSX.Element;
|
|
462
|
+
//#endregion
|
|
463
|
+
//#region src/components/tabs/shared.d.ts
|
|
464
|
+
type TabsVariant = 'line' | 'segmented';
|
|
465
|
+
type TabsSize = 'sm' | 'md';
|
|
466
|
+
type TabContentProps = {
|
|
467
|
+
/** Decorative leading icon (hidden from assistive tech). */
|
|
468
|
+
icon?: ReactNode;
|
|
469
|
+
/** Trailing slot, usually a Badge; part of the accessible name (e.g. "Resources 12"). */
|
|
470
|
+
badge?: ReactNode;
|
|
471
|
+
children?: ReactNode;
|
|
472
|
+
};
|
|
473
|
+
//#endregion
|
|
474
|
+
//#region src/components/tabs/tab-nav.d.ts
|
|
475
|
+
type TabNavLabel = {
|
|
476
|
+
'aria-label': string;
|
|
477
|
+
'aria-labelledby'?: never;
|
|
478
|
+
} | {
|
|
479
|
+
'aria-labelledby': string;
|
|
480
|
+
'aria-label'?: never;
|
|
481
|
+
};
|
|
482
|
+
type TabNavProps = Omit<ComponentProps<'nav'>, 'aria-label' | 'aria-labelledby'> & TabNavLabel & {
|
|
483
|
+
variant?: TabsVariant;
|
|
484
|
+
size?: TabsSize;
|
|
485
|
+
/** Classes for the inner `<ul>` (the scrolling bar); `className` goes to the `<nav>`. */
|
|
486
|
+
listClassName?: string;
|
|
487
|
+
};
|
|
488
|
+
/**
|
|
489
|
+
* Tabs that change the URL: a `<nav>` of links, the current one marked (by the router, usually)
|
|
490
|
+
* with aria-current="page". Same look as Tabs, but link semantics: Tab moves between links, Enter
|
|
491
|
+
* follows one, and each can be opened in a new tab. For in-page panels, use Tabs.
|
|
492
|
+
*/
|
|
493
|
+
export declare function TabNav({ variant, size, className, listClassName, children, ...props }: TabNavProps): import("react").JSX.Element;
|
|
494
|
+
type TabNavLinkProps = ComponentProps<'a'> & TabContentProps & {
|
|
495
|
+
/**
|
|
496
|
+
* Render the only child (usually a router Link) as the tab, merging these props into it. The
|
|
497
|
+
* link sets href, aria-current="page" and aria-disabled; the tab is styled from them.
|
|
498
|
+
*/
|
|
499
|
+
asChild?: boolean;
|
|
500
|
+
};
|
|
501
|
+
/**
|
|
502
|
+
* A link styled as a tab. Plain `<a>` by default; with `asChild`, your router's Link (for an index
|
|
503
|
+
* route, make it current only on an exact match, or it stays current on every child route).
|
|
504
|
+
*/
|
|
505
|
+
export declare function TabNavLink({ asChild, icon, badge, className, onFocus, children, ...props }: TabNavLinkProps): import("react").JSX.Element;
|
|
506
|
+
//#endregion
|
|
507
|
+
//#region src/components/tabs/tabs.d.ts
|
|
508
|
+
type TabsActivationMode = 'automatic' | 'manual';
|
|
509
|
+
type TabsLabel = {
|
|
510
|
+
'aria-label': string;
|
|
511
|
+
'aria-labelledby'?: never;
|
|
512
|
+
} | {
|
|
513
|
+
'aria-labelledby': string;
|
|
514
|
+
'aria-label'?: never;
|
|
515
|
+
};
|
|
516
|
+
type TabsState = {
|
|
517
|
+
value: string;
|
|
518
|
+
defaultValue?: never;
|
|
519
|
+
onValueChange?: (value: string) => void;
|
|
520
|
+
} | {
|
|
521
|
+
value?: never;
|
|
522
|
+
defaultValue: string;
|
|
523
|
+
onValueChange?: (value: string) => void;
|
|
524
|
+
};
|
|
525
|
+
type TabsProps = Omit<ComponentProps<'div'>, 'defaultValue' | 'onChange' | 'aria-label' | 'aria-labelledby'> & TabsLabel & TabsState & {
|
|
526
|
+
/**
|
|
527
|
+
* `automatic` (default): arrow keys select as they move, for panels that show instantly.
|
|
528
|
+
* `manual`: arrows only move focus, Enter/Space selects; use it when a panel loads data.
|
|
529
|
+
*/
|
|
530
|
+
activationMode?: TabsActivationMode;
|
|
531
|
+
variant?: TabsVariant;
|
|
532
|
+
size?: TabsSize;
|
|
533
|
+
};
|
|
534
|
+
/**
|
|
535
|
+
* In-page tabs (WAI-ARIA APG tabs pattern): a tablist that switches panels without changing the
|
|
536
|
+
* URL. For tabs that navigate between routes, use TabNav.
|
|
537
|
+
*/
|
|
538
|
+
export declare function Tabs({ value, defaultValue, onValueChange, activationMode, variant, size, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, children, ...props }: TabsProps): import("react").JSX.Element;
|
|
539
|
+
type TabListProps = Omit<ComponentProps<'div'>, 'role'>;
|
|
540
|
+
export declare function TabList({ className, ref, onKeyDown, onPointerMove, onPointerLeave, children, ...props }: TabListProps): import("react").JSX.Element;
|
|
541
|
+
type TabProps = Omit<ComponentProps<'button'>, 'value' | 'role' | 'type' | 'children'> & TabContentProps & {
|
|
542
|
+
value: string;
|
|
543
|
+
};
|
|
544
|
+
export declare function Tab({ value, icon, badge, disabled, className, ref, onClick, onFocus, children, ...props }: TabProps): import("react").JSX.Element;
|
|
545
|
+
type TabPanelProps = Omit<ComponentProps<'div'>, 'role' | 'hidden'> & {
|
|
546
|
+
value: string;
|
|
547
|
+
/** Keep the panel (and its state) mounted while hidden; by default only the selected panel renders. */
|
|
548
|
+
keepMounted?: boolean;
|
|
549
|
+
};
|
|
550
|
+
export declare function TabPanel({ value, keepMounted, className, ...props }: TabPanelProps): import("react").JSX.Element | null;
|
|
551
|
+
//#endregion
|
|
552
|
+
//#region src/components/theme-switcher/use-theme.d.ts
|
|
553
|
+
type Theme = 'system' | 'light' | 'dark';
|
|
554
|
+
type UseThemeOptions = {
|
|
555
|
+
/** localStorage key the choice is saved under. */
|
|
556
|
+
storageKey?: string;
|
|
557
|
+
};
|
|
558
|
+
/** Persisted color theme; `system` clears data-theme so prefers-color-scheme decides. */
|
|
559
|
+
export declare function useTheme({ storageKey }?: UseThemeOptions): {
|
|
560
|
+
theme: Theme;
|
|
561
|
+
setTheme: import("react").Dispatch<import("react").SetStateAction<Theme>>;
|
|
562
|
+
};
|
|
563
|
+
//#endregion
|
|
564
|
+
//#region src/components/theme-switcher/theme-switcher.d.ts
|
|
565
|
+
type ThemeSwitcherProps = Omit<ComponentProps<'button'>, 'onChange' | 'value' | 'defaultValue' | 'children'> & {
|
|
566
|
+
value: Theme;
|
|
567
|
+
onChange: (value: Theme) => void;
|
|
568
|
+
};
|
|
569
|
+
/** Toggle the visible theme in one click, including when the initial choice follows the system. */
|
|
570
|
+
export declare function ThemeSwitcher({ value, onChange, onClick, className, 'aria-label': ariaLabel, ...props }: ThemeSwitcherProps): import("react").JSX.Element;
|
|
571
|
+
//#endregion
|
|
572
|
+
//#region src/components/toast/store.d.ts
|
|
573
|
+
type ToastType = 'neutral' | 'success' | 'info' | 'warning' | 'danger' | 'loading';
|
|
574
|
+
/** A button rendered with the toast's Button styling. Clicking it dismisses the toast unless `onClick` calls `event.preventDefault()`. */
|
|
575
|
+
type ToastActionButton = {
|
|
576
|
+
label: string;
|
|
577
|
+
onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
|
|
578
|
+
};
|
|
579
|
+
type ToastOptions = {
|
|
580
|
+
/** Reusing the id of a toast still on screen updates that toast in place instead of adding one. */
|
|
581
|
+
id?: string;
|
|
582
|
+
title: ReactNode;
|
|
583
|
+
description?: ReactNode;
|
|
584
|
+
/** Default `neutral`. */
|
|
585
|
+
type?: ToastType;
|
|
586
|
+
/**
|
|
587
|
+
* `{ label, onClick }` renders a small secondary Button. Any other node (e.g. a router `<Link>`
|
|
588
|
+
* styled as a button) is rendered as-is and never dismisses the toast by itself.
|
|
589
|
+
*/
|
|
590
|
+
action?: ToastActionButton | ReactNode;
|
|
591
|
+
/**
|
|
592
|
+
* Milliseconds on screen; `Infinity` keeps it until dismissed. Default: 5000, 10000 with an
|
|
593
|
+
* action, never for `danger` and `loading`.
|
|
594
|
+
*/
|
|
595
|
+
duration?: number;
|
|
596
|
+
/** False hides the close button and turns off swipe and Esc. Default true. */
|
|
597
|
+
dismissible?: boolean;
|
|
598
|
+
/** The `<Toaster id>` that shows it. Left out, it goes to the Toaster without an id. */
|
|
599
|
+
toasterId?: string;
|
|
600
|
+
};
|
|
601
|
+
type ToastPatch = Partial<Omit<ToastOptions, 'id' | 'toasterId'>>;
|
|
602
|
+
declare function update(id: string, patch: ToastPatch): void;
|
|
603
|
+
type ShortcutOptions = Omit<ToastOptions, 'title' | 'type'>;
|
|
604
|
+
type PromiseStep = ReactNode | Omit<ToastOptions, 'id' | 'type'>;
|
|
605
|
+
type ToastPromiseOptions<T> = {
|
|
606
|
+
id?: string;
|
|
607
|
+
toasterId?: string;
|
|
608
|
+
loading: PromiseStep;
|
|
609
|
+
success: PromiseStep | ((data: T) => PromiseStep);
|
|
610
|
+
error: PromiseStep | ((error: unknown) => PromiseStep);
|
|
611
|
+
};
|
|
612
|
+
/**
|
|
613
|
+
* Imperative toasts, callable from anywhere (event handlers, mutations, loaders) once a
|
|
614
|
+
* `<Toaster />` is mounted. Every call returns the toast's id. `toasterId` routes a toast to a
|
|
615
|
+
* `<Toaster id>` instead.
|
|
616
|
+
*/
|
|
617
|
+
export declare const toast: ((options: ToastOptions) => string) & {
|
|
618
|
+
success: (title: ReactNode, options?: ShortcutOptions) => string;
|
|
619
|
+
info: (title: ReactNode, options?: ShortcutOptions) => string;
|
|
620
|
+
warning: (title: ReactNode, options?: ShortcutOptions) => string;
|
|
621
|
+
/** Renders as the `danger` type. Stays until dismissed. */
|
|
622
|
+
error: (title: ReactNode, options?: ShortcutOptions) => string;
|
|
623
|
+
/** Spinner; stays until updated or dismissed. */
|
|
624
|
+
loading: (title: ReactNode, options?: ShortcutOptions) => string;
|
|
625
|
+
/** Merges into a toast still on screen and restarts its timer. No-op for unknown ids. */
|
|
626
|
+
update: typeof update;
|
|
627
|
+
/** Plays the exit of one toast, or of all of them without an id. */
|
|
628
|
+
dismiss: (id?: string) => void;
|
|
629
|
+
/**
|
|
630
|
+
* Loading toast that turns into success or danger in place when the promise settles. Steps
|
|
631
|
+
* are a title or full options; success/error may be functions of the result / the error.
|
|
632
|
+
*/
|
|
633
|
+
promise<T>(promise: Promise<T> | (() => Promise<T>), steps: ToastPromiseOptions<T>): string;
|
|
634
|
+
};
|
|
635
|
+
//#endregion
|
|
636
|
+
//#region src/components/toast/toaster.d.ts
|
|
637
|
+
type ToastPosition = 'bottom-right' | 'bottom-left' | 'bottom-center' | 'top-right' | 'top-left' | 'top-center';
|
|
638
|
+
type ToasterProps = {
|
|
639
|
+
/**
|
|
640
|
+
* Shows only toasts created with this `toasterId`. Without one it shows toasts that have none:
|
|
641
|
+
* that's the app's single main Toaster. Ids let a separate area (or each Storybook docs story)
|
|
642
|
+
* keep its own stack and position.
|
|
643
|
+
*/
|
|
644
|
+
id?: string;
|
|
645
|
+
/** Corner (or edge center) the stack grows from. Default `bottom-right`. */
|
|
646
|
+
position?: ToastPosition;
|
|
647
|
+
/** Cards shown in the collapsed stack; older ones wait hidden. Default 3, at most 2 on phones. */
|
|
648
|
+
visibleToasts?: number;
|
|
649
|
+
};
|
|
650
|
+
/**
|
|
651
|
+
* The single place toasts render: mount one near the app root (inside the router, so a `<Link>`
|
|
652
|
+
* action has its context). Toasts themselves come from `toast()` and friends.
|
|
653
|
+
*/
|
|
654
|
+
export declare function Toaster(props: ToasterProps): import("react").ReactPortal | null;
|
|
655
|
+
//#endregion
|
|
656
|
+
//#region src/lib/cn.d.ts
|
|
657
|
+
export declare function cn(...inputs: ClassValue[]): string;
|
|
658
|
+
//#endregion
|
|
659
|
+
export type { BadgeProps, BadgeTone, ButtonProps, CardHeaderProps, CardProps, CheckboxGroupProps, CheckboxProps, CopyInputProps, DialogCloseReason, DialogHeaderProps, DialogProps, DialogSize, DrawerCloseProps, DrawerCloseReason, DrawerHeaderProps, DrawerProps, DrawerSide, DrawerSize, InputProps, MeterProps, MeterSegment, MeterTone, PasswordInputProps, SearchInputProps, SelectGroup, SelectOption, SelectProps, SidebarGroupProps, SidebarItemProps, SidebarProps, SidebarTriggerProps, SwitchProps, SwitchSize, TabListProps, TabNavLinkProps, TabNavProps, TabPanelProps, TabProps, TabsActivationMode, TabsProps, TabsSize, TabsVariant, Theme, ThemeSwitcherProps, ToastActionButton, ToastOptions, ToastPatch, ToastPosition, ToastPromiseOptions, ToastType, ToasterProps, TooltipProps, UseThemeOptions };
|