efficient-shell 4.132.0 → 4.134.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.
Files changed (111) hide show
  1. package/README.md +62 -12
  2. package/dist/{Browser-XPVJ2K7B.js → Browser-O3QZGUF2.js} +11 -11
  3. package/dist/{Browser-XPVJ2K7B.js.map → Browser-O3QZGUF2.js.map} +1 -1
  4. package/dist/{Calculator-ZXJPXG7F.js → Calculator-L6N5X3KU.js} +9 -9
  5. package/dist/{Calculator-ZXJPXG7F.js.map → Calculator-L6N5X3KU.js.map} +1 -1
  6. package/dist/ConfirmDialog-LYSSZSUD.js +4 -0
  7. package/dist/{ConfirmDialog-MTC7QMUJ.js.map → ConfirmDialog-LYSSZSUD.js.map} +1 -1
  8. package/dist/{CurrencyConverter-WSJ2BBSX.js → CurrencyConverter-64MKXB3D.js} +9 -9
  9. package/dist/{CurrencyConverter-WSJ2BBSX.js.map → CurrencyConverter-64MKXB3D.js.map} +1 -1
  10. package/dist/{Documents-ONGSXUJI.js → Documents-5WXXYCLI.js} +11 -11
  11. package/dist/{Documents-ONGSXUJI.js.map → Documents-5WXXYCLI.js.map} +1 -1
  12. package/dist/{Files-GQZMFWXQ.js → Files-AUURUUDN.js} +17 -17
  13. package/dist/{Files-GQZMFWXQ.js.map → Files-AUURUUDN.js.map} +1 -1
  14. package/dist/{Notepad-HM73XAM4.js → Notepad-GPXJVPB7.js} +12 -12
  15. package/dist/{Notepad-HM73XAM4.js.map → Notepad-GPXJVPB7.js.map} +1 -1
  16. package/dist/PdfViewer-HKO6P4SR.js +5 -0
  17. package/dist/{PdfViewer-M2YGZIYX.js.map → PdfViewer-HKO6P4SR.js.map} +1 -1
  18. package/dist/{PomodoroTimer-DG3LI5CX.js → PomodoroTimer-4TQBWLP2.js} +11 -11
  19. package/dist/{PomodoroTimer-DG3LI5CX.js.map → PomodoroTimer-4TQBWLP2.js.map} +1 -1
  20. package/dist/{Preview-TUSV4UMO.js → Preview-FOZYPKM2.js} +14 -14
  21. package/dist/{Preview-TUSV4UMO.js.map → Preview-FOZYPKM2.js.map} +1 -1
  22. package/dist/{Spreadsheet-3WTXCHYQ.js → Spreadsheet-3C66BBBF.js} +12 -12
  23. package/dist/{Spreadsheet-3WTXCHYQ.js.map → Spreadsheet-3C66BBBF.js.map} +1 -1
  24. package/dist/{Stock-YMPOMUAW.js → Stock-IF4IHYLU.js} +9 -9
  25. package/dist/{Stock-YMPOMUAW.js.map → Stock-IF4IHYLU.js.map} +1 -1
  26. package/dist/{Weather-NZO3CWLH.js → Weather-725PFR7T.js} +9 -9
  27. package/dist/{Weather-NZO3CWLH.js.map → Weather-725PFR7T.js.map} +1 -1
  28. package/dist/{WorldClock-HUC6D3AD.js → WorldClock-UU4NZIQ7.js} +9 -9
  29. package/dist/{WorldClock-HUC6D3AD.js.map → WorldClock-UU4NZIQ7.js.map} +1 -1
  30. package/dist/apps/index.d.ts +2 -2
  31. package/dist/apps/index.js +28 -28
  32. package/dist/apps/index.js.map +1 -1
  33. package/dist/brand.css +1 -1
  34. package/dist/{chunk-TQURTLK2.js → chunk-2TPTHAKI.js} +5 -5
  35. package/dist/{chunk-TQURTLK2.js.map → chunk-2TPTHAKI.js.map} +1 -1
  36. package/dist/{chunk-EENVXIVU.js → chunk-4P44JXDS.js} +3 -3
  37. package/dist/{chunk-EENVXIVU.js.map → chunk-4P44JXDS.js.map} +1 -1
  38. package/dist/{chunk-CT3HVZRZ.js → chunk-5O42JXQE.js} +2 -2
  39. package/dist/chunk-5O42JXQE.js.map +1 -0
  40. package/dist/{chunk-7IN7YZAL.js → chunk-72CQWN7O.js} +3 -3
  41. package/dist/chunk-72CQWN7O.js.map +1 -0
  42. package/dist/{chunk-I464GYJJ.js → chunk-BE7FZOFU.js} +2 -2
  43. package/dist/chunk-BE7FZOFU.js.map +1 -0
  44. package/dist/{chunk-3L463T5H.js → chunk-DVZWYWSD.js} +2 -2
  45. package/dist/chunk-DVZWYWSD.js.map +1 -0
  46. package/dist/{chunk-FONEQRBH.js → chunk-ET6ID4LP.js} +3 -3
  47. package/dist/{chunk-FONEQRBH.js.map → chunk-ET6ID4LP.js.map} +1 -1
  48. package/dist/{chunk-CGXMWHQW.js → chunk-GIGV2ZRW.js} +3 -3
  49. package/dist/{chunk-CGXMWHQW.js.map → chunk-GIGV2ZRW.js.map} +1 -1
  50. package/dist/{chunk-CJYO4RVV.js → chunk-IULP5BCD.js} +5 -5
  51. package/dist/chunk-IULP5BCD.js.map +1 -0
  52. package/dist/{chunk-BJ34QOR3.js → chunk-OLJDJYSU.js} +287 -146
  53. package/dist/chunk-OLJDJYSU.js.map +1 -0
  54. package/dist/{chunk-7MA5XBWD.js → chunk-PIGDNN5F.js} +5 -5
  55. package/dist/{chunk-7MA5XBWD.js.map → chunk-PIGDNN5F.js.map} +1 -1
  56. package/dist/chunk-Q2MJVSJT.js +7 -0
  57. package/dist/{chunk-JMKYYPOF.js.map → chunk-Q2MJVSJT.js.map} +1 -1
  58. package/dist/{chunk-ZKHD4J73.js → chunk-Q3LT745N.js} +10 -10
  59. package/dist/chunk-Q3LT745N.js.map +1 -0
  60. package/dist/{chunk-CLGNTGC5.js → chunk-QAGQRNKI.js} +3 -3
  61. package/dist/{chunk-CLGNTGC5.js.map → chunk-QAGQRNKI.js.map} +1 -1
  62. package/dist/{chunk-E3TWIN7Z.js → chunk-QRL64J5F.js} +3 -3
  63. package/dist/{chunk-E3TWIN7Z.js.map → chunk-QRL64J5F.js.map} +1 -1
  64. package/dist/{chunk-TFXJRHJV.js → chunk-QSKCQUZE.js} +3 -3
  65. package/dist/{chunk-TFXJRHJV.js.map → chunk-QSKCQUZE.js.map} +1 -1
  66. package/dist/{chunk-MQPX6ERJ.js → chunk-R4OQIQYX.js} +4 -4
  67. package/dist/{chunk-MQPX6ERJ.js.map → chunk-R4OQIQYX.js.map} +1 -1
  68. package/dist/{chunk-LQTVTOSY.js → chunk-RT6DSB5Y.js} +45 -19
  69. package/dist/chunk-RT6DSB5Y.js.map +1 -0
  70. package/dist/{chunk-VWZIGZFF.js → chunk-SHQM5CK3.js} +4 -4
  71. package/dist/{chunk-VWZIGZFF.js.map → chunk-SHQM5CK3.js.map} +1 -1
  72. package/dist/{chunk-KWEX4ZAF.js → chunk-T4VQHMG4.js} +3 -3
  73. package/dist/{chunk-KWEX4ZAF.js.map → chunk-T4VQHMG4.js.map} +1 -1
  74. package/dist/{chunk-BFBWLCO6.js → chunk-TW7LPMVR.js} +2 -2
  75. package/dist/chunk-TW7LPMVR.js.map +1 -0
  76. package/dist/{chunk-XH3ELPQZ.js → chunk-W622KQTD.js} +3 -3
  77. package/dist/chunk-W622KQTD.js.map +1 -0
  78. package/dist/{chunk-SEWF4O3H.js → chunk-X4Q6G253.js} +3 -3
  79. package/dist/chunk-X4Q6G253.js.map +1 -0
  80. package/dist/file-intake/index.js +2 -2
  81. package/dist/{index-COwksV6G.d.ts → index-DZ7E7bCl.d.ts} +196 -4
  82. package/dist/index.d.ts +3 -3
  83. package/dist/index.js +35 -35
  84. package/dist/index.js.map +1 -1
  85. package/dist/map/index.js +1 -1
  86. package/dist/markdown/index.d.ts +4 -4
  87. package/dist/markdown/index.js.map +1 -1
  88. package/dist/markup/index.d.ts +2 -2
  89. package/dist/markup/index.js.map +1 -1
  90. package/dist/page-tabs/index.js +3 -3
  91. package/dist/shell.css +1 -1
  92. package/dist/styles.css +4 -4
  93. package/dist/themes.css +3 -3
  94. package/dist/ui/index.d.ts +1 -1
  95. package/dist/ui/index.js +12 -12
  96. package/dist/ui.css +233 -8
  97. package/package.json +1 -1
  98. package/dist/ConfirmDialog-MTC7QMUJ.js +0 -4
  99. package/dist/PdfViewer-M2YGZIYX.js +0 -5
  100. package/dist/chunk-3L463T5H.js.map +0 -1
  101. package/dist/chunk-7IN7YZAL.js.map +0 -1
  102. package/dist/chunk-BFBWLCO6.js.map +0 -1
  103. package/dist/chunk-BJ34QOR3.js.map +0 -1
  104. package/dist/chunk-CJYO4RVV.js.map +0 -1
  105. package/dist/chunk-CT3HVZRZ.js.map +0 -1
  106. package/dist/chunk-I464GYJJ.js.map +0 -1
  107. package/dist/chunk-JMKYYPOF.js +0 -7
  108. package/dist/chunk-LQTVTOSY.js.map +0 -1
  109. package/dist/chunk-SEWF4O3H.js.map +0 -1
  110. package/dist/chunk-XH3ELPQZ.js.map +0 -1
  111. package/dist/chunk-ZKHD4J73.js.map +0 -1
