@jirawatpyk/aura-react 5.19.0 → 5.20.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,12 @@ 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.20 — Chamber-OS addendum 20, items 115–116
190
+
191
+ - **Table follows the page's density** (item 115): without a `density` prop a Table takes the nearest AuraProvider's density, as its docs said — inside `AuraProvider density="compact"` the wrap carries `data-density="compact"` and cells get 8px vertical padding (were 12px). A `density` prop still wins. The padding comes from the nearest `data-density` (a provider, `<html>`, any element, or the table's own), so `comfortable` inside a compact page switches back as it does for fields. As before with an explicit `compact`, cells stay compact on touch screens. A visible change for Tables inside a compact provider or page.
192
+ - **ActionBar `start`** (item 116): buttons at the bar's start edge — Cancel in a wizard — outside the `status` live region. When the bar is 640px or wider (its own width — a bar in a narrow card or dialog counts as narrow) they sit flush with the start edge, the status (if any) next, `children` at the end; narrower, the status takes its own row and the start buttons sit before the actions. In the tab order they come before `children`. Hidden with the actions when a bulk bar is idle; an empty `start` renders nothing.
193
+ - **ActionBar in right-to-left pages**: the actions now sit at the end (left) edge — they used a physical `margin-left`, so a wrapped actions row landed next to the status. The bar is now `width: 100%` and a size container: give it no horizontal margins, and in a shrink-to-fit parent (inline-block, a grid `auto` track, a `max-content` popover) give the parent a width — otherwise the bar falls back to 20rem.
194
+
189
195
  ## 5.19 — Chamber-OS addendum 20
190
196
 
191
197
  - **Switch `readOnly`, `icon` and `aria-describedby`** (item 113): `readOnly` keeps a locked switch in the Tab order with `aria-readonly="true"`, so its name, state and notes are heard; click, Space, its label and its row change nothing. It keeps its colours (a locked "on" reads as on) and loses the pointer. `icon` puts an icon at the end of the row, the field icon's size, in fg-secondary (`icon={<IconLock />}`), hidden from screen readers. `aria-describedby` is merged with the description's id, as on TextField and Select. `disabled` wins over `readOnly`.
@@ -7164,6 +7164,9 @@ window.Aura = (() => {
7164
7164
  const bulk = props.selected != null;
7165
7165
  const idle = bulk && !props.selected;
7166
7166
  const count = bulk && props.selected ? t.selectedCount(props.selected) : null;
7167
+ const hasStart = React42.Children.toArray(props.start).some(function(c) {
7168
+ return c !== "";
7169
+ });
7167
7170
  const cameFrom = React42.useRef(null);
7168
7171
  const own = React42.useRef(null);
7169
7172
  function clear() {
@@ -7195,7 +7198,7 @@ window.Aura = (() => {
7195
7198
  props.className
7196
7199
  )
7197
7200
  },
7198
- /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__inner" }, /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React42.createElement(Button, { variant: "ghost", size: "sm", onClick: clear }, t.clear()) : null, props.children) : null)
7201
+ /* @__PURE__ */ React42.createElement("div", { className: cx("aura-actionbar__inner", hasStart && "has-start") }, /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle && hasStart ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__start" }, props.start) : null, !idle ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React42.createElement(Button, { variant: "ghost", size: "sm", onClick: clear }, t.clear()) : null, props.children) : null)
7199
7202
  );
7200
7203
  });
7201
7204
 
@@ -7273,6 +7276,7 @@ window.Aura = (() => {
7273
7276
  "Table stackBelow: no THead > Tr > Th found among its children, so cells have no labels. Pass `label` on each Td."
7274
7277
  );
7275
7278
  const outer = React44.useContext(StackLabels);
7279
+ const pageDensity = useDensity();
7276
7280
  const capId = uid();
7277
7281
  const wrap = React44.useRef(null);
7278
7282
  const sc = React44.useState(false), scrolls = sc[0];
@@ -7294,7 +7298,7 @@ window.Aura = (() => {
7294
7298
  {
7295
7299
  ref: wrap,
7296
7300
  className: cx("aura-tbl-wrap", stackBelow && "is-stackable", bordered === false && "is-flush"),
7297
- "data-density": density,
7301
+ "data-density": density || pageDensity,
7298
7302
  tabIndex: scrolls ? 0 : void 0,
7299
7303
  role: scrolls && (caption != null || rest["aria-label"]) ? "region" : void 0,
7300
7304
  "aria-labelledby": scrolls && caption != null ? capId : void 0,
@@ -7146,6 +7146,9 @@ var ActionBar = React42.forwardRef(function ActionBar2(props, ref) {
7146
7146
  const bulk = props.selected != null;
7147
7147
  const idle = bulk && !props.selected;
7148
7148
  const count = bulk && props.selected ? t.selectedCount(props.selected) : null;
7149
+ const hasStart = React42.Children.toArray(props.start).some(function(c) {
7150
+ return c !== "";
7151
+ });
7149
7152
  const cameFrom = React42.useRef(null);
7150
7153
  const own = React42.useRef(null);
7151
7154
  function clear() {
@@ -7177,7 +7180,7 @@ var ActionBar = React42.forwardRef(function ActionBar2(props, ref) {
7177
7180
  props.className
7178
7181
  )
7179
7182
  },
7180
- /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__inner" }, /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React42.createElement(Button, { variant: "ghost", size: "sm", onClick: clear }, t.clear()) : null, props.children) : null)
7183
+ /* @__PURE__ */ React42.createElement("div", { className: cx("aura-actionbar__inner", hasStart && "has-start") }, /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle && hasStart ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__start" }, props.start) : null, !idle ? /* @__PURE__ */ React42.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React42.createElement(Button, { variant: "ghost", size: "sm", onClick: clear }, t.clear()) : null, props.children) : null)
7181
7184
  );
7182
7185
  });
7183
7186
 
@@ -7255,6 +7258,7 @@ var Table = React44.forwardRef(function Table2(props, ref) {
7255
7258
  "Table stackBelow: no THead > Tr > Th found among its children, so cells have no labels. Pass `label` on each Td."
7256
7259
  );
7257
7260
  const outer = React44.useContext(StackLabels);
7261
+ const pageDensity = useDensity();
7258
7262
  const capId = uid();
7259
7263
  const wrap = React44.useRef(null);
7260
7264
  const sc = React44.useState(false), scrolls = sc[0];
@@ -7276,7 +7280,7 @@ var Table = React44.forwardRef(function Table2(props, ref) {
7276
7280
  {
7277
7281
  ref: wrap,
7278
7282
  className: cx("aura-tbl-wrap", stackBelow && "is-stackable", bordered === false && "is-flush"),
7279
- "data-density": density,
7283
+ "data-density": density || pageDensity,
7280
7284
  tabIndex: scrolls ? 0 : void 0,
7281
7285
  role: scrolls && (caption != null || rest["aria-label"]) ? "region" : void 0,
7282
7286
  "aria-labelledby": scrolls && caption != null ? capId : void 0,
@@ -8,6 +8,9 @@ const ActionBar = React.forwardRef(function ActionBar2(props, ref) {
8
8
  const bulk = props.selected != null;
9
9
  const idle = bulk && !props.selected;
10
10
  const count = bulk && props.selected ? t.selectedCount(props.selected) : null;
11
+ const hasStart = React.Children.toArray(props.start).some(function(c) {
12
+ return c !== "";
13
+ });
11
14
  const cameFrom = React.useRef(null);
12
15
  const own = React.useRef(null);
13
16
  function clear() {
@@ -39,7 +42,7 @@ const ActionBar = React.forwardRef(function ActionBar2(props, ref) {
39
42
  props.className
40
43
  )
41
44
  },
42
- /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__inner" }, /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle ? /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React.createElement(Button, { variant: "ghost", size: "sm", onClick: clear }, t.clear()) : null, props.children) : null)
45
+ /* @__PURE__ */ React.createElement("div", { className: cx("aura-actionbar__inner", hasStart && "has-start") }, /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle && hasStart ? /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__start" }, props.start) : null, !idle ? /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React.createElement(Button, { variant: "ghost", size: "sm", onClick: clear }, t.clear()) : null, props.children) : null)
43
46
  );
44
47
  });
45
48
  export {
package/dist/esm/Table.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
  import * as React from "react";
3
3
  import { cx, devWarnOnce, uid, useIsoLayoutEffect } from "./internal.js";
4
+ import { useDensity } from "./locale.js";
4
5
  const StackLabels = React.createContext(null);
5
6
  const ColumnIndex = React.createContext(-1);
6
7
  function flat(children) {
@@ -56,6 +57,7 @@ const Table = React.forwardRef(function Table2(props, ref) {
56
57
  "Table stackBelow: no THead > Tr > Th found among its children, so cells have no labels. Pass `label` on each Td."
57
58
  );
58
59
  const outer = React.useContext(StackLabels);
60
+ const pageDensity = useDensity();
59
61
  const capId = uid();
60
62
  const wrap = React.useRef(null);
61
63
  const sc = React.useState(false), scrolls = sc[0];
@@ -77,7 +79,7 @@ const Table = React.forwardRef(function Table2(props, ref) {
77
79
  {
78
80
  ref: wrap,
79
81
  className: cx("aura-tbl-wrap", stackBelow && "is-stackable", bordered === false && "is-flush"),
80
- "data-density": density,
82
+ "data-density": density || pageDensity,
81
83
  tabIndex: scrolls ? 0 : void 0,
82
84
  role: scrolls && (caption != null || rest["aria-label"]) ? "region" : void 0,
83
85
  "aria-labelledby": scrolls && caption != null ? capId : void 0,
package/dist/index.d.cts CHANGED
@@ -1176,6 +1176,10 @@ export interface TableCellProps extends Omit<React$1.TdHTMLAttributes<HTMLTableC
1176
1176
  export interface ActionBarProps {
1177
1177
  /** Buttons, right-aligned (the primary one last). */
1178
1178
  children?: React$1.ReactNode | undefined;
1179
+ /** 5.20 (Chamber-OS 116): buttons at the start edge — Cancel in a wizard — outside the `status` live region. When
1180
+ * the bar itself is 640px or wider they sit flush with its start edge and `children` at its end; in a narrower bar a
1181
+ * status line takes its own row and they sit before the actions. In the tab order they come before `children`. */
1182
+ start?: React$1.ReactNode | undefined;
1179
1183
  /** A short line such as "Total 107,000.00 THB · due Oct 22, 2026" or "Unsaved changes". It sits in a polite live
1180
1184
  * region that is always in the page, so a change is announced. */
1181
1185
  status?: React$1.ReactNode | undefined;
package/dist/index.d.ts CHANGED
@@ -1176,6 +1176,10 @@ export interface TableCellProps extends Omit<React$1.TdHTMLAttributes<HTMLTableC
1176
1176
  export interface ActionBarProps {
1177
1177
  /** Buttons, right-aligned (the primary one last). */
1178
1178
  children?: React$1.ReactNode | undefined;
1179
+ /** 5.20 (Chamber-OS 116): buttons at the start edge — Cancel in a wizard — outside the `status` live region. When
1180
+ * the bar itself is 640px or wider they sit flush with its start edge and `children` at its end; in a narrower bar a
1181
+ * status line takes its own row and they sit before the actions. In the tab order they come before `children`. */
1182
+ start?: React$1.ReactNode | undefined;
1179
1183
  /** A short line such as "Total 107,000.00 THB · due Oct 22, 2026" or "Unsaved changes". It sits in a polite live
1180
1184
  * region that is always in the page, so a change is announced. */
1181
1185
  status?: React$1.ReactNode | undefined;
package/dist/styles.css CHANGED
@@ -1574,10 +1574,14 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1574
1574
  [data-density='compact'] {
1575
1575
  --aura-input-height: 36px; --aura-button-height: 36px; --aura-table-row-height: 40px;
1576
1576
  --aura-button-padding-x: var(--aura-space-4);
1577
+ /* 5.20 (Chamber-OS 115): a static Table's vertical cell padding, and its stacked cards', inherited from the nearest
1578
+ * density — a provider's wrapper, <html>, or the table's own wrap — so "comfortable" inside compact switches back. */
1579
+ --aura-tbl-cell-py: var(--aura-space-2); --aura-tbl-card-py: var(--aura-space-2);
1577
1580
  }
1578
1581
  [data-density='comfortable'] {
1579
1582
  --aura-input-height: 44px; --aura-button-height: 44px; --aura-table-row-height: 48px;
1580
1583
  --aura-button-padding-x: var(--aura-space-6);
1584
+ --aura-tbl-cell-py: var(--aura-space-3); --aura-tbl-card-py: var(--aura-space-4);
1581
1585
  }
1582
1586
  @media (pointer: coarse) {
1583
1587
  [data-density='compact'] { --aura-input-height: 44px; --aura-button-height: 44px; --aura-table-row-height: 48px; --aura-button-padding-x: var(--aura-space-6); }
@@ -1636,20 +1640,31 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1636
1640
 
1637
1641
  /* ---------- 4.19: ActionBar ---------- */
1638
1642
  /* Sticky, not fixed: it keeps its place at the end of its parent, so it never covers the last field. */
1639
- .aura-actionbar { position: sticky; z-index: var(--aura-z-bar); box-sizing: border-box; background: var(--aura-bg-surface); color: var(--aura-fg-primary); font-family: var(--font-sans); }
1643
+ .aura-actionbar { position: sticky; z-index: var(--aura-z-bar); box-sizing: border-box; width: 100%; container: aura-actionbar / inline-size; contain-intrinsic-inline-size: auto 20rem; /* 5.20: its own width decides its layout (a bar in a card or dialog); a size container can't size to its content, so in a shrink-to-fit parent it falls back to 20rem */ background: var(--aura-bg-surface); color: var(--aura-fg-primary); font-family: var(--font-sans); }
1640
1644
  .aura-actionbar--viewport {
1641
1645
  bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px)));
1642
1646
  margin-top: var(--aura-space-6);
1643
1647
  border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay);
1644
1648
  }
1645
1649
  .aura-actionbar--container { bottom: 0; border-top: 1px solid var(--aura-border-default); }
1646
- .aura-actionbar__inner { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2) var(--aura-space-3); min-height: 60px; box-sizing: border-box; padding: var(--aura-space-2) var(--aura-space-3) var(--aura-space-2) var(--aura-space-4); }
1650
+ .aura-actionbar__inner { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2) var(--aura-space-3); min-height: 60px; box-sizing: border-box; padding-block: var(--aura-space-2); padding-inline: var(--aura-space-4) var(--aura-space-3); }
1647
1651
  .aura-actionbar__status { flex: 1 1 8rem; min-width: 0; font-size: 14px; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; }
1648
1652
  .aura-actionbar__status:empty { flex-basis: 0; }
1649
- .aura-actionbar__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin-left: auto; }
1653
+ /* 5.20: an empty status leaves the row (it would still take a gap and push the start slot away from its edge) but
1654
+ * stays in the page as a live region, so the next status is announced. */
1655
+ .aura-actionbar__inner.has-start > .aura-actionbar__status:empty { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
1656
+ .aura-actionbar__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin-inline-start: auto; }
1650
1657
  /* Bulk bar with nothing selected: out of sight and out of the tab order, its live region still in the page. */
1651
1658
  .aura-actionbar.is-idle { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; box-shadow: none; }
1652
- .aura-actionbar--container > .aura-actionbar__inner { padding-left: 0; padding-right: 0; }
1659
+ .aura-actionbar--container > .aura-actionbar__inner { padding-inline: 0; }
1660
+ /* 5.20 (Chamber-OS 116): the start slot. After the status in the markup, so Tab reaches it before the actions (the
1661
+ * status is a live region, not focusable, so only reading order differs); when the bar is 640px or wider it moves to
1662
+ * the start edge, the status (if any) between. Narrower bars — a phone, a card, a dialog — put a status line on its own
1663
+ * row, so the start slot and the actions stay together on the next. */
1664
+ .aura-actionbar__start { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); }
1665
+ .aura-actionbar__start:empty { display: none; }
1666
+ @container aura-actionbar (min-width: 640px) { .aura-actionbar__start { order: -1; } }
1667
+ @container aura-actionbar (max-width: 639.98px) { .aura-actionbar__inner.has-start > .aura-actionbar__status:not(:empty) { flex-basis: 100%; } }
1653
1668
 
1654
1669
  /* ---------- 4.20: Separator ---------- */
1655
1670
  .aura-separator { flex: none; align-self: stretch; height: 1px; margin: var(--aura-separator-space, 0) 0; background: var(--aura-border-default); border: 0; }
@@ -1663,7 +1678,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1663
1678
  }
1664
1679
  .aura-tbl { width: 100%; border-collapse: collapse; border-spacing: 0; font-size: 13px; line-height: 20px; }
1665
1680
  .aura-tbl__caption { caption-side: top; padding: var(--aura-space-4) var(--aura-space-6) 0; text-align: left; font-size: 14px; font-weight: 600; }
1666
- .aura-tbl__th, .aura-tbl__td { padding: var(--aura-space-3) var(--aura-space-4); text-align: left; vertical-align: top; overflow-wrap: anywhere; }
1681
+ .aura-tbl__th, .aura-tbl__td { padding: var(--aura-tbl-cell-py, var(--aura-space-3)) var(--aura-space-4); text-align: left; vertical-align: top; overflow-wrap: anywhere; }
1667
1682
  .aura-tbl__th:first-child, .aura-tbl__td:first-child { padding-left: var(--aura-space-6); }
1668
1683
  .aura-tbl__th:last-child, .aura-tbl__td:last-child { padding-right: var(--aura-space-6); }
1669
1684
  .aura-tbl__head .aura-tbl__th {
@@ -1678,7 +1693,6 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1678
1693
  .aura-tbl .is-end { text-align: right; }
1679
1694
  .aura-tbl .is-center { text-align: center; }
1680
1695
  .aura-tbl .is-numeric { font-variant-numeric: tabular-nums; white-space: nowrap; }
1681
- .aura-tbl-wrap[data-density='compact'] .aura-tbl__th, .aura-tbl-wrap[data-density='compact'] .aura-tbl__td { padding-top: var(--aura-space-2); padding-bottom: var(--aura-space-2); }
1682
1696
  .aura-tbl-wrap:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 2px; }
1683
1697
  /* 5.13 (Chamber-OS 81): align="middle" centres body and footer cells on their row; bordered={false} drops the frame and
1684
1698
  * the outer cells' side padding, so the table lines up with what's around it (a Card's heading). */
@@ -1695,8 +1709,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1695
1709
  .aura-tbl--stack-md, .aura-tbl--stack-md > .aura-tbl__body, .aura-tbl--stack-md > .aura-tbl__foot, .aura-tbl--stack-md > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row, .aura-tbl--stack-md > * > .aura-tbl__row > .aura-tbl__th, .aura-tbl--stack-md > * > .aura-tbl__row > .aura-tbl__td { display: block; }
1696
1710
  .aura-tbl--stack-md > .aura-tbl__head { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1697
1711
  .aura-tbl--stack-md > .aura-tbl__caption { display: block; padding: var(--aura-space-4) var(--aura-space-4) 0; }
1698
- .aura-tbl--stack-md > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row { padding: var(--aura-space-3) var(--aura-space-4); }
1699
- .aura-tbl-wrap[data-density='compact'] > .aura-tbl--stack-md > * > .aura-tbl__row { padding-top: var(--aura-space-2); padding-bottom: var(--aura-space-2); }
1712
+ .aura-tbl--stack-md > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row { padding: var(--aura-tbl-cell-py, var(--aura-space-3)) var(--aura-space-4); }
1700
1713
  .aura-tbl--stack-md > .aura-tbl__body > .aura-tbl__row + .aura-tbl__row, .aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row:first-child { border-top: 1px solid var(--aura-border-default); }
1701
1714
  .aura-tbl--stack-md > * > .aura-tbl__row > .aura-tbl__th, .aura-tbl--stack-md > * > .aura-tbl__row > .aura-tbl__td { padding: 0; border-top: 0; background: none; text-align: start; white-space: normal; }
1702
1715
  .aura-tbl--stack-md > * > .aura-tbl__row > * + * { margin-top: var(--aura-space-2); }
@@ -1718,8 +1731,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1718
1731
  .aura-tbl--stack-sm, .aura-tbl--stack-sm > .aura-tbl__body, .aura-tbl--stack-sm > .aura-tbl__foot, .aura-tbl--stack-sm > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row, .aura-tbl--stack-sm > * > .aura-tbl__row > .aura-tbl__th, .aura-tbl--stack-sm > * > .aura-tbl__row > .aura-tbl__td { display: block; }
1719
1732
  .aura-tbl--stack-sm > .aura-tbl__head { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1720
1733
  .aura-tbl--stack-sm > .aura-tbl__caption { display: block; padding: var(--aura-space-4) var(--aura-space-4) 0; }
1721
- .aura-tbl--stack-sm > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row { padding: var(--aura-space-3) var(--aura-space-4); }
1722
- .aura-tbl-wrap[data-density='compact'] > .aura-tbl--stack-sm > * > .aura-tbl__row { padding-top: var(--aura-space-2); padding-bottom: var(--aura-space-2); }
1734
+ .aura-tbl--stack-sm > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row { padding: var(--aura-tbl-cell-py, var(--aura-space-3)) var(--aura-space-4); }
1723
1735
  .aura-tbl--stack-sm > .aura-tbl__body > .aura-tbl__row + .aura-tbl__row, .aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row:first-child { border-top: 1px solid var(--aura-border-default); }
1724
1736
  .aura-tbl--stack-sm > * > .aura-tbl__row > .aura-tbl__th, .aura-tbl--stack-sm > * > .aura-tbl__row > .aura-tbl__td { padding: 0; border-top: 0; background: none; text-align: start; white-space: normal; }
1725
1737
  .aura-tbl--stack-sm > * > .aura-tbl__row > * + * { margin-top: var(--aura-space-2); }
@@ -1745,24 +1757,22 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1745
1757
  .aura-tbl-cards--md > .aura-tbl-wrap { border: 0; border-radius: 0; background: transparent; overflow: visible; }
1746
1758
  .aura-tbl--cards.aura-tbl--stack-md > .aura-tbl__caption { padding: 0 0 var(--aura-space-3); }
1747
1759
  .aura-tbl--cards.aura-tbl--stack-md > .aura-tbl__body > .aura-tbl__row, .aura-tbl--cards.aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row {
1748
- margin-bottom: var(--aura-space-2); padding: var(--aura-space-4);
1760
+ margin-bottom: var(--aura-space-2); padding: var(--aura-tbl-card-py, var(--aura-space-4)) var(--aura-space-4);
1749
1761
  border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); background: var(--aura-bg-surface);
1750
1762
  }
1751
1763
  .aura-tbl--cards.aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row { background: var(--aura-bg-canvas); }
1752
1764
  .aura-tbl--cards.aura-tbl--stack-md > :last-child > .aura-tbl__row:last-child { margin-bottom: 0; }
1753
- .aura-tbl-wrap[data-density='compact'] > .aura-tbl--cards.aura-tbl--stack-md > * > .aura-tbl__row { padding-top: var(--aura-space-2); padding-bottom: var(--aura-space-2); }
1754
1765
  .aura-tbl-wrap.is-flush > .aura-tbl--cards.aura-tbl--stack-md > .aura-tbl__caption { padding: 0 0 var(--aura-space-3); }
1755
1766
  }
1756
1767
  @container aura-tbl (width < 640px) {
1757
1768
  .aura-tbl-cards--sm > .aura-tbl-wrap { border: 0; border-radius: 0; background: transparent; overflow: visible; }
1758
1769
  .aura-tbl--cards.aura-tbl--stack-sm > .aura-tbl__caption { padding: 0 0 var(--aura-space-3); }
1759
1770
  .aura-tbl--cards.aura-tbl--stack-sm > .aura-tbl__body > .aura-tbl__row, .aura-tbl--cards.aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row {
1760
- margin-bottom: var(--aura-space-2); padding: var(--aura-space-4);
1771
+ margin-bottom: var(--aura-space-2); padding: var(--aura-tbl-card-py, var(--aura-space-4)) var(--aura-space-4);
1761
1772
  border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); background: var(--aura-bg-surface);
1762
1773
  }
1763
1774
  .aura-tbl--cards.aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row { background: var(--aura-bg-canvas); }
1764
1775
  .aura-tbl--cards.aura-tbl--stack-sm > :last-child > .aura-tbl__row:last-child { margin-bottom: 0; }
1765
- .aura-tbl-wrap[data-density='compact'] > .aura-tbl--cards.aura-tbl--stack-sm > * > .aura-tbl__row { padding-top: var(--aura-space-2); padding-bottom: var(--aura-space-2); }
1766
1776
  .aura-tbl-wrap.is-flush > .aura-tbl--cards.aura-tbl--stack-sm > .aura-tbl__caption { padding: 0 0 var(--aura-space-3); }
1767
1777
  }
1768
1778
 
@@ -1576,10 +1576,14 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1576
1576
  [data-density='compact'] {
1577
1577
  --aura-input-height: 36px; --aura-button-height: 36px; --aura-table-row-height: 40px;
1578
1578
  --aura-button-padding-x: var(--aura-space-4);
1579
+ /* 5.20 (Chamber-OS 115): a static Table's vertical cell padding, and its stacked cards', inherited from the nearest
1580
+ * density — a provider's wrapper, <html>, or the table's own wrap — so "comfortable" inside compact switches back. */
1581
+ --aura-tbl-cell-py: var(--aura-space-2); --aura-tbl-card-py: var(--aura-space-2);
1579
1582
  }
1580
1583
  [data-density='comfortable'] {
1581
1584
  --aura-input-height: 44px; --aura-button-height: 44px; --aura-table-row-height: 48px;
1582
1585
  --aura-button-padding-x: var(--aura-space-6);
1586
+ --aura-tbl-cell-py: var(--aura-space-3); --aura-tbl-card-py: var(--aura-space-4);
1583
1587
  }
1584
1588
  @media (pointer: coarse) {
1585
1589
  [data-density='compact'] { --aura-input-height: 44px; --aura-button-height: 44px; --aura-table-row-height: 48px; --aura-button-padding-x: var(--aura-space-6); }
@@ -1638,20 +1642,31 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1638
1642
 
1639
1643
  /* ---------- 4.19: ActionBar ---------- */
1640
1644
  /* Sticky, not fixed: it keeps its place at the end of its parent, so it never covers the last field. */
1641
- .aura-actionbar { position: sticky; z-index: var(--aura-z-bar); box-sizing: border-box; background: var(--aura-bg-surface); color: var(--aura-fg-primary); font-family: var(--font-sans); }
1645
+ .aura-actionbar { position: sticky; z-index: var(--aura-z-bar); box-sizing: border-box; width: 100%; container: aura-actionbar / inline-size; contain-intrinsic-inline-size: auto 20rem; /* 5.20: its own width decides its layout (a bar in a card or dialog); a size container can't size to its content, so in a shrink-to-fit parent it falls back to 20rem */ background: var(--aura-bg-surface); color: var(--aura-fg-primary); font-family: var(--font-sans); }
1642
1646
  .aura-actionbar--viewport {
1643
1647
  bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px)));
1644
1648
  margin-top: var(--aura-space-6);
1645
1649
  border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay);
1646
1650
  }
1647
1651
  .aura-actionbar--container { bottom: 0; border-top: 1px solid var(--aura-border-default); }
1648
- .aura-actionbar__inner { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2) var(--aura-space-3); min-height: 60px; box-sizing: border-box; padding: var(--aura-space-2) var(--aura-space-3) var(--aura-space-2) var(--aura-space-4); }
1652
+ .aura-actionbar__inner { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2) var(--aura-space-3); min-height: 60px; box-sizing: border-box; padding-block: var(--aura-space-2); padding-inline: var(--aura-space-4) var(--aura-space-3); }
1649
1653
  .aura-actionbar__status { flex: 1 1 8rem; min-width: 0; font-size: 14px; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; }
1650
1654
  .aura-actionbar__status:empty { flex-basis: 0; }
1651
- .aura-actionbar__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin-left: auto; }
1655
+ /* 5.20: an empty status leaves the row (it would still take a gap and push the start slot away from its edge) but
1656
+ * stays in the page as a live region, so the next status is announced. */
1657
+ .aura-actionbar__inner.has-start > .aura-actionbar__status:empty { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
1658
+ .aura-actionbar__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin-inline-start: auto; }
1652
1659
  /* Bulk bar with nothing selected: out of sight and out of the tab order, its live region still in the page. */
1653
1660
  .aura-actionbar.is-idle { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; box-shadow: none; }
1654
- .aura-actionbar--container > .aura-actionbar__inner { padding-left: 0; padding-right: 0; }
1661
+ .aura-actionbar--container > .aura-actionbar__inner { padding-inline: 0; }
1662
+ /* 5.20 (Chamber-OS 116): the start slot. After the status in the markup, so Tab reaches it before the actions (the
1663
+ * status is a live region, not focusable, so only reading order differs); when the bar is 640px or wider it moves to
1664
+ * the start edge, the status (if any) between. Narrower bars — a phone, a card, a dialog — put a status line on its own
1665
+ * row, so the start slot and the actions stay together on the next. */
1666
+ .aura-actionbar__start { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); }
1667
+ .aura-actionbar__start:empty { display: none; }
1668
+ @container aura-actionbar (min-width: 640px) { .aura-actionbar__start { order: -1; } }
1669
+ @container aura-actionbar (max-width: 639.98px) { .aura-actionbar__inner.has-start > .aura-actionbar__status:not(:empty) { flex-basis: 100%; } }
1655
1670
 
1656
1671
  /* ---------- 4.20: Separator ---------- */
1657
1672
  .aura-separator { flex: none; align-self: stretch; height: 1px; margin: var(--aura-separator-space, 0) 0; background: var(--aura-border-default); border: 0; }
@@ -1665,7 +1680,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1665
1680
  }
1666
1681
  .aura-tbl { width: 100%; border-collapse: collapse; border-spacing: 0; font-size: 13px; line-height: 20px; }
1667
1682
  .aura-tbl__caption { caption-side: top; padding: var(--aura-space-4) var(--aura-space-6) 0; text-align: left; font-size: 14px; font-weight: 600; }
1668
- .aura-tbl__th, .aura-tbl__td { padding: var(--aura-space-3) var(--aura-space-4); text-align: left; vertical-align: top; overflow-wrap: anywhere; }
1683
+ .aura-tbl__th, .aura-tbl__td { padding: var(--aura-tbl-cell-py, var(--aura-space-3)) var(--aura-space-4); text-align: left; vertical-align: top; overflow-wrap: anywhere; }
1669
1684
  .aura-tbl__th:first-child, .aura-tbl__td:first-child { padding-left: var(--aura-space-6); }
1670
1685
  .aura-tbl__th:last-child, .aura-tbl__td:last-child { padding-right: var(--aura-space-6); }
1671
1686
  .aura-tbl__head .aura-tbl__th {
@@ -1680,7 +1695,6 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1680
1695
  .aura-tbl .is-end { text-align: right; }
1681
1696
  .aura-tbl .is-center { text-align: center; }
1682
1697
  .aura-tbl .is-numeric { font-variant-numeric: tabular-nums; white-space: nowrap; }
1683
- .aura-tbl-wrap[data-density='compact'] .aura-tbl__th, .aura-tbl-wrap[data-density='compact'] .aura-tbl__td { padding-top: var(--aura-space-2); padding-bottom: var(--aura-space-2); }
1684
1698
  .aura-tbl-wrap:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 2px; }
1685
1699
  /* 5.13 (Chamber-OS 81): align="middle" centres body and footer cells on their row; bordered={false} drops the frame and
1686
1700
  * the outer cells' side padding, so the table lines up with what's around it (a Card's heading). */
@@ -1697,8 +1711,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1697
1711
  .aura-tbl--stack-md, .aura-tbl--stack-md > .aura-tbl__body, .aura-tbl--stack-md > .aura-tbl__foot, .aura-tbl--stack-md > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row, .aura-tbl--stack-md > * > .aura-tbl__row > .aura-tbl__th, .aura-tbl--stack-md > * > .aura-tbl__row > .aura-tbl__td { display: block; }
1698
1712
  .aura-tbl--stack-md > .aura-tbl__head { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1699
1713
  .aura-tbl--stack-md > .aura-tbl__caption { display: block; padding: var(--aura-space-4) var(--aura-space-4) 0; }
1700
- .aura-tbl--stack-md > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row { padding: var(--aura-space-3) var(--aura-space-4); }
1701
- .aura-tbl-wrap[data-density='compact'] > .aura-tbl--stack-md > * > .aura-tbl__row { padding-top: var(--aura-space-2); padding-bottom: var(--aura-space-2); }
1714
+ .aura-tbl--stack-md > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row { padding: var(--aura-tbl-cell-py, var(--aura-space-3)) var(--aura-space-4); }
1702
1715
  .aura-tbl--stack-md > .aura-tbl__body > .aura-tbl__row + .aura-tbl__row, .aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row:first-child { border-top: 1px solid var(--aura-border-default); }
1703
1716
  .aura-tbl--stack-md > * > .aura-tbl__row > .aura-tbl__th, .aura-tbl--stack-md > * > .aura-tbl__row > .aura-tbl__td { padding: 0; border-top: 0; background: none; text-align: start; white-space: normal; }
1704
1717
  .aura-tbl--stack-md > * > .aura-tbl__row > * + * { margin-top: var(--aura-space-2); }
@@ -1720,8 +1733,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1720
1733
  .aura-tbl--stack-sm, .aura-tbl--stack-sm > .aura-tbl__body, .aura-tbl--stack-sm > .aura-tbl__foot, .aura-tbl--stack-sm > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row, .aura-tbl--stack-sm > * > .aura-tbl__row > .aura-tbl__th, .aura-tbl--stack-sm > * > .aura-tbl__row > .aura-tbl__td { display: block; }
1721
1734
  .aura-tbl--stack-sm > .aura-tbl__head { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1722
1735
  .aura-tbl--stack-sm > .aura-tbl__caption { display: block; padding: var(--aura-space-4) var(--aura-space-4) 0; }
1723
- .aura-tbl--stack-sm > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row { padding: var(--aura-space-3) var(--aura-space-4); }
1724
- .aura-tbl-wrap[data-density='compact'] > .aura-tbl--stack-sm > * > .aura-tbl__row { padding-top: var(--aura-space-2); padding-bottom: var(--aura-space-2); }
1736
+ .aura-tbl--stack-sm > .aura-tbl__body > .aura-tbl__row, .aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row { padding: var(--aura-tbl-cell-py, var(--aura-space-3)) var(--aura-space-4); }
1725
1737
  .aura-tbl--stack-sm > .aura-tbl__body > .aura-tbl__row + .aura-tbl__row, .aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row:first-child { border-top: 1px solid var(--aura-border-default); }
1726
1738
  .aura-tbl--stack-sm > * > .aura-tbl__row > .aura-tbl__th, .aura-tbl--stack-sm > * > .aura-tbl__row > .aura-tbl__td { padding: 0; border-top: 0; background: none; text-align: start; white-space: normal; }
1727
1739
  .aura-tbl--stack-sm > * > .aura-tbl__row > * + * { margin-top: var(--aura-space-2); }
@@ -1747,24 +1759,22 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1747
1759
  .aura-tbl-cards--md > .aura-tbl-wrap { border: 0; border-radius: 0; background: transparent; overflow: visible; }
1748
1760
  .aura-tbl--cards.aura-tbl--stack-md > .aura-tbl__caption { padding: 0 0 var(--aura-space-3); }
1749
1761
  .aura-tbl--cards.aura-tbl--stack-md > .aura-tbl__body > .aura-tbl__row, .aura-tbl--cards.aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row {
1750
- margin-bottom: var(--aura-space-2); padding: var(--aura-space-4);
1762
+ margin-bottom: var(--aura-space-2); padding: var(--aura-tbl-card-py, var(--aura-space-4)) var(--aura-space-4);
1751
1763
  border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); background: var(--aura-bg-surface);
1752
1764
  }
1753
1765
  .aura-tbl--cards.aura-tbl--stack-md > .aura-tbl__foot > .aura-tbl__row { background: var(--aura-bg-canvas); }
1754
1766
  .aura-tbl--cards.aura-tbl--stack-md > :last-child > .aura-tbl__row:last-child { margin-bottom: 0; }
1755
- .aura-tbl-wrap[data-density='compact'] > .aura-tbl--cards.aura-tbl--stack-md > * > .aura-tbl__row { padding-top: var(--aura-space-2); padding-bottom: var(--aura-space-2); }
1756
1767
  .aura-tbl-wrap.is-flush > .aura-tbl--cards.aura-tbl--stack-md > .aura-tbl__caption { padding: 0 0 var(--aura-space-3); }
1757
1768
  }
1758
1769
  @container aura-tbl (width < 640px) {
1759
1770
  .aura-tbl-cards--sm > .aura-tbl-wrap { border: 0; border-radius: 0; background: transparent; overflow: visible; }
1760
1771
  .aura-tbl--cards.aura-tbl--stack-sm > .aura-tbl__caption { padding: 0 0 var(--aura-space-3); }
1761
1772
  .aura-tbl--cards.aura-tbl--stack-sm > .aura-tbl__body > .aura-tbl__row, .aura-tbl--cards.aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row {
1762
- margin-bottom: var(--aura-space-2); padding: var(--aura-space-4);
1773
+ margin-bottom: var(--aura-space-2); padding: var(--aura-tbl-card-py, var(--aura-space-4)) var(--aura-space-4);
1763
1774
  border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); background: var(--aura-bg-surface);
1764
1775
  }
1765
1776
  .aura-tbl--cards.aura-tbl--stack-sm > .aura-tbl__foot > .aura-tbl__row { background: var(--aura-bg-canvas); }
1766
1777
  .aura-tbl--cards.aura-tbl--stack-sm > :last-child > .aura-tbl__row:last-child { margin-bottom: 0; }
1767
- .aura-tbl-wrap[data-density='compact'] > .aura-tbl--cards.aura-tbl--stack-sm > * > .aura-tbl__row { padding-top: var(--aura-space-2); padding-bottom: var(--aura-space-2); }
1768
1778
  .aura-tbl-wrap.is-flush > .aura-tbl--cards.aura-tbl--stack-sm > .aura-tbl__caption { padding: 0 0 var(--aura-space-3); }
1769
1779
  }
1770
1780
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.19.0",
3
+ "version": "5.20.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",