@godxjp/ui 18.6.0 → 18.8.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 (53) hide show
  1. package/dist/components/data-display/card.d.ts +27 -3
  2. package/dist/components/data-display/card.js +4 -1
  3. package/dist/components/data-entry/input-otp.d.ts +1 -1
  4. package/dist/components/feedback/alert.d.ts +20 -2
  5. package/dist/components/feedback/alert.js +11 -1
  6. package/dist/components/feedback/index.d.ts +2 -2
  7. package/dist/components/feedback/index.js +3 -1
  8. package/dist/components/layout/auth-shell.d.ts +4 -2
  9. package/dist/components/layout/index.d.ts +2 -0
  10. package/dist/components/layout/index.js +2 -0
  11. package/dist/components/layout/page-container.d.ts +1 -1
  12. package/dist/components/layout/page-container.js +19 -41
  13. package/dist/components/layout/page-header.d.ts +22 -0
  14. package/dist/components/layout/page-header.js +89 -0
  15. package/dist/components/navigation/filter-bar.d.ts +2 -2
  16. package/dist/components/navigation/filter-bar.js +44 -1
  17. package/dist/components/navigation/index.d.ts +1 -1
  18. package/dist/components/navigation/steps.d.ts +2 -2
  19. package/dist/components/navigation/steps.js +4 -2
  20. package/dist/components/ui/avatar.d.ts +1 -1
  21. package/dist/components/ui/avatar.js +2 -1
  22. package/dist/components/ui/input-otp.d.ts +15 -3
  23. package/dist/components/ui/input-otp.js +2 -1
  24. package/dist/email/tokens.generated.d.ts +2 -2
  25. package/dist/email/tokens.generated.js +2 -2
  26. package/dist/i18n/messages/en.json +11 -0
  27. package/dist/i18n/messages/ja.json +8 -0
  28. package/dist/i18n/messages/vi.json +8 -0
  29. package/dist/props/components/data-display.prop.d.ts +16 -0
  30. package/dist/props/components/data-entry.prop.d.ts +7 -0
  31. package/dist/props/components/feedback.prop.d.ts +6 -0
  32. package/dist/props/components/layout.prop.d.ts +53 -0
  33. package/dist/props/components/navigation.prop.d.ts +61 -0
  34. package/dist/props/registry.d.ts +75 -1
  35. package/dist/props/registry.js +96 -1
  36. package/dist/props/vocabulary/interaction.prop.d.ts +10 -2
  37. package/dist/props/vocabulary/layout.prop.d.ts +5 -2
  38. package/dist/styles/alert-layout.css +36 -0
  39. package/dist/styles/card-layout.css +49 -13
  40. package/dist/styles/control.css +12 -2
  41. package/dist/styles/data-display-layout.css +16 -0
  42. package/dist/styles/layout.css +113 -0
  43. package/dist/styles/navigation-layout.css +8 -3
  44. package/dist/styles/shell-layout.css +44 -1
  45. package/dist/tokens/components/card.css +12 -0
  46. package/dist/tokens/components/control.css +16 -0
  47. package/dist/tokens/components/data-display.css +12 -0
  48. package/dist/tokens/components/email.css +8 -2
  49. package/dist/tokens/components/feedback.css +20 -0
  50. package/dist/tokens/components/navigation.css +35 -0
  51. package/dist/tokens/components/shell.css +64 -4
  52. package/dist/tokens/semantic/layout.css +13 -0
  53. package/package.json +2 -2
@@ -4,11 +4,12 @@ import * as React from "react";
4
4
  import { OTPInput, OTPInputContext } from "input-otp";
5
5
  import { Minus } from "lucide-react";
6
6
  import { cn } from "../../lib/utils.js";
