@jirawatpyk/aura-react 5.44.0 → 5.45.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.
@@ -12,6 +12,8 @@ const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
12
12
  const below = props.actionsFullWidthBelow;
13
13
  const hide = props.titleHideBelow;
14
14
  const hasMeta = props.meta != null && props.meta !== false;
15
+ const hasActions = props.actions != null && props.actions !== false;
16
+ const bar = hasActions && (props.actionsBarBelow === "sm" || props.actionsBarBelow === "md") ? props.actionsBarBelow : null;
15
17
  return h(
16
18
  "div",
17
19
  Object.assign(attrs, {
@@ -21,6 +23,7 @@ const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
21
23
  (below === "sm" || below === "md" || below === "lg") && "aura-page-header--actions-full-below-" + below,
22
24
  (hide === "sm" || hide === "md" || hide === "lg") && "aura-page-header--title-hide-below-" + hide,
23
25
  (hide === "sm" || hide === "md" || hide === "lg") && !hasMeta && "has-no-meta",
26
+ bar && "aura-page-header--actions-bar-below-" + bar,
24
27
  props.className
25
28
  ),
26
29
  style: props.style
@@ -33,7 +36,12 @@ const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
33
36
  h("h" + level, { className: "aura-page-header__title", id: props.titleId }, props.title),
34
37
  props.meta != null && props.meta !== false ? h("div", { className: "aura-page-header__meta" }, props.meta) : null
35
38
  ),
36
- props.actions != null && props.actions !== false ? h("div", { className: "aura-page-header__actions" }, props.actions) : null
39
+ props.actions != null && props.actions !== false ? h(
40
+ "div",
41
+ { className: "aura-page-header__actions" },
42
+ bar && props.actionsStatus != null && props.actionsStatus !== false ? h("div", { className: "aura-page-header__status", role: "status" }, props.actionsStatus) : null,
43
+ props.actions
44
+ ) : null
37
45
  );
38
46
  });
