@lessly/ui 0.27.0 → 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/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ClassValue } from 'clsx';
2
- import * as class_variance_authority_types from 'class-variance-authority/types';
3
2
  import * as React$1 from 'react';
4
3
  import { ComponentProps } from 'react';
4
+ import * as class_variance_authority_types from 'class-variance-authority/types';
5
5
  import * as class_variance_authority from 'class-variance-authority';
6
6
  import { VariantProps } from 'class-variance-authority';
7
7
  import * as DialogPrimitive from '@radix-ui/react-dialog';
@@ -31,6 +31,7 @@ import * as TabsPrimitive from '@radix-ui/react-tabs';
31
31
  import * as AccordionPrimitive from '@radix-ui/react-accordion';
32
32
  import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
33
33
  import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
34
+ import { Command as Command$1 } from 'cmdk';
34
35
  import * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';
35
36
  import { Toaster as Toaster$1 } from 'sonner';
36
37
  export { toast } from 'sonner';
@@ -41,18 +42,110 @@ import { FieldValues, FieldPath, ControllerProps } from 'react-hook-form';
41
42
 
42
43
  declare function cn(...inputs: ClassValue[]): string;
43
44
 
45
+ type AutoHeightProps = React$1.HTMLAttributes<HTMLDivElement>;
46
+ /**
47
+ * Eases its own height as the content inside it changes size — a dialog body that swaps between two
48
+ * layouts, a panel that reveals a section — so the container grows or shrinks smoothly instead of
49
+ * jumping. The content's height is measured with a ResizeObserver and written straight onto the
50
+ * wrapper; routing it through React state instead lands a re-render between the measure and the
51
+ * paint, which swallows the transition. The transition itself is the `.motion-auto-height` class
52
+ * (shipped in styles.css): it is motion-token driven, so it inherits the viewer's reduce-motion
53
+ * preference (the duration resolves to 0ms then).
54
+ *
55
+ * Wrap the changing content directly; anything that resizes it — a conditional branch, added rows,
56
+ * a data update — animates. Extra props and `className` land on the outer element.
57
+ *
58
+ * This is for size changes of content that stays mounted (a dialog body swapping layouts). For a
59
+ * show/hide reveal where the content mounts/unmounts (`{open ? <block/> : null}`), use `Collapsible`
60
+ * instead: AutoHeight flashes the block for a frame on show and can't animate the unmount on hide.
61
+ *
62
+ * Three things to know as a consumer: it owns `height` imperatively, so a `style={{ height }}` or
63
+ * `maxHeight` you pass is overwritten; it clips overflow *while animating* and gives your own
64
+ * `overflow` back at rest, so anything inside that must escape the box mid-ease — a tooltip, a
65
+ * non-portaled dropdown — should portal to the body; and the content sits in a block formatting
66
+ * context, so a vertical margin on a direct child is measured inside the box instead of collapsing
67
+ * out of it.
68
+ */
69
+ declare const AutoHeight: React$1.ForwardRefExoticComponent<AutoHeightProps & React$1.RefAttributes<HTMLDivElement>>;
70
+
44
71
  declare const buttonVariants: (props?: ({
45
- variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
46
- size?: "default" | "sm" | "lg" | "icon" | null | undefined;
72
+ variant?: "link" | "default" | "destructive" | "destructive-ghost" | "destructive-solid" | "outline" | "secondary" | "ghost" | null | undefined;
73
+ size?: "default" | "sm" | "xs" | "lg" | "icon" | null | undefined;
47
74
  } & class_variance_authority_types.ClassProp) | undefined) => string;
48
- interface ButtonProps extends React$1.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
75
+ type ButtonBase = Omit<React$1.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> & VariantProps<typeof buttonVariants>;
76
+ /**
77
+ * The labelled form. With the `icon` prop the component renders and sizes the glyph and marks it
78
+ * `aria-hidden`, because the label beside it already carries the meaning.
79
+ *
80
+ * `asChild` hands the element to the consumer, which leaves nowhere to put an `icon` — passing both
81
+ * warns in dev and renders the child untouched.
82
+ */
83
+ type ButtonLabelledProps = ButtonBase & {
84
+ children: React$1.ReactNode;
85
+ icon?: React$1.ReactNode;
86
+ iconPosition?: 'leading' | 'trailing';
49
87
  asChild?: boolean;
50
- }
88
+ };
89
+ /**
90
+ * Icon-only: an icon and no children, and the type is what enforces the accessible name.
91
+ *
92
+ * It owes a **tooltip** as well, and that half is not enforced here on purpose: `Tooltip.Root`
93
+ * throws without a `TooltipProvider` above it, and one provider is mounted per canvas — never one
94
+ * per icon — so a Button that mounted its own would crash any consumer rendering outside an
95
+ * `AppShell`. Wrap the call site instead.
96
+ *
97
+ * Known consequence: the base class sets `disabled:pointer-events-none`, so a **disabled** icon-only
98
+ * button fires no hover and its tooltip never opens — on exactly the button whose disabled reason
99
+ * most needs explaining. Put the trigger on a wrapping element when the hint has to survive the
100
+ * disabled state (`Button --disabled-with-tooltip` shows both).
101
+ */
102
+ type ButtonIconOnlyProps = ButtonBase & {
103
+ children?: never;
104
+ icon: React$1.ReactNode;
105
+ iconPosition?: never;
106
+ asChild?: never;
107
+ } & ({
108
+ 'aria-label': string;
109
+ } | {
110
+ 'aria-labelledby': string;
111
+ });
112
+ /**
113
+ * No label and no icon. Nonsense to render, but it is what `<Button />` typed as before the union
114
+ * landed, and this arm is what keeps that true.
115
+ */
116
+ type ButtonEmptyProps = ButtonBase & {
117
+ children?: never;
118
+ icon?: never;
119
+ iconPosition?: never;
120
+ asChild?: boolean;
121
+ };
122
+ type ButtonProps = ButtonLabelledProps | ButtonIconOnlyProps | ButtonEmptyProps;
51
123
  declare const Button: React$1.ForwardRefExoticComponent<ButtonProps & React$1.RefAttributes<HTMLButtonElement>>;
52
124
 
53
- declare const Card: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
125
+ interface CardProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'title'> {
126
+ /**
127
+ * A title bar: a heading left, one action right, over a hairline. With neither a title nor an
128
+ * action no bar is drawn at all, so a list starts at the top of the card.
129
+ */
130
+ title?: React$1.ReactNode;
131
+ action?: React$1.ReactNode;
132
+ /**
133
+ * `list` clips to the card's radius and hairlines between children.
134
+ * `nested` is the quiet inner box: a smaller radius, sunk a step, no shadow.
135
+ */
136
+ variant?: 'default' | 'list' | 'nested';
137
+ }
138
+ declare const Card: React$1.ForwardRefExoticComponent<CardProps & React$1.RefAttributes<HTMLDivElement>>;
54
139
  declare const CardHeader: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
55
- declare const CardTitle: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLHeadingElement> & React$1.RefAttributes<HTMLParagraphElement>>;
140
+ interface CardTitleProps extends React$1.HTMLAttributes<HTMLElement> {
141
+ /**
142
+ * The tag the title emits, so the card can take the outline level the page around it leaves
143
+ * free. A title that isn't a section heading — inside a dialog, or a card whose heading is
144
+ * already stated — takes `p`, `div` or `span` instead of a level nobody wanted.
145
+ */
146
+ as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'div' | 'span';
147
+ }
148
+ declare const CardTitle: React$1.ForwardRefExoticComponent<CardTitleProps & React$1.RefAttributes<HTMLElement>>;
56
149
  declare const CardDescription: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLParagraphElement> & React$1.RefAttributes<HTMLParagraphElement>>;
57
150
  declare const CardContent: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
58
151
  declare const CardFooter: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
@@ -62,7 +155,20 @@ declare const DialogTrigger: React$1.ForwardRefExoticComponent<DialogPrimitive.D
62
155
  declare const DialogPortal: React$1.FC<DialogPrimitive.DialogPortalProps>;
63
156
  declare const DialogClose: React$1.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & React$1.RefAttributes<HTMLButtonElement>>;
64
157
  declare const DialogOverlay: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
65
- declare const DialogContent: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
158
+ interface DialogContentProps extends React$1.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
159
+ /**
160
+ * Whether the corner ✕ is drawn. On by default — a dialog someone opened is one they can shut,
161
+ * and the mark is where every dialog in the console keeps it.
162
+ *
163
+ * Turn it off for a surface that is not the console's to close: a step mocking an OS sheet, whose
164
+ * real counterpart has no web close affordance. **Escape and the overlay still dismiss the
165
+ * dialog** — Radix owns both and neither is touched here — so this removes an affordance, never
166
+ * the only way out. A step whose only exit should be its own footer is a different thing again,
167
+ * and it is built by holding `open` yourself, not by hiding this.
168
+ */
169
+ showClose?: boolean;
170
+ }
171
+ declare const DialogContent: React$1.ForwardRefExoticComponent<DialogContentProps & React$1.RefAttributes<HTMLDivElement>>;
66
172
  declare const DialogHeader: {
67
173
  ({ className, ...props }: React$1.HTMLAttributes<HTMLDivElement>): React$1.JSX.Element;
68
174
  displayName: string;
@@ -75,11 +181,51 @@ declare const DialogTitle: React$1.ForwardRefExoticComponent<Omit<DialogPrimitiv
75
181
  declare const DialogDescription: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React$1.RefAttributes<HTMLParagraphElement>, "ref"> & React$1.RefAttributes<HTMLParagraphElement>>;
76
182
 
77
183
  declare const DropdownMenu: React$1.FC<DropdownMenuPrimitive.DropdownMenuProps>;
78
- declare const DropdownMenuTrigger: React$1.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuTriggerProps & React$1.RefAttributes<HTMLButtonElement>>;
79
184
  declare const DropdownMenuGroup: React$1.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuGroupProps & React$1.RefAttributes<HTMLDivElement>>;
80
185
  declare const DropdownMenuPortal: React$1.FC<DropdownMenuPrimitive.DropdownMenuPortalProps>;
81
186
  declare const DropdownMenuSub: React$1.FC<DropdownMenuPrimitive.DropdownMenuSubProps>;
82
187
  declare const DropdownMenuRadioGroup: React$1.ForwardRefExoticComponent<DropdownMenuPrimitive.DropdownMenuRadioGroupProps & React$1.RefAttributes<HTMLDivElement>>;
188
+ type DropdownMenuTriggerBaseProps = React$1.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Trigger>;
189
+ /**
190
+ * `quiet` appends the chevron as a second child, so it cannot be combined with `asChild`: a Radix
191
+ * `Slot` takes exactly one and throws on two. `asChild?: never` is what makes that a compile error
192
+ * rather than a runtime one. `bare` hands `children` straight through untouched, so a `false` from
193
+ * the unrendered chevron never reaches `Slot` and counts as that second child.
194
+ */
195
+ type DropdownMenuTriggerProps = (DropdownMenuTriggerBaseProps & {
196
+ variant?: 'bare';
197
+ chevron?: never;
198
+ }) | (Omit<DropdownMenuTriggerBaseProps, 'asChild'> & {
199
+ variant: 'quiet';
200
+ asChild?: never;
201
+ /**
202
+ * Whether the trigger wears its chevron. That mark means "there is something to pick here"
203
+ * (Guidelines/Controls/Stated, not picked), so a menu that only explains — a role a group
204
+ * carries, a reader who may not act — sets it `false` and stays pressable without promising a
205
+ * choice. Defaults to `true`.
206
+ */
207
+ chevron?: boolean;
208
+ });
209
+ /**
210
+ * `bare` is the Radix trigger with nothing added — whatever it wraps is the whole control, which is
211
+ * what `asChild` around a `Button` wants and what every trigger shipped before this prop existed
212
+ * got. It stays the default, and it stays byte-identical: `className` is left inside the spread
213
+ * rather than destructured and re-passed, so a trigger given none renders with no `class` attribute
214
+ * at all. Handing Radix an explicit `className={undefined}` is not the same thing — its `Slot`
215
+ * copies the key because the key is present, and writes `class=""`.
216
+ *
217
+ * `quiet` is the trigger that answers a row rather than a form: no border, sized to the words it
218
+ * happens to be showing, with the hover fill saying it can be pressed and the chevron saying a menu
219
+ * is behind it. A row's answer is already labelled by the row, so a bordered box beside it marks
220
+ * nothing, and a column of them down a list reads as a form put inside a list.
221
+ *
222
+ * **One `quiet`, one box.** It is spelled to match `Select variant="quiet"` step for step, because
223
+ * the two answer rows on the same screens and a word that meant three sizes was a word that meant
224
+ * nothing. The 36px floor is not decoration: a 20px control fails WCAG 2.5.8's 24px target size.
225
+ * A caption-scale handle inside a sub-line takes `min-h-6 text-xs` on top — smaller type in a
226
+ * smaller row, still on the floor.
227
+ */
228
+ declare const DropdownMenuTrigger: React$1.ForwardRefExoticComponent<DropdownMenuTriggerProps & React$1.RefAttributes<HTMLButtonElement>>;
83
229
  declare const DropdownMenuSubTrigger: React$1.ForwardRefExoticComponent<Omit<DropdownMenuPrimitive.DropdownMenuSubTriggerProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & {
84
230
  inset?: boolean;
85
231
  } & React$1.RefAttributes<HTMLDivElement>>;
@@ -100,7 +246,14 @@ declare const DropdownMenuShortcut: {
100
246
  displayName: string;
101
247
  };
102
248
 
103
- type InputProps = React$1.InputHTMLAttributes<HTMLInputElement>;
249
+ interface InputProps extends React$1.InputHTMLAttributes<HTMLInputElement> {
250
+ /**
251
+ * The unit the value is in — a currency, a period, a rate. It sits inside the field's border, on
252
+ * the side the number ends, because a unit set outside the box reads as the next word of the row
253
+ * rather than as part of the answer. It is text, never a control: nothing here is pressable.
254
+ */
255
+ suffix?: React$1.ReactNode;
256
+ }
104
257
  declare const Input: React$1.ForwardRefExoticComponent<InputProps & React$1.RefAttributes<HTMLInputElement>>;
105
258
 
106
259
  type InputGroupProps = React$1.HTMLAttributes<HTMLDivElement>;
@@ -141,9 +294,13 @@ interface PageHeaderProps {
141
294
  }
142
295
  /**
143
296
  * The standard page header for Organization and Product screens. Encodes the medallion↔subtitle
144
- * pair rule (Guidelines/Page headers): a decorative section medallion earns its place only beside a
145
- * subtitle, so keep both or drop both — you cannot render a lone medallion. An entity glyph (`media`)
146
- * is identity and always stays.
297
+ * pair rule (Guidelines/Page headers): a section medallion earns its place only beside a subtitle,
298
+ * so keep both or drop both — you cannot render a lone medallion. Cut a filler subtitle and the
299
+ * medallion goes with it, leaving a bare `<h2>`. An entity glyph (`media`) is identity, not
300
+ * decoration, and always stays.
301
+ *
302
+ * A header carrying a leading glyph indents its title past the content edge; a bare title sits on
303
+ * it. That difference is deliberate — it is what tells you a page has a mark.
147
304
  */
148
305
  declare function PageHeader({ title, subtitle, icon: Icon, media, badge, actions, id }: PageHeaderProps): React$1.JSX.Element;
149
306
 
@@ -156,6 +313,9 @@ declare function SectionIntro({ what, when }: SectionIntroProps): React$1.JSX.El
156
313
  interface SelectOption {
157
314
  value: string;
158
315
  label: string;
316
+ /** The line under the label, saying what choosing it does. Off the trigger — it belongs to the
317
+ * choice, not to the answer. */
318
+ description?: string;
159
319
  }
160
320
  interface SelectProps {
161
321
  value?: string;
@@ -169,8 +329,51 @@ interface SelectProps {
169
329
  'aria-label'?: string;
170
330
  'aria-labelledby'?: string;
171
331
  optionTestId?: (value: string) => string;
332
+ /**
333
+ * `quiet` is the select that answers a row rather than a form: no field border, no fixed height,
334
+ * sized to the word it is showing. A row's answer is already labelled by the row, so the box a
335
+ * field draws to say "type here" marks nothing — and a column of them down a list reads as a form
336
+ * put inside a list. Use it inside a row or a line of prose; keep `field` anywhere a label sits
337
+ * above the control.
338
+ */
339
+ variant?: 'field' | 'quiet';
340
+ }
341
+ declare function Select({ value, onValueChange, options, placeholder, disabled, className, 'data-testid': testId, id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, optionTestId, variant, }: SelectProps): React$1.JSX.Element;
342
+
343
+ interface SettingRowProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'title'> {
344
+ /** Leading glyph. Absent, the label starts at the row's left edge. */
345
+ icon?: LucideIcon;
346
+ label: React$1.ReactNode;
347
+ /** The second line under the label. */
348
+ description?: React$1.ReactNode;
349
+ /**
350
+ * Which side of the row carries the answer. `primary` is the settings row — the label names the
351
+ * thing and the control is whatever you set it to. `secondary` is the row that states a fact — a
352
+ * plan, a spend cap — where the value is what you came to read and the label only says what it is.
353
+ * Secondary also holds the label at the body weight under a description, because a quiet label
354
+ * does not become a heading by growing a second line, and it tops the value against that label
355
+ * rather than centring it: the right side is a string the reader baselines against the left, not
356
+ * an object beside a block.
357
+ */
358
+ labelTone?: 'primary' | 'secondary';
359
+ /** Names the control this row carries; renders <label>, otherwise <span>. */
360
+ htmlFor?: string;
361
+ /** The right-hand side — a Switch, a Select, a Button, or the value the row states. */
362
+ children: React$1.ReactNode;
172
363
  }
173
- declare function Select({ value, onValueChange, options, placeholder, disabled, className, 'data-testid': testId, id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, optionTestId, }: SelectProps): React$1.JSX.Element;
364
+ /**
365
+ * One `label … value` line inside a card — where the value is a control you set, or a fact you read.
366
+ *
367
+ * `description` decides the row's shape, and that is a rule rather than an accident: a bare
368
+ * `label … control` line is a field caption, so it takes the body weight and centres on its
369
+ * control, while a label carrying a second line is the heading of a small block, so the two lines
370
+ * align to the top of the glyph beside them.
371
+ *
372
+ * `labelTone` decides which side the reader's eye lands on, and it is the one thing `description`
373
+ * does not settle: a row stating a plan or a spend cap wants a quiet label whether or not a second
374
+ * line explains who may change it.
375
+ */
376
+ declare const SettingRow: React$1.ForwardRefExoticComponent<SettingRowProps & React$1.RefAttributes<HTMLDivElement>>;
174
377
 
175
378
  interface SwitchProps {
176
379
  checked: boolean;
@@ -189,29 +392,95 @@ declare const RadioGroup: React$1.ForwardRefExoticComponent<Omit<RadioGroupPrimi
189
392
  declare const RadioGroupItem: React$1.ForwardRefExoticComponent<Omit<RadioGroupPrimitive.RadioGroupItemProps & React$1.RefAttributes<HTMLButtonElement>, "ref"> & React$1.RefAttributes<HTMLButtonElement>>;
190
393
 
191
394
  type TextareaProps = React$1.TextareaHTMLAttributes<HTMLTextAreaElement>;
395
+ /** The same field edge an `Input` takes, for the same reason (`Guidelines/Look/Borders`, #417). */
192
396
  declare const Textarea: React$1.ForwardRefExoticComponent<TextareaProps & React$1.RefAttributes<HTMLTextAreaElement>>;
193
397
 
194
398
  declare const Slider: React$1.ForwardRefExoticComponent<Omit<SliderPrimitive.SliderProps & React$1.RefAttributes<HTMLSpanElement>, "ref"> & React$1.RefAttributes<HTMLSpanElement>>;
195
399
 
400
+ /**
401
+ * Two signals on two channels that never touch (#446), and two treatments for two shapes.
402
+ *
403
+ * **Fill means the pointer is here.** Selection reads as an edge, and `ToggleGroup` picks which
404
+ * edge from its `type` — the question being "can nothing be selected?".
405
+ *
406
+ * - `frame` (a standalone `Toggle`, and every `type="multiple"` group): each item carries its own
407
+ * 1px hairline and selection steps it up to `border-strong` — 5.17:1 against the page in light and
408
+ * 5.47:1 in dark, and 3.63:1 / 4.31:1 above the resting hairline it replaces. Fill used to say both
409
+ * things at 1.07:1, which is why a filter row could not say which of its filters were applied.
410
+ * - `track` (every `type="single"` group): the group draws the track and the selected slot takes the
411
+ * selection pair (#452) — `bg-bg-selected` filled inside a `ring-border-selected` edge. The fill is
412
+ * 1.08:1 against the page in dark and 1.04:1 in light, so it is the **edge** that carries the
413
+ * reading: 3.81:1 above the slot's own fill in dark and 3.75:1 in light, against 1.07:1 / 1.53:1
414
+ * for the `border-subtle` ring over `bg-bg-overlay` it replaces. A fill that faint is only placed
415
+ * at all against the track's own frame, which is why the track belongs to the component and not to
416
+ * the call site.
417
+ *
418
+ * The mark is a **ring**, not a border: a ring is a box-shadow, so it costs no layout and an
419
+ * icon-only toggle stays square at the height its `size` declares. It is also the whole mark —
420
+ * `track` carries no `shadow-sm`. The shadow was the raised reading a 1.18:1 fill could not give
421
+ * alone; under a 3.81:1 edge it is a second, weaker statement of one state, its blur compositing to
422
+ * 1.11:1 against the page in dark and 1.14:1 in light, and `shadow-sm` is the one dark step
423
+ * `@lessly/tokens@0.7.0` leaves without a rim, so in dark it can only darken.
424
+ *
425
+ * Focus is an **outline held 2px off the box** — a flush ring painted over the selection mark, and
426
+ * focused-selected and focused-unselected measured 1.55:1 apart, which is #446 on the keyboard.
427
+ *
428
+ * **An icon-only box drops its horizontal padding** (`ICON_ONLY_BOX` below), the same trade
429
+ * `Button`'s icon-only box makes with `p-0`. Padding is the whole of the intrinsic width when the
430
+ * only content is a 16px glyph, so `min-w-*` binds only while it stays under it: `sm` and `default`
431
+ * cleared that by coincidence (10+16+10 = 36, 12+16+12 = 40) and `lg` did not — `px-5` around a
432
+ * glyph is 56 against `h-12`, and an icon-only `lg` shipped 56&times;48. A **text** toggle is
433
+ * untouched at every size.
434
+ */
196
435
  declare const toggleVariants: (props?: ({
436
+ treatment?: "track" | "frame" | null | undefined;
197
437
  variant?: "default" | "outline" | null | undefined;
198
438
  size?: "default" | "sm" | "lg" | null | undefined;
199
439
  } & class_variance_authority_types.ClassProp) | undefined) => string;
200
440
  declare const Toggle: React$1.ForwardRefExoticComponent<Omit<TogglePrimitive.ToggleProps & React$1.RefAttributes<HTMLButtonElement>, "ref"> & VariantProps<(props?: ({
441
+ treatment?: "track" | "frame" | null | undefined;
201
442
  variant?: "default" | "outline" | null | undefined;
202
443
  size?: "default" | "sm" | "lg" | null | undefined;
203
444
  } & class_variance_authority_types.ClassProp) | undefined) => string> & React$1.RefAttributes<HTMLButtonElement>>;
204
445
 
446
+ /**
447
+ * `type` answers "can nothing be selected?", and that is what decides how selection reads (#446).
448
+ *
449
+ * `multiple` is a set of independent chips — a filter row, where nothing need be on — so each chip
450
+ * carries its own edge and selection steps that edge up. `single` is one object with a moving part,
451
+ * so it takes the segmented-control treatment (#346): the group draws the **track** — a hairline
452
+ * frame with no fill — and the selected slot is the only filled thing in the row.
453
+ *
454
+ * The track is the component's, not the call site's: the slot fill measures 1.04:1 against the page
455
+ * in light and 1.08:1 in dark, so without the track's edge a selected slot reads as nothing at all —
456
+ * the defect #446 reports. A component cannot own half of a two-part signal.
457
+ */
205
458
  declare const ToggleGroup: React$1.ForwardRefExoticComponent<((Omit<ToggleGroupPrimitive.ToggleGroupSingleProps & React$1.RefAttributes<HTMLDivElement>, "ref"> | Omit<ToggleGroupPrimitive.ToggleGroupMultipleProps & React$1.RefAttributes<HTMLDivElement>, "ref">) & VariantProps<(props?: ({
459
+ treatment?: "track" | "frame" | null | undefined;
206
460
  variant?: "default" | "outline" | null | undefined;
207
461
  size?: "default" | "sm" | "lg" | null | undefined;
208
- } & class_variance_authority_types.ClassProp) | undefined) => string>) & React$1.RefAttributes<HTMLDivElement>>;
462
+ } & class_variance_authority_types.ClassProp) | undefined) => string> & {
463
+ /**
464
+ * The selection mark is one element that slides between slots on the motion tokens, rather
465
+ * than appearing on each. The group makes its slots equal-width to carry it; the width of the
466
+ * **track** is still the caller's, and defaults to the width of whatever holds it.
467
+ */
468
+ sliding?: boolean;
469
+ }) & React$1.RefAttributes<HTMLDivElement>>;
209
470
  declare const ToggleGroupItem: React$1.ForwardRefExoticComponent<Omit<ToggleGroupPrimitive.ToggleGroupItemProps & React$1.RefAttributes<HTMLButtonElement>, "ref"> & VariantProps<(props?: ({
471
+ treatment?: "track" | "frame" | null | undefined;
210
472
  variant?: "default" | "outline" | null | undefined;
211
473
  size?: "default" | "sm" | "lg" | null | undefined;
212
- } & class_variance_authority_types.ClassProp) | undefined) => string> & React$1.RefAttributes<HTMLButtonElement>>;
474
+ } & class_variance_authority_types.ClassProp) | undefined) => string> & {
475
+ /**
476
+ * Holds its column without being selectable — a rung that does not apply to this row, so a
477
+ * ladder of levels still lines up down a long list. Renders non-focusable and aria-hidden at
478
+ * the same width, with its label kept for the width and hidden from view.
479
+ */
480
+ inert?: boolean;
481
+ } & React$1.RefAttributes<HTMLButtonElement>>;
213
482
 
