@jirawatpyk/aura-react 5.61.0 → 5.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -186,6 +186,15 @@ DataTable with sort and page in the URL (4.17): `onStateChange={({ sort, page })
186
186
  - **Time zone**: `timeZone` on AuraProvider, DatePicker, DateRangePicker and Calendar decides "today" (the marker, `min`/`max="today"`, the first month shown); or pass `today` as an ISO date. `todayIn('Asia/Bangkok')` is exported from the root and `/server`.
187
187
  - **Toasts** queue past three instead of dropping: six in a row all show, in order, three at a time.
188
188
 
189
+ ## 5.63 — Chamber-OS addendum 79 (#178)
190
+
191
+ - **A lazy chip still makes `meta` the chip row:** a Server Component's Badge or StatusPill passed through a `'use client'` wrapper can arrive as a lazy node on Next's dev server. PageHeader now looks through a resolved lazy node (a chip makes the row, text keeps the line, as when it arrives resolved), and an unresolved one is neutral — the other children decide — so the layout no longer depends on the build mode. Anything else unresolved (a promise, an iterator) keeps a line.
192
+ - **`metaLayout`:** `"row"` lays `meta` out as the wrapping chip row whatever it holds, `"line"` as a text line; `"auto"` (default) keeps 5.62's guess (elements only → row). Pass `metaLayout="row"` where chips come from a Server Component, so nothing is guessed (an all-lazy meta that hasn't resolved would otherwise be a line). Also from `/server`. Drop the `flex flex-wrap items-center gap-2` stand-in.
193
+
194
+ ## 5.62 — Chamber-OS addendum 78 (#177)
195
+
196
+ - **PageHeader `meta` lays chips out as a row:** a `meta` made only of elements (Badges, a StatusPill — through Fragments and arrays) is now a wrapping row, 8px apart and vertically centred, as `eyebrow` — so chips no longer touch when the JSX has no space between them, and they wrap on a phone. Any text in it — a string `meta` ("128 members · updated 3 min ago"), or a sentence with a `<strong>`, `<time>`, a link or `{count}` — keeps it a text line, as before. Also from `/server`. Drop a `flex flex-wrap items-center gap-2` stand-in wrapper.
197
+
189
198
  ## 5.61 — Chamber-OS addendum 77 (#176)
190
199
 
191
200
  - **A visually hidden child of full-width header actions stays hidden:** below the `actionsFullWidthBelow` width every direct child of PageHeader's actions took a share of the row with `min-width: max-content` — including a visually hidden description beside a button (`aria-describedby` → a `.sr-only` / `.aura-sr-only` span), which grew to its text's width and scrolled the page sideways. The share rule — here and in the `actionsBarBelow` bar — now skips a visually hidden child: `.sr-only`, `.aura-sr-only`, `.visually-hidden`, `.screen-reader-text`, `[hidden]`, or one with an inline `position: absolute` (Radix and React Aria `VisuallyHidden`); the buttons share the row as before. Drop a `.sr-only { min-width: 0 }` stand-in. Another out-of-flow child styled by a class of your own (an absolutely positioned badge) needs `min-width: 0`, or put it inside the button.
@@ -7914,6 +7914,33 @@ window.Aura = (() => {
7914
7914
  // src/PageHeader.tsx
7915
7915
  var React43 = __toESM(require_react(), 1);
7916
7916
  var h8 = React43.createElement;
7917
+ var LAZY = Symbol.for("react.lazy");
7918
+ function chipsOnly(node) {
7919
+ let el = 0;
7920
+ const walk = function(n3) {
7921
+ if (n3 == null || typeof n3 === "boolean") return true;
7922
+ if (typeof n3 === "string") return n3.trim() === "";
7923
+ if (typeof n3 === "number" || typeof n3 === "bigint") return false;
7924
+ if (Array.isArray(n3)) return n3.every(walk);
7925
+ if (typeof n3 === "object" && n3.$$typeof === LAZY) {
7926
+ const lazy = n3;
7927
+ let value;
7928
+ try {
7929
+ value = lazy._init(lazy._payload);
7930
+ } catch {
7931
+ return true;
7932
+ }
7933
+ return walk(value);
7934
+ }
7935
+ if (React43.isValidElement(n3)) {
7936
+ if (n3.type === React43.Fragment) return walk(n3.props.children);
7937
+ el++;
7938
+ return true;
7939
+ }
7940
+ return false;
7941
+ };
7942
+ return walk(node) && el > 0;
7943
+ }
7917
7944
  var PageHeader = React43.forwardRef(function PageHeader2(props, ref) {
7918
7945
  const attrs2 = {};
7919
7946
  Object.keys(props).forEach(function(k) {
@@ -7930,6 +7957,7 @@ window.Aura = (() => {
7930
7957
  const size = props.size === "compact" || props.size === "hero" || props.size === "hero-lg" ? props.size : null;
7931
7958
  const eyebrow = props.eyebrow;
7932
7959
  const plainEyebrow = typeof eyebrow === "string" || typeof eyebrow === "number";
7960
+ const richMeta = props.metaLayout === "row" ? true : props.metaLayout === "line" ? false : chipsOnly(props.meta);
7933
7961
  const heading = h8(
7934
7962
  "h" + level,
7935
7963
  {
@@ -7971,7 +7999,7 @@ window.Aura = (() => {
7971
7999
  h8("div", { className: "aura-page-header__title-addon" }, props.titleAddon)
7972
8000
  ) : heading,
7973
8001
  shown(props.subtitle) ? h8("div", { className: "aura-page-header__subtitle" }, props.subtitle) : null,
7974
- props.meta != null && props.meta !== false ? h8("div", { className: "aura-page-header__meta" }, props.meta) : null
8002
+ props.meta != null && props.meta !== false ? h8("div", { className: cx("aura-page-header__meta", richMeta && "aura-page-header__meta--rich") }, props.meta) : null
7975
8003
  ),
7976
8004
  props.actions != null && props.actions !== false ? h8(
7977
8005
  "div",
@@ -7896,6 +7896,33 @@ var React44 = __toESM(require("react"), 1);
7896
7896
  // src/PageHeader.tsx
7897
7897
  var React43 = __toESM(require("react"), 1);
7898
7898
  var h8 = React43.createElement;
7899
+ var LAZY = Symbol.for("react.lazy");
7900
+ function chipsOnly(node) {
7901
+ let el = 0;
7902
+ const walk = function(n3) {
7903
+ if (n3 == null || typeof n3 === "boolean") return true;
7904
+ if (typeof n3 === "string") return n3.trim() === "";
7905
+ if (typeof n3 === "number" || typeof n3 === "bigint") return false;
7906
+ if (Array.isArray(n3)) return n3.every(walk);
7907
+ if (typeof n3 === "object" && n3.$$typeof === LAZY) {
7908
+ const lazy = n3;
7909
+ let value;
7910
+ try {
7911
+ value = lazy._init(lazy._payload);
7912
+ } catch {
7913
+ return true;
7914
+ }
7915
+ return walk(value);
7916
+ }
7917
+ if (React43.isValidElement(n3)) {
7918
+ if (n3.type === React43.Fragment) return walk(n3.props.children);
7919
+ el++;
7920
+ return true;
7921
+ }
7922
+ return false;
7923
+ };
7924
+ return walk(node) && el > 0;
7925
+ }
7899
7926
  var PageHeader = React43.forwardRef(function PageHeader2(props, ref) {
7900
7927
  const attrs2 = {};
7901
7928
  Object.keys(props).forEach(function(k) {
@@ -7912,6 +7939,7 @@ var PageHeader = React43.forwardRef(function PageHeader2(props, ref) {
7912
7939
  const size = props.size === "compact" || props.size === "hero" || props.size === "hero-lg" ? props.size : null;
7913
7940
  const eyebrow = props.eyebrow;
7914
7941
  const plainEyebrow = typeof eyebrow === "string" || typeof eyebrow === "number";
7942
+ const richMeta = props.metaLayout === "row" ? true : props.metaLayout === "line" ? false : chipsOnly(props.meta);
7915
7943
  const heading = h8(
7916
7944
  "h" + level,
7917
7945
  {
@@ -7953,7 +7981,7 @@ var PageHeader = React43.forwardRef(function PageHeader2(props, ref) {
7953
7981
  h8("div", { className: "aura-page-header__title-addon" }, props.titleAddon)
7954
7982
  ) : heading,
7955
7983
  shown(props.subtitle) ? h8("div", { className: "aura-page-header__subtitle" }, props.subtitle) : null,
7956
- props.meta != null && props.meta !== false ? h8("div", { className: "aura-page-header__meta" }, props.meta) : null
7984
+ props.meta != null && props.meta !== false ? h8("div", { className: cx("aura-page-header__meta", richMeta && "aura-page-header__meta--rich") }, props.meta) : null
7957
7985
  ),
7958
7986
  props.actions != null && props.actions !== false ? h8(
7959
7987
  "div",
@@ -2,6 +2,33 @@
2
2
  import * as React from "react";
3
3
  import { cx } from "./classes.js";
4
4
  const h = React.createElement;
5
+ const LAZY = Symbol.for("react.lazy");
6
+ function chipsOnly(node) {
7
+ let el = 0;
8
+ const walk = function(n) {
9
+ if (n == null || typeof n === "boolean") return true;
10
+ if (typeof n === "string") return n.trim() === "";
11
+ if (typeof n === "number" || typeof n === "bigint") return false;
12
+ if (Array.isArray(n)) return n.every(walk);
13
+ if (typeof n === "object" && n.$$typeof === LAZY) {
14
+ const lazy = n;
15
+ let value;
16
+ try {
17
+ value = lazy._init(lazy._payload);
18
+ } catch {
19
+ return true;
20
+ }
21
+ return walk(value);
22
+ }
23
+ if (React.isValidElement(n)) {
24
+ if (n.type === React.Fragment) return walk(n.props.children);
25
+ el++;
26
+ return true;
27
+ }
28
+ return false;
29
+ };
30
+ return walk(node) && el > 0;
31
+ }
5
32
  const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
6
33
  const attrs = {};
7
34
  Object.keys(props).forEach(function(k) {
@@ -18,6 +45,7 @@ const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
18
45
  const size = props.size === "compact" || props.size === "hero" || props.size === "hero-lg" ? props.size : null;
19
46
  const eyebrow = props.eyebrow;
20
47
  const plainEyebrow = typeof eyebrow === "string" || typeof eyebrow === "number";
48
+ const richMeta = props.metaLayout === "row" ? true : props.metaLayout === "line" ? false : chipsOnly(props.meta);
21
49
  const heading = h(
22
50
  "h" + level,
23
51
  {
@@ -59,7 +87,7 @@ const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
59
87
  h("div", { className: "aura-page-header__title-addon" }, props.titleAddon)
60
88
  ) : heading,
61
89
  shown(props.subtitle) ? h("div", { className: "aura-page-header__subtitle" }, props.subtitle) : null,
62
- props.meta != null && props.meta !== false ? h("div", { className: "aura-page-header__meta" }, props.meta) : null
90
+ props.meta != null && props.meta !== false ? h("div", { className: cx("aura-page-header__meta", richMeta && "aura-page-header__meta--rich") }, props.meta) : null
63
91
  ),
64
92
  props.actions != null && props.actions !== false ? h(
65
93
  "div",
package/dist/index.d.cts CHANGED
@@ -2072,8 +2072,13 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
2072
2072
  /** 5.46: `end` (default) lines the actions up with the bottom of the text; `start` with its top (the title, when
2073
2073
  * there is no breadcrumb or eyebrow). */
2074
2074
  actionsAlign?: "end" | "start" | undefined;
2075
- /** A line under the title — counts, last update, owner. */
2075
+ /** A line under the title — counts, last update, owner. 5.62 (Chamber-OS 177): made only of elements (Badges, a
2076
+ * StatusPill), it is laid out as a wrapping row, 8px apart; any text in it keeps it a line. */
2076
2077
  meta?: React$1.ReactNode | undefined;
2078
+ /** 5.63 (Chamber-OS 178): `row` lays `meta` out as the wrapping chip row whatever its children are, `line` as a text
2079
+ * line; `auto` (default) guesses from them (elements only → row). Pass `row` when chips come from a Server Component
2080
+ * through a client wrapper, where they may arrive unresolved. */
2081
+ metaLayout?: "auto" | "row" | "line" | undefined;
2077
2082
  /** Buttons for the page, bottom-aligned at the end; they wrap below the text on a narrow screen. */
2078
2083
  actions?: React$1.ReactNode | undefined;
2079
2084
  /** 5.37 (DxT Monitor #17): below this breakpoint (`sm` 640px, `md` 768px, `lg` 1024px) the actions take the whole
package/dist/index.d.ts CHANGED
@@ -2072,8 +2072,13 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
2072
2072
  /** 5.46: `end` (default) lines the actions up with the bottom of the text; `start` with its top (the title, when
2073
2073
  * there is no breadcrumb or eyebrow). */
2074
2074
  actionsAlign?: "end" | "start" | undefined;
2075
- /** A line under the title — counts, last update, owner. */
2075
+ /** A line under the title — counts, last update, owner. 5.62 (Chamber-OS 177): made only of elements (Badges, a
2076
+ * StatusPill), it is laid out as a wrapping row, 8px apart; any text in it keeps it a line. */
2076
2077
  meta?: React$1.ReactNode | undefined;
2078
+ /** 5.63 (Chamber-OS 178): `row` lays `meta` out as the wrapping chip row whatever its children are, `line` as a text
2079
+ * line; `auto` (default) guesses from them (elements only → row). Pass `row` when chips come from a Server Component
2080
+ * through a client wrapper, where they may arrive unresolved. */
2081
+ metaLayout?: "auto" | "row" | "line" | undefined;
2077
2082
  /** Buttons for the page, bottom-aligned at the end; they wrap below the text on a narrow screen. */
2078
2083
  actions?: React$1.ReactNode | undefined;
2079
2084
  /** 5.37 (DxT Monitor #17): below this breakpoint (`sm` 640px, `md` 768px, `lg` 1024px) the actions take the whole
@@ -1632,6 +1632,33 @@ function TableSkeleton(props) {
1632
1632
  // src/PageHeader.tsx
1633
1633
  var React6 = __toESM(require("react"), 1);
1634
1634
  var h5 = React6.createElement;
1635
+ var LAZY = Symbol.for("react.lazy");
1636
+ function chipsOnly(node) {
1637
+ let el = 0;
1638
+ const walk = function(n3) {
1639
+ if (n3 == null || typeof n3 === "boolean") return true;
1640
+ if (typeof n3 === "string") return n3.trim() === "";
1641
+ if (typeof n3 === "number" || typeof n3 === "bigint") return false;
1642
+ if (Array.isArray(n3)) return n3.every(walk);
1643
+ if (typeof n3 === "object" && n3.$$typeof === LAZY) {
1644
+ const lazy = n3;
1645
+ let value;
1646
+ try {
1647
+ value = lazy._init(lazy._payload);
1648
+ } catch {
1649
+ return true;
1650
+ }
1651
+ return walk(value);
1652
+ }
1653
+ if (React6.isValidElement(n3)) {
1654
+ if (n3.type === React6.Fragment) return walk(n3.props.children);
1655
+ el++;
1656
+ return true;
1657
+ }
1658
+ return false;
1659
+ };
1660
+ return walk(node) && el > 0;
1661
+ }
1635
1662
  var PageHeader = React6.forwardRef(function PageHeader2(props, ref) {
1636
1663
  const attrs2 = {};
1637
1664
  Object.keys(props).forEach(function(k) {
@@ -1648,6 +1675,7 @@ var PageHeader = React6.forwardRef(function PageHeader2(props, ref) {
1648
1675
  const size = props.size === "compact" || props.size === "hero" || props.size === "hero-lg" ? props.size : null;
1649
1676
  const eyebrow = props.eyebrow;
1650
1677
  const plainEyebrow = typeof eyebrow === "string" || typeof eyebrow === "number";
1678
+ const richMeta = props.metaLayout === "row" ? true : props.metaLayout === "line" ? false : chipsOnly(props.meta);
1651
1679
  const heading = h5(
1652
1680
  "h" + level,
1653
1681
  {
@@ -1689,7 +1717,7 @@ var PageHeader = React6.forwardRef(function PageHeader2(props, ref) {
1689
1717
  h5("div", { className: "aura-page-header__title-addon" }, props.titleAddon)
1690
1718
  ) : heading,
1691
1719
  shown(props.subtitle) ? h5("div", { className: "aura-page-header__subtitle" }, props.subtitle) : null,
1692
- props.meta != null && props.meta !== false ? h5("div", { className: "aura-page-header__meta" }, props.meta) : null
1720
+ props.meta != null && props.meta !== false ? h5("div", { className: cx("aura-page-header__meta", richMeta && "aura-page-header__meta--rich") }, props.meta) : null
1693
1721
  ),
1694
1722
  props.actions != null && props.actions !== false ? h5(
1695
1723
  "div",
@@ -582,8 +582,13 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
582
582
  /** 5.46: `end` (default) lines the actions up with the bottom of the text; `start` with its top (the title, when
583
583
  * there is no breadcrumb or eyebrow). */
584
584
  actionsAlign?: "end" | "start" | undefined;
585
- /** A line under the title — counts, last update, owner. */
585
+ /** A line under the title — counts, last update, owner. 5.62 (Chamber-OS 177): made only of elements (Badges, a
586
+ * StatusPill), it is laid out as a wrapping row, 8px apart; any text in it keeps it a line. */
586
587
  meta?: React$1.ReactNode | undefined;
588
+ /** 5.63 (Chamber-OS 178): `row` lays `meta` out as the wrapping chip row whatever its children are, `line` as a text
589
+ * line; `auto` (default) guesses from them (elements only → row). Pass `row` when chips come from a Server Component
590
+ * through a client wrapper, where they may arrive unresolved. */
591
+ metaLayout?: "auto" | "row" | "line" | undefined;
587
592
  /** Buttons for the page, bottom-aligned at the end; they wrap below the text on a narrow screen. */
588
593
  actions?: React$1.ReactNode | undefined;
589
594
  /** 5.37 (DxT Monitor #17): below this breakpoint (`sm` 640px, `md` 768px, `lg` 1024px) the actions take the whole
@@ -582,8 +582,13 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
582
582
  /** 5.46: `end` (default) lines the actions up with the bottom of the text; `start` with its top (the title, when
583
583
  * there is no breadcrumb or eyebrow). */
584
584
  actionsAlign?: "end" | "start" | undefined;
585
- /** A line under the title — counts, last update, owner. */
585
+ /** A line under the title — counts, last update, owner. 5.62 (Chamber-OS 177): made only of elements (Badges, a
586
+ * StatusPill), it is laid out as a wrapping row, 8px apart; any text in it keeps it a line. */
586
587
  meta?: React$1.ReactNode | undefined;
588
+ /** 5.63 (Chamber-OS 178): `row` lays `meta` out as the wrapping chip row whatever its children are, `line` as a text
589
+ * line; `auto` (default) guesses from them (elements only → row). Pass `row` when chips come from a Server Component
590
+ * through a client wrapper, where they may arrive unresolved. */
591
+ metaLayout?: "auto" | "row" | "line" | undefined;
587
592
  /** Buttons for the page, bottom-aligned at the end; they wrap below the text on a narrow screen. */
588
593
  actions?: React$1.ReactNode | undefined;
589
594
  /** 5.37 (DxT Monitor #17): below this breakpoint (`sm` 640px, `md` 768px, `lg` 1024px) the actions take the whole
@@ -1566,6 +1566,33 @@ function TableSkeleton(props) {
1566
1566
  // src/PageHeader.tsx
1567
1567
  import * as React6 from "react";
1568
1568
  var h5 = React6.createElement;
1569
+ var LAZY = Symbol.for("react.lazy");
1570
+ function chipsOnly(node) {
1571
+ let el = 0;
1572
+ const walk = function(n3) {
1573
+ if (n3 == null || typeof n3 === "boolean") return true;
1574
+ if (typeof n3 === "string") return n3.trim() === "";
1575
+ if (typeof n3 === "number" || typeof n3 === "bigint") return false;
1576
+ if (Array.isArray(n3)) return n3.every(walk);
1577
+ if (typeof n3 === "object" && n3.$$typeof === LAZY) {
1578
+ const lazy = n3;
1579
+ let value;
1580
+ try {
1581
+ value = lazy._init(lazy._payload);
1582
+ } catch {
1583
+ return true;
1584
+ }
1585
+ return walk(value);
1586
+ }
1587
+ if (React6.isValidElement(n3)) {
1588
+ if (n3.type === React6.Fragment) return walk(n3.props.children);
1589
+ el++;
1590
+ return true;
1591
+ }
1592
+ return false;
1593
+ };
1594
+ return walk(node) && el > 0;
1595
+ }
1569
1596
  var PageHeader = React6.forwardRef(function PageHeader2(props, ref) {
1570
1597
  const attrs2 = {};
1571
1598
  Object.keys(props).forEach(function(k) {
@@ -1582,6 +1609,7 @@ var PageHeader = React6.forwardRef(function PageHeader2(props, ref) {
1582
1609
  const size = props.size === "compact" || props.size === "hero" || props.size === "hero-lg" ? props.size : null;
1583
1610
  const eyebrow = props.eyebrow;
1584
1611
  const plainEyebrow = typeof eyebrow === "string" || typeof eyebrow === "number";
1612
+ const richMeta = props.metaLayout === "row" ? true : props.metaLayout === "line" ? false : chipsOnly(props.meta);
1585
1613
  const heading = h5(
1586
1614
  "h" + level,
1587
1615
  {
@@ -1623,7 +1651,7 @@ var PageHeader = React6.forwardRef(function PageHeader2(props, ref) {
1623
1651
  h5("div", { className: "aura-page-header__title-addon" }, props.titleAddon)
1624
1652
  ) : heading,
1625
1653
  shown(props.subtitle) ? h5("div", { className: "aura-page-header__subtitle" }, props.subtitle) : null,
1626
- props.meta != null && props.meta !== false ? h5("div", { className: "aura-page-header__meta" }, props.meta) : null
1654
+ props.meta != null && props.meta !== false ? h5("div", { className: cx("aura-page-header__meta", richMeta && "aura-page-header__meta--rich") }, props.meta) : null
1627
1655
  ),
1628
1656
  props.actions != null && props.actions !== false ? h5(
1629
1657
  "div",
package/dist/styles.css CHANGED
@@ -1365,6 +1365,8 @@ summary.aura-link::-webkit-details-marker { display: none; }
1365
1365
  .aura-page-header__title-row > .aura-page-header__title { min-width: 0; }
1366
1366
  .aura-page-header__title-addon { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); min-width: 0; }
1367
1367
  .aura-page-header__eyebrow--rich { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); font-family: var(--font-sans); line-height: 1.5; }
1368
+ /* 5.62 (Chamber-OS 177): a meta of chips only (no text) is a wrapping row, as the eyebrow — 8px apart, 4px under the title. */
1369
+ .aura-page-header__meta--rich { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); }
1368
1370
  .aura-page-header--hero, .aura-page-header--hero-lg { padding-top: var(--aura-page-header-hero-space, var(--aura-space-4)); }
1369
1371
  .aura-page-header--hero .aura-page-header__title { font-size: var(--aura-page-header-title-size, max(30px, 1.875rem)); line-height: var(--aura-page-header-title-line-height, 1.2); }
1370
1372
  /* 5.47 (Chamber-OS 152): compact — the staff boards' 26 / 32; hero steps to 36px from 1024px like hero-lg. */
@@ -1367,6 +1367,8 @@ summary.aura-link::-webkit-details-marker { display: none; }
1367
1367
  .aura-page-header__title-row > .aura-page-header__title { min-width: 0; }
1368
1368
  .aura-page-header__title-addon { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); min-width: 0; }
1369
1369
  .aura-page-header__eyebrow--rich { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); font-family: var(--font-sans); line-height: 1.5; }
1370
+ /* 5.62 (Chamber-OS 177): a meta of chips only (no text) is a wrapping row, as the eyebrow — 8px apart, 4px under the title. */
1371
+ .aura-page-header__meta--rich { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); }
1370
1372
  .aura-page-header--hero, .aura-page-header--hero-lg { padding-top: var(--aura-page-header-hero-space, var(--aura-space-4)); }
1371
1373
  .aura-page-header--hero .aura-page-header__title { font-size: var(--aura-page-header-title-size, max(30px, 1.875rem)); line-height: var(--aura-page-header-title-line-height, 1.2); }
1372
1374
  /* 5.47 (Chamber-OS 152): compact — the staff boards' 26 / 32; hero steps to 36px from 1024px like hero-lg. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.61.0",
3
+ "version": "5.63.0",
4
4
  "description": "AURA Design System — React components (Enterprise Standard, Human Creative). Thai-first: Buddhist-era dates, Thai collation.",
5
5
  "license": "MIT",
6
6
  "type": "module",