39
47
  export {
@@ -0,0 +1,62 @@
1
+ 'use client';
2
+ import * as React from "react";
3
+ import { PageHeader as StaticPageHeader } from "./PageHeader.js";
4
+ import { devWarnOnce, useMergedRef } from "./internal.js";
5
+ const NAME = "--aura-page-actions-height";
6
+ const bars = [];
7
+ function trapped(el) {
8
+ for (let p = el.parentElement; p && p !== document.documentElement; p = p.parentElement) {
9
+ const s = getComputedStyle(p);
10
+ if (s.transform !== "none" || s.filter !== "none" || (s.backdropFilter || "none") !== "none" || s.contentVisibility === "auto" || s.perspective !== "none" || /transform|filter|perspective/.test(s.willChange) || /paint|layout|strict|content/.test(s.contain))
11
+ return true;
12
+ }
13
+ return false;
14
+ }
15
+ const PageHeader = React.forwardRef(function PageHeader2(props, ref) {
16
+ const own = React.useRef(null);
17
+ const merged = useMergedRef(ref, own);
18
+ const bar = props.actionsBarBelow;
19
+ const hasActions = props.actions != null && props.actions !== false;
20
+ React.useEffect(
21
+ function() {
22
+ if (bar !== "sm" && bar !== "md" || !hasActions || !own.current) return;
23
+ const el = own.current.querySelector(":scope > .aura-page-header__actions");
24
+ if (!el) return;
25
+ const root = document.documentElement;
26
+ let checked = false;
27
+ function sync() {
28
+ if (bars[bars.length - 1] !== sync) return;
29
+ if (getComputedStyle(el).position === "fixed") {
30
+ root.style.setProperty(NAME, el.offsetHeight + "px");
31
+ if (!checked && (checked = true, trapped(el)))
32
+ devWarnOnce(
33
+ "pageheader-bar-trapped",
34
+ "PageHeader actionsBarBelow: an ancestor has a transform, filter, will-change or paint containment, so the fixed bar is placed against it instead of the screen. Remove it from the page header's ancestors."
35
+ );
36
+ } else root.style.removeProperty(NAME);
37
+ }
38
+ if (bars.length)
39
+ devWarnOnce(
40
+ "pageheader-bar-twice",
41
+ "PageHeader actionsBarBelow: two bars on one page overlap at the bottom of the screen. Give it to one PageHeader per page."
42
+ );
43
+ bars.push(sync);
44
+ const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(sync);
45
+ if (ro) ro.observe(el);
46
+ window.addEventListener("resize", sync);
47
+ sync();
48
+ return function() {
49
+ if (ro) ro.disconnect();
50
+ window.removeEventListener("resize", sync);
51
+ bars.splice(bars.indexOf(sync), 1);
52
+ if (bars.length) bars[bars.length - 1]();
53
+ else root.style.removeProperty(NAME);
54
+ };
55
+ },
56
+ [bar, hasActions]
57
+ );
58
+ return /* @__PURE__ */ React.createElement(StaticPageHeader, { ...props, ref: merged });
59
+ });
60
+ export {
61
+ PageHeader
62
+ };
package/dist/esm/index.js CHANGED
@@ -35,7 +35,7 @@ import { Avatar } from "./Avatar.js";
35
35
  import { Stack } from "./Stack.js";
36
36
  import { Grid } from "./Grid.js";
37
37
  import { Container } from "./Container.js";
38
- import { PageHeader } from "./PageHeader.js";
38
+ import { PageHeader } from "./PageHeaderClient.js";
39
39
  import { StatusTile } from "./StatusTile.js";
40
40
  import { TileGrid, Sparkline } from "./tiles.js";
41
41
  import { AppShell } from "./AppShell.js";
package/dist/index.d.cts CHANGED
@@ -1953,6 +1953,19 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
1953
1953
  * readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
1954
1954
  * meta line and actions stay; with no meta, the actions start the header. */
1955
1955
  titleHideBelow?: "sm" | "md" | "lg" | undefined;
1956
+ /** 5.45 (Chamber-OS 150): below this breakpoint (`sm` 640px, `md` 768px) the same `actions` — rendered once, so a
1957
+ * dialog trigger or test id is never doubled — become a bar fixed to the bottom of the screen with ActionBar's look:
1958
+ * above a BottomNav, clear of the home indicator, `actionsStatus` as its status line. The page's end and a focused
1959
+ * field scroll clear of it (AppShell's content, or the body, gains the bar's height). With an IconButton among them
1960
+ * the actions share one row, labels wrapping inside the buttons (as `actionsFullWidthBelow`, Chamber-OS 149); with only icon
1961
+ * buttons the status and the icons share one row. From the breakpoint up nothing changes. Use it for a detail page's
1962
+ * own actions (Issue credit note…, ⋯) — one per page. The bar is `position: fixed`: no ancestor of the header may
1963
+ * have a transform, filter, backdrop-filter, will-change, paint/layout containment or `content-visibility: auto`, or it is placed
1964
+ * against that ancestor instead of the screen — the main entry warns in development. */
1965
+ actionsBarBelow?: "sm" | "md" | undefined;
1966
+ /** 5.45: the bar's status line ("Total 10,700.00 THB incl. VAT · due 22 Oct 2026"), shown only while the actions are
1967
+ * a bar, in a polite live region. */
1968
+ actionsStatus?: React$1.ReactNode | undefined;
1956
1969
  /** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
1957
1970
  headingLevel?: 1 | 2 | 3 | undefined;
1958
1971
  /** The heading's id, for `aria-labelledby` on the page's region. */
package/dist/index.d.ts CHANGED
@@ -1953,6 +1953,19 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
1953
1953
  * readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
1954
1954
  * meta line and actions stay; with no meta, the actions start the header. */
1955
1955
  titleHideBelow?: "sm" | "md" | "lg" | undefined;
1956
+ /** 5.45 (Chamber-OS 150): below this breakpoint (`sm` 640px, `md` 768px) the same `actions` — rendered once, so a
1957
+ * dialog trigger or test id is never doubled — become a bar fixed to the bottom of the screen with ActionBar's look:
1958
+ * above a BottomNav, clear of the home indicator, `actionsStatus` as its status line. The page's end and a focused
1959
+ * field scroll clear of it (AppShell's content, or the body, gains the bar's height). With an IconButton among them
1960
+ * the actions share one row, labels wrapping inside the buttons (as `actionsFullWidthBelow`, Chamber-OS 149); with only icon
1961
+ * buttons the status and the icons share one row. From the breakpoint up nothing changes. Use it for a detail page's
1962
+ * own actions (Issue credit note…, ⋯) — one per page. The bar is `position: fixed`: no ancestor of the header may
1963
+ * have a transform, filter, backdrop-filter, will-change, paint/layout containment or `content-visibility: auto`, or it is placed
1964
+ * against that ancestor instead of the screen — the main entry warns in development. */
1965
+ actionsBarBelow?: "sm" | "md" | undefined;
1966
+ /** 5.45: the bar's status line ("Total 10,700.00 THB incl. VAT · due 22 Oct 2026"), shown only while the actions are
1967
+ * a bar, in a polite live region. */
1968
+ actionsStatus?: React$1.ReactNode | undefined;
1956
1969
  /** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
1957
1970
  headingLevel?: 1 | 2 | 3 | undefined;
1958
1971
  /** The heading's id, for `aria-labelledby` on the page's region. */
@@ -1443,6 +1443,8 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1443
1443
  const below = props.actionsFullWidthBelow;
1444
1444
  const hide = props.titleHideBelow;
1445
1445
  const hasMeta = props.meta != null && props.meta !== false;
1446
+ const hasActions = props.actions != null && props.actions !== false;
1447
+ const bar = hasActions && (props.actionsBarBelow === "sm" || props.actionsBarBelow === "md") ? props.actionsBarBelow : null;
1446
1448
  return h4(
1447
1449
  "div",
1448
1450
  Object.assign(attrs2, {
@@ -1452,6 +1454,7 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1452
1454
  (below === "sm" || below === "md" || below === "lg") && "aura-page-header--actions-full-below-" + below,
1453
1455
  (hide === "sm" || hide === "md" || hide === "lg") && "aura-page-header--title-hide-below-" + hide,
1454
1456
  (hide === "sm" || hide === "md" || hide === "lg") && !hasMeta && "has-no-meta",
1457
+ bar && "aura-page-header--actions-bar-below-" + bar,
1455
1458
  props.className
1456
1459
  ),
1457
1460
  style: props.style
@@ -1464,7 +1467,12 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1464
1467
  h4("h" + level, { className: "aura-page-header__title", id: props.titleId }, props.title),
1465
1468
  props.meta != null && props.meta !== false ? h4("div", { className: "aura-page-header__meta" }, props.meta) : null
1466
1469
  ),
1467
- props.actions != null && props.actions !== false ? h4("div", { className: "aura-page-header__actions" }, props.actions) : null
1470
+ props.actions != null && props.actions !== false ? h4(
1471
+ "div",
1472
+ { className: "aura-page-header__actions" },
1473
+ bar && props.actionsStatus != null && props.actionsStatus !== false ? h4("div", { className: "aura-page-header__status", role: "status" }, props.actionsStatus) : null,
1474
+ props.actions
1475
+ ) : null
1468
1476
  );
1469
1477
  });
