@jirawatpyk/aura-react 5.12.0 → 5.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -186,6 +186,21 @@ DataTable with sort and page in the URL (4.17): `onStateChange={({ sort, page })
186
186
  - **Time zone**: `timeZone` on AuraProvider, DatePicker, DateRangePicker and Calendar decides "today" (the marker, `min`/`max="today"`, the first month shown); or pass `today` as an ISO date. `todayIn('Asia/Bangkok')` is exported from the root and `/server`.
187
187
  - **Toasts** queue past three instead of dropping: six in a row all show, in order, three at a time.
188
188
 
189
+ ## 5.13 — Chamber-OS addendum 13 (board parity)
190
+
191
+ - **DataTable card options** (item 80): per column, `card: 'hide'` leaves it out of the stacked card (the grid keeps it), `card: 'title' | 'pill' | 'field'` places it (a declared title or pill replaces the automatic one; the automatic title is the first column without a `card` — normally the first column — skipping `actions` columns), and `cardOrder` orders the fields (lowest first; others sort by column index) without touching the grid's order. `hideSelectionInCards` drops the row boxes and the select-all line from the cards only; the selection is kept, and Space doesn't change it while cards show. Screen readers and arrow keys follow the grid's order and skip what the card leaves out (the tab stop too); each remaining field keeps its label; loading skeletons leave out the same columns. With `getRowHref`, the link is the first column's text, so hiding that column in cards leaves the card clickable but without a link to Tab to. All in CSS, so the server HTML is already right.
192
+ ```tsx
193
+ <DataTable stackBelow={640} hideSelectionInCards columns={[{ key: 'company', label: 'COMPANY' }, { key: 'flag', label: 'COUNTRY', card: 'hide' }, { key: 'id', label: 'MEMBER NO.', cardOrder: 1 }, …]} />
194
+ ```
195
+ - **Table `align="middle"` and `bordered={false}`** (item 81): `middle` centres body and footer cells on their row (default `top`); `bordered={false}` drops the frame and the outer cells' side padding, so a table inside a Card lines up with its heading. Stacked rows keep their layout. `Table`'s type no longer accepts the obsolete HTML `align` attribute (`left | center | right`).
196
+ - **EmptyState `tone="danger"`** (item 82): the danger tint, a danger-coloured icon and, with `bordered`, a solid danger frame — for "couldn't load". It stays quiet (no role); pass `role="alert"` to interrupt. EmptyState now passes `id`, `data-*`, `aria-*`, `role` and `style` to its root.
197
+ - **FilterBar search filling the row** (item 83): that is 5.12's `searchGrow`; nothing new was needed.
198
+ - **Td `card="title" | "action"`** (item 84; also on a row header, `Th scope="row"`): in a stacked Table row the title takes the first line without a label, the action sits at the end of that line at its natural size, and the other cells fall two to a line below. A long title wraps before the action. The desktop table is unchanged.
199
+ ```tsx
200
+ <Tr><Td card="title">{company} <span className="aura-table__mono">{no}</span></Td><Td>{type}</Td><Td>{date}</Td>
201
+ <Td card="action"><Button size="sm" variant="secondary">Review</Button></Td></Tr>
202
+ ```
203
+
189
204
  ## 5.12 — Chamber-OS addendum 12 (compact filters)
190
205
 
191
206
  - **FilterSelect** (item 79): a filter for `FilterBar` drawn as one small button — "Status All ▾" — as wide as its words, so several filters and a toggle `Tag` share a row, three and a Tag even at 375px. It is Select underneath: it opens the same AURA list (on phones too, as Select does since 5.3), with the same keys (arrows, typing, Enter, Escape), `name` in a form and a real `<select>` before hydration (with JavaScript off a choice still posts with the form, but the face keeps the server's value). `onChange` gets the value, so with react-hook-form use a `Controller` (`render={({ field }) => <FilterSelect label="Plan" {...field} options={plans} />}`), not `register`. `label` is the filter's name and its accessible name; screen readers hear the chosen option as the value. The first option is the "all" choice: `allLabel` is the shorter word its face shows ("All" for "All statuses"). A long value ("Diamond Partnership") shows in full and the button moves to the next row instead of cutting it. Right to left, the list opens from the face's right edge.
@@ -675,11 +675,30 @@ window.Aura = (() => {
675
675
  }
676
676
  function emptyStateElement(props, ref) {
677
677
  const HT = "h" + (props.headingLevel || 3);
678
+ const rest = omit(props, [
679
+ "title",
680
+ "description",
681
+ "icon",
682
+ "action",
683
+ "size",
684
+ "bordered",
685
+ "headingLevel",
686
+ "tone",
687
+ "className",
688
+ "children"
689
+ ]);
678
690
  return /* @__PURE__ */ React4.createElement(
679
691
  "div",
680
692
  {
693
+ ...rest,
681
694
  ref,
682
- className: cx("aura-empty", props.size === "sm" && "is-sm", props.bordered && "is-bordered", props.className)
695
+ className: cx(
696
+ "aura-empty",
697
+ props.size === "sm" && "is-sm",
698
+ props.bordered && "is-bordered",
699
+ props.tone === "danger" && "is-danger",
700
+ props.className
701
+ )
683
702
  },
684
703
  /* @__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" })),
685
704
  /* @__PURE__ */ React4.createElement(HT, { className: "aura-empty__title" }, props.title),
@@ -4811,6 +4830,7 @@ window.Aura = (() => {
4811
4830
  [measure, levelShape]
4812
4831
  );
4813
4832
  const stacked = !!props.stackBelow && boxWidth[0] != null && below(boxWidth[0], props.stackBelow);
4833
+ const noCardSel = !!props.hideSelectionInCards && selectable;
4814
4834
  useIsoLayoutEffect(
4815
4835
  function() {
4816
4836
  if (measure && wrapRef.current) boxWidth[1](wrapRef.current.getBoundingClientRect().width);
@@ -4911,9 +4931,38 @@ window.Aura = (() => {
4911
4931
  const pillKey = (vis.filter(function(c, i) {
4912
4932
  return i > 0 && c.pill;
4913
4933
  })[0] || { key: "" }).key;
4914
- function cardPart(c, i) {
4915
- return i === 0 ? "title" : c.key === pillKey ? "pill" : c.actions ? "actions" : "field";
4934
+ const ownTitle = vis.some(function(c) {
4935
+ return c.card === "title";
4936
+ }), ownPill = vis.some(function(c) {
4937
+ return c.card === "pill";
4938
+ });
4939
+ let autoTitle = -1;
4940
+ if (!ownTitle) {
4941
+ for (let i = 0; i < vis.length; i++)
4942
+ if (!vis[i].card && (i === 0 || !vis[i].actions)) {
4943
+ autoTitle = i;
4944
+ break;
4945
+ }
4916
4946
  }
4947
+ function cardPart(c, i) {
4948
+ if (c.card) return c.card;
4949
+ if (i === autoTitle) return "title";
4950
+ if (c.key === pillKey && !ownPill) return "pill";
4951
+ return c.actions ? "actions" : "field";
4952
+ }
4953
+ const cardRank = {};
4954
+ if (vis.some(function(c) {
4955
+ return c.cardOrder != null;
4956
+ }))
4957
+ vis.map(function(c, i) {
4958
+ return { c, i, o: c.cardOrder != null ? c.cardOrder : i };
4959
+ }).filter(function(x) {
4960
+ return cardPart(x.c, x.i) === "field";
4961
+ }).sort(function(a, b) {
4962
+ return a.o - b.o || a.i - b.i;
4963
+ }).forEach(function(x, n3) {
4964
+ cardRank[x.c.key] = n3;
4965
+ });
4917
4966
  function cardAttrs(c, i) {
4918
4967
  const part = cardPart(c, i), lv = hideLevel(c);
4919
4968
  return {
@@ -4955,6 +5004,7 @@ window.Aura = (() => {
4955
5004
  s["--aura-cell-w"] = w + "px";
4956
5005
  }
4957
5006
  if (isPinned(c)) s["--aura-cell-left"] = "calc(var(--aura-space-6)" + selW + " + " + pinOffsets[c.key] + ")";
5007
+ if (cardRank[c.key] != null) s["--aura-card-order"] = String(5 + cardRank[c.key]);
4958
5008
  return s;
4959
5009
  }
4960
5010
  const sortCol = sort && sort.key ? byKey[sort.key] : void 0;
@@ -5095,9 +5145,37 @@ window.Aura = (() => {
5095
5145
  function colAt(ci) {
5096
5146
  return selectable ? ci === 0 ? null : vis[ci - 1] : vis[ci];
5097
5147
  }
5148
+ const cardHidden = [];
5149
+ for (let ci = 0; ci < nCols; ci++) {
5150
+ const col = colAt(ci);
5151
+ cardHidden.push(stacked && (col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel));
5152
+ }
5153
+ function nearestShown(c, dir, ok) {
5154
+ if (ok(c)) return c;
5155
+ for (let d = 1; d < nCols; d++) {
5156
+ const a = c + d * dir, b = c - d * dir;
5157
+ if (a >= 0 && a < nCols && ok(a)) return a;
5158
+ if (b >= 0 && b < nCols && ok(b)) return b;
5159
+ }
5160
+ return c;
5161
+ }
5162
+ const acShown = nearestShown(ac, 1, function(cc) {
5163
+ return !cardHidden[cc];
5164
+ });
5165
+ const lastFocus = React31.useRef(null);
5166
+ React31.useEffect(
5167
+ function() {
5168
+ const was = lastFocus.current, g = gridRef.current;
5169
+ if (!stacked || !was || !g || !g.contains(was) || was.getClientRects().length > 0) return;
5170
+ if (document.activeElement && document.activeElement !== document.body && document.activeElement !== was) return;
5171
+ const el = g.querySelector('[data-rc="' + Math.max(1, ar) + ":" + acShown + '"]');
5172
+ if (el && el.getClientRects().length > 0) el.focus();
5173
+ },
5174
+ [stacked]
5175
+ );
5098
5176
  function tabFor(r, c) {
5099
5177
  if (!activeRendered) return r === 0 && c === ac ? 0 : -1;
5100
- return r === ar && c === ac ? 0 : -1;
5178
+ return r === ar && c === acShown ? 0 : -1;
5101
5179
  }
5102
5180
  React31.useEffect(function() {
5103
5181
  const p = pending.current;
@@ -5121,26 +5199,17 @@ window.Aura = (() => {
5121
5199
  el.focus();
5122
5200
  }
5123
5201
  });
5124
- function focusCell(r, c) {
5202
+ function focusCell(r, c, dir) {
5125
5203
  r = Math.max(0, Math.min(r, lastR));
5126
5204
  c = Math.max(0, Math.min(c, nCols - 1));
5127
- if (stacked && r === 0 && nRows > 0 && !(selectable && c === 0)) r = 1;
5128
- if (gridRef.current && r === T && hasTotal) {
5205
+ if (stacked && r === 0 && nRows > 0 && (!(selectable && c === 0) || noCardSel)) r = 1;
5206
+ if (gridRef.current && (r === T && hasTotal || stacked)) {
5129
5207
  const shown2 = function(cc) {
5208
+ if (cardHidden[cc]) return false;
5130
5209
  const e = gridRef.current.querySelector('[data-rc="' + r + ":" + cc + '"]');
5131
5210
  return !!e && e.getClientRects().length > 0;
5132
5211
  };
5133
- if (!shown2(c))
5134
- for (let d = 1; d < nCols; d++) {
5135
- if (c + d < nCols && shown2(c + d)) {
5136
- c = c + d;
5137
- break;
5138
- }
5139
- if (c - d >= 0 && shown2(c - d)) {
5140
- c = c - d;
5141
- break;
5142
- }
5143
- }
5212
+ c = nearestShown(c, dir || 1, shown2);
5144
5213
  }
5145
5214
  activeState[1]({ r, c });
5146
5215
  pending.current = { r, c };
@@ -5400,7 +5469,7 @@ window.Aura = (() => {
5400
5469
  } else if (r === 0 && col && (e.altKey && k === "ArrowDown" || k === "ContextMenu" || e.shiftKey && k === "F10") && controls)
5401
5470
  openMenu("col", col.key, target, { r: 0, c });
5402
5471
  else if (k === "ArrowRight") focusCell(r, c + 1);
5403
- else if (k === "ArrowLeft") focusCell(r, c - 1);
5472
+ else if (k === "ArrowLeft") focusCell(r, c - 1, -1);
5404
5473
  else if (k === "ArrowDown") {
5405
5474
  if (r < lastR) focusCell(r + 1, c);
5406
5475
  else if (pageSize && page < pageCount && goPage(page + 1, { r: 1, c })) activeState[1]({ r: 1, c });
@@ -5408,7 +5477,7 @@ window.Aura = (() => {
5408
5477
  if (r > 1 || r === 1 && !(pageSize && page > 1)) focusCell(r - 1, c);
5409
5478
  else if (r === 1 && goPage(page - 1, { r: pageSize, c })) activeState[1]({ r: pageSize, c });
5410
5479
  } else if (k === "Home") focusCell(e.ctrlKey ? 1 : r, 0);
5411
- else if (k === "End") focusCell(e.ctrlKey ? lastR : r, nCols - 1);
5480
+ else if (k === "End") focusCell(e.ctrlKey ? lastR : r, nCols - 1, -1);
5412
5481
  else if (k === "PageDown") {
5413
5482
  if (pageSize) {
5414
5483
  if (goPage(page + 1, { r: 1, c })) activeState[1]({ r: 1, c });
@@ -5428,7 +5497,7 @@ window.Aura = (() => {
5428
5497
  if (pageKeys.length) toggleAll();
5429
5498
  } else if (r === 0 && col && col.sortable && canSortAny) sortBy(col.key);
5430
5499
  else if (r > 0 && k === " " && selectable) {
5431
- if (canSelect(row)) toggle(row[rowKey], !selSet[row[rowKey]]);
5500
+ if (canSelect(row) && !(stacked && noCardSel)) toggle(row[rowKey], !selSet[row[rowKey]]);
5432
5501
  } else if (r > 0 && k === "Enter" && rowHref && !target.querySelector("button, a[href]:not(.aura-table__row-link), input, select, textarea"))
5433
5502
  followRow(target.closest('[role="row"]'), e);
5434
5503
  else if (r > 0 && k === "Enter" && target.querySelector("button, a[href], input, select, textarea"))
@@ -5488,6 +5557,7 @@ window.Aura = (() => {
5488
5557
  "aria-colindex": ci + 1,
5489
5558
  style: cellStyle(c, i),
5490
5559
  "data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
5560
+ "data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
5491
5561
  tabIndex: tabFor(0, ci),
5492
5562
  "data-rc": "0:" + ci,
5493
5563
  className: cx(
@@ -5853,7 +5923,7 @@ window.Aura = (() => {
5853
5923
  ),
5854
5924
  style: cellStyle(c, j),
5855
5925
  ...cardAttrs(c, j),
5856
- "data-label": j === 0 ? void 0 : c.label || t.totals
5926
+ "data-label": cardPart(c, j) === "title" ? void 0 : c.label || t.totals
5857
5927
  },
5858
5928
  props.footer[c.key]
5859
5929
  );
@@ -5881,6 +5951,7 @@ window.Aura = (() => {
5881
5951
  className: cx(
5882
5952
  "aura-table",
5883
5953
  stacked && "aura-table--stacked",
5954
+ noCardSel && "aura-table--cards-nosel",
5884
5955
  scrolledX[0] && "is-scrolled-x",
5885
5956
  refreshing && "is-refreshing",
5886
5957
  !levels.length && props.className
@@ -5898,8 +5969,16 @@ window.Aura = (() => {
5898
5969
  className: "aura-table__scroll",
5899
5970
  onMouseOver: showFull,
5900
5971
  onMouseLeave: hideFull,
5901
- onFocus: showFull,
5902
- onBlur: hideFull,
5972
+ onFocus: function(e) {
5973
+ lastFocus.current = e.target;
5974
+ showFull(e);
5975
+ },
5976
+ onBlur: function(e) {
5977
+ const to = e.relatedTarget;
5978
+ if ((!to || !e.currentTarget.contains(to)) && e.target.getClientRects().length > 0)
5979
+ lastFocus.current = null;
5980
+ hideFull();
5981
+ },
5903
5982
  style: scrollStyle,
5904
5983
  role: "grid",
5905
5984
  "aria-label": props.label,
@@ -6704,7 +6783,7 @@ window.Aura = (() => {
6704
6783
  return out;
6705
6784
  }
6706
6785
  var Table = React44.forwardRef(function Table2(props, ref) {
6707
- const { caption, captionHidden, density, stackBelow, className, children, ...rest } = props;
6786
+ const { caption, captionHidden, density, stackBelow, align, bordered, className, children, ...rest } = props;
6708
6787
  const labels = stackBelow ? headerLabels(children) : null;
6709
6788
  if (labels && !labels.length)
6710
6789
  devWarnOnce(
@@ -6732,7 +6811,7 @@ window.Aura = (() => {
6732
6811
  "div",
6733
6812
  {
6734
6813
  ref: wrap,
6735
- className: cx("aura-tbl-wrap", stackBelow && "is-stackable"),
6814
+ className: cx("aura-tbl-wrap", stackBelow && "is-stackable", bordered === false && "is-flush"),
6736
6815
  "data-density": density,
6737
6816
  tabIndex: scrolls ? 0 : void 0,
6738
6817
  role: scrolls && (caption != null || rest["aria-label"]) ? "region" : void 0,
@@ -6743,7 +6822,12 @@ window.Aura = (() => {
6743
6822
  "table",
6744
6823
  {
6745
6824
  ref,
6746
- className: cx("aura-tbl", stackBelow && "aura-tbl--stack-" + stackBelow, className),
6825
+ className: cx(
6826
+ "aura-tbl",
6827
+ stackBelow && "aura-tbl--stack-" + stackBelow,
6828
+ align === "middle" && "aura-tbl--middle",
6829
+ className
6830
+ ),
6747
6831
  role: stackBelow ? "table" : void 0,
6748
6832
  ...rest
6749
6833
  },
@@ -6791,7 +6875,7 @@ window.Aura = (() => {
6791
6875
  );
6792
6876
  }
6793
6877
  var Th = React44.forwardRef(function Th2(props, ref) {
6794
- const { align, numeric, mono, className, scope, label, ...rest } = props;
6878
+ const { align, numeric, mono, className, scope, label, card, ...rest } = props;
6795
6879
  const stacked = React44.useContext(StackLabels) != null;
6796
6880
  return /* @__PURE__ */ React44.createElement(
6797
6881
  "th",
@@ -6800,14 +6884,16 @@ window.Aura = (() => {
6800
6884
  scope: scope || "col",
6801
6885
  className: cellClass("aura-tbl__th", props),
6802
6886
  role: stacked ? scope === "row" ? "rowheader" : "columnheader" : void 0,
6887
+ "data-card": stacked && (card === "title" || card === "action") ? card : void 0,
6803
6888
  ...rest
6804
6889
  }
6805
6890
  );
6806
6891
  });
6807
6892
  var Td = React44.forwardRef(function Td2(props, ref) {
6808
- const { align, numeric, mono, className, scope, label, ...rest } = props;
6893
+ const { align, numeric, mono, className, scope, label, card, ...rest } = props;
6809
6894
  const labels = React44.useContext(StackLabels), col = React44.useContext(ColumnIndex);
6810
- const shown = labels ? label != null ? label : col >= 0 ? labels[col] : void 0 : void 0;
6895
+ const slot = labels && (card === "title" || card === "action") ? card : void 0;
6896
+ const shown = labels && !slot ? label != null ? label : col >= 0 ? labels[col] : void 0 : void 0;
6811
6897
  return /* @__PURE__ */ React44.createElement(
6812
6898
  "td",
6813
6899
  {
@@ -6815,6 +6901,7 @@ window.Aura = (() => {
6815
6901
  className: cellClass("aura-tbl__td", props),
6816
6902
  role: labels ? "cell" : void 0,
6817
6903
  "data-label": shown || void 0,
6904
+ "data-card": slot,
6818
6905
  ...rest
6819
6906
  }
6820
6907
  );
@@ -657,11 +657,30 @@ function badgeElement(props, ref) {
657
657
  }
658
658
  function emptyStateElement(props, ref) {
659
659
  const HT = "h" + (props.headingLevel || 3);
660
+ const rest = omit(props, [
661
+ "title",
662
+ "description",
663
+ "icon",
664
+ "action",
665
+ "size",
666
+ "bordered",
667
+ "headingLevel",
668
+ "tone",
669
+ "className",
670
+ "children"
671
+ ]);
660
672
  return /* @__PURE__ */ React4.createElement(
661
673
  "div",
662
674
  {
675
+ ...rest,
663
676
  ref,
664
- className: cx("aura-empty", props.size === "sm" && "is-sm", props.bordered && "is-bordered", props.className)
677
+ className: cx(
678
+ "aura-empty",
679
+ props.size === "sm" && "is-sm",
680
+ props.bordered && "is-bordered",
681
+ props.tone === "danger" && "is-danger",
682
+ props.className
683
+ )
665
684
  },
666
685
  /* @__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" })),
667
686
  /* @__PURE__ */ React4.createElement(HT, { className: "aura-empty__title" }, props.title),
@@ -4793,6 +4812,7 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
4793
4812
  [measure, levelShape]
4794
4813
  );
4795
4814
  const stacked = !!props.stackBelow && boxWidth[0] != null && below(boxWidth[0], props.stackBelow);
4815
+ const noCardSel = !!props.hideSelectionInCards && selectable;
4796
4816
  useIsoLayoutEffect(
4797
4817
  function() {
4798
4818
  if (measure && wrapRef.current) boxWidth[1](wrapRef.current.getBoundingClientRect().width);
@@ -4893,9 +4913,38 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
4893
4913
  const pillKey = (vis.filter(function(c, i) {
4894
4914
  return i > 0 && c.pill;
4895
4915
  })[0] || { key: "" }).key;
4896
- function cardPart(c, i) {
4897
- return i === 0 ? "title" : c.key === pillKey ? "pill" : c.actions ? "actions" : "field";
4916
+ const ownTitle = vis.some(function(c) {
4917
+ return c.card === "title";
4918
+ }), ownPill = vis.some(function(c) {
4919
+ return c.card === "pill";
4920
+ });
4921
+ let autoTitle = -1;
4922
+ if (!ownTitle) {
4923
+ for (let i = 0; i < vis.length; i++)
4924
+ if (!vis[i].card && (i === 0 || !vis[i].actions)) {
4925
+ autoTitle = i;
4926
+ break;
4927
+ }
4898
4928
  }
4929
+ function cardPart(c, i) {
4930
+ if (c.card) return c.card;
4931
+ if (i === autoTitle) return "title";
4932
+ if (c.key === pillKey && !ownPill) return "pill";
4933
+ return c.actions ? "actions" : "field";
4934
+ }
4935
+ const cardRank = {};
4936
+ if (vis.some(function(c) {
4937
+ return c.cardOrder != null;
4938
+ }))
4939
+ vis.map(function(c, i) {
4940
+ return { c, i, o: c.cardOrder != null ? c.cardOrder : i };
4941
+ }).filter(function(x) {
4942
+ return cardPart(x.c, x.i) === "field";
4943
+ }).sort(function(a, b) {
4944
+ return a.o - b.o || a.i - b.i;
4945
+ }).forEach(function(x, n3) {
4946
+ cardRank[x.c.key] = n3;
4947
+ });
4899
4948
  function cardAttrs(c, i) {
4900
4949
  const part = cardPart(c, i), lv = hideLevel(c);
4901
4950
  return {
@@ -4937,6 +4986,7 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
4937
4986
  s["--aura-cell-w"] = w + "px";
4938
4987
  }
4939
4988
  if (isPinned(c)) s["--aura-cell-left"] = "calc(var(--aura-space-6)" + selW + " + " + pinOffsets[c.key] + ")";
4989
+ if (cardRank[c.key] != null) s["--aura-card-order"] = String(5 + cardRank[c.key]);
4940
4990
  return s;
4941
4991
  }
4942
4992
  const sortCol = sort && sort.key ? byKey[sort.key] : void 0;
@@ -5077,9 +5127,37 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
5077
5127
  function colAt(ci) {
5078
5128
  return selectable ? ci === 0 ? null : vis[ci - 1] : vis[ci];
5079
5129
  }
5130
+ const cardHidden = [];
5131
+ for (let ci = 0; ci < nCols; ci++) {
5132
+ const col = colAt(ci);
5133
+ cardHidden.push(stacked && (col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel));
5134
+ }
5135
+ function nearestShown(c, dir, ok) {
5136
+ if (ok(c)) return c;
5137
+ for (let d = 1; d < nCols; d++) {
5138
+ const a = c + d * dir, b = c - d * dir;
5139
+ if (a >= 0 && a < nCols && ok(a)) return a;
5140
+ if (b >= 0 && b < nCols && ok(b)) return b;
5141
+ }
5142
+ return c;
5143
+ }
5144
+ const acShown = nearestShown(ac, 1, function(cc) {
5145
+ return !cardHidden[cc];
5146
+ });
5147
+ const lastFocus = React31.useRef(null);
5148
+ React31.useEffect(
5149
+ function() {
5150
+ const was = lastFocus.current, g = gridRef.current;
5151
+ if (!stacked || !was || !g || !g.contains(was) || was.getClientRects().length > 0) return;
5152
+ if (document.activeElement && document.activeElement !== document.body && document.activeElement !== was) return;
5153
+ const el = g.querySelector('[data-rc="' + Math.max(1, ar) + ":" + acShown + '"]');
5154
+ if (el && el.getClientRects().length > 0) el.focus();
5155
+ },
5156
+ [stacked]
5157
+ );
5080
5158
  function tabFor(r, c) {
5081
5159
  if (!activeRendered) return r === 0 && c === ac ? 0 : -1;
5082
- return r === ar && c === ac ? 0 : -1;
5160
+ return r === ar && c === acShown ? 0 : -1;
5083
5161
  }
5084
5162
  React31.useEffect(function() {
5085
5163
  const p = pending.current;
@@ -5103,26 +5181,17 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
5103
5181
  el.focus();
5104
5182
  }
5105
5183
  });
5106
- function focusCell(r, c) {
5184
+ function focusCell(r, c, dir) {
5107
5185
  r = Math.max(0, Math.min(r, lastR));
5108
5186
  c = Math.max(0, Math.min(c, nCols - 1));
5109
- if (stacked && r === 0 && nRows > 0 && !(selectable && c === 0)) r = 1;
5110
- if (gridRef.current && r === T && hasTotal) {
5187
+ if (stacked && r === 0 && nRows > 0 && (!(selectable && c === 0) || noCardSel)) r = 1;
5188
+ if (gridRef.current && (r === T && hasTotal || stacked)) {
5111
5189
  const shown2 = function(cc) {
5190
+ if (cardHidden[cc]) return false;
5112
5191
  const e = gridRef.current.querySelector('[data-rc="' + r + ":" + cc + '"]');
5113
5192
  return !!e && e.getClientRects().length > 0;
5114
5193
  };
5115
- if (!shown2(c))
5116
- for (let d = 1; d < nCols; d++) {
5117
- if (c + d < nCols && shown2(c + d)) {
5118
- c = c + d;
5119
- break;
5120
- }
5121
- if (c - d >= 0 && shown2(c - d)) {
5122
- c = c - d;
5123
- break;
5124
- }
5125
- }
5194
+ c = nearestShown(c, dir || 1, shown2);
5126
5195
  }
5127
5196
  activeState[1]({ r, c });
5128
5197
  pending.current = { r, c };
@@ -5382,7 +5451,7 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
5382
5451
  } else if (r === 0 && col && (e.altKey && k === "ArrowDown" || k === "ContextMenu" || e.shiftKey && k === "F10") && controls)
5383
5452
  openMenu("col", col.key, target, { r: 0, c });
5384
5453
  else if (k === "ArrowRight") focusCell(r, c + 1);
5385
- else if (k === "ArrowLeft") focusCell(r, c - 1);
5454
+ else if (k === "ArrowLeft") focusCell(r, c - 1, -1);
5386
5455
  else if (k === "ArrowDown") {
5387
5456
  if (r < lastR) focusCell(r + 1, c);
5388
5457
  else if (pageSize && page < pageCount && goPage(page + 1, { r: 1, c })) activeState[1]({ r: 1, c });
@@ -5390,7 +5459,7 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
5390
5459
  if (r > 1 || r === 1 && !(pageSize && page > 1)) focusCell(r - 1, c);
5391
5460
  else if (r === 1 && goPage(page - 1, { r: pageSize, c })) activeState[1]({ r: pageSize, c });
5392
5461
  } else if (k === "Home") focusCell(e.ctrlKey ? 1 : r, 0);
5393
- else if (k === "End") focusCell(e.ctrlKey ? lastR : r, nCols - 1);
5462
+ else if (k === "End") focusCell(e.ctrlKey ? lastR : r, nCols - 1, -1);
5394
5463
  else if (k === "PageDown") {
5395
5464
  if (pageSize) {
5396
5465
  if (goPage(page + 1, { r: 1, c })) activeState[1]({ r: 1, c });
@@ -5410,7 +5479,7 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
5410
5479
  if (pageKeys.length) toggleAll();
5411
5480
  } else if (r === 0 && col && col.sortable && canSortAny) sortBy(col.key);
5412
5481
  else if (r > 0 && k === " " && selectable) {
5413
- if (canSelect(row)) toggle(row[rowKey], !selSet[row[rowKey]]);
5482
+ if (canSelect(row) && !(stacked && noCardSel)) toggle(row[rowKey], !selSet[row[rowKey]]);
5414
5483
  } else if (r > 0 && k === "Enter" && rowHref && !target.querySelector("button, a[href]:not(.aura-table__row-link), input, select, textarea"))
5415
5484
  followRow(target.closest('[role="row"]'), e);
5416
5485
  else if (r > 0 && k === "Enter" && target.querySelector("button, a[href], input, select, textarea"))
@@ -5470,6 +5539,7 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
5470
5539
  "aria-colindex": ci + 1,
5471
5540
  style: cellStyle(c, i),
5472
5541
  "data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
5542
+ "data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
5473
5543
  tabIndex: tabFor(0, ci),
5474
5544
  "data-rc": "0:" + ci,
5475
5545
  className: cx(
@@ -5835,7 +5905,7 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
5835
5905
  ),
5836
5906
  style: cellStyle(c, j),
5837
5907
  ...cardAttrs(c, j),
5838
- "data-label": j === 0 ? void 0 : c.label || t.totals
5908
+ "data-label": cardPart(c, j) === "title" ? void 0 : c.label || t.totals
5839
5909
  },
5840
5910
  props.footer[c.key]
5841
5911
  );
@@ -5863,6 +5933,7 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
5863
5933
  className: cx(
5864
5934
  "aura-table",
5865
5935
  stacked && "aura-table--stacked",
5936
+ noCardSel && "aura-table--cards-nosel",
5866
5937
  scrolledX[0] && "is-scrolled-x",
5867
5938
  refreshing && "is-refreshing",
5868
5939
  !levels.length && props.className
@@ -5880,8 +5951,16 @@ var DataTableImpl = React31.forwardRef(function DataTable(props, ref) {
5880
5951
  className: "aura-table__scroll",
5881
5952
  onMouseOver: showFull,
5882
5953
  onMouseLeave: hideFull,
5883
- onFocus: showFull,
5884
- onBlur: hideFull,
5954
+ onFocus: function(e) {
5955
+ lastFocus.current = e.target;
5956
+ showFull(e);
5957
+ },
5958
+ onBlur: function(e) {
5959
+ const to = e.relatedTarget;
5960
+ if ((!to || !e.currentTarget.contains(to)) && e.target.getClientRects().length > 0)
5961
+ lastFocus.current = null;
5962
+ hideFull();
5963
+ },
5885
5964
  style: scrollStyle,
5886
5965
  role: "grid",
5887
5966
  "aria-label": props.label,
@@ -6686,7 +6765,7 @@ function headerLabels(children) {
6686
6765
  return out;
6687
6766
  }
6688
6767
  var Table = React44.forwardRef(function Table2(props, ref) {
6689
- const { caption, captionHidden, density, stackBelow, className, children, ...rest } = props;
6768
+ const { caption, captionHidden, density, stackBelow, align, bordered, className, children, ...rest } = props;
6690
6769
  const labels = stackBelow ? headerLabels(children) : null;
6691
6770
  if (labels && !labels.length)
6692
6771
  devWarnOnce(
@@ -6714,7 +6793,7 @@ var Table = React44.forwardRef(function Table2(props, ref) {
6714
6793
  "div",
6715
6794
  {
6716
6795
  ref: wrap,
6717
- className: cx("aura-tbl-wrap", stackBelow && "is-stackable"),
6796
+ className: cx("aura-tbl-wrap", stackBelow && "is-stackable", bordered === false && "is-flush"),
6718
6797
  "data-density": density,
6719
6798
  tabIndex: scrolls ? 0 : void 0,
6720
6799
  role: scrolls && (caption != null || rest["aria-label"]) ? "region" : void 0,
@@ -6725,7 +6804,12 @@ var Table = React44.forwardRef(function Table2(props, ref) {
6725
6804
  "table",
6726
6805
  {
6727
6806
  ref,
6728
- className: cx("aura-tbl", stackBelow && "aura-tbl--stack-" + stackBelow, className),
6807
+ className: cx(
6808
+ "aura-tbl",
6809
+ stackBelow && "aura-tbl--stack-" + stackBelow,
6810
+ align === "middle" && "aura-tbl--middle",
6811
+ className
6812
+ ),
6729
6813
  role: stackBelow ? "table" : void 0,
6730
6814
  ...rest
6731
6815
  },
@@ -6773,7 +6857,7 @@ function cellClass(base, p) {
6773
6857
  );
6774
6858
  }
6775
6859
  var Th = React44.forwardRef(function Th2(props, ref) {
6776
- const { align, numeric, mono, className, scope, label, ...rest } = props;
6860
+ const { align, numeric, mono, className, scope, label, card, ...rest } = props;
6777
6861
  const stacked = React44.useContext(StackLabels) != null;
6778
6862
  return /* @__PURE__ */ React44.createElement(
6779
6863
  "th",
@@ -6782,14 +6866,16 @@ var Th = React44.forwardRef(function Th2(props, ref) {
6782
6866
  scope: scope || "col",
6783
6867
  className: cellClass("aura-tbl__th", props),
6784
6868
  role: stacked ? scope === "row" ? "rowheader" : "columnheader" : void 0,
6869
+ "data-card": stacked && (card === "title" || card === "action") ? card : void 0,
6785
6870
  ...rest
6786
6871
  }
6787
6872
  );
6788
6873
  });
6789
6874
  var Td = React44.forwardRef(function Td2(props, ref) {
6790
- const { align, numeric, mono, className, scope, label, ...rest } = props;
6875
+ const { align, numeric, mono, className, scope, label, card, ...rest } = props;
6791
6876
  const labels = React44.useContext(StackLabels), col = React44.useContext(ColumnIndex);
6792
- const shown = labels ? label != null ? label : col >= 0 ? labels[col] : void 0 : void 0;
6877
+ const slot = labels && (card === "title" || card === "action") ? card : void 0;
6878
+ const shown = labels && !slot ? label != null ? label : col >= 0 ? labels[col] : void 0 : void 0;
6793
6879
  return /* @__PURE__ */ React44.createElement(
6794
6880
  "td",
6795
6881
  {
@@ -6797,6 +6883,7 @@ var Td = React44.forwardRef(function Td2(props, ref) {
6797
6883
  className: cellClass("aura-tbl__td", props),
6798
6884
  role: labels ? "cell" : void 0,
6799
6885
  "data-label": shown || void 0,
6886
+ "data-card": slot,
6800
6887
  ...rest
6801
6888
  }
6802
6889
  );