214
- declare const InputOTP: React$1.ForwardRefExoticComponent<(Omit<Omit<React$1.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
483
+ declare const InputOTP: React$1.ForwardRefExoticComponent<(Omit<Omit<React$1.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
215
484
  value?: string;
216
485
  onChange?: (newValue: string) => unknown;
217
486
  maxLength: number;
@@ -224,7 +493,7 @@ declare const InputOTP: React$1.ForwardRefExoticComponent<(Omit<Omit<React$1.Inp
224
493
  } & {
225
494
  render: (props: input_otp.RenderProps) => React$1.ReactNode;
226
495
  children?: never;
227
- } & React$1.RefAttributes<HTMLInputElement>, "ref"> | Omit<Omit<React$1.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
496
+ } & React$1.RefAttributes<HTMLInputElement>, "ref"> | Omit<Omit<React$1.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
228
497
  value?: string;
229
498
  onChange?: (newValue: string) => unknown;
230
499
  maxLength: number;
@@ -250,9 +519,26 @@ declare const PopoverAnchor: React$1.ForwardRefExoticComponent<PopoverPrimitive.
250
519
  declare const PopoverContent: React$1.ForwardRefExoticComponent<Omit<PopoverPrimitive.PopoverContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
251
520
 
252
521
  declare const TooltipProvider: React$1.FC<TooltipPrimitive.TooltipProviderProps>;
253
- declare const Tooltip: React$1.FC<TooltipPrimitive.TooltipProps>;
254
- declare const TooltipTrigger: React$1.ForwardRefExoticComponent<TooltipPrimitive.TooltipTriggerProps & React$1.RefAttributes<HTMLButtonElement>>;
255
- declare const TooltipContent: React$1.ForwardRefExoticComponent<Omit<TooltipPrimitive.TooltipContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
522
+ declare const Tooltip: {
523
+ ({ children, ...props }: React$1.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>): React$1.JSX.Element;
524
+ displayName: string;
525
+ };
526
+ declare const TooltipTrigger: React$1.ForwardRefExoticComponent<Omit<TooltipPrimitive.TooltipTriggerProps & React$1.RefAttributes<HTMLButtonElement>, "ref"> & React$1.RefAttributes<HTMLButtonElement>>;
527
+ type TooltipPrimitiveContentProps = React$1.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>;
528
+ interface TooltipContentProps extends TooltipPrimitiveContentProps {
529
+ /**
530
+ * Which side of the trigger the tooltip sits on. Physical: `left` and `right`
531
+ * are screen edges and stay where they are in a right-to-left layout.
532
+ */
533
+ side?: TooltipPrimitiveContentProps['side'];
534
+ /**
535
+ * Which end of the trigger the tooltip lines up with. Logical: `start` is the
536
+ * end the text starts at — the left in a left-to-right layout, the right in a
537
+ * right-to-left one.
538
+ */
539
+ align?: TooltipPrimitiveContentProps['align'];
540
+ }
541
+ declare const TooltipContent: React$1.ForwardRefExoticComponent<TooltipContentProps & React$1.RefAttributes<HTMLDivElement>>;
256
542
 
257
543
  declare const HoverCard: React$1.FC<HoverCardPrimitive.HoverCardProps>;
258
544
  declare const HoverCardTrigger: React$1.ForwardRefExoticComponent<HoverCardPrimitive.HoverCardTriggerProps & React$1.RefAttributes<HTMLAnchorElement>>;
@@ -264,7 +550,7 @@ declare const SheetClose: React$1.ForwardRefExoticComponent<DialogPrimitive.Dial
264
550
  declare const SheetPortal: React$1.FC<DialogPrimitive.DialogPortalProps>;
265
551
  declare const SheetOverlay: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
266
552
  declare const SheetContent: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & VariantProps<(props?: ({
267
- side?: "top" | "right" | "bottom" | "left" | null | undefined;
553
+ side?: "bottom" | "left" | "right" | "top" | null | undefined;
268
554
  } & class_variance_authority_types.ClassProp) | undefined) => string> & React$1.RefAttributes<HTMLDivElement>>;
269
555
  declare const SheetHeader: {
270
556
  ({ className, ...props }: React$1.HTMLAttributes<HTMLDivElement>): React$1.JSX.Element;
@@ -369,28 +655,129 @@ declare const MenubarShortcut: {
369
655
  displayName: string;
370
656
  };
371
657
 
658
+ /**
659
+ * `status` (#359) is the console's state pill: borderless, filled with `bg-bg-sunken`.
660
+ * `outline` gives a status the same hairline frame a button has — and since a ghost button carries
661
+ * no border at rest, the status pill ended up the most button-shaped object in a row. A fill with no
662
+ * frame reads as a label rather than a control. It is deliberately *not* `secondary`: that's the
663
+ * attribute chip (scope, auth method), so a status painted with it reads as an attribute. Under the
664
+ * cursor no neutral fill carries the pill's shape at all: `EntityRow` washes to `bg-bg-elevated`,
665
+ * and `bg-bg-sunken` measures 1.12:1 against it in light, `bg-bg-secondary` 1.01:1, where a non-text
666
+ * mark needs 3:1. `bg-bg-sunken` is the convention, not the measurement — there is no better fill in
667
+ * the ramp to go looking for.
668
+ *
669
+ * `danger-subtle`, `warning-subtle` and `neutral-subtle` are the three rungs of a severity ladder —
670
+ * critical, important, and the rung that is only worth knowing. They are the one place colour marks
671
+ * a state rather than an action, and *subtle* is the whole permission: the solid `destructive` and
672
+ * `warning` fills belong to a thing you must act on, and three of those read as three shouting
673
+ * pills. See Guidelines/Colour marks actions.
674
+ *
675
+ * The bottom rung is its own variant rather than the `status` pill because the three have to be read
676
+ * as one ladder: `bg-bg-sunken` is the strongest plate of the three in light, so a ladder resting on
677
+ * it puts its heaviest mark under its two lightest and reads upside down.
678
+ */
372
679
  declare const badgeVariants: (props?: ({
373
- variant?: "default" | "destructive" | "outline" | "secondary" | "success" | "warning" | null | undefined;
680
+ variant?: "status" | "default" | "destructive" | "outline" | "secondary" | "danger-subtle" | "warning-subtle" | "neutral-subtle" | "success" | "warning" | null | undefined;
374
681
  } & class_variance_authority_types.ClassProp) | undefined) => string;
375
682
  interface BadgeProps extends React$1.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
376
683
  }
377
684
  declare const Badge: React$1.ForwardRefExoticComponent<BadgeProps & React$1.RefAttributes<HTMLDivElement>>;
378
685
 
379
- declare const Table: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLTableElement> & React$1.RefAttributes<HTMLTableElement>>;
686
+ interface TableProps extends React$1.HTMLAttributes<HTMLTableElement> {
687
+ /**
688
+ * Name the table. Three tables on one page announce identically without a name,
689
+ * and a screen-reader user picking one out of the list has nothing to pick by.
690
+ * A `TableCaption` names it visibly and is the first choice; use this when the
691
+ * name is already on the page as a heading — then prefer `aria-labelledby`.
692
+ */
693
+ 'aria-label'?: string;
694
+ /** Names the table from a heading already on the page. See `aria-label`. */
695
+ 'aria-labelledby'?: string;
696
+ }
697
+ /**
698
+ * A data table. Give every one of them a name — a `TableCaption`, or
699
+ * `aria-label` / `aria-labelledby` when the name is already on the page.
700
+ */
701
+ declare const Table: React$1.ForwardRefExoticComponent<TableProps & React$1.RefAttributes<HTMLTableElement>>;
380
702
  declare const TableHeader: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLTableSectionElement> & React$1.RefAttributes<HTMLTableSectionElement>>;
381
703
  declare const TableBody: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLTableSectionElement> & React$1.RefAttributes<HTMLTableSectionElement>>;
382
704
  declare const TableFooter: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLTableSectionElement> & React$1.RefAttributes<HTMLTableSectionElement>>;
383
705
  declare const TableRow: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLTableRowElement> & React$1.RefAttributes<HTMLTableRowElement>>;
384
706
  declare const TableHead: React$1.ForwardRefExoticComponent<React$1.ThHTMLAttributes<HTMLTableCellElement> & React$1.RefAttributes<HTMLTableCellElement>>;
385
707
  declare const TableCell: React$1.ForwardRefExoticComponent<React$1.TdHTMLAttributes<HTMLTableCellElement> & React$1.RefAttributes<HTMLTableCellElement>>;
708
+ /** The table's visible name. Ends up as the table's accessible name. */
386
709
  declare const TableCaption: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLTableCaptionElement> & React$1.RefAttributes<HTMLTableCaptionElement>>;
387
710
 
388
711
  declare const Skeleton: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
389
712
 
713
+ /**
714
+ * @deprecated Use `PersonAvatar` for a person, `GlyphAvatar` for an agent or a group, or
715
+ * `EntityTile` for an object. Those three share one size scale, a tint family that holds contrast in
716
+ * both themes, and a fallback that survives a 404. `Avatar` will be removed in 1.0.
717
+ */
390
718
  declare const Avatar: React$1.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React$1.RefAttributes<HTMLSpanElement>, "ref"> & React$1.RefAttributes<HTMLSpanElement>>;
391
719
  declare const AvatarImage: React$1.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps & React$1.RefAttributes<HTMLImageElement>, "ref"> & React$1.RefAttributes<HTMLImageElement>>;
392
720
  declare const AvatarFallback: React$1.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarFallbackProps & React$1.RefAttributes<HTMLSpanElement>, "ref"> & React$1.RefAttributes<HTMLSpanElement>>;
393
721
 
722
+ /**
723
+ * The box every identity mark is drawn in. Internal on purpose: it is the only place that knows
724
+ * about `shape`, and keeping it unexported is what makes a round product unspellable. Import one of
725
+ * `PersonAvatar`, `GlyphAvatar` or `EntityTile` instead.
726
+ */
727
+ type MarkSize = 'xs' | 'sm' | 'md' | 'lg';
728
+
729
+ /**
730
+ * A person's mark: their photo, or their initials on a colour picked from their id so the same
731
+ * person is the same colour on every screen.
732
+ *
733
+ * Round, because a circle is a principal (`Guidelines/Avatars`). Pass `id` rather than relying on the
734
+ * name if the colour should survive a rename.
735
+ */
736
+ interface PersonAvatarProps {
737
+ name: string;
738
+ /** Seeds the tint. Falls back to the name, which is stable until the person is renamed. */
739
+ id?: string;
740
+ src?: string;
741
+ size?: MarkSize;
742
+ /** Opt into the accessibility tree. Omit beside a row title that already names the person. */
743
+ label?: string;
744
+ }
745
+ declare function PersonAvatar({ name, id, src, size, label }: PersonAvatarProps): React$1.JSX.Element;
746
+
747
+ /**
748
+ * The mark for a principal with no photo and no initials — an agent or a group.
749
+ *
750
+ * Round, like every principal. Never tinted: a tint follows a name, and `agent` is a kind rather than
751
+ * an identity, so colouring it would say nothing. Its job is to settle which glyph an agent gets, so
752
+ * two screens cannot pick different ones.
753
+ */
754
+ interface GlyphAvatarProps {
755
+ kind: 'agent' | 'group';
756
+ size?: MarkSize;
757
+ label?: string;
758
+ }
759
+ declare function GlyphAvatar({ kind, size, label }: GlyphAvatarProps): React$1.JSX.Element;
760
+
761
+ /**
762
+ * The mark for an object — a product, a connector, an API key, a device, a passkey.
763
+ *
764
+ * A rounded square, because a square is an object and a circle is a principal
765
+ * (`Guidelines/Avatars`). You can tell what a row is about before reading a word of it.
766
+ *
767
+ * **A tint follows a name, not a type.** A named thing you re-recognise across screens gets a colour;
768
+ * a thing identified only by what it is stays neutral. So a product tints and an API key does not.
769
+ */
770
+ interface EntityTileProps {
771
+ /** The object's own name. Its presence is what earns a tint, and its first letter is the fallback. */
772
+ name?: string;
773
+ /** A type glyph. Wins over the initial, and never tints. */
774
+ glyph?: React$1.ReactNode;
775
+ src?: string;
776
+ size?: MarkSize;
777
+ label?: string;
778
+ }
779
+ declare function EntityTile({ name, glyph, src, size, label }: EntityTileProps): React$1.JSX.Element;
780
+
394
781
  declare const Separator: React$1.ForwardRefExoticComponent<Omit<SeparatorPrimitive.SeparatorProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
395
782
 
396
783
  declare const Progress: React$1.ForwardRefExoticComponent<Omit<ProgressPrimitive.ProgressProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
@@ -417,9 +804,16 @@ declare const ScrollBar: React$1.ForwardRefExoticComponent<Omit<ScrollAreaPrimit
417
804
  declare const alertVariants: (props?: ({
418
805
  variant?: "default" | "destructive" | "success" | "warning" | null | undefined;
419
806
  } & class_variance_authority_types.ClassProp) | undefined) => string;
420
- declare const Alert: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
421
- variant?: "default" | "destructive" | "success" | "warning" | null | undefined;
422
- } & class_variance_authority_types.ClassProp) | undefined) => string> & React$1.RefAttributes<HTMLDivElement>>;
807
+ interface AlertProps extends React$1.HTMLAttributes<HTMLDivElement>, VariantProps<typeof alertVariants> {
808
+ /**
809
+ * The value the alert is about — a secret, an id, an endpoint. It gets its own line below the
810
+ * words, in monospace, and truncates instead of running off the edge of the card.
811
+ */
812
+ value?: React$1.ReactNode;
813
+ /** What to do with that value — copy it, dismiss it. Sits at the end of the value's line, at full width. */
814
+ action?: React$1.ReactNode;
815
+ }
816
+ declare const Alert: React$1.ForwardRefExoticComponent<AlertProps & React$1.RefAttributes<HTMLDivElement>>;
423
817
  declare const AlertTitle: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLHeadingElement> & React$1.RefAttributes<HTMLParagraphElement>>;
424
818
  declare const AlertDescription: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLParagraphElement> & React$1.RefAttributes<HTMLParagraphElement>>;
425
819
 
@@ -489,7 +883,7 @@ declare const CommandInput: React$1.ForwardRefExoticComponent<Omit<Omit<Pick<Pic
489
883
  ref?: React$1.Ref<HTMLInputElement>;
490
884
  } & {
491
885
  asChild?: boolean;
492
- }, "asChild" | "key" | keyof React$1.InputHTMLAttributes<HTMLInputElement>>, "type" | "value" | "onChange"> & {
886
+ }, "asChild" | "key" | keyof React$1.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "type" | "value"> & {
493
887
  value?: string;
494
888
  onValueChange?: (search: string) => void;
495
889
  } & React$1.RefAttributes<HTMLInputElement>, "ref"> & React$1.RefAttributes<HTMLInputElement>>;
@@ -515,7 +909,7 @@ declare const CommandGroup: React$1.ForwardRefExoticComponent<Omit<{
515
909
  ref?: React$1.Ref<HTMLDivElement>;
516
910
  } & {
517
911
  asChild?: boolean;
518
- }, "asChild" | "key" | keyof React$1.HTMLAttributes<HTMLDivElement>>, "value" | "heading"> & {
912
+ }, "asChild" | "key" | keyof React$1.HTMLAttributes<HTMLDivElement>>, "heading" | "value"> & {
519
913
  heading?: React$1.ReactNode;
520
914
  value?: string;
521
915
  forceMount?: boolean;
@@ -527,19 +921,13 @@ declare const CommandSeparator: React$1.ForwardRefExoticComponent<Omit<Pick<Pick
527
921
  }, "asChild" | "key" | keyof React$1.HTMLAttributes<HTMLDivElement>> & {
528
922
  alwaysRender?: boolean;
529
923
  } & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