1470
1478
 
@@ -511,6 +511,19 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
511
511
  * readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
512
512
  * meta line and actions stay; with no meta, the actions start the header. */
513
513
  titleHideBelow?: "sm" | "md" | "lg" | undefined;
514
+ /** 5.45 (Chamber-OS 150): below this breakpoint (`sm` 640px, `md` 768px) the same `actions` — rendered once, so a
515
+ * dialog trigger or test id is never doubled — become a bar fixed to the bottom of the screen with ActionBar's look:
516
+ * above a BottomNav, clear of the home indicator, `actionsStatus` as its status line. The page's end and a focused
517
+ * field scroll clear of it (AppShell's content, or the body, gains the bar's height). With an IconButton among them
518
+ * the actions share one row, labels wrapping inside the buttons (as `actionsFullWidthBelow`, Chamber-OS 149); with only icon
519
+ * buttons the status and the icons share one row. From the breakpoint up nothing changes. Use it for a detail page's
520
+ * own actions (Issue credit note…, ⋯) — one per page. The bar is `position: fixed`: no ancestor of the header may
521
+ * have a transform, filter, backdrop-filter, will-change, paint/layout containment or `content-visibility: auto`, or it is placed
522
+ * against that ancestor instead of the screen — the main entry warns in development. */
523
+ actionsBarBelow?: "sm" | "md" | undefined;
524
+ /** 5.45: the bar's status line ("Total 10,700.00 THB incl. VAT · due 22 Oct 2026"), shown only while the actions are
525
+ * a bar, in a polite live region. */
526
+ actionsStatus?: React$1.ReactNode | undefined;
514
527
  /** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
515
528
  headingLevel?: 1 | 2 | 3 | undefined;
516
529
  /** The heading's id, for `aria-labelledby` on the page's region. */
