@mithrl/design-system 0.3.0 → 0.4.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.
Files changed (31) hide show
  1. package/dist/components/approval-card/ApprovalCard.d.ts +70 -0
  2. package/dist/components/code-block/CodeBlock.d.ts +64 -0
  3. package/dist/components/command-search/CommandSearch.d.ts +57 -0
  4. package/dist/components/context-cards/ContextCards.d.ts +53 -0
  5. package/dist/components/disclosure/Disclosure.d.ts +38 -0
  6. package/dist/components/field-message/FieldMessage.d.ts +12 -0
  7. package/dist/components/filter-table/FilterTable.d.ts +61 -0
  8. package/dist/components/flap-text/FlapText.d.ts +68 -0
  9. package/dist/components/flowchart/Flowchart.d.ts +140 -0
  10. package/dist/components/global-app-bar/GlobalAppBar.d.ts +14 -4
  11. package/dist/components/icon-swap/IconSwap.d.ts +30 -0
  12. package/dist/components/insight-cards/InsightCards.d.ts +97 -0
  13. package/dist/components/number-flow/NumberFlow.d.ts +93 -0
  14. package/dist/components/progress-indicator/ProgressIndicator.d.ts +9 -1
  15. package/dist/components/prompt-bar/PromptBar.d.ts +103 -0
  16. package/dist/components/recommendation-card/RecommendationCard.d.ts +77 -0
  17. package/dist/components/records-table/RecordsTable.d.ts +87 -0
  18. package/dist/components/resizable-panels/ResizablePanels.d.ts +22 -0
  19. package/dist/components/selection-actions/SelectionActions.d.ts +72 -0
  20. package/dist/components/skeleton-reveal/SkeletonReveal.d.ts +33 -0
  21. package/dist/components/status-orb/StatusOrb.d.ts +51 -0
  22. package/dist/components/streaming-text/StreamingText.d.ts +85 -0
  23. package/dist/components/task-rows/TaskRows.d.ts +77 -0
  24. package/dist/components/upload-queue/UploadQueue.d.ts +10 -0
  25. package/dist/index.d.ts +41 -1
  26. package/dist/index.js +5041 -1845
  27. package/dist/internal/useStaggerBatch.d.ts +22 -0
  28. package/dist/patterns/notifications/Notifications.d.ts +159 -0
  29. package/dist/patterns/workspace-app-shell/WorkspaceAppShell.d.ts +50 -0
  30. package/dist/styles.css +1 -1
  31. package/package.json +4 -2