7
- const InputOTP = React.forwardRef(({ className, containerClassName, ...props }, ref) => /* @__PURE__ */ jsx(
7
+ const InputOTP = React.forwardRef(({ className, containerClassName, align, ...props }, ref) => /* @__PURE__ */ jsx(
8
8
  OTPInput,
9
9
  {
10
10
  ref,
11
11
  "data-slot": "input-otp",
12
+ "data-align": align && align !== "start" ? align : void 0,
12
13
  containerClassName: cn("ui-otp-container", containerClassName),
13
14
  className: cn("ui-otp-input", className),
14
15
  ...props
@@ -146,8 +146,8 @@ export declare const EMAIL_GEOMETRY_SOURCE: {
146
146
  readonly "--email-heading-font-size": "17px";
147
147
  readonly "--email-heading-line-height": "1.7";
148
148
  readonly "--email-heading-font-weight": "500";
149
- readonly "--email-cta-height": "36px";
150
- readonly "--email-cta-line-height": "36px";
149
+ readonly "--email-cta-height": "44px";
150
+ readonly "--email-cta-line-height": "44px";
151
151
  readonly "--email-cta-padding-x": "16px";
152
152
  readonly "--email-cta-radius": "6px";
153
153
  readonly "--email-cta-font-size": "14px";
@@ -136,8 +136,8 @@ const EMAIL_GEOMETRY_SOURCE = {
136
136
  "--email-heading-font-size": "17px",
137
137
  "--email-heading-line-height": "1.7",
138
138
  "--email-heading-font-weight": "500",
139
- "--email-cta-height": "36px",
140
- "--email-cta-line-height": "36px",
139
+ "--email-cta-height": "44px",
140
+ "--email-cta-line-height": "44px",
141
141
  "--email-cta-padding-x": "16px",
142
142
  "--email-cta-radius": "6px",
143
143
  "--email-cta-font-size": "14px",
@@ -135,6 +135,9 @@
135
135
  "openNav": "Open navigation menu",
136
136
  "navLabel": "Menu"
137
137
  },
138
+ "pageHeader": {
139
+ "loading": "Loading page…"
140
+ },
138
141
  "authShell": {
139
142
  "brandLabel": "Brand",
140
143
  "mainLabel": "Main content",
@@ -227,6 +230,14 @@
227
230
  "toolbar": {
228
231
  "ariaLabel": "Filters"
229
232
  },
233
+ "filterBar": {
234
+ "appliedFilters": "Applied filters",
235
+ "removeFilter": "Remove filter {label}",
236
+ "resultCount": {
237
+ "one": "{count} result",
238
+ "other": "{count} results"
239
+ }
240
+ },
230
241
  "localePicker": {
231
242
  "ariaLabel": "Language"
232
243
  },
@@ -135,6 +135,9 @@
135
135
  "openNav": "ナビゲーションメニューを開く",
136
136
  "navLabel": "メニュー"
137
137
  },
138
+ "pageHeader": {
139
+ "loading": "ページを読み込んでいます…"
140
+ },
138
141
  "authShell": {
139
142
  "brandLabel": "ブランド",
140
143
  "mainLabel": "メインコンテンツ",
@@ -227,6 +230,11 @@
227
230
  "toolbar": {
228
231
  "ariaLabel": "フィルター"
229
232
  },
233
+ "filterBar": {
234
+ "appliedFilters": "適用中のフィルター",
235
+ "removeFilter": "フィルター「{label}」を解除",
236
+ "resultCount": "{count} 件"
237
+ },
230
238
  "localePicker": {
231
239
  "ariaLabel": "言語"
232
240
  },
@@ -135,6 +135,9 @@
135
135
  "openNav": "Mở menu điều hướng",
136
136
  "navLabel": "Menu"
137
137
  },
138
+ "pageHeader": {
139
+ "loading": "Đang tải trang…"
140
+ },
138
141
  "authShell": {
139
142
  "brandLabel": "Thương hiệu",
140
143
  "mainLabel": "Nội dung chính",
@@ -227,6 +230,11 @@
227
230
  "toolbar": {
228
231
  "ariaLabel": "Bộ lọc"
229
232
  },
233
+ "filterBar": {
234
+ "appliedFilters": "Bộ lọc đang áp dụng",
235
+ "removeFilter": "Bỏ bộ lọc {label}",
236
+ "resultCount": "{count} kết quả"
237
+ },
230
238
  "localePicker": {
231
239
  "ariaLabel": "Ngôn ngữ"
232
240
  },
@@ -62,9 +62,25 @@ export type DescriptionsItemProp = {
62
62
  */
63
63
  export type AvatarProp = React.ComponentPropsWithoutRef<"span"> & {
64
64
  shape?: AvatarShapeProp;
65
+ appearance?: AvatarAppearanceProp;
65
66
  className?: ClassNameProp;
66
67
  children?: ChildrenProp;
67
68
  };
69
+ /**
70
+ * Avatar fill treatment.
71
+ *
72
+ * - `"default"` — the identity fill: `--muted` for a person, the solid brand mark for
73
+ * `shape="square"`.
74
+ * - `"tinted"` — the **capability medallion**: a soft role wash behind a role-coloured glyph.
75
+ * This is the plate a capability/feature icon sits on (`shape="square" appearance="tinted"` for
76
+ * the canonical rounded square). It exists because the medallion is a composition — `Avatar` +
77
+ * a Lucide glyph, per docs/COMPOSITION-VS-COMPONENT.md — but its *tint* was not reachable from
78
+ * a token, so consumers were re-deriving `hsl(var(--primary) / 0.1)` in page CSS or giving up
79
+ * and rendering a bare glyph. Retune with `--avatar-tinted-*`.
80
+ *
81
+ * @see Avatar
82
+ */
83
+ export type AvatarAppearanceProp = "default" | "tinted";
68
84
  /** @see Badge */
69
85
  export type BadgeProp = {
70
86
  variant?: "default" | "secondary" | "outline";
@@ -16,6 +16,13 @@ export type InputOTPGroupAppearanceProp = "slots" | "grouped";
16
16
  export type InputOTPGroupProp = React.HTMLAttributes<HTMLDivElement> & {
17
17
  appearance?: InputOTPGroupAppearanceProp;
18
18
  };
19
+ /**
20
+ * Main-axis alignment of the whole code row (groups + separators) inside its container.
21
+ * `start` is the historical default. A centred challenge is the common auth case and used to
22
+ * force every consumer to wrap `.ui-otp-container` in their own flex-centring div.
23
+ * @see InputOTP
24
+ */
25
+ export type InputOTPAlignProp = "start" | "center" | "end";
19
26
  /** @see Input */
20
27
  export type InputProp = React.InputHTMLAttributes<HTMLInputElement> & {
21
28
  /** Show an inline ✕ that clears the field while it holds text (default false). */
@@ -42,6 +42,12 @@ export type AlertProp = React.HTMLAttributes<HTMLDivElement> & {
42
42
  className?: ClassNameProp;
43
43
  children?: ChildrenProp;
44
44
  };
45
+ /**
46
+ * @see Banner — page-level Alert. `variant` is fixed to `"banner"` by the alias, so it is the one
47
+ * prop a Banner does not take; everything else (tone, icon, onDismiss, children) is Alert's
48
+ * contract verbatim. gh#255.
49
+ */
50
+ export type BannerProp = Omit<AlertProp, "variant">;
45
51
  /** @see AlertTitle */
46
52
  export type AlertTitleProp = React.HTMLAttributes<HTMLParagraphElement> & {
47
53
  className?: ClassNameProp;
@@ -24,10 +24,55 @@ export type PageContainerPresetProp = "default" | "admin-collection";
24
24
  * fluid at the compact gutter.
25
25
  */
26
26
  export type PageContainerMeasureProp = "default" | "narrow" | "medium";
27
+ /**
28
+ * @see PageHeader — the canonical page title band, extracted from PageContainer so a consumer can
29
+ * mount the SAME token-owned geometry outside a full page shell (a Sheet detail, a MasterDetail
30
+ * pane, a tab body) instead of re-authoring `.ui-page-header` CSS locally (gh#255).
31
+ */
32
+ export type PageHeaderProp = {
33
+ title: TitleProp;
34
+ subtitle?: SubtitleProp;
35
+ /**
36
+ * Status / meta band rendered INLINE with the title (a `Badge` tone, an ID, a timestamp).
37
+ * Omitted → the title band emits its historical single-`<h1>` DOM, so no existing page moves.
38
+ */
39
+ meta?: ReactNode;
40
+ /** Trailing action region — buttons, a search field, an overflow menu. */
41
+ extra?: ExtraProp;
42
+ breadcrumb?: BreadcrumbProp;
43
+ /**
44
+ * Override the breadcrumb `<nav>` landmark's accessible name. Defaults to a localized
45
+ * "Breadcrumb". Needed when more than one header (each with its own `breadcrumb`) renders on the
46
+ * same page/view — two `<nav>` landmarks sharing one name/role fail axe's `landmark-unique`
47
+ * (WCAG 2.4.1 / 1.3.1).
48
+ */
49
+ breadcrumbLabel?: string;
50
+ /** Kebab/DOM-style alias of `breadcrumbLabel` (same landmark-unique override). */
51
+ breadcrumbAriaLabel?: string;
52
+ linkComponent?: React.ElementType;
53
+ /**
54
+ * How the title band and `extra` share the header row below the 640px step. Defaults to
55
+ * `stack`. @see PageContainerHeaderLayoutProp
56
+ */
57
+ layout?: PageContainerHeaderLayoutProp;
58
+ /**
59
+ * Pending state for the title band while the page's own data resolves. Renders the title/subtitle
60
+ * /meta as `Skeleton` placeholders and marks the header `aria-busy`, keeping the `<h1>` in the
61
+ * document with an accessible name (an empty heading is an axe violation) so the page's heading
62
+ * outline never disappears mid-load. Breadcrumbs and `extra` are NOT skeletonised — they come
63
+ * from the route, not the record.
64
+ */
65
+ loading?: boolean;
66
+ className?: ClassNameProp;
67
+ };
27
68
  /** @see PageContainer */
28
69
  export type PageContainerProp = {
29
70
  title: TitleProp;
30
71
  subtitle?: SubtitleProp;
72
+ /** Status / meta band rendered inline with the title. @see PageHeaderProp.meta */
73
+ meta?: ReactNode;
74
+ /** Skeletonise the title band while the page record loads. @see PageHeaderProp.loading */
75
+ headerLoading?: boolean;
31
76
  extra?: ExtraProp;
32
77
  footer?: FooterProp;
33
78
  breadcrumb?: BreadcrumbProp;
@@ -240,6 +285,14 @@ export type AuthShellProp = {
240
285
  * so standalone, one-line requester and wrapped two-line requester states keep the same card
241
286
  * position without truncating or inventing requester data. Pass AuthIdentity, Card and
242
287
  * AuthFooter as direct children (an anchor may wrap AuthIdentity).
288
+ * - `"registration"` — the 360px sign-up measure with a 15px inline gutter at 390px (the same
289
+ * page rhythm as `"login"`, so sign-in → sign-up never jumps on a phone). The ONLY preset whose
290
+ * column is START-aligned: a registration card is the tallest surface in the hosted-identity
291
+ * set (name · email · password · confirm · strength · consent · submit · providers), and a
292
+ * vertically centred tall card overflows ABOVE the scroll origin on a short viewport, putting
293
+ * its first field out of reach. It is also the only preset with a footer-clearance knob of its
294
+ * own, so the legal/consent footer never sits flush against the submit button. Carries the full
295
+ * password form and the pending-email confirmation state with no consumer geometry CSS.
243
296
  * - `"device-authorization"` — 380px card measure with a 5px inline page gutter at a 390px
244
297
  * viewport (canonical device-grant artboard).
245
298
  * - `"context-selection"` — 25rem card measure on desktop/tablet, edge-to-edge on mobile, and a
@@ -7,10 +7,62 @@ import type { ChildrenProp, ClassNameProp, DisabledProp, HasActiveFiltersProp, I
7
7
  * bounded row that scrolls inline, so a wide filter set never pushes the list below the fold.
8
8
  */
9
9
  export type FilterBarOverflowProp = "wrap" | "scroll";
10
+ /**
11
+ * One APPLIED filter, rendered as a removable chip under the control row (#258).
12
+ *
13
+ * The chip is the visible record of a filter that is already in effect — it is NOT the control that
14
+ * sets it. `label` is caller-localized text (the bar never interprets or formats domain values);
15
+ * omit `onRemove` for a chip the user may not lift (a scope locked by the route or by permission),
16
+ * and the chip renders as a static token with no dead button.
17
+ */
18
+ export type FilterBarChipProp = {
19
+ /** Stable identity — also the argument passed back to {@link ToolbarProp.onChipRemove}. */
20
+ id: string;
21
+ /** Already-localized chip text, e.g. "状態: 未払い". */
22
+ label: string;
23
+ /**
24
+ * Per-chip removal. Omit for a chip the user cannot lift; the bar then renders no remove control
25
+ * rather than a disabled one, so nothing focusable is dead.
26
+ */
27
+ onRemove?: () => void;
28
+ };
10
29
  /** @see Toolbar */
11
30
  export type ToolbarProp = {
12
31
  onClear?: OnClearFiltersProp;
13
32
  hasActiveFilters?: HasActiveFiltersProp;
33
+ /**
34
+ * The search control (#258). A slot, not a rendered input: the bar owns its MEASURE
35
+ * (`--filter-bar-search-width`) and its position at the START of the row, while the caller
36
+ * still chooses the real primitive (`SearchInput`, or a `Select showSearch` for scoped search)
37
+ * and owns its debounce and value. Passing the control as a child instead is what produced the
38
+ * inconsistent search widths the issue was filed against.
39
+ */
40
+ search?: ChildrenProp;
41
+ /**
42
+ * Applied filters as removable chips (#258). The bar owns the CHIP LIFECYCLE — chips render
43
+ * below the control row, each with an accessible remove control, and the row disappears entirely
44
+ * when the array is empty (never an empty reserved strip). It owns no state: removing a chip
45
+ * calls back and the caller re-renders the array.
46
+ */
47
+ chips?: readonly FilterBarChipProp[];
48
+ /**
49
+ * Called with the chip's `id` when its remove control is activated. Fires in addition to that
50
+ * chip's own `onRemove`, so a caller may handle removal per chip, centrally, or both.
51
+ */
52
+ onChipRemove?: (id: string) => void;
53
+ /**
54
+ * Number of records the current filters resolve to (#258). Rendered in a POLITE LIVE REGION and
55
+ * formatted with `Intl.NumberFormat` + CLDR plurals for the active locale — which is the point:
56
+ * a sighted user sees the table change, and this is what tells everyone else that filtering
57
+ * happened. Omit when the count is unknown or still loading.
58
+ */
59
+ resultCount?: number;
60
+ /**
61
+ * Trailing action region (#258) — export, column settings, a saved-view menu. Rendered AFTER the
62
+ * reset control, so "clear filters" never sits at the end of the row beside an unrelated primary
63
+ * action. The bar owns the ordering; the caller owns the controls.
64
+ */
65
+ actions?: ChildrenProp;
14
66
  /**
15
67
  * Pin the strip to the top of its scroll container while the list scrolls beneath it
16
68
  * (list-page filter bars, #197). Opt-in — default `false` keeps the toolbar quiet. Tune
@@ -92,9 +144,18 @@ export type StepsProp = {
92
144
  type?: "default" | "dot" | "inline";
93
145
  size?: "md" | "sm";
94
146
  titlePlacement?: "horizontal" | "vertical";
147
+ /**
148
+ * The glyph between inline steps (`type="inline"` only). `chevron` (default, `›`) is the
149
+ * breadcrumb-flavoured original. `arrow` (`→`) is the canonical hosted-identity progression
150
+ * marker: a chevron reads as "drill into", an arrow reads as "then" — which is what a step row
151
+ * means. Ignored by every other `type`.
152
+ */
153
+ separator?: StepsSeparatorProp;
95
154
  onValueChange?: (value: number) => void;
96
155
  className?: ClassNameProp;
97
156
  };
157
+ /** @see Steps — inline separator glyph. */
158
+ export type StepsSeparatorProp = "chevron" | "arrow";
98
159
  /** Tab pane — Ant Design `items` entry. */
99
160
  export type TabItemProp = {
100
161
  value: string;
@@ -461,10 +461,35 @@ export declare const COMPONENT_PROP_REGISTRY: {
461
461
  readonly file: "components/layout.prop.ts";
462
462
  readonly vocabulary: readonly [];
463
463
  };
464
+ readonly PageHeaderProp: {
465
+ readonly group: "layout";
466
+ readonly file: "components/layout.prop.ts";
467
+ readonly vocabulary: readonly ["TitleProp", "SubtitleProp", "ExtraProp", "BreadcrumbProp", {
468
+ readonly field: "meta";
469
+ readonly local: true;
470
+ readonly reason: "Status/meta band rendered inline with the `<h1>` (a Badge tone, a record id, a timestamp). A free ReactNode slot, not a controlled value — the header never interprets what it holds.";
471
+ }, {
472
+ readonly field: "layout";
473
+ readonly local: true;
474
+ readonly reason: "Header ARRANGEMENT of the title band vs the extra slot below the 640px step (stack | responsive-inline) — the standalone spelling of PageContainer's `headerLayout`.";
475
+ }, {
476
+ readonly field: "loading";
477
+ readonly local: true;
478
+ readonly reason: "Pending state of the TITLE BAND only (skeleton title/subtitle + aria-busy), distinct from a page-wide DataState: breadcrumbs and actions come from the route and stay live while the record resolves.";
479
+ }];
480
+ };
464
481
  readonly PageContainerProp: {
465
482
  readonly group: "layout";
466
483
  readonly file: "components/layout.prop.ts";
467
484
  readonly vocabulary: readonly ["TitleProp", "SubtitleProp", "ExtraProp", "FooterProp", "BreadcrumbProp", "DensityProp", "PageContainerVariantProp", {
485
+ readonly field: "meta";
486
+ readonly local: true;
487
+ readonly reason: "Forwarded verbatim to PageHeader's `meta` slot — see PageHeaderProp.";
488
+ }, {
489
+ readonly field: "headerLoading";
490
+ readonly local: true;
491
+ readonly reason: "Forwarded to PageHeader's `loading`. Named for the BAND it skeletonises, so it can never be read as a page-wide loading flag (that is DataState's job).";
492
+ }, {
468
493
  readonly field: "headerLayout";
469
494
  readonly local: true;
470
495
  readonly reason: "Header ARRANGEMENT of the title band vs the extra slot below the 640px step (stack | responsive-inline) — orthogonal to PageContainerVariantProp, which selects the page shell layout.";
@@ -1038,6 +1063,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
1038
1063
  readonly file: "components/data-display.prop.ts";
1039
1064
  readonly vocabulary: readonly ["AvatarShapeProp", "ChildrenProp", "ClassNameProp"];
1040
1065
  };
1066
+ readonly AvatarAppearanceProp: {
1067
+ readonly group: "data-display";
1068
+ readonly file: "components/data-display.prop.ts";
1069
+ readonly vocabulary: readonly [];
1070
+ };
1041
1071
  readonly BadgeProp: {
1042
1072
  readonly group: "data-display";
1043
1073
  readonly file: "components/data-display.prop.ts";
@@ -1350,6 +1380,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
1350
1380
  readonly file: "components/feedback.prop.ts";
1351
1381
  readonly vocabulary: readonly ["AlertVariantProp", "ToneProp", "IconProp", "OnValueChangeProp", "ClassNameProp", "ChildrenProp"];
1352
1382
  };
1383
+ readonly BannerProp: {
1384
+ readonly group: "feedback";
1385
+ readonly file: "components/feedback.prop.ts";
1386
+ readonly vocabulary: readonly ["ToneProp", "IconProp", "OnValueChangeProp", "ClassNameProp", "ChildrenProp"];
1387
+ };
1353
1388
  readonly AlertTitleProp: {
1354
1389
  readonly group: "feedback";
1355
1390
  readonly file: "components/feedback.prop.ts";
@@ -1383,7 +1418,36 @@ export declare const COMPONENT_PROP_REGISTRY: {
1383
1418
  readonly ToolbarProp: {
1384
1419
  readonly group: "navigation";
1385
1420
  readonly file: "components/navigation.prop.ts";
1386
- readonly vocabulary: readonly ["OnClearFiltersProp", "HasActiveFiltersProp", "StickyProp", "ClassNameProp", "ChildrenProp"];
1421
+ readonly vocabulary: readonly ["OnClearFiltersProp", "HasActiveFiltersProp", "StickyProp", "ClassNameProp", "ChildrenProp", {
1422
+ readonly field: "search";
1423
+ readonly local: true;
1424
+ readonly reason: "SLOT for the caller's own search control, positioned at the start of the row and measured by --filter-bar-search-width. Not a value/onValueChange pair: the bar owns the search's PLACE and WIDTH, never its state (gh#258).";
1425
+ }, {
1426
+ readonly field: "chips";
1427
+ readonly local: true;
1428
+ readonly reason: "APPLIED filters as removable chips — the visible record of filters already in effect, distinct from the controls that set them. A bar-specific shape (id/label/onRemove), not a shared vocabulary type (gh#258).";
1429
+ }, {
1430
+ readonly field: "onChipRemove";
1431
+ readonly local: true;
1432
+ readonly reason: "Chip-removal callback keyed by chip id. Not `onValueChange`: it reports ONE lifted filter rather than the bar's whole value, which the bar deliberately does not hold (gh#258).";
1433
+ }, {
1434
+ readonly field: "resultCount";
1435
+ readonly local: true;
1436
+ readonly reason: "Number of records the current filters resolve to, announced in a polite live region and formatted via Intl.NumberFormat + CLDR plurals. Presentational output, not a controlled value (gh#258).";
1437
+ }, {
1438
+ readonly field: "actions";
1439
+ readonly local: true;
1440
+ readonly reason: "Trailing action SLOT (export, column settings, saved views), ordered AFTER the reset control by the bar so `clear filters` never sits beside an unrelated primary action (gh#258).";
1441
+ }];
1442
+ };
1443
+ readonly FilterBarChipProp: {
1444
+ readonly group: "navigation";
1445
+ readonly file: "components/navigation.prop.ts";
1446
+ readonly vocabulary: readonly ["IdProp", "LabelProp", {
1447
+ readonly field: "onRemove";
1448
+ readonly local: true;
1449
+ readonly reason: "Per-chip removal. Omitting it is meaningful — the chip renders with NO remove control (a filter the user may not lift), rather than a disabled button that is a dead tab stop (gh#258).";
1450
+ }];
1387
1451
  };
1388
1452
  readonly FilterBarOverflowProp: {
1389
1453
  readonly group: "navigation";
@@ -1415,6 +1479,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
1415
1479
  readonly file: "components/data-entry.prop.ts";
1416
1480
  readonly vocabulary: readonly [];
1417
1481
  };
1482
+ readonly InputOTPAlignProp: {
1483
+ readonly group: "data-entry";
1484
+ readonly file: "components/data-entry.prop.ts";
1485
+ readonly vocabulary: readonly [];
1486
+ };
1418
1487
  readonly StepItemProp: {
1419
1488
  readonly group: "navigation";
1420
1489
  readonly file: "components/navigation.prop.ts";
@@ -1425,6 +1494,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
1425
1494
  readonly file: "components/navigation.prop.ts";
1426
1495
  readonly vocabulary: readonly [];
1427
1496
  };
1497
+ readonly StepsSeparatorProp: {
1498
+ readonly group: "navigation";
1499
+ readonly file: "components/navigation.prop.ts";
1500
+ readonly vocabulary: readonly [];
1501
+ };
1428
1502
  readonly TabsProp: {
1429
1503
  readonly group: "navigation";
1430
1504
  readonly file: "components/navigation.prop.ts";
@@ -465,6 +465,31 @@ const COMPONENT_PROP_REGISTRY = {
465
465
  file: "components/layout.prop.ts",
466
466
  vocabulary: []
467
467
  },
468
+ PageHeaderProp: {
469
+ group: "layout",
470
+ file: "components/layout.prop.ts",
471
+ vocabulary: [
472
+ "TitleProp",
473
+ "SubtitleProp",
474
+ "ExtraProp",
475
+ "BreadcrumbProp",
476
+ {
477
+ field: "meta",
478
+ local: true,
479
+ reason: "Status/meta band rendered inline with the `<h1>` (a Badge tone, a record id, a timestamp). A free ReactNode slot, not a controlled value \u2014 the header never interprets what it holds."
480
+ },
481
+ {
482
+ field: "layout",
483
+ local: true,
484
+ reason: "Header ARRANGEMENT of the title band vs the extra slot below the 640px step (stack | responsive-inline) \u2014 the standalone spelling of PageContainer's `headerLayout`."
485
+ },
486
+ {
487
+ field: "loading",
488
+ local: true,
489
+ reason: "Pending state of the TITLE BAND only (skeleton title/subtitle + aria-busy), distinct from a page-wide DataState: breadcrumbs and actions come from the route and stay live while the record resolves."
490
+ }
491
+ ]
492
+ },
468
493
  PageContainerProp: {
469
494
  group: "layout",
470
495
  file: "components/layout.prop.ts",
@@ -476,6 +501,16 @@ const COMPONENT_PROP_REGISTRY = {
476
501
  "BreadcrumbProp",
477
502
  "DensityProp",
478
503
  "PageContainerVariantProp",
504
+ {
505
+ field: "meta",
506
+ local: true,
507
+ reason: "Forwarded verbatim to PageHeader's `meta` slot \u2014 see PageHeaderProp."
508
+ },
509
+ {
510
+ field: "headerLoading",
511
+ local: true,
512
+ reason: "Forwarded to PageHeader's `loading`. Named for the BAND it skeletonises, so it can never be read as a page-wide loading flag (that is DataState's job)."
513
+ },
479
514
  {
480
515
  field: "headerLayout",
481
516
  local: true,
@@ -1189,6 +1224,11 @@ const COMPONENT_PROP_REGISTRY = {
1189
1224
  file: "components/data-display.prop.ts",
1190
1225
  vocabulary: ["AvatarShapeProp", "ChildrenProp", "ClassNameProp"]
1191
1226
  },
1227
+ AvatarAppearanceProp: {
1228
+ group: "data-display",
1229
+ file: "components/data-display.prop.ts",
1230
+ vocabulary: []
1231
+ },
1192
1232
  BadgeProp: {
1193
1233
  group: "data-display",
1194
1234
  file: "components/data-display.prop.ts",
@@ -1483,6 +1523,13 @@ const COMPONENT_PROP_REGISTRY = {
1483
1523
  "ChildrenProp"
1484
1524
  ]
1485
1525
  },
1526
+ BannerProp: {
1527
+ group: "feedback",
1528
+ file: "components/feedback.prop.ts",
1529
+ // `Omit<AlertProp, "variant">` — the alias fixes the one prop it drops, so it inherits Alert's
1530
+ // vocabulary exactly. Listing it again here is what keeps the guard honest if Alert's API moves.
1531
+ vocabulary: ["ToneProp", "IconProp", "OnValueChangeProp", "ClassNameProp", "ChildrenProp"]
1532
+ },
1486
1533
  AlertTitleProp: {
1487
1534
  group: "feedback",
1488
1535
  file: "components/feedback.prop.ts",
@@ -1513,7 +1560,45 @@ const COMPONENT_PROP_REGISTRY = {
1513
1560
  "HasActiveFiltersProp",
1514
1561
  "StickyProp",
1515
1562
  "ClassNameProp",
1516
- "ChildrenProp"
1563
+ "ChildrenProp",
1564
+ {
1565
+ field: "search",
1566
+ local: true,
1567
+ reason: "SLOT for the caller's own search control, positioned at the start of the row and measured by --filter-bar-search-width. Not a value/onValueChange pair: the bar owns the search's PLACE and WIDTH, never its state (gh#258)."
1568
+ },
1569
+ {
1570
+ field: "chips",
1571
+ local: true,
1572
+ reason: "APPLIED filters as removable chips \u2014 the visible record of filters already in effect, distinct from the controls that set them. A bar-specific shape (id/label/onRemove), not a shared vocabulary type (gh#258)."
1573
+ },
1574
+ {
1575
+ field: "onChipRemove",
1576
+ local: true,
1577
+ reason: "Chip-removal callback keyed by chip id. Not `onValueChange`: it reports ONE lifted filter rather than the bar's whole value, which the bar deliberately does not hold (gh#258)."
1578
+ },
1579
+ {
1580
+ field: "resultCount",
1581
+ local: true,
1582
+ reason: "Number of records the current filters resolve to, announced in a polite live region and formatted via Intl.NumberFormat + CLDR plurals. Presentational output, not a controlled value (gh#258)."
1583
+ },
1584
+ {
1585
+ field: "actions",
1586
+ local: true,
1587
+ reason: "Trailing action SLOT (export, column settings, saved views), ordered AFTER the reset control by the bar so `clear filters` never sits beside an unrelated primary action (gh#258)."
1588
+ }
1589
+ ]
1590
+ },
1591
+ FilterBarChipProp: {
1592
+ group: "navigation",
1593
+ file: "components/navigation.prop.ts",
1594
+ vocabulary: [
1595
+ "IdProp",
1596
+ "LabelProp",
1597
+ {
1598
+ field: "onRemove",
1599
+ local: true,
1600
+ reason: "Per-chip removal. Omitting it is meaningful \u2014 the chip renders with NO remove control (a filter the user may not lift), rather than a disabled button that is a dead tab stop (gh#258)."
1601
+ }
1517
1602
  ]
1518
1603
  },
1519
1604
  FilterBarOverflowProp: {
@@ -1546,12 +1631,22 @@ const COMPONENT_PROP_REGISTRY = {
1546
1631
  file: "components/data-entry.prop.ts",
1547
1632
  vocabulary: []
1548
1633
  },
1634
+ InputOTPAlignProp: {
1635
+ group: "data-entry",
1636
+ file: "components/data-entry.prop.ts",
1637
+ vocabulary: []
1638
+ },
1549
1639
  StepItemProp: {
1550
1640
  group: "navigation",
1551
1641
  file: "components/navigation.prop.ts",
1552
1642
  vocabulary: ["TitleProp", "SubtitleProp", "DescriptionProp", "IconProp", "DisabledProp"]
1553
1643
  },
1554
1644
  StepStatusProp: { group: "navigation", file: "components/navigation.prop.ts", vocabulary: [] },
1645
+ StepsSeparatorProp: {
1646
+ group: "navigation",
1647
+ file: "components/navigation.prop.ts",
1648
+ vocabulary: []
1649
+ },
1555
1650
  TabsProp: {
1556
1651
  group: "navigation",
1557
1652
  file: "components/navigation.prop.ts",
@@ -54,8 +54,16 @@ export type BreakpointProp = "sm" | "md" | "lg" | "xl";
54
54
  export type ConfirmVariantProp = "default" | "destructive";
55
55
  /** Semantic color/status intent. */
56
56
  export type ToneProp = "default" | "success" | "warning" | "destructive" | "info" | "muted" | "neutral";
57
- /** Inline Alert visual treatment. */
58
- export type AlertVariantProp = "default";
57
+ /**
58
+ * Alert visual treatment.
59
+ *
60
+ * `"default"` is the inset, rounded, fully-bordered INLINE alert that sits inside a page body.
61
+ * `"banner"` is the page-level strip the `Banner` alias ships (gh#255): square, edge-to-edge, ruled
62
+ * on the block-end edge only, so it reads as page chrome above the content rather than as a card
63
+ * inside it. Both share one implementation, one tone scale and one dismiss/actions contract —
64
+ * `banner` re-measures the box through `--banner-*` tokens and changes nothing else.
65
+ */
66
+ export type AlertVariantProp = "default" | "banner";
59
67
  /** Sort direction for table columns. */
60
68
  export type SortDirectionProp = "asc" | "desc";
61
69
  /** Table column text alignment. */
@@ -45,10 +45,13 @@ export type ErrorSurfaceStatusProp = 403 | 404 | 500 | 503;
45
45
  * standalone and requester flows; `"device-authorization"` is the 380px device-grant measure with
46
46
  * a 5px mobile inline gutter; `"context-selection"` is the 25rem organisation/context picker
47
47
  * measure that goes edge-to-edge on mobile; `"account-recovery"` is the 432px SCR-008 measure
48
- * shared by the password-recovery and sign-in MFA challenge panels (15px mobile inline gutter).
48
+ * shared by the password-recovery and sign-in MFA challenge panels (15px mobile inline gutter);
49
+ * `"registration"` is the 360px sign-up measure — the only START-aligned preset, because a
50
+ * registration card is the tallest surface in the set and a centred tall card overflows above the
51
+ * scroll origin, and the only one with its own footer-clearance knob.
49
52
  * Orthogonal to AuthShell's `variant` (which owns control density and heading size) — combine them.
50
53
  */
51
- export type AuthShellPresetProp = "default" | "login" | "device-authorization" | "context-selection" | "account-recovery";
54
+ export type AuthShellPresetProp = "default" | "login" | "registration" | "device-authorization" | "context-selection" | "account-recovery";
52
55
  /** Shared gap between layout children; components may document subsets. */
53
56
  export type GapProp = "xs" | "sm" | "md" | "lg" | "xl";
54
57
  /** DataTable row density subset. */