530
- declare const CommandItem: React$1.ForwardRefExoticComponent<Omit<{
531
- children?: React$1.ReactNode;
532
- } & Omit<Pick<Pick<React$1.DetailedHTMLProps<React$1.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React$1.HTMLAttributes<HTMLDivElement>> & {
533
- ref?: React$1.Ref<HTMLDivElement>;
534
- } & {
535
- asChild?: boolean;
536
- }, "asChild" | "key" | keyof React$1.HTMLAttributes<HTMLDivElement>>, "disabled" | "value" | "onSelect"> & {
537
- disabled?: boolean;
538
- onSelect?: (value: string) => void;
539
- value?: string;
540
- keywords?: string[];
541
- forceMount?: boolean;
542
- } & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
924
+ interface CommandItemProps extends React$1.ComponentPropsWithoutRef<typeof Command$1.Item> {
925
+ /** Leading mark — an avatar or tile. Does not shrink; the item switches to top alignment. */
926
+ mark?: React$1.ReactNode;
927
+ /** The second line under the label. */
928
+ sub?: React$1.ReactNode;
929
+ }
930
+ declare const CommandItem: React$1.ForwardRefExoticComponent<CommandItemProps & React$1.RefAttributes<HTMLDivElement>>;
543
931
  declare const CommandShortcut: {
544
932
  ({ className, ...props }: React$1.HTMLAttributes<HTMLSpanElement>): React$1.JSX.Element;
545
933
  displayName: string;
@@ -586,6 +974,40 @@ declare namespace DatePicker {
586
974
  var displayName: string;
587
975
  }
588
976
 
977
+ interface AddPickerItem {
978
+ id: string;
979
+ name: string;
980
+ /** Second line under the name. */
981
+ sub?: string;
982
+ /** Leading mark — an avatar or a tile. */
983
+ mark?: React$1.ReactNode;
984
+ }
985
+ interface AddPickerProps {
986
+ /** Trigger label after the `+`. "Product" → "+ Product". */
987
+ label: string;
988
+ /** Plural noun for the search field: "Search 100 products". */
989
+ noun: string;
990
+ items: AddPickerItem[];
991
+ /** Ids already taken. Filtered out of the list, still counted in the placeholder. */
992
+ exclude?: string[];
993
+ onPick: (id: string) => void;
994
+ className?: string;
995
+ }
996
+ /**
997
+ * The quiet `+ Label` that picks something that already exists, and behind it a search you type into
998
+ * rather than a list you scroll (Guidelines/Controls/Add & search). The trigger is four lines; what
999
+ * this owns is the forty under it — the open state, the query, the reset on both ways out of it, and
1000
+ * the filter.
1001
+ *
1002
+ * The count in the placeholder is the whole set, not what is left: it says how big the thing you are
1003
+ * searching is, which is why `exclude` leaves the list and not the number.
1004
+ *
1005
+ * `shouldFilter={false}` and our own `includes`: cmdk scores what it filters and reorders the list as
1006
+ * you type, and a reader looking for a name they can already see is helped by it shortening and not
1007
+ * by it rearranging.
1008
+ */
1009
+ declare const AddPicker: React$1.ForwardRefExoticComponent<AddPickerProps & React$1.RefAttributes<HTMLButtonElement>>;
1010
+
589
1011
  type CarouselApi = UseEmblaCarouselType[1];
590
1012
  type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
591
1013
  type CarouselOptions = UseCarouselParameters[0];
@@ -634,32 +1056,89 @@ declare const FormControl: React$1.ForwardRefExoticComponent<Omit<React$1.HTMLAt
634
1056
  declare const FormDescription: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLParagraphElement> & React$1.RefAttributes<HTMLParagraphElement>>;
635
1057
  declare const FormMessage: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLParagraphElement> & React$1.RefAttributes<HTMLParagraphElement>>;
636
1058
 
1059
+ /**
1060
+ * A dot is a small mark on a surface, so it paints from the theme-aware `--icon-*` status
1061
+ * tokens rather than the `--bg-*` fills, which exist to sit solid behind text and are not all
1062
+ * overridden per theme. Every variant clears 3:1 against `--bg-surface` in both themes —
1063
+ * `status-dot.test.tsx` pins that, reading the token straight off these class names.
1064
+ */
637
1065
  declare const statusDotVariants: (props?: ({
638
- status?: "success" | "warning" | "brand" | "danger" | "neutral" | null | undefined;
1066
+ status?: "success" | "warning" | "neutral" | "brand" | "danger" | null | undefined;
639
1067
  size?: "sm" | "lg" | "md" | null | undefined;
640
1068
  } & class_variance_authority_types.ClassProp) | undefined) => string;
641
1069
  interface StatusDotProps extends React$1.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof statusDotVariants> {
642
1070
  pulse?: boolean;
1071
+ /**
1072
+ * What the dot means, for the case where the dot is the only signal. Say the state in the
1073
+ * product's own words — "Blocked", "Awaiting review" — never the variant name, which is a
1074
+ * palette token the design system may rename without telling anyone downstream.
1075
+ *
1076
+ * Leave it off whenever a text label sits beside the dot. That is nearly every real usage,
1077
+ * and the dot then stays out of the accessibility tree so the label reads alone.
1078
+ */
1079
+ label?: string;
643
1080
  }
1081
+ /**
1082
+ * @deprecated A coloured circle that marks state. The console reads state as `Badge
1083
+ * variant="status"` — a borderless fill on `bg-bg-sunken`, no colour — because colour marks
1084
+ * actions there, never state, and decorative circles are banned outright. #334 took the last
1085
+ * three published components off this. It stays exported for the reference app's demo pages,
1086
+ * where a coloured dot on a campaign status is data, not console chrome. Reach for
1087
+ * `Badge variant="status"` in anything console-shaped.
1088
+ *
1089
+ * The dot is decorative unless you pass `label`, so a text label beside it reads on its own.
1090
+ */
644
1091
  declare const StatusDot: React$1.ForwardRefExoticComponent<StatusDotProps & React$1.RefAttributes<HTMLSpanElement>>;
645
1092
 
646
1093
  interface DocsLinkProps extends React$1.AnchorHTMLAttributes<HTMLAnchorElement> {
647
1094
  href?: string;
648
1095
  label?: string;
1096
+ /**
1097
+ * Show the leading `BookOpen` glyph. Defaults to `true` — the docs affordance. Set it `false`
1098
+ * where the target isn't documentation (a legal document, a status page): the book would either
1099
+ * mislabel the link or repeat a book already on screen, while the trailing `ExternalLink` mark,
1100
+ * the new-tab target and the `rel` are exactly what such a link still wants.
1101
+ */
1102
+ showLeadingIcon?: boolean;
649
1103
  }
650
1104
  declare const DocsLink: React$1.ForwardRefExoticComponent<DocsLinkProps & React$1.RefAttributes<HTMLAnchorElement>>;
651
1105
 
652
1106
  interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'title'> {
653
1107
  icon?: LucideIcon;
654
1108
  title: React$1.ReactNode;
1109
+ /**
1110
+ * The tag the title emits. It defaults to `p` because an empty state usually sits inside a card
1111
+ * that already holds the heading; a page whose only text is an empty state names a level here so
1112
+ * the page has an outline at all.
1113
+ */
1114
+ titleAs?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p';
655
1115
  description?: React$1.ReactNode;
656
1116
  action?: React$1.ReactNode;
657
1117
  }
1118
+ /**
1119
+ * The empty state for any list, table or panel that can be empty (#356).
1120
+ *
1121
+ * It draws no frame and no fill of its own, because an empty state lives inside a Card and a second
1122
+ * border 16px in from the first is the same edge drawn twice. The glyph is bare for that same
1123
+ * reason, and only that one: it is already inside a frame. A plate is not decoration everywhere —
1124
+ * `PageHeader` gives the identical section glyph a medallion, because there the mark appears once
1125
+ * and stands alone on the page (Guidelines/Section glyphs). Standing on its own, wrap it in a Card.
1126
+ *
1127
+ * `title` states what is missing; `description` says what to do about it, and only earns its line
1128
+ * when it carries a fact the title doesn't; `action` is that step inline, so the way forward is
1129
+ * where the eye already is.
1130
+ */
658
1131
  declare const EmptyState: React$1.ForwardRefExoticComponent<EmptyStateProps & React$1.RefAttributes<HTMLDivElement>>;
659
1132
 
660
- interface CopyButtonProps extends Omit<ButtonProps, 'value'> {
1133
+ interface CopyButtonProps extends Omit<ButtonProps, 'value' | 'children' | 'icon' | 'iconPosition' | 'asChild'> {
661
1134
  value: string;
662
1135
  label?: string;
1136
+ /**
1137
+ * The value is a secret. Show it in front of the button as a fixed run of dots and its last four
1138
+ * characters — enough to tell two secrets apart, never enough to read one — and name the button by
1139
+ * that tail, so a screen reader says "Copy ending 7f3a" instead of reading out the dots.
1140
+ */
1141
+ masked?: boolean;
663
1142
  }
664
1143
  declare const CopyButton: React$1.ForwardRefExoticComponent<CopyButtonProps & React$1.RefAttributes<HTMLButtonElement>>;
665
1144
 
@@ -679,10 +1158,140 @@ interface StatCardProps extends React$1.HTMLAttributes<HTMLDivElement> {
679
1158
  }
680
1159
  declare const StatCard: React$1.ForwardRefExoticComponent<StatCardProps & React$1.RefAttributes<HTMLDivElement>>;
681
1160
 
1161
+ /** The factors this challenge can present. Order in `methods` is preference, not availability. */
1162
+ type StepUpMethod = 'passkey' | 'code';
1163
+ /**
1164
+ * The events that carry the digits of a one-time code. They are refused at compile time and stopped
1165
+ * at the field, so the code does not bubble out to a parent by the ordinary React route.
1166
+ */
1167
+ type CodeBearingHandler = 'onChange' | 'onChangeCapture' | 'onInput' | 'onInputCapture' | 'onBeforeInput' | 'onBeforeInputCapture' | 'onKeyDown' | 'onKeyDownCapture' | 'onKeyUp' | 'onKeyUpCapture' | 'onKeyPress' | 'onKeyPressCapture' | 'onPaste' | 'onPasteCapture' | 'onCopy' | 'onCopyCapture' | 'onCut' | 'onCutCapture' | 'onDrop' | 'onDropCapture';
1168
+ interface StepUpChallengeProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, CodeBearingHandler> {
1169
+ /**
1170
+ * What this person can actually use, strongest first. `['code']` is the user with no passkey
1171
+ * enrolled — the passkey route then isn't offered at all, rather than offered and failing.
1172
+ */
1173
+ methods?: readonly StepUpMethod[];
1174
+ /**
1175
+ * Which factor to open on, when it shouldn't be the first in `methods` — resuming a flow that had
1176
+ * already fallen back to the code, say. Ignored if it isn't one of `methods`.
1177
+ */
1178
+ defaultMethod?: StepUpMethod;
1179
+ /** Fires when the user changes factor. The switch itself is handled here. */
1180
+ onMethodChange?: (method: StepUpMethod) => void;
1181
+ /** Digits in the one-time code. 6 is TOTP's norm; some issuers use 8. */
1182
+ codeLength?: number;
1183
+ /**
1184
+ * A verification is out. Both actions freeze. It is the honest signal and worth wiring, but it is
1185
+ * not what makes one press one attempt — the component latches that itself, because a handler
1186
+ * that awaits a nonce before setting this leaves a window where it is still `false`.
1187
+ */
1188
+ verifying?: boolean;
1189
+ /**
1190
+ * What the user is told about a failed attempt, in the product's own words. Repeat the same
1191
+ * string as often as you like: nothing here keys off its identity, so one constant "That code is
1192
+ * not right" for every wrong code — which is what a server that doesn't leak *why* it failed
1193
+ * sends — behaves exactly like a message that changes every time.
1194
+ */
1195
+ error?: string;
1196
+ /** The confirm's label. The caller names the action its window is about, e.g. `Archive product`. */
1197
+ confirmLabel?: string;
1198
+ /**
1199
+ * The confirm rests filled red. For the window whose confirm **is** the destructive act — a dialog
1200
+ * asking for a code before it turns two-factor authentication off — where a dialog's confirm is
1201
+ * the one place red rests (Guidelines/Destructive actions). Leave it off when the challenge only
1202
+ * guards a step on the way somewhere: a red button there paints the verification as the damage.
1203
+ *
1204
+ * It changes the button and nothing else. **It does not turn the challenge into a confirmation**
1205
+ * — the question is still who you are, never whether you meant it, so no "are you sure?" appears
1206
+ * beside it and the window above still owes the stakes in its own words.
1207
+ */
1208
+ destructive?: boolean;
1209
+ /** The way back's label. `Cancel` when it closes the window, `Back` when it steps back. */
1210
+ backLabel?: string;
1211
+ /** Omit it and there is no way back — an inline challenge on a page has nowhere to go. */
1212
+ onBack?: () => void;
1213
+ /** The user asked to use their passkey. Perform the WebAuthn call here. */
1214
+ onVerifyPasskey?: () => void;
1215
+ /** The user submitted a complete code. Verify it here. It is handed over exactly once. */
1216
+ onVerifyCode?: (code: string) => void;
1217
+ }
1218
+ /**
1219
+ * Prove it's you before something serious happens: a passkey by preference, a one-time code as the
1220
+ * way out when the passkey can't answer.
1221
+ *
1222
+ * **A step-up is orthogonal to a confirm.** It asks *who you are*, never *whether you meant it*, so
1223
+ * it neither replaces an Undo nor is replaced by one — every Danger-zone action proves it's you, and
1224
+ * Archive passes its step-up and then fires with an Undo (Guidelines/Undo over confirmation). This
1225
+ * component must not grow a "are you sure?" question: that belongs to the window around it.
1226
+ *
1227
+ * **Where the boundary sits.** This renders the challenge and reports which factor the user reached
1228
+ * for; the product performs the verification. `onVerifyPasskey` is where a real consumer calls
1229
+ * `navigator.credentials.get()`; `onVerifyCode` is where it posts the code. Neither is awaited here.
1230
+ * The outcome comes back as props — `verifying` while the call is out, `error` when it failed — so
1231
+ * the component never stringifies an exception and the product owns every word a user is told about
1232
+ * a failure. The caller also owns the window: the `Dialog`, its title, and what happens on success.
1233
+ *
1234
+ * **Nothing keys off the identity of a message.** A product sends one constant string for every
1235
+ * wrong code, precisely so the wording doesn't leak which factor failed or why, and `Object.is`
1236
+ * cannot tell two of those apart. So the code is dropped the moment it is handed over rather than
1237
+ * when a new `error` arrives, and an error is hidden by *which factor it belongs to* rather than by
1238
+ * a latch some prop change has to clear. A caller owes nothing here: it need not vary the message,
1239
+ * and it need not pass an attempt token.
1240
+ *
1241
+ * **The code never leaves except on submit.** There is deliberately no `value`, no `defaultValue`
1242
+ * and no `onChange`, and the handlers that would see the digits — change, input, key, clipboard —
1243
+ * are omitted from the props type *and* stopped at the field, so a parent can neither seed a
1244
+ * one-time code nor watch one being typed by the ordinary React route. It reaches the caller once,
1245
+ * in `onVerifyCode`, and the boxes empty in the same breath: a code the server refused can never be
1246
+ * sent twice, and a challenge that passed leaves nothing behind in a mounted instance. The field
1247
+ * carries no `name`, so a surrounding form never serializes it, and every control here is
1248
+ * `type="button"`, so none of them submits that form either.
1249
+ *
1250
+ * **Two things it does not defend against, and the consumer owes both.** A parent that reaches the
1251
+ * DOM node through a `ref`, or listens on `document` in the capture phase, still sees the
1252
+ * keystrokes — the fence above is against the accidental route, not a hostile parent. And the
1253
+ * digits render as **text nodes** inside the slots, not as an input value: session-replay tools
1254
+ * mask `<input>` values by default and do not mask arbitrary text, so a product that records
1255
+ * sessions must exclude this subtree explicitly (PostHog `ph-no-capture`, FullStory
1256
+ * `data-fs-exclude`, Datadog `data-dd-privacy="mask"`). The code pane carries
1257
+ * `data-sensitive="one-time-code"` so one rule can find it.
1258
+ *
1259
+ * **A failed passkey does not fall back on the user's behalf.** The challenge holds the passkey
1260
+ * pane and leaves the code one press away. Downgrading someone to the weaker factor because the
1261
+ * strong one didn't answer is a decision about their security posture, and it belongs to them —
1262
+ * a cancelled prompt and a missing authenticator look identical from here. For the same reason the
1263
+ * WebAuthn ceremony never auto-starts and a complete code never auto-submits: every attempt is a
1264
+ * press the user made.
1265
+ */
1266
+ declare const StepUpChallenge: React$1.ForwardRefExoticComponent<StepUpChallengeProps & React$1.RefAttributes<HTMLDivElement>>;
1267
+
682
1268
  interface InlineErrorProps extends React$1.HTMLAttributes<HTMLDivElement> {
683
1269
  children: React$1.ReactNode;
684
1270
  }
685
1271
  declare const InlineError: React$1.ForwardRefExoticComponent<InlineErrorProps & React$1.RefAttributes<HTMLDivElement>>;
1272
+ /**
1273
+ * What the user did to prove it was them, handed to `onConfirm` so the product can verify it. Only a
1274
+ * dialog carrying `stepUp` sends one; every other confirm calls `onConfirm` with nothing.
1275
+ */
1276
+ type StepUpProof = {
1277
+ method: 'passkey';
1278
+ } | {
1279
+ method: 'code';
1280
+ code: string;
1281
+ };
1282
+ /**
1283
+ * The identity challenge a `ConfirmDialog` puts in place of its footer, and the words above it.
1284
+ *
1285
+ * The four factor settings are the caller's. Everything else the challenge takes is the dialog's,
1286
+ * because the dialog is the thing that knows the answer: the confirm's label, the way back, and
1287
+ * whether a verification is out or has failed all come from the confirm it replaced.
1288
+ */
1289
+ interface ConfirmDialogStepUp extends Pick<StepUpChallengeProps, 'methods' | 'defaultMethod' | 'codeLength' | 'onMethodChange'> {
1290
+ /** The panel's own title, when proving it's you is a different question from the one asked first. */
1291
+ title?: React$1.ReactNode;
1292
+ /** The panel's own description. Say what is about to happen, not how the challenge works. */
1293
+ description?: React$1.ReactNode;
1294
+ }
686
1295
  interface ConfirmDialogProps {
687
1296
  open?: boolean;
688
1297
  onOpenChange?: (open: boolean) => void;
@@ -692,14 +1301,35 @@ interface ConfirmDialogProps {
692
1301
  confirmLabel?: string;
693
1302
  cancelLabel?: string;
694
1303
  destructive?: boolean;
695
- onConfirm: () => void | Promise<void>;
1304
+ /**
1305
+ * The words the user has to type before the confirm will fire — a product's name, `DELETE`. For an
1306
+ * action whose cost is that it cannot be taken back by the person taking it.
1307
+ */
1308
+ confirmPhrase?: string;
1309
+ /**
1310
+ * Prove it's you before this fires. The challenge takes the footer's place, so there is no live
1311
+ * confirm sitting over an unanswered one. Orthogonal to `confirmPhrase`: that asks whether you
1312
+ * meant it, this asks who you are, and an action can want both.
1313
+ */
1314
+ stepUp?: ConfirmDialogStepUp;
1315
+ onConfirm: (proof?: StepUpProof) => void | Promise<void>;
1316
+ /**
1317
+ * Turns whatever `onConfirm` threw into the line the dialog shows. Without it the dialog shows
1318
+ * `CONFIRM_FAILED` and nothing else — a thrown value is written for whoever reads the logs, and
1319
+ * `e.message` on the screen has already put a host, a port and an internal id in front of a user
1320
+ * (#473). The product owns that translation because only it knows which failures it can name.
1321
+ */
1322
+ onError?: (error: unknown) => string;
696
1323
  }
697
- declare function ConfirmDialog({ open, onOpenChange, trigger, title, description, confirmLabel, cancelLabel, destructive, onConfirm, }: ConfirmDialogProps): React$1.JSX.Element;
1324
+ declare function ConfirmDialog({ open, onOpenChange, trigger, title, description, confirmLabel, cancelLabel, destructive, confirmPhrase, stepUp, onConfirm, onError, }: ConfirmDialogProps): React$1.JSX.Element;
698
1325
 
699
1326
  interface UserMenuUser {
700
1327
  name: string;
701
- /** Second line of the row. The shipped rail shows the org name here. */
1328
+ /** Seeds the avatar tint, so the colour survives a rename. Optional; falls back to the name. */
1329
+ id?: string;
1330
+ /** Overrides the second line where a rail needs something other than the email there. */
702
1331
  subtitle?: string;
1332
+ /** Second line of the row: the address this person signs in with. */
703
1333
  email?: string;
704
1334
  avatarUrl?: string;
705
1335
  }
@@ -755,42 +1385,950 @@ interface ExtensionIconProps extends LucideProps {
755
1385
  */
756
1386
  declare const ExtensionIcon: React$1.ForwardRefExoticComponent<Omit<ExtensionIconProps, "ref"> & React$1.RefAttributes<SVGSVGElement>>;
757
1387
 
758
- /** True when the viewport is narrower than the `md` breakpoint (768px). SSR-safe. */
759
- declare function useIsMobile(): boolean;
760
-
761
- interface UseSidebarOptions {
762
- /** Controlled collapsed value. When provided, the hook does not own state. */
763
- collapsed?: boolean;
764
- /** Initial collapsed value in uncontrolled mode. Default false (expanded). */
765
- defaultCollapsed?: boolean;
766
- /** Called whenever the collapsed value should change (both modes). */
767
- onCollapsedChange?: (collapsed: boolean) => void;
768
- }
769
- interface UseSidebarResult {
770
- collapsed: boolean;
771
- setCollapsed: (collapsed: boolean) => void;
772
- toggle: () => void;
773
- }
774
1388
  /**
775
- * Controllable sidebar collapse state. Controlled when `collapsed` is passed,
776
- * otherwise internal state seeded by `defaultCollapsed`. Pureno persistence
777
- * or context; the host app owns persistence.
1389
+ * A glyph that stands on its own a warning triangle in a summary line, a lock beside a group
1390
+ * name, an info mark in a rowand explains itself.
1391
+ *
1392
+ * **Reach for this one when nothing else on screen says what the glyph means.** Its sibling
1393
+ * {@link DecorativeIcon} is for the opposite case, a glyph inside a control that already has a
1394
+ * name; the two render identically and differ only in the accessibility tree, which is why they
1395
+ * ship together and why the names have to carry the condition — picking the wrong one is not
1396
+ * visible in a screenshot.
1397
+ *
1398
+ * Four things it owns, and each of them is a bug you get composing `Tooltip` by hand:
1399
+ *
1400
+ * - **A role.** `aria-label` on a bare `<span>` is not reliably exposed. `role="img"` is what makes
1401
+ * the name count, and it is honest: the glyph *is* an image carrying meaning.
1402
+ * - **A tab stop, with a ring on it.** A tooltip only reachable by pointer is an explanation
1403
+ * keyboard and screen reader users never get. The trigger is focusable, focus opens the tooltip,
1404
+ * and `focus-visible` draws the ring — a tab stop nobody can see is not a tab stop.
1405
+ * - **One announcement.** Radix does two things with the sentence: it points the trigger's
1406
+ * `aria-describedby` at the open bubble, and it renders a `VisuallyHidden role="tooltip"` copy of
1407
+ * the text *inside* that bubble. With the sentence already serving as the accessible name, both
1408
+ * are duplicates — and suppressing only the relation leaves the copy orphaned, referenced by
1409
+ * nothing and still read. So the relation is suppressed **and** the bubble is `aria-hidden`: it
1410
+ * is a picture of the name, drawn for the people who can see it. WAI-ARIA APG: a tooltip that
1411
+ * supplies the name labels; it does not also describe.
1412
+ * - **Pointer events of its own.** A `disabled` control sets `pointer-events: none` over its whole
1413
+ * subtree (the kit `Button` does), which is exactly when a glyph explaining *why* it is disabled
1414
+ * matters most — and exactly when it would otherwise fall out of the hit stack. The trigger
1415
+ * re-enables its own. The trade-off is real and worth stating: one small part of a disabled
1416
+ * control now answers the pointer.
1417
+ *
1418
+ * **`label` is one string on purpose.** Splitting the name from the tooltip text would let them
1419
+ * drift, and drifting is the failure this component exists to stop. A blank one is a bug, not a
1420
+ * variant: a focusable `role="img"` with no name is a WCAG 4.1.2 failure and the bubble would open
1421
+ * empty. A blank `label` therefore renders the glyph as decorative — `aria-hidden`, no role, no tab
1422
+ * stop, no tooltip — and warns in development. Keep the sentence short, too: the bubble sets no
1423
+ * maximum width, so a paragraph runs off the edge of the viewport.
1424
+ *
1425
+ * **The component's own attributes win, not the call site's.** `role`, `aria-label`, `aria-hidden`,
1426
+ * `aria-describedby` and `tabIndex` are applied *after* your props are spread, so passing your own
1427
+ * cannot quietly undo any of the above. The `Omit` below stops `role` and `tabIndex` at compile
1428
+ * time; it cannot
1429
+ * stop `aria-*`, because TypeScript exempts hyphenated JSX attributes from excess-property
1430
+ * checking — which is why the ordering, and not the type, is the guarantee.
1431
+ *
1432
+ * **Requires a `TooltipProvider` above it.** One per app, near the root — never one per icon, which
1433
+ * puts every glyph in its own delay group so moving between two of them re-waits the full delay.
1434
+ * With none mounted, Radix throws ``\`Tooltip\` must be used within \`TooltipProvider\``` — and
1435
+ * because `@lessly/ui` re-exports those names verbatim, that message names two things you can
1436
+ * import from this package. See `Guidelines/Icons & tooltips`.
778
1437
  */
779
- declare function useSidebar(options?: UseSidebarOptions): UseSidebarResult;
780
-
781
- type NavRowVariant = 'rail' | 'menu';
782
- interface NavRowOwnProps {
783
- /** Leading glyph. Rendered in a fixed 20px box; SVGs are normalized to 18px.
784
- * A falsy value (`null`/`false`/`0`/`''`) renders nothing — there is no reserved
785
- * empty slot, so the row's content shifts left when `icon` is falsy. */
786
- icon?: React$1.ReactNode;
1438
+ interface IconHintProps extends Omit<React$1.ComponentPropsWithoutRef<'span'>, 'role' | 'tabIndex' | 'children'> {
1439
+ /** The glyph. Size and colour it at the call site — this component owns behaviour, not looks. */
1440
+ children: React$1.ReactNode;
1441
+ /** The sentence. It is both the tooltip text and the glyph's accessible name. */
787
1442
  label: string;
788
- active?: boolean;
789
- variant: NavRowVariant;
790
- /** Right-aligned adornment: chevron, checkmark, action. Keeps its own size.
1443
+ /** Which edge the tooltip lands on. */
1444
+ side?: 'top' | 'right' | 'bottom' | 'left';
1445
+ /** How the tooltip lines up along that edge — for a glyph pinned to the edge of a narrow column. */
1446
+ align?: 'start' | 'center' | 'end';
1447
+ }
1448
+ declare const IconHint: React$1.ForwardRefExoticComponent<IconHintProps & React$1.RefAttributes<HTMLSpanElement>>;
1449
+
1450
+ /**
1451
+ * A glyph *inside* something that already has a name — a flag in a `Report` button, an info mark
1452
+ * after a role's label — with a hover hint for sighted users and nothing else.
1453
+ *
1454
+ * **Reach for this one when the text or control around the glyph already says what it means.** Its
1455
+ * sibling {@link IconHint} is for a glyph that stands alone. The two render identically; only the
1456
+ * accessibility tree tells them apart, which is why the name has to carry the condition for
1457
+ * choosing it — *decorative* is the term for a glyph that carries no meaning of its own, and that
1458
+ * is the whole test. (It was called `IconTip` and the name said nothing: both are icons, both are
1459
+ * tips.)
1460
+ *
1461
+ * Naming this glyph and giving it a tab stop — the obvious thing, and what you get by copying
1462
+ * `IconHint` — is wrong twice over:
1463
+ *
1464
+ * - **The name announces nothing.** The host's own `aria-label` halts descendant traversal, so a
1465
+ * name here is never read. Where the host is named by its text instead, the name *does* get
1466
+ * through and corrupts it: the control stops announcing "Report" and starts announcing "Report,
1467
+ * we'll sign this device out".
1468
+ * - **The tab stop is a stray one.** A focusable child inside a button makes the control take two
1469
+ * tabs, and the first lands somewhere that does nothing. A focusable `aria-hidden` element is an
1470
+ * ARIA violation in its own right.
1471
+ *
1472
+ * So the trigger is `aria-hidden` and takes no focus, and the bubble is `aria-hidden` too — Radix
1473
+ * renders a `VisuallyHidden role="tooltip"` copy of the text inside it, and leaving that in the
1474
+ * tree would put a loose sentence next to a glyph that is meant to be silent. `label` is hover
1475
+ * text, never a name. If a keyboard or screen reader user needs the sentence, that is the signal
1476
+ * that the glyph is not decorative and the wrong component is in use.
1477
+ *
1478
+ * **It keeps its own pointer events.** A `disabled` control sets `pointer-events: none` over its
1479
+ * whole subtree (the kit `Button` does), and that is the one moment the glyph's sentence matters
1480
+ * most — it is usually what says *why* the control is disabled. The trigger re-enables its own so a
1481
+ * disabled control can still explain itself. The trade-off is real and worth stating: one small
1482
+ * part of a disabled control now answers the pointer.
1483
+ *
1484
+ * A blank `label` leaves nothing to show, so it renders the bare glyph with no tooltip at all
1485
+ * rather than an empty bubble, and warns in development. Keep the sentence short: the bubble sets
1486
+ * no maximum width, so a paragraph runs off the edge of the viewport.
1487
+ *
1488
+ * **The component's own attributes win, not the call site's.** `aria-hidden` is applied *after*
1489
+ * your props are spread, and no `role`, `aria-label` or `tabIndex` is passed through, so a call
1490
+ * site cannot turn this back into an `IconHint`. The `Omit` below stops `role` and `tabIndex` at
1491
+ * compile time; it cannot stop `aria-*`, because TypeScript exempts hyphenated JSX attributes from
1492
+ * excess-property checking — which is why the ordering, and not the type, is the guarantee.
1493
+ *
1494
+ * **Requires a `TooltipProvider` above it** — one per app, near the root. See
1495
+ * `Guidelines/Icons & tooltips`.
1496
+ */
1497
+ interface DecorativeIconProps extends Omit<React$1.ComponentPropsWithoutRef<'span'>, 'role' | 'tabIndex' | 'children'> {
1498
+ /** The glyph. Hidden from assistive technology whatever it is. */
1499
+ children: React$1.ReactNode;
1500
+ /** The hover text. Not an accessible name — the host control owns that. */
1501
+ label: string;
1502
+ /** Which edge the tooltip lands on. */
1503
+ side?: 'top' | 'right' | 'bottom' | 'left';
1504
+ /** How the tooltip lines up along that edge. */
1505
+ align?: 'start' | 'center' | 'end';
1506
+ }
1507
+ declare const DecorativeIcon: React$1.ForwardRefExoticComponent<DecorativeIconProps & React$1.RefAttributes<HTMLSpanElement>>;
1508
+
1509
+ type ImageCropShape = 'square' | 'circle';
1510
+ type ImageCropType = 'image/png' | 'image/jpeg' | 'image/webp';
1511
+ interface ImageCropperProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'onError' | 'onLoad'> {
1512
+ /** The image to crop: a data URL, an object URL, or a URL the browser can fetch. */
1513
+ src: string;
1514
+ /**
1515
+ * The mask. `square` is the default because a logo is the commoner case and a rectangle is what an
1516
+ * image already is; `circle` is the avatar case and is baked into the export, not just previewed.
1517
+ */
1518
+ shape?: ImageCropShape;
1519
+ /** Edge of the exported square, in pixels. 256 covers every avatar slot the console draws. */
1520
+ outputSize?: number;
1521
+ /**
1522
+ * `image/jpeg` is the one format with no alpha channel, so it alone gets a ground painted under
1523
+ * the crop. PNG and WebP both carry alpha — including the canvas encoder that writes them — so a
1524
+ * circle exported as either comes back genuinely transparent in the corners.
1525
+ */
1526
+ outputType?: ImageCropType;
1527
+ /** 0–1, for the lossy formats. Ignored by `image/png`. */
1528
+ outputQuality?: number;
1529
+ /**
1530
+ * What is painted over the whole canvas before the crop, and before any mask. Defaults to white
1531
+ * for `image/jpeg` and to nothing for the two formats that can be transparent. Pass a colour to
1532
+ * flatten a PNG or WebP onto a ground, or `null` to let a JPEG's empty pixels fall to black.
1533
+ */
1534
+ background?: string | null;
1535
+ /** The smallest crop, in stage pixels, so the four corner grips never blanket the move region. */
1536
+ minCropSize?: number;
1537
+ /**
1538
+ * Set it when the image is served from another origin. Without it the image loads perfectly and
1539
+ * taints the canvas, so the failure arrives on Save as `exportErrorMessage`, not on load.
1540
+ */
1541
+ crossOrigin?: 'anonymous' | 'use-credentials';
1542
+ /** The cropped region, as a data URL of `outputType`. */
1543
+ onCrop: (dataUrl: string) => void;
1544
+ /** Omit it and no Cancel renders — for a cropper embedded in a page that owns its own way out. */
1545
+ onCancel?: () => void;
1546
+ saveLabel?: string;
1547
+ cancelLabel?: string;
1548
+ /** The line under the stage. Pass `null` to drop it. */
1549
+ hint?: React$1.ReactNode;
1550
+ /** Shown in place of the image when the source cannot be read. */
1551
+ errorMessage?: React$1.ReactNode;
1552
+ /**
1553
+ * Shown under a stage that still holds the photo, when the *export* was refused. A cross-origin
1554
+ * image with no `crossOrigin` loads perfectly and taints the canvas, so the failure arrives on
1555
+ * Save and the load copy would be describing something that never happened.
1556
+ */
1557
+ exportErrorMessage?: React$1.ReactNode;
1558
+ }
1559
+ declare const ImageCropper: React$1.ForwardRefExoticComponent<ImageCropperProps & React$1.RefAttributes<HTMLDivElement>>;
1560
+
1561
+ /**
1562
+ * `ImageCropper` in a window, which is where a crop step almost always happens: a file is picked,
1563
+ * and the crop is the one thing between picking it and saving it.
1564
+ *
1565
+ * It is small on purpose, and it exists for one reason — **it takes the caller's word for the thing
1566
+ * being cropped and puts it in the title**, so a logo is never called an avatar. `label` is the
1567
+ * whole feature; `title` is there for a sentence the "Crop <thing>" pattern does not fit.
1568
+ *
1569
+ * Controlled only. There is no uncontrolled form because a crop window has nothing to show until
1570
+ * the caller has a file in hand, so the caller already owns the open state.
1571
+ */
1572
+ interface ImageCropDialogProps extends Omit<ImageCropperProps, 'src' | 'onCancel' | 'className' | 'title'> {
1573
+ open: boolean;
1574
+ onOpenChange: (open: boolean) => void;
1575
+ /**
1576
+ * The picked image, or `null` before anything has been picked — the window then renders its frame
1577
+ * and no cropper, rather than a cropper pointed at nothing.
1578
+ */
1579
+ src: string | null;
1580
+ /** The thing being cropped, in the caller's own words: `Logo`, `Avatar`, `Cover image`. */
1581
+ label?: string;
1582
+ /** Overrides the whole title. Use it when `Crop <label>` is not the sentence you want. */
1583
+ title?: React$1.ReactNode;
1584
+ /** A crop window usually has nothing to add beyond its title; say something only when it does. */
1585
+ description?: React$1.ReactNode;
1586
+ }
1587
+ declare function ImageCropDialog({ open, onOpenChange, src, label, title, description, onCrop, ...cropperProps }: ImageCropDialogProps): React$1.JSX.Element;
1588
+ declare namespace ImageCropDialog {
1589
+ var displayName: string;
1590
+ }
1591
+
1592
+ /**
1593
+ * Pick an image, see it, crop it, keep it — an account photo, a product logo, an organization logo.
1594
+ * Without this a product gets the browser's bare file input, which is why every one of them would
1595
+ * otherwise install a package on day one.
1596
+ *
1597
+ * The value is a data URL, so it renders straight into an `<img>` and uploads with one line
1598
+ * (`await (await fetch(value)).blob()`). `onChange(null)` is the removal.
1599
+ *
1600
+ * **The word for the thing is the caller's.** `label` names it in the file input, the preview and
1601
+ * the crop window's title, so an organization logo is never called an avatar.
1602
+ */
1603
+ type ImageUploadSize = 'sm' | 'md' | 'lg';
1604
+ interface ImageUploadProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'onChange' | 'onError'> {
1605
+ /** The image, as a data URL or any src the browser can render. `null` is "nothing set yet". */
1606
+ value: string | null;
1607
+ /** The cropped image, or `null` when it is removed. */
1608
+ onChange: (value: string | null) => void;
1609
+ /**
1610
+ * What is being uploaded, in the caller's own words: `Logo`, `Avatar`, `Organization logo`. It
1611
+ * names the file input, the preview and the crop window.
1612
+ */
1613
+ label?: string;
1614
+ /**
1615
+ * A circle is a principal, a rounded square is an object (Guidelines/Avatars) — and the same
1616
+ * shape masks the crop, so what you see in the tile is what was saved.
1617
+ */
1618
+ shape?: ImageCropShape;
1619
+ /** The preview tile: 32, 48 or 64px. */
1620
+ size?: ImageUploadSize;
1621
+ /**
1622
+ * What the tile shows before anything is picked. Supply one and you own its frame — the tile
1623
+ * draws no ring of its own, so a `PersonAvatar` here doesn't end up double-ringed.
1624
+ */
1625
+ fallback?: React$1.ReactNode;
1626
+ /** A line under the buttons. There is no default: only the caller knows the real constraint. */
1627
+ hint?: React$1.ReactNode;
1628
+ /** The file input's filter. Anything that isn't an image is refused regardless. */
1629
+ accept?: string;
1630
+ /** In bytes. A picker with no ceiling is a bug waiting on the first 40MB photo. */
1631
+ maxFileSize?: number;
1632
+ /** Skip the crop step and take the file as it was picked. */
1633
+ crop?: boolean;
1634
+ disabled?: boolean;
1635
+ /** Edge of the stored square, in pixels. */
1636
+ outputSize?: number;
1637
+ outputType?: ImageCropType;
1638
+ outputQuality?: number;
1639
+ /** Called with the same sentence the control shows, for a caller that reports errors its own way. */
1640
+ onError?: (message: string) => void;
1641
+ uploadLabel?: string;
1642
+ changeLabel?: string;
1643
+ removeLabel?: string;
1644
+ }
1645
+ declare const ImageUpload: React$1.ForwardRefExoticComponent<ImageUploadProps & React$1.RefAttributes<HTMLDivElement>>;
1646
+
1647
+ /**
1648
+ * What opening this row does. The row's trailing column is a promise, and this states it.
1649
+ *
1650
+ * This is the set of **values**, for a caller's own data model — not a prop bag. `opens` lives in a
1651
+ * discriminated union with `expanded` (see `EntityRowOpensProps`), so a variable typed as this one
1652
+ * widens across both arms and satisfies neither: `<EntityRow opens={row.opens} />` does not compile.
1653
+ * A config-driven list narrows to `EntityRowOpensProps` and spreads that instead.
1654
+ */
1655
+ type EntityRowOpens = 'page' | 'modal' | 'disclosure' | 'none';
1656
+ interface EntityRowOwnProps {
1657
+ /**
1658
+ * Leading mark — who or what the row is about. Round for a principal (a person, an agent, a
1659
+ * group), a rounded square for an object (a product, a connector, a key). `PersonAvatar`,
1660
+ * `GlyphAvatar` and `EntityTile` are the three that ship; each is already `shrink-0`, which a
1661
+ * hand-rolled mark has to be too or a long title will squash it.
1662
+ */
1663
+ mark?: React$1.ReactNode;
1664
+ /**
1665
+ * The name of the thing this row is — a string in almost every list, and any node where the name
1666
+ * is built out of parts: an activity log's sentence with the agent's name a link inside it.
1667
+ *
1668
+ * A **focusable** node here is legal only on `opens="none"`, which renders a `<div>` and is not a
1669
+ * target — which is exactly how the activity log gets a link into the sentence. On the other three
1670
+ * the row is itself the control, so a control in the title nests one button inside another: broken
1671
+ * tab order, invalid HTML, and a hydration mismatch on the server.
1672
+ *
1673
+ * **The DOM `title` attribute is not in this component's type.** A row's name is content, not a
1674
+ * tooltip, and nothing here sets the attribute: a tooltip that only appears on hover, after a
1675
+ * delay, and never for a keyboard, is not where a row's name goes.
1676
+ */
1677
+ title: React$1.ReactNode;
1678
+ /**
1679
+ * A small chip beside the title — `You`, `Guest`, `Synced from Okta`. It sits in a slot that does
1680
+ * not shrink, so a long title truncates and the chip stays whole rather than the other way round.
1681
+ */
1682
+ badge?: React$1.ReactNode;
1683
+ /** The second line under the title: an email, a device, a count. Drops a type step (#364). */
1684
+ sub?: React$1.ReactNode;
1685
+ /**
1686
+ * The trailing value before the reserved column — a role name, a status `Badge`, an expiry. It is
1687
+ * the answer to the row, not a caption, so it holds `text-sm` (#364). Text and non-focusable
1688
+ * marks only on a row that opens something: the row is one target, so nothing focusable may sit
1689
+ * inside it. `opens="none"` is the exception — that row is not a target, so a control belongs here.
1690
+ */
1691
+ meta?: React$1.ReactNode;
1692
+ /**
1693
+ * A line under the whole row at full width — the row's question answered without opening it.
1694
+ * Unlike `sub` it does not share a line with `meta`, so a long summary is not truncated by the
1695
+ * trailing value. Inert content only: the row is one target.
1696
+ */
1697
+ summary?: React$1.ReactNode;
1698
+ }
1699
+ /**
1700
+ * What the trailing column promises, and — for the one value that has a state — which state the row
1701
+ * is in. Press Esc: if nothing is lost it is a modal, if something is it is a page, and "lost"
1702
+ * includes your place (#361).
1703
+ *
1704
+ * `expanded` is required by `disclosure` and rejected by the other two, so a row cannot claim a
1705
+ * state it does not have and a disclosure cannot forget to say which one it is in.
1706
+ */
1707
+ type EntityRowOpensProps = {
1708
+ /**
1709
+ * `page` (the default) is what opening an entity does, and it wears the `ChevronRight`. That
1710
+ * mark means an entity opening as a **page** and nothing else in this console carries one, so
1711
+ * it is stated here rather than passed in as an icon (#363, #411).
1712
+ *
1713
+ * `modal` opens a detail in place over the list and wears nothing: a modal moves you nowhere,
1714
+ * so a mark would promise travel that never happens.
1715
+ *
1716
+ * `disclosure` grows the detail underneath the row, and wears the caret the kit already gives
1717
+ * every disclosure — `Accordion`, `ConnectorCard` — a `ChevronDown` turning 180° (#401). It
1718
+ * takes `expanded`.
1719
+ *
1720
+ * The 16px column stays reserved whichever it is, so a list mixing them keeps one right edge
1721
+ * for its `meta`.
1722
+ */
1723
+ opens?: 'page' | 'modal';
1724
+ expanded?: never;
1725
+ } | {
1726
+ opens: 'disclosure';
1727
+ /**
1728
+ * Whether the block below the row is open. It drives the caret's rotation **and**
1729
+ * `aria-expanded`, so the mark and the accessibility tree cannot drift apart.
1730
+ */
1731
+ expanded: boolean;
1732
+ } | {
1733
+ /**
1734
+ * `none` opens nothing: the row is a line in a list you read, and whatever can be done to it
1735
+ * sits in `meta` as its own control — a role picker on a grant, a ✕. It is the same row
1736
+ * geometry and the same slots, with the three things that follow from "a row is something you
1737
+ * click" taken back off: no element to press, so no `<button>`, no `onClick` and no `asChild`;
1738
+ * no reserved trailing column, because there is no mark it could ever hold and a static list
1739
+ * has no chevron to line up with; and no hover plate, which on a row with nothing to press
1740
+ * promises a click that never happens. The title drops to the regular weight the rest of the
1741
+ * row already reads at.
1742
+ */
1743
+ opens: 'none';
1744
+ expanded?: never;
1745
+ onClick?: never;
1746
+ asChild?: never;
1747
+ };
1748
+ /**
1749
+ * Render the single child element instead of a button — a router `<Link>`, an `<a>`. The row builds
1750
+ * its content from props, so the child's own children are replaced; `children` is therefore only
1751
+ * accepted when `asChild` is true, and rejected at the type level otherwise rather than silently
1752
+ * dropped at render time.
1753
+ *
1754
+ * `title` is omitted from the button props alongside `children` for the same reason: the row owns
1755
+ * both slots. See `EntityRowOwnProps['title']`.
1756
+ */
1757
+ type EntityRowProps = EntityRowOwnProps & EntityRowOpensProps & Omit<React$1.ComponentPropsWithoutRef<'button'>, 'children' | 'title'> & ({
1758
+ asChild: true;
1759
+ children: React$1.ReactElement;
1760
+ } | {
1761
+ asChild?: false;
1762
+ children?: never;
1763
+ });
1764
+ /**
1765
+ * The console's one list item. Members, groups, products, roles and keys all render through it, so
1766
+ * the lists read the same from screen to screen.
1767
+ *
1768
+ * The whole row is the click target and it carries **no** inline action and no overflow menu —
1769
+ * entity actions live in the detail, where there is room to confirm and explain. A row that is not
1770
+ * navigable at all (a pending invite with Approve / Deny) is a different pattern and does not use
1771
+ * this. See `Guidelines/List items`.
1772
+ *
1773
+ * `opens="none"` is the one form that is not a target: a static line in a list, rendered as a `<div>`
1774
+ * with its controls in `meta`. Everything below is about the other three.
1775
+ *
1776
+ * **Hover and focus are one plate, and it is paint.** The fill and the focus ring share one
1777
+ * `::after`, inset from the row's box (see `rowClass` for the numbers). The row's own box, padding
1778
+ * and hit area are untouched, so do not shrink a row to match what it paints.
1779
+ *
1780
+ * Five consequences for a caller:
1781
+ *
1782
+ * 1. The row is `position: relative` and `isolation: isolate`.
1783
+ * 2. Being a stacking context, the row can no longer be painted over by a non-portaled popover
1784
+ * inside `mark`, `badge` or `meta` — such a popover is now trapped above this row and below the
1785
+ * next. Portal it, as the kit's own overlays do.
1786
+ * 3. `::before` is deliberately left free, for a caller stretching the row's hit area over a box
1787
+ * bigger than the button (#409).
1788
+ * 4. A caller whose row is bigger than this button needs **both** `static` **and** `isolation-auto`
1789
+ * on the button. `relative` alone is not a stacking context, so the `-z-10` plate escapes and
1790
+ * paints behind the host `Card` — hover fill and focus ring both vanish; `static` alone without
1791
+ * `isolation-auto` gives the mirror bug, a giant unclipped plate.
1792
+ * 5. The fill moved merge groups. A caller who used to override it with `className="hover:bg-…"`
1793
+ * now replaces nothing, because the fill is `hover:after:bg-…`. Turn this one off with
1794
+ * `hover:after:bg-transparent` and paint your own.
1795
+ */
1796
+ declare const EntityRow: React$1.ForwardRefExoticComponent<((EntityRowOwnProps & {
1797
+ /**
1798
+ * `page` (the default) is what opening an entity does, and it wears the `ChevronRight`. That
1799
+ * mark means an entity opening as a **page** and nothing else in this console carries one, so
1800
+ * it is stated here rather than passed in as an icon (#363, #411).
1801
+ *
1802
+ * `modal` opens a detail in place over the list and wears nothing: a modal moves you nowhere,
1803
+ * so a mark would promise travel that never happens.
1804
+ *
1805
+ * `disclosure` grows the detail underneath the row, and wears the caret the kit already gives
1806
+ * every disclosure — `Accordion`, `ConnectorCard` — a `ChevronDown` turning 180° (#401). It
1807
+ * takes `expanded`.
1808
+ *
1809
+ * The 16px column stays reserved whichever it is, so a list mixing them keeps one right edge
1810
+ * for its `meta`.
1811
+ */
1812
+ opens?: "page" | "modal";
1813
+ expanded?: never;
1814
+ } & Omit<Omit<React$1.DetailedHTMLProps<React$1.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref">, "title" | "children"> & {
1815
+ asChild: true;
1816
+ children: React$1.ReactElement;
1817
+ }) | (EntityRowOwnProps & {
1818
+ /**
1819
+ * `page` (the default) is what opening an entity does, and it wears the `ChevronRight`. That
1820
+ * mark means an entity opening as a **page** and nothing else in this console carries one, so
1821
+ * it is stated here rather than passed in as an icon (#363, #411).
1822
+ *
1823
+ * `modal` opens a detail in place over the list and wears nothing: a modal moves you nowhere,
1824
+ * so a mark would promise travel that never happens.
1825
+ *
1826
+ * `disclosure` grows the detail underneath the row, and wears the caret the kit already gives
1827
+ * every disclosure — `Accordion`, `ConnectorCard` — a `ChevronDown` turning 180° (#401). It
1828
+ * takes `expanded`.
1829
+ *
1830
+ * The 16px column stays reserved whichever it is, so a list mixing them keeps one right edge
1831
+ * for its `meta`.
1832
+ */
1833
+ opens?: "page" | "modal";
1834
+ expanded?: never;
1835
+ } & Omit<Omit<React$1.DetailedHTMLProps<React$1.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref">, "title" | "children"> & {
1836
+ asChild?: false;
1837
+ children?: never;
1838
+ }) | (EntityRowOwnProps & {
1839
+ opens: "disclosure";
1840
+ /**
1841
+ * Whether the block below the row is open. It drives the caret's rotation **and**
1842
+ * `aria-expanded`, so the mark and the accessibility tree cannot drift apart.
1843
+ */
1844
+ expanded: boolean;
1845
+ } & Omit<Omit<React$1.DetailedHTMLProps<React$1.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref">, "title" | "children"> & {
1846
+ asChild: true;
1847
+ children: React$1.ReactElement;
1848
+ }) | (EntityRowOwnProps & {
1849
+ opens: "disclosure";
1850
+ /**
1851
+ * Whether the block below the row is open. It drives the caret's rotation **and**
1852
+ * `aria-expanded`, so the mark and the accessibility tree cannot drift apart.
1853
+ */
1854
+ expanded: boolean;
1855
+ } & Omit<Omit<React$1.DetailedHTMLProps<React$1.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref">, "title" | "children"> & {
1856
+ asChild?: false;
1857
+ children?: never;
1858
+ }) | (EntityRowOwnProps & {
1859
+ /**
1860
+ * `none` opens nothing: the row is a line in a list you read, and whatever can be done to it
1861
+ * sits in `meta` as its own control — a role picker on a grant, a ✕. It is the same row
1862
+ * geometry and the same slots, with the three things that follow from "a row is something you
1863
+ * click" taken back off: no element to press, so no `<button>`, no `onClick` and no `asChild`;
1864
+ * no reserved trailing column, because there is no mark it could ever hold and a static list
1865
+ * has no chevron to line up with; and no hover plate, which on a row with nothing to press
1866
+ * promises a click that never happens. The title drops to the regular weight the rest of the
1867
+ * row already reads at.
1868
+ */
1869
+ opens: "none";
1870
+ expanded?: never;
1871
+ onClick?: never;
1872
+ asChild?: never;
1873
+ } & Omit<Omit<React$1.DetailedHTMLProps<React$1.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref">, "title" | "children"> & {
1874
+ asChild?: false;
1875
+ children?: never;
1876
+ })) & React$1.RefAttributes<HTMLButtonElement>>;
1877
+
1878
+ interface BackLinkProps extends Omit<React$1.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
1879
+ /**
1880
+ * The name of the page this returns to — `Members`, `Roles`, `Agents & API`. It names the parent
1881
+ * so the control reads without the trail above it; never the bare word "Back".
1882
+ */
1883
+ parent: string;
1884
+ /**
1885
+ * Hand the element to a router's own link (`<Link>`, `<a href>`): the component keeps the arrow,
1886
+ * the label and the geometry, the consumer keeps the URL. Pass exactly one element as `children`.
1887
+ */
1888
+ asChild?: boolean;
1889
+ /** The router link to slot. Only read when `asChild` is set. */
1890
+ children?: React$1.ReactNode;
1891
+ }
1892
+ /**
1893
+ * The way back from a sub-page (#362) — a member, a group, a product, a credential, a role, a
1894
+ * provider's configuration. **One** control, above the page title, on the content column's left
1895
+ * edge, naming the parent rather than saying "Back".
1896
+ *
1897
+ * It is not a second trail: the top bar keeps the whole breadcrumb, and the back/forward history
1898
+ * arrows are gone (#337), which is what leaves this the one control that walks. A **wizard gets
1899
+ * none** — its steps are the navigation. See `Guidelines/Second level navigation`.
1900
+ *
1901
+ * **Two ways to spell the destination, and one of them is required.**
1902
+ *
1903
+ * ```tsx
1904
+ * <BackLink parent="Members" onClick={() => attemptLeave(onBack)} /> // no router
1905
+ * <BackLink parent="Members" asChild><Link to="/org/members" /></BackLink> // a router
1906
+ * ```
1907
+ *
1908
+ * A product with a router should reach for `asChild`: the parent has a URL, so the way back is a
1909
+ * real link — Cmd-click opens the list in a new tab, the status bar previews it, and the router
1910
+ * navigates on the client. `onClick` is the form for a screen with no URL for its parent, which is
1911
+ * every prototype and any panel routed by component state.
1912
+ *
1913
+ * Where a guard stands between the reader and the parent — unsaved changes on the role editor — the
1914
+ * handler must be the *same* one the second-to-last crumb carries (`attemptLeave(onBack)`, not
1915
+ * `onBack`). Under `asChild`, that guard is the link's own `onClick` calling `preventDefault`.
1916
+ *
1917
+ * **No destination means no control.** Some detail views are reachable in a mode with no way back
1918
+ * wired, and the crumb above goes inert in exactly that case; a button that looks like an exit and
1919
+ * does nothing is worse than no button, so this renders `null` rather than a dead or disabled one.
1920
+ */
1921
+ declare const BackLink: React$1.ForwardRefExoticComponent<BackLinkProps & React$1.RefAttributes<HTMLButtonElement>>;
1922
+
1923
+ interface CardNoteProps extends React$1.HTMLAttributes<HTMLParagraphElement> {
1924
+ /** One sentence. Who may change what's above, or why nobody can right now. */
1925
+ children: React$1.ReactNode;
1926
+ }
1927
+ /**
1928
+ * The one-line constraint a card states at its foot: who may change what the card holds, or which
1929
+ * state has taken its controls away (#372).
1930
+ *
1931
+ * **It speaks for the card, not for one control on it.** A sentence about a single row belongs on
1932
+ * that row, as a second line under its label, where the reader meets it with the value it governs.
1933
+ * This is for the line that covers everything the card offers — a Danger zone's actions, a list's
1934
+ * add, a profile's name and logo together.
1935
+ *
1936
+ * **The line looks the same either way, and that is the component.** A card whose field has just
1937
+ * been frozen must not grow a box it didn't have when the field was live — so this takes no tone,
1938
+ * no severity and no variant, and there is deliberately no way to make the frozen sentence louder
1939
+ * than the permission one. Reaching for `Alert` here is the regression it exists to prevent:
1940
+ * `Alert` is a filled, four-sided, `role="alert"` box, and it shouts over the field it is about.
1941
+ *
1942
+ * A lock and one sentence. The glyph is fixed, because every line this component carries is about
1943
+ * permission — if a card's foot wants to say something else, it is not a `CardNote`.
1944
+ *
1945
+ * It draws one edge, the seam at the card's foot, and takes the card's own 16px inset, so it sits
1946
+ * flush at the bottom of a `Card` with no wrapper:
1947
+ *
1948
+ * ```tsx
1949
+ * <Card title="Danger zone">
1950
+ * {rows}
1951
+ * <CardNote>These actions come back when the block is lifted.</CardNote>
1952
+ * </Card>
1953
+ * ```
1954
+ *
1955
+ * The sentence itself follows `Guidelines/State with a reason`: it names the way back, or names
1956
+ * that there isn't one — an archived product's name points at Restore, a blocked one names nothing,
1957
+ * because the organization has nothing to name.
1958
+ */
1959
+ declare const CardNote: React$1.ForwardRefExoticComponent<CardNoteProps & React$1.RefAttributes<HTMLParagraphElement>>;
1960
+
1961
+ /** The three scales a remove ✕ rides at: 28px in a card header, 36px in a list row, 40px beside a
1962
+ * default-size text button. Literal strings, resolved by `Button` — this component never sizes a
1963
+ * box with a `className`. `lg` and the legacy `icon` size are deliberately not offered: nothing in
1964
+ * the console removes a row at 44px, and `icon` predates the icon-only form. */
1965
+ type RemoveButtonSize = 'xs' | 'sm' | 'default';
1966
+ interface RemoveButtonProps extends Omit<React$1.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
1967
+ /**
1968
+ * The whole sentence: `"Remove Ana Ruiz"`, not `"Ana Ruiz"`. It is **both** the tooltip text and
1969
+ * the button's accessible name, deliberately one string — splitting them would let the hint a
1970
+ * sighted user reads and the name a screen reader hears drift apart, and drifting is one of the
1971
+ * two failures this component exists to stop.
1972
+ */
1973
+ label: string;
1974
+ /** Required. A ✕ with no handler is a button that lies about being one. */
1975
+ onClick: React$1.MouseEventHandler<HTMLButtonElement>;
1976
+ /** The square box. `sm` (36px) is the list-row scale and the default. */
1977
+ size?: RemoveButtonSize;
1978
+ /** Which edge the tooltip lands on. Radix pushes it off a viewport edge on its own. */
1979
+ side?: 'top' | 'right' | 'bottom' | 'left';
1980
+ }
1981
+ /**
1982
+ * A ✕ that removes a row, **shipped already wearing its tooltip**.
1983
+ *
1984
+ * The kit `Button` has had the right style for this all along — `variant="destructive-ghost"` rests
1985
+ * neutral and reddens only under the pointer (Guidelines/Destructive actions), borderless because a
1986
+ * column of framed ✕ buttons is a wall (Guidelines/Button pairs). What `Button` cannot ship is the
1987
+ * tooltip: it never mounts one, so every call site has to remember to compose `Tooltip` +
1988
+ * `TooltipTrigger asChild` + `TooltipContent` around it, and that is exactly the step people skip.
1989
+ * A ✕ with an `aria-label` and no tooltip is a control that explains itself to a screen reader and
1990
+ * to nobody else. So the pairing is the component.
1991
+ *
1992
+ * **What "paired" can mean, and what it can't.** It cannot mean owning a `TooltipProvider`. One
1993
+ * provider is mounted per canvas — never one per control, which puts every ✕ in its own delay group
1994
+ * so moving between two of them re-waits the full delay — and a component that mounted its own
1995
+ * would be a second provider inside every app that already has one. So this owns the *pairing* and
1996
+ * requires the *provider*, and with none mounted Radix throws
1997
+ * ``` `Tooltip` must be used within `TooltipProvider` ```. That message is a usable instruction
1998
+ * rather than a puzzle here, because `@lessly/ui` re-exports Radix's names verbatim: both symbols
1999
+ * it names are importable from this package. Mount `TooltipProvider` once near your root — `AppShell`
2000
+ * already does.
2001
+ *
2002
+ * **Disabled.** `Button`'s base class sets `disabled:pointer-events-none`, which would kill the
2003
+ * hover on exactly the button whose reason most needs explaining ("you can't remove the last
2004
+ * owner"). When `disabled` is set, the tooltip trigger moves to a wrapping `<span>` so the hint
2005
+ * survives; the wrapper is `inline-flex`, so it disappears into a flex row. It costs one layout
2006
+ * node, and only in the state that needs it. There is no keyboard path to it — a disabled button
2007
+ * is not a tab stop, by design — so if the reason has to reach a keyboard user, say it in the text
2008
+ * nearby (Guidelines/Button forms).
2009
+ *
2010
+ * **One announcement.** The sentence is the button's *name*, so it must not also be its
2011
+ * *description*. Radix does two things with the text: it points the trigger's `aria-describedby` at
2012
+ * the open bubble, and it renders a `VisuallyHidden role="tooltip"` copy inside it. Chrome's
2013
+ * accessibility tree showed the result as `button name="Remove Ana Ruiz" desc="Remove Ana Ruiz"`
2014
+ * plus an orphan tooltip node — the same words twice. Suppressing only the relation would leave the
2015
+ * copy referenced by nothing and still read, so the relation is suppressed **and** the bubble is
2016
+ * `aria-hidden`: it is a picture of the name, drawn for the people who can see it. WAI-ARIA APG: a
2017
+ * tooltip that supplies the name labels; it does not also describe.
2018
+ *
2019
+ * **The component's own attributes win.** `aria-label`, `aria-describedby`, `type` and the variant
2020
+ * are applied *after* your props are spread, so a caller's `aria-label` cannot quietly replace the
2021
+ * label the tooltip is showing. An `Omit` would not have done this: TypeScript exempts hyphenated
2022
+ * JSX attributes from excess-property checking, so every `aria-*` entry in an `Omit` is inert and
2023
+ * the ordering is the only real guard.
2024
+ *
2025
+ * Its sibling is {@link RemovableChip}, whose ✕ deliberately does *not* redden — see there.
2026
+ */
2027
+ declare const RemoveButton: React$1.ForwardRefExoticComponent<RemoveButtonProps & React$1.RefAttributes<HTMLButtonElement>>;
2028
+
2029
+ /**
2030
+ * A role a grant can name, as this control takes one. Roles are data rather than a fixed ladder,
2031
+ * because a console that lets an admin define a role has no enum to type against.
2032
+ */
2033
+ interface GrantRole {
2034
+ id: string;
2035
+ name: string;
2036
+ /** The line under the name in the menu: what choosing it does. */
2037
+ hint?: string;
2038
+ /**
2039
+ * Where this role sits on the power ladder. Drawn as monochrome weight and nothing else — colour
2040
+ * marks an action, never a state (Guidelines/Look/Colour marks actions). Defaults to `normal`.
2041
+ */
2042
+ weight?: 'faint' | 'normal' | 'strong';
2043
+ /** The band this role is listed under. Roles with no band are listed first, unbanded. */
2044
+ group?: string;
2045
+ }
2046
+ /**
2047
+ * How a role name is drawn, wherever one is drawn: the trigger, the rungs in the menu, and the
2048
+ * stated role on a `GrantRow` that offers no picker. One recipe, because a reader compares role
2049
+ * names down a card and a shape that dropped the ladder would rank them by which control happened
2050
+ * to draw them. Literal strings, so the scanner sees every step.
2051
+ */
2052
+ declare const WEIGHT_TONE: Record<NonNullable<GrantRole['weight']>, string>;
2053
+ /** A value naming no role is a broken grant needing attention, so it reads noticeably rather than
2054
+ * quietly — never the faint tone, which is what "reads everything, changes nothing" looks like. */
2055
+ declare const MISSING_TONE = "italic text-text-primary";
2056
+ /**
2057
+ * The removal's sentence: the words the control shows, then the caller's detail. One function
2058
+ * because `GrantRow` puts the same act on a trailing ✕ in its other shapes, and because a control
2059
+ * whose accessible name does not contain the words on screen cannot be fired by speech control
2060
+ * (WCAG 2.5.3) — which holds here by construction rather than by every caller remembering to write
2061
+ * the right opening.
2062
+ */
2063
+ declare const grantRemoveLabel: (detail: string | undefined, notInForce: boolean) => string;
2064
+ /**
2065
+ * The lines the menu states in place of a choice it cannot offer. The component decides which one
2066
+ * applies, because only it knows what it drew; the words are the caller's, because only the caller
2067
+ * knows what its roles are called and why its cap is where it is.
2068
+ *
2069
+ * Each is an imposed state and owes its reason on the spot, in one line
2070
+ * (Guidelines/Controls/State with a reason).
2071
+ */
2072
+ interface GrantRoleNotes {
2073
+ /** Nothing to pick, no group to name and nothing to clear. Without it the menu opens on a box. */
2074
+ empty?: React$1.ReactNode;
2075
+ /** The role in force is one `allow` excludes, so it is on the trigger and not in the list. */
2076
+ aboveCap?: React$1.ReactNode;
2077
+ /** `value` names no role in `roles` — a grant left pointing at one that was deleted. */
2078
+ missing?: React$1.ReactNode;
2079
+ }
2080
+ interface GrantRolePickerProps {
2081
+ /** The role in force. It displays even when `allow` excludes it. */
2082
+ value: string;
2083
+ roles: GrantRole[];
2084
+ onChange: (id: string) => void;
2085
+ /** The row this control answers for. The role in force is appended, so the name a screen reader
2086
+ * hears out of the row's context says both what is being set and what it is set to. */
2087
+ ariaLabel?: string;
2088
+ align?: 'start' | 'end';
2089
+ /**
2090
+ * Caps what may be picked. The current value still displays on the trigger even outside the cap,
2091
+ * so a capped grant can only be changed down rather than being silently re-pointed.
2092
+ */
2093
+ allow?: (r: GrantRole) => boolean;
2094
+ /**
2095
+ * The group whose grant is the one standing. Present means no rungs at all: a group's grant wins
2096
+ * outright, so no rung on this row would change anything, and the menu names the group instead
2097
+ * (Guidelines/Controls/Stated, not picked).
2098
+ */
2099
+ via?: string;
2100
+ /** A direct grant the group's grant overtook: the role id, struck through, with the caller's
2101
+ * reason beside it. */
2102
+ notInForce?: {
2103
+ role: string;
2104
+ why: string;
2105
+ };
2106
+ /** The row's removal, as a menu item rather than a trailing ✕, so the row ends in one control
2107
+ * whatever state it is in. Absent where there is nothing to clear. */
2108
+ onRemove?: () => void;
2109
+ /**
2110
+ * What the removal's sentence says *after* its visible words — `"Acme Store"`, or
2111
+ * `"the direct grant on Acme Store, which is not in force. Ana keeps Admin via Engineers"` minus
2112
+ * its opening. This component owns the opening, because which words the item shows depends on
2113
+ * `notInForce` and only the component knows that: handed the whole sentence, a caller has to
2114
+ * guess which opening to write, and a name that does not contain its own visible label is a
2115
+ * control a speech-control user cannot fire (WCAG 2.5.3).
2116
+ */
2117
+ removeDetail?: string;
2118
+ /** The reader may not pick here. */
2119
+ readOnly?: boolean;
2120
+ /** What the menu says where it has no choice to offer. Owed by any caller that can reach one of
2121
+ * those states. */
2122
+ notes?: GrantRoleNotes;
2123
+ /** What the trigger shows when `value` names no role in `roles`. */
2124
+ missingLabel?: string;
2125
+ className?: string;
2126
+ }
2127
+ /**
2128
+ * The one control a grant row ends in: it states the role, and everything there is to do or to know
2129
+ * about that role is behind it.
2130
+ *
2131
+ * It is a picker wherever the reader can choose, and a menu that **explains rather than offers**
2132
+ * where there is nothing to choose. Four things can be in it, and at least one of them always is:
2133
+ * the group carrying the row (`via`), the rungs, the direct grant that group overtook
2134
+ * (`notInForce`), and the row's removal (`onRemove`). Where it has no choice to offer it says why,
2135
+ * through `notes`, and the trigger drops its chevron — that mark means "there is something to pick
2136
+ * here" (Guidelines/Controls/Stated, not picked), so a menu that only explains must not wear it.
2137
+ *
2138
+ * It is not a `Select`. A select answers with one of its options; this one can also take the thing
2139
+ * it describes away, and a command sitting among options is neither a listbox nor a set of radios.
2140
+ * So it is a menu, and the removal is a menu item (Guidelines/Controls/When it isn't a Button),
2141
+ * which reddens under the pointer or the keyboard and drops the red frame a destructive `Button`
2142
+ * rests on, because a row repeated down a menu would shout (Guidelines/Controls/Destructive
2143
+ * actions).
2144
+ */
2145
+ declare const GrantRolePicker: React$1.ForwardRefExoticComponent<GrantRolePickerProps & React$1.RefAttributes<HTMLButtonElement>>;
2146
+
2147
+ /** What every shape of the row takes. The three that differ are split below. */
2148
+ interface GrantRowBase {
2149
+ /** What the grant is on — a product, a workspace, whatever the row lists. */
2150
+ name: string;
2151
+ /** The role in force, by id. */
2152
+ role: string;
2153
+ roles: GrantRole[];
2154
+ /** Absent = nothing here to remove, so no remove control. */
2155
+ onRemove?: () => void;
2156
+ /** What the picker's trigger is named after, where the row draws one. Defaults to `name`, which
2157
+ * is the row the trigger belongs to — pass this only to say it some other way. */
2158
+ ariaLabel?: string;
2159
+ /**
2160
+ * What the removal's sentence says *after* the words the control shows. The row owns the opening
2161
+ * — `"Remove"`, or `"Remove the direct grant"` where a group's grant overtook one — so the ✕ and
2162
+ * the menu item word one act one way, and the menu item's name contains its own visible label
2163
+ * (WCAG 2.5.3). Defaults to `name`.
2164
+ */
2165
+ removeDetail?: string;
2166
+ /** The group this row's standing role comes from, `''` when the direct grant stands. */
2167
+ via?: string;
2168
+ /** A direct grant the group's grant overtook: the role id and the reason it does nothing. */
2169
+ notInForce?: {
2170
+ role: string;
2171
+ why: string;
2172
+ };
2173
+ /** The reader may not manage this row: the role is stated and the controls go with it. Implies
2174
+ * `stated`. */
2175
+ readOnly?: boolean;
2176
+ /** Caps which roles the picker offers. The role in force still displays. */
2177
+ allow?: (r: GrantRole) => boolean;
2178
+ /** What the menu says where it has no choice to offer. */
2179
+ notes?: GrantRoleNotes;
2180
+ /** What a role naming nothing in `roles` reads as. */
2181
+ missingLabel?: string;
2182
+ className?: string;
2183
+ }
2184
+ /**
2185
+ * The row ends in the role control and everything it can do is inside it. The three props below are
2186
+ * `never` rather than ignored: under one control there is no second column to hold open, so a
2187
+ * reservation lines up against nothing, and `stated` names a shape this one already derives from
2188
+ * `via` — passing either used to compile and do nothing.
2189
+ */
2190
+ interface GrantRowOneControl extends GrantRowBase {
2191
+ actionsInMenu: true;
2192
+ /** This shape always draws the picker, so it always has somewhere to send the change. */
2193
+ onChange: (id: string) => void;
2194
+ stated?: never;
2195
+ reserveRemove?: never;
2196
+ reserveChevron?: never;
2197
+ }
2198
+ /** The role control sits beside the row's other trailing marks, or the role is stated in its place. */
2199
+ interface GrantRowControlsBeside extends GrantRowBase {
2200
+ actionsInMenu?: false;
2201
+ /** Absent = nothing here to change, so the role is stated rather than picked. */
2202
+ onChange?: (id: string) => void;
2203
+ /** The role is stated, not picked — a group carries this row and its role is not this row's to
2204
+ * change (Guidelines/Controls/Stated, not picked). */
2205
+ stated?: boolean;
2206
+ /** This row carries no ✕, but a sibling row does — hold the width, so the card reads as one right
2207
+ * edge rather than two. */
2208
+ reserveRemove?: boolean;
2209
+ /** This row states its role, but a sibling row picks one — hold the picker's chevron, for the same
2210
+ * reason. */
2211
+ reserveChevron?: boolean;
2212
+ }
2213
+ type GrantRowProps = GrantRowOneControl | GrantRowControlsBeside;
2214
+ /**
2215
+ * One grant, as a row: what it is on, the role it confers, and the way to change or clear it.
2216
+ *
2217
+ * The three shapes it takes are three answers to one question — whose the role is and whether the
2218
+ * reader may act on it.
2219
+ *
2220
+ * * **Picked** is the default: the role is this row's to set, and a ✕ beside it clears the grant.
2221
+ * * **Stated** (`stated`, `readOnly` which implies it, or no `onChange` at all) prints the role
2222
+ * instead of offering it, with `via` and `notInForce` under it. A group's grant wins outright, so
2223
+ * a row a group carries has nothing on it to choose; `readOnly` answers the different question of
2224
+ * whether the *reader* may act, and a carried row can still carry the ✕ that clears a direct
2225
+ * grant sitting under the group's.
2226
+ * * **One control** (`actionsInMenu`) ends the row at the role control and puts the group, the
2227
+ * overtaken grant and the removal inside it. Every row is then one line tall and none holds a
2228
+ * column open against a control a sibling might have — which is why `reserveRemove` and
2229
+ * `reserveChevron` belong to the other two shapes and not to this one.
2230
+ */
2231
+ declare const GrantRow: React$1.ForwardRefExoticComponent<GrantRowProps & React$1.RefAttributes<HTMLDivElement>>;
2232
+
2233
+ interface RemovableChipProps extends Omit<React$1.HTMLAttributes<HTMLSpanElement>, 'children'> {
2234
+ /** The name on the chip. Also the thing the ✕ says it removes, so the two cannot drift. */
2235
+ label: string;
2236
+ /** Required. A chip you cannot unpick is a `Badge`. */
2237
+ onRemove: React$1.MouseEventHandler<HTMLButtonElement>;
2238
+ /**
2239
+ * The avatar or glyph. Consumer-owned on purpose: the chip needn't know a person from a group
2240
+ * from an agent — the frame and the ✕ are the same either way, and the mark that says which is a
2241
+ * decision the consuming console already made elsewhere.
2242
+ */
2243
+ leading?: React$1.ReactNode;
2244
+ /** Replaces the generated `Remove {label}` accessible name, for a console that isn't English. */
2245
+ removeLabel?: string;
2246
+ }
2247
+ /**
2248
+ * A principal you have **picked but not yet saved** — the chips that fill the recipient field of an
2249
+ * invite dialog or the member field of a new group — with a ✕ to unpick them.
2250
+ *
2251
+ * **Why it is not a `Badge`.** `Badge` renders nearly the same pixels and is a label: there is
2252
+ * nothing in it to click. This carries a control, and everything below follows from that.
2253
+ *
2254
+ * **The ✕ stays grey on hover, and that is the point.** Every other remove in this console wears its
2255
+ * danger — `Button variant="destructive"` rests on a red frame and reddens under the pointer, which
2256
+ * is how a revoke or a teardown announces what it costs (Guidelines/Destructive actions). This one does
2257
+ * not, because **taking someone out of a draft has not done anything yet**: nothing is revoked,
2258
+ * nothing is saved, and the only state it changes is a list you are still assembling. Red here
2259
+ * would charge the price of a destructive act for editing a field. It is `variant="ghost"` for that
2260
+ * reason and not by omission — if you are here to make it consistent with the other removes,
2261
+ * that consistency is the bug.
2262
+ *
2263
+ * **It needs no `TooltipProvider`.** Its ✕ sits beside the name that says what it removes, and
2264
+ * Guidelines/Icons & tooltips is explicit that an icon already next to its own label gets no
2265
+ * tooltip. So unlike {@link RemoveButton}, this renders anywhere — including a dialog a consumer
2266
+ * mounted outside an `AppShell`.
2267
+ *
2268
+ * **The frame is the chip; the fill is a plane.** `bg-bg-sunken` is the one surface token that sits
2269
+ * *below* the ground in both themes, so a chip reads as recessed on a page (`bg-bg-primary`) and
2270
+ * inside a dialog (`bg-bg-elevated`) alike — where `bg-bg-secondary`, the obvious choice, is within
2271
+ * 1.01:1 of a light dialog and disappears. The ✕'s hover plate then has to move up with it, which
2272
+ * is the one class this component sets on the kit `Button` (see the note at the call below).
2273
+ *
2274
+ * **Long names truncate rather than overflow.** The chip caps at its container's width and the
2275
+ * label truncates inside it; wrapping a row of them is the call site's job (`flex flex-wrap
2276
+ * gap-2`).
2277
+ */
2278
+ declare const RemovableChip: React$1.ForwardRefExoticComponent<RemovableChipProps & React$1.RefAttributes<HTMLSpanElement>>;
2279
+
2280
+ /** True when the viewport is narrower than the `md` breakpoint (768px). SSR-safe. */
2281
+ declare function useIsMobile(): boolean;
2282
+
2283
+ interface UseSidebarOptions {
2284
+ /** Controlled collapsed value. When provided, the hook does not own state. */
2285
+ collapsed?: boolean;
2286
+ /** Initial collapsed value in uncontrolled mode. Default false (expanded). */
2287
+ defaultCollapsed?: boolean;
2288
+ /** Called whenever the collapsed value should change (both modes). */
2289
+ onCollapsedChange?: (collapsed: boolean) => void;
2290
+ }
2291
+ interface UseSidebarResult {
2292
+ collapsed: boolean;
2293
+ setCollapsed: (collapsed: boolean) => void;
2294
+ toggle: () => void;
2295
+ }
2296
+ /**
2297
+ * Controllable sidebar collapse state. Controlled when `collapsed` is passed,
2298
+ * otherwise internal state seeded by `defaultCollapsed`. Pure — no persistence
2299
+ * or context; the host app owns persistence.
2300
+ */
2301
+ declare function useSidebar(options?: UseSidebarOptions): UseSidebarResult;
2302
+
2303
+ /** `rail` is the sidebar, `menu` a popup surface, `card` a settings line inside a `Card`. */
2304
+ type NavRowVariant = 'rail' | 'menu' | 'card';
2305
+ interface NavRowOwnProps {
2306
+ /** Leading glyph. Rendered in a fixed 20px box with SVGs normalized to 18px — 16px and 16px on
2307
+ * `card`, where the row sits beside body text rather than in a rail.
2308
+ * A falsy value (`null`/`false`/`0`/`''`) renders nothing — there is no reserved
2309
+ * empty slot, so the row's content shifts left when `icon` is falsy. */
2310
+ icon?: React$1.ReactNode;
2311
+ label: string;
2312
+ /** A second line under `label`, in the same column: the source a row is fed from, the owner
2313
+ * behind a setting — the fact that would otherwise be crammed into the label or dropped.
2314
+ * `card` only; `rail` and `menu` are one line and ignore it.
2315
+ *
2316
+ * Dropped at render time rather than refused at the type level, unlike `children` below.
2317
+ * Refusing it means discriminating `NavRowProps` on `variant`, and that stops
2318
+ * `<NavRow variant={v} />` compiling for anyone who types `v` as the exported
2319
+ * `NavRowVariant` — the ordinary shape of a rendered nav array. A prop that is quietly
2320
+ * ignored costs less than a variant that cannot be held in a variable. */
2321
+ sub?: React$1.ReactNode;
2322
+ /** Marks the row as the current destination. `card` has no selected form — a settings line is
2323
+ * never where you are — so it reads the same either way. */
2324
+ active?: boolean;
2325
+ variant: NavRowVariant;
2326
+ /** Right-aligned adornment: chevron, checkmark, action. Keeps its own size.
791
2327
  * A falsy value (`null`/`false`/`0`/`''`) renders nothing — e.g. passing
792
2328
  * `trailing={count}` with `count === 0` produces no adornment, not a "0". */
793
2329
  trailing?: React$1.ReactNode;
2330
+ /** The trailing value is an absence ("None yet") — a step quieter. */
2331
+ mutedTrailing?: boolean;
794
2332
  /** Icon-only row (collapsed rails). `label` becomes the aria-label. */
795
2333
  hideLabel?: boolean;
796
2334
  }
