@platned/ui 0.1.4 → 0.3.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.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as react from 'react';
2
- import { ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, TextareaHTMLAttributes, SelectHTMLAttributes } from 'react';
2
+ import { ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, TextareaHTMLAttributes, SelectHTMLAttributes, HTMLAttributes, RefObject, Key } from 'react';
3
+ import { ClassValue } from 'clsx';
3
4
 
4
5
  type ButtonVariant = 'primary' | 'neutral' | 'subtle' | 'danger' | 'danger-subtle';
5
6
  type ButtonSize = 'lg' | 'md' | 'sm';
@@ -81,18 +82,6 @@ interface AvatarBlockProps {
81
82
  }
82
83
  declare function AvatarBlock({ children, title, description, className }: AvatarBlockProps): react.JSX.Element;
83
84
 
84
- interface NavItemProps {
85
- icon?: ReactNode;
86
- label: string;
87
- isActive?: boolean;
88
- /** Red indicator dot at top-right corner (e.g. unread count) */
89
- indicator?: boolean;
90
- /** Collapsed mode — icon only, label hidden */
91
- collapsed?: boolean;
92
- className?: string;
93
- }
94
- declare function NavItem({ icon, label, isActive, indicator, collapsed, className, }: NavItemProps): react.JSX.Element;
95
-
96
85
  type InputSize = 'lg' | 'md' | 'sm';
97
86
  interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
98
87
  label?: string;
@@ -104,6 +93,9 @@ interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'>
104
93
  size?: InputSize;
105
94
  leadingIcon?: ReactNode;
106
95
  trailingIcon?: ReactNode;
96
+ /** Interactive trailing slot (e.g. a show/hide password button) — unlike
97
+ * `trailingIcon` it receives pointer events. */
98
+ trailingAction?: ReactNode;
107
99
  }
108
100
  declare const Input: react.ForwardRefExoticComponent<InputProps & react.RefAttributes<HTMLInputElement>>;
109
101
 
@@ -131,6 +123,15 @@ interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'siz
131
123
  }
132
124
  declare const Select: react.ForwardRefExoticComponent<SelectProps & react.RefAttributes<HTMLSelectElement>>;
133
125
 
126
+ interface DatePickerProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {
127
+ label?: string;
128
+ description?: string;
129
+ error?: string;
130
+ hint?: string;
131
+ size?: InputSize;
132
+ }
133
+ declare const DatePicker: react.ForwardRefExoticComponent<DatePickerProps & react.RefAttributes<HTMLInputElement>>;
134
+
134
135
  type StepStatus = 'complete' | 'active' | 'upcoming';
