@jirawatpyk/aura-react 5.84.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,16 @@ 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
+
257
+ ## 5.85 — Chamber-OS 198 (DataTable columns for the cards only)
258
+
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.
260
+
251
261
  ## 5.84 — Chamber-OS 197 (cursor Pagination without Previous)
252
262
 
253
263
  - **Pagination `mode="cursor"` `showPrevious`** (#197): default `true`; `false` leaves Previous out entirely, as `showFirst={false}` does First — for a list that only goes forward (keyset, newest first), where a disabled Previous could never become live. The nav then holds Next (and First when shown) and the `status`.
@@ -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
@@ -6135,7 +6182,7 @@ window.Aura = (() => {
6135
6182
  return w < threshold * (1 - 0.5 / Q);
6136
6183
  }
6137
6184
  function hidePx(c) {
6138
- if (c.hideBelow == null) return void 0;
6185
+ if (c.hideBelow == null || c.grid === false) return void 0;
6139
6186
  const px = typeof c.hideBelow === "number" ? c.hideBelow : BP[c.hideBelow];
6140
6187
  return px != null && px > 0 ? px : void 0;
6141
6188
  }
@@ -6390,10 +6437,16 @@ window.Aura = (() => {
6390
6437
  }).map(function(k) {
6391
6438
  return byKey[k];
6392
6439
  }).filter(function(c) {
6393
- return !tooNarrow(c);
6440
+ return !tooNarrow(c) && (c.grid !== false || !!props.stackBelow);
6394
6441
  });
6442
+ const hasCardOnly = shown.some(function(c) {
6443
+ return c.grid === false;
6444
+ });
6445
+ const gridShown = shown.filter(function(c) {
6446
+ return c.grid !== false;
6447
+ }).length;
6395
6448
  function isPinned(c) {
6396
- return pinnedKeys.indexOf(c.key) >= 0 && c.width != null;
6449
+ return pinnedKeys.indexOf(c.key) >= 0 && c.width != null && c.grid !== false;
6397
6450
  }
6398
6451
  const vis = shown.filter(isPinned).concat(
6399
6452
  shown.filter(function(c) {
@@ -6441,7 +6494,8 @@ window.Aura = (() => {
6441
6494
  return {
6442
6495
  "data-card": part,
6443
6496
  "data-label": part === "field" || part === "wide" ? c.label || void 0 : void 0,
6444
- "data-hide": lv ? String(lv) : void 0
6497
+ "data-hide": lv ? String(lv) : void 0,
6498
+ "data-grid": c.grid === false ? "off" : void 0
6445
6499
  };
6446
6500
  }
6447
6501
  const hasFields = vis.some(function(c, i) {
@@ -6449,10 +6503,13 @@ window.Aura = (() => {
6449
6503
  return p === "field" || p === "wide";
6450
6504
  });
6451
6505
  const hasFlex = vis.some(function(c) {
6452
- return widthOf2(c) == null;
6506
+ return widthOf2(c) == null && c.grid !== false;
6453
6507
  });
6508
+ let lastGridCol = vis.length - 1;
6509
+ while (lastGridCol > 0 && vis[lastGridCol].grid === false) lastGridCol--;
6454
6510
  let fixedSum = 0, hideTerms = "";
6455
6511
  vis.forEach(function(c) {
6512
+ if (c.grid === false) return;
6456
6513
  const w = widthOf2(c) != null ? widthOf2(c) : c.minWidth || FLEX_MIN, lv = hideLevel(c);
6457
6514
  if (lv && boxWidth[0] == null) hideTerms += " + " + w + "px * var(--aura-h" + lv + "-on, 1)";
6458
6515
  else fixedSum += w;
@@ -6482,7 +6539,7 @@ window.Aura = (() => {
6482
6539
  s["--aura-cell-flex"] = g + " 1 0";
6483
6540
  s["--aura-cell-min"] = (c.minWidth || FLEX_MIN) + "px";
6484
6541
  } else {
6485
- s["--aura-cell-flex"] = !hasFlex && i === vis.length - 1 ? "1 0 auto" : "none";
6542
+ s["--aura-cell-flex"] = !hasFlex && i === lastGridCol ? "1 0 auto" : "none";
6486
6543
  s["--aura-cell-w"] = w + "px";
6487
6544
  }
6488
6545
  if (isPinned(c)) s["--aura-cell-left"] = "calc(var(--aura-space-6)" + selW + " + " + pinOffsets[c.key] + ")";
@@ -6620,6 +6677,12 @@ window.Aura = (() => {
6620
6677
  }
6621
6678
  const visibleRows = Math.max(1, Math.floor(bodyH / ROW_H));
6622
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
+ }
6623
6686
  const nRows = loading ? 0 : pageRows.length;
6624
6687
  const hasTotal = !!(props.footer && rows.length && !loading), T = nRows + 1, lastR = nRows + (hasTotal ? 1 : 0);
6625
6688
  const active = activeState[0];
@@ -6631,7 +6694,12 @@ window.Aura = (() => {
6631
6694
  const cardHidden = [];
6632
6695
  for (let ci = 0; ci < nCols; ci++) {
6633
6696
  const col = colAt(ci);
6634
- cardHidden.push(stacked && (col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel));
6697
+ cardHidden.push(
6698
+ stacked ? col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel : (
6699
+ /* before the first measure the layout is CSS's: the DOM check below decides */
6700
+ boxWidth[0] != null && !!col && col.grid === false
6701
+ )
6702
+ );
6635
6703
  }
6636
6704
  function nearestShown(c, dir, ok) {
6637
6705
  if (ok(c)) return c;
@@ -6692,7 +6760,7 @@ window.Aura = (() => {
6692
6760
  r2 = Math.max(0, Math.min(r2, lastR));
6693
6761
  c = Math.max(0, Math.min(c, nCols - 1));
6694
6762
  if (stacked && r2 === 0 && nRows > 0 && (!(selectable && c === 0) || noCardSel)) r2 = 1;
6695
- if (gridRef.current && (r2 === T && hasTotal || stacked)) {
6763
+ if (gridRef.current && (r2 === T && hasTotal || stacked || hasCardOnly)) {
6696
6764
  const shown2 = function(cc) {
6697
6765
  if (cardHidden[cc]) return false;
6698
6766
  const e = gridRef.current.querySelector('[data-rc="' + r2 + ":" + cc + '"]');
@@ -6819,8 +6887,9 @@ window.Aura = (() => {
6819
6887
  window.addEventListener("pointerup", up2);
6820
6888
  }
6821
6889
  function moveCol(key, delta) {
6890
+ if (byKey[key] && byKey[key].grid === false) return false;
6822
6891
  const c = byKey[key], group = vis.filter(function(x) {
6823
- return isPinned(x) === isPinned(c);
6892
+ return isPinned(x) === isPinned(c) && x.grid !== false;
6824
6893
  });
6825
6894
  const gi = group.indexOf(c), target = group[gi + delta];
6826
6895
  if (!target) return false;
@@ -6879,7 +6948,7 @@ window.Aura = (() => {
6879
6948
  }
6880
6949
  function columnMenuItems(c) {
6881
6950
  const group = vis.filter(function(x) {
6882
- return isPinned(x) === isPinned(c);
6951
+ return isPinned(x) === isPinned(c) && x.grid !== false;
6883
6952
  }), gi = group.indexOf(c);
6884
6953
  const items2 = [];
6885
6954
  if (c.sortable)
@@ -6932,7 +7001,7 @@ window.Aura = (() => {
6932
7001
  {
6933
7002
  label: t.hideColumn,
6934
7003
  icon: /* @__PURE__ */ React34.createElement(IconEyeOff, null),
6935
- disabled: shown.length <= 1,
7004
+ disabled: gridShown <= 1,
6936
7005
  onSelect: function() {
6937
7006
  setHidden(c.key, true);
6938
7007
  }
@@ -6941,13 +7010,15 @@ window.Aura = (() => {
6941
7010
  return items2;
6942
7011
  }
6943
7012
  function pickerItems() {
6944
- return order.map(function(k) {
7013
+ return order.filter(function(k) {
7014
+ return byKey[k].grid !== false;
7015
+ }).map(function(k) {
6945
7016
  const c = byKey[k], on = hidden.indexOf(k) < 0;
6946
7017
  return {
6947
7018
  label: c.label || (c.actions ? t.actions : c.key),
6948
7019
  checked: on,
6949
7020
  keepOpen: true,
6950
- disabled: on && shown.length <= 1,
7021
+ disabled: on && gridShown <= 1,
6951
7022
  onSelect: function() {
6952
7023
  setHidden(k, on);
6953
7024
  }
@@ -7075,10 +7146,11 @@ window.Aura = (() => {
7075
7146
  key: c.key,
7076
7147
  role: "columnheader",
7077
7148
  "aria-sort": ariaSort,
7078
- "aria-colindex": ci + 1,
7149
+ "aria-colindex": ariaIdx[ci],
7079
7150
  style: cellStyle(c, i),
7080
7151
  "data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
7081
7152
  "data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
7153
+ "data-grid": c.grid === false ? "off" : void 0,
7082
7154
  tabIndex: tabFor(0, ci),
7083
7155
  "data-rc": "0:" + ci,
7084
7156
  className: cx(
@@ -7237,7 +7309,7 @@ window.Aura = (() => {
7237
7309
  {
7238
7310
  key: c.key,
7239
7311
  role: "gridcell",
7240
- "aria-colindex": ci + 1,
7312
+ "aria-colindex": ariaIdx[ci],
7241
7313
  tabIndex: tabFor(ri, ci),
7242
7314
  "data-rc": ri + ":" + ci,
7243
7315
  className: cx(
@@ -7465,7 +7537,7 @@ window.Aura = (() => {
7465
7537
  {
7466
7538
  key: c.key,
7467
7539
  role: "gridcell",
7468
- "aria-colindex": j + (selectable ? 2 : 1),
7540
+ "aria-colindex": ariaIdx[j + (selectable ? 1 : 0)],
7469
7541
  tabIndex: tabFor(T, ci),
7470
7542
  "data-rc": T + ":" + ci,
7471
7543
  onFocus: function() {
@@ -7560,7 +7632,7 @@ window.Aura = (() => {
7560
7632
  "aria-label": props.label,
7561
7633
  "aria-busy": busy || void 0,
7562
7634
  "aria-rowcount": loading || manual && props.totalRows == null && pageSize && rows.length >= pageSize ? -1 : shownTotal + 1 + (totalRow ? 1 : 0),
7563
- "aria-colcount": nCols,
7635
+ "aria-colcount": ariaColCount,
7564
7636
  "aria-multiselectable": selectable || void 0,
7565
7637
  onKeyDown: onGridKey,
7566
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
@@ -6117,7 +6164,7 @@ function below(w, threshold) {
6117
6164
  return w < threshold * (1 - 0.5 / Q);
6118
6165
  }
6119
6166
  function hidePx(c) {
6120
- if (c.hideBelow == null) return void 0;
6167
+ if (c.hideBelow == null || c.grid === false) return void 0;
6121
6168
  const px = typeof c.hideBelow === "number" ? c.hideBelow : BP[c.hideBelow];
6122
6169
  return px != null && px > 0 ? px : void 0;
6123
6170
  }
@@ -6372,10 +6419,16 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6372
6419
  }).map(function(k) {
6373
6420
  return byKey[k];
6374
6421
  }).filter(function(c) {
6375
- return !tooNarrow(c);
6422
+ return !tooNarrow(c) && (c.grid !== false || !!props.stackBelow);
6376
6423
  });
6424
+ const hasCardOnly = shown.some(function(c) {
6425
+ return c.grid === false;
6426
+ });
6427
+ const gridShown = shown.filter(function(c) {
6428
+ return c.grid !== false;
6429
+ }).length;
6377
6430
  function isPinned(c) {
6378
- return pinnedKeys.indexOf(c.key) >= 0 && c.width != null;
6431
+ return pinnedKeys.indexOf(c.key) >= 0 && c.width != null && c.grid !== false;
6379
6432
  }
6380
6433
  const vis = shown.filter(isPinned).concat(
6381
6434
  shown.filter(function(c) {
@@ -6423,7 +6476,8 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6423
6476
  return {
6424
6477
  "data-card": part,
6425
6478
  "data-label": part === "field" || part === "wide" ? c.label || void 0 : void 0,
6426
- "data-hide": lv ? String(lv) : void 0
6479
+ "data-hide": lv ? String(lv) : void 0,
6480
+ "data-grid": c.grid === false ? "off" : void 0
6427
6481
  };
6428
6482
  }
6429
6483
  const hasFields = vis.some(function(c, i) {
@@ -6431,10 +6485,13 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6431
6485
  return p === "field" || p === "wide";
6432
6486
  });
6433
6487
  const hasFlex = vis.some(function(c) {
6434
- return widthOf2(c) == null;
6488
+ return widthOf2(c) == null && c.grid !== false;
6435
6489
  });
6490
+ let lastGridCol = vis.length - 1;
6491
+ while (lastGridCol > 0 && vis[lastGridCol].grid === false) lastGridCol--;
6436
6492
  let fixedSum = 0, hideTerms = "";
6437
6493
  vis.forEach(function(c) {
6494
+ if (c.grid === false) return;
6438
6495
  const w = widthOf2(c) != null ? widthOf2(c) : c.minWidth || FLEX_MIN, lv = hideLevel(c);
6439
6496
  if (lv && boxWidth[0] == null) hideTerms += " + " + w + "px * var(--aura-h" + lv + "-on, 1)";
6440
6497
  else fixedSum += w;
@@ -6464,7 +6521,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6464
6521
  s["--aura-cell-flex"] = g + " 1 0";
6465
6522
  s["--aura-cell-min"] = (c.minWidth || FLEX_MIN) + "px";
6466
6523
  } else {
6467
- s["--aura-cell-flex"] = !hasFlex && i === vis.length - 1 ? "1 0 auto" : "none";
6524
+ s["--aura-cell-flex"] = !hasFlex && i === lastGridCol ? "1 0 auto" : "none";
6468
6525
  s["--aura-cell-w"] = w + "px";
6469
6526
  }
6470
6527
  if (isPinned(c)) s["--aura-cell-left"] = "calc(var(--aura-space-6)" + selW + " + " + pinOffsets[c.key] + ")";
@@ -6602,6 +6659,12 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6602
6659
  }
6603
6660
  const visibleRows = Math.max(1, Math.floor(bodyH / ROW_H));
6604
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
+ }
6605
6668
  const nRows = loading ? 0 : pageRows.length;
6606
6669
  const hasTotal = !!(props.footer && rows.length && !loading), T = nRows + 1, lastR = nRows + (hasTotal ? 1 : 0);
6607
6670
  const active = activeState[0];
@@ -6613,7 +6676,12 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6613
6676
  const cardHidden = [];
6614
6677
  for (let ci = 0; ci < nCols; ci++) {
6615
6678
  const col = colAt(ci);
6616
- cardHidden.push(stacked && (col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel));
6679
+ cardHidden.push(
6680
+ stacked ? col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel : (
6681
+ /* before the first measure the layout is CSS's: the DOM check below decides */
6682
+ boxWidth[0] != null && !!col && col.grid === false
6683
+ )
6684
+ );
6617
6685
  }
6618
6686
  function nearestShown(c, dir, ok) {
6619
6687
  if (ok(c)) return c;
@@ -6674,7 +6742,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6674
6742
  r2 = Math.max(0, Math.min(r2, lastR));
6675
6743
  c = Math.max(0, Math.min(c, nCols - 1));
6676
6744
  if (stacked && r2 === 0 && nRows > 0 && (!(selectable && c === 0) || noCardSel)) r2 = 1;
6677
- if (gridRef.current && (r2 === T && hasTotal || stacked)) {
6745
+ if (gridRef.current && (r2 === T && hasTotal || stacked || hasCardOnly)) {
6678
6746
  const shown2 = function(cc) {
6679
6747
  if (cardHidden[cc]) return false;
6680
6748
  const e = gridRef.current.querySelector('[data-rc="' + r2 + ":" + cc + '"]');
@@ -6801,8 +6869,9 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6801
6869
  window.addEventListener("pointerup", up2);
6802
6870
  }
6803
6871
  function moveCol(key, delta) {
6872
+ if (byKey[key] && byKey[key].grid === false) return false;
6804
6873
  const c = byKey[key], group = vis.filter(function(x) {
6805
- return isPinned(x) === isPinned(c);
6874
+ return isPinned(x) === isPinned(c) && x.grid !== false;
6806
6875
  });
6807
6876
  const gi = group.indexOf(c), target = group[gi + delta];
6808
6877
  if (!target) return false;
@@ -6861,7 +6930,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6861
6930
  }
6862
6931
  function columnMenuItems(c) {
6863
6932
  const group = vis.filter(function(x) {
6864
- return isPinned(x) === isPinned(c);
6933
+ return isPinned(x) === isPinned(c) && x.grid !== false;
6865
6934
  }), gi = group.indexOf(c);
6866
6935
  const items2 = [];
6867
6936
  if (c.sortable)
@@ -6914,7 +6983,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6914
6983
  {
6915
6984
  label: t.hideColumn,
6916
6985
  icon: /* @__PURE__ */ React34.createElement(IconEyeOff, null),
6917
- disabled: shown.length <= 1,
6986
+ disabled: gridShown <= 1,
6918
6987
  onSelect: function() {
6919
6988
  setHidden(c.key, true);
6920
6989
  }
@@ -6923,13 +6992,15 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6923
6992
  return items2;
6924
6993
  }
6925
6994
  function pickerItems() {
6926
- return order.map(function(k) {
6995
+ return order.filter(function(k) {
6996
+ return byKey[k].grid !== false;
6997
+ }).map(function(k) {
6927
6998
  const c = byKey[k], on = hidden.indexOf(k) < 0;
6928
6999
  return {
6929
7000
  label: c.label || (c.actions ? t.actions : c.key),
6930
7001
  checked: on,
6931
7002
  keepOpen: true,
6932
- disabled: on && shown.length <= 1,
7003
+ disabled: on && gridShown <= 1,
6933
7004
  onSelect: function() {
6934
7005
  setHidden(k, on);
6935
7006
  }
@@ -7057,10 +7128,11 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
7057
7128
  key: c.key,
7058
7129
  role: "columnheader",
7059
7130
  "aria-sort": ariaSort,
7060
- "aria-colindex": ci + 1,
7131
+ "aria-colindex": ariaIdx[ci],
7061
7132
  style: cellStyle(c, i),
7062
7133
  "data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
7063
7134
  "data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
7135
+ "data-grid": c.grid === false ? "off" : void 0,
7064
7136
  tabIndex: tabFor(0, ci),
7065
7137
  "data-rc": "0:" + ci,
7066
7138
  className: cx(
@@ -7219,7 +7291,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
7219
7291
  {
7220
7292
  key: c.key,
7221
7293
  role: "gridcell",
7222
- "aria-colindex": ci + 1,
7294
+ "aria-colindex": ariaIdx[ci],
7223
7295
  tabIndex: tabFor(ri, ci),
7224
7296
  "data-rc": ri + ":" + ci,
7225
7297
  className: cx(
@@ -7447,7 +7519,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
7447
7519
  {
7448
7520
  key: c.key,
7449
7521
  role: "gridcell",
7450
- "aria-colindex": j + (selectable ? 2 : 1),
7522
+ "aria-colindex": ariaIdx[j + (selectable ? 1 : 0)],
7451
7523
  tabIndex: tabFor(T, ci),
7452
7524
  "data-rc": T + ":" + ci,
7453
7525
  onFocus: function() {
@@ -7542,7 +7614,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
7542
7614
  "aria-label": props.label,
7543
7615
  "aria-busy": busy || void 0,
7544
7616
  "aria-rowcount": loading || manual && props.totalRows == null && pageSize && rows.length >= pageSize ? -1 : shownTotal + 1 + (totalRow ? 1 : 0),
7545
- "aria-colcount": nCols,
7617
+ "aria-colcount": ariaColCount,
7546
7618
  "aria-multiselectable": selectable || void 0,
7547
7619
  onKeyDown: onGridKey,
7548
7620
  onScroll: function(e) {
@@ -59,7 +59,7 @@ function below(w, threshold) {
59
59
  return w < threshold * (1 - 0.5 / Q);
60
60
  }
61
61
  function hidePx(c) {
62
- if (c.hideBelow == null) return void 0;
62
+ if (c.hideBelow == null || c.grid === false) return void 0;
63
63
  const px = typeof c.hideBelow === "number" ? c.hideBelow : BP[c.hideBelow];
64
64
  return px != null && px > 0 ? px : void 0;
65
65
  }
@@ -312,10 +312,16 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
312
312
  }).map(function(k) {
313
313
  return byKey[k];
314
314
  }).filter(function(c) {
315
- return !tooNarrow(c);
315
+ return !tooNarrow(c) && (c.grid !== false || !!props.stackBelow);
316
316
  });
317
+ const hasCardOnly = shown.some(function(c) {
318
+ return c.grid === false;
319
+ });
320
+ const gridShown = shown.filter(function(c) {
321
+ return c.grid !== false;
322
+ }).length;
317
323
  function isPinned(c) {
318
- return pinnedKeys.indexOf(c.key) >= 0 && c.width != null;
324
+ return pinnedKeys.indexOf(c.key) >= 0 && c.width != null && c.grid !== false;
319
325
  }
320
326
  const vis = shown.filter(isPinned).concat(
321
327
  shown.filter(function(c) {
@@ -363,7 +369,8 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
363
369
  return {
364
370
  "data-card": part,
365
371
  "data-label": part === "field" || part === "wide" ? c.label || void 0 : void 0,
366
- "data-hide": lv ? String(lv) : void 0
372
+ "data-hide": lv ? String(lv) : void 0,
373
+ "data-grid": c.grid === false ? "off" : void 0
367
374
  };
368
375
  }
369
376
  const hasFields = vis.some(function(c, i) {
@@ -371,10 +378,13 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
371
378
  return p === "field" || p === "wide";
372
379
  });
373
380
  const hasFlex = vis.some(function(c) {
374
- return widthOf(c) == null;
381
+ return widthOf(c) == null && c.grid !== false;
375
382
  });
383
+ let lastGridCol = vis.length - 1;
384
+ while (lastGridCol > 0 && vis[lastGridCol].grid === false) lastGridCol--;
376
385
  let fixedSum = 0, hideTerms = "";
377
386
  vis.forEach(function(c) {
387
+ if (c.grid === false) return;
378
388
  const w = widthOf(c) != null ? widthOf(c) : c.minWidth || FLEX_MIN, lv = hideLevel(c);
379
389
  if (lv && boxWidth[0] == null) hideTerms += " + " + w + "px * var(--aura-h" + lv + "-on, 1)";
380
390
  else fixedSum += w;
@@ -404,7 +414,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
404
414
  s["--aura-cell-flex"] = g + " 1 0";
405
415
  s["--aura-cell-min"] = (c.minWidth || FLEX_MIN) + "px";
406
416
  } else {
407
- s["--aura-cell-flex"] = !hasFlex && i === vis.length - 1 ? "1 0 auto" : "none";
417
+ s["--aura-cell-flex"] = !hasFlex && i === lastGridCol ? "1 0 auto" : "none";
408
418
  s["--aura-cell-w"] = w + "px";
409
419
  }
410
420
  if (isPinned(c)) s["--aura-cell-left"] = "calc(var(--aura-space-6)" + selW + " + " + pinOffsets[c.key] + ")";
@@ -542,6 +552,12 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
542
552
  }
543
553
  const visibleRows = Math.max(1, Math.floor(bodyH / ROW_H));
544
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
+ }
545
561
  const nRows = loading ? 0 : pageRows.length;
546
562
  const hasTotal = !!(props.footer && rows.length && !loading), T = nRows + 1, lastR = nRows + (hasTotal ? 1 : 0);
547
563
  const active = activeState[0];
@@ -553,7 +569,12 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
553
569
  const cardHidden = [];
554
570
  for (let ci = 0; ci < nCols; ci++) {
555
571
  const col = colAt(ci);
556
- cardHidden.push(stacked && (col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel));
572
+ cardHidden.push(
573
+ stacked ? col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel : (
574
+ /* before the first measure the layout is CSS's: the DOM check below decides */
575
+ boxWidth[0] != null && !!col && col.grid === false
576
+ )
577
+ );
557
578
  }
558
579
  function nearestShown(c, dir, ok) {
559
580
  if (ok(c)) return c;
@@ -614,7 +635,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
614
635
  r = Math.max(0, Math.min(r, lastR));
615
636
  c = Math.max(0, Math.min(c, nCols - 1));
616
637
  if (stacked && r === 0 && nRows > 0 && (!(selectable && c === 0) || noCardSel)) r = 1;
617
- if (gridRef.current && (r === T && hasTotal || stacked)) {
638
+ if (gridRef.current && (r === T && hasTotal || stacked || hasCardOnly)) {
618
639
  const shown2 = function(cc) {
619
640
  if (cardHidden[cc]) return false;
620
641
  const e = gridRef.current.querySelector('[data-rc="' + r + ":" + cc + '"]');
@@ -741,8 +762,9 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
741
762
  window.addEventListener("pointerup", up);
742
763
  }
743
764
  function moveCol(key, delta) {
765
+ if (byKey[key] && byKey[key].grid === false) return false;
744
766
  const c = byKey[key], group = vis.filter(function(x) {
745
- return isPinned(x) === isPinned(c);
767
+ return isPinned(x) === isPinned(c) && x.grid !== false;
746
768
  });
747
769
  const gi = group.indexOf(c), target = group[gi + delta];
748
770
  if (!target) return false;
@@ -801,7 +823,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
801
823
  }
802
824
  function columnMenuItems(c) {
803
825
  const group = vis.filter(function(x) {
804
- return isPinned(x) === isPinned(c);
826
+ return isPinned(x) === isPinned(c) && x.grid !== false;
805
827
  }), gi = group.indexOf(c);
806
828
  const items = [];
807
829
  if (c.sortable)
@@ -854,7 +876,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
854
876
  {
855
877
  label: t.hideColumn,
856
878
  icon: /* @__PURE__ */ React.createElement(IconEyeOff, null),
857
- disabled: shown.length <= 1,
879
+ disabled: gridShown <= 1,
858
880
  onSelect: function() {
859
881
  setHidden(c.key, true);
860
882
  }
@@ -863,13 +885,15 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
863
885
  return items;
864
886
  }
865
887
  function pickerItems() {
866
- return order.map(function(k) {
888
+ return order.filter(function(k) {
889
+ return byKey[k].grid !== false;
890
+ }).map(function(k) {
867
891
  const c = byKey[k], on = hidden.indexOf(k) < 0;
868
892
  return {
869
893
  label: c.label || (c.actions ? t.actions : c.key),
870
894
  checked: on,
871
895
  keepOpen: true,
872
- disabled: on && shown.length <= 1,
896
+ disabled: on && gridShown <= 1,
873
897
  onSelect: function() {
874
898
  setHidden(k, on);
875
899
  }
@@ -997,10 +1021,11 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
997
1021
  key: c.key,
998
1022
  role: "columnheader",
999
1023
  "aria-sort": ariaSort,
1000
- "aria-colindex": ci + 1,
1024
+ "aria-colindex": ariaIdx[ci],
1001
1025
  style: cellStyle(c, i),
1002
1026
  "data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
1003
1027
  "data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
1028
+ "data-grid": c.grid === false ? "off" : void 0,
1004
1029
  tabIndex: tabFor(0, ci),
1005
1030
  "data-rc": "0:" + ci,
1006
1031
  className: cx(
@@ -1159,7 +1184,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
1159
1184
  {
1160
1185
  key: c.key,
1161
1186
  role: "gridcell",
1162
- "aria-colindex": ci + 1,
1187
+ "aria-colindex": ariaIdx[ci],
1163
1188
  tabIndex: tabFor(ri, ci),
1164
1189
  "data-rc": ri + ":" + ci,
1165
1190
  className: cx(
@@ -1387,7 +1412,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
1387
1412
  {
1388
1413
  key: c.key,
1389
1414
  role: "gridcell",
1390
- "aria-colindex": j + (selectable ? 2 : 1),
1415
+ "aria-colindex": ariaIdx[j + (selectable ? 1 : 0)],
1391
1416
  tabIndex: tabFor(T, ci),
1392
1417
  "data-rc": T + ":" + ci,
1393
1418
  onFocus: function() {
@@ -1482,7 +1507,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
1482
1507
  "aria-label": props.label,
1483
1508
  "aria-busy": busy || void 0,
1484
1509
  "aria-rowcount": loading || manual && props.totalRows == null && pageSize && rows.length >= pageSize ? -1 : shownTotal + 1 + (totalRow ? 1 : 0),
1485
- "aria-colcount": nCols,
1510
+ "aria-colcount": ariaColCount,
1486
1511
  "aria-multiselectable": selectable || void 0,
1487
1512
  onKeyDown: onGridKey,
1488
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
@@ -127,6 +127,12 @@ export interface DataTableColumn<Row extends Record<string, any> = Record<string
127
127
  * after the half-width fields (in column order; `cardOrder` doesn't move it), its label above and its text wrapping —
128
128
  * a reason with its evidence. Default: today's rule. The grid is unchanged by any of them. */
129
129
  card?: "hide" | "field" | "title" | "pill" | "footer" | "wide" | undefined;
130
+ /** 5.85 (Chamber-OS 198): `false` — the column shows only in stacked cards (below `stackBelow`), never in the grid,
131
+ * the reverse of `card: 'hide'`. Its place in the card still follows `card`. It spends no width-query level, takes no
132
+ * width in the grid, isn't pinned and isn't in the columns button; `hideBelow` is ignored. Needs `stackBelow` (without
133
+ * it the column isn't rendered). Its header isn't in the grid, so it can't be sorted, moved or hidden from the UI —
134
+ * sort by it through `sort`; a controlled `hidden` that lists it hides it in the cards too. Default true. */
135
+ grid?: boolean | undefined;
130
136
  /** How many text lines its loading skeleton draws (5.29, Chamber-OS 134) — 2 for a cell that shows two lines (a
131
137
  * reason and its evidence), so the skeleton row is as tall as the real one with `rowHeight="auto"`. Default 1, at
132
138
  * most 10; ignored on a `pill` column. */
@@ -872,7 +878,10 @@ export interface CardProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "ti
872
878
  interactive?: boolean | undefined;
873
879
  as?: keyof React$1.JSX.IntrinsicElements | undefined;
874
880
  className?: string | undefined;
875
- /** 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). */
876
885
  titleId?: string | undefined;
877
886
  /** Free head content in place of `title` and `description` (5.15, Chamber-OS 87): skeleton bars while the card
878
887
  * loads, a status pill above a title you mark up yourself. No heading is added; `actions` still sit top-right. */
@@ -1789,7 +1798,9 @@ export interface SkeletonProps {
1789
1798
  export interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
1790
1799
  title: React$1.ReactNode;
1791
1800
  description?: React$1.ReactNode | undefined;
1792
- 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;
1793
1804
  /** One or two buttons. */
1794
1805
  action?: React$1.ReactNode | undefined;
1795
1806
  size?: "sm" | "md" | undefined;
package/dist/index.d.ts CHANGED
@@ -127,6 +127,12 @@ export interface DataTableColumn<Row extends Record<string, any> = Record<string
127
127
  * after the half-width fields (in column order; `cardOrder` doesn't move it), its label above and its text wrapping —
128
128
  * a reason with its evidence. Default: today's rule. The grid is unchanged by any of them. */
129
129
  card?: "hide" | "field" | "title" | "pill" | "footer" | "wide" | undefined;
130
+ /** 5.85 (Chamber-OS 198): `false` — the column shows only in stacked cards (below `stackBelow`), never in the grid,
131
+ * the reverse of `card: 'hide'`. Its place in the card still follows `card`. It spends no width-query level, takes no
132
+ * width in the grid, isn't pinned and isn't in the columns button; `hideBelow` is ignored. Needs `stackBelow` (without
133
+ * it the column isn't rendered). Its header isn't in the grid, so it can't be sorted, moved or hidden from the UI —
134
+ * sort by it through `sort`; a controlled `hidden` that lists it hides it in the cards too. Default true. */
135
+ grid?: boolean | undefined;
130
136
  /** How many text lines its loading skeleton draws (5.29, Chamber-OS 134) — 2 for a cell that shows two lines (a
131
137
  * reason and its evidence), so the skeleton row is as tall as the real one with `rowHeight="auto"`. Default 1, at
132
138
  * most 10; ignored on a `pill` column. */
@@ -872,7 +878,10 @@ export interface CardProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "ti
872
878
  interactive?: boolean | undefined;
873
879
  as?: keyof React$1.JSX.IntrinsicElements | undefined;
874
880
  className?: string | undefined;
875
- /** 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). */
876
885
  titleId?: string | undefined;
877
886
  /** Free head content in place of `title` and `description` (5.15, Chamber-OS 87): skeleton bars while the card
878
887
  * loads, a status pill above a title you mark up yourself. No heading is added; `actions` still sit top-right. */
@@ -1789,7 +1798,9 @@ export interface SkeletonProps {
1789
1798
  export interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
1790
1799
  title: React$1.ReactNode;
1791
1800
  description?: React$1.ReactNode | undefined;
1792
- 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;
1793
1804
  /** One or two buttons. */
1794
1805
  action?: React$1.ReactNode | undefined;
1795
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/dist/styles.css CHANGED
@@ -2659,6 +2659,9 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
2659
2659
  @container aura-h1 (width < 9999.5px) { .aura-table { --aura-h1-on: 0; } .aura-table [data-hide='1'] { display: none; } }
2660
2660
  @container aura-h2 (width < 9999.5px) { .aura-table { --aura-h2-on: 0; } .aura-table [data-hide='2'] { display: none; } }
2661
2661
  @container aura-h3 (width < 9999.5px) { .aura-table { --aura-h3-on: 0; } .aura-table [data-hide='3'] { display: none; } }
2662
+ /* 5.85 (Chamber-OS 198): grid: false — in the cards only. Hidden while the table is at or above stackBelow (the grid);
2663
+ * DataTable doesn't render such a column without stackBelow. */
2664
+ @container aura-stack (width >= 9999.5px) { .aura-table [data-grid='off'] { display: none; } }
2662
2665
 
2663
2666
  /* Below stackBelow the same grid lays out as cards: the first column is the title, the first other pill column sits
2664
2667
  * beside it, `actions` columns go top-right, the rest are label/value fields two to a line. Column headers stay for
@@ -2661,6 +2661,9 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
2661
2661
  @container aura-h1 (width < 9999.5px) { .aura-table { --aura-h1-on: 0; } .aura-table [data-hide='1'] { display: none; } }
2662
2662
  @container aura-h2 (width < 9999.5px) { .aura-table { --aura-h2-on: 0; } .aura-table [data-hide='2'] { display: none; } }
2663
2663
  @container aura-h3 (width < 9999.5px) { .aura-table { --aura-h3-on: 0; } .aura-table [data-hide='3'] { display: none; } }
2664
+ /* 5.85 (Chamber-OS 198): grid: false — in the cards only. Hidden while the table is at or above stackBelow (the grid);
2665
+ * DataTable doesn't render such a column without stackBelow. */
2666
+ @container aura-stack (width >= 9999.5px) { .aura-table [data-grid='off'] { display: none; } }
2664
2667
 
2665
2668
  /* Below stackBelow the same grid lays out as cards: the first column is the title, the first other pill column sits
2666
2669
  * beside it, `actions` columns go top-right, the rest are label/value fields two to a line. Column headers stay for
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.84.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",