@@ -805,9 +2343,13 @@ type NavRowProps = NavRowOwnProps & Omit<React$1.ComponentPropsWithoutRef<'butto
805
2343
  asChild?: false;
806
2344
  children?: never;
807
2345
  });
808
- /** Nav row primitive (rail and menu variants). Composes an icon, label and trailing slot
2346
+ /** Nav row primitive (rail, menu and card variants). Composes an icon, label and trailing slot
809
2347
  * into a button, or into a single child via `asChild` (e.g. a router `<Link>`).
810
2348
  *
2349
+ * The `card` variant is the settings line that leaves the page for another section — People →
2350
+ * Members, Security → Identity. It carries no trailing mark and no underline: a section jump is
2351
+ * not an entity opening as a page, so the hover fill is the whole affordance.
2352
+ *
811
2353
  * Rail rows are designed for the `bg-surface` canvas. In the light theme `--hov-bg` is an
812
2354
  * opaque `#ffffff` plate, so a rail `NavRow` has no hover contrast on a surface that is
813
2355
  * already white — notably a `--menu-bg` plate. Use the `menu` variant there; its
@@ -877,7 +2419,7 @@ interface AppSidebarProps {
877
2419
  * `collapsible`. A collapsible rail should supply this (or `logo`): `header` is expanded-only
878
2420
  * and is never read while collapsed, so without a mark the collapsed rail shows just the pin. */
