react-os-shell 0.2.60 → 0.2.62

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 (48) hide show
  1. package/dist/{Browser-P7TWQQYY.js → Browser-46QICOBV.js} +3 -3
  2. package/dist/{Browser-P7TWQQYY.js.map → Browser-46QICOBV.js.map} +1 -1
  3. package/dist/{Calculator-PVTLAMJG.js → Calculator-2454MDQH.js} +4 -4
  4. package/dist/{Calculator-PVTLAMJG.js.map → Calculator-2454MDQH.js.map} +1 -1
  5. package/dist/{Calendar-UUBCO6DL.js → Calendar-NOVX5TSS.js} +3 -3
  6. package/dist/{Calendar-UUBCO6DL.js.map → Calendar-NOVX5TSS.js.map} +1 -1
  7. package/dist/{CurrencyConverter-C6YPYMKF.js → CurrencyConverter-LVUXSR57.js} +4 -4
  8. package/dist/{CurrencyConverter-C6YPYMKF.js.map → CurrencyConverter-LVUXSR57.js.map} +1 -1
  9. package/dist/{Documents-W2KVAGMZ.js → Documents-QJDM3JQZ.js} +3 -3
  10. package/dist/{Documents-W2KVAGMZ.js.map → Documents-QJDM3JQZ.js.map} +1 -1
  11. package/dist/{Email-LL5ABOWG.js → Email-N27XXAW3.js} +4 -4
  12. package/dist/{Email-LL5ABOWG.js.map → Email-N27XXAW3.js.map} +1 -1
  13. package/dist/Files-W3PU2D6S.js +8 -0
  14. package/dist/{Files-EJOCVUFL.js.map → Files-W3PU2D6S.js.map} +1 -1
  15. package/dist/{Minesweeper-A63TCDW2.js → Minesweeper-Q4UYGWYG.js} +3 -3
  16. package/dist/{Minesweeper-A63TCDW2.js.map → Minesweeper-Q4UYGWYG.js.map} +1 -1
  17. package/dist/{Notepad-6J6NAWRN.js → Notepad-XU7VIXYV.js} +3 -3
  18. package/dist/{Notepad-6J6NAWRN.js.map → Notepad-XU7VIXYV.js.map} +1 -1
  19. package/dist/{PomodoroTimer-2O2YIXLM.js → PomodoroTimer-4UXR4OLK.js} +4 -4
  20. package/dist/{PomodoroTimer-2O2YIXLM.js.map → PomodoroTimer-4UXR4OLK.js.map} +1 -1
  21. package/dist/Preview-EOZK5EBA.js +7 -0
  22. package/dist/{Preview-GTN5ZMQA.js.map → Preview-EOZK5EBA.js.map} +1 -1
  23. package/dist/Spreadsheet-2GWD45U4.js +6 -0
  24. package/dist/Spreadsheet-2GWD45U4.js.map +1 -0
  25. package/dist/{Weather-LTHMP7VM.js → Weather-6GOXYALT.js} +4 -4
  26. package/dist/{Weather-LTHMP7VM.js.map → Weather-6GOXYALT.js.map} +1 -1
  27. package/dist/{WorldClock-LKSGXQ4D.js → WorldClock-35S3SRPP.js} +4 -4
  28. package/dist/{WorldClock-LKSGXQ4D.js.map → WorldClock-35S3SRPP.js.map} +1 -1
  29. package/dist/apps/index.d.ts +9 -1
  30. package/dist/apps/index.js +19 -17
  31. package/dist/apps/index.js.map +1 -1
  32. package/dist/{Spreadsheet-T3AHYV5C.js → chunk-BZQALPHC.js} +46 -7
  33. package/dist/chunk-BZQALPHC.js.map +1 -0
  34. package/dist/{chunk-YMXAXNA5.js → chunk-NGGVYK5F.js} +4 -4
  35. package/dist/{chunk-YMXAXNA5.js.map → chunk-NGGVYK5F.js.map} +1 -1
  36. package/dist/{chunk-FBOBSZM5.js → chunk-RGAFGLUW.js} +32 -9
  37. package/dist/chunk-RGAFGLUW.js.map +1 -0
  38. package/dist/{chunk-6W6HAU2K.js → chunk-ST7KKB2W.js} +3 -3
  39. package/dist/{chunk-6W6HAU2K.js.map → chunk-ST7KKB2W.js.map} +1 -1
  40. package/dist/{chunk-7ZPVS3H2.js → chunk-VH7LZ3JT.js} +3 -3
  41. package/dist/{chunk-7ZPVS3H2.js.map → chunk-VH7LZ3JT.js.map} +1 -1
  42. package/dist/index.js +286 -13
  43. package/dist/index.js.map +1 -1
  44. package/package.json +1 -1
  45. package/dist/Files-EJOCVUFL.js +0 -8
  46. package/dist/Preview-GTN5ZMQA.js +0 -7
  47. package/dist/Spreadsheet-T3AHYV5C.js.map +0 -1
  48. package/dist/chunk-FBOBSZM5.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { Modal } from './chunk-FBOBSZM5.js';
