@ceebee/ui 0.5.2 → 1.0.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/dist/client.d.ts CHANGED
@@ -1,7 +1,24 @@
1
+ import { ThemeConfig } from 'antd';
2
+ export * from 'antd';
1
3
  import * as react from 'react';
2
- import { ReactNode, ButtonHTMLAttributes, InputHTMLAttributes, TextareaHTMLAttributes, ReactElement } from 'react';
4
+ import { ReactNode } from 'react';
5
+ export { default as enUSLocale } from 'antd/locale/en_US';
6
+ export { default as enUSDatePickerLocale } from 'antd/es/date-picker/locale/en_US';
7
+ export { default as idIDLocale } from 'antd/locale/id_ID';
8
+ export { default as zhCNLocale } from 'antd/locale/zh_CN';
3
9
  import * as _base_ui_react from '@base-ui/react';
4
10
 
11
+ interface ThemeBridgeProps {
12
+ children: ReactNode;
13
+ mode: 'light' | 'dark';
14
+ theme?: ThemeConfig;
15
+ }
16
+ /**
17
+ * Translates Ceebee's live CSS Tokens into Ant's theme seed. Ant still owns component geometry,
18
+ * interaction, accessibility, and derived tokens; Ceebee owns the active Skin and colour mode.
19
+ */
20
+ declare function ThemeBridge({ children, mode, theme }: ThemeBridgeProps): react.JSX.Element;
21
+
5
22
  /**
6
23
  * Every string the library says out loud. They are here rather than inline because a component
7
24
  * that hard-codes "Previous slide" is an English component, and this library is used to build
@@ -34,13 +51,8 @@ interface Labels {
34
51
  decrease: string;
35
52
  expandNavigation: string;
36
53
  collapseNavigation: string;
37
- /** Tour buttons. A Tour's own `labels` prop still wins over these. */
38
- back: string;
54
+ /** Carousel and image-preview stepping. */
39
55
  next: string;
40
- done: string;
41
- skip: string;
42
- /** Coachmark and Checklist progress, e.g. "2 of 5". */
43
- progress: (current: number, total: number) => string;
44
56
  }
45
57
  declare const DEFAULT_LABELS: Labels;
