@jirawatpyk/aura-react 5.31.0 → 5.32.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/dist/index.d.ts CHANGED
@@ -344,7 +344,8 @@ export interface IconButtonProps extends React$1.ButtonHTMLAttributes<HTMLButton
344
344
  icon: IconInput;
345
345
  /** `danger` colours the icon and hover for a destructive action (Delete, Revoke). */
346
346
  tone?: "neutral" | "danger" | undefined;
347
- /** Accessible name and tooltip (required). */
347
+ /** Accessible name and tooltip (required). Since 5.32 the tooltip is AURA's own (hover and keyboard focus), not a
348
+ * native `title`; pass `title` yourself to keep a native one instead. */
348
349
  label: string;
349
350
  /** Icon size. Default `sm` (16). */
350
351
  size?: "sm" | "md" | undefined;
@@ -828,6 +829,10 @@ export interface SideNavProps {
828
829
  defaultValue?: string | undefined;
829
830
  onChange?: ((id: string) => void) | undefined;
830
831
  header?: React$1.ReactNode | undefined;
832
+ /** 5.32 (DxT Monitor request 1): a full-width 1px aura-border-default line under `header`, with the board's metrics:
833
+ * the header at least 72px tall with its content 20px from the top and start, the line at its foot, and 16px
834
+ * before the first item. Default `false`. */
835
+ headerDivider?: boolean | undefined;
831
836
  footer?: React$1.ReactNode | undefined;
832
837
  /** Default "Main". */
833
838
  label?: string | undefined;
@@ -1214,7 +1219,9 @@ export interface AppShellProps {
1214
1219
  /** A BottomNav for phones (4.19). Shown below its `hideFrom` breakpoint; the content keeps room for it, and a
1215
1220
  * viewport ActionBar sits on top of it. With a `bottomNav` and no `nav`, there is no menu button. */
1216
1221
  bottomNav?: React$1.ReactElement | undefined;
1217
- /** `false` (5.14): `<main>` has no padding, for pages whose containers own the page padding and column. */
1222
+ /** The content padding is the page margin: 16px at the sides and 24px top and bottom on phones, 24px from 640px,
1223
+ * 32px from 1024px. Pages don't add their own (a PageHeader has none, 5.32). `false` (5.14): `<main>` has no
1224
+ * padding, for pages whose containers own the page padding and column. */
1218
1225
  contentPadding?: boolean | undefined;
1219
1226
  className?: string | undefined;
1220
1227
  }
@@ -1338,7 +1345,8 @@ export interface BottomNavItem {
1338
1345
  /** Read after the label when `badge` is set, e.g. "new". */
1339
1346
  badgeLabel?: string | undefined;
1340
1347
  /** The full name for screen readers when `label` is shortened to fit (5.7), e.g. label "Konto", ariaLabel
1341
- * "Mitt konto". Include the visible label in it (WCAG 2.5.3). The count or badge is still appended. */
1348
+ * "Mitt konto". Include the visible label in it (WCAG 2.5.3); a dev warning says when it doesn't (5.32). The count or badge is
1349
+ * still appended. */
1342
1350
  ariaLabel?: string | undefined;
1343
1351
  }
1344
1352
  export interface BottomNavProps {
@@ -1490,7 +1498,10 @@ export interface ProgressProps {
1490
1498
  className?: string | undefined;
1491
1499
  }
1492
1500
  export interface SkeletonProps {
1493
- variant?: "text" | "rect" | "circle" | undefined;
1501
+ /** 5.32 (DxT Monitor request 4): `pill` is a StatusPill's size (20px tall, 22px under `lang="th"`, 72px wide) and
1502
+ * `badge` a Badge's (20px, 56px wide), both fully rounded, so the row doesn't move when the real one arrives.
1503
+ * `width` overrides the width. */
1504
+ variant?: "text" | "rect" | "circle" | "pill" | "badge" | undefined;
1494
1505
  /** text only: number of lines (the last is shorter). */
1495
1506
  lines?: number | undefined;
1496
1507
  width?: number | string | undefined;
@@ -1783,6 +1794,28 @@ export interface ContainerProps extends Pick<React$1.HTMLAttributes<HTMLElement>
1783
1794
  }
1784
1795
  /** Container — centres content up to aura-container-max (1280px) with responsive side padding. */
1785
1796
  export declare const Container: React$1.ForwardRefExoticComponent<ContainerProps & React$1.RefAttributes<HTMLElement>>;
1797
+ /** PageHeader (5.32, DxT Monitor request 3): the top of a page — an eyebrow, the page's heading, a meta line and the
1798
+ * page's actions. It has no outer padding: inside AppShell, the content padding is the page margin (16px at the sides
1799
+ * and 24px top and bottom on phones, 24px from 640px, 32px from 1024px). Stateless, so it is also exported from
1800
+ * `/server`. It renders a plain `div`: to name a region by its title, put `aria-labelledby={titleId}` on your own
1801
+ * `<section>`, or pass `role="region"` with it. */
1802
+ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "lang" | "dir" | "role">, React$1.AriaAttributes, DataAttributes {
1803
+ /** Small mono line above the title — a section or breadcrumb-like context ("Monitor / Sites"). */
1804
+ eyebrow?: React$1.ReactNode | undefined;
1805
+ /** The page's heading. */
1806
+ title: React$1.ReactNode;
1807
+ /** A line under the title — counts, last update, owner. */
1808
+ meta?: React$1.ReactNode | undefined;
1809
+ /** Buttons for the page, bottom-aligned at the end; they wrap below the text on a narrow screen. */
1810
+ actions?: React$1.ReactNode | undefined;
1811
+ /** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
1812
+ headingLevel?: 1 | 2 | 3 | undefined;
1813
+ /** The heading's id, for `aria-labelledby` on the page's region. */
1814
+ titleId?: string | undefined;
1815
+ className?: string | undefined;
1816
+ style?: React$1.CSSProperties | undefined;
1817
+ }
1818
+ export declare const PageHeader: React$1.ForwardRefExoticComponent<PageHeaderProps & React$1.RefAttributes<HTMLDivElement>>;
1786
1819
  /** AppShell — side navigation + top bar + content. The nav is fixed from lg (1024px) up and a Drawer below it.
1787
1820
  * Which one shows is decided in CSS (4.16), so the server's HTML is already right on a phone and nothing shifts on
1788
1821
  * hydration; JavaScript only opens and closes the drawer. */
@@ -37,6 +37,7 @@ __export(server_exports, {
37
37
  Container: () => Container,
38
38
  EmptyState: () => ServerEmptyState,
39
39
  Icon: () => Icon,
40
+ PageHeader: () => PageHeader,
40
41
  STRINGS: () => STRINGS,
41
42
  Stat: () => ServerStat,
42
43
  StatusPill: () => ServerStatusPill,
@@ -606,14 +607,14 @@ var STRINGS = {
606
607
 
607
608
  // src/theme.ts
608
609
  function hexToRgb(hex) {
609
- let h4 = String(hex).trim().replace("#", "");
610
- if (h4.length === 3)
611
- h4 = h4.split("").map(function(c) {
610
+ let h5 = String(hex).trim().replace("#", "");
611
+ if (h5.length === 3)
612
+ h5 = h5.split("").map(function(c) {
612
613
  return c + c;
613
614
  }).join("");
614
- if (!/^[0-9a-f]{6}$/i.test(h4)) throw new Error('createTheme: "' + hex + '" is not a #rgb or #rrggbb colour');
615
+ if (!/^[0-9a-f]{6}$/i.test(h5)) throw new Error('createTheme: "' + hex + '" is not a #rgb or #rrggbb colour');
615
616
  return [0, 2, 4].map(function(i) {
616
- return parseInt(h4.slice(i, i + 2), 16) / 255;
617
+ return parseInt(h5.slice(i, i + 2), 16) / 255;
617
618
  });
618
619
  }
619
620
  function rgbToHex(rgb) {
@@ -1375,3 +1376,27 @@ var Container = React4.forwardRef(function Container2(props, ref) {
1375
1376
  props.children
1376
1377
  );
1377
1378
  });
1379
+
1380
+ // src/PageHeader.tsx
1381
+ var React5 = __toESM(require("react"), 1);
1382
+ var h4 = React5.createElement;
1383
+ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1384
+ const attrs = {};
1385
+ Object.keys(props).forEach(function(k) {
1386
+ if (k === "id" || k === "lang" || k === "dir" || k === "role" || /^(aria|data)-/.test(k))
1387
+ attrs[k] = props[k];
1388
+ });
1389
+ const level = props.headingLevel || 1;
1390
+ return h4(
1391
+ "div",
1392
+ Object.assign(attrs, { ref, className: cx("aura-page-header", props.className), style: props.style }),
1393
+ h4(
1394
+ "div",
1395
+ { className: "aura-page-header__text" },
1396
+ props.eyebrow != null && props.eyebrow !== false ? h4("p", { className: "aura-page-header__eyebrow" }, props.eyebrow) : null,
1397
+ h4("h" + level, { className: "aura-page-header__title", id: props.titleId }, props.title),
1398
+ props.meta != null && props.meta !== false ? h4("div", { className: "aura-page-header__meta" }, props.meta) : null
1399
+ ),
1400
+ props.actions != null && props.actions !== false ? h4("div", { className: "aura-page-header__actions" }, props.actions) : null
1401
+ );
1402
+ });
@@ -404,6 +404,28 @@ export interface ContainerProps extends Pick<React$1.HTMLAttributes<HTMLElement>
404
404
  }
405
405
  /** Container — centres content up to aura-container-max (1280px) with responsive side padding. */
406
406
  export declare const Container: React$1.ForwardRefExoticComponent<ContainerProps & React$1.RefAttributes<HTMLElement>>;
407
+ /** PageHeader (5.32, DxT Monitor request 3): the top of a page — an eyebrow, the page's heading, a meta line and the
408
+ * page's actions. It has no outer padding: inside AppShell, the content padding is the page margin (16px at the sides
409
+ * and 24px top and bottom on phones, 24px from 640px, 32px from 1024px). Stateless, so it is also exported from
410
+ * `/server`. It renders a plain `div`: to name a region by its title, put `aria-labelledby={titleId}` on your own
411
+ * `<section>`, or pass `role="region"` with it. */
412
+ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "lang" | "dir" | "role">, React$1.AriaAttributes, DataAttributes {
413
+ /** Small mono line above the title — a section or breadcrumb-like context ("Monitor / Sites"). */
414
+ eyebrow?: React$1.ReactNode | undefined;
415
+ /** The page's heading. */
416
+ title: React$1.ReactNode;
417
+ /** A line under the title — counts, last update, owner. */
418
+ meta?: React$1.ReactNode | undefined;
419
+ /** Buttons for the page, bottom-aligned at the end; they wrap below the text on a narrow screen. */
420
+ actions?: React$1.ReactNode | undefined;
421
+ /** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
422
+ headingLevel?: 1 | 2 | 3 | undefined;
423
+ /** The heading's id, for `aria-labelledby` on the page's region. */
424
+ titleId?: string | undefined;
425
+ className?: string | undefined;
426
+ style?: React$1.CSSProperties | undefined;
427
+ }
428
+ export declare const PageHeader: React$1.ForwardRefExoticComponent<PageHeaderProps & React$1.RefAttributes<HTMLDivElement>>;
407
429
 
408
430
  export {
409
431
  ServerAlert as Alert,
@@ -404,6 +404,28 @@ export interface ContainerProps extends Pick<React$1.HTMLAttributes<HTMLElement>
404
404
  }
405
405
  /** Container — centres content up to aura-container-max (1280px) with responsive side padding. */
406
406
  export declare const Container: React$1.ForwardRefExoticComponent<ContainerProps & React$1.RefAttributes<HTMLElement>>;
407
+ /** PageHeader (5.32, DxT Monitor request 3): the top of a page — an eyebrow, the page's heading, a meta line and the
408
+ * page's actions. It has no outer padding: inside AppShell, the content padding is the page margin (16px at the sides
409
+ * and 24px top and bottom on phones, 24px from 640px, 32px from 1024px). Stateless, so it is also exported from
410
+ * `/server`. It renders a plain `div`: to name a region by its title, put `aria-labelledby={titleId}` on your own
411
+ * `<section>`, or pass `role="region"` with it. */
412
+ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "lang" | "dir" | "role">, React$1.AriaAttributes, DataAttributes {
413
+ /** Small mono line above the title — a section or breadcrumb-like context ("Monitor / Sites"). */
414
+ eyebrow?: React$1.ReactNode | undefined;
415
+ /** The page's heading. */
416
+ title: React$1.ReactNode;
417
+ /** A line under the title — counts, last update, owner. */
418
+ meta?: React$1.ReactNode | undefined;
419
+ /** Buttons for the page, bottom-aligned at the end; they wrap below the text on a narrow screen. */
420
+ actions?: React$1.ReactNode | undefined;
421
+ /** Default 1. Use 2 when the page already has an h1 (e.g. in the AppShell bar). */
422
+ headingLevel?: 1 | 2 | 3 | undefined;
423
+ /** The heading's id, for `aria-labelledby` on the page's region. */
424
+ titleId?: string | undefined;
425
+ className?: string | undefined;
426
+ style?: React$1.CSSProperties | undefined;
427
+ }
428
+ export declare const PageHeader: React$1.ForwardRefExoticComponent<PageHeaderProps & React$1.RefAttributes<HTMLDivElement>>;
407
429
 
408
430
  export {
409
431
  ServerAlert as Alert,
@@ -546,14 +546,14 @@ var STRINGS = {
546
546
 
547
547
  // src/theme.ts
548
548
  function hexToRgb(hex) {
549
- let h4 = String(hex).trim().replace("#", "");
550
- if (h4.length === 3)
551
- h4 = h4.split("").map(function(c) {
549
+ let h5 = String(hex).trim().replace("#", "");
550
+ if (h5.length === 3)
551
+ h5 = h5.split("").map(function(c) {
552
552
  return c + c;
553
553
  }).join("");
554
- if (!/^[0-9a-f]{6}$/i.test(h4)) throw new Error('createTheme: "' + hex + '" is not a #rgb or #rrggbb colour');
554
+ if (!/^[0-9a-f]{6}$/i.test(h5)) throw new Error('createTheme: "' + hex + '" is not a #rgb or #rrggbb colour');
555
555
  return [0, 2, 4].map(function(i) {
556
- return parseInt(h4.slice(i, i + 2), 16) / 255;
556
+ return parseInt(h5.slice(i, i + 2), 16) / 255;
557
557
  });
558
558
  }
559
559
  function rgbToHex(rgb) {
@@ -1315,6 +1315,30 @@ var Container = React4.forwardRef(function Container2(props, ref) {
1315
1315
  props.children
1316
1316
  );
1317
1317
  });
1318
+
1319
+ // src/PageHeader.tsx
1320
+ import * as React5 from "react";
1321
+ var h4 = React5.createElement;
1322
+ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1323
+ const attrs = {};
1324
+ Object.keys(props).forEach(function(k) {
1325
+ if (k === "id" || k === "lang" || k === "dir" || k === "role" || /^(aria|data)-/.test(k))
1326
+ attrs[k] = props[k];
1327
+ });
1328
+ const level = props.headingLevel || 1;
1329
+ return h4(
1330
+ "div",
1331
+ Object.assign(attrs, { ref, className: cx("aura-page-header", props.className), style: props.style }),
1332
+ h4(
1333
+ "div",
1334
+ { className: "aura-page-header__text" },
1335
+ props.eyebrow != null && props.eyebrow !== false ? h4("p", { className: "aura-page-header__eyebrow" }, props.eyebrow) : null,
1336
+ h4("h" + level, { className: "aura-page-header__title", id: props.titleId }, props.title),
1337
+ props.meta != null && props.meta !== false ? h4("div", { className: "aura-page-header__meta" }, props.meta) : null
1338
+ ),
1339
+ props.actions != null && props.actions !== false ? h4("div", { className: "aura-page-header__actions" }, props.actions) : null
1340
+ );
1341
+ });
1318
1342
  export {
1319
1343
  ServerAlert as Alert,
1320
1344
  ServerAvatar as Avatar,
@@ -1323,6 +1347,7 @@ export {
1323
1347
  Container,
1324
1348
  ServerEmptyState as EmptyState,
1325
1349
  Icon,
1350
+ PageHeader,
1326
1351
  STRINGS,
1327
1352
  ServerStat as Stat,
1328
1353
  ServerStatusPill as StatusPill,
package/dist/styles.css CHANGED
@@ -356,6 +356,9 @@ a.aura-icon-btn { text-decoration: none; }
356
356
  background: var(--aura-bg-skeleton); animation: aura-pulse var(--aura-duration-pulse) var(--aura-ease) infinite;
357
357
  }
358
358
  .aura-skel--pill { width: 72px; height: 20px; }
359
+ .aura-skel--badge { width: 56px; height: 20px; } /* 5.32: a Badge is 20px in every language */
360
+ /* 5.32: they stand in for inline pills, so they sit in a line of text like them. */
361
+ .aura-skel--pill, .aura-skel--badge { display: inline-block; vertical-align: middle; }
359
362
  .aura-skel--box { width: var(--aura-icon-sm); height: var(--aura-icon-sm); border-radius: var(--aura-radius-xs); }
360
363
  @media (prefers-reduced-motion: reduce) { .aura-skel { animation: none; } }
361
364
  /* 5.29 (Chamber-OS 134): a DataTable skeleton row stands in for the real one — text lines (skeletonLines) on the 20px
@@ -656,6 +659,8 @@ a.aura-icon-btn { text-decoration: none; }
656
659
  }
657
660
  /* The Tooltip component's own tips can be hovered (WCAG 1.4.13, 5.1.1); rail labels and cell tips stay click-through. */
658
661
  .aura-tooltip--hoverable { pointer-events: auto; }
662
+ /* 5.32: the shared tip for icon buttons, Pagination arrows, icon-only segments and cut Tags (was a native title). */
663
+ .aura-tooltip--auto:lang(th) { line-height: 1.6; }
659
664
  @keyframes aura-fade-in { from { opacity: 0; } }
660
665
 
661
666
  /* ---------- Dialog ---------- */
@@ -762,6 +767,10 @@ a.aura-tab { text-decoration: none; }
762
767
  }
763
768
  .aura-nav__header { padding: var(--aura-space-5) var(--aura-space-4) var(--aura-space-4); padding-inline-end: var(--aura-space-2); } /* 5.16 (Chamber-OS 96): 8px at the end, so a brand, its dot and a badge share one row at 240px */
764
769
  .aura-nav__scroll { flex: 1; overflow-y: auto; padding: 0 var(--aura-space-3); }
770
+ /* 5.32 (DxT Monitor request 1): headerDivider — the board's header: 72px, content 20px from the top and start, a
771
+ * full-width line at its foot, 16px before the first item. The collapsed rail keeps its own 8px sides (below). */
772
+ .aura-nav--header-divider > .aura-nav__header { box-sizing: border-box; min-height: 72px; padding-top: var(--aura-space-5); padding-bottom: var(--aura-space-3); padding-inline-start: var(--aura-space-5); border-bottom: 1px solid var(--aura-border-default); }
773
+ .aura-nav--header-divider > .aura-nav__header + .aura-nav__scroll { padding-top: var(--aura-space-4); }
765
774
  /* No header: keep the first item off the top edge (5.0.2). */
766
775
  .aura-nav > .aura-nav__scroll:first-child { padding-top: var(--aura-space-3); }
767
776
  .aura-nav--borderless { border-right: 0; }
@@ -987,7 +996,7 @@ a.aura-tab { text-decoration: none; }
987
996
  .aura-drawer--lg { max-width: var(--aura-drawer-lg); }
988
997
  .aura-drawer--nav { max-width: var(--aura-sidenav-width); }
989
998
  .aura-drawer__head { display: flex; align-items: center; gap: var(--aura-space-3); padding: var(--aura-space-4) var(--aura-space-4) var(--aura-space-2) var(--aura-space-6); }
990
- .aura-drawer--nav .aura-drawer__head { position: absolute; top: var(--aura-space-2); right: var(--aura-space-2); padding: 0; z-index: 1; }
999
+ .aura-drawer--nav .aura-drawer__head { position: absolute; top: var(--aura-space-2); inset-inline-end: var(--aura-space-2); padding: 0; z-index: 1; } /* 5.32: inline-end, so RTL puts it on the left with the header's room */
991
1000
  .aura-drawer__title { flex: 1; margin: 0; font-size: 16px; line-height: 1.5; font-weight: 600; }
992
1001
  .aura-drawer__desc { margin: 0; padding: 0 var(--aura-space-6); font-size: 14px; line-height: 1.7; color: var(--aura-fg-secondary); }
993
1002
  .aura-drawer__body {
@@ -997,6 +1006,8 @@ a.aura-tab { text-decoration: none; }
997
1006
  }
998
1007
  .aura-drawer--nav .aura-drawer__body { padding: 0; }
999
1008
  .aura-drawer--nav .aura-nav { width: 100%; border-right: 0; }
1009
+ /* 5.32: the phone drawer's close button (32px, 8px in) sits over the header's end: keep the brand clear of it. */
1010
+ .aura-drawer--nav .aura-nav__header { padding-inline-end: 48px; }
1000
1011
  .aura-drawer__foot { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--aura-space-3); padding: var(--aura-space-4) var(--aura-space-6); border-top: 1px solid var(--aura-border-default); }
1001
1012
  @media (prefers-reduced-motion: reduce) { .aura-drawer { animation: none; } }
1002
1013
 
@@ -1074,6 +1085,21 @@ a.aura-tab { text-decoration: none; }
1074
1085
  /* The shell already pads its content: a Container directly inside only caps the width. */
1075
1086
  .aura-shell__content:not(.is-flush) > .aura-container { padding-left: 0; padding-right: 0; }
1076
1087
 
1088
+ /* ---------- PageHeader (5.32, DxT Monitor request 3) ----------
1089
+ * No outer padding: AppShell's content padding is the page margin. Eyebrow mono 12/1.7, h1 display 36/1.15,
1090
+ * meta 13/1.5, 4px between them; actions at the end, on the text's last line, 24px away; below 640px the title is
1091
+ * 28px and the actions wrap under the text. */
1092
+ .aura-page-header { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--aura-space-4) var(--aura-space-6); min-width: 0; font-family: var(--font-sans); }
1093
+ .aura-page-header__text { display: flex; flex-direction: column; gap: var(--aura-space-1); flex: 1 1 320px; min-width: 0; }
1094
+ .aura-page-header__eyebrow { margin: 0; font-family: var(--font-mono); font-size: 12px; line-height: 1.7; color: var(--aura-fg-secondary); overflow-wrap: anywhere; }
1095
+ .aura-page-header__title { margin: 0; font-family: var(--font-display); font-size: 28px; line-height: 1.15; font-weight: 600; letter-spacing: -0.01em; color: var(--aura-fg-primary); overflow-wrap: anywhere; }
1096
+ .aura-page-header__meta { min-width: 0; font-size: 13px; line-height: 1.5; color: var(--aura-fg-secondary); overflow-wrap: anywhere; }
1097
+ .aura-page-header__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); }
1098
+ @media (min-width: 640px) { .aura-page-header__title { font-size: 36px; } }
1099
+ /* Thai marks need the room a 1.15 line takes away. */
1100
+ .aura-page-header__title:lang(th) { line-height: 1.4; letter-spacing: 0; }
1101
+ .aura-page-header__meta:lang(th) { line-height: 1.6; }
1102
+
1077
1103
  /* Totals row (4.19): under the body, a strong top edge; sticky at the bottom of a `height` table with stickyFooter. */
1078
1104
  /* 5.30: a 2px hairline-colour rule over the totals (border-strong was a glaring white line in dark); a pinned totals row
1079
1105
  * casts a soft shadow over the rows scrolling under it. */
@@ -358,6 +358,9 @@ a.aura-icon-btn { text-decoration: none; }
358
358
  background: var(--aura-bg-skeleton); animation: aura-pulse var(--aura-duration-pulse) var(--aura-ease) infinite;
359
359
  }
360
360
  .aura-skel--pill { width: 72px; height: 20px; }
361
+ .aura-skel--badge { width: 56px; height: 20px; } /* 5.32: a Badge is 20px in every language */
362
+ /* 5.32: they stand in for inline pills, so they sit in a line of text like them. */
363
+ .aura-skel--pill, .aura-skel--badge { display: inline-block; vertical-align: middle; }
361
364
  .aura-skel--box { width: var(--aura-icon-sm); height: var(--aura-icon-sm); border-radius: var(--aura-radius-xs); }
362
365
  @media (prefers-reduced-motion: reduce) { .aura-skel { animation: none; } }
363
366
  /* 5.29 (Chamber-OS 134): a DataTable skeleton row stands in for the real one — text lines (skeletonLines) on the 20px
@@ -658,6 +661,8 @@ a.aura-icon-btn { text-decoration: none; }
658
661
  }
659
662
  /* The Tooltip component's own tips can be hovered (WCAG 1.4.13, 5.1.1); rail labels and cell tips stay click-through. */
660
663
  .aura-tooltip--hoverable { pointer-events: auto; }
664
+ /* 5.32: the shared tip for icon buttons, Pagination arrows, icon-only segments and cut Tags (was a native title). */
665
+ .aura-tooltip--auto:lang(th) { line-height: 1.6; }
661
666
  @keyframes aura-fade-in { from { opacity: 0; } }
662
667
 
663
668
  /* ---------- Dialog ---------- */
@@ -764,6 +769,10 @@ a.aura-tab { text-decoration: none; }
764
769
  }