@@ -1,35 +1,26 @@
1
- import { Breadcrumbs } from './chunk-CGXMWHQW.js';
2
- import { SidebarLayout } from './chunk-FONEQRBH.js';
1
+ import { Breadcrumbs } from './chunk-GIGV2ZRW.js';
2
+ import { SidebarLayout } from './chunk-ET6ID4LP.js';
3
3
  import { BrandMark } from './chunk-TRCWINHF.js';
4
- import { toast_default } from './chunk-EENVXIVU.js';
5
- import { useIsMobile, useShortcutLabel, useShellPrefs } from './chunk-TQURTLK2.js';
6
- import { useFileIntake, humanSize, FileIntakeAlert } from './chunk-CLGNTGC5.js';
7
- import { BUTTON_BASE, BUTTON_VARIANTS, Button_default } from './chunk-LQTVTOSY.js';
8
- import { PopupMenu, PopupMenuItem } from './chunk-E3TWIN7Z.js';
9
- import { registerModalEscapeInterceptor, onOverlayOpen, Z_LAYERS, useDismissPopupsOnOpen, useFocusTrap, useScrollLock } from './chunk-XH3ELPQZ.js';
4
+ import { toast_default } from './chunk-4P44JXDS.js';
5
+ import { useIsMobile, useShortcutLabel, useShellPrefs } from './chunk-2TPTHAKI.js';
6
+ import { useFileIntake, humanSize, FileIntakeAlert } from './chunk-QAGQRNKI.js';
7
+ import { iconButtonClasses, Button_default } from './chunk-RT6DSB5Y.js';
8
+ import { PopupMenu, PopupMenuItem } from './chunk-QRL64J5F.js';
9
+ import { registerModalEscapeInterceptor, onOverlayOpen, Z_LAYERS, useDismissPopupsOnOpen, useFocusTrap, useScrollLock } from './chunk-W622KQTD.js';
10
10
  import { glassStyle } from './chunk-D276EMXS.js';