879
2421
  logoCollapsed?: React$1.ReactNode;
880
- /** Identity slot above the rail — e.g. a <SidebarProductHeader/>. Falls back to `logo`.
2422
+ /** Identity slot above the rail — e.g. an <OrgProductSwitcher/> (#266). Falls back to `logo`.
881
2423
  * Expanded-only: rendering it in the 52px collapsed rail would overflow, so the collapsed
882
2424
  * branch never reads it — supply `logoCollapsed` (or `logo`) for that state instead. */
883
2425
  header?: React$1.ReactNode;
@@ -916,6 +2458,10 @@ type SidebarProductHeaderProps = SidebarProductHeaderOwnProps & Omit<React$1.Com
916
2458
  children?: never;
917
2459
  });
918
2460
  /** Identity row for the sidebar header slot: product tile + name, opening the product menu.
2461
+ *
2462
+ * @deprecated Use {@link OrgProductSwitcher} for the sidebar header slot (#266). It is the single,
2463
+ * redesigned org·product switcher and supports both an org-level and an org/product trigger. This
2464
+ * component is kept for backward compatibility and will be removed in a future major.
919
2465
  *
920
2466
  * Deliberately inert on hover — no background, no transition — unlike the rail rows below
921
2467
  * it. `rounded-xl` is not dead weight despite nothing tinting the box: this declares no
@@ -947,14 +2493,17 @@ interface OrgProductSwitcherProps {
947
2493
  organizations: OrgProductSwitcherItem[];
948
2494
  activeOrgId: string;
949
2495
  onOrgSelect: (id: string) => void;
950
- /** Products for the ACTIVE org. The consumer re-supplies these when the org changes. */
951
- products: OrgProductSwitcherItem[];
952
- activeProductId: string;
953
- onProductSelect: (id: string) => void;
2496
+ /** Products for the ACTIVE org. The consumer re-supplies these when the org changes. Omit (or
2497
+ * leave `activeProductId` unset) for an org-level context — the trigger then shows just the org,
2498
+ * and the menu still lists any products so you can jump into one. */
2499
+ products?: OrgProductSwitcherItem[];
2500
+ activeProductId?: string;
2501
+ onProductSelect?: (id: string) => void;
954
2502
  /** Footer actions below the products (Create product, Product settings, …). The group and
955
2503
  * its divider render only when this is non-empty — the consumer owns which rows appear. */
