react-os-shell 0.6.9 → 0.7.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.
Files changed (54) hide show
  1. package/dist/{Browser-42ZTL3DQ.js → Browser-WVSS64J6.js} +3 -3
  2. package/dist/{Browser-42ZTL3DQ.js.map → Browser-WVSS64J6.js.map} +1 -1
  3. package/dist/{Calculator-QMC43H6W.js → Calculator-37EIFRDU.js} +4 -4
  4. package/dist/{Calculator-QMC43H6W.js.map → Calculator-37EIFRDU.js.map} +1 -1
  5. package/dist/{Calendar-OSPNZXPD.js → Calendar-KCZQJ5CY.js} +3 -3
  6. package/dist/{Calendar-OSPNZXPD.js.map → Calendar-KCZQJ5CY.js.map} +1 -1
  7. package/dist/{CurrencyConverter-RQKXZ56O.js → CurrencyConverter-PWX3FKRK.js} +4 -4
  8. package/dist/{CurrencyConverter-RQKXZ56O.js.map → CurrencyConverter-PWX3FKRK.js.map} +1 -1
  9. package/dist/{Documents-SNNWYPAS.js → Documents-W2DABIOW.js} +3 -3
  10. package/dist/{Documents-SNNWYPAS.js.map → Documents-W2DABIOW.js.map} +1 -1
  11. package/dist/{Email-QIDYGDSR.js → Email-GTGL7CW5.js} +3 -3
  12. package/dist/{Email-QIDYGDSR.js.map → Email-GTGL7CW5.js.map} +1 -1
  13. package/dist/Files-XNAPEBFF.js +11 -0
  14. package/dist/{Files-JUWNFKSF.js.map → Files-XNAPEBFF.js.map} +1 -1
  15. package/dist/{Minesweeper-TZU7VTBR.js → Minesweeper-N73MSPJV.js} +3 -3
  16. package/dist/{Minesweeper-TZU7VTBR.js.map → Minesweeper-N73MSPJV.js.map} +1 -1
  17. package/dist/{Notepad-RXDODESR.js → Notepad-MXEQCIC7.js} +3 -3
  18. package/dist/{Notepad-RXDODESR.js.map → Notepad-MXEQCIC7.js.map} +1 -1
  19. package/dist/{PomodoroTimer-YYFTVAAT.js → PomodoroTimer-VEYXRZWZ.js} +4 -4
  20. package/dist/{PomodoroTimer-YYFTVAAT.js.map → PomodoroTimer-VEYXRZWZ.js.map} +1 -1
  21. package/dist/Preview-VMKMY6SY.js +8 -0
  22. package/dist/{Preview-HDHGK3QA.js.map → Preview-VMKMY6SY.js.map} +1 -1
  23. package/dist/{Sidebar-Q3PRJ2FP.js → Sidebar-BW7SYNBA.js} +2 -13
  24. package/dist/Sidebar-BW7SYNBA.js.map +1 -0
  25. package/dist/Spreadsheet-UZMNMLZH.js +6 -0
  26. package/dist/{Spreadsheet-2ZWIDCBD.js.map → Spreadsheet-UZMNMLZH.js.map} +1 -1
  27. package/dist/{Weather-G7GAZWKB.js → Weather-R6ULA547.js} +4 -4
  28. package/dist/{Weather-G7GAZWKB.js.map → Weather-R6ULA547.js.map} +1 -1
  29. package/dist/{WorldClock-H3TAHY3V.js → WorldClock-HHIBQXUR.js} +4 -5
  30. package/dist/WorldClock-HHIBQXUR.js.map +1 -0
  31. package/dist/apps/index.js +21 -21
  32. package/dist/apps/index.js.map +1 -1
  33. package/dist/{chunk-ZIRRB5P2.js → chunk-3T6SQ4UO.js} +36 -15
  34. package/dist/chunk-3T6SQ4UO.js.map +1 -0
  35. package/dist/{chunk-EIMG6KP7.js → chunk-CDSFAXIS.js} +4 -4
  36. package/dist/{chunk-EIMG6KP7.js.map → chunk-CDSFAXIS.js.map} +1 -1
  37. package/dist/{chunk-VIUW7IPZ.js → chunk-KJ5664G7.js} +3 -3
  38. package/dist/{chunk-VIUW7IPZ.js.map → chunk-KJ5664G7.js.map} +1 -1
  39. package/dist/{chunk-U7XDTOFD.js → chunk-LWVRQWGV.js} +3 -3
  40. package/dist/{chunk-U7XDTOFD.js.map → chunk-LWVRQWGV.js.map} +1 -1
  41. package/dist/{chunk-QWQHSHAX.js → chunk-SUUADOG6.js} +4 -4
  42. package/dist/{chunk-QWQHSHAX.js.map → chunk-SUUADOG6.js.map} +1 -1
  43. package/dist/{chunk-OMCRYSXD.js → chunk-ZETQWO2W.js} +3 -3
  44. package/dist/{chunk-OMCRYSXD.js.map → chunk-ZETQWO2W.js.map} +1 -1
  45. package/dist/index.d.ts +42 -1
  46. package/dist/index.js +172 -16
  47. package/dist/index.js.map +1 -1
  48. package/package.json +1 -1
  49. package/dist/Files-JUWNFKSF.js +0 -11
  50. package/dist/Preview-HDHGK3QA.js +0 -8
  51. package/dist/Sidebar-Q3PRJ2FP.js.map +0 -1
  52. package/dist/Spreadsheet-2ZWIDCBD.js +0 -6
  53. package/dist/WorldClock-H3TAHY3V.js.map +0 -1
  54. package/dist/chunk-ZIRRB5P2.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -131,6 +131,27 @@ declare function setWindowDefaultPosition(key: string, pos: {
131
131
  w: number;
132
132
  h: number;
133
133
  }): void;