765
770
  .aura-nav__header { padding: var(--aura-space-5) var(--aura-space-4) var(--aura-space-4); padding-inline-end: var(--aura-space-2); } /* 5.16 (Chamber-OS 96): 8px at the end, so a brand, its dot and a badge share one row at 240px */
766
771
  .aura-nav__scroll { flex: 1; overflow-y: auto; padding: 0 var(--aura-space-3); }
772
+ /* 5.32 (DxT Monitor request 1): headerDivider — the board's header: 72px, content 20px from the top and start, a
773
+ * full-width line at its foot, 16px before the first item. The collapsed rail keeps its own 8px sides (below). */
774
+ .aura-nav--header-divider > .aura-nav__header { box-sizing: border-box; min-height: 72px; padding-top: var(--aura-space-5); padding-bottom: var(--aura-space-3); padding-inline-start: var(--aura-space-5); border-bottom: 1px solid var(--aura-border-default); }
775
+ .aura-nav--header-divider > .aura-nav__header + .aura-nav__scroll { padding-top: var(--aura-space-4); }
767
776
  /* No header: keep the first item off the top edge (5.0.2). */
768
777
  .aura-nav > .aura-nav__scroll:first-child { padding-top: var(--aura-space-3); }
769
778
  .aura-nav--borderless { border-right: 0; }