@@ -511,6 +511,19 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
511
511
  * readers — and the breadcrumb and eyebrow are hidden, for phone layouts that show the title in the top bar. The
512
512
  * meta line and actions stay; with no meta, the actions start the header. */
513
513
  titleHideBelow?: "sm" | "md" | "lg" | undefined;
514
+ /** 5.45 (Chamber-OS 150): below this breakpoint (`sm` 640px, `md` 768px) the same `actions` — rendered once, so a
515
+ * dialog trigger or test id is never doubled — become a bar fixed to the bottom of the screen with ActionBar's look:
516
+ * above a BottomNav, clear of the home indicator, `actionsStatus` as its status line. The page's end and a focused
517
+ * field scroll clear of it (AppShell's content, or the body, gains the bar's height). With an IconButton among them
518
+ * the actions share one row, labels wrapping inside the buttons (as `actionsFullWidthBelow`, Chamber-OS 149); with only icon
519
+ * buttons the status and the icons share one row. From the breakpoint up nothing changes. Use it for a detail page's
520
+ * own actions (Issue credit note…, ⋯) — one per page. The bar is `position: fixed`: no ancestor of the header may
521
+ * have a transform, filter, backdrop-filter, will-change, paint/layout containment or `content-visibility: auto`, or it is placed
522
+ * against that ancestor instead of the screen — the main entry warns in development. */
523
+ actionsBarBelow?: "sm" | "md" | undefined;
524
+ /** 5.45: the bar's status line ("Total 10,700.00 THB incl. VAT · due 22 Oct 2026"), shown only while the actions are
525
+ * a bar, in a polite live region. */
526
+ actionsStatus?: React$1.ReactNode | undefined;
514
527
  /** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
515
528
  headingLevel?: 1 | 2 | 3 | undefined;
516
529
  /** The heading's id, for `aria-labelledby` on the page's region. */
@@ -1379,6 +1379,8 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1379
1379
  const below = props.actionsFullWidthBelow;
1380
1380
  const hide = props.titleHideBelow;
1381
1381
  const hasMeta = props.meta != null && props.meta !== false;
1382
+ const hasActions = props.actions != null && props.actions !== false;
1383
+ const bar = hasActions && (props.actionsBarBelow === "sm" || props.actionsBarBelow === "md") ? props.actionsBarBelow : null;
1382
1384
  return h4(
1383
1385
  "div",
1384
1386
  Object.assign(attrs2, {
@@ -1388,6 +1390,7 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1388
1390
  (below === "sm" || below === "md" || below === "lg") && "aura-page-header--actions-full-below-" + below,
1389
1391
  (hide === "sm" || hide === "md" || hide === "lg") && "aura-page-header--title-hide-below-" + hide,
1390
1392
  (hide === "sm" || hide === "md" || hide === "lg") && !hasMeta && "has-no-meta",
1393
+ bar && "aura-page-header--actions-bar-below-" + bar,
1391
1394
  props.className
1392
1395
  ),
1393
1396
  style: props.style
@@ -1400,7 +1403,12 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1400
1403
  h4("h" + level, { className: "aura-page-header__title", id: props.titleId }, props.title),
1401
1404
  props.meta != null && props.meta !== false ? h4("div", { className: "aura-page-header__meta" }, props.meta) : null
1402
1405
  ),
1403
- props.actions != null && props.actions !== false ? h4("div", { className: "aura-page-header__actions" }, props.actions) : null
1406
+ props.actions != null && props.actions !== false ? h4(
1407
+ "div",
1408
+ { className: "aura-page-header__actions" },
1409
+ bar && props.actionsStatus != null && props.actionsStatus !== false ? h4("div", { className: "aura-page-header__status", role: "status" }, props.actionsStatus) : null,
1410
+ props.actions
1411
+ ) : null
1404
1412
  );
