react-os-shell 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/{Calculator-PTET7HM2.js → Calculator-PBCTMZCM.js} +4 -4
  2. package/dist/{Calculator-PTET7HM2.js.map → Calculator-PBCTMZCM.js.map} +1 -1
  3. package/dist/{Calendar-H6WA57K2.js → Calendar-ULBZI2ZZ.js} +4 -4
  4. package/dist/{Calendar-H6WA57K2.js.map → Calendar-ULBZI2ZZ.js.map} +1 -1
  5. package/dist/{CurrencyConverter-ZLZIO4TW.js → CurrencyConverter-6LQTPUPC.js} +4 -4
  6. package/dist/{CurrencyConverter-ZLZIO4TW.js.map → CurrencyConverter-6LQTPUPC.js.map} +1 -1
  7. package/dist/{Email-E3ZZUUON.js → Email-CJYW4OOP.js} +3 -3
  8. package/dist/{Email-E3ZZUUON.js.map → Email-CJYW4OOP.js.map} +1 -1
  9. package/dist/{Minesweeper-OBQCXZKI.js → Minesweeper-YNR4S3EJ.js} +3 -3
  10. package/dist/{Minesweeper-OBQCXZKI.js.map → Minesweeper-YNR4S3EJ.js.map} +1 -1
  11. package/dist/{Notepad-6L6BWIBG.js → Notepad-7ALDRLDP.js} +4 -4
  12. package/dist/{Notepad-6L6BWIBG.js.map → Notepad-7ALDRLDP.js.map} +1 -1
  13. package/dist/{PomodoroTimer-SDRN2GZD.js → PomodoroTimer-F2NAJ63E.js} +4 -4
  14. package/dist/{PomodoroTimer-SDRN2GZD.js.map → PomodoroTimer-F2NAJ63E.js.map} +1 -1
  15. package/dist/{Spreadsheet-N6CTEPJM.js → Spreadsheet-RJKUJDQS.js} +3 -3
  16. package/dist/{Spreadsheet-N6CTEPJM.js.map → Spreadsheet-RJKUJDQS.js.map} +1 -1
  17. package/dist/{Weather-QZJWPPUP.js → Weather-CQ4ECULG.js} +5 -5
  18. package/dist/{Weather-QZJWPPUP.js.map → Weather-CQ4ECULG.js.map} +1 -1
  19. package/dist/apps/index.js +9 -9
  20. package/dist/{chunk-ZR2DVGZI.js → chunk-24K73LGZ.js} +59 -12
  21. package/dist/chunk-24K73LGZ.js.map +1 -0
  22. package/dist/{chunk-TFGOLXGD.js → chunk-36VM54SC.js} +6 -5
  23. package/dist/chunk-36VM54SC.js.map +1 -0
  24. package/dist/{chunk-4POBPSEW.js → chunk-TAQJD73Z.js} +3 -3
  25. package/dist/{chunk-4POBPSEW.js.map → chunk-TAQJD73Z.js.map} +1 -1
  26. package/dist/index.d.ts +6 -2
  27. package/dist/index.js +135 -51
  28. package/dist/index.js.map +1 -1
  29. package/package.json +1 -1
  30. package/dist/chunk-TFGOLXGD.js.map +0 -1
  31. package/dist/chunk-ZR2DVGZI.js.map +0 -1
package/dist/index.js CHANGED
@@ -5,10 +5,10 @@ export { formatDate } from './chunk-NSU7OHPC.js';
5
5
  import { toast_default } from './chunk-WIJ45SYD.js';
6
6
  export { toast_default as toast } from './chunk-WIJ45SYD.js';
7
7
  import { playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, playLogout, setSoundForType, previewSound, setAllSounds } from './chunk-D7PYW2QS.js';
