react-os-shell 0.2.64 → 0.2.67
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-OL4SV34L.js → Browser-OH3E6TIZ.js} +3 -3
- package/dist/{Browser-OL4SV34L.js.map → Browser-OH3E6TIZ.js.map} +1 -1
- package/dist/{Calculator-VALSEOQD.js → Calculator-DBSWD2RM.js} +4 -4
- package/dist/{Calculator-VALSEOQD.js.map → Calculator-DBSWD2RM.js.map} +1 -1
- package/dist/{Calendar-I4OLRGNW.js → Calendar-5S3MOTVB.js} +3 -3
- package/dist/{Calendar-I4OLRGNW.js.map → Calendar-5S3MOTVB.js.map} +1 -1
- package/dist/{CurrencyConverter-3DLJRL24.js → CurrencyConverter-TDAW7VME.js} +4 -4
- package/dist/{CurrencyConverter-3DLJRL24.js.map → CurrencyConverter-TDAW7VME.js.map} +1 -1
- package/dist/{Documents-JLIRD3ML.js → Documents-R4DZLBJU.js} +3 -3
- package/dist/{Documents-JLIRD3ML.js.map → Documents-R4DZLBJU.js.map} +1 -1
- package/dist/{Email-PN2CNRLE.js → Email-OAQ76CET.js} +3 -3
- package/dist/{Email-PN2CNRLE.js.map → Email-OAQ76CET.js.map} +1 -1
- package/dist/Files-XD7SWQSG.js +12 -0
- package/dist/{Files-VQCZUKNU.js.map → Files-XD7SWQSG.js.map} +1 -1
- package/dist/{Minesweeper-IGIPALMP.js → Minesweeper-YWYMJQN6.js} +3 -3
- package/dist/{Minesweeper-IGIPALMP.js.map → Minesweeper-YWYMJQN6.js.map} +1 -1
- package/dist/{Notepad-Q5SSDZNW.js → Notepad-F3BJYZJL.js} +3 -3
- package/dist/{Notepad-Q5SSDZNW.js.map → Notepad-F3BJYZJL.js.map} +1 -1
- package/dist/{PomodoroTimer-PD2HIZMT.js → PomodoroTimer-VLPDNV7W.js} +4 -4
- package/dist/{PomodoroTimer-PD2HIZMT.js.map → PomodoroTimer-VLPDNV7W.js.map} +1 -1
- package/dist/Preview-XOCYZM4T.js +8 -0
- package/dist/{Preview-WFIQOE3T.js.map → Preview-XOCYZM4T.js.map} +1 -1
- package/dist/{Spreadsheet-Y5LACQRY.js → Spreadsheet-7NEC5RBR.js} +4 -4
- package/dist/{Spreadsheet-Y5LACQRY.js.map → Spreadsheet-7NEC5RBR.js.map} +1 -1
- package/dist/{Weather-GEA3GBQQ.js → Weather-HLXHNBM4.js} +4 -4
- package/dist/{Weather-GEA3GBQQ.js.map → Weather-HLXHNBM4.js.map} +1 -1
- package/dist/{WorldClock-W2ENBGFS.js → WorldClock-HIWKHF6U.js} +4 -4
- package/dist/{WorldClock-W2ENBGFS.js.map → WorldClock-HIWKHF6U.js.map} +1 -1
- package/dist/apps/index.js +19 -19
- package/dist/{chunk-MY5PL6MK.js → chunk-62EP7CNW.js} +3 -3
- package/dist/{chunk-MY5PL6MK.js.map → chunk-62EP7CNW.js.map} +1 -1
- package/dist/{chunk-2RIRISNW.js → chunk-EXYMMWOS.js} +4 -4
- package/dist/{chunk-2RIRISNW.js.map → chunk-EXYMMWOS.js.map} +1 -1
- package/dist/{chunk-4CFEJ4CC.js → chunk-GAC6D4LN.js} +16 -16
- package/dist/chunk-GAC6D4LN.js.map +1 -0
- package/dist/{chunk-BUJKR34D.js → chunk-HAUVCQNK.js} +3 -3
- package/dist/{chunk-BUJKR34D.js.map → chunk-HAUVCQNK.js.map} +1 -1
- package/dist/{chunk-VDNTGVGH.js → chunk-KFRHMW57.js} +3 -3
- package/dist/{chunk-VDNTGVGH.js.map → chunk-KFRHMW57.js.map} +1 -1
- package/dist/{chunk-JDRZX27J.js → chunk-VG5ZM3QD.js} +4 -4
- package/dist/{chunk-JDRZX27J.js.map → chunk-VG5ZM3QD.js.map} +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +207 -119
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/Files-VQCZUKNU.js +0 -12
- package/dist/Preview-WFIQOE3T.js +0 -8
- package/dist/chunk-4CFEJ4CC.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -5,16 +5,16 @@ import { subscribePomo, getPomoSnapshot } from './chunk-MK3HLUO4.js';
|
|
|
5
5
|
import { useGoogleAuth } from './chunk-MVWEL34Y.js';
|
|
6
6
|
import { useShellPrefs } from './chunk-36VM54SC.js';
|
|
7
7
|
export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
|
|
8
|
-
import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-
|
|
8
|
+
import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-EXYMMWOS.js';
|
|
9
9
|
import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, playLogout, setSoundForType, previewSound, setAllSounds } from './chunk-D7PYW2QS.js';
|
|
10
|
-
import { setPdfPreview } from './chunk-
|
|
10
|
+
import { setPdfPreview } from './chunk-HAUVCQNK.js';
|
|
11
11
|
import './chunk-KUIPWCTJ.js';
|
|
12
12
|
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
13
13
|
export { toast_default as toast } from './chunk-WIJ45SYD.js';
|
|
14
|
-
import './chunk-
|
|
14
|
+
import './chunk-62EP7CNW.js';
|
|
15
15
|
export { EditableGrid } from './chunk-GP4Y3VCB.js';
|
|
16
|
-
import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, useIsMobile, ModalActions, useModalActive, WINDOW_REGISTRY, isPageEntry, LoadingSpinner, ThumbCard, activateModal } from './chunk-
|
|
17
|
-
export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, subscribeExposeHighlight, toggleExposeMode, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-
|
|
16
|
+
import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, useIsMobile, ModalActions, useModalActive, WINDOW_REGISTRY, isPageEntry, LoadingSpinner, ThumbCard, activateModal } from './chunk-GAC6D4LN.js';
|
|
17
|
+
export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, subscribeExposeHighlight, toggleExposeMode, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-GAC6D4LN.js';
|
|
18
18
|
import { confirm } from './chunk-PLGHQ7QW.js';
|
|
19
19
|
export { ConfirmProvider, confirm, confirmDestructive, prompt } from './chunk-PLGHQ7QW.js';
|
|
20
20
|
import { useAuth } from './chunk-ADJ3CERD.js';
|
|
@@ -915,7 +915,7 @@ function StatusBadge({ status }) {
|
|
|
915
915
|
}
|
|
916
916
|
|
|
917
917
|
// src/version.ts
|
|
918
|
-
var VERSION = "0.2.
|
|
918
|
+
var VERSION = "0.2.67" ;
|
|
919
919
|
var APP_VERSION = VERSION;
|
|
920
920
|
|
|
921
921
|
// src/changelog.ts
|
|
@@ -1028,6 +1028,29 @@ var PREVIEW_FILE_COLORS = {
|
|
|
1028
1028
|
};
|
|
1029
1029
|
var DOCUMENTS_FOLDER_ID = "documents";
|
|
1030
1030
|
var DOCUMENTS_FOLDER_NAME = "Documents";
|
|
1031
|
+
function FileIconTile({ entityType, isSelected, entityId, label, fileKind }) {
|
|
1032
|
+
const isPreviewFile = entityType === "preview-file" && fileKind;
|
|
1033
|
+
const previewColor2 = isPreviewFile ? PREVIEW_FILE_COLORS[fileKind] : null;
|
|
1034
|
+
const previewCode = isPreviewFile ? PREVIEW_FILE_CODES[fileKind] : null;
|
|
1035
|
+
if (entityType === "folder") {
|
|
1036
|
+
return /* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: /* @__PURE__ */ jsxs("svg", { className: "h-12 w-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)]", viewBox: "0 0 48 48", children: [
|
|
1037
|
+
/* @__PURE__ */ jsx("path", { d: "M6 12a4 4 0 014-4h10l4 4h14a4 4 0 014 4v20a4 4 0 01-4 4H10a4 4 0 01-4-4V12z", fill: "white", stroke: "#eab308", strokeWidth: "2", strokeLinejoin: "round" }),
|
|
1038
|
+
/* @__PURE__ */ jsx("path", { d: "M6 18h36", stroke: "#eab308", strokeWidth: "1.5" })
|
|
1039
|
+
] }) });
|
|
1040
|
+
}
|
|
1041
|
+
if (entityType === "page") {
|
|
1042
|
+
const icon = label && navIcons[label] || (entityId ? navIcons[entityId] : void 0);
|
|
1043
|
+
return /* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: icon && isValidElement(icon) ? cloneElement(icon, { className: "h-10 w-10 text-white drop-shadow-[0_2px_3px_rgba(0,0,0,0.4)]" }) : /* @__PURE__ */ jsx("svg", { className: "h-10 w-10 text-white drop-shadow-[0_2px_3px_rgba(0,0,0,0.4)]", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6z" }) }) });
|
|
1044
|
+
}
|
|
1045
|
+
return /* @__PURE__ */ jsxs("div", { className: `w-12 h-12 relative flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: [
|
|
1046
|
+
/* @__PURE__ */ jsxs("svg", { className: `w-10 h-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)] ${previewColor2 ?? ENTITY_ICON_COLORS[entityType] ?? "text-gray-500"}`, viewBox: "0 0 40 48", fill: "none", children: [
|
|
1047
|
+
/* @__PURE__ */ jsx("path", { d: "M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z", fill: "white", fillOpacity: "0.92" }),
|
|
1048
|
+
/* @__PURE__ */ jsx("path", { d: "M26 0l10 10H30a4 4 0 01-4-4V0z", fill: "currentColor", fillOpacity: "0.2" }),
|
|
1049
|
+
/* @__PURE__ */ jsx("path", { d: "M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z", stroke: "currentColor", strokeWidth: "1.5", strokeOpacity: "0.5" })
|
|
1050
|
+
] }),
|
|
1051
|
+
/* @__PURE__ */ jsx("span", { className: `absolute inset-0 flex items-center justify-center text-[9px] font-bold pt-2 ${previewColor2 ?? ENTITY_ICON_COLORS[entityType] ?? "text-gray-600"}`, children: previewCode ?? ENTITY_ICONS[entityType] ?? entityType.slice(0, 3).toUpperCase() })
|
|
1052
|
+
] });
|
|
1053
|
+
}
|
|
1031
1054
|
var GRID = 90;
|
|
1032
1055
|
function snapToGrid(x, y) {
|
|
1033
1056
|
return { x: Math.round(x / GRID) * GRID, y: Math.round(y / GRID) * GRID };
|
|
@@ -1039,13 +1062,35 @@ function DesktopHostProvider({ value, children }) {
|
|
|
1039
1062
|
function useDesktopHost() {
|
|
1040
1063
|
return useContext(DesktopHostContext);
|
|
1041
1064
|
}
|
|
1042
|
-
|
|
1065
|
+
var FOLDER_GRID = 90;
|
|
1066
|
+
var FOLDER_ITEM_H = 80;
|
|
1067
|
+
var FOLDER_PAD = 12;
|
|
1068
|
+
function FolderWindow({ folder, items, onClose, onOpen, onMoveOut, onSetFolderPosition, onDragOutToDesktop }) {
|
|
1043
1069
|
const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
|
|
1044
1070
|
const [rubber, setRubber] = useState(null);
|
|
1045
1071
|
const didDragRubber = useRef(false);
|
|
1046
1072
|
const bodyRef = useRef(null);
|
|
1047
|
-
const [
|
|
1048
|
-
const
|
|
1073
|
+
const [bodyWidth, setBodyWidth] = useState(800);
|
|
1074
|
+
const setDragOutsideClass = (on) => {
|
|
1075
|
+
const el = bodyRef.current;
|
|
1076
|
+
if (!el) return;
|
|
1077
|
+
el.style.outline = on ? "2px dashed rgb(96 165 250 / 0.6)" : "";
|
|
1078
|
+
el.style.outlineOffset = on ? "-2px" : "";
|
|
1079
|
+
};
|
|
1080
|
+
useEffect(() => {
|
|
1081
|
+
const el = bodyRef.current;
|
|
1082
|
+
if (!el) return;
|
|
1083
|
+
const update = () => setBodyWidth(el.clientWidth);
|
|
1084
|
+
update();
|
|
1085
|
+
const ro = new ResizeObserver(update);
|
|
1086
|
+
ro.observe(el);
|
|
1087
|
+
return () => ro.disconnect();
|
|
1088
|
+
}, []);
|
|
1089
|
+
const cols = Math.max(1, Math.floor((bodyWidth - FOLDER_PAD) / FOLDER_GRID));
|
|
1090
|
+
const getItemFolderPos = (item, idx) => {
|
|
1091
|
+
if (item.folderX != null && item.folderY != null) return { x: item.folderX, y: item.folderY };
|
|
1092
|
+
return { x: FOLDER_PAD + idx % cols * FOLDER_GRID, y: FOLDER_PAD + Math.floor(idx / cols) * FOLDER_GRID };
|
|
1093
|
+
};
|
|
1049
1094
|
const toggleSelect = (i, e) => {
|
|
1050
1095
|
e.stopPropagation();
|
|
1051
1096
|
if (e.shiftKey || e.metaKey || e.ctrlKey) {
|
|
@@ -1054,53 +1099,57 @@ function FolderWindow({ folder, items, onClose, onOpen, onMoveOut, onReorder })
|
|
|
1054
1099
|
next.has(i) ? next.delete(i) : next.add(i);
|
|
1055
1100
|
return next;
|
|
1056
1101
|
});
|
|
1057
|
-
} else {
|
|
1102
|
+
} else if (!selected.has(i)) {
|
|
1058
1103
|
setSelected(/* @__PURE__ */ new Set([i]));
|
|
1059
1104
|
}
|
|
1060
1105
|
};
|
|
1061
1106
|
const startRubber = (e) => {
|
|
1062
1107
|
if (e.button !== 0 || e.target !== bodyRef.current) return;
|
|
1063
|
-
const
|
|
1064
|
-
const
|
|
1065
|
-
const
|
|
1108
|
+
const el = bodyRef.current;
|
|
1109
|
+
const r = el.getBoundingClientRect();
|
|
1110
|
+
const x = e.clientX - r.left + el.scrollLeft;
|
|
1111
|
+
const y = e.clientY - r.top + el.scrollTop;
|
|
1066
1112
|
setRubber({ x1: x, y1: y, x2: x, y2: y });
|
|
1067
1113
|
didDragRubber.current = false;
|
|
1068
1114
|
setSelected(/* @__PURE__ */ new Set());
|
|
1069
1115
|
};
|
|
1070
1116
|
useEffect(() => {
|
|
1071
1117
|
if (!rubber) return;
|
|
1118
|
+
const computeSelection = (minX, maxX, minY, maxY) => {
|
|
1119
|
+
const next = /* @__PURE__ */ new Set();
|
|
1120
|
+
const r = bodyRef.current;
|
|
1121
|
+
if (!r) return next;
|
|
1122
|
+
const tiles = r.querySelectorAll("[data-folder-item]");
|
|
1123
|
+
const containerRect = r.getBoundingClientRect();
|
|
1124
|
+
tiles.forEach((t) => {
|
|
1125
|
+
const tr = t.getBoundingClientRect();
|
|
1126
|
+
const tx = tr.left - containerRect.left + r.scrollLeft;
|
|
1127
|
+
const ty = tr.top - containerRect.top + r.scrollTop;
|
|
1128
|
+
if (tx + tr.width > minX && tx < maxX && ty + tr.height > minY && ty < maxY) {
|
|
1129
|
+
const i = parseInt(t.getAttribute("data-folder-item") || "-1", 10);
|
|
1130
|
+
if (i >= 0) next.add(i);
|
|
1131
|
+
}
|
|
1132
|
+
});
|
|
1133
|
+
return next;
|
|
1134
|
+
};
|
|
1072
1135
|
const move = (e) => {
|
|
1073
|
-
const
|
|
1074
|
-
if (!
|
|
1075
|
-
const
|
|
1076
|
-
const
|
|
1136
|
+
const el = bodyRef.current;
|
|
1137
|
+
if (!el) return;
|
|
1138
|
+
const r = el.getBoundingClientRect();
|
|
1139
|
+
const x = e.clientX - r.left + el.scrollLeft;
|
|
1140
|
+
const y = e.clientY - r.top + el.scrollTop;
|
|
1077
1141
|
const dx = x - rubber.x1, dy = y - rubber.y1;
|
|
1078
1142
|
if (dx * dx + dy * dy > 16) didDragRubber.current = true;
|
|
1079
1143
|
setRubber((prev) => prev ? { ...prev, x2: x, y2: y } : null);
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
const maxX = Math.max(rubber.x1, rubber.x2);
|
|
1087
|
-
const minY = Math.min(rubber.y1, rubber.y2);
|
|
1088
|
-
const maxY = Math.max(rubber.y1, rubber.y2);
|
|
1089
|
-
const tiles = r.querySelectorAll("[data-folder-item]");
|
|
1090
|
-
const containerRect = r.getBoundingClientRect();
|
|
1091
|
-
tiles.forEach((t) => {
|
|
1092
|
-
const tr = t.getBoundingClientRect();
|
|
1093
|
-
const tx = tr.left - containerRect.left;
|
|
1094
|
-
const ty = tr.top - containerRect.top;
|
|
1095
|
-
if (tx + tr.width > minX && tx < maxX && ty + tr.height > minY && ty < maxY) {
|
|
1096
|
-
const i = parseInt(t.getAttribute("data-folder-item") || "-1", 10);
|
|
1097
|
-
if (i >= 0) next.add(i);
|
|
1098
|
-
}
|
|
1099
|
-
});
|
|
1144
|
+
if (didDragRubber.current) {
|
|
1145
|
+
const minX = Math.min(rubber.x1, x);
|
|
1146
|
+
const maxX = Math.max(rubber.x1, x);
|
|
1147
|
+
const minY = Math.min(rubber.y1, y);
|
|
1148
|
+
const maxY = Math.max(rubber.y1, y);
|
|
1149
|
+
setSelected(computeSelection(minX, maxX, minY, maxY));
|
|
1100
1150
|
}
|
|
1101
|
-
if (didDragRubber.current) setSelected(next);
|
|
1102
|
-
setRubber(null);
|
|
1103
1151
|
};
|
|
1152
|
+
const up = () => setRubber(null);
|
|
1104
1153
|
window.addEventListener("pointermove", move);
|
|
1105
1154
|
window.addEventListener("pointerup", up);
|
|
1106
1155
|
return () => {
|
|
@@ -1108,28 +1157,75 @@ function FolderWindow({ folder, items, onClose, onOpen, onMoveOut, onReorder })
|
|
|
1108
1157
|
window.removeEventListener("pointerup", up);
|
|
1109
1158
|
};
|
|
1110
1159
|
}, [rubber]);
|
|
1111
|
-
const
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
const onItemDragOver = (i) => (e) => {
|
|
1117
|
-
e.preventDefault();
|
|
1118
|
-
if (dragIdx !== null && dragIdx !== i) setDropIdx(i);
|
|
1119
|
-
};
|
|
1120
|
-
const onItemDrop = (i) => (e) => {
|
|
1160
|
+
const dragEntriesRef = useRef([]);
|
|
1161
|
+
const dragStartRef = useRef(null);
|
|
1162
|
+
const startItemDrag = (i, e) => {
|
|
1163
|
+
if (e.button !== 0) return;
|
|
1164
|
+
e.stopPropagation();
|
|
1121
1165
|
e.preventDefault();
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1166
|
+
const useMulti = selected.has(i) && selected.size > 1;
|
|
1167
|
+
const idxs = useMulti ? Array.from(selected) : [i];
|
|
1168
|
+
if (!useMulti) setSelected(/* @__PURE__ */ new Set([i]));
|
|
1169
|
+
const entries = idxs.map((idx) => {
|
|
1170
|
+
const item = items[idx];
|
|
1171
|
+
const pos = getItemFolderPos(item, idx);
|
|
1172
|
+
const el = bodyRef.current?.querySelector(`[data-folder-item="${idx}"]`) ?? null;
|
|
1173
|
+
return { idx, item, origX: pos.x, origY: pos.y, el };
|
|
1174
|
+
}).filter((e2) => e2.item);
|
|
1175
|
+
dragEntriesRef.current = entries;
|
|
1176
|
+
dragStartRef.current = { clientX: e.clientX, clientY: e.clientY };
|
|
1177
|
+
setDragOutsideClass(false);
|
|
1178
|
+
let moved = false;
|
|
1179
|
+
const move = (ev) => {
|
|
1180
|
+
const start = dragStartRef.current;
|
|
1181
|
+
if (!start) return;
|
|
1182
|
+
const dx = ev.clientX - start.clientX;
|
|
1183
|
+
const dy = ev.clientY - start.clientY;
|
|
1184
|
+
if (!moved && (Math.abs(dx) > 3 || Math.abs(dy) > 3)) moved = true;
|
|
1185
|
+
if (!moved) return;
|
|
1186
|
+
for (const entry of dragEntriesRef.current) {
|
|
1187
|
+
if (!entry.el) continue;
|
|
1188
|
+
entry.el.style.left = `${entry.origX + dx}px`;
|
|
1189
|
+
entry.el.style.top = `${entry.origY + dy}px`;
|
|
1190
|
+
entry.el.style.zIndex = "100";
|
|
1191
|
+
entry.el.style.opacity = "0.85";
|
|
1192
|
+
}
|
|
1193
|
+
const r = bodyRef.current?.getBoundingClientRect();
|
|
1194
|
+
const inside = !!r && ev.clientX >= r.left && ev.clientX <= r.right && ev.clientY >= r.top && ev.clientY <= r.bottom;
|
|
1195
|
+
setDragOutsideClass(!inside);
|
|
1196
|
+
};
|
|
1197
|
+
const up = (ev) => {
|
|
1198
|
+
window.removeEventListener("pointermove", move);
|
|
1199
|
+
window.removeEventListener("pointerup", up);
|
|
1200
|
+
const entries2 = dragEntriesRef.current;
|
|
1201
|
+
dragEntriesRef.current = [];
|
|
1202
|
+
dragStartRef.current = null;
|
|
1203
|
+
for (const entry of entries2) {
|
|
1204
|
+
if (!entry.el) continue;
|
|
1205
|
+
entry.el.style.zIndex = "";
|
|
1206
|
+
entry.el.style.opacity = "";
|
|
1207
|
+
}
|
|
1208
|
+
setDragOutsideClass(false);
|
|
1209
|
+
if (!moved) return;
|
|
1210
|
+
const r = bodyRef.current?.getBoundingClientRect();
|
|
1211
|
+
const inside = !!r && ev.clientX >= r.left && ev.clientX <= r.right && ev.clientY >= r.top && ev.clientY <= r.bottom;
|
|
1212
|
+
if (!inside) {
|
|
1213
|
+
const drops = entries2.map((e2) => ({ item: e2.item, clientX: ev.clientX, clientY: ev.clientY }));
|
|
1214
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
1215
|
+
onDragOutToDesktop(drops);
|
|
1216
|
+
} else {
|
|
1217
|
+
const updates = entries2.map((e2) => {
|
|
1218
|
+
const leftStr = e2.el?.style.left || `${e2.origX}px`;
|
|
1219
|
+
const topStr = e2.el?.style.top || `${e2.origY}px`;
|
|
1220
|
+
const x = Math.max(0, parseFloat(leftStr));
|
|
1221
|
+
const y = Math.max(0, parseFloat(topStr));
|
|
1222
|
+
return { item: e2.item, x, y };
|
|
1223
|
+
});
|
|
1224
|
+
onSetFolderPosition(updates);
|
|
1225
|
+
}
|
|
1226
|
+
};
|
|
1227
|
+
window.addEventListener("pointermove", move);
|
|
1228
|
+
window.addEventListener("pointerup", up);
|
|
1133
1229
|
};
|
|
1134
1230
|
const moveSelectedOut = () => {
|
|
1135
1231
|
if (selected.size === 0) return;
|
|
@@ -1137,6 +1233,10 @@ function FolderWindow({ folder, items, onClose, onOpen, onMoveOut, onReorder })
|
|
|
1137
1233
|
setSelected(/* @__PURE__ */ new Set());
|
|
1138
1234
|
};
|
|
1139
1235
|
const folderIcon = /* @__PURE__ */ jsx("svg", { className: "h-5 w-5 text-amber-500", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { d: "M2 6a2 2 0 012-2h5l2 2h9a2 2 0 012 2v10a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" }) });
|
|
1236
|
+
const contentHeight = items.reduce((max, item, i) => {
|
|
1237
|
+
const pos = getItemFolderPos(item, i);
|
|
1238
|
+
return Math.max(max, pos.y + FOLDER_ITEM_H + FOLDER_PAD);
|
|
1239
|
+
}, 300);
|
|
1140
1240
|
return /* @__PURE__ */ jsx(Modal, { open: true, onClose, title: folder.name, icon: folderIcon, size: "lg", children: /* @__PURE__ */ jsxs(
|
|
1141
1241
|
"div",
|
|
1142
1242
|
{
|
|
@@ -1154,7 +1254,7 @@ function FolderWindow({ folder, items, onClose, onOpen, onMoveOut, onReorder })
|
|
|
1154
1254
|
background: "linear-gradient(135deg, rgba(254, 243, 199, 0.55) 0%, rgba(253, 230, 138, 0.4) 50%, rgba(252, 211, 77, 0.3) 100%)"
|
|
1155
1255
|
},
|
|
1156
1256
|
children: [
|
|
1157
|
-
selected.size > 0 && /* @__PURE__ */ jsxs("div", { className: "sticky top-0 z-
|
|
1257
|
+
selected.size > 0 && /* @__PURE__ */ jsxs("div", { className: "sticky top-0 z-20 mb-2 flex items-center gap-2 px-2 py-1 rounded-md bg-white/80 backdrop-blur-sm shadow border border-gray-200 text-xs text-gray-700 w-fit", children: [
|
|
1158
1258
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
1159
1259
|
selected.size,
|
|
1160
1260
|
" selected"
|
|
@@ -1162,40 +1262,22 @@ function FolderWindow({ folder, items, onClose, onOpen, onMoveOut, onReorder })
|
|
|
1162
1262
|
/* @__PURE__ */ jsx("button", { onClick: moveSelectedOut, className: "px-2 py-0.5 rounded text-blue-600 hover:bg-blue-50", children: "Move to desktop" }),
|
|
1163
1263
|
/* @__PURE__ */ jsx("button", { onClick: () => setSelected(/* @__PURE__ */ new Set()), className: "px-2 py-0.5 rounded text-gray-500 hover:bg-gray-100", children: "Clear" })
|
|
1164
1264
|
] }),
|
|
1165
|
-
items.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 text-center py-8 italic", children: "Folder is empty. Drag documents here." }) : /* @__PURE__ */ jsx("div", { className: "
|
|
1265
|
+
items.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 text-center py-8 italic", children: "Folder is empty. Drag documents here." }) : /* @__PURE__ */ jsx("div", { className: "relative", style: { height: contentHeight }, children: items.map((item, i) => {
|
|
1166
1266
|
const isSelected = selected.has(i);
|
|
1167
|
-
const
|
|
1168
|
-
return /* @__PURE__ */
|
|
1267
|
+
const pos = getItemFolderPos(item, i);
|
|
1268
|
+
return /* @__PURE__ */ jsx(
|
|
1169
1269
|
"div",
|
|
1170
1270
|
{
|
|
1171
1271
|
"data-folder-item": i,
|
|
1172
|
-
|
|
1173
|
-
onDragStart: onItemDragStart(i),
|
|
1174
|
-
onDragOver: onItemDragOver(i),
|
|
1175
|
-
onDrop: onItemDrop(i),
|
|
1176
|
-
onDragEnd: () => {
|
|
1177
|
-
setDragIdx(null);
|
|
1178
|
-
setDropIdx(null);
|
|
1179
|
-
},
|
|
1272
|
+
onPointerDown: (e) => startItemDrag(i, e),
|
|
1180
1273
|
onClick: (e) => toggleSelect(i, e),
|
|
1181
1274
|
onDoubleClick: () => onOpen(item),
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
e.stopPropagation();
|
|
1189
|
-
onMoveOut([item]);
|
|
1190
|
-
},
|
|
1191
|
-
title: "Move to desktop",
|
|
1192
|
-
className: "absolute -top-1 -right-1 h-5 w-5 rounded-full bg-gray-200 text-gray-500 flex items-center justify-center text-[10px] opacity-0 group-hover:opacity-100 transition-opacity hover:bg-red-100 hover:text-red-600 shadow-sm z-10",
|
|
1193
|
-
children: /* @__PURE__ */ jsx("svg", { className: "h-3 w-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3" }) })
|
|
1194
|
-
}
|
|
1195
|
-
),
|
|
1196
|
-
/* @__PURE__ */ jsx("div", { className: `w-12 h-12 rounded-lg bg-white shadow flex items-center justify-center text-xs font-bold ${item.entityType === "preview-file" && item.fileKind ? PREVIEW_FILE_COLORS[item.fileKind] : ENTITY_ICON_COLORS[item.entityType] || "text-gray-600"}`, children: item.entityType === "preview-file" && item.fileKind ? PREVIEW_FILE_CODES[item.fileKind] : ENTITY_ICONS[item.entityType] || item.entityType.slice(0, 3).toUpperCase() }),
|
|
1197
|
-
/* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium text-center leading-tight truncate w-full ${isSelected ? "text-blue-900" : "text-gray-700"}`, children: item.label })
|
|
1198
|
-
]
|
|
1275
|
+
style: { position: "absolute", left: pos.x, top: pos.y },
|
|
1276
|
+
className: "cursor-default select-none",
|
|
1277
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 w-20 p-2", children: [
|
|
1278
|
+
/* @__PURE__ */ jsx(FileIconTile, { entityType: item.entityType, isSelected, entityId: item.entityId, label: item.label, fileKind: item.fileKind }),
|
|
1279
|
+
/* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium text-center leading-tight truncate w-full ${isSelected ? "text-blue-900 bg-blue-200/60 rounded px-1" : "text-gray-700"}`, children: item.label })
|
|
1280
|
+
] })
|
|
1199
1281
|
},
|
|
1200
1282
|
`${item.entityType}-${item.entityId}-${i}`
|
|
1201
1283
|
);
|
|
@@ -1495,7 +1577,7 @@ function Desktop({ profile }) {
|
|
|
1495
1577
|
const desktopIdx = favDocs.indexOf(desktopItems[move2.entry.idx]);
|
|
1496
1578
|
if (desktopIdx === -1) continue;
|
|
1497
1579
|
if (droppedOnFolder) {
|
|
1498
|
-
updated[desktopIdx] = { ...updated[desktopIdx], folderId: droppedOnFolder.id, x: void 0, y: void 0 };
|
|
1580
|
+
updated[desktopIdx] = { ...updated[desktopIdx], folderId: droppedOnFolder.id, x: void 0, y: void 0, folderX: void 0, folderY: void 0 };
|
|
1499
1581
|
} else {
|
|
1500
1582
|
updated[desktopIdx] = { ...updated[desktopIdx], x: move2.finalRight, y: move2.finalTop, folderId: void 0 };
|
|
1501
1583
|
positionsPatch[`item-${desktopIdx}`] = { right: move2.finalRight, top: move2.finalTop };
|
|
@@ -1771,31 +1853,10 @@ function Desktop({ profile }) {
|
|
|
1771
1853
|
purple: "bg-purple-100 border-purple-300",
|
|
1772
1854
|
orange: "bg-orange-100 border-orange-300"
|
|
1773
1855
|
};
|
|
1774
|
-
const renderIcon = (entityType, label, isSelected, entityId, fileKind) => {
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 w-20 p-2", children: [
|
|
1779
|
-
entityType === "folder" ? /* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: /* @__PURE__ */ jsxs("svg", { className: "h-12 w-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)]", viewBox: "0 0 48 48", children: [
|
|
1780
|
-
/* @__PURE__ */ jsx("path", { d: "M6 12a4 4 0 014-4h10l4 4h14a4 4 0 014 4v20a4 4 0 01-4 4H10a4 4 0 01-4-4V12z", fill: "white", stroke: "#eab308", strokeWidth: "2", strokeLinejoin: "round" }),
|
|
1781
|
-
/* @__PURE__ */ jsx("path", { d: "M6 18h36", stroke: "#eab308", strokeWidth: "1.5" })
|
|
1782
|
-
] }) }) : entityType === "page" ? /* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: (() => {
|
|
1783
|
-
const icon = navIcons[label] || (entityId ? navIcons[entityId] : void 0);
|
|
1784
|
-
if (icon && isValidElement(icon)) {
|
|
1785
|
-
return cloneElement(icon, { className: "h-10 w-10 text-white drop-shadow-[0_2px_3px_rgba(0,0,0,0.4)]" });
|
|
1786
|
-
}
|
|
1787
|
-
return /* @__PURE__ */ jsx("svg", { className: "h-10 w-10 text-white drop-shadow-[0_2px_3px_rgba(0,0,0,0.4)]", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6z" }) });
|
|
1788
|
-
})() }) : /* @__PURE__ */ jsxs("div", { className: `w-12 h-12 relative flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: [
|
|
1789
|
-
/* @__PURE__ */ jsxs("svg", { className: `w-10 h-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)] ${previewColor2 ?? ENTITY_ICON_COLORS[entityType] ?? "text-gray-500"}`, viewBox: "0 0 40 48", fill: "none", children: [
|
|
1790
|
-
/* @__PURE__ */ jsx("path", { d: "M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z", fill: "white", fillOpacity: "0.92" }),
|
|
1791
|
-
/* @__PURE__ */ jsx("path", { d: "M26 0l10 10H30a4 4 0 01-4-4V0z", fill: "currentColor", fillOpacity: "0.2" }),
|
|
1792
|
-
/* @__PURE__ */ jsx("path", { d: "M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z", stroke: "currentColor", strokeWidth: "1.5", strokeOpacity: "0.5" })
|
|
1793
|
-
] }),
|
|
1794
|
-
/* @__PURE__ */ jsx("span", { className: `absolute inset-0 flex items-center justify-center text-[9px] font-bold pt-2 ${previewColor2 ?? ENTITY_ICON_COLORS[entityType] ?? "text-gray-600"}`, children: previewCode ?? ENTITY_ICONS[entityType] ?? entityType.slice(0, 3).toUpperCase() })
|
|
1795
|
-
] }),
|
|
1796
|
-
/* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium text-center leading-tight w-full drop-shadow-[0_1px_2px_rgba(0,0,0,0.8)] ${isSelected ? "text-blue-200 bg-blue-600/60 rounded px-1" : "text-white"}`, children: label })
|
|
1797
|
-
] });
|
|
1798
|
-
};
|
|
1856
|
+
const renderIcon = (entityType, label, isSelected, entityId, fileKind) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 w-20 p-2", children: [
|
|
1857
|
+
/* @__PURE__ */ jsx(FileIconTile, { entityType, isSelected, entityId, label, fileKind }),
|
|
1858
|
+
/* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium text-center leading-tight w-full drop-shadow-[0_1px_2px_rgba(0,0,0,0.8)] ${isSelected ? "text-blue-200 bg-blue-600/60 rounded px-1" : "text-white"}`, children: label })
|
|
1859
|
+
] });
|
|
1799
1860
|
const menuStyle = (x, y) => ({
|
|
1800
1861
|
...x + 180 > window.innerWidth ? { right: window.innerWidth - x } : { left: x },
|
|
1801
1862
|
...y + 250 > window.innerHeight ? { bottom: window.innerHeight - y } : { top: y }
|
|
@@ -2239,13 +2300,40 @@ function Desktop({ profile }) {
|
|
|
2239
2300
|
onMoveOut: (toMove) => {
|
|
2240
2301
|
const ids = new Set(toMove.map((t) => `${t.entityType}|${t.entityId}`));
|
|
2241
2302
|
const updated = favDocs.map(
|
|
2242
|
-
(d) => d.folderId === openFolder && ids.has(`${d.entityType}|${d.entityId}`) ? { ...d, folderId: void 0 } : d
|
|
2303
|
+
(d) => d.folderId === openFolder && ids.has(`${d.entityType}|${d.entityId}`) ? { ...d, folderId: void 0, folderX: void 0, folderY: void 0 } : d
|
|
2243
2304
|
);
|
|
2244
2305
|
saveDocs(updated);
|
|
2245
2306
|
},
|
|
2246
|
-
|
|
2247
|
-
const
|
|
2248
|
-
|
|
2307
|
+
onSetFolderPosition: (updates) => {
|
|
2308
|
+
const patch = new Map(updates.map((u) => [`${u.item.entityType}|${u.item.entityId}`, u]));
|
|
2309
|
+
const updated = favDocs.map((d) => {
|
|
2310
|
+
const u = patch.get(`${d.entityType}|${d.entityId}`);
|
|
2311
|
+
return u ? { ...d, folderX: u.x, folderY: u.y } : d;
|
|
2312
|
+
});
|
|
2313
|
+
saveDocs(updated);
|
|
2314
|
+
},
|
|
2315
|
+
onDragOutToDesktop: (drops) => {
|
|
2316
|
+
const containerRect = containerRef.current?.getBoundingClientRect();
|
|
2317
|
+
const cw = containerRef.current?.clientWidth ?? window.innerWidth;
|
|
2318
|
+
const patch = /* @__PURE__ */ new Map();
|
|
2319
|
+
for (const d of drops) {
|
|
2320
|
+
const offX = containerRect ? d.clientX - containerRect.left : d.clientX;
|
|
2321
|
+
const offY = containerRect ? d.clientY - containerRect.top : d.clientY;
|
|
2322
|
+
let right = cw - offX - 40;
|
|
2323
|
+
let top = Math.max(0, offY - 40);
|
|
2324
|
+
if (snapEnabled) {
|
|
2325
|
+
const s = snapToGrid(right, top);
|
|
2326
|
+
right = s.x;
|
|
2327
|
+
top = s.y;
|
|
2328
|
+
}
|
|
2329
|
+
right = Math.max(0, right);
|
|
2330
|
+
patch.set(`${d.item.entityType}|${d.item.entityId}`, { right, top });
|
|
2331
|
+
}
|
|
2332
|
+
const updated = favDocs.map((d) => {
|
|
2333
|
+
const p = patch.get(`${d.entityType}|${d.entityId}`);
|
|
2334
|
+
return p ? { ...d, folderId: void 0, folderX: void 0, folderY: void 0, x: p.right, y: p.top } : d;
|
|
2335
|
+
});
|
|
2336
|
+
saveDocs(updated);
|
|
2249
2337
|
}
|
|
2250
2338
|
}
|
|
2251
2339
|
);
|