956
2504
  actions?: OrgProductSwitcherAction[];
957
- /** Accessible name for the trigger. Defaults to `"<org> / <product>"`. */
2505
+ /** Accessible name for the trigger. Defaults to `"<org> / <product>"`, and to whatever the
2506
+ * trigger reads before an org resolves. */
958
2507
  'aria-label'?: string;
959
2508
  className?: string;
960
2509
  }
@@ -1083,20 +2632,32 @@ declare const Col: React$1.ForwardRefExoticComponent<ColProps & React$1.RefAttri
1083
2632
  /**
1084
2633
  * Dependency-free syntax highlighter for docs/consumer code snippets. A single
1085
2634
  * ordered-alternation regex per language tokenizes the source into typed runs;
1086
- * no prism/shiki. Fidelity is "good enough for short snippets", and the public
1087
- * API is stable so the engine can be swapped later. Generalized from the
1088
- * landing page's local highlighter (ui.lessly.com #62).
2635
+ * no prism/shiki, so nothing ships to a consumer's browser but this file.
2636
+ * Fidelity is "good enough for short snippets", and the public API is stable so
2637
+ * the engine can be swapped later. Generalized from the landing page's local
2638
+ * highlighter (ui.lessly.com #62).
2639
+ *
2640
+ * Rendering is line-based so the block can carry line numbers, a per-line
2641
+ * highlight wash, and the diff/terminal variants — the polish the docs' Shiki
2642
+ * block has, brought here without the build-time dependency (#263).
1089
2643
  */
1090
2644
  type CodeLang = 'tsx' | 'ts' | 'bash' | 'json' | 'css';
2645
+ type CodeVariant = 'default' | 'diff' | 'terminal';
1091
2646
  interface CodeBlockProps extends React$1.HTMLAttributes<HTMLPreElement> {
1092
2647
  code: string;
1093
2648
  lang?: CodeLang;
1094
- /** Show a copy button in the header (frames the block). */
2649
+ /** `default` plain, `diff` tints `+`/`-` lines, `terminal` dims the `$` prompt and drops copy. */
2650
+ variant?: CodeVariant;
2651
+ /** Show a copy control — in the filename header, or as an overlay in the corner when there's none. */
1095
2652
  copy?: boolean;
1096
- /** Optional filename caption in the header (frames the block). */
2653
+ /** Optional filename caption in a header row above the code. */
1097
2654
  filename?: string;
1098
2655
  /** Scroll long lines instead of wrapping (default: wrap). */
1099
2656
  scroll?: boolean;
2657
+ /** Lines to wash for emphasis, e.g. `"1,3-5"`. */
2658
+ highlightLines?: string;
2659
+ /** Show a line-number gutter. */
2660
+ showLineNumbers?: boolean;
1100
2661
  }
1101
2662
  declare const CodeBlock: React$1.ForwardRefExoticComponent<CodeBlockProps & React$1.RefAttributes<HTMLPreElement>>;
1102
2663
  type CodeProps = React$1.HTMLAttributes<HTMLElement>;
@@ -1111,65 +2672,79 @@ interface GridOverlayProps extends React$1.HTMLAttributes<HTMLDivElement> {
1111
2672
  }
1112
2673
  declare const GridOverlay: React$1.ForwardRefExoticComponent<GridOverlayProps & React$1.RefAttributes<HTMLDivElement>>;
1113
2674
 
