efficient-shell 4.132.0 → 4.137.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 +142 -18
- package/dist/{Browser-XPVJ2K7B.js → Browser-ZNX4WFUH.js} +13 -13
- package/dist/{Browser-XPVJ2K7B.js.map → Browser-ZNX4WFUH.js.map} +1 -1
- package/dist/{Calculator-ZXJPXG7F.js → Calculator-6FGNKOXU.js} +11 -11
- package/dist/{Calculator-ZXJPXG7F.js.map → Calculator-6FGNKOXU.js.map} +1 -1
- package/dist/ConfirmDialog-NPQMIGUR.js +4 -0
- package/dist/{ConfirmDialog-MTC7QMUJ.js.map → ConfirmDialog-NPQMIGUR.js.map} +1 -1
- package/dist/{CurrencyConverter-WSJ2BBSX.js → CurrencyConverter-FF7EXRYL.js} +11 -11
- package/dist/{CurrencyConverter-WSJ2BBSX.js.map → CurrencyConverter-FF7EXRYL.js.map} +1 -1
- package/dist/{Documents-ONGSXUJI.js → Documents-H3R7XSBH.js} +13 -13
- package/dist/{Documents-ONGSXUJI.js.map → Documents-H3R7XSBH.js.map} +1 -1
- package/dist/{Files-GQZMFWXQ.js → Files-ZHJIAUC2.js} +19 -19
- package/dist/{Files-GQZMFWXQ.js.map → Files-ZHJIAUC2.js.map} +1 -1
- package/dist/{Notepad-HM73XAM4.js → Notepad-VE7ISWRQ.js} +14 -14
- package/dist/{Notepad-HM73XAM4.js.map → Notepad-VE7ISWRQ.js.map} +1 -1
- package/dist/PdfViewer-SQBFYAGW.js +5 -0
- package/dist/{PdfViewer-M2YGZIYX.js.map → PdfViewer-SQBFYAGW.js.map} +1 -1
- package/dist/{PomodoroTimer-DG3LI5CX.js → PomodoroTimer-IR3WREED.js} +13 -13
- package/dist/{PomodoroTimer-DG3LI5CX.js.map → PomodoroTimer-IR3WREED.js.map} +1 -1
- package/dist/{Preview-TUSV4UMO.js → Preview-DAQGRNRM.js} +16 -16
- package/dist/{Preview-TUSV4UMO.js.map → Preview-DAQGRNRM.js.map} +1 -1
- package/dist/{Sidebar-BPU7RCZP.js → Sidebar-YW6H4NDJ.js} +3 -3
- package/dist/{Sidebar-BPU7RCZP.js.map → Sidebar-YW6H4NDJ.js.map} +1 -1
- package/dist/{Spreadsheet-3WTXCHYQ.js → Spreadsheet-HOCPHJOC.js} +14 -14
- package/dist/{Spreadsheet-3WTXCHYQ.js.map → Spreadsheet-HOCPHJOC.js.map} +1 -1
- package/dist/{Stock-YMPOMUAW.js → Stock-LVRQPURG.js} +11 -11
- package/dist/{Stock-YMPOMUAW.js.map → Stock-LVRQPURG.js.map} +1 -1
- package/dist/{Weather-NZO3CWLH.js → Weather-LZQGVDJL.js} +11 -11
- package/dist/{Weather-NZO3CWLH.js.map → Weather-LZQGVDJL.js.map} +1 -1
- package/dist/{WorldClock-HUC6D3AD.js → WorldClock-XPD7WOZT.js} +11 -11
- package/dist/{WorldClock-HUC6D3AD.js.map → WorldClock-XPD7WOZT.js.map} +1 -1
- package/dist/apps/index.d.ts +2 -2
- package/dist/apps/index.js +30 -30
- package/dist/apps/index.js.map +1 -1
- package/dist/brand.css +1 -1
- package/dist/{chunk-CT3HVZRZ.js → chunk-5O42JXQE.js} +2 -2
- package/dist/chunk-5O42JXQE.js.map +1 -0
- package/dist/{chunk-CGXMWHQW.js → chunk-5RPTS3BT.js} +3 -3
- package/dist/{chunk-CGXMWHQW.js.map → chunk-5RPTS3BT.js.map} +1 -1
- package/dist/{chunk-D276EMXS.js → chunk-6XJEJWNJ.js} +7 -3
- package/dist/chunk-6XJEJWNJ.js.map +1 -0
- package/dist/{chunk-I464GYJJ.js → chunk-BE7FZOFU.js} +2 -2
- package/dist/chunk-BE7FZOFU.js.map +1 -0
- package/dist/{chunk-CJYO4RVV.js → chunk-COWYSHG2.js} +5 -5
- package/dist/chunk-COWYSHG2.js.map +1 -0
- package/dist/{chunk-3L463T5H.js → chunk-DVZWYWSD.js} +2 -2
- package/dist/chunk-DVZWYWSD.js.map +1 -0
- package/dist/{chunk-MQPX6ERJ.js → chunk-E7TB6WD2.js} +4 -4
- package/dist/{chunk-MQPX6ERJ.js.map → chunk-E7TB6WD2.js.map} +1 -1
- package/dist/{chunk-SEWF4O3H.js → chunk-FIHOGVUP.js} +3 -3
- package/dist/chunk-FIHOGVUP.js.map +1 -0
- package/dist/{chunk-TQURTLK2.js → chunk-HUBJAUGG.js} +5 -5
- package/dist/{chunk-TQURTLK2.js.map → chunk-HUBJAUGG.js.map} +1 -1
- package/dist/{chunk-XH3ELPQZ.js → chunk-I2TAAJHS.js} +3 -3
- package/dist/chunk-I2TAAJHS.js.map +1 -0
- package/dist/{chunk-ZKHD4J73.js → chunk-ICTRCKUE.js} +10 -10
- package/dist/chunk-ICTRCKUE.js.map +1 -0
- package/dist/{chunk-E3TWIN7Z.js → chunk-JOPU6WPY.js} +7 -6
- package/dist/chunk-JOPU6WPY.js.map +1 -0
- package/dist/{chunk-7MA5XBWD.js → chunk-PVPPAWVM.js} +5 -5
- package/dist/{chunk-7MA5XBWD.js.map → chunk-PVPPAWVM.js.map} +1 -1
- package/dist/{chunk-FONEQRBH.js → chunk-R7QGMK6N.js} +3 -3
- package/dist/{chunk-FONEQRBH.js.map → chunk-R7QGMK6N.js.map} +1 -1
- package/dist/{chunk-LQTVTOSY.js → chunk-RT6DSB5Y.js} +45 -19
- package/dist/chunk-RT6DSB5Y.js.map +1 -0
- package/dist/{chunk-BFBWLCO6.js → chunk-TW7LPMVR.js} +2 -2
- package/dist/chunk-TW7LPMVR.js.map +1 -0
- package/dist/{chunk-EENVXIVU.js → chunk-UTYKLGGT.js} +3 -3
- package/dist/{chunk-EENVXIVU.js.map → chunk-UTYKLGGT.js.map} +1 -1
- package/dist/{chunk-KWEX4ZAF.js → chunk-VNJJCH5A.js} +3 -3
- package/dist/{chunk-KWEX4ZAF.js.map → chunk-VNJJCH5A.js.map} +1 -1
- package/dist/{chunk-TFXJRHJV.js → chunk-XJHZWSKV.js} +3 -3
- package/dist/{chunk-TFXJRHJV.js.map → chunk-XJHZWSKV.js.map} +1 -1
- package/dist/{chunk-VWZIGZFF.js → chunk-Y3GYJ7YR.js} +4 -4
- package/dist/{chunk-VWZIGZFF.js.map → chunk-Y3GYJ7YR.js.map} +1 -1
- package/dist/{chunk-BJ34QOR3.js → chunk-YA4EE7ST.js} +842 -272
- package/dist/chunk-YA4EE7ST.js.map +1 -0
- package/dist/{chunk-CLGNTGC5.js → chunk-YDHXWCCJ.js} +3 -3
- package/dist/{chunk-CLGNTGC5.js.map → chunk-YDHXWCCJ.js.map} +1 -1
- package/dist/{chunk-7IN7YZAL.js → chunk-YE6GUDGP.js} +4 -3
- package/dist/chunk-YE6GUDGP.js.map +1 -0
- package/dist/chunk-ZS7PMGUW.js +7 -0
- package/dist/{chunk-JMKYYPOF.js.map → chunk-ZS7PMGUW.js.map} +1 -1
- package/dist/file-intake/index.js +2 -2
- package/dist/{index-COwksV6G.d.ts → index-DVI9DMSu.d.ts} +383 -20
- package/dist/index.d.ts +3 -3
- package/dist/index.js +39 -39
- package/dist/index.js.map +1 -1
- package/dist/map/index.js +1 -1
- package/dist/markdown/index.d.ts +4 -4
- package/dist/markdown/index.js.map +1 -1
- package/dist/markup/index.d.ts +2 -2
- package/dist/markup/index.js.map +1 -1
- package/dist/page-tabs/index.js +5 -5
- package/dist/shell.css +1 -1
- package/dist/styles.css +4 -4
- package/dist/themes.css +3 -3
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +14 -14
- package/dist/ui.css +311 -18
- package/package.json +1 -1
- package/dist/ConfirmDialog-MTC7QMUJ.js +0 -4
- package/dist/PdfViewer-M2YGZIYX.js +0 -5
- package/dist/chunk-3L463T5H.js.map +0 -1
- package/dist/chunk-7IN7YZAL.js.map +0 -1
- package/dist/chunk-BFBWLCO6.js.map +0 -1
- package/dist/chunk-BJ34QOR3.js.map +0 -1
- package/dist/chunk-CJYO4RVV.js.map +0 -1
- package/dist/chunk-CT3HVZRZ.js.map +0 -1
- package/dist/chunk-D276EMXS.js.map +0 -1
- package/dist/chunk-E3TWIN7Z.js.map +0 -1
- package/dist/chunk-I464GYJJ.js.map +0 -1
- package/dist/chunk-JMKYYPOF.js +0 -7
- package/dist/chunk-LQTVTOSY.js.map +0 -1
- package/dist/chunk-SEWF4O3H.js.map +0 -1
- package/dist/chunk-XH3ELPQZ.js.map +0 -1
- package/dist/chunk-ZKHD4J73.js.map +0 -1
|
@@ -1,35 +1,26 @@
|
|
|
1
|
-
import { Breadcrumbs } from './chunk-
|
|
2
|
-
import { SidebarLayout } from './chunk-
|
|
1
|
+
import { Breadcrumbs } from './chunk-5RPTS3BT.js';
|
|
2
|
+
import { SidebarLayout } from './chunk-R7QGMK6N.js';
|
|
3
3
|
import { BrandMark } from './chunk-TRCWINHF.js';
|
|
4
|
-
import { toast_default } from './chunk-
|
|
5
|
-
import { useIsMobile, useShortcutLabel, useShellPrefs } from './chunk-
|
|
6
|
-
import { useFileIntake, humanSize, FileIntakeAlert } from './chunk-
|
|
7
|
-
import {
|
|
8
|
-
import { PopupMenu,
|
|
9
|
-
import { registerModalEscapeInterceptor, onOverlayOpen, Z_LAYERS, useDismissPopupsOnOpen, useFocusTrap, useScrollLock } from './chunk-
|
|
10
|
-
import { glassStyle } from './chunk-
|
|
11
|
-
import { useShellLocale, useShellStrings, DEFAULT_SHELL_STRINGS, currentShellStrings, formatPlain, formatFixed, formatPercent, splitAround } from './chunk-
|
|
4
|
+
import { toast_default } from './chunk-UTYKLGGT.js';
|
|
5
|
+
import { useIsMobile, useShortcutLabel, useShellPrefs } from './chunk-HUBJAUGG.js';
|
|
6
|
+
import { useFileIntake, humanSize, FileIntakeAlert } from './chunk-YDHXWCCJ.js';
|
|
7
|
+
import { iconButtonClasses, Button_default } from './chunk-RT6DSB5Y.js';
|
|
8
|
+
import { PopupMenu, PopupMenuDivider, PopupMenuLabel, itemLook } from './chunk-JOPU6WPY.js';
|
|
9
|
+
import { registerModalEscapeInterceptor, onOverlayOpen, Z_LAYERS, useDismissPopupsOnOpen, useFocusTrap, useScrollLock } from './chunk-I2TAAJHS.js';
|
|
10
|
+
import { glassStyle, glassFill } from './chunk-6XJEJWNJ.js';
|
|
11
|
+
import { useShellLocale, useShellStrings, DEFAULT_SHELL_STRINGS, currentShellStrings, formatPlain, formatFixed, formatPercent, splitAround } from './chunk-YE6GUDGP.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:
|
|
23
|
+
className: iconButtonClasses({ variant, size, className }),
|
|
33
24
|
...rest,
|
|
34
25
|
children
|
|
35
26
|
}
|
|
@@ -130,11 +121,142 @@ 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 roomAround(anchor, bounds, gap) {
|
|
137
|
+
return {
|
|
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
|
+
}
|
|
144
|
+
var within = (value, lo, hi) => Math.max(lo, Math.min(value, hi));
|
|
145
|
+
function placeBeside(anchor, size, side, bounds, gap) {
|
|
146
|
+
const room = roomAround(anchor, bounds, gap);
|
|
147
|
+
const spare = (s) => room[s] - (s === "top" || s === "bottom" ? size.height : size.width);
|
|
148
|
+
const order = [side, OPPOSITE[side], ...ACROSS[side]];
|
|
149
|
+
const chosen = order.find((s) => spare(s) >= 0) ?? order.reduce((best, s) => spare(s) > spare(best) ? s : best);
|
|
150
|
+
const centreX = (anchor.left + anchor.right) / 2;
|
|
151
|
+
const centreY = (anchor.top + anchor.bottom) / 2;
|
|
152
|
+
let left;
|
|
153
|
+
let top;
|
|
154
|
+
switch (chosen) {
|
|
155
|
+
case "top":
|
|
156
|
+
left = centreX - size.width / 2;
|
|
157
|
+
top = anchor.top - gap - size.height;
|
|
158
|
+
break;
|
|
159
|
+
case "bottom":
|
|
160
|
+
left = centreX - size.width / 2;
|
|
161
|
+
top = anchor.bottom + gap;
|
|
162
|
+
break;
|
|
163
|
+
case "left":
|
|
164
|
+
left = anchor.left - gap - size.width;
|
|
165
|
+
top = centreY - size.height / 2;
|
|
166
|
+
break;
|
|
167
|
+
case "right":
|
|
168
|
+
left = anchor.right + gap;
|
|
169
|
+
top = centreY - size.height / 2;
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
side: chosen,
|
|
174
|
+
left: within(left, bounds.left + VIEWPORT_MARGIN, bounds.right - VIEWPORT_MARGIN - size.width),
|
|
175
|
+
top: within(top, bounds.top + VIEWPORT_MARGIN, bounds.bottom - VIEWPORT_MARGIN - size.height)
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function placeArrow(anchor, placed, size, inset, depth) {
|
|
179
|
+
const { side, left, top } = placed;
|
|
180
|
+
const right = left + size.width;
|
|
181
|
+
const bottom = top + size.height;
|
|
182
|
+
const clearance = {
|
|
183
|
+
top: anchor.top - bottom,
|
|
184
|
+
bottom: top - anchor.bottom,
|
|
185
|
+
left: anchor.left - right,
|
|
186
|
+
right: left - anchor.right
|
|
187
|
+
}[side];
|
|
188
|
+
if (clearance < depth) return null;
|
|
189
|
+
const along = (target, start, length) => length < 2 * inset ? start + length / 2 : Math.max(start + inset, Math.min(target, start + length - inset));
|
|
190
|
+
const centreX = (anchor.left + anchor.right) / 2;
|
|
191
|
+
const centreY = (anchor.top + anchor.bottom) / 2;
|
|
192
|
+
switch (side) {
|
|
193
|
+
case "top":
|
|
194
|
+
return { side, x: along(centreX, left, size.width), y: bottom };
|
|
195
|
+
case "bottom":
|
|
196
|
+
return { side, x: along(centreX, left, size.width), y: top };
|
|
197
|
+
case "left":
|
|
198
|
+
return { side, x: right, y: along(centreY, top, size.height) };
|
|
199
|
+
case "right":
|
|
200
|
+
return { side, x: left, y: along(centreY, top, size.height) };
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function followAnchor(anchor, onMove, watch) {
|
|
204
|
+
let lastLeft = NaN, lastTop = NaN, lastRight = NaN, lastBottom = NaN, lastWatched = NaN;
|
|
205
|
+
const remember = () => {
|
|
206
|
+
const rect = anchor()?.getBoundingClientRect();
|
|
207
|
+
if (!rect) return false;
|
|
208
|
+
const watched = watch ? watch() : NaN;
|
|
209
|
+
const moved = rect.left !== lastLeft || rect.top !== lastTop || rect.right !== lastRight || rect.bottom !== lastBottom || watched !== lastWatched && !(Number.isNaN(watched) && Number.isNaN(lastWatched));
|
|
210
|
+
lastLeft = rect.left;
|
|
211
|
+
lastTop = rect.top;
|
|
212
|
+
lastRight = rect.right;
|
|
213
|
+
lastBottom = rect.bottom;
|
|
214
|
+
lastWatched = watched;
|
|
215
|
+
return moved;
|
|
216
|
+
};
|
|
217
|
+
remember();
|
|
218
|
+
const run = () => {
|
|
219
|
+
remember();
|
|
220
|
+
onMove();
|
|
221
|
+
};
|
|
222
|
+
let raf = requestAnimationFrame(function tick() {
|
|
223
|
+
if (remember()) onMove();
|
|
224
|
+
raf = requestAnimationFrame(tick);
|
|
225
|
+
});
|
|
226
|
+
window.addEventListener("scroll", run, true);
|
|
227
|
+
window.addEventListener("resize", run);
|
|
228
|
+
return () => {
|
|
229
|
+
cancelAnimationFrame(raf);
|
|
230
|
+
window.removeEventListener("scroll", run, true);
|
|
231
|
+
window.removeEventListener("resize", run);
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function placeMenu({ trigger, menu, bounds, align, side }) {
|
|
235
|
+
const room = roomAround(trigger, bounds, MENU_GAP);
|
|
236
|
+
const other = side === "bottom" ? "top" : "bottom";
|
|
237
|
+
const chosen = menu.height > room[side] && (menu.height <= room[other] || room[other] > room[side]) ? other : side;
|
|
238
|
+
const maxHeight = Math.max(Math.min(menu.height, 96), room[chosen]);
|
|
239
|
+
const height = Math.min(menu.height, maxHeight);
|
|
240
|
+
const top = within(
|
|
241
|
+
chosen === "bottom" ? trigger.bottom + MENU_GAP : trigger.top - MENU_GAP - height,
|
|
242
|
+
bounds.top + VIEWPORT_MARGIN,
|
|
243
|
+
bounds.bottom - VIEWPORT_MARGIN - height
|
|
244
|
+
);
|
|
245
|
+
const maxWidth = Math.max(0, bounds.right - bounds.left - 2 * VIEWPORT_MARGIN);
|
|
246
|
+
const width = Math.min(menu.width, maxWidth);
|
|
247
|
+
const left = within(
|
|
248
|
+
align === "start" ? trigger.left : trigger.right - width,
|
|
249
|
+
bounds.left + VIEWPORT_MARGIN,
|
|
250
|
+
bounds.right - VIEWPORT_MARGIN - width
|
|
251
|
+
);
|
|
252
|
+
return { left, top, side: chosen, maxHeight, maxWidth };
|
|
253
|
+
}
|
|
133
254
|
function useDropdownPosition(triggerRef, open, options = {}) {
|
|
134
255
|
const {
|
|
135
256
|
matchTriggerWidth = false,
|
|
136
257
|
preferredMaxWidth = POPUP_MAX_WIDTH,
|
|
137
|
-
preferredMaxHeight = MENU_MAX_HEIGHT
|
|
258
|
+
preferredMaxHeight = MENU_MAX_HEIGHT,
|
|
259
|
+
popupRef
|
|
138
260
|
} = options;
|
|
139
261
|
const [pos, setPos] = useState(null);
|
|
140
262
|
useBrowserLayoutEffect(() => {
|
|
@@ -142,15 +264,10 @@ function useDropdownPosition(triggerRef, open, options = {}) {
|
|
|
142
264
|
setPos(null);
|
|
143
265
|
return;
|
|
144
266
|
}
|
|
145
|
-
let lastLeft = NaN, lastTop = NaN, lastRight = NaN, lastBottom = NaN;
|
|
146
267
|
const compute = () => {
|
|
147
268
|
const trigger = triggerRef.current;
|
|
148
269
|
const rect = trigger?.getBoundingClientRect();
|
|
149
270
|
if (!rect) return;
|
|
150
|
-
lastLeft = rect.left;
|
|
151
|
-
lastTop = rect.top;
|
|
152
|
-
lastRight = rect.right;
|
|
153
|
-
lastBottom = rect.bottom;
|
|
154
271
|
const bounds = popupBounds(trigger);
|
|
155
272
|
const spaceBelow = bounds.bottom - rect.bottom - MENU_GAP - VIEWPORT_MARGIN;
|
|
156
273
|
const spaceAbove = rect.top - bounds.top - MENU_GAP - VIEWPORT_MARGIN;
|
|
@@ -170,6 +287,13 @@ function useDropdownPosition(triggerRef, open, options = {}) {
|
|
|
170
287
|
Math.max(bounds.left + VIEWPORT_MARGIN, rect.left),
|
|
171
288
|
bounds.right - VIEWPORT_MARGIN - width
|
|
172
289
|
);
|
|
290
|
+
} else if (popupRef && bounds.right - VIEWPORT_MARGIN - rect.left < next.maxWidth && Math.min(rect.right, bounds.right - VIEWPORT_MARGIN) - bounds.left - VIEWPORT_MARGIN < next.maxWidth) {
|
|
291
|
+
const measured = popupRef.current?.offsetWidth ?? 0;
|
|
292
|
+
const width = measured > 0 ? Math.min(measured, next.maxWidth) : next.maxWidth;
|
|
293
|
+
next.left = Math.max(
|
|
294
|
+
bounds.left + VIEWPORT_MARGIN,
|
|
295
|
+
Math.min(rect.left, bounds.right - VIEWPORT_MARGIN - width)
|
|
296
|
+
);
|
|
173
297
|
} else if (bounds.right - VIEWPORT_MARGIN - rect.left < next.maxWidth) {
|
|
174
298
|
const rightEdge = Math.min(rect.right, bounds.right - VIEWPORT_MARGIN);
|
|
175
299
|
next.right = window.innerWidth - rightEdge;
|
|
@@ -185,21 +309,12 @@ function useDropdownPosition(triggerRef, open, options = {}) {
|
|
|
185
309
|
setPos(next);
|
|
186
310
|
};
|
|
187
311
|
compute();
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
});
|
|
195
|
-
window.addEventListener("scroll", compute, true);
|
|
196
|
-
window.addEventListener("resize", compute);
|
|
197
|
-
return () => {
|
|
198
|
-
cancelAnimationFrame(raf);
|
|
199
|
-
window.removeEventListener("scroll", compute, true);
|
|
200
|
-
window.removeEventListener("resize", compute);
|
|
201
|
-
};
|
|
202
|
-
}, [open, triggerRef, matchTriggerWidth, preferredMaxWidth, preferredMaxHeight]);
|
|
312
|
+
return followAnchor(
|
|
313
|
+
() => triggerRef.current,
|
|
314
|
+
compute,
|
|
315
|
+
popupRef ? () => popupRef.current?.offsetWidth ?? NaN : void 0
|
|
316
|
+
);
|
|
317
|
+
}, [open, triggerRef, matchTriggerWidth, preferredMaxWidth, preferredMaxHeight, popupRef]);
|
|
203
318
|
return pos;
|
|
204
319
|
}
|
|
205
320
|
|
|
@@ -1535,6 +1650,22 @@ function calendarNames(locale) {
|
|
|
1535
1650
|
localeNames.set(locale, names);
|
|
1536
1651
|
return names;
|
|
1537
1652
|
}
|
|
1653
|
+
var weekStarts = /* @__PURE__ */ new Map();
|
|
1654
|
+
function firstDayOfWeek(locale) {
|
|
1655
|
+
if (!locale) return 0;
|
|
1656
|
+
let first = weekStarts.get(locale);
|
|
1657
|
+
if (first === void 0) {
|
|
1658
|
+
first = 0;
|
|
1659
|
+
try {
|
|
1660
|
+
const tag = new Intl.Locale(locale);
|
|
1661
|
+
const info = typeof tag.getWeekInfo === "function" ? tag.getWeekInfo() : tag.weekInfo;
|
|
1662
|
+
if (info?.firstDay === 1) first = 1;
|
|
1663
|
+
} catch {
|
|
1664
|
+
}
|
|
1665
|
+
weekStarts.set(locale, first);
|
|
1666
|
+
}
|
|
1667
|
+
return first;
|
|
1668
|
+
}
|
|
1538
1669
|
var pad = (n) => String(n).padStart(2, "0");
|
|
1539
1670
|
function toKey(d) {
|
|
1540
1671
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
@@ -1576,7 +1707,7 @@ function Calendar({
|
|
|
1576
1707
|
month,
|
|
1577
1708
|
defaultMonth,
|
|
1578
1709
|
onMonthChange,
|
|
1579
|
-
weekStartsOn
|
|
1710
|
+
weekStartsOn: weekStartsOnProp,
|
|
1580
1711
|
quickJump = true,
|
|
1581
1712
|
"aria-label": ariaLabel,
|
|
1582
1713
|
className = ""
|
|
@@ -1585,7 +1716,10 @@ function Calendar({
|
|
|
1585
1716
|
const todayKey = useBrowserValue(readTodayKey, null);
|
|
1586
1717
|
const today = fromKey(todayKey);
|
|
1587
1718
|
const strings = useShellStrings().calendar;
|
|
1588
|
-
const
|
|
1719
|
+
const locale = useShellLocale();
|
|
1720
|
+
const names = calendarNames(locale);
|
|
1721
|
+
const localeWeekStart = useBrowserValue(() => firstDayOfWeek(locale), 0);
|
|
1722
|
+
const weekStartsOn = weekStartsOnProp ?? localeWeekStart;
|
|
1589
1723
|
const openingMonth = () => {
|
|
1590
1724
|
if (!today) return null;
|
|
1591
1725
|
const here = monthKey(today);
|
|
@@ -1834,7 +1968,13 @@ function DateRangePicker({
|
|
|
1834
1968
|
to,
|
|
1835
1969
|
onChange,
|
|
1836
1970
|
formatDisplay: formatDisplayProp,
|
|
1837
|
-
clearable
|
|
1971
|
+
clearable: clearableProp,
|
|
1972
|
+
required = false,
|
|
1973
|
+
name,
|
|
1974
|
+
id,
|
|
1975
|
+
"aria-labelledby": ariaLabelledBy,
|
|
1976
|
+
"aria-label": ariaLabel,
|
|
1977
|
+
weekStartsOn,
|
|
1838
1978
|
placeholder: placeholderProp,
|
|
1839
1979
|
fullWidth = false
|
|
1840
1980
|
}) {
|
|
@@ -1842,16 +1982,44 @@ function DateRangePicker({
|
|
|
1842
1982
|
const locale = useShellLocale();
|
|
1843
1983
|
const formatDisplay = formatDisplayProp ?? (locale ? localeFormatDisplay(locale) : defaultFormatDisplay);
|
|
1844
1984
|
const placeholder = placeholderProp ?? strings.placeholder;
|
|
1985
|
+
const clearable = clearableProp ?? !required;
|
|
1845
1986
|
const [open, setOpen] = useState(false);
|
|
1846
1987
|
const [tempFrom, setTempFrom] = useState(from);
|
|
1847
1988
|
const [tempTo, setTempTo] = useState(to);
|
|
1848
1989
|
const [activePreset, setActivePreset] = useState(null);
|
|
1849
1990
|
const ref = useRef(null);
|
|
1991
|
+
const triggerRef = useRef(null);
|
|
1850
1992
|
const panelRef = useRef(null);
|
|
1993
|
+
const panelId = useId();
|
|
1994
|
+
const descriptionId = useId();
|
|
1995
|
+
const [stacked, setStacked] = useState(false);
|
|
1851
1996
|
const pos = useDropdownPosition(ref, open, {
|
|
1852
1997
|
preferredMaxWidth: 520,
|
|
1853
|
-
preferredMaxHeight: 560
|
|
1998
|
+
preferredMaxHeight: stacked ? 720 : 560,
|
|
1999
|
+
popupRef: panelRef
|
|
1854
2000
|
});
|
|
2001
|
+
const sideRowRef = useRef(null);
|
|
2002
|
+
const sideWidth = useRef(null);
|
|
2003
|
+
useBrowserLayoutEffect(() => {
|
|
2004
|
+
const panel = panelRef.current;
|
|
2005
|
+
if (!open || !pos || !panel) return;
|
|
2006
|
+
const style = getComputedStyle(panel);
|
|
2007
|
+
const room = pos.maxWidth - (panel.offsetWidth - panel.clientWidth) - parseFloat(style.paddingLeft) - parseFloat(style.paddingRight);
|
|
2008
|
+
if (!stacked) {
|
|
2009
|
+
const natural = sideRowRef.current?.offsetWidth ?? 0;
|
|
2010
|
+
if (natural === 0) return;
|
|
2011
|
+
sideWidth.current = natural;
|
|
2012
|
+
if (natural > room + 0.5) setStacked(true);
|
|
2013
|
+
} else if (sideWidth.current !== null && sideWidth.current <= room) {
|
|
2014
|
+
setStacked(false);
|
|
2015
|
+
}
|
|
2016
|
+
});
|
|
2017
|
+
const [hasLabelElement, setHasLabelElement] = useState(false);
|
|
2018
|
+
useBrowserLayoutEffect(() => {
|
|
2019
|
+
const labelled = !!id && (triggerRef.current?.labels?.length ?? 0) > 0;
|
|
2020
|
+
if (labelled !== hasLabelElement) setHasLabelElement(labelled);
|
|
2021
|
+
});
|
|
2022
|
+
const namedElsewhere = !!ariaLabel || !!ariaLabelledBy || hasLabelElement;
|
|
1855
2023
|
const now = /* @__PURE__ */ new Date();
|
|
1856
2024
|
const [viewMonth, setViewMonth] = useState(() => monthKeyOf(from ? parseDate(from) : now));
|
|
1857
2025
|
const displayDate = (s) => s ? formatDisplay(s) : "";
|
|
@@ -1931,6 +2099,37 @@ function DateRangePicker({
|
|
|
1931
2099
|
setOpen(false);
|
|
1932
2100
|
};
|
|
1933
2101
|
const displayText = from && to ? `${displayDate(from)} \u2014 ${displayDate(to)}` : from ? strings.fromOnly(displayDate(from)) : to ? strings.toOnly(displayDate(to)) : "";
|
|
2102
|
+
const names = calendarNames(locale);
|
|
2103
|
+
const spoken = (iso) => {
|
|
2104
|
+
const d = fromKey(iso);
|
|
2105
|
+
return d ? names.longDate(d.getFullYear(), d.getMonth(), d.getDate()) : iso;
|
|
2106
|
+
};
|
|
2107
|
+
const description = from && to ? strings.range(spoken(from), spoken(to)) : from ? strings.fromOnly(spoken(from)) : to ? strings.toOnly(spoken(to)) : placeholder;
|
|
2108
|
+
const presetClass = (key) => stacked ? `rounded-md border px-2.5 py-1 text-sm transition-colors ${activePreset === key ? "border-blue-300 bg-blue-50 text-blue-700 font-medium" : "border-gray-200 text-gray-700 hover:bg-gray-50"}` : `text-left px-3 py-1.5 text-sm rounded-md transition-colors ${activePreset === key ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`;
|
|
2109
|
+
const presets = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2110
|
+
PRESETS.map((label) => /* @__PURE__ */ jsx("button", { type: "button", onClick: () => handlePreset(label), className: presetClass(label), children: strings[label] }, label)),
|
|
2111
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setActivePreset("Custom"), className: presetClass("Custom"), children: strings.custom })
|
|
2112
|
+
] });
|
|
2113
|
+
const calendar = (
|
|
2114
|
+
// The grid, its keyboard model and its ARIA all come from Calendar, which
|
|
2115
|
+
// is also what DatePicker draws — so a range and a single date look and
|
|
2116
|
+
// behave like the same control. This used to be 95 lines of hand-built
|
|
2117
|
+
// cells here with no arrow keys and a day whose accessible name was its
|
|
2118
|
+
// number.
|
|
2119
|
+
/* @__PURE__ */ jsx(
|
|
2120
|
+
Calendar,
|
|
2121
|
+
{
|
|
2122
|
+
mode: "range",
|
|
2123
|
+
value: tempFrom || null,
|
|
2124
|
+
endValue: tempTo || null,
|
|
2125
|
+
month: viewMonth,
|
|
2126
|
+
onMonthChange: setViewMonth,
|
|
2127
|
+
onSelect: handleCalendarSelect,
|
|
2128
|
+
weekStartsOn,
|
|
2129
|
+
"aria-label": strings.dialog
|
|
2130
|
+
}
|
|
2131
|
+
)
|
|
2132
|
+
);
|
|
1934
2133
|
return /* @__PURE__ */ jsxs("div", { className: `relative${fullWidth ? " w-full" : ""}`, ref, children: [
|
|
1935
2134
|
/* @__PURE__ */ jsxs(
|
|
1936
2135
|
"div",
|
|
@@ -1940,13 +2139,20 @@ function DateRangePicker({
|
|
|
1940
2139
|
/* @__PURE__ */ jsxs(
|
|
1941
2140
|
"button",
|
|
1942
2141
|
{
|
|
2142
|
+
ref: triggerRef,
|
|
1943
2143
|
type: "button",
|
|
1944
2144
|
onClick: handleOpen,
|
|
1945
2145
|
"aria-haspopup": "dialog",
|
|
1946
2146
|
"aria-expanded": open,
|
|
2147
|
+
id,
|
|
2148
|
+
"aria-label": ariaLabel,
|
|
2149
|
+
"aria-labelledby": ariaLabelledBy,
|
|
2150
|
+
"aria-describedby": namedElsewhere ? descriptionId : void 0,
|
|
2151
|
+
"aria-controls": open ? panelId : void 0,
|
|
2152
|
+
"aria-required": required || void 0,
|
|
1947
2153
|
className: `inline-flex items-center gap-2 rosh-focus-ring${fullWidth ? " min-w-0 flex-1 justify-start" : ""}`,
|
|
1948
2154
|
children: [
|
|
1949
|
-
/* @__PURE__ */ jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
|
|
2155
|
+
/* @__PURE__ */ jsx("svg", { className: "w-4 h-4 shrink-0", fill: "none", stroke: "currentColor", strokeWidth: "2", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
|
|
1950
2156
|
/* @__PURE__ */ jsx("span", { className: "truncate", children: displayText || placeholder })
|
|
1951
2157
|
]
|
|
1952
2158
|
}
|
|
@@ -1964,13 +2170,20 @@ function DateRangePicker({
|
|
|
1964
2170
|
]
|
|
1965
2171
|
}
|
|
1966
2172
|
),
|
|
2173
|
+
namedElsewhere && /* @__PURE__ */ jsx("span", { id: descriptionId, className: "sr-only", children: description }),
|
|
2174
|
+
name && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2175
|
+
/* @__PURE__ */ jsx("input", { type: "hidden", name: name.from, value: from }),
|
|
2176
|
+
/* @__PURE__ */ jsx("input", { type: "hidden", name: name.to, value: to })
|
|
2177
|
+
] }),
|
|
1967
2178
|
open && createPortal(
|
|
1968
2179
|
/* @__PURE__ */ jsxs(
|
|
1969
2180
|
"div",
|
|
1970
2181
|
{
|
|
1971
2182
|
ref: panelRef,
|
|
2183
|
+
id: panelId,
|
|
1972
2184
|
role: "dialog",
|
|
1973
2185
|
"aria-label": strings.dialog,
|
|
2186
|
+
"data-layout": stacked ? "stacked" : "side",
|
|
1974
2187
|
className: "fixed rounded-2xl p-4",
|
|
1975
2188
|
style: {
|
|
1976
2189
|
zIndex: Z_LAYERS.popup,
|
|
@@ -1980,8 +2193,9 @@ function DateRangePicker({
|
|
|
1980
2193
|
bottom: pos?.bottom,
|
|
1981
2194
|
// The panel states its own size. `max-content` is the calendar plus
|
|
1982
2195
|
// the presets column at whatever font size the reader has, and the
|
|
1983
|
-
// cap is what the owning window allows.
|
|
1984
|
-
|
|
2196
|
+
// cap is what the owning window allows. Stacked, it is the cap
|
|
2197
|
+
// itself: the calendar fills it, and its days are bigger targets.
|
|
2198
|
+
width: stacked && pos ? pos.maxWidth : "max-content",
|
|
1985
2199
|
maxWidth: pos?.maxWidth,
|
|
1986
2200
|
maxHeight: pos?.maxHeight,
|
|
1987
2201
|
overflowY: "auto",
|
|
@@ -1991,53 +2205,29 @@ function DateRangePicker({
|
|
|
1991
2205
|
...glassStyle()
|
|
1992
2206
|
},
|
|
1993
2207
|
children: [
|
|
1994
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-3", children: [
|
|
1995
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2208
|
+
/* @__PURE__ */ jsxs("div", { className: stacked ? "mb-3 flex flex-wrap items-center gap-x-4 gap-y-2" : "flex items-center gap-3 mb-3", children: [
|
|
2209
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 whitespace-nowrap", children: [
|
|
1996
2210
|
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-500", children: strings.from }),
|
|
1997
2211
|
/* @__PURE__ */ jsx("span", { className: `text-sm px-2 py-1 rounded border min-w-[90px] ${tempFrom ? "border-blue-300 bg-blue-50 text-blue-700" : "border-gray-200 bg-gray-50 text-gray-400"}`, children: tempFrom ? displayDate(tempFrom) : strings.start })
|
|
1998
2212
|
] }),
|
|
1999
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-300", children: "\u2014" }),
|
|
2000
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2213
|
+
!stacked && /* @__PURE__ */ jsx("span", { className: "text-gray-300", children: "\u2014" }),
|
|
2214
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 whitespace-nowrap", children: [
|
|
2001
2215
|
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-500", children: strings.to }),
|
|
2002
2216
|
/* @__PURE__ */ jsx("span", { className: `text-sm px-2 py-1 rounded border min-w-[90px] ${tempTo ? "border-blue-300 bg-blue-50 text-blue-700" : "border-gray-200 bg-gray-50 text-gray-400"}`, children: tempTo ? displayDate(tempTo) : strings.end })
|
|
2003
2217
|
] })
|
|
2004
2218
|
] }),
|
|
2005
|
-
/* @__PURE__ */ jsxs(
|
|
2006
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
onSelect: handleCalendarSelect,
|
|
2015
|
-
"aria-label": strings.dialog
|
|
2016
|
-
}
|
|
2017
|
-
) }),
|
|
2018
|
-
/* @__PURE__ */ jsxs("div", { className: "border-l border-gray-200 pl-4 flex flex-col gap-1 min-w-[130px]", children: [
|
|
2019
|
-
PRESETS.map((label) => /* @__PURE__ */ jsx(
|
|
2020
|
-
"button",
|
|
2021
|
-
{
|
|
2022
|
-
type: "button",
|
|
2023
|
-
onClick: () => handlePreset(label),
|
|
2024
|
-
className: `text-left px-3 py-1.5 text-sm rounded-md transition-colors ${activePreset === label ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
|
|
2025
|
-
children: strings[label]
|
|
2026
|
-
},
|
|
2027
|
-
label
|
|
2028
|
-
)),
|
|
2029
|
-
/* @__PURE__ */ jsx(
|
|
2030
|
-
"button",
|
|
2031
|
-
{
|
|
2032
|
-
type: "button",
|
|
2033
|
-
onClick: () => setActivePreset("Custom"),
|
|
2034
|
-
className: `text-left px-3 py-1.5 text-sm rounded-md transition-colors ${activePreset === "Custom" ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-700 hover:bg-gray-50"}`,
|
|
2035
|
-
children: strings.custom
|
|
2036
|
-
}
|
|
2037
|
-
)
|
|
2219
|
+
stacked ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2220
|
+
/* @__PURE__ */ jsx("div", { className: "mb-3 flex flex-wrap gap-1.5", children: presets }),
|
|
2221
|
+
/* @__PURE__ */ jsx("div", { className: "w-full", children: calendar })
|
|
2222
|
+
] }) : (
|
|
2223
|
+
// `w-max`: the row is drawn at its natural width even in a panel
|
|
2224
|
+
// capped narrower, which is what the measurement above reads.
|
|
2225
|
+
/* @__PURE__ */ jsxs("div", { ref: sideRowRef, className: "flex w-max gap-4", children: [
|
|
2226
|
+
/* @__PURE__ */ jsx("div", { className: "w-64", children: calendar }),
|
|
2227
|
+
/* @__PURE__ */ jsx("div", { className: "border-l border-gray-200 pl-4 flex flex-col gap-1 min-w-[130px]", children: presets })
|
|
2038
2228
|
] })
|
|
2039
|
-
|
|
2040
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 mt-4 pt-3 border-t border-gray-200", children: [
|
|
2229
|
+
),
|
|
2230
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap justify-end gap-2 mt-4 pt-3 border-t border-gray-200", children: [
|
|
2041
2231
|
clearable && /* @__PURE__ */ jsx("button", { type: "button", onClick: handleClear, className: "px-3 py-1.5 text-sm text-gray-500 hover:text-gray-700", children: strings.clear }),
|
|
2042
2232
|
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setOpen(false), className: "px-3 py-1.5 text-sm text-gray-600 border border-gray-300 rounded-md hover:bg-gray-50", children: strings.cancel }),
|
|
2043
2233
|
/* @__PURE__ */ jsx(
|
|
@@ -2091,6 +2281,7 @@ var TimePicker = forwardRef(function TimePicker2({ value, onChange, min, max, in
|
|
|
2091
2281
|
});
|
|
2092
2282
|
var TimePicker_default = TimePicker;
|
|
2093
2283
|
var ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
|
|
2284
|
+
var GLOBAL_ATTRIBUTE = /^(aria|data)-/;
|
|
2094
2285
|
function toInputValue2(value) {
|
|
2095
2286
|
if (value === null || value === void 0 || value === "") return "";
|
|
2096
2287
|
if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : toISODate(value);
|
|
@@ -2120,12 +2311,22 @@ var DatePicker = forwardRef(function DatePicker2({
|
|
|
2120
2311
|
className = "",
|
|
2121
2312
|
"aria-label": ariaLabel,
|
|
2122
2313
|
"aria-describedby": describedBy,
|
|
2314
|
+
"aria-labelledby": labelledBy,
|
|
2123
2315
|
id,
|
|
2124
2316
|
name,
|
|
2125
2317
|
disabled,
|
|
2126
2318
|
placeholder,
|
|
2319
|
+
required,
|
|
2320
|
+
clearable: clearableProp,
|
|
2321
|
+
form,
|
|
2322
|
+
title,
|
|
2323
|
+
tabIndex,
|
|
2324
|
+
autoFocus,
|
|
2325
|
+
onFocus,
|
|
2326
|
+
onBlur,
|
|
2127
2327
|
...rest
|
|
2128
2328
|
}, ref) {
|
|
2329
|
+
const clearable = clearableProp ?? !required;
|
|
2129
2330
|
const current = toInputValue2(value);
|
|
2130
2331
|
const lo = toInputValue2(min);
|
|
2131
2332
|
const hi = toInputValue2(max);
|
|
@@ -2137,7 +2338,14 @@ var DatePicker = forwardRef(function DatePicker2({
|
|
|
2137
2338
|
const triggerRef = useRef(null);
|
|
2138
2339
|
const panelRef = useRef(null);
|
|
2139
2340
|
const panelId = useId();
|
|
2140
|
-
const
|
|
2341
|
+
const valueId = useId();
|
|
2342
|
+
const pos = useDropdownPosition(triggerRef, open, { popupRef: panelRef });
|
|
2343
|
+
const [hasLabelElement, setHasLabelElement] = useState(false);
|
|
2344
|
+
useBrowserLayoutEffect(() => {
|
|
2345
|
+
const labelled = !!id && (triggerRef.current?.labels?.length ?? 0) > 0;
|
|
2346
|
+
if (labelled !== hasLabelElement) setHasLabelElement(labelled);
|
|
2347
|
+
});
|
|
2348
|
+
const describeValue = !ariaLabel && (!!labelledBy || hasLabelElement);
|
|
2141
2349
|
useEffect(() => {
|
|
2142
2350
|
if (!open) return;
|
|
2143
2351
|
const onPointerDown = (e) => {
|
|
@@ -2179,33 +2387,56 @@ var DatePicker = forwardRef(function DatePicker2({
|
|
|
2179
2387
|
max: hi || void 0,
|
|
2180
2388
|
onChange: (event) => onChange?.(fromInputValue(event.target.value)),
|
|
2181
2389
|
className: inputClasses({ invalid, size, className }),
|
|
2390
|
+
"aria-labelledby": labelledBy,
|
|
2391
|
+
required,
|
|
2392
|
+
form,
|
|
2393
|
+
title,
|
|
2394
|
+
tabIndex,
|
|
2395
|
+
autoFocus,
|
|
2396
|
+
onFocus,
|
|
2397
|
+
onBlur,
|
|
2182
2398
|
...rest
|
|
2183
2399
|
}
|
|
2184
2400
|
);
|
|
2185
2401
|
}
|
|
2402
|
+
const triggerAttributes = Object.fromEntries(
|
|
2403
|
+
Object.entries(rest).filter(([key]) => GLOBAL_ATTRIBUTE.test(key))
|
|
2404
|
+
);
|
|
2405
|
+
const todayKey = toISODate(/* @__PURE__ */ new Date());
|
|
2406
|
+
const todayAllowed = (!lo || todayKey >= lo) && (!hi || todayKey <= hi);
|
|
2407
|
+
const placeholderText = placeholder ?? strings.placeholder;
|
|
2186
2408
|
return /* @__PURE__ */ jsxs("div", { ref: wrapRef, className: "relative", children: [
|
|
2187
|
-
/* @__PURE__ */ jsx("input", { ref, type: "hidden", name, value: current }),
|
|
2409
|
+
/* @__PURE__ */ jsx("input", { ref, type: "hidden", name, form, value: current }),
|
|
2188
2410
|
/* @__PURE__ */ jsxs(
|
|
2189
2411
|
"button",
|
|
2190
2412
|
{
|
|
2191
2413
|
ref: triggerRef,
|
|
2192
2414
|
type: "button",
|
|
2415
|
+
...triggerAttributes,
|
|
2193
2416
|
id,
|
|
2194
2417
|
disabled,
|
|
2418
|
+
title,
|
|
2419
|
+
tabIndex,
|
|
2420
|
+
autoFocus,
|
|
2421
|
+
onFocus,
|
|
2422
|
+
onBlur,
|
|
2195
2423
|
"aria-haspopup": "dialog",
|
|
2196
2424
|
"aria-expanded": open,
|
|
2197
2425
|
"aria-controls": open ? panelId : void 0,
|
|
2198
|
-
"aria-
|
|
2426
|
+
"aria-labelledby": labelledBy,
|
|
2427
|
+
"aria-describedby": [describeValue ? valueId : void 0, describedBy].filter(Boolean).join(" ") || void 0,
|
|
2199
2428
|
"aria-invalid": invalid || void 0,
|
|
2429
|
+
"aria-required": required || void 0,
|
|
2200
2430
|
"aria-label": ariaLabel ? `${ariaLabel}${current ? `, ${display(current, names)}` : ""}` : void 0,
|
|
2201
2431
|
onClick: () => setOpen((o) => !o),
|
|
2202
2432
|
className: `${inputClasses({ invalid, size, className })} flex items-center justify-between text-left`,
|
|
2203
2433
|
children: [
|
|
2204
|
-
/* @__PURE__ */ jsx("span", { className: current ? "text-gray-900" : "text-gray-400", children: current ? display(current, names) :
|
|
2434
|
+
/* @__PURE__ */ jsx("span", { className: current ? "text-gray-900" : "text-gray-400", children: current ? display(current, names) : placeholderText }),
|
|
2205
2435
|
/* @__PURE__ */ jsx("svg", { className: "h-4 w-4 shrink-0 text-gray-400", fill: "none", stroke: "currentColor", strokeWidth: "1.75", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8 7V3m8 4V3M4 11h16M5 7h14a1 1 0 011 1v11a1 1 0 01-1 1H5a1 1 0 01-1-1V8a1 1 0 011-1z" }) })
|
|
2206
2436
|
]
|
|
2207
2437
|
}
|
|
2208
2438
|
),
|
|
2439
|
+
describeValue && /* @__PURE__ */ jsx("span", { id: valueId, className: "sr-only", children: current ? display(current, names) : placeholderText }),
|
|
2209
2440
|
open && createPortal(
|
|
2210
2441
|
/* @__PURE__ */ jsxs(
|
|
2211
2442
|
"div",
|
|
@@ -2221,6 +2452,9 @@ var DatePicker = forwardRef(function DatePicker2({
|
|
|
2221
2452
|
right: pos?.right,
|
|
2222
2453
|
top: pos?.top,
|
|
2223
2454
|
bottom: pos?.bottom,
|
|
2455
|
+
// 288 px where it fits; narrower, never past the box's margins,
|
|
2456
|
+
// in a box that cannot hold that.
|
|
2457
|
+
maxWidth: pos?.maxWidth,
|
|
2224
2458
|
// Hidden for the first paint until the layout effect measures the
|
|
2225
2459
|
// trigger, so the panel never flashes at (0,0).
|
|
2226
2460
|
visibility: pos ? void 0 : "hidden"
|
|
@@ -2240,8 +2474,8 @@ var DatePicker = forwardRef(function DatePicker2({
|
|
|
2240
2474
|
}
|
|
2241
2475
|
}
|
|
2242
2476
|
),
|
|
2243
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex justify-between border-t border-gray-100 pt-2", children: [
|
|
2244
|
-
/* @__PURE__ */ jsx(
|
|
2477
|
+
(clearable || todayAllowed) && /* @__PURE__ */ jsxs("div", { className: "mt-2 flex justify-between border-t border-gray-100 pt-2", children: [
|
|
2478
|
+
clearable && /* @__PURE__ */ jsx(
|
|
2245
2479
|
"button",
|
|
2246
2480
|
{
|
|
2247
2481
|
type: "button",
|
|
@@ -2254,7 +2488,7 @@ var DatePicker = forwardRef(function DatePicker2({
|
|
|
2254
2488
|
children: strings.clear
|
|
2255
2489
|
}
|
|
2256
2490
|
),
|
|
2257
|
-
/* @__PURE__ */ jsx(
|
|
2491
|
+
todayAllowed && /* @__PURE__ */ jsx(
|
|
2258
2492
|
"button",
|
|
2259
2493
|
{
|
|
2260
2494
|
type: "button",
|
|
@@ -2263,7 +2497,7 @@ var DatePicker = forwardRef(function DatePicker2({
|
|
|
2263
2497
|
triggerRef.current?.focus();
|
|
2264
2498
|
onChange?.(/* @__PURE__ */ new Date());
|
|
2265
2499
|
},
|
|
2266
|
-
className: "rounded-md px-2 py-1 text-sm font-medium text-blue-600 hover:bg-blue-50",
|
|
2500
|
+
className: "ml-auto rounded-md px-2 py-1 text-sm font-medium text-blue-600 hover:bg-blue-50",
|
|
2267
2501
|
children: strings.today
|
|
2268
2502
|
}
|
|
2269
2503
|
)
|
|
@@ -4227,14 +4461,21 @@ function Accordion({
|
|
|
4227
4461
|
}) });
|
|
4228
4462
|
}
|
|
4229
4463
|
var SIDE_POS = {
|
|
4230
|
-
top: "bottom-full left-1/2 -translate-x-1/2 mb-
|
|
4231
|
-
bottom: "top-full left-1/2 -translate-x-1/2 mt-
|
|
4232
|
-
left: "right-full top-1/2 -translate-y-1/2 mr-
|
|
4233
|
-
right: "left-full top-1/2 -translate-y-1/2 ml-
|
|
4464
|
+
top: "bottom-full left-1/2 -translate-x-1/2 mb-3",
|
|
4465
|
+
bottom: "top-full left-1/2 -translate-x-1/2 mt-3",
|
|
4466
|
+
left: "right-full top-1/2 -translate-y-1/2 mr-3",
|
|
4467
|
+
right: "left-full top-1/2 -translate-y-1/2 ml-3"
|
|
4234
4468
|
};
|
|
4469
|
+
var GAP2 = 6;
|
|
4470
|
+
var ARROW_DEPTH = 6;
|
|
4471
|
+
var ARROW_INSET = 16;
|
|
4472
|
+
var samePlace = (a, b) => a.left === b.left && a.top === b.top && a.maxWidth === b.maxWidth && a.maxHeight === b.maxHeight && a.side === b.side && a.arrow?.left === b.arrow?.left && a.arrow?.top === b.arrow?.top;
|
|
4235
4473
|
function Tooltip({ content, side = "top", delay = 200, children }) {
|
|
4236
4474
|
const [show, setShow] = useState(false);
|
|
4475
|
+
const [placed, setPlaced] = useState(null);
|
|
4237
4476
|
const timer = useRef(void 0);
|
|
4477
|
+
const wrapRef = useRef(null);
|
|
4478
|
+
const tipRef = useRef(null);
|
|
4238
4479
|
const id = useId();
|
|
4239
4480
|
const open = () => {
|
|
4240
4481
|
timer.current = window.setTimeout(() => setShow(true), delay);
|
|
@@ -4244,6 +4485,43 @@ function Tooltip({ content, side = "top", delay = 200, children }) {
|
|
|
4244
4485
|
setShow(false);
|
|
4245
4486
|
};
|
|
4246
4487
|
useEffect(() => () => window.clearTimeout(timer.current), []);
|
|
4488
|
+
useBrowserLayoutEffect(() => {
|
|
4489
|
+
if (!show) {
|
|
4490
|
+
setPlaced(null);
|
|
4491
|
+
return;
|
|
4492
|
+
}
|
|
4493
|
+
const place = () => {
|
|
4494
|
+
const wrap = wrapRef.current;
|
|
4495
|
+
const tip = tipRef.current;
|
|
4496
|
+
if (!wrap || !tip) return;
|
|
4497
|
+
const bounds = popupBounds(wrap);
|
|
4498
|
+
const maxWidth = Math.max(0, bounds.right - bounds.left - 2 * VIEWPORT_MARGIN);
|
|
4499
|
+
const maxHeight = Math.max(0, bounds.bottom - bounds.top - 2 * VIEWPORT_MARGIN);
|
|
4500
|
+
tip.style.maxWidth = `${maxWidth}px`;
|
|
4501
|
+
tip.style.maxHeight = `${maxHeight}px`;
|
|
4502
|
+
const size = tip.getBoundingClientRect();
|
|
4503
|
+
if (size.width <= 0 || size.height <= 0) return;
|
|
4504
|
+
const anchor = wrap.getBoundingClientRect();
|
|
4505
|
+
const at = placeBeside(anchor, size, side, bounds, GAP2 + ARROW_DEPTH);
|
|
4506
|
+
const point = placeArrow(anchor, at, size, ARROW_INSET, ARROW_DEPTH);
|
|
4507
|
+
const next = {
|
|
4508
|
+
left: at.left - anchor.left,
|
|
4509
|
+
top: at.top - anchor.top,
|
|
4510
|
+
maxWidth,
|
|
4511
|
+
maxHeight,
|
|
4512
|
+
side: at.side,
|
|
4513
|
+
arrow: point && { left: point.x - anchor.left, top: point.y - anchor.top }
|
|
4514
|
+
};
|
|
4515
|
+
setPlaced((prev) => prev && samePlace(prev, next) ? prev : next);
|
|
4516
|
+
};
|
|
4517
|
+
place();
|
|
4518
|
+
window.addEventListener("scroll", place, true);
|
|
4519
|
+
window.addEventListener("resize", place);
|
|
4520
|
+
return () => {
|
|
4521
|
+
window.removeEventListener("scroll", place, true);
|
|
4522
|
+
window.removeEventListener("resize", place);
|
|
4523
|
+
};
|
|
4524
|
+
}, [show, side, content]);
|
|
4247
4525
|
useEffect(() => {
|
|
4248
4526
|
if (!show) return;
|
|
4249
4527
|
return registerModalEscapeInterceptor((event) => {
|
|
@@ -4256,9 +4534,12 @@ function Tooltip({ content, side = "top", delay = 200, children }) {
|
|
|
4256
4534
|
const trigger = isValidElement(children) ? cloneElement(children, {
|
|
4257
4535
|
"aria-describedby": [children.props["aria-describedby"], describedBy].filter(Boolean).join(" ") || void 0
|
|
4258
4536
|
}) : children;
|
|
4537
|
+
const glass = show ? glassStyle() : void 0;
|
|
4538
|
+
const fill = show ? glassFill() : void 0;
|
|
4259
4539
|
return /* @__PURE__ */ jsxs(
|
|
4260
4540
|
"span",
|
|
4261
4541
|
{
|
|
4542
|
+
ref: wrapRef,
|
|
4262
4543
|
className: "relative inline-flex",
|
|
4263
4544
|
"aria-describedby": isValidElement(children) ? void 0 : describedBy,
|
|
4264
4545
|
onMouseEnter: open,
|
|
@@ -4267,15 +4548,61 @@ function Tooltip({ content, side = "top", delay = 200, children }) {
|
|
|
4267
4548
|
onBlur: close,
|
|
4268
4549
|
children: [
|
|
4269
4550
|
trigger,
|
|
4270
|
-
show &&
|
|
4551
|
+
show && // `w-max` rather than the `whitespace-nowrap` this was: both keep a
|
|
4552
|
+
// short bubble on one line however narrow its trigger, but only
|
|
4553
|
+
// `w-max` lets the width cap above take effect — a bubble longer than
|
|
4554
|
+
// its window is wide wraps inside it instead of running past both
|
|
4555
|
+
// edges. `whitespace-normal` and `text-start` so a trigger inside a
|
|
4556
|
+
// `nowrap` or right-aligned cell does not hand the bubble its own.
|
|
4557
|
+
// `box-border` so the caps measure the whole bubble, padding and
|
|
4558
|
+
// border included, in a host without Tailwind's preflight.
|
|
4559
|
+
// Nothing here animates, so there is no motion to reduce.
|
|
4560
|
+
/* @__PURE__ */ jsx(
|
|
4271
4561
|
"span",
|
|
4272
4562
|
{
|
|
4563
|
+
ref: tipRef,
|
|
4273
4564
|
id,
|
|
4274
4565
|
role: "tooltip",
|
|
4275
|
-
className: `pointer-events-none absolute z-[300] whitespace-
|
|
4276
|
-
style:
|
|
4566
|
+
className: `pointer-events-none absolute z-[300] box-border w-max overflow-hidden whitespace-normal break-words text-start rounded-md px-2 py-1 text-xs text-gray-800 ${placed ? "" : SIDE_POS[side]}`,
|
|
4567
|
+
style: {
|
|
4568
|
+
...glass,
|
|
4569
|
+
...placed && {
|
|
4570
|
+
left: placed.left,
|
|
4571
|
+
top: placed.top,
|
|
4572
|
+
maxWidth: placed.maxWidth,
|
|
4573
|
+
maxHeight: placed.maxHeight
|
|
4574
|
+
}
|
|
4575
|
+
},
|
|
4277
4576
|
children: content
|
|
4278
4577
|
}
|
|
4578
|
+
),
|
|
4579
|
+
show && (!placed || placed.arrow) && // The arrow is the bubble's SIBLING, not its child: the bubble is
|
|
4580
|
+
// `overflow: hidden` for its height cap, and an arrow inside it would
|
|
4581
|
+
// be cut off at the very edge it is meant to stand out from. Drawn after
|
|
4582
|
+
// the bubble on the same layer, so it lies over the bubble's border
|
|
4583
|
+
// where the two meet and there is no seam.
|
|
4584
|
+
//
|
|
4585
|
+
// `data-side` is the side the BUBBLE is on, after any flip; ui.css
|
|
4586
|
+
// turns it into which way the arrow points and which two of its edges
|
|
4587
|
+
// carry the border. Unmeasured, it is the side asked for and ui.css
|
|
4588
|
+
// centres the arrow there, as `SIDE_POS` centres the bubble.
|
|
4589
|
+
//
|
|
4590
|
+
// Decorative: the bubble's text is the description, and the arrow says
|
|
4591
|
+
// nothing a screen reader needs.
|
|
4592
|
+
/* @__PURE__ */ jsx(
|
|
4593
|
+
"span",
|
|
4594
|
+
{
|
|
4595
|
+
"aria-hidden": "true",
|
|
4596
|
+
className: "rosh-tooltip-arrow",
|
|
4597
|
+
"data-side": placed?.side ?? side,
|
|
4598
|
+
style: {
|
|
4599
|
+
background: fill,
|
|
4600
|
+
// The bubble's border as one value, for ui.css to put on the two
|
|
4601
|
+
// edges that face outward — the side's own rule picks which.
|
|
4602
|
+
["--rosh-tooltip-edge"]: glass?.border,
|
|
4603
|
+
...placed?.arrow && { left: placed.arrow.left, top: placed.arrow.top }
|
|
4604
|
+
}
|
|
4605
|
+
}
|
|
4279
4606
|
)
|
|
4280
4607
|
]
|
|
4281
4608
|
}
|
|
@@ -4455,7 +4782,7 @@ function reportUnknownSeverity(component, described) {
|
|
|
4455
4782
|
if (reported.has(key)) return;
|
|
4456
4783
|
reported.add(key);
|
|
4457
4784
|
console.error(
|
|
4458
|
-
`[
|
|
4785
|
+
`[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
4786
|
);
|
|
4460
4787
|
}
|
|
4461
4788
|
function resolveSeverity(severity, component) {
|
|
@@ -4512,7 +4839,7 @@ function MetricBar({
|
|
|
4512
4839
|
if (scale == null) {
|
|
4513
4840
|
warnOnce(
|
|
4514
4841
|
`MetricBar:max:${String(max)}`,
|
|
4515
|
-
`[
|
|
4842
|
+
`[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
4843
|
);
|
|
4517
4844
|
}
|
|
4518
4845
|
const supplied = resolveSeverity(severity, "MetricBar");
|
|
@@ -8334,6 +8661,12 @@ function TopNav({ items, activeKey, onSelect, brand, actions, className }) {
|
|
|
8334
8661
|
}
|
|
8335
8662
|
);
|
|
8336
8663
|
}
|
|
8664
|
+
var TRIGGER_CLASS = "inline-flex items-center justify-center rounded-md text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900 rosh-focus-ring focus-visible:ring-2 focus-visible:ring-[color:var(--rosh-focus-ring-solid)] disabled:cursor-not-allowed disabled:opacity-60";
|
|
8665
|
+
var OWNS_Z = /(^|[\s:])!?z-/;
|
|
8666
|
+
var TYPEAHEAD_MS = 500;
|
|
8667
|
+
var CHECK = /* @__PURE__ */ jsx("svg", { "aria-hidden": true, className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.5 12.75l6 6 9-13.5" }) });
|
|
8668
|
+
var isLink = (entry) => entry.type === "link" || entry.type === void 0 && typeof entry.href === "string";
|
|
8669
|
+
var isFocusable = (entry) => !!entry && entry.type !== "label" && entry.type !== "divider" && !entry.disabled;
|
|
8337
8670
|
function DropdownMenu({
|
|
8338
8671
|
trigger,
|
|
8339
8672
|
items,
|
|
@@ -8341,35 +8674,84 @@ function DropdownMenu({
|
|
|
8341
8674
|
side = "bottom",
|
|
8342
8675
|
"aria-label": ariaLabel,
|
|
8343
8676
|
className = "",
|
|
8677
|
+
triggerClassName,
|
|
8678
|
+
menuClassName = "",
|
|
8679
|
+
minWidth = 180,
|
|
8680
|
+
linkAs,
|
|
8344
8681
|
disabled
|
|
8345
8682
|
}) {
|
|
8346
8683
|
const [open, setOpen] = useState(false);
|
|
8347
|
-
const [active, setActive] = useState(
|
|
8684
|
+
const [active, setActive] = useState(-1);
|
|
8348
8685
|
const wrapRef = useRef(null);
|
|
8349
8686
|
const triggerRef = useRef(null);
|
|
8350
|
-
const
|
|
8687
|
+
const menuRef = useRef(null);
|
|
8688
|
+
const typed = useRef({ text: "", at: 0 });
|
|
8351
8689
|
const menuId = useId();
|
|
8690
|
+
const triggerId = useId();
|
|
8352
8691
|
const close = useCallback((restoreFocus) => {
|
|
8353
8692
|
setOpen(false);
|
|
8354
8693
|
if (restoreFocus) triggerRef.current?.focus();
|
|
8355
8694
|
}, []);
|
|
8356
|
-
const
|
|
8357
|
-
|
|
8358
|
-
|
|
8359
|
-
|
|
8695
|
+
const focusableFrom = (from, step) => {
|
|
8696
|
+
const n = items.length;
|
|
8697
|
+
for (let i = 0; i < n; i += 1) {
|
|
8698
|
+
const at = ((from + step * i) % n + n) % n;
|
|
8699
|
+
if (isFocusable(items[at])) return at;
|
|
8360
8700
|
}
|
|
8361
|
-
return
|
|
8701
|
+
return -1;
|
|
8362
8702
|
};
|
|
8703
|
+
const surface = () => menuRef.current?.closest("[data-popup-menu-tree]") ?? null;
|
|
8363
8704
|
useEffect(() => {
|
|
8364
8705
|
if (!open) return;
|
|
8365
8706
|
const onPointerDown = (e) => {
|
|
8366
|
-
|
|
8707
|
+
const target = e.target;
|
|
8708
|
+
if (wrapRef.current?.contains(target) || surface()?.contains(target)) return;
|
|
8709
|
+
close(false);
|
|
8367
8710
|
};
|
|
8368
8711
|
document.addEventListener("pointerdown", onPointerDown, true);
|
|
8369
|
-
|
|
8712
|
+
const offOverlay = onOverlayOpen(() => close(false));
|
|
8713
|
+
return () => {
|
|
8714
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
8715
|
+
offOverlay();
|
|
8716
|
+
};
|
|
8370
8717
|
}, [open, close]);
|
|
8718
|
+
const place = useCallback(() => {
|
|
8719
|
+
const el = surface();
|
|
8720
|
+
const anchor = triggerRef.current;
|
|
8721
|
+
if (!el || !anchor) return;
|
|
8722
|
+
const s = el.style;
|
|
8723
|
+
s.left = "0px";
|
|
8724
|
+
s.top = "0px";
|
|
8725
|
+
s.maxWidth = "none";
|
|
8726
|
+
s.maxHeight = "none";
|
|
8727
|
+
const size = { width: el.offsetWidth, height: el.offsetHeight };
|
|
8728
|
+
const at = placeMenu({
|
|
8729
|
+
trigger: anchor.getBoundingClientRect(),
|
|
8730
|
+
menu: size,
|
|
8731
|
+
bounds: popupBounds(anchor),
|
|
8732
|
+
align,
|
|
8733
|
+
side
|
|
8734
|
+
});
|
|
8735
|
+
s.left = `${at.left}px`;
|
|
8736
|
+
s.top = `${at.top}px`;
|
|
8737
|
+
s.maxWidth = `${at.maxWidth}px`;
|
|
8738
|
+
s.maxHeight = `${at.maxHeight}px`;
|
|
8739
|
+
s.overflowY = size.height > at.maxHeight ? "auto" : "";
|
|
8740
|
+
el.dataset.side = at.side;
|
|
8741
|
+
el.dataset.align = align;
|
|
8742
|
+
}, [align, side]);
|
|
8743
|
+
useBrowserLayoutEffect(() => {
|
|
8744
|
+
if (open) place();
|
|
8745
|
+
});
|
|
8371
8746
|
useEffect(() => {
|
|
8372
|
-
if (open)
|
|
8747
|
+
if (!open) return;
|
|
8748
|
+
return followAnchor(() => triggerRef.current, place);
|
|
8749
|
+
}, [open, place]);
|
|
8750
|
+
useEffect(() => {
|
|
8751
|
+
if (!open) return;
|
|
8752
|
+
const menu = menuRef.current;
|
|
8753
|
+
const target = isFocusable(items[active]) ? menu?.querySelector(`[data-dropdown-index="${active}"]`) : null;
|
|
8754
|
+
(target ?? menu)?.focus({ preventScroll: true });
|
|
8373
8755
|
}, [open, active]);
|
|
8374
8756
|
useEffect(() => {
|
|
8375
8757
|
if (!open) return;
|
|
@@ -8386,80 +8768,212 @@ function DropdownMenu({
|
|
|
8386
8768
|
const onTriggerKeyDown = (e) => {
|
|
8387
8769
|
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " ") {
|
|
8388
8770
|
e.preventDefault();
|
|
8389
|
-
openAt(
|
|
8771
|
+
openAt(focusableFrom(0, 1));
|
|
8390
8772
|
} else if (e.key === "ArrowUp") {
|
|
8391
8773
|
e.preventDefault();
|
|
8392
|
-
openAt(
|
|
8774
|
+
openAt(focusableFrom(items.length - 1, -1));
|
|
8775
|
+
}
|
|
8776
|
+
};
|
|
8777
|
+
const typeahead = (e) => {
|
|
8778
|
+
const now = Date.now();
|
|
8779
|
+
const char = e.key.toLowerCase();
|
|
8780
|
+
const text = now - typed.current.at < TYPEAHEAD_MS ? typed.current.text + char : char;
|
|
8781
|
+
typed.current = { text, at: now };
|
|
8782
|
+
const repeated = [...text].every((c) => c === text[0]);
|
|
8783
|
+
const query = repeated ? text[0] : text;
|
|
8784
|
+
const from = repeated ? active + 1 : Math.max(active, 0);
|
|
8785
|
+
const menu = menuRef.current;
|
|
8786
|
+
const n = items.length;
|
|
8787
|
+
for (let i = 0; i < n; i += 1) {
|
|
8788
|
+
const at = ((from + i) % n + n) % n;
|
|
8789
|
+
if (!isFocusable(items[at])) continue;
|
|
8790
|
+
const label = menu?.querySelector(`[data-dropdown-index="${at}"]`)?.textContent?.trim().toLowerCase() ?? "";
|
|
8791
|
+
if (label.startsWith(query)) {
|
|
8792
|
+
e.preventDefault();
|
|
8793
|
+
setActive(at);
|
|
8794
|
+
return;
|
|
8795
|
+
}
|
|
8393
8796
|
}
|
|
8394
8797
|
};
|
|
8395
8798
|
const onMenuKeyDown = (e) => {
|
|
8396
8799
|
if (e.key === "ArrowDown") {
|
|
8397
8800
|
e.preventDefault();
|
|
8398
|
-
setActive(
|
|
8801
|
+
setActive(focusableFrom(active + 1, 1));
|
|
8399
8802
|
} else if (e.key === "ArrowUp") {
|
|
8400
8803
|
e.preventDefault();
|
|
8401
|
-
setActive(
|
|
8804
|
+
setActive(focusableFrom(active - 1, -1));
|
|
8402
8805
|
} else if (e.key === "Home") {
|
|
8403
8806
|
e.preventDefault();
|
|
8404
|
-
setActive(
|
|
8807
|
+
setActive(focusableFrom(0, 1));
|
|
8405
8808
|
} else if (e.key === "End") {
|
|
8406
8809
|
e.preventDefault();
|
|
8407
|
-
setActive(
|
|
8810
|
+
setActive(focusableFrom(items.length - 1, -1));
|
|
8408
8811
|
} else if (e.key === "Tab") {
|
|
8409
8812
|
e.preventDefault();
|
|
8410
8813
|
close(true);
|
|
8814
|
+
} else if (e.key === " ") {
|
|
8815
|
+
const target = e.target;
|
|
8816
|
+
if (target.matches?.("a[href]")) {
|
|
8817
|
+
e.preventDefault();
|
|
8818
|
+
target.click();
|
|
8819
|
+
}
|
|
8820
|
+
} else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
|
8821
|
+
typeahead(e);
|
|
8411
8822
|
}
|
|
8412
8823
|
};
|
|
8413
|
-
const
|
|
8414
|
-
if (
|
|
8824
|
+
const choose = (entry) => {
|
|
8825
|
+
if (entry.disabled) return;
|
|
8415
8826
|
close(true);
|
|
8416
|
-
|
|
8827
|
+
entry.onSelect();
|
|
8828
|
+
};
|
|
8829
|
+
const Link = linkAs ?? "a";
|
|
8830
|
+
const rowProps = (i, entry) => ({
|
|
8831
|
+
"data-dropdown-index": i,
|
|
8832
|
+
// One tab stop for the whole menu; the arrows move inside it.
|
|
8833
|
+
tabIndex: i === active ? 0 : -1,
|
|
8834
|
+
onMouseEnter: () => {
|
|
8835
|
+
if (!entry.disabled) setActive(i);
|
|
8836
|
+
}
|
|
8837
|
+
});
|
|
8838
|
+
const renderEntry = (entry, i) => {
|
|
8839
|
+
if (entry.type === "divider") {
|
|
8840
|
+
return /* @__PURE__ */ jsx("div", { role: "separator", children: /* @__PURE__ */ jsx(PopupMenuDivider, {}) }, entry.key);
|
|
8841
|
+
}
|
|
8842
|
+
if (entry.type === "label") {
|
|
8843
|
+
return /* @__PURE__ */ jsx("div", { id: `${menuId}-label-${i}`, children: /* @__PURE__ */ jsx(PopupMenuLabel, { children: entry.label }) }, entry.key);
|
|
8844
|
+
}
|
|
8845
|
+
if (entry.type === "radio") {
|
|
8846
|
+
const look2 = itemLook(false, entry.disabled, "");
|
|
8847
|
+
return /* @__PURE__ */ jsxs(
|
|
8848
|
+
"button",
|
|
8849
|
+
{
|
|
8850
|
+
type: "button",
|
|
8851
|
+
role: "menuitemradio",
|
|
8852
|
+
"aria-checked": entry.checked,
|
|
8853
|
+
disabled: entry.disabled,
|
|
8854
|
+
className: look2.className,
|
|
8855
|
+
style: look2.style,
|
|
8856
|
+
onClick: () => choose(entry),
|
|
8857
|
+
...rowProps(i, entry),
|
|
8858
|
+
children: [
|
|
8859
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "inline-flex h-4 w-4 shrink-0 items-center justify-center", children: entry.checked && CHECK }),
|
|
8860
|
+
entry.icon,
|
|
8861
|
+
entry.label
|
|
8862
|
+
]
|
|
8863
|
+
},
|
|
8864
|
+
entry.key
|
|
8865
|
+
);
|
|
8866
|
+
}
|
|
8867
|
+
if (isLink(entry)) {
|
|
8868
|
+
const look2 = itemLook(false, entry.disabled, `no-underline ${entry.current ? "font-medium" : ""}`);
|
|
8869
|
+
if (entry.disabled) {
|
|
8870
|
+
return /* @__PURE__ */ jsxs("a", { role: "menuitem", "aria-disabled": "true", className: look2.className, style: look2.style, ...rowProps(i, entry), children: [
|
|
8871
|
+
entry.icon,
|
|
8872
|
+
entry.label
|
|
8873
|
+
] }, entry.key);
|
|
8874
|
+
}
|
|
8875
|
+
return /* @__PURE__ */ jsxs(
|
|
8876
|
+
Link,
|
|
8877
|
+
{
|
|
8878
|
+
href: entry.href,
|
|
8879
|
+
role: "menuitem",
|
|
8880
|
+
"aria-current": entry.current ? "page" : void 0,
|
|
8881
|
+
className: look2.className,
|
|
8882
|
+
style: look2.style,
|
|
8883
|
+
onClick: () => close(true),
|
|
8884
|
+
...rowProps(i, entry),
|
|
8885
|
+
children: [
|
|
8886
|
+
entry.icon,
|
|
8887
|
+
entry.label
|
|
8888
|
+
]
|
|
8889
|
+
},
|
|
8890
|
+
entry.key
|
|
8891
|
+
);
|
|
8892
|
+
}
|
|
8893
|
+
const look = itemLook(entry.danger, entry.disabled, "");
|
|
8894
|
+
return /* @__PURE__ */ jsxs(
|
|
8895
|
+
"button",
|
|
8896
|
+
{
|
|
8897
|
+
type: "button",
|
|
8898
|
+
role: "menuitem",
|
|
8899
|
+
disabled: entry.disabled,
|
|
8900
|
+
className: look.className,
|
|
8901
|
+
style: look.style,
|
|
8902
|
+
onClick: () => choose(entry),
|
|
8903
|
+
...rowProps(i, entry),
|
|
8904
|
+
children: [
|
|
8905
|
+
entry.icon,
|
|
8906
|
+
entry.label
|
|
8907
|
+
]
|
|
8908
|
+
},
|
|
8909
|
+
entry.key
|
|
8910
|
+
);
|
|
8911
|
+
};
|
|
8912
|
+
const renderEntries = () => {
|
|
8913
|
+
const out = [];
|
|
8914
|
+
for (let i = 0; i < items.length; ) {
|
|
8915
|
+
const entry = items[i];
|
|
8916
|
+
if (entry.type !== "radio") {
|
|
8917
|
+
out.push(renderEntry(entry, i));
|
|
8918
|
+
i += 1;
|
|
8919
|
+
continue;
|
|
8920
|
+
}
|
|
8921
|
+
const start = i;
|
|
8922
|
+
const run = [];
|
|
8923
|
+
while (i < items.length && items[i].type === "radio") {
|
|
8924
|
+
run.push(renderEntry(items[i], i));
|
|
8925
|
+
i += 1;
|
|
8926
|
+
}
|
|
8927
|
+
const heading = items[start - 1]?.type === "label" ? `${menuId}-label-${start - 1}` : void 0;
|
|
8928
|
+
out.push(/* @__PURE__ */ jsx("div", { role: "group", "aria-labelledby": heading, children: run }, `group:${entry.key}`));
|
|
8929
|
+
}
|
|
8930
|
+
return out;
|
|
8931
|
+
};
|
|
8932
|
+
const menuStyle = {
|
|
8933
|
+
// The popup layer, as every portalled kit popup: above dialogs and the
|
|
8934
|
+
// window stack, so a menu opened in either is drawn over it. A caller that
|
|
8935
|
+
// layered it with a `z-…` class keeps its own.
|
|
8936
|
+
...OWNS_Z.test(menuClassName) ? {} : { zIndex: Z_LAYERS.popup },
|
|
8937
|
+
minWidth
|
|
8417
8938
|
};
|
|
8418
8939
|
return /* @__PURE__ */ jsxs("div", { ref: wrapRef, className: `relative inline-flex ${className}`.trim(), children: [
|
|
8419
8940
|
/* @__PURE__ */ jsx(
|
|
8420
8941
|
"button",
|
|
8421
8942
|
{
|
|
8422
8943
|
ref: triggerRef,
|
|
8944
|
+
id: triggerId,
|
|
8423
8945
|
type: "button",
|
|
8424
8946
|
"aria-haspopup": "menu",
|
|
8425
8947
|
"aria-expanded": open,
|
|
8426
8948
|
"aria-controls": open ? menuId : void 0,
|
|
8427
8949
|
"aria-label": ariaLabel,
|
|
8428
8950
|
disabled,
|
|
8429
|
-
onClick: () => open ? close(false) : openAt(
|
|
8951
|
+
onClick: () => open ? close(false) : openAt(focusableFrom(0, 1)),
|
|
8430
8952
|
onKeyDown: onTriggerKeyDown,
|
|
8431
|
-
className:
|
|
8953
|
+
className: triggerClassName ?? TRIGGER_CLASS,
|
|
8432
8954
|
children: trigger
|
|
8433
8955
|
}
|
|
8434
8956
|
),
|
|
8435
|
-
open &&
|
|
8957
|
+
open && // No `onClose`: PopupMenu's own dismissal calls the same callback for
|
|
8958
|
+
// Escape and for a click elsewhere, and those want opposite things.
|
|
8959
|
+
// Escape is the user putting the menu away, so focus goes back to the
|
|
8960
|
+
// trigger; a click elsewhere is them going somewhere, and dragging
|
|
8961
|
+
// focus back would take them off what they just clicked. The handlers
|
|
8962
|
+
// above tell the two apart.
|
|
8963
|
+
/* @__PURE__ */ jsx(PopupMenu, { portal: true, className: menuClassName, style: menuStyle, children: /* @__PURE__ */ jsx(
|
|
8436
8964
|
"div",
|
|
8437
8965
|
{
|
|
8438
|
-
|
|
8966
|
+
ref: menuRef,
|
|
8967
|
+
id: menuId,
|
|
8968
|
+
role: "menu",
|
|
8969
|
+
"aria-orientation": "vertical",
|
|
8970
|
+
"aria-label": ariaLabel,
|
|
8971
|
+
"aria-labelledby": ariaLabel ? void 0 : triggerId,
|
|
8972
|
+
tabIndex: -1,
|
|
8439
8973
|
onKeyDown: onMenuKeyDown,
|
|
8440
|
-
children:
|
|
8441
|
-
PopupMenuItem,
|
|
8442
|
-
{
|
|
8443
|
-
ref: (el) => {
|
|
8444
|
-
itemRefs.current[i] = el;
|
|
8445
|
-
},
|
|
8446
|
-
role: "menuitem",
|
|
8447
|
-
tabIndex: i === active ? 0 : -1,
|
|
8448
|
-
danger: item.danger,
|
|
8449
|
-
disabled: item.disabled,
|
|
8450
|
-
onMouseEnter: () => {
|
|
8451
|
-
if (!item.disabled) setActive(i);
|
|
8452
|
-
},
|
|
8453
|
-
onClick: () => select(item),
|
|
8454
|
-
children: [
|
|
8455
|
-
item.icon,
|
|
8456
|
-
item.label
|
|
8457
|
-
]
|
|
8458
|
-
},
|
|
8459
|
-
item.key
|
|
8460
|
-
)) }) })
|
|
8974
|
+
children: renderEntries()
|
|
8461
8975
|
}
|
|
8462
|
-
)
|
|
8976
|
+
) })
|
|
8463
8977
|
] });
|
|
8464
8978
|
}
|
|
8465
8979
|
var APP_UPDATE_POLL_MS = 6e4;
|
|
@@ -9045,11 +9559,18 @@ function DataTable({
|
|
|
9045
9559
|
selection,
|
|
9046
9560
|
footer,
|
|
9047
9561
|
virtualized,
|
|
9562
|
+
stackOnNarrow = false,
|
|
9048
9563
|
className = ""
|
|
9049
9564
|
}) {
|
|
9050
9565
|
const strings = useShellStrings();
|
|
9051
9566
|
const emptyContent = emptyText ?? strings.table.empty;
|
|
9052
9567
|
const keyOf = (row, i) => typeof rowKey === "function" ? rowKey(row, i) : String(row[rowKey]);
|
|
9568
|
+
const stack = stackOnNarrow && !virtualized;
|
|
9569
|
+
const role = (r) => stack ? { role: r } : {};
|
|
9570
|
+
const textOf = (title, label) => {
|
|
9571
|
+
const text = label ?? (typeof title === "string" || typeof title === "number" ? String(title) : "");
|
|
9572
|
+
return text.trim() || void 0;
|
|
9573
|
+
};
|
|
9053
9574
|
const [startRow, setStartRow] = useState(0);
|
|
9054
9575
|
const overscan = virtualized?.overscan ?? 6;
|
|
9055
9576
|
const onBodyScroll = virtualized ? (e) => {
|
|
@@ -9082,6 +9603,17 @@ function DataTable({
|
|
|
9082
9603
|
};
|
|
9083
9604
|
const leaves = columns.flatMap((h) => isGroup(h) ? h.columns : [h]);
|
|
9084
9605
|
const grouped = columns.some(isGroup);
|
|
9606
|
+
const groupOf = /* @__PURE__ */ new Map();
|
|
9607
|
+
if (stack) {
|
|
9608
|
+
for (const h of columns) {
|
|
9609
|
+
if (isGroup(h)) for (const c of h.columns) groupOf.set(c, textOf(h.title, h.label));
|
|
9610
|
+
}
|
|
9611
|
+
}
|
|
9612
|
+
const cardLabel = (col) => {
|
|
9613
|
+
const own = textOf(col.title, col.label);
|
|
9614
|
+
const group = groupOf.get(col);
|
|
9615
|
+
return own && group ? `${group} \xB7 ${own}` : own;
|
|
9616
|
+
};
|
|
9085
9617
|
const selectedSet = new Set(selection?.selected ?? []);
|
|
9086
9618
|
const pageKeys = selection ? data.map((row, i) => keyOf(row, i)) : [];
|
|
9087
9619
|
const allSelected = pageKeys.length > 0 && pageKeys.every((k) => selectedSet.has(k));
|
|
@@ -9108,12 +9640,14 @@ function DataTable({
|
|
|
9108
9640
|
const dir = directionFor(col);
|
|
9109
9641
|
const align = ALIGN2[col.align ?? (col.numeric ? "right" : "left")];
|
|
9110
9642
|
const pinned = col.fixed === "left";
|
|
9643
|
+
const sorts = !!(col.sortable && onSortChange);
|
|
9111
9644
|
return /* @__PURE__ */ jsx(
|
|
9112
9645
|
"th",
|
|
9113
9646
|
{
|
|
9114
9647
|
scope: "col",
|
|
9648
|
+
...role("columnheader"),
|
|
9115
9649
|
rowSpan: rowSpan > 1 ? rowSpan : void 0,
|
|
9116
|
-
"aria-sort": dir === "asc" ? "ascending" : dir === "desc" ? "descending" :
|
|
9650
|
+
"aria-sort": dir === "asc" ? "ascending" : dir === "desc" ? "descending" : sorts ? "none" : void 0,
|
|
9117
9651
|
style: {
|
|
9118
9652
|
width: col.width,
|
|
9119
9653
|
...pinned ? { left: (offsets[ci] ?? 0) + selOffset } : {},
|
|
@@ -9128,13 +9662,17 @@ function DataTable({
|
|
|
9128
9662
|
"font-semibold uppercase tracking-wide text-gray-500",
|
|
9129
9663
|
size === "sm" ? "text-[10px]" : "text-xs",
|
|
9130
9664
|
pinned ? virtualized ? "sticky z-20 bg-gray-50" : "sticky z-10 bg-gray-50" : virtualized ? "sticky z-10 bg-gray-50" : "",
|
|
9665
|
+
// Stacked, a sortable header is one of the sort row's chips and
|
|
9666
|
+
// every other header is hidden from sight — see `rosh-dt-head`.
|
|
9667
|
+
stack && sorts ? "rosh-dt-sort" : "",
|
|
9131
9668
|
col.headerClassName ?? ""
|
|
9132
9669
|
].filter(Boolean).join(" "),
|
|
9133
|
-
children:
|
|
9670
|
+
children: sorts ? /* @__PURE__ */ jsxs(
|
|
9134
9671
|
"button",
|
|
9135
9672
|
{
|
|
9136
9673
|
type: "button",
|
|
9137
9674
|
onClick: () => toggleSort(col),
|
|
9675
|
+
"data-group": stack ? groupOf.get(col) : void 0,
|
|
9138
9676
|
className: `inline-flex items-center font-semibold uppercase tracking-wide hover:text-gray-700 ${align}`,
|
|
9139
9677
|
children: [
|
|
9140
9678
|
col.title,
|
|
@@ -9153,13 +9691,13 @@ function DataTable({
|
|
|
9153
9691
|
fixedOffset += col.width ?? 0;
|
|
9154
9692
|
return at;
|
|
9155
9693
|
});
|
|
9156
|
-
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
9694
|
+
return /* @__PURE__ */ jsxs("div", { className: stack ? `rosh-dt-stack ${className}`.trim() : className, children: [
|
|
9157
9695
|
/* @__PURE__ */ jsxs(
|
|
9158
9696
|
"div",
|
|
9159
9697
|
{
|
|
9160
9698
|
onScroll: onBodyScroll,
|
|
9161
9699
|
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(),
|
|
9700
|
+
className: `relative overflow-x-auto ${virtualized ? "overflow-y-auto" : ""} ${bordered ? "rounded-lg border border-gray-200" : ""}${stack ? " rosh-dt-scroll" : ""}`.trim(),
|
|
9163
9701
|
children: [
|
|
9164
9702
|
loading && // An overlay rather than replacing the rows: the table keeps its
|
|
9165
9703
|
// height and its scroll position, so re-sorting does not throw the
|
|
@@ -9168,140 +9706,172 @@ function DataTable({
|
|
|
9168
9706
|
/* @__PURE__ */ jsx("span", { className: "h-6 w-6 animate-spin rounded-full border-2 border-gray-200 border-t-blue-600" }),
|
|
9169
9707
|
/* @__PURE__ */ jsx("span", { className: "sr-only", children: strings.table.loading })
|
|
9170
9708
|
] }),
|
|
9171
|
-
/* @__PURE__ */ jsxs(
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
|
|
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(
|
|
9709
|
+
/* @__PURE__ */ jsxs(
|
|
9710
|
+
"table",
|
|
9711
|
+
{
|
|
9712
|
+
...role("table"),
|
|
9713
|
+
className: `${stack ? "rosh-dt-table " : ""}w-full border-collapse tabular-nums`,
|
|
9714
|
+
style: minWidth ? { minWidth } : void 0,
|
|
9715
|
+
children: [
|
|
9716
|
+
caption && /* @__PURE__ */ jsx("caption", { className: "sr-only", children: caption }),
|
|
9717
|
+
/* @__PURE__ */ jsxs("thead", { ...role("rowgroup"), className: stack ? "rosh-dt-head" : void 0, children: [
|
|
9718
|
+
/* @__PURE__ */ jsxs("tr", { ref: headRowRef, ...role("row"), className: "border-b border-gray-200 bg-gray-50", children: [
|
|
9719
|
+
selection && /* @__PURE__ */ jsx(
|
|
9200
9720
|
"th",
|
|
9201
9721
|
{
|
|
9202
|
-
scope: "
|
|
9203
|
-
|
|
9204
|
-
|
|
9722
|
+
scope: "col",
|
|
9723
|
+
...role("columnheader"),
|
|
9724
|
+
rowSpan: grouped ? 2 : void 0,
|
|
9725
|
+
style: { width: SELECT_W, ...virtualized ? { top: 0 } : {} },
|
|
9205
9726
|
className: [
|
|
9206
9727
|
cellBase,
|
|
9207
|
-
"
|
|
9208
|
-
"
|
|
9209
|
-
|
|
9210
|
-
"
|
|
9211
|
-
virtualized ? "sticky z-10 bg-gray-50" : "",
|
|
9212
|
-
h.headerClassName ?? ""
|
|
9728
|
+
hasPinned || virtualized ? "sticky z-20 bg-gray-50" : "",
|
|
9729
|
+
hasPinned ? "left-0" : "",
|
|
9730
|
+
// Stacked, "select all" leads the sort row.
|
|
9731
|
+
stack ? "rosh-dt-select" : ""
|
|
9213
9732
|
].filter(Boolean).join(" "),
|
|
9214
|
-
children:
|
|
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",
|
|
9733
|
+
children: /* @__PURE__ */ jsx(
|
|
9734
|
+
Checkbox_default,
|
|
9256
9735
|
{
|
|
9257
|
-
|
|
9258
|
-
|
|
9259
|
-
|
|
9260
|
-
|
|
9261
|
-
Checkbox_default,
|
|
9262
|
-
{
|
|
9263
|
-
"aria-label": strings.table.selectRow,
|
|
9264
|
-
checked: selectedSet.has(key),
|
|
9265
|
-
onChange: () => toggleRow(key)
|
|
9266
|
-
}
|
|
9267
|
-
)
|
|
9736
|
+
"aria-label": strings.table.selectAll,
|
|
9737
|
+
checked: allSelected,
|
|
9738
|
+
indeterminate: someSelected && !allSelected,
|
|
9739
|
+
onChange: toggleAll
|
|
9268
9740
|
}
|
|
9269
|
-
)
|
|
9270
|
-
}
|
|
9271
|
-
|
|
9272
|
-
|
|
9741
|
+
)
|
|
9742
|
+
}
|
|
9743
|
+
),
|
|
9744
|
+
columns.map((h, hi) => {
|
|
9745
|
+
if (isGroup(h)) {
|
|
9273
9746
|
return /* @__PURE__ */ jsx(
|
|
9274
|
-
"
|
|
9747
|
+
"th",
|
|
9275
9748
|
{
|
|
9276
|
-
|
|
9749
|
+
scope: "colgroup",
|
|
9750
|
+
...role("columnheader"),
|
|
9751
|
+
colSpan: h.columns.length,
|
|
9752
|
+
style: virtualized ? { top: 0 } : void 0,
|
|
9277
9753
|
className: [
|
|
9278
9754
|
cellBase,
|
|
9279
|
-
|
|
9280
|
-
|
|
9281
|
-
"text-
|
|
9282
|
-
|
|
9283
|
-
|
|
9284
|
-
|
|
9285
|
-
pinned ? "sticky z-10 bg-white" : ""
|
|
9755
|
+
"text-center",
|
|
9756
|
+
"font-semibold uppercase tracking-wide text-gray-500",
|
|
9757
|
+
size === "sm" ? "text-[10px]" : "text-xs",
|
|
9758
|
+
"border-b border-gray-200",
|
|
9759
|
+
virtualized ? "sticky z-10 bg-gray-50" : "",
|
|
9760
|
+
h.headerClassName ?? ""
|
|
9286
9761
|
].filter(Boolean).join(" "),
|
|
9287
|
-
children:
|
|
9762
|
+
children: h.title
|
|
9288
9763
|
},
|
|
9289
|
-
|
|
9764
|
+
h.key ?? `group-${hi}`
|
|
9290
9765
|
);
|
|
9291
|
-
}
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
|
|
9298
|
-
|
|
9299
|
-
|
|
9766
|
+
}
|
|
9767
|
+
return headerCell(h, leaves.indexOf(h), grouped ? 2 : 1);
|
|
9768
|
+
})
|
|
9769
|
+
] }),
|
|
9770
|
+
grouped && /* @__PURE__ */ jsx("tr", { ...role("row"), className: "border-b border-gray-200 bg-gray-50", children: columns.flatMap((h) => isGroup(h) ? h.columns : []).map(
|
|
9771
|
+
(col) => headerCell(col, leaves.indexOf(col), 1, headRowH)
|
|
9772
|
+
) })
|
|
9773
|
+
] }),
|
|
9774
|
+
/* @__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: [
|
|
9775
|
+
topPad > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx("td", { colSpan: colCount, style: { height: topPad, padding: 0, border: 0 } }) }),
|
|
9776
|
+
data.slice(start, end).map((row, si) => {
|
|
9777
|
+
const i = start + si;
|
|
9778
|
+
const rowProps = onRow?.(row, i);
|
|
9779
|
+
return /* @__PURE__ */ jsxs(
|
|
9780
|
+
"tr",
|
|
9781
|
+
{
|
|
9782
|
+
...role("row"),
|
|
9783
|
+
style: virtualized ? { height: virtualized.rowHeight } : void 0,
|
|
9784
|
+
onClick: rowProps?.onClick,
|
|
9785
|
+
...rowProps?.onClick ? {
|
|
9786
|
+
tabIndex: 0,
|
|
9787
|
+
onKeyDown: (e) => {
|
|
9788
|
+
if (e.target !== e.currentTarget) return;
|
|
9789
|
+
if (e.key !== "Enter" && e.key !== " ") return;
|
|
9790
|
+
e.preventDefault();
|
|
9791
|
+
rowProps.onClick?.();
|
|
9792
|
+
}
|
|
9793
|
+
} : {},
|
|
9794
|
+
className: [
|
|
9795
|
+
stack ? selection ? "rosh-dt-row rosh-dt-row-select" : "rosh-dt-row" : "",
|
|
9796
|
+
"border-b border-gray-100 last:border-b-0",
|
|
9797
|
+
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)]" : "",
|
|
9798
|
+
rowClassName?.(row, i) ?? "",
|
|
9799
|
+
rowProps?.className ?? ""
|
|
9800
|
+
].filter(Boolean).join(" "),
|
|
9801
|
+
children: [
|
|
9802
|
+
selection && (() => {
|
|
9803
|
+
const key = keyOf(row, i);
|
|
9804
|
+
return /* @__PURE__ */ jsx(
|
|
9805
|
+
"td",
|
|
9806
|
+
{
|
|
9807
|
+
...role("cell"),
|
|
9808
|
+
style: { width: SELECT_W },
|
|
9809
|
+
onClick: (e) => e.stopPropagation(),
|
|
9810
|
+
className: [
|
|
9811
|
+
cellBase,
|
|
9812
|
+
hasPinned ? "sticky left-0 z-10 bg-white" : "",
|
|
9813
|
+
stack ? "rosh-dt-select" : ""
|
|
9814
|
+
].filter(Boolean).join(" "),
|
|
9815
|
+
children: /* @__PURE__ */ jsx(
|
|
9816
|
+
Checkbox_default,
|
|
9817
|
+
{
|
|
9818
|
+
"aria-label": strings.table.selectRow,
|
|
9819
|
+
checked: selectedSet.has(key),
|
|
9820
|
+
onChange: () => toggleRow(key)
|
|
9821
|
+
}
|
|
9822
|
+
)
|
|
9823
|
+
}
|
|
9824
|
+
);
|
|
9825
|
+
})(),
|
|
9826
|
+
leaves.map((col, ci) => {
|
|
9827
|
+
const pinned = col.fixed === "left";
|
|
9828
|
+
const content = col.render ? col.render(row, i) : col.dataIndex ? row[col.dataIndex] : null;
|
|
9829
|
+
return /* @__PURE__ */ jsx(
|
|
9830
|
+
"td",
|
|
9831
|
+
{
|
|
9832
|
+
...role("cell"),
|
|
9833
|
+
"data-label": stack ? cardLabel(col) : void 0,
|
|
9834
|
+
style: pinned ? { left: (offsets[ci] ?? 0) + selOffset } : void 0,
|
|
9835
|
+
className: [
|
|
9836
|
+
stack ? col.ellipsis ? "rosh-dt-cell rosh-dt-clip" : "rosh-dt-cell" : "",
|
|
9837
|
+
cellBase,
|
|
9838
|
+
ALIGN2[col.align ?? (col.numeric ? "right" : "left")],
|
|
9839
|
+
// Stacked, the monospace moves onto the value, so
|
|
9840
|
+
// the label beside it keeps the header's typeface.
|
|
9841
|
+
col.numeric && !stack ? "font-mono" : "",
|
|
9842
|
+
"text-gray-900",
|
|
9843
|
+
col.ellipsis ? "max-w-0 truncate" : "",
|
|
9844
|
+
// A pinned cell needs its own background or the
|
|
9845
|
+
// scrolling columns show through it.
|
|
9846
|
+
pinned ? "sticky z-10 bg-white" : ""
|
|
9847
|
+
].filter(Boolean).join(" "),
|
|
9848
|
+
children: stack ? (
|
|
9849
|
+
// One box for the value, whatever `render` returns
|
|
9850
|
+
// — text, a fragment, three badges — so the card
|
|
9851
|
+
// line is always two items: the label and this.
|
|
9852
|
+
// `display: contents` in the wide layout, where
|
|
9853
|
+
// the cell lays its content out exactly as before.
|
|
9854
|
+
/* @__PURE__ */ jsx("span", { className: col.numeric ? "rosh-dt-value font-mono" : "rosh-dt-value", children: content })
|
|
9855
|
+
) : content
|
|
9856
|
+
},
|
|
9857
|
+
col.key
|
|
9858
|
+
);
|
|
9859
|
+
})
|
|
9860
|
+
]
|
|
9861
|
+
},
|
|
9862
|
+
keyOf(row, i)
|
|
9863
|
+
);
|
|
9864
|
+
}),
|
|
9865
|
+
bottomPad > 0 && /* @__PURE__ */ jsx("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx("td", { colSpan: colCount, style: { height: bottomPad, padding: 0, border: 0 } }) })
|
|
9866
|
+
] }) })
|
|
9867
|
+
]
|
|
9868
|
+
}
|
|
9869
|
+
),
|
|
9300
9870
|
footer
|
|
9301
9871
|
]
|
|
9302
9872
|
}
|
|
9303
9873
|
),
|
|
9304
|
-
pagination && pagination.pageCount > 1 && /* @__PURE__ */ jsx("div", { className: "mt-3 flex justify-end", children: /* @__PURE__ */ jsx(
|
|
9874
|
+
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
9875
|
Pagination,
|
|
9306
9876
|
{
|
|
9307
9877
|
page: pagination.page,
|
|
@@ -13532,6 +14102,6 @@ function ChordChart({
|
|
|
13532
14102
|
] });
|
|
13533
14103
|
}
|
|
13534
14104
|
|
|
13535
|
-
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-
|
|
13537
|
-
//# sourceMappingURL=chunk-
|
|
14105
|
+
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, firstDayOfWeek, 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 };
|
|
14106
|
+
//# sourceMappingURL=chunk-YA4EE7ST.js.map
|
|
14107
|
+
//# sourceMappingURL=chunk-YA4EE7ST.js.map
|