@@ -989,7 +998,7 @@ a.aura-tab { text-decoration: none; }
989
998
  .aura-drawer--lg { max-width: var(--aura-drawer-lg); }
990
999
  .aura-drawer--nav { max-width: var(--aura-sidenav-width); }
991
1000
  .aura-drawer__head { display: flex; align-items: center; gap: var(--aura-space-3); padding: var(--aura-space-4) var(--aura-space-4) var(--aura-space-2) var(--aura-space-6); }
992
- .aura-drawer--nav .aura-drawer__head { position: absolute; top: var(--aura-space-2); right: var(--aura-space-2); padding: 0; z-index: 1; }
1001
+ .aura-drawer--nav .aura-drawer__head { position: absolute; top: var(--aura-space-2); inset-inline-end: var(--aura-space-2); padding: 0; z-index: 1; } /* 5.32: inline-end, so RTL puts it on the left with the header's room */
993
1002
  .aura-drawer__title { flex: 1; margin: 0; font-size: 16px; line-height: 1.5; font-weight: 600; }
994
1003
  .aura-drawer__desc { margin: 0; padding: 0 var(--aura-space-6); font-size: 14px; line-height: 1.7; color: var(--aura-fg-secondary); }
995
1004
  .aura-drawer__body {
@@ -999,6 +1008,8 @@ a.aura-tab { text-decoration: none; }
999
1008
  }