134
+ /** Read the saved box for a window key (viewport-relative px), or null. */
135
+ declare function getWindowPosition(key: string): {
136
+ x: number;
137
+ y: number;
138
+ w: number;
139
+ h: number;
140
+ } | null;
141
+ /**
142
+ * Force a window's saved position — unlike `setWindowDefaultPosition` this
143
+ * overwrites any existing entry. Use when the consumer wants to deliberately
144
+ * (re)place a window, e.g. the Widget Manager dropping a freshly-added widget
145
+ * into a tidy top-left slot regardless of where it last sat. For `autoHeight`
146
+ * windows the `h` here is only a first-paint placeholder — the window
147
+ * re-measures its content height on open.
148
+ */
149
+ declare function setWindowPosition(key: string, pos: {
150
+ x: number;
151
+ y: number;
152
+ w: number;
153
+ h: number;
154
+ }): void;
134
155
  interface ModalProps {
135
156
  open: boolean;
136
157
  onClose: () => void;
@@ -801,6 +822,26 @@ interface StartMenuProps {
801
822
  }
802
823
  declare function StartMenu({ open, onClose, openPage, profile, user, onLogout, taskbarPosition, taskbarH, taskbarW, size, navSections, navIcons, sectionIcons, categories, }: StartMenuProps): react_jsx_runtime.JSX.Element | null;
803
824
 
825
+ /**
826
+ * Widget gallery — the "manage widgets on the desktop" surface.
827
+ *
828
+ * Enumerates every widget-flagged page in the live window registry (so it
829
+ * automatically lists whatever the consumer registered, not just the bundled
830
+ * five) and cross-references the window manager's `openWindows` to know which
831
+ * are currently sitting on the desktop. Adding a widget calls `openPage`
832
+ * (which drops the chrome-less panel onto the desktop and persists it via the
833
+ * normal open-windows session store); removing one calls `closeEntity` on the
834
+ * live window. No new persistence layer — it drives the same plumbing the
835
+ * Start Menu already uses.
836
+ *
837
+ * Surfaced from the desktop right-click menu ("Manage Widgets…") and exported
838
+ * so a consumer can also register it as a window or wire it to a tray button.
839
+ */
840
+ declare function WidgetManager({ open, onClose }: {
841
+ open: boolean;
842
+ onClose: () => void;
843
+ }): react_jsx_runtime.JSX.Element | null;
844
+
804
845
  /** Sections that can be omitted from the inline Customization page when the
805
846
  * consumer renders them elsewhere (e.g. as separate entries in SystemPreferences). */
806
847
  type CustomizationOmitSection = 'behavior' | 'desktop';
@@ -1268,4 +1309,4 @@ declare function useNewHotkey(callback: () => void): void;
1268
1309
  */
1269
1310
  declare function useEditHotkey(callback: (() => void) | null): void;
1270
1311
 
1271
- export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, type BugReport, type BugReportConfig, BugReportConfigProvider, BugReportDetail, type BugReportExtraField, type BugReportExtraSelectField, BugReportProvider, type BugReportSubmission, type BugReportSubmitPayload, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CancelButton, type CellStyle, type ChangelogEntry, type ColumnDef, ConfirmProvider, CopyButton, Customization, type CustomizationOmitSection, type CustomizationProps, Desktop, type DesktopHostConfig, DesktopHostProvider, DocFavStar, ENTER, EditableGrid, type EditableGridProps, type EntityFetcher, EntityList, type EntityListColumn, type EntityListProps, GLASS_DIVIDER, GLASS_INPUT_BG, GlobalSearch, type GridColumn, HelpCenter, type HelpCenterDoc, type HelpCenterProps, Layout, type LayoutProps, ListFooter, type LoginPayload, MOD, type MailCapabilities, MailConnectModal, type MailUser, Markdown, type MarkdownProps, Modal, ModalActions, NotificationBell, type NotificationsConfig, type PaginatedResponse, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, type ReportType, ResizableTable, SHIFT, type SearchConfig, type SearchProvider, type SearchResult, type SemanticGroup, type ShellAuth, ShellAuthProvider, ShellEntityFetcherProvider, type ShellNotification, type ShellPrefsAdapter, ShellPrefsProvider, ShortcutHelp, type SortState, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, type StickyEntityRef, type StickyResolver, SystemPreferences, type SystemPreferencesProps, type SystemPreferencesSection, VERSION, WindowManagerProvider, WindowRegistry, WindowTitle, commitExposeHighlight, confirm, confirmDestructive, createWindowRegistry, exitExposeMode, formatDate, getActiveWindowRoute, getExposeHighlight, glassStyle, isMac, openBugReportDialog, prompt, reportBug, setExposeHighlight, setShellApiClient, setShellAuthBridge, setShellMailServer, setShellNavIcons, setWindowDefaultPosition, subscribeExposeHighlight, toast, toggleExposeMode, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useLocalStoragePrefs, useMailAuth, useModalActive, useNewHotkey, useShellAuth, useShellEntityFetcher, useShellPrefs, useSort, useTableNav, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
1312
+ export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, type BugReport, type BugReportConfig, BugReportConfigProvider, BugReportDetail, type BugReportExtraField, type BugReportExtraSelectField, BugReportProvider, type BugReportSubmission, type BugReportSubmitPayload, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CancelButton, type CellStyle, type ChangelogEntry, type ColumnDef, ConfirmProvider, CopyButton, Customization, type CustomizationOmitSection, type CustomizationProps, Desktop, type DesktopHostConfig, DesktopHostProvider, DocFavStar, ENTER, EditableGrid, type EditableGridProps, type EntityFetcher, EntityList, type EntityListColumn, type EntityListProps, GLASS_DIVIDER, GLASS_INPUT_BG, GlobalSearch, type GridColumn, HelpCenter, type HelpCenterDoc, type HelpCenterProps, Layout, type LayoutProps, ListFooter, type LoginPayload, MOD, type MailCapabilities, MailConnectModal, type MailUser, Markdown, type MarkdownProps, Modal, ModalActions, NotificationBell, type NotificationsConfig, type PaginatedResponse, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, type ReportType, ResizableTable, SHIFT, type SearchConfig, type SearchProvider, type SearchResult, type SemanticGroup, type ShellAuth, ShellAuthProvider, ShellEntityFetcherProvider, type ShellNotification, type ShellPrefsAdapter, ShellPrefsProvider, ShortcutHelp, type SortState, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, type StickyEntityRef, type StickyResolver, SystemPreferences, type SystemPreferencesProps, type SystemPreferencesSection, VERSION, WidgetManager, WindowManagerProvider, WindowRegistry, WindowTitle, commitExposeHighlight, confirm, confirmDestructive, createWindowRegistry, exitExposeMode, formatDate, getActiveWindowRoute, getExposeHighlight, getWindowPosition, glassStyle, isMac, openBugReportDialog, prompt, reportBug, setExposeHighlight, setShellApiClient, setShellAuthBridge, setShellMailServer, setShellNavIcons, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toast, toggleExposeMode, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useLocalStoragePrefs, useMailAuth, useModalActive, useNewHotkey, useShellAuth, useShellEntityFetcher, useShellPrefs, useSort, useTableNav, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
package/dist/index.js CHANGED
@@ -6,15 +6,15 @@ export { setShellMailServer, useMailAuth } from './chunk-VBFB3ZIN.js';
6
6
  import { subscribePomo, getPomoSnapshot } from './chunk-MK3HLUO4.js';
7
7
  import { useShellPrefs } from './chunk-36VM54SC.js';
8
8
  export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
9
- import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-QWQHSHAX.js';
9
+ import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-SUUADOG6.js';
10
10
  import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, setSoundForType, previewSound, setAllSounds, playLogout } from './chunk-D7PYW2QS.js';
11
- import { setPdfPreview } from './chunk-VIUW7IPZ.js';
11
+ import { setPdfPreview } from './chunk-KJ5664G7.js';
12
12
  import './chunk-KUIPWCTJ.js';
13
13
  import { toast_default } from './chunk-WIJ45SYD.js';
14
14
  export { toast_default as toast } from './chunk-WIJ45SYD.js';
15
- export { EditableGrid } from './chunk-OMCRYSXD.js';
16
- import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, ModalActions, useIsMobile, useModalActive, client_default, LoadingSpinner, WINDOW_REGISTRY, isPageEntry, ThumbCard, activateModal } from './chunk-ZIRRB5P2.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-ZIRRB5P2.js';
15
+ export { EditableGrid } from './chunk-ZETQWO2W.js';
16
+ import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, WINDOW_REGISTRY, isPageEntry, ModalActions, useIsMobile, useModalActive, client_default, LoadingSpinner, setWindowPosition, ThumbCard, activateModal } from './chunk-3T6SQ4UO.js';
17
+ export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-3T6SQ4UO.js';
18
18
  import { confirm } from './chunk-UBN4IUDE.js';
19
19
  export { ConfirmProvider, confirm, confirmDestructive, prompt } from './chunk-UBN4IUDE.js';
20
20
  import { useAuth, useShellAuth } from './chunk-ADJ3CERD.js';
@@ -1219,9 +1219,159 @@ function StatusBadge({ status }) {
1219
1219
  const label = status.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
1220
1220
  return /* @__PURE__ */ jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${color}`, children: label });
1221
1221
  }
1222
+ function FallbackIcon() {
1223
+ return /* @__PURE__ */ jsxs("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: [
1224
+ /* @__PURE__ */ jsx("rect", { x: "3.5", y: "3.5", width: "7", height: "7", rx: "1.5" }),
1225
+ /* @__PURE__ */ jsx("rect", { x: "13.5", y: "3.5", width: "7", height: "7", rx: "1.5" }),
1226
+ /* @__PURE__ */ jsx("rect", { x: "3.5", y: "13.5", width: "7", height: "7", rx: "1.5" }),
1227
+ /* @__PURE__ */ jsx("rect", { x: "13.5", y: "13.5", width: "7", height: "7", rx: "1.5" })
1228
+ ] });
1229
+ }
1230
+ function widgetIcon(entry, route) {
1231
+ const icon = navIcons[entry.icon ?? route];
1232
+ if (icon && isValidElement(icon)) {
1233
+ return cloneElement(icon, { className: "h-5 w-5" });
1234
+ }
1235
+ return /* @__PURE__ */ jsx(FallbackIcon, {});
1236
+ }
1237
+ function WidgetManager({ open, onClose }) {
1238
+ const { openWindows, openPage, closeEntity } = useWindowManager();
1239
+ const widgets = useMemo(() => {
1240
+ if (!open) return [];
1241
+ return Object.entries(WINDOW_REGISTRY).filter(([, e]) => isPageEntry(e) && e.widget).map(([route, e]) => ({ route, label: e.label, entry: e })).sort((a, b) => a.label.localeCompare(b.label));
1242
+ }, [open]);
1243
+ if (!open) return null;
1244
+ const activeByRoute = new Map(openWindows.filter((w) => w.route).map((w) => [w.route, w]));
1245
+ const isActive = (route) => activeByRoute.has(route);
1246
+ const PAD = 20, GAP = 16;
1247
+ const workArea = () => {
1248
+ const cs = getComputedStyle(document.documentElement);
1249
+ const tbH = parseInt(cs.getPropertyValue("--taskbar-height")) || 0;
1250
+ const tbW = parseInt(cs.getPropertyValue("--taskbar-width")) || 0;
1251
+ const tbPos = cs.getPropertyValue("--taskbar-position").trim() || "bottom";
1252
+ const sidebarW = parseInt(cs.getPropertyValue("--sidebar-width")) || 0;
1253
+ return {
1254
+ leftOffset: (tbPos === "left" ? tbW : 0) + sidebarW + PAD,
1255
+ topOffset: (tbPos === "top" ? tbH : 0) + PAD,
1256
+ maxBottom: window.innerHeight - (tbPos === "bottom" ? tbH : 0) - PAD
1257
+ };
1258
+ };
1259
+ const liveWidgetRects = () => [...document.querySelectorAll("[data-modal-panel][data-widget]")].map((el) => {
1260
+ const r = el.getBoundingClientRect();
1261
+ return { x: r.left, y: r.top, w: r.width, h: r.height };
1262
+ }).filter((r) => r.w > 0 && r.h > 0);
1263
+ const computeSlot = (occupied, w, h) => {
1264
+ const { leftOffset, topOffset, maxBottom } = workArea();
1265
+ const rightLimit = window.innerWidth - PAD;
1266
+ const lowestInColumn = (colX) => {
1267
+ const ov = occupied.filter((r) => r.x < colX + w && r.x + r.w > colX);
1268
+ return ov.length ? Math.max(...ov.map((r) => r.y + r.h)) + GAP : topOffset;
1269
+ };
1270
+ let x = leftOffset, y = lowestInColumn(x), guard = 0;
1271
+ while (y + h > maxBottom && x + (w + GAP) + w <= rightLimit && guard < 12) {
1272
+ x += w + GAP;
1273
+ y = lowestInColumn(x);
1274
+ guard++;
1275
+ }
1276
+ return { x, y };
1277
+ };
1278
+ const dimsFor = (route) => {
1279
+ const e = WINDOW_REGISTRY[route];
1280
+ return { w: e?.dimensions?.[0] ?? 320, h: e?.dimensions?.[1] ?? 240, auto: !!e?.autoHeight };
1281
+ };
1282
+ const placeAndOpen = (route) => {
1283
+ const { w, h, auto } = dimsFor(route);
1284
+ const selfH = auto ? Math.min(h, 160) : h;
1285
+ const { x, y } = computeSlot(liveWidgetRects(), w, selfH);
1286
+ setWindowPosition(`page:${route}`, { x, y, w, h });
1287
+ openPage(route);
1288
+ };
1289
+ const waitForWidget = (route) => new Promise((resolve) => {
1290
+ const sel = `[data-modal-panel][data-window-key="page:${route}"]`;
1291
+ let n = 0;
1292
+ const tick = () => {
1293
+ const el = document.querySelector(sel);
1294
+ if (el && el.getBoundingClientRect().height > 40 || n++ > 30) resolve();
1295
+ else setTimeout(tick, 30);
1296
+ };
1297
+ setTimeout(tick, 30);
1298
+ });
1299
+ const add = (route) => {
1300
+ if (!isActive(route)) placeAndOpen(route);
1301
+ };
1302
+ const remove = (route) => {
1303
+ const w = activeByRoute.get(route);
1304
+ if (w) closeEntity(w.id);
1305
+ };
1306
+ const toggle = (route) => {
1307
+ isActive(route) ? remove(route) : add(route);
1308
+ };
1309
+ const activeCount = widgets.reduce((n, w) => n + (isActive(w.route) ? 1 : 0), 0);
1310
+ const allActive = widgets.length > 0 && activeCount === widgets.length;
1311
+ const addAll = async () => {
1312
+ for (const w of widgets) {
1313
+ if (isActive(w.route)) continue;
1314
+ placeAndOpen(w.route);
1315
+ await waitForWidget(w.route);
1316
+ }
1317
+ };
1318
+ const removeAll = () => widgets.forEach((w) => remove(w.route));
1319
+ const widgetGlyph = /* @__PURE__ */ jsxs("svg", { className: "h-5 w-5 text-blue-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: [
1320
+ /* @__PURE__ */ jsx("rect", { x: "3.5", y: "3.5", width: "7", height: "7", rx: "1.5" }),
1321
+ /* @__PURE__ */ jsx("rect", { x: "13.5", y: "3.5", width: "7", height: "7", rx: "1.5" }),
1322
+ /* @__PURE__ */ jsx("rect", { x: "3.5", y: "13.5", width: "7", height: "7", rx: "1.5" }),
1323
+ /* @__PURE__ */ jsx("rect", { x: "13.5", y: "13.5", width: "7", height: "7", rx: "1.5" })
1324
+ ] });
1325
+ return /* @__PURE__ */ jsx(Modal, { open, onClose, title: "Widgets", icon: widgetGlyph, size: "md", compact: true, dimensions: [480, 560], children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
1326
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-1 pb-3", children: [
1327
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: widgets.length === 0 ? "No widgets available" : /* @__PURE__ */ jsxs(Fragment, { children: [
1328
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-gray-700", children: activeCount }),
1329
+ " of ",
1330
+ widgets.length,
1331
+ " on your desktop"
1332
+ ] }) }),
1333
+ widgets.length > 0 && /* @__PURE__ */ jsx(
1334
+ "button",
1335
+ {
1336
+ onClick: allActive ? removeAll : addAll,
1337
+ className: "text-xs font-medium text-blue-600 hover:text-blue-700 hover:underline",
1338
+ children: allActive ? "Remove all" : "Add all"
1339
+ }
1340
+ )
1341
+ ] }),
1342
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto -mx-1 px-1", children: widgets.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center text-center py-12 text-gray-400", children: [
1343
+ /* @__PURE__ */ jsx("div", { className: "opacity-60 mb-2", children: widgetGlyph }),
1344
+ /* @__PURE__ */ jsx("p", { className: "text-sm", children: "No widgets are registered." }),
1345
+ /* @__PURE__ */ jsx("p", { className: "text-xs mt-1", children: "Widgets like Weather, Currency, and the Pomodoro timer appear here once available." })
1346
+ ] }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-2", children: widgets.map(({ route, label, entry }) => {
1347
+ const active = isActive(route);
1348
+ return /* @__PURE__ */ jsxs(
1349
+ "button",
1350
+ {
1351
+ onClick: () => toggle(route),
1352
+ title: active ? `Remove ${label} from desktop` : `Add ${label} to desktop`,
1353
+ className: `group relative flex items-center gap-3 rounded-xl border p-3 text-left transition-colors ${active ? "border-blue-300 bg-blue-50/70 hover:bg-blue-50" : "border-gray-200 bg-white/60 hover:border-gray-300 hover:bg-gray-50"}`,
1354
+ children: [
1355
+ /* @__PURE__ */ jsx("span", { className: `shrink-0 flex items-center justify-center h-10 w-10 rounded-lg ${active ? "bg-blue-100 text-blue-600" : "bg-gray-100 text-gray-500"}`, children: widgetIcon(entry, route) }),
1356
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
1357
+ /* @__PURE__ */ jsx("span", { className: "block text-sm font-medium text-gray-900 truncate", children: label }),
1358
+ /* @__PURE__ */ jsx("span", { className: `block text-[11px] ${active ? "text-blue-600" : "text-gray-400"}`, children: active ? "On desktop" : "Available" })
1359
+ ] }),
1360
+ /* @__PURE__ */ jsx("span", { className: `shrink-0 inline-flex items-center justify-center h-6 w-6 rounded-full border transition-colors ${active ? "border-blue-500 bg-blue-500 text-white group-hover:border-red-400 group-hover:bg-red-400" : "border-gray-300 text-gray-400 group-hover:border-blue-400 group-hover:text-blue-500"}`, children: active ? /* @__PURE__ */ jsxs(Fragment, { children: [
1361
+ /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5 group-hover:hidden", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M4.5 12.75l6 6 9-13.5" }) }),
1362
+ /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5 hidden group-hover:block", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) })
1363
+ ] }) : /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4.5v15m7.5-7.5h-15" }) }) })
1364
+ ]
1365
+ },
1366
+ route
1367
+ );
1368
+ }) }) }),
1369
+ /* @__PURE__ */ jsx("p", { className: "shrink-0 pt-3 mt-1 border-t border-gray-100 text-[11px] text-gray-400 leading-relaxed", children: "Drag a widget anywhere on the desktop to reposition it. Right-click a widget for its appearance settings." })
1370
+ ] }) });
1371
+ }
1222
1372
 
1223
1373
  // src/version.ts
1224
- var VERSION = "0.6.9" ;
1374
+ var VERSION = "0.7.1" ;
1225
1375
  var APP_VERSION = VERSION;
1226
1376
 
1227
1377
  // src/changelog.ts
@@ -1708,6 +1858,7 @@ function Desktop({ profile }) {
1708
1858
  const [openFolder, setOpenFolder] = useState(null);
1709
1859
  const [aboutOpen, setAboutOpen] = useState(false);
1710
1860
  const [whatsNewOpen, setWhatsNewOpen] = useState(false);
1861
+ const [widgetsOpen, setWidgetsOpen] = useState(false);
1711
1862
  const [renamingFolder, setRenamingFolder] = useState(null);
1712
1863
  const [renameValue, setRenameValue] = useState("");
1713
1864
  const [editingStickyId, setEditingStickyId] = useState(null);
@@ -2526,6 +2677,18 @@ function Desktop({ profile }) {
2526
2677
  /* @__PURE__ */ jsx("svg", { className: "h-4 w-4 text-gray-400", 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.25V6zM3.75 15.75A2.25 2.25 0 016 13.5h2.25a2.25 2.25 0 012.25 2.25V18a2.25 2.25 0 01-2.25 2.25H6A2.25 2.25 0 013.75 18v-2.25zM13.5 6a2.25 2.25 0 012.25-2.25H18A2.25 2.25 0 0120.25 6v2.25A2.25 2.25 0 0118 10.5h-2.25a2.25 2.25 0 01-2.25-2.25V6zM13.5 15.75a2.25 2.25 0 012.25-2.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-2.25A2.25 2.25 0 0113.5 18v-2.25z" }) }),
2527
2678
  "Snap to Grid"
2528
2679
  ] }),
2680
+ /* @__PURE__ */ jsxs(PopupMenuItem, { onClick: () => {
2681
+ setContextMenu(null);
2682
+ setWidgetsOpen(true);
2683
+ }, children: [
2684
+ /* @__PURE__ */ jsxs("svg", { className: "h-4 w-4 text-blue-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: [
2685
+ /* @__PURE__ */ jsx("rect", { x: "3.5", y: "3.5", width: "7", height: "7", rx: "1.5" }),
2686
+ /* @__PURE__ */ jsx("rect", { x: "13.5", y: "3.5", width: "7", height: "7", rx: "1.5" }),
2687
+ /* @__PURE__ */ jsx("rect", { x: "3.5", y: "13.5", width: "7", height: "7", rx: "1.5" }),
2688
+ /* @__PURE__ */ jsx("rect", { x: "13.5", y: "13.5", width: "7", height: "7", rx: "1.5" })
2689
+ ] }),
2690
+ "Manage Widgets\u2026"
2691
+ ] }),
2529
2692
  /* @__PURE__ */ jsx(PopupMenuDivider, {}),
2530
2693
  /* @__PURE__ */ jsxs(PopupMenuItem, { onClick: () => {
2531
2694
  setContextMenu(null);
@@ -2644,6 +2807,7 @@ function Desktop({ profile }) {
2644
2807
  }
2645
2808
  );
2646
2809
  })(),
2810
+ /* @__PURE__ */ jsx(WidgetManager, { open: widgetsOpen, onClose: () => setWidgetsOpen(false) }),
2647
2811
  aboutOpen && (() => {
2648
2812
  const version = host.productVersion ?? APP_VERSION;
2649
2813
  return /* @__PURE__ */ jsx(Modal, { open: true, onClose: () => setAboutOpen(false), title: `About ${host.productName ?? "this app"}`, size: "sm", bodyScroll: false, compact: true, dimensions: [340, 420], children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
@@ -3510,10 +3674,6 @@ function StartMenu({
3510
3674
  ),
3511
3675
  item.dividerAfter && /* @__PURE__ */ jsx("div", { className: "border-t border-white/20 my-1.5 mx-2" })
3512
3676
  ] }, item.to)),
3513
- /* @__PURE__ */ jsxs("button", { onClick: () => handleClick("/notifications"), className: `${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`, children: [
3514
- /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", 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" }) }),
3515
- /* @__PURE__ */ jsx("span", { children: "Notifications" })
3516
- ] }),
3517
3677
  systemSections.map((s) => renderSection(s, false)),
3518
3678
  virtualSections.map((v) => renderVirtualSection(v))
3519
3679
  ] }),
@@ -3532,10 +3692,6 @@ function StartMenu({
3532
3692
  ),
3533
3693
  item.dividerAfter && /* @__PURE__ */ jsx("div", { className: "border-t border-white/20 my-1.5 mx-2" })
3534
3694
  ] }, item.to)),
3535
- /* @__PURE__ */ jsxs("button", { onClick: () => handleClick("/notifications"), className: `${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`, children: [
3536
- /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", 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" }) }),
3537
- /* @__PURE__ */ jsx("span", { children: "Notifications" })
3538
- ] }),
3539
3695
  systemSections.map((s) => renderSection(s, false)),
3540
3696
  virtualSections.map((v) => renderVirtualSection(v)),
3541
3697
  /* @__PURE__ */ jsx("div", { className: "border-t border-white/20 my-1.5 mx-2" }),
@@ -4443,7 +4599,7 @@ function MobileBottomNav({
4443
4599
  }
4444
4600
  );
4445
4601
  }
4446
- var Sidebar = lazy(() => import('./Sidebar-Q3PRJ2FP.js'));
4602
+ var Sidebar = lazy(() => import('./Sidebar-BW7SYNBA.js'));
4447
4603
  function useFavorites(wallpapers) {
4448
4604
  const { prefs, save } = useShellPrefs();
4449
4605
  const favorites = prefs.favorite_pages || [];
@@ -6447,6 +6603,6 @@ function useEditHotkey(callback) {
6447
6603
  }, [callback, isActive]);
6448
6604
  }
6449
6605
 
6450
- export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, BugReportConfigProvider, BugReportDetail, BugReportProvider, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Customization, Desktop, DesktopHostProvider, ENTER, EntityList, GlobalSearch, HelpCenter, Layout, ListFooter, MOD, MailConnectModal, Markdown, NotificationBell, ResizableTable, SHIFT, ShellEntityFetcherProvider, ShortcutHelp, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, SystemPreferences, VERSION, createWindowRegistry, isMac, openBugReportDialog, reportBug, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useSort, useTableNav };
6606
+ export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, BugReportConfigProvider, BugReportDetail, BugReportProvider, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Customization, Desktop, DesktopHostProvider, ENTER, EntityList, GlobalSearch, HelpCenter, Layout, ListFooter, MOD, MailConnectModal, Markdown, NotificationBell, ResizableTable, SHIFT, ShellEntityFetcherProvider, ShortcutHelp, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, SystemPreferences, VERSION, WidgetManager, createWindowRegistry, isMac, openBugReportDialog, reportBug, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useSort, useTableNav };
6451
6607
  //# sourceMappingURL=index.js.map
6452
6608
  //# sourceMappingURL=index.js.map