@jirawatpyk/aura-react 5.83.0 → 5.85.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,14 @@ 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.85 — Chamber-OS 198 (DataTable columns for the cards only)
252
+
253
+ - **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.
254
+
255
+ ## 5.84 — Chamber-OS 197 (cursor Pagination without Previous)
256
+
257
+ - **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`.
258
+
251
259
  ## 5.83 — Chamber-OS 195–196 (Combobox announcements, Alert dismissLabel)
252
260
 
253
261
  - **Combobox status region** (#195): one `role="status"` region is part of the field for its whole life (beside the input, so inside a Dialog too, where the portaled list sits outside the modal) and only its text changes. Closed: empty. Open: the loading text, then the empty text or — with `onSearch`, once a search has come back (`loading` back to `false` after the person typed) — the result count ("12 results", the `results` string in EN, TH, SV). The count needs a managed `loading` prop. An `onSearch` field says nothing before the person types (an empty server list doesn't say "No matches" on open). Without `onSearch`, "no matches" and "keep typing" are the same words as before, now announced reliably. A region inserted already holding text is often not announced (NVDA, VoiceOver), which is why the old line was mostly silent. The visible note is unchanged and hidden from screen readers, which hear the region. A test that finds the note by its words (`getByText('No matches')`) now matches the region too: scope it to `.aura-combo__note`, or use `getByRole('status')`.
@@ -6135,7 +6135,7 @@ window.Aura = (() => {
6135
6135
  return w < threshold * (1 - 0.5 / Q);
6136
6136
  }
6137
6137
  function hidePx(c) {
6138
- if (c.hideBelow == null) return void 0;
6138
+ if (c.hideBelow == null || c.grid === false) return void 0;
6139
6139
  const px = typeof c.hideBelow === "number" ? c.hideBelow : BP[c.hideBelow];
6140
6140
  return px != null && px > 0 ? px : void 0;
6141
6141
  }
@@ -6390,10 +6390,16 @@ window.Aura = (() => {
6390
6390
  }).map(function(k) {
6391
6391
  return byKey[k];
6392
6392
  }).filter(function(c) {
6393
- return !tooNarrow(c);
6393
+ return !tooNarrow(c) && (c.grid !== false || !!props.stackBelow);
6394
6394
  });
6395
+ const hasCardOnly = shown.some(function(c) {
6396
+ return c.grid === false;
6397
+ });
6398
+ const gridShown = shown.filter(function(c) {
6399
+ return c.grid !== false;
6400
+ }).length;
6395
6401
  function isPinned(c) {
6396
- return pinnedKeys.indexOf(c.key) >= 0 && c.width != null;
6402
+ return pinnedKeys.indexOf(c.key) >= 0 && c.width != null && c.grid !== false;
6397
6403
  }
6398
6404
  const vis = shown.filter(isPinned).concat(
6399
6405
  shown.filter(function(c) {
@@ -6441,7 +6447,8 @@ window.Aura = (() => {
6441
6447
  return {
6442
6448
  "data-card": part,
6443
6449
  "data-label": part === "field" || part === "wide" ? c.label || void 0 : void 0,
6444
- "data-hide": lv ? String(lv) : void 0
6450
+ "data-hide": lv ? String(lv) : void 0,
6451
+ "data-grid": c.grid === false ? "off" : void 0
6445
6452
  };
6446
6453
  }
6447
6454
  const hasFields = vis.some(function(c, i) {
@@ -6449,10 +6456,13 @@ window.Aura = (() => {
6449
6456
  return p === "field" || p === "wide";
6450
6457
  });
6451
6458
  const hasFlex = vis.some(function(c) {
6452
- return widthOf2(c) == null;
6459
+ return widthOf2(c) == null && c.grid !== false;
6453
6460
  });
6461
+ let lastGridCol = vis.length - 1;
6462
+ while (lastGridCol > 0 && vis[lastGridCol].grid === false) lastGridCol--;
6454
6463
  let fixedSum = 0, hideTerms = "";
6455
6464
  vis.forEach(function(c) {
6465
+ if (c.grid === false) return;
6456
6466
  const w = widthOf2(c) != null ? widthOf2(c) : c.minWidth || FLEX_MIN, lv = hideLevel(c);
6457
6467
  if (lv && boxWidth[0] == null) hideTerms += " + " + w + "px * var(--aura-h" + lv + "-on, 1)";
6458
6468
  else fixedSum += w;
@@ -6482,7 +6492,7 @@ window.Aura = (() => {
6482
6492
  s["--aura-cell-flex"] = g + " 1 0";
6483
6493
  s["--aura-cell-min"] = (c.minWidth || FLEX_MIN) + "px";
6484
6494
  } else {
6485
- s["--aura-cell-flex"] = !hasFlex && i === vis.length - 1 ? "1 0 auto" : "none";
6495
+ s["--aura-cell-flex"] = !hasFlex && i === lastGridCol ? "1 0 auto" : "none";
6486
6496
  s["--aura-cell-w"] = w + "px";
6487
6497
  }
6488
6498
  if (isPinned(c)) s["--aura-cell-left"] = "calc(var(--aura-space-6)" + selW + " + " + pinOffsets[c.key] + ")";
@@ -6631,7 +6641,12 @@ window.Aura = (() => {
6631
6641
  const cardHidden = [];
6632
6642
  for (let ci = 0; ci < nCols; ci++) {
6633
6643
  const col = colAt(ci);
6634
- cardHidden.push(stacked && (col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel));
6644
+ cardHidden.push(
6645
+ stacked ? col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel : (
6646
+ /* before the first measure the layout is CSS's: the DOM check below decides */
6647
+ boxWidth[0] != null && !!col && col.grid === false
6648
+ )
6649
+ );
6635
6650
  }
6636
6651
  function nearestShown(c, dir, ok) {
6637
6652
  if (ok(c)) return c;
@@ -6692,7 +6707,7 @@ window.Aura = (() => {
6692
6707
  r2 = Math.max(0, Math.min(r2, lastR));
6693
6708
  c = Math.max(0, Math.min(c, nCols - 1));
6694
6709
  if (stacked && r2 === 0 && nRows > 0 && (!(selectable && c === 0) || noCardSel)) r2 = 1;
6695
- if (gridRef.current && (r2 === T && hasTotal || stacked)) {
6710
+ if (gridRef.current && (r2 === T && hasTotal || stacked || hasCardOnly)) {
6696
6711
  const shown2 = function(cc) {
6697
6712
  if (cardHidden[cc]) return false;
6698
6713
  const e = gridRef.current.querySelector('[data-rc="' + r2 + ":" + cc + '"]');
@@ -6819,8 +6834,9 @@ window.Aura = (() => {
6819
6834
  window.addEventListener("pointerup", up2);
6820
6835
  }
6821
6836
  function moveCol(key, delta) {
6837
+ if (byKey[key] && byKey[key].grid === false) return false;
6822
6838
  const c = byKey[key], group = vis.filter(function(x) {
6823
- return isPinned(x) === isPinned(c);
6839
+ return isPinned(x) === isPinned(c) && x.grid !== false;
6824
6840
  });
6825
6841
  const gi = group.indexOf(c), target = group[gi + delta];
6826
6842
  if (!target) return false;
@@ -6879,7 +6895,7 @@ window.Aura = (() => {
6879
6895
  }
6880
6896
  function columnMenuItems(c) {
6881
6897
  const group = vis.filter(function(x) {
6882
- return isPinned(x) === isPinned(c);
6898
+ return isPinned(x) === isPinned(c) && x.grid !== false;
6883
6899
  }), gi = group.indexOf(c);
6884
6900
  const items2 = [];
6885
6901
  if (c.sortable)
@@ -6932,7 +6948,7 @@ window.Aura = (() => {
6932
6948
  {
6933
6949
  label: t.hideColumn,
6934
6950
  icon: /* @__PURE__ */ React34.createElement(IconEyeOff, null),
6935
- disabled: shown.length <= 1,
6951
+ disabled: gridShown <= 1,
6936
6952
  onSelect: function() {
6937
6953
  setHidden(c.key, true);
6938
6954
  }
@@ -6941,13 +6957,15 @@ window.Aura = (() => {
6941
6957
  return items2;
6942
6958
  }
6943
6959
  function pickerItems() {
6944
- return order.map(function(k) {
6960
+ return order.filter(function(k) {
6961
+ return byKey[k].grid !== false;
6962
+ }).map(function(k) {
6945
6963
  const c = byKey[k], on = hidden.indexOf(k) < 0;
6946
6964
  return {
6947
6965
  label: c.label || (c.actions ? t.actions : c.key),
6948
6966
  checked: on,
6949
6967
  keepOpen: true,
6950
- disabled: on && shown.length <= 1,
6968
+ disabled: on && gridShown <= 1,
6951
6969
  onSelect: function() {
6952
6970
  setHidden(k, on);
6953
6971
  }
@@ -7079,6 +7097,7 @@ window.Aura = (() => {
7079
7097
  style: cellStyle(c, i),
7080
7098
  "data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
7081
7099
  "data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
7100
+ "data-grid": c.grid === false ? "off" : void 0,
7082
7101
  tabIndex: tabFor(0, ci),
7083
7102
  "data-rc": "0:" + ci,
7084
7103
  className: cx(
@@ -10948,7 +10967,7 @@ window.Aura = (() => {
10948
10967
  "aria-label": props.label || t.pagination
10949
10968
  },
10950
10969
  props.status != null && props.status !== false && props.status !== "" ? /* @__PURE__ */ React65.createElement("span", { className: "aura-pagination__status" }, props.status) : null,
10951
- /* @__PURE__ */ React65.createElement("span", { className: "aura-pagination__steps" }, props.showFirst === false ? null : step("first", props.firstHref, props.onFirst, props.hasFirst, t.firstPage, void 0, null, false), step(
10970
+ /* @__PURE__ */ React65.createElement("span", { className: "aura-pagination__steps" }, props.showFirst === false ? null : step("first", props.firstHref, props.onFirst, props.hasFirst, t.firstPage, void 0, null, false), props.showPrevious === false ? null : step(
10952
10971
  "prev",
10953
10972
  props.previousHref,
10954
10973
  props.onPrevious,
@@ -6117,7 +6117,7 @@ function below(w, threshold) {
6117
6117
  return w < threshold * (1 - 0.5 / Q);
6118
6118
  }
6119
6119
  function hidePx(c) {
6120
- if (c.hideBelow == null) return void 0;
6120
+ if (c.hideBelow == null || c.grid === false) return void 0;
6121
6121
  const px = typeof c.hideBelow === "number" ? c.hideBelow : BP[c.hideBelow];
6122
6122
  return px != null && px > 0 ? px : void 0;
6123
6123
  }
@@ -6372,10 +6372,16 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6372
6372
  }).map(function(k) {
6373
6373
  return byKey[k];
6374
6374
  }).filter(function(c) {
6375
- return !tooNarrow(c);
6375
+ return !tooNarrow(c) && (c.grid !== false || !!props.stackBelow);
6376
6376
  });
6377
+ const hasCardOnly = shown.some(function(c) {
6378
+ return c.grid === false;
6379
+ });
6380
+ const gridShown = shown.filter(function(c) {
6381
+ return c.grid !== false;
6382
+ }).length;
6377
6383
  function isPinned(c) {
6378
- return pinnedKeys.indexOf(c.key) >= 0 && c.width != null;
6384
+ return pinnedKeys.indexOf(c.key) >= 0 && c.width != null && c.grid !== false;
6379
6385
  }
6380
6386
  const vis = shown.filter(isPinned).concat(
6381
6387
  shown.filter(function(c) {
@@ -6423,7 +6429,8 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6423
6429
  return {
6424
6430
  "data-card": part,
6425
6431
  "data-label": part === "field" || part === "wide" ? c.label || void 0 : void 0,
6426
- "data-hide": lv ? String(lv) : void 0
6432
+ "data-hide": lv ? String(lv) : void 0,
6433
+ "data-grid": c.grid === false ? "off" : void 0
6427
6434
  };
6428
6435
  }
6429
6436
  const hasFields = vis.some(function(c, i) {
@@ -6431,10 +6438,13 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6431
6438
  return p === "field" || p === "wide";
6432
6439
  });
6433
6440
  const hasFlex = vis.some(function(c) {
6434
- return widthOf2(c) == null;
6441
+ return widthOf2(c) == null && c.grid !== false;
6435
6442
  });
6443
+ let lastGridCol = vis.length - 1;
6444
+ while (lastGridCol > 0 && vis[lastGridCol].grid === false) lastGridCol--;
6436
6445
  let fixedSum = 0, hideTerms = "";
6437
6446
  vis.forEach(function(c) {
6447
+ if (c.grid === false) return;
6438
6448
  const w = widthOf2(c) != null ? widthOf2(c) : c.minWidth || FLEX_MIN, lv = hideLevel(c);
6439
6449
  if (lv && boxWidth[0] == null) hideTerms += " + " + w + "px * var(--aura-h" + lv + "-on, 1)";
6440
6450
  else fixedSum += w;
@@ -6464,7 +6474,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6464
6474
  s["--aura-cell-flex"] = g + " 1 0";
6465
6475
  s["--aura-cell-min"] = (c.minWidth || FLEX_MIN) + "px";
6466
6476
  } else {
6467
- s["--aura-cell-flex"] = !hasFlex && i === vis.length - 1 ? "1 0 auto" : "none";
6477
+ s["--aura-cell-flex"] = !hasFlex && i === lastGridCol ? "1 0 auto" : "none";
6468
6478
  s["--aura-cell-w"] = w + "px";
6469
6479
  }
6470
6480
  if (isPinned(c)) s["--aura-cell-left"] = "calc(var(--aura-space-6)" + selW + " + " + pinOffsets[c.key] + ")";
@@ -6613,7 +6623,12 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6613
6623
  const cardHidden = [];
6614
6624
  for (let ci = 0; ci < nCols; ci++) {
6615
6625
  const col = colAt(ci);
6616
- cardHidden.push(stacked && (col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel));
6626
+ cardHidden.push(
6627
+ stacked ? col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel : (
6628
+ /* before the first measure the layout is CSS's: the DOM check below decides */
6629
+ boxWidth[0] != null && !!col && col.grid === false
6630
+ )
6631
+ );
6617
6632
  }
6618
6633
  function nearestShown(c, dir, ok) {
6619
6634
  if (ok(c)) return c;
@@ -6674,7 +6689,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6674
6689
  r2 = Math.max(0, Math.min(r2, lastR));
6675
6690
  c = Math.max(0, Math.min(c, nCols - 1));
6676
6691
  if (stacked && r2 === 0 && nRows > 0 && (!(selectable && c === 0) || noCardSel)) r2 = 1;
6677
- if (gridRef.current && (r2 === T && hasTotal || stacked)) {
6692
+ if (gridRef.current && (r2 === T && hasTotal || stacked || hasCardOnly)) {
6678
6693
  const shown2 = function(cc) {
6679
6694
  if (cardHidden[cc]) return false;
6680
6695
  const e = gridRef.current.querySelector('[data-rc="' + r2 + ":" + cc + '"]');
@@ -6801,8 +6816,9 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6801
6816
  window.addEventListener("pointerup", up2);
6802
6817
  }
6803
6818
  function moveCol(key, delta) {
6819
+ if (byKey[key] && byKey[key].grid === false) return false;
6804
6820
  const c = byKey[key], group = vis.filter(function(x) {
6805
- return isPinned(x) === isPinned(c);
6821
+ return isPinned(x) === isPinned(c) && x.grid !== false;
6806
6822
  });
6807
6823
  const gi = group.indexOf(c), target = group[gi + delta];
6808
6824
  if (!target) return false;
@@ -6861,7 +6877,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6861
6877
  }
6862
6878
  function columnMenuItems(c) {
6863
6879
  const group = vis.filter(function(x) {
6864
- return isPinned(x) === isPinned(c);
6880
+ return isPinned(x) === isPinned(c) && x.grid !== false;
6865
6881
  }), gi = group.indexOf(c);
6866
6882
  const items2 = [];
6867
6883
  if (c.sortable)
@@ -6914,7 +6930,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6914
6930
  {
6915
6931
  label: t.hideColumn,
6916
6932
  icon: /* @__PURE__ */ React34.createElement(IconEyeOff, null),
6917
- disabled: shown.length <= 1,
6933
+ disabled: gridShown <= 1,
6918
6934
  onSelect: function() {
6919
6935
  setHidden(c.key, true);
6920
6936
  }
@@ -6923,13 +6939,15 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
6923
6939
  return items2;
6924
6940
  }
6925
6941
  function pickerItems() {
6926
- return order.map(function(k) {
6942
+ return order.filter(function(k) {
6943
+ return byKey[k].grid !== false;
6944
+ }).map(function(k) {
6927
6945
  const c = byKey[k], on = hidden.indexOf(k) < 0;
6928
6946
  return {
6929
6947
  label: c.label || (c.actions ? t.actions : c.key),
6930
6948
  checked: on,
6931
6949
  keepOpen: true,
6932
- disabled: on && shown.length <= 1,
6950
+ disabled: on && gridShown <= 1,
6933
6951
  onSelect: function() {
6934
6952
  setHidden(k, on);
6935
6953
  }
@@ -7061,6 +7079,7 @@ var DataTableImpl = React34.forwardRef(function DataTable(props, ref) {
7061
7079
  style: cellStyle(c, i),
7062
7080
  "data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
7063
7081
  "data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
7082
+ "data-grid": c.grid === false ? "off" : void 0,
7064
7083
  tabIndex: tabFor(0, ci),
7065
7084
  "data-rc": "0:" + ci,
7066
7085
  className: cx(
@@ -10930,7 +10949,7 @@ function cursorNav(props, ref, Link, t) {
10930
10949
  "aria-label": props.label || t.pagination
10931
10950
  },
10932
10951
  props.status != null && props.status !== false && props.status !== "" ? /* @__PURE__ */ React65.createElement("span", { className: "aura-pagination__status" }, props.status) : null,
10933
- /* @__PURE__ */ React65.createElement("span", { className: "aura-pagination__steps" }, props.showFirst === false ? null : step("first", props.firstHref, props.onFirst, props.hasFirst, t.firstPage, void 0, null, false), step(
10952
+ /* @__PURE__ */ React65.createElement("span", { className: "aura-pagination__steps" }, props.showFirst === false ? null : step("first", props.firstHref, props.onFirst, props.hasFirst, t.firstPage, void 0, null, false), props.showPrevious === false ? null : step(
10934
10953
  "prev",
10935
10954
  props.previousHref,
10936
10955
  props.onPrevious,
@@ -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] + ")";
@@ -553,7 +563,12 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
553
563
  const cardHidden = [];
554
564
  for (let ci = 0; ci < nCols; ci++) {
555
565
  const col = colAt(ci);
556
- cardHidden.push(stacked && (col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel));
566
+ cardHidden.push(
567
+ stacked ? col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel : (
568
+ /* before the first measure the layout is CSS's: the DOM check below decides */
569
+ boxWidth[0] != null && !!col && col.grid === false
570
+ )
571
+ );
557
572
  }
558
573
  function nearestShown(c, dir, ok) {
559
574
  if (ok(c)) return c;
@@ -614,7 +629,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
614
629
  r = Math.max(0, Math.min(r, lastR));
615
630
  c = Math.max(0, Math.min(c, nCols - 1));
616
631
  if (stacked && r === 0 && nRows > 0 && (!(selectable && c === 0) || noCardSel)) r = 1;
617
- if (gridRef.current && (r === T && hasTotal || stacked)) {
632
+ if (gridRef.current && (r === T && hasTotal || stacked || hasCardOnly)) {
618
633
  const shown2 = function(cc) {
619
634
  if (cardHidden[cc]) return false;
620
635
  const e = gridRef.current.querySelector('[data-rc="' + r + ":" + cc + '"]');
@@ -741,8 +756,9 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
741
756
  window.addEventListener("pointerup", up);
742
757
  }
743
758
  function moveCol(key, delta) {
759
+ if (byKey[key] && byKey[key].grid === false) return false;
744
760
  const c = byKey[key], group = vis.filter(function(x) {
745
- return isPinned(x) === isPinned(c);
761
+ return isPinned(x) === isPinned(c) && x.grid !== false;
746
762
  });
747
763
  const gi = group.indexOf(c), target = group[gi + delta];
748
764
  if (!target) return false;
@@ -801,7 +817,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
801
817
  }
802
818
  function columnMenuItems(c) {
803
819
  const group = vis.filter(function(x) {
804
- return isPinned(x) === isPinned(c);
820
+ return isPinned(x) === isPinned(c) && x.grid !== false;
805
821
  }), gi = group.indexOf(c);
806
822
  const items = [];
807
823
  if (c.sortable)
@@ -854,7 +870,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
854
870
  {
855
871
  label: t.hideColumn,
856
872
  icon: /* @__PURE__ */ React.createElement(IconEyeOff, null),
857
- disabled: shown.length <= 1,
873
+ disabled: gridShown <= 1,
858
874
  onSelect: function() {
859
875
  setHidden(c.key, true);
860
876
  }
@@ -863,13 +879,15 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
863
879
  return items;
864
880
  }
865
881
  function pickerItems() {
866
- return order.map(function(k) {
882
+ return order.filter(function(k) {
883
+ return byKey[k].grid !== false;
884
+ }).map(function(k) {
867
885
  const c = byKey[k], on = hidden.indexOf(k) < 0;
868
886
  return {
869
887
  label: c.label || (c.actions ? t.actions : c.key),
870
888
  checked: on,
871
889
  keepOpen: true,
872
- disabled: on && shown.length <= 1,
890
+ disabled: on && gridShown <= 1,
873
891
  onSelect: function() {
874
892
  setHidden(k, on);
875
893
  }
@@ -1001,6 +1019,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
1001
1019
  style: cellStyle(c, i),
1002
1020
  "data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
1003
1021
  "data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
1022
+ "data-grid": c.grid === false ? "off" : void 0,
1004
1023
  tabIndex: tabFor(0, ci),
1005
1024
  "data-rc": "0:" + ci,
1006
1025
  className: cx(
@@ -59,7 +59,7 @@ function cursorNav(props, ref, Link, t) {
59
59
  "aria-label": props.label || t.pagination
60
60
  },
61
61
  props.status != null && props.status !== false && props.status !== "" ? /* @__PURE__ */ React.createElement("span", { className: "aura-pagination__status" }, props.status) : null,
62
- /* @__PURE__ */ React.createElement("span", { className: "aura-pagination__steps" }, props.showFirst === false ? null : step("first", props.firstHref, props.onFirst, props.hasFirst, t.firstPage, void 0, null, false), step(
62
+ /* @__PURE__ */ React.createElement("span", { className: "aura-pagination__steps" }, props.showFirst === false ? null : step("first", props.firstHref, props.onFirst, props.hasFirst, t.firstPage, void 0, null, false), props.showPrevious === false ? null : step(
63
63
  "prev",
64
64
  props.previousHref,
65
65
  props.onPrevious,
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. */
@@ -1820,6 +1826,9 @@ export interface CursorPaginationProps {
1820
1826
  hasNext?: boolean | undefined;
1821
1827
  /** Default true. `false` leaves the First link out (a list that only goes forward). */
1822
1828
  showFirst?: boolean | undefined;
1829
+ /** 5.84 (Chamber-OS 197): default true. `false` leaves Previous out entirely — for a list that only goes forward
1830
+ * (keyset, newest first), where a disabled Previous could never become live. */
1831
+ showPrevious?: boolean | undefined;
1823
1832
  /** A line at the start, e.g. "Showing 50 of 1,240". Not a live region. */
1824
1833
  status?: React$1.ReactNode | undefined;
1825
1834
  /** Name of the nav. Default "Pagination". */
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. */
@@ -1820,6 +1826,9 @@ export interface CursorPaginationProps {
1820
1826
  hasNext?: boolean | undefined;
1821
1827
  /** Default true. `false` leaves the First link out (a list that only goes forward). */
1822
1828
  showFirst?: boolean | undefined;
1829
+ /** 5.84 (Chamber-OS 197): default true. `false` leaves Previous out entirely — for a list that only goes forward
1830
+ * (keyset, newest first), where a disabled Previous could never become live. */
1831
+ showPrevious?: boolean | undefined;
1823
1832
  /** A line at the start, e.g. "Showing 50 of 1,240". Not a live region. */
1824
1833
  status?: React$1.ReactNode | undefined;
1825
1834
  /** Name of the nav. Default "Pagination". */
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.83.0",
3
+ "version": "5.85.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",