react-os-shell 4.63.0 → 4.74.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +3 -0
  2. package/dist/{Browser-SPTNLEMR.js → Browser-ZF5X2FON.js} +7 -7
  3. package/dist/{Browser-SPTNLEMR.js.map → Browser-ZF5X2FON.js.map} +1 -1
  4. package/dist/{Calculator-XMOPPCK3.js → Calculator-SA62H5S3.js} +6 -6
  5. package/dist/{Calculator-XMOPPCK3.js.map → Calculator-SA62H5S3.js.map} +1 -1
  6. package/dist/ConfirmDialog-SREDNTIB.js +3 -0
  7. package/dist/{ConfirmDialog-EEH4CWSW.js.map → ConfirmDialog-SREDNTIB.js.map} +1 -1
  8. package/dist/{CurrencyConverter-24HNX6C6.js → CurrencyConverter-BMCRLZLY.js} +6 -6
  9. package/dist/{CurrencyConverter-24HNX6C6.js.map → CurrencyConverter-BMCRLZLY.js.map} +1 -1
  10. package/dist/{Documents-GMRVVCH7.js → Documents-2TGJPV2Y.js} +8 -8
  11. package/dist/{Documents-GMRVVCH7.js.map → Documents-2TGJPV2Y.js.map} +1 -1
  12. package/dist/{Files-ITH4SVML.js → Files-Z3ONKUA6.js} +9 -9
  13. package/dist/{Files-ITH4SVML.js.map → Files-Z3ONKUA6.js.map} +1 -1
  14. package/dist/{Notepad-GE5P55TL.js → Notepad-JWZS5YKJ.js} +8 -8
  15. package/dist/{Notepad-GE5P55TL.js.map → Notepad-JWZS5YKJ.js.map} +1 -1
  16. package/dist/{PomodoroTimer-ER5STVKM.js → PomodoroTimer-DRM5W25H.js} +8 -8
  17. package/dist/{PomodoroTimer-ER5STVKM.js.map → PomodoroTimer-DRM5W25H.js.map} +1 -1
  18. package/dist/{Preview-UXVDXCDJ.js → Preview-7O7W7OMQ.js} +9 -9
  19. package/dist/{Preview-UXVDXCDJ.js.map → Preview-7O7W7OMQ.js.map} +1 -1
  20. package/dist/{Spreadsheet-B32JQVX4.js → Spreadsheet-CLTZSW3T.js} +7 -7
  21. package/dist/{Spreadsheet-B32JQVX4.js.map → Spreadsheet-CLTZSW3T.js.map} +1 -1
  22. package/dist/{Stock-FSFPFDQT.js → Stock-CO5N3N2M.js} +6 -6
  23. package/dist/{Stock-FSFPFDQT.js.map → Stock-CO5N3N2M.js.map} +1 -1
  24. package/dist/{Weather-HXOERJJV.js → Weather-IEGJX7RI.js} +6 -6
  25. package/dist/{Weather-HXOERJJV.js.map → Weather-IEGJX7RI.js.map} +1 -1
  26. package/dist/{WorldClock-2FUGLIUZ.js → WorldClock-FLW3QZYG.js} +6 -6
  27. package/dist/{WorldClock-2FUGLIUZ.js.map → WorldClock-FLW3QZYG.js.map} +1 -1
  28. package/dist/apps/index.js +17 -17
  29. package/dist/{chunk-TK6HI2U4.js → chunk-2VM2FRZJ.js} +42 -11
  30. package/dist/chunk-2VM2FRZJ.js.map +1 -0
  31. package/dist/{chunk-ECE3B3FZ.js → chunk-AXWC3332.js} +3 -3
  32. package/dist/{chunk-ECE3B3FZ.js.map → chunk-AXWC3332.js.map} +1 -1
  33. package/dist/{chunk-ZCDFNZQS.js → chunk-BLLINYDD.js} +97 -5
  34. package/dist/chunk-BLLINYDD.js.map +1 -0
  35. package/dist/{chunk-OXLLRKBC.js → chunk-CDR2Q64Q.js} +38 -22
  36. package/dist/chunk-CDR2Q64Q.js.map +1 -0
  37. package/dist/{chunk-TO6ZZHJK.js → chunk-EG3WEQBH.js} +4 -4
  38. package/dist/{chunk-TO6ZZHJK.js.map → chunk-EG3WEQBH.js.map} +1 -1
  39. package/dist/{chunk-JMESET3G.js → chunk-G7IHPEJE.js} +138 -39
  40. package/dist/chunk-G7IHPEJE.js.map +1 -0
  41. package/dist/chunk-NJDH5PHA.js +7 -0
  42. package/dist/{chunk-WCGHIJZR.js.map → chunk-NJDH5PHA.js.map} +1 -1
  43. package/dist/{chunk-LYQVLRWQ.js → chunk-RUAZJ54W.js} +3 -3
  44. package/dist/{chunk-LYQVLRWQ.js.map → chunk-RUAZJ54W.js.map} +1 -1
  45. package/dist/{chunk-CWA27IGB.js → chunk-S6K37RLY.js} +781 -344
  46. package/dist/chunk-S6K37RLY.js.map +1 -0
  47. package/dist/{chunk-IOCOH2QQ.js → chunk-TT2WNTDS.js} +4 -4
  48. package/dist/{chunk-IOCOH2QQ.js.map → chunk-TT2WNTDS.js.map} +1 -1
  49. package/dist/{chunk-3OCL3DB4.js → chunk-TT56U4GY.js} +3 -3
  50. package/dist/{chunk-3OCL3DB4.js.map → chunk-TT56U4GY.js.map} +1 -1
  51. package/dist/{index-Ka32s3Ij.d.ts → index-DVekeidu.d.ts} +258 -27
  52. package/dist/index.d.ts +2 -2
  53. package/dist/index.js +121 -35
  54. package/dist/index.js.map +1 -1
  55. package/dist/ui/index.d.ts +1 -1
  56. package/dist/ui/index.js +5 -5
  57. package/package.json +2 -2
  58. package/dist/ConfirmDialog-EEH4CWSW.js +0 -3
  59. package/dist/chunk-CWA27IGB.js.map +0 -1
  60. package/dist/chunk-JMESET3G.js.map +0 -1
  61. package/dist/chunk-OXLLRKBC.js.map +0 -1
  62. package/dist/chunk-TK6HI2U4.js.map +0 -1
  63. package/dist/chunk-WCGHIJZR.js +0 -7
  64. package/dist/chunk-ZCDFNZQS.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,30 +1,30 @@
1
- import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-3OCL3DB4.js';
2
- import { subscribePomo, getPomoSnapshot } from './chunk-IOCOH2QQ.js';
3
- export { setShellTodoProvider } from './chunk-IOCOH2QQ.js';
4
- export { ImageAnnotator_default as ImageAnnotator } from './chunk-ECE3B3FZ.js';
1
+ import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-TT56U4GY.js';
2
+ import { subscribePomo, getPomoSnapshot } from './chunk-TT2WNTDS.js';
3
+ export { setShellTodoProvider } from './chunk-TT2WNTDS.js';
4
+ export { ImageAnnotator_default as ImageAnnotator } from './chunk-AXWC3332.js';
5
5
  import { publishDesktopFolders, requestFilesTrashView, FolderGlyph, requestFilesDesktopFolderView, FileIconTile } from './chunk-OQ7GRU7G.js';
6
6
  import './chunk-4SQU5YV6.js';
7
7
  import { setPdfPreview } from './chunk-BV6SQ46N.js';
8
- import { CMD_K, CMD_DOT, SHIFT, MOD, ENTER, CMD_A, ALT_SHIFT_N, ALT_SHIFT_E, CMD_ENTER, CMD_S, ALT_SHIFT_D, CMD_Z, CMD_SHIFT_Z, formatDate, useTheme, GlobalSearch, resolveTheme, useClickOutside, ListLoadError, ListFooter, firstEnabledIndex, Button_default, FormField, Input_default, applyThemePrefs, lastEnabledIndex, nextEnabledIndex, matchTypeahead } from './chunk-CWA27IGB.js';
9
- export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, Accordion, AuthScreen, Avatar, AvatarGroup, Banner, BarChart, Button_default as Button, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Card, ChatTemplate, Checkbox_default as Checkbox, CheckoutTemplate, ColoredBadge, ContainerFillChart, CountBadge, DashboardTemplate, DataTable, DataTablePage, DatePicker_default as DatePicker, DateRangePicker, DateTimePicker_default as DateTimePicker, DescriptionList, Divider, DonutChart, Drawer, DropdownMenu, ENTER, EmailTemplate, EmptyState, ErrorBoundary, ErrorPage, FilePicker, FormField, FormLayoutPage, GROUP_COLORS, GalleryTemplate, GlobalSearch, Grid, HelpCenter, INPUT_BASE, INPUT_SIZES, IconButton_default as IconButton, Inline, Input_default as Input, InputNumber_default as InputNumber, Kanban, Label, LineChart, ListFooter, ListLoadError, LoadingSpinner, MAX_FRACTION_DIGITS, MOD, Markdown, MediaUploadField, MediaUploadGrid, MetricBar, MilestoneTimeline, NativeSelect, NumericKeypad, PageHeader, Pagination, Paragraph, Radio_default as Radio, Result, SHIFT, SearchableSelect, Segmented, Select_default as Select, SidebarActionButton, SidebarGroupLabel, SidebarNavItem, Skeleton, Sparkline, Stack, StatCard, Statistic, StatusBadge, StatusBadgeProvider, Stepper, Switch_default as Switch, Tabs, TagInput, Text, Textarea_default as Textarea, TileButton_default as TileButton, TimePicker_default as TimePicker, Title, Tooltip, TopNav, appendKey, applyThemePrefs, backspace, formatDate, inputClasses, isMac, isSeverityTone, mediaFileName, resolveTheme, severityOf, tabButtonId, tabPanelId, toISODate, useClickOutside, useTheme } from './chunk-CWA27IGB.js';
8
+ import { CMD_K, CMD_DOT, SHIFT, MOD, ENTER, CMD_A, ALT_SHIFT_N, ALT_SHIFT_E, CMD_ENTER, CMD_S, ALT_SHIFT_D, CMD_Z, CMD_SHIFT_Z, formatDate, useTheme, GlobalSearch, resolveTheme, useClickOutside, ListLoadError, ListFooter, firstEnabledIndex, Button_default, FormField, Input_default, applyThemePrefs, lastEnabledIndex, nextEnabledIndex, matchTypeahead } from './chunk-S6K37RLY.js';
9
+ export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, Accordion, AuthScreen, Avatar, AvatarGroup, Banner, BarChart, Button_default as Button, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Calendar, Card, ChatTemplate, Checkbox_default as Checkbox, CheckoutTemplate, ColoredBadge, ContainerFillChart, CountBadge, DashboardTemplate, DataTable, DataTablePage, DatePicker_default as DatePicker, DateRangePicker, DateTimePicker_default as DateTimePicker, DescriptionList, Divider, DonutChart, Drawer, DropdownMenu, ENTER, EmailTemplate, EmptyState, ErrorBoundary, ErrorPage, FilePicker, FormErrorSummary, FormField, FormLayoutPage, GROUP_COLORS, GalleryTemplate, GlobalSearch, Grid, HelpCenter, INPUT_BASE, INPUT_SIZES, IconButton_default as IconButton, Inline, Input_default as Input, InputNumber_default as InputNumber, Kanban, Label, LineChart, ListFooter, ListLoadError, LoadingSpinner, MAX_FRACTION_DIGITS, MOD, Markdown, MediaUploadField, MediaUploadGrid, MetricBar, MilestoneTimeline, NativeSelect, NumericKeypad, PageHeader, Pagination, Paragraph, Radio_default as Radio, Result, SHIFT, SearchableSelect, Segmented, Select_default as Select, SidebarActionButton, SidebarGroupLabel, SidebarNavItem, Skeleton, Sparkline, Stack, StatCard, Statistic, StatusBadge, StatusBadgeProvider, Stepper, Switch_default as Switch, Tabs, TagInput, Text, Textarea_default as Textarea, TileButton_default as TileButton, TimePicker_default as TimePicker, Title, Tooltip, TopNav, appendKey, applyThemePrefs, backspace, formatDate, fromKey as fromDateKey, inputClasses, isMac, isSeverityTone, mediaFileName, resolveTheme, severityOf, tabButtonId, tabPanelId, toKey as toDateKey, toISODate, useClickOutside, useTheme } from './chunk-S6K37RLY.js';
10
10
  export { Breadcrumbs } from './chunk-HNH7FOYB.js';
11
11
  import { withSpareRow, EditableGrid } from './chunk-DC6BYGZ6.js';
12
12
  export { EditableGrid } from './chunk-DC6BYGZ6.js';
13
13
  import { SidebarLayout } from './chunk-YG45DAUT.js';
14
14
  export { SidebarLayout } from './chunk-YG45DAUT.js';
15
- import { toast_default } from './chunk-TK6HI2U4.js';
16
- export { toast_default as toast } from './chunk-TK6HI2U4.js';
17
- import { APP_VERSION, VERSION } from './chunk-WCGHIJZR.js';
18
- export { VERSION } from './chunk-WCGHIJZR.js';
15
+ import { toast_default } from './chunk-2VM2FRZJ.js';
16
+ export { toast_default as toast } from './chunk-2VM2FRZJ.js';
17
+ import { APP_VERSION, VERSION } from './chunk-NJDH5PHA.js';
18
+ export { VERSION } from './chunk-NJDH5PHA.js';
19
19
  import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, setSoundForType, previewSound, setAllSounds, playLogout } from './chunk-D7PYW2QS.js';
20
20
  import { useAuth } from './chunk-EWDYCO65.js';
21
21
  export { setShellAuthBridge } from './chunk-EWDYCO65.js';
22
- import { cancelWindowFront, requestWindowFront, useWindowManager, WINDOW_REGISTRY, isPageEntry, Modal, setPerfCollecting, drainPerfEvents, markMenuOpen, SIDEBAR_STRIP_W, forgetMaximizedWindowBoxes, ModalActions, useModalActive, client_default, LoadingSpinner, isShellApiClientConfigured, useUndo, useEnclosingModalId, CancelButton, setWindowPosition } from './chunk-JMESET3G.js';
23
- export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, UndoProvider, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowTitle, beginWindowGesture, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, markMenuOpen, requestWindowFront, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useEnclosingModalId, useIsActiveWindow, useModalActive, useUndo, useUndoable, useUndoableState, useWidgetSettings, useWindowDirty, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-JMESET3G.js';
24
- import { PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, useShellPrefs, useIsMobile } from './chunk-ZCDFNZQS.js';
25
- export { PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ShellPrefsProvider, useIsMobile, useLocalStoragePrefs, useShellPrefs } from './chunk-ZCDFNZQS.js';
26
- import { registerModalEscapeInterceptor } from './chunk-OXLLRKBC.js';
27
- export { ConfirmProvider, Dialog, confirm, confirmDestructive, prompt, registerModalEscapeInterceptor, useConfirm, useFocusTrap, useScrollLock } from './chunk-OXLLRKBC.js';
22
+ import { cancelWindowFront, requestWindowFront, useWindowManager, WINDOW_REGISTRY, isPageEntry, Modal, setPerfCollecting, drainPerfEvents, markMenuOpen, SIDEBAR_STRIP_W, forgetMaximizedWindowBoxes, ModalActions, useModalActive, client_default, LoadingSpinner, isShellApiClientConfigured, useUndo, useEnclosingModalId, CancelButton, setWindowPosition } from './chunk-G7IHPEJE.js';
23
+ export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, UndoProvider, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowTitle, beginWindowGesture, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, markMenuOpen, requestWindowFront, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useEnclosingModalId, useIsActiveWindow, useModalActive, useUndo, useUndoable, useUndoableState, useWidgetSettings, useWindowDirty, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-G7IHPEJE.js';
24
+ import { useShellStrings, useShellPrefs, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, useIsMobile } from './chunk-BLLINYDD.js';
25
+ export { DEFAULT_SHELL_STRINGS, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ShellPrefsProvider, ShellStringsProvider, useIsMobile, useLocalStoragePrefs, useShellPrefs, useShellStrings } from './chunk-BLLINYDD.js';
26
+ import { registerModalEscapeInterceptor } from './chunk-CDR2Q64Q.js';
27
+ export { ConfirmProvider, Dialog, confirm, confirmDestructive, prompt, registerModalEscapeInterceptor, useConfirm, useFocusTrap, useScrollLock } from './chunk-CDR2Q64Q.js';
28
28
  import { startMenuCategories, navVisible, navSections, isSection, navIcons, isReachable, sectionIcons, useShellAuth, visibleChildren } from './chunk-WNLPTLT6.js';
29
29
  export { ShellAuthProvider, setShellNavIcons, useShellAuth } from './chunk-WNLPTLT6.js';
30
30
  import { GLASS_INPUT_BG, glassStyle } from './chunk-3CUSBZWG.js';
@@ -191,6 +191,10 @@ function NotificationBell({
191
191
  popDirection
192
192
  }) {
193
193
  const [open, setOpen] = useState(false);
194
+ const strings = useShellStrings().notifications;
195
+ const { prefs, save: savePrefs } = useShellPrefs();
196
+ const dnd = prefs.notifications_dnd === true;
197
+ const toggleDnd = () => savePrefs({ notifications_dnd: !dnd });
194
198
  const dropdownRef = useRef(null);
195
199
  const buttonRef = useRef(null);
196
200
  const queryClient = useQueryClient();
@@ -237,7 +241,7 @@ function NotificationBell({
237
241
  prevCountRef.current = unreadCount;
238
242
  return;
239
243
  }
240
- if (unreadCount > prevCountRef.current) {
244
+ if (unreadCount > prevCountRef.current && !dnd) {
241
245
  list({ page_size: 1 }).then((data) => {
242
246
  const latest = data?.results?.[0];
243
247
  if (!latest) return;
@@ -259,7 +263,7 @@ function NotificationBell({
259
263
  });
260
264
  }
261
265
  prevCountRef.current = unreadCount;
262
- }, [unreadCount, list, showInlineNotif]);
266
+ }, [unreadCount, list, showInlineNotif, dnd]);
263
267
  const { data: notifData } = useQuery({
264
268
  queryKey: ["notifications-dropdown"],
265
269
  queryFn: () => list({ page_size: 30 }),
@@ -307,25 +311,40 @@ function NotificationBell({
307
311
  "data-menu-toggle": true,
308
312
  onMouseEnter: () => queryClient.prefetchQuery({ queryKey: ["notifications-dropdown"], queryFn: () => list({ page_size: 30 }) }),
309
313
  onClick: () => setOpen((prev) => !prev),
310
- title: "Notifications",
314
+ title: dnd ? strings.dndOn : strings.title,
311
315
  className: "relative shrink-0 rounded-md p-2 text-gray-900 hover:text-black hover:bg-white/20 transition-colors",
312
316
  children: [
313
317
  /* @__PURE__ */ jsx("svg", { className: "h-5 w-5", 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" }) }),
314
- unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute top-0.5 right-0.5 flex h-4 min-w-[16px] items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold text-white", children: unreadCount > 99 ? "99+" : unreadCount })
318
+ unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute top-0.5 right-0.5 flex h-4 min-w-[16px] items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold text-white", children: unreadCount > 99 ? "99+" : unreadCount }),
319
+ dnd && /* A quiet moon on the bell: DND is on. Decorative — the button's
320
+ title and the popover toggle carry the state for AT. */
321
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "absolute bottom-0.5 right-0.5 flex h-3 w-3 items-center justify-center rounded-full bg-indigo-500 text-white", children: /* @__PURE__ */ jsx("svg", { className: "h-2 w-2", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { d: "M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z" }) }) })
315
322
  ]
316
323
  }
317
324
  ),
318
325
  open && createPortal(
319
326
  /* @__PURE__ */ jsxs(PopupMenu, { minWidth: 320, className: "w-80 flex flex-col overflow-hidden", style: { ...dropdownPos }, onClose: () => setOpen(false), children: [
320
- /* @__PURE__ */ jsx(PopupMenuLabel, { children: /* @__PURE__ */ jsxs("span", { className: "flex items-center justify-between w-full", children: [
321
- /* @__PURE__ */ jsx("span", { children: "Notifications" }),
322
- unreadCount > 0 && /* @__PURE__ */ jsx("button", { onClick: handleMarkAllRead, className: "text-[10px] text-blue-600 hover:text-blue-700 font-medium normal-case tracking-normal", children: "Mark all read" })
327
+ /* @__PURE__ */ jsx(PopupMenuLabel, { children: /* @__PURE__ */ jsxs("span", { className: "flex items-center justify-between w-full gap-2", children: [
328
+ /* @__PURE__ */ jsx("span", { children: strings.title }),
329
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
330
+ unreadCount > 0 && /* @__PURE__ */ jsx("button", { onClick: handleMarkAllRead, className: "text-[10px] text-blue-600 hover:text-blue-700 font-medium normal-case tracking-normal", children: strings.markAllRead }),
331
+ /* @__PURE__ */ jsx(
332
+ "button",
333
+ {
334
+ onClick: toggleDnd,
335
+ "aria-pressed": dnd,
336
+ title: strings.dnd,
337
+ className: `rounded p-0.5 transition-colors ${dnd ? "text-indigo-600 bg-indigo-50" : "text-gray-400 hover:text-gray-600"}`,
338
+ children: /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5", fill: dnd ? "currentColor" : "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.8, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z" }) })
339
+ }
340
+ )
341
+ ] })
323
342
  ] }) }),
324
343
  /* @__PURE__ */ jsx(PopupMenuDivider, {}),
325
344
  /* @__PURE__ */ jsx("div", { className: "overflow-y-auto", style: { flex: "1 1 auto", minHeight: 0 }, children: notifications.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-8 px-4 text-center", children: [
326
345
  /* @__PURE__ */ jsx("svg", { className: "h-8 w-8 text-gray-300 mb-2", 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" }) }),
327
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 font-medium", children: "All caught up" }),
328
- /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-400 mt-0.5", children: "No notifications yet" })
346
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-600 font-medium", children: strings.caughtUp }),
347
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-400 mt-0.5", children: strings.empty })
329
348
  ] }) : notifications.map((notif) => /* @__PURE__ */ jsxs(PopupMenuItem, { onClick: () => handleClick(notif), children: [
330
349
  /* @__PURE__ */ jsx("div", { className: "pt-0.5 shrink-0", children: !notif.is_read ? /* @__PURE__ */ jsx("div", { className: "h-2 w-2 rounded-full bg-blue-500" }) : /* @__PURE__ */ jsx("div", { className: "h-2 w-2" }) }),
331
350
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
@@ -345,7 +364,7 @@ function NotificationBell({
345
364
  /* @__PURE__ */ jsx(PopupMenuItem, { onClick: () => {
346
365
  setOpen(false);
347
366
  onViewAll();
348
- }, children: /* @__PURE__ */ jsx("span", { className: "w-full text-center text-xs text-blue-600 font-medium", children: "View all notifications" }) })
367
+ }, children: /* @__PURE__ */ jsx("span", { className: "w-full text-center text-xs text-blue-600 font-medium", children: strings.viewAll }) })
349
368
  ] })
350
369
  ] }),
351
370
  document.body
@@ -365,7 +384,7 @@ function NotificationBell({
365
384
  children: [
366
385
  /* @__PURE__ */ jsx("div", { className: "h-9 w-9 shrink-0 rounded-lg bg-blue-500/15 flex items-center justify-center", children: /* @__PURE__ */ jsx("svg", { className: "h-5 w-5 text-blue-500", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, 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" }) }) }),
367
386
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 max-h-[60vh] overflow-y-auto", children: [
368
- /* @__PURE__ */ jsx("div", { className: "text-[11px] font-semibold uppercase tracking-wide text-blue-600 mb-0.5", children: "Notification" }),
387
+ /* @__PURE__ */ jsx("div", { className: "text-[11px] font-semibold uppercase tracking-wide text-blue-600 mb-0.5", children: strings.cardLabel }),
369
388
  /* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-gray-800 leading-snug break-words", children: inlineNotif.title }),
370
389
  inlineNotif.message && /* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500 leading-snug break-words mt-0.5", children: inlineNotif.message })
371
390
  ] }),
@@ -377,7 +396,7 @@ function NotificationBell({
377
396
  dismissInline();
378
397
  },
379
398
  className: "shrink-0 p-1 -mr-1 -mt-1 text-gray-400 hover:text-gray-600 transition-colors",
380
- "aria-label": "Dismiss notification",
399
+ "aria-label": strings.dismiss,
381
400
  children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) })
382
401
  }
383
402
  )
@@ -1280,6 +1299,7 @@ function useDesktopHost() {
1280
1299
  return useContext(DesktopHostContext);
1281
1300
  }
1282
1301
  function Desktop({ profile }) {
1302
+ const shellStrings = useShellStrings();
1283
1303
  useQueryClient();
1284
1304
  const { openEntity, openPage } = useWindowManager();
1285
1305
  const containerRef = useRef(null);
@@ -2351,8 +2371,9 @@ function Desktop({ profile }) {
2351
2371
  setAboutOpen(true);
2352
2372
  }, children: [
2353
2373
  /* @__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: "M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" }) }),
2354
- "About ",
2355
- host.productName ?? "this app"
2374
+ shellStrings.about.aboutPrefix,
2375
+ " ",
2376
+ host.productName ?? shellStrings.about.thisApp
2356
2377
  ] }),
2357
2378
  host.onReportBug && /* @__PURE__ */ jsxs(Fragment, { children: [
2358
2379
  /* @__PURE__ */ jsx(PopupMenuDivider, {}),
@@ -2391,7 +2412,7 @@ function Desktop({ profile }) {
2391
2412
  /* @__PURE__ */ jsx(WidgetManager, { open: widgetsOpen, onClose: () => setWidgetsOpen(false) }),
2392
2413
  aboutOpen && (() => {
2393
2414
  const version = host.productVersion ?? APP_VERSION;
2394
- 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: [
2415
+ return /* @__PURE__ */ jsx(Modal, { open: true, onClose: () => setAboutOpen(false), title: `${shellStrings.about.aboutPrefix} ${host.productName ?? shellStrings.about.thisApp}`, size: "sm", bodyScroll: false, compact: true, dimensions: [340, 420], children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
2395
2416
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 pt-4 pb-3 w-full", children: [
2396
2417
  /* @__PURE__ */ jsx("img", { src: host.productIcon ?? "/favicon.svg", alt: "", className: "h-16 w-16" }),
2397
2418
  /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
@@ -2401,7 +2422,7 @@ function Desktop({ profile }) {
2401
2422
  ] })
2402
2423
  ] }),
2403
2424
  /* @__PURE__ */ jsxs("div", { className: "py-3 border-t border-gray-200 w-full px-4", children: [
2404
- /* @__PURE__ */ jsx("h3", { className: "text-[10px] font-semibold text-gray-400 uppercase tracking-wide mb-2 text-center", children: "Open Source Licenses" }),
2425
+ /* @__PURE__ */ jsx("h3", { className: "text-[10px] font-semibold text-gray-400 uppercase tracking-wide mb-2 text-center", children: shellStrings.about.openSourceLicenses }),
2405
2426
  /* @__PURE__ */ jsx("div", { className: "max-h-40 overflow-y-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-[11px]", children: [
2406
2427
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "text-gray-500 border-b border-gray-100", children: [
2407
2428
  /* @__PURE__ */ jsx("th", { className: "text-left py-1 font-medium", children: "Package" }),
@@ -2465,7 +2486,7 @@ function Desktop({ profile }) {
2465
2486
  ),
2466
2487
  whatsNewOpen && (() => {
2467
2488
  const entries = host.productChangelog ?? changelog_default;
2468
- return /* @__PURE__ */ jsx(Modal, { open: true, onClose: () => setWhatsNewOpen(false), title: "What's New", size: "md", bodyScroll: false, children: /* @__PURE__ */ jsx("div", { className: "space-y-5 max-h-[60vh] overflow-y-auto px-1", children: entries.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-400 text-center py-6", children: "No changelog available." }) : entries.map((entry, i) => /* @__PURE__ */ jsxs("div", { children: [
2489
+ return /* @__PURE__ */ jsx(Modal, { open: true, onClose: () => setWhatsNewOpen(false), title: shellStrings.about.whatsNew, size: "md", bodyScroll: false, children: /* @__PURE__ */ jsx("div", { className: "space-y-5 max-h-[60vh] overflow-y-auto px-1", children: entries.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-400 text-center py-6", children: shellStrings.about.noChangelog }) : entries.map((entry, i) => /* @__PURE__ */ jsxs("div", { children: [
2469
2490
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-2", children: [
2470
2491
  /* @__PURE__ */ jsx("span", { className: "text-sm font-bold text-gray-900 font-mono", children: entry.version }),
2471
2492
  /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400", children: formatDate(entry.date) })
@@ -2577,6 +2598,7 @@ function StartupAnimation({ onComplete, ready = false, productName = "react-os-s
2577
2598
  }
2578
2599
  function LogoutAnimation({ onComplete, subtitle, logo = "/favicon.svg" }) {
2579
2600
  const [phase, setPhase] = useState("show");
2601
+ const strings = useShellStrings();
2580
2602
  useEffect(() => {
2581
2603
  playLogout();
2582
2604
  const t1 = setTimeout(() => setPhase("out"), 800);
@@ -2614,8 +2636,8 @@ function LogoutAnimation({ onComplete, subtitle, logo = "/favicon.svg" }) {
2614
2636
  }
2615
2637
  ),
2616
2638
  /* @__PURE__ */ jsxs("div", { className: `mt-6 text-center transition-all duration-700 ${phase === "show" ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`, children: [
2617
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-[0.3em] text-white/90 uppercase", children: "Goodbye" }),
2618
- /* @__PURE__ */ jsx("p", { className: "mt-2 text-xs text-white/40", children: "See you next time" })
2639
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold tracking-[0.3em] text-white/90 uppercase", children: strings.logout.goodbye }),
2640
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-xs text-white/40", children: strings.logout.seeYou })
2619
2641
  ] }),
2620
2642
  subtitle && /* @__PURE__ */ jsx("div", { className: `absolute bottom-8 transition-all duration-500 ${phase === "show" ? "opacity-40" : "opacity-0"}`, children: /* @__PURE__ */ jsx("p", { className: "text-[10px] text-white/40 font-mono tracking-wider", children: subtitle }) }),
2621
2643
  /* @__PURE__ */ jsx("style", { children: `
@@ -2636,6 +2658,43 @@ function LogoutAnimation({ onComplete, subtitle, logo = "/favicon.svg" }) {
2636
2658
  }
2637
2659
  );
2638
2660
  }
2661
+ function toSessionRefs(openWindows) {
2662
+ const refs = [];
2663
+ for (const w of openWindows) {
2664
+ if (w.type === "page" && w.route) {
2665
+ refs.push({ type: "page", route: w.route });
2666
+ } else if (w.entityType && w.entityId && w.type !== "part_number") {
2667
+ refs.push({ type: "entity", entityType: w.entityType, entityId: w.entityId, label: w.label, route: w.route });
2668
+ }
2669
+ }
2670
+ return refs;
2671
+ }
2672
+ var SAVE_DEBOUNCE_MS = 800;
2673
+ function SessionWindowRestore() {
2674
+ const { openWindows, openEntity, openPage } = useWindowManager();
2675
+ const { prefs, save } = useShellPrefs();
2676
+ const restoredRef = useRef(false);
2677
+ const saveTimer = useRef(void 0);
2678
+ useEffect(() => {
2679
+ if (restoredRef.current) return;
2680
+ restoredRef.current = true;
2681
+ if (prefs.restore_windows === false) return;
2682
+ if (openWindows.length > 0) return;
2683
+ const saved = Array.isArray(prefs.session_windows) ? prefs.session_windows : [];
2684
+ for (const w of saved) {
2685
+ if (w.type === "page" && w.route) openPage(w.route);
2686
+ else if (w.type === "entity" && w.entityType && w.entityId) openEntity(w.entityType, w.entityId, void 0, w.label, w.route);
2687
+ }
2688
+ }, []);
2689
+ useEffect(() => {
2690
+ if (!restoredRef.current) return;
2691
+ clearTimeout(saveTimer.current);
2692
+ const refs = toSessionRefs(openWindows);
2693
+ saveTimer.current = setTimeout(() => save({ session_windows: refs }), SAVE_DEBOUNCE_MS);
2694
+ return () => clearTimeout(saveTimer.current);
2695
+ }, [openWindows, save]);
2696
+ return null;
2697
+ }
2639
2698
 
2640
2699
  // src/shell/menuPath.ts
2641
2700
  function openMenuLevel(path, depth, anchor) {
@@ -3635,6 +3694,7 @@ function Layout({
3635
3694
  };
3636
3695
  }, [toggleFullscreen]);
3637
3696
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-screen", children: [
3697
+ /* @__PURE__ */ jsx(SessionWindowRestore, {}),
3638
3698
  showStartup && /* @__PURE__ */ jsx(StartupAnimation, { onComplete: () => setShowStartup(false), ready: !!profile, productName: brandName, logo: brandIcon, subtitle: brandTagline }),
3639
3699
  showLogout && /* @__PURE__ */ jsx(LogoutAnimation, { onComplete: () => {
3640
3700
  sessionStorage.removeItem("erp_startup_shown");
@@ -4397,6 +4457,19 @@ function Customization({ omit, section } = {}) {
4397
4457
  /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-700", children: "Enter full screen mode automatically" }),
4398
4458
  /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400 ml-1", children: "\u2014 on login" })
4399
4459
  ] }),
4460
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 cursor-pointer mt-2", children: [
4461
+ /* @__PURE__ */ jsx(
4462
+ "input",
4463
+ {
4464
+ type: "checkbox",
4465
+ checked: prefs.restore_windows ?? true,
4466
+ onChange: (e) => savePref("restore_windows", e.target.checked),
4467
+ className: "h-4 w-4 rounded border-gray-300 text-blue-600"
4468
+ }
4469
+ ),
4470
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-700", children: "Reopen windows from the last session" }),
4471
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400 ml-1", children: "\u2014 on login" })
4472
+ ] }),
4400
4473
  /* @__PURE__ */ jsx(SoundSettings, {})
4401
4474
  ] }),
4402
4475
  /* @__PURE__ */ jsx(ModalActions, { children: /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400", children: "Changes are saved automatically" }) })
@@ -4528,6 +4601,19 @@ function BehaviorPanel() {
4528
4601
  ),
4529
4602
  /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-700", children: "Enter full screen mode automatically" }),
4530
4603
  /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400 ml-1", children: "\u2014 on login" })
4604
+ ] }),
4605
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 cursor-pointer mt-2", children: [
4606
+ /* @__PURE__ */ jsx(
4607
+ "input",
4608
+ {
4609
+ type: "checkbox",
4610
+ checked: prefs.restore_windows ?? true,
4611
+ onChange: (e) => savePref("restore_windows", e.target.checked),
4612
+ className: "h-4 w-4 rounded border-gray-300 text-blue-600"
4613
+ }
4614
+ ),
4615
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-700", children: "Reopen windows from the last session" }),
4616
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400 ml-1", children: "\u2014 on login" })
4531
4617
  ] })
4532
4618
  ] }),
4533
4619
  /* @__PURE__ */ jsx(ModalActions, { children: /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400", children: "Changes are saved automatically" }) })