1000
1009
  .aura-drawer--nav .aura-drawer__body { padding: 0; }
1001
1010
  .aura-drawer--nav .aura-nav { width: 100%; border-right: 0; }
1011
+ /* 5.32: the phone drawer's close button (32px, 8px in) sits over the header's end: keep the brand clear of it. */
1012
+ .aura-drawer--nav .aura-nav__header { padding-inline-end: 48px; }
1002
1013
  .aura-drawer__foot { display: flex; justify-content: flex-end; flex-wrap: wrap; gap: var(--aura-space-3); padding: var(--aura-space-4) var(--aura-space-6); border-top: 1px solid var(--aura-border-default); }
1003
1014
  @media (prefers-reduced-motion: reduce) { .aura-drawer { animation: none; } }
1004
1015
 
@@ -1076,6 +1087,21 @@ a.aura-tab { text-decoration: none; }
1076
1087
  /* The shell already pads its content: a Container directly inside only caps the width. */
1077
1088
  .aura-shell__content:not(.is-flush) > .aura-container { padding-left: 0; padding-right: 0; }
1078
1089
 
1090
+ /* ---------- PageHeader (5.32, DxT Monitor request 3) ----------
1091
+ * No outer padding: AppShell's content padding is the page margin. Eyebrow mono 12/1.7, h1 display 36/1.15,
1092
+ * meta 13/1.5, 4px between them; actions at the end, on the text's last line, 24px away; below 640px the title is
1093
+ * 28px and the actions wrap under the text. */
1094
+ .aura-page-header { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--aura-space-4) var(--aura-space-6); min-width: 0; font-family: var(--font-sans); }
1095
+ .aura-page-header__text { display: flex; flex-direction: column; gap: var(--aura-space-1); flex: 1 1 320px; min-width: 0; }
1096
+ .aura-page-header__eyebrow { margin: 0; font-family: var(--font-mono); font-size: 12px; line-height: 1.7; color: var(--aura-fg-secondary); overflow-wrap: anywhere; }
1097
+ .aura-page-header__title { margin: 0; font-family: var(--font-display); font-size: 28px; line-height: 1.15; font-weight: 600; letter-spacing: -0.01em; color: var(--aura-fg-primary); overflow-wrap: anywhere; }
1098
+ .aura-page-header__meta { min-width: 0; font-size: 13px; line-height: 1.5; color: var(--aura-fg-secondary); overflow-wrap: anywhere; }
1099
+ .aura-page-header__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); }
1100
+ @media (min-width: 640px) { .aura-page-header__title { font-size: 36px; } }
1101
+ /* Thai marks need the room a 1.15 line takes away. */
1102
+ .aura-page-header__title:lang(th) { line-height: 1.4; letter-spacing: 0; }
1103
+ .aura-page-header__meta:lang(th) { line-height: 1.6; }
1104
+
1079
1105
  /* Totals row (4.19): under the body, a strong top edge; sticky at the bottom of a `height` table with stickyFooter. */
1080
1106
  /* 5.30: a 2px hairline-colour rule over the totals (border-strong was a glaring white line in dark); a pinned totals row
1081
1107
  * casts a soft shadow over the rows scrolling under it. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.31.0",
3
+ "version": "5.32.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",