1405
1413
  });
1406
1414
 
package/dist/styles.css CHANGED
@@ -1184,6 +1184,7 @@ a.aura-tab { text-decoration: none; }
1184
1184
  .aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: nowrap; align-items: stretch; }
1185
1185
  .aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > * { min-width: 0; }
1186
1186
  .aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1187
+ .aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; } /* 5.45 (Chamber-OS addendum 52): centred on a taller button */
1187
1188
  }
1188
1189
  @media (max-width: 767.98px) {
1189
1190
  .aura-page-header--actions-full-below-md > .aura-page-header__actions { flex: 1 1 100%; gap: var(--aura-space-3); }
@@ -1194,6 +1195,7 @@ a.aura-tab { text-decoration: none; }
1194
1195
  .aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: nowrap; align-items: stretch; }
1195
1196
  .aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > * { min-width: 0; }
1196
1197
  .aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1198
+ .aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; } /* 5.45 (Chamber-OS addendum 52): centred on a taller button */
1197
1199
  }
1198
1200
  @media (max-width: 1023.98px) {
1199
1201
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions { flex: 1 1 100%; gap: var(--aura-space-3); }
@@ -1204,7 +1206,44 @@ a.aura-tab { text-decoration: none; }
1204
1206
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: nowrap; align-items: stretch; }
1205
1207
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > * { min-width: 0; }
1206
1208
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1209
+ .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; } /* 5.45 (Chamber-OS addendum 52): centred on a taller button */
1207
1210
  }
1211
+ /* 5.45 (Chamber-OS 150): actionsBarBelow — the same actions become a fixed bar with a status line; the page gains its
1212
+ * height (--aura-page-actions-height, measured on the client) so its end and a focused field scroll clear. */
1213
+ .aura-page-header__status { display: none; }
1214
+ @media (max-width: 639.98px) {
1215
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions { position: fixed; z-index: var(--aura-z-bar); left: var(--aura-space-4); right: var(--aura-space-4); bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px))); box-sizing: border-box; min-height: 60px; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin: 0; padding: var(--aura-space-2) var(--aura-space-3) var(--aura-space-2) var(--aura-space-4); background: var(--aura-bg-surface); color: var(--aura-fg-primary); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay); transition: bottom var(--aura-duration-base) var(--aura-ease); }
1216
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > .aura-page-header__status { display: block; flex: 1 1 100%; min-width: 0; font-size: max(14px, .875rem); line-height: 1.5; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
1217
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > :not(.aura-page-header__status) { flex: 1 1 0; min-width: max-content; }
1218
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > :is(.aura-dropdown, .aura-tooltip-anchor, .aura-popover-anchor) > * { flex: 1 1 auto; }
1219
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > .aura-icon-btn { flex: none; }
1220
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > :has(> .aura-icon-btn) { flex: none; }
1221
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: wrap; align-items: stretch; }
1222
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :not(.aura-page-header__status) { min-width: 0; }
1223
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; }
1224
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1225
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions:not(:has(> .aura-btn, > * > .aura-btn)) > .aura-page-header__status { flex: 1 1 0; align-self: center; }
1226
+ :root:has(.aura-page-header--actions-bar-below-sm) { --aura-page-actions-space: calc(var(--aura-page-actions-height, 7rem) + var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px)) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-page-actions-space); }
1227
+ :root:has(.aura-page-header--actions-bar-below-sm) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-page-actions-space)); }
1228
+ :root:has(.aura-page-header--actions-bar-below-sm):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-page-actions-space); }
1229
+ }
1230
+ @media (max-width: 767.98px) {
1231
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions { position: fixed; z-index: var(--aura-z-bar); left: var(--aura-space-4); right: var(--aura-space-4); bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px))); box-sizing: border-box; min-height: 60px; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin: 0; padding: var(--aura-space-2) var(--aura-space-3) var(--aura-space-2) var(--aura-space-4); background: var(--aura-bg-surface); color: var(--aura-fg-primary); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay); transition: bottom var(--aura-duration-base) var(--aura-ease); }
1232
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions > .aura-page-header__status { display: block; flex: 1 1 100%; min-width: 0; font-size: max(14px, .875rem); line-height: 1.5; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
1233
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions > :not(.aura-page-header__status) { flex: 1 1 0; min-width: max-content; }
1234
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions > :is(.aura-dropdown, .aura-tooltip-anchor, .aura-popover-anchor) > * { flex: 1 1 auto; }
1235
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions > .aura-icon-btn { flex: none; }
1236
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions > :has(> .aura-icon-btn) { flex: none; }
1237
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: wrap; align-items: stretch; }
1238
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :not(.aura-page-header__status) { min-width: 0; }
1239
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; }
1240
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1241
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions:not(:has(> .aura-btn, > * > .aura-btn)) > .aura-page-header__status { flex: 1 1 0; align-self: center; }
1242
+ :root:has(.aura-page-header--actions-bar-below-md) { --aura-page-actions-space: calc(var(--aura-page-actions-height, 7rem) + var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px)) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-page-actions-space); }
1243
+ :root:has(.aura-page-header--actions-bar-below-md) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-page-actions-space)); }
1244
+ :root:has(.aura-page-header--actions-bar-below-md):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-page-actions-space); }
1245
+ }
1246
+ @media (prefers-reduced-motion: reduce) { .aura-page-header__actions { transition: none; } }
1208
1247
  @media (min-width: 640px) { .aura-page-header__title { font-size: max(36px, 2.25rem); } }