46
58
  interface LabelsProviderProps {
@@ -67,7 +79,7 @@ interface MotionProviderProps {
67
79
  }
68
80
  /**
69
81
  * The one place animation is scaled or switched off, and the seam that honours
70
- * `prefers-reduced-motion` (ADR 0004). Reduced motion means transforms drop and opacity
82
+ * `prefers-reduced-motion`. Reduced motion means transforms drop and opacity
71
83
  * stays; it never means a state change happens invisibly.
72
84
  */
73
85
  declare function MotionProvider({ children, enabled, scale }: MotionProviderProps): react.JSX.Element;
@@ -87,397 +99,19 @@ interface ThemeState {
87
99
  resolved: 'light' | 'dark';
88
100
  }
89
101
  /**
90
- * Colour itself comes from CSS, not from here (ADR 0002) — this only flips `data-theme`
102
+ * Colour itself comes from CSS, not from here — this only flips `data-theme`
91
103
  * on the document root, so the first paint is already correct without a blocking script
92
104
  * for anyone who never overrides the system setting.
93
105
  */
94
- declare function ThemeProvider({ children, defaultChoice, persist, }: {
106
+ declare function ThemeProvider({ children, defaultChoice, persist, antdTheme, }: {
95
107
  children: ReactNode;
96
108
  defaultChoice?: ThemeChoice;
97
109
  persist?: boolean;
110
+ /** Optional Ant token/component overrides applied after the active Ceebee Skin. */
111
+ antdTheme?: ThemeConfig;
98
112
  }): react.JSX.Element;
99
113
  declare function useTheme(): ThemeState;
100
114
 
101
- type Tone = 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'danger';
102
- type Size = 'sm' | 'md' | 'lg';
103
-
104
- /** Motion redefines the drag and animation event handlers, so the DOM versions are dropped
105
- * rather than silently conflicting. A button that needs HTML5 drag is not this component. */
106
- type NativeButtonProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'color' | 'onDrag' | 'onDragStart' | 'onDragEnd' | 'onAnimationStart' | 'onAnimationEnd' | 'onAnimationIteration'>;
107
- interface ButtonProps extends NativeButtonProps {
108
- variant?: 'solid' | 'soft' | 'outline' | 'ghost';
109
- tone?: Tone;
110
- size?: Size;
111
- /** Shown instead of the label, with the button held at its current width. */
112
- loading?: boolean;
113
- iconStart?: ReactNode;
114
- iconEnd?: ReactNode;
115
- /** Opts this button out of press feedback without touching the provider. */
116
- motion?: boolean;
117
- }
118
- declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
119
-
120
- interface FieldWiring {
121
- controlId: string;
122
- describedBy: string | undefined;
123
- invalid: boolean;
124
- required: boolean;
125
- }
126
- /** Inputs read their id and aria wiring from here; standalone use returns null. */
127
- declare function useFieldWiring(): FieldWiring | null;
128
- interface FieldProps {
129
- label: ReactNode;
130
- hint?: ReactNode;
131
- /** A string renders the message; `true` marks invalid without one. */
132
- error?: ReactNode | boolean;
133
- required?: boolean;
134
- /** Hides the label visually while keeping it for screen readers. */
135
- labelHidden?: boolean;
136
- className?: string;
137
- children: ReactNode;
138
- }
139
- /**
140
- * Label, hint, error, and the `aria-describedby` / `aria-invalid` links between them —
141
- * the part that is most often silently wrong. The library owns this and refuses to own
142
- * form state or validation (ADR 0011).
143
- */
144
- declare function Field({ label, hint, error, required, labelHidden, className, children }: FieldProps): react.JSX.Element;
145
-
146
- interface TextInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
147
- size?: Size;
148
- /** Marks invalid when used outside a Field; inside one, the Field decides. */
149
- invalid?: boolean;
150
- }
151
- declare const Input: react.ForwardRefExoticComponent<TextInputProps & react.RefAttributes<HTMLInputElement>>;
152
- interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
153
- invalid?: boolean;
154
- }
155
- declare const Textarea: react.ForwardRefExoticComponent<TextareaProps & react.RefAttributes<HTMLTextAreaElement>>;
156
-
157
- interface SelectOption<T extends string = string> {
158
- value: T;
159
- label: ReactNode;
160
- disabled?: boolean;
161
- }
162
- interface SelectProps<T extends string = string> {
163
- items: Array<SelectOption<T>>;
164
- value?: T | null;
165
- defaultValue?: T | null;
166
- onValueChange?: (value: T) => void;
167
- placeholder?: string;
168
- size?: Size;
169
- disabled?: boolean;
170
- invalid?: boolean;
171
- name?: string;
172
- id?: string;
173
- className?: string;
174
- }
175
- /**
176
- * Listbox behaviour — typeahead, roving focus, scroll containment, form association —
177
- * is Base UI's (ADR 0003). This adds the brand and the Field wiring.
178
- */
179
- declare function Select<T extends string = string>({ items, value, defaultValue, onValueChange, placeholder, size, disabled, invalid, name, id, className, }: SelectProps<T>): react.JSX.Element;
180
-
181
- interface CheckboxProps {
182
- label: ReactNode;
183
- checked?: boolean;
184
- defaultChecked?: boolean;
185
- indeterminate?: boolean;
186
- onCheckedChange?: (checked: boolean) => void;
187
- disabled?: boolean;
188
- name?: string;
189
- value?: string;
190
- /** Secondary line under the label — the place for "why would I tick this". */
191
- description?: ReactNode;
192
- className?: string;
193
- }
194
- /** The control and its label are one component: a checkbox whose label is not wired is a bug. */
195
- declare function Checkbox({ label, checked, defaultChecked, indeterminate, onCheckedChange, disabled, name, value, description, className, }: CheckboxProps): react.JSX.Element;
196
- interface RadioOption<T extends string = string> {
197
- value: T;
198
- label: ReactNode;
199
- description?: ReactNode;
200
- disabled?: boolean;
201
- }
202
- interface RadioGroupProps<T extends string = string> {
203
- options: Array<RadioOption<T>>;
204
- value?: T;
205
- defaultValue?: T;
206
- onValueChange?: (value: T) => void;
207
- name?: string;
208
- /** Names the group for assistive technology when it is not inside a Field. */
209
- label?: string;
210
- direction?: 'column' | 'row';
211
- /**
212
- * `segmented` draws the group as one track of adjoining cells instead of a
213
- * list of dots. Appearance and geometry only — the role, the keyboard, and
214
- * the value it reports are a radiogroup's either way (ADR 0014). Reach for it
215
- * where the options are few enough to show at once, which is where a dropdown
216
- * is the wrong control anyway.
217
- */
218
- variant?: 'list' | 'segmented';
219
- disabled?: boolean;
220
- className?: string;
221
- }
222
- declare function RadioGroup<T extends string = string>({ options, value, defaultValue, onValueChange, name, label, direction, variant, disabled, className, }: RadioGroupProps<T>): react.JSX.Element;
223
- interface SwitchProps {
224
- label: ReactNode;
225
- checked?: boolean;
226
- defaultChecked?: boolean;
227
- onCheckedChange?: (checked: boolean) => void;
228
- disabled?: boolean;
229
- name?: string;
230
- description?: ReactNode;
231
- /** Label on the left, control on the right — the settings-row arrangement. */
232
- justified?: boolean;
233
- className?: string;
234
- }
235
- /** A Switch applies immediately. If a change needs saving, that is a Checkbox in a form. */
236
- declare function Switch({ label, checked, defaultChecked, onCheckedChange, disabled, name, description, justified, className, }: SwitchProps): react.JSX.Element;
237
-
238
- interface ComboboxOption {
239
- value: string;
240
- label: string;
241
- description?: ReactNode;
242
- disabled?: boolean;
243
- }
244
- /**
245
- * Fetches the options for a query. Receiving one puts the AutoComplete in async mode:
246
- * the built-in match is switched off, because whatever answered the query has
247
- * already decided what matches and filtering the reply again would drop rows whose
248
- * label does not happen to contain what was typed.
249
- *
250
- * The `signal` aborts when a newer query supersedes this one. Replies are also
251
- * discarded by sequence, so a slow "a" landing after a fast "abc" cannot overwrite
252
- * the newer list — the failure that makes an async picker show the wrong rows.
253
- */
254
- type ComboboxLoader = (query: string, signal: AbortSignal) => Promise<ComboboxOption[]>;
255
- interface ComboboxProps {
256
- /** The whole list, filtered in the browser. Omit when `loadItems` is given. */
257
- items?: ComboboxOption[];
258
- /** Asks somewhere else for the options instead of holding them all (ADR 0006). */
259
- loadItems?: ComboboxLoader;
260
- /** How long typing has to stop before `loadItems` is asked. */
261
- loadDelay?: number;
262
- value?: string | null;
263
- defaultValue?: string | null;
264
- onValueChange?: (value: string | null) => void;
265
- placeholder?: string;
266
- /** Shown when the query matches nothing. */
267
- emptyMessage?: ReactNode;
268
- /** Shown while `loadItems` is outstanding. */
269
- loadingMessage?: ReactNode;
270
- /** Shown when `loadItems` rejects. */
271
- errorMessage?: ReactNode;
272
- size?: Size;
273
- disabled?: boolean;
274
- invalid?: boolean;
275
- name?: string;
276
- id?: string;
277
- className?: string;
278
- }
279
- /**
280
- * A Select you can type into. Reach for it past roughly a dozen options — below that, scanning a
281
- * list is faster than typing, and Select is the simpler component.
282
- */
283
- declare function AutoComplete({ items, loadItems, loadDelay, value, defaultValue, onValueChange, placeholder, emptyMessage, loadingMessage, errorMessage, size, disabled, invalid, name, id, className, }: ComboboxProps): react.JSX.Element;
284
-
285
- interface DateInputProps {
286
- value?: Date | null;
287
- defaultValue?: Date | null;
288
- onValueChange?: (value: Date | null) => void;
289
- min?: Date;
290
- max?: Date;
291
- /** How the chosen date reads in the field. Defaults to the viewer's locale, medium length. */
292
- format?: (date: Date) => string;
293
- weekStartsOn?: 0 | 1;
294
- size?: Size;
295
- disabled?: boolean;
296
- invalid?: boolean;
297
- placeholder?: string;
298
- className?: string;
299
- }
300
- /**
301
- * Typing and picking, both. Typing is what fast people do and what a date of birth needs; the
302
- * calendar is for "the second Tuesday" questions a text field cannot answer.
303
- */
304
- declare function DatePicker({ value, defaultValue, onValueChange, min, max, format, weekStartsOn, size, disabled, invalid, placeholder, className, }: DateInputProps): react.JSX.Element;
305
-
306
- /** Date arithmetic for the picker. Pure, and dealing only in local calendar days. */
307
- interface DayCell {
308
- date: Date;
309
- /** False for the leading and trailing days that belong to the neighbouring months. */
310
- inMonth: boolean;
311
- }
312
- declare function isSameDay(a: Date | null, b: Date | null): boolean;
313
- declare function startOfDay(date: Date): Date;
314
- /**
315
- * Six weeks of cells, always. A fixed grid height means the popover does not resize when a
316
- * month happens to span five weeks instead of six.
317
- */
318
- declare function monthMatrix(year: number, month: number, weekStartsOn?: 0 | 1): DayCell[][];
319
- /**
320
- * Reads what a person typed. ISO first, then day-first with `/`, `-`, or `.` — day-first because
321
- * that is what most of the world writes, and an ambiguous `03/04` has to pick a side.
322
- */
323
- declare function parseDateInput(input: string): Date | null;
324
- declare function formatISO(date: Date | null): string;
325
- declare function isOutOfRange(date: Date, min?: Date, max?: Date): boolean;
326
-
327
- /** Time-of-day parsing and formatting. Pure, like the date maths next to it. */
328
- interface TimeValue {
329
- hours: number;
330
- minutes: number;
331
- }
332
- /**
333
- * Reads what a person typed: `9`, `9:30`, `0930`, `9.30`, `9 pm`, `21:05`. Returns null rather
334
- * than guessing when the result would not be a real time.
335
- */
336
- declare function parseTime(input: string): TimeValue | null;
337
- declare function formatTime({ hours, minutes }: TimeValue): string;
338
- declare function timeToMinutes({ hours, minutes }: TimeValue): number;
339
- /** Every selectable time between two bounds, at `step` minutes. Bounds are inclusive. */
340
- declare function timeOptions(step: number, min?: TimeValue, max?: TimeValue): TimeValue[];
341
- declare function isTimeOutOfRange(value: TimeValue, min?: TimeValue, max?: TimeValue): boolean;
342
-
343
- interface TimeInputProps {
344
- value?: TimeValue | null;
345
- defaultValue?: TimeValue | null;
346
- onValueChange?: (value: TimeValue | null) => void;
347
- min?: TimeValue;
348
- max?: TimeValue;
349
- /** Minutes between the offered times. Typing is never restricted to them. */
350
- step?: number;
351
- size?: Size;
352
- disabled?: boolean;
353
- invalid?: boolean;
354
- placeholder?: string;
355
- className?: string;
356
- }
357
- /**
358
- * The DatePicker's sibling. Typing accepts what people actually type — `9`, `0930`, `9:30`,
359
- * `9pm` — and the list is a convenience on top, never the only way to answer.
360
- */
361
- declare function TimePicker({ value, defaultValue, onValueChange, min, max, step, size, disabled, invalid, placeholder, className, }: TimeInputProps): react.JSX.Element;
362
-
363
- /** File acceptance rules, kept pure: what gets rejected and why is worth asserting. */
364
- interface FileRules {
365
- /** Extensions or MIME types, e.g. ['.pdf', 'image/*']. */
366
- accept?: string[];
367
- /** Bytes. */
368
- maxSize?: number;
369
- maxFiles?: number;
370
- multiple?: boolean;
371
- }
372
- interface Rejection {
373
- file: File;
374
- reason: string;
375
- }
376
- declare function matchesAccept(file: File, accept: string[] | undefined): boolean;
377
- /**
378
- * Splits an incoming batch against the rules and what is already held. Every rejection carries
379
- * a reason, because a file that disappears without explanation reads as a broken uploader.
380
- */
381
- declare function partitionFiles(incoming: File[], existing: File[], rules: FileRules): {
382
- accepted: File[];
383
- rejected: Rejection[];
384
- };
385
- /** The " — PDF up to 5 MB" tail under the drop zone. Empty when there is nothing to say. */
386
- declare function describeAccept(rules: FileRules): string;
387
-
388
- interface UploadProps extends FileRules {
389
- onFilesChange: (files: File[]) => void;
390
- files?: File[];
391
- /** Rejections are surfaced rather than swallowed — a file that vanishes silently reads as a bug. */
392
- onReject?: (rejections: Array<{
393
- file: File;
394
- reason: string;
395
- }>) => void;
396
- disabled?: boolean;
397
- children?: ReactNode;
398
- className?: string;
399
- }
400
- declare function Upload({ onFilesChange, files, onReject, accept, maxSize, maxFiles, multiple, disabled, children, className, }: UploadProps): react.JSX.Element;
401
-
402
- /** Numeric input arithmetic, kept pure so the awkward cases are asserted, not hoped for. */
403
- interface NumberBounds {
404
- min?: number;
405
- max?: number;
406
- step?: number;
407
- }
408
- /** Parses what a person typed. Accepts a comma decimal separator; returns null for nonsense. */
409
- declare function parseNumber(input: string): number | null;
410
- declare function clamp(value: number, { min, max }: NumberBounds): number;
411
- /**
412
- * Steps by `step` and clamps. Floating point is rounded back to the step's own precision,
413
- * because 0.1 + 0.2 must read as 0.3 in an input a person is looking at.
414
- */
415
- declare function stepBy(value: number | null, direction: 1 | -1, bounds: NumberBounds): number;
416
- declare function decimalPlaces(step: number): number;
417
- /** Whether stepping in this direction would do anything — drives the disabled state. */
418
- declare function canStep(value: number | null, direction: 1 | -1, bounds: NumberBounds): boolean;
419
-
420
- interface NumberInputProps extends NumberBounds {
421
- value?: number | null;
422
- defaultValue?: number | null;
423
- onValueChange?: (value: number | null) => void;
424
- size?: Size;
425
- disabled?: boolean;
426
- invalid?: boolean;
427
- name?: string;
428
- placeholder?: string;
429
- /** Shown inside the control, e.g. 'kg', 'IDR'. Decorative — keep the unit in the label too. */
430
- suffix?: string;
431
- className?: string;
432
- }
433
- /**
434
- * A text input that speaks numbers, not `<input type="number">`: that one scrolls its value
435
- * away under the wheel, accepts 'e' and '+', and formats inconsistently across locales.
436
- */
437
- declare function InputNumber({ value, defaultValue, onValueChange, min, max, step, size, disabled, invalid, name, placeholder, suffix, className, }: NumberInputProps): react.JSX.Element;
438
-
439
- interface DialogProps {
440
- open?: boolean;
441
- defaultOpen?: boolean;
442
- onOpenChange?: (open: boolean) => void;
443
- title: ReactNode;
444
- description?: ReactNode;
445
- children?: ReactNode;
446
- footer?: ReactNode;
447
- size?: 'sm' | 'md' | 'lg';
448
- /** Slides from the edge instead of scaling in the centre. */
449
- placement?: 'center' | 'end';
450
- /** The element that opens it. Omit for a fully controlled dialog. */
451
- trigger?: ReactNode;
452
- className?: string;
453
- }
454
- /**
455
- * Focus trapping, scroll locking, dismissal, and the `aria-labelledby` wiring are Base UI's
456
- * (ADR 0003). Enter and exit are CSS transitions driven by Base UI's own state attributes,
457
- * because Base UI owns this element's mount lifecycle — motion is used where we own it.
458
- */
459
- declare function Modal({ open, defaultOpen, onOpenChange, title, description, children, footer, size, placement, trigger, className, }: DialogProps): react.JSX.Element;
460
- declare const DialogClose: react.ForwardRefExoticComponent<Omit<_base_ui_react.AlertDialogCloseProps, "ref"> & react.RefAttributes<HTMLButtonElement>>;
461
-
462
- interface DrawerProps {
463
- open?: boolean;
464
- defaultOpen?: boolean;
465
- onOpenChange?: (open: boolean) => void;
466
- title: ReactNode;
467
- description?: ReactNode;
468
- children?: ReactNode;
469
- footer?: ReactNode;
470
- /** The element that opens it. Omit for a fully controlled drawer. */
471
- trigger?: ReactNode;
472
- className?: string;
473
- }
474
- /**
475
- * Modal navigation or task panel anchored to the inline end edge. Base UI supplies
476
- * focus trapping, dismissal, scroll locking, and accessible dialog semantics.
477
- */
478
- declare function Drawer({ open, defaultOpen, onOpenChange, title, description, children, footer, trigger, className, }: DrawerProps): react.JSX.Element;
479
- declare const DrawerClose: react.ForwardRefExoticComponent<Omit<_base_ui_react.AlertDialogCloseProps, "ref"> & react.RefAttributes<HTMLButtonElement>>;
480
-
481
115
  /** Command matching and ranking. Pure — search that ranks badly is a bug you can only see in a test. */
482
116
  interface Command {
483
117
  id: string;
@@ -539,111 +173,11 @@ interface ChecklistProps {
539
173
  /**
540
174
  * Getting-started tasks with progress. Which tasks are done is the app's knowledge, passed in —
541
175
  * the library does not track anyone's account state, the same rule the Seen Store follows
542
- * (ADR 0006).
176
+ *.
543
177
  */
544
178
  declare function Checklist({ title, tasks, completeSlot, className }: ChecklistProps): react.JSX.Element;
545
179
 
546
- type Side = 'top' | 'right' | 'bottom' | 'left';
547
- type Align = 'start' | 'center' | 'end';
548
- interface PopoverProps {
549
- trigger: ReactElement;
550
- children: ReactNode;
551
- side?: Side;
552
- align?: Align;
553
- /** Distance from the anchor, in px. Keep it at the token step unless the arrow needs room. */
554
- sideOffset?: number;
555
- showArrow?: boolean;
556
- open?: boolean;
557
- onOpenChange?: (open: boolean) => void;
558
- className?: string;
559
- }
560
- /** Positioning, dismissal, and focus return come from Base UI; this adds the surface (ADR 0003). */
561
- declare function Popover({ trigger, children, side, align, sideOffset, showArrow, open, onOpenChange, className, }: PopoverProps): react.JSX.Element;
562
- interface TooltipProps {
563
- children: ReactElement;
564
- /** Plain text. A tooltip that needs markup is a Popover — screen readers read this as a label. */
565
- label: string;
566
- side?: Side;
567
- align?: Align;
568
- /** Distance from the anchor, in px. */
569
- sideOffset?: number;
570
- showArrow?: boolean;
571
- delay?: number;
572
- }
573
- declare function Tooltip({ children, label, side, align, sideOffset, showArrow, delay, }: TooltipProps): react.JSX.Element;
574
-
575
- interface TagProps {
576
- children: ReactNode;
577
- tone?: Tone;
578
- variant?: 'soft' | 'solid' | 'outline';
579
- size?: 'sm' | 'md';
580
- icon?: ReactNode;
581
- /** Makes the tag itself pressable — filtering by it, or opening what it names. */
582
- onClick?: () => void;
583
- /** Whether a pressable tag is currently on. Reported as `aria-pressed`. */
584
- pressed?: boolean;
585
- /** Adds a control that takes the tag away. Not the same as pressing it. */
586
- onClose?: () => void;
587
- /** Render something else in the tag's place — a router's own Link. */
588
- render?: ReactElement;
589
- className?: string;
590
- }
591
- /**
592
- * A label you can do something to.
593
- *
594
- * `Badge` is the one you cannot: it says what something is and nothing more, and
595
- * its own note says that a label which can be pressed or removed is this instead.
596
- * That is the whole boundary between them — not the size, not the colour, but
597
- * whether there is anything to press (ADR 0014). They share the look and differ
598
- * in what they are.
599
- *
600
- * Pressing and removing are also two different things, so they are two props. A
601
- * tag that filters by its own value and a tag that takes itself off a list are
602
- * not the same gesture, and one component that guessed which you meant would be
603
- * wrong half the time.
604
- */
605
- declare function Tag({ children, tone, variant, size, icon, onClick, pressed, onClose, render, className, }: TagProps): react.JSX.Element;
606
-
607
- interface RateProps {
608
- /** 0 means nothing chosen, which is different from choosing the lowest score. */
609
- value: number;
610
- onValueChange?: (value: number) => void;
611
- count?: number;
612
- size?: number;
613
- /** Shows a score without offering to change it. */
614
- readOnly?: boolean;
615
- /** Names the group when it is not inside a Field. */
616
- label?: string;
617
- className?: string;
618
- }
619
- /**
620
- * A score out of a few, set by pressing one of them.
621
- *
622
- * A radiogroup, not a row of buttons: exactly one of a small visible set is the
623
- * definition of one, and it buys the arrow keys and the announced position for
624
- * free. Read-only it is not a group at all — there is nothing to choose, so it
625
- * is an image with a label saying what it shows.
626
- *
627
- * Pressing the current score again clears it. Nought stars and one star are
628
- * different answers, and without this there is no way back to the first.
629
- */
630
- declare function Rate({ value, onValueChange, count, size, readOnly, label, className, }: RateProps): react.JSX.Element;
631
-
632
- interface AlertProps {
633
- title?: ReactNode;
634
- children?: ReactNode;
635
- tone?: Tone;
636
- /** Replaces the tone's default icon. Pass null to drop it. */
637
- icon?: ReactNode | null;
638
- actions?: ReactNode;
639
- onDismiss?: () => void;
640
- className?: string;
641
- }
642
- /**
643
- * `danger` and `warning` announce themselves through `role="alert"`; the quieter tones do not,
644
- * because a success note that interrupts a screen reader mid-sentence is not helpful.
645
- */
646
- declare function Alert({ title, children, tone, icon, actions, onDismiss, className }: AlertProps): react.JSX.Element;
180
+ type Tone = 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'danger';
647
181
 
648
182
  type ToastPosition = 'bottom-end' | 'bottom-center' | 'bottom-start' | 'top-end' | 'top-center' | 'top-start';
649
183
  interface ToastProviderProps {
@@ -676,56 +210,6 @@ declare function useToast(): {
676
210
  promise: <Value, T extends any = any>(promise: Promise<Value>, options: _base_ui_react.ToastManagerPromiseOptions<Value, T>) => Promise<Value>;
677
211
  };
678
212
 
679
- interface TabItem {
680
- value: string;
681
- label: ReactNode;
682
- /** Count or status shown after the label, e.g. a Badge. */
683
- adornment?: ReactNode;
684
- disabled?: boolean;
685
- content: ReactNode;
686
- }
687
- interface TabsProps {
688
- items: TabItem[];
689
- value?: string;
690
- defaultValue?: string;
691
- onValueChange?: (value: string) => void;
692
- variant?: 'underline' | 'pill';
693
- className?: string;
694
- }
695
- /** Roving focus, panel association, and the moving indicator are Base UI's (ADR 0003). */
696
- declare function Tabs({ items, value, defaultValue, onValueChange, variant, className }: TabsProps): react.JSX.Element;
697
-
698
- interface MenuItem {
699
- /** Omit everything but `separator` to draw a divider. */
700
- separator?: boolean;
701
- label?: ReactNode;
702
- icon?: ReactNode;
703
- shortcut?: string;
704
- tone?: Extract<Tone, 'neutral' | 'danger'>;
705
- disabled?: boolean;
706
- checked?: boolean;
707
- onSelect?: () => void;
708
- }
709
- interface MenuSection {
710
- label?: ReactNode;
711
- items: MenuItem[];
712
- }
713
- interface DropdownMenuBaseProps {
714
- trigger: ReactElement;
715
- align?: 'start' | 'center' | 'end';
716
- side?: 'top' | 'right' | 'bottom' | 'left';
717
- className?: string;
718
- }
719
- type DropdownMenuProps = DropdownMenuBaseProps & ({
720
- items: MenuItem[];
721
- sections?: never;
722
- } | {
723
- items?: never;
724
- sections: MenuSection[];
725
- });
726
- /** Typeahead, roving focus, and dismissal are Base UI's; the surface and the rhythm are ours. */
727
- declare function Dropdown({ trigger, items, sections, align, side, className }: DropdownMenuProps): react.JSX.Element;
728
-
729
213
  interface NavItem {
730
214
  label: ReactNode;
731
215
  icon?: ReactNode;
@@ -768,264 +252,6 @@ interface TopBarProps {
768
252
  }
769
253
  declare function TopBar({ title, subtitle, center, actions, sticky, className }: TopBarProps): react.JSX.Element;
770
254
 
771
- /** Sorting and pagination arithmetic, kept pure so the off-by-ones are asserted (ADR 0012). */
772
- type SortDirection = 'asc' | 'desc';
773
- interface SortState {
774
- column: string;
775
- direction: SortDirection;
776
- }
777
- /**
778
- * What clicking a header does. Sorting a new column starts ascending; clicking the sorted
779
- * column flips it; clicking a descending column clears the sort — three states, because
780
- * "back to the order the server gave me" is a state people look for.
781
- */
782
- declare function nextSort(current: SortState | null, column: string): SortState | null;
783
- declare function ariaSortFor(current: SortState | null, column: string): 'ascending' | 'descending' | 'none';
784
- interface PageRange {
785
- /** Page numbers to render; `null` is an ellipsis. */
786
- items: Array<number | null>;
787
- totalPages: number;
788
- /** 1-based index of the first and last row on this page, for "1–20 of 137". */
789
- from: number;
790
- to: number;
791
- }
792
- /**
793
- * The page list, with ellipses. `siblings` is how many pages flank the current one; first and
794
- * last are always shown, because jumping to the end is the second most common thing people do.
795
- */
796
- declare function pageRange(page: number, pageSize: number, total: number, siblings?: number): PageRange;
797
-
798
- interface Column<Row> {
799
- key: string;
800
- header: ReactNode;
801
- /** Cell content. Given the row, so a column can render a Badge or an Avatar. */
802
- cell: (row: Row) => ReactNode;
803
- align?: 'start' | 'end';
804
- width?: string;
805
- sortable?: boolean;
806
- /** Hides the column below 720px — for the ones a phone can live without. */
807
- secondary?: boolean;
808
- /** Clips overflowing text with an ellipsis instead of widening the column. */
809
- truncate?: boolean;
810
- }
811
- interface DataTableProps<Row> {
812
- columns: Array<Column<Row>>;
813
- rows: Row[];
814
- rowKey: (row: Row) => string;
815
- /** Accessible name for the table. */
816
- label: string;
817
- sort?: SortState | null;
818
- onSortChange?: (sort: SortState | null) => void;
819
- onRowClick?: (row: Row) => void;
820
- /** Rendered in place of the body when there are no rows — an Empty, usually. */
821
- empty?: ReactNode;
822
- className?: string;
823
- }
824
- /**
825
- * A table, not a grid: no virtualisation, no column resizing, no editing. It renders rows and
826
- * sorts by a column, and anything past that is a product feature rather than a design system one.
827
- */
828
- declare function Table<Row>({ columns, rows, rowKey, label, sort, onSortChange, onRowClick, empty, className, }: DataTableProps<Row>): react.JSX.Element;
829
- declare namespace Table {
830
- var Skeleton: typeof DataTableSkeleton;
831
- }
832
- interface DataTableSkeletonProps {
833
- columns: number;
834
- rows?: number;
835
- className?: string;
836
- }
837
- /** Same row height and column count as the real table, so the page does not jump (ADR 0009). */
838
- declare function DataTableSkeleton({ columns, rows, className }: DataTableSkeletonProps): react.JSX.Element;
839
-
840
- interface PaginationProps {
841
- page: number;
842
- pageSize: number;
843
- total: number;
844
- onPageChange: (page: number) => void;
845
- /** Shows "1–20 of 137" beside the controls. */
846
- showSummary?: boolean;
847
- siblings?: number;
848
- className?: string;
849
- }
850
- declare function Pagination({ page, pageSize, total, onPageChange, showSummary, siblings, className, }: PaginationProps): react.JSX.Element;
851
-
852
- interface ImageProps {
853
- src: string;
854
- /** Empty string is allowed, and means "decorative" — but it has to be said out loud. */
855
- alt: string;
856
- /** Width / height, e.g. 16 / 9. Reserves the space so nothing below it jumps. */
857
- aspectRatio?: number;
858
- /** A tiny data URI, blurred up while the real image loads. */
859
- blurDataUrl?: string;
860
- /** Flat colour to sit behind the image when there is no blur placeholder. */
861
- background?: string;
862
- fit?: 'cover' | 'contain';
863
- radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
864
- loading?: 'lazy' | 'eager';
865
- className?: string;
866
- }
867
- /**
868
- * An `<img>` that reserves its space and fades in. It is not a Next.js Image and does not want to
869
- * be: no resizing service, no loader — those belong to the framework the app already chose.
870
- */
871
- declare function Image({ src, alt, aspectRatio, blurDataUrl, background, fit, radius, loading, className, }: ImageProps): react.JSX.Element;
872
-
873
- interface CarouselProps {
874
- children: ReactNode;
875
- /** Accessible name — a carousel with no name is an unlabelled region to a screen reader. */
876
- label: string;
877
- /** Slide width as a CSS length or fraction of the viewport, e.g. '18rem' or '50%'. */
878
- slideWidth?: string;
879
- gap?: 2 | 3 | 4 | 5;
880
- loop?: boolean;
881
- align?: 'start' | 'center';
882
- /** Milliseconds between advances. Omit for a carousel that only moves when asked. */
883
- autoplay?: number;
884
- showArrows?: boolean;
885
- showDots?: boolean;
886
- className?: string;
887
- }
888
- declare function CarouselRoot({ children, label, slideWidth, gap, loop, align, autoplay, showArrows, showDots, className, }: CarouselProps): react.JSX.Element;
889
- interface CarouselSlideProps {
890
- children: ReactNode;
891
- className?: string;
892
- }
893
- declare function CarouselSlide({ children, className }: CarouselSlideProps): react.JSX.Element;
894
- interface CarouselSkeletonProps {
895
- slides?: number;
896
- slideWidth?: string;
897
- slideHeight?: string;
898
- gap?: 2 | 3 | 4 | 5;
899
- }
900
- /** Same track geometry as the real carousel, so slides do not resize on load (ADR 0009). */
901
- declare function CarouselSkeleton({ slides, slideWidth, slideHeight, gap, }: CarouselSkeletonProps): react.JSX.Element;
902
- declare const Carousel: typeof CarouselRoot & {
903
- Slide: typeof CarouselSlide;
904
- Skeleton: typeof CarouselSkeleton;
905
- };
906
-
907
- /** Inputs that decide whether a carousel may advance on its own. */
908
- interface AutoplayConditions {
909
- /** The caller asked for autoplay at all. */
910
- requested: boolean;
911
- pointerInside: boolean;
912
- /** Focus is somewhere inside the carousel — keyboard users must not lose their place. */
913
- focusInside: boolean;
914
- documentHidden: boolean;
915
- reducedMotion: boolean;
916
- }
917
- /**
918
- * Autoplay stops for four separate reasons, and every one of them is a bug when missed:
919
- * a hovered carousel that keeps moving, a focused one that steals the slide out from under
920
- * a keyboard user, a background tab burning frames, and motion nobody asked for.
921
- */
922
- declare function shouldAutoplay(conditions: AutoplayConditions): boolean;
923
-
924
- interface CoachmarkProps {
925
- open: boolean;
926
- /** The element being pointed at. Already resolved — a Tour does the resolving. */
927
- anchor: Element | null;
928
- title: ReactNode;
929
- children?: ReactNode;
930
- side?: Side;
931
- align?: Align;
932
- /** Dims the page and cuts a hole around the anchor. A number sets the hole's padding in px. */
933
- spotlight?: boolean | number;
934
- /** e.g. `{ current: 2, total: 5 }` — rendered as "2 of 5" and announced. */
935
- progress?: {
936
- current: number;
937
- total: number;
938
- };
939
- actions?: ReactNode;
940
- onDismiss?: () => void;
941
- className?: string;
942
- }
943
- /**
944
- * One anchored bubble pointing at one element. It knows nothing about sequence and nothing
945
- * about who has seen it — those are Tour and the Seen Store (ADR 0006).
946
- */
947
- declare function Coachmark({ open, anchor, title, children, side, align, spotlight, progress, actions, onDismiss, className, }: CoachmarkProps): react.JSX.Element;
948
-
949
- /**
950
- * How a Tour asks whether someone has already been through it.
951
- *
952
- * The library ships this interface and no implementation on purpose (ADR 0006): a library that
953
- * reaches for localStorage has decided what a user is and where their state lives, and that is
954
- * the assumption that makes an onboarding library impossible to remove later.
955
- *
956
- * A localStorage adapter is four lines; a server-backed one is a fetch. Both are yours.
957
- */
958
- interface SeenStore {
959
- /** Whether this tour has been completed or skipped before. May be async. */
960
- has: (tourId: string) => boolean | Promise<boolean>;
961
- /** Records that it has now. Called once, when the tour finishes or is skipped. */
962
- mark: (tourId: string) => void | Promise<void>;
963
- }
964
-
965
- /** Tour sequencing, kept pure so every edge is assertable (ADR 0012). */
966
- type TourStatus = 'idle' | 'running' | 'finished' | 'skipped';
967
- interface TourState {
968
- index: number;
969
- status: TourStatus;
970
- }
971
- type TourAction = {
972
- type: 'start';
973
- } | {
974
- type: 'next';
975
- } | {
976
- type: 'prev';
977
- } | {
978
- type: 'goto';
979
- index: number;
980
- } | {
981
- type: 'skip';
982
- } | {
983
- type: 'finish';
984
- };
985
- declare const initialTourState: TourState;
986
- /**
987
- * `stepCount` is passed in rather than held in state because steps are props: a tour whose
988
- * steps change while it runs must not point past the end of the new list.
989
- */
990
- declare function tourReducer(state: TourState, action: TourAction, stepCount: number): TourState;
991
- /** A tour that ended, either way. Both outcomes mark the Seen Store. */
992
- declare function hasEnded(status: TourStatus): boolean;
993
- type StepTarget = string | Element | {
994
- current: Element | null;
995
- } | (() => Element | null) | null;
996
- /**
997
- * Resolves a step's target. Returns null rather than throwing when the element is not mounted
998
- * yet — the Tour retries, because a target that appears one frame late is normal, not an error.
999
- */
1000
- declare function resolveTarget(target: StepTarget, root: ParentNode): Element | null;
1001
-
1002
- interface TourStep {
1003
- target: StepTarget;
1004
- title: ReactNode;
1005
- content?: ReactNode;
1006
- side?: Side;
1007
- align?: Align;
1008
- spotlight?: boolean | number;
1009
- }
1010
- interface TourProps {
1011
- /** Stable id — this is what the Seen Store remembers. */
1012
- id: string;
1013
- steps: TourStep[];
1014
- /** Starts the tour when it turns true. */
1015
- open?: boolean;
1016
- onOpenChange?: (open: boolean) => void;
1017
- /** Injected by the app; without one the tour runs every time it is opened (ADR 0006). */
1018
- seenStore?: SeenStore;
1019
- onFinish?: () => void;
1020
- onSkip?: () => void;
1021
- labels?: Partial<Record<'back' | 'next' | 'done' | 'skip', string>>;
1022
- }
1023
- /**
1024
- * Sequences Coachmarks. It owns order and nothing else: memory is the Seen Store's, the bubble
1025
- * is the Coachmark's, and the steps belong to the caller.
1026
- */
1027
- declare function Tour({ id, steps, open, onOpenChange, seenStore, onFinish, onSkip, labels }: TourProps): react.JSX.Element | null;
1028
-
1029
255
  interface RevealProps {
1030
256
  children: ReactNode;
1031
257
  /** Direction the content travels from. Under reduced motion it only fades. */
@@ -1049,4 +275,4 @@ interface StaggerProps {
1049
275
  /** Wraps each child in a Reveal with an increasing delay — the list arrives, it does not pop. */
1050
276
  declare function Stagger({ children, step, from, onView, className }: StaggerProps): react.JSX.Element;
1051
277
 
1052
- export { Alert, type AlertProps, type Align, AutoComplete, type AutoplayConditions, Button, type ButtonProps, Carousel, type CarouselProps, type CarouselSkeletonProps, type CarouselSlideProps, Checkbox, type CheckboxProps, Checklist, type ChecklistProps, type ChecklistTask, Coachmark, type CoachmarkProps, type Column, type ComboboxOption, type ComboboxProps, type Command, CommandPalette, type CommandPaletteProps, DEFAULT_LABELS, type DataTableProps, type DataTableSkeletonProps, type DateInputProps, DatePicker, type DayCell, DialogClose, type DialogProps, Drawer, DrawerClose, type DrawerProps, Dropdown, type DropdownMenuProps, type DurationToken, Field, type FieldProps, type FileRules, Image, type ImageProps, Input, InputNumber, type Labels, LabelsProvider, type LabelsProviderProps, type MenuItem, type MenuSection, Modal, type MotionHelpers, MotionProvider, type MotionProviderProps, type MotionSettings, type NavItem, type NavSection, type NumberBounds, type NumberInputProps, type PageRange, Pagination, type PaginationProps, type PaletteCommand, Popover, type PopoverProps, RadioGroup, type RadioGroupProps, type RadioOption, type RankedCommand, Rate, type RateProps, type Rejection, Reveal, type RevealProps, type SeenStore, Select, type SelectOption, type SelectProps, type Side, Sidebar, type SidebarProps, type SortDirection, type SortState, type SpringPreset, Stagger, type StaggerProps, type StepTarget, Switch, type SwitchProps, type TabItem, Table, Tabs, type TabsProps, Tag, type TagProps, type TextInputProps, Textarea, type TextareaProps, type ThemeChoice, ThemeProvider, type TimeInputProps, TimePicker, type TimeValue, type ToastOptions, type ToastPosition, ToastProvider, type ToastProviderProps, Tooltip, type TooltipProps, TopBar, type TopBarProps, Tour, type TourAction, type TourProps, type TourState, type TourStatus, type TourStep, Upload, type UploadProps, ariaSortFor, canStep, clamp, decimalPlaces, describeAccept, filterCommands, formatISO, formatTime, groupCommands, hasEnded, initialTourState, isOutOfRange, isSameDay, isTimeOutOfRange, matchesAccept, monthMatrix, nextSort, pageRange, parseDateInput, parseNumber, parseTime, partitionFiles, rankCommand, resolveTarget, shouldAutoplay, startOfDay, stepBy, timeOptions, timeToMinutes, tourReducer, useFieldWiring, useLabels, useMotionSettings, useTheme, useToast };
278
+ export { Checklist, type ChecklistProps, type ChecklistTask, type Command, CommandPalette, type CommandPaletteProps, DEFAULT_LABELS, type DurationToken, type Labels, LabelsProvider, type LabelsProviderProps, type MotionHelpers, MotionProvider, type MotionProviderProps, type MotionSettings, type NavItem, type NavSection, type PaletteCommand, type RankedCommand, Reveal, type RevealProps, Sidebar, type SidebarProps, type SpringPreset, Stagger, type StaggerProps, ThemeBridge, type ThemeBridgeProps, type ThemeChoice, ThemeProvider, type ToastOptions, type ToastPosition, ToastProvider, type ToastProviderProps, TopBar, type TopBarProps, filterCommands, groupCommands, rankCommand, useLabels, useMotionSettings, useTheme, useToast };