135
136
  interface StepItem {
136
137
  label: string;
@@ -152,69 +153,35 @@ interface MultiSelectCardProps {
152
153
  }
153
154
  declare function MultiSelectCard({ icon, title, description, selected, onToggle, className, }: MultiSelectCardProps): react.JSX.Element;
154
155
 
155
- interface ColumnDef<T> {
156
- key: string;
157
- header: string;
158
- /** CSS width value — e.g. "320px", "10rem". When grow is true, acts as min-width. */
159
- width: string;
160
- /** When true the column fills remaining row width; width becomes a min-width floor. */
161
- grow?: boolean;
162
- render: (row: T) => ReactNode;
163
- }
164
- declare function DataTable<T>({ columns, rows, getRowKey, className, onRowClick, }: {
165
- columns: ColumnDef<T>[];
166
- rows: T[];
167
- getRowKey: (row: T, index: number) => React.Key;
168
- className?: string;
169
- onRowClick?: (row: T) => void;
170
- }): react.JSX.Element;
171
- /** Primary bold text + optional muted subtitle — for lead entity/name cells */
172
- declare function TableCellLeadText({ primary, secondary, }: {
173
- primary: string;
174
- secondary?: string;
175
- }): react.JSX.Element;
176
- /** Plain text cell — muted (secondary) by default, pass muted=false for primary colour */
177
- declare function TableCellText({ children, muted, }: {
178
- children: ReactNode;
179
- muted?: boolean;
180
- }): react.JSX.Element;
181
- /** Small outlined chip — Supplier / Customer, entity type labels etc. */
182
- declare function TableCellBadge({ label }: {
183
- label: string;
184
- }): react.JSX.Element;
185
- /** Coloured pill with a leading dot — pass explicit colours for full design-system flexibility */
186
- declare function TableCellStatusPill({ label, dotColor, backgroundColor, textColor, }: {
187
- label: string;
188
- dotColor: string;
189
- backgroundColor: string;
190
- textColor: string;
191
- }): react.JSX.Element;
192
- /** Mini horizontal progress bar with a percentage label below */
193
- declare function TableCellProgress({ percent, barColor, }: {
194
- percent: number;
195
- barColor?: string;
196
- }): react.JSX.Element;
197
-
198
- interface StatTileProps {
199
- label: string;
200
- value: string | number;
201
- dotColor?: string;
202
- className?: string;
203
- }
204
- declare function StatTile({ label, value, dotColor, className }: StatTileProps): react.JSX.Element;
205
-
156
+ type ToggleSize = 'sm' | 'md';
206
157
  interface ToggleProps {
207
158
  checked: boolean;
208
159
  onChange: (checked: boolean) => void;
160
+ /** Visible text beside the switch. Doubles as the accessible name. */
209
161
  label?: string;
162
+ /** Track size. `sm` is 36×20, `md` is 44×24. */
163
+ size?: ToggleSize;
210
164
  disabled?: boolean;
165
+ id?: string;
166
+ /** Accessible name when there is no visible `label`. */
167
+ 'aria-label'?: string;
168
+ /** Points at the id of an existing visible label elsewhere on the page. */
169
+ 'aria-labelledby'?: string;
170
+ className?: string;
211
171
  }
212
- declare function Toggle({ checked, onChange, label, disabled }: ToggleProps): react.JSX.Element;
172
+ declare function Toggle({ checked, onChange, label, size, disabled, id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, className, }: ToggleProps): react.JSX.Element;
213
173
 
214
174
  interface FileDropZoneProps {
215
175
  className?: string;
176
+ /** Caption shown under "Upload file". Defaults to the generic document hint. */
177
+ description?: string;
178
+ accept?: string;
179
+ /** Files above this size are rejected before any upload starts. */
180
+ maxSizeBytes?: number;
181
+ onFileSelected?: (file: File) => void;
182
+ disabled?: boolean;
216
183
  }
217
- declare function FileDropZone({ className }: FileDropZoneProps): react.JSX.Element;
184
+ declare function FileDropZone({ className, description, accept, maxSizeBytes, onFileSelected, disabled, }: FileDropZoneProps): react.JSX.Element;
218
185
 
219
186
  declare function FormCard({ children, className, }: {
220
187
  children: ReactNode;
@@ -231,37 +198,36 @@ interface FormCardFooterProps {
231
198
  onContinue?: () => void;
232
199
  continueLabel?: string;
233
200
  backDisabled?: boolean;
201
+ continueDisabled?: boolean;
234
202
  }
235
- declare function FormCardFooter({ onSaveDraft, onBack, onContinue, continueLabel, backDisabled, }: FormCardFooterProps): react.JSX.Element;
203
+ declare function FormCardFooter({ onSaveDraft, onBack, onContinue, continueLabel, backDisabled, continueDisabled, }: FormCardFooterProps): react.JSX.Element;
236
204
 
237
- type DocumentStatus = 'uploaded' | 'under-review' | 'processing' | 'missing' | 'not-provided';
238
- interface DocumentRowProps {
239
- title: string;
240
- required: boolean;
241
- description: string;
242
- status: DocumentStatus;
243
- fileName?: string;
244
- fileSize?: string;
245
- fileType?: string;
246
- }
247
- declare function DocumentRow({ title, required, description, status, fileName, fileSize, fileType, }: DocumentRowProps): react.JSX.Element;
248
-
249
- interface ModalProps {
250
- isOpen: boolean;
251
- onClose: () => void;
252
- title: string;
253
- subtitle?: string;
254
- children: ReactNode;
255
- footer?: ReactNode;
256
- maxWidth?: string;
205
+ type BadgeColor = 'gray' | 'red' | 'yellow' | 'lime' | 'green' | 'teal' | 'blue' | 'pink' | 'slate';
206
+ type BadgeSize = 'sm' | 'lg';
207
+ type BadgeVariant = 'default' | 'subtle';
208
+ interface BadgeProps {
209
+ label: string;
210
+ color?: BadgeColor;
211
+ size?: BadgeSize;
212
+ variant?: BadgeVariant;
213
+ indicator?: boolean;
214
+ onClose?: () => void;
215
+ className?: string;
257
216
  }
258
- declare function Modal({ isOpen, onClose, title, subtitle, children, footer, maxWidth }: ModalProps): react.JSX.Element | null;
217
+ declare function Badge({ label, color, size, variant, indicator, onClose, className, }: BadgeProps): react.JSX.Element;
259
218
 
260
219
  interface RoleBadgeProps {
261
220
  role: string;
262
221
  size?: 'sm' | 'md';
222
+ /**
223
+ * Explicit role colour as a solid 6-digit hex (e.g. `#0c2d58`). When set it drives
224
+ * the badge — text uses the hex and the background a light tint of it. Prefer this
225
+ * over relying on the built-in name map, which only covers a fixed set of English
226
+ * role names. Falls back to the name map, then grey.
227
+ */
228
+ color?: string | null;
263
229
  }
264
- declare function RoleBadge({ role, size }: RoleBadgeProps): react.JSX.Element;
230
+ declare function RoleBadge({ role, size, color }: RoleBadgeProps): react.JSX.Element;
265
231
 
266
232
  interface RoleOption {
267
233
  role: string;
@@ -275,26 +241,1471 @@ interface RoleComboBoxProps {
275
241
  }
276
242
  declare function RoleComboBox({ value, onChange, options }: RoleComboBoxProps): react.JSX.Element;
277
243
 
278
- declare function Panel({ children, className }: {
244
+ /**
245
+ * The six status tones from the Figma design system.
246
+ * Values live in `src/app/styles/tokens/status.css`; see that file for why they do
247
+ * not derive from the SDS semantic colour families.
248
+ */
249
+ type StatusTone = 'neutral' | 'info' | 'warning' | 'caution' | 'accent' | 'positive' | 'danger';
250
+ type StatusBadgeSize = 'sm' | 'md';
251
+ interface StatusBadgeProps {
252
+ label: string;
253
+ tone?: StatusTone;
254
+ size?: StatusBadgeSize;
255
+ /** Leading dot. On by default — the Figma status pills all carry one. */
256
+ dot?: boolean;
257
+ /**
258
+ * Leading glyph, replacing the dot — e.g. `<LuCheck className="size-3" />`.
259
+ * Use for states a colour alone under-states, like verified or rejected.
260
+ */
261
+ icon?: ReactNode;
262
+ className?: string;
263
+ }
264
+ /**
265
+ * The status pill.
266
+ *
267
+ * Replaces thirteen inline re-implementations of the same markup plus five
268
+ * competing hardcoded hex palettes. Generalises `TableCellStatusPill`, which had
269
+ * this exact markup but required callers to pass raw hex strings.
270
+ *
271
+ * Note this is NOT `StatusChip` — that one renders a label *and a count* and is a
272
+ * different component.
273
+ */
274
+ declare function StatusBadge({ label, tone, size, dot, icon, className, }: StatusBadgeProps): react.JSX.Element;
275
+
276
+ type StatusDotTone = 'brand' | 'positive' | 'warning' | 'danger' | 'neutral' | 'default';
277
+ interface StatusDotProps {
278
+ tone?: StatusDotTone;
279
+ /** @deprecated Bypasses the design tokens — pass `tone` instead. Raw hex color, overrides `tone` via inline style. Use when the exact source color doesn't match a design token. */
280
+ color?: string;
281
+ className?: string;
282
+ }
283
+ declare function StatusDot({ tone, color, className }: StatusDotProps): react.JSX.Element;
284
+
285
+ interface StatusChipProps {
286
+ label: string;
287
+ count: number | string;
288
+ tone?: StatusDotTone;
289
+ /** @deprecated Bypasses the design tokens — pass `tone` instead. Raw hex dot color, overrides `tone` via inline style. Use when the exact source color doesn't match a design token. */
290
+ dotColor?: string;
291
+ bg?: string;
292
+ className?: string;
293
+ }
294
+ declare function StatusChip({ label, count, tone, dotColor, bg, className }: StatusChipProps): react.JSX.Element;
295
+
296
+ interface CountBadgeProps {
297
+ count: number | string;
298
+ label?: string;
299
+ tone?: StatusDotTone;
300
+ className?: string;
301
+ }
302
+ declare function CountBadge({ count, label, tone, className }: CountBadgeProps): react.JSX.Element;
303
+
304
+ type TagPillTone = 'default' | 'brand' | 'positive' | 'warning' | 'danger';
305
+ interface TagPillProps {
306
+ label: string;
307
+ tone?: TagPillTone;
308
+ /** @deprecated Bypasses the design tokens — pass `tone` instead. Raw hex bg/text pair, overrides `tone` via inline style. Use when the exact source colors don't match design tokens. */
309
+ bg?: string;
310
+ color?: string;
311
+ className?: string;
312
+ }
313
+ declare function TagPill({ label, tone, bg, color, className }: TagPillProps): react.JSX.Element;
314
+
315
+ interface TrailChipProps {
316
+ label: string;
317
+ value: string;
318
+ tone?: StatusTone;
319
+ /**
320
+ * Data-driven dot colour, overriding `tone`. The investigations trail mirrors the
321
+ * severity accent of whichever tree node is selected, and those accents come from
322
+ * the row data rather than the status palette — this is the escape hatch Phase 10
323
+ * classifies as "genuinely data-driven colour", not a token bypass.
324
+ */
325
+ dotColor?: string;
326
+ className?: string;
327
+ }
328
+ /**
329
+ * Dot + small uppercase label + value, used for the drill-down breadcrumb trail on
330
+ * the investigations page.
331
+ *
332
+ * Promoted from `pages/investigations`, where the dot colour was passed as a raw hex.
333
+ */
334
+ declare function TrailChip({ label, value, tone, dotColor, className }: TrailChipProps): react.JSX.Element;
335
+
336
+ type UserAccountStatus = 'active' | 'pending' | 'deactivated';
337
+ interface UserStatusPillProps {
338
+ status: UserAccountStatus;
339
+ }
340
+ /** Account-status pill. A thin wrapper over `StatusBadge`. */
341
+ declare function UserStatusPill({ status }: UserStatusPillProps): react.JSX.Element;
342
+
343
+ /**
344
+ * States of a compliance check.
345
+ *
346
+ * Union of the two previously-divergent local unions:
347
+ * - `features/entity-detail` had passed | in_progress | pending | action_required
348
+ * - `features/reviewer-detail` had passed | in-progress | failed | pending | waived
349
+ *
350
+ * Note `in_progress` (underscore) is canonical — entity-detail's spelling, which is
351
+ * the one backed by the API. reviewer-detail used `in-progress` (hyphen) in mock data.
352
+ */
353
+ type CheckIndicatorStatus = 'passed' | 'in_progress' | 'action_required' | 'failed' | 'pending' | 'waived';
354
+ interface CheckIndicatorProps {
355
+ status: CheckIndicatorStatus;
356
+ /** Accessible label. Without one the indicator is decorative, which is correct when an adjacent text label already names the state. */
357
+ label?: string;
358
+ className?: string;
359
+ }
360
+ /**
361
+ * The 22px outlined circle used for compliance-check state in entity and reviewer
362
+ * detail. Ring and glyph share one colour; see the check tokens in
363
+ * `src/app/styles/tokens/status.css`.
364
+ */
365
+ declare function CheckIndicator({ status, label, className }: CheckIndicatorProps): react.JSX.Element;
366
+
367
+ type EntityIconBadgeSize = 'sm' | 'md';
368
+ type EntityIconBadgeTone = 'default' | 'brand' | 'positive' | 'warning' | 'danger' | 'neutral';
369
+ type EntityIconBadgeShape = 'square' | 'circle';
370
+ interface EntityIconBadgeProps {
371
+ size?: EntityIconBadgeSize;
372
+ tone?: EntityIconBadgeTone;
373
+ /**
374
+ * `square` is the rounded-rect used on entity rows. `circle` is the tinted glyph
375
+ * circle used in modal headers. A prop rather than a `className` override, so it
376
+ * does not depend on Tailwind's stylesheet emit order.
377
+ */
378
+ shape?: EntityIconBadgeShape;
379
+ /** @deprecated Bypasses the design tokens — pass `tone` instead. Raw hex background, overrides `tone` via inline style. Use when the exact source color doesn't match a design token. */
380
+ bg?: string;
381
+ iconColor?: string;
279
382
  children: ReactNode;
280
383
  className?: string;
281
- }): react.JSX.Element;
282
- declare function MetricCard({ label, value, tone }: {
384
+ }
385
+ declare function EntityIconBadge({ size, tone, shape, bg, iconColor, children, className }: EntityIconBadgeProps): react.JSX.Element;
386
+
387
+ interface CheckboxProps {
388
+ checked: boolean;
389
+ onChange: (checked: boolean) => void;
390
+ label?: ReactNode;
391
+ disabled?: boolean;
392
+ indeterminate?: boolean;
393
+ className?: string;
394
+ }
395
+ /** Checkbox built on a real `<input type="checkbox">` — the hand-rolled `<div onClick>` version
396
+ * this replaces was not keyboard-reachable and exposed no checked state to assistive tech. */
397
+ declare function Checkbox({ checked, onChange, label, disabled, indeterminate, className, }: CheckboxProps): react.JSX.Element;
398
+
399
+ interface SegmentedControlOption {
400
+ value: string;
401
+ label: string;
402
+ }
403
+ interface SegmentedControlProps {
404
+ options: SegmentedControlOption[];
405
+ value: string;
406
+ onChange?: (value: string) => void;
407
+ className?: string;
408
+ }
409
+ declare function SegmentedControl({ options, value, onChange, className }: SegmentedControlProps): react.JSX.Element;
410
+
411
+ type ModalSize = 'sm' | 'md' | 'lg' | 'xl';
412
+ /**
413
+ * Note `positive`, not `success` — every other tone union in the library
414
+ * (`InlineAlertTone`, `TagPillTone`, `EntityIconBadgeTone`) and the token layer say
415
+ * `positive`, and one vocabulary beats a familiar synonym.
416
+ */
417
+ type ModalTone = 'default' | 'info' | 'positive' | 'warning' | 'danger';
418
+ type ModalFooterAlign = 'start' | 'between' | 'end';
419
+ interface ModalProps {
420
+ isOpen: boolean;
421
+ onClose: () => void;
422
+ /**
423
+ * Accessible name for the dialog. Required, so a slot-composed modal can never ship
424
+ * unnamed. Was `title` in 0.2.0, renamed because `title` is also an HTML attribute
425
+ * that renders a tooltip.
426
+ */
427
+ label: string;
428
+ children: ReactNode;
429
+ size?: ModalSize;
430
+ /** Renders the top-right close button. */
431
+ showClose?: boolean;
432
+ /** Applied to the panel. With `cn`, `className="sm:max-w-[560px]"` beats `size`. */
433
+ className?: string;
434
+ }
435
+ /**
436
+ * A centred dialog above `sm`, a bottom sheet below it.
437
+ *
438
+ * Composed from `ModalHeader` / `ModalBody` / `ModalFooter`, mirroring the `Card`
439
+ * parts — so a modal can take any layout a card can, including headerless. Tone lives
440
+ * on `ModalHeader` (the part that draws the glyph); `ConfirmDialog` and
441
+ * `NoteConfirmModal` accept `tone` at their top level and forward it.
442
+ */
443
+ declare function Modal(props: ModalProps): react.JSX.Element | null;
444
+ interface ModalHeaderProps extends HTMLAttributes<HTMLDivElement> {
445
+ children: ReactNode;
446
+ /** Adds a tinted glyph circle. `default` renders none. */
447
+ tone?: ModalTone;
448
+ divider?: boolean;
449
+ }
450
+ declare function ModalHeader({ children, tone, divider, className, ...rest }: ModalHeaderProps): react.JSX.Element;
451
+ interface ModalTitleProps extends HTMLAttributes<HTMLHeadingElement> {
452
+ children: ReactNode;
453
+ }
454
+ declare function ModalTitle({ children, className, ...rest }: ModalTitleProps): react.JSX.Element;
455
+ interface ModalDescriptionProps extends HTMLAttributes<HTMLParagraphElement> {
456
+ children: ReactNode;
457
+ }
458
+ declare function ModalDescription({ children, className, ...rest }: ModalDescriptionProps): react.JSX.Element;
459
+ interface ModalBodyProps extends HTMLAttributes<HTMLDivElement> {
460
+ children: ReactNode;
461
+ }
462
+ /** Must not carry its own `overflow` — the panel is the scroll container. */
463
+ declare function ModalBody({ children, className, ...rest }: ModalBodyProps): react.JSX.Element;
464
+ interface ModalFooterProps extends HTMLAttributes<HTMLDivElement> {
465
+ children: ReactNode;
466
+ align?: ModalFooterAlign;
467
+ divider?: boolean;
468
+ }
469
+ declare function ModalFooter({ children, align, divider, className, ...rest }: ModalFooterProps): react.JSX.Element;
470
+
471
+ interface DrawerProps {
472
+ /** Required as of 0.3.0 — every overlay is now `isOpen` + `onClose`. */
473
+ isOpen: boolean;
474
+ onClose: () => void;
475
+ /** Header content (left side). The copies this replaces differ only here — a status badge +
476
+ * title in one, an avatar + title + category in another — so it is a slot, not props. */
477
+ header: ReactNode;
478
+ children: ReactNode;
479
+ footer?: ReactNode;
480
+ /** `between` when the footer has a left-aligned secondary action. */
481
+ footerAlign?: 'end' | 'between';
482
+ /** Panel width. Defaults to the `w-[440px] max-w-[90vw]` shared by every existing drawer. */
483
+ width?: string;
484
+ /** Accessible name for the dialog. */
485
+ label?: string;
486
+ className?: string;
487
+ }
488
+ /**
489
+ * Right-hand side panel. Handles Esc, traps Tab focus, and restores focus to the
490
+ * trigger on close.
491
+ */
492
+ declare function Drawer(props: DrawerProps): react.JSX.Element | null;
493
+
494
+ interface ConfirmDialogProps {
495
+ isOpen: boolean;
496
+ title: string;
497
+ subtitle?: string;
498
+ /**
499
+ * Adds a tinted glyph to the header. Defaults to `default` (no glyph) so existing
500
+ * call sites look unchanged; opt in per dialog rather than deriving it from
501
+ * `confirmVariant`, which would silently restyle every destructive confirm.
502
+ */
503
+ tone?: ModalTone;
504
+ size?: ModalSize;
505
+ confirmLabel?: string;
506
+ cancelLabel?: string;
507
+ confirmVariant?: 'primary' | 'danger';
508
+ /** Disables the confirm button and swaps its label — the double-submit guard. */
509
+ isConfirming?: boolean;
510
+ /** Label shown on the confirm button while `isConfirming`. */
511
+ confirmingLabel?: string;
512
+ /** Optional body — a warning callout, a consequences list, or a failed-attempt error. */
513
+ children?: ReactNode;
514
+ className?: string;
515
+ onConfirm: () => void;
516
+ /** Renamed from `onCancel` in 0.3.0 — every overlay now uses `isOpen` + `onClose`. */
517
+ onClose: () => void;
518
+ }
519
+ /**
520
+ * The in-app replacement for `window.confirm`: a title, an optional body, and a
521
+ * cancel/confirm pair.
522
+ *
523
+ * Kept as a preset rather than folded into `Modal` because it carries *behaviour*, not
524
+ * just layout — the `isConfirming` guard that disables the button and swaps its label
525
+ * is the thing call sites get wrong when they hand-roll a confirm. For any other
526
+ * shape, compose `Modal` and its parts directly.
527
+ */
528
+ declare function ConfirmDialog({ isOpen, title, subtitle, tone, size, confirmLabel, cancelLabel, confirmVariant, isConfirming, confirmingLabel, children, className, onConfirm, onClose, }: ConfirmDialogProps): react.JSX.Element;
529
+
530
+ interface NoteConfirmModalProps {
531
+ /** Required as of 0.3.0 — this is now a controlled overlay like every other. */
532
+ isOpen: boolean;
533
+ title: string;
534
+ subtitle?: string;
535
+ tone?: ModalTone;
536
+ size?: ModalSize;
537
+ confirmLabel: string;
538
+ cancelLabel?: string;
539
+ confirmVariant?: 'primary' | 'danger';
540
+ /** Block confirmation until the note has content. */
541
+ requireNote?: boolean;
542
+ notePlaceholder?: string;
543
+ submittingLabel?: string;
544
+ isSubmitting?: boolean;
545
+ className?: string;
546
+ onClose: () => void;
547
+ onConfirm: (note: string) => void;
548
+ }
549
+ /**
550
+ * Confirm dialog that collects a free-text note — approvals, rejections, information
551
+ * requests. The note is trimmed before it reaches `onConfirm`.
552
+ *
553
+ * Kept as a preset because it owns state, and a composition cannot.
554
+ */
555
+ declare function NoteConfirmModal({ isOpen, ...rest }: NoteConfirmModalProps): react.JSX.Element | null;
556
+
557
+ interface DropdownMenuItem {
558
+ label: string;
559
+ onSelect: () => void;
560
+ tone?: 'default' | 'danger';
561
+ disabled?: boolean;
562
+ /** Draw a separator above this item. */
563
+ separatorBefore?: boolean;
564
+ }
565
+ interface DropdownMenuProps {
566
+ items: DropdownMenuItem[];
567
+ /** Custom trigger content. Defaults to a `⋯` overflow button. */
568
+ trigger?: ReactNode;
569
+ /** Accessible name for the trigger, e.g. `Open actions for Admin`. */
570
+ label: string;
571
+ align?: 'left' | 'right';
572
+ className?: string;
573
+ }
574
+ /** Overflow / row-actions menu.
575
+ *
576
+ * Keeps the outside-click dismissal and `aria-haspopup`/`aria-expanded` wiring from the
577
+ * hand-rolled `RowMenu` it replaces, and adds Esc-to-close. `mousedown` is stopped at the
578
+ * wrapper so the menu works inside clickable table rows. */
579
+ declare function DropdownMenu({ items, trigger, label, align, className, }: DropdownMenuProps): react.JSX.Element;
580
+
581
+ /** The one scrim for every overlay primitive.
582
+ *
583
+ * Modal and Drawer both reference this constant, so there is a single place to change
584
+ * the dimming behind a dialog. Backed by `--color-background-utilities-overlay`. */
585
+ declare const OVERLAY_SCRIM = "bg-overlay";
586
+ /** Esc-to-close, a Tab focus trap, and focus restore for a mounted overlay.
587
+ *
588
+ * None of the hand-rolled drawers/modals this replaces handled Esc or trapped focus —
589
+ * they closed on scrim click only. Pass the ref of the panel element (not the scrim). */
590
+ declare function useOverlayDismiss(onClose: () => void, panelRef: RefObject<HTMLElement | null>): void;
591
+
592
+ /**
593
+ * `clsx` + `tailwind-merge`.
594
+ *
595
+ * Use this instead of bare `clsx` in any component whose `className` prop is meant to
596
+ * *override* a base utility — the composable `Card*` and `Modal*` parts, and anything
597
+ * else built to be reshaped by its caller.
598
+ *
599
+ * Why it is necessary: `clsx` only concatenates. When two conflicting Tailwind
600
+ * utilities both end up in the attribute, the winner is decided by *stylesheet order*,
601
+ * not attribute order. Tailwind emits `flex-row` before `flex-col` and `gap-3` before
602
+ * `gap-4`, so under plain `clsx`:
603
+ *
604
+ * <CardBody className="flex-row gap-3" /> // base is 'flex flex-col gap-4 p-4'
605
+ *
606
+ * silently stays a column with a 4-unit gap. `twMerge` drops the losing class instead,
607
+ * so the caller's intent wins.
608
+ *
609
+ * Everywhere else in the library `className` is purely additive, and plain `clsx`
610
+ * remains correct — and cheaper. Do not sweep it out of those files.
611
+ */
612
+ declare function cn(...inputs: ClassValue[]): string;
613
+
614
+ type CardSize = 'sm' | 'md' | 'lg';
615
+ type CardRadius = 'lg' | 'xl' | '2xl';
616
+ type CardTone = 'default' | 'brand' | 'positive' | 'warning' | 'danger';
617
+ type CardFooterAlign = 'start' | 'between' | 'end';
618
+ interface CardProps extends HTMLAttributes<HTMLDivElement> {
619
+ children: ReactNode;
620
+ /** `2xl` suits detail pages, `xl` section panels, `lg` dense or nested cards. */
621
+ radius?: CardRadius;
622
+ /**
623
+ * Surface tint. This is a prop rather than a `className` because a tone has to
624
+ * un-set the base `border-default bg-default` pair, not add to it.
625
+ */
626
+ tone?: CardTone;
627
+ }
628
+ /**
629
+ * The card shell. Composed from `CardHeader`, `CardBody` and `CardFooter` — or from
630
+ * nothing at all, if you want content to bleed to the edges (drop `CardBody` and put
631
+ * a `DataTable` straight inside).
632
+ *
633
+ * Replaces `SectionCard` and the two monolithic cards that shipped beside it,
634
+ * `AlertCard` and `BenchmarkCard`. Both of those are now documented compositions; see
635
+ * the Cards page. The vocabulary follows shadcn/ui so it is already familiar, with
636
+ * `CardBody` in place of its `CardContent`.
637
+ */
638
+ declare function Card({ children, radius, tone, className, ...rest }: CardProps): react.JSX.Element;
639
+ interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {
640
+ children: ReactNode;
641
+ size?: CardSize;
642
+ /** Bottom rule separating the header from the body. */
643
+ divider?: boolean;
644
+ }
645
+ /**
646
+ * Header row. Holds `CardTitle`, `CardDescription` and an optional `CardAction`.
647
+ *
648
+ * The `has-[…]` selector switches to a two-column grid only when a `CardAction` is
649
+ * present, which is what lets title, description and action share a header with no
650
+ * wrapper div and no stray gap when the action is absent.
651
+ */
652
+ declare function CardHeader({ children, size, divider, className, ...rest }: CardHeaderProps): react.JSX.Element;
653
+ interface CardTitleProps extends HTMLAttributes<HTMLElement> {
654
+ children: ReactNode;
655
+ size?: CardSize;
656
+ /** Heading level. Defaults to `p`; use h2/h3 where the page has a real hierarchy. */
657
+ as?: 'h2' | 'h3' | 'h4' | 'p';
658
+ }
659
+ declare function CardTitle({ children, size, as: Tag, className, ...rest }: CardTitleProps): react.JSX.Element;
660
+ interface CardDescriptionProps extends HTMLAttributes<HTMLParagraphElement> {
661
+ children: ReactNode;
662
+ }
663
+ declare function CardDescription({ children, className, ...rest }: CardDescriptionProps): react.JSX.Element;
664
+ interface CardActionProps extends HTMLAttributes<HTMLDivElement> {
665
+ children: ReactNode;
666
+ }
667
+ /** Right-hand slot in a `CardHeader` — a button, a count, a status badge, a menu. */
668
+ declare function CardAction({ children, className, ...rest }: CardActionProps): react.JSX.Element;
669
+ interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {
670
+ children: ReactNode;
671
+ size?: CardSize;
672
+ }
673
+ /**
674
+ * The content region. A vertical stack by default.
675
+ *
676
+ * Because this file uses `cn`, `className` genuinely overrides the base — so
677
+ * `className="flex-row items-center"` gives you a row, and
678
+ * `className="grid grid-cols-3"` a grid. That is what makes the `AlertCard` and
679
+ * `BenchmarkCard` rebuilds possible without a `layout` prop.
680
+ */
681
+ declare function CardBody({ children, size, className, ...rest }: CardBodyProps): react.JSX.Element;
682
+ interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {
683
+ children: ReactNode;
684
+ size?: CardSize;
685
+ divider?: boolean;
686
+ align?: CardFooterAlign;
687
+ }
688
+ /** Action row at the foot of a card. Mirrors `ModalFooter` and `Drawer`'s footer. */
689
+ declare function CardFooter({ children, size, divider, align, className, ...rest }: CardFooterProps): react.JSX.Element;
690
+
691
+ /**
692
+ * Two genuinely different heading contexts, which the source markup distinguished:
693
+ *
694
+ * `page` 24px title / 14px subtitle — an in-body page heading (settings, users,
695
+ * alerts), i.e. the old `text-2xl` + `mt-1 text-body-sm` block.
696
+ * `toolbar` 20px title / 13px subtitle — inside a `PageToolbar`, where the bar is
697
+ * only 72px tall. Flattening these into one size would have grown ten
698
+ * toolbar titles by 4px.
699
+ * `section` 18px — a panel or card heading.
700
+ */
701
+ type PageHeadingSize = 'page' | 'toolbar' | 'section';
702
+ interface PageHeadingProps {
703
+ title: ReactNode;
704
+ subtitle?: ReactNode;
705
+ size?: PageHeadingSize;
706
+ /** Heading level. Defaults to `h1` for page/toolbar and `h2` for section. */
707
+ as?: 'h1' | 'h2' | 'h3';
708
+ /** Right-aligned action cluster. When set, the heading becomes a flex row. */
709
+ actions?: ReactNode;
710
+ /** Clamp a long title to one line — needed when the title is user data, e.g. an article headline. */
711
+ truncateTitle?: boolean;
712
+ className?: string;
713
+ }
714
+ /**
715
+ * Page or section title with an optional subtitle underneath.
716
+ *
717
+ * Replaces nine copies of the `<h1>` + `<p className="mt-1 …">` block, plus the
718
+ * heading halves of `SettingsTabs` and `my-account/tabs`.
719
+ *
720
+ * Emitting a real heading element matters: `reviewer-detail`,
721
+ * `settings-audit-log`'s table area and `widget-gallery` render their titles as
722
+ * `<p>`/`<div>` today, so `getByRole('heading')` finds nothing there — an
723
+ * accessibility gap the e2e specs currently work around.
724
+ */
725
+ declare function PageHeading({ title, subtitle, size, as, actions, truncateTitle, className, }: PageHeadingProps): react.JSX.Element;
726
+
727
+ type PageToolbarSize = 'sm' | 'md';
728
+ interface PageToolbarProps {
729
+ children: ReactNode;
730
+ /** Allow the row to wrap when the action cluster is wide (entity-detail has seven buttons). */
731
+ wrap?: boolean;
732
+ /** Bar height and padding. `sm` suits a secondary bar under the main toolbar. */
733
+ size?: PageToolbarSize;
734
+ className?: string;
735
+ }
736
+ /**
737
+ * The sticky top bar on a full-bleed detail or list screen: title block on the
738
+ * left, actions on the right.
739
+ *
740
+ * Replaces ten copies of this class string. Three of those copies used the
741
+ * responsive `px-4 py-4 md:px-7` and seven used a fixed `px-7 py-4`; the responsive
742
+ * variant is adopted here, which is a deliberate improvement below `md` where the
743
+ * fixed 28px padding was cramped.
744
+ */
745
+ declare function PageToolbar({ children, wrap, size, className }: PageToolbarProps): react.JSX.Element;
746
+
747
+ type FilterBarSize = 'sm' | 'md';
748
+ interface FilterBarProps {
749
+ children: ReactNode;
750
+ /** Right-aligned slot for a result count or a secondary action. */
751
+ trailing?: ReactNode;
752
+ /** Gap between controls. `sm` for a filter row inside a card or drawer. */
753
+ size?: FilterBarSize;
754
+ className?: string;
755
+ }
756
+ /**
757
+ * Row of search inputs and filter selects above a table.
758
+ *
759
+ * Replaces nine copies of `flex flex-wrap items-center gap-3`. Thin by design — the
760
+ * value is that the spacing is decided once, not that it hides anything.
761
+ */
762
+ declare function FilterBar({ children, trailing, size, className }: FilterBarProps): react.JSX.Element;
763
+
764
+ type TabsVariant = 'underline' | 'pill';
765
+ type TabsSize = 'sm' | 'md';
766
+ interface TabItem<K extends string = string> {
767
+ key: K;
768
+ label: string;
769
+ /** Renders a count chip after the label. */
770
+ count?: number;
771
+ }
772
+ interface TabsProps<K extends string = string> {
773
+ items: TabItem<K>[];
774
+ value: K;
775
+ onChange: (key: K) => void;
776
+ /**
777
+ * `underline` is the detail-page form (entity detail, reviewer detail, role detail).
778
+ * `pill` is the filter-style form used by the reviewer queue.
779
+ */
780
+ variant?: TabsVariant;
781
+ /** `md` is the page-level strip; `sm` suits a tab strip inside a card or drawer. */
782
+ size?: TabsSize;
783
+ className?: string;
784
+ }
785
+ /**
786
+ * State-driven tab strip.
787
+ *
788
+ * The `underline` active colour is `background-brand` (#0C2D58), which is what Figma
789
+ * specifies. Two of the source copies also set `style={{ borderColor: '#0c2d58' }}`
790
+ * redundantly next to the same Tailwind class — dropped here.
791
+ */
792
+ declare function Tabs<K extends string = string>({ items, value, onChange, variant, size, className, }: TabsProps<K>): react.JSX.Element;
793
+
794
+ type NavItemSize = 'sm' | 'md';
795
+ interface NavItemProps {
796
+ icon?: ReactNode;
797
+ label: string;
798
+ isActive?: boolean;
799
+ /** Red indicator dot at top-right corner (e.g. unread count) */
800
+ indicator?: boolean;
801
+ /** Collapsed mode — icon only, label hidden */
802
+ collapsed?: boolean;
803
+ /** Row height. `sm` suits a dense secondary nav or a nested group. */
804
+ size?: NavItemSize;
805
+ className?: string;
806
+ }
807
+ declare function NavItem({ icon, label, isActive, indicator, collapsed, size, className, }: NavItemProps): react.JSX.Element;
808
+
809
+ type EyebrowLabelVariant = 'uppercase' | 'plain';
810
+ interface EyebrowLabelProps {
811
+ children: ReactNode;
812
+ /**
813
+ * `uppercase` is the dominant form (nine of twelve source copies).
814
+ * `plain` covers the entity-detail / reviewer-detail variant, whose label text is
815
+ * already capitalised in the source string.
816
+ */
817
+ variant?: EyebrowLabelVariant;
818
+ className?: string;
819
+ }
820
+ /**
821
+ * Small semibold label above a group of fields.
822
+ *
823
+ * Replaces twelve copies across three variants:
824
+ * `mb-2 text-body-tiny font-semibold uppercase tracking-wide …` (×9)
825
+ * `text-[11px] font-semibold … tracking-wide` (×5, entity/reviewer detail)
826
+ * `text-body-tiny font-semibold uppercase tracking-wider` (×2, entity onboarding)
827
+ *
828
+ * `text-body-tiny` is 11px, so the `text-[11px]` variant collapses into it exactly.
829
+ * The `tracking-wider` copies become `tracking-wide` — a 0.0125em difference at 11px,
830
+ * i.e. sub-pixel.
831
+ */
832
+ declare function EyebrowLabel({ children, variant, className }: EyebrowLabelProps): react.JSX.Element;
833
+
834
+ type WidgetTitleSize = 'sm' | 'md' | 'lg';
835
+ interface WidgetTitleProps {
836
+ children: ReactNode;
837
+ size?: WidgetTitleSize;
838
+ className?: string;
839
+ }
840
+ declare function WidgetTitle({ children, size, className }: WidgetTitleProps): react.JSX.Element;
841
+
842
+ type WidgetHeaderEyebrowVariant = 'uppercase' | 'plain';
843
+ interface WidgetHeaderProps {
844
+ eyebrow?: string;
845
+ eyebrowVariant?: WidgetHeaderEyebrowVariant;
846
+ title: string;
847
+ titleSize?: WidgetTitleSize;
848
+ subtitle?: string;
849
+ badge?: ReactNode;
850
+ action?: ReactNode;
851
+ className?: string;
852
+ }
853
+ declare function WidgetHeader({ eyebrow, eyebrowVariant, title, titleSize, subtitle, badge, action, className, }: WidgetHeaderProps): react.JSX.Element;
854
+
855
+ interface WidgetFooterProps {
856
+ caption?: string;
857
+ subcaption?: string;
858
+ action?: ReactNode;
859
+ className?: string;
860
+ }
861
+ declare function WidgetFooter({ caption, subcaption, action, className }: WidgetFooterProps): react.JSX.Element;
862
+
863
+ interface StatTileProps {
283
864
  label: string;
284
865
  value: string | number;
285
- tone?: 'default' | 'signal' | 'ember' | 'moss';
286
- }): react.JSX.Element;
287
- declare function SeverityBadge({ severity }: {
288
- severity?: string | null;
289
- }): react.JSX.Element;
290
- declare function SentimentBadge({ sentiment }: {
291
- sentiment?: string | null;
292
- }): react.JSX.Element;
866
+ /** Status tone for the leading dot. Prefer this over `dotColor`. */
867
+ tone?: StatusTone;
868
+ /**
869
+ * @deprecated Pass `tone` instead. A raw colour here bypasses the token layer,
870
+ * which is how competing status palettes drift apart.
871
+ */
872
+ dotColor?: string;
873
+ className?: string;
874
+ }
875
+ declare function StatTile({ label, value, tone, dotColor, className }: StatTileProps): react.JSX.Element;
876
+
877
+ type StatNumberSize = 'sm' | 'md' | 'lg';
878
+ type StatNumberWeight = 'medium' | 'bold';
879
+ interface StatNumberProps {
880
+ value: string | number;
881
+ unit?: string;
882
+ size?: StatNumberSize;
883
+ weight?: StatNumberWeight;
884
+ /** @deprecated Bypasses the design tokens — pass `tone` instead. Raw hex color, overrides the default text color via inline style. Use when the exact source color doesn't match a design token. */
885
+ color?: string;
886
+ className?: string;
887
+ }
888
+ declare function StatNumber({ value, unit, size, weight, color, className }: StatNumberProps): react.JSX.Element;
889
+
890
+ type ScoreValueSize = 'sm' | 'md' | 'lg' | 'xl' | '2xl';
891
+ type ScoreValueWeight = 'normal' | 'semibold' | 'bold';
892
+ type ScoreTone = 'brand' | 'positive' | 'warning' | 'danger' | 'neutral' | 'default';
893
+ type ScoreValueTone = ScoreTone | 'auto';
894
+ /**
895
+ * The four tones the automatic ramp can produce.
896
+ *
897
+ * Narrower than `ScoreTone` on purpose: a ramp position is always one of these, so the
898
+ * result is directly assignable to `ProgressBarTone` too — which is what lets a caller
899
+ * tone a bar and its score from one `getScoreTone` call.
900
+ */
901
+ type ScoreRampTone = 'positive' | 'neutral' | 'warning' | 'danger';
902
+ /** Which end of the scale is the bad end. */
903
+ type ScoreDirection = 'higher-is-worse' | 'higher-is-better';
904
+ interface ScoreThresholds {
905
+ /** At or above this, the score is `danger`. */
906
+ danger: number;
907
+ /** At or above this, `warning`. */
908
+ warning: number;
909
+ /** At or above this, `neutral`. Below it, `positive`. */
910
+ neutral: number;
911
+ }
912
+ /**
913
+ * Default ramp, on a 0–100 scale read as "higher is worse" — the risk case.
914
+ *
915
+ * 0.2.0's ramp had only four stops and resolved 65–79 to `brand` (the blue brand
916
+ * colour), which left `warning` and `positive` unreachable without passing `tone`
917
+ * by hand. This is a real five-stop ramp.
918
+ */
919
+ declare const DEFAULT_SCORE_THRESHOLDS: ScoreThresholds;
920
+ /**
921
+ * Resolve a numeric score to a tone.
922
+ *
923
+ * Was `getRiskTone` in 0.2.0, with the thresholds and the direction both hardcoded.
924
+ */
925
+ declare function getScoreTone(score: number, { direction, thresholds, }?: {
926
+ direction?: ScoreDirection;
927
+ thresholds?: ScoreThresholds;
928
+ }): ScoreRampTone;
929
+ interface ScoreValueProps {
930
+ value: string | number;
931
+ /** Trailing caption — `/100`, `High`, `of target`. */
932
+ label?: string;
933
+ size?: ScoreValueSize;
934
+ weight?: ScoreValueWeight;
935
+ /** `auto` derives the tone from `value` via {@link getScoreTone}. */
936
+ tone?: ScoreValueTone;
937
+ direction?: ScoreDirection;
938
+ thresholds?: ScoreThresholds;
939
+ className?: string;
940
+ }
941
+ /**
942
+ * A scored number with an optional caption and a tone that can track its value.
943
+ *
944
+ * Was `RiskScore`. Nothing about it was ever risk-specific except the name and the
945
+ * direction of its ramp, so both are now parameters: use it for a risk score, a
946
+ * compliance score, a match confidence, a utilisation percentage.
947
+ *
948
+ * Not to be confused with `StatNumber`, which is the *large display* number with a
949
+ * unit (32–48px, for tiles and widget headlines). `ScoreValue` is the inline one with
950
+ * a label and a tone ramp.
951
+ */
952
+ declare function ScoreValue({ value, label, size, weight, tone, direction, thresholds, className, }: ScoreValueProps): react.JSX.Element;
953
+
954
+ type TileGridColumns = 2 | 3 | 4 | 5 | 6;
955
+ /**
956
+ * Responsive column counts. Every source copy started two-up on mobile and stepped
957
+ * to its full count at one breakpoint.
958
+ *
959
+ * The twelve source grids disagreed on which: seven used `lg:`, three used `md:`.
960
+ * Standardising on `lg:` matches eight of them byte-for-byte and is the safer choice
961
+ * — five tiles at `md` (768px) was cramped. `alerts`, `settings-users` and
962
+ * `settings-organization` therefore stay two-up slightly longer on tablets than
963
+ * before; that is the one deliberate layout change here.
964
+ *
965
+ * Six keeps its intermediate `sm:grid-cols-3` step, matching entities-listing —
966
+ * without it, six tiles would stack 2×3 on tablet instead of 3×2.
967
+ */
968
+ type TileGridBreakpoint = 'sm' | 'md' | 'lg';
969
+ interface TileGridProps {
970
+ children: ReactNode;
971
+ columns?: TileGridColumns;
972
+ /**
973
+ * Breakpoint at which the grid reaches its full column count. `lg` is the default
974
+ * and correct for a full-width page. Narrow contexts — a stat row inside a panel,
975
+ * as on the article detail page — legitimately need `sm`.
976
+ */
977
+ at?: TileGridBreakpoint;
978
+ className?: string;
979
+ }
980
+ /**
981
+ * A responsive grid of equal-width tiles.
982
+ *
983
+ * Was `StatTileGrid`, which read as a `StatTile`-specific component. It has never been
984
+ * coupled to one: no context, no cloning, no constraint on `children`. It takes any
985
+ * nodes — `StatTile`s, `Card`s, chart tiles — and only owns the column counts and the
986
+ * `gap-3`. The rename says so.
987
+ */
988
+ declare function TileGrid({ children, columns, at, className, }: TileGridProps): react.JSX.Element;
989
+
990
+ /**
991
+ * Chart colour.
992
+ *
993
+ * SVG paints via the `stroke` / `fill` *attributes*, which cannot take a Tailwind
994
+ * class — so charts resolve a `tone` to a CSS variable reference instead of a utility.
995
+ * That keeps them on the token layer; 0.2.0's charts defaulted to raw hex (`#0c2d58`,
996
+ * `rgba(140,155,176,0.5)`) and drifted from it.
997
+ *
998
+ * Every chart still accepts an explicit `color` string for genuinely data-driven
999
+ * colour — a series whose colour comes from the data, not from semantics.
1000
+ */
1001
+ type ChartTone = 'brand' | 'info' | 'positive' | 'warning' | 'danger' | 'neutral';
1002
+ declare const CHART_TONE: Record<ChartTone, string>;
1003
+ /** The muted track/rest colour behind a highlighted series. */
1004
+ declare const CHART_TRACK = "var(--color-background-default-tertiary)";
1005
+ /**
1006
+ * Ordered sequence for multi-series charts, so two donuts in the same product never
1007
+ * assign different colours to the same first category. Semantic tones come first
1008
+ * because a chart with two or three series is usually still saying something.
1009
+ */
1010
+ declare const CHART_SEQUENCE: ChartTone[];
1011
+ /** Resolve an explicit colour, else a tone, else the sequence position. */
1012
+ declare function resolveChartColor(color: string | undefined, tone: ChartTone | undefined, index?: number): string;
1013
+
1014
+ type BarChartOrientation = 'vertical' | 'horizontal';
1015
+ type BarChartSize = 'sm' | 'md' | 'lg';
1016
+ interface BarChartSeries {
1017
+ label: string;
1018
+ /** One value per category. */
1019
+ values: number[];
1020
+ tone?: ChartTone;
1021
+ color?: string;
1022
+ }
1023
+ interface BarChartProps {
1024
+ /** Category names — the axis labels. */
1025
+ categories: string[];
1026
+ series: BarChartSeries[];
1027
+ orientation?: BarChartOrientation;
1028
+ /** Stack series on top of each other instead of placing them side by side. */
1029
+ stacked?: boolean;
1030
+ size?: BarChartSize;
1031
+ /** Overall length of the value axis, in px. */
1032
+ length?: number;
1033
+ /** Show the category labels along the axis. */
1034
+ showLabels?: boolean;
1035
+ /** Print each bar's value at the end of the bar. Horizontal orientation only. */
1036
+ showValues?: boolean;
1037
+ radius?: number;
1038
+ label?: string;
1039
+ className?: string;
1040
+ }
1041
+ /**
1042
+ * Grouped or stacked bars, in either orientation.
1043
+ *
1044
+ * Horizontal is the orientation the library was missing and the one that actually suits
1045
+ * category data, because long category names get a full line of width rather than being
1046
+ * rotated or truncated under a vertical bar.
1047
+ *
1048
+ * Deliberately axis-light: one baseline, no gridlines, no ticks. For anything needing
1049
+ * real axes or interaction, this is the wrong component.
1050
+ */
1051
+ declare function BarChart({ categories, series, orientation, stacked, size, length, showLabels, showValues, radius, label, className, }: BarChartProps): react.JSX.Element | null;
1052
+
1053
+ type DonutChartSize = 'sm' | 'md' | 'lg';
1054
+ interface DonutSegment {
1055
+ label: string;
1056
+ value: number;
1057
+ /** Token-backed colour. Falls back to the segment's position in the chart sequence. */
1058
+ tone?: ChartTone;
1059
+ /** Explicit colour, for data-driven series. */
1060
+ color?: string;
1061
+ }
1062
+ interface DonutChartProps {
1063
+ segments: DonutSegment[];
1064
+ size?: DonutChartSize;
1065
+ /** Ring thickness in px. Overrides the `size` preset. */
1066
+ thickness?: number;
1067
+ /** Large text at the centre — a total, a percentage. */
1068
+ centerValue?: ReactNode;
1069
+ /** Caption beneath `centerValue`. */
1070
+ centerLabel?: ReactNode;
1071
+ /** Gap between segments, in degrees. */
1072
+ gap?: number;
1073
+ /** Accessible description. */
1074
+ label?: string;
1075
+ className?: string;
1076
+ }
1077
+ /**
1078
+ * A proportional ring.
1079
+ *
1080
+ * Drawn with `stroke-dasharray` on circles rather than arc paths: one element per
1081
+ * segment, no trigonometry, and the segments stay crisp at any thickness.
1082
+ */
1083
+ declare function DonutChart({ segments, size, thickness, centerValue, centerLabel, gap, label, className, }: DonutChartProps): react.JSX.Element;
1084
+
1085
+ type RadialGaugeSize = 'sm' | 'md' | 'lg';
1086
+ interface RadialGaugeProps {
1087
+ value: number;
1088
+ /** Top of the scale. */
1089
+ max?: number;
1090
+ size?: RadialGaugeSize;
1091
+ tone?: ChartTone;
1092
+ color?: string;
1093
+ /** Ring thickness in px. Overrides the `size` preset. */
1094
+ thickness?: number;
1095
+ /**
1096
+ * Sweep in degrees. 360 is a full ring; 270 leaves a gap at the bottom, which reads
1097
+ * more like a dial than a pie.
1098
+ */
1099
+ sweep?: number;
1100
+ /** Centre content. Defaults to the value; pass `null` for an empty ring. */
1101
+ children?: ReactNode;
1102
+ /** Caption beneath the centre value. */
1103
+ centerLabel?: ReactNode;
1104
+ label?: string;
1105
+ className?: string;
1106
+ }
1107
+ /**
1108
+ * A single-value arc — a score ring, a utilisation dial, a completion meter.
1109
+ *
1110
+ * The shape the library had no form for: `ProgressBar` covers linear progress and
1111
+ * `DonutChart` compares parts of a whole, but neither draws "one number against its
1112
+ * ceiling" in a round frame.
1113
+ */
1114
+ declare function RadialGauge({ value, max, size, tone, color, thickness, sweep, children, centerLabel, label, className, }: RadialGaugeProps): react.JSX.Element;
1115
+
1116
+ type SparklineVariant = 'line' | 'area';
1117
+ type SparklineSize = 'sm' | 'md' | 'lg';
1118
+ interface SparklineProps {
1119
+ data: number[];
1120
+ variant?: SparklineVariant;
1121
+ /** Token-backed colour. Ignored when `color` is set. */
1122
+ tone?: ChartTone;
1123
+ /** Explicit colour, for series whose colour comes from the data. */
1124
+ color?: string;
1125
+ size?: SparklineSize;
1126
+ /** Overrides the `size` preset. */
1127
+ width?: number;
1128
+ height?: number;
1129
+ strokeWidth?: number;
1130
+ /** Dot on the final point — useful when the line is the "current value". */
1131
+ showEndDot?: boolean;
1132
+ /** Accessible description. Omit to keep the chart decorative. */
1133
+ label?: string;
1134
+ className?: string;
1135
+ }
1136
+ /**
1137
+ * A compact trend line, with no axes and no interaction.
1138
+ *
1139
+ * `variant="area"` adds the gradient fill beneath the line that 0.2.0 had no way to
1140
+ * draw, which is what makes a sparkline readable at `lg` where a bare 1.5px stroke
1141
+ * looks thin.
1142
+ */
1143
+ declare function Sparkline({ data, variant, tone, color, size, width, height, strokeWidth, showEndDot, label, className, }: SparklineProps): react.JSX.Element | null;
1144
+
1145
+ type MiniBarChartSize = 'sm' | 'md' | 'lg';
1146
+ type MiniBarChartOrientation = 'vertical' | 'horizontal';
1147
+ interface MiniBarChartProps {
1148
+ bars: number[];
1149
+ /** Colour of the highlighted bars. */
1150
+ tone?: ChartTone;
1151
+ color?: string;
1152
+ /** Colour of the un-highlighted bars. Defaults to the muted track token. */
1153
+ restColor?: string;
1154
+ /**
1155
+ * Which bars are highlighted. A number or list of indices; negatives count from the
1156
+ * end, so `-1` is the last bar. Pass `[]` to highlight none.
1157
+ *
1158
+ * Replaces 0.2.0's `highlightLastBar` boolean, which could only ever mean `-1`.
1159
+ */
1160
+ highlight?: number | number[];
1161
+ size?: MiniBarChartSize;
1162
+ /** Overrides the `size` preset. */
1163
+ width?: number;
1164
+ height?: number;
1165
+ gap?: number;
1166
+ orientation?: MiniBarChartOrientation;
1167
+ radius?: number;
1168
+ label?: string;
1169
+ className?: string;
1170
+ }
1171
+ /** A compact bar series with no axes — a distribution or a per-period count. */
1172
+ declare function MiniBarChart({ bars, tone, color, restColor, highlight, size, width, height, gap, orientation, radius, label, className, }: MiniBarChartProps): react.JSX.Element | null;
1173
+
1174
+ type LegendDotSize = 'sm' | 'md';
1175
+ /** `line` is the swatch for a line series; `dot` and `square` for areas and bars. */
1176
+ type LegendDotShape = 'dot' | 'square' | 'line';
1177
+ interface LegendDotProps {
1178
+ /** Token-backed colour. Ignored when `color` is set. */
1179
+ tone?: ChartTone;
1180
+ /** Explicit colour, for data-driven series. */
1181
+ color?: string;
1182
+ size?: LegendDotSize;
1183
+ shape?: LegendDotShape;
1184
+ className?: string;
1185
+ }
1186
+ /** The colour swatch beside a series name. */
1187
+ declare function LegendDot({ tone, color, size, shape, className }: LegendDotProps): react.JSX.Element;
1188
+
1189
+ type ChartLegendOrientation = 'vertical' | 'horizontal';
1190
+ interface ChartLegendItem {
1191
+ label: string;
1192
+ /** Trailing value. Omit for a legend that only names the series. */
1193
+ count?: number | string;
1194
+ /** Token-backed colour. Falls back to the item's position in the chart sequence. */
1195
+ tone?: ChartTone;
1196
+ /** Explicit colour, for data-driven series. */
1197
+ color?: string;
1198
+ }
1199
+ interface ChartLegendProps {
1200
+ items: ChartLegendItem[];
1201
+ /**
1202
+ * `vertical` spreads each row to fill its container, so the counts align in a column
1203
+ * beside a donut. `horizontal` wraps inline, for a legend under a bar chart.
1204
+ */
1205
+ orientation?: ChartLegendOrientation;
1206
+ size?: LegendDotSize;
1207
+ shape?: LegendDotShape;
1208
+ className?: string;
1209
+ }
1210
+ /** Series names, swatches and optional values. */
1211
+ declare function ChartLegend({ items, orientation, size, shape, className, }: ChartLegendProps): react.JSX.Element;
1212
+
1213
+ type TrendLabelWeight = 'semibold' | 'bold';
1214
+ type TrendLabelSize = 'sm' | 'md' | 'lg';
1215
+ /**
1216
+ * Which direction is the good one.
1217
+ *
1218
+ * A delta component cannot infer this: +4% on-time delivery is good, +4% unit cost is
1219
+ * not. 0.2.0 had no such prop, so the only way to render a "rising is bad" delta was to
1220
+ * pass a raw hex — which is exactly what the deleted `BenchmarkCard` did, inverting its
1221
+ * own `positiveColor` default to red to compensate.
1222
+ */
1223
+ type TrendDirection = 'up-is-good' | 'up-is-bad';
1224
+ interface TrendLabelProps {
1225
+ value: number;
1226
+ suffix?: string;
1227
+ size?: TrendLabelSize;
1228
+ weight?: TrendLabelWeight;
1229
+ direction?: TrendDirection;
1230
+ /** Trend arrow. On by default — the docs described one long before there was one. */
1231
+ showArrow?: boolean;
1232
+ /** Explicit colour, for the rare data-driven case. Overrides the direction logic. */
1233
+ color?: string;
1234
+ className?: string;
1235
+ }
1236
+ /** A signed delta with a direction arrow, toned by whether the movement is good news. */
1237
+ declare function TrendLabel({ value, suffix, size, weight, direction, showArrow, color, className, }: TrendLabelProps): react.JSX.Element;
1238
+
1239
+ type ListRowDensity = 'default' | 'compact';
1240
+ type ListRowDivider = 'none' | 'top' | 'bottom';
1241
+ interface ListRowProps {
1242
+ /** Left of the title, on the title line — an icon badge, avatar, checkbox, file chip. */
1243
+ leading?: ReactNode;
1244
+ title?: ReactNode;
1245
+ /** Inline after the title — a Required/Optional chip, a count, a tag. */
1246
+ titleMeta?: ReactNode;
1247
+ /** Muted line under the title. */
1248
+ description?: ReactNode;
1249
+ /** Right end of the title line — a `StatusBadge`, a score, a timestamp. */
1250
+ meta?: ReactNode;
1251
+ /** Right-hand column spanning the whole row, vertically centred — actions, a `Toggle`. */
1252
+ trailing?: ReactNode;
1253
+ /** Full-width block below the title line — a `FileRow`, a `FileDropZone`, an alert, a nested list. */
1254
+ footer?: ReactNode;
1255
+ density?: ListRowDensity;
1256
+ divider?: ListRowDivider;
1257
+ /** Render an `<li>` instead of a `<div>` — use inside a `<ul>`/`<ol>`. */
1258
+ as?: 'div' | 'li';
1259
+ onClick?: () => void;
1260
+ className?: string;
1261
+ }
1262
+ /**
1263
+ * The generic list row: six slots and no opinion about what goes in them.
1264
+ *
1265
+ * Replaces `DocumentRow` and `DocumentChecklistRow`, which baked one product's
1266
+ * document-upload flow — its status vocabulary, its five raw-hex pills and its
1267
+ * unicode-glyph labels — into the library. Every feature of those rows is reachable by
1268
+ * composing this with `FileRow`, `FileDropZone` and `StatusBadge`; see the docs.
1269
+ */
1270
+ declare function ListRow({ leading, title, titleMeta, description, meta, trailing, footer, density, divider, as: Tag, onClick, className, }: ListRowProps): react.JSX.Element;
1271
+
1272
+ interface FileRowProps {
1273
+ name: string;
1274
+ /** Muted second line — size, upload date, uploader. */
1275
+ detail?: ReactNode;
1276
+ /** Leading chip showing the file extension, e.g. `"PDF"`. Ignored when `leading` is set. */
1277
+ fileType?: string;
1278
+ /** Custom leading node — overrides `fileType`. */
1279
+ leading?: ReactNode;
1280
+ /** The canonical action. Renders a text link before `actions`. */
1281
+ onDownload?: () => void;
1282
+ downloadLabel?: string;
1283
+ /** Everything else on the right — `Button`s, a `DropdownMenu`. */
1284
+ actions?: ReactNode;
1285
+ className?: string;
1286
+ }
1287
+ /**
1288
+ * One attached file: name, optional detail line, and actions.
1289
+ *
1290
+ * This strip was hardcoded inline inside both `DocumentRow` and
1291
+ * `DocumentChecklistRow`. Nothing about it is document-specific — it is the same row
1292
+ * for a generated export, an invoice or an evidence attachment.
1293
+ */
1294
+ declare function FileRow({ name, detail, fileType, leading, onDownload, downloadLabel, actions, className, }: FileRowProps): react.JSX.Element;
1295
+
1296
+ type ScoredRowAlign = 'center' | 'end';
1297
+ /** 8 / 12 / 20 / 48px — the four gaps the source mockups actually used. */
1298
+ type ScoredRowGap = 'sm' | 'md' | 'lg' | 'xl';
1299
+ interface ScoredRowProps {
1300
+ /** Leading visual — an `EntityIconBadge`, an `Avatar`, a rank number, or nothing. */
1301
+ leading?: ReactNode;
1302
+ title: ReactNode;
1303
+ subtitle?: ReactNode;
1304
+ /** Fixed-width column between the title block and the meter. */
1305
+ aside?: ReactNode;
1306
+ /** The bar. Put a `<ProgressBar>` here — the row does not choose one for you. */
1307
+ meter?: ReactNode;
1308
+ /** Right-hand value — a `<ScoreValue>`, a `<TrendLabel>`, a `<Badge>`, a button. */
1309
+ trailing?: ReactNode;
1310
+ /** CSS width values. Omit one and that slot flexes instead. */
1311
+ titleWidth?: string;
1312
+ asideWidth?: string;
1313
+ meterWidth?: string;
1314
+ trailingWidth?: string;
1315
+ gap?: ScoredRowGap;
1316
+ /** Gap between `leading` and the title block. Defaults to `gap`. */
1317
+ leadingGap?: ScoredRowGap;
1318
+ align?: ScoredRowAlign;
1319
+ className?: string;
1320
+ }
1321
+ /**
1322
+ * A row with a title block, an optional bar and a right-hand value.
1323
+ *
1324
+ * Was `EntityRow`. The rename is the smaller half of the change: the old component
1325
+ * hardcoded `RiskScore`, `WidgetProgressBar`, `TrendLabel` and `getRiskTone`, which
1326
+ * locked it to one scoring domain and forced 32 props — including four raw
1327
+ * `CSSProperties` escape hatches and a magic `nameWidth = '133px'` — to make it fit
1328
+ * anything else. The score and the bar are now slots, so the caller decides.
1329
+ */
1330
+ declare function ScoredRow({ leading, title, subtitle, aside, meter, trailing, titleWidth, asideWidth, meterWidth, trailingWidth, gap, leadingGap, align, className, }: ScoredRowProps): react.JSX.Element;
1331
+
1332
+ type ProgressBarTone = 'brand' | 'positive' | 'warning' | 'danger' | 'neutral';
1333
+ type ProgressBarSize = 'xs' | 'sm' | 'md' | 'lg';
1334
+ interface ProgressBarProps {
1335
+ /** 0–100. Values outside the range are clamped. */
1336
+ value: number;
1337
+ tone?: ProgressBarTone;
1338
+ size?: ProgressBarSize;
1339
+ /** Caption above the bar. Also becomes the accessible name. */
1340
+ label?: string;
1341
+ /** Show the percentage at the right of the label row. */
1342
+ showValue?: boolean;
1343
+ /** CSS radius override, e.g. `'1px'` for a square-ended bar. Defaults to fully round. */
1344
+ radius?: string;
1345
+ /** Accessible name when there is no visible `label`. */
1346
+ 'aria-label'?: string;
1347
+ /**
1348
+ * Applied to the track. This is how you set a fixed width — `className="w-16"`.
1349
+ * It genuinely overrides the base `w-full` because this file uses `cn`.
1350
+ */
1351
+ className?: string;
1352
+ }
1353
+ /**
1354
+ * A horizontal progress / proportion bar.
1355
+ *
1356
+ * Was `WidgetProgressBar` in 0.2.0, which fixed the height at 6px and lived under
1357
+ * `widgets/` despite being a general-purpose primitive — so `TableCellProgress`
1358
+ * hand-rolled a second copy rather than reuse it. It also had no ARIA at all.
1359
+ */
1360
+ declare function ProgressBar({ value, tone, size, label, showValue, radius, 'aria-label': ariaLabel, className, }: ProgressBarProps): react.JSX.Element;
1361
+
1362
+ interface RankedRowProps {
1363
+ rank?: number;
1364
+ name: string;
1365
+ sublabel?: string;
1366
+ score: number;
1367
+ /** Bar and value colour. `auto` derives it from `score`. */
1368
+ tone?: ProgressBarTone | 'auto';
1369
+ /** Which end of the scale is bad, when `tone` is `auto`. */
1370
+ direction?: ScoreDirection;
1371
+ scoreSize?: ScoreValueSize;
1372
+ scoreWeight?: ScoreValueWeight;
1373
+ className?: string;
1374
+ }
1375
+ /**
1376
+ * A leaderboard row: rank, name, score, and a full-width bar underneath.
1377
+ *
1378
+ * Was `RankedListItem` — the only `…Item` in a folder of `…Row`s. Its three raw-hex
1379
+ * colour props (`scoreColor`, `barColor`, `barTrackColor`) are gone in favour of
1380
+ * `tone`, and its `gap` CSS string is now the `gap-1.5` it always resolved to.
1381
+ */
1382
+ declare function RankedRow({ rank, name, sublabel, score, tone, direction, scoreSize, scoreWeight, className, }: RankedRowProps): react.JSX.Element;
293
1383
 
294
- declare function SectionHeading({ eyebrow, title, detail }: {
295
- eyebrow: string;
1384
+ interface IconTextRowProps {
1385
+ icon: ReactNode;
296
1386
  title: string;
297
- detail?: string;
298
- }): react.JSX.Element;
1387
+ detail: string;
1388
+ className?: string;
1389
+ }
1390
+ /**
1391
+ * A circular icon badge, a title, and one line of detail.
1392
+ *
1393
+ * Feature lists, empty-state explanations, onboarding intros, "what happens next"
1394
+ * steps. Was `FeatureRow`, which named it after the one screen it was extracted from.
1395
+ */
1396
+ declare function IconTextRow({ icon, title, detail, className }: IconTextRowProps): react.JSX.Element;
1397
+
1398
+ type ChecklistRowState = 'done' | 'active' | 'pending';
1399
+ interface ChecklistRowProps {
1400
+ label: string;
1401
+ state: ChecklistRowState;
1402
+ className?: string;
1403
+ }
1404
+ /**
1405
+ * One step in a progress checklist: a done tick, a spinning active ring, or an empty
1406
+ * pending ring.
1407
+ *
1408
+ * Shared by the event-onboarding "building your dashboard" screen and the
1409
+ * intelligence page's processing checklist. Both drove the same three states; only
1410
+ * the onboarding copy had the animated ring, which is the better treatment and is
1411
+ * adopted for both.
1412
+ *
1413
+ * Renders an `<li>` — callers must wrap it in a list, which is what both sources did.
1414
+ */
1415
+ declare function ChecklistRow({ label, state, className }: ChecklistRowProps): react.JSX.Element;
1416
+
1417
+ interface NumberedStepsListProps {
1418
+ steps: ReactNode[];
1419
+ className?: string;
1420
+ }
1421
+ /**
1422
+ * Ordered list with small filled number bullets.
1423
+ *
1424
+ * Promoted from entity-detail's "what happens next" panel. The panel's copy is
1425
+ * review-lifecycle business content and stays there; only the list chrome moves.
1426
+ *
1427
+ * The bullet was `bg-[#e7edfb] text-[#1d4ed8]` — a pale blue pair that is not in the
1428
+ * token set. It now uses the brand-tertiary background and brand text, which is the
1429
+ * documented treatment for a subtle brand-tinted chip.
1430
+ */
1431
+ declare function NumberedStepsList({ steps, className }: NumberedStepsListProps): react.JSX.Element;
1432
+
1433
+ type MetaFieldLayout = 'stacked' | 'inline';
1434
+ interface MetaFieldProps {
1435
+ label: string;
1436
+ value: ReactNode;
1437
+ /** Optional second line under the value (used by the onboarding review sections). */
1438
+ detail?: ReactNode;
1439
+ /**
1440
+ * `stacked` puts the label above the value (detail pages, onboarding review).
1441
+ * `inline` puts a fixed-width label beside it (drawer detail rows).
1442
+ */
1443
+ layout?: MetaFieldLayout;
1444
+ /** Fixed width for the `stacked` form, e.g. `sm:w-[262px]` on the overview grid. */
1445
+ className?: string;
1446
+ }
1447
+ /**
1448
+ * A label/value pair.
1449
+ *
1450
+ * Consolidates the same shape from six places: the entity-detail overview grid, the
1451
+ * reviewer-detail metric column, three `DetailRow` copies in drawers (queues,
1452
+ * filings, website-intel) and `ReviewMeta` in both onboarding wizards.
1453
+ *
1454
+ * An empty value renders an em dash, which is what every source copy did by hand.
1455
+ */
1456
+ declare function MetaField({ label, value, detail, layout, className, }: MetaFieldProps): react.JSX.Element;
1457
+ interface MetaFieldGridProps {
1458
+ children: ReactNode;
1459
+ className?: string;
1460
+ }
1461
+ /**
1462
+ * Wrapper for a set of `MetaField`s that wrap into columns.
1463
+ *
1464
+ * Matches the entity-detail overview grid, which relies on each field carrying its
1465
+ * own width rather than on fixed grid columns — long values (aliases, legal names)
1466
+ * need to be able to occupy a full row on narrow viewports.
1467
+ */
1468
+ declare function MetaFieldGrid({ children, className }: MetaFieldGridProps): react.JSX.Element;
1469
+
1470
+ type CheckedGroupListColumns = 1 | 2 | 3;
1471
+ /** One labelled group of ticked items. */
1472
+ interface CheckedGroup {
1473
+ label: string;
1474
+ items: string[];
1475
+ }
1476
+ interface CheckedGroupListProps {
1477
+ groups: CheckedGroup[];
1478
+ columns?: CheckedGroupListColumns;
1479
+ /** Leading glyph for every item. Defaults to a check; pass `null` for none. */
1480
+ icon?: ReactNode | null;
1481
+ emptyLabel?: string;
1482
+ className?: string;
1483
+ }
1484
+ /**
1485
+ * A read-only, grouped list of ticked items in a balanced multi-column flow.
1486
+ *
1487
+ * Was `PermissionGrid` — RBAC-specific naming for a generic shape, and not a grid
1488
+ * either: groups pack tightly down each column rather than aligning to shared row
1489
+ * heights, so a tall group beside a short one leaves no ragged gap.
1490
+ * `break-inside-avoid` keeps each group whole within a column.
1491
+ *
1492
+ * Granted permissions, included plan features, completed requirements, matched
1493
+ * criteria — anything that is "these labels, grouped, all ticked".
1494
+ */
1495
+ declare function CheckedGroupList({ groups, columns, icon, emptyLabel, className, }: CheckedGroupListProps): react.JSX.Element;
1496
+
1497
+ interface ColumnDef<T> {
1498
+ key: string;
1499
+ header: string;
1500
+ /**
1501
+ * CSS width value — e.g. `"320px"`, `"10rem"`. When `grow` is true this becomes the
1502
+ * column's floor: it counts toward the table's min-width, below which the wrapper
1503
+ * scrolls sideways rather than crushing the columns.
1504
+ */
1505
+ width: string;
1506
+ /**
1507
+ * When true the column absorbs the remaining table width.
1508
+ *
1509
+ * With no `grow` column, `table-fixed` distributes surplus width proportionally
1510
+ * across every column — the old flex layout left it blank on the right instead. Mark
1511
+ * whichever column should soak it up.
1512
+ */
1513
+ grow?: boolean;
1514
+ render: (row: T) => ReactNode;
1515
+ }
1516
+ type DataTableDensity = 'default' | 'compact';
1517
+ type DataTableAlign = 'center' | 'top';
1518
+ interface DataTableProps<T> {
1519
+ columns: ColumnDef<T>[];
1520
+ rows: T[];
1521
+ getRowKey: (row: T, index: number) => Key;
1522
+ /** Row and header padding. `compact` also steps the header and cell type down. */
1523
+ density?: DataTableDensity;
1524
+ /** Vertical alignment of every body cell. Use `top` for multi-line or ragged cells. */
1525
+ align?: DataTableAlign;
1526
+ onRowClick?: (row: T) => void;
1527
+ /** Rendered as one full-width row when `rows` is empty. Omit to render nothing. */
1528
+ emptyLabel?: string;
1529
+ className?: string;
1530
+ }
1531
+ /**
1532
+ * A real `<table>` with `table-fixed` and a `<colgroup>`.
1533
+ *
1534
+ * 0.2.0 laid each row out as its own flex container sized `w-max`, so a `grow` column
1535
+ * sized itself per row and one long cell shunted that row's remaining columns out of
1536
+ * line with its neighbours. `table-fixed` resolves column widths once for the whole
1537
+ * table, which is the property the consuming app hand-rolled a separate audit table
1538
+ * to get.
1539
+ */
1540
+ declare function DataTable<T>({ columns, rows, getRowKey, density, align, onRowClick, emptyLabel, className, }: DataTableProps<T>): react.JSX.Element;
1541
+ /**
1542
+ * Cell type scale.
1543
+ *
1544
+ * Named `size`, not `density`, and deliberately *not* inherited from the table: the two
1545
+ * real compact tables disagree about the mapping — the audit table wants default
1546
+ * padding with small cell text — so inheritance could not express it anyway, and it
1547
+ * would make these render one size inside a table and another outside one.
1548
+ */
1549
+ type TableCellSize = 'sm' | 'md';
1550
+ interface TableCellLeadTextProps {
1551
+ primary: string;
1552
+ secondary?: string;
1553
+ size?: TableCellSize;
1554
+ className?: string;
1555
+ }
1556
+ /** Primary text plus an optional muted subtitle — for lead entity/name cells. */
1557
+ declare function TableCellLeadText({ primary, secondary, size, className }: TableCellLeadTextProps): react.JSX.Element;
1558
+ interface TableCellTextProps {
1559
+ children: ReactNode;
1560
+ /** Muted (secondary) by default; pass false for the primary colour. */
1561
+ muted?: boolean;
1562
+ size?: TableCellSize;
1563
+ /** Ellipsise instead of wrapping, so every row keeps the same height. */
1564
+ truncate?: boolean;
1565
+ className?: string;
1566
+ }
1567
+ /** Plain text cell. */
1568
+ declare function TableCellText({ children, muted, size, truncate, className, }: TableCellTextProps): react.JSX.Element;
1569
+ interface TableCellBadgeProps {
1570
+ label: string;
1571
+ className?: string;
1572
+ }
1573
+ /** Small outlined chip — entity type labels, categories. */
1574
+ declare function TableCellBadge({ label, className }: TableCellBadgeProps): react.JSX.Element;
1575
+ interface TableCellProgressProps {
1576
+ percent: number;
1577
+ /**
1578
+ * Bar colour. `brand` is 0.2.0's default and byte-identical to it — `bg-brand`
1579
+ * resolves to the same `--prim-brand-900` the old raw-hex default hardcoded.
1580
+ */
1581
+ tone?: ProgressBarTone;
1582
+ size?: TableCellSize;
1583
+ className?: string;
1584
+ }
1585
+ /** Mini progress bar with a percentage label below. */
1586
+ declare function TableCellProgress({ percent, tone, size, className, }: TableCellProgressProps): react.JSX.Element;
1587
+
1588
+ type InlineAlertTone = 'info' | 'warning' | 'danger' | 'positive';
1589
+ interface InlineAlertProps {
1590
+ tone: InlineAlertTone;
1591
+ children: ReactNode;
1592
+ /** Overrides the per-tone default glyph. Pass `null` for no icon. */
1593
+ icon?: ReactNode | null;
1594
+ className?: string;
1595
+ }
1596
+ /** Banner for inline messaging — form errors, destructive-action warnings, success confirmations.
1597
+ *
1598
+ * Replaces four byte-identical raw-`amber-*` callouts, five competing error-text styles and a
1599
+ * standalone `Banner` component. `danger` renders as `role="alert"`; the rest as `role="status"`. */
1600
+ declare function InlineAlert({ tone, children, icon, className }: InlineAlertProps): react.JSX.Element;
1601
+
1602
+ type EmptyStateVariant = 'empty' | 'loading' | 'error';
1603
+ type EmptyStateSize = 'sm' | 'md' | 'lg';
1604
+ interface EmptyStateProps {
1605
+ message: string;
1606
+ /** `error` is the only variant that changes colour; `loading` exists for intent. */
1607
+ variant?: EmptyStateVariant;
1608
+ size?: EmptyStateSize;
1609
+ icon?: ReactNode;
1610
+ /** A primary action, e.g. "Add your first source". */
1611
+ action?: ReactNode;
1612
+ className?: string;
1613
+ }
1614
+ /**
1615
+ * Centred placeholder for an empty list, a loading list, or a failed fetch.
1616
+ *
1617
+ * Replaces eighteen copies of `py-8 text-center text-body-sm
1618
+ * text-default-secondary` plus four divergent variants. Loading and empty were
1619
+ * always the same markup in this codebase, so they are one component with a
1620
+ * `variant` rather than two near-identical ones.
1621
+ *
1622
+ * `aria-live` is set for the loading and error variants so a screen reader announces
1623
+ * the state change instead of silently swapping list content.
1624
+ */
1625
+ declare function EmptyState({ message, variant, size, icon, action, className, }: EmptyStateProps): react.JSX.Element;
1626
+
1627
+ type PasswordInputProps = Omit<InputProps, 'type' | 'trailingIcon' | 'trailingAction'>;
1628
+ /** Password field with a show/hide visibility toggle. */
1629
+ declare const PasswordInput: react.ForwardRefExoticComponent<PasswordInputProps & react.RefAttributes<HTMLInputElement>>;
1630
+
1631
+ interface AIChatBarProps {
1632
+ placeholder?: string;
1633
+ className?: string;
1634
+ }
1635
+ declare function AIChatBar({ placeholder, className, }: AIChatBarProps): react.JSX.Element;
1636
+
1637
+ interface AISuggestionChipProps {
1638
+ prompt: string;
1639
+ onClick?: () => void;
1640
+ className?: string;
1641
+ }
1642
+ declare function AISuggestionChip({ prompt, onClick, className }: AISuggestionChipProps): react.JSX.Element;
1643
+
1644
+ interface QuickAction {
1645
+ label: string;
1646
+ value: string;
1647
+ }
1648
+ interface QuickActionsBarProps {
1649
+ actions: QuickAction[];
1650
+ active?: string;
1651
+ onSelect?: (value: string) => void;
1652
+ className?: string;
1653
+ }
1654
+ declare function QuickActionsBar({ actions, active, onSelect, className }: QuickActionsBarProps): react.JSX.Element;
1655
+
1656
+ /** Soft aurora atmosphere used by the public-facing screens (auth, event
1657
+ * onboarding) — mirrors AuroraBackground in pages/intelligence. Blobs are
1658
+ * corner-anchored so the effect scales from phones to kiosk displays.
1659
+ * Render inside a `relative overflow-hidden` container; content goes on top
1660
+ * with `relative`. */
1661
+ declare function AuroraBackdrop(): react.JSX.Element;
1662
+
1663
+ /** Bespoke icon art with no equivalent in the stroked icon set.
1664
+ *
1665
+ * The library's icons come from `react-icons/lu`, which is a *stroked* set. What
1666
+ * lives here is the small set of *filled* 20×20 marks: swapping these for
1667
+ * `LuInfo`/`LuArrowRight`/etc. would turn a solid glyph into an outline — a visual
1668
+ * change, not a redraw. They keep their own `viewBox="0 0 20 20"` and
1669
+ * `fill="currentColor"`, and size via `className` (e.g. `className="size-5"`).
1670
+ *
1671
+ * Do not add stroked icons here — import them from `react-icons/lu` instead.
1672
+ */
1673
+ interface SolidIconProps {
1674
+ className?: string;
1675
+ }
1676
+ declare const SolidAlertTriangle: {
1677
+ ({ className }: SolidIconProps): react.JSX.Element;
1678
+ displayName: string;
1679
+ };
1680
+ declare const SolidShieldCheck: {
1681
+ ({ className }: SolidIconProps): react.JSX.Element;
1682
+ displayName: string;
1683
+ };
1684
+ declare const SolidGlobe: {
1685
+ ({ className }: SolidIconProps): react.JSX.Element;
1686
+ displayName: string;
1687
+ };
1688
+ declare const SolidMapPin: {
1689
+ ({ className }: SolidIconProps): react.JSX.Element;
1690
+ displayName: string;
1691
+ };
1692
+ declare const SolidClock: {
1693
+ ({ className }: SolidIconProps): react.JSX.Element;
1694
+ displayName: string;
1695
+ };
1696
+ declare const SolidArrowRight: {
1697
+ ({ className }: SolidIconProps): react.JSX.Element;
1698
+ displayName: string;
1699
+ };
1700
+ declare const SolidInfoCircle: {
1701
+ ({ className }: SolidIconProps): react.JSX.Element;
1702
+ displayName: string;
1703
+ };
1704
+ declare const SolidCheck: {
1705
+ ({ className }: SolidIconProps): react.JSX.Element;
1706
+ displayName: string;
1707
+ };
1708
+ /** Chart bars — the one mark here without a `fillRule`/`clipRule` pair. */
1709
+ declare function SolidChartBar({ className }: SolidIconProps): react.JSX.Element;
299
1710
 
300
- export { Avatar, AvatarBlock, type AvatarBlockProps, AvatarGroup, type AvatarGroupProps, type AvatarGroupSpacing, type AvatarImageProps, type AvatarInitialProps, type AvatarProps, type AvatarShape, type AvatarSize, Button, ButtonGroup, type ButtonGroupAlign, type ButtonGroupItem, type ButtonGroupProps, type ButtonGroupVariant, type ButtonProps, type ButtonSize, type ButtonVariant, type ColumnDef, DataTable, DocumentRow, type DocumentRowProps, type DocumentStatus, FileDropZone, type FileDropZoneProps, FormCard, FormCardFooter, type FormCardFooterProps, FormCardHeader, type FormCardHeaderProps, IconButton, type IconButtonProps, type IconButtonVariant, Input, type InputProps, type InputSize, MetricCard, Modal, type ModalProps, MultiSelectCard, type MultiSelectCardProps, NavItem, type NavItemProps, Panel, ROLE_COMBO_OPTIONS, RoleBadge, type RoleBadgeProps, RoleComboBox, type RoleComboBoxProps, type RoleOption, SectionHeading, Select, type SelectOption, type SelectProps, SentimentBadge, SeverityBadge, StatTile, type StatTileProps, type StepItem, type StepStatus, Stepper, type StepperProps, TableCellBadge, TableCellLeadText, TableCellProgress, TableCellStatusPill, TableCellText, Textarea, type TextareaProps, Toggle, type ToggleProps };
1711
+ export { AIChatBar, type AIChatBarProps, AISuggestionChip, type AISuggestionChipProps, AuroraBackdrop, Avatar, AvatarBlock, type AvatarBlockProps, AvatarGroup, type AvatarGroupProps, type AvatarGroupSpacing, type AvatarImageProps, type AvatarInitialProps, type AvatarProps, type AvatarShape, type AvatarSize, Badge, type BadgeColor, type BadgeProps, type BadgeSize, type BadgeVariant, BarChart, type BarChartOrientation, type BarChartProps, type BarChartSeries, type BarChartSize, Button, ButtonGroup, type ButtonGroupAlign, type ButtonGroupItem, type ButtonGroupProps, type ButtonGroupVariant, type ButtonProps, type ButtonSize, type ButtonVariant, CHART_SEQUENCE, CHART_TONE, CHART_TRACK, Card, CardAction, type CardActionProps, CardBody, type CardBodyProps, CardDescription, type CardDescriptionProps, CardFooter, type CardFooterAlign, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, type CardRadius, type CardSize, CardTitle, type CardTitleProps, type CardTone, ChartLegend, type ChartLegendItem, type ChartLegendOrientation, type ChartLegendProps, type ChartTone, CheckIndicator, type CheckIndicatorProps, type CheckIndicatorStatus, Checkbox, type CheckboxProps, type CheckedGroup, CheckedGroupList, type CheckedGroupListColumns, type CheckedGroupListProps, ChecklistRow, type ChecklistRowProps, type ChecklistRowState, type ColumnDef, ConfirmDialog, type ConfirmDialogProps, CountBadge, type CountBadgeProps, DEFAULT_SCORE_THRESHOLDS, DataTable, type DataTableAlign, type DataTableDensity, type DataTableProps, DatePicker, type DatePickerProps, DonutChart, type DonutChartProps, type DonutChartSize, type DonutSegment, Drawer, type DrawerProps, DropdownMenu, type DropdownMenuItem, type DropdownMenuProps, EmptyState, type EmptyStateProps, type EmptyStateSize, type EmptyStateVariant, EntityIconBadge, type EntityIconBadgeProps, type EntityIconBadgeSize, type EntityIconBadgeTone, EyebrowLabel, type EyebrowLabelProps, type EyebrowLabelVariant, FileDropZone, type FileDropZoneProps, FileRow, type FileRowProps, FilterBar, type FilterBarProps, type FilterBarSize, FormCard, FormCardFooter, type FormCardFooterProps, FormCardHeader, type FormCardHeaderProps, IconButton, type IconButtonProps, type IconButtonVariant, IconTextRow, type IconTextRowProps, InlineAlert, type InlineAlertProps, type InlineAlertTone, Input, type InputProps, type InputSize, LegendDot, type LegendDotProps, type LegendDotShape, type LegendDotSize, ListRow, type ListRowDensity, type ListRowDivider, type ListRowProps, MetaField, MetaFieldGrid, type MetaFieldGridProps, type MetaFieldLayout, type MetaFieldProps, MiniBarChart, type MiniBarChartOrientation, type MiniBarChartProps, type MiniBarChartSize, Modal, ModalBody, type ModalBodyProps, ModalDescription, type ModalDescriptionProps, ModalFooter, type ModalFooterAlign, type ModalFooterProps, ModalHeader, type ModalHeaderProps, type ModalProps, type ModalSize, ModalTitle, type ModalTitleProps, type ModalTone, MultiSelectCard, type MultiSelectCardProps, NavItem, type NavItemProps, type NavItemSize, NoteConfirmModal, type NoteConfirmModalProps, NumberedStepsList, type NumberedStepsListProps, OVERLAY_SCRIM, PageHeading, type PageHeadingProps, type PageHeadingSize, PageToolbar, type PageToolbarProps, type PageToolbarSize, PasswordInput, type PasswordInputProps, ProgressBar, type ProgressBarProps, type ProgressBarSize, type ProgressBarTone, type QuickAction, QuickActionsBar, type QuickActionsBarProps, ROLE_COMBO_OPTIONS, RadialGauge, type RadialGaugeProps, type RadialGaugeSize, RankedRow, type RankedRowProps, RoleBadge, type RoleBadgeProps, RoleComboBox, type RoleComboBoxProps, type RoleOption, type ScoreDirection, type ScoreRampTone, type ScoreThresholds, type ScoreTone, ScoreValue, type ScoreValueProps, type ScoreValueSize, type ScoreValueTone, type ScoreValueWeight, ScoredRow, type ScoredRowAlign, type ScoredRowGap, type ScoredRowProps, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, type SelectOption, type SelectProps, SolidAlertTriangle, SolidArrowRight, SolidChartBar, SolidCheck, SolidClock, SolidGlobe, SolidInfoCircle, SolidMapPin, SolidShieldCheck, Sparkline, type SparklineProps, type SparklineSize, type SparklineVariant, StatNumber, type StatNumberProps, type StatNumberSize, type StatNumberWeight, StatTile, type StatTileProps, StatusBadge, type StatusBadgeProps, type StatusBadgeSize, StatusChip, type StatusChipProps, StatusDot, type StatusDotProps, type StatusDotTone, type StatusTone, type StepItem, type StepStatus, Stepper, type StepperProps, type TabItem, TableCellBadge, type TableCellBadgeProps, TableCellLeadText, type TableCellLeadTextProps, TableCellProgress, type TableCellProgressProps, type TableCellSize, TableCellText, type TableCellTextProps, Tabs, type TabsProps, type TabsSize, type TabsVariant, TagPill, type TagPillProps, type TagPillTone, Textarea, type TextareaProps, TileGrid, type TileGridBreakpoint, type TileGridColumns, type TileGridProps, Toggle, type ToggleProps, type ToggleSize, TrailChip, type TrailChipProps, type TrendDirection, TrendLabel, type TrendLabelProps, type TrendLabelSize, type TrendLabelWeight, type UserAccountStatus, UserStatusPill, type UserStatusPillProps, WidgetFooter, type WidgetFooterProps, WidgetHeader, type WidgetHeaderEyebrowVariant, type WidgetHeaderProps, WidgetTitle, type WidgetTitleProps, type WidgetTitleSize, cn, getScoreTone, resolveChartColor, useOverlayDismiss };