11
- import { useShellLocale, useShellStrings, DEFAULT_SHELL_STRINGS, currentShellStrings, formatPlain, formatFixed, formatPercent, splitAround } from './chunk-7IN7YZAL.js';
11
+ import { useShellLocale, useShellStrings, DEFAULT_SHELL_STRINGS, currentShellStrings, formatPlain, formatFixed, formatPercent, splitAround } from './chunk-72CQWN7O.js';
12
12
  import { useBrowserLayoutEffect, useBrowserValue, useBrowserValueOnce } from './chunk-IRWSRJ4K.js';
13
13
  import { forwardRef, useCallback, useState, useRef, useId, useEffect, createContext, useMemo, Children, isValidElement, cloneElement, useContext, Fragment as Fragment$1, Component, useSyncExternalStore, useLayoutEffect } from 'react';
14
14
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
15
15
  import { createPortal } from 'react-dom';
16
16
 
17
- var SQUARE = {
18
- sm: "h-6 w-6",
19
- md: "h-8 w-8",
20
- lg: "h-10 w-10",
21
- "touch-sm": "h-11 w-11",
22
- "touch": "h-14 w-14",
23
- "touch-lg": "h-16 w-16",
24
- "touch-xl": "h-20 w-20"
25
- };
26
17
  var IconButton = forwardRef(function IconButton2({ children, variant = "ghost", size = "md", type = "button", className = "", ...rest }, ref) {
27
18
  return /* @__PURE__ */ jsx(
28
19
  "button",
29
20
  {
30
21
  ref,
31
22
  type,
32
- className: [BUTTON_BASE, BUTTON_VARIANTS[variant], SQUARE[size], "shrink-0 p-0", className].filter(Boolean).join(" "),
23
+ className: iconButtonClasses({ variant, size, className }),
33
24
  ...rest,
34
25
  children
35
26
  }
@@ -130,6 +121,57 @@ function popupBounds(trigger) {
130
121
  bottom: Math.min(viewport.bottom, rect.bottom)
131
122
  };
132
123
  }
124
+ var OPPOSITE = {
125
+ top: "bottom",
126
+ bottom: "top",
127
+ left: "right",
128
+ right: "left"
129
+ };
130
+ var ACROSS = {
131
+ top: ["right", "left"],
132
+ bottom: ["right", "left"],
133
+ left: ["top", "bottom"],
134
+ right: ["top", "bottom"]
135
+ };
136
+ function placeBeside(anchor, size, side, bounds, gap) {
137
+ const room = {
138
+ top: anchor.top - gap - (bounds.top + VIEWPORT_MARGIN),
139
+ bottom: bounds.bottom - VIEWPORT_MARGIN - (anchor.bottom + gap),
140
+ left: anchor.left - gap - (bounds.left + VIEWPORT_MARGIN),
141
+ right: bounds.right - VIEWPORT_MARGIN - (anchor.right + gap)
142
+ };
143
+ const spare = (s) => room[s] - (s === "top" || s === "bottom" ? size.height : size.width);
144
+ const order = [side, OPPOSITE[side], ...ACROSS[side]];
145
+ const chosen = order.find((s) => spare(s) >= 0) ?? order.reduce((best, s) => spare(s) > spare(best) ? s : best);
146
+ const centreX = (anchor.left + anchor.right) / 2;
147
+ const centreY = (anchor.top + anchor.bottom) / 2;
148
+ let left;
149
+ let top;
150
+ switch (chosen) {
151
+ case "top":
152
+ left = centreX - size.width / 2;
153
+ top = anchor.top - gap - size.height;
154
+ break;
155
+ case "bottom":
156
+ left = centreX - size.width / 2;
157
+ top = anchor.bottom + gap;
158
+ break;
159
+ case "left":
160
+ left = anchor.left - gap - size.width;
161
+ top = centreY - size.height / 2;
162
+ break;
163
+ case "right":
164
+ left = anchor.right + gap;
165
+ top = centreY - size.height / 2;
166
+ break;
167
+ }
168
+ const within = (value, lo, hi) => Math.max(lo, Math.min(value, hi));
169
+ return {
170
+ side: chosen,
171
+ left: within(left, bounds.left + VIEWPORT_MARGIN, bounds.right - VIEWPORT_MARGIN - size.width),
172
+ top: within(top, bounds.top + VIEWPORT_MARGIN, bounds.bottom - VIEWPORT_MARGIN - size.height)
173
+ };
174
+ }
133
175
  function useDropdownPosition(triggerRef, open, options = {}) {
134
176
  const {
135
177
  matchTriggerWidth = false,
@@ -4232,9 +4274,13 @@ var SIDE_POS = {
4232
4274
  left: "right-full top-1/2 -translate-y-1/2 mr-1.5",
4233
4275
  right: "left-full top-1/2 -translate-y-1/2 ml-1.5"
4234
4276
  };
4277
+ var GAP2 = 6;
4235
4278
  function Tooltip({ content, side = "top", delay = 200, children }) {
4236
4279
  const [show, setShow] = useState(false);
4280
+ const [placed, setPlaced] = useState(null);
4237
4281
  const timer = useRef(void 0);
4282
+ const wrapRef = useRef(null);
4283
+ const tipRef = useRef(null);
4238
4284
  const id = useId();
4239
4285
  const open = () => {
4240
4286
  timer.current = window.setTimeout(() => setShow(true), delay);
@@ -4244,6 +4290,33 @@ function Tooltip({ content, side = "top", delay = 200, children }) {
4244
4290
  setShow(false);
4245
4291
  };
4246
4292
  useEffect(() => () => window.clearTimeout(timer.current), []);
4293
+ useBrowserLayoutEffect(() => {
4294
+ if (!show) {
4295
+ setPlaced(null);
4296
+ return;
4297
+ }
4298
+ const place = () => {
4299
+ const wrap = wrapRef.current;
4300
+ const tip = tipRef.current;
4301
+ if (!wrap || !tip) return;
4302
+ const bounds = popupBounds(wrap);
4303
+ const maxWidth = Math.max(0, bounds.right - bounds.left - 2 * VIEWPORT_MARGIN);
4304
+ tip.style.maxWidth = `${maxWidth}px`;
4305
+ const size = tip.getBoundingClientRect();
4306
+ if (size.width <= 0 || size.height <= 0) return;
4307
+ const anchor = wrap.getBoundingClientRect();
4308
+ const at = placeBeside(anchor, size, side, bounds, GAP2);
4309
+ const next = { left: at.left - anchor.left, top: at.top - anchor.top, maxWidth };
4310
+ setPlaced((prev) => prev && prev.left === next.left && prev.top === next.top && prev.maxWidth === next.maxWidth ? prev : next);
4311
+ };
4312
+ place();
4313
+ window.addEventListener("scroll", place, true);
4314
+ window.addEventListener("resize", place);
4315
+ return () => {
4316
+ window.removeEventListener("scroll", place, true);
4317
+ window.removeEventListener("resize", place);
4318
+ };
4319
+ }, [show, side, content]);
4247
4320
  useEffect(() => {
4248
4321
  if (!show) return;
4249
4322
  return registerModalEscapeInterceptor((event) => {
@@ -4259,6 +4332,7 @@ function Tooltip({ content, side = "top", delay = 200, children }) {
4259
4332
  return /* @__PURE__ */ jsxs(
4260
4333
  "span",
4261
4334
  {
4335
+ ref: wrapRef,
4262
4336
  className: "relative inline-flex",
4263
4337
  "aria-describedby": isValidElement(children) ? void 0 : describedBy,
4264
4338
  onMouseEnter: open,
@@ -4267,13 +4341,24 @@ function Tooltip({ content, side = "top", delay = 200, children }) {
4267
4341
  onBlur: close,
4268
4342
  children: [
4269
4343
  trigger,
4270
- show && /* @__PURE__ */ jsx(
4344
+ show && // `w-max` rather than the `whitespace-nowrap` this was: both keep a
4345
+ // short bubble on one line however narrow its trigger, but only
4346
+ // `w-max` lets the width cap above take effect — a bubble longer than
4347
+ // its window is wide wraps inside it instead of running past both
4348
+ // edges. `whitespace-normal` and `text-start` so a trigger inside a
4349
+ // `nowrap` or right-aligned cell does not hand the bubble its own.
4350
+ // Nothing here animates, so there is no motion to reduce.
4351
+ /* @__PURE__ */ jsx(
4271
4352
  "span",
4272
4353
  {
4354
+ ref: tipRef,
4273
4355
  id,
4274
4356
  role: "tooltip",
4275
- className: `pointer-events-none absolute z-[300] whitespace-nowrap rounded-md px-2 py-1 text-xs text-gray-800 ${SIDE_POS[side]}`,
4276
- style: glassStyle(),
4357
+ className: `pointer-events-none absolute z-[300] w-max whitespace-normal break-words text-start rounded-md px-2 py-1 text-xs text-gray-800 ${placed ? "" : SIDE_POS[side]}`,
4358
+ style: {
4359
+ ...glassStyle(),
4360
+ ...placed && { left: placed.left, top: placed.top, maxWidth: placed.maxWidth }
4361
+ },
4277
4362
  children: content
4278
4363
  }
4279
4364
  )
@@ -4455,7 +4540,7 @@ function reportUnknownSeverity(component, described) {
4455
4540
  if (reported.has(key)) return;
4456
4541
  reported.add(key);
4457
4542
  console.error(
4458
- `[react-os-shell] ${component}: severity ${described} is not one of ${SEVERITY_TONES.join(" | ")}. Rendering an "unknown severity" marker \u2014 a health marker must never silently disappear. If this came from a backend rollup, map it to the shell's vocabulary at the fetch boundary (see isSeverityTone).`
4543
+ `[efficient-shell] ${component}: severity ${described} is not one of ${SEVERITY_TONES.join(" | ")}. Rendering an "unknown severity" marker \u2014 a health marker must never silently disappear. If this came from a backend rollup, map it to the shell's vocabulary at the fetch boundary (see isSeverityTone).`
4459
4544
  );
4460
4545
  }
4461
4546
  function resolveSeverity(severity, component) {
@@ -4512,7 +4597,7 @@ function MetricBar({
4512
4597
  if (scale == null) {
4513
4598
  warnOnce(
4514
4599
  `MetricBar:max:${String(max)}`,
4515
- `[react-os-shell] MetricBar: max=${String(max)} is not a positive finite number, so there is no scale to draw a proportional bar against. Printing the value without a bar. Pass the real capacity, or leave the reading out entirely (value={null}) when it is unknown \u2014 do not pass 0.`
4600
+ `[efficient-shell] MetricBar: max=${String(max)} is not a positive finite number, so there is no scale to draw a proportional bar against. Printing the value without a bar. Pass the real capacity, or leave the reading out entirely (value={null}) when it is unknown \u2014 do not pass 0.`
4516
4601
  );
4517
4602
  }
4518
4603
  const supplied = resolveSeverity(severity, "MetricBar");
@@ -9045,11 +9130,18 @@ function DataTable({
9045
9130
  selection,
9046
9131
  footer,
9047
9132
  virtualized,
9133
+ stackOnNarrow = false,
9048
9134
  className = ""
9049
9135
  }) {
9050
9136
  const strings = useShellStrings();
9051
9137
  const emptyContent = emptyText ?? strings.table.empty;
9052
9138
  const keyOf = (row, i) => typeof rowKey === "function" ? rowKey(row, i) : String(row[rowKey]);
9139
+ const stack = stackOnNarrow && !virtualized;
9140
+ const role = (r) => stack ? { role: r } : {};
9141
+ const textOf = (title, label) => {
9142
+ const text = label ?? (typeof title === "string" || typeof title === "number" ? String(title) : "");
9143
+ return text.trim() || void 0;
9144
+ };
9053
9145
  const [startRow, setStartRow] = useState(0);
9054
9146
  const overscan = virtualized?.overscan ?? 6;
9055
9147
  const onBodyScroll = virtualized ? (e) => {
@@ -9082,6 +9174,17 @@ function DataTable({
9082
9174
  };
9083
9175
  const leaves = columns.flatMap((h) => isGroup(h) ? h.columns : [h]);
9084
9176
  const grouped = columns.some(isGroup);
9177
+ const groupOf = /* @__PURE__ */ new Map();
9178
+ if (stack) {
9179
+ for (const h of columns) {
9180
+ if (isGroup(h)) for (const c of h.columns) groupOf.set(c, textOf(h.title, h.label));
9181
+ }
9182
+ }
9183
+ const cardLabel = (col) => {
9184
+ const own = textOf(col.title, col.label);
9185
+ const group = groupOf.get(col);
9186
+ return own && group ? `${group} \xB7 ${own}` : own;
9187
+ };
9085
9188
  const selectedSet = new Set(selection?.selected ?? []);
9086
9189
  const pageKeys = selection ? data.map((row, i) => keyOf(row, i)) : [];
9087
9190
  const allSelected = pageKeys.length > 0 && pageKeys.every((k) => selectedSet.has(k));
@@ -9108,12 +9211,14 @@ function DataTable({
9108
9211
  const dir = directionFor(col);
9109
9212
  const align = ALIGN2[col.align ?? (col.numeric ? "right" : "left")];
9110
9213
  const pinned = col.fixed === "left";
9214
+ const sorts = !!(col.sortable && onSortChange);
9111
9215
  return /* @__PURE__ */ jsx(
9112
9216
  "th",
9113
9217
  {
9114
9218
  scope: "col",
9219
+ ...role("columnheader"),
9115
9220
  rowSpan: rowSpan > 1 ? rowSpan : void 0,
9116
- "aria-sort": dir === "asc" ? "ascending" : dir === "desc" ? "descending" : col.sortable && onSortChange ? "none" : void 0,
9221
+ "aria-sort": dir === "asc" ? "ascending" : dir === "desc" ? "descending" : sorts ? "none" : void 0,
9117
9222
  style: {
9118
9223
  width: col.width,
9119
9224
  ...pinned ? { left: (offsets[ci] ?? 0) + selOffset } : {},
@@ -9128,13 +9233,17 @@ function DataTable({
9128
9233
  "font-semibold uppercase tracking-wide text-gray-500",
9129
9234
  size === "sm" ? "text-[10px]" : "text-xs",
9130
9235
  pinned ? virtualized ? "sticky z-20 bg-gray-50" : "sticky z-10 bg-gray-50" : virtualized ? "sticky z-10 bg-gray-50" : "",
9236
+ // Stacked, a sortable header is one of the sort row's chips and
9237
+ // every other header is hidden from sight — see `rosh-dt-head`.
9238
+ stack && sorts ? "rosh-dt-sort" : "",
9131
9239
  col.headerClassName ?? ""
9132
9240
  ].filter(Boolean).join(" "),
9133
- children: col.sortable && onSortChange ? /* @__PURE__ */ jsxs(
9241
+ children: sorts ? /* @__PURE__ */ jsxs(
9134
9242
  "button",
9135
9243
  {
9136
9244
  type: "button",
9137
9245
  onClick: () => toggleSort(col),
9246
+ "data-group": stack ? groupOf.get(col) : void 0,
9138
9247
  className: `inline-flex items-center font-semibold uppercase tracking-wide hover:text-gray-700 ${align}`,
9139
9248
  children: [
9140
9249
  col.title,
@@ -9153,13 +9262,13 @@ function DataTable({
9153
9262
  fixedOffset += col.width ?? 0;
9154
9263
  return at;
9155
9264
  });
9156
- return /* @__PURE__ */ jsxs("div", { className, children: [
9265
+ return /* @__PURE__ */ jsxs("div", { className: stack ? `rosh-dt-stack ${className}`.trim() : className, children: [
9157
9266
  /* @__PURE__ */ jsxs(
9158
9267
  "div",
9159
9268
  {
9160
9269
  onScroll: onBodyScroll,
9161
9270
  style: virtualized ? { maxHeight: virtualized.height } : void 0,
9162
- className: `relative overflow-x-auto ${virtualized ? "overflow-y-auto" : ""} ${bordered ? "rounded-lg border border-gray-200" : ""}`.trim(),
9271
+ className: `relative overflow-x-auto ${virtualized ? "overflow-y-auto" : ""} ${bordered ? "rounded-lg border border-gray-200" : ""}${stack ? " rosh-dt-scroll" : ""}`.trim(),
9163
9272
  children: [
9164
9273
  loading && // An overlay rather than replacing the rows: the table keeps its
9165
9274
  // height and its scroll position, so re-sorting does not throw the
@@ -9168,140 +9277,172 @@ function DataTable({
9168
9277
  /* @__PURE__ */ jsx("span", { className: "h-6 w-6 animate-spin rounded-full border-2 border-gray-200 border-t-blue-600" }),
9169
9278
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: strings.table.loading })
9170
9279
  ] }),
9171
- /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse tabular-nums", style: minWidth ? { minWidth } : void 0, children: [
9172
- caption && /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }),
9173
- /* @__PURE__ */ jsxs("thead", { children: [
9174
- /* @__PURE__ */ jsxs("tr", { ref: headRowRef, className: "border-b border-gray-200 bg-gray-50", children: [
9175
- selection && /* @__PURE__ */ jsx(
9176
- "th",
9177
- {
9178
- scope: "col",
9179
- rowSpan: grouped ? 2 : void 0,
9180
- style: { width: SELECT_W, ...virtualized ? { top: 0 } : {} },
9181
- className: [
9182
- cellBase,
9183
- hasPinned || virtualized ? "sticky z-20 bg-gray-50" : "",
9184
- hasPinned ? "left-0" : ""
9185
- ].filter(Boolean).join(" "),
9186
- children: /* @__PURE__ */ jsx(
9187
- Checkbox_default,
9188
- {
9189
- "aria-label": strings.table.selectAll,
9190
- checked: allSelected,
9191
- indeterminate: someSelected && !allSelected,
9192
- onChange: toggleAll
9193
- }
9194
- )
9195
- }
9196
- ),
9197
- columns.map((h, hi) => {
9198
- if (isGroup(h)) {
9199
- return /* @__PURE__ */ jsx(
9280
+ /* @__PURE__ */ jsxs(
9281
+ "table",
9282
+ {
9283
+ ...role("table"),
9284
+ className: `${stack ? "rosh-dt-table " : ""}w-full border-collapse tabular-nums`,
9285
+ style: minWidth ? { minWidth } : void 0,
9286
+ children: [
9287
+ caption && /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }),
9288
+ /* @__PURE__ */ jsxs("thead", { ...role("rowgroup"), className: stack ? "rosh-dt-head" : void 0, children: [
9289
+ /* @__PURE__ */ jsxs("tr", { ref: headRowRef, ...role("row"), className: "border-b border-gray-200 bg-gray-50", children: [
9290
+ selection && /* @__PURE__ */ jsx(
9200
9291
  "th",
9201
9292
  {
9202
- scope: "colgroup",
9203
- colSpan: h.columns.length,
9204
- style: virtualized ? { top: 0 } : void 0,
9293
+ scope: "col",
9294
+ ...role("columnheader"),
9295
+ rowSpan: grouped ? 2 : void 0,
9296
+ style: { width: SELECT_W, ...virtualized ? { top: 0 } : {} },
9205
9297
  className: [
9206
9298
  cellBase,
9207
- "text-center",
9208
- "font-semibold uppercase tracking-wide text-gray-500",
9209
- size === "sm" ? "text-[10px]" : "text-xs",
9210
- "border-b border-gray-200",
9211
- virtualized ? "sticky z-10 bg-gray-50" : "",
9212
- h.headerClassName ?? ""
9299
+ hasPinned || virtualized ? "sticky z-20 bg-gray-50" : "",
9300
+ hasPinned ? "left-0" : "",
9301
+ // Stacked, "select all" leads the sort row.
9302
+ stack ? "rosh-dt-select" : ""
9213
9303
  ].filter(Boolean).join(" "),
9214
- children: h.title
9215
- },
9216
- h.key ?? `group-${hi}`
9217
- );
9218
- }
9219
- return headerCell(h, leaves.indexOf(h), grouped ? 2 : 1);
9220
- })
9221
- ] }),
9222
- grouped && /* @__PURE__ */ jsx("tr", { className: "border-b border-gray-200 bg-gray-50", children: columns.flatMap((h) => isGroup(h) ? h.columns : []).map(
9223
- (col) => headerCell(col, leaves.indexOf(col), 1, headRowH)
9224
- ) })
9225
- ] }),
9226
- /* @__PURE__ */ jsx("tbody", { children: data.length === 0 && !loading ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: colCount, className: `${cellBase} py-10 text-center text-gray-500`, children: emptyContent }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
9227
- topPad > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx("td", { colSpan: colCount, style: { height: topPad, padding: 0, border: 0 } }) }),
9228
- data.slice(start, end).map((row, si) => {
9229
- const i = start + si;
9230
- const rowProps = onRow?.(row, i);
9231
- return /* @__PURE__ */ jsxs(
9232
- "tr",
9233
- {
9234
- style: virtualized ? { height: virtualized.rowHeight } : void 0,
9235
- onClick: rowProps?.onClick,
9236
- ...rowProps?.onClick ? {
9237
- tabIndex: 0,
9238
- onKeyDown: (e) => {
9239
- if (e.target !== e.currentTarget) return;
9240
- if (e.key !== "Enter" && e.key !== " ") return;
9241
- e.preventDefault();
9242
- rowProps.onClick?.();
9243
- }
9244
- } : {},
9245
- className: [
9246
- "border-b border-gray-100 last:border-b-0",
9247
- rowProps?.onClick ? "cursor-pointer hover:bg-gray-50 rosh-focus-ring focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[color:var(--rosh-focus-ring-solid)]" : "",
9248
- rowClassName?.(row, i) ?? "",
9249
- rowProps?.className ?? ""
9250
- ].filter(Boolean).join(" "),
9251
- children: [
9252
- selection && (() => {
9253
- const key = keyOf(row, i);
9254
- return /* @__PURE__ */ jsx(
9255
- "td",
9304
+ children: /* @__PURE__ */ jsx(
9305
+ Checkbox_default,
9256
9306
  {
9257
- style: { width: SELECT_W },
9258
- onClick: (e) => e.stopPropagation(),
9259
- className: [cellBase, hasPinned ? "sticky left-0 z-10 bg-white" : ""].filter(Boolean).join(" "),
9260
- children: /* @__PURE__ */ jsx(
9261
- Checkbox_default,
9262
- {
9263
- "aria-label": strings.table.selectRow,
9264
- checked: selectedSet.has(key),
9265
- onChange: () => toggleRow(key)
9266
- }
9267
- )
9307
+ "aria-label": strings.table.selectAll,
9308
+ checked: allSelected,
9309
+ indeterminate: someSelected && !allSelected,
9310
+ onChange: toggleAll
9268
9311
  }
9269
- );
9270
- })(),
9271
- leaves.map((col, ci) => {
9272
- const pinned = col.fixed === "left";
9312
+ )
9313
+ }
9314
+ ),
9315
+ columns.map((h, hi) => {
9316
+ if (isGroup(h)) {
9273
9317
  return /* @__PURE__ */ jsx(
9274
- "td",
9318
+ "th",
9275
9319
  {
9276
- style: pinned ? { left: (offsets[ci] ?? 0) + selOffset } : void 0,
9320
+ scope: "colgroup",
9321
+ ...role("columnheader"),
9322
+ colSpan: h.columns.length,
9323
+ style: virtualized ? { top: 0 } : void 0,
9277
9324
  className: [
9278
9325
  cellBase,
9279
- ALIGN2[col.align ?? (col.numeric ? "right" : "left")],
9280
- col.numeric ? "font-mono" : "",
9281
- "text-gray-900",
9282
- col.ellipsis ? "max-w-0 truncate" : "",
9283
- // A pinned cell needs its own background or the
9284
- // scrolling columns show through it.
9285
- pinned ? "sticky z-10 bg-white" : ""
9326
+ "text-center",
9327
+ "font-semibold uppercase tracking-wide text-gray-500",
9328
+ size === "sm" ? "text-[10px]" : "text-xs",
9329
+ "border-b border-gray-200",
9330
+ virtualized ? "sticky z-10 bg-gray-50" : "",
9331
+ h.headerClassName ?? ""
9286
9332
  ].filter(Boolean).join(" "),
9287
- children: col.render ? col.render(row, i) : col.dataIndex ? row[col.dataIndex] : null
9333
+ children: h.title
9288
9334
  },
9289
- col.key
9335
+ h.key ?? `group-${hi}`
9290
9336
  );
9291
- })
9292
- ]
9293
- },
9294
- keyOf(row, i)
9295
- );
9296
- }),
9297
- bottomPad > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx("td", { colSpan: colCount, style: { height: bottomPad, padding: 0, border: 0 } }) })
9298
- ] }) })
9299
- ] }),
9337
+ }
9338
+ return headerCell(h, leaves.indexOf(h), grouped ? 2 : 1);
9339
+ })
9340
+ ] }),
9341
+ grouped && /* @__PURE__ */ jsx("tr", { ...role("row"), className: "border-b border-gray-200 bg-gray-50", children: columns.flatMap((h) => isGroup(h) ? h.columns : []).map(
9342
+ (col) => headerCell(col, leaves.indexOf(col), 1, headRowH)
9343
+ ) })
9344
+ ] }),
9345
+ /* @__PURE__ */ jsx("tbody", { ...role("rowgroup"), className: stack ? "rosh-dt-body" : void 0, children: data.length === 0 && !loading ? /* @__PURE__ */ jsx("tr", { ...role("row"), className: stack ? "rosh-dt-empty" : void 0, children: /* @__PURE__ */ jsx("td", { ...role("cell"), colSpan: colCount, className: `${cellBase} py-10 text-center text-gray-500`, children: emptyContent }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
9346
+ topPad > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx("td", { colSpan: colCount, style: { height: topPad, padding: 0, border: 0 } }) }),
9347
+ data.slice(start, end).map((row, si) => {
9348
+ const i = start + si;
9349
+ const rowProps = onRow?.(row, i);
9350
+ return /* @__PURE__ */ jsxs(
9351
+ "tr",
9352
+ {
9353
+ ...role("row"),
9354
+ style: virtualized ? { height: virtualized.rowHeight } : void 0,
9355
+ onClick: rowProps?.onClick,
9356
+ ...rowProps?.onClick ? {
9357
+ tabIndex: 0,
9358
+ onKeyDown: (e) => {
9359
+ if (e.target !== e.currentTarget) return;
9360
+ if (e.key !== "Enter" && e.key !== " ") return;
9361
+ e.preventDefault();
9362
+ rowProps.onClick?.();
9363
+ }
9364
+ } : {},
9365
+ className: [
9366
+ stack ? selection ? "rosh-dt-row rosh-dt-row-select" : "rosh-dt-row" : "",
9367
+ "border-b border-gray-100 last:border-b-0",
9368
+ rowProps?.onClick ? "cursor-pointer hover:bg-gray-50 rosh-focus-ring focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[color:var(--rosh-focus-ring-solid)]" : "",
9369
+ rowClassName?.(row, i) ?? "",
9370
+ rowProps?.className ?? ""
9371
+ ].filter(Boolean).join(" "),
9372
+ children: [
9373
+ selection && (() => {
9374
+ const key = keyOf(row, i);
9375
+ return /* @__PURE__ */ jsx(
9376
+ "td",
9377
+ {
9378
+ ...role("cell"),
9379
+ style: { width: SELECT_W },
9380
+ onClick: (e) => e.stopPropagation(),
9381
+ className: [
9382
+ cellBase,
9383
+ hasPinned ? "sticky left-0 z-10 bg-white" : "",
9384
+ stack ? "rosh-dt-select" : ""
9385
+ ].filter(Boolean).join(" "),
9386
+ children: /* @__PURE__ */ jsx(
9387
+ Checkbox_default,
9388
+ {
9389
+ "aria-label": strings.table.selectRow,
9390
+ checked: selectedSet.has(key),
9391
+ onChange: () => toggleRow(key)
9392
+ }
9393
+ )
9394
+ }
9395
+ );
9396
+ })(),
9397
+ leaves.map((col, ci) => {
9398
+ const pinned = col.fixed === "left";
9399
+ const content = col.render ? col.render(row, i) : col.dataIndex ? row[col.dataIndex] : null;
9400
+ return /* @__PURE__ */ jsx(
9401
+ "td",
9402
+ {
9403
+ ...role("cell"),
9404
+ "data-label": stack ? cardLabel(col) : void 0,
9405
+ style: pinned ? { left: (offsets[ci] ?? 0) + selOffset } : void 0,
9406
+ className: [
9407
+ stack ? col.ellipsis ? "rosh-dt-cell rosh-dt-clip" : "rosh-dt-cell" : "",
9408
+ cellBase,
9409
+ ALIGN2[col.align ?? (col.numeric ? "right" : "left")],
9410
+ // Stacked, the monospace moves onto the value, so
9411
+ // the label beside it keeps the header's typeface.
9412
+ col.numeric && !stack ? "font-mono" : "",
9413
+ "text-gray-900",
9414
+ col.ellipsis ? "max-w-0 truncate" : "",
9415
+ // A pinned cell needs its own background or the
9416
+ // scrolling columns show through it.
9417
+ pinned ? "sticky z-10 bg-white" : ""
9418
+ ].filter(Boolean).join(" "),
9419
+ children: stack ? (
9420
+ // One box for the value, whatever `render` returns
9421
+ // — text, a fragment, three badges — so the card
9422
+ // line is always two items: the label and this.
9423
+ // `display: contents` in the wide layout, where
9424
+ // the cell lays its content out exactly as before.
9425
+ /* @__PURE__ */ jsx("span", { className: col.numeric ? "rosh-dt-value font-mono" : "rosh-dt-value", children: content })
9426
+ ) : content
9427
+ },
9428
+ col.key
9429
+ );
9430
+ })
9431
+ ]
9432
+ },
9433
+ keyOf(row, i)
9434
+ );
9435
+ }),
9436
+ bottomPad > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx("td", { colSpan: colCount, style: { height: bottomPad, padding: 0, border: 0 } }) })
9437
+ ] }) })
9438
+ ]
9439
+ }
9440
+ ),
9300
9441
  footer
9301
9442
  ]
9302
9443
  }
9303
9444
  ),
9304
- pagination && pagination.pageCount > 1 && /* @__PURE__ */ jsx("div", { className: "mt-3 flex justify-end", children: /* @__PURE__ */ jsx(
9445
+ pagination && pagination.pageCount > 1 && /* @__PURE__ */ jsx("div", { className: stack ? "rosh-dt-pager mt-3 flex justify-end" : "mt-3 flex justify-end", children: /* @__PURE__ */ jsx(
9305
9446
  Pagination,
9306
9447
  {
9307
9448
  page: pagination.page,
@@ -13533,5 +13674,5 @@ function ChordChart({
13533
13674
  }
13534
13675
 
13535
13676
  export { APP_UPDATE_POLL_MS, Accordion, AppUpdateBanner, AttachButton, AttachmentDropZone, AttachmentList, AuthScreen, Avatar, AvatarGroup, Banner, BarChart, BoxPlotChart, BrandAssetEditor, BudgetBar, CHART_INK, Calendar, CandlestickChart, Card, CartesianPlot, ChartBrush, ChartDefs, ChartDot, ChartFrame, ChartHighlightProvider, ChartSkeleton, ChartTooltip, ChatTemplate, Checkbox_default, CheckoutTemplate, ChordChart, ColoredBadge, ColumnChart, ComposerAttachments, ContainerFillChart, CountBadge, DAY_MS, DashboardTemplate, DataTable, DataTablePage, DatePicker_default, DateRangePicker, DateTimePicker_default, DescriptionList, Divider, DonutChart, Drawer, DropdownMenu, EmailTemplate, EmptyState, ErrorBoundary, ErrorPage, FilePicker_default, FormErrorSummary, FormField, FormLayoutPage, FunnelChart, GROUP_COLORS, GROUP_COLORS_SOLID, GalleryTemplate, GlobalSearch, Grid, HeatmapChart, HelpCenter, HistogramChart, INPUT_BASE, INPUT_SIZES, IconButton_default, Inline, InputNumber_default, Input_default, Kanban, Label, LineChart, ListFooter, ListLoadError, MAX_FRACTION_DIGITS, MENU_MAX_HEIGHT, MOTION, Markdown, MediaUploadField, MediaUploadGrid, Meter, MetricBar, MilestoneTimeline, NativeSelect, NumericKeypad, POPUP_MAX_WIDTH, POST_PRODUCTION_STATUSES, PageHeader, Pagination, PaperclipGlyph, Paragraph, PieChart, PortalBrandingProvider, ProductionTimeline, RADAR_SERIES_CAP, RadarChart, RadialBarChart, RadioGroup, Radio_default, RangeChart, RankedBars, SCATTER_SERIES_CAP, SERIES_SLOT_COUNT, SERIES_VARS, STAGES, STATUS_VARS, SankeyChart, ScatterChart, SearchableSelect, Segmented, Select_default, SettingRow, SidebarActionButton, SidebarGroupLabel, SidebarNavItem, Skeleton, Snippet, Sparkline, Stack, StatCard, StatTile, Statistic, StatusBadge, StatusBadgeProvider, Stepper, SunburstChart, Switch_default, Tabs, TagInput, Text, Textarea_default, TileButton_default, TimePicker_default, TimeSeriesChart, TimelineTrack, Title, Tooltip, TopNav, TreemapChart, WaterfallChart, angleScale, appendKey, applyThemePrefs, arcPath, areaBetween, areaFrom, autoHighlightIndex, backspace, bandScale, binValues, budgetState, bumpPath, calcOverall, calcReportOverall, copyToClipboard, curvePath, dashFor, fillFor, fillId, firstEnabledIndex, fmtSliderDate, formatDate, fromKey, glowId, groundId, groupColors, highlightOpacity, inputClasses, isSeverityTone, ladderScale, lastEnabledIndex, linearPath, linearScale, logScale, maskId, matchTypeahead, mediaFileName, monotonePath, nextEnabledIndex, niceMax, polygonPoints, popupBounds, radiusScale, resolvePortalBrandAsset, resolveSeriesColor, resolveTheme, selectionAt, seriesColor, severityOf, splinePath, squarify, stagger, stepPath, tabButtonId, tabPanelId, toDayMs, toISODate, toKey, useAppUpdate, useClickOutside, useDropdownPosition, useHighlight, usePlotWidth, usePortalBranding, useProductionTimeline, useTheme };
13536
- //# sourceMappingURL=chunk-BJ34QOR3.js.map
13537
- //# sourceMappingURL=chunk-BJ34QOR3.js.map
13677
+ //# sourceMappingURL=chunk-OLJDJYSU.js.map
13678
+ //# sourceMappingURL=chunk-OLJDJYSU.js.map