1114
- declare const segmentChipVariants: (props?: ({
1115
- kind?: "granted" | "own" | "pending" | "available" | null | undefined;
2675
+ declare const attachmentChipVariants: (props?: ({
2676
+ state?: "attached" | "requested" | "available" | null | undefined;
1116
2677
  } & class_variance_authority_types.ClassProp) | undefined) => string;
1117
- interface SegmentChipProps extends Omit<React$1.HTMLAttributes<HTMLSpanElement>, 'children' | 'resource'>, VariantProps<typeof segmentChipVariants> {
1118
- /** The resource this segment points at, e.g. "a GitHub repo", "Ads account 123-456". */
1119
- resource: React$1.ReactNode;
1120
- /** Override the leading icon; defaults to a glyph derived from `kind`. */
2678
+ type AttachmentState = NonNullable<VariantProps<typeof attachmentChipVariants>['state']>;
2679
+ interface AttachmentChipProps extends Omit<React$1.HTMLAttributes<HTMLSpanElement>, 'children'>, VariantProps<typeof attachmentChipVariants> {
2680
+ /**
2681
+ * The sub-account this attachment points at, in the provider's own words — the attachment's
2682
+ * `customerId` + `descriptiveName`, e.g. "Ads account 762-703-9086, Acme Store EU". Providers
2683
+ * without a sub-account have nothing to name here; render a status `Badge` instead of a chip.
2684
+ */
2685
+ account: React$1.ReactNode;
2686
+ /** Override the leading icon; defaults to a glyph derived from `state`. */
1121
2687
  icon?: LucideIcon;
1122
2688
  /** Hide the leading icon entirely. */
1123
2689
  hideIcon?: boolean;
1124
2690
  }
1125
- declare const SegmentChip: React$1.ForwardRefExoticComponent<SegmentChipProps & React$1.RefAttributes<HTMLSpanElement>>;
2691
+ declare const AttachmentChip: React$1.ForwardRefExoticComponent<AttachmentChipProps & React$1.RefAttributes<HTMLSpanElement>>;
1126
2692
 
1127
- type ConnectionScope = 'org' | 'org/product' | 'product';
1128
- type ConnectionAuth = 'app' | 'oauth' | 'token';
1129
- type ConnectionStatus = 'connected' | 'error' | 'disconnected';
1130
- interface ConnectionCardProps extends React$1.HTMLAttributes<HTMLDivElement> {
1131
- /** Display name, e.g. "GitHub apliteni". */
2693
+ /** Who attached the connector to the product this card is shown on. Both sides say *attached*. */
2694
+ type ConnectorOrigin = 'org' | 'product';
2695
+ /**
2696
+ * `active` is the resting state and shows no badge — almost every connector is active, so a pill on
2697
+ * it states nothing and stacks a column of identical marks down a list (#343). The two states worth
2698
+ * a badge are the ones that stop a product using the account.
2699
+ */
2700
+ type ConnectorStatus = 'active' | 'needs-reconnect' | 'not-connected';
2701
+ interface ConnectorCardProps extends React$1.HTMLAttributes<HTMLDivElement> {
2702
+ /**
2703
+ * The account name — what this connector is linked WITH, never a bare provider name and never a
2704
+ * bare "Connected" (#270). E.g. "GitHub — acme", "Google Ads — ads@acme.com".
2705
+ */
1132
2706
  name: string;
1133
- scope: ConnectionScope;
1134
- auth: ConnectionAuth;
1135
- status: ConnectionStatus;
2707
+ /** What kind of external account this is, in the provider's words: "GitHub organization". */
2708
+ kind?: string;
2709
+ /** Who attached it, on a surface where that is a fact — a product's own list. Omit on the org roster. */
2710
+ origin?: ConnectorOrigin;
2711
+ status: ConnectorStatus;
1136
2712
  /** Provider mark; falls back to a monogram box derived from `name`. */
1137
2713
  glyph?: React$1.ReactNode;
1138
- /** Override the default status label (e.g. "Token expired" for `error`). */
2714
+ /** Override the status label (e.g. "Authorisation expired" for `needs-reconnect`). */
1139
2715
  statusLabel?: string;
1140
2716
  /**
1141
- * How many products hold a segment of this connection. `undefined` renders the
1142
- * "Not granted to any product yet" default — pass it ONLY on a surface where
1143
- * that claim is true and knowable (the org roster); on a product surface pass
1144
- * neither `grantedCount` nor a footer `action` to render no footer at all.
2717
+ * How many products this connector is attached to. `undefined` renders the "Not attached to any
2718
+ * product yet" default — pass it ONLY on a surface where that claim is true and knowable (the org
2719
+ * roster); on a product surface pass neither `attachedCount` nor a footer `action` to render no
2720
+ * footer at all.
1145
2721
  */
1146
- grantedCount?: number;
2722
+ attachedCount?: number;
1147
2723
  /**
1148
2724
  * Footer action — typically a <Button> ("Manage", "Reconnect", "Connect").
1149
- * Flat mode: a disconnected card shows it in the header. Collapsible mode: the
1150
- * header is a disclosure trigger (nesting a button would be invalid), so the
1151
- * action always renders in the expanded footer instead.
2725
+ * Flat mode: a not-connected card shows it in the header. Collapsible mode: the header is a
2726
+ * disclosure trigger (nesting a button would be invalid), so the action always renders in the
2727
+ * expanded footer instead.
1152
2728
  */
1153
2729
  action?: React$1.ReactNode;
1154
2730
  /**
1155
- * Blast-radius disclosure. Some providers (GitHub, ClickUp) grant all-or-nothing
1156
- * access to the whole external org — there is no per-repo/per-space permission,
1157
- * and the vended credential genuinely reaches the whole external org. Copy passed
1158
- * here must state that blast radius honestly (e.g. "Full org access any product
1159
- * granted this connection can reach every repository"); do NOT claim the segment
1160
- * is enforced by Lessly — for these providers it is not.
2731
+ * Blast-radius disclosure. Some providers (GitHub, ClickUp) hand out all-or-nothing access to the
2732
+ * whole external org — there is no per-repo/per-space permission, and the vended credential
2733
+ * genuinely reaches everything. Copy passed here must state that blast radius honestly (e.g.
2734
+ * "Full org access any product this connector is attached to can reach every repository"); do
2735
+ * NOT claim Lessly narrows it, because for these providers it does not.
1161
2736
  */
1162
2737
  access?: React$1.ReactNode;
1163
2738
  /**
1164
- * Drawer content rendered below the card body — the per-product grants roster,
1165
- * inline requests, "+ Grant to a product". Flat mode: the caller owns visibility,
1166
- * pass children only while open (unchanged behavior). Collapsible mode: pass
1167
- * children unconditionally — the card shows them while expanded.
2739
+ * Drawer content rendered below the card body — the per-product attachment roster, inline
2740
+ * requests, "+ Attach to a product". Flat mode: the caller owns visibility, pass children only
2741
+ * while open. Collapsible mode: pass children unconditionally — the card shows them while
2742
+ * expanded.
1168
2743
  */
1169
2744
  children?: React$1.ReactNode;
1170
2745
  /**
1171
- * Disclosure mode: the header row toggles the card open/closed; the access
1172
- * notice, footer, and drawer render only while open. Collapsed by default.
2746
+ * Disclosure mode: the header row toggles the card open/closed; the access notice, footer, and
2747
+ * drawer render only while open. Collapsed by default.
1173
2748
  */
1174
2749
  collapsible?: boolean;
1175
2750
  /** Uncontrolled initial state (collapsible mode). Default: false (collapsed). */
@@ -1178,10 +2753,18 @@ interface ConnectionCardProps extends React$1.HTMLAttributes<HTMLDivElement> {
1178
2753
  open?: boolean;
1179
2754
  onOpenChange?: (open: boolean) => void;
1180
2755
  }
1181
- declare const ConnectionCard: React$1.ForwardRefExoticComponent<ConnectionCardProps & React$1.RefAttributes<HTMLDivElement>>;
2756
+ declare const ConnectorCard: React$1.ForwardRefExoticComponent<ConnectorCardProps & React$1.RefAttributes<HTMLDivElement>>;
1182
2757
 
1183
2758
  type RequestSurface = 'org' | 'product';
1184
- type RequestState = 'available' | 'pending' | 'granted';
2759
+ /**
2760
+ * Where this product stands with one connector: the org holds it and this product has not asked
2761
+ * (`available`), it has asked (`pending`), an admin said no (`denied`), or it is attached and in use
2762
+ * (`attached`).
2763
+ *
2764
+ * `sent` is the other end of the same handshake — a request this side made, waiting on someone
2765
+ * else's answer. It is the sender's own row, so the only thing it can do is take the request back.
2766
+ */
2767
+ type RequestState = 'available' | 'pending' | 'denied' | 'attached' | 'sent';
1185
2768
  interface RequestRowProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'children'> {
1186
2769
  surface: RequestSurface;
1187
2770
  /** Provider display name, e.g. "Google Ads". */
@@ -1189,16 +2772,22 @@ interface RequestRowProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, '
1189
2772
  state: RequestState;
1190
2773
  /** Provider mark; falls back to a monogram box derived from `name`. */
1191
2774
  glyph?: React$1.ReactNode;
1192
- /** Secondary line — requester + resource (org), or availability (product). */
2775
+ /** Secondary line — requester + account (org), or where the connector stands (product). */
1193
2776
  subtitle?: React$1.ReactNode;
1194
- /** The granted resource label; renders a <SegmentChip> when `state` is `granted`. */
1195
- grantedResource?: React$1.ReactNode;
2777
+ /**
2778
+ * The sub-account the attachment points at — the attachment's `customerId` + `descriptiveName`,
2779
+ * e.g. "Ads account 762-703-9086, Acme Store EU". Renders an <AttachmentChip> when `state` is
2780
+ * `attached`; providers without a sub-account leave it unset and get an "In use" status badge.
2781
+ */
2782
+ account?: React$1.ReactNode;
1196
2783
  /** Approve an org-side request. */
1197
2784
  onApprove?: () => void;
1198
2785
  /** Deny an org-side request. */
1199
2786
  onDeny?: () => void;
1200
- /** Request an available connection from the product side. */
2787
+ /** Request a connector the organization holds, from the product side. */
1201
2788
  onRequest?: () => void;
2789
+ /** Withdraw a request this side sent. Drawn for `state: 'sent'`, on either surface. */
2790
+ onRevoke?: () => void;
1202
2791
  /** Override the trailing controls entirely. */
1203
2792
  action?: React$1.ReactNode;
1204
2793
  }
@@ -1237,60 +2826,10 @@ interface FeedbackButtonProps {
1237
2826
  }
1238
2827
  declare function FeedbackButton({ onSubmit, labels, className }: FeedbackButtonProps): React$1.JSX.Element;
1239
2828
 
1240
- interface CreateProductWindowOrganization {
1241
- id: string;
1242
- name: string;
1243
- }
1244
- interface CreateProductWindowProduct {
1245
- id: string;
1246
- name: string;
1247
- slug: string;
1248
- }
1249
- type CreateProductSubmit = {
1250
- name: string;
1251
- organizationId: string;
1252
- }
1253
- /** @deprecated Emitted only by the deprecated create-new-org mode — see
1254
- * `CreateProductWindowProps.selectedOrgId`. Use `OrganizationCreateScreen` instead. */
1255
- | {
1256
- name: string;
1257
- organizationName: string;
1258
- };
1259
- interface CreateProductWindowProps {
1260
- organizations: CreateProductWindowOrganization[];
1261
- /**
1262
- * null => create-new-org mode.
1263
- *
1264
- * @deprecated The create-new-org mode is deprecated. Organization creation now goes
1265
- * through `OrganizationCreateScreen`, which collects the legal details the API needs
1266
- * (legal name, country of incorporation, beneficial owners) — this window only ever
1267
- * sends a bare `organizationName`. Pass a real org id and let the onboarding screens
1268
- * handle the org-first flow. Selecting an existing org here is unaffected.
1269
- */
1270
- selectedOrgId: string | null;
1271
- /** products of the selected org */
1272
- products: CreateProductWindowProduct[];
1273
- productsLoading?: boolean;
1274
- submitting?: boolean;
1275
- error?: string | null;
1276
- /** null when "+ Create new organization" chosen */
1277
- onOrganizationChange: (orgId: string | null) => void;
1278
- onEnterProduct: (product: CreateProductWindowProduct) => void;
1279
- onSubmit: (data: CreateProductSubmit) => void;
1280
- }
1281
- /**
1282
- * The legacy first-run window: pick an organization and name a product, in one panel.
1283
- *
1284
- * Still supported for picking an existing organization. Its **create-new-org mode**
1285
- * (`selectedOrgId: null`, or an empty `organizations` list) is deprecated — org creation
1286
- * now goes through `OrganizationCreateScreen`, followed by `ProductCreateScreen`.
1287
- */
1288
- declare function CreateProductWindow({ organizations, selectedOrgId, products, productsLoading, submitting, error, onOrganizationChange, onEnterProduct, onSubmit, }: CreateProductWindowProps): React$1.JSX.Element;
1289
-
1290
2829
  /** FYI / Important / Critical — the one severity vocabulary. */
1291
2830
  type NotificationSeverity = 'critical' | 'important' | 'fyi';
1292
2831
  /**
1293
- * How the item behaves, not how loud it is. `informational` settles when read,
2832
+ * How the item behaves, not how loud it is. `informational` is a statement,
1294
2833
  * `actionable` waits on a decision, `ephemeral` is ambient progress and never
1295
2834
  * settles.
1296
2835
  */
@@ -1310,7 +2849,14 @@ interface NotificationAction {
1310
2849
  */
1311
2850
  variant?: 'primary' | 'destructive' | 'link';
1312
2851
  }
1313
- /** A durable destination. Survives into the archive after the row settles. */
2852
+ /**
2853
+ * A durable destination. Survives into the archive after the row settles.
2854
+ *
2855
+ * `href` makes the control an anchor, so middle-click, open-in-new-tab and the
2856
+ * status-bar target come with it, and the surface's click handler fires beside it
2857
+ * rather than instead of it — the same contract `OrgProductSwitcherAction` and
2858
+ * `UserMenu` hold. Without an `href` the handler is the only thing that happens.
2859
+ */
1314
2860
  interface NotificationDeepLink {
1315
2861
  label: string;
1316
2862
  href?: string;
@@ -1324,10 +2870,15 @@ interface NotificationItem {
1324
2870
  body?: string;
1325
2871
  /** Default `informational`. */
1326
2872
  cls?: NotificationClass;
2873
+ /**
2874
+ * You have seen it. Independent of the receipt: a read row quietens and drops
2875
+ * its own mark-read control, and keeps every action it came with.
2876
+ */
1327
2877
  read?: boolean;
1328
2878
  /**
1329
2879
  * The receipt for a handled item, e.g. "Approved by artur". Its presence is
1330
- * what makes a row settled: the row dims and one-time actions drop off.
2880
+ * what makes a row settled: the row quietens further and one-time actions drop
2881
+ * off.
1331
2882
  */
1332
2883
  receipt?: string;
1333
2884
  createdAt?: string | Date;
@@ -1370,12 +2921,17 @@ declare const TOAST_DWELL: NotificationToastDwell;
1370
2921
  * Reads a stamp as a relative age. `now` is injectable so the components stay
1371
2922
  * testable and consumers can substitute an absolute or localized formatter; the
1372
2923
  * default reads the clock once during render, which is not a timer.
2924
+ *
2925
+ * Relative up to a week, then the date. Past that "how long ago" stops being the
2926
+ * question a reader is asking, and a running count answers it with a number that
2927
+ * only ever grows.
1373
2928
  */
1374
2929
  declare function formatRelativeAge(createdAt: string | Date, now?: Date): string;
1375
2930
  /**
1376
- * A settled item is one that has been dealt with: it dims, keeps its deep link
1377
- * and drops its one-time actions. Ephemeral items are ambient progressthey
1378
- * are never "handled", so they never settle.
2931
+ * A settled item is one that has been dealt with: it quietens, keeps its deep link
2932
+ * and drops its one-time actions. The receipt is what says so seeing an item is
2933
+ * not handling it, so a read row is still a row you can act on. Ephemeral items are
2934
+ * ambient progress and are never handled, so they never settle.
1379
2935
  */
1380
2936
  declare function isNotificationSettled(item: NotificationItem): boolean;
1381
2937
 
@@ -1397,6 +2953,17 @@ interface NotificationBellProps {
1397
2953
  onOpenSettings?(): void;
1398
2954
  /** Footer link. Rendered only when supplied and there is at least one item. */
1399
2955
  onOpenArchive?(): void;
2956
+ /**
2957
+ * A node at the foot of the panel, above the archive row and outside the region
2958
+ * the rows scroll in, so it stays reachable whatever the list is doing. Absent by
2959
+ * default; muted to match the archive row unless your node says otherwise.
2960
+ *
2961
+ * It composes with `onOpenArchive` rather than replacing it — supply either or
2962
+ * both. What it is for is a fact about the list that is not one of its rows: a
2963
+ * count the panel's own scope excludes, for one, which otherwise has to be
2964
+ * smuggled in as a synthetic `items` entry that the row semantics then apply to.
2965
+ */
2966
+ footer?: React$1.ReactNode;
1400
2967
  open?: boolean;
1401
2968
  onOpenChange?(open: boolean): void;
1402
2969
  /** Override the default relative-age label. */
@@ -1430,6 +2997,26 @@ interface NotificationCenterProps {
1430
2997
  }
1431
2998
  declare const NotificationCenter: React$1.ForwardRefExoticComponent<NotificationCenterProps & React$1.RefAttributes<HTMLDivElement>>;
1432
2999
 
3000
+ interface NotificationRowProps extends React$1.HTMLAttributes<HTMLDivElement> {
3001
+ item: NotificationItem;
3002
+ onItemClick?(item: NotificationItem): void;
3003
+ onActionClick?(item: NotificationItem, action: NotificationAction): void;
3004
+ /**
3005
+ * Marks the item read. Supplying it puts a quiet check control on the row when
3006
+ * the item is not read and not ephemeral.
3007
+ */
3008
+ onMarkRead?(id: string): void;
3009
+ /** Override the default relative-age label. */
3010
+ formatAge?(createdAt: Date): string;
3011
+ /**
3012
+ * The card rests on `bg-bg-surface`, which assumes an elevated parent — it is the
3013
+ * step the bell's panel gives it. On a page, whose ground is `bg-bg-primary`, that
3014
+ * step inverts sign: pass `bg-bg-elevated` to keep the row reading as raised.
3015
+ */
3016
+ className?: string;
3017
+ }
3018
+ declare const NotificationRow: React$1.ForwardRefExoticComponent<NotificationRowProps & React$1.RefAttributes<HTMLDivElement>>;
3019
+
1433
3020
  interface NotificationSettingsProps {
1434
3021
  subscriptions: NotificationSubscription[];
1435
3022
  /** Keyed by product id, plus the required `default` key. */
@@ -1452,6 +3039,19 @@ interface NotificationToastProps {
1452
3039
  showSource?: boolean;
1453
3040
  /** A short state line under the body, e.g. "Awaiting your decision — expires in 20s." */
1454
3041
  note?: React$1.ReactNode;
3042
+ /** The card's own controls: mute the source, turn its pushes off. Sits before the dismiss ✕. */
3043
+ overflow?: React$1.ReactNode;
3044
+ /** Ambient progress, 0 to 100. An ephemeral card is never handled, so it carries no actions.
3045
+ * Out of range is clamped, and a non-finite number counts as no progress at all — `done / total`
3046
+ * with `total === 0` draws no bar rather than a full one. */
3047
+ progress?: number;
3048
+ /**
3049
+ * The line under the bar. A slot, not a string, because the bar is the component's
3050
+ * and the wording is the consumer's — theirs is the run that knows whether it is
3051
+ * counting steps, bytes or minutes, and theirs is the language it is read in.
3052
+ * Defaults to `"live, n%"`; pass `null` for a bar with no line at all.
3053
+ */
3054
+ progressLabel?: React$1.ReactNode;
1455
3055
  onItemClick?(item: NotificationItem): void;
1456
3056
  onAction?(action: NotificationAction, item: NotificationItem): void;
1457
3057
  onDismiss?(item: NotificationItem): void;
@@ -1478,6 +3078,21 @@ interface NotificationToasterProps {
1478
3078
  onAction?(action: NotificationAction, item: NotificationItem): void;
1479
3079
  /** Per-item state line, e.g. a TTL countdown the consumer already tracks. */
1480
3080
  renderNote?(item: NotificationItem): React$1.ReactNode;
3081
+ /** Per-item card controls — a source menu beside the dismiss ✕. */
3082
+ renderOverflow?(item: NotificationItem): React$1.ReactNode;
3083
+ /**
3084
+ * Per-item ambient progress, 0 to 100. Read here rather than carried on the item
3085
+ * because it moves while the card is on screen, where `NotificationItem` is stable
3086
+ * data the bell and the centre read too — and neither of those draws a bar.
3087
+ */
3088
+ progressOf?(item: NotificationItem): number | undefined;
3089
+ /**
3090
+ * Per-item wording for the line under the bar. Unlike `renderNote`, whose `undefined` means
3091
+ * no note, `undefined` here means *take the card's default* `"live, n%"` — there is no way to
3092
+ * tell "this hook has no opinion about this item" apart from "this item wants no line". Return
3093
+ * `null` for a bar with no line at all.
3094
+ */
3095
+ renderProgressLabel?(item: NotificationItem): React$1.ReactNode;
1481
3096
  className?: string;
1482
3097
  }
1483
3098
  declare const NotificationToaster: React$1.ForwardRefExoticComponent<NotificationToasterProps & React$1.RefAttributes<HTMLDivElement>>;
@@ -1490,98 +3105,6 @@ declare const NotificationToaster: React$1.ForwardRefExoticComponent<Notificatio
1490
3105
  */
1491
3106
  declare const COUNTRY_OPTIONS: SelectOption[];
1492
3107
 
1493
- interface BetaGateScreenProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'title' | 'onSubmit'> {
1494
- /** Fires with the trimmed code. The screen never checks it — the caller does. */
1495
- onSubmit: (code: string) => void;
1496
- defaultCode?: string;
1497
- /** Fires with the raw field value on every keystroke — the seam a caller uses to clear
1498
- * its own `error` as the user starts correcting the code. */
1499
- onCodeChange?: (code: string) => void;
1500
- /** Focuses the access-code field on mount. On by default: the screen is one field, so
1501
- * that is where the caret belongs. Pass `false` to leave the focus alone. */
1502
- autoFocus?: boolean;
1503
- /** Disables the submit button and swaps its label while the caller's check is in flight. */
1504
- submitting?: boolean;
1505
- /** Rendered as an alert above the field — typically a rejected code. */
1506
- error?: string | null;
1507
- /** Social sign-in buttons, rendered above an "or" divider. Without it there is no divider. */
1508
- socialAuth?: React$1.ReactNode;
1509
- /** Target of the waitlist link in the default description. */
1510
- waitlistHref?: string;
1511
- /** Renders "Already have an account? Sign in" as a link. */
1512
- signInHref?: string;
1513
- /** Renders the same affordance as a button. Ignored when `signInHref` is given. */
1514
- onSignIn?: () => void;
1515
- submitLabel?: React$1.ReactNode;
1516
- /** Brand mark above the headline. */
1517
- logo?: React$1.ReactNode;
1518
- /** Rendered top-right. Defaults to the kit's own `ThemeToggle`; pass your own node to
1519
- * replace it, or `null` to drop it. */
1520
- themeToggle?: React$1.ReactNode;
1521
- /** Pass `null` to render no page heading — same meaning as on `SignupScreen`. */
1522
- title?: React$1.ReactNode;
1523
- description?: React$1.ReactNode;
1524
- /** Muted footer signature. Absent by default; pass a node to render one. */
1525
- footer?: React$1.ReactNode;
1526
- }
1527
- /**
1528
- * The gate in front of registration while the product is in closed beta: a single access
1529
- * code, optionally preceded by social sign-in. Presentational and self-contained — it never
1530
- * validates the code, never calls an API and never navigates; the caller handles the
1531
- * outcome of `onSubmit`.
1532
- */
1533
- declare function BetaGateScreen({ onSubmit, defaultCode, onCodeChange, autoFocus, submitting, error, socialAuth, waitlistHref, signInHref, onSignIn, submitLabel, logo, themeToggle, title, description, footer, ...props }: BetaGateScreenProps): React$1.JSX.Element;
1534
-
1535
- /** The submit payload — what a registration endpoint takes, minus anything the caller owns
1536
- * (the beta code, the invite, the return URL). */
1537
- interface SignupScreenSubmit {
1538
- name: string;
1539
- email: string;
1540
- password: string;
1541
- }
1542
- interface SignupScreenProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'title' | 'onSubmit'> {
1543
- onSubmit: (payload: SignupScreenSubmit) => void;
1544
- defaultValues?: Partial<SignupScreenSubmit>;
1545
- /** Disables the submit button and swaps its label while the caller's request is in flight. */
1546
- submitting?: boolean;
1547
- serverError?: string | null;
1548
- /** Field-level messages returned alongside a server error. */
1549
- violations?: string[];
1550
- /** Social sign-in buttons, rendered above an "or continue with email" divider. Not shown
1551
- * when `children` take over the body. */
1552
- socialAuth?: React$1.ReactNode;
1553
- /** Renders "Use a different code" under the form — the way back to the beta gate. */
1554
- onEditCode?: () => void;
1555
- /** Renders "Already have an account? Sign in" as a link. */
1556
- signInHref?: string;
1557
- /** Renders the same affordance as a button. Ignored when `signInHref` is given. */
1558
- onSignIn?: () => void;
1559
- submitLabel?: React$1.ReactNode;
1560
- /**
1561
- * Replaces the whole body — social auth, divider, register form and all. This is the seam
1562
- * the consumer uses to host steps the kit deliberately does not know about (MFA challenge,
1563
- * TOTP enrolment) inside the same window.
1564
- */
1565
- children?: React$1.ReactNode;
1566
- /** Brand mark above the headline. */
1567
- logo?: React$1.ReactNode;
1568
- /** Rendered top-right. Defaults to the kit's own `ThemeToggle`; pass your own node to
1569
- * replace it, or `null` to drop it. */
1570
- themeToggle?: React$1.ReactNode;
1571
- /** Pass `null` to render no page heading — for a body (MFA steps) that brings its own. */
1572
- title?: React$1.ReactNode;
1573
- description?: React$1.ReactNode;
1574
- /** Muted footer signature. Absent by default; pass a node to render one. */
1575
- footer?: React$1.ReactNode;
1576
- }
1577
- /**
1578
- * The registration window: social sign-in, then name / email / password. Presentational and
1579
- * self-contained — it never calls an API and never navigates; the caller handles the outcome
1580
- * of `onSubmit`. Password rules are checked here because they are the same rules the
1581
- * registration endpoint enforces, and failing them client-side saves a round trip.
1582
- */
1583
- declare function SignupScreen({ onSubmit, defaultValues, submitting, serverError, violations, socialAuth, onEditCode, signInHref, onSignIn, submitLabel, children, logo, themeToggle, title, description, footer, ...props }: SignupScreenProps): React$1.JSX.Element;
1584
-
1585
3108
  /** One beneficial owner, in the shape the organization API takes it. */
1586
3109
  interface BeneficialOwnerPayload {
1587
3110
  name: string;
@@ -1633,137 +3156,200 @@ interface OrganizationOnboardingFormProps {
1633
3156
  */
1634
3157
  declare function OrganizationOnboardingForm({ requireSanctionsFields, onSubmit, defaultValues, submitting, serverError, violations, countries, submitLabel, onCancel, className, }: OrganizationOnboardingFormProps): React$1.JSX.Element;
1635
3158
 
1636
- interface OrganizationCreateScreenProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'title' | 'onSubmit'> {
1637
- /** Makes the country of incorporation and the ownership confirmation, where it is
1638
- * shownmandatory. Mirrors the server-side requirement the consumer runs under. */
1639
- requireSanctionsFields: boolean;
1640
- onSubmit: (payload: OrganizationOnboardingPayload) => void;
1641
- defaultValues?: OrganizationOnboardingDefaults;
1642
- /** Disables the submit button and swaps its label while the caller's request is in flight. */
1643
- submitting?: boolean;
1644
- serverError?: string | null;
1645
- /** Field-level messages returned alongside a server error. */
1646
- violations?: string[];
1647
- /** Defaults to the built-in ISO 3166-1 alpha-2 list. */
1648
- countries?: SelectOption[];
1649
- submitLabel?: string;
1650
- /** Renders a Cancel button in the form when provided. */
1651
- onCancel?: () => void;
1652
- /** Brand mark above the headline. */
1653
- logo?: React$1.ReactNode;
1654
- /** Rendered top-right. Defaults to the kit's own `ThemeToggle`; pass your own node to
1655
- * replace it, or `null` to drop it. */
1656
- themeToggle?: React$1.ReactNode;
1657
- title?: React$1.ReactNode;
1658
- description?: React$1.ReactNode;
1659
- /** Muted footer signature. Absent by default; pass a node to render one. */
1660
- footer?: React$1.ReactNode;
3159
+ /**
3160
+ * The width steps a trailing cell may take, as literal classes. A width is picked from this map and
3161
+ * never assembled `` `w-${n}` `` is a string Tailwind's scanner never sees, so the class would
3162
+ * never be generated and the cell would size to its content instead.
3163
+ */
3164
+ declare const CELL_WIDTH: {
3165
+ readonly 20: "w-20";
3166
+ readonly 24: "w-24";
3167
+ readonly 28: "w-28";
3168
+ readonly 32: "w-32";
3169
+ };
3170
+ /** 5rem to 8rem: a date, a relative time, a short phrase like "Renews itself". */
3171
+ type ListColumnWidth = keyof typeof CELL_WIDTH;
3172
+ /**
3173
+ * One trailing column of a list, declared once and handed to both the header and every row — which
3174
+ * is the whole point of the pair. A cell that cannot ask its header for a width is two literals kept
3175
+ * in step by hand, and they drift the first time one list is edited and the one below it is not.
3176
+ */
3177
+ interface ListColumn {
3178
+ /** Which value in a row's `values` this column draws. */
3179
+ key: string;
3180
+ /** What the header says over it. */
3181
+ label: React$1.ReactNode;
3182
+ width: ListColumnWidth;
3183
+ /**
3184
+ * Drawn when the row says nothing here — a missing key, `null`, or an empty string. "Never"
3185
+ * rather than an empty cell the eye reads as a gap.
3186
+ */
3187
+ fallback?: React$1.ReactNode;
3188
+ /** One tone quieter — a column that qualifies the row rather than answering it. */
3189
+ quiet?: boolean;
3190
+ }
3191
+ interface ListHeaderProps extends React$1.HTMLAttributes<HTMLDivElement> {
3192
+ /** The label over the flexible name column — what the rows below are a list of. */
3193
+ lead: React$1.ReactNode;
3194
+ columns: readonly ListColumn[];
3195
+ /**
3196
+ * Reserve the `size-8` leading column `EntityRow` gives its `mark`. Off for a list whose rows
3197
+ * carry no mark, where the reserve would push the lead 44px off the card's own padding.
3198
+ */
3199
+ mark?: boolean;
3200
+ /**
3201
+ * Reserve the `size-4` trailing column `EntityRow` keeps for its chevron. Off for a list of
3202
+ * `opens="none"` rows, which is the one form that reserves nothing.
3203
+ */
3204
+ trailing?: boolean;
1661
3205
  }
1662
3206
  /**
1663
- * Full-page first step of the org-first onboarding flow: the screen a user lands on when
1664
- * they have no organization yet. It is the screen wrapper around
1665
- * `OrganizationOnboardingForm` — presentational and self-contained, it never calls an API
1666
- * and never navigates; the caller handles the outcome of `onSubmit`.
3207
+ * The column header over a list of `EntityRow`s. It is not a table head: the rows stay rows you open,
3208
+ * with their hover plate, their focus ring and their one target.
3209
+ *
3210
+ * It takes the same `columns` array the rows' `ListCells` takes, so the widths are declared once and
3211
+ * two lists on one page rule their trailing columns at the same x.
1667
3212
  */
1668
- declare function OrganizationCreateScreen({ requireSanctionsFields, onSubmit, defaultValues, submitting, serverError, violations, countries, submitLabel, onCancel, logo, themeToggle, title, description, footer, ...props }: OrganizationCreateScreenProps): React$1.JSX.Element;
1669
-
1670
- interface OrganizationUnderReviewScreenProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'title'> {
1671
- /** The only always-present action: the user cannot go anywhere else from this screen. */
1672
- onLogout: () => void;
1673
- /** Renders the secondary "Send feedback" button when provided. */
1674
- onFeedback?: () => void;
1675
- logoutLabel?: string;
1676
- feedbackLabel?: string;
1677
- /** Brand mark above the headline. */
1678
- logo?: React$1.ReactNode;
1679
- /** Rendered top-right. Defaults to the kit's own `ThemeToggle`; pass your own node to
1680
- * replace it, or `null` to drop it. */
1681
- themeToggle?: React$1.ReactNode;
1682
- title?: React$1.ReactNode;
1683
- description?: React$1.ReactNode;
1684
- /** Muted footer signature. Absent by default; pass a node to render one. */
1685
- footer?: React$1.ReactNode;
1686
- /** Extra content between the header copy and the actions — a support link, a reference
1687
- * number, whatever the product needs to add. */
1688
- children?: React$1.ReactNode;
3213
+ declare const ListHeader: React$1.ForwardRefExoticComponent<ListHeaderProps & React$1.RefAttributes<HTMLDivElement>>;
3214
+ interface ListCellsProps extends React$1.HTMLAttributes<HTMLSpanElement> {
3215
+ columns: readonly ListColumn[];
3216
+ /** This row's answer per column `key`. A key with no value draws that column's `fallback`. */
3217
+ values: Record<string, React$1.ReactNode>;
1689
3218
  }
1690
3219
  /**
1691
- * The waiting room of the org-first onboarding flow: the screen a user lands on once their
1692
- * organization has been submitted and is not usable yet. Same login-card format as
1693
- * `OrganizationCreateScreen`.
3220
+ * A row's trailing cells, for `EntityRow`'s `meta` slot spans rather than divs, because `meta`
3221
+ * renders inside the row's own inline content.
1694
3222
  *
1695
- * The copy is deliberately neutral it states that a review is in progress and how long it
1696
- * usually takes, and nothing about why or against what. Keep it that way; the reason for the
1697
- * wait is never the user-facing story here.
3223
+ * It reads the widths off the same `columns` the header was given, so a column that changes width
3224
+ * changes in both places or in neither.
3225
+ */
3226
+ declare const ListCells: React$1.ForwardRefExoticComponent<ListCellsProps & React$1.RefAttributes<HTMLSpanElement>>;
3227
+
3228
+ type ThemePickerBaseProps = Omit<React$1.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>;
3229
+ /**
3230
+ * Controlled or wired, and the union is what makes a caller say which.
3231
+ *
3232
+ * `value` alone used to compile: three cards that look pressable, and pressing one changed nothing,
3233
+ * because the only thing that could have moved was the handler that was not passed. So the arm that
3234
+ * takes `value` takes `onValueChange` with it.
1698
3235
  *
1699
- * Presentational and self-contained: it never calls an API and never navigates; the caller
1700
- * handles `onLogout` and `onFeedback`.
3236
+ * The other arm takes neither, and is the console's own setting it reads and writes `useTheme()`,
3237
+ * so picking repaints the surface you are standing on, which is what a settings page wants.
3238
+ * `onValueChange` is still allowed there, as a notification after the console has been set.
3239
+ *
3240
+ * What the union does not catch is `value={prefs?.theme}`: a `Theme | undefined` satisfies the second
3241
+ * arm, so the call compiles and the picker is wired until the value lands. That is the call that
3242
+ * writes `<html>` behind a caller who thinks they are holding the value, and it is why `ThemePicker`
3243
+ * settles its mode at mount and warns — the type cannot reach this one, so the runtime does.
1701
3244
  */
1702
- declare function OrganizationUnderReviewScreen({ onLogout, onFeedback, logoutLabel, feedbackLabel, logo, themeToggle, title, description, footer, children, ...props }: OrganizationUnderReviewScreenProps): React$1.JSX.Element;
3245
+ type ThemePickerProps = ThemePickerBaseProps & ({
3246
+ /** The chosen theme. Nothing outside the component moves: no `<html>` class, no localStorage. */
3247
+ value: Theme;
3248
+ onValueChange: (theme: Theme) => void;
3249
+ } | {
3250
+ value?: undefined;
3251
+ onValueChange?: (theme: Theme) => void;
3252
+ });
3253
+ /**
3254
+ * Choosing the console's theme, by looking at it: Light and Dark are miniatures of the console they
3255
+ * offer, and Auto is the `Monitor` glyph, because it follows the machine and has no one console to
3256
+ * show. Auto is `system`, and it is here because `ThemeToggle` already cycles through it — a picker
3257
+ * offering only light and dark would contradict the console's own control.
3258
+ */
3259
+ declare const ThemePicker: React$1.ForwardRefExoticComponent<ThemePickerProps & React$1.RefAttributes<HTMLDivElement>>;
1703
3260
 
1704
- /** One organization the user can create the product in. */
1705
- interface ProductCreateScreenOrganization {
1706
- id: string;
1707
- name: string;
1708
- }
1709
- /** One product already living in the target organization. */
1710
- interface ProductCreateScreenProduct {
1711
- id: string;
1712
- name: string;
1713
- slug?: string;
1714
- }
1715
- /** The submit payload. The organization is implied — the screen only ever creates inside
1716
- * the organization it was given. */
1717
- interface ProductCreateScreenSubmit {
1718
- name: string;
1719
- }
1720
- interface ProductCreateScreenProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'title' | 'onSubmit'> {
1721
- /**
1722
- * @deprecated No longer rendered. The first-product screen shows no organization
1723
- * context at all, and where the user does have a choice the screen renders the
1724
- * `organizations` select instead. Kept so existing callers still type-check.
1725
- */
1726
- organizationName?: string;
1727
- /** The organizations the user can pick between. Omit (or pass an empty list) for the
1728
- * first-product screen, which shows no organization UI. Passing organizations switches
1729
- * the screen to the picker layout: select on top, that org's products, then the name. */
1730
- organizations?: ProductCreateScreenOrganization[];
1731
- /** The organization currently selected in the picker layout. */
1732
- selectedOrganizationId?: string;
1733
- /** Fires with the picked organization id. Without it the select is read-only. */
1734
- onOrganizationChange?: (organizationId: string) => void;
1735
- /** Shows a loading note in place of the products list while the caller fetches them. */
1736
- productsLoading?: boolean;
1737
- onSubmit: (data: ProductCreateScreenSubmit) => void;
1738
- defaultName?: string;
1739
- /** Disables the submit button and swaps its label while the caller's request is in flight. */
1740
- submitting?: boolean;
1741
- serverError?: string | null;
1742
- /** Products the organization already has. Omit (or pass an empty list) to hide the
1743
- * "Your products" section entirely. */
1744
- existingProducts?: ProductCreateScreenProduct[];
1745
- /** Makes each existing product a button. Without it the list is read-only. */
1746
- onOpenProduct?: (product: ProductCreateScreenProduct) => void;
1747
- /** Heading above the existing-products list. */
1748
- existingProductsLabel?: React$1.ReactNode;
1749
- submitLabel?: React$1.ReactNode;
1750
- /** Renders a Cancel button when provided. */
1751
- onCancel?: () => void;
1752
- /** Brand mark above the headline. */
1753
- logo?: React$1.ReactNode;
1754
- /** Rendered top-right. Defaults to the kit's own `ThemeToggle`; pass your own node to
1755
- * replace it, or `null` to drop it. */
1756
- themeToggle?: React$1.ReactNode;
1757
- title?: React$1.ReactNode;
1758
- description?: React$1.ReactNode;
1759
- /** Muted footer signature. Absent by default; pass a node to render one. */
1760
- footer?: React$1.ReactNode;
3261
+ interface MedallionProps extends Omit<React$1.HTMLAttributes<HTMLSpanElement>, 'children'> {
3262
+ /** The glyph. The medallion owns its 24px sizing, so a caller can never leave one at the wrong step. */
3263
+ icon: LucideIcon;
3264
+ /** The payoff tone: an inverted plate for the end of a flow, not a resting state. */
3265
+ filled?: boolean;
1761
3266
  }
1762
3267
  /**
1763
- * Full-page second step of the org-first onboarding flow: create the first product inside
1764
- * an organization that already exists. Presentational and self-contained it never calls
1765
- * an API and never navigates; the caller handles the outcome of `onSubmit`.
3268
+ * The circle that stands for nothing a section, a screen or a step, never a principal. That is why
3269
+ * it is neither `GlyphAvatar` nor a `Mark`: `Guidelines/Avatars` maps person, agent and group to a
3270
+ * circle and every object to `EntityTile`'s rounded square, and an arbitrary glyph on the principal
3271
+ * mark would make a round object spellable.
3272
+ *
3273
+ * The plate is the same geometry as an `lg` `Mark` — same box, same neutral tone — because the two sit
3274
+ * side by side on a page and a reader takes a difference in either as meaning something. Each file
3275
+ * writes its own; `medallion.test.tsx` holds them together.
3276
+ *
3277
+ * One size, because every place that draws it is 48px. A size prop would only offer a smaller box
3278
+ * around the same 24px glyph.
3279
+ *
3280
+ * `filled` marks a payoff — "you're in" at the end of a challenge — with weight rather than colour,
3281
+ * so success does not reach for green (Guidelines/Colour marks actions). It is the end of a flow,
3282
+ * never a resting state, which is why a page header has no use for it. It is local to the medallion:
3283
+ * `Mark`'s tones are the identity tints, and no avatar has a filled step.
3284
+ *
3285
+ * It is a mark, not a control: no role, no name, nothing to press. A medallion that wants a click
3286
+ * wants a button around the thing it marks.
1766
3287
  */
1767
- declare function ProductCreateScreen({ organizationName: _organizationName, organizations, selectedOrganizationId, onOrganizationChange, productsLoading, onSubmit, defaultName, submitting, serverError, existingProducts, onOpenProduct, existingProductsLabel, submitLabel, onCancel, logo, themeToggle, title, description, footer, ...props }: ProductCreateScreenProps): React$1.JSX.Element;
3288
+ declare const Medallion: React$1.ForwardRefExoticComponent<MedallionProps & React$1.RefAttributes<HTMLSpanElement>>;
3289
+
3290
+ /**
3291
+ * A secret the console will never show again — recovery codes, a provisioning token, an agent secret
3292
+ * — held in an inset well until the person confirms they have taken it.
3293
+ *
3294
+ * The well is the emphasis and it does not fade: a sunken tone behind a `border-border-strong`
3295
+ * outline, which `Guidelines/Look/Borders` gives to an edge that is itself the point. Monochrome
3296
+ * throughout, no icon on the container, because `Guidelines/Look/Colour marks actions` leaves colour
3297
+ * to actions and this is a state.
3298
+ *
3299
+ * **The confirm is never disabled.** Before the secret has been taken it rests `ghost` on the holding
3300
+ * word; once Copy or Download has succeeded it settles to the `secondary` fill carrying the
3301
+ * affirmative the call site asked for. Both words are the same exit and both call `onConfirm`, so the
3302
+ * holding word has to name what leaving now does.
3303
+ *
3304
+ * `Copy` and `Download` are peers, not a ranked pair, so both stay `outline`
3305
+ * (`Guidelines/Controls/Button pairs`).
3306
+ *
3307
+ * Nothing here writes a file or raises a toast: `onCopied` and `onDownload` fire so the call site
3308
+ * names what was taken in its own words, and the clipboard is the one side effect the component owns.
3309
+ */
3310
+ interface SecretRevealProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'children'> {
3311
+ /** One value on a line, or several in two columns. */
3312
+ value: string | string[];
3313
+ /** The prose above the value: what it is, and that it will not be shown again. */
3314
+ caption: string;
3315
+ /** The affirmative, once the secret has been taken: "Done", "Done, turn on". */
3316
+ confirmLabel: string;
3317
+ /** Both words are one exit — pressed before the secret is taken, and after. */
3318
+ onConfirm: () => void;
3319
+ /**
3320
+ * The holding word, before the secret has been taken. Required, and where leaving now has a
3321
+ * consequence the word has to name it: the exit is live either way. Where closing the block is all
3322
+ * it does, `Dismiss` says so.
3323
+ */
3324
+ dismissLabel: string;
3325
+ /** Fires once the value has reached the clipboard, for the call site's own toast. */
3326
+ onCopied?: () => void;
3327
+ /**
3328
+ * Draws the Download control, and fires when it is pressed. Omit it and there is no second control:
3329
+ * recovery codes are the only secret with a file to save, so the presence of a handler is the
3330
+ * question "is there a file?" already answered.
3331
+ */
3332
+ onDownload?: () => void;
3333
+ /** Defaults to `Copy`, or `Copy all` when the value is a list. */
3334
+ copyLabel?: string;
3335
+ downloadLabel?: string;
3336
+ /**
3337
+ * Move focus to the copy control on arrival. Off by default: a page holding more than one of these
3338
+ * would fight over the focus, and a focus scrolls the page to whatever received it. Pass it where
3339
+ * the reveal is the thing that just happened.
3340
+ */
3341
+ autoFocus?: boolean;
3342
+ /**
3343
+ * A class for the layer between the well's tone and its outline, for a highlight that marks the
3344
+ * block as newly arrived. It exists as a layer of its own because such a wash typically ends on
3345
+ * `background-color: transparent` and holds it, so an element carrying both the wash and a resting
3346
+ * tone is painted transparent through the fade — the tone is on the well, the wash goes here, the
3347
+ * outline and content sit above it.
3348
+ */
3349
+ highlightClassName?: string;
3350
+ /** The same layer, for a hook that needs the element — a scroll-into-view on arrival. */
3351
+ highlightRef?: React$1.Ref<HTMLDivElement>;
3352
+ }
3353
+ declare const SecretReveal: React$1.ForwardRefExoticComponent<SecretRevealProps & React$1.RefAttributes<HTMLDivElement>>;
1768
3354
 
1769
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, type AppShellProps, AppSidebar, type AppSidebarProps, AspectRatio, AuthenticatedLayout, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, type BeneficialOwnerPayload, BetaGateScreen, type BetaGateScreenProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, type ButtonProps, COUNTRY_OPTIONS, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, type CarouselApi, CarouselContent, type CarouselContextProps, CarouselItem, CarouselNext, type CarouselOptions, type CarouselPlugin, CarouselPrevious, type CarouselProps, Checkbox, Code, CodeBlock, type CodeBlockProps, type CodeLang, type CodeProps, Col, type ColProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ConfirmDialog, type ConfirmDialogProps, type ConnectionAuth, ConnectionCard, type ConnectionCardProps, type ConnectionScope, type ConnectionStatus, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, type CopyButtonProps, type CreateProductSubmit, CreateProductWindow, type CreateProductWindowOrganization, type CreateProductWindowProduct, type CreateProductWindowProps, DatePicker, type DatePickerProps, type DeltaDirection, type DeltaTone, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DocsLink, type DocsLinkProps, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ExtensionIcon, type ExtensionIconProps, ExtensionLink, type ExtensionLinkProps, type ExtensionLinkUiMode, FeedbackButton, type FeedbackButtonLabels, type FeedbackButtonProps, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, Grid, GridOverlay, type GridOverlayProps, type GridProps, HoverCard, HoverCardContent, HoverCardTrigger, InlineError, type InlineErrorProps, Input, InputAddon, type InputAddonProps, InputGroup, InputGroupInput, type InputGroupInputProps, type InputGroupProps, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Label, MenuDivider, MenuPopup, type MenuPopupProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, type NavItem, type NavLinkComponent, NavRow, type NavRowProps, type NavRowVariant, NavSectionLabel, type NavSectionLabelProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, type NotifClass, type NotificationAction, NotificationBell, type NotificationBellProps, NotificationCenter, type NotificationCenterProps, type NotificationClass, type NotificationDeepLink, type NotificationItem, type NotificationMute, type NotificationPreferences, type NotificationProduct, NotificationSettings, type NotificationSettingsProps, type NotificationSeverity, type NotificationSubscription, type NotificationThreshold, NotificationToast, type NotificationToastDwell, type NotificationToastProps, NotificationToaster, type NotificationToasterPosition, type NotificationToasterProps, OrgProductSwitcher, type OrgProductSwitcherAction, type OrgProductSwitcherItem, type OrgProductSwitcherProps, OrganizationCreateScreen, type OrganizationCreateScreenProps, type OrganizationOnboardingDefaults, OrganizationOnboardingForm, type OrganizationOnboardingFormProps, type OrganizationOnboardingPayload, OrganizationUnderReviewScreen, type OrganizationUnderReviewScreenProps, PageHeader, type PageHeaderProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, type PaginationLinkProps, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ProductCreateScreen, type ProductCreateScreenOrganization, type ProductCreateScreenProduct, type ProductCreateScreenProps, type ProductCreateScreenSubmit, Progress, RadioGroup, RadioGroupItem, RequestRow, type RequestRowProps, type RequestState, type RequestSurface, type ResolvedTheme, type Responsive, ScrollArea, ScrollBar, SectionIntro, type SectionIntroProps, SegmentChip, type SegmentChipProps, Select, type SelectOption, type SelectProps, Separator, type Severity, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarBackHeader, type SidebarBackHeaderProps, SidebarNav, SidebarNavLink, type SidebarNavLinkProps, type SidebarNavProps, SidebarProductHeader, type SidebarProductHeaderProps, SignupScreen, type SignupScreenProps, type SignupScreenSubmit, Skeleton, Slider, StatCard, type StatCardProps, StatusDot, type StatusDotProps, Switch, type SwitchProps, TOAST_DWELL, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, type TextareaProps, type Theme, ThemeToggle, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UseSidebarOptions, type UseSidebarResult, UserMenu, type UserMenuItem, type UserMenuProps, type UserMenuUser, alertVariants, badgeVariants, buttonVariants, cn, formatRelativeAge, isKnownExtensionIcon, isNotificationSettled, navigationMenuTriggerStyle, segmentChipVariants, severityBadgeVariant, severityLabels, statusDotVariants, toggleVariants, useCarousel, useFormField, useIsMobile, useSidebar, useTheme };
3355
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AddPicker, type AddPickerItem, type AddPickerProps, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, type AppShellProps, AppSidebar, type AppSidebarProps, AspectRatio, AttachmentChip, type AttachmentChipProps, type AttachmentState, AuthenticatedLayout, AutoHeight, type AutoHeightProps, Avatar, AvatarFallback, AvatarImage, BackLink, type BackLinkProps, Badge, type BadgeProps, type BeneficialOwnerPayload, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, type ButtonProps, COUNTRY_OPTIONS, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardNote, type CardNoteProps, type CardProps, CardTitle, type CardTitleProps, Carousel, type CarouselApi, CarouselContent, type CarouselContextProps, CarouselItem, CarouselNext, type CarouselOptions, type CarouselPlugin, CarouselPrevious, type CarouselProps, Checkbox, Code, CodeBlock, type CodeBlockProps, type CodeLang, type CodeProps, type CodeVariant, Col, type ColProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, type CommandItemProps, CommandList, CommandSeparator, CommandShortcut, ConfirmDialog, type ConfirmDialogProps, type ConfirmDialogStepUp, ConnectorCard, type ConnectorCardProps, type ConnectorOrigin, type ConnectorStatus, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, type CopyButtonProps, DatePicker, type DatePickerProps, DecorativeIcon, type DecorativeIconProps, type DeltaDirection, type DeltaTone, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DocsLink, type DocsLinkProps, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, EntityRow, type EntityRowOpens, type EntityRowOpensProps, type EntityRowProps, EntityTile, type EntityTileProps, ExtensionIcon, type ExtensionIconProps, ExtensionLink, type ExtensionLinkProps, type ExtensionLinkUiMode, FeedbackButton, type FeedbackButtonLabels, type FeedbackButtonProps, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, GlyphAvatar, type GlyphAvatarProps, type GrantRole, type GrantRoleNotes, GrantRolePicker, type GrantRolePickerProps, GrantRow, type GrantRowProps, Grid, GridOverlay, type GridOverlayProps, type GridProps, HoverCard, HoverCardContent, HoverCardTrigger, IconHint, type IconHintProps, ImageCropDialog, type ImageCropDialogProps, type ImageCropShape, type ImageCropType, ImageCropper, type ImageCropperProps, ImageUpload, type ImageUploadProps, type ImageUploadSize, InlineError, type InlineErrorProps, Input, InputAddon, type InputAddonProps, InputGroup, InputGroupInput, type InputGroupInputProps, type InputGroupProps, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Label, ListCells, type ListCellsProps, type ListColumn, type ListColumnWidth, ListHeader, type ListHeaderProps, MISSING_TONE, Medallion, type MedallionProps, MenuDivider, MenuPopup, type MenuPopupProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, type NavItem, type NavLinkComponent, NavRow, type NavRowProps, type NavRowVariant, NavSectionLabel, type NavSectionLabelProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, type NotifClass, type NotificationAction, NotificationBell, type NotificationBellProps, NotificationCenter, type NotificationCenterProps, type NotificationClass, type NotificationDeepLink, type NotificationItem, type NotificationMute, type NotificationPreferences, type NotificationProduct, NotificationRow, type NotificationRowProps, NotificationSettings, type NotificationSettingsProps, type NotificationSeverity, type NotificationSubscription, type NotificationThreshold, NotificationToast, type NotificationToastDwell, type NotificationToastProps, NotificationToaster, type NotificationToasterPosition, type NotificationToasterProps, OrgProductSwitcher, type OrgProductSwitcherAction, type OrgProductSwitcherItem, type OrgProductSwitcherProps, type OrganizationOnboardingDefaults, OrganizationOnboardingForm, type OrganizationOnboardingFormProps, type OrganizationOnboardingPayload, PageHeader, type PageHeaderProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, type PaginationLinkProps, PaginationNext, PaginationPrevious, PersonAvatar, type PersonAvatarProps, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, RemovableChip, type RemovableChipProps, RemoveButton, type RemoveButtonProps, RequestRow, type RequestRowProps, type RequestState, type RequestSurface, type ResolvedTheme, type Responsive, ScrollArea, ScrollBar, SecretReveal, type SecretRevealProps, SectionIntro, type SectionIntroProps, Select, type SelectOption, type SelectProps, Separator, SettingRow, type SettingRowProps, type Severity, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarBackHeader, type SidebarBackHeaderProps, SidebarNav, SidebarNavLink, type SidebarNavLinkProps, type SidebarNavProps, SidebarProductHeader, type SidebarProductHeaderProps, Skeleton, Slider, StatCard, type StatCardProps, StatusDot, type StatusDotProps, StepUpChallenge, type StepUpChallengeProps, type StepUpMethod, type StepUpProof, Switch, type SwitchProps, TOAST_DWELL, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, type TableProps, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, type TextareaProps, type Theme, ThemePicker, type ThemePickerProps, ThemeToggle, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UseSidebarOptions, type UseSidebarResult, UserMenu, type UserMenuItem, type UserMenuProps, type UserMenuUser, WEIGHT_TONE, alertVariants, attachmentChipVariants, badgeVariants, buttonVariants, cn, formatRelativeAge, grantRemoveLabel, isKnownExtensionIcon, isNotificationSettled, navigationMenuTriggerStyle, severityBadgeVariant, severityLabels, statusDotVariants, toggleVariants, useCarousel, useFormField, useIsMobile, useSidebar, useTheme };