@@ -0,0 +1,97 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+
3
+ /** Direction of a change, mapped to semantic color. */
4
+ export type InsightTone = "neutral" | "success" | "danger";
5
+ /**
6
+ * One run of an insight sentence. `text` reads as prose, `entity` names a
7
+ * cohort, gene, batch, or assay, and `metric` carries a figure or delta.
8
+ */
9
+ export type InsightSegment = {
10
+ kind: "text";
11
+ text: string;
12
+ } | {
13
+ kind: "entity";
14
+ text: string;
15
+ } | {
16
+ kind: "metric";
17
+ text: string;
18
+ tone?: InsightTone;
19
+ };
20
+ /** A compact before/after row rendered beneath the sentence. */
21
+ export type InsightComparison = {
22
+ /** What is being compared, e.g. `Median TPM, responders`. */
23
+ label: string;
24
+ /** Signed relative change, already formatted, e.g. `+18.4%`. */
25
+ delta: string;
26
+ /** Absolute value, already formatted, e.g. `412.6 TPM`. */
27
+ value: string;
28
+ /** Semantic direction. @default "neutral" */
29
+ tone?: InsightTone;
30
+ };
31
+ /** A single plotted observation for the embedded mini chart. */
32
+ export type InsightChartPoint = {
33
+ /** Axis label for the scrub readout, e.g. `Day 14`. */
34
+ label: string;
35
+ /** Plotted magnitude in the series' own units. */
36
+ value: number;
37
+ };
38
+ export type InsightChart = {
39
+ points: readonly InsightChartPoint[];
40
+ /** Unit suffix shown in the scrub readout, e.g. `TPM`. */
41
+ unit?: string;
42
+ /** Accessible summary of the series. Required — the SVG carries no text. */
43
+ ariaLabel: string;
44
+ };
45
+ export type InsightFollowUp = {
46
+ /** The suggested next question, phrased as the agent would ask it. */
47
+ label: string;
48
+ /** Stable identifier handed back to `onFollowUpSelect`. */
49
+ id?: string;
50
+ };
51
+ export type Insight = {
52
+ /** Stable identity for the page. */
53
+ id: string;
54
+ /** Short headline for the insight. */
55
+ title: string;
56
+ /** The insight itself, composed of prose, entity, and metric runs. */
57
+ sentence: readonly InsightSegment[];
58
+ /** Optional comparison rows. */
59
+ comparisons?: readonly InsightComparison[];
60
+ /** Optional embedded trend chart. */
61
+ chart?: InsightChart;
62
+ /** Optional suggested follow-up rendered in the footer. */
63
+ followUp?: InsightFollowUp;
64
+ };
65
+ export type InsightCardsProps = Omit<HTMLAttributes<HTMLElement>, "children" | "onSelect"> & {
66
+ /** The pages, in reading order. At least one is required. */
67
+ insights: readonly Insight[];
68
+ /** Header title. @default "Insights" */
69
+ heading?: ReactNode;
70
+ /** Controlled page index. */
71
+ page?: number;
72
+ /** Initial page index for uncontrolled use. @default 0 */
73
+ defaultPage?: number;
74
+ /** Called with the next index whenever the page changes. */
75
+ onPageChange?: (page: number) => void;
76
+ /** Called when the footer follow-up chip is activated. */
77
+ onFollowUpSelect?: (followUp: InsightFollowUp, insight: Insight) => void;
78
+ };
79
+ /**
80
+ * A paged carousel of agent-authored insights. Each page states one finding
81
+ * in a sentence built from entity and metric chips, supports it with
82
+ * comparison rows and a mini trend chart, and offers one follow-up question.
83
+ */
84
+ export declare const InsightCards: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLElement>, "children" | "onSelect"> & {
85
+ /** The pages, in reading order. At least one is required. */
86
+ insights: readonly Insight[];
87
+ /** Header title. @default "Insights" */
88
+ heading?: ReactNode;
89
+ /** Controlled page index. */
90
+ page?: number;
91
+ /** Initial page index for uncontrolled use. @default 0 */
92
+ defaultPage?: number;
93
+ /** Called with the next index whenever the page changes. */
94
+ onPageChange?: (page: number) => void;
95
+ /** Called when the footer follow-up chip is activated. */
96
+ onFollowUpSelect?: (followUp: InsightFollowUp, insight: Insight) => void;
97
+ } & import("react").RefAttributes<HTMLElement>>;
@@ -0,0 +1,93 @@
1
+ import { type CSSProperties } from "react";
2
+
3
+ /**
4
+ * Milliseconds one digit spends rolling. Mirrors `--motion-duration-moderate`;
5
+ * the CSS reads the token directly and only falls back to this number when the
6
+ * caller overrides `rollDuration`.
7
+ */
8
+ export declare const NUMBER_FLOW_DEFAULT_DURATION_MS = 220;
9
+ /** Milliseconds each successive cell waits before it starts rolling. */
10
+ export declare const NUMBER_FLOW_DEFAULT_STAGGER_MS = 18;
11
+ export type NumberFlowElement = "span" | "div" | "p" | "strong" | "em";
12
+ export type NumberFlowSize = "small" | "medium" | "large";
13
+ export interface NumberFlowProps {
14
+ /** The number to display. Changing it rolls the digits that differ. */
15
+ value: number;
16
+ /** `Intl.NumberFormat` options. Changing them reformats and animates. */
17
+ format?: Intl.NumberFormatOptions;
18
+ /** BCP 47 locale(s) for formatting. Defaults to the runtime locale. */
19
+ locale?: string | string[];
20
+ /**
21
+ * Height of the clipped roll window, as a multiple of the inherited line box.
22
+ * This is the only size NumberFlow owns — it never sets a font property.
23
+ * @default "medium"
24
+ */
25
+ size?: NumberFlowSize;
26
+ /** Host element. @default "span" */
27
+ as?: NumberFlowElement;
28
+ /** Per-digit delay, in milliseconds. @default 18 */
29
+ stagger?: number;
30
+ /** Roll duration, in milliseconds. @default `--motion-duration-moderate` */
31
+ rollDuration?: number;
32
+ className?: string;
33
+ style?: CSSProperties;
34
+ }
35
+ export type NumberFlowDirection = "up" | "down";
36
+ export type NumberFlowCell = {
37
+ /** Glyph shown once the cell settles. */
38
+ char: string;
39
+ /** Glyph leaving the window, or `null` when the cell is new or unchanged. */
40
+ previous: string | null;
41
+ /** Digit-to-digit change: a clipped vertical roll. */
42
+ roll: boolean;
43
+ /** Any other change (separator, sign, or a brand new place): a crossfade. */
44
+ fade: boolean;
45
+ /** Roll direction, taken from the sign of the value delta. */
46
+ direction: NumberFlowDirection;
47
+ };
48
+ /**
49
+ * Cells are aligned from the RIGHT, not the left: in a number the units column
50
+ * is the fixed point, so 99 -> 100 must roll the two nines against the new
51
+ * tens and units rather than sliding every place one column over.
52
+ *
53
+ * Only cells whose glyph actually changed move — the same rule FlapText
54
+ * applies to characters. A digit replacing a digit rolls; anything else
55
+ * (a separator appearing, a sign flipping, a brand new leading place) is a
56
+ * quiet crossfade, because rolling a comma into a digit reads as noise.
57
+ */
58
+ export declare function numberFlowCells(previous: string, next: string, direction?: NumberFlowDirection): NumberFlowCell[];
59
+ /**
60
+ * A number that resolves instead of blinking.
61
+ *
62
+ * Each character of the formatted value is its own cell. When `value` changes,
63
+ * only the cells whose glyph differs move: a digit rolls vertically through a
64
+ * clipped window — the outgoing glyph leaves through one edge as the incoming
65
+ * one arrives from the other, softened by `--motion-blur-soft` — while
66
+ * separators and new leading places simply crossfade. Cells are staggered left
67
+ * to right so the least significant digit is the last to settle.
68
+ *
69
+ * This is a short roll, not a slot machine. The spinning-counter recipe's
70
+ * multi-revolution 0-9 strip, its directional SVG blur filter and its masked
71
+ * window edges are all deliberately absent: a scientific workspace wants a
72
+ * number that has clearly *changed*, not one that celebrates.
73
+ *
74
+ * Sharpness: settled cells carry `transform: none` exactly — never an identity
75
+ * matrix — `will-change` is present only while a cell is in flight, no scale is
76
+ * ever applied, and the component sets no font property, so text metrics are
77
+ * the caller's. `font-variant-numeric: tabular-nums` keeps the box from
78
+ * wobbling as digits change width.
79
+ *
80
+ * Accessibility: cells are `aria-hidden`, the host carries the formatted value
81
+ * as `aria-label`, and a visually hidden polite live region announces one clean
82
+ * string.
83
+ *
84
+ * Reduced motion: no roll and no blur — the value swaps instantly behind a
85
+ * `--motion-duration-fast` opacity crossfade.
86
+ */
87
+ export declare function NumberFlow({ value, format, locale, size, as, stagger, rollDuration, className, style, }: NumberFlowProps): import("react").DetailedReactHTMLElement<{
88
+ className: string;
89
+ style: CSSProperties | undefined;
90
+ "aria-label": string;
91
+ "data-size": NumberFlowSize;
92
+ "data-animating": string;
93
+ }, HTMLElement>;
@@ -7,8 +7,16 @@ export declare const progressIndicatorVariants: (props?: ({
7
7
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
8
  export type ProgressIndicatorSize = NonNullable<VariantProps<typeof progressIndicatorVariants>["size"]>;
9
9
  export type ProgressIndicatorTone = NonNullable<VariantProps<typeof progressIndicatorVariants>["tone"]>;
10
+ /**
11
+ * Loading is the default so every existing usage keeps its current behavior.
12
+ * Done resolves the same indicator into a drawn completion check.
13
+ */
14
+ export type ProgressIndicatorState = "loading" | "done";
10
15
  type RestrictedProgressIndicatorAttribute = "aria-atomic" | "aria-busy" | "aria-hidden" | "aria-label" | "aria-live" | "children" | "onClick" | "onDoubleClick" | "onKeyDown" | "onKeyUp" | "role" | "tabIndex";
11
- type ProgressIndicatorBaseProps = Omit<HTMLAttributes<HTMLSpanElement>, RestrictedProgressIndicatorAttribute> & VariantProps<typeof progressIndicatorVariants>;
16
+ type ProgressIndicatorBaseProps = Omit<HTMLAttributes<HTMLSpanElement>, RestrictedProgressIndicatorAttribute> & VariantProps<typeof progressIndicatorVariants> & {
17
+ /** Completion state. Defaults to `"loading"`. */
18
+ state?: ProgressIndicatorState;
19
+ };
12
20
  type InformativeProgressIndicatorProps = {
13
21
  /** Concise accessible name announced through the status live region. */
14
22
  label: string;
@@ -0,0 +1,103 @@
1
+ import { type IconGlyphComponent } from "../icon/Icon";
2
+
3
+
4
+ export type PromptBarShape = "rounded" | "pill";
5
+ /** Trigger characters that open the anchored suggestion popover. */
6
+ export type PromptBarTrigger = "@" | "/";
7
+ export type PromptBarSource = {
8
+ /** Stable identity used for selection and de-duplication. */
9
+ id: string;
10
+ /** Visible row label and entity chip label. */
11
+ label: string;
12
+ /** Short qualifier rendered beside the label, e.g. "dataset". */
13
+ kind?: string;
14
+ /** Optional approved Lucide glyph for the row and the chip. */
15
+ icon?: IconGlyphComponent;
16
+ };
17
+ export type PromptBarCommand = {
18
+ /** Stable identity, also inserted as `/{id}` unless `insert` is provided. */
19
+ id: string;
20
+ /** Visible row label. */
21
+ label: string;
22
+ /** Short qualifier rendered beside the label, e.g. "analysis". */
23
+ kind?: string;
24
+ /** Optional approved Lucide glyph for the row. */
25
+ icon?: IconGlyphComponent;
26
+ /** Text inserted in place of the `/` token. Defaults to `/{id}`. */
27
+ insert?: string;
28
+ };
29
+ export type PromptBarModel = {
30
+ /** Stable identity used for selection. */
31
+ id: string;
32
+ /** Visible label in the trigger and in the option list. */
33
+ label: string;
34
+ /** Optional short qualifier shown under the label in the option list. */
35
+ description?: string;
36
+ };
37
+ export type PromptBarLabels = {
38
+ input: string;
39
+ submit: string;
40
+ dictate: string;
41
+ model: string;
42
+ attachments: string;
43
+ removeSource: string;
44
+ sourceSuggestions: string;
45
+ commandSuggestions: string;
46
+ emptySuggestions: string;
47
+ };
48
+ export type PromptBarProps = {
49
+ /** Controlled prompt text. */
50
+ value: string;
51
+ /** Called on every keystroke and on suggestion insertion. */
52
+ onValueChange: (value: string) => void;
53
+ /** Called with the trimmed prompt and the sources attached to it. */
54
+ onSubmit?: (value: string, sources: readonly PromptBarSource[]) => void;
55
+ /** Rows offered by the `@` popover. */
56
+ sources?: readonly PromptBarSource[];
57
+ /** Rows offered by the `/` popover. */
58
+ commands?: readonly PromptBarCommand[];
59
+ /** Controlled attachment chips. Omit to let PromptBar own them. */
60
+ selectedSources?: readonly PromptBarSource[];
61
+ /** Initial attachment chips for uncontrolled use. */
62
+ defaultSelectedSources?: readonly PromptBarSource[];
63
+ /** Called whenever the attachment row changes. */
64
+ onSelectedSourcesChange?: (sources: readonly PromptBarSource[]) => void;
65
+ /** Models offered by the footer model picker. */
66
+ models?: readonly PromptBarModel[];
67
+ /** Controlled model id. */
68
+ selectedModel?: string;
69
+ /** Called with the newly chosen model id. */
70
+ onModelChange?: (modelId: string) => void;
71
+ /** Renders the dictation microphone slot. Presentation only. */
72
+ onDictate?: () => void;
73
+ /** Geometry of the bar. */
74
+ shape?: PromptBarShape;
75
+ placeholder?: string;
76
+ disabled?: boolean;
77
+ autoFocus?: boolean;
78
+ name?: string;
79
+ labels?: Partial<PromptBarLabels>;
80
+ className?: string;
81
+ /** Storybook-only hook that forces the popover open for review. */
82
+ "data-preview-trigger"?: PromptBarTrigger;
83
+ };
84
+ type TriggerMatch = {
85
+ trigger: PromptBarTrigger;
86
+ query: string;
87
+ start: number;
88
+ end: number;
89
+ };
90
+ /**
91
+ * Reads the token immediately before the caret. A token qualifies when it
92
+ * starts at the beginning of the value or after whitespace, is introduced by
93
+ * `@` or `/`, and contains no whitespace of its own.
94
+ */
95
+ export declare function readTriggerAtCaret(value: string, caret: number): TriggerMatch | null;
96
+ /**
97
+ * Command-style prompt entry with `@` source mentions, `/` commands, an
98
+ * attachment chip row, and a model rail. PromptBar is a sibling of Composer,
99
+ * not a replacement: Composer owns conversational entry, PromptBar owns
100
+ * command-shaped prompting where sources and commands are addressable.
101
+ */
102
+ export declare const PromptBar: import("react").ForwardRefExoticComponent<PromptBarProps & import("react").RefAttributes<HTMLTextAreaElement>>;
103
+ export {};
@@ -0,0 +1,77 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ import type { MetadataTone } from "../badge/Badge";
3
+
4
+ /** How sure the agent is about the action it is proposing. */
5
+ export type RecommendationConfidence = "low" | "medium" | "high";
6
+ /** A path the agent considered but did not lead with. */
7
+ export interface RecommendationAlternative {
8
+ id: string;
9
+ label: string;
10
+ /** One sentence on what this path would do differently. */
11
+ description?: string;
12
+ /** Short status Tag, e.g. "Needs review" or "No signal". */
13
+ statusLabel?: string;
14
+ statusTone?: MetadataTone;
15
+ disabled?: boolean;
16
+ }
17
+ export interface RecommendationEntityChipProps {
18
+ children: ReactNode;
19
+ /** Optional kind shown to assistive tech, e.g. "dataset" or "gene". */
20
+ kind?: string;
21
+ className?: string;
22
+ }
23
+ /**
24
+ * Inline reference to a real object — a dataset, a run, a gene — set inside
25
+ * the recommendation body so the sentence stays readable.
26
+ */
27
+ export declare function RecommendationEntityChip({ children, kind, className, }: RecommendationEntityChipProps): import("react/jsx-runtime").JSX.Element;
28
+ type RestrictedRecommendationCardAttribute = "children" | "role" | "title";
29
+ export type RecommendationCardProps = Omit<HTMLAttributes<HTMLElement>, RestrictedRecommendationCardAttribute> & {
30
+ /** The suggestion, phrased as a question the scientist can answer. */
31
+ headline: ReactNode;
32
+ /** What the agent would actually do. Inline entity chips belong here. */
33
+ body?: ReactNode;
34
+ confidence: RecommendationConfidence;
35
+ /** Overrides the default "High confidence" style label. */
36
+ confidenceLabel?: string;
37
+ /** Why the agent is this confident. Shown next to the meter. */
38
+ confidenceReason?: ReactNode;
39
+ alternatives?: RecommendationAlternative[];
40
+ alternativesLabel?: string;
41
+ /** Controlled disclosure state for the alternatives list. */
42
+ alternativesOpen?: boolean;
43
+ defaultAlternativesOpen?: boolean;
44
+ onAlternativesOpenChange?: (open: boolean) => void;
45
+ onAlternativeSelect?: (alternative: RecommendationAlternative) => void;
46
+ onAccept?: () => void;
47
+ acceptLabel?: string;
48
+ /** Disables the primary action while the proposal is still resolving. */
49
+ acceptDisabled?: boolean;
50
+ };
51
+ /**
52
+ * An agent suggestion with its confidence shown plainly, the alternatives it
53
+ * weighed kept one click away, and a single primary action to accept.
54
+ */
55
+ export declare const RecommendationCard: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLElement>, RestrictedRecommendationCardAttribute> & {
56
+ /** The suggestion, phrased as a question the scientist can answer. */
57
+ headline: ReactNode;
58
+ /** What the agent would actually do. Inline entity chips belong here. */
59
+ body?: ReactNode;
60
+ confidence: RecommendationConfidence;
61
+ /** Overrides the default "High confidence" style label. */
62
+ confidenceLabel?: string;
63
+ /** Why the agent is this confident. Shown next to the meter. */
64
+ confidenceReason?: ReactNode;
65
+ alternatives?: RecommendationAlternative[];
66
+ alternativesLabel?: string;
67
+ /** Controlled disclosure state for the alternatives list. */
68
+ alternativesOpen?: boolean;
69
+ defaultAlternativesOpen?: boolean;
70
+ onAlternativesOpenChange?: (open: boolean) => void;
71
+ onAlternativeSelect?: (alternative: RecommendationAlternative) => void;
72
+ onAccept?: () => void;
73
+ acceptLabel?: string;
74
+ /** Disables the primary action while the proposal is still resolving. */
75
+ acceptDisabled?: boolean;
76
+ } & import("react").RefAttributes<HTMLElement>>;
77
+ export {};
@@ -0,0 +1,87 @@
1
+ import { type ForwardedRef, type HTMLAttributes, type ReactNode, type TableHTMLAttributes } from "react";
2
+ import type { MetadataTone } from "../badge/Badge";
3
+
4
+ export type RecordsTableAlign = "start" | "end";
5
+ export type RecordsTableSortDirection = "ascending" | "descending";
6
+ export type RecordsTableSort = {
7
+ /** Column currently driving row order. */
8
+ columnId: string;
9
+ direction: RecordsTableSortDirection;
10
+ };
11
+ export type RecordsTableColumn<Row> = {
12
+ /** Stable identifier used for sorting and cell keys. */
13
+ id: string;
14
+ /** Visible column header text. */
15
+ header: string;
16
+ /** Enables the header sort control and aria-sort reporting. */
17
+ sortable?: boolean;
18
+ /** Horizontal alignment of the header and its cells. */
19
+ align?: RecordsTableAlign;
20
+ /** Cell renderer. Defaults to the raw `sortValue` string. */
21
+ render?: (row: Row, index: number) => ReactNode;
22
+ /** Comparable primitive used when this column is sorted. */
23
+ sortValue?: (row: Row) => string | number;
24
+ /** Optional fixed column width, e.g. `var(--space-64)`. */
25
+ width?: string;
26
+ };
27
+ export type RecordsTableProps<Row> = Omit<TableHTMLAttributes<HTMLTableElement>, "children"> & {
28
+ columns: readonly RecordsTableColumn<Row>[];
29
+ rows: readonly Row[];
30
+ /** Stable row identity used for React keys. */
31
+ getRowId: (row: Row, index: number) => string;
32
+ /** Required accessible name for the grid. */
33
+ caption: string;
34
+ /** Renders the caption above the table instead of only for assistive tech. */
35
+ captionVisible?: boolean;
36
+ /** Renders the leading ordinal / group-letter cell. */
37
+ showIndex?: boolean;
38
+ /** When provided, alphabetical separator rows are inserted on letter change. */
39
+ groupLetter?: (row: Row) => string;
40
+ /** Controlled sort state. */
41
+ sort?: RecordsTableSort | null;
42
+ /** Initial sort for uncontrolled use. */
43
+ defaultSort?: RecordsTableSort | null;
44
+ onSortChange?: (sort: RecordsTableSort) => void;
45
+ /** Summary cells rendered in a sticky-free footer row, keyed by column id. */
46
+ footer?: Partial<Record<string, ReactNode>>;
47
+ /** Optional label rendered in the footer's leading cell. */
48
+ footerLabel?: ReactNode;
49
+ };
50
+ /**
51
+ * A column-configuration driven record grid. RecordsTable owns row order,
52
+ * sticky header semantics, and optional alphabetical grouping. Cell content
53
+ * is supplied by the caller, usually through the exported cell primitives.
54
+ */
55
+ declare function RecordsTableInner<Row>({ columns, rows, getRowId, caption, captionVisible, showIndex, groupLetter, sort, defaultSort, onSortChange, footer, footerLabel, className, ...props }: RecordsTableProps<Row>, ref: ForwardedRef<HTMLTableElement>): import("react/jsx-runtime").JSX.Element;
56
+ export declare const RecordsTable: <Row>(props: RecordsTableProps<Row> & {
57
+ ref?: ForwardedRef<HTMLTableElement>;
58
+ }) => ReturnType<typeof RecordsTableInner>;
59
+ export type RecordsTableTagsProps = HTMLAttributes<HTMLDivElement> & {
60
+ /** Category labels rendered as Tag metadata. */
61
+ tags: readonly string[];
62
+ /** Number of tags shown before collapsing into a "+N" indicator. */
63
+ max?: number;
64
+ tone?: MetadataTone;
65
+ };
66
+ /** Tag cluster cell with a deterministic "+N" overflow indicator. */
67
+ export declare function RecordsTableTags({ tags, max, tone, className, ...props }: RecordsTableTagsProps): import("react/jsx-runtime").JSX.Element;
68
+ export declare const recordsTableStrengthLevels: readonly ["No communication", "Very weak", "Weak", "Strong", "Very strong"];
69
+ export type RecordsTableStrengthLevel = 0 | 1 | 2 | 3 | 4;
70
+ export type RecordsTableStrengthProps = HTMLAttributes<HTMLSpanElement> & {
71
+ /** Ordinal level from 0 (no communication) through 4 (very strong). */
72
+ level: RecordsTableStrengthLevel;
73
+ /** Hides the text label while keeping the accessible name. */
74
+ hideLabel?: boolean;
75
+ };
76
+ /** Five-step ordinal meter for relationship or signal strength. */
77
+ export declare function RecordsTableStrength({ level, hideLabel, className, ...props }: RecordsTableStrengthProps): import("react/jsx-runtime").JSX.Element;
78
+ export type RecordsTableLinkProps = {
79
+ href: string;
80
+ children: ReactNode;
81
+ /** Marks the destination as external and adds safe rel attributes. */
82
+ external?: boolean;
83
+ className?: string;
84
+ };
85
+ /** Destination cell that keeps the external affordance inside the grid. */
86
+ export declare function RecordsTableLink({ href, children, external, className, }: RecordsTableLinkProps): import("react/jsx-runtime").JSX.Element;
87
+ export {};
@@ -30,6 +30,17 @@ export type ResizablePanelGroupProps = Omit<HTMLAttributes<HTMLDivElement>, "chi
30
30
  onSecondarySizeChange?: (size: number) => void;
31
31
  /** Reports the final pointer value or each keyboard step in pixels. */
32
32
  onSecondarySizeCommit?: (size: number) => void;
33
+ /**
34
+ * Reports one drag-to-dismiss intent per pointer drag when the pointer
35
+ * travels past a panel minimum by more than `dismissThreshold`. Visibility
36
+ * stays with the consumer; the group never hides a panel on its own.
37
+ */
38
+ onCollapseIntent?: (region: "primary" | "secondary") => void;
39
+ /**
40
+ * Share of a panel minimum the pointer must cross before a drag counts as a
41
+ * dismissal request. Defaults to 0.5, i.e. half the minimum width.
42
+ */
43
+ dismissThreshold?: number;
33
44
  /** Exactly Primary Panel, Handle, and Secondary Panel in that order. */
34
45
  children: ReactNode;
35
46
  };
@@ -74,6 +85,17 @@ export declare const ResizablePanelGroup: import("react").ForwardRefExoticCompon
74
85
  onSecondarySizeChange?: (size: number) => void;
75
86
  /** Reports the final pointer value or each keyboard step in pixels. */
76
87
  onSecondarySizeCommit?: (size: number) => void;
88
+ /**
89
+ * Reports one drag-to-dismiss intent per pointer drag when the pointer
90
+ * travels past a panel minimum by more than `dismissThreshold`. Visibility
91
+ * stays with the consumer; the group never hides a panel on its own.
92
+ */
93
+ onCollapseIntent?: (region: "primary" | "secondary") => void;
94
+ /**
95
+ * Share of a panel minimum the pointer must cross before a drag counts as a
96
+ * dismissal request. Defaults to 0.5, i.e. half the minimum width.
97
+ */
98
+ dismissThreshold?: number;
77
99
  /** Exactly Primary Panel, Handle, and Secondary Panel in that order. */
78
100
  children: ReactNode;
79
101
  } & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,72 @@
1
+ import { type HTMLAttributes, type RefObject } from "react";
2
+ import { type IconGlyphComponent } from "../icon/Icon";
3
+
4
+ /** A viewport-relative rectangle, matching the shape of `DOMRect`. */
5
+ export interface SelectionRect {
6
+ top: number;
7
+ left: number;
8
+ width: number;
9
+ height: number;
10
+ }
11
+ export interface UseSelectionRectOptions {
12
+ /**
13
+ * Restrict tracking to selections that start and end inside this element.
14
+ * Omit to track the whole document.
15
+ */
16
+ containerRef?: RefObject<HTMLElement | null>;
17
+ /** Stop tracking without unmounting the caller. @default false */
18
+ disabled?: boolean;
19
+ }
20
+ /**
21
+ * Tracks the current document selection and returns its viewport-relative
22
+ * rectangle, or `null` when nothing is selected.
23
+ *
24
+ * Recomputes on `selectionchange` and on scroll/resize so the toolbar stays
25
+ * pinned to the passage while the page moves under it. Safe during SSR: the
26
+ * first render returns `null` and tracking starts after mount.
27
+ */
28
+ export declare function useSelectionRect({ containerRef, disabled, }?: UseSelectionRectOptions): SelectionRect | null;
29
+ export interface SelectionAction {
30
+ /** Stable identity, passed to `onSelect` and used as the React key. */
31
+ id: string;
32
+ /** Visible label. Keep it a single verb where possible. */
33
+ label: string;
34
+ /** Optional approved Lucide glyph shown before the label. */
35
+ icon?: IconGlyphComponent;
36
+ /**
37
+ * Emphasis. `primary` actions read as full labelled buttons; `secondary`
38
+ * actions are compact and sit after a divider.
39
+ * @default "primary"
40
+ */
41
+ emphasis?: "primary" | "secondary";
42
+ /** Invoked when the action is chosen. */
43
+ onSelect: () => void;
44
+ /** Renders the action non-interactive. */
45
+ disabled?: boolean;
46
+ }
47
+ export interface SelectionActionsProps extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
48
+ /** Actions offered for the highlighted passage. */
49
+ actions: SelectionAction[];
50
+ /**
51
+ * Viewport-relative rectangle of the passage. Pass the value from
52
+ * `useSelectionRect()`, or your own rect for a controlled placement. When
53
+ * `null` the toolbar renders nothing.
54
+ */
55
+ anchorRect: SelectionRect | null;
56
+ /** Called on Escape, on a click outside, or after an action is chosen. */
57
+ onDismiss?: () => void;
58
+ /** Accessible name for the toolbar. @default "Actions for the selected text" */
59
+ label?: string;
60
+ /** Gap between the passage and the toolbar, in pixels. @default 8 */
61
+ offset?: number;
62
+ }
63
+ /**
64
+ * A floating toolbar anchored above a highlighted passage.
65
+ *
66
+ * Keyboard contract: the bar is a `role="toolbar"` with roving tabindex — one
67
+ * tab stop for the whole bar, then Arrow Left/Right to move between actions,
68
+ * with Home and End jumping to the ends. Escape dismisses without acting, as
69
+ * does a click outside the bar. Focus is never stolen from the document
70
+ * selection; the bar becomes reachable by Tab and only takes focus once entered.
71
+ */
72
+ export declare const SelectionActions: import("react").ForwardRefExoticComponent<SelectionActionsProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,33 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+
3
+ export interface SkeletonRevealProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "placeholder"> {
4
+ /** Whether the real content has arrived. Flipping this plays the hand-off. */
5
+ loaded: boolean;
6
+ /** The loading surface — normally one or more `Skeleton` elements. */
7
+ placeholder: ReactNode;
8
+ /** The real content. */
9
+ children: ReactNode;
10
+ }
11
+ /**
12
+ * Cross-fades a loading placeholder into the content that replaces it, so
13
+ * arriving data resolves instead of snapping.
14
+ *
15
+ * Both layers occupy the same grid cell, so they stack without either one
16
+ * leaving the flow: the box is as tall as whichever layer is taller and the
17
+ * swap costs no layout. The outgoing placeholder fades away through
18
+ * `--motion-blur-soft` while the content fades in from the same blur, the two
19
+ * crossing through each other over one shared duration.
20
+ *
21
+ * The hidden layer is `visibility: hidden`, so it is out of the tab order and
22
+ * out of the accessibility tree until it is the live one — the visibility
23
+ * switch is delayed to the end of the fade on the way out and immediate on the
24
+ * way in.
25
+ *
26
+ * `Skeleton` itself is untouched by this: it stays a decorative surface that
27
+ * rejects children and semantics. The hand-off needs both layers mounted at
28
+ * once, which a prop on a childless primitive cannot express.
29
+ *
30
+ * Reduced motion: no blur and no cross-fade timing — the layers swap behind a
31
+ * `--motion-duration-fast` opacity change.
32
+ */
33
+ export declare const SkeletonReveal: import("react").ForwardRefExoticComponent<SkeletonRevealProps & import("react").RefAttributes<HTMLDivElement>>;