1209
1248
  /* Thai marks need the room a 1.15 line takes away. */
1210
1249
  .aura-page-header__title:lang(th) { line-height: 1.4; letter-spacing: 0; }
@@ -1186,6 +1186,7 @@ a.aura-tab { text-decoration: none; }
1186
1186
  .aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: nowrap; align-items: stretch; }
1187
1187
  .aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > * { min-width: 0; }
1188
1188
  .aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1189
+ .aura-page-header--actions-full-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; } /* 5.45 (Chamber-OS addendum 52): centred on a taller button */
1189
1190
  }
1190
1191
  @media (max-width: 767.98px) {
1191
1192
  .aura-page-header--actions-full-below-md > .aura-page-header__actions { flex: 1 1 100%; gap: var(--aura-space-3); }
@@ -1196,6 +1197,7 @@ a.aura-tab { text-decoration: none; }
1196
1197
  .aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: nowrap; align-items: stretch; }
1197
1198
  .aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > * { min-width: 0; }
1198
1199
  .aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1200
+ .aura-page-header--actions-full-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; } /* 5.45 (Chamber-OS addendum 52): centred on a taller button */
1199
1201
  }
1200
1202
  @media (max-width: 1023.98px) {
1201
1203
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions { flex: 1 1 100%; gap: var(--aura-space-3); }
@@ -1206,7 +1208,44 @@ a.aura-tab { text-decoration: none; }
1206
1208
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: nowrap; align-items: stretch; }
1207
1209
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > * { min-width: 0; }
1208
1210
  .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1211
+ .aura-page-header--actions-full-below-lg > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; } /* 5.45 (Chamber-OS addendum 52): centred on a taller button */
1209
1212
  }
