@jirawatpyk/aura-react 5.85.0 → 5.86.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
@@ -248,6 +248,12 @@ DataTable with sort and page in the URL (4.17): `onStateChange={({ sort, page })
248
248
  - **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`.
249
249
  - **Toasts** queue past three instead of dropping: six in a row all show, in order, three at a time.
250
250
 
251
+ ## 5.86 — Chamber-OS 199–202 (Card names, DataTable column numbering, EmptyState icons)
252
+
253
+ - **Card `titleId`** (#199): a titled Card labels its root by its title (`aria-labelledby`) only where the root takes a name — the default `section`, `article`, `aside`, `nav`, `main`, `search`, `form`, `fieldset`, `details`, `dialog`, `figure`, `li`, `ul`, `ol`, `menu`, or any root with a `role` (the first token of a role list; except `generic`, `none`, `presentation` and the other roles that prohibit a name). With `as="div"` and no role the heading keeps its `id` and the root stays unlabelled; before, it carried an `aria-labelledby` that ARIA 1.2 prohibits (axe `aria-prohibited-attr`) and screen readers ignored. A step card in a list of steps can now use `title`. Same from `/server`.
254
+ - **DataTable `aria-colcount` / `aria-colindex` with `grid: false`** (#200, a 5.85 gap): in the grid (and before the first measure) card-only columns are left out of the count and the numbering, so the visible columns read 1…N of N; in the stacked cards every column counts. The hidden cells carry no `aria-colindex`.
255
+ - **EmptyState `icon={false}`** (#201): no icon and no icon circle, for a short placeholder in a table cell or a small panel. **`tone="danger"` defaults to `triangle-alert`** (#202) instead of the inbox, so a failed read doesn't look like "nothing here"; a passed `icon` still wins.
256
+
251
257
  ## 5.85 — Chamber-OS 198 (DataTable columns for the cards only)
252
258
 
253
259
  - **DataTable column `grid: false`** (#198): the column shows only in the stacked cards (below `stackBelow`), never in the grid — the reverse of `card: 'hide'`. Its place in the card still follows `card` (`'title'`, `'pill'`, a field…), so a grid that puts the status under the number can give the phone card its own title and pill. It spends no width-query level (any `hideBelow` on it is ignored), takes no width in the grid, isn't pinned, isn't in the columns button and is skipped by the arrow keys there. Without `stackBelow` it isn't rendered. Replaces the `hideBelow: 100_000` workaround.
@@ -843,6 +843,45 @@ window.Aura = (() => {
843
843
  close
844
844
  );
845
845
  }
846
+ var NAMED_ROOTS = [
847
+ "section",
848
+ "article",
849
+ "aside",
850
+ "nav",
851
+ "main",
852
+ "search",
853
+ "form",
854
+ "fieldset",
855
+ "details",
856
+ "dialog",
857
+ "figure",
858
+ "li",
859
+ "ul",
860
+ "ol",
861
+ "menu"
862
+ ];
863
+ var NAMELESS_ROLES = [
864
+ "generic",
865
+ "none",
866
+ "presentation",
867
+ "paragraph",
868
+ "caption",
869
+ "code",
870
+ "deletion",
871
+ "emphasis",
872
+ "insertion",
873
+ "strong",
874
+ "subscript",
875
+ "superscript",
876
+ "term",
877
+ "time",
878
+ "mark"
879
+ ];
880
+ function cardTakesName(as, role) {
881
+ const first = role ? role.trim().split(/\s+/)[0].toLowerCase() : "";
882
+ if (first) return NAMELESS_ROLES.indexOf(first) < 0;
883
+ return NAMED_ROOTS.indexOf(as) >= 0;
884
+ }
846
885
  function cardElement(props, ref) {
847
886
  const creative = props.variant === "creative";
848
887
  const rest = omit(props, [
@@ -872,8 +911,10 @@ window.Aura = (() => {
872
911
  props.flushBelow && "aura-card--flush-below-" + props.flushBelow,
873
912
  props.className
874
913
  ),
875
- /* A titled card is labelled by its title; otherwise the caller's aria-labelledby stays (5.8). */
876
- "aria-labelledby": !head && props.title && props.titleId ? props.titleId : props["aria-labelledby"]
914
+ /* A titled card is labelled by its title; otherwise the caller's aria-labelledby stays (5.8). 5.86 (Chamber-OS
915
+ * 199): only where a name is allowed — a root that takes one (section, article…) or one with a role; a plain
916
+ * div is generic, where ARIA 1.2 prohibits a name. The title keeps its id either way. */
917
+ "aria-labelledby": !head && props.title && props.titleId && cardTakesName(props.as || "section", props.role) ? props.titleId : props["aria-labelledby"]
877
918
  }),
878
919
  head || props.title || props.actions ? /* @__PURE__ */ React4.createElement("div", { className: "aura-card__head" }, /* @__PURE__ */ React4.createElement("div", { className: "aura-card__heading" }, head ? props.header : null, !head && props.title ? h2("h" + (props.headingLevel || 3), { className: "aura-card__title", id: props.titleId }, props.title) : null, !head && props.description ? /* @__PURE__ */ React4.createElement("p", { className: "aura-card__desc" }, props.description) : null), props.actions ? /* @__PURE__ */ React4.createElement("div", { className: "aura-card__actions" }, props.actions) : null) : null,
879
920
  props.children ? /* @__PURE__ */ React4.createElement("div", { className: "aura-card__body" }, props.children) : null,
@@ -973,7 +1014,13 @@ window.Aura = (() => {
973
1014
  props.className
974
1015
  )
975
1016
  },
976
- /* @__PURE__ */ React4.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React4.createElement(Icon, { name: props.icon || /* @__PURE__ */ React4.createElement(IconInbox, null), size: props.size === "sm" ? "md" : "lg" })),
1017
+ props.icon === false ? null : /* @__PURE__ */ React4.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React4.createElement(
1018
+ Icon,
1019
+ {
1020
+ name: props.icon || (props.tone === "danger" ? /* @__PURE__ */ React4.createElement(IconTriangleAlert, null) : /* @__PURE__ */ React4.createElement(IconInbox, null)),
1021
+ size: props.size === "sm" ? "md" : "lg"
1022
+ }
1023
+ )),
977
1024
  /* @__PURE__ */ React4.createElement(HT, { className: "aura-empty__title" }, props.title),
978
1025
  props.description ? /* @__PURE__ */ React4.createElement("p", { className: "aura-empty__text" }, props.description) : null,
979
1026
  props.action ? /* @__PURE__ */ React4.createElement("div", { className: "aura-empty__action" }, props.action) : null
@@ -6630,6 +6677,12 @@ window.Aura = (() => {
6630
6677
  }
6631
6678
  const visibleRows = Math.max(1, Math.floor(bodyH / ROW_H));
6632
6679
  const nCols = vis.length + (selectable ? 1 : 0);
6680
+ const ariaIdx = [];
6681
+ let ariaColCount = 0;
6682
+ for (let ci = 0; ci < nCols; ci++) {
6683
+ const col = selectable ? ci === 0 ? null : vis[ci - 1] : vis[ci];
6684
+ ariaIdx.push(!stacked && col && col.grid === false ? void 0 : ++ariaColCount);
6685
+ }
6633
6686
  const nRows = loading ? 0 : pageRows.length;
6634
6687
  const hasTotal = !!(props.footer && rows.length && !loading), T = nRows + 1, lastR = nRows + (hasTotal ? 1 : 0);
6635
6688
  const active = activeState[0];
@@ -7093,7 +7146,7 @@ window.Aura = (() => {
7093
7146
  key: c.key,
7094
7147
  role: "columnheader",
7095
7148
  "aria-sort": ariaSort,
7096
- "aria-colindex": ci + 1,
7149
+ "aria-colindex": ariaIdx[ci],
7097
7150
  style: cellStyle(c, i),
7098
7151
  "data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
7099
7152
  "data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
@@ -7256,7 +7309,7 @@ window.Aura = (() => {
7256
7309
  {
7257
7310
  key: c.key,
7258
7311
  role: "gridcell",
7259
- "aria-colindex": ci + 1,
7312
+ "aria-colindex": ariaIdx[ci],
7260
7313
  tabIndex: tabFor(ri, ci),
7261
7314
  "data-rc": ri + ":" + ci,
7262
7315
  className: cx(
@@ -7484,7 +7537,7 @@ window.Aura = (() => {
7484
7537
  {
7485
7538
  key: c.key,
7486
7539
  role: "gridcell",
7487
- "aria-colindex": j + (selectable ? 2 : 1),
7540
+ "aria-colindex": ariaIdx[j + (selectable ? 1 : 0)],
7488
7541
  tabIndex: tabFor(T, ci),
7489
7542
  "data-rc": T + ":" + ci,
7490
7543
  onFocus: function() {
@@ -7579,7 +7632,7 @@ window.Aura = (() => {
7579
7632
  "aria-label": props.label,
7580
7633
  "aria-busy": busy || void 0,
7581
7634
  "aria-rowcount": loading || manual && props.totalRows == null && pageSize && rows.length >= pageSize ? -1 : shownTotal + 1 + (totalRow ? 1 : 0),
7582
- "aria-colcount": nCols,
7635
+ "aria-colcount": ariaColCount,
7583
7636
  "aria-multiselectable": selectable || void 0,
7584
7637
  onKeyDown: onGridKey,
7585
7638
  onScroll: function(e) {
@@ -825,6 +825,45 @@ function alertElement(props, ref, close, autoId) {
825
825
  close
826
826
  );
827
827
  }
828
+ var NAMED_ROOTS = [
829
+ "section",
830
+ "article",
831
+ "aside",
832
+ "nav",
833
+ "main",
834
+ "search",
835
+ "form",
836
+ "fieldset",
837
+ "details",
838
+ "dialog",
839
+ "figure",
840
+ "li",
841
+ "ul",
842
+ "ol",
843
+ "menu"
844
+ ];
845
+ var NAMELESS_ROLES = [
846
+ "generic",
847
+ "none",
848
+ "presentation",
849
+ "paragraph",
850
+ "caption",
851
+ "code",
852
+ "deletion",
853
+ "emphasis",
854
+ "insertion",
855
+ "strong",
856
+ "subscript",
857
+ "superscript",
858
+ "term",
859
+ "time",
860
+ "mark"
861
+ ];
862
+ function cardTakesName(as, role) {
863
+ const first = role ? role.trim().split(/\s+/)[0].toLowerCase() : "";
864
+ if (first) return NAMELESS_ROLES.indexOf(first) < 0;
865
+ return NAMED_ROOTS.indexOf(as) >= 0;
866
+ }
828
867
  function cardElement(props, ref) {
829
868
  const creative = props.variant === "creative";
830
869
  const rest = omit(props, [
@@ -854,8 +893,10 @@ function cardElement(props, ref) {
854
893
  props.flushBelow && "aura-card--flush-below-" + props.flushBelow,
855
894
  props.className
856
895
  ),
857
- /* A titled card is labelled by its title; otherwise the caller's aria-labelledby stays (5.8). */
858
- "aria-labelledby": !head && props.title && props.titleId ? props.titleId : props["aria-labelledby"]
896
+ /* A titled card is labelled by its title; otherwise the caller's aria-labelledby stays (5.8). 5.86 (Chamber-OS
897
+ * 199): only where a name is allowed — a root that takes one (section, article…) or one with a role; a plain
898
+ * div is generic, where ARIA 1.2 prohibits a name. The title keeps its id either way. */
899
+ "aria-labelledby": !head && props.title && props.titleId && cardTakesName(props.as || "section", props.role) ? props.titleId : props["aria-labelledby"]
859
900
  }),
860
901
  head || props.title || props.actions ? /* @__PURE__ */ React4.createElement("div", { className: "aura-card__head" }, /* @__PURE__ */ React4.createElement("div", { className: "aura-card__heading" }, head ? props.header : null, !head && props.title ? h2("h" + (props.headingLevel || 3), { className: "aura-card__title", id: props.titleId }, props.title) : null, !head && props.description ? /* @__PURE__ */ React4.createElement("p", { className: "aura-card__desc" }, props.description) : null), props.actions ? /* @__PURE__ */ React4.createElement("div", { className: "aura-card__actions" }, props.actions) : null) : null,
861
902
  props.children ? /* @__PURE__ */ React4.createElement("div", { className: "aura-card__body" }, props.children) : null,
@@ -955,7 +996,13 @@ function emptyStateElement(props, ref) {
955
996
  props.className
956
997
  )
957
998
  },
958
- /* @__PURE__ */ React4.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React4.createElement(Icon, { name: props.icon || /* @__PURE__ */ React4.createElement(IconInbox, null), size: props.size === "sm" ? "md" : "lg" })),
999
+ props.icon === false ? null : /* @__PURE__ */ React4.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React4.createElement(
1000
+ Icon,
1001
+ {
1002
+ name: props.icon || (props.tone === "danger" ? /* @__PURE__ */ React4.createElement(IconTriangleAlert, null) : /* @__PURE__ */ React4.createElement(IconInbox, null)),
1003
+ size: props.size === "sm" ? "md" : "lg"
1004
+ }
1005
+ )),
959
1006
  /* @__PURE__ */ React4.createElement(HT, { className: "aura-empty__title" }, props.title),
960
1007
  props.description ? /* @__PURE__ */ React4.createElement("p", { className: "aura-empty__text" }, props.description) : null,
961
1008
  props.action ? /* @__PURE__ */ React4.createElement("div", { className: "aura-empty__action" }, props.action) : null
@@ -6612,6 +6659,12 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6612
6659
  }
6613
6660
  const visibleRows = Math.max(1, Math.floor(bodyH / ROW_H));
6614
6661
  const nCols = vis.length + (selectable ? 1 : 0);
6662
+ const ariaIdx = [];
6663
+ let ariaColCount = 0;
6664
+ for (let ci = 0; ci < nCols; ci++) {
6665
+ const col = selectable ? ci === 0 ? null : vis[ci - 1] : vis[ci];
6666
+ ariaIdx.push(!stacked && col && col.grid === false ? void 0 : ++ariaColCount);
6667
+ }
6615
6668
  const nRows = loading ? 0 : pageRows.length;
6616
6669
  const hasTotal = !!(props.footer && rows.length && !loading), T = nRows + 1, lastR = nRows + (hasTotal ? 1 : 0);
6617
6670
  const active = activeState[0];
@@ -7075,7 +7128,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
7075
7128
  key: c.key,
7076
7129
  role: "columnheader",
7077
7130
  "aria-sort": ariaSort,
7078
- "aria-colindex": ci + 1,
7131
+ "aria-colindex": ariaIdx[ci],
7079
7132
  style: cellStyle(c, i),
7080
7133
  "data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
7081
7134
  "data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
@@ -7238,7 +7291,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
7238
7291
  {
7239
7292
  key: c.key,
7240
7293
  role: "gridcell",
7241
- "aria-colindex": ci + 1,
7294
+ "aria-colindex": ariaIdx[ci],
7242
7295
  tabIndex: tabFor(ri, ci),
7243
7296
  "data-rc": ri + ":" + ci,
7244
7297
  className: cx(
@@ -7466,7 +7519,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
7466
7519
  {
7467
7520
  key: c.key,
7468
7521
  role: "gridcell",
7469
- "aria-colindex": j + (selectable ? 2 : 1),
7522
+ "aria-colindex": ariaIdx[j + (selectable ? 1 : 0)],
7470
7523
  tabIndex: tabFor(T, ci),
7471
7524
  "data-rc": T + ":" + ci,
7472
7525
  onFocus: function() {
@@ -7561,7 +7614,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
7561
7614
  "aria-label": props.label,
7562
7615
  "aria-busy": busy || void 0,
7563
7616
  "aria-rowcount": loading || manual && props.totalRows == null && pageSize && rows.length >= pageSize ? -1 : shownTotal + 1 + (totalRow ? 1 : 0),
7564
- "aria-colcount": nCols,
7617
+ "aria-colcount": ariaColCount,
7565
7618
  "aria-multiselectable": selectable || void 0,
7566
7619
  onKeyDown: onGridKey,
7567
7620
  onScroll: function(e) {
@@ -552,6 +552,12 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
552
552
  }
553
553
  const visibleRows = Math.max(1, Math.floor(bodyH / ROW_H));
554
554
  const nCols = vis.length + (selectable ? 1 : 0);
555
+ const ariaIdx = [];
556
+ let ariaColCount = 0;
557
+ for (let ci = 0; ci < nCols; ci++) {
558
+ const col = selectable ? ci === 0 ? null : vis[ci - 1] : vis[ci];
559
+ ariaIdx.push(!stacked && col && col.grid === false ? void 0 : ++ariaColCount);
560
+ }
555
561
  const nRows = loading ? 0 : pageRows.length;
556
562
  const hasTotal = !!(props.footer && rows.length && !loading), T = nRows + 1, lastR = nRows + (hasTotal ? 1 : 0);
557
563
  const active = activeState[0];
@@ -1015,7 +1021,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
1015
1021
  key: c.key,
1016
1022
  role: "columnheader",
1017
1023
  "aria-sort": ariaSort,
1018
- "aria-colindex": ci + 1,
1024
+ "aria-colindex": ariaIdx[ci],
1019
1025
  style: cellStyle(c, i),
1020
1026
  "data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
1021
1027
  "data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
@@ -1178,7 +1184,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
1178
1184
  {
1179
1185
  key: c.key,
1180
1186
  role: "gridcell",
1181
- "aria-colindex": ci + 1,
1187
+ "aria-colindex": ariaIdx[ci],
1182
1188
  tabIndex: tabFor(ri, ci),
1183
1189
  "data-rc": ri + ":" + ci,
1184
1190
  className: cx(
@@ -1406,7 +1412,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
1406
1412
  {
1407
1413
  key: c.key,
1408
1414
  role: "gridcell",
1409
- "aria-colindex": j + (selectable ? 2 : 1),
1415
+ "aria-colindex": ariaIdx[j + (selectable ? 1 : 0)],
1410
1416
  tabIndex: tabFor(T, ci),
1411
1417
  "data-rc": T + ":" + ci,
1412
1418
  onFocus: function() {
@@ -1501,7 +1507,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
1501
1507
  "aria-label": props.label,
1502
1508
  "aria-busy": busy || void 0,
1503
1509
  "aria-rowcount": loading || manual && props.totalRows == null && pageSize && rows.length >= pageSize ? -1 : shownTotal + 1 + (totalRow ? 1 : 0),
1504
- "aria-colcount": nCols,
1510
+ "aria-colcount": ariaColCount,
1505
1511
  "aria-multiselectable": selectable || void 0,
1506
1512
  onKeyDown: onGridKey,
1507
1513
  onScroll: function(e) {
@@ -57,6 +57,45 @@ function alertElement(props, ref, close, autoId) {
57
57
  close
58
58
  );
59
59
  }
60
+ const NAMED_ROOTS = [
61
+ "section",
62
+ "article",
63
+ "aside",
64
+ "nav",
65
+ "main",
66
+ "search",
67
+ "form",
68
+ "fieldset",
69
+ "details",
70
+ "dialog",
71
+ "figure",
72
+ "li",
73
+ "ul",
74
+ "ol",
75
+ "menu"
76
+ ];
77
+ const NAMELESS_ROLES = [
78
+ "generic",
79
+ "none",
80
+ "presentation",
81
+ "paragraph",
82
+ "caption",
83
+ "code",
84
+ "deletion",
85
+ "emphasis",
86
+ "insertion",
87
+ "strong",
88
+ "subscript",
89
+ "superscript",
90
+ "term",
91
+ "time",
92
+ "mark"
93
+ ];
94
+ function cardTakesName(as, role) {
95
+ const first = role ? role.trim().split(/\s+/)[0].toLowerCase() : "";
96
+ if (first) return NAMELESS_ROLES.indexOf(first) < 0;
97
+ return NAMED_ROOTS.indexOf(as) >= 0;
98
+ }
60
99
  function cardElement(props, ref) {
61
100
  const creative = props.variant === "creative";
62
101
  const rest = omit(props, [
@@ -86,8 +125,10 @@ function cardElement(props, ref) {
86
125
  props.flushBelow && "aura-card--flush-below-" + props.flushBelow,
87
126
  props.className
88
127
  ),
89
- /* A titled card is labelled by its title; otherwise the caller's aria-labelledby stays (5.8). */
90
- "aria-labelledby": !head && props.title && props.titleId ? props.titleId : props["aria-labelledby"]
128
+ /* A titled card is labelled by its title; otherwise the caller's aria-labelledby stays (5.8). 5.86 (Chamber-OS
129
+ * 199): only where a name is allowed — a root that takes one (section, article…) or one with a role; a plain
130
+ * div is generic, where ARIA 1.2 prohibits a name. The title keeps its id either way. */
131
+ "aria-labelledby": !head && props.title && props.titleId && cardTakesName(props.as || "section", props.role) ? props.titleId : props["aria-labelledby"]
91
132
  }),
92
133
  head || props.title || props.actions ? /* @__PURE__ */ React.createElement("div", { className: "aura-card__head" }, /* @__PURE__ */ React.createElement("div", { className: "aura-card__heading" }, head ? props.header : null, !head && props.title ? h("h" + (props.headingLevel || 3), { className: "aura-card__title", id: props.titleId }, props.title) : null, !head && props.description ? /* @__PURE__ */ React.createElement("p", { className: "aura-card__desc" }, props.description) : null), props.actions ? /* @__PURE__ */ React.createElement("div", { className: "aura-card__actions" }, props.actions) : null) : null,
93
134
  props.children ? /* @__PURE__ */ React.createElement("div", { className: "aura-card__body" }, props.children) : null,
@@ -187,7 +228,13 @@ function emptyStateElement(props, ref) {
187
228
  props.className
188
229
  )
189
230
  },
190
- /* @__PURE__ */ React.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React.createElement(Icon, { name: props.icon || /* @__PURE__ */ React.createElement(IconInbox, null), size: props.size === "sm" ? "md" : "lg" })),
231
+ props.icon === false ? null : /* @__PURE__ */ React.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React.createElement(
232
+ Icon,
233
+ {
234
+ name: props.icon || (props.tone === "danger" ? /* @__PURE__ */ React.createElement(IconTriangleAlert, null) : /* @__PURE__ */ React.createElement(IconInbox, null)),
235
+ size: props.size === "sm" ? "md" : "lg"
236
+ }
237
+ )),
191
238
  /* @__PURE__ */ React.createElement(HT, { className: "aura-empty__title" }, props.title),
192
239
  props.description ? /* @__PURE__ */ React.createElement("p", { className: "aura-empty__text" }, props.description) : null,
193
240
  props.action ? /* @__PURE__ */ React.createElement("div", { className: "aura-empty__action" }, props.action) : null
package/dist/index.d.cts CHANGED
@@ -878,7 +878,10 @@ export interface CardProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "ti
878
878
  interactive?: boolean | undefined;
879
879
  as?: keyof React$1.JSX.IntrinsicElements | undefined;
880
880
  className?: string | undefined;
881
- /** id for the title element; the card is then labelled by it (aria-labelledby). */
881
+ /** id for the title element; the card is then labelled by it (aria-labelledby) — when its root takes a name: the
882
+ * default `section`, `article`, `aside`, `nav`, `form`, `fieldset`… or any root with a `role` (5.86, Chamber-OS 199).
883
+ * With `as="div"` and no role the title keeps its id but the root stays unlabelled (ARIA 1.2 prohibits a name on a
884
+ * generic element). */
882
885
  titleId?: string | undefined;
883
886
  /** Free head content in place of `title` and `description` (5.15, Chamber-OS 87): skeleton bars while the card
884
887
  * loads, a status pill above a title you mark up yourself. No heading is added; `actions` still sit top-right. */
@@ -1795,7 +1798,9 @@ export interface SkeletonProps {
1795
1798
  export interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
1796
1799
  title: React$1.ReactNode;
1797
1800
  description?: React$1.ReactNode | undefined;
1798
- icon?: IconInput | undefined;
1801
+ /** Default `inbox`, or `triangle-alert` with `tone="danger"` (5.86, Chamber-OS 202). `false` (5.86, Chamber-OS 201)
1802
+ * draws no icon and no circle — a short placeholder in a table cell or a small panel. */
1803
+ icon?: IconInput | false | undefined;
1799
1804
  /** One or two buttons. */
1800
1805
  action?: React$1.ReactNode | undefined;
1801
1806
  size?: "sm" | "md" | undefined;
package/dist/index.d.ts CHANGED
@@ -878,7 +878,10 @@ export interface CardProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "ti
878
878
  interactive?: boolean | undefined;
879
879
  as?: keyof React$1.JSX.IntrinsicElements | undefined;
880
880
  className?: string | undefined;
881
- /** id for the title element; the card is then labelled by it (aria-labelledby). */
881
+ /** id for the title element; the card is then labelled by it (aria-labelledby) — when its root takes a name: the
882
+ * default `section`, `article`, `aside`, `nav`, `form`, `fieldset`… or any root with a `role` (5.86, Chamber-OS 199).
883
+ * With `as="div"` and no role the title keeps its id but the root stays unlabelled (ARIA 1.2 prohibits a name on a
884
+ * generic element). */
882
885
  titleId?: string | undefined;
883
886
  /** Free head content in place of `title` and `description` (5.15, Chamber-OS 87): skeleton bars while the card
884
887
  * loads, a status pill above a title you mark up yourself. No heading is added; `actions` still sit top-right. */
@@ -1795,7 +1798,9 @@ export interface SkeletonProps {
1795
1798
  export interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
1796
1799
  title: React$1.ReactNode;
1797
1800
  description?: React$1.ReactNode | undefined;
1798
- icon?: IconInput | undefined;
1801
+ /** Default `inbox`, or `triangle-alert` with `tone="danger"` (5.86, Chamber-OS 202). `false` (5.86, Chamber-OS 201)
1802
+ * draws no icon and no circle — a short placeholder in a table cell or a small panel. */
1803
+ icon?: IconInput | false | undefined;
1799
1804
  /** One or two buttons. */
1800
1805
  action?: React$1.ReactNode | undefined;
1801
1806
  size?: "sm" | "md" | undefined;
@@ -1228,6 +1228,45 @@ function alertElement(props, ref, close, autoId) {
1228
1228
  close
1229
1229
  );
1230
1230
  }
1231
+ var NAMED_ROOTS = [
1232
+ "section",
1233
+ "article",
1234
+ "aside",
1235
+ "nav",
1236
+ "main",
1237
+ "search",
1238
+ "form",
1239
+ "fieldset",
1240
+ "details",
1241
+ "dialog",
1242
+ "figure",
1243
+ "li",
1244
+ "ul",
1245
+ "ol",
1246
+ "menu"
1247
+ ];
1248
+ var NAMELESS_ROLES = [
1249
+ "generic",
1250
+ "none",
1251
+ "presentation",
1252
+ "paragraph",
1253
+ "caption",
1254
+ "code",
1255
+ "deletion",
1256
+ "emphasis",
1257
+ "insertion",
1258
+ "strong",
1259
+ "subscript",
1260
+ "superscript",
1261
+ "term",
1262
+ "time",
1263
+ "mark"
1264
+ ];
1265
+ function cardTakesName(as, role) {
1266
+ const first = role ? role.trim().split(/\s+/)[0].toLowerCase() : "";
1267
+ if (first) return NAMELESS_ROLES.indexOf(first) < 0;
1268
+ return NAMED_ROOTS.indexOf(as) >= 0;
1269
+ }
1231
1270
  function cardElement(props, ref) {
1232
1271
  const creative = props.variant === "creative";
1233
1272
  const rest = omit(props, [
@@ -1257,8 +1296,10 @@ function cardElement(props, ref) {
1257
1296
  props.flushBelow && "aura-card--flush-below-" + props.flushBelow,
1258
1297
  props.className
1259
1298
  ),
1260
- /* A titled card is labelled by its title; otherwise the caller's aria-labelledby stays (5.8). */
1261
- "aria-labelledby": !head && props.title && props.titleId ? props.titleId : props["aria-labelledby"]
1299
+ /* A titled card is labelled by its title; otherwise the caller's aria-labelledby stays (5.8). 5.86 (Chamber-OS
1300
+ * 199): only where a name is allowed — a root that takes one (section, article…) or one with a role; a plain
1301
+ * div is generic, where ARIA 1.2 prohibits a name. The title keeps its id either way. */
1302
+ "aria-labelledby": !head && props.title && props.titleId && cardTakesName(props.as || "section", props.role) ? props.titleId : props["aria-labelledby"]
1262
1303
  }),
1263
1304
  head || props.title || props.actions ? /* @__PURE__ */ React3.createElement("div", { className: "aura-card__head" }, /* @__PURE__ */ React3.createElement("div", { className: "aura-card__heading" }, head ? props.header : null, !head && props.title ? h2("h" + (props.headingLevel || 3), { className: "aura-card__title", id: props.titleId }, props.title) : null, !head && props.description ? /* @__PURE__ */ React3.createElement("p", { className: "aura-card__desc" }, props.description) : null), props.actions ? /* @__PURE__ */ React3.createElement("div", { className: "aura-card__actions" }, props.actions) : null) : null,
1264
1305
  props.children ? /* @__PURE__ */ React3.createElement("div", { className: "aura-card__body" }, props.children) : null,
@@ -1358,7 +1399,13 @@ function emptyStateElement(props, ref) {
1358
1399
  props.className
1359
1400
  )
1360
1401
  },
1361
- /* @__PURE__ */ React3.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React3.createElement(Icon, { name: props.icon || /* @__PURE__ */ React3.createElement(IconInbox, null), size: props.size === "sm" ? "md" : "lg" })),
1402
+ props.icon === false ? null : /* @__PURE__ */ React3.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React3.createElement(
1403
+ Icon,
1404
+ {
1405
+ name: props.icon || (props.tone === "danger" ? /* @__PURE__ */ React3.createElement(IconTriangleAlert, null) : /* @__PURE__ */ React3.createElement(IconInbox, null)),
1406
+ size: props.size === "sm" ? "md" : "lg"
1407
+ }
1408
+ )),
1362
1409
  /* @__PURE__ */ React3.createElement(HT, { className: "aura-empty__title" }, props.title),
1363
1410
  props.description ? /* @__PURE__ */ React3.createElement("p", { className: "aura-empty__text" }, props.description) : null,
1364
1411
  props.action ? /* @__PURE__ */ React3.createElement("div", { className: "aura-empty__action" }, props.action) : null
@@ -114,7 +114,10 @@ export interface CardProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "ti
114
114
  interactive?: boolean | undefined;
115
115
  as?: keyof React$1.JSX.IntrinsicElements | undefined;
116
116
  className?: string | undefined;
117
- /** id for the title element; the card is then labelled by it (aria-labelledby). */
117
+ /** id for the title element; the card is then labelled by it (aria-labelledby) — when its root takes a name: the
118
+ * default `section`, `article`, `aside`, `nav`, `form`, `fieldset`… or any root with a `role` (5.86, Chamber-OS 199).
119
+ * With `as="div"` and no role the title keeps its id but the root stays unlabelled (ARIA 1.2 prohibits a name on a
120
+ * generic element). */
118
121
  titleId?: string | undefined;
119
122
  /** Free head content in place of `title` and `description` (5.15, Chamber-OS 87): skeleton bars while the card
120
123
  * loads, a status pill above a title you mark up yourself. No heading is added; `actions` still sit top-right. */
@@ -233,7 +236,9 @@ export interface BadgeProps extends React$1.HTMLAttributes<HTMLSpanElement> {
233
236
  export interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
234
237
  title: React$1.ReactNode;
235
238
  description?: React$1.ReactNode | undefined;
236
- icon?: IconInput | undefined;
239
+ /** Default `inbox`, or `triangle-alert` with `tone="danger"` (5.86, Chamber-OS 202). `false` (5.86, Chamber-OS 201)
240
+ * draws no icon and no circle — a short placeholder in a table cell or a small panel. */
241
+ icon?: IconInput | false | undefined;
237
242
  /** One or two buttons. */
238
243
  action?: React$1.ReactNode | undefined;
239
244
  size?: "sm" | "md" | undefined;
@@ -114,7 +114,10 @@ export interface CardProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "ti
114
114
  interactive?: boolean | undefined;
115
115
  as?: keyof React$1.JSX.IntrinsicElements | undefined;
116
116
  className?: string | undefined;
117
- /** id for the title element; the card is then labelled by it (aria-labelledby). */
117
+ /** id for the title element; the card is then labelled by it (aria-labelledby) — when its root takes a name: the
118
+ * default `section`, `article`, `aside`, `nav`, `form`, `fieldset`… or any root with a `role` (5.86, Chamber-OS 199).
119
+ * With `as="div"` and no role the title keeps its id but the root stays unlabelled (ARIA 1.2 prohibits a name on a
120
+ * generic element). */
118
121
  titleId?: string | undefined;
119
122
  /** Free head content in place of `title` and `description` (5.15, Chamber-OS 87): skeleton bars while the card
120
123
  * loads, a status pill above a title you mark up yourself. No heading is added; `actions` still sit top-right. */
@@ -233,7 +236,9 @@ export interface BadgeProps extends React$1.HTMLAttributes<HTMLSpanElement> {
233
236
  export interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
234
237
  title: React$1.ReactNode;
235
238
  description?: React$1.ReactNode | undefined;
236
- icon?: IconInput | undefined;
239
+ /** Default `inbox`, or `triangle-alert` with `tone="danger"` (5.86, Chamber-OS 202). `false` (5.86, Chamber-OS 201)
240
+ * draws no icon and no circle — a short placeholder in a table cell or a small panel. */
241
+ icon?: IconInput | false | undefined;
237
242
  /** One or two buttons. */
238
243
  action?: React$1.ReactNode | undefined;
239
244
  size?: "sm" | "md" | undefined;
@@ -1161,6 +1161,45 @@ function alertElement(props, ref, close, autoId) {
1161
1161
  close
1162
1162
  );
1163
1163
  }
1164
+ var NAMED_ROOTS = [
1165
+ "section",
1166
+ "article",
1167
+ "aside",
1168
+ "nav",
1169
+ "main",
1170
+ "search",
1171
+ "form",
1172
+ "fieldset",
1173
+ "details",
1174
+ "dialog",
1175
+ "figure",
1176
+ "li",
1177
+ "ul",
1178
+ "ol",
1179
+ "menu"
1180
+ ];
1181
+ var NAMELESS_ROLES = [
1182
+ "generic",
1183
+ "none",
1184
+ "presentation",
1185
+ "paragraph",
1186
+ "caption",
1187
+ "code",
1188
+ "deletion",
1189
+ "emphasis",
1190
+ "insertion",
1191
+ "strong",
1192
+ "subscript",
1193
+ "superscript",
1194
+ "term",
1195
+ "time",
1196
+ "mark"
1197
+ ];
1198
+ function cardTakesName(as, role) {
1199
+ const first = role ? role.trim().split(/\s+/)[0].toLowerCase() : "";
1200
+ if (first) return NAMELESS_ROLES.indexOf(first) < 0;
1201
+ return NAMED_ROOTS.indexOf(as) >= 0;
1202
+ }
1164
1203
  function cardElement(props, ref) {
1165
1204
  const creative = props.variant === "creative";
1166
1205
  const rest = omit(props, [
@@ -1190,8 +1229,10 @@ function cardElement(props, ref) {
1190
1229
  props.flushBelow && "aura-card--flush-below-" + props.flushBelow,
1191
1230
  props.className
1192
1231
  ),
1193
- /* A titled card is labelled by its title; otherwise the caller's aria-labelledby stays (5.8). */
1194
- "aria-labelledby": !head && props.title && props.titleId ? props.titleId : props["aria-labelledby"]
1232
+ /* A titled card is labelled by its title; otherwise the caller's aria-labelledby stays (5.8). 5.86 (Chamber-OS
1233
+ * 199): only where a name is allowed — a root that takes one (section, article…) or one with a role; a plain
1234
+ * div is generic, where ARIA 1.2 prohibits a name. The title keeps its id either way. */
1235
+ "aria-labelledby": !head && props.title && props.titleId && cardTakesName(props.as || "section", props.role) ? props.titleId : props["aria-labelledby"]
1195
1236
  }),
1196
1237
  head || props.title || props.actions ? /* @__PURE__ */ React3.createElement("div", { className: "aura-card__head" }, /* @__PURE__ */ React3.createElement("div", { className: "aura-card__heading" }, head ? props.header : null, !head && props.title ? h2("h" + (props.headingLevel || 3), { className: "aura-card__title", id: props.titleId }, props.title) : null, !head && props.description ? /* @__PURE__ */ React3.createElement("p", { className: "aura-card__desc" }, props.description) : null), props.actions ? /* @__PURE__ */ React3.createElement("div", { className: "aura-card__actions" }, props.actions) : null) : null,
1197
1238
  props.children ? /* @__PURE__ */ React3.createElement("div", { className: "aura-card__body" }, props.children) : null,
@@ -1291,7 +1332,13 @@ function emptyStateElement(props, ref) {
1291
1332
  props.className
1292
1333
  )
1293
1334
  },
1294
- /* @__PURE__ */ React3.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React3.createElement(Icon, { name: props.icon || /* @__PURE__ */ React3.createElement(IconInbox, null), size: props.size === "sm" ? "md" : "lg" })),
1335
+ props.icon === false ? null : /* @__PURE__ */ React3.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React3.createElement(
1336
+ Icon,
1337
+ {
1338
+ name: props.icon || (props.tone === "danger" ? /* @__PURE__ */ React3.createElement(IconTriangleAlert, null) : /* @__PURE__ */ React3.createElement(IconInbox, null)),
1339
+ size: props.size === "sm" ? "md" : "lg"
1340
+ }
1341
+ )),
1295
1342
  /* @__PURE__ */ React3.createElement(HT, { className: "aura-empty__title" }, props.title),
1296
1343
  props.description ? /* @__PURE__ */ React3.createElement("p", { className: "aura-empty__text" }, props.description) : null,
1297
1344
  props.action ? /* @__PURE__ */ React3.createElement("div", { className: "aura-empty__action" }, props.action) : null
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.85.0",
3
+ "version": "5.86.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",