8
- import { useShellPrefs } from './chunk-TFGOLXGD.js';
9
- export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-TFGOLXGD.js';
10
- import { useWindowManager, glassStyle, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, startMenuCategories, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons, ModalActions, useModalActive } from './chunk-ZR2DVGZI.js';
11
- export { CancelButton, CopyButton, DocFavStar, GLASS_DIVIDER, GLASS_INPUT_BG, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, glassStyle, isEntityEntry, isPageEntry, setShellApiClient, setShellNavIcons, setShellWindowRegistry, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-ZR2DVGZI.js';
8
+ import { useShellPrefs } from './chunk-36VM54SC.js';
9
+ export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
10
+ import { useWindowManager, glassStyle, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, startMenuCategories, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons, ModalActions, useModalActive } from './chunk-24K73LGZ.js';
11
+ export { CancelButton, CopyButton, DocFavStar, GLASS_DIVIDER, GLASS_INPUT_BG, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, glassStyle, isEntityEntry, isPageEntry, setShellApiClient, setShellNavIcons, setShellWindowRegistry, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-24K73LGZ.js';
12
12
  export { ConfirmProvider, confirm, confirmDestructive } from './chunk-RFTLYCSF.js';
13
13
  import { createContext, useState, useRef, useEffect, useCallback, useLayoutEffect, useContext, isValidElement, cloneElement, useSyncExternalStore } from 'react';
14
14
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -643,7 +643,7 @@ function StatusBadge({ status }) {
643
643
  }
644
644
 
645
645
  // src/version.ts
646
- var VERSION = "0.1.10" ;
646
+ var VERSION = "0.1.12" ;
647
647
  var APP_VERSION = VERSION;
648
648
 
649
649
  // src/changelog.ts
@@ -885,65 +885,129 @@ function Desktop({ profile }) {
885
885
  const desktopItems = favDocs.filter((d) => !d.folderId);
886
886
  const folderItems = (folderId) => favDocs.filter((d) => d.folderId === folderId);
887
887
  const [localPositions, setLocalPositions] = useState({});
888
- const dragElRef = useRef(null);
888
+ const dragEntriesRef = useRef([]);
889
889
  const startDrag = (type, idx, e) => {
890
890
  if (e.button !== 0) return;
891
- const items = type === "item" ? desktopItems : folders;
892
- const item = items[idx];
893
- const pos = type === "item" ? getItemPos(item, idx) : getFolderPos(item, idx);
894
- setDragging({ type, idx, startX: e.clientX, startY: e.clientY, origX: pos.right, origY: pos.top });
895
- dragElRef.current = e.target.closest("[data-desktop-icon]");
891
+ const primaryKey = `${type}-${idx}`;
892
+ const draggingMulti = selected.has(primaryKey) && selected.size > 1;
893
+ const keys = draggingMulti ? Array.from(selected) : [primaryKey];
894
+ const entries = [];
895
+ for (const key of keys) {
896
+ if (key.startsWith("item-")) {
897
+ const i = parseInt(key.slice(5), 10);
898
+ const itm = desktopItems[i];
899
+ if (!itm) continue;
900
+ const pos = getItemPos(itm, i);
901
+ const el = document.querySelector(`[data-desktop-icon="${key}"]`);
902
+ entries.push({ key, type: "item", idx: i, origX: pos.right, origY: pos.top, el });
903
+ } else if (key.startsWith("folder-")) {
904
+ const i = parseInt(key.slice(7), 10);
905
+ const f = folders[i];
906
+ if (!f) continue;
907
+ const pos = getFolderPos(f, i);
908
+ const el = document.querySelector(`[data-desktop-icon="${key}"]`);
909
+ entries.push({ key, type: "folder", idx: i, origX: pos.right, origY: pos.top, el });
910
+ }
911
+ }
912
+ dragEntriesRef.current = entries;
913
+ const primaryEntry = entries.find((e2) => e2.key === primaryKey) ?? entries[0];
914
+ if (!primaryEntry) return;
915
+ setDragging({ type, idx, startX: e.clientX, startY: e.clientY, origX: primaryEntry.origX, origY: primaryEntry.origY });
896
916
  e.preventDefault();
897
917
  };
898
918
  useEffect(() => {
899
919
  if (!dragging) return;
900
- const el = dragElRef.current;
920
+ const entries = dragEntriesRef.current;
901
921
  const move = (e) => {
902
- const nr = dragging.origX - (e.clientX - dragging.startX);
903
- const nt = dragging.origY + e.clientY - dragging.startY;
904
- if (el) {
905
- el.style.right = `${nr}px`;
906
- el.style.top = `${nt}px`;
907
- el.style.left = "auto";
908
- el.style.zIndex = "100";
909
- el.style.opacity = "0.7";
922
+ const dx = e.clientX - dragging.startX;
923
+ const dy = e.clientY - dragging.startY;
924
+ for (const entry of entries) {
925
+ if (!entry.el) continue;
926
+ entry.el.style.right = `${entry.origX - dx}px`;
927
+ entry.el.style.top = `${entry.origY + dy}px`;
928
+ entry.el.style.left = "auto";
929
+ entry.el.style.zIndex = "100";
930
+ entry.el.style.opacity = "0.7";
910
931
  }
911
932
  };
912
933
  const up = (e) => {
913
- let finalRight = dragging.origX - (e.clientX - dragging.startX);
914
- let finalTop = Math.max(0, dragging.origY + e.clientY - dragging.startY);
915
- if (snapEnabled) {
916
- const s = snapToGrid(finalRight, finalTop);
917
- finalRight = s.x;
918
- finalTop = s.y;
919
- }
920
- finalRight = Math.max(0, finalRight);
921
- if (el) {
922
- el.style.zIndex = "";
923
- el.style.opacity = "";
934
+ const dx = e.clientX - dragging.startX;
935
+ const dy = e.clientY - dragging.startY;
936
+ for (const entry of entries) {
937
+ if (!entry.el) continue;
938
+ entry.el.style.zIndex = "";
939
+ entry.el.style.opacity = "";
924
940
  }
925
- if (dragging.type === "item") {
926
- const droppedOnFolder = folders.find((f, fi) => {
927
- const fp = getFolderPos(f, fi);
928
- return Math.abs(finalRight - fp.right) < 40 && Math.abs(finalTop - fp.top) < 40;
929
- });
941
+ const computedPositions = entries.map((entry) => {
942
+ let finalRight = entry.origX - dx;
943
+ let finalTop = Math.max(0, entry.origY + dy);
944
+ if (snapEnabled) {
945
+ const s = snapToGrid(finalRight, finalTop);
946
+ finalRight = s.x;
947
+ finalTop = s.y;
948
+ }
949
+ finalRight = Math.max(0, finalRight);
950
+ return { entry, finalRight, finalTop };
951
+ });
952
+ const itemMoves = computedPositions.filter((p) => p.entry.type === "item");
953
+ if (itemMoves.length > 0) {
930
954
  const updated = [...favDocs];
931
- const desktopIdx = favDocs.indexOf(desktopItems[dragging.idx]);
932
- if (droppedOnFolder) {
933
- updated[desktopIdx] = { ...updated[desktopIdx], folderId: droppedOnFolder.id, x: void 0, y: void 0 };
934
- } else {
935
- updated[desktopIdx] = { ...updated[desktopIdx], x: finalRight, y: finalTop, folderId: void 0 };
936
- setLocalPositions((prev) => ({ ...prev, [`item-${desktopIdx}`]: { right: finalRight, top: finalTop } }));
955
+ const positionsPatch = {};
956
+ const singleItem = itemMoves.length === 1 && entries.length === 1 ? itemMoves[0] : null;
957
+ const droppedOnFolder = singleItem ? folders.find((f, fi) => {
958
+ const fp = getFolderPos(f, fi);
959
+ return Math.abs(singleItem.finalRight - fp.right) < 40 && Math.abs(singleItem.finalTop - fp.top) < 40;
960
+ }) : void 0;
961
+ if (droppedOnFolder && singleItem?.entry.el) {
962
+ const itemEl = singleItem.entry.el;
963
+ const folderIdx = folders.indexOf(droppedOnFolder);
964
+ const folderEl = document.querySelector(`[data-desktop-icon="folder-${folderIdx}"]`);
965
+ if (folderEl) {
966
+ const ir = itemEl.getBoundingClientRect();
967
+ const fr = folderEl.getBoundingClientRect();
968
+ const dx2 = fr.left + fr.width / 2 - (ir.left + ir.width / 2);
969
+ const dy2 = fr.top + fr.height / 2 - (ir.top + ir.height / 2);
970
+ itemEl.style.transition = "transform 220ms ease-out, opacity 220ms ease-out";
971
+ itemEl.style.transform = `translate(${dx2}px, ${dy2}px) scale(0.2)`;
972
+ itemEl.style.opacity = "0";
973
+ }
974
+ folderEl?.animate(
975
+ [{ transform: "scale(1)" }, { transform: "scale(1.15)" }, { transform: "scale(1)" }],
976
+ { duration: 280, easing: "ease-out" }
977
+ );
978
+ }
979
+ for (const move2 of itemMoves) {
980
+ const desktopIdx = favDocs.indexOf(desktopItems[move2.entry.idx]);
981
+ if (desktopIdx === -1) continue;
982
+ if (droppedOnFolder) {
983
+ updated[desktopIdx] = { ...updated[desktopIdx], folderId: droppedOnFolder.id, x: void 0, y: void 0 };
984
+ } else {
985
+ updated[desktopIdx] = { ...updated[desktopIdx], x: move2.finalRight, y: move2.finalTop, folderId: void 0 };
986
+ positionsPatch[`item-${desktopIdx}`] = { right: move2.finalRight, top: move2.finalTop };
987
+ }
937
988
  }
938
- saveDocs(updated);
939
- } else {
989
+ const commit = () => {
990
+ saveDocs(updated);
991
+ if (Object.keys(positionsPatch).length > 0) {
992
+ setLocalPositions((prev) => ({ ...prev, ...positionsPatch }));
993
+ }
994
+ };
995
+ if (droppedOnFolder) setTimeout(commit, 220);
996
+ else commit();
997
+ }
998
+ const folderMoves = computedPositions.filter((p) => p.entry.type === "folder");
999
+ if (folderMoves.length > 0) {
940
1000
  const updated = [...folders];
941
- updated[dragging.idx] = { ...updated[dragging.idx], x: finalRight, y: finalTop };
942
- setLocalPositions((prev) => ({ ...prev, [`folder-${dragging.idx}`]: { right: finalRight, top: finalTop } }));
1001
+ const positionsPatch = {};
1002
+ for (const move2 of folderMoves) {
1003
+ updated[move2.entry.idx] = { ...updated[move2.entry.idx], x: move2.finalRight, y: move2.finalTop };
1004
+ positionsPatch[`folder-${move2.entry.idx}`] = { right: move2.finalRight, top: move2.finalTop };
1005
+ }
943
1006
  saveFolders(updated);
1007
+ setLocalPositions((prev) => ({ ...prev, ...positionsPatch }));
944
1008
  }
945
1009
  setDragging(null);
946
- dragElRef.current = null;
1010
+ dragEntriesRef.current = [];
947
1011
  };
948
1012
  window.addEventListener("pointermove", move);
949
1013
  window.addEventListener("pointerup", up);
@@ -1233,7 +1297,7 @@ function Desktop({ profile }) {
1233
1297
  return /* @__PURE__ */ jsx(
1234
1298
  "div",
1235
1299
  {
1236
- "data-desktop-icon": true,
1300
+ "data-desktop-icon": `item-${i}`,
1237
1301
  style: { position: "absolute", right: pos.right, top: pos.top, zIndex: 1 },
1238
1302
  onPointerDown: (e) => {
1239
1303
  e.stopPropagation();
@@ -1241,7 +1305,15 @@ function Desktop({ profile }) {
1241
1305
  },
1242
1306
  onClick: (e) => {
1243
1307
  e.stopPropagation();
1244
- setSelected(/* @__PURE__ */ new Set([`item-${i}`]));
1308
+ if (e.shiftKey || e.metaKey || e.ctrlKey) {
1309
+ setSelected((prev) => {
1310
+ const next = new Set(prev);
1311
+ next.has(`item-${i}`) ? next.delete(`item-${i}`) : next.add(`item-${i}`);
1312
+ return next;
1313
+ });
1314
+ } else if (!selected.has(`item-${i}`)) {
1315
+ setSelected(/* @__PURE__ */ new Set([`item-${i}`]));
1316
+ }
1245
1317
  },
1246
1318
  onContextMenu: (e) => handleItemContextMenu(e, i),
1247
1319
  onDoubleClick: (e) => {
@@ -1261,7 +1333,7 @@ function Desktop({ profile }) {
1261
1333
  return /* @__PURE__ */ jsx(
1262
1334
  "div",
1263
1335
  {
1264
- "data-desktop-icon": true,
1336
+ "data-desktop-icon": `folder-${i}`,
1265
1337
  style: { position: "absolute", right: pos.right, top: pos.top, zIndex: 1 },
1266
1338
  onPointerDown: (e) => {
1267
1339
  e.stopPropagation();
@@ -1269,7 +1341,15 @@ function Desktop({ profile }) {
1269
1341
  },
1270
1342
  onClick: (e) => {
1271
1343
  e.stopPropagation();
1272
- setSelected(/* @__PURE__ */ new Set([`folder-${i}`]));
1344
+ if (e.shiftKey || e.metaKey || e.ctrlKey) {
1345
+ setSelected((prev) => {
1346
+ const next = new Set(prev);
1347
+ next.has(`folder-${i}`) ? next.delete(`folder-${i}`) : next.add(`folder-${i}`);
1348
+ return next;
1349
+ });
1350
+ } else if (!selected.has(`folder-${i}`)) {
1351
+ setSelected(/* @__PURE__ */ new Set([`folder-${i}`]));
1352
+ }
1273
1353
  },
1274
1354
  onContextMenu: (e) => handleFolderContextMenu(e, i),
1275
1355
  onDoubleClick: (e) => {
@@ -1337,6 +1417,7 @@ function Desktop({ profile }) {
1337
1417
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsx(
1338
1418
  "button",
1339
1419
  {
1420
+ onPointerDown: (e) => e.stopPropagation(),
1340
1421
  onClick: (e) => {
1341
1422
  e.stopPropagation();
1342
1423
  cycleStickyColor(note.id);
@@ -1349,6 +1430,7 @@ function Desktop({ profile }) {
1349
1430
  /* @__PURE__ */ jsx(
1350
1431
  "button",
1351
1432
  {
1433
+ onPointerDown: (e) => e.stopPropagation(),
1352
1434
  onClick: (e) => {
1353
1435
  e.stopPropagation();
1354
1436
  toggleStickyOnTop(note.id);
@@ -1364,6 +1446,7 @@ function Desktop({ profile }) {
1364
1446
  /* @__PURE__ */ jsx(
1365
1447
  "button",
1366
1448
  {
1449
+ onPointerDown: (e) => e.stopPropagation(),
1367
1450
  onClick: (e) => {
1368
1451
  e.stopPropagation();
1369
1452
  removeStickyFromDesktop(note.id);
@@ -1376,6 +1459,7 @@ function Desktop({ profile }) {
1376
1459
  /* @__PURE__ */ jsx(
1377
1460
  "button",
1378
1461
  {
1462
+ onPointerDown: (e) => e.stopPropagation(),
1379
1463
  onClick: (e) => {
1380
1464
  e.stopPropagation();
1381
1465
  deleteStickyNote(note.id);