react-os-shell 3.26.0 → 4.0.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/dist/{Browser-OYJVFNED.js → Browser-YRYIHBS5.js} +5 -5
- package/dist/{Browser-OYJVFNED.js.map → Browser-YRYIHBS5.js.map} +1 -1
- package/dist/{Calculator-DMOIIGKO.js → Calculator-ZB3PBT4Y.js} +4 -4
- package/dist/{Calculator-DMOIIGKO.js.map → Calculator-ZB3PBT4Y.js.map} +1 -1
- package/dist/ConfirmDialog-YEYQG4TI.js +4 -0
- package/dist/{ConfirmDialog-3RUHJG5R.js.map → ConfirmDialog-YEYQG4TI.js.map} +1 -1
- package/dist/{CurrencyConverter-ROSY6A3Q.js → CurrencyConverter-LARMJEQO.js} +4 -4
- package/dist/{CurrencyConverter-ROSY6A3Q.js.map → CurrencyConverter-LARMJEQO.js.map} +1 -1
- package/dist/{Documents-VLKG4D22.js → Documents-LNKBJNNL.js} +5 -5
- package/dist/{Documents-VLKG4D22.js.map → Documents-LNKBJNNL.js.map} +1 -1
- package/dist/{Files-WRMJX4QG.js → Files-SAV2TFVZ.js} +7 -7
- package/dist/{Files-WRMJX4QG.js.map → Files-SAV2TFVZ.js.map} +1 -1
- package/dist/{Notepad-JVB7OIPO.js → Notepad-V3Y6YWWL.js} +5 -5
- package/dist/{Notepad-JVB7OIPO.js.map → Notepad-V3Y6YWWL.js.map} +1 -1
- package/dist/{PomodoroTimer-RVNX4CYS.js → PomodoroTimer-IFNOHNFU.js} +5 -5
- package/dist/{PomodoroTimer-RVNX4CYS.js.map → PomodoroTimer-IFNOHNFU.js.map} +1 -1
- package/dist/{Preview-DUADZWDA.js → Preview-FFBHSUHL.js} +5 -5
- package/dist/{Preview-DUADZWDA.js.map → Preview-FFBHSUHL.js.map} +1 -1
- package/dist/{Spreadsheet-EIWL7RIF.js → Spreadsheet-6WDNXIAL.js} +5 -5
- package/dist/{Spreadsheet-EIWL7RIF.js.map → Spreadsheet-6WDNXIAL.js.map} +1 -1
- package/dist/{Stock-7BIHXBPQ.js → Stock-QVCSPVG2.js} +4 -4
- package/dist/{Stock-7BIHXBPQ.js.map → Stock-QVCSPVG2.js.map} +1 -1
- package/dist/{Weather-7KUHPWTZ.js → Weather-LJLGXB5M.js} +4 -4
- package/dist/{Weather-7KUHPWTZ.js.map → Weather-LJLGXB5M.js.map} +1 -1
- package/dist/{WorldClock-I24ASGUI.js → WorldClock-N5CTLHPG.js} +4 -4
- package/dist/{WorldClock-I24ASGUI.js.map → WorldClock-N5CTLHPG.js.map} +1 -1
- package/dist/apps/index.js +17 -17
- package/dist/{chunk-NQ2QVUVX.js → chunk-63Y56L3Z.js} +3 -3
- package/dist/{chunk-NQ2QVUVX.js.map → chunk-63Y56L3Z.js.map} +1 -1
- package/dist/{chunk-MU7UZXAS.js → chunk-PG2PMKTJ.js} +3 -3
- package/dist/{chunk-MU7UZXAS.js.map → chunk-PG2PMKTJ.js.map} +1 -1
- package/dist/{chunk-LRVPNWRE.js → chunk-QXWBHX7J.js} +3 -3
- package/dist/chunk-QXWBHX7J.js.map +1 -0
- package/dist/{chunk-AA24QYTD.js → chunk-RVUMXSQE.js} +3 -3
- package/dist/{chunk-AA24QYTD.js.map → chunk-RVUMXSQE.js.map} +1 -1
- package/dist/{chunk-FPDVIPLM.js → chunk-V45E4R5P.js} +4 -4
- package/dist/{chunk-FPDVIPLM.js.map → chunk-V45E4R5P.js.map} +1 -1
- package/dist/chunk-YIDTMPOP.js +7 -0
- package/dist/{chunk-4BOGLRCL.js.map → chunk-YIDTMPOP.js.map} +1 -1
- package/dist/{chunk-E6ZOCXEA.js → chunk-YJJDW4GG.js} +87 -25
- package/dist/chunk-YJJDW4GG.js.map +1 -0
- package/dist/index.d.ts +66 -5
- package/dist/index.js +580 -824
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/ConfirmDialog-3RUHJG5R.js +0 -4
- package/dist/chunk-4BOGLRCL.js +0 -7
- package/dist/chunk-E6ZOCXEA.js.map +0 -1
- package/dist/chunk-LRVPNWRE.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { subscribePomo, getPomoSnapshot } from './chunk-
|
|
2
|
-
export { setShellTodoProvider } from './chunk-
|
|
1
|
+
import { subscribePomo, getPomoSnapshot } from './chunk-PG2PMKTJ.js';
|
|
2
|
+
export { setShellTodoProvider } from './chunk-PG2PMKTJ.js';
|
|
3
3
|
export { ImageAnnotator_default as ImageAnnotator } from './chunk-QU5L5ZYM.js';
|
|
4
4
|
import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-DINNWYVB.js';
|
|
5
5
|
export { Breadcrumbs } from './chunk-DINNWYVB.js';
|
|
@@ -7,7 +7,7 @@ import { SidebarLayout } from './chunk-YG45DAUT.js';
|
|
|
7
7
|
export { SidebarLayout } from './chunk-YG45DAUT.js';
|
|
8
8
|
import { toast_default } from './chunk-VENYVK3L.js';
|
|
9
9
|
export { toast_default as toast } from './chunk-VENYVK3L.js';
|
|
10
|
-
import { publishDesktopFolders, requestFilesTrashView, FolderGlyph, requestFilesDesktopFolderView, FileIconTile
|
|
10
|
+
import { publishDesktopFolders, requestFilesTrashView, FolderGlyph, requestFilesDesktopFolderView, FileIconTile } from './chunk-QXWBHX7J.js';
|
|
11
11
|
import { setPdfPreview } from './chunk-BV6SQ46N.js';
|
|
12
12
|
import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, setSoundForType, previewSound, setAllSounds, playLogout } from './chunk-D7PYW2QS.js';
|
|
13
13
|
import { useAuth, useShellAuth } from './chunk-ADJ3CERD.js';
|
|
@@ -15,13 +15,13 @@ export { ShellAuthProvider, setShellAuthBridge, useShellAuth } from './chunk-ADJ
|
|
|
15
15
|
import { EditableGrid } from './chunk-GP4Y3VCB.js';
|
|
16
16
|
export { EditableGrid } from './chunk-GP4Y3VCB.js';
|
|
17
17
|
import './chunk-4SQU5YV6.js';
|
|
18
|
-
import { APP_VERSION, VERSION } from './chunk-
|
|
19
|
-
export { VERSION } from './chunk-
|
|
20
|
-
import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, WINDOW_REGISTRY, isPageEntry, Modal, useShellPrefs,
|
|
21
|
-
export { CancelButton, ConfirmProvider, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ShellPrefsProvider, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowTitle, commitExposeHighlight, confirm, confirmDestructive, exitExposeMode, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, prompt, registerModalEscapeInterceptor, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useLocalStoragePrefs, useModalActive, useShellPrefs, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-
|
|
18
|
+
import { APP_VERSION, VERSION } from './chunk-YIDTMPOP.js';
|
|
19
|
+
export { VERSION } from './chunk-YIDTMPOP.js';
|
|
20
|
+
import { registerModalEscapeInterceptor, useIsMobile, useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, WINDOW_REGISTRY, isPageEntry, Modal, useShellPrefs, SIDEBAR_STRIP_W, forgetMaximizedWindowBoxes, ModalActions, useModalActive, client_default, LoadingSpinner, isShellApiClientConfigured, CancelButton, setWindowPosition } from './chunk-YJJDW4GG.js';
|
|
21
|
+
export { CancelButton, ConfirmProvider, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ShellPrefsProvider, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowTitle, commitExposeHighlight, confirm, confirmDestructive, exitExposeMode, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, prompt, registerModalEscapeInterceptor, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useLocalStoragePrefs, useModalActive, useShellPrefs, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-YJJDW4GG.js';
|
|
22
22
|
import { glassStyle, startMenuCategories, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons } from './chunk-GW3RA6IS.js';
|
|
23
23
|
export { GLASS_DIVIDER, GLASS_INPUT_BG, glassStyle, setShellNavIcons } from './chunk-GW3RA6IS.js';
|
|
24
|
-
import { createContext, lazy, forwardRef, useCallback, useState, useRef,
|
|
24
|
+
import { createContext, lazy, forwardRef, useCallback, useState, useRef, useId, useEffect, useLayoutEffect, useMemo, useContext, isValidElement, cloneElement, Suspense, Fragment as Fragment$1, Children, useSyncExternalStore } from 'react';
|
|
25
25
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
26
26
|
import { Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react';
|
|
27
27
|
import { createPortal } from 'react-dom';
|
|
@@ -3336,744 +3336,45 @@ function StartMenu({
|
|
|
3336
3336
|
] })
|
|
3337
3337
|
);
|
|
3338
3338
|
}
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
return _mode;
|
|
3345
|
-
}
|
|
3346
|
-
function setMobileMode(mode) {
|
|
3347
|
-
if (_mode === mode) return;
|
|
3348
|
-
_mode = mode;
|
|
3349
|
-
listeners.forEach((fn) => fn());
|
|
3350
|
-
}
|
|
3351
|
-
function subscribeMobileMode(cb) {
|
|
3352
|
-
listeners.add(cb);
|
|
3353
|
-
return () => {
|
|
3354
|
-
listeners.delete(cb);
|
|
3355
|
-
};
|
|
3356
|
-
}
|
|
3357
|
-
var MOBILE_WIDGET_ORDER_KEY = "erp_mobile_widget_order";
|
|
3358
|
-
var MOBILE_HOME_ORDER_KEY = "erp_mobile_home_order";
|
|
3359
|
-
var LONG_PRESS_MS = 400;
|
|
3360
|
-
function loadOrder(key) {
|
|
3361
|
-
try {
|
|
3362
|
-
const raw = localStorage.getItem(key);
|
|
3363
|
-
if (raw) {
|
|
3364
|
-
const parsed = JSON.parse(raw);
|
|
3365
|
-
if (Array.isArray(parsed)) return parsed.filter((s) => typeof s === "string");
|
|
3366
|
-
}
|
|
3367
|
-
} catch {
|
|
3368
|
-
}
|
|
3369
|
-
return [];
|
|
3370
|
-
}
|
|
3371
|
-
function saveOrder(key, order) {
|
|
3372
|
-
try {
|
|
3373
|
-
localStorage.setItem(key, JSON.stringify(order));
|
|
3374
|
-
} catch {
|
|
3375
|
-
}
|
|
3376
|
-
}
|
|
3377
|
-
var FALLBACK_APP_ICON = /* @__PURE__ */ jsx("svg", { className: "h-10 w-10", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6.75A2.25 2.25 0 016 4.5h12a2.25 2.25 0 012.25 2.25v10.5A2.25 2.25 0 0118 19.5H6a2.25 2.25 0 01-2.25-2.25V6.75z" }) });
|
|
3378
|
-
function sizeIcon(node, fallback, sizeClass = "h-10 w-10") {
|
|
3379
|
-
if (!node) return fallback;
|
|
3380
|
-
if (isValidElement(node)) {
|
|
3381
|
-
return cloneElement(node, {
|
|
3382
|
-
className: `${sizeClass} ${node.props?.className ?? ""}`.trim()
|
|
3383
|
-
});
|
|
3384
|
-
}
|
|
3385
|
-
return node;
|
|
3386
|
-
}
|
|
3387
|
-
function AppTile({ route, icon }) {
|
|
3388
|
-
return /* @__PURE__ */ jsx("span", { className: `relative aspect-square w-full rounded-2xl bg-gradient-to-br ${hashGradient(route)} flex items-center justify-center text-white shadow-sm border border-white/30`, children: sizeIcon(icon, FALLBACK_APP_ICON, "h-11 w-11") });
|
|
3389
|
-
}
|
|
3390
|
-
function FolderTile({ section, navIcons: navIcons2 }) {
|
|
3391
|
-
const previewItems = section.items.slice(0, 4);
|
|
3392
|
-
return /* @__PURE__ */ jsxs("span", { className: "relative aspect-square w-full rounded-2xl bg-white/30 backdrop-blur-sm border border-white/40 p-1.5 grid grid-cols-2 gap-1 shadow-sm", children: [
|
|
3393
|
-
previewItems.map((item) => /* @__PURE__ */ jsx(
|
|
3394
|
-
"span",
|
|
3395
|
-
{
|
|
3396
|
-
className: `rounded-md bg-gradient-to-br ${hashGradient(item.to)} flex items-center justify-center text-white`,
|
|
3397
|
-
children: sizeIcon(navIcons2[item.to], FALLBACK_APP_ICON, "h-3.5 w-3.5")
|
|
3398
|
-
},
|
|
3399
|
-
item.to
|
|
3400
|
-
)),
|
|
3401
|
-
Array.from({ length: Math.max(0, 4 - previewItems.length) }).map((_, i) => /* @__PURE__ */ jsx("span", { className: "rounded-md bg-white/20" }, `empty-${i}`))
|
|
3402
|
-
] });
|
|
3403
|
-
}
|
|
3404
|
-
function MobileHome({
|
|
3405
|
-
navSections: navSections2,
|
|
3406
|
-
navIcons: navIcons2,
|
|
3407
|
-
sectionIcons: sectionIcons2,
|
|
3408
|
-
openWindows,
|
|
3409
|
-
onOpenApp,
|
|
3410
|
-
onActivateWindow
|
|
3339
|
+
function MobileAppLanding({
|
|
3340
|
+
productName,
|
|
3341
|
+
productIcon,
|
|
3342
|
+
config,
|
|
3343
|
+
wallpaperStyle
|
|
3411
3344
|
}) {
|
|
3412
|
-
const
|
|
3413
|
-
const
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
const sec = entry;
|
|
3418
|
-
list.push({ kind: "folder", id: `folder:${sec.label}`, label: sec.label, section: sec });
|
|
3419
|
-
} else {
|
|
3420
|
-
const it = entry;
|
|
3421
|
-
list.push({ kind: "app", id: `app:${it.to}`, label: it.label, route: it.to });
|
|
3422
|
-
}
|
|
3423
|
-
}
|
|
3424
|
-
return list;
|
|
3425
|
-
}, [navSections2]);
|
|
3426
|
-
const [homeOrder, setHomeOrder] = useState(() => loadOrder(MOBILE_HOME_ORDER_KEY));
|
|
3427
|
-
const homeIcons = useMemo(() => {
|
|
3428
|
-
const indexFor = (id) => {
|
|
3429
|
-
const i = homeOrder.indexOf(id);
|
|
3430
|
-
return i === -1 ? Number.MAX_SAFE_INTEGER : i;
|
|
3431
|
-
};
|
|
3432
|
-
return homeIconsRaw.slice().sort((a, b) => {
|
|
3433
|
-
const ia = indexFor(a.id);
|
|
3434
|
-
const ib = indexFor(b.id);
|
|
3435
|
-
if (ia !== ib) return ia - ib;
|
|
3436
|
-
return homeIconsRaw.indexOf(a) - homeIconsRaw.indexOf(b);
|
|
3437
|
-
});
|
|
3438
|
-
}, [homeIconsRaw, homeOrder]);
|
|
3439
|
-
useEffect(() => {
|
|
3440
|
-
const visibleIds = homeIconsRaw.map((i) => i.id);
|
|
3441
|
-
const next = [
|
|
3442
|
-
...homeOrder.filter((id) => visibleIds.includes(id)),
|
|
3443
|
-
...visibleIds.filter((id) => !homeOrder.includes(id))
|
|
3444
|
-
];
|
|
3445
|
-
if (next.length !== homeOrder.length || next.some((id, i) => id !== homeOrder[i])) {
|
|
3446
|
-
setHomeOrder(next);
|
|
3447
|
-
saveOrder(MOBILE_HOME_ORDER_KEY, next);
|
|
3448
|
-
}
|
|
3449
|
-
}, [homeIconsRaw, homeOrder]);
|
|
3450
|
-
const [dragId, setDragId] = useState(null);
|
|
3451
|
-
const [dragPos, setDragPos] = useState(null);
|
|
3452
|
-
const dragOffsetRef = useRef({ x: 0, y: 0 });
|
|
3453
|
-
const longPressTimerRef = useRef(null);
|
|
3454
|
-
const longPressFiredRef = useRef(false);
|
|
3455
|
-
const cancelLongPress = () => {
|
|
3456
|
-
if (longPressTimerRef.current) {
|
|
3457
|
-
clearTimeout(longPressTimerRef.current);
|
|
3458
|
-
longPressTimerRef.current = null;
|
|
3459
|
-
}
|
|
3460
|
-
};
|
|
3461
|
-
const beginLongPress = (id, e) => {
|
|
3462
|
-
if (dragId) return;
|
|
3463
|
-
const x = e.clientX;
|
|
3464
|
-
const y = e.clientY;
|
|
3465
|
-
const target = e.currentTarget;
|
|
3466
|
-
longPressFiredRef.current = false;
|
|
3467
|
-
cancelLongPress();
|
|
3468
|
-
longPressTimerRef.current = setTimeout(() => {
|
|
3469
|
-
if (!target.isConnected) return;
|
|
3470
|
-
const rect = target.getBoundingClientRect();
|
|
3471
|
-
dragOffsetRef.current = { x: x - rect.left, y: y - rect.top };
|
|
3472
|
-
longPressFiredRef.current = true;
|
|
3473
|
-
setDragId(id);
|
|
3474
|
-
setDragPos({ x, y });
|
|
3475
|
-
try {
|
|
3476
|
-
navigator.vibrate?.(15);
|
|
3477
|
-
} catch {
|
|
3478
|
-
}
|
|
3479
|
-
}, LONG_PRESS_MS);
|
|
3480
|
-
};
|
|
3481
|
-
useEffect(() => {
|
|
3482
|
-
if (!dragId) return;
|
|
3483
|
-
const onMove = (e) => {
|
|
3484
|
-
setDragPos({ x: e.clientX, y: e.clientY });
|
|
3485
|
-
const el = document.elementFromPoint(e.clientX, e.clientY);
|
|
3486
|
-
const targetEl = el?.closest("[data-home-icon-id]");
|
|
3487
|
-
if (!targetEl) return;
|
|
3488
|
-
const targetId = targetEl.dataset.homeIconId;
|
|
3489
|
-
if (targetId === dragId) return;
|
|
3490
|
-
setHomeOrder((prev) => {
|
|
3491
|
-
const fromIdx = prev.indexOf(dragId);
|
|
3492
|
-
const toIdx = prev.indexOf(targetId);
|
|
3493
|
-
if (fromIdx === -1 || toIdx === -1) return prev;
|
|
3494
|
-
const next = prev.slice();
|
|
3495
|
-
next.splice(fromIdx, 1);
|
|
3496
|
-
next.splice(toIdx, 0, dragId);
|
|
3497
|
-
return next;
|
|
3498
|
-
});
|
|
3499
|
-
};
|
|
3500
|
-
const onUp = () => {
|
|
3501
|
-
setDragId(null);
|
|
3502
|
-
setDragPos(null);
|
|
3503
|
-
setHomeOrder((prev) => {
|
|
3504
|
-
saveOrder(MOBILE_HOME_ORDER_KEY, prev);
|
|
3505
|
-
return prev;
|
|
3506
|
-
});
|
|
3507
|
-
};
|
|
3508
|
-
window.addEventListener("pointermove", onMove);
|
|
3509
|
-
window.addEventListener("pointerup", onUp);
|
|
3510
|
-
window.addEventListener("pointercancel", onUp);
|
|
3511
|
-
return () => {
|
|
3512
|
-
window.removeEventListener("pointermove", onMove);
|
|
3513
|
-
window.removeEventListener("pointerup", onUp);
|
|
3514
|
-
window.removeEventListener("pointercancel", onUp);
|
|
3515
|
-
};
|
|
3516
|
-
}, [dragId]);
|
|
3517
|
-
const handleIconClick = (icon) => {
|
|
3518
|
-
if (longPressFiredRef.current) {
|
|
3519
|
-
longPressFiredRef.current = false;
|
|
3520
|
-
return;
|
|
3521
|
-
}
|
|
3522
|
-
if (icon.kind === "app") onOpenApp(icon.route);
|
|
3523
|
-
else setSelectedFolder(icon.section);
|
|
3524
|
-
};
|
|
3525
|
-
const [widgetOrder, _setWidgetOrder] = useState(() => loadOrder(MOBILE_WIDGET_ORDER_KEY));
|
|
3526
|
-
const widgetWindows = useMemo(() => {
|
|
3527
|
-
const widgets = openWindows.filter((w) => {
|
|
3528
|
-
if (!w.route) return false;
|
|
3529
|
-
const entry = WINDOW_REGISTRY[w.route];
|
|
3530
|
-
return entry && isPageEntry(entry) && entry.widget;
|
|
3531
|
-
});
|
|
3532
|
-
const indexFor = (route) => {
|
|
3533
|
-
const i = widgetOrder.indexOf(route);
|
|
3534
|
-
return i === -1 ? Number.MAX_SAFE_INTEGER : i;
|
|
3535
|
-
};
|
|
3536
|
-
return widgets.slice().sort((a, b) => indexFor(a.route) - indexFor(b.route));
|
|
3537
|
-
}, [openWindows, widgetOrder]);
|
|
3538
|
-
useEffect(() => {
|
|
3539
|
-
const visibleRoutes = widgetWindows.map((w) => w.route).filter(Boolean);
|
|
3540
|
-
const next = [
|
|
3541
|
-
...widgetOrder.filter((r) => visibleRoutes.includes(r)),
|
|
3542
|
-
...visibleRoutes.filter((r) => !widgetOrder.includes(r))
|
|
3543
|
-
];
|
|
3544
|
-
if (next.length !== widgetOrder.length || next.some((r, i) => r !== widgetOrder[i])) {
|
|
3545
|
-
_setWidgetOrder(next);
|
|
3546
|
-
saveOrder(MOBILE_WIDGET_ORDER_KEY, next);
|
|
3547
|
-
}
|
|
3548
|
-
}, [widgetWindows, widgetOrder]);
|
|
3549
|
-
useMemo(() => {
|
|
3550
|
-
const map = /* @__PURE__ */ new Map();
|
|
3551
|
-
for (const w of openWindows) {
|
|
3552
|
-
if (!w.route) continue;
|
|
3553
|
-
map.set(w.route, (map.get(w.route) ?? 0) + 1);
|
|
3554
|
-
}
|
|
3555
|
-
return map;
|
|
3556
|
-
}, [openWindows]);
|
|
3557
|
-
const draggedIcon = dragId ? homeIcons.find((i) => i.id === dragId) : null;
|
|
3558
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3559
|
-
/* @__PURE__ */ jsx(
|
|
3560
|
-
"div",
|
|
3561
|
-
{
|
|
3562
|
-
className: "h-full overflow-y-auto px-4 pt-4 pb-4 select-none",
|
|
3563
|
-
style: {
|
|
3564
|
-
// Disable iOS long-press text-selection / "Copy" callout on icon labels.
|
|
3565
|
-
WebkitUserSelect: "none",
|
|
3566
|
-
WebkitTouchCallout: "none"
|
|
3567
|
-
},
|
|
3568
|
-
children: /* @__PURE__ */ jsxs("div", { children: [
|
|
3569
|
-
widgetWindows.length > 0 && /* @__PURE__ */ jsx("section", { className: "mb-4", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-4", children: widgetWindows.map((w) => {
|
|
3570
|
-
const entry = WINDOW_REGISTRY[w.route];
|
|
3571
|
-
if (!entry) return null;
|
|
3572
|
-
const Component = entry.component;
|
|
3573
|
-
return /* @__PURE__ */ jsx(
|
|
3574
|
-
"div",
|
|
3575
|
-
{
|
|
3576
|
-
className: "col-span-2 relative rounded-2xl bg-white/85 backdrop-blur border border-white/40 shadow-md overflow-hidden aspect-square",
|
|
3577
|
-
children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsx(LoadingSpinner, {}) }), children: /* @__PURE__ */ jsx(Component, {}) })
|
|
3578
|
-
},
|
|
3579
|
-
w.id
|
|
3580
|
-
);
|
|
3581
|
-
}) }) }),
|
|
3582
|
-
homeIcons.length > 0 && /* @__PURE__ */ jsx("section", { children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-4", children: homeIcons.map((icon) => {
|
|
3583
|
-
const isFolder = icon.kind === "folder";
|
|
3584
|
-
const isBeingDragged = dragId === icon.id;
|
|
3585
|
-
return /* @__PURE__ */ jsxs(
|
|
3586
|
-
"button",
|
|
3587
|
-
{
|
|
3588
|
-
"data-home-icon-id": icon.id,
|
|
3589
|
-
onPointerDown: (e) => beginLongPress(icon.id, e),
|
|
3590
|
-
onPointerUp: cancelLongPress,
|
|
3591
|
-
onPointerCancel: cancelLongPress,
|
|
3592
|
-
onPointerLeave: cancelLongPress,
|
|
3593
|
-
onClick: () => handleIconClick(icon),
|
|
3594
|
-
style: { touchAction: "none", visibility: isBeingDragged ? "hidden" : "visible" },
|
|
3595
|
-
className: `flex flex-col items-center gap-1 py-1 rounded-lg active:bg-white/20 ${dragId && !isBeingDragged ? "transition-transform" : ""}`,
|
|
3596
|
-
children: [
|
|
3597
|
-
isFolder ? /* @__PURE__ */ jsx(FolderTile, { section: icon.section, navIcons: navIcons2 }) : /* @__PURE__ */ jsx(AppTile, { route: icon.route, icon: navIcons2[icon.route] }),
|
|
3598
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-white drop-shadow-sm truncate w-full text-center", children: icon.label })
|
|
3599
|
-
]
|
|
3600
|
-
},
|
|
3601
|
-
icon.id
|
|
3602
|
-
);
|
|
3603
|
-
}) }) })
|
|
3604
|
-
] })
|
|
3605
|
-
}
|
|
3606
|
-
),
|
|
3607
|
-
draggedIcon && dragPos && /* @__PURE__ */ jsx(
|
|
3608
|
-
"div",
|
|
3609
|
-
{
|
|
3610
|
-
className: "fixed pointer-events-none z-[400] transition-none",
|
|
3611
|
-
style: {
|
|
3612
|
-
left: dragPos.x - dragOffsetRef.current.x,
|
|
3613
|
-
top: dragPos.y - dragOffsetRef.current.y,
|
|
3614
|
-
transform: "scale(1.12)"
|
|
3615
|
-
},
|
|
3616
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 py-1 w-20", children: [
|
|
3617
|
-
draggedIcon.kind === "folder" ? /* @__PURE__ */ jsx(FolderTile, { section: draggedIcon.section, navIcons: navIcons2 }) : /* @__PURE__ */ jsx(AppTile, { route: draggedIcon.route, icon: navIcons2[draggedIcon.route] }),
|
|
3618
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-white drop-shadow-md truncate w-full text-center", children: draggedIcon.label })
|
|
3619
|
-
] })
|
|
3620
|
-
}
|
|
3621
|
-
),
|
|
3622
|
-
selectedFolder && /* @__PURE__ */ jsx(
|
|
3623
|
-
FolderPopup,
|
|
3624
|
-
{
|
|
3625
|
-
folder: selectedFolder,
|
|
3626
|
-
navIcons: navIcons2,
|
|
3627
|
-
onClose: () => setSelectedFolder(null),
|
|
3628
|
-
onOpenApp: (path) => {
|
|
3629
|
-
setSelectedFolder(null);
|
|
3630
|
-
onOpenApp(path);
|
|
3631
|
-
}
|
|
3632
|
-
}
|
|
3633
|
-
)
|
|
3634
|
-
] });
|
|
3635
|
-
}
|
|
3636
|
-
function FolderPopup({
|
|
3637
|
-
folder,
|
|
3638
|
-
navIcons: navIcons2,
|
|
3639
|
-
onClose,
|
|
3640
|
-
onOpenApp
|
|
3641
|
-
}) {
|
|
3642
|
-
const [closing, setClosing] = useState(false);
|
|
3643
|
-
const beginClose = () => {
|
|
3644
|
-
if (closing) return;
|
|
3645
|
-
setClosing(true);
|
|
3646
|
-
setTimeout(onClose, 200);
|
|
3647
|
-
};
|
|
3648
|
-
const closeThen = (after) => {
|
|
3649
|
-
if (closing) return;
|
|
3650
|
-
setClosing(true);
|
|
3651
|
-
setTimeout(after, 200);
|
|
3652
|
-
};
|
|
3653
|
-
return /* @__PURE__ */ jsxs(
|
|
3654
|
-
"div",
|
|
3655
|
-
{
|
|
3656
|
-
className: "fixed inset-0 z-[210] flex flex-col items-center justify-center px-6 bg-black/45 backdrop-blur-xl select-none",
|
|
3657
|
-
style: {
|
|
3658
|
-
paddingBottom: "calc(var(--mobile-bottom-nav, 70px) + 16px)",
|
|
3659
|
-
animation: closing ? "folder-fade-out 200ms ease-in forwards" : "folder-fade-in 220ms ease-out",
|
|
3660
|
-
WebkitUserSelect: "none",
|
|
3661
|
-
WebkitTouchCallout: "none"
|
|
3662
|
-
},
|
|
3663
|
-
onClick: beginClose,
|
|
3664
|
-
children: [
|
|
3665
|
-
/* @__PURE__ */ jsx("style", { children: `
|
|
3666
|
-
@keyframes folder-fade-in { from { opacity: 0; } to { opacity: 1; } }
|
|
3667
|
-
@keyframes folder-fade-out { from { opacity: 1; } to { opacity: 0; } }
|
|
3668
|
-
@keyframes folder-pop-in { from { opacity: 0; transform: scale(0.86) translateY(8px); } to { opacity: 1; transform: scale(1) translateY(0); } }
|
|
3669
|
-
@keyframes folder-pop-out { from { opacity: 1; transform: scale(1) translateY(0); } to { opacity: 0; transform: scale(0.9) translateY(4px); } }
|
|
3670
|
-
` }),
|
|
3671
|
-
/* @__PURE__ */ jsxs("div", { className: "w-full max-w-[304px]", children: [
|
|
3672
|
-
/* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold text-white drop-shadow-md mb-4 ml-4", children: folder.label }),
|
|
3673
|
-
/* @__PURE__ */ jsx(
|
|
3674
|
-
"div",
|
|
3675
|
-
{
|
|
3676
|
-
className: "max-h-[70vh] flex flex-col rounded-3xl bg-white/15 backdrop-blur-xl border border-white/25 shadow-2xl overflow-hidden",
|
|
3677
|
-
style: {
|
|
3678
|
-
animation: closing ? "folder-pop-out 180ms ease-in forwards" : "folder-pop-in 240ms cubic-bezier(0.34, 1.56, 0.64, 1)"
|
|
3679
|
-
},
|
|
3680
|
-
onClick: (e) => e.stopPropagation(),
|
|
3681
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto px-4 py-5", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-4", children: folder.items.map((item) => {
|
|
3682
|
-
return /* @__PURE__ */ jsxs(
|
|
3683
|
-
"button",
|
|
3684
|
-
{
|
|
3685
|
-
onClick: () => closeThen(() => onOpenApp(item.to)),
|
|
3686
|
-
className: "flex flex-col items-center gap-1 py-1 rounded-lg active:bg-white/15",
|
|
3687
|
-
children: [
|
|
3688
|
-
/* @__PURE__ */ jsx(AppTile, { route: item.to, icon: navIcons2[item.to] }),
|
|
3689
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-white drop-shadow-sm truncate w-full text-center", children: item.label })
|
|
3690
|
-
]
|
|
3691
|
-
},
|
|
3692
|
-
item.to
|
|
3693
|
-
);
|
|
3694
|
-
}) }) })
|
|
3695
|
-
}
|
|
3696
|
-
)
|
|
3697
|
-
] })
|
|
3698
|
-
]
|
|
3699
|
-
}
|
|
3700
|
-
);
|
|
3701
|
-
}
|
|
3702
|
-
function MobileSwitcher({ windows, onActivate, onClose, onCloseAll }) {
|
|
3703
|
-
const [cardSize, setCardSize] = useState(() => computeCardSize());
|
|
3704
|
-
useEffect(() => {
|
|
3705
|
-
const onResize = () => setCardSize(computeCardSize());
|
|
3706
|
-
window.addEventListener("resize", onResize);
|
|
3707
|
-
return () => window.removeEventListener("resize", onResize);
|
|
3708
|
-
}, []);
|
|
3709
|
-
if (windows.length === 0) {
|
|
3710
|
-
return /* @__PURE__ */ jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-3 text-white/80 px-6 text-center", children: [
|
|
3711
|
-
/* @__PURE__ */ jsxs("svg", { className: "h-12 w-12 text-white/40", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.4, children: [
|
|
3712
|
-
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "3.5", width: "7", height: "7", rx: "1.25" }),
|
|
3713
|
-
/* @__PURE__ */ jsx("rect", { x: "13.5", y: "3.5", width: "7", height: "7", rx: "1.25" }),
|
|
3714
|
-
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "13.5", width: "7", height: "7", rx: "1.25" }),
|
|
3715
|
-
/* @__PURE__ */ jsx("rect", { x: "13.5", y: "13.5", width: "7", height: "7", rx: "1.25" })
|
|
3716
|
-
] }),
|
|
3717
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "No open apps." }),
|
|
3718
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-white/50", children: "Tap Home to launch one." })
|
|
3719
|
-
] });
|
|
3720
|
-
}
|
|
3721
|
-
return /* @__PURE__ */ jsxs("div", { className: "h-full flex flex-col", children: [
|
|
3722
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-3 pt-4 pb-4", children: [
|
|
3723
|
-
/* @__PURE__ */ jsxs("h1", { className: "text-white text-base font-semibold mb-3 px-1", children: [
|
|
3724
|
-
"Open apps \xB7 ",
|
|
3725
|
-
windows.length
|
|
3726
|
-
] }),
|
|
3727
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-3", children: windows.map((w) => /* @__PURE__ */ jsxs("div", { className: "group flex flex-col items-stretch gap-1", children: [
|
|
3728
|
-
/* @__PURE__ */ jsx(
|
|
3729
|
-
ThumbCard,
|
|
3730
|
-
{
|
|
3731
|
-
id: w.id,
|
|
3732
|
-
label: w.label,
|
|
3733
|
-
maxW: cardSize.w,
|
|
3734
|
-
maxH: cardSize.h,
|
|
3735
|
-
titleAbove: true,
|
|
3736
|
-
onClick: () => onActivate(w.id),
|
|
3737
|
-
onClose: () => onClose(w.id)
|
|
3738
|
-
}
|
|
3739
|
-
),
|
|
3740
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] text-white/80 truncate px-1", children: w.label })
|
|
3741
|
-
] }, w.id)) })
|
|
3742
|
-
] }),
|
|
3743
|
-
/* @__PURE__ */ jsx("div", { className: "shrink-0 px-3 py-3 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
3744
|
-
"button",
|
|
3745
|
-
{
|
|
3746
|
-
onClick: onCloseAll,
|
|
3747
|
-
className: "px-5 py-2.5 rounded-full bg-white/15 backdrop-blur-md border border-white/25 text-white text-sm font-medium active:bg-white/25 shadow-lg",
|
|
3748
|
-
children: "Close All"
|
|
3749
|
-
}
|
|
3750
|
-
) })
|
|
3751
|
-
] });
|
|
3752
|
-
}
|
|
3753
|
-
function computeCardSize() {
|
|
3754
|
-
const w = typeof window !== "undefined" ? window.innerWidth : 360;
|
|
3755
|
-
const h = typeof window !== "undefined" ? window.innerHeight : 640;
|
|
3756
|
-
const cardW = Math.max(120, Math.floor((w - 36) / 2));
|
|
3757
|
-
const cardH = Math.min(cardW * 1.4, Math.floor(h * 0.4));
|
|
3758
|
-
return { w: cardW, h: cardH };
|
|
3759
|
-
}
|
|
3760
|
-
function timeAgo2(dateStr) {
|
|
3761
|
-
const diff = Date.now() - new Date(dateStr).getTime();
|
|
3762
|
-
const mins = Math.floor(diff / 6e4);
|
|
3763
|
-
if (mins < 1) return "just now";
|
|
3764
|
-
if (mins < 60) return `${mins}m ago`;
|
|
3765
|
-
const hrs = Math.floor(mins / 60);
|
|
3766
|
-
if (hrs < 24) return `${hrs}h ago`;
|
|
3767
|
-
const days = Math.floor(hrs / 24);
|
|
3768
|
-
if (days < 7) return `${days}d ago`;
|
|
3769
|
-
return formatDate(dateStr);
|
|
3770
|
-
}
|
|
3771
|
-
function MobileNotificationSheet({ config, onClose }) {
|
|
3772
|
-
const { list, markRead, markAllRead, onItemClick } = config;
|
|
3773
|
-
const queryClient = useQueryClient();
|
|
3774
|
-
const unreadCount = config.useUnreadCount();
|
|
3775
|
-
const { data: notifData } = useQuery({
|
|
3776
|
-
queryKey: ["notifications-dropdown"],
|
|
3777
|
-
queryFn: () => list({ page_size: 30 }),
|
|
3778
|
-
staleTime: 3e4
|
|
3779
|
-
});
|
|
3780
|
-
const notifications = notifData?.results ?? [];
|
|
3781
|
-
const handleClick = useCallback((notif) => {
|
|
3782
|
-
if (!notif.is_read) {
|
|
3783
|
-
queryClient.setQueryData(["notification-unread-count"], (old) => old ? { ...old, count: Math.max(0, (old.count || 0) - 1) } : old);
|
|
3784
|
-
queryClient.setQueryData(["notifications-dropdown"], (old) => {
|
|
3785
|
-
if (!old?.results) return old;
|
|
3786
|
-
return { ...old, results: old.results.map((n) => n.id === notif.id ? { ...n, is_read: true } : n) };
|
|
3787
|
-
});
|
|
3788
|
-
markRead(notif.id).catch(() => {
|
|
3789
|
-
queryClient.invalidateQueries({ queryKey: ["notification-unread-count"] });
|
|
3790
|
-
queryClient.invalidateQueries({ queryKey: ["notifications-dropdown"] });
|
|
3791
|
-
});
|
|
3792
|
-
}
|
|
3793
|
-
onClose();
|
|
3794
|
-
onItemClick(notif);
|
|
3795
|
-
}, [queryClient, markRead, onItemClick, onClose]);
|
|
3796
|
-
const handleMarkAllRead = () => {
|
|
3797
|
-
queryClient.setQueryData(["notification-unread-count"], (old) => old ? { ...old, count: 0 } : old);
|
|
3798
|
-
queryClient.setQueryData(["notifications-dropdown"], (old) => {
|
|
3799
|
-
if (!old?.results) return old;
|
|
3800
|
-
return { ...old, results: old.results.map((n) => ({ ...n, is_read: true })) };
|
|
3801
|
-
});
|
|
3802
|
-
markAllRead().then(() => {
|
|
3803
|
-
queryClient.invalidateQueries({ queryKey: ["notification-unread-count"] });
|
|
3804
|
-
queryClient.invalidateQueries({ queryKey: ["notifications-dropdown"] });
|
|
3805
|
-
});
|
|
3806
|
-
};
|
|
3807
|
-
return /* @__PURE__ */ jsxs(
|
|
3808
|
-
"div",
|
|
3809
|
-
{
|
|
3810
|
-
className: "fixed inset-0 z-[210] flex flex-col bg-white",
|
|
3811
|
-
style: { paddingBottom: "var(--mobile-bottom-nav, 70px)" },
|
|
3812
|
-
children: [
|
|
3813
|
-
/* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between px-3 py-3 border-b border-gray-200 shrink-0", children: [
|
|
3814
|
-
/* @__PURE__ */ jsx("button", { onClick: onClose, className: "p-2 -ml-1 rounded-full active:bg-gray-200 text-gray-700", "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }),
|
|
3815
|
-
/* @__PURE__ */ jsx("h1", { className: "text-base font-semibold text-gray-900", children: "Notifications" }),
|
|
3816
|
-
unreadCount > 0 ? /* @__PURE__ */ jsx("button", { onClick: handleMarkAllRead, className: "text-xs text-blue-600 font-medium px-2 py-1 active:bg-blue-50 rounded", children: "Mark all read" }) : /* @__PURE__ */ jsx("span", { className: "w-[88px]" })
|
|
3817
|
-
] }),
|
|
3818
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: notifications.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-16 px-6 text-center", children: [
|
|
3819
|
-
/* @__PURE__ */ jsx("svg", { className: "h-10 w-10 text-gray-300 mb-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" }) }),
|
|
3820
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-700 font-medium", children: "All caught up" }),
|
|
3821
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-400 mt-1", children: "No notifications yet" })
|
|
3822
|
-
] }) : notifications.map((notif) => /* @__PURE__ */ jsxs(
|
|
3823
|
-
"button",
|
|
3824
|
-
{
|
|
3825
|
-
onClick: () => handleClick(notif),
|
|
3826
|
-
className: "w-full flex items-start gap-3 px-4 py-3 active:bg-gray-100 border-b border-gray-100 text-left",
|
|
3827
|
-
children: [
|
|
3828
|
-
/* @__PURE__ */ jsx("div", { className: "pt-1 shrink-0", children: !notif.is_read ? /* @__PURE__ */ jsx("div", { className: "h-2.5 w-2.5 rounded-full bg-blue-500" }) : /* @__PURE__ */ jsx("div", { className: "h-2.5 w-2.5" }) }),
|
|
3829
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
3830
|
-
/* @__PURE__ */ jsx("p", { className: `text-sm leading-snug ${!notif.is_read ? "font-medium text-gray-900" : "text-gray-700"}`, children: notif.title }),
|
|
3831
|
-
notif.message && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1 line-clamp-2", children: notif.message }),
|
|
3832
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-1.5", children: [
|
|
3833
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] text-gray-400", children: timeAgo2(notif.created_at) }),
|
|
3834
|
-
notif.actor_name && /* @__PURE__ */ jsxs("span", { className: "text-[11px] text-gray-400", children: [
|
|
3835
|
-
"by ",
|
|
3836
|
-
notif.actor_name
|
|
3837
|
-
] })
|
|
3838
|
-
] })
|
|
3839
|
-
] })
|
|
3840
|
-
]
|
|
3841
|
-
},
|
|
3842
|
-
notif.id
|
|
3843
|
-
)) })
|
|
3844
|
-
]
|
|
3845
|
-
}
|
|
3846
|
-
);
|
|
3847
|
-
}
|
|
3848
|
-
function MobileProfileSheet({ profile, user, onClose, onNavigate, onLogout }) {
|
|
3849
|
-
const initial = (profile?.first_name?.charAt(0) || user?.email?.charAt(0) || "?").toUpperCase();
|
|
3850
|
-
const displayName = profile?.first_name ? `${profile.first_name} ${profile.last_name || ""}`.trim() : user?.email ?? "Account";
|
|
3851
|
-
const groups = profile?.group_names ?? [];
|
|
3852
|
-
const handleNav = (path) => {
|
|
3853
|
-
onNavigate(path);
|
|
3854
|
-
onClose();
|
|
3855
|
-
};
|
|
3856
|
-
return /* @__PURE__ */ jsxs(
|
|
3345
|
+
const hasLink = !!config?.url;
|
|
3346
|
+
const heading = config?.heading ?? (hasLink ? `Continue in the ${productName} app` : `${productName} works best on desktop`);
|
|
3347
|
+
const description = config?.description ?? (hasLink ? "This experience is built for the mobile app. Open it to continue on your phone." : "Open this page on a larger screen to continue.");
|
|
3348
|
+
const ctaLabel = config?.ctaLabel ?? "Open the app";
|
|
3349
|
+
return /* @__PURE__ */ jsx(
|
|
3857
3350
|
"div",
|
|
3858
3351
|
{
|
|
3859
|
-
className: "
|
|
3860
|
-
style: { paddingBottom: "
|
|
3861
|
-
children:
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
/* @__PURE__ */
|
|
3871
|
-
|
|
3872
|
-
groups.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap justify-center gap-1.5", children: groups.map((g) => /* @__PURE__ */ jsx("span", { className: "text-[11px] px-2 py-0.5 rounded-full bg-gray-100 text-gray-700", children: g }, g)) })
|
|
3873
|
-
] }),
|
|
3874
|
-
/* @__PURE__ */ jsxs("div", { className: "py-2", children: [
|
|
3875
|
-
/* @__PURE__ */ jsxs(
|
|
3876
|
-
"button",
|
|
3877
|
-
{
|
|
3878
|
-
onClick: () => handleNav("/customization"),
|
|
3879
|
-
className: "w-full flex items-center gap-3 px-4 py-4 active:bg-gray-100 border-b border-gray-100 text-left",
|
|
3880
|
-
children: [
|
|
3881
|
-
/* @__PURE__ */ jsx("span", { className: "h-9 w-9 rounded-lg bg-gray-100 flex items-center justify-center text-gray-700 shrink-0", children: /* @__PURE__ */ jsxs("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: [
|
|
3882
|
-
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" }),
|
|
3883
|
-
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" })
|
|
3884
|
-
] }) }),
|
|
3885
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1 text-sm font-medium text-gray-800", children: "Preferences" }),
|
|
3886
|
-
/* @__PURE__ */ jsx("svg", { className: "h-4 w-4 text-gray-400 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 4.5l7.5 7.5-7.5 7.5" }) })
|
|
3887
|
-
]
|
|
3888
|
-
}
|
|
3889
|
-
),
|
|
3890
|
-
/* @__PURE__ */ jsxs(
|
|
3891
|
-
"button",
|
|
3352
|
+
className: "flex-1 flex items-center justify-center p-6",
|
|
3353
|
+
style: { ...wallpaperStyle, paddingBottom: "calc(env(safe-area-inset-bottom) + 1.5rem)" },
|
|
3354
|
+
children: /* @__PURE__ */ jsxs(
|
|
3355
|
+
"div",
|
|
3356
|
+
{
|
|
3357
|
+
className: "w-full max-w-sm rounded-3xl p-8 flex flex-col items-center text-center",
|
|
3358
|
+
style: glassStyle(),
|
|
3359
|
+
children: [
|
|
3360
|
+
/* @__PURE__ */ jsx("div", { className: "h-20 w-20 rounded-2xl overflow-hidden bg-white/60 flex items-center justify-center shadow-sm mb-5", children: /* @__PURE__ */ jsx("img", { src: productIcon, alt: "", className: "h-full w-full object-contain p-3" }) }),
|
|
3361
|
+
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-gray-900 leading-snug", children: heading }),
|
|
3362
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-gray-600 leading-relaxed", children: description }),
|
|
3363
|
+
hasLink && /* @__PURE__ */ jsxs(
|
|
3364
|
+
"a",
|
|
3892
3365
|
{
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
},
|
|
3897
|
-
className: "w-full flex items-center gap-3 px-4 py-4 active:bg-red-50 text-left",
|
|
3366
|
+
href: config.url,
|
|
3367
|
+
rel: "noopener noreferrer",
|
|
3368
|
+
className: "mt-6 w-full inline-flex items-center justify-center gap-2 rounded-xl bg-blue-600 px-5 py-3 text-sm font-semibold text-white shadow-sm transition-colors hover:bg-blue-700 active:bg-blue-800",
|
|
3898
3369
|
children: [
|
|
3899
|
-
|
|
3900
|
-
/* @__PURE__ */ jsx("
|
|
3370
|
+
ctaLabel,
|
|
3371
|
+
/* @__PURE__ */ jsx("svg", { 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: "M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" }) })
|
|
3901
3372
|
]
|
|
3902
3373
|
}
|
|
3903
3374
|
)
|
|
3904
|
-
]
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
}
|
|
3908
|
-
);
|
|
3909
|
-
}
|
|
3910
|
-
function MobileShell({
|
|
3911
|
-
navSections: navSections2,
|
|
3912
|
-
navIcons: navIcons2,
|
|
3913
|
-
sectionIcons: sectionIcons2,
|
|
3914
|
-
wallpaperStyle,
|
|
3915
|
-
notifications,
|
|
3916
|
-
profile,
|
|
3917
|
-
user,
|
|
3918
|
-
onNavigate,
|
|
3919
|
-
onLogout
|
|
3920
|
-
}) {
|
|
3921
|
-
const { openWindows, openPage, closeEntity } = useWindowManager();
|
|
3922
|
-
const mode = useSyncExternalStore(subscribeMobileMode, getMobileMode);
|
|
3923
|
-
const [sheet, setSheet] = useState(null);
|
|
3924
|
-
const unreadCount = notifications?.useUnreadCount() ?? 0;
|
|
3925
|
-
const switcherWindows = useMemo(() => {
|
|
3926
|
-
return openWindows.filter((w) => {
|
|
3927
|
-
if (!w.route) return true;
|
|
3928
|
-
const entry = WINDOW_REGISTRY[w.route];
|
|
3929
|
-
if (!entry || !isPageEntry(entry)) return true;
|
|
3930
|
-
return !entry.widget;
|
|
3931
|
-
});
|
|
3932
|
-
}, [openWindows]);
|
|
3933
|
-
const prevOpenCountRef = useRef(openWindows.length);
|
|
3934
|
-
useEffect(() => {
|
|
3935
|
-
if (openWindows.length === 0 && mode === "app") {
|
|
3936
|
-
setMobileMode("home");
|
|
3937
|
-
}
|
|
3938
|
-
prevOpenCountRef.current = openWindows.length;
|
|
3939
|
-
}, [openWindows.length, mode]);
|
|
3940
|
-
const activateWindowById = (windowId) => {
|
|
3941
|
-
const panel = document.querySelector(`[data-modal-panel][data-window-key="${windowId}"]`);
|
|
3942
|
-
const mid = panel?.getAttribute("data-modal-id");
|
|
3943
|
-
if (mid) activateModal(mid);
|
|
3944
|
-
};
|
|
3945
|
-
const handleOpenApp = (path) => {
|
|
3946
|
-
openPage(path);
|
|
3947
|
-
setMobileMode("app");
|
|
3948
|
-
};
|
|
3949
|
-
const handleActivateWindow = (id) => {
|
|
3950
|
-
activateWindowById(id);
|
|
3951
|
-
setMobileMode("app");
|
|
3952
|
-
};
|
|
3953
|
-
const closeSheet = () => setSheet(null);
|
|
3954
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3955
|
-
/* @__PURE__ */ jsx(
|
|
3956
|
-
"div",
|
|
3957
|
-
{
|
|
3958
|
-
className: "fixed inset-0 z-0 pointer-events-none",
|
|
3959
|
-
style: wallpaperStyle
|
|
3960
|
-
}
|
|
3961
|
-
),
|
|
3962
|
-
mode === "home" && /* @__PURE__ */ jsx(
|
|
3963
|
-
"div",
|
|
3964
|
-
{
|
|
3965
|
-
className: "fixed inset-0 z-[200]",
|
|
3966
|
-
style: {
|
|
3967
|
-
...wallpaperStyle,
|
|
3968
|
-
paddingBottom: "var(--mobile-bottom-nav, 70px)"
|
|
3969
|
-
},
|
|
3970
|
-
children: /* @__PURE__ */ jsx(
|
|
3971
|
-
MobileHome,
|
|
3972
|
-
{
|
|
3973
|
-
navSections: navSections2,
|
|
3974
|
-
navIcons: navIcons2,
|
|
3975
|
-
sectionIcons: sectionIcons2,
|
|
3976
|
-
openWindows,
|
|
3977
|
-
onOpenApp: handleOpenApp,
|
|
3978
|
-
onActivateWindow: handleActivateWindow
|
|
3979
|
-
}
|
|
3980
|
-
)
|
|
3981
|
-
}
|
|
3982
|
-
),
|
|
3983
|
-
mode === "switcher" && /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-[200] bg-gray-900/95 backdrop-blur-sm", style: { paddingBottom: "var(--mobile-bottom-nav, 70px)" }, children: /* @__PURE__ */ jsx(
|
|
3984
|
-
MobileSwitcher,
|
|
3985
|
-
{
|
|
3986
|
-
windows: switcherWindows,
|
|
3987
|
-
onActivate: handleActivateWindow,
|
|
3988
|
-
onClose: (id) => closeEntity(id),
|
|
3989
|
-
onCloseAll: () => switcherWindows.forEach((w) => closeEntity(w.id))
|
|
3990
|
-
}
|
|
3991
|
-
) }),
|
|
3992
|
-
sheet === "notifications" && notifications && /* @__PURE__ */ jsx(MobileNotificationSheet, { config: notifications, onClose: closeSheet }),
|
|
3993
|
-
sheet === "profile" && /* @__PURE__ */ jsx(
|
|
3994
|
-
MobileProfileSheet,
|
|
3995
|
-
{
|
|
3996
|
-
profile,
|
|
3997
|
-
user,
|
|
3998
|
-
onClose: closeSheet,
|
|
3999
|
-
onNavigate: (path) => {
|
|
4000
|
-
onNavigate?.(path);
|
|
4001
|
-
},
|
|
4002
|
-
onLogout: () => onLogout?.()
|
|
4003
|
-
}
|
|
4004
|
-
),
|
|
4005
|
-
/* @__PURE__ */ jsx(
|
|
4006
|
-
MobileBottomNav,
|
|
4007
|
-
{
|
|
4008
|
-
mode,
|
|
4009
|
-
unreadCount,
|
|
4010
|
-
showNotifications: !!notifications,
|
|
4011
|
-
profileAvatar: profile?.avatar_url,
|
|
4012
|
-
profileInitial: (profile?.first_name?.charAt(0) || user?.email?.charAt(0) || "?").toUpperCase(),
|
|
4013
|
-
onHome: () => {
|
|
4014
|
-
closeSheet();
|
|
4015
|
-
setMobileMode("home");
|
|
4016
|
-
},
|
|
4017
|
-
onSwitcher: () => {
|
|
4018
|
-
closeSheet();
|
|
4019
|
-
setMobileMode("switcher");
|
|
4020
|
-
},
|
|
4021
|
-
onNotifications: () => setSheet(sheet === "notifications" ? null : "notifications"),
|
|
4022
|
-
onProfile: () => setSheet(sheet === "profile" ? null : "profile")
|
|
4023
|
-
}
|
|
4024
|
-
)
|
|
4025
|
-
] });
|
|
4026
|
-
}
|
|
4027
|
-
function MobileBottomNav({
|
|
4028
|
-
mode,
|
|
4029
|
-
unreadCount,
|
|
4030
|
-
showNotifications,
|
|
4031
|
-
profileAvatar,
|
|
4032
|
-
profileInitial,
|
|
4033
|
-
onHome,
|
|
4034
|
-
onSwitcher,
|
|
4035
|
-
onNotifications,
|
|
4036
|
-
onProfile
|
|
4037
|
-
}) {
|
|
4038
|
-
const btnClass = (active) => `flex-1 flex flex-col items-center justify-center gap-0.5 py-2 transition-colors select-none ${active ? "text-blue-600" : "text-gray-700 active:text-gray-900"}`;
|
|
4039
|
-
return /* @__PURE__ */ jsxs(
|
|
4040
|
-
"nav",
|
|
4041
|
-
{
|
|
4042
|
-
className: "fixed bottom-0 inset-x-0 z-[300] flex items-stretch border-t border-white/40",
|
|
4043
|
-
style: {
|
|
4044
|
-
height: "var(--mobile-bottom-nav, 70px)",
|
|
4045
|
-
paddingBottom: "env(safe-area-inset-bottom)",
|
|
4046
|
-
WebkitBackdropFilter: "blur(28px) saturate(1.8)",
|
|
4047
|
-
backdropFilter: "blur(28px) saturate(1.8)",
|
|
4048
|
-
background: "linear-gradient(135deg, rgba(255,255,255,0.65) 0%, rgba(255,255,255,0.45) 50%, rgba(255,255,255,0.55) 100%)",
|
|
4049
|
-
boxShadow: "inset 0 1px 0 rgba(255,255,255,0.6), 0 -2px 12px rgba(0,0,0,0.08)"
|
|
4050
|
-
},
|
|
4051
|
-
children: [
|
|
4052
|
-
/* @__PURE__ */ jsxs("button", { onClick: onHome, className: btnClass(mode === "home"), "aria-label": "Home", children: [
|
|
4053
|
-
/* @__PURE__ */ jsx("svg", { className: "h-8 w-8", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.7, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" }) }),
|
|
4054
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Home" })
|
|
4055
|
-
] }),
|
|
4056
|
-
/* @__PURE__ */ jsxs("button", { onClick: onSwitcher, className: btnClass(mode === "switcher"), "aria-label": "App switcher", children: [
|
|
4057
|
-
/* @__PURE__ */ jsxs("svg", { className: "h-8 w-8", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.7, children: [
|
|
4058
|
-
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "3.5", width: "7", height: "7", rx: "1.25" }),
|
|
4059
|
-
/* @__PURE__ */ jsx("rect", { x: "13.5", y: "3.5", width: "7", height: "7", rx: "1.25" }),
|
|
4060
|
-
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "13.5", width: "7", height: "7", rx: "1.25" }),
|
|
4061
|
-
/* @__PURE__ */ jsx("rect", { x: "13.5", y: "13.5", width: "7", height: "7", rx: "1.25" })
|
|
4062
|
-
] }),
|
|
4063
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Apps" })
|
|
4064
|
-
] }),
|
|
4065
|
-
showNotifications && /* @__PURE__ */ jsxs("button", { onClick: onNotifications, className: btnClass(false), "aria-label": "Notifications", children: [
|
|
4066
|
-
/* @__PURE__ */ jsxs("span", { className: "relative", children: [
|
|
4067
|
-
/* @__PURE__ */ jsx("svg", { className: "h-8 w-8", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.7, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" }) }),
|
|
4068
|
-
unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute -top-1.5 -right-2 min-w-[18px] h-[18px] px-1 rounded-full bg-red-500 text-white text-[10px] font-bold leading-[18px] text-center", children: unreadCount > 99 ? "99+" : unreadCount })
|
|
4069
|
-
] }),
|
|
4070
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Alerts" })
|
|
4071
|
-
] }),
|
|
4072
|
-
/* @__PURE__ */ jsxs("button", { onClick: onProfile, className: btnClass(false), "aria-label": "Profile", children: [
|
|
4073
|
-
profileAvatar ? /* @__PURE__ */ jsx("img", { src: profileAvatar, alt: "", className: "h-8 w-8 rounded-full object-cover border border-gray-200" }) : /* @__PURE__ */ jsx("div", { className: "h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center text-xs font-bold text-blue-700", children: profileInitial }),
|
|
4074
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Profile" })
|
|
4075
|
-
] })
|
|
4076
|
-
]
|
|
3375
|
+
]
|
|
3376
|
+
}
|
|
3377
|
+
)
|
|
4077
3378
|
}
|
|
4078
3379
|
);
|
|
4079
3380
|
}
|
|
@@ -4357,7 +3658,8 @@ function Layout({
|
|
|
4357
3658
|
notifications,
|
|
4358
3659
|
search,
|
|
4359
3660
|
taskbarTrayLeft,
|
|
4360
|
-
clockCalendar
|
|
3661
|
+
clockCalendar,
|
|
3662
|
+
mobileApp
|
|
4361
3663
|
} = {}) {
|
|
4362
3664
|
const host = useDesktopHost();
|
|
4363
3665
|
const { user, logout, hasAnyPerm } = useAuth();
|
|
@@ -4370,7 +3672,7 @@ function Layout({
|
|
|
4370
3672
|
const { prefs, save: savePrefs } = useShellPrefs();
|
|
4371
3673
|
const layoutMode = prefs.layout_mode === "sidebar" ? "sidebar" : "classic";
|
|
4372
3674
|
const sidebarMode = layoutMode === "sidebar";
|
|
4373
|
-
const sidebarWidth = sidebarMode ?
|
|
3675
|
+
const sidebarWidth = sidebarMode ? SIDEBAR_STRIP_W : 0;
|
|
4374
3676
|
const taskbarPositionRaw = prefs.taskbar_position || "bottom";
|
|
4375
3677
|
const taskbarPosition = sidebarMode ? "bottom" : taskbarPositionRaw;
|
|
4376
3678
|
const taskbarSize = prefs.taskbar_size || "medium";
|
|
@@ -4419,8 +3721,8 @@ function Layout({
|
|
|
4419
3721
|
root.style.setProperty("--window-tab-font-size", sv.tabFont);
|
|
4420
3722
|
}, [reduceTransparency, inactiveHeaderOpacity, inactiveContentOpacity, activeHeaderOpacity, activeContentOpacity, taskbarH, taskbarPosition, prefs.default_window_size, prefs.window_position, prefs.menu_density, prefs.start_menu_size, sidebarWidth, layoutMode]);
|
|
4421
3723
|
useEffect(() => {
|
|
4422
|
-
document.documentElement.style.setProperty("--mobile-bottom-nav",
|
|
4423
|
-
}, [
|
|
3724
|
+
document.documentElement.style.setProperty("--mobile-bottom-nav", "0px");
|
|
3725
|
+
}, []);
|
|
4424
3726
|
const [balloonDismissed, setBalloonDismissed] = useState(false);
|
|
4425
3727
|
const [isFullscreen, setIsFullscreen] = useState(!!document.fullscreenElement);
|
|
4426
3728
|
const [taskbarMenu, setTaskbarMenu] = useState(null);
|
|
@@ -4578,19 +3880,12 @@ function Layout({
|
|
|
4578
3880
|
};
|
|
4579
3881
|
if (isMobile) {
|
|
4580
3882
|
return /* @__PURE__ */ jsx(
|
|
4581
|
-
|
|
3883
|
+
MobileAppLanding,
|
|
4582
3884
|
{
|
|
4583
3885
|
productName,
|
|
4584
3886
|
productIcon,
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
sectionIcons: sectionIcons2,
|
|
4588
|
-
wallpaperStyle,
|
|
4589
|
-
notifications,
|
|
4590
|
-
profile,
|
|
4591
|
-
user,
|
|
4592
|
-
onNavigate: (path) => openPage(path),
|
|
4593
|
-
onLogout: () => setShowLogout(true)
|
|
3887
|
+
config: mobileApp,
|
|
3888
|
+
wallpaperStyle
|
|
4594
3889
|
}
|
|
4595
3890
|
);
|
|
4596
3891
|
}
|
|
@@ -5081,7 +4376,7 @@ function Customization({ omit, section } = {}) {
|
|
|
5081
4376
|
inSection("layout") && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5082
4377
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
5083
4378
|
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900 mb-3", children: "Layout Mode" }),
|
|
5084
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mb-3", children: "Sidebar mode is designed for small screens \u2014 windows always run maximized and the start menu lives in a persistent left sidebar (sections expand inline instead of opening flyouts)." }),
|
|
4379
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mb-3", children: "Sidebar mode is designed for small screens \u2014 windows always run maximized and the start menu lives in a persistent left sidebar (sections expand inline instead of opening flyouts). Classic is the windowed mode: choosing it puts every open window back to its normal size." }),
|
|
5085
4380
|
/* @__PURE__ */ jsx("div", { className: "flex gap-2", children: [
|
|
5086
4381
|
{ key: "classic", label: "Classic" },
|
|
5087
4382
|
{ key: "sidebar", label: "Sidebar" }
|
|
@@ -5090,7 +4385,11 @@ function Customization({ omit, section } = {}) {
|
|
|
5090
4385
|
{
|
|
5091
4386
|
onClick: () => {
|
|
5092
4387
|
savePref("layout_mode", m.key);
|
|
5093
|
-
if (m.key === "
|
|
4388
|
+
if (m.key === "classic") {
|
|
4389
|
+
if (prefs.default_window_size === "maximized") savePref("default_window_size", "large");
|
|
4390
|
+
forgetMaximizedWindowBoxes();
|
|
4391
|
+
window.dispatchEvent(new CustomEvent("react-os-shell:restore-windowed"));
|
|
4392
|
+
}
|
|
5094
4393
|
},
|
|
5095
4394
|
className: `px-3 py-1.5 text-xs font-medium rounded-lg border transition-colors ${(prefs.layout_mode || "classic") === m.key ? "bg-blue-600 text-white border-blue-600" : "bg-white text-gray-700 border-gray-300 hover:bg-gray-50"}`,
|
|
5096
4395
|
children: m.label
|
|
@@ -5969,13 +5268,75 @@ function ListFooter({
|
|
|
5969
5268
|
isFetchingMore,
|
|
5970
5269
|
extra
|
|
5971
5270
|
}) {
|
|
5972
|
-
const total = totalCount ?? loadedCount;
|
|
5973
|
-
const allLoaded = loadedCount >= total;
|
|
5974
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5975
|
-
extra,
|
|
5976
|
-
selectedCount > 0 ? `${selectedCount} selected \u2014 ` : "",
|
|
5977
|
-
allLoaded ? totalCount != null ? `All ${total.toLocaleString()} ${label} loaded` : `${total.toLocaleString()} ${label}` : `${loadedCount.toLocaleString()} of ${total.toLocaleString()} ${label}`,
|
|
5978
|
-
isFetchingMore ? " \xB7 Loading more..." : ""
|
|
5271
|
+
const total = totalCount ?? loadedCount;
|
|
5272
|
+
const allLoaded = loadedCount >= total;
|
|
5273
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5274
|
+
extra,
|
|
5275
|
+
selectedCount > 0 ? `${selectedCount} selected \u2014 ` : "",
|
|
5276
|
+
allLoaded ? totalCount != null ? `All ${total.toLocaleString()} ${label} loaded` : `${total.toLocaleString()} ${label}` : `${loadedCount.toLocaleString()} of ${total.toLocaleString()} ${label}`,
|
|
5277
|
+
isFetchingMore ? " \xB7 Loading more..." : ""
|
|
5278
|
+
] });
|
|
5279
|
+
}
|
|
5280
|
+
var BASE = "inline-flex items-center justify-center rounded-md font-medium transition-colors focus:outline-none focus:ring-2 disabled:cursor-not-allowed disabled:opacity-60";
|
|
5281
|
+
var VARIANTS2 = {
|
|
5282
|
+
primary: "bg-blue-600 text-white shadow-sm hover:bg-blue-700 focus:ring-blue-400/40",
|
|
5283
|
+
secondary: "border border-gray-300 bg-white text-gray-700 shadow-sm hover:bg-gray-50 focus:ring-blue-400/30",
|
|
5284
|
+
ghost: "text-gray-700 hover:bg-gray-100 focus:ring-blue-400/30",
|
|
5285
|
+
danger: "bg-red-600 text-white shadow-sm hover:bg-red-700 focus:ring-red-400/40"
|
|
5286
|
+
};
|
|
5287
|
+
var SIZES = {
|
|
5288
|
+
sm: "gap-1 px-2.5 py-1 text-xs",
|
|
5289
|
+
md: "gap-1.5 px-3 py-1.5 text-sm"
|
|
5290
|
+
};
|
|
5291
|
+
function Spinner() {
|
|
5292
|
+
return /* @__PURE__ */ jsxs("svg", { className: "h-3.5 w-3.5 animate-spin", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
|
|
5293
|
+
/* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
5294
|
+
/* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" })
|
|
5295
|
+
] });
|
|
5296
|
+
}
|
|
5297
|
+
var Button = forwardRef(function Button2({
|
|
5298
|
+
variant = "primary",
|
|
5299
|
+
size = "md",
|
|
5300
|
+
loading = false,
|
|
5301
|
+
leftIcon,
|
|
5302
|
+
rightIcon,
|
|
5303
|
+
block = false,
|
|
5304
|
+
disabled,
|
|
5305
|
+
type = "button",
|
|
5306
|
+
children,
|
|
5307
|
+
className = "",
|
|
5308
|
+
...rest
|
|
5309
|
+
}, ref) {
|
|
5310
|
+
return /* @__PURE__ */ jsxs(
|
|
5311
|
+
"button",
|
|
5312
|
+
{
|
|
5313
|
+
ref,
|
|
5314
|
+
type,
|
|
5315
|
+
disabled: disabled || loading,
|
|
5316
|
+
"aria-busy": loading || void 0,
|
|
5317
|
+
className: [BASE, VARIANTS2[variant], SIZES[size], block ? "w-full" : "", className].filter(Boolean).join(" "),
|
|
5318
|
+
...rest,
|
|
5319
|
+
children: [
|
|
5320
|
+
loading ? /* @__PURE__ */ jsx(Spinner, {}) : leftIcon,
|
|
5321
|
+
children,
|
|
5322
|
+
!loading && rightIcon
|
|
5323
|
+
]
|
|
5324
|
+
}
|
|
5325
|
+
);
|
|
5326
|
+
});
|
|
5327
|
+
var Button_default = Button;
|
|
5328
|
+
function ListLoadError({
|
|
5329
|
+
title = "Couldn't load this list",
|
|
5330
|
+
message = "Something went wrong fetching these records. Check your connection and try again.",
|
|
5331
|
+
onRetry,
|
|
5332
|
+
variant = "dashed"
|
|
5333
|
+
}) {
|
|
5334
|
+
const frame = variant === "card" ? "rounded-md border border-gray-200 bg-white px-6 py-12" : variant === "none" ? "px-6 py-12" : "rounded-lg border-2 border-dashed border-red-200 px-6 py-12";
|
|
5335
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex flex-col items-center justify-center text-center ${frame}`, role: "alert", children: [
|
|
5336
|
+
/* @__PURE__ */ jsx("svg", { className: "h-10 w-10 text-red-300 mb-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1, "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 9v3.75m0 3.75h.008M10.34 3.94l-8.4 14.55A1.5 1.5 0 003.24 21h17.52a1.5 1.5 0 001.3-2.51l-8.4-14.55a1.5 1.5 0 00-2.6 0z" }) }),
|
|
5337
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-gray-900", children: title }),
|
|
5338
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-2", children: message }),
|
|
5339
|
+
onRetry && /* @__PURE__ */ jsx("div", { className: "mt-4", children: /* @__PURE__ */ jsx(Button_default, { variant: "secondary", size: "sm", onClick: onRetry, children: "Try again" }) })
|
|
5979
5340
|
] });
|
|
5980
5341
|
}
|
|
5981
5342
|
function EntityList(props) {
|
|
@@ -5984,6 +5345,8 @@ function EntityList(props) {
|
|
|
5984
5345
|
isLoading,
|
|
5985
5346
|
emptyState,
|
|
5986
5347
|
totalCount,
|
|
5348
|
+
isError,
|
|
5349
|
+
onRetry,
|
|
5987
5350
|
tableId,
|
|
5988
5351
|
columns,
|
|
5989
5352
|
renderCell,
|
|
@@ -6069,6 +5432,7 @@ function EntityList(props) {
|
|
|
6069
5432
|
}
|
|
6070
5433
|
};
|
|
6071
5434
|
if (isLoading) return /* @__PURE__ */ jsx(LoadingSpinner, {});
|
|
5435
|
+
if (isError && items.length === 0) return /* @__PURE__ */ jsx(ListLoadError, { onRetry });
|
|
6072
5436
|
if (items.length === 0) return /* @__PURE__ */ jsx(Fragment, { children: emptyState });
|
|
6073
5437
|
const allSelected = items.length > 0 && selected.size === items.length;
|
|
6074
5438
|
const fullColumns = [
|
|
@@ -6426,6 +5790,10 @@ function useInfiniteScroll({
|
|
|
6426
5790
|
items: allItems,
|
|
6427
5791
|
totalCount,
|
|
6428
5792
|
isLoading: query.isLoading,
|
|
5793
|
+
// Surface the query's error state so a failed fetch renders as an error
|
|
5794
|
+
// (with retry) rather than a misleading empty list. `refetch` is the retry.
|
|
5795
|
+
isError: query.isError,
|
|
5796
|
+
error: query.error,
|
|
6429
5797
|
isFetchingNextPage,
|
|
6430
5798
|
hasNextPage: !!hasNextPage,
|
|
6431
5799
|
sentinelRef,
|
|
@@ -6542,54 +5910,6 @@ function Pagination({
|
|
|
6542
5910
|
showEdges && /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Last page", disabled: page === pageCount, onClick: () => go(pageCount), className: `${BTN} text-gray-600 hover:bg-gray-100`, children: "\xBB" })
|
|
6543
5911
|
] });
|
|
6544
5912
|
}
|
|
6545
|
-
var BASE = "inline-flex items-center justify-center rounded-md font-medium transition-colors focus:outline-none focus:ring-2 disabled:cursor-not-allowed disabled:opacity-60";
|
|
6546
|
-
var VARIANTS2 = {
|
|
6547
|
-
primary: "bg-blue-600 text-white shadow-sm hover:bg-blue-700 focus:ring-blue-400/40",
|
|
6548
|
-
secondary: "border border-gray-300 bg-white text-gray-700 shadow-sm hover:bg-gray-50 focus:ring-blue-400/30",
|
|
6549
|
-
ghost: "text-gray-700 hover:bg-gray-100 focus:ring-blue-400/30",
|
|
6550
|
-
danger: "bg-red-600 text-white shadow-sm hover:bg-red-700 focus:ring-red-400/40"
|
|
6551
|
-
};
|
|
6552
|
-
var SIZES = {
|
|
6553
|
-
sm: "gap-1 px-2.5 py-1 text-xs",
|
|
6554
|
-
md: "gap-1.5 px-3 py-1.5 text-sm"
|
|
6555
|
-
};
|
|
6556
|
-
function Spinner() {
|
|
6557
|
-
return /* @__PURE__ */ jsxs("svg", { className: "h-3.5 w-3.5 animate-spin", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
|
|
6558
|
-
/* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
6559
|
-
/* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" })
|
|
6560
|
-
] });
|
|
6561
|
-
}
|
|
6562
|
-
var Button = forwardRef(function Button2({
|
|
6563
|
-
variant = "primary",
|
|
6564
|
-
size = "md",
|
|
6565
|
-
loading = false,
|
|
6566
|
-
leftIcon,
|
|
6567
|
-
rightIcon,
|
|
6568
|
-
block = false,
|
|
6569
|
-
disabled,
|
|
6570
|
-
type = "button",
|
|
6571
|
-
children,
|
|
6572
|
-
className = "",
|
|
6573
|
-
...rest
|
|
6574
|
-
}, ref) {
|
|
6575
|
-
return /* @__PURE__ */ jsxs(
|
|
6576
|
-
"button",
|
|
6577
|
-
{
|
|
6578
|
-
ref,
|
|
6579
|
-
type,
|
|
6580
|
-
disabled: disabled || loading,
|
|
6581
|
-
"aria-busy": loading || void 0,
|
|
6582
|
-
className: [BASE, VARIANTS2[variant], SIZES[size], block ? "w-full" : "", className].filter(Boolean).join(" "),
|
|
6583
|
-
...rest,
|
|
6584
|
-
children: [
|
|
6585
|
-
loading ? /* @__PURE__ */ jsx(Spinner, {}) : leftIcon,
|
|
6586
|
-
children,
|
|
6587
|
-
!loading && rightIcon
|
|
6588
|
-
]
|
|
6589
|
-
}
|
|
6590
|
-
);
|
|
6591
|
-
});
|
|
6592
|
-
var Button_default = Button;
|
|
6593
5913
|
var Input = forwardRef(function Input2({ invalid, leftIcon, rightAdornment, className = "", ...rest }, ref) {
|
|
6594
5914
|
const pad = `${leftIcon ? "pl-9" : ""} ${rightAdornment ? "pr-9" : ""}`.trim();
|
|
6595
5915
|
const field = /* @__PURE__ */ jsx(
|
|
@@ -6629,7 +5949,44 @@ var Textarea = forwardRef(function Textarea2({ invalid, autoGrow, className = ""
|
|
|
6629
5949
|
);
|
|
6630
5950
|
});
|
|
6631
5951
|
var Textarea_default = Textarea;
|
|
6632
|
-
|
|
5952
|
+
|
|
5953
|
+
// src/forms/selectNav.ts
|
|
5954
|
+
function firstEnabledIndex(options) {
|
|
5955
|
+
for (let i = 0; i < options.length; i++) {
|
|
5956
|
+
if (!options[i].disabled) return i;
|
|
5957
|
+
}
|
|
5958
|
+
return -1;
|
|
5959
|
+
}
|
|
5960
|
+
function lastEnabledIndex(options) {
|
|
5961
|
+
for (let i = options.length - 1; i >= 0; i--) {
|
|
5962
|
+
if (!options[i].disabled) return i;
|
|
5963
|
+
}
|
|
5964
|
+
return -1;
|
|
5965
|
+
}
|
|
5966
|
+
function nextEnabledIndex(options, from, dir) {
|
|
5967
|
+
let i = from + dir;
|
|
5968
|
+
while (i >= 0 && i < options.length) {
|
|
5969
|
+
if (!options[i].disabled) return i;
|
|
5970
|
+
i += dir;
|
|
5971
|
+
}
|
|
5972
|
+
if (from >= 0 && from < options.length && !options[from].disabled) return from;
|
|
5973
|
+
return dir > 0 ? firstEnabledIndex(options) : lastEnabledIndex(options);
|
|
5974
|
+
}
|
|
5975
|
+
function matchTypeahead(options, buffer, fromIndex) {
|
|
5976
|
+
const q = buffer.toLowerCase();
|
|
5977
|
+
const n = options.length;
|
|
5978
|
+
if (!q || n === 0) return -1;
|
|
5979
|
+
for (let step = 1; step <= n; step++) {
|
|
5980
|
+
const i = ((fromIndex + step) % n + n) % n;
|
|
5981
|
+
const o = options[i];
|
|
5982
|
+
if (!o.disabled && o.label.toLowerCase().startsWith(q)) return i;
|
|
5983
|
+
}
|
|
5984
|
+
return -1;
|
|
5985
|
+
}
|
|
5986
|
+
var MENU_GAP2 = 4;
|
|
5987
|
+
var VIEWPORT_MARGIN2 = 8;
|
|
5988
|
+
var MENU_MAX_HEIGHT2 = 240;
|
|
5989
|
+
var NativeSelect = forwardRef(function NativeSelect2({ value, onChange, options, placeholder, invalid, className = "", ...rest }, ref) {
|
|
6633
5990
|
return /* @__PURE__ */ jsxs(
|
|
6634
5991
|
"select",
|
|
6635
5992
|
{
|
|
@@ -6645,6 +6002,260 @@ var Select = forwardRef(function Select2({ value, onChange, options, placeholder
|
|
|
6645
6002
|
}
|
|
6646
6003
|
);
|
|
6647
6004
|
});
|
|
6005
|
+
function useAnchoredPosition(triggerRef, open) {
|
|
6006
|
+
const [pos, setPos] = useState(null);
|
|
6007
|
+
useLayoutEffect(() => {
|
|
6008
|
+
if (!open) {
|
|
6009
|
+
setPos(null);
|
|
6010
|
+
return;
|
|
6011
|
+
}
|
|
6012
|
+
let lastLeft = NaN, lastTop = NaN, lastBottom = NaN;
|
|
6013
|
+
const compute = () => {
|
|
6014
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
6015
|
+
if (!rect) return;
|
|
6016
|
+
lastLeft = rect.left;
|
|
6017
|
+
lastTop = rect.top;
|
|
6018
|
+
lastBottom = rect.bottom;
|
|
6019
|
+
const spaceBelow = window.innerHeight - rect.bottom - MENU_GAP2 - VIEWPORT_MARGIN2;
|
|
6020
|
+
const spaceAbove = rect.top - MENU_GAP2 - VIEWPORT_MARGIN2;
|
|
6021
|
+
const placeAbove = spaceBelow < Math.min(MENU_MAX_HEIGHT2, 160) && spaceAbove > spaceBelow;
|
|
6022
|
+
const maxHeight = Math.max(96, Math.min(MENU_MAX_HEIGHT2, placeAbove ? spaceAbove : spaceBelow));
|
|
6023
|
+
const left = Math.max(VIEWPORT_MARGIN2, Math.min(rect.left, window.innerWidth - rect.width - VIEWPORT_MARGIN2));
|
|
6024
|
+
const next = { left, minWidth: rect.width, maxHeight };
|
|
6025
|
+
if (placeAbove) next.bottom = window.innerHeight - rect.top + MENU_GAP2;
|
|
6026
|
+
else next.top = rect.bottom + MENU_GAP2;
|
|
6027
|
+
setPos(next);
|
|
6028
|
+
};
|
|
6029
|
+
compute();
|
|
6030
|
+
let raf = requestAnimationFrame(function tick() {
|
|
6031
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
6032
|
+
if (rect && (rect.left !== lastLeft || rect.top !== lastTop || rect.bottom !== lastBottom)) compute();
|
|
6033
|
+
raf = requestAnimationFrame(tick);
|
|
6034
|
+
});
|
|
6035
|
+
window.addEventListener("scroll", compute, true);
|
|
6036
|
+
window.addEventListener("resize", compute);
|
|
6037
|
+
return () => {
|
|
6038
|
+
cancelAnimationFrame(raf);
|
|
6039
|
+
window.removeEventListener("scroll", compute, true);
|
|
6040
|
+
window.removeEventListener("resize", compute);
|
|
6041
|
+
};
|
|
6042
|
+
}, [open, triggerRef]);
|
|
6043
|
+
return pos;
|
|
6044
|
+
}
|
|
6045
|
+
var ListboxSelect = forwardRef(function ListboxSelect2({ value, onChange, options, placeholder, invalid, className = "", id, disabled, ...rest }, ref) {
|
|
6046
|
+
const [open, setOpen] = useState(false);
|
|
6047
|
+
const [active, setActive] = useState(-1);
|
|
6048
|
+
const wrapRef = useRef(null);
|
|
6049
|
+
const triggerRef = useRef(null);
|
|
6050
|
+
const listRef = useRef(null);
|
|
6051
|
+
const openRef = useRef(open);
|
|
6052
|
+
openRef.current = open;
|
|
6053
|
+
const typeahead = useRef({ buffer: "", timer: null });
|
|
6054
|
+
const baseId = useId();
|
|
6055
|
+
const listboxId = `${baseId}-listbox`;
|
|
6056
|
+
const optionId = (i) => `${baseId}-opt-${i}`;
|
|
6057
|
+
const menuPos = useAnchoredPosition(triggerRef, open);
|
|
6058
|
+
const selectedIndex = options.findIndex((o) => o.value === value);
|
|
6059
|
+
const selectedLabel = selectedIndex >= 0 ? options[selectedIndex].label : void 0;
|
|
6060
|
+
const close = useCallback((refocus = true) => {
|
|
6061
|
+
setOpen(false);
|
|
6062
|
+
setActive(-1);
|
|
6063
|
+
if (refocus) triggerRef.current?.focus();
|
|
6064
|
+
}, []);
|
|
6065
|
+
const openList = useCallback(() => {
|
|
6066
|
+
if (disabled) return;
|
|
6067
|
+
setActive(selectedIndex >= 0 ? selectedIndex : firstEnabledIndex(options));
|
|
6068
|
+
setOpen(true);
|
|
6069
|
+
}, [disabled, options, selectedIndex]);
|
|
6070
|
+
const commit = useCallback((i) => {
|
|
6071
|
+
const o = options[i];
|
|
6072
|
+
if (!o || o.disabled) return;
|
|
6073
|
+
onChange(o.value);
|
|
6074
|
+
close();
|
|
6075
|
+
}, [options, onChange, close]);
|
|
6076
|
+
useEffect(() => {
|
|
6077
|
+
if (!open) return;
|
|
6078
|
+
const unregister = registerModalEscapeInterceptor((e) => {
|
|
6079
|
+
if (e.key !== "Escape" || !openRef.current) return false;
|
|
6080
|
+
close();
|
|
6081
|
+
return true;
|
|
6082
|
+
});
|
|
6083
|
+
return unregister;
|
|
6084
|
+
}, [open, close]);
|
|
6085
|
+
useEffect(() => {
|
|
6086
|
+
if (!open) return;
|
|
6087
|
+
const handler = (e) => {
|
|
6088
|
+
const t = e.target;
|
|
6089
|
+
if (wrapRef.current?.contains(t) || listRef.current?.contains(t)) return;
|
|
6090
|
+
close(false);
|
|
6091
|
+
};
|
|
6092
|
+
document.addEventListener("pointerdown", handler);
|
|
6093
|
+
return () => document.removeEventListener("pointerdown", handler);
|
|
6094
|
+
}, [open, close]);
|
|
6095
|
+
useEffect(() => {
|
|
6096
|
+
if (!open || active < 0) return;
|
|
6097
|
+
listRef.current?.querySelector(`#${CSS.escape(optionId(active))}`)?.scrollIntoView({ block: "nearest" });
|
|
6098
|
+
});
|
|
6099
|
+
const runTypeahead = useCallback((char) => {
|
|
6100
|
+
const ta = typeahead.current;
|
|
6101
|
+
if (ta.timer) clearTimeout(ta.timer);
|
|
6102
|
+
ta.buffer += char;
|
|
6103
|
+
ta.timer = setTimeout(() => {
|
|
6104
|
+
ta.buffer = "";
|
|
6105
|
+
ta.timer = null;
|
|
6106
|
+
}, 500);
|
|
6107
|
+
const from = open ? active : selectedIndex;
|
|
6108
|
+
const hit = matchTypeahead(options, ta.buffer, from);
|
|
6109
|
+
if (hit < 0) return;
|
|
6110
|
+
if (open) setActive(hit);
|
|
6111
|
+
else commit(hit);
|
|
6112
|
+
}, [open, active, selectedIndex, options, commit]);
|
|
6113
|
+
const onKeyDown = (e) => {
|
|
6114
|
+
if (disabled) return;
|
|
6115
|
+
switch (e.key) {
|
|
6116
|
+
case "ArrowDown":
|
|
6117
|
+
e.preventDefault();
|
|
6118
|
+
if (!open) openList();
|
|
6119
|
+
else setActive((a) => nextEnabledIndex(options, a, 1));
|
|
6120
|
+
return;
|
|
6121
|
+
case "ArrowUp":
|
|
6122
|
+
e.preventDefault();
|
|
6123
|
+
if (!open) openList();
|
|
6124
|
+
else setActive((a) => nextEnabledIndex(options, a, -1));
|
|
6125
|
+
return;
|
|
6126
|
+
case "Home":
|
|
6127
|
+
if (open) {
|
|
6128
|
+
e.preventDefault();
|
|
6129
|
+
setActive(firstEnabledIndex(options));
|
|
6130
|
+
}
|
|
6131
|
+
return;
|
|
6132
|
+
case "End":
|
|
6133
|
+
if (open) {
|
|
6134
|
+
e.preventDefault();
|
|
6135
|
+
setActive(lastEnabledIndex(options));
|
|
6136
|
+
}
|
|
6137
|
+
return;
|
|
6138
|
+
case "Enter":
|
|
6139
|
+
if (open) {
|
|
6140
|
+
e.preventDefault();
|
|
6141
|
+
commit(active);
|
|
6142
|
+
}
|
|
6143
|
+
return;
|
|
6144
|
+
case " ":
|
|
6145
|
+
e.preventDefault();
|
|
6146
|
+
if (!open) openList();
|
|
6147
|
+
else commit(active);
|
|
6148
|
+
return;
|
|
6149
|
+
case "Escape":
|
|
6150
|
+
if (open) {
|
|
6151
|
+
e.preventDefault();
|
|
6152
|
+
e.stopPropagation();
|
|
6153
|
+
close();
|
|
6154
|
+
}
|
|
6155
|
+
return;
|
|
6156
|
+
case "Tab":
|
|
6157
|
+
if (open) close(false);
|
|
6158
|
+
return;
|
|
6159
|
+
default:
|
|
6160
|
+
if (e.key.length === 1 && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
|
6161
|
+
e.preventDefault();
|
|
6162
|
+
runTypeahead(e.key);
|
|
6163
|
+
}
|
|
6164
|
+
}
|
|
6165
|
+
};
|
|
6166
|
+
return /* @__PURE__ */ jsxs("div", { ref: wrapRef, className: "relative", children: [
|
|
6167
|
+
/* @__PURE__ */ jsx(
|
|
6168
|
+
"button",
|
|
6169
|
+
{
|
|
6170
|
+
ref: triggerRef,
|
|
6171
|
+
id,
|
|
6172
|
+
type: "button",
|
|
6173
|
+
role: "combobox",
|
|
6174
|
+
"aria-haspopup": "listbox",
|
|
6175
|
+
"aria-expanded": open,
|
|
6176
|
+
"aria-controls": open ? listboxId : void 0,
|
|
6177
|
+
"aria-activedescendant": open && active >= 0 ? optionId(active) : void 0,
|
|
6178
|
+
"aria-invalid": invalid || void 0,
|
|
6179
|
+
disabled,
|
|
6180
|
+
onClick: () => open ? close() : openList(),
|
|
6181
|
+
onKeyDown,
|
|
6182
|
+
className: inputClasses({ invalid, className: `pr-8 text-left ${className}`.trim() }),
|
|
6183
|
+
children: /* @__PURE__ */ jsx("span", { className: `block truncate ${selectedLabel === void 0 ? "text-gray-400" : ""}`, children: selectedLabel ?? placeholder ?? "\xA0" })
|
|
6184
|
+
}
|
|
6185
|
+
),
|
|
6186
|
+
/* @__PURE__ */ jsx(
|
|
6187
|
+
"svg",
|
|
6188
|
+
{
|
|
6189
|
+
"aria-hidden": "true",
|
|
6190
|
+
className: "pointer-events-none absolute right-2.5 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400",
|
|
6191
|
+
fill: "none",
|
|
6192
|
+
viewBox: "0 0 24 24",
|
|
6193
|
+
stroke: "currentColor",
|
|
6194
|
+
strokeWidth: 2,
|
|
6195
|
+
children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 9l3.75-3.75L15.75 9M8.25 15l3.75 3.75L15.75 15" })
|
|
6196
|
+
}
|
|
6197
|
+
),
|
|
6198
|
+
/* @__PURE__ */ jsxs(
|
|
6199
|
+
"select",
|
|
6200
|
+
{
|
|
6201
|
+
ref,
|
|
6202
|
+
value,
|
|
6203
|
+
onChange: (e) => onChange(e.target.value),
|
|
6204
|
+
disabled,
|
|
6205
|
+
"aria-hidden": "true",
|
|
6206
|
+
tabIndex: -1,
|
|
6207
|
+
className: "sr-only",
|
|
6208
|
+
...rest,
|
|
6209
|
+
children: [
|
|
6210
|
+
placeholder !== void 0 && /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: placeholder }),
|
|
6211
|
+
options.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, disabled: o.disabled, children: o.label }, o.value))
|
|
6212
|
+
]
|
|
6213
|
+
}
|
|
6214
|
+
),
|
|
6215
|
+
open && createPortal(
|
|
6216
|
+
/* @__PURE__ */ jsx(
|
|
6217
|
+
"div",
|
|
6218
|
+
{
|
|
6219
|
+
ref: listRef,
|
|
6220
|
+
id: listboxId,
|
|
6221
|
+
role: "listbox",
|
|
6222
|
+
className: "fixed z-[400] overflow-y-auto rounded-2xl py-1",
|
|
6223
|
+
style: {
|
|
6224
|
+
left: menuPos?.left,
|
|
6225
|
+
top: menuPos?.top,
|
|
6226
|
+
bottom: menuPos?.bottom,
|
|
6227
|
+
minWidth: menuPos?.minWidth,
|
|
6228
|
+
maxHeight: menuPos?.maxHeight ?? MENU_MAX_HEIGHT2,
|
|
6229
|
+
visibility: menuPos ? void 0 : "hidden",
|
|
6230
|
+
...glassStyle()
|
|
6231
|
+
},
|
|
6232
|
+
children: options.map((o, i) => /* @__PURE__ */ jsx(
|
|
6233
|
+
"div",
|
|
6234
|
+
{
|
|
6235
|
+
id: optionId(i),
|
|
6236
|
+
role: "option",
|
|
6237
|
+
"aria-selected": value === o.value,
|
|
6238
|
+
"aria-disabled": o.disabled || void 0,
|
|
6239
|
+
onPointerEnter: () => {
|
|
6240
|
+
if (!o.disabled) setActive(i);
|
|
6241
|
+
},
|
|
6242
|
+
onClick: () => commit(i),
|
|
6243
|
+
className: `mx-1 cursor-pointer truncate rounded-lg px-3 py-1.5 text-sm
|
|
6244
|
+
${o.disabled ? "cursor-not-allowed text-gray-400" : i === active ? "bg-blue-50 text-blue-700" : value === o.value ? "font-medium text-blue-600" : "text-gray-700"}`,
|
|
6245
|
+
children: o.label
|
|
6246
|
+
},
|
|
6247
|
+
o.value
|
|
6248
|
+
))
|
|
6249
|
+
}
|
|
6250
|
+
),
|
|
6251
|
+
document.body
|
|
6252
|
+
)
|
|
6253
|
+
] });
|
|
6254
|
+
});
|
|
6255
|
+
var Select = forwardRef(function Select2(props, ref) {
|
|
6256
|
+
const isMobile = useIsMobile();
|
|
6257
|
+
return isMobile ? /* @__PURE__ */ jsx(NativeSelect, { ref, ...props }) : /* @__PURE__ */ jsx(ListboxSelect, { ref, ...props });
|
|
6258
|
+
});
|
|
6648
6259
|
var Select_default = Select;
|
|
6649
6260
|
var BOX = "h-4 w-4 shrink-0 rounded border-gray-300 accent-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-400/30 disabled:cursor-not-allowed disabled:opacity-60";
|
|
6650
6261
|
var Checkbox = forwardRef(function Checkbox2({ checked, onChange, label, description, disabled, className = "", ...rest }, ref) {
|
|
@@ -7489,16 +7100,12 @@ function FilterBar({ filters, values, onChange, onClear, children }) {
|
|
|
7489
7100
|
onChange: (v) => onChange(f.field, v)
|
|
7490
7101
|
},
|
|
7491
7102
|
f.field
|
|
7492
|
-
) : /* @__PURE__ */
|
|
7493
|
-
|
|
7103
|
+
) : /* @__PURE__ */ jsx(
|
|
7104
|
+
PlainFilter,
|
|
7494
7105
|
{
|
|
7106
|
+
filter: f,
|
|
7495
7107
|
value: values[f.field] || "",
|
|
7496
|
-
onChange: (
|
|
7497
|
-
className: `border rounded-lg px-2.5 py-1.5 text-sm ${values[f.field] ? "border-blue-400 bg-blue-50 text-blue-700" : "border-gray-300 text-gray-600"}`,
|
|
7498
|
-
children: [
|
|
7499
|
-
/* @__PURE__ */ jsx("option", { value: "", children: f.label }),
|
|
7500
|
-
f.options.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
|
|
7501
|
-
]
|
|
7108
|
+
onChange: (v) => onChange(f.field, v)
|
|
7502
7109
|
},
|
|
7503
7110
|
f.field
|
|
7504
7111
|
);
|
|
@@ -7510,6 +7117,155 @@ function FilterBar({ filters, values, onChange, onClear, children }) {
|
|
|
7510
7117
|
] })
|
|
7511
7118
|
] });
|
|
7512
7119
|
}
|
|
7120
|
+
function PlainFilter({ filter, value, onChange }) {
|
|
7121
|
+
const [open, setOpen] = useState(false);
|
|
7122
|
+
const [active, setActive] = useState(-1);
|
|
7123
|
+
const ref = useRef(null);
|
|
7124
|
+
const triggerRef = useRef(null);
|
|
7125
|
+
const listRef = useRef(null);
|
|
7126
|
+
const openRef = useRef(open);
|
|
7127
|
+
openRef.current = open;
|
|
7128
|
+
const typeahead = useRef({ buffer: "", timer: null });
|
|
7129
|
+
const baseId = useId();
|
|
7130
|
+
const listboxId = `${baseId}-listbox`;
|
|
7131
|
+
const optionId = (i) => `${baseId}-opt-${i}`;
|
|
7132
|
+
const items = [{ value: "", label: filter.label }, ...filter.options];
|
|
7133
|
+
const selectedIndex = value ? items.findIndex((o) => o.value === value) : 0;
|
|
7134
|
+
const selectedLabel = value ? filter.options.find((o) => o.value === value)?.label : null;
|
|
7135
|
+
const close = useCallback((refocus = true) => {
|
|
7136
|
+
setOpen(false);
|
|
7137
|
+
setActive(-1);
|
|
7138
|
+
if (refocus) triggerRef.current?.focus();
|
|
7139
|
+
}, []);
|
|
7140
|
+
const openList = useCallback(() => {
|
|
7141
|
+
setActive(selectedIndex >= 0 ? selectedIndex : firstEnabledIndex(items));
|
|
7142
|
+
setOpen(true);
|
|
7143
|
+
}, [selectedIndex, items]);
|
|
7144
|
+
const commit = useCallback((i) => {
|
|
7145
|
+
const o = items[i];
|
|
7146
|
+
if (!o) return;
|
|
7147
|
+
onChange(o.value);
|
|
7148
|
+
close();
|
|
7149
|
+
}, [items, onChange, close]);
|
|
7150
|
+
useClickOutside(ref, useCallback(() => {
|
|
7151
|
+
if (open) close(false);
|
|
7152
|
+
}, [open, close]));
|
|
7153
|
+
useEffect(() => {
|
|
7154
|
+
if (!open) return;
|
|
7155
|
+
return registerModalEscapeInterceptor((e) => {
|
|
7156
|
+
if (e.key !== "Escape" || !openRef.current) return false;
|
|
7157
|
+
close();
|
|
7158
|
+
return true;
|
|
7159
|
+
});
|
|
7160
|
+
}, [open, close]);
|
|
7161
|
+
useEffect(() => {
|
|
7162
|
+
if (!open || active < 0) return;
|
|
7163
|
+
listRef.current?.querySelector(`#${CSS.escape(optionId(active))}`)?.scrollIntoView({ block: "nearest" });
|
|
7164
|
+
});
|
|
7165
|
+
const runTypeahead = (char) => {
|
|
7166
|
+
const ta = typeahead.current;
|
|
7167
|
+
if (ta.timer) clearTimeout(ta.timer);
|
|
7168
|
+
ta.buffer += char;
|
|
7169
|
+
ta.timer = setTimeout(() => {
|
|
7170
|
+
ta.buffer = "";
|
|
7171
|
+
ta.timer = null;
|
|
7172
|
+
}, 500);
|
|
7173
|
+
const hit = matchTypeahead(items, ta.buffer, open ? active : selectedIndex);
|
|
7174
|
+
if (hit < 0) return;
|
|
7175
|
+
if (open) setActive(hit);
|
|
7176
|
+
else commit(hit);
|
|
7177
|
+
};
|
|
7178
|
+
const onKeyDown = (e) => {
|
|
7179
|
+
switch (e.key) {
|
|
7180
|
+
case "ArrowDown":
|
|
7181
|
+
e.preventDefault();
|
|
7182
|
+
if (!open) openList();
|
|
7183
|
+
else setActive((a) => nextEnabledIndex(items, a, 1));
|
|
7184
|
+
return;
|
|
7185
|
+
case "ArrowUp":
|
|
7186
|
+
e.preventDefault();
|
|
7187
|
+
if (!open) openList();
|
|
7188
|
+
else setActive((a) => nextEnabledIndex(items, a, -1));
|
|
7189
|
+
return;
|
|
7190
|
+
case "Home":
|
|
7191
|
+
if (open) {
|
|
7192
|
+
e.preventDefault();
|
|
7193
|
+
setActive(firstEnabledIndex(items));
|
|
7194
|
+
}
|
|
7195
|
+
return;
|
|
7196
|
+
case "End":
|
|
7197
|
+
if (open) {
|
|
7198
|
+
e.preventDefault();
|
|
7199
|
+
setActive(lastEnabledIndex(items));
|
|
7200
|
+
}
|
|
7201
|
+
return;
|
|
7202
|
+
case "Enter":
|
|
7203
|
+
if (open) {
|
|
7204
|
+
e.preventDefault();
|
|
7205
|
+
commit(active);
|
|
7206
|
+
}
|
|
7207
|
+
return;
|
|
7208
|
+
case " ":
|
|
7209
|
+
e.preventDefault();
|
|
7210
|
+
if (!open) openList();
|
|
7211
|
+
else commit(active);
|
|
7212
|
+
return;
|
|
7213
|
+
case "Escape":
|
|
7214
|
+
if (open) {
|
|
7215
|
+
e.preventDefault();
|
|
7216
|
+
e.stopPropagation();
|
|
7217
|
+
close();
|
|
7218
|
+
}
|
|
7219
|
+
return;
|
|
7220
|
+
case "Tab":
|
|
7221
|
+
if (open) close(false);
|
|
7222
|
+
return;
|
|
7223
|
+
default:
|
|
7224
|
+
if (e.key.length === 1 && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
|
7225
|
+
e.preventDefault();
|
|
7226
|
+
runTypeahead(e.key);
|
|
7227
|
+
}
|
|
7228
|
+
}
|
|
7229
|
+
};
|
|
7230
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: "relative", children: [
|
|
7231
|
+
/* @__PURE__ */ jsxs(
|
|
7232
|
+
"button",
|
|
7233
|
+
{
|
|
7234
|
+
ref: triggerRef,
|
|
7235
|
+
type: "button",
|
|
7236
|
+
role: "combobox",
|
|
7237
|
+
"aria-haspopup": "listbox",
|
|
7238
|
+
"aria-expanded": open,
|
|
7239
|
+
"aria-controls": open ? listboxId : void 0,
|
|
7240
|
+
"aria-activedescendant": open && active >= 0 ? optionId(active) : void 0,
|
|
7241
|
+
onClick: () => open ? close() : openList(),
|
|
7242
|
+
onKeyDown,
|
|
7243
|
+
className: `flex items-center gap-1.5 border rounded-lg px-2.5 py-1.5 text-sm transition-colors ${value ? "border-blue-400 bg-blue-50 text-blue-700" : "border-gray-300 text-gray-600 hover:border-gray-400"}`,
|
|
7244
|
+
children: [
|
|
7245
|
+
/* @__PURE__ */ jsx("span", { className: "truncate max-w-[140px]", children: selectedLabel || filter.label }),
|
|
7246
|
+
value ? /* @__PURE__ */ jsx("button", { type: "button", onClick: (e) => {
|
|
7247
|
+
e.stopPropagation();
|
|
7248
|
+
onChange("");
|
|
7249
|
+
}, className: "text-blue-400 hover:text-blue-600", children: /* @__PURE__ */ jsx(XMarkIcon, { className: "h-3.5 w-3.5" }) }) : /* @__PURE__ */ jsx("svg", { className: `h-3.5 w-3.5 text-gray-400 transition-transform ${open ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19.5 8.25l-7.5 7.5-7.5-7.5" }) })
|
|
7250
|
+
]
|
|
7251
|
+
}
|
|
7252
|
+
),
|
|
7253
|
+
open && /* @__PURE__ */ jsx("div", { ref: listRef, id: listboxId, role: "listbox", className: "absolute top-full left-0 mt-1 w-56 rounded-2xl z-[400] max-h-52 overflow-y-auto py-1", style: glassStyle(), children: items.map((o, i) => /* @__PURE__ */ jsx(
|
|
7254
|
+
"div",
|
|
7255
|
+
{
|
|
7256
|
+
id: optionId(i),
|
|
7257
|
+
role: "option",
|
|
7258
|
+
"aria-selected": i === selectedIndex,
|
|
7259
|
+
onPointerEnter: () => setActive(i),
|
|
7260
|
+
onClick: () => commit(i),
|
|
7261
|
+
className: `mx-1 cursor-pointer truncate rounded-lg px-3 py-1.5 text-sm
|
|
7262
|
+
${i === active ? "bg-blue-50 text-blue-700" : i === selectedIndex ? "font-medium text-blue-600" : "text-gray-700"}`,
|
|
7263
|
+
children: o.label
|
|
7264
|
+
},
|
|
7265
|
+
o.value || "__all__"
|
|
7266
|
+
)) })
|
|
7267
|
+
] });
|
|
7268
|
+
}
|
|
7513
7269
|
function SearchableFilter({ filter, value, onChange }) {
|
|
7514
7270
|
const [open, setOpen] = useState(false);
|
|
7515
7271
|
const [search, setSearch] = useState("");
|
|
@@ -8499,7 +8255,7 @@ function ContainerFillChart({
|
|
|
8499
8255
|
}
|
|
8500
8256
|
var DEFAULT_POLL_MS = 15e3;
|
|
8501
8257
|
var DEFAULT_REQUEST_TIMEOUT_MS = 5e3;
|
|
8502
|
-
function
|
|
8258
|
+
function timeAgo2(date) {
|
|
8503
8259
|
if (!date) return "\u2014";
|
|
8504
8260
|
const diff = Math.max(0, Date.now() - date.getTime());
|
|
8505
8261
|
if (diff < 1500) return "just now";
|
|
@@ -8688,12 +8444,12 @@ function ServerStatusIndicator({
|
|
|
8688
8444
|
/* @__PURE__ */ jsxs("p", { className: "mt-1 text-[11px] text-gray-500", children: [
|
|
8689
8445
|
status === "connected" && lastOkAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8690
8446
|
"Last poll ",
|
|
8691
|
-
|
|
8447
|
+
timeAgo2(lastOkAt),
|
|
8692
8448
|
"."
|
|
8693
8449
|
] }),
|
|
8694
8450
|
status === "disconnected" && lastFailAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8695
8451
|
"Last failure ",
|
|
8696
|
-
|
|
8452
|
+
timeAgo2(lastFailAt),
|
|
8697
8453
|
"."
|
|
8698
8454
|
] }),
|
|
8699
8455
|
status === "checking" && /* @__PURE__ */ jsx(Fragment, { children: "First poll in flight\u2026" })
|
|
@@ -8711,7 +8467,7 @@ function ServerStatusIndicator({
|
|
|
8711
8467
|
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: lastOkAt.toLocaleTimeString() }),
|
|
8712
8468
|
/* @__PURE__ */ jsxs("span", { className: "text-gray-400 ml-1", children: [
|
|
8713
8469
|
"\xB7 ",
|
|
8714
|
-
|
|
8470
|
+
timeAgo2(lastOkAt)
|
|
8715
8471
|
] })
|
|
8716
8472
|
] }) : "\u2014" }),
|
|
8717
8473
|
lastFailAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -8720,7 +8476,7 @@ function ServerStatusIndicator({
|
|
|
8720
8476
|
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: lastFailAt.toLocaleTimeString() }),
|
|
8721
8477
|
/* @__PURE__ */ jsxs("span", { className: "text-gray-400 ml-1", children: [
|
|
8722
8478
|
"\xB7 ",
|
|
8723
|
-
|
|
8479
|
+
timeAgo2(lastFailAt)
|
|
8724
8480
|
] })
|
|
8725
8481
|
] })
|
|
8726
8482
|
] }),
|
|
@@ -9879,6 +9635,6 @@ function useEditHotkey(callback) {
|
|
|
9879
9635
|
}, [callback, isActive]);
|
|
9880
9636
|
}
|
|
9881
9637
|
|
|
9882
|
-
export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, Accordion, AuthScreen, Avatar, AvatarGroup, Banner, BarChart, BehaviorPanel, BulkImportGrid, Button_default as Button, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Card, ChangePasswordForm, ChatTemplate, Checkbox_default as Checkbox, CheckoutTemplate, ColoredBadge, ContainerFillChart, Customization, DEV_BANNER_TEXT, DashboardTemplate, DataTablePage, Desktop, DesktopHostProvider, DevIndicator, DonutChart, ENTER, EmailTemplate, EmptyState, EntityList, ErrorPage, FilterBar, FormField, FormLayoutPage, GalleryTemplate, GlobalSearch, HelpCenter, INPUT_BASE, Input_default as Input, Kanban, Label, Layout, ListFooter, LoadingSpinner2 as LoadingSpinner, MOD, Markdown, MediaUploadField, MediaUploadGrid, MetricBar, MilestoneTimeline, NotificationBell, PageHeader, Pagination, PdfActionButton, Radio_default as Radio, ResizableTable, SHIFT, SearchableSelect, Select_default as Select, ServerStatusIndicator, ShellEntityFetcherProvider, ShortcutHelp, SidebarActionButton, SidebarGroupLabel, SidebarNavItem, SoundsPanel, Sparkline, StartMenu, StatCard, StatusBadge, StatusBadgeProvider, SystemPreferences, Tabs, Textarea_default as Textarea, Tooltip, TopNav, WidgetManager, applyDevTitle, createWindowRegistry, findDuplicateKeys, formatDate, inputClasses, isDevEnv, isMac, isSeverityTone, mediaFileName, mergeBulkItems, severityOf, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useFilters, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useSort, useTableNav };
|
|
9638
|
+
export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, Accordion, AuthScreen, Avatar, AvatarGroup, Banner, BarChart, BehaviorPanel, BulkImportGrid, Button_default as Button, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Card, ChangePasswordForm, ChatTemplate, Checkbox_default as Checkbox, CheckoutTemplate, ColoredBadge, ContainerFillChart, Customization, DEV_BANNER_TEXT, DashboardTemplate, DataTablePage, Desktop, DesktopHostProvider, DevIndicator, DonutChart, ENTER, EmailTemplate, EmptyState, EntityList, ErrorPage, FilterBar, FormField, FormLayoutPage, GalleryTemplate, GlobalSearch, HelpCenter, INPUT_BASE, Input_default as Input, Kanban, Label, Layout, ListFooter, ListLoadError, LoadingSpinner2 as LoadingSpinner, MOD, Markdown, MediaUploadField, MediaUploadGrid, MetricBar, MilestoneTimeline, NativeSelect, NotificationBell, PageHeader, Pagination, PdfActionButton, Radio_default as Radio, ResizableTable, SHIFT, SearchableSelect, Select_default as Select, ServerStatusIndicator, ShellEntityFetcherProvider, ShortcutHelp, SidebarActionButton, SidebarGroupLabel, SidebarNavItem, SoundsPanel, Sparkline, StartMenu, StatCard, StatusBadge, StatusBadgeProvider, SystemPreferences, Tabs, Textarea_default as Textarea, Tooltip, TopNav, WidgetManager, applyDevTitle, createWindowRegistry, findDuplicateKeys, formatDate, inputClasses, isDevEnv, isMac, isSeverityTone, mediaFileName, mergeBulkItems, severityOf, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useFilters, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useSort, useTableNav };
|
|
9883
9639
|
//# sourceMappingURL=index.js.map
|
|
9884
9640
|
//# sourceMappingURL=index.js.map
|