react-os-shell 3.10.0 → 3.11.1
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-OMB2YWT7.js +7 -0
- package/dist/{Browser-KMNCDY7D.js.map → Browser-OMB2YWT7.js.map} +1 -1
- package/dist/{Calculator-2HX5CQHC.js → Calculator-K3KWPHJI.js} +4 -4
- package/dist/{Calculator-2HX5CQHC.js.map → Calculator-K3KWPHJI.js.map} +1 -1
- package/dist/{CurrencyConverter-CCYVPA2T.js → CurrencyConverter-ROLJLHT4.js} +4 -4
- package/dist/{CurrencyConverter-CCYVPA2T.js.map → CurrencyConverter-ROLJLHT4.js.map} +1 -1
- package/dist/{Documents-7GJ5YKN5.js → Documents-FNUDJADL.js} +4 -4
- package/dist/{Documents-7GJ5YKN5.js.map → Documents-FNUDJADL.js.map} +1 -1
- package/dist/Files-YVG267R2.js +12 -0
- package/dist/{Files-ERJ5LMYQ.js.map → Files-YVG267R2.js.map} +1 -1
- package/dist/{Notepad-FQM7GCF7.js → Notepad-ZOF2A7Q7.js} +4 -4
- package/dist/{Notepad-FQM7GCF7.js.map → Notepad-ZOF2A7Q7.js.map} +1 -1
- package/dist/{PomodoroTimer-CHR6G3HN.js → PomodoroTimer-IKLRQIU3.js} +5 -5
- package/dist/{PomodoroTimer-CHR6G3HN.js.map → PomodoroTimer-IKLRQIU3.js.map} +1 -1
- package/dist/Preview-PNMJG2WL.js +8 -0
- package/dist/{Preview-XJLBPDGQ.js.map → Preview-PNMJG2WL.js.map} +1 -1
- package/dist/Spreadsheet-BPJIYAXF.js +7 -0
- package/dist/{Spreadsheet-TFBKD377.js.map → Spreadsheet-BPJIYAXF.js.map} +1 -1
- package/dist/{Stock-ALK2CV7R.js → Stock-VGTJEM4B.js} +4 -4
- package/dist/{Stock-ALK2CV7R.js.map → Stock-VGTJEM4B.js.map} +1 -1
- package/dist/{Weather-CW5JMDKQ.js → Weather-JXDY47YQ.js} +4 -4
- package/dist/{Weather-CW5JMDKQ.js.map → Weather-JXDY47YQ.js.map} +1 -1
- package/dist/{WorldClock-7B4JZOQR.js → WorldClock-ACR63JED.js} +4 -4
- package/dist/{WorldClock-7B4JZOQR.js.map → WorldClock-ACR63JED.js.map} +1 -1
- package/dist/apps/index.js +19 -19
- package/dist/{chunk-HMCBPRIZ.js → chunk-5HBGCZKG.js} +4 -4
- package/dist/{chunk-HMCBPRIZ.js.map → chunk-5HBGCZKG.js.map} +1 -1
- package/dist/{chunk-7UJLZUWX.js → chunk-76SEPQRP.js} +5 -5
- package/dist/{chunk-7UJLZUWX.js.map → chunk-76SEPQRP.js.map} +1 -1
- package/dist/{chunk-HUQGQCC7.js → chunk-GOT6PRT2.js} +4 -4
- package/dist/{chunk-HUQGQCC7.js.map → chunk-GOT6PRT2.js.map} +1 -1
- package/dist/{chunk-JXW7H3DU.js → chunk-HLWEKEKD.js} +10 -3
- package/dist/chunk-HLWEKEKD.js.map +1 -0
- package/dist/{chunk-PM5G3GVW.js → chunk-MRFKIP3G.js} +3 -3
- package/dist/{chunk-PM5G3GVW.js.map → chunk-MRFKIP3G.js.map} +1 -1
- package/dist/{chunk-ZYKRG3BM.js → chunk-MSP7WNTK.js} +4 -4
- package/dist/{chunk-ZYKRG3BM.js.map → chunk-MSP7WNTK.js.map} +1 -1
- package/dist/{chunk-IIEI3RDA.js → chunk-PQYTYQ62.js} +4 -4
- package/dist/{chunk-IIEI3RDA.js.map → chunk-PQYTYQ62.js.map} +1 -1
- package/dist/{chunk-YLJY5LDU.js → chunk-VGJ3KCOP.js} +3 -3
- package/dist/{chunk-YLJY5LDU.js.map → chunk-VGJ3KCOP.js.map} +1 -1
- package/dist/{chunk-S6CH5S26.js → chunk-XORQ5BQL.js} +4 -4
- package/dist/{chunk-S6CH5S26.js.map → chunk-XORQ5BQL.js.map} +1 -1
- package/dist/index.d.ts +138 -2
- package/dist/index.js +460 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/Browser-KMNCDY7D.js +0 -7
- package/dist/Files-ERJ5LMYQ.js +0 -12
- package/dist/Preview-XJLBPDGQ.js +0 -8
- package/dist/Spreadsheet-TFBKD377.js +0 -7
- package/dist/chunk-JXW7H3DU.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { subscribePomo, getPomoSnapshot } from './chunk-
|
|
2
|
-
export { setShellTodoProvider } from './chunk-
|
|
3
|
-
import { PREVIEW_OPENED_EVENT, publishDesktopFolders, requestFilesTrashView, FolderGlyph, openPreviewFile, requestFilesDesktopFolderView, FileIconTile, hashGradient } from './chunk-
|
|
4
|
-
export { Breadcrumbs } from './chunk-
|
|
1
|
+
import { subscribePomo, getPomoSnapshot } from './chunk-VGJ3KCOP.js';
|
|
2
|
+
export { setShellTodoProvider } from './chunk-VGJ3KCOP.js';
|
|
3
|
+
import { PREVIEW_OPENED_EVENT, publishDesktopFolders, requestFilesTrashView, FolderGlyph, openPreviewFile, requestFilesDesktopFolderView, FileIconTile, hashGradient } from './chunk-XORQ5BQL.js';
|
|
4
|
+
export { Breadcrumbs } from './chunk-XORQ5BQL.js';
|
|
5
5
|
import { SidebarLayout } from './chunk-YG45DAUT.js';
|
|
6
6
|
export { SidebarLayout } from './chunk-YG45DAUT.js';
|
|
7
7
|
import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, setSoundForType, previewSound, setAllSounds, playLogout } from './chunk-D7PYW2QS.js';
|
|
8
|
-
import { setPdfPreview } from './chunk-
|
|
9
|
-
export { ImageAnnotator_default as ImageAnnotator } from './chunk-
|
|
8
|
+
import { setPdfPreview } from './chunk-PQYTYQ62.js';
|
|
9
|
+
export { ImageAnnotator_default as ImageAnnotator } from './chunk-PQYTYQ62.js';
|
|
10
10
|
import { toast_default } from './chunk-VENYVK3L.js';
|
|
11
11
|
export { toast_default as toast } from './chunk-VENYVK3L.js';
|
|
12
|
-
import { EditableGrid } from './chunk-
|
|
13
|
-
export { EditableGrid } from './chunk-
|
|
12
|
+
import { EditableGrid } from './chunk-GOT6PRT2.js';
|
|
13
|
+
export { EditableGrid } from './chunk-GOT6PRT2.js';
|
|
14
14
|
import { useAuth, useShellAuth } from './chunk-ADJ3CERD.js';
|
|
15
15
|
export { ShellAuthProvider, setShellAuthBridge, useShellAuth } from './chunk-ADJ3CERD.js';
|
|
16
|
-
import { APP_VERSION, VERSION } from './chunk-
|
|
17
|
-
export { VERSION } from './chunk-
|
|
18
|
-
import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, WINDOW_REGISTRY, isPageEntry, Modal, useShellPrefs, useIsMobile, ModalActions, useModalActive, client_default, LoadingSpinner, CancelButton, setWindowPosition, ThumbCard, activateModal } from './chunk-
|
|
19
|
-
export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ShellPrefsProvider, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, registerModalEscapeInterceptor, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useLocalStoragePrefs, useModalActive, useShellPrefs, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-
|
|
16
|
+
import { APP_VERSION, VERSION } from './chunk-5HBGCZKG.js';
|
|
17
|
+
export { VERSION } from './chunk-5HBGCZKG.js';
|
|
18
|
+
import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, WINDOW_REGISTRY, isPageEntry, Modal, useShellPrefs, useIsMobile, ModalActions, useModalActive, client_default, LoadingSpinner, CancelButton, setWindowPosition, ThumbCard, activateModal } from './chunk-HLWEKEKD.js';
|
|
19
|
+
export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ShellPrefsProvider, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, registerModalEscapeInterceptor, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useLocalStoragePrefs, useModalActive, useShellPrefs, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-HLWEKEKD.js';
|
|
20
20
|
export { ConfirmProvider, confirm, confirmDestructive, prompt } from './chunk-UBN4IUDE.js';
|
|
21
21
|
import { glassStyle, startMenuCategories, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons } from './chunk-ZF6AYO4G.js';
|
|
22
22
|
export { GLASS_DIVIDER, GLASS_INPUT_BG, glassStyle, setShellNavIcons } from './chunk-ZF6AYO4G.js';
|
|
23
|
-
import { createContext, lazy, forwardRef, useCallback, useState, useRef, useEffect, useMemo, useLayoutEffect, useContext, isValidElement, cloneElement, Suspense, Fragment as Fragment$1,
|
|
23
|
+
import { createContext, lazy, forwardRef, useCallback, useState, useRef, useEffect, useMemo, useLayoutEffect, useContext, isValidElement, cloneElement, Suspense, Fragment as Fragment$1, useId, Children, useSyncExternalStore } from 'react';
|
|
24
24
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
25
25
|
import { Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react';
|
|
26
26
|
import { createPortal } from 'react-dom';
|
|
@@ -6436,6 +6436,7 @@ var Radio_default = Radio;
|
|
|
6436
6436
|
function FormField({
|
|
6437
6437
|
label,
|
|
6438
6438
|
htmlFor,
|
|
6439
|
+
labelId,
|
|
6439
6440
|
hint,
|
|
6440
6441
|
error,
|
|
6441
6442
|
required,
|
|
@@ -6443,12 +6444,12 @@ function FormField({
|
|
|
6443
6444
|
children
|
|
6444
6445
|
}) {
|
|
6445
6446
|
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
6446
|
-
label && /* @__PURE__ */ jsxs("label", { htmlFor, className: "mb-1 block text-xs font-medium text-gray-600", children: [
|
|
6447
|
+
label && /* @__PURE__ */ jsxs("label", { id: labelId, htmlFor, className: "mb-1 block text-xs font-medium text-gray-600", children: [
|
|
6447
6448
|
label,
|
|
6448
6449
|
required && /* @__PURE__ */ jsx("span", { className: "ml-0.5 text-red-500", children: "*" })
|
|
6449
6450
|
] }),
|
|
6450
6451
|
children,
|
|
6451
|
-
error ? /* @__PURE__ */ jsx("p", { className: "mt-1 text-[11px] text-red-600", children: error }) : hint ? /* @__PURE__ */ jsx("p", { className: "mt-1 text-[11px] text-gray-400", children: hint }) : null
|
|
6452
|
+
error ? /* @__PURE__ */ jsx("p", { id: htmlFor ? `${htmlFor}-error` : void 0, className: "mt-1 text-[11px] text-red-600", children: error }) : hint ? /* @__PURE__ */ jsx("p", { id: htmlFor ? `${htmlFor}-hint` : void 0, className: "mt-1 text-[11px] text-gray-400", children: hint }) : null
|
|
6452
6453
|
] });
|
|
6453
6454
|
}
|
|
6454
6455
|
function Label({ required, children, className = "", ...rest }) {
|
|
@@ -6457,6 +6458,449 @@ function Label({ required, children, className = "", ...rest }) {
|
|
|
6457
6458
|
required && /* @__PURE__ */ jsx("span", { className: "ml-0.5 text-red-500", children: "*" })
|
|
6458
6459
|
] });
|
|
6459
6460
|
}
|
|
6461
|
+
function mediaFileName(url) {
|
|
6462
|
+
const path = (url || "").split("?")[0].split("#")[0];
|
|
6463
|
+
const last = path.substring(path.lastIndexOf("/") + 1);
|
|
6464
|
+
try {
|
|
6465
|
+
return decodeURIComponent(last.replace(/^[0-9a-f]{32}_/i, "")) || last || "media";
|
|
6466
|
+
} catch {
|
|
6467
|
+
return last || "media";
|
|
6468
|
+
}
|
|
6469
|
+
}
|
|
6470
|
+
var VIDEO_EXT_RE = /\.(mp4|webm|ogg|ogv|mov|m4v)(\?|#|$)/i;
|
|
6471
|
+
function isVideoUrl(url, accept = "") {
|
|
6472
|
+
if (!url) return false;
|
|
6473
|
+
const acceptsVideo = accept.includes("video");
|
|
6474
|
+
const acceptsImage = accept.includes("image") || accept === "*" || accept === "";
|
|
6475
|
+
return VIDEO_EXT_RE.test(url) || acceptsVideo && !acceptsImage;
|
|
6476
|
+
}
|
|
6477
|
+
function Spinner2({ className = "h-5 w-5" }) {
|
|
6478
|
+
return /* @__PURE__ */ jsxs("svg", { className: `${className} animate-spin text-gray-400`, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
|
|
6479
|
+
/* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
6480
|
+
/* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" })
|
|
6481
|
+
] });
|
|
6482
|
+
}
|
|
6483
|
+
function UploadGlyph({ className = "h-6 w-6" }) {
|
|
6484
|
+
return /* @__PURE__ */ jsxs(
|
|
6485
|
+
"svg",
|
|
6486
|
+
{
|
|
6487
|
+
viewBox: "0 0 24 24",
|
|
6488
|
+
fill: "none",
|
|
6489
|
+
stroke: "currentColor",
|
|
6490
|
+
strokeWidth: 1.6,
|
|
6491
|
+
strokeLinecap: "round",
|
|
6492
|
+
strokeLinejoin: "round",
|
|
6493
|
+
"aria-hidden": "true",
|
|
6494
|
+
className,
|
|
6495
|
+
children: [
|
|
6496
|
+
/* @__PURE__ */ jsx("path", { d: "M12 15V4" }),
|
|
6497
|
+
/* @__PURE__ */ jsx("path", { d: "M8 8l4-4 4 4" }),
|
|
6498
|
+
/* @__PURE__ */ jsx("path", { d: "M4 15v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3" })
|
|
6499
|
+
]
|
|
6500
|
+
}
|
|
6501
|
+
);
|
|
6502
|
+
}
|
|
6503
|
+
function MediaUploadField({
|
|
6504
|
+
value,
|
|
6505
|
+
onChange,
|
|
6506
|
+
onPick,
|
|
6507
|
+
label,
|
|
6508
|
+
hint,
|
|
6509
|
+
error,
|
|
6510
|
+
required,
|
|
6511
|
+
className,
|
|
6512
|
+
accept = "image/*",
|
|
6513
|
+
fit = "cover",
|
|
6514
|
+
height = 112,
|
|
6515
|
+
placeholder,
|
|
6516
|
+
cta = "Choose from library or upload",
|
|
6517
|
+
acceptHint,
|
|
6518
|
+
showFilename = true,
|
|
6519
|
+
allowReplace = true,
|
|
6520
|
+
allowRemove = true,
|
|
6521
|
+
replaceLabel = "Replace",
|
|
6522
|
+
removeLabel = "Remove",
|
|
6523
|
+
busy = false,
|
|
6524
|
+
busyLabel = "Uploading\u2026",
|
|
6525
|
+
disabled = false
|
|
6526
|
+
}) {
|
|
6527
|
+
const inputRef = useRef(null);
|
|
6528
|
+
const [dragOver, setDragOver] = useState(false);
|
|
6529
|
+
const [focused, setFocused] = useState(false);
|
|
6530
|
+
const fieldId = useId();
|
|
6531
|
+
const objectUrlRef = useRef(null);
|
|
6532
|
+
const [videoBlobUrl, setVideoBlobUrl] = useState(null);
|
|
6533
|
+
useEffect(() => () => {
|
|
6534
|
+
if (objectUrlRef.current) URL.revokeObjectURL(objectUrlRef.current);
|
|
6535
|
+
}, []);
|
|
6536
|
+
const locked = disabled || busy;
|
|
6537
|
+
const acceptsVideo = accept.includes("video");
|
|
6538
|
+
const acceptsImage = accept.includes("image") || accept === "*" || accept === "";
|
|
6539
|
+
const isVideo = !!value && (isVideoUrl(value, accept) || value === videoBlobUrl);
|
|
6540
|
+
const kindWord = acceptsVideo && !acceptsImage ? "video" : acceptsImage && !acceptsVideo ? "image" : "file";
|
|
6541
|
+
const dimLine = placeholder ?? `Upload ${kindWord === "image" ? "an image" : `a ${kindWord}`}`;
|
|
6542
|
+
const emitObjectUrl = (file) => {
|
|
6543
|
+
if (objectUrlRef.current) URL.revokeObjectURL(objectUrlRef.current);
|
|
6544
|
+
const url = URL.createObjectURL(file);
|
|
6545
|
+
objectUrlRef.current = url;
|
|
6546
|
+
setVideoBlobUrl(file.type.startsWith("video/") ? url : null);
|
|
6547
|
+
onChange(url);
|
|
6548
|
+
};
|
|
6549
|
+
const clearValue = () => {
|
|
6550
|
+
if (objectUrlRef.current) {
|
|
6551
|
+
URL.revokeObjectURL(objectUrlRef.current);
|
|
6552
|
+
objectUrlRef.current = null;
|
|
6553
|
+
}
|
|
6554
|
+
setVideoBlobUrl(null);
|
|
6555
|
+
onChange("");
|
|
6556
|
+
};
|
|
6557
|
+
const pick = (file) => {
|
|
6558
|
+
if (locked) return;
|
|
6559
|
+
if (onPick) {
|
|
6560
|
+
onPick(file ?? void 0);
|
|
6561
|
+
return;
|
|
6562
|
+
}
|
|
6563
|
+
if (file) {
|
|
6564
|
+
emitObjectUrl(file);
|
|
6565
|
+
return;
|
|
6566
|
+
}
|
|
6567
|
+
inputRef.current?.click();
|
|
6568
|
+
};
|
|
6569
|
+
const onNativeFile = (e) => {
|
|
6570
|
+
const file = e.target.files?.[0];
|
|
6571
|
+
if (file) emitObjectUrl(file);
|
|
6572
|
+
if (inputRef.current) inputRef.current.value = "";
|
|
6573
|
+
};
|
|
6574
|
+
const dropHandlers = locked ? {} : {
|
|
6575
|
+
onDragOver: (e) => {
|
|
6576
|
+
e.preventDefault();
|
|
6577
|
+
setDragOver(true);
|
|
6578
|
+
},
|
|
6579
|
+
onDragLeave: () => setDragOver(false),
|
|
6580
|
+
onDrop: (e) => {
|
|
6581
|
+
e.preventDefault();
|
|
6582
|
+
setDragOver(false);
|
|
6583
|
+
const file = e.dataTransfer.files?.[0];
|
|
6584
|
+
if (file) pick(file);
|
|
6585
|
+
}
|
|
6586
|
+
};
|
|
6587
|
+
const previewName = value ? mediaFileName(value) : "";
|
|
6588
|
+
const filled = /* @__PURE__ */ jsxs("div", { children: [
|
|
6589
|
+
/* @__PURE__ */ jsxs(
|
|
6590
|
+
"div",
|
|
6591
|
+
{
|
|
6592
|
+
...dropHandlers,
|
|
6593
|
+
className: [
|
|
6594
|
+
"relative overflow-hidden rounded-md border bg-gray-100 transition-colors",
|
|
6595
|
+
dragOver ? "border-blue-500" : "border-gray-200"
|
|
6596
|
+
].join(" "),
|
|
6597
|
+
style: { height },
|
|
6598
|
+
children: [
|
|
6599
|
+
isVideo ? /* @__PURE__ */ jsx(
|
|
6600
|
+
"video",
|
|
6601
|
+
{
|
|
6602
|
+
src: value ?? void 0,
|
|
6603
|
+
muted: true,
|
|
6604
|
+
playsInline: true,
|
|
6605
|
+
preload: "metadata",
|
|
6606
|
+
"aria-label": previewName || void 0,
|
|
6607
|
+
className: "h-full w-full",
|
|
6608
|
+
style: { objectFit: fit }
|
|
6609
|
+
}
|
|
6610
|
+
) : /* @__PURE__ */ jsx("img", { src: value ?? void 0, alt: previewName, className: "h-full w-full", style: { objectFit: fit } }),
|
|
6611
|
+
showFilename && value && /* @__PURE__ */ jsx(
|
|
6612
|
+
"span",
|
|
6613
|
+
{
|
|
6614
|
+
className: "absolute inset-x-1 bottom-1 truncate rounded px-1.5 py-0.5 text-xs text-white",
|
|
6615
|
+
style: { background: "rgba(0,0,0,0.6)" },
|
|
6616
|
+
children: previewName
|
|
6617
|
+
}
|
|
6618
|
+
),
|
|
6619
|
+
busy && /* @__PURE__ */ jsxs(
|
|
6620
|
+
"div",
|
|
6621
|
+
{
|
|
6622
|
+
role: "status",
|
|
6623
|
+
className: "absolute inset-0 flex items-center justify-center gap-2",
|
|
6624
|
+
style: { background: "rgba(255,255,255,0.6)" },
|
|
6625
|
+
children: [
|
|
6626
|
+
/* @__PURE__ */ jsx(Spinner2, {}),
|
|
6627
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-600", children: busyLabel })
|
|
6628
|
+
]
|
|
6629
|
+
}
|
|
6630
|
+
)
|
|
6631
|
+
]
|
|
6632
|
+
}
|
|
6633
|
+
),
|
|
6634
|
+
!disabled && (allowReplace || allowRemove) && /* @__PURE__ */ jsxs("div", { className: "mt-2 flex gap-2", children: [
|
|
6635
|
+
allowReplace && /* @__PURE__ */ jsx(Button_default, { id: fieldId, variant: "secondary", size: "sm", onClick: () => pick(), disabled: busy, children: replaceLabel }),
|
|
6636
|
+
allowRemove && /* @__PURE__ */ jsx(Button_default, { variant: "ghost", size: "sm", onClick: clearValue, disabled: busy, children: removeLabel })
|
|
6637
|
+
] })
|
|
6638
|
+
] });
|
|
6639
|
+
const empty = /* @__PURE__ */ jsx(
|
|
6640
|
+
"button",
|
|
6641
|
+
{
|
|
6642
|
+
type: "button",
|
|
6643
|
+
id: fieldId,
|
|
6644
|
+
onClick: () => pick(),
|
|
6645
|
+
disabled: locked,
|
|
6646
|
+
"aria-label": typeof dimLine === "string" ? dimLine : "Upload media",
|
|
6647
|
+
"aria-busy": busy || void 0,
|
|
6648
|
+
"aria-invalid": error ? true : void 0,
|
|
6649
|
+
"aria-required": required || void 0,
|
|
6650
|
+
"aria-describedby": error ? `${fieldId}-error` : hint ? `${fieldId}-hint` : void 0,
|
|
6651
|
+
onFocus: () => setFocused(true),
|
|
6652
|
+
onBlur: () => setFocused(false),
|
|
6653
|
+
...dropHandlers,
|
|
6654
|
+
className: [
|
|
6655
|
+
"flex w-full flex-col items-center justify-center gap-1.5 rounded-lg border-2 border-dashed text-center transition-colors",
|
|
6656
|
+
locked ? "cursor-not-allowed opacity-60" : "cursor-pointer",
|
|
6657
|
+
dragOver ? "border-blue-500 bg-blue-50" : "border-gray-300 bg-gray-50 hover:bg-gray-100"
|
|
6658
|
+
].join(" "),
|
|
6659
|
+
style: {
|
|
6660
|
+
minHeight: height,
|
|
6661
|
+
outline: "none",
|
|
6662
|
+
boxShadow: focused && !locked ? "0 0 0 2px rgba(59,130,246,0.45)" : void 0
|
|
6663
|
+
},
|
|
6664
|
+
children: busy ? /* @__PURE__ */ jsxs("span", { role: "status", className: "flex flex-col items-center gap-1.5", children: [
|
|
6665
|
+
/* @__PURE__ */ jsx(Spinner2, {}),
|
|
6666
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-500", children: busyLabel })
|
|
6667
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6668
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-400", children: /* @__PURE__ */ jsx(UploadGlyph, {}) }),
|
|
6669
|
+
/* @__PURE__ */ jsx("span", { className: "px-3 text-xs text-gray-500", children: dimLine }),
|
|
6670
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-blue-600", children: cta }),
|
|
6671
|
+
acceptHint && /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400", children: acceptHint })
|
|
6672
|
+
] })
|
|
6673
|
+
}
|
|
6674
|
+
);
|
|
6675
|
+
return /* @__PURE__ */ jsxs(FormField, { label, htmlFor: fieldId, hint, error, required, className, children: [
|
|
6676
|
+
value ? filled : empty,
|
|
6677
|
+
!onPick && /* @__PURE__ */ jsx("input", { ref: inputRef, type: "file", accept, className: "hidden", onChange: onNativeFile })
|
|
6678
|
+
] });
|
|
6679
|
+
}
|
|
6680
|
+
var REMOVE_ICON = /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", "aria-hidden": "true", className: "h-3 w-3", children: /* @__PURE__ */ jsx("path", { d: "M6 6l12 12M18 6L6 18" }) });
|
|
6681
|
+
function MediaUploadGrid({
|
|
6682
|
+
items,
|
|
6683
|
+
onPick,
|
|
6684
|
+
onRemove,
|
|
6685
|
+
onReorder,
|
|
6686
|
+
label,
|
|
6687
|
+
hint,
|
|
6688
|
+
error,
|
|
6689
|
+
required,
|
|
6690
|
+
className,
|
|
6691
|
+
accept = "image/*",
|
|
6692
|
+
fit = "cover",
|
|
6693
|
+
thumbSize = 96,
|
|
6694
|
+
placeholder,
|
|
6695
|
+
cta = "Choose from library or upload",
|
|
6696
|
+
acceptHint,
|
|
6697
|
+
showCover = false,
|
|
6698
|
+
coverLabel = "Cover",
|
|
6699
|
+
busy = false,
|
|
6700
|
+
busyLabel = "Uploading\u2026",
|
|
6701
|
+
disabled = false,
|
|
6702
|
+
readOnly = false
|
|
6703
|
+
}) {
|
|
6704
|
+
const gridId = useId();
|
|
6705
|
+
const [zoneDragOver, setZoneDragOver] = useState(false);
|
|
6706
|
+
const [draggingIndex, setDraggingIndex] = useState(null);
|
|
6707
|
+
const [focusedKey, setFocusedKey] = useState(null);
|
|
6708
|
+
const ringStyle = (key) => ({
|
|
6709
|
+
outline: "none",
|
|
6710
|
+
...focusedKey === key && !locked ? { boxShadow: "0 0 0 2px rgba(59,130,246,0.45)" } : {}
|
|
6711
|
+
});
|
|
6712
|
+
const blurKey = (key) => setFocusedKey((k) => k === key ? null : k);
|
|
6713
|
+
const locked = disabled || busy;
|
|
6714
|
+
const canAdd = !!onPick && !locked && !readOnly;
|
|
6715
|
+
const canRemove = !!onRemove && !locked && !readOnly;
|
|
6716
|
+
const reorderEnabled = !!onReorder && !locked && !readOnly;
|
|
6717
|
+
const acceptsVideo = accept.includes("video");
|
|
6718
|
+
const acceptsImage = accept.includes("image") || accept === "*" || accept === "";
|
|
6719
|
+
const kindWord = acceptsVideo && !acceptsImage ? "video" : acceptsImage && !acceptsVideo ? "image" : "file";
|
|
6720
|
+
const dimLine = placeholder ?? `Upload ${kindWord === "image" ? "an image" : `a ${kindWord}`}`;
|
|
6721
|
+
const pick = (file) => {
|
|
6722
|
+
if (!canAdd) return;
|
|
6723
|
+
onPick(file ?? void 0);
|
|
6724
|
+
};
|
|
6725
|
+
const isFileDrag = (e) => Array.from(e.dataTransfer.types || []).includes("Files");
|
|
6726
|
+
const zoneHandlers = canAdd ? {
|
|
6727
|
+
onDragOver: (e) => {
|
|
6728
|
+
if (!isFileDrag(e)) return;
|
|
6729
|
+
e.preventDefault();
|
|
6730
|
+
setZoneDragOver(true);
|
|
6731
|
+
},
|
|
6732
|
+
onDragLeave: () => setZoneDragOver(false),
|
|
6733
|
+
onDrop: (e) => {
|
|
6734
|
+
const file = e.dataTransfer.files?.[0];
|
|
6735
|
+
if (!file) return;
|
|
6736
|
+
e.preventDefault();
|
|
6737
|
+
setZoneDragOver(false);
|
|
6738
|
+
pick(file);
|
|
6739
|
+
}
|
|
6740
|
+
} : {};
|
|
6741
|
+
const square = { width: thumbSize, height: thumbSize };
|
|
6742
|
+
const thumb = (item, index) => {
|
|
6743
|
+
const video = item.kind ? item.kind === "video" : isVideoUrl(item.url, accept);
|
|
6744
|
+
const name = mediaFileName(item.url);
|
|
6745
|
+
const isCover = showCover && (item.cover ?? index === 0);
|
|
6746
|
+
return /* @__PURE__ */ jsxs(
|
|
6747
|
+
"div",
|
|
6748
|
+
{
|
|
6749
|
+
draggable: reorderEnabled || void 0,
|
|
6750
|
+
onDragStart: reorderEnabled ? (e) => {
|
|
6751
|
+
e.dataTransfer.effectAllowed = "move";
|
|
6752
|
+
e.dataTransfer.setData("text/plain", String(index));
|
|
6753
|
+
setDraggingIndex(index);
|
|
6754
|
+
} : void 0,
|
|
6755
|
+
onDragEnd: reorderEnabled ? () => setDraggingIndex(null) : void 0,
|
|
6756
|
+
onDragOver: reorderEnabled ? (e) => {
|
|
6757
|
+
if (draggingIndex == null) return;
|
|
6758
|
+
e.preventDefault();
|
|
6759
|
+
e.stopPropagation();
|
|
6760
|
+
} : void 0,
|
|
6761
|
+
onDrop: reorderEnabled ? (e) => {
|
|
6762
|
+
if (draggingIndex == null) return;
|
|
6763
|
+
e.preventDefault();
|
|
6764
|
+
e.stopPropagation();
|
|
6765
|
+
if (draggingIndex !== index) onReorder(draggingIndex, index);
|
|
6766
|
+
setDraggingIndex(null);
|
|
6767
|
+
} : void 0,
|
|
6768
|
+
tabIndex: reorderEnabled ? 0 : void 0,
|
|
6769
|
+
"aria-label": reorderEnabled ? `${name}, item ${index + 1} of ${items.length}. Use arrow keys to reorder.` : void 0,
|
|
6770
|
+
onKeyDown: reorderEnabled ? (e) => {
|
|
6771
|
+
if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
|
|
6772
|
+
if (index > 0) {
|
|
6773
|
+
e.preventDefault();
|
|
6774
|
+
onReorder(index, index - 1);
|
|
6775
|
+
}
|
|
6776
|
+
} else if (e.key === "ArrowRight" || e.key === "ArrowDown") {
|
|
6777
|
+
if (index < items.length - 1) {
|
|
6778
|
+
e.preventDefault();
|
|
6779
|
+
onReorder(index, index + 1);
|
|
6780
|
+
}
|
|
6781
|
+
}
|
|
6782
|
+
} : void 0,
|
|
6783
|
+
onFocus: reorderEnabled ? (e) => {
|
|
6784
|
+
if (e.target === e.currentTarget) setFocusedKey(`thumb:${item.id}`);
|
|
6785
|
+
} : void 0,
|
|
6786
|
+
onBlur: reorderEnabled ? (e) => {
|
|
6787
|
+
if (e.target === e.currentTarget) blurKey(`thumb:${item.id}`);
|
|
6788
|
+
} : void 0,
|
|
6789
|
+
className: [
|
|
6790
|
+
"relative shrink-0 overflow-hidden rounded-md border border-gray-200 bg-gray-100",
|
|
6791
|
+
draggingIndex === index ? "opacity-50" : ""
|
|
6792
|
+
].join(" "),
|
|
6793
|
+
style: { ...square, cursor: reorderEnabled ? "move" : void 0, ...ringStyle(`thumb:${item.id}`) },
|
|
6794
|
+
children: [
|
|
6795
|
+
video ? /* @__PURE__ */ jsx("video", { src: item.url, muted: true, playsInline: true, preload: "metadata", "aria-label": name, className: "h-full w-full", style: { objectFit: fit } }) : /* @__PURE__ */ jsx("img", { src: item.url, alt: name, className: "h-full w-full", style: { objectFit: fit } }),
|
|
6796
|
+
isCover && /* @__PURE__ */ jsx("span", { className: "absolute left-1 top-1 rounded bg-blue-600 px-1.5 py-0.5 text-xs font-medium text-white", children: coverLabel }),
|
|
6797
|
+
item.caption != null && /* @__PURE__ */ jsx(
|
|
6798
|
+
"span",
|
|
6799
|
+
{
|
|
6800
|
+
className: "absolute inset-x-1 bottom-1 truncate rounded px-1.5 py-0.5 text-xs text-white",
|
|
6801
|
+
style: { background: "rgba(0,0,0,0.6)" },
|
|
6802
|
+
children: item.caption
|
|
6803
|
+
}
|
|
6804
|
+
),
|
|
6805
|
+
canRemove && /* @__PURE__ */ jsx(
|
|
6806
|
+
"button",
|
|
6807
|
+
{
|
|
6808
|
+
type: "button",
|
|
6809
|
+
onClick: () => onRemove(item.id),
|
|
6810
|
+
"aria-label": `Remove ${name}`,
|
|
6811
|
+
onFocus: () => setFocusedKey(`rm:${item.id}`),
|
|
6812
|
+
onBlur: () => blurKey(`rm:${item.id}`),
|
|
6813
|
+
className: "absolute right-1 top-1 flex h-5 w-5 items-center justify-center rounded-full text-white",
|
|
6814
|
+
style: { background: "rgba(0,0,0,0.55)", ...ringStyle(`rm:${item.id}`) },
|
|
6815
|
+
children: REMOVE_ICON
|
|
6816
|
+
}
|
|
6817
|
+
)
|
|
6818
|
+
]
|
|
6819
|
+
},
|
|
6820
|
+
item.id
|
|
6821
|
+
);
|
|
6822
|
+
};
|
|
6823
|
+
const addTile = canAdd && /* @__PURE__ */ jsxs(
|
|
6824
|
+
"button",
|
|
6825
|
+
{
|
|
6826
|
+
type: "button",
|
|
6827
|
+
onClick: () => pick(),
|
|
6828
|
+
"aria-label": "Add media",
|
|
6829
|
+
onFocus: () => setFocusedKey("add"),
|
|
6830
|
+
onBlur: () => blurKey("add"),
|
|
6831
|
+
className: "flex shrink-0 flex-col items-center justify-center gap-1 rounded-md border-2 border-dashed border-gray-300 bg-gray-50 text-gray-400 transition-colors hover:bg-gray-100 hover:text-gray-500",
|
|
6832
|
+
style: { ...square, ...ringStyle("add") },
|
|
6833
|
+
children: [
|
|
6834
|
+
/* @__PURE__ */ jsx(UploadGlyph, { className: "h-5 w-5" }),
|
|
6835
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-500", children: "Add" })
|
|
6836
|
+
]
|
|
6837
|
+
}
|
|
6838
|
+
);
|
|
6839
|
+
const emptyDropzone = canAdd ? /* @__PURE__ */ jsxs(
|
|
6840
|
+
"button",
|
|
6841
|
+
{
|
|
6842
|
+
type: "button",
|
|
6843
|
+
onClick: () => pick(),
|
|
6844
|
+
"aria-label": typeof dimLine === "string" ? dimLine : "Upload media",
|
|
6845
|
+
onFocus: () => setFocusedKey("zone"),
|
|
6846
|
+
onBlur: () => blurKey("zone"),
|
|
6847
|
+
className: [
|
|
6848
|
+
"flex w-full flex-col items-center justify-center gap-1.5 rounded-lg border-2 border-dashed text-center transition-colors cursor-pointer",
|
|
6849
|
+
zoneDragOver ? "border-blue-500 bg-blue-50" : "border-gray-300 bg-gray-50 hover:bg-gray-100"
|
|
6850
|
+
].join(" "),
|
|
6851
|
+
style: { minHeight: thumbSize + 32, ...ringStyle("zone") },
|
|
6852
|
+
children: [
|
|
6853
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-400", children: /* @__PURE__ */ jsx(UploadGlyph, {}) }),
|
|
6854
|
+
/* @__PURE__ */ jsx("span", { className: "px-3 text-xs text-gray-500", children: dimLine }),
|
|
6855
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-blue-600", children: cta }),
|
|
6856
|
+
acceptHint && /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400", children: acceptHint })
|
|
6857
|
+
]
|
|
6858
|
+
}
|
|
6859
|
+
) : /* @__PURE__ */ jsx(
|
|
6860
|
+
"div",
|
|
6861
|
+
{
|
|
6862
|
+
className: "flex w-full items-center justify-center rounded-lg border border-gray-200 bg-gray-50 px-3 text-xs text-gray-400",
|
|
6863
|
+
style: { minHeight: thumbSize + 32 },
|
|
6864
|
+
children: "No media."
|
|
6865
|
+
}
|
|
6866
|
+
);
|
|
6867
|
+
return /* @__PURE__ */ jsx(FormField, { label, labelId: label ? `${gridId}-label` : void 0, htmlFor: gridId, hint, error, required, className, children: /* @__PURE__ */ jsxs(
|
|
6868
|
+
"div",
|
|
6869
|
+
{
|
|
6870
|
+
id: gridId,
|
|
6871
|
+
role: "group",
|
|
6872
|
+
"aria-labelledby": label ? `${gridId}-label` : void 0,
|
|
6873
|
+
"aria-describedby": error ? `${gridId}-error` : hint ? `${gridId}-hint` : void 0,
|
|
6874
|
+
"aria-busy": busy || void 0,
|
|
6875
|
+
...zoneHandlers,
|
|
6876
|
+
className: "relative rounded-lg transition-colors",
|
|
6877
|
+
style: {
|
|
6878
|
+
...locked ? { opacity: 0.6 } : {},
|
|
6879
|
+
// Inline box-shadow, not `ring-*` — the kit's shipped stylesheet has no
|
|
6880
|
+
// Tailwind ring machinery (see MediaUploadField's focus ring).
|
|
6881
|
+
...zoneDragOver ? { boxShadow: "0 0 0 2px rgba(59,130,246,0.5)" } : {}
|
|
6882
|
+
},
|
|
6883
|
+
children: [
|
|
6884
|
+
items.length === 0 ? emptyDropzone : /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
6885
|
+
items.map(thumb),
|
|
6886
|
+
addTile
|
|
6887
|
+
] }),
|
|
6888
|
+
busy && /* @__PURE__ */ jsxs(
|
|
6889
|
+
"div",
|
|
6890
|
+
{
|
|
6891
|
+
role: "status",
|
|
6892
|
+
className: "absolute inset-0 flex items-center justify-center gap-2 rounded-lg",
|
|
6893
|
+
style: { background: "rgba(255,255,255,0.6)" },
|
|
6894
|
+
children: [
|
|
6895
|
+
/* @__PURE__ */ jsx(Spinner2, {}),
|
|
6896
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-600", children: busyLabel })
|
|
6897
|
+
]
|
|
6898
|
+
}
|
|
6899
|
+
)
|
|
6900
|
+
]
|
|
6901
|
+
}
|
|
6902
|
+
) });
|
|
6903
|
+
}
|
|
6460
6904
|
function Card({ children, header, footer, padded = true, className = "" }) {
|
|
6461
6905
|
return /* @__PURE__ */ jsxs("div", { className: `rounded-lg border border-gray-200 bg-white shadow-sm ${className}`.trim(), children: [
|
|
6462
6906
|
header && /* @__PURE__ */ jsx("div", { className: "border-b border-gray-100 px-4 py-3 text-sm font-semibold text-gray-900", children: header }),
|
|
@@ -8968,6 +9412,6 @@ function useEditHotkey(callback) {
|
|
|
8968
9412
|
}, [callback, isActive]);
|
|
8969
9413
|
}
|
|
8970
9414
|
|
|
8971
|
-
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, 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, mergeBulkItems, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useFilters, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useSort, useTableNav };
|
|
9415
|
+
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, 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, mediaFileName, mergeBulkItems, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useFilters, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useSort, useTableNav };
|
|
8972
9416
|
//# sourceMappingURL=index.js.map
|
|
8973
9417
|
//# sourceMappingURL=index.js.map
|