1213
+ /* 5.45 (Chamber-OS 150): actionsBarBelow — the same actions become a fixed bar with a status line; the page gains its
1214
+ * height (--aura-page-actions-height, measured on the client) so its end and a focused field scroll clear. */
1215
+ .aura-page-header__status { display: none; }
1216
+ @media (max-width: 639.98px) {
1217
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions { position: fixed; z-index: var(--aura-z-bar); left: var(--aura-space-4); right: var(--aura-space-4); bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px))); box-sizing: border-box; min-height: 60px; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin: 0; padding: var(--aura-space-2) var(--aura-space-3) var(--aura-space-2) var(--aura-space-4); background: var(--aura-bg-surface); color: var(--aura-fg-primary); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay); transition: bottom var(--aura-duration-base) var(--aura-ease); }
1218
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > .aura-page-header__status { display: block; flex: 1 1 100%; min-width: 0; font-size: max(14px, .875rem); line-height: 1.5; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
1219
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > :not(.aura-page-header__status) { flex: 1 1 0; min-width: max-content; }
1220
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > :is(.aura-dropdown, .aura-tooltip-anchor, .aura-popover-anchor) > * { flex: 1 1 auto; }
1221
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > .aura-icon-btn { flex: none; }
1222
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions > :has(> .aura-icon-btn) { flex: none; }
1223
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: wrap; align-items: stretch; }
1224
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :not(.aura-page-header__status) { min-width: 0; }
1225
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; }
1226
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1227
+ .aura-page-header--actions-bar-below-sm > .aura-page-header__actions:not(:has(> .aura-btn, > * > .aura-btn)) > .aura-page-header__status { flex: 1 1 0; align-self: center; }
1228
+ :root:has(.aura-page-header--actions-bar-below-sm) { --aura-page-actions-space: calc(var(--aura-page-actions-height, 7rem) + var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px)) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-page-actions-space); }
1229
+ :root:has(.aura-page-header--actions-bar-below-sm) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-page-actions-space)); }
1230
+ :root:has(.aura-page-header--actions-bar-below-sm):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-page-actions-space); }
1231
+ }
1232
+ @media (max-width: 767.98px) {
1233
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions { position: fixed; z-index: var(--aura-z-bar); left: var(--aura-space-4); right: var(--aura-space-4); bottom: calc(var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px))); box-sizing: border-box; min-height: 60px; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--aura-space-2); margin: 0; padding: var(--aura-space-2) var(--aura-space-3) var(--aura-space-2) var(--aura-space-4); background: var(--aura-bg-surface); color: var(--aura-fg-primary); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); box-shadow: var(--aura-shadow-overlay); transition: bottom var(--aura-duration-base) var(--aura-ease); }
1234
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions > .aura-page-header__status { display: block; flex: 1 1 100%; min-width: 0; font-size: max(14px, .875rem); line-height: 1.5; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
1235
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions > :not(.aura-page-header__status) { flex: 1 1 0; min-width: max-content; }
1236
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions > :is(.aura-dropdown, .aura-tooltip-anchor, .aura-popover-anchor) > * { flex: 1 1 auto; }
1237
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions > .aura-icon-btn { flex: none; }
1238
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions > :has(> .aura-icon-btn) { flex: none; }
1239
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) { flex-wrap: wrap; align-items: stretch; }
1240
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :not(.aura-page-header__status) { min-width: 0; }
1241
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-icon-btn, :has(> .aura-icon-btn)) { align-self: center; }
1242
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions:has(> .aura-icon-btn, > * > .aura-icon-btn) > :is(.aura-btn, * > .aura-btn):not(.aura-icon-btn) { height: auto; min-height: var(--aura-button-height); white-space: normal; padding: var(--aura-space-2) var(--aura-space-3); line-height: 1.35; text-align: center; overflow-wrap: anywhere; hyphens: auto; border-radius: min(var(--aura-button-radius), 22px); }
1243
+ .aura-page-header--actions-bar-below-md > .aura-page-header__actions:not(:has(> .aura-btn, > * > .aura-btn)) > .aura-page-header__status { flex: 1 1 0; align-self: center; }
1244
+ :root:has(.aura-page-header--actions-bar-below-md) { --aura-page-actions-space: calc(var(--aura-page-actions-height, 7rem) + var(--aura-bottomnav-offset, 0px) + max(var(--aura-space-3), env(safe-area-inset-bottom, 0px)) + var(--aura-space-3)); scroll-padding-bottom: var(--aura-page-actions-space); }
1245
+ :root:has(.aura-page-header--actions-bar-below-md) .aura-shell__content { padding-bottom: calc(var(--aura-space-6) + var(--aura-page-actions-space)); }
1246
+ :root:has(.aura-page-header--actions-bar-below-md):not(:has(.aura-shell__content)) body { padding-bottom: var(--aura-page-actions-space); }
1247
+ }
1248
+ @media (prefers-reduced-motion: reduce) { .aura-page-header__actions { transition: none; } }
1210
1249
  @media (min-width: 640px) { .aura-page-header__title { font-size: max(36px, 2.25rem); } }
1211
1250
  /* Thai marks need the room a 1.15 line takes away. */
1212
1251
  .aura-page-header__title:lang(th) { line-height: 1.4; letter-spacing: 0; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.44.0",
3
+ "version": "5.45.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",