@juwel-development/design-system 3.11.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +16 -3
  2. package/dist/design-system.js +1029 -540
  3. package/dist/styles.css +2 -0
  4. package/dist/styles.dark.css +2 -0
  5. package/dist/styles.light.css +2 -0
  6. package/dist/types/Arrangement/ColumnLayout/ColumnLayout.d.ts +38 -18
  7. package/dist/types/Display/Callout/Callout.d.ts +31 -0
  8. package/dist/types/Display/Icon/Icon.d.ts +20 -24
  9. package/dist/types/Display/Meter/Meter.d.ts +5 -6
  10. package/dist/types/Display/Rule/Rule.d.ts +22 -0
  11. package/dist/types/Display/Table/Table.d.ts +57 -7
  12. package/dist/types/Display/Typography/Eyebrow/Eyebrow.d.ts +1 -1
  13. package/dist/types/Display/Typography/H1/H1.d.ts +1 -1
  14. package/dist/types/Display/Typography/H2/H2.d.ts +1 -1
  15. package/dist/types/Display/Typography/H3/H3.d.ts +1 -1
  16. package/dist/types/Display/Typography/H4/H4.d.ts +1 -1
  17. package/dist/types/Display/Typography/H5/H5.d.ts +1 -1
  18. package/dist/types/Display/Typography/H6/H6.d.ts +1 -1
  19. package/dist/types/Display/Typography/Note/Note.d.ts +16 -3
  20. package/dist/types/Display/Typography/P/P.d.ts +15 -2
  21. package/dist/types/Display/Typography/Prose/Prose.d.ts +14 -6
  22. package/dist/types/Interaction/Button/Button.d.ts +10 -4
  23. package/dist/types/Interaction/Slider/Slider.d.ts +3 -0
  24. package/dist/types/Interaction/Stepper/Stepper.d.ts +59 -0
  25. package/dist/types/Interaction/Stepper/StepperCompositionError.d.ts +3 -0
  26. package/dist/types/Interaction/Switch/Switch.d.ts +20 -0
  27. package/dist/types/Interaction/Tabs/Tabs.d.ts +24 -3
  28. package/dist/types/Layout/Dialog/Dialog.d.ts +11 -3
  29. package/dist/types/Layout/Form/FormConfigurationError.d.ts +3 -0
  30. package/dist/types/Layout/Pane/Pane.d.ts +55 -0
  31. package/dist/types/Layout/Shell/Shell.d.ts +39 -0
  32. package/dist/types/Layout/Sidebar/Sidebar.d.ts +16 -2
  33. package/dist/types/Theme/Palette.d.ts +11 -4
  34. package/dist/types/index.d.ts +21 -1
  35. package/package.json +18 -8
  36. package/src/Arrangement/ColumnLayout/ColumnLayout.tsx +86 -28
  37. package/src/Display/Callout/Callout.tsx +64 -0
  38. package/src/Display/Icon/Icon.tsx +53 -13
  39. package/src/Display/Meter/Meter.tsx +12 -13
  40. package/src/Display/Rule/Rule.tsx +31 -0
  41. package/src/Display/Table/Table.tsx +189 -24
  42. package/src/Display/Typography/Note/Note.tsx +27 -11
  43. package/src/Display/Typography/P/P.tsx +29 -4
  44. package/src/Display/Typography/Prose/Prose.tsx +44 -19
  45. package/src/Interaction/Button/Button.tsx +11 -4
  46. package/src/Interaction/Slider/Slider.tsx +3 -5
  47. package/src/Interaction/Stepper/Stepper.tsx +307 -0
  48. package/src/Interaction/Stepper/StepperCompositionError.ts +6 -0
  49. package/src/Interaction/Switch/Switch.tsx +64 -0
  50. package/src/Interaction/Tabs/Tabs.tsx +44 -10
  51. package/src/Layout/Dialog/Dialog.tsx +19 -6
  52. package/src/Layout/Form/Form.tsx +2 -1
  53. package/src/Layout/Form/FormConfigurationError.ts +6 -0
  54. package/src/Layout/Pane/Pane.tsx +159 -0
  55. package/src/Layout/Shell/Shell.tsx +124 -0
  56. package/src/Layout/Sidebar/Sidebar.tsx +31 -7
  57. package/src/Theme/Palette.ts +17 -6
  58. package/src/Theme/renderTokens.ts +61 -12
  59. package/src/index.ts +21 -2
  60. package/src/styles.css +5 -6
  61. package/src/styles.dark.css +5 -6
  62. package/src/styles.light.css +5 -6
  63. package/src/tokens.css +54 -9
  64. package/src/tokens.dark.css +51 -8
  65. package/src/tokens.light.css +49 -6
  66. package/dist/index.css +0 -2
@@ -1,9 +1,13 @@
1
1
  import type { VariantProps } from 'class-variance-authority';
2
2
  import type { FunctionComponent } from 'react';
3
3
  declare const icon: (props?: ({
4
- color?: "muted" | "success" | "warning" | "error" | "info" | null | undefined;
4
+ color?: "warning" | "info" | "success" | "error" | "muted" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  declare const drawings: {
7
+ readonly plus: readonly ["M3 8h10", "M8 3v10"];
8
+ readonly right: readonly ["M3 8h10", "M9 4l4 4-4 4"];
9
+ readonly remove: readonly ["M3 8h10"];
10
+ readonly dot: readonly ["M8 5a3 3 0 1 0 0 6a3 3 0 1 0 0-6z"];
7
11
  readonly sort: readonly ["M5.5 13V3", "M3 5.5l2.5-2.5L8 5.5", "M10.5 3v10", "M8 10.5l2.5 2.5 2.5-2.5"];
8
12
  readonly 'sort-ascending': readonly ["M8 13V3", "M4 7l4-4 4 4"];
9
13
  readonly 'sort-descending': readonly ["M8 3v10", "M4 9l4 4 4-4"];
@@ -11,9 +15,7 @@ declare const drawings: {
11
15
  readonly 'bubble-exclamation': readonly ["M3.5 2h9a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7.25L4 13.75V11h-.5a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1z", "M8 4.5v2", "M8 8.75h.01"];
12
16
  readonly 'bubble-tick': readonly ["M3.5 2h9a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H7.25L4 13.75V11h-.5a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1z", "M5.75 6.75l1.5 1.5 3-3.5"];
13
17
  };
14
- export interface IIconProps extends VariantProps<typeof icon> {
15
- /** Which drawing. A name selects a shape, never a state or a behaviour. */
16
- name: keyof typeof drawings;
18
+ export interface IIconPartProps extends VariantProps<typeof icon> {
17
19
  /**
18
20
  * The accessible name that makes the icon a status mark (CONTEXT.md). Give it only where the icon
19
21
  * stands alone for a state; absent or empty, the icon stays hidden from assistive technology.
@@ -21,25 +23,19 @@ export interface IIconProps extends VariantProps<typeof icon> {
21
23
  label?: string;
22
24
  testId?: string;
23
25
  }
24
- /**
25
- * A reusable visual glyph in six drawings: three sort indicators, a bin, and a speech bubble holding
26
- * an exclamation mark or a tick. Decorative beside the control or text that names it, or - given a
27
- * `label` - a status mark that stands alone for an item's state.
28
- *
29
- * @Guarantees — enforced on every render
30
- * - Out of the tab order in both forms: it adds no stop.
31
- * - Without a `label` it is hidden from assistive technology and adds no spoken name.
32
- * - With a non-empty `label` it is one image named by that label alone, announced once; an image
33
- * without a name is never rendered.
34
- * - Scales with the surrounding font-size and takes the surrounding text colour unless `color`
35
- * selects `muted` or a status tone. The tone changes colour only: no role, name or announcement.
36
- * - Every drawing differs in shape, so no meaning is carried by colour alone.
37
- *
38
- * @CallerMustEnsure
39
- * - An unlabelled icon sits beside what carries the meaning: a `Button` label or `ariaLabel`, a
40
- * header cell's `ariaSort`. Inside a named control it stays unlabelled, or the name is said twice.
41
- * - A status mark's `label` states the status in the reader's language; the library words nothing.
42
- * - The two forms of one state use two drawings, never one drawing in two colours.
26
+ export interface IIconProps extends IIconPartProps {
27
+ /** Legacy selector, retained alongside the compound drawing components. */
28
+ name: Exclude<keyof typeof drawings, 'plus' | 'right' | 'remove'>;
29
+ }
30
+ /** Legacy named drawings and five compound action drawings, all sharing em sizing, currentColor,
31
+ * optional status tones, label and testId. Parts take no name. Leave parts decorative inside
32
+ * Buttons and supply the action-specific ariaLabel on the Button itself. Remove is a minus, not bin.
43
33
  */
44
- export declare const Icon: FunctionComponent<IIconProps>;
34
+ export declare const Icon: FunctionComponent<IIconProps> & {
35
+ Plus: FunctionComponent<IIconPartProps>;
36
+ Up: FunctionComponent<IIconPartProps>;
37
+ Down: FunctionComponent<IIconPartProps>;
38
+ Right: FunctionComponent<IIconPartProps>;
39
+ Remove: FunctionComponent<IIconPartProps>;
40
+ };
45
41
  export {};
@@ -4,9 +4,8 @@ declare const meterFill: (props?: ({
4
4
  treatment?: "neutral" | "depleting" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  export interface IMeterProps extends VariantProps<typeof meterFill> {
7
- /** The current level. Must lie inside `[min, max]`; an outside value throws
8
- * {@link MeterConfigurationError} rather than clamping - a wrong number must not render as a
9
- * plausible level. */
7
+ /** The current level. Off-range values clamp the visual fill to the nearest bound;
8
+ * `aria-valuenow` retains the raw value. */
10
9
  value: number;
11
10
  /** The bottom of the scale. Defaults to `0`. */
12
11
  min?: number;
@@ -29,8 +28,8 @@ export interface IMeterProps extends VariantProps<typeof meterFill> {
29
28
  * - The root carries `role="meter"`, `aria-valuenow`/`aria-valuemin`/`aria-valuemax`, the `label`
30
29
  * as its accessible name, and `aria-valuetext` exactly when `valueText` is supplied. It is not
31
30
  * focusable, and the visual fill is hidden from the accessibility tree.
32
- * - The filled share is `(value - min) / (max - min)` of the container and begins at logical
33
- * inline-start under both LTR and RTL direction.
31
+ * - The filled share is `(value - min) / (max - min)`, clamped to `[0, 1]`, and begins at logical
32
+ * inline-start under both LTR and RTL direction. `aria-valuenow` retains the raw value.
34
33
  * - Neutral paints the fill with `meterFill`; `depleting` maps the normalized level linearly
35
34
  * through OKLab from `meterFill` at the maximum to `error` at the minimum - no threshold, no
36
35
  * wording, no icon (docs/adr/0010-meter-depletion-is-a-treatment.md).
@@ -39,7 +38,7 @@ export interface IMeterProps extends VariantProps<typeof meterFill> {
39
38
  * radius token - Meter is not a control), and draws a persistent one-pixel `rule` line that
40
39
  * identifies the whole capacity against the surface.
41
40
  * - Invalid numeric configuration throws {@link MeterConfigurationError}: non-finite `value`,
42
- * `min` or `max`, `min >= max`, or a value outside the inclusive range. Nothing is clamped.
41
+ * `min` or `max`, or `min >= max`.
43
42
  * - No visible wording of its own, no numeric readout, no caption slot, no `className`/`style`
44
43
  * passthrough.
45
44
  *
@@ -0,0 +1,22 @@
1
+ import type { FunctionComponent } from 'react';
2
+ export interface IRuleProps {
3
+ testId?: string;
4
+ }
5
+ /**
6
+ * A decorative horizontal hairline between two blocks of one arrangement.
7
+ *
8
+ * @Guarantees
9
+ * - One CSS pixel in the theme's border role, spanning its holder's width.
10
+ * - Forced colours use CanvasText so the hairline survives the user's palette.
11
+ * - Always hidden from assistive technology, with no role, content or focus stop.
12
+ * - No margin or padding: the surrounding arrangement owns space on both sides.
13
+ *
14
+ * @CallerMustEnsure
15
+ * - Place it between blocks in a column Stack; Stack's gap supplies the space role.
16
+ * - Rule is never a semantic separator. A thematic break that must be conveyed to
17
+ * assistive technology requires semantic markup instead of this component.
18
+ *
19
+ * @UXGuidelines
20
+ * - Use Collection for a semantic list with rules between items; Rule creates no list.
21
+ */
22
+ export declare const Rule: FunctionComponent<IRuleProps>;
@@ -2,6 +2,9 @@ import type { VariantProps } from 'class-variance-authority';
2
2
  import { type FunctionComponent, type ReactNode } from 'react';
3
3
  import type { Observable, Subject } from 'rxjs';
4
4
  declare const table: (props?: ({
5
+ bounded?: boolean | null | undefined;
6
+ selectionTreatment?: "marker" | "highlight" | null | undefined;
7
+ captionVisibility?: "hidden" | "visible" | null | undefined;
5
8
  density?: "compact" | "comfortable" | null | undefined;
6
9
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
10
  declare const tableCell: (props?: ({
@@ -21,6 +24,11 @@ type TableColumnWidthRole = 'name' | 'fact' | 'figure' | 'action';
21
24
  * optional named minimum as its floor. Declared once on `Table.Root`, in cell order.
22
25
  */
23
26
  export type TableColumnAllocation = {
27
+ /** Fits the widest rendered action group, without sharing surplus width. */
28
+ readonly width: 'icon-action';
29
+ readonly weight?: never;
30
+ readonly minWidth?: never;
31
+ } | {
24
32
  /** The role whose width this column takes exactly, at any available width. */
25
33
  readonly width: TableColumnWidthRole;
26
34
  readonly weight?: never;
@@ -36,13 +44,15 @@ export type TableColumnAllocation = {
36
44
  readonly minWidth?: TableColumnWidthRole;
37
45
  };
38
46
  export interface ITableRootProps extends VariantProps<typeof table> {
47
+ /** Opt into parent-bounded scrolling on both axes with a pinned header; short tables keep natural height. */
48
+ bounded?: boolean;
39
49
  /** The table's accessible name. Rendered as the first child; always present. */
40
50
  caption: string;
41
51
  /** What the note column is. Governs narrow-viewport behaviour; omit when there is none. */
42
52
  notes?: 'supplementary' | 'content';
43
53
  /** The columns' allocations, in the order the cells of every row are written. Omit it and widths
44
54
  * follow content as before; declare it and every row shares one allocation the rows' content
45
- * cannot move, and the narrow-viewport `notes` behaviour is replaced by residual scrolling. */
55
+ * cannot move (except content-sized `icon-action` tracks), and the narrow-viewport `notes` behaviour is replaced by residual scrolling. */
46
56
  columns?: readonly TableColumnAllocation[];
47
57
  children?: ReactNode;
48
58
  testId?: string;
@@ -83,26 +93,43 @@ export interface ITableHeaderCellProps extends VariantProps<typeof tableHeaderCe
83
93
  * @Guarantees — enforced on every render
84
94
  * - Renders semantic `table`/`thead`/`tbody`/`tfoot`/`tr`/`th`/`td`, and works with JavaScript off.
85
95
  * - `Root` renders its required `caption` as the table's first child, so every table is named.
96
+ * `captionVisibility` defaults to `visible`; `hidden` visually clips the caption out of flow,
97
+ * including its spacing, while preserving its native accessible name and the scroll wrapper's name.
98
+ * Hide it only when visible text directly above the table already names what it lists; the
99
+ * enclosing arrangement owns the gap above the table. The consumer still supplies the caption.
86
100
  * - The block reads as a table from two rule weights alone: the heavier `rule` above the first row,
87
- * `border` hairlines between rows, and no bottom rule on the last. No cell borders, fill, zebra or hover.
101
+ * `border` hairlines between rows, and no bottom rule on the last. No cell borders, default fill, zebra or hover.
88
102
  * - `Cell variant="value"` sets tabular figures; `variant="note"` does not. Both at the 15px small role.
89
103
  * - `HeaderCell` emits the `scope` it is given; none is inferred. It emits `ariaSort` the same way:
90
104
  * the attribute states the displayed order and the component never orders, cycles or requests one.
91
105
  * - Residual horizontal overflow scrolls in every `notes` mode, with no opt-in. The wrapper is
92
106
  * keyboard-reachable while there is something to scroll - always, as a named region, with no note
93
- * column; as a named group only once the table overflows, with one. No vertical bound is ever set:
94
- * a long table sits inside a `ScrollContainer` with `axis="vertical"`, which owns that axis.
107
+ * column; as a named group only once the table overflows, with one. Bounded tables instead expose
108
+ * a named group and keyboard stop only while either axis overflows, retained while focused.
109
+ * - `bounded` makes this same wrapper own both scroll axes within the parent's allocated height.
110
+ * Short tables retain natural height; unsized parents allow natural growth. Only the header pins,
111
+ * on the themed surface; captions scroll normally and keep naming the table. All columns and rows
112
+ * remain tabular at every width, including both notes modes. Unbounded behavior is unchanged.
113
+ * - Focus reveals rows and controls below the pinned header inside the wrapper. Selection updates
114
+ * alone never scroll. The wrapper reserves the shared focus ring's room.
95
115
  * - `Root columns` declares every column's allocation once, in cell order, and every row shares it:
96
116
  * a fixed column takes its named width role at any available width; proportional columns share
97
117
  * the width the fixed ones leave by their weights, each floored at its named minimum, and while a
98
118
  * minimum holds one column the others share what is left. A fixed width below its minimum is the
99
- * minimum. Nothing a row holds moves a boundary: filtering, sorting, paging, long or short content,
119
+ * minimum. Except for `icon-action`, nothing a row holds moves a boundary: filtering, sorting, paging, long or short content,
100
120
  * an empty body and its repopulation all leave the allocation as it was. Only the definitions, the
101
121
  * theme's `--table-column-*` values and the available width can. All-fixed columns do not stretch.
122
+ * - `{ width: 'icon-action' }` fits the widest rendered cell (including its header and insets),
123
+ * takes no surplus width, and may shrink after filtering. Compose multiple plain icon buttons
124
+ * in `Cluster gap="stack"`; max-content track sizing keeps the group on one line.
102
125
  * - With `columns` declared, no narrow-viewport rule applies whatever `notes` says: the note column
103
126
  * stays, rows stay tabular, and what does not fit scrolls in the wrapper as above. Text wraps inside
104
- * its allocation, an unbroken run included; the table never truncates, hides or resizes content.
127
+ * its allocation, an unbroken run included; the table does not itself truncate, hide or resize content.
105
128
  * Without `columns`, widths follow content and both `notes` behaviours are exactly as before.
129
+ * - Exception: a consumer may mark individual `P` or `Note` content with `truncate`. Only that
130
+ * text stays on one line and ellipsizes at its allocated inline end, in either column layout;
131
+ * its full DOM text remains accessible and does not force the table wider. Unmarked siblings
132
+ * retain their wrapping/overflow behavior; fixed column widths and minimums still hold.
106
133
  * - `Root density` insets every header and body cell from one theme pair: `comfortable` (the
107
134
  * default, the former spacing exactly) or `compact`, per table. It moves no type size and no
108
135
  * control's own dimensions. A non-positive or non-finite `weight` throws
@@ -117,6 +144,10 @@ export interface ITableHeaderCellProps extends VariantProps<typeof tableHeaderCe
117
144
  * emitted reads unselected; a replaced source reads unselected until it emits; unmounting
118
145
  * unsubscribes. The selection input is independent of `onClick$`, so a row may be selected and
119
146
  * noninteractive, interactive and unselected, or both. Rendering and selection changes emit nothing.
147
+ * - `Root selectionTreatment="highlight"` adds `selectedSurface` behind selected rows only;
148
+ * the default `marker` preserves the former presentation. Neither treatment changes on hover.
149
+ * The marker remains a border in forced colours, where backgrounds may be suppressed; selection
150
+ * stays distinct from the focus outline. A nested table chooses its own treatment.
120
151
  * - The row stays a `tr` in a `table`: no grid role, no arrow-key navigation. `aria-selected` is a
121
152
  * WAI-ARIA 1.2 state of `row` and valid here, but Chromium exposes a row's selected state only
122
153
  * inside a `grid`, so Chrome and Edge screen readers do not announce it on these rows (accepted
@@ -127,12 +158,31 @@ export interface ITableHeaderCellProps extends VariantProps<typeof tableHeaderCe
127
158
  * clipped by the scroll region. A table with neither keeps its static geometry exactly.
128
159
  *
129
160
  * @CallerMustEnsure — the component cannot see these and does not check them
161
+ * - For bounded mode supply finite usable parent height, with room for the header and readable rows.
162
+ * Compose directly inside `Pane.Body scrollOwner="child"` or `Dialog.Content scrollOwner="child"`:
163
+ * those holders add no scrolling. Intermediate wrappers must preserve the height allocation.
164
+ * Fixed surrounding content must fit; no component promises impossible viewport fitting.
165
+ * - For narrow comparisons use weighted columns without minimums when the content can wrap into
166
+ * their shares. Fixed widths and declared minimums retain their meaning; controls may overflow.
167
+ * - A theme's `selectedSurface` differs from resting/hover surfaces and keeps foreground, muted
168
+ * and link/status text at 4.5:1, and the marker, rule and focus ring at 3:1.
169
+ * Highlighted rows use selectedError for their error ink/fill. Other consumer-composed inks and
170
+ * controls must meet their own contrast constraints against this surface too.
130
171
  * - Every row writes exactly as many cells as there are `columns`, in the same order. A row with
131
172
  * fewer leaves tracks empty; one with more breaks onto a second line of its own row.
132
173
  * - A cell whose content cannot wrap - a `Button`, an `Input`, an image - sits in a column whose
133
174
  * fixed width or minimum holds it: the `action` role holds one standard control at comfortable
134
175
  * density. The allocation never widens for content, so an under-allocated control overflows its
135
- * cell rather than moving its neighbours.
176
+ * cell rather than moving its neighbours. The content-sized icon-action allocation is the exception.
177
+ * - Every icon-only Button needs an action-specific `ariaLabel`; leave its nested Icon decorative.
178
+ * Prefer labelled buttons wherever there is room. No tooltip is required. Only plain buttons
179
+ * inherit cell typography without increasing a single-line row's height; ghost keeps its padding.
180
+ * - For icon actions, theme `--space-stack` must be at least the focus width plus offset, so a ring
181
+ * cannot reach its neighbour. Twice the cell block inset must hold that same ring extent
182
+ * between adjacent rows. Keep line height at least one em. The wrapper
183
+ * reserves ring room at scroll boundaries without changing row height.
184
+ * - For truncated text, provide an operable path to the full wording (for example row activation
185
+ * opening the item). Truncation must not hide essential content or interactive descendants.
136
186
  * - A cell's `align` and `variant` are the consumer's as before; an allocation sets neither.
137
187
  * - Each row's `onClick$` and `isSelected$` are tied to that row's stable identity, so a reordered or
138
188
  * temporarily removed row keeps its association. Table holds no identity, registry or policy, and
@@ -1,7 +1,7 @@
1
1
  import type { VariantProps } from 'class-variance-authority';
2
2
  import type { FunctionComponent, ReactNode } from 'react';
3
3
  declare const eyebrow: (props?: ({
4
- color?: "muted" | "success" | "warning" | "error" | "info" | "foreground" | null | undefined;
4
+ color?: "warning" | "info" | "success" | "error" | "muted" | "foreground" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  interface IEyebrowProps extends VariantProps<typeof eyebrow> {
7
7
  children: ReactNode;
@@ -1,7 +1,7 @@
1
1
  import type { VariantProps } from 'class-variance-authority';
2
2
  import type { FunctionComponent, ReactNode } from 'react';
3
3
  declare const h1: (props?: ({
4
- color?: "muted" | "success" | "warning" | "error" | "info" | "foreground" | null | undefined;
4
+ color?: "warning" | "info" | "success" | "error" | "muted" | "foreground" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  interface IH1Props extends VariantProps<typeof h1> {
7
7
  children: ReactNode;
@@ -1,7 +1,7 @@
1
1
  import type { VariantProps } from 'class-variance-authority';
2
2
  import type { FunctionComponent, ReactNode } from 'react';
3
3
  declare const h2: (props?: ({
4
- color?: "muted" | "success" | "warning" | "error" | "info" | "foreground" | null | undefined;
4
+ color?: "warning" | "info" | "success" | "error" | "muted" | "foreground" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  interface IH2Props extends VariantProps<typeof h2> {
7
7
  children: ReactNode;
@@ -1,7 +1,7 @@
1
1
  import type { VariantProps } from 'class-variance-authority';
2
2
  import type { FunctionComponent, ReactNode } from 'react';
3
3
  declare const h3: (props?: ({
4
- color?: "muted" | "success" | "warning" | "error" | "info" | "foreground" | null | undefined;
4
+ color?: "warning" | "info" | "success" | "error" | "muted" | "foreground" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  interface IH3Props extends VariantProps<typeof h3> {
7
7
  children: ReactNode;
@@ -1,7 +1,7 @@
1
1
  import type { VariantProps } from 'class-variance-authority';
2
2
  import type { FunctionComponent, ReactNode } from 'react';
3
3
  declare const h4: (props?: ({
4
- color?: "muted" | "success" | "warning" | "error" | "info" | "foreground" | null | undefined;
4
+ color?: "warning" | "info" | "success" | "error" | "muted" | "foreground" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  interface IH4Props extends VariantProps<typeof h4> {
7
7
  children: ReactNode;
@@ -1,7 +1,7 @@
1
1
  import type { VariantProps } from 'class-variance-authority';
2
2
  import type { FunctionComponent, ReactNode } from 'react';
3
3
  declare const h5: (props?: ({
4
- color?: "muted" | "success" | "warning" | "error" | "info" | "foreground" | null | undefined;
4
+ color?: "warning" | "info" | "success" | "error" | "muted" | "foreground" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  interface IH5Props extends VariantProps<typeof h5> {
7
7
  children: ReactNode;
@@ -1,7 +1,7 @@
1
1
  import type { VariantProps } from 'class-variance-authority';
2
2
  import type { FunctionComponent, ReactNode } from 'react';
3
3
  declare const h6: (props?: ({
4
- color?: "muted" | "success" | "warning" | "error" | "info" | "foreground" | null | undefined;
4
+ color?: "warning" | "info" | "success" | "error" | "muted" | "foreground" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  interface IH6Props extends VariantProps<typeof h6> {
7
7
  children: ReactNode;
@@ -1,7 +1,9 @@
1
1
  import type { VariantProps } from 'class-variance-authority';
2
2
  import type { FunctionComponent, ReactNode } from 'react';
3
3
  declare const note: (props?: ({
4
- color?: "muted" | "success" | "warning" | "error" | "info" | "foreground" | null | undefined;
4
+ emphasis?: "strong" | "regular" | null | undefined;
5
+ truncate?: boolean | null | undefined;
6
+ color?: "warning" | "info" | "success" | "error" | "muted" | "foreground" | null | undefined;
5
7
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
8
  export interface INoteProps extends VariantProps<typeof note> {
7
9
  /** The annotation. A `ReactNode` rather than a string, because these lines carry inline links. */
@@ -12,16 +14,27 @@ export interface INoteProps extends VariantProps<typeof note> {
12
14
  * A short annotation at the small type role in the secondary family — a routing line above a submit
13
15
  * button, a privacy line at the point of submission, a line beside a control. Not reading matter:
14
16
  * it takes no measure and sits in no reading column, which is what separates it from `Prose.Tail`
15
- * at the same size, and it carries neither the tracking nor the weight that make an `Eyebrow`.
17
+ * at the same size. It carries no tracking and inherits weight unless emphasis is requested.
16
18
  *
17
19
  * @Guarantees — enforced on every render
18
20
  * - Renders a `p`, reading `--font-secondary` and sized by `--text-small`.
19
21
  * - `color` selects `foreground` (default), `muted`, `success`, `warning`, `error` or `info`;
20
22
  * nothing else paints text. A status tone changes colour only.
21
- * - Emits no tracking, no font-weight, no measure and no margin under any prop.
23
+ * - Emits no tracking, no measure and no margin under any prop.
22
24
  * - Carries no ARIA role and no live region under any prop.
25
+ * - `truncate` opts into one line with an ellipsis at the inline end, following inherited writing
26
+ * direction. The complete text stays in the DOM and accessibility tree. Omitted or false wraps
27
+ * as before. Marked text can shrink inside ordinary and allocated Table cells.
28
+ * - `emphasis="strong"` reads `--font-weight-strong` without changing size, family or line height.
29
+ * This is visual only: no `strong` element, importance semantics or live announcement is added.
30
+ * Omitted or `regular` leaves weight inherited, exactly as before.
23
31
  *
24
32
  * @CallerMustEnsure — the component cannot see these and does not check them
33
+ * - Communicate state in words or an accessible name; weight alone must never carry a state.
34
+ * - Allocate a width through the enclosing layout: truncated text does not size its holder.
35
+ * - Make the full wording reachable to sighted readers, for example by opening the item. Never
36
+ * truncate essential content without that path, or put links, controls or line breaks inside
37
+ * truncated text; use text and noninteractive inline phrasing only. No tooltip is added.
25
38
  * - The device has three carriers and this primitive is only one: use it for an annotation no other
26
39
  * component owns. A form's own message belongs to `Form`'s `note` and a table's to its note cell,
27
40
  * each painted by the component that owns it.
@@ -1,9 +1,11 @@
1
1
  import type { VariantProps } from 'class-variance-authority';
2
2
  import type { FunctionComponent, ReactNode } from 'react';
3
3
  declare const p: (props?: ({
4
- color?: "muted" | "success" | "warning" | "error" | "info" | "foreground" | null | undefined;
4
+ emphasis?: "strong" | "regular" | null | undefined;
5
+ truncate?: boolean | null | undefined;
6
+ color?: "warning" | "info" | "success" | "error" | "muted" | "foreground" | null | undefined;
5
7
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
- interface IPProps extends VariantProps<typeof p> {
8
+ export interface IPProps extends VariantProps<typeof p> {
7
9
  children: ReactNode;
8
10
  testId?: string;
9
11
  }
@@ -16,8 +18,19 @@ interface IPProps extends VariantProps<typeof p> {
16
18
  * theme re-points it, #120), sized by `--text-body` and led by `--leading-body`.
17
19
  * - `color` selects `foreground`, `muted`, `success`, `warning`, `error` or `info`; nothing else
18
20
  * paints text. A status tone changes colour only and adds no announcement semantics.
21
+ * - `truncate` opts into one line with an ellipsis at the inline end, following inherited writing
22
+ * direction. The complete text stays in the DOM and accessibility tree. Omitted or false wraps
23
+ * as before. Marked text can shrink inside ordinary and allocated Table cells.
24
+ * - `emphasis="strong"` reads `--font-weight-strong` without changing size, family or line height.
25
+ * This is visual only: no `strong` element, importance semantics or live announcement is added.
26
+ * Omitted or `regular` leaves weight inherited, exactly as before.
19
27
  *
20
28
  * @CallerMustEnsure — the component cannot see these and does not check them
29
+ * - Communicate state in words or an accessible name; weight alone must never carry a state.
30
+ * - Allocate a width through the enclosing layout: truncated text does not size its holder.
31
+ * - Make the full wording reachable to sighted readers, for example by opening the item. Never
32
+ * truncate essential content without that path, or put links, controls or line breaks inside
33
+ * truncated text; use text and noninteractive inline phrasing only. No tooltip is added.
21
34
  * - Where line length matters, place the paragraph inside whatever bounds the reading measure; `P`
22
35
  * does not constrain its own width.
23
36
  * - For a paragraph inside a reading column, reach for `Prose.Body`, which is measure-bounded by its
@@ -1,16 +1,20 @@
1
1
  import type { VariantProps } from 'class-variance-authority';
2
- import type { FunctionComponent, ReactNode } from 'react';
2
+ import { type FunctionComponent, type ReactNode } from 'react';
3
+ declare const proseRoot: (props?: ({
4
+ variant?: "default" | "letter" | null | undefined;
5
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
3
6
  declare const proseBody: (props?: ({
4
- color?: "muted" | "success" | "warning" | "error" | "info" | "foreground" | null | undefined;
7
+ letter?: boolean | null | undefined;
8
+ color?: "warning" | "info" | "success" | "error" | "muted" | "foreground" | null | undefined;
5
9
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
- interface IProseRootProps {
10
+ export interface IProseRootProps extends VariantProps<typeof proseRoot> {
7
11
  children?: ReactNode;
8
12
  testId?: string;
9
13
  }
10
14
  interface IProseLedeProps {
11
15
  children?: ReactNode;
12
16
  }
13
- interface IProseBodyProps extends VariantProps<typeof proseBody> {
17
+ interface IProseBodyProps extends Pick<VariantProps<typeof proseBody>, 'color'> {
14
18
  children?: ReactNode;
15
19
  }
16
20
  interface IProseTailProps {
@@ -22,15 +26,19 @@ interface IProseTailProps {
22
26
  * bounding the column. Composed from the four members; the consumer supplies the copy.
23
27
  *
24
28
  * @Guarantees — enforced on every render
25
- * - `Root` renders a `div` (never a `section`: it owns no landmark and no heading), capped at
29
+ * - Ordinary `Root` renders a `div` (never a `section`: it owns no landmark and no heading), capped at
26
30
  * `--measure`, setting no font-size so the `ch` measure resolves against inherited body type.
31
+ * - `Root variant="letter"` selects --measure-letter resolved against its own letter family and
32
+ * size, capped by available width. Body uses --text-letter and --leading-letter, and --font-letter
33
+ * falling back to --font-primary at the element. Lede and Tail keep their explicit roles.
27
34
  * - `Root` stacks its children on `--space-stack` and takes no outer margin: the page owns the
28
35
  * rhythm around the block, and the air the block wants is at its edges and inside the type.
29
- * - `Lede` renders a fixed-foreground `p` at the lede role; `Body` at the body role with a
36
+ * - `Lede` renders a fixed-foreground `p` at the lede role; `Body` at the selected root's role with a
30
37
  * `foreground`, `muted`, `success`, `warning`, `error` or `info` `color`; `Tail` at the small
31
38
  * role, always muted. A status tone changes colour only and adds no announcement semantics.
32
39
  *
33
40
  * @CallerMustEnsure — the component cannot see these and does not check them
41
+ * - Use Body throughout a letter, including the consumer-worded salutation and signature.
34
42
  * - Use `Prose.Body` for a paragraph inside this reading column; for a paragraph with no reading
35
43
  * column around it - in a form, a card, a table cell - use `P` instead.
36
44
  * - Status-toned content communicates its status without relying on colour. The caller owns any
@@ -2,9 +2,9 @@ import type { VariantProps } from 'class-variance-authority';
2
2
  import type { FunctionComponent, ReactNode } from 'react';
3
3
  import type { Subject } from 'rxjs';
4
4
  declare const button: (props?: ({
5
- variant?: "primary" | "secondary" | "ghost" | "outlined" | "destructive" | "plain" | null | undefined;
5
+ variant?: "link" | "primary" | "secondary" | "ghost" | "outlined" | "destructive" | "plain" | null | undefined;
6
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
- interface IButtonProps extends VariantProps<typeof button> {
7
+ export interface IButtonProps extends VariantProps<typeof button> {
8
8
  /** Optional: an icon-only button renders none, and names itself with `ariaLabel` instead. */
9
9
  children?: ReactNode;
10
10
  onClick$?: Subject<void>;
@@ -45,17 +45,23 @@ interface IButtonProps extends VariantProps<typeof button> {
45
45
  * text around it, with no face, padding, corner or hover underline of its own. Reach for it where
46
46
  * the action belongs to a line of content - a sortable column header composed with `Icon` - and
47
47
  * for `ghost` where a quiet but still button-shaped action is wanted
48
+ * - `link` is an inline action with the prose Link treatment: persistent underline and link ink,
49
+ * inheriting the surrounding face, size and line height, with no inset, corner or minimum width.
50
+ * Use `Link` when there is an address; use `Button variant="link"` with `onClick$` when there is
51
+ * none. The consumer owns the action and navigation. Supply text, not nested interactive content.
48
52
  * - Maintain consistent button styling throughout the application
49
53
  * - Provide visual feedback on hover/active states
50
- * - Ensure sufficient touch target size (minimum 44x44px) for mobile users
54
+ * - Inline actions take their target size from the surrounding text; use faced actions for standalone controls
51
55
  * - Position primary actions on the right for multi-button layouts
52
56
  * - A submit button's busy state is a label swap ("Send" to "Sending…"), never a spinner: it costs
53
57
  * nothing to render server-side and keeps a Form's `sending` state driver-agnostic
54
58
  *
55
59
  * @Accessibility
56
60
  * - Ensure adequate color contrast (4.5:1 minimum ratio)
57
- * - Provide focus styles for keyboard navigation: every variant, `plain` included, draws the shared
61
+ * - Provide focus styles for keyboard navigation: every variant, including `plain` and `link`, draws the shared
58
62
  * focus ring and nothing else changes on focus
63
+ * - A disabled `link` retains its underline, uses the disabled ink and does not thicken on hover.
64
+ * Native disabled semantics prevent activation and remove it from the tab sequence.
59
65
  * - A disabled `plain` button is told apart by the `disabled` text tone and keeps native disabled semantics
60
66
  * - Use appropriate ARIA attributes when needed
61
67
  * - Status colour never stands alone: a destructive action is named by its words or symbol
@@ -42,5 +42,8 @@ export interface ISliderProps {
42
42
  * `Input` too: visible, associated, and the only text the component renders (#112). It is still
43
43
  * a live control and not a form field, so none of Input's annotations - hint, error, optional
44
44
  * marker - come with it. `disabled` is the explicit non-operable state.
45
+ *
46
+ * An off-range value renders at the nearest bound through the native control. The consumer still
47
+ * owns the value: the clamped position is not emitted on `onInput$` until the user moves the thumb.
45
48
  */
46
49
  export declare const Slider: FunctionComponent<ISliderProps>;
@@ -0,0 +1,59 @@
1
+ import { type FunctionComponent, type ReactNode } from 'react';
2
+ import type { Observable, Subject } from 'rxjs';
3
+ export interface IStepperRootProps {
4
+ /** Consumer-owned selection. No panel is active before this source first emits. */
5
+ active$: Observable<string>;
6
+ /** Requests selection, including blocked steps, without changing the input. */
7
+ onSelect$: Subject<string>;
8
+ label: string;
9
+ children: ReactNode;
10
+ testId?: string;
11
+ }
12
+ export interface IStepperListProps {
13
+ children: ReactNode;
14
+ testId?: string;
15
+ }
16
+ export interface IStepperStepProps {
17
+ /** Stable identity, unique within Root, paired with exactly one Panel. */
18
+ value: string;
19
+ label: string;
20
+ status: 'done' | 'open' | 'blocked';
21
+ /** Noninteractive consumer content, rendered whole and included in the accessible name. */
22
+ valueText: ReactNode;
23
+ /** Optional visible wording, associated as the control's accessible description. */
24
+ statusContent?: ReactNode;
25
+ testId?: string;
26
+ }
27
+ export interface IStepperPanelProps {
28
+ /** The tab this panel belongs to - exactly one panel per tab value within a Root. */
29
+ value: string;
30
+ /** Mounted only while active; departure unmounts it, return mounts it fresh. */
31
+ children: ReactNode;
32
+ testId?: string;
33
+ }
34
+ /**
35
+ * Connected form steps with independent status and consumer-controlled selection.
36
+ * @Guarantees
37
+ * - Root observes active$ and emits identities through onSelect$ without changing selection.
38
+ * - Source replacement clears selection until the new source emits; subscriptions tear down.
39
+ * - Done and blocked steps remain selectable. Left/Right wraps focus and requests selection.
40
+ * - Label and value text name each tab; optional visible status content describes it.
41
+ * - Only the active panel mounts content; returning mounts fresh with no state cache.
42
+ * - The row wraps text before scrolling horizontally and reveals focused steps.
43
+ * - Root takes its parent's height; Panel passes the remainder without owning scrolling.
44
+ * An unsized parent retains natural content height.
45
+ * @CallerMustEnsure
46
+ * - Supply a valid selected identity, unique stable Step values and matching Panels.
47
+ * - Compose one List of direct Steps (arrays/fragments supported), no wrapper components.
48
+ * - For bounded content, List and Panels are direct DOM children of Root and the Panel's
49
+ * direct child accepts height (for example Pane). Fixed content must leave usable body space.
50
+ * - Value and status slots contain no interactive descendants. Supply localized status wording
51
+ * when spoken status is needed; the library supplies shapes but no status translations.
52
+ * - Persist form state outside Stepper and restore it into controls when they mount.
53
+ */
54
+ export declare const Stepper: {
55
+ readonly Root: FunctionComponent<IStepperRootProps>;
56
+ readonly List: FunctionComponent<IStepperListProps>;
57
+ readonly Step: FunctionComponent<IStepperStepProps>;
58
+ readonly Panel: FunctionComponent<IStepperPanelProps>;
59
+ };
@@ -0,0 +1,3 @@
1
+ export declare class StepperCompositionError extends Error {
2
+ constructor(member: string);
3
+ }
@@ -0,0 +1,20 @@
1
+ import { type FunctionComponent } from 'react';
2
+ import type { Observable, Subject } from 'rxjs';
3
+ export interface ISwitchProps {
4
+ /** A visible, stable name for the setting, not a changing on/off caption. */
5
+ label: string;
6
+ /** Consumer-owned state. Off until the current source first emits, including on replacement. */
7
+ checked$: Observable<boolean>;
8
+ /** Requests the opposite of the displayed state; only an input emission changes the display. */
9
+ onChange$: Subject<boolean>;
10
+ /** Native disabled conduct; the current state remains visible. */
11
+ disabled?: boolean;
12
+ testId?: string;
13
+ }
14
+ /**
15
+ * One immediate binary setting, named by its visible label. A native button supplies a single
16
+ * tab stop and Space/Enter activation without submitting a surrounding form. Thumb position and
17
+ * aria-checked expose the input state; neither activation nor focus changes it independently.
18
+ * Use Choices for described alternatives, or a checkbox in a Form for a submitted selection.
19
+ */
20
+ export declare const Switch: FunctionComponent<ISwitchProps>;