1
+ import { Modal } from './chunk-RGAFGLUW.js';
2
2
  import { jsx, jsxs } from 'react/jsx-runtime';
3
3
 
4
4
  var DEFAULT_APPEARANCE = { activeOpacity: 70, inactiveOpacity: 50, activeBlur: 0, inactiveBlur: 0 };
@@ -138,5 +138,5 @@ function WidgetSettingsModal({ open, onClose, title, appearance, onAppearanceCha
138
138
  }
139
139
 
140
140
  export { WidgetSettingsModal, loadAppearance };
141
- //# sourceMappingURL=chunk-7ZPVS3H2.js.map
142
- //# sourceMappingURL=chunk-7ZPVS3H2.js.map
141
+ //# sourceMappingURL=chunk-VH7LZ3JT.js.map
142
+ //# sourceMappingURL=chunk-VH7LZ3JT.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shell/WidgetSettingsModal.tsx"],"names":[],"mappings":"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","file":"chunk-7ZPVS3H2.js","sourcesContent":["import Modal from './Modal';\n\nexport interface WidgetAppearance {\n activeOpacity: number;\n inactiveOpacity: number;\n activeBlur: number;\n inactiveBlur: number;\n}\n\nexport const DEFAULT_APPEARANCE: WidgetAppearance = { activeOpacity: 70, inactiveOpacity: 50, activeBlur: 0, inactiveBlur: 0 };\n\nexport function loadAppearance(key: string): WidgetAppearance {\n try {\n const saved = JSON.parse(localStorage.getItem(key) || '');\n // Migrate old single `blur` field to activeBlur/inactiveBlur\n if (saved.blur != null && saved.activeBlur == null) {\n saved.activeBlur = saved.blur;\n saved.inactiveBlur = saved.blur;\n delete saved.blur;\n }\n return { ...DEFAULT_APPEARANCE, ...saved };\n }\n catch { return DEFAULT_APPEARANCE; }\n}\n\n/** Reusable settings modal for widgets — renders appearance sliders + optional extra content above */\nexport default function WidgetSettingsModal({ open, onClose, title, appearance, onAppearanceChange, onSave, children }: {\n open: boolean;\n onClose: () => void;\n title: string;\n appearance: WidgetAppearance;\n onAppearanceChange: (a: WidgetAppearance) => void;\n onSave: () => void;\n children?: React.ReactNode;\n}) {\n if (!open) return null;\n\n const inp = 'w-full h-1.5 rounded-full appearance-none bg-gray-200 cursor-pointer accent-blue-500';\n const lbl = 'flex items-center justify-between text-xs text-gray-500';\n\n return (\n <div onPointerDown={e => e.stopPropagation()} onContextMenu={e => e.stopPropagation()}>\n <Modal open={open} onClose={onClose} title={title} size=\"sm\">\n <div className=\"space-y-4\">\n {children}\n\n {/* Appearance */}\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-3\">Appearance</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <div className=\"text-xs font-medium text-gray-600 mb-2\">Active</div>\n <div className=\"space-y-2\">\n <div>\n <div className={lbl}><span>Opacity</span><span>{appearance.activeOpacity}%</span></div>\n <input type=\"range\" min={20} max={100} value={appearance.activeOpacity}\n onChange={e => onAppearanceChange({ ...appearance, activeOpacity: +e.target.value })} className={inp} />\n </div>\n <div>\n <div className={lbl}><span>Blur</span><span>{appearance.activeBlur}px</span></div>\n <input type=\"range\" min={0} max={20} value={appearance.activeBlur}\n onChange={e => onAppearanceChange({ ...appearance, activeBlur: +e.target.value })} className={inp} />\n </div>\n </div>\n </div>\n <div>\n <div className=\"text-xs font-medium text-gray-600 mb-2\">Inactive</div>\n <div className=\"space-y-2\">\n <div>\n <div className={lbl}><span>Opacity</span><span>{appearance.inactiveOpacity}%</span></div>\n <input type=\"range\" min={20} max={100} value={appearance.inactiveOpacity}\n onChange={e => onAppearanceChange({ ...appearance, inactiveOpacity: +e.target.value })} className={inp} />\n </div>\n <div>\n <div className={lbl}><span>Blur</span><span>{appearance.inactiveBlur}px</span></div>\n <input type=\"range\" min={0} max={20} value={appearance.inactiveBlur}\n onChange={e => onAppearanceChange({ ...appearance, inactiveBlur: +e.target.value })} className={inp} />\n </div>\n </div>\n </div>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex gap-2 pt-2\">\n <button onClick={onSave}\n className=\"flex-1 text-sm font-medium py-2 rounded-lg bg-blue-600 text-white hover:bg-blue-700 transition\">Save</button>\n <button onClick={onClose}\n className=\"flex-1 text-sm font-medium py-2 rounded-lg border border-gray-300 text-gray-600 hover:bg-gray-50 transition\">Cancel</button>\n </div>\n </div>\n </Modal>\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/shell/WidgetSettingsModal.tsx"],"names":[],"mappings":"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","file":"chunk-VH7LZ3JT.js","sourcesContent":["import Modal from './Modal';\n\nexport interface WidgetAppearance {\n activeOpacity: number;\n inactiveOpacity: number;\n activeBlur: number;\n inactiveBlur: number;\n}\n\nexport const DEFAULT_APPEARANCE: WidgetAppearance = { activeOpacity: 70, inactiveOpacity: 50, activeBlur: 0, inactiveBlur: 0 };\n\nexport function loadAppearance(key: string): WidgetAppearance {\n try {\n const saved = JSON.parse(localStorage.getItem(key) || '');\n // Migrate old single `blur` field to activeBlur/inactiveBlur\n if (saved.blur != null && saved.activeBlur == null) {\n saved.activeBlur = saved.blur;\n saved.inactiveBlur = saved.blur;\n delete saved.blur;\n }\n return { ...DEFAULT_APPEARANCE, ...saved };\n }\n catch { return DEFAULT_APPEARANCE; }\n}\n\n/** Reusable settings modal for widgets — renders appearance sliders + optional extra content above */\nexport default function WidgetSettingsModal({ open, onClose, title, appearance, onAppearanceChange, onSave, children }: {\n open: boolean;\n onClose: () => void;\n title: string;\n appearance: WidgetAppearance;\n onAppearanceChange: (a: WidgetAppearance) => void;\n onSave: () => void;\n children?: React.ReactNode;\n}) {\n if (!open) return null;\n\n const inp = 'w-full h-1.5 rounded-full appearance-none bg-gray-200 cursor-pointer accent-blue-500';\n const lbl = 'flex items-center justify-between text-xs text-gray-500';\n\n return (\n <div onPointerDown={e => e.stopPropagation()} onContextMenu={e => e.stopPropagation()}>\n <Modal open={open} onClose={onClose} title={title} size=\"sm\">\n <div className=\"space-y-4\">\n {children}\n\n {/* Appearance */}\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-3\">Appearance</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <div className=\"text-xs font-medium text-gray-600 mb-2\">Active</div>\n <div className=\"space-y-2\">\n <div>\n <div className={lbl}><span>Opacity</span><span>{appearance.activeOpacity}%</span></div>\n <input type=\"range\" min={20} max={100} value={appearance.activeOpacity}\n onChange={e => onAppearanceChange({ ...appearance, activeOpacity: +e.target.value })} className={inp} />\n </div>\n <div>\n <div className={lbl}><span>Blur</span><span>{appearance.activeBlur}px</span></div>\n <input type=\"range\" min={0} max={20} value={appearance.activeBlur}\n onChange={e => onAppearanceChange({ ...appearance, activeBlur: +e.target.value })} className={inp} />\n </div>\n </div>\n </div>\n <div>\n <div className=\"text-xs font-medium text-gray-600 mb-2\">Inactive</div>\n <div className=\"space-y-2\">\n <div>\n <div className={lbl}><span>Opacity</span><span>{appearance.inactiveOpacity}%</span></div>\n <input type=\"range\" min={20} max={100} value={appearance.inactiveOpacity}\n onChange={e => onAppearanceChange({ ...appearance, inactiveOpacity: +e.target.value })} className={inp} />\n </div>\n <div>\n <div className={lbl}><span>Blur</span><span>{appearance.inactiveBlur}px</span></div>\n <input type=\"range\" min={0} max={20} value={appearance.inactiveBlur}\n onChange={e => onAppearanceChange({ ...appearance, inactiveBlur: +e.target.value })} className={inp} />\n </div>\n </div>\n </div>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex gap-2 pt-2\">\n <button onClick={onSave}\n className=\"flex-1 text-sm font-medium py-2 rounded-lg bg-blue-600 text-white hover:bg-blue-700 transition\">Save</button>\n <button onClick={onClose}\n className=\"flex-1 text-sm font-medium py-2 rounded-lg border border-gray-300 text-gray-600 hover:bg-gray-50 transition\">Cancel</button>\n </div>\n </div>\n </Modal>\n </div>\n );\n}\n"]}
package/dist/index.js CHANGED
@@ -1,18 +1,18 @@
1
1
  import { useEmailUnreadCount } from './chunk-PDFQNHW7.js';
2
2
  import { formatDate } from './chunk-NSU7OHPC.js';
3
3
  export { formatDate } from './chunk-NSU7OHPC.js';
4
- export { EditableGrid } from './chunk-GP4Y3VCB.js';
5
4
  import { subscribePomo, getPomoSnapshot } from './chunk-MK3HLUO4.js';
6
5
  import { useGoogleAuth } from './chunk-MVWEL34Y.js';
7
6
  import { useShellPrefs } from './chunk-36VM54SC.js';
8
7
  export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
9
8
  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-6W6HAU2K.js';
9
+ export { EditableGrid } from './chunk-GP4Y3VCB.js';
10
+ import { setPdfPreview } from './chunk-ST7KKB2W.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 { useWindowManager, glassStyle, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, startMenuCategories, useIsMobile, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons, ModalActions, useModalActive, WINDOW_REGISTRY, isPageEntry, LoadingSpinner, ThumbCard, activateModal } from './chunk-FBOBSZM5.js';
15
- export { CancelButton, CopyButton, DocFavStar, GLASS_DIVIDER, GLASS_INPUT_BG, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, glassStyle, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellNavIcons, setShellWindowRegistry, setWindowDefaultPosition, subscribeExposeHighlight, toggleExposeMode, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-FBOBSZM5.js';
14
+ import { useWindowManager, glassStyle, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, startMenuCategories, useIsMobile, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons, ModalActions, useModalActive, WINDOW_REGISTRY, isPageEntry, LoadingSpinner, ThumbCard, activateModal } from './chunk-RGAFGLUW.js';
15
+ export { CancelButton, CopyButton, DocFavStar, GLASS_DIVIDER, GLASS_INPUT_BG, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, glassStyle, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellNavIcons, setShellWindowRegistry, setWindowDefaultPosition, subscribeExposeHighlight, toggleExposeMode, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-RGAFGLUW.js';
16
16
  import { confirm } from './chunk-PLGHQ7QW.js';
17
17
  export { ConfirmProvider, confirm, confirmDestructive, prompt } from './chunk-PLGHQ7QW.js';
18
18
  import { createContext, lazy, useState, useRef, useEffect, useCallback, useLayoutEffect, useContext, Suspense, isValidElement, cloneElement, useSyncExternalStore, useMemo } from 'react';
@@ -909,7 +909,7 @@ function StatusBadge({ status }) {
909
909
  }
910
910
 
911
911
  // src/version.ts
912
- var VERSION = "0.2.60" ;
912
+ var VERSION = "0.2.61" ;
913
913
  var APP_VERSION = VERSION;
914
914
 
915
915
  // src/changelog.ts
@@ -2997,6 +2997,231 @@ function StartMenu({
2997
2997
  ` })
2998
2998
  ] });
2999
2999
  }
3000
+ function Sidebar({
3001
+ width,
3002
+ openPage,
3003
+ profile,
3004
+ user,
3005
+ onLogout,
3006
+ onNavigate,
3007
+ navSections: navSections2 = navSections,
3008
+ navIcons: navIcons2 = navIcons,
3009
+ sectionIcons: sectionIcons2 = sectionIcons,
3010
+ categories = startMenuCategories,
3011
+ productName,
3012
+ productIcon
3013
+ }) {
3014
+ const { hasAnyPerm } = useAuth();
3015
+ const erpLabels = new Set(categories.erp);
3016
+ const systemLabels = new Set(categories.system);
3017
+ const virtualSections = categories.virtual ?? [];
3018
+ const [search, setSearch] = useState("");
3019
+ const [expanded, setExpanded] = useState(/* @__PURE__ */ new Set());
3020
+ const searchRef = useRef(null);
3021
+ const toggleExpanded = (label) => {
3022
+ setExpanded((prev) => {
3023
+ const next = new Set(prev);
3024
+ if (next.has(label)) next.delete(label);
3025
+ else next.add(label);
3026
+ return next;
3027
+ });
3028
+ };
3029
+ const topItems = navSections2.filter((item) => !isSection(item));
3030
+ const erpSections = navSections2.filter((item) => isSection(item) && erpLabels.has(item.label));
3031
+ const systemSections = navSections2.filter((item) => isSection(item) && systemLabels.has(item.label));
3032
+ const getVisibleItems = (section) => {
3033
+ if (section.perms && !hasAnyPerm(section.perms)) return [];
3034
+ return section.items.filter((it) => !it.perms || hasAnyPerm(it.perms));
3035
+ };
3036
+ const searchResults = useMemo(() => {
3037
+ if (search.length < 2) return [];
3038
+ const q = search.toLowerCase();
3039
+ return navSections2.flatMap((entry) => {
3040
+ if (isSection(entry)) {
3041
+ return getVisibleItems(entry).filter((it) => it.label.toLowerCase().includes(q));
3042
+ }
3043
+ return entry.label.toLowerCase().includes(q) ? [entry] : [];
3044
+ });
3045
+ }, [search, navSections2, hasAnyPerm]);
3046
+ useEffect(() => {
3047
+ const onKey = (e) => {
3048
+ if (e.key === "Escape") {
3049
+ setExpanded(/* @__PURE__ */ new Set());
3050
+ setSearch("");
3051
+ } else if (e.key === "/" && document.activeElement?.tagName !== "INPUT" && document.activeElement?.tagName !== "TEXTAREA") {
3052
+ e.preventDefault();
3053
+ searchRef.current?.focus();
3054
+ }
3055
+ };
3056
+ window.addEventListener("keydown", onKey);
3057
+ return () => window.removeEventListener("keydown", onKey);
3058
+ }, []);
3059
+ const handleClick = (path) => {
3060
+ onNavigate(path);
3061
+ onPageOpenedReset();
3062
+ };
3063
+ const onPageOpenedReset = () => {
3064
+ setSearch("");
3065
+ };
3066
+ const itemCls = "w-full flex items-center gap-2 rounded-lg px-3 py-2 text-sm";
3067
+ const menuGlass = glassStyle();
3068
+ const iconEl = (to) => {
3069
+ const icon = navIcons2[to];
3070
+ if (icon && isValidElement(icon)) {
3071
+ return cloneElement(icon, {
3072
+ className: "h-4 w-4 shrink-0 text-gray-500"
3073
+ });
3074
+ }
3075
+ return /* @__PURE__ */ jsx("span", { className: "h-4 w-4 shrink-0" });
3076
+ };
3077
+ const secIcon = (label) => {
3078
+ const icon = sectionIcons2[label];
3079
+ if (icon && isValidElement(icon)) {
3080
+ return cloneElement(icon, {
3081
+ className: "h-4 w-4 shrink-0 text-gray-500"
3082
+ });
3083
+ }
3084
+ return /* @__PURE__ */ jsx("span", { className: "h-4 w-4 shrink-0" });
3085
+ };
3086
+ const renderItem = (item) => /* @__PURE__ */ jsxs("div", { children: [
3087
+ /* @__PURE__ */ jsxs(
3088
+ "button",
3089
+ {
3090
+ onClick: () => handleClick(item.to),
3091
+ className: `${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`,
3092
+ children: [
3093
+ iconEl(item.to),
3094
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: item.label })
3095
+ ]
3096
+ }
3097
+ ),
3098
+ item.dividerAfter && /* @__PURE__ */ jsx("div", { className: "border-t border-white/20 my-1.5 mx-2" })
3099
+ ] }, item.to);
3100
+ const renderSectionAccordion = (section, isErp) => {
3101
+ const items = "perms" in section ? getVisibleItems(section) : section.items;
3102
+ if (items.length === 0) return null;
3103
+ const isOpen = expanded.has(section.label);
3104
+ return /* @__PURE__ */ jsxs("div", { children: [
3105
+ /* @__PURE__ */ jsxs(
3106
+ "button",
3107
+ {
3108
+ onClick: () => toggleExpanded(section.label),
3109
+ "aria-expanded": isOpen,
3110
+ className: `${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`,
3111
+ children: [
3112
+ "icon" in section && section.icon ? section.icon : secIcon(section.label),
3113
+ /* @__PURE__ */ jsx("span", { className: `truncate ${isErp ? "font-medium" : ""}`, children: section.label }),
3114
+ /* @__PURE__ */ jsx(
3115
+ "svg",
3116
+ {
3117
+ className: `h-3.5 w-3.5 ml-auto text-gray-500 transition-transform ${isOpen ? "rotate-90" : ""}`,
3118
+ fill: "none",
3119
+ viewBox: "0 0 24 24",
3120
+ stroke: "currentColor",
3121
+ strokeWidth: 2,
3122
+ children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 4.5l7.5 7.5-7.5 7.5" })
3123
+ }
3124
+ )
3125
+ ]
3126
+ }
3127
+ ),
3128
+ isOpen && /* @__PURE__ */ jsx("div", { className: "pl-4 mt-0.5 mb-1 space-y-0.5", children: items.map((it) => /* @__PURE__ */ jsxs(
3129
+ "button",
3130
+ {
3131
+ onClick: () => handleClick(it.to),
3132
+ className: `${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`,
3133
+ children: [
3134
+ iconEl(it.to),
3135
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: it.label })
3136
+ ]
3137
+ },
3138
+ it.to
3139
+ )) })
3140
+ ] }, section.label);
3141
+ };
3142
+ return /* @__PURE__ */ jsxs(
3143
+ "div",
3144
+ {
3145
+ className: "fixed top-0 left-0 bottom-0 z-[260] flex flex-col rounded-r-2xl overflow-hidden",
3146
+ style: { width, ...menuGlass },
3147
+ children: [
3148
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-4 py-3 border-b border-white/15 shrink-0", children: [
3149
+ productIcon && /* @__PURE__ */ jsx("img", { src: productIcon, alt: "", className: "h-5 w-5 shrink-0 opacity-80" }),
3150
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-gray-800 truncate", children: productName ?? "Apps" })
3151
+ ] }),
3152
+ /* @__PURE__ */ jsx("div", { className: "px-3 pt-3 pb-2 shrink-0", children: /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-2 ${GLASS_INPUT_BG} rounded-lg px-2.5 py-1.5`, children: [
3153
+ /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5 text-gray-400 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" }) }),
3154
+ /* @__PURE__ */ jsx(
3155
+ "input",
3156
+ {
3157
+ ref: searchRef,
3158
+ value: search,
3159
+ onChange: (e) => setSearch(e.target.value),
3160
+ placeholder: "Search...",
3161
+ className: "flex-1 bg-transparent text-xs outline-none placeholder-gray-400"
3162
+ }
3163
+ ),
3164
+ search && /* @__PURE__ */ jsx("button", { onClick: () => setSearch(""), className: "text-gray-400 hover:text-gray-600 text-xs", children: "\xD7" })
3165
+ ] }) }),
3166
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto px-1 pb-1", children: search.length >= 2 ? (
3167
+ // Search results take over the body.
3168
+ /* @__PURE__ */ jsx("div", { children: searchResults.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-3 py-6 text-center text-xs text-gray-400", children: "No matches" }) : searchResults.map((r) => /* @__PURE__ */ jsxs(
3169
+ "button",
3170
+ {
3171
+ onClick: () => handleClick(r.to),
3172
+ className: `${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`,
3173
+ children: [
3174
+ iconEl(r.to),
3175
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: r.label })
3176
+ ]
3177
+ },
3178
+ r.to
3179
+ )) })
3180
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
3181
+ topItems.map(renderItem),
3182
+ /* @__PURE__ */ jsxs(
3183
+ "button",
3184
+ {
3185
+ onClick: () => handleClick("/notifications"),
3186
+ className: `${itemCls} text-gray-700 hover:bg-blue-50 hover:text-blue-700 transition-colors`,
3187
+ children: [
3188
+ /* @__PURE__ */ jsx("svg", { className: "h-4 w-4 shrink-0 text-gray-500", 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" }) }),
3189
+ /* @__PURE__ */ jsx("span", { children: "Notifications" })
3190
+ ]
3191
+ }
3192
+ ),
3193
+ /* @__PURE__ */ jsx("div", { className: "border-t border-white/15 my-1.5 mx-2" }),
3194
+ erpSections.map((s) => renderSectionAccordion(s, true)),
3195
+ systemSections.map((s) => renderSectionAccordion(s, false)),
3196
+ virtualSections.map((v) => renderSectionAccordion(v, false))
3197
+ ] }) }),
3198
+ /* @__PURE__ */ jsx("div", { className: "border-t border-white/15 p-1 shrink-0", children: /* @__PURE__ */ jsxs(
3199
+ "div",
3200
+ {
3201
+ onClick: () => handleClick("/profile"),
3202
+ className: "rounded-lg px-2 py-1.5 flex items-center gap-2.5 hover:bg-blue-50 hover:text-blue-700 transition-colors cursor-pointer",
3203
+ children: [
3204
+ profile?.avatar_url ? /* @__PURE__ */ jsx("img", { src: profile.avatar_url, alt: "", className: "h-8 w-8 rounded-full object-cover border border-white/20 shrink-0" }) : /* @__PURE__ */ jsx("div", { className: "h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center text-sm font-bold text-blue-700 shrink-0", children: (profile?.first_name?.charAt(0) || user?.email?.charAt(0) || "?").toUpperCase() }),
3205
+ /* @__PURE__ */ jsx("p", { className: "flex-1 min-w-0 text-sm font-medium text-gray-900 truncate", children: profile?.first_name ? `${profile.first_name} ${profile.last_name || ""}`.trim() : user?.email }),
3206
+ /* @__PURE__ */ jsx(
3207
+ "button",
3208
+ {
3209
+ onClick: (e) => {
3210
+ e.stopPropagation();
3211
+ onLogout();
3212
+ },
3213
+ title: "Sign Out",
3214
+ className: "shrink-0 p-1.5 rounded-md text-gray-500 hover:text-red-600 hover:bg-red-50 transition-colors",
3215
+ children: /* @__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: "M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9" }) })
3216
+ }
3217
+ )
3218
+ ]
3219
+ }
3220
+ ) })
3221
+ ]
3222
+ }
3223
+ );
3224
+ }
3000
3225
 
3001
3226
  // src/shell/mobileShellStore.ts
3002
3227
  var _mode = "home";
@@ -3968,7 +4193,11 @@ function Layout({
3968
4193
  useTheme();
3969
4194
  const { desktopBg} = useFavorites(wallpapers);
3970
4195
  const { prefs, save: savePrefs } = useShellPrefs();
3971
- const taskbarPosition = prefs.taskbar_position || "bottom";
4196
+ const layoutMode = prefs.layout_mode === "sidebar" ? "sidebar" : "classic";
4197
+ const sidebarMode = layoutMode === "sidebar";
4198
+ const sidebarWidth = sidebarMode ? 280 : 0;
4199
+ const taskbarPositionRaw = prefs.taskbar_position || "bottom";
4200
+ const taskbarPosition = sidebarMode ? "bottom" : taskbarPositionRaw;
3972
4201
  const taskbarSize = prefs.taskbar_size || "medium";
3973
4202
  const desktopDblClick = prefs.desktop_dblclick || "deactivate";
3974
4203
  const isVerticalTaskbar = taskbarPosition === "left" || taskbarPosition === "right";
@@ -3992,6 +4221,9 @@ function Layout({
3992
4221
  root.style.setProperty("--taskbar-height", String(taskbarH));
3993
4222
  root.style.setProperty("--taskbar-width", String(taskbarW));
3994
4223
  root.style.setProperty("--taskbar-position", taskbarPosition);
4224
+ root.style.setProperty("--sidebar-width", String(sidebarWidth));
4225
+ root.style.setProperty("--layout-mode", layoutMode);
4226
+ window.dispatchEvent(new CustomEvent("react-os-shell:layout-mode-changed"));
3995
4227
  root.style.setProperty("--default-window-size", prefs.default_window_size || "large");
3996
4228
  root.style.setProperty("--window-position", prefs.window_position || "cascade");
3997
4229
  root.style.setProperty("--menu-density", prefs.menu_density || "normal");
@@ -4007,7 +4239,7 @@ function Layout({
4007
4239
  root.style.setProperty("--menu-padding-y", sv.py);
4008
4240
  root.style.setProperty("--window-tab-width", sv.tabW);
4009
4241
  root.style.setProperty("--window-tab-font-size", sv.tabFont);
4010
- }, [inactiveHeaderOpacity, inactiveContentOpacity, activeHeaderOpacity, activeContentOpacity, taskbarH, taskbarPosition, prefs.default_window_size, prefs.window_position, prefs.menu_density, prefs.start_menu_size]);
4242
+ }, [inactiveHeaderOpacity, inactiveContentOpacity, activeHeaderOpacity, activeContentOpacity, taskbarH, taskbarPosition, prefs.default_window_size, prefs.window_position, prefs.menu_density, prefs.start_menu_size, sidebarWidth, layoutMode]);
4011
4243
  useEffect(() => {
4012
4244
  document.documentElement.style.setProperty("--mobile-bottom-nav", isMobile ? "100px" : "0px");
4013
4245
  }, [isMobile]);
@@ -4114,7 +4346,7 @@ function Layout({
4114
4346
  sessionStorage.removeItem("erp_startup_shown");
4115
4347
  logout();
4116
4348
  } }),
4117
- /* @__PURE__ */ jsx(
4349
+ !sidebarMode && /* @__PURE__ */ jsx(
4118
4350
  StartMenu,
4119
4351
  {
4120
4352
  open: menuOpen,
@@ -4141,6 +4373,23 @@ function Layout({
4141
4373
  categories
4142
4374
  }
4143
4375
  ),
4376
+ sidebarMode && /* @__PURE__ */ jsx(
4377
+ Sidebar,
4378
+ {
4379
+ width: sidebarWidth,
4380
+ openPage: (path) => openPage(path),
4381
+ profile,
4382
+ user,
4383
+ onLogout: () => setShowLogout(true),
4384
+ onNavigate: (path) => openPage(path),
4385
+ navSections: navSections2,
4386
+ navIcons: navIcons2,
4387
+ sectionIcons: sectionIcons2,
4388
+ categories,
4389
+ productName,
4390
+ productIcon
4391
+ }
4392
+ ),
4144
4393
  (() => {
4145
4394
  const wallpaperStyle = {
4146
4395
  backgroundColor: desktopBg?.startsWith("#") ? desktopBg : desktopBg === "none" ? (() => {
@@ -4191,14 +4440,17 @@ function Layout({
4191
4440
  /* @__PURE__ */ jsxs(
4192
4441
  "div",
4193
4442
  {
4194
- className: `flex backdrop-blur-sm border-gray-200 z-[250] fixed ${isVerticalTaskbar ? `flex-col items-center ${taskbarWClass} py-3 gap-2 top-0 bottom-0 ${taskbarPosition === "left" ? "left-0 border-r" : "right-0 border-l"}` : `items-center ${taskbarHClass} px-3 gap-2 left-0 right-0 ${taskbarPosition === "top" ? "top-0 border-b" : "bottom-0 border-t"}`}`,
4195
- style: { backgroundColor: `rgb(var(--taskbar-bg-rgb, 243 244 246) / ${taskbarOpacity})` },
4443
+ className: `flex backdrop-blur-sm border-gray-200 z-[250] fixed ${isVerticalTaskbar ? `flex-col items-center ${taskbarWClass} py-3 gap-2 top-0 bottom-0 ${taskbarPosition === "left" ? "left-0 border-r" : "right-0 border-l"}` : `items-center ${taskbarHClass} px-3 gap-2 right-0 ${taskbarPosition === "top" ? "top-0 border-b" : "bottom-0 border-t"}`}`,
4444
+ style: {
4445
+ backgroundColor: `rgb(var(--taskbar-bg-rgb, 243 244 246) / ${taskbarOpacity})`,
4446
+ ...isVerticalTaskbar ? {} : { left: sidebarWidth }
4447
+ },
4196
4448
  onContextMenu: (e) => {
4197
4449
  e.preventDefault();
4198
4450
  setTaskbarMenu({ x: e.clientX, y: e.clientY });
4199
4451
  },
4200
4452
  children: [
4201
- /* @__PURE__ */ jsxs("div", { className: "relative shrink-0", children: [
4453
+ !sidebarMode && /* @__PURE__ */ jsxs("div", { className: "relative shrink-0", children: [
4202
4454
  openWindows.length === 0 && !menuOpen && !balloonDismissed && /* @__PURE__ */ jsxs(
4203
4455
  "div",
4204
4456
  {
@@ -4255,7 +4507,7 @@ function Layout({
4255
4507
  }
4256
4508
  )
4257
4509
  ] }),
4258
- /* @__PURE__ */ jsx("div", { className: isVerticalTaskbar ? "h-px w-6 bg-gray-300 my-1" : "w-px h-6 bg-gray-300 mx-1" }),
4510
+ !sidebarMode && /* @__PURE__ */ jsx("div", { className: isVerticalTaskbar ? "h-px w-6 bg-gray-300 my-1" : "w-px h-6 bg-gray-300 mx-1" }),
4259
4511
  /* @__PURE__ */ jsx("div", { id: "taskbar-windows", className: `flex-1 flex ${isVerticalTaskbar ? "flex-col items-center gap-1 min-h-0 overflow-y-auto w-full" : "items-center gap-1.5 min-w-0 overflow-x-auto"}` }),
4260
4512
  /* @__PURE__ */ jsx("div", { className: isVerticalTaskbar ? "h-px w-6 bg-gray-300 my-1" : "w-px h-6 bg-gray-300 mx-1" }),
4261
4513
  isVerticalTaskbar ? (
@@ -4624,6 +4876,25 @@ function Customization() {
4624
4876
  ] }, item.key);
4625
4877
  }) })
4626
4878
  ] }),
4879
+ /* @__PURE__ */ jsxs("div", { children: [
4880
+ /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900 mb-3", children: "Layout Mode" }),
4881
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mb-3", children: "Sidebar mode is designed for small screens \u2014 windows always run maximized and the start menu lives in a persistent left sidebar (sections expand inline instead of opening flyouts)." }),
4882
+ /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: [
4883
+ { key: "classic", label: "Classic" },
4884
+ { key: "sidebar", label: "Sidebar" }
4885
+ ].map((m) => /* @__PURE__ */ jsx(
4886
+ "button",
4887
+ {
4888
+ onClick: () => {
4889
+ savePref("layout_mode", m.key);
4890
+ if (m.key === "sidebar") savePref("default_window_size", "maximized");
4891
+ },
4892
+ className: `px-3 py-1.5 text-xs font-medium rounded-lg border transition-colors ${(prefs.layout_mode || "classic") === m.key ? "bg-blue-600 text-white border-blue-600" : "bg-white text-gray-700 border-gray-300 hover:bg-gray-50"}`,
4893
+ children: m.label
4894
+ },
4895
+ m.key
4896
+ )) })
4897
+ ] }),
4627
4898
  /* @__PURE__ */ jsxs("div", { children: [
4628
4899
  /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-900 mb-3", children: "Taskbar" }),
4629
4900
  /* @__PURE__ */ jsx("div", { className: "space-y-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
@@ -4632,7 +4903,9 @@ function Customization() {
4632
4903
  "button",
4633
4904
  {
4634
4905
  onClick: () => savePref("taskbar_position", pos),
4635
- className: `px-3 py-1.5 text-xs font-medium rounded-lg border transition-colors ${(prefs.taskbar_position || "bottom") === pos ? "bg-blue-600 text-white border-blue-600" : "bg-white text-gray-700 border-gray-300 hover:bg-gray-50"}`,
4906
+ disabled: prefs.layout_mode === "sidebar",
4907
+ title: prefs.layout_mode === "sidebar" ? "Sidebar mode forces a horizontal taskbar." : void 0,
4908
+ className: `px-3 py-1.5 text-xs font-medium rounded-lg border transition-colors disabled:opacity-40 disabled:cursor-not-allowed ${(prefs.taskbar_position || "bottom") === pos ? "bg-blue-600 text-white border-blue-600" : "bg-white text-gray-700 border-gray-300 hover:bg-gray-50"}`,
4636
4909
  children: pos.charAt(0).toUpperCase() + pos.slice(1)
4637
4910
  },
4638
4911
  pos