@fde-desktop/fde-core 0.3.8 → 0.4.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 (148) hide show
  1. package/README.md +419 -68
  2. package/dist/CalendarApp-CHLUCAI7.css +744 -0
  3. package/dist/CalendarApp-K7ZOUZ6C.js +2 -0
  4. package/dist/CalendarApp-OTGEERSS.cjs +8 -0
  5. package/dist/CodeServerApp-5KZGO7HL.css +75 -0
  6. package/dist/CodeServerApp-LUZFCQBI.js +3 -0
  7. package/dist/CodeServerApp-P3TMJPLY.cjs +9 -0
  8. package/dist/CreateItemApp-NAZMXOPK.cjs +14 -0
  9. package/dist/CreateItemApp-PQB5GTFG.css +107 -0
  10. package/dist/CreateItemApp-ZHCTSPQE.js +8 -0
  11. package/dist/DeviceInfoApp-R6YNVIGX.cjs +11 -0
  12. package/dist/DeviceInfoApp-YHCYAO6N.js +5 -0
  13. package/dist/DeviceInfoApp-ZSMRSITP.css +7 -0
  14. package/dist/FilesApp-AKCVRTXR.js +8 -0
  15. package/dist/FilesApp-E6L5W3T2.css +1817 -0
  16. package/dist/FilesApp-RW3Y6ILO.cjs +14 -0
  17. package/dist/ImageViewerApp-5UXNSW2O.js +11 -0
  18. package/dist/ImageViewerApp-N2Q7E7WZ.css +215 -0
  19. package/dist/ImageViewerApp-RRRRKSFN.cjs +17 -0
  20. package/dist/ImageViewerMenuBar-I3TFKQPS.cjs +14 -0
  21. package/dist/ImageViewerMenuBar-TV5C6TM2.js +5 -0
  22. package/dist/ImageViewerMenuBar-XLK4LIHW.css +56 -0
  23. package/dist/MenuEditApp-HUZRFEHE.js +9 -0
  24. package/dist/MenuEditApp-MCUHGTKQ.cjs +15 -0
  25. package/dist/MenuEditApp-YA6HSAMJ.css +94 -0
  26. package/dist/MenuEditMenuBar-7VHMZNRM.css +56 -0
  27. package/dist/MenuEditMenuBar-GF6L4PGZ.cjs +15 -0
  28. package/dist/MenuEditMenuBar-IUXFPZE5.js +6 -0
  29. package/dist/NotesApp-37BV33C6.js +10 -0
  30. package/dist/NotesApp-4EVUQEFZ.cjs +16 -0
  31. package/dist/NotesApp-TQ6IHDNX.css +302 -0
  32. package/dist/NotesMenuBar-25LKN3SE.cjs +15 -0
  33. package/dist/NotesMenuBar-MXLOX7OT.css +56 -0
  34. package/dist/NotesMenuBar-SRV3AIAL.js +6 -0
  35. package/dist/PdfApp-5VBDNRMC.cjs +16 -0
  36. package/dist/PdfApp-BUIC5U5H.css +206 -0
  37. package/dist/PdfApp-RH6MZZX5.js +10 -0
  38. package/dist/PdfMenuBar-NLZC6JHS.js +4 -0
  39. package/dist/PdfMenuBar-QUM72EE4.css +56 -0
  40. package/dist/PdfMenuBar-WBRTKMLN.cjs +13 -0
  41. package/dist/SettingsApp-5LDHEHYV.cjs +20 -0
  42. package/dist/SettingsApp-JVOSEFH3.css +283 -0
  43. package/dist/SettingsApp-X6764D7T.js +14 -0
  44. package/dist/SettingsMenuBar-5CBSSMVM.css +56 -0
  45. package/dist/SettingsMenuBar-VLT6TTCM.js +6 -0
  46. package/dist/SettingsMenuBar-Y5QEXDEO.cjs +15 -0
  47. package/dist/StorybookApp-NQ244BER.css +7 -0
  48. package/dist/StorybookApp-NZDV4X3Y.js +1 -0
  49. package/dist/StorybookApp-VF3KIMU3.cjs +7 -0
  50. package/dist/TerminalApp-CDGWRBFJ.cjs +10 -0
  51. package/dist/TerminalApp-EAATMIMX.css +77 -0
  52. package/dist/TerminalApp-GCKJCM55.js +4 -0
  53. package/dist/TerminalMenuBar-3J26O26Q.css +56 -0
  54. package/dist/TerminalMenuBar-7BH7MGNJ.cjs +14 -0
  55. package/dist/TerminalMenuBar-7JAEQUZ4.js +5 -0
  56. package/dist/UploaderApp-2WYRCUQV.js +10 -0
  57. package/dist/UploaderApp-6KV3TGCT.css +1817 -0
  58. package/dist/UploaderApp-EYFC36PM.cjs +16 -0
  59. package/dist/chunk-2FO445RM.cjs +449 -0
  60. package/dist/chunk-2PSTHGTD.cjs +42 -0
  61. package/dist/chunk-2RQX7QBP.cjs +148 -0
  62. package/dist/chunk-3IICBLEA.js +442 -0
  63. package/dist/chunk-43W6UDUZ.cjs +19 -0
  64. package/dist/chunk-4E45FBAH.js +223 -0
  65. package/dist/chunk-4MCFQPKY.js +444 -0
  66. package/dist/chunk-4OH5RPSQ.cjs +38 -0
  67. package/dist/chunk-4XURSNM4.js +43 -0
  68. package/dist/chunk-4ZCRYHL6.js +407 -0
  69. package/dist/chunk-54PYEQLK.js +283 -0
  70. package/dist/chunk-5C6IQE42.cjs +35 -0
  71. package/dist/chunk-5NOHYJNH.js +84 -0
  72. package/dist/chunk-5PYK5ASL.js +162 -0
  73. package/dist/chunk-5YH6AKEO.js +146 -0
  74. package/dist/chunk-657BJOY5.cjs +324 -0
  75. package/dist/chunk-6QOUYSEE.cjs +2303 -0
  76. package/dist/chunk-7SAFECOJ.js +215 -0
  77. package/dist/chunk-7Y7HB7FB.cjs +53 -0
  78. package/dist/chunk-ABIAPZ6S.cjs +45 -0
  79. package/dist/chunk-AQL372JF.cjs +219 -0
  80. package/dist/chunk-AXDUVZVP.cjs +88 -0
  81. package/dist/chunk-AYFNYHMP.js +541 -0
  82. package/dist/chunk-BDO6B7MZ.cjs +451 -0
  83. package/dist/chunk-BKXEA2BK.cjs +286 -0
  84. package/dist/chunk-BLV47DX2.js +47 -0
  85. package/dist/chunk-BQCD5RAF.cjs +48 -0
  86. package/dist/chunk-BQL3YXMV.js +17429 -0
  87. package/dist/chunk-C6BEZNAM.cjs +45 -0
  88. package/dist/chunk-CFWV2JMR.js +234 -0
  89. package/dist/chunk-CV5PUHAE.cjs +86 -0
  90. package/dist/chunk-D5MVFFID.js +42 -0
  91. package/dist/chunk-D7R55WWT.js +1601 -0
  92. package/dist/chunk-DMNF4CNN.cjs +49 -0
  93. package/dist/chunk-DWP2SYF7.js +55 -0
  94. package/dist/chunk-E55VXNLK.cjs +17498 -0
  95. package/dist/chunk-EAELL43F.js +42 -0
  96. package/dist/chunk-EUQLZW6P.js +48 -0
  97. package/dist/chunk-EX5V2ZTU.js +40 -0
  98. package/dist/chunk-FH4ILMKF.js +38 -0
  99. package/dist/chunk-FRHBM2U7.js +33 -0
  100. package/dist/chunk-FX2TPX3L.cjs +45 -0
  101. package/dist/chunk-GCYD6T52.js +32 -0
  102. package/dist/chunk-GRYCUBJZ.js +9 -0
  103. package/dist/chunk-HWHBSAUC.js +40 -0
  104. package/dist/chunk-ICUE6T7J.cjs +50 -0
  105. package/dist/chunk-IDHP3R4I.js +31 -0
  106. package/dist/chunk-IUOQPOEN.js +2293 -0
  107. package/dist/chunk-J7L2S2GT.cjs +34 -0
  108. package/dist/chunk-JEBKLIMU.cjs +123 -0
  109. package/dist/chunk-KQHICFX3.js +121 -0
  110. package/dist/chunk-LMJE6V4N.cjs +42 -0
  111. package/dist/chunk-MVDGM5Y4.js +68 -0
  112. package/dist/chunk-NVEGEK3N.js +31 -0
  113. package/dist/chunk-NWMSWRUD.js +2236 -0
  114. package/dist/chunk-ODXL6BR3.js +77 -0
  115. package/dist/chunk-OJIDKDKF.js +68 -0
  116. package/dist/chunk-PKPQA5NR.js +15 -0
  117. package/dist/chunk-PNDBLFJW.cjs +50 -0
  118. package/dist/chunk-PYTKNRGM.js +280 -0
  119. package/dist/chunk-Q3WA72BF.cjs +70 -0
  120. package/dist/chunk-QB72BLCJ.cjs +237 -0
  121. package/dist/chunk-QHBBLML3.js +86 -0
  122. package/dist/chunk-RDIDAZ3S.cjs +9 -0
  123. package/dist/chunk-RGJPRXYY.js +48 -0
  124. package/dist/chunk-RQ6OZRUW.cjs +41 -0
  125. package/dist/chunk-SBE4SZAN.cjs +226 -0
  126. package/dist/chunk-SYGUWGWK.cjs +2329 -0
  127. package/dist/chunk-TDZ43MUX.cjs +165 -0
  128. package/dist/chunk-TGWMOHAO.js +17 -0
  129. package/dist/chunk-U4RYIS6Z.cjs +548 -0
  130. package/dist/chunk-UIQCTAVM.cjs +59 -0
  131. package/dist/chunk-XVASHRCE.cjs +70 -0
  132. package/dist/chunk-XYSMVQQD.cjs +1608 -0
  133. package/dist/chunk-YAIWI4Z5.js +7 -0
  134. package/dist/chunk-YP2PLNOF.cjs +34 -0
  135. package/dist/chunk-YSOLW4FS.cjs +11 -0
  136. package/dist/chunk-YY6OUR2U.js +44 -0
  137. package/dist/chunk-YZWS7FDT.cjs +409 -0
  138. package/dist/chunk-Z5YGWL65.cjs +39 -0
  139. package/dist/chunk-ZBGWYTCU.cjs +83 -0
  140. package/dist/chunk-ZHB5Q2M6.js +36 -0
  141. package/dist/chunk-ZHNDXNL4.js +45 -0
  142. package/dist/chunk-ZX3EDZ5C.cjs +17 -0
  143. package/dist/index.cjs +4405 -5156
  144. package/dist/index.css +9192 -0
  145. package/dist/index.d.cts +1324 -762
  146. package/dist/index.d.ts +1324 -762
  147. package/dist/index.js +3648 -5038
  148. package/package.json +14 -6
package/dist/index.d.cts CHANGED
@@ -1,68 +1,116 @@
1
- import * as zustand_middleware from 'zustand/middleware';
2
- import * as zustand from 'zustand';
3
- import * as framer_motion from 'framer-motion';
4
- import { Transition, TargetAndTransition, Variants } from 'framer-motion';
5
1
  import * as react from 'react';
6
- import { MouseEvent, RefObject, ReactNode, FC } from 'react';
7
- import { IconType } from 'react-icons';
8
- import * as _tanstack_react_query from '@tanstack/react-query';
2
+ import react__default, { ReactNode, FC, MouseEvent, ReactElement } from 'react';
9
3
  import { MantineThemeOverride } from '@mantine/core';
4
+ import i18n from 'i18next';
10
5
  export { default as i18n } from 'i18next';
6
+ import * as framer_motion from 'framer-motion';
7
+ import { Transition, TargetAndTransition, Variants } from 'framer-motion';
8
+ import { IconType, IconBaseProps } from 'react-icons';
9
+ import * as _tanstack_react_query from '@tanstack/react-query';
10
+ import * as zustand_middleware from 'zustand/middleware';
11
+ import * as zustand from 'zustand';
11
12
  export { v4 as uuidv4 } from 'uuid';
12
13
 
13
- interface AppEntry {
14
- id: string;
15
- name: string;
16
- icon: string;
17
- fcIcon?: string;
18
- iconUrl?: string;
19
- iconColor?: string;
20
- defaultWidth?: number;
21
- defaultHeight?: number;
22
- minWidth?: number | false;
23
- minHeight?: number | false;
24
- canMaximize?: boolean;
25
- alwaysOnTop?: boolean;
26
- autoLoad?: {
27
- url: string;
28
- name?: string;
29
- };
30
- hasContextMenu?: boolean;
31
- multipleWindow?: boolean;
14
+ type SupportedLanguage$2 = 'en' | 'es';
15
+ interface CustomThemeColors {
16
+ taskbar: string;
17
+ window: string;
18
+ accent: string;
19
+ }
20
+ interface ISettingsState {
21
+ wallpaper: string | null;
22
+ wallpaperModule: string;
23
+ launcherIcon: string;
24
+ font: string;
25
+ downloadedFonts: string[];
26
+ fontSize: number;
27
+ animationDuration: number;
28
+ theme: FdeTheme;
29
+ themeSetManually: boolean;
30
+ customThemeColors: CustomThemeColors | null;
31
+ language: SupportedLanguage$2;
32
+ setWallpaper: (url: string | null) => void;
33
+ setWallpaperModule: (module: string) => void;
34
+ setLauncherIcon: (icon: string) => void;
35
+ setFont: (font: string) => void;
36
+ markFontDownloaded: (fontName: string) => void;
37
+ setFontSize: (size: number) => void;
38
+ setAnimationDuration: (duration: number) => void;
39
+ setThemeMode: (mode: ThemeMode) => void;
40
+ toggleTheme: () => void;
41
+ setThemeAutomatic: () => void;
42
+ applySystemTheme: (mode: ThemeMode) => void;
43
+ setCustomThemeColors: (colors: CustomThemeColors | null) => void;
44
+ setLanguage: (lang: SupportedLanguage$2) => void;
32
45
  }
33
46
 
34
- declare const DEFAULT_WINDOW_DIMENSIONS: {
35
- readonly defaultWidth: 800;
36
- readonly defaultHeight: 600;
37
- readonly minWidth: 640;
38
- readonly minHeight: 480;
39
- };
40
- declare const FilesApp: AppEntry;
41
- declare const SettingsApp: AppEntry;
42
- declare const NotepadApp: AppEntry;
43
- declare const ImageViewerApp: AppEntry;
44
- declare const PdfApp: AppEntry;
45
- declare const UploaderApp: AppEntry;
46
- declare const MenuEditApp: AppEntry;
47
- declare const DeviceInfoApp: AppEntry;
48
- declare const CalendarApp: AppEntry;
49
- declare const CORE_APPS: AppEntry[];
50
- declare const CORE_APP_IDS: string[];
51
-
52
- interface CreateFolderOptions {
53
- iconName?: string;
54
- iconColor?: string;
47
+ type ThemeMode = 'light' | 'dark';
48
+ interface Theme {
49
+ mode: ThemeMode;
50
+ desktop: string;
51
+ taskbar: string;
52
+ window: string;
53
+ accent: string;
54
+ }
55
+ interface WindowTheme {
56
+ borderRadius: string;
57
+ headerHeight: number;
58
+ minWidth: number;
59
+ minHeight: number;
60
+ defaultWidth: number;
61
+ defaultHeight: number;
62
+ shadow: string;
63
+ }
64
+ interface TaskbarTheme {
65
+ height: number;
66
+ position: 'bottom' | 'top';
67
+ background: string;
68
+ blur: boolean;
69
+ }
70
+ interface DesktopTheme {
71
+ background: string;
72
+ iconSize: number;
73
+ iconSpacing: number;
74
+ }
75
+ interface FdeTheme {
76
+ mode: ThemeMode;
77
+ colors: {
78
+ desktop: string;
79
+ taskbar: string;
80
+ window: string;
81
+ accent: string;
82
+ };
83
+ window: WindowTheme;
84
+ taskbar: TaskbarTheme;
85
+ desktop: DesktopTheme;
86
+ }
87
+ interface PartialFdeTheme {
88
+ mode?: ThemeMode;
89
+ colors?: Partial<FdeTheme['colors']>;
90
+ window?: Partial<WindowTheme>;
91
+ taskbar?: Partial<TaskbarTheme>;
92
+ desktop?: Partial<DesktopTheme>;
93
+ }
94
+ interface IThemeProvider {
95
+ getTheme(): FdeTheme;
96
+ setMode(mode: ThemeMode): void;
97
+ toggle(): void;
98
+ setCustomColors(colors: CustomThemeColors | null): void;
55
99
  }
56
100
 
57
- interface FolderNode extends FileSystemNode {
58
- type: 'folder';
59
- children: string[];
60
- iconName?: string;
61
- iconColor?: string;
101
+ interface ThemeProviderProps {
102
+ children: react__default.ReactNode;
103
+ initialMode?: ThemeMode;
104
+ /** External mode override - when provided, syncs internal state with this value */
105
+ mode?: ThemeMode;
106
+ theme?: PartialFdeTheme;
62
107
  }
108
+ declare function ThemeProvider({ children, initialMode, mode: externalMode, theme, }: ThemeProviderProps): react__default.ReactElement;
63
109
 
64
- type FileSystemNodeType = 'file' | 'folder';
65
- type FSNode = FileNode | FolderNode;
110
+ declare function useTheme(): FdeTheme;
111
+ declare function useThemeContext(): IThemeProvider;
112
+
113
+ declare const DEFAULT_FDE_THEME: Record<ThemeMode, FdeTheme>;
66
114
 
67
115
  interface FileSystemNode {
68
116
  id: string;
@@ -82,6 +130,16 @@ interface FileNode extends FileSystemNode {
82
130
  iconColor?: string;
83
131
  }
84
132
 
133
+ interface FolderNode extends FileSystemNode {
134
+ type: 'folder';
135
+ children: string[];
136
+ iconName?: string;
137
+ iconColor?: string;
138
+ }
139
+
140
+ type FileSystemNodeType = 'file' | 'folder';
141
+ type FSNode = FileNode | FolderNode;
142
+
85
143
  interface FsManifestFile {
86
144
  name: string;
87
145
  folder: string;
@@ -119,99 +177,68 @@ interface IFileSystem {
119
177
  clearAll(): Promise<void>;
120
178
  }
121
179
 
122
- declare class IndexedDBFileSystem implements IFileSystem {
123
- private db;
124
- private nodes;
125
- private ready;
126
- private initPromise;
127
- private persistQueue;
128
- private persistScheduled;
129
- initialize(): Promise<void>;
130
- private doInitialize;
131
- private openDatabase;
132
- private loadNodes;
133
- private migrateFromLocalStorage;
134
- isReady(): boolean;
135
- reinitialize(): Promise<void>;
136
- private persistAllNodes;
137
- private schedulePersist;
138
- private flushPersistQueue;
139
- private persistNode;
140
- private deleteNodeFromPersist;
141
- saveBlob(blob: Blob): Promise<string>;
142
- /** Accepts the full URL returned by saveBlob (e.g. `idb://{hash}`) */
143
- getBlob(url: string): Promise<Blob | null>;
144
- toBlobUrl(url: string): Promise<string | null>;
145
- clearBlobs(): Promise<void>;
146
- readFile(_path: string): Promise<string>;
147
- writeFile(_path: string, _content: string): Promise<void>;
148
- getNode(id: string): FSNode | undefined;
149
- getChildren(folderId: string): FSNode[];
150
- getRootNodes(): FSNode[];
151
- getAllNodes(): FSNode[];
152
- isEmpty(): boolean;
153
- createFile(name: string, content: string, parentId: string | null, url?: string): Promise<FileNode>;
154
- createFolder(name: string, parentId: string | null, iconName?: string, iconColor?: string): Promise<FolderNode>;
155
- updateFile(id: string, content: string): Promise<FileNode>;
156
- move(id: string, newParentId: string | null): Promise<FSNode>;
157
- delete(id: string): Promise<void>;
158
- getManifestSha(): Promise<string | null>;
159
- saveManifestSha(sha: string): Promise<void>;
160
- clearAll(): Promise<void>;
161
- seed(manifest: FsManifest): Promise<void>;
162
- mergeSeed(manifest: FsManifest): Promise<void>;
163
- /**
164
- * Builds a folderPath → FolderNode map from a manifest, creating all intermediate
165
- * subfolders (e.g. "Documents/docker") as children of their parent folders.
166
- * @param mergeMode - when true, reuse existing nodes from this.nodes instead of creating new ones
167
- */
168
- private buildFolderMapFromManifest;
169
- private addChildToFolder;
170
- private removeChildFromParent;
171
- private deleteRecursive;
180
+ interface FdeProviderProps {
181
+ children: react__default.ReactNode;
182
+ fileSystem: IFileSystem;
183
+ initialMode?: ThemeMode;
184
+ theme?: PartialFdeTheme;
185
+ mantineTheme?: MantineThemeOverride;
186
+ fallback?: react__default.ReactNode;
187
+ onError?: (error: Error) => void;
172
188
  }
189
+ declare function FdeProvider({ children, fileSystem, initialMode, theme, mantineTheme, fallback, onError, }: FdeProviderProps): react__default.ReactElement;
173
190
 
174
- declare class DockerFileSystemAdapter implements IFileSystem {
175
- private nodes;
176
- private pathToId;
177
- private ready;
178
- private rootFolderId;
179
- private initPromise;
180
- constructor();
181
- initialize(): Promise<void>;
182
- private doInitialize;
183
- reinitialize(): Promise<void>;
184
- isReady(): boolean;
185
- isEmpty(): boolean;
186
- getNode(id: string): FSNode | undefined;
187
- getChildren(folderId: string): FSNode[];
188
- getRootNodes(): FSNode[];
189
- getAllNodes(): FSNode[];
190
- createFile(name: string, content: string, parentId: string | null, url?: string): Promise<FileNode>;
191
- createFolder(name: string, parentId: string | null, iconName?: string, iconColor?: string): Promise<FolderNode>;
192
- updateFile(id: string, content: string): Promise<FileNode>;
193
- move(id: string, newParentId: string | null): Promise<FSNode>;
194
- delete(id: string): Promise<void>;
195
- readFile(path: string): Promise<string>;
196
- writeFile(path: string, content: string): Promise<void>;
197
- saveBlob(blob: Blob): Promise<string>;
198
- getBlob(url: string): Promise<Blob | null>;
199
- toBlobUrl(url: string): Promise<string | null>;
200
- getManifestSha(): Promise<string | null>;
201
- saveManifestSha(_sha: string): Promise<void>;
202
- seed(_manifest: FsManifest): Promise<void>;
203
- mergeSeed(_manifest: FsManifest): Promise<void>;
204
- clearAll(): Promise<void>;
205
- private getMimeType;
206
- private getPathFromId;
207
- private deleteRecursive;
208
- private syncFromEntries;
209
- private fetchReaddir;
210
- private writeFileToServer;
211
- private createDirOnServer;
212
- private deleteFromServer;
191
+ interface FdeContextValue {
192
+ fs: IFileSystem | null;
193
+ isReady: boolean;
194
+ error: Error | null;
195
+ theme: FdeTheme;
196
+ setThemeMode: (mode: ThemeMode) => void;
197
+ toggleTheme: () => void;
198
+ }
199
+
200
+ declare function useFdeContext(): FdeContextValue;
201
+
202
+ interface AppEntry {
203
+ id: string;
204
+ name: string;
205
+ icon: string;
206
+ fcIcon?: string;
207
+ iconUrl?: string;
208
+ iconColor?: string;
209
+ defaultWidth?: number;
210
+ defaultHeight?: number;
211
+ minWidth?: number | false;
212
+ minHeight?: number | false;
213
+ canMaximize?: boolean;
214
+ alwaysOnTop?: boolean;
215
+ autoLoad?: {
216
+ url: string;
217
+ name?: string;
218
+ };
219
+ hasContextMenu?: boolean;
220
+ singleWindow?: boolean;
213
221
  }
214
222
 
223
+ type WindowState = 'normal' | 'minimized' | 'maximized';
224
+ type WindowInput<T = Record<string, unknown>> = {
225
+ title: string;
226
+ content: string;
227
+ x: number;
228
+ y: number;
229
+ width: number;
230
+ height: number;
231
+ minWidth?: number;
232
+ minHeight?: number;
233
+ icon?: string;
234
+ fcIcon?: string;
235
+ iconUrl?: string;
236
+ iconColor?: string;
237
+ canMaximize?: boolean;
238
+ alwaysOnTop?: boolean;
239
+ contentData?: T;
240
+ };
241
+
215
242
  interface WindowEntity {
216
243
  id: string;
217
244
  title: string;
@@ -235,37 +262,239 @@ interface WindowEntity {
235
262
  closeInterceptor?: () => boolean;
236
263
  }
237
264
 
238
- type WindowState = 'normal' | 'minimized' | 'maximized';
239
- type WindowInput = Omit<WindowEntity, 'id' | 'isOpen' | 'state' | 'zIndex'>;
240
-
241
- interface DesktopIconEntity {
242
- id: string;
243
- name: string;
244
- icon: string;
245
- iconName?: string;
246
- iconColor?: string;
247
- x: number;
248
- y: number;
249
- appId: string;
250
- nodeId?: string;
265
+ interface MenuItemAction {
266
+ type: 'item';
267
+ label: string;
268
+ icon?: string;
269
+ onClick: () => void;
270
+ disabled?: boolean;
251
271
  }
252
-
253
- type DesktopIconInput = Omit<DesktopIconEntity, 'id'>;
254
-
255
- /**
256
- * Sorts an array of filesystem nodes: folders first, then files, each group
257
- * sorted alphabetically by name (locale-aware, case-insensitive).
258
- */
259
- declare const sortNodes: (nodes: FSNode[]) => FSNode[];
260
- type DesktopSortMode = 'default' | 'name-asc' | 'name-desc' | 'type';
261
- /**
262
- * Sorts desktop icons by DESKTOP_APPS_ORDER (apps first, then folders, then files).
263
- */
264
- declare const sortDesktopIcons: (icons: DesktopIconEntity[]) => DesktopIconEntity[];
265
- /**
266
- * Sorts desktop icons by the specified mode.
267
- */
268
- declare const sortDesktopIconsByMode: (icons: DesktopIconEntity[], mode: DesktopSortMode) => DesktopIconEntity[];
272
+ interface MenuItemDivider {
273
+ type: 'divider';
274
+ }
275
+ interface MenuItemSlider {
276
+ type: 'slider';
277
+ label?: string;
278
+ min: number;
279
+ max: number;
280
+ value: number;
281
+ onChange: (value: number) => void;
282
+ labelFormat?: (value: number) => string;
283
+ }
284
+ type MenuItem = MenuItemAction | MenuItemDivider | MenuItemSlider;
285
+ interface AppMenuDropdown {
286
+ type: 'menu';
287
+ label: string;
288
+ icon?: string;
289
+ items: MenuItem[];
290
+ rightSection?: ReactNode;
291
+ }
292
+ interface AppMenuCombobox {
293
+ type: 'combobox';
294
+ label?: string;
295
+ options: string[];
296
+ value: string;
297
+ onChange: (value: string) => void;
298
+ }
299
+ interface AppMenuSwitch {
300
+ type: 'switch';
301
+ label: string;
302
+ checked: boolean;
303
+ onChange: (value: boolean) => void;
304
+ }
305
+ interface AppMenuSlider {
306
+ type: 'slider';
307
+ label?: string;
308
+ min: number;
309
+ max: number;
310
+ value: number;
311
+ onChange: (value: number) => void;
312
+ marks?: {
313
+ value: number;
314
+ label?: string;
315
+ }[];
316
+ labelFormat?: (value: number) => string;
317
+ }
318
+ interface AppMenuTextInput {
319
+ type: 'text-input';
320
+ placeholder?: string;
321
+ value: string;
322
+ onChange: (value: string) => void;
323
+ }
324
+ interface AppMenuNumberInput {
325
+ type: 'number-input';
326
+ label?: string;
327
+ value: number;
328
+ onChange: (value: number) => void;
329
+ min?: number;
330
+ max?: number;
331
+ step?: number;
332
+ placeholder?: string;
333
+ }
334
+ interface AppMenuSelect {
335
+ type: 'select';
336
+ label?: string;
337
+ options: {
338
+ value: string;
339
+ label: string;
340
+ }[];
341
+ value: string;
342
+ onChange: (value: string) => void;
343
+ }
344
+ interface AppMenuDirtyIndicator {
345
+ type: 'dirty-indicator';
346
+ }
347
+ type AppMenuElement = AppMenuDropdown | AppMenuCombobox | AppMenuSwitch | AppMenuSlider | AppMenuTextInput | AppMenuNumberInput | AppMenuSelect | AppMenuDirtyIndicator;
348
+
349
+ interface WindowContentProps {
350
+ window?: WindowEntity;
351
+ notifyReady?: (contentData?: Record<string, unknown>) => void;
352
+ }
353
+ type AppComponent$1 = FC<WindowContentProps>;
354
+ type MenuBarBuilder = (window: WindowEntity) => AppMenuElement[] | undefined;
355
+ interface MenuBarComponentProps {
356
+ windowId: string;
357
+ onExit: () => void;
358
+ contentData?: Record<string, unknown>;
359
+ }
360
+ type MenuBarComponent = FC<MenuBarComponentProps>;
361
+ interface AppRegistration {
362
+ component: AppComponent$1;
363
+ buildMenuBar?: MenuBarBuilder;
364
+ MenuBarComponent?: MenuBarComponent;
365
+ }
366
+
367
+ interface DesktopIconEntity {
368
+ id: string;
369
+ name: string;
370
+ icon: string;
371
+ iconName?: string;
372
+ iconColor?: string;
373
+ x: number;
374
+ y: number;
375
+ appId: string;
376
+ nodeId?: string;
377
+ }
378
+
379
+ interface MenuPosition {
380
+ x: number;
381
+ y: number;
382
+ }
383
+
384
+ interface CreateFolderOptions {
385
+ iconName?: string;
386
+ iconColor?: string;
387
+ }
388
+
389
+ type LoadingState = 'idle' | 'fetching' | 'compiling' | 'loading' | 'ready' | 'error';
390
+ interface LoadingProgress {
391
+ state: LoadingState;
392
+ progress: number;
393
+ message?: string;
394
+ appName?: string;
395
+ error?: string;
396
+ }
397
+ interface WindowLoading extends LoadingProgress {
398
+ windowId: string;
399
+ }
400
+
401
+ type DesktopIconInput = Omit<DesktopIconEntity, 'id'>;
402
+
403
+ interface OpenAppOptions {
404
+ title?: string;
405
+ icon?: string;
406
+ contentData?: Record<string, unknown>;
407
+ position?: {
408
+ x?: number;
409
+ y?: number;
410
+ };
411
+ size?: {
412
+ width?: number;
413
+ height?: number;
414
+ };
415
+ }
416
+ interface FileDialogOptions {
417
+ acceptedMimeTypes?: string[];
418
+ multiple?: boolean;
419
+ defaultPath?: string;
420
+ }
421
+ interface SaveDialogOptions {
422
+ defaultName?: string;
423
+ defaultPath?: string;
424
+ acceptedMimeTypes?: string[];
425
+ }
426
+ interface NotificationOptions {
427
+ title: string;
428
+ message: string;
429
+ type?: 'info' | 'success' | 'warning' | 'error';
430
+ duration?: number;
431
+ }
432
+ type FdeEventType = 'window-opened' | 'window-closed' | 'window-focused' | 'window-minimized' | 'window-maximized' | 'file-opened' | 'file-saved' | 'theme-changed' | 'notification-shown';
433
+ interface FdeEventPayloads {
434
+ 'window-opened': {
435
+ windowId: string;
436
+ content: string;
437
+ };
438
+ 'window-closed': {
439
+ windowId: string;
440
+ };
441
+ 'window-focused': {
442
+ windowId: string;
443
+ };
444
+ 'window-minimized': {
445
+ windowId: string;
446
+ };
447
+ 'window-maximized': {
448
+ windowId: string;
449
+ };
450
+ 'file-opened': {
451
+ path: string;
452
+ appId?: string;
453
+ };
454
+ 'file-saved': {
455
+ path: string;
456
+ success: boolean;
457
+ };
458
+ 'theme-changed': {
459
+ theme: string;
460
+ };
461
+ 'notification-shown': {
462
+ notificationId: string;
463
+ };
464
+ }
465
+ interface FdeDesktopAPI {
466
+ openApp: (appId: string, options?: OpenAppOptions) => void;
467
+ closeWindow: (windowId?: string) => void;
468
+ minimizeWindow: (windowId?: string) => void;
469
+ maximizeWindow: (windowId?: string) => void;
470
+ restoreWindow: (windowId?: string) => void;
471
+ focusWindow: (windowId?: string) => void;
472
+ openFile: (path: string, appId?: string) => void;
473
+ openFileDialog: (options?: FileDialogOptions) => Promise<string | null>;
474
+ saveFile: (content: string, options?: SaveDialogOptions) => Promise<boolean>;
475
+ saveFileDialog: (options?: SaveDialogOptions) => Promise<string | null>;
476
+ getTheme: () => Record<string, unknown>;
477
+ setTheme: (theme: Record<string, unknown>) => void;
478
+ showNotification: (options: NotificationOptions) => string;
479
+ hideNotification: (notificationId: string) => void;
480
+ getWindows: () => WindowEntity[];
481
+ getActiveWindow: () => WindowEntity | null;
482
+ getWindowById: (windowId: string) => WindowEntity | null;
483
+ fs: IFileSystem;
484
+ on: <T extends FdeEventType>(event: T, callback: (data: FdeEventPayloads[T]) => void) => () => void;
485
+ off: <T extends FdeEventType>(event: T, callback: (data: FdeEventPayloads[T]) => void) => void;
486
+ appReady: (appId: string) => void;
487
+ registerAppInstance: (appId: string, instance: unknown) => void;
488
+ }
489
+ declare global {
490
+ interface Window {
491
+ __FDE_API__?: FdeDesktopAPI;
492
+ }
493
+ }
494
+
495
+ declare const createWindow: (input: WindowInput) => WindowEntity;
496
+
497
+ declare const createDesktopIcon: (input: DesktopIconInput) => DesktopIconEntity;
269
498
 
270
499
  interface LauncherFolder {
271
500
  id: string;
@@ -285,8 +514,12 @@ interface LauncherFolderInput {
285
514
  order?: number;
286
515
  }
287
516
  declare const createLauncherFolder: (input: LauncherFolderInput) => LauncherFolder;
517
+ declare const createPredefinedLauncherFolder: (input: Omit<LauncherFolderInput, "isPredefined">) => LauncherFolder;
288
518
  declare const updateLauncherFolder: (folder: LauncherFolder, updates: Partial<Omit<LauncherFolder, "id" | "isPredefined">>) => LauncherFolder;
289
519
 
520
+ declare const createFolder: (name: string, parentId?: string | null, options?: CreateFolderOptions) => FolderNode;
521
+ declare const createFile: (name: string, content: string, parentId?: string | null, mimeType?: string, url?: string) => FileNode;
522
+
290
523
  interface CustomAppManifest {
291
524
  id: string;
292
525
  name: string;
@@ -301,14 +534,43 @@ interface CustomAppManifest {
301
534
  minHeight?: number | false;
302
535
  canMaximize?: boolean;
303
536
  alwaysOnTop?: boolean;
537
+ singleWindow?: boolean;
304
538
  };
305
539
  }
540
+ interface AppsManifest {
541
+ version: string;
542
+ generated: string;
543
+ apps: CustomAppManifest[];
544
+ }
545
+ declare function fetchAppManifest(forceRefresh?: boolean): Promise<AppsManifest | null>;
546
+ declare function getCachedManifest(): AppsManifest | null;
547
+ declare function clearManifestCache(): void;
548
+ declare function updateManifestCache(manifest: CustomAppManifest): void;
549
+ declare function removeFromManifestCache(appId: string): void;
550
+ declare function getCustomApps(): Promise<CustomAppManifest[]>;
551
+ declare function getCustomAppById(appId: string): Promise<CustomAppManifest | undefined>;
552
+ declare function isCustomApp(appId: string): boolean;
553
+ declare function convertToAppEntry(manifest: CustomAppManifest): Partial<AppEntry>;
554
+ declare function mergeAppsWithCustomApps(staticApps: AppEntry[], customApps: CustomAppManifest[]): AppEntry[];
555
+ declare function syncWithServer(currentRegisteredApps: Record<string, CustomAppManifest>): Promise<{
556
+ added: CustomAppManifest[];
557
+ removed: string[];
558
+ manifest: AppsManifest | null;
559
+ }>;
306
560
 
307
561
  type ClipboardAction = 'copy' | 'cut' | null;
308
562
  interface ClipboardState {
309
563
  content: FSNode[];
310
564
  action: ClipboardAction;
311
565
  }
566
+ type DesktopSortMode$1 = 'default' | 'name-asc' | 'name-desc' | 'type';
567
+ interface NotificationItem {
568
+ id: string;
569
+ title: string;
570
+ message: string;
571
+ onClose?: () => void;
572
+ fcIcon?: string;
573
+ }
312
574
  interface DesktopState {
313
575
  windows: WindowEntity[];
314
576
  openWindow: (input: WindowInput) => void;
@@ -357,10 +619,10 @@ interface DesktopState {
357
619
  viewportHeight: number;
358
620
  isViewportInitialized: boolean;
359
621
  setViewportSize: (width: number, height: number) => void;
360
- desktopSortMode: DesktopSortMode;
361
- filesSortMode: DesktopSortMode;
362
- setDesktopSortMode: (mode: DesktopSortMode) => void;
363
- setFilesSortMode: (mode: DesktopSortMode) => void;
622
+ desktopSortMode: DesktopSortMode$1;
623
+ filesSortMode: DesktopSortMode$1;
624
+ setDesktopSortMode: (mode: DesktopSortMode$1) => void;
625
+ setFilesSortMode: (mode: DesktopSortMode$1) => void;
364
626
  launcherFolders: LauncherFolder[];
365
627
  setLauncherFolders: (folders: LauncherFolder[]) => void;
366
628
  createLauncherFolder: (input: LauncherFolderInput) => LauncherFolder;
@@ -374,89 +636,6 @@ interface DesktopState {
374
636
  handleCustomAppRegistered: (manifest: CustomAppManifest) => void;
375
637
  handleCustomAppUnregistered: (appId: string) => void;
376
638
  }
377
- interface NotificationItem {
378
- id: string;
379
- title: string;
380
- message: string;
381
- onClose?: () => void;
382
- fcIcon?: string;
383
- }
384
-
385
- declare const fileSystem: IndexedDBFileSystem | DockerFileSystemAdapter;
386
- /** Sync reset for tests — clears in-memory state immediately, async DB flush follows. */
387
- declare const resetFileSystem: () => void;
388
- declare const resetWindowManager: () => void;
389
- declare const useDesktopStore: zustand.UseBoundStore<Omit<zustand.StoreApi<DesktopState>, "setState" | "persist"> & {
390
- setState(partial: DesktopState | Partial<DesktopState> | ((state: DesktopState) => DesktopState | Partial<DesktopState>), replace?: false | undefined): unknown;
391
- setState(state: DesktopState | ((state: DesktopState) => DesktopState), replace: true): unknown;
392
- persist: {
393
- setOptions: (options: Partial<zustand_middleware.PersistOptions<DesktopState, unknown, unknown>>) => void;
394
- clearStorage: () => void;
395
- rehydrate: () => Promise<void> | void;
396
- hasHydrated: () => boolean;
397
- onHydrate: (fn: (state: DesktopState) => void) => () => void;
398
- onFinishHydration: (fn: (state: DesktopState) => void) => () => void;
399
- getOptions: () => Partial<zustand_middleware.PersistOptions<DesktopState, unknown, unknown>>;
400
- };
401
- }>;
402
-
403
- type ThemeMode = 'light' | 'dark';
404
- interface Theme {
405
- mode: ThemeMode;
406
- desktop: string;
407
- taskbar: string;
408
- window: string;
409
- accent: string;
410
- }
411
-
412
- declare const SUPPORTED_LANGUAGES: readonly ["en", "es"];
413
- type SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number];
414
-
415
- interface CustomThemeColors {
416
- taskbar: string;
417
- window: string;
418
- accent: string;
419
- }
420
- interface ISettingsState {
421
- wallpaper: string | null;
422
- wallpaperModule: string;
423
- launcherIcon: string;
424
- font: string;
425
- downloadedFonts: string[];
426
- fontSize: number;
427
- animationDuration: number;
428
- theme: Theme;
429
- themeSetManually: boolean;
430
- customThemeColors: CustomThemeColors | null;
431
- language: SupportedLanguage;
432
- setWallpaper: (url: string | null) => void;
433
- setWallpaperModule: (module: string) => void;
434
- setLauncherIcon: (icon: string) => void;
435
- setFont: (font: string) => void;
436
- markFontDownloaded: (fontName: string) => void;
437
- setFontSize: (size: number) => void;
438
- setAnimationDuration: (duration: number) => void;
439
- setThemeMode: (mode: ThemeMode) => void;
440
- toggleTheme: () => void;
441
- setThemeAutomatic: () => void;
442
- applySystemTheme: (mode: ThemeMode) => void;
443
- setCustomThemeColors: (colors: CustomThemeColors | null) => void;
444
- setLanguage: (lang: SupportedLanguage) => void;
445
- }
446
-
447
- declare const useSettingsStore: zustand.UseBoundStore<Omit<zustand.StoreApi<ISettingsState>, "setState" | "persist"> & {
448
- setState(partial: ISettingsState | Partial<ISettingsState> | ((state: ISettingsState) => ISettingsState | Partial<ISettingsState>), replace?: false | undefined): unknown;
449
- setState(state: ISettingsState | ((state: ISettingsState) => ISettingsState), replace: true): unknown;
450
- persist: {
451
- setOptions: (options: Partial<zustand_middleware.PersistOptions<ISettingsState, unknown, unknown>>) => void;
452
- clearStorage: () => void;
453
- rehydrate: () => Promise<void> | void;
454
- hasHydrated: () => boolean;
455
- onHydrate: (fn: (state: ISettingsState) => void) => () => void;
456
- onFinishHydration: (fn: (state: ISettingsState) => void) => () => void;
457
- getOptions: () => Partial<zustand_middleware.PersistOptions<ISettingsState, unknown, unknown>>;
458
- };
459
- }>;
460
639
 
461
640
  interface MountedAppState {
462
641
  isLoaded: boolean;
@@ -488,162 +667,408 @@ interface CustomAppState {
488
667
  resetHmrRetry: () => void;
489
668
  }
490
669
 
491
- declare const useCustomAppStore: zustand.UseBoundStore<zustand.StoreApi<CustomAppState>>;
670
+ interface IWindowManager {
671
+ getAll(): WindowEntity[];
672
+ getById(id: string): WindowEntity | undefined;
673
+ open(input: WindowInput): WindowEntity;
674
+ close(id: string): void;
675
+ minimize(id: string): void;
676
+ maximize(id: string): void;
677
+ restore(id: string): void;
678
+ focus(id: string): void;
679
+ move(id: string, x: number, y: number): void;
680
+ resize(id: string, width: number, height: number): void;
681
+ loadWindows(windows: WindowEntity[]): void;
682
+ }
492
683
 
493
- /**
494
- * Store for temporary snapshots used by the `useIsDirty` hook.
495
- * Each app (identified by a unique string id) can store its own snapshot.
496
- * Snapshots are persisted to `localStorage` so they survive page reloads.
497
- */
498
- interface AppTempMemoryState {
499
- /** Mapping of appId → snapshot (any serializable value) */
500
- snapshots: Record<string, unknown>;
501
- /** Set a snapshot for a given appId */
502
- setSnapshot: (appId: string, snapshot: unknown) => void;
503
- /** Retrieve a snapshot for a given appId */
504
- getSnapshot: (appId: string) => unknown | null;
505
- /** Clear the snapshot for a given appId */
506
- clearSnapshot: (appId: string) => void;
684
+ interface WindowProps {
685
+ window: WindowEntity;
686
+ menuBar?: AppMenuElement[];
687
+ children?: ReactNode;
688
+ closeInterceptor?: () => boolean;
689
+ }
690
+ interface DesktopIconProps {
691
+ icon: DesktopIconEntity;
692
+ onDoubleClick: (appId: string, nodeId?: string) => void;
693
+ onContextMenu: (e: React.MouseEvent, nodeId: string) => void;
694
+ }
695
+ interface DesktopContextMenuProps {
696
+ opened: boolean;
697
+ position: MenuPosition;
698
+ onClose: () => void;
699
+ onOpenApp: (appId: string) => void;
700
+ onToggleTheme: () => void;
701
+ }
702
+ interface LauncherProps {
703
+ fcIcon?: string;
704
+ onContextMenu?: (e: React.MouseEvent) => void;
705
+ }
706
+ interface DesktopAreaProps {
707
+ children?: ReactNode;
708
+ onContextMenu?: (e: MouseEvent<HTMLDivElement>) => void;
709
+ }
710
+ interface TaskbarContextMenuProps {
711
+ windowMenuOpened: boolean;
712
+ panelMenuOpened: boolean;
713
+ launcherMenuOpened: boolean;
714
+ menuPosition: MenuPosition;
715
+ targetWindowId: string | null;
716
+ targetWindowState: string | null;
717
+ onCloseWindow: (id: string) => void;
718
+ onMinimizeWindow: (id: string) => void;
719
+ onMaximizeWindow: (id: string) => void;
720
+ onRestoreWindow: (id: string) => void;
721
+ onClose: () => void;
507
722
  }
508
- declare const useAppTempMemoryStore: zustand.UseBoundStore<Omit<zustand.StoreApi<AppTempMemoryState>, "setState" | "persist"> & {
509
- setState(partial: AppTempMemoryState | Partial<AppTempMemoryState> | ((state: AppTempMemoryState) => AppTempMemoryState | Partial<AppTempMemoryState>), replace?: false | undefined): unknown;
510
- setState(state: AppTempMemoryState | ((state: AppTempMemoryState) => AppTempMemoryState), replace: true): unknown;
511
- persist: {
512
- setOptions: (options: Partial<zustand_middleware.PersistOptions<AppTempMemoryState, unknown, unknown>>) => void;
513
- clearStorage: () => void;
514
- rehydrate: () => Promise<void> | void;
515
- hasHydrated: () => boolean;
516
- onHydrate: (fn: (state: AppTempMemoryState) => void) => () => void;
517
- onFinishHydration: (fn: (state: AppTempMemoryState) => void) => () => void;
518
- getOptions: () => Partial<zustand_middleware.PersistOptions<AppTempMemoryState, unknown, unknown>>;
519
- };
520
- }>;
521
723
 
522
- type OpenAppOptions$1 = {
523
- /** Extra data passed to the window's content component. */
524
- contentData?: Record<string, unknown>;
525
- /** Override position (e.g. for the initial seed window). */
526
- position?: {
527
- x: number;
528
- y: number;
529
- };
530
- };
531
- /**
532
- * Returns a stable `openApp(appId, options?)` callback that looks up app
533
- * metadata from static or custom apps, picks a random desktop position
534
- * (unless overridden) and calls `openWindow` on the desktop store.
535
- *
536
- * If `multipleWindow: true` on the app, always opens a new window.
537
- * Otherwise, focuses existing window if one is already open.
538
- */
539
- declare const useOpenApp: () => (appId: string, { contentData, position }?: OpenAppOptions$1) => void;
724
+ interface FileIconProps {
725
+ type: 'file' | 'folder';
726
+ name?: string;
727
+ folderNode?: FolderNode;
728
+ fileNode?: FileNode;
729
+ size?: number;
730
+ iconName?: string;
731
+ }
540
732
 
541
- interface OpenAppOptions {
542
- title?: string;
733
+ type AppComponent = FC<WindowContentProps>;
734
+ interface AppRegistryEntry {
735
+ component?: AppComponent;
736
+ loader?: () => Promise<{
737
+ default: AppComponent;
738
+ }>;
739
+ menuBarLoader?: () => Promise<{
740
+ default: MenuBarComponent;
741
+ }>;
742
+ buildMenuBar?: MenuBarBuilder;
743
+ MenuBarComponent?: MenuBarComponent;
744
+ isLazy?: boolean;
745
+ appName?: string;
746
+ singleWindow?: boolean;
747
+ defaultWidth?: number;
748
+ defaultHeight?: number;
749
+ minWidth?: number | false;
750
+ minHeight?: number | false;
751
+ canMaximize?: boolean;
752
+ alwaysOnTop?: boolean;
543
753
  icon?: string;
544
- contentData?: Record<string, unknown>;
545
- position?: {
546
- x?: number;
547
- y?: number;
548
- };
549
- size?: {
550
- width?: number;
551
- height?: number;
552
- };
754
+ fcIcon?: string;
755
+ iconUrl?: string;
756
+ iconColor?: string;
553
757
  }
554
- interface FileDialogOptions {
555
- acceptedMimeTypes?: string[];
556
- multiple?: boolean;
557
- defaultPath?: string;
758
+ declare function initRegistry(registry: Record<string, AppRegistryEntry>): void;
759
+ declare function getAppComponent(content: string): AppComponent;
760
+ declare function getMenuBarBuilder(content: string): MenuBarBuilder | undefined;
761
+ declare function getMenuBarComponent(content: string): MenuBarComponent | undefined;
762
+ declare function isLazyApp(content: string): boolean;
763
+ declare function getAppName(content: string): string | undefined;
764
+ declare function registerComponents(entries: Record<string, AppRegistryEntry>): void;
765
+ declare const CORE_REGISTRY: Record<string, AppRegistryEntry>;
766
+
767
+ interface FdeDesktopProps {
768
+ children?: react__default.ReactNode;
769
+ fallback?: react__default.ReactNode;
770
+ theme?: PartialFdeTheme;
771
+ mantineTheme?: MantineThemeOverride;
772
+ fileSystem?: IFileSystem;
773
+ initialMode?: ThemeMode;
774
+ customApps?: Record<string, AppRegistryEntry>;
775
+ onError?: (error: Error) => void;
776
+ /** URL or import of the default wallpaper image */
777
+ defaultWallpaper?: string;
778
+ /** App ID to open on startup */
779
+ initialApp?: string;
780
+ /** Loaders to prefetch in the background after startup */
781
+ prefetchLoaders?: Array<{
782
+ id: string;
783
+ loader: () => Promise<unknown>;
784
+ }>;
558
785
  }
559
- interface SaveDialogOptions {
560
- defaultName?: string;
561
- defaultPath?: string;
786
+ declare function FdeDesktop({ children, fallback, theme, mantineTheme, fileSystem, initialMode, customApps, onError, defaultWallpaper, initialApp, prefetchLoaders, }: FdeDesktopProps): react__default.ReactElement;
787
+
788
+ declare const Window: FC<WindowProps>;
789
+
790
+ declare const AppReadyProvider: FC<{
791
+ children: ReactNode;
792
+ }>;
793
+
794
+ interface AppReadyContextValue {
795
+ notifyReady: (contentData?: Record<string, unknown>) => void;
796
+ getContentData: () => Record<string, unknown> | undefined;
797
+ }
798
+ declare const useAppReady: () => AppReadyContextValue;
799
+
800
+ declare const FilesAppLazy: react.LazyExoticComponent<react.FC<WindowContentProps>>;
801
+ declare const NotesAppLazy: react.LazyExoticComponent<react.FC<WindowContentProps>>;
802
+ declare const ImageViewerAppLazy: react.LazyExoticComponent<react.FC<WindowContentProps>>;
803
+ declare const PdfAppLazy: react.LazyExoticComponent<react.FC<WindowContentProps>>;
804
+ declare const MenuEditAppLazy: react.LazyExoticComponent<react.FC<WindowContentProps>>;
805
+ declare const UploaderAppLazy: react.LazyExoticComponent<react.FC<WindowContentProps>>;
806
+ declare const SettingsAppLazy: react.LazyExoticComponent<react.FC<WindowContentProps>>;
807
+ declare const DeviceInfoAppLazy: react.LazyExoticComponent<react.FC<WindowContentProps>>;
808
+ declare const CalendarAppLazy: react.LazyExoticComponent<react.FC<WindowContentProps>>;
809
+ declare const CreateItemAppLazy: react.LazyExoticComponent<react.FC<WindowContentProps>>;
810
+ declare const NotesMenuBarLazy: MenuBarComponent;
811
+ declare const MenuEditMenuBarLazy: MenuBarComponent;
812
+ declare const SettingsMenuBarLazy: MenuBarComponent;
813
+ declare const PdfMenuBarLazy: MenuBarComponent;
814
+ declare const ImageViewerMenuBarLazy: MenuBarComponent;
815
+
816
+ interface AppMenuBarProps {
817
+ elements: AppMenuElement[];
818
+ }
819
+ declare const AppMenuBar: FC<AppMenuBarProps>;
820
+
821
+ interface TaskbarProps {
822
+ calendarSlot?: ReactNode;
823
+ }
824
+ declare const Taskbar: FC<TaskbarProps>;
825
+
826
+ declare const LanguageSelector: FC;
827
+
828
+ declare const Launcher: FC<LauncherProps>;
829
+
830
+ declare const TaskbarContextMenu: FC<TaskbarContextMenuProps>;
831
+
832
+ interface DesktopProps extends DesktopAreaProps {
833
+ wallpaper?: string;
834
+ backgroundColor?: string;
835
+ }
836
+ declare const Desktop: FC<DesktopProps>;
837
+
838
+ declare const DesktopIcon: FC<DesktopIconProps>;
839
+
840
+ interface DynamicMenuBarRendererProps {
841
+ component?: MenuBarComponent;
842
+ windowId: string;
843
+ contentData: Record<string, unknown> | undefined;
844
+ onExit: () => void;
845
+ }
846
+ declare const DynamicMenuBarRenderer: FC<DynamicMenuBarRendererProps>;
847
+
848
+ declare const ContextMenu: FC<DesktopContextMenuProps>;
849
+
850
+ interface CreateItemContextMenuProps {
851
+ owner: string;
852
+ parentId: string | null;
853
+ currentPath: string;
854
+ }
855
+ declare const CreateItemContextMenu: FC<CreateItemContextMenuProps>;
856
+
857
+ declare const CalendarApp: FC<WindowContentProps>;
858
+
859
+ declare const FilesApp: FC<WindowContentProps>;
860
+
861
+ declare const NotesApp: FC<WindowContentProps>;
862
+
863
+ declare const ImageViewerApp: FC<WindowContentProps>;
864
+
865
+ declare const PdfApp: FC<WindowContentProps>;
866
+
867
+ declare const MenuEditApp: FC<WindowContentProps>;
868
+
869
+ declare const UploaderApp: FC<WindowContentProps>;
870
+
871
+ declare const StorybookApp: FC<WindowContentProps>;
872
+
873
+ declare const SettingsApp: FC<WindowContentProps>;
874
+
875
+ declare const DeviceInfoApp: FC<WindowContentProps>;
876
+
877
+ interface SettingsSection$1 {
878
+ id: 'wallpaper' | 'appearance' | 'launcher' | 'font' | 'language' | 'reset';
879
+ label: string;
880
+ fcIcon: string;
881
+ description: string;
882
+ }
883
+ declare const SETTINGS_SECTIONS: SettingsSection$1[];
884
+
885
+ declare const NotesMenuBar: FC<MenuBarComponentProps>;
886
+
887
+ declare const MenuEditMenuBar: FC<MenuBarComponentProps>;
888
+
889
+ declare const SettingsMenuBar: FC<MenuBarComponentProps>;
890
+
891
+ declare const PdfMenuBar: FC<MenuBarComponentProps>;
892
+
893
+ declare const ImageViewerMenuBar: FC<MenuBarComponentProps>;
894
+
895
+ interface AppIconProps {
896
+ fcIcon?: string;
897
+ fallback?: string;
898
+ iconUrl?: string;
899
+ size?: number;
900
+ color?: string;
901
+ }
902
+ declare const AppIcon: FC<AppIconProps>;
903
+
904
+ interface VscIconProps {
905
+ name: string;
906
+ size?: number;
907
+ color?: string;
908
+ }
909
+ declare const VscIcon: FC<VscIconProps>;
910
+
911
+ interface AppLoadingProps {
912
+ message?: string;
913
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
914
+ }
915
+ declare const AppLoading: FC<AppLoadingProps>;
916
+
917
+ interface DirtyIndicatorProps {
918
+ size?: number;
919
+ }
920
+ declare const DirtyIndicator: FC<DirtyIndicatorProps>;
921
+
922
+ declare const ContextMenuAnchor: FC<MenuPosition>;
923
+
924
+ declare const FileIcon: FC<FileIconProps>;
925
+
926
+ interface AppEmptyStateProps {
927
+ label?: string;
928
+ }
929
+ declare const AppEmptyState: FC<AppEmptyStateProps>;
930
+
931
+ interface ColorPickerProps {
932
+ value: string;
933
+ onChange: (color: string) => void;
934
+ error?: string;
935
+ disabled?: boolean;
936
+ }
937
+ declare const ColorPicker: FC<ColorPickerProps>;
938
+
939
+ declare const CreateItemApp: FC<WindowContentProps>;
940
+
941
+ type DownloadStatus = 'idle' | 'downloading' | 'done' | 'error';
942
+ interface DownloadState {
943
+ status: DownloadStatus;
944
+ loaded: number;
945
+ total: number | null;
946
+ percent: number | null;
947
+ error: string | null;
948
+ }
949
+ interface UseDownloadReturn extends DownloadState {
950
+ download: (url: string) => Promise<string | null>;
951
+ reset: () => void;
952
+ }
953
+ declare const useDownload: () => UseDownloadReturn;
954
+
955
+ interface DownloadProgressProps {
956
+ state: DownloadState;
957
+ ariaLabel?: string;
958
+ minDisplayTime?: number;
959
+ }
960
+ declare const DownloadProgress: FC<DownloadProgressProps>;
961
+
962
+ interface FilePickerAppProps {
562
963
  acceptedMimeTypes?: string[];
964
+ onConfirm: (node: FileNode) => void;
965
+ onCancel: () => void;
563
966
  }
564
- interface NotificationOptions {
967
+ declare const FilePickerApp: FC<FilePickerAppProps>;
968
+ interface FilePickerModalProps extends FilePickerAppProps {
969
+ opened: boolean;
970
+ }
971
+ declare const FilePickerModal: FC<FilePickerModalProps>;
972
+
973
+ interface PickerModalProps {
974
+ opened: boolean;
975
+ children: ReactNode;
976
+ ariaLabelKey: string;
977
+ ariaLabelNs?: string;
978
+ }
979
+ declare const PickerModal: react.NamedExoticComponent<PickerModalProps>;
980
+
981
+ interface IconColorPickerProps {
982
+ selectedIcon: string;
983
+ selectedColor: string;
984
+ onIconChange: (icon: string) => void;
985
+ onColorChange: (color: string) => void;
986
+ colorError?: string;
987
+ }
988
+ declare const IconColorPicker: FC<IconColorPickerProps>;
989
+
990
+ interface SettingsSectionProps {
565
991
  title: string;
566
- message: string;
567
- type?: 'info' | 'success' | 'warning' | 'error';
568
- duration?: number;
992
+ description?: string;
993
+ children: ReactNode;
569
994
  }
570
- type FdeEventType = 'window-opened' | 'window-closed' | 'window-focused' | 'window-minimized' | 'window-maximized' | 'file-opened' | 'file-saved' | 'theme-changed' | 'notification-shown';
571
- interface FdeEventPayloads {
572
- 'window-opened': {
573
- windowId: string;
574
- content: string;
575
- };
576
- 'window-closed': {
577
- windowId: string;
578
- };
579
- 'window-focused': {
580
- windowId: string;
581
- };
582
- 'window-minimized': {
583
- windowId: string;
584
- };
585
- 'window-maximized': {
586
- windowId: string;
587
- };
588
- 'file-opened': {
589
- path: string;
590
- appId?: string;
591
- };
592
- 'file-saved': {
593
- path: string;
594
- success: boolean;
595
- };
596
- 'theme-changed': {
597
- theme: string;
598
- };
599
- 'notification-shown': {
600
- notificationId: string;
601
- };
995
+ declare const SettingsSection: FC<SettingsSectionProps>;
996
+
997
+ interface ExternalLinkAppConfig {
998
+ icon: string;
999
+ iconColor: string;
1000
+ title: string;
1001
+ url: string;
1002
+ buttonLabel: string;
1003
+ description?: string;
602
1004
  }
603
- interface FdeDesktopAPI {
604
- openApp: (appId: string, options?: OpenAppOptions) => void;
605
- closeWindow: (windowId?: string) => void;
606
- minimizeWindow: (windowId?: string) => void;
607
- maximizeWindow: (windowId?: string) => void;
608
- restoreWindow: (windowId?: string) => void;
609
- focusWindow: (windowId?: string) => void;
610
- openFile: (path: string, appId?: string) => void;
611
- openFileDialog: (options?: FileDialogOptions) => Promise<string | null>;
612
- saveFile: (content: string, options?: SaveDialogOptions) => Promise<boolean>;
613
- saveFileDialog: (options?: SaveDialogOptions) => Promise<string | null>;
614
- getTheme: () => Record<string, unknown>;
615
- setTheme: (theme: Record<string, unknown>) => void;
616
- showNotification: (options: NotificationOptions) => string;
617
- hideNotification: (notificationId: string) => void;
618
- getWindows: () => WindowEntity[];
619
- getActiveWindow: () => WindowEntity | null;
620
- getWindowById: (windowId: string) => WindowEntity | null;
621
- fs: IFileSystem;
622
- on: <T extends FdeEventType>(event: T, callback: (data: FdeEventPayloads[T]) => void) => () => void;
623
- off: <T extends FdeEventType>(event: T, callback: (data: FdeEventPayloads[T]) => void) => void;
624
- appReady: (appId: string) => void;
625
- registerAppInstance: (appId: string, instance: unknown) => void;
1005
+ declare const ExternalLinkApp: FC<WindowContentProps & {
1006
+ config: ExternalLinkAppConfig;
1007
+ }>;
1008
+
1009
+ declare const SUPPORTED_LANGUAGES$1: readonly ["en", "es"];
1010
+ type SupportedLanguage$1 = (typeof SUPPORTED_LANGUAGES$1)[number];
1011
+
1012
+ interface LanguageFlagProps {
1013
+ lang: SupportedLanguage$1;
1014
+ size?: number;
626
1015
  }
627
- declare global {
628
- interface Window {
629
- __FDE_API__?: FdeDesktopAPI;
630
- }
1016
+ declare const LanguageFlag: FC<LanguageFlagProps>;
1017
+
1018
+ interface CollapsibleSectionProps {
1019
+ title: string;
1020
+ fcIcon?: string;
1021
+ expanded: boolean;
1022
+ onToggle: () => void;
1023
+ children: ReactNode;
1024
+ className?: string;
1025
+ 'aria-label'?: string;
631
1026
  }
1027
+ declare const CollapsibleSection: FC<CollapsibleSectionProps>;
632
1028
 
633
- declare function useFdeApi(): FdeDesktopAPI | null;
1029
+ interface CustomAppLoaderProps {
1030
+ appId: string;
1031
+ windowIcon?: string;
1032
+ notifyReady?: WindowContentProps['notifyReady'];
1033
+ }
1034
+ declare const CustomAppLoader: FC<CustomAppLoaderProps>;
634
1035
 
635
- declare const useNotifications: () => {
636
- notifications: NotificationItem[];
637
- notify: (title: string, message: string, options?: {
638
- fcIcon?: string;
639
- onClose?: () => void;
640
- }) => string;
641
- dismiss: (id: string) => void;
642
- addNotification: (item: NotificationItem) => void;
643
- removeNotification: (id: string) => void;
644
- };
1036
+ interface CustomAppLoadingScreenProps {
1037
+ progress: LoadingProgress;
1038
+ windowIcon?: string;
1039
+ }
1040
+ declare const CustomAppLoadingScreen: FC<CustomAppLoadingScreenProps>;
645
1041
 
646
- declare const useSystemTheme: () => void;
1042
+ interface CustomAppOfflineProps {
1043
+ appId: string;
1044
+ }
1045
+ declare const CustomAppOffline: FC<CustomAppOfflineProps>;
1046
+
1047
+ interface CustomAppNotSupportedProps {
1048
+ appId: string;
1049
+ }
1050
+ declare const CustomAppNotSupported: FC<CustomAppNotSupportedProps>;
1051
+
1052
+ declare const registerCloseInterceptor: (windowId: string, interceptor: () => boolean) => void;
1053
+ declare const unregisterCloseInterceptor: (windowId: string) => void;
1054
+ declare const getCloseInterceptor: (windowId: string) => (() => boolean) | undefined;
1055
+ interface UseCloseInterceptorOptions {
1056
+ isDirtyGetter: () => boolean;
1057
+ windowId?: string;
1058
+ onDiscard?: () => void;
1059
+ onSave?: () => void;
1060
+ }
1061
+ declare function useCloseInterceptor({ isDirtyGetter, windowId, onDiscard, onSave, }: UseCloseInterceptorOptions): void;
1062
+
1063
+ declare function useAppName(appId: string | undefined): string;
1064
+
1065
+ declare function useFolderName(folder: {
1066
+ id: string;
1067
+ name: string;
1068
+ isPredefined: boolean;
1069
+ }): string;
1070
+
1071
+ declare const useClock: () => string;
647
1072
 
648
1073
  declare const useAnimationDuration: () => {
649
1074
  duration: number;
@@ -674,9 +1099,35 @@ declare const useAnimationDuration: () => {
674
1099
  easeOut: framer_motion.Transition;
675
1100
  };
676
1101
 
677
- declare function useAppName(appId: string | undefined): string;
1102
+ type IconLibrary = 'fi' | 'fc' | 'vsc';
1103
+ declare const useDynamicIcon: (name: string, library: IconLibrary) => IconType | null;
1104
+ declare const useDynamicIconElement: (name: string, library: IconLibrary, props?: IconBaseProps) => ReactElement | null;
1105
+ declare const useFiIcon: (name: string) => IconType | null;
1106
+ declare const useFcIcon: (name: string) => IconType | null;
1107
+ declare const useVscIcon: (name: string) => IconType | null;
1108
+ declare const useFiIconElement: (name: string, props?: IconBaseProps) => ReactElement | null;
1109
+ declare const useFcIconElement: (name: string, props?: IconBaseProps) => ReactElement | null;
1110
+ declare const useVscIconElement: (name: string, props?: IconBaseProps) => ReactElement | null;
678
1111
 
679
- declare const useClock: () => string;
1112
+ declare const useTaskbarHeight: (opened: boolean) => {
1113
+ menuRef: react.RefObject<HTMLDivElement | null>;
1114
+ menuHeight: number;
1115
+ };
1116
+
1117
+ type TaskbarMenuType = 'window' | 'panel' | 'launcher' | null;
1118
+ interface UseTaskbarContextMenuReturn {
1119
+ activeMenu: TaskbarMenuType;
1120
+ position: MenuPosition;
1121
+ targetWindowId: string | null;
1122
+ windowMenuOpened: boolean;
1123
+ panelMenuOpened: boolean;
1124
+ launcherMenuOpened: boolean;
1125
+ openWindowMenu: (e: React.MouseEvent, windowId: string) => void;
1126
+ openPanelMenu: (e: React.MouseEvent) => void;
1127
+ openLauncherMenu: (e: React.MouseEvent) => void;
1128
+ closeMenu: () => void;
1129
+ }
1130
+ declare const useTaskbarContextMenu: () => UseTaskbarContextMenuReturn;
680
1131
 
681
1132
  declare function useCollapsible(initialExpanded?: Set<string>): {
682
1133
  expanded: Set<string>;
@@ -689,10 +1140,33 @@ declare function useCollapsible(initialExpanded?: Set<string>): {
689
1140
  isExpanded: (id: string) => boolean;
690
1141
  };
691
1142
 
692
- interface MenuPosition {
693
- x: number;
694
- y: number;
1143
+ declare function useSearchFilter<T>(items: T[], searchQuery: string, getSearchableText: (item: T) => string | string[]): T[];
1144
+
1145
+ interface RegistryContextValue {
1146
+ register: (id: string, rect: DOMRect) => void;
1147
+ unregister: (id: string) => void;
1148
+ getRect: (id: string) => DOMRect | undefined;
695
1149
  }
1150
+ declare const WindowButtonRegistryProvider: FC<{
1151
+ children: ReactNode;
1152
+ }>;
1153
+ declare const useWindowButtonRegistry: () => RegistryContextValue;
1154
+
1155
+ declare const AVAILABLE_FONTS: {
1156
+ value: string;
1157
+ label: string;
1158
+ stack: string;
1159
+ }[];
1160
+ declare const FONT_STACKS: Record<string, string>;
1161
+ declare const GOOGLE_FONTS_HREF: Record<string, string>;
1162
+
1163
+ /**
1164
+ * Applies the currently selected font stack to the document root.
1165
+ * Also re-injects <link> tags for all previously downloaded fonts on mount.
1166
+ */
1167
+ declare const useApplyFont: () => void;
1168
+
1169
+ declare const useAppUpdate: () => void;
696
1170
 
697
1171
  interface UseContextMenuReturn {
698
1172
  opened: boolean;
@@ -702,141 +1176,68 @@ interface UseContextMenuReturn {
702
1176
  }
703
1177
  declare const useContextMenu: (offsetY?: number, appId?: string) => UseContextMenuReturn;
704
1178
 
705
- interface DeviceInfo {
706
- isMobile: boolean;
707
- isTablet: boolean;
708
- isDesktop: boolean;
709
- isPortrait: boolean;
710
- shouldShowWarning: boolean;
711
- screenWidth: number;
712
- screenHeight: number;
713
- }
714
- declare function useDeviceDetection(): DeviceInfo;
715
-
716
- type DownloadStatus = 'idle' | 'downloading' | 'done' | 'error';
717
- interface DownloadState {
718
- status: DownloadStatus;
719
- /** Bytes received so far */
720
- loaded: number;
721
- /** Total bytes, or null if Content-Length is not available */
722
- total: number | null;
723
- /** 0–100, or null when total is unknown */
724
- percent: number | null;
725
- error: string | null;
726
- }
727
- interface UseDownloadReturn extends DownloadState {
728
- download: (url: string) => Promise<string | null>;
729
- reset: () => void;
1179
+ type DragItemType = 'app' | 'file' | 'folder';
1180
+ type DropTargetType = 'launcher-folder' | 'filesystem-folder' | 'desktop' | 'available-apps';
1181
+ interface DragItemData {
1182
+ type: DragItemType;
1183
+ id: string;
1184
+ name: string;
1185
+ sourceId: string;
1186
+ sourceType: DropTargetType;
1187
+ metadata?: {
1188
+ fcIcon?: string;
1189
+ iconUrl?: string;
1190
+ icon?: string;
1191
+ iconColor?: string;
1192
+ };
730
1193
  }
731
- /**
732
- * Hook for tracking streamed HTTP downloads with real-time progress.
733
- * Returns a `download(url)` function that resolves with the response text
734
- * (or null on error) and updates progress state as data arrives.
735
- */
736
- declare const useDownload: () => UseDownloadReturn;
737
-
738
- type IconLibrary = 'fi' | 'fc' | 'vsc';
739
- declare const useDynamicIcon: (name: string, library: IconLibrary) => IconType | null;
740
- declare const useFiIcon: (name: string) => IconType | null;
741
- declare const useFcIcon: (name: string) => IconType | null;
742
- declare const useVscIcon: (name: string) => IconType | null;
743
-
744
- declare function useFolderName(folder: {
1194
+ interface DropTarget {
1195
+ type: DropTargetType;
745
1196
  id: string;
746
1197
  name: string;
747
- isPredefined: boolean;
748
- }): string;
749
-
750
- interface UseIsDirtyOptions<T> {
751
- /** Mutable ref that holds the snapshot (used internally). */
752
- snapshotRef: React.MutableRefObject<T | null>;
753
- /** Function that returns the current state of the app. */
754
- getCurrentState: () => T;
755
- /** Optional initial snapshot – used when no stored snapshot exists. */
756
- initialSnapshot?: T;
757
- /** Optional callback invoked when the dirty flag changes. */
758
- onChange?: (isDirty: boolean) => void;
759
- /** Unique identifier for the app – used to persist the snapshot in the global store. */
760
- appId?: string;
1198
+ accepts: DragItemType[];
761
1199
  }
762
- declare function useIsDirty<T>({ snapshotRef, getCurrentState, initialSnapshot, onChange, appId, }: UseIsDirtyOptions<T>): {
763
- isDirty: boolean;
764
- takeSnapshot: () => void;
765
- reset: () => void;
766
- };
767
-
768
- interface UseJsDosOptions {
769
- autoLoad?: {
770
- url: string;
771
- name?: string;
772
- };
1200
+ interface DragDropContextValue {
1201
+ activeItem: DragItemData | null;
1202
+ overTarget: DropTarget | null;
773
1203
  }
774
- interface UseJsDosReturn {
775
- containerRef: RefObject<HTMLDivElement | null>;
776
- isRunning: boolean;
777
- isPaused: boolean;
778
- isMuted: boolean;
779
- volume: number;
780
- isLoading: boolean;
781
- error: string | null;
782
- bundleName: string | null;
783
- loadBundle: (url: string, name?: string) => Promise<void>;
784
- exit: () => Promise<void>;
785
- restart: () => Promise<void>;
786
- pause: () => void;
787
- resume: () => void;
788
- mute: () => void;
789
- unmute: () => void;
790
- setVolume: (level: number) => void;
791
- }
792
- declare function useJsDos(options?: UseJsDosOptions): UseJsDosReturn;
793
-
794
- declare function useLanguageSync(): void;
795
-
796
- declare function useResolvedUrl(url: string | undefined): string | undefined;
797
-
798
- declare function useSearchFilter<T>(items: T[], searchQuery: string, getSearchableText: (item: T) => string | string[]): T[];
799
1204
 
800
- declare const useTaskbarHeight: (opened: boolean) => {
801
- menuRef: react.RefObject<HTMLDivElement | null>;
802
- menuHeight: number;
803
- };
804
-
805
- type TaskbarMenuType = 'window' | 'panel' | 'launcher' | null;
806
- interface UseTaskbarContextMenuReturn {
807
- activeMenu: TaskbarMenuType;
808
- position: MenuPosition;
809
- targetWindowId: string | null;
810
- windowMenuOpened: boolean;
811
- panelMenuOpened: boolean;
812
- launcherMenuOpened: boolean;
813
- openWindowMenu: (e: React.MouseEvent, windowId: string) => void;
814
- openPanelMenu: (e: React.MouseEvent) => void;
815
- openLauncherMenu: (e: React.MouseEvent) => void;
816
- closeMenu: () => void;
1205
+ interface DragDropProviderProps {
1206
+ children: ReactNode;
1207
+ onDrop: (item: DragItemData, target: DropTarget) => void;
1208
+ onCancel?: () => void;
817
1209
  }
818
- declare const useTaskbarContextMenu: () => UseTaskbarContextMenuReturn;
1210
+ declare const DragDropProvider: FC<DragDropProviderProps>;
819
1211
 
820
- interface RegistryContextValue {
821
- register: (id: string, rect: DOMRect) => void;
822
- unregister: (id: string) => void;
823
- getRect: (id: string) => DOMRect | undefined;
1212
+ interface UseDraggableItemOptions {
1213
+ item: DragItemData;
1214
+ disabled?: boolean;
824
1215
  }
825
- declare const useWindowButtonRegistry: () => RegistryContextValue;
1216
+ interface UseDraggableItemReturn {
1217
+ attributes: React.HTMLAttributes<HTMLElement>;
1218
+ listeners: Record<string, unknown> | undefined;
1219
+ setNodeRef: (node: HTMLElement | null) => void;
1220
+ isDragging: boolean;
1221
+ transform: {
1222
+ x: number;
1223
+ y: number;
1224
+ } | null;
1225
+ style: React.CSSProperties;
1226
+ }
1227
+ declare function useDraggableItem(options: UseDraggableItemOptions): UseDraggableItemReturn;
826
1228
 
827
- declare const AVAILABLE_FONTS: {
828
- value: string;
829
- label: string;
830
- stack: string;
831
- }[];
832
- declare const FONT_STACKS: Record<string, string>;
833
- declare const GOOGLE_FONTS_HREF: Record<string, string>;
1229
+ interface UseDroppableAreaOptions {
1230
+ target: DropTarget;
1231
+ disabled?: boolean;
1232
+ }
1233
+ interface UseDroppableAreaReturn {
1234
+ setNodeRef: (node: HTMLElement | null) => void;
1235
+ isOver: boolean;
1236
+ active: DragItemData | null;
1237
+ }
1238
+ declare function useDroppableArea(options: UseDroppableAreaOptions): UseDroppableAreaReturn;
834
1239
 
835
- /**
836
- * Applies the currently selected font stack to the document root.
837
- * Also re-injects <link> tags for all previously downloaded fonts on mount.
838
- */
839
- declare const useApplyFont: () => void;
1240
+ declare function useDragDropState(): DragDropContextValue;
840
1241
 
841
1242
  interface FontDownloadProgress {
842
1243
  status: 'idle' | 'downloading' | 'done' | 'error';
@@ -1031,166 +1432,302 @@ declare const useFontDownload: (font: string | null) => {
1031
1432
  promise: Promise<FontDownloadResult>;
1032
1433
  };
1033
1434
 
1034
- interface AdaptiveDimensions {
1035
- defaultWidth: number;
1036
- defaultHeight: number;
1037
- minWidth: number;
1038
- minHeight: number;
1039
- }
1040
- declare function useAdaptiveDimensions(): AdaptiveDimensions;
1041
-
1042
- type AppReloadCallback = (appId: string) => void;
1043
- type AppRegisteredCallback = (manifest: CustomAppManifest) => void;
1044
- type AppUnregisteredCallback = (appId: string) => void;
1045
- interface HMRCallbacks {
1046
- onReload: AppReloadCallback;
1047
- onRegistered?: AppRegisteredCallback;
1048
- onUnregistered?: AppUnregisteredCallback;
1435
+ interface UseIsDirtyOptions<T> {
1436
+ /** Mutable ref that holds the snapshot (used internally). */
1437
+ snapshotRef: React.MutableRefObject<T | null>;
1438
+ /** Function that returns the current state of the app. */
1439
+ getCurrentState: () => T;
1440
+ /** Optional initial snapshot – used when no stored snapshot exists. */
1441
+ initialSnapshot?: T;
1442
+ /** Optional callback invoked when the dirty flag changes. */
1443
+ onChange?: (isDirty: boolean) => void;
1444
+ /** Unique identifier for the app – used to persist the snapshot in the global store. */
1445
+ appId?: string;
1049
1446
  }
1050
- declare function useCustomAppHMR(callbacksArg: HMRCallbacks): void;
1447
+ declare function useIsDirty<T>({ snapshotRef, getCurrentState, initialSnapshot, onChange, appId, }: UseIsDirtyOptions<T>): {
1448
+ isDirty: boolean;
1449
+ takeSnapshot: () => void;
1450
+ reset: () => void;
1451
+ };
1051
1452
 
1052
- type LoadingState = 'idle' | 'fetching' | 'compiling' | 'loading' | 'ready' | 'error';
1453
+ declare function useLanguageSync(): void;
1053
1454
 
1054
- interface MenuItemAction {
1055
- type: 'item';
1056
- label: string;
1057
- icon?: string;
1058
- onClick: () => void;
1059
- disabled?: boolean;
1060
- }
1061
- interface MenuItemDivider {
1062
- type: 'divider';
1063
- }
1064
- interface MenuItemSlider {
1065
- type: 'slider';
1066
- label?: string;
1067
- min: number;
1068
- max: number;
1069
- value: number;
1070
- onChange: (value: number) => void;
1071
- labelFormat?: (value: number) => string;
1072
- }
1073
- type MenuItem = MenuItemAction | MenuItemDivider | MenuItemSlider;
1074
- interface AppMenuDropdown {
1075
- type: 'menu';
1076
- label: string;
1077
- icon?: string;
1078
- items: MenuItem[];
1079
- rightSection?: ReactNode;
1080
- }
1081
- interface AppMenuCombobox {
1082
- type: 'combobox';
1083
- label?: string;
1084
- options: string[];
1085
- value: string;
1086
- onChange: (value: string) => void;
1087
- }
1088
- interface AppMenuSwitch {
1089
- type: 'switch';
1090
- label: string;
1091
- checked: boolean;
1092
- onChange: (value: boolean) => void;
1093
- }
1094
- interface AppMenuSlider {
1095
- type: 'slider';
1096
- label?: string;
1097
- min: number;
1098
- max: number;
1099
- value: number;
1100
- onChange: (value: number) => void;
1101
- marks?: {
1102
- value: number;
1103
- label?: string;
1104
- }[];
1105
- labelFormat?: (value: number) => string;
1455
+ declare class IndexedDBFileSystem implements IFileSystem {
1456
+ private db;
1457
+ private nodes;
1458
+ private ready;
1459
+ private initPromise;
1460
+ private persistQueue;
1461
+ private persistScheduled;
1462
+ initialize(): Promise<void>;
1463
+ private doInitialize;
1464
+ private openDatabase;
1465
+ private loadNodes;
1466
+ private migrateFromLocalStorage;
1467
+ isReady(): boolean;
1468
+ reinitialize(): Promise<void>;
1469
+ private persistAllNodes;
1470
+ private schedulePersist;
1471
+ private flushPersistQueue;
1472
+ private persistNode;
1473
+ private deleteNodeFromPersist;
1474
+ saveBlob(blob: Blob): Promise<string>;
1475
+ getBlob(url: string): Promise<Blob | null>;
1476
+ toBlobUrl(url: string): Promise<string | null>;
1477
+ clearBlobs(): Promise<void>;
1478
+ readFile(_path: string): Promise<string>;
1479
+ writeFile(_path: string, _content: string): Promise<void>;
1480
+ getNode(id: string): FSNode | undefined;
1481
+ getChildren(folderId: string): FSNode[];
1482
+ getRootNodes(): FSNode[];
1483
+ getAllNodes(): FSNode[];
1484
+ isEmpty(): boolean;
1485
+ createFile(name: string, content: string, parentId: string | null, url?: string): Promise<FileNode>;
1486
+ createFolder(name: string, parentId: string | null, iconName?: string, iconColor?: string): Promise<FolderNode>;
1487
+ updateFile(id: string, content: string): Promise<FileNode>;
1488
+ move(id: string, newParentId: string | null): Promise<FSNode>;
1489
+ delete(id: string): Promise<void>;
1490
+ getManifestSha(): Promise<string | null>;
1491
+ saveManifestSha(sha: string): Promise<void>;
1492
+ clearAll(): Promise<void>;
1493
+ seed(manifest: FsManifest): Promise<void>;
1494
+ mergeSeed(manifest: FsManifest): Promise<void>;
1495
+ private buildFolderMapFromManifest;
1496
+ private addChildToFolder;
1497
+ private removeChildFromParent;
1498
+ private deleteRecursive;
1106
1499
  }
1107
- interface AppMenuTextInput {
1108
- type: 'text-input';
1109
- placeholder?: string;
1110
- value: string;
1111
- onChange: (value: string) => void;
1500
+
1501
+ declare function setApiBaseUrl(url: string): void;
1502
+ declare class DockerFileSystemAdapter implements IFileSystem {
1503
+ private nodes;
1504
+ private pathToId;
1505
+ private ready;
1506
+ private rootFolderId;
1507
+ private initPromise;
1508
+ constructor();
1509
+ initialize(): Promise<void>;
1510
+ private doInitialize;
1511
+ reinitialize(): Promise<void>;
1512
+ isReady(): boolean;
1513
+ isEmpty(): boolean;
1514
+ getNode(id: string): FSNode | undefined;
1515
+ getChildren(folderId: string): FSNode[];
1516
+ getRootNodes(): FSNode[];
1517
+ getAllNodes(): FSNode[];
1518
+ createFile(name: string, content: string, parentId: string | null, url?: string): Promise<FileNode>;
1519
+ createFolder(name: string, parentId: string | null, iconName?: string, iconColor?: string): Promise<FolderNode>;
1520
+ updateFile(id: string, content: string): Promise<FileNode>;
1521
+ move(id: string, newParentId: string | null): Promise<FSNode>;
1522
+ delete(id: string): Promise<void>;
1523
+ readFile(path: string): Promise<string>;
1524
+ writeFile(path: string, content: string): Promise<void>;
1525
+ saveBlob(blob: Blob): Promise<string>;
1526
+ getBlob(url: string): Promise<Blob | null>;
1527
+ toBlobUrl(url: string): Promise<string | null>;
1528
+ getManifestSha(): Promise<string | null>;
1529
+ saveManifestSha(_sha: string): Promise<void>;
1530
+ seed(_manifest: FsManifest): Promise<void>;
1531
+ mergeSeed(_manifest: FsManifest): Promise<void>;
1532
+ clearAll(): Promise<void>;
1533
+ private getMimeType;
1534
+ private getPathFromId;
1535
+ private deleteRecursive;
1536
+ private syncFromEntries;
1537
+ private fetchReaddir;
1538
+ private writeFileToServer;
1539
+ private createDirOnServer;
1540
+ private deleteFromServer;
1112
1541
  }
1113
- interface AppMenuNumberInput {
1114
- type: 'number-input';
1115
- label?: string;
1116
- value: number;
1117
- onChange: (value: number) => void;
1118
- min?: number;
1119
- max?: number;
1120
- step?: number;
1121
- placeholder?: string;
1542
+
1543
+ declare const fileSystem: IndexedDBFileSystem | DockerFileSystemAdapter;
1544
+ declare const resetFileSystem: () => void;
1545
+ declare const resetWindowManager: () => void;
1546
+ declare function resolveFileUrl(url: string, signal?: AbortSignal): Promise<string>;
1547
+ declare const useDesktopStore: zustand.UseBoundStore<Omit<zustand.StoreApi<DesktopState>, "setState" | "persist"> & {
1548
+ setState(partial: DesktopState | Partial<DesktopState> | ((state: DesktopState) => DesktopState | Partial<DesktopState>), replace?: false | undefined): unknown;
1549
+ setState(state: DesktopState | ((state: DesktopState) => DesktopState), replace: true): unknown;
1550
+ persist: {
1551
+ setOptions: (options: Partial<zustand_middleware.PersistOptions<DesktopState, unknown, unknown>>) => void;
1552
+ clearStorage: () => void;
1553
+ rehydrate: () => Promise<void> | void;
1554
+ hasHydrated: () => boolean;
1555
+ onHydrate: (fn: (state: DesktopState) => void) => () => void;
1556
+ onFinishHydration: (fn: (state: DesktopState) => void) => () => void;
1557
+ getOptions: () => Partial<zustand_middleware.PersistOptions<DesktopState, unknown, unknown>>;
1558
+ };
1559
+ }>;
1560
+
1561
+ declare const getPersistedThemeMode: () => ThemeMode | null;
1562
+ declare const useSettingsStore: zustand.UseBoundStore<Omit<zustand.StoreApi<ISettingsState>, "setState" | "persist"> & {
1563
+ setState(partial: ISettingsState | Partial<ISettingsState> | ((state: ISettingsState) => ISettingsState | Partial<ISettingsState>), replace?: false | undefined): unknown;
1564
+ setState(state: ISettingsState | ((state: ISettingsState) => ISettingsState), replace: true): unknown;
1565
+ persist: {
1566
+ setOptions: (options: Partial<zustand_middleware.PersistOptions<ISettingsState, unknown, unknown>>) => void;
1567
+ clearStorage: () => void;
1568
+ rehydrate: () => Promise<void> | void;
1569
+ hasHydrated: () => boolean;
1570
+ onHydrate: (fn: (state: ISettingsState) => void) => () => void;
1571
+ onFinishHydration: (fn: (state: ISettingsState) => void) => () => void;
1572
+ getOptions: () => Partial<zustand_middleware.PersistOptions<ISettingsState, unknown, unknown>>;
1573
+ };
1574
+ }>;
1575
+
1576
+ declare const useCustomAppStore: zustand.UseBoundStore<zustand.StoreApi<CustomAppState>>;
1577
+
1578
+ interface AppTempMemoryState {
1579
+ snapshots: Record<string, unknown>;
1580
+ setSnapshot: (appId: string, snapshot: unknown) => void;
1581
+ getSnapshot: (appId: string) => unknown | null;
1582
+ clearSnapshot: (appId: string) => void;
1122
1583
  }
1123
- interface AppMenuSelect {
1124
- type: 'select';
1125
- label?: string;
1126
- options: {
1127
- value: string;
1128
- label: string;
1129
- }[];
1130
- value: string;
1131
- onChange: (value: string) => void;
1584
+ declare const useAppTempMemoryStore: zustand.UseBoundStore<Omit<zustand.StoreApi<AppTempMemoryState>, "setState" | "persist"> & {
1585
+ setState(partial: AppTempMemoryState | Partial<AppTempMemoryState> | ((state: AppTempMemoryState) => AppTempMemoryState | Partial<AppTempMemoryState>), replace?: false | undefined): unknown;
1586
+ setState(state: AppTempMemoryState | ((state: AppTempMemoryState) => AppTempMemoryState), replace: true): unknown;
1587
+ persist: {
1588
+ setOptions: (options: Partial<zustand_middleware.PersistOptions<AppTempMemoryState, unknown, unknown>>) => void;
1589
+ clearStorage: () => void;
1590
+ rehydrate: () => Promise<void> | void;
1591
+ hasHydrated: () => boolean;
1592
+ onHydrate: (fn: (state: AppTempMemoryState) => void) => () => void;
1593
+ onFinishHydration: (fn: (state: AppTempMemoryState) => void) => () => void;
1594
+ getOptions: () => Partial<zustand_middleware.PersistOptions<AppTempMemoryState, unknown, unknown>>;
1595
+ };
1596
+ }>;
1597
+
1598
+ interface CloseModalState {
1599
+ isOpen: boolean;
1600
+ windowId: string | null;
1601
+ onSave: (() => void) | null;
1602
+ onDiscard: (() => void) | null;
1132
1603
  }
1133
- interface AppMenuDirtyIndicator {
1134
- type: 'dirty-indicator';
1604
+ interface CloseModalActions {
1605
+ openModal: (windowId: string, onSave: () => void, onDiscard: () => void) => void;
1606
+ closeModal: () => void;
1135
1607
  }
1136
- type AppMenuElement = AppMenuDropdown | AppMenuCombobox | AppMenuSwitch | AppMenuSlider | AppMenuTextInput | AppMenuNumberInput | AppMenuSelect | AppMenuDirtyIndicator;
1608
+ declare const useCloseModalStore: zustand.UseBoundStore<zustand.StoreApi<CloseModalState & CloseModalActions>>;
1137
1609
 
1138
- interface WindowContentProps {
1139
- window?: WindowEntity;
1140
- notifyReady?: (contentData?: Record<string, unknown>) => void;
1610
+ interface AdaptiveDimensions {
1611
+ defaultWidth: number;
1612
+ defaultHeight: number;
1613
+ minWidth: number;
1614
+ minHeight: number;
1141
1615
  }
1142
- type AppComponent = FC<WindowContentProps>;
1143
- type MenuBarBuilder = (window: WindowEntity) => AppMenuElement[] | undefined;
1144
- interface MenuBarComponentProps {
1145
- windowId: string;
1146
- onExit: () => void;
1616
+ declare function useAdaptiveDimensions(): AdaptiveDimensions;
1617
+
1618
+ declare const useNotifications: () => {
1619
+ notifications: NotificationItem[];
1620
+ notify: (title: string, message: string, options?: {
1621
+ fcIcon?: string;
1622
+ onClose?: () => void;
1623
+ }) => string;
1624
+ dismiss: (id: string) => void;
1625
+ addNotification: (item: NotificationItem) => void;
1626
+ removeNotification: (id: string) => void;
1627
+ };
1628
+
1629
+ declare const useSystemTheme: () => void;
1630
+
1631
+ type OpenHookOptions = {
1147
1632
  contentData?: Record<string, unknown>;
1633
+ position?: {
1634
+ x: number;
1635
+ y: number;
1636
+ };
1637
+ };
1638
+ declare const useOpenApp: () => (appId: string, { contentData, position }?: OpenHookOptions) => void;
1639
+
1640
+ declare function useFdeApi(): FdeDesktopAPI | null;
1641
+
1642
+ declare function useResolvedUrl(url: string | undefined): string | undefined;
1643
+
1644
+ interface DeviceInfo {
1645
+ isMobile: boolean;
1646
+ isTablet: boolean;
1647
+ isDesktop: boolean;
1648
+ isPortrait: boolean;
1649
+ shouldShowWarning: boolean;
1650
+ screenWidth: number;
1651
+ screenHeight: number;
1148
1652
  }
1149
- type MenuBarComponent = FC<MenuBarComponentProps>;
1150
- interface AppRegistration {
1151
- component: AppComponent;
1152
- buildMenuBar?: MenuBarBuilder;
1153
- MenuBarComponent?: MenuBarComponent;
1653
+ declare function useDeviceDetection(): DeviceInfo;
1654
+
1655
+ type AppReloadCallback = (appId: string) => void;
1656
+ type AppRegisteredCallback = (manifest: CustomAppManifest) => void;
1657
+ type AppUnregisteredCallback = (appId: string) => void;
1658
+ interface HMRCallbacks {
1659
+ onReload: AppReloadCallback;
1660
+ onRegistered?: AppRegisteredCallback;
1661
+ onUnregistered?: AppUnregisteredCallback;
1154
1662
  }
1663
+ /**
1664
+ * Reset connection state - useful for testing
1665
+ * @internal
1666
+ */
1667
+ declare function resetHMRState(): void;
1668
+ declare function checkHMREndpointExists(): Promise<boolean>;
1669
+ declare function useCustomAppHMR(callbacksArg: HMRCallbacks): void;
1670
+ declare function useCustomAppLifecycle(): void;
1155
1671
 
1156
- type Runtime = 'browser' | 'docker' | 'electron';
1157
1672
  /**
1158
- * Detects the current runtime environment.
1159
- * - browser: Standard web browser
1160
- * - docker: Running inside Docker container (detected via injected flag)
1161
- * - electron: Electron desktop app
1673
+ * Appends a dirty-indicator element to menu items if dirty.
1674
+ * Returns a new array when dirty (immutable), or the original array when not dirty.
1675
+ *
1676
+ * @param items - The array of menu elements
1677
+ * @param isDirty - Whether there are unsaved changes
1678
+ * @returns The same array if not dirty, or a new array with dirty-indicator appended
1679
+ *
1680
+ * @example
1681
+ * const items: AppMenuElement[] = [
1682
+ * { type: 'menu', label: 'File', items: [...] }
1683
+ * ];
1684
+ *
1685
+ * return appendDirtyIndicator(items, isDirty);
1162
1686
  */
1687
+ declare function appendDirtyIndicator(items: AppMenuElement[], isDirty: boolean): AppMenuElement[];
1688
+
1689
+ declare const injectFontLink: (font: string) => void;
1690
+
1691
+ type Runtime = 'browser' | 'docker' | 'electron';
1163
1692
  declare function getRuntime(): Runtime;
1164
1693
  declare function isDocker(): boolean;
1165
1694
  declare function isElectron(): boolean;
1166
1695
  declare function isBrowser(): boolean;
1167
- /**
1168
- * Detects if running in development mode.
1169
- * - Checks window.__IS_DEV__ flag (injected by Docker entrypoint)
1170
- * - Falls back to hostname detection for local development
1171
- */
1172
1696
  declare function isDev(): boolean;
1173
1697
 
1174
1698
  declare function generateUUID(): string;
1175
1699
 
1176
- /**
1177
- * Waits for a DOM element with the given ID to appear in the document.
1178
- * Uses polling with 1 second intervals.
1179
- *
1180
- * @param containerId - The ID of the container element to wait for (without #)
1181
- * @param timeout - Maximum time to wait in milliseconds (default: 5000)
1182
- * @returns Promise that resolves with the container element
1183
- * @throws Error if container is not found within timeout
1184
- */
1185
1700
  declare function waitForContainer(containerId: string, timeout?: number): Promise<HTMLElement>;
1186
1701
 
1702
+ declare function setTestBaseUrl(url: string | null): void;
1187
1703
  declare function getBaseUrl(): string;
1704
+ declare function resetBaseUrlCache(): void;
1188
1705
  declare function resolveUrl(relativeUrl: string): string;
1189
1706
 
1707
+ declare const sortNodes: (nodes: FSNode[]) => FSNode[];
1708
+ declare const SortOptions: {
1709
+ readonly BY_TYPE: "byType";
1710
+ readonly BY_NAME: "byName";
1711
+ readonly BY_DATE: "byDate";
1712
+ };
1713
+ type SortOption = (typeof SortOptions)[keyof typeof SortOptions];
1714
+ type DesktopSortMode = 'default' | 'name-asc' | 'name-desc' | 'type';
1715
+ declare function sortDesktopIcons(icons: DesktopIconEntity[], desktopAppsOrder?: readonly string[]): DesktopIconEntity[];
1716
+ declare const sortDesktopIconsByMode: (icons: DesktopIconEntity[], mode: DesktopSortMode) => DesktopIconEntity[];
1717
+ declare const sortNodesByMode: (nodes: FSNode[], mode: DesktopSortMode) => FSNode[];
1718
+
1190
1719
  declare function formatBytes(bytes: number): string;
1191
1720
 
1192
1721
  declare function hashBlob(blob: Blob): Promise<string>;
1193
1722
 
1723
+ interface AppFileHandler {
1724
+ appId: string;
1725
+ mimeTypes: string[] | ((mimeType: string) => boolean);
1726
+ transformContentData: (node: FileNode) => Record<string, unknown>;
1727
+ }
1728
+ declare const registerAppFileHandler: (handler: AppFileHandler) => void;
1729
+ declare const IMAGE_MIME_TYPES: Set<string>;
1730
+ declare const TEXT_MIME_TYPES: Set<string>;
1194
1731
  declare function getAppIdForMime(mimeType: string | undefined): string;
1195
1732
  declare function getAppIdForMime(node: FileNode): {
1196
1733
  appId: string;
@@ -1207,104 +1744,26 @@ type Breadcrumb = {
1207
1744
  id: string | null;
1208
1745
  name: string;
1209
1746
  };
1210
- /**
1211
- * Builds a breadcrumb trail from the root to the given folder.
1212
- * Always starts with `{ id: null, name: 'Home' }`.
1213
- */
1214
1747
  declare const buildBreadcrumbs: (currentFolderId: string | null, fsNodes: FSNode[]) => Breadcrumb[];
1215
1748
 
1216
1749
  declare const isNewerVersion: (latest: string, current: string) => boolean;
1217
1750
 
1218
- /**
1219
- * Clears all browser data: Service Workers, Cache API, IndexedDB, localStorage, sessionStorage.
1220
- * Useful for tests and for the reset settings feature.
1221
- */
1222
1751
  interface ClearBrowserDataOptions {
1223
- /** If true, keep IndexedDB databases (user files) */
1224
1752
  keepIndexedDB?: boolean;
1225
- /** If true, keep Service Workers registered */
1226
1753
  keepServiceWorker?: boolean;
1227
- /** If true, keep localStorage */
1228
1754
  keepLocalStorage?: boolean;
1229
- /** If true, keep sessionStorage */
1230
1755
  keepSessionStorage?: boolean;
1231
1756
  }
1232
- /**
1233
- * Clears all browser data with configurable options.
1234
- *
1235
- * @param options - Configuration options for what to keep
1236
- *
1237
- * @example
1238
- * // Clear everything (full reset)
1239
- * await clearBrowserData();
1240
- *
1241
- * @example
1242
- * // Keep user files (IndexedDB)
1243
- * await clearBrowserData({ keepIndexedDB: true });
1244
- *
1245
- * @example
1246
- * // Keep everything except cache
1247
- * await clearBrowserData({ keepIndexedDB: true, keepServiceWorker: true, keepLocalStorage: true });
1248
- */
1249
1757
  declare function clearBrowserData(options?: ClearBrowserDataOptions): Promise<void>;
1250
1758
 
1251
- declare const WelcomeApp: AppEntry;
1252
- declare const StorybookApp: AppEntry;
1253
- declare const LinkedinApp: AppEntry;
1254
- declare const GithubApp: AppEntry;
1255
- declare const TerminalApp: AppEntry;
1256
- declare const CodeServerApp: AppEntry;
1257
- declare const DosEmulatorApp: AppEntry;
1258
- declare const DoomApp: AppEntry;
1259
- declare const EXTRA_APPS: AppEntry[];
1260
- declare const EXTRA_APP_IDS: string[];
1261
-
1262
- declare const APPS: AppEntry[];
1263
- declare const DESKTOP_APPS_ORDER: string[];
1264
- declare function registerCustomApps(apps: AppEntry[]): void;
1265
- declare function registerDesktopApps(appIds: string[]): void;
1266
-
1267
- declare const APP_IDS: {
1268
- readonly WELCOME: "welcome";
1269
- readonly NOTEPAD: "notepad";
1270
- readonly UPLOADER: "uploader";
1271
- readonly FILES: "files";
1272
- readonly SETTINGS: "settings";
1273
- readonly PDF: "pdf";
1274
- readonly CALENDAR: "calendar";
1275
- readonly STORYBOOK: "storybook";
1276
- readonly LINKEDIN: "linkedin";
1277
- readonly GITHUB: "github";
1278
- readonly IMAGE_VIEWER: "image-viewer";
1279
- readonly DOS_EMULATOR: "dos-emulator";
1280
- readonly DOOM: "doom";
1281
- readonly TERMINAL: "terminal";
1282
- readonly CODE_SERVER: "code-server";
1283
- readonly DEVICE_INFO: "device-info";
1284
- readonly MENUEDIT: "menuedit";
1285
- };
1286
-
1287
- declare const CUSTOM_APPS_FOLDER_ID = "launcher-folder-custom-apps";
1288
- declare const DEFAULT_LAUNCHER_FOLDERS: LauncherFolder[];
1289
-
1290
- declare const BREAKPOINTS: {
1291
- readonly MOBILE: 768;
1292
- readonly TABLET: 1024;
1293
- readonly DESKTOP: 1280;
1759
+ declare const DEFAULT_WINDOW_DIMENSIONS: {
1760
+ readonly defaultWidth: 800;
1761
+ readonly defaultHeight: 600;
1762
+ readonly minWidth: 640;
1763
+ readonly minHeight: 480;
1294
1764
  };
1295
-
1296
- declare const TASKBAR_HEIGHT = 48;
1297
- declare const ICON_COLUMN_WIDTH = 80;
1298
- declare const ICON_ROW_HEIGHT = 80;
1299
- declare const ICON_MARGIN = 20;
1300
- declare const DEFAULT_VIEWPORT_WIDTH: 1280;
1301
- declare const DEFAULT_VIEWPORT_HEIGHT: 800;
1302
-
1303
- declare const DEFAULT_THEME_COLORS: Record<ThemeMode, Theme>;
1304
-
1305
- declare const PRESET_COLORS: string[];
1306
-
1307
- declare const PRESET_ICONS: string[];
1765
+ declare const CORE_APPS: AppEntry[];
1766
+ declare const CORE_APP_IDS: string[];
1308
1767
 
1309
1768
  declare const ANIMATION_DURATION = 0.3;
1310
1769
  declare const createEaseIn: (duration: number) => Transition;
@@ -1401,37 +1860,94 @@ declare const centerWindowPosition: (viewportWidth: number, viewportHeight: numb
1401
1860
  y: number;
1402
1861
  };
1403
1862
 
1404
- declare const createWindow: (input: WindowInput) => WindowEntity;
1863
+ declare const BREAKPOINTS: {
1864
+ readonly MOBILE: 768;
1865
+ readonly TABLET: 1024;
1866
+ readonly DESKTOP: 1280;
1867
+ };
1868
+ type Breakpoint = (typeof BREAKPOINTS)[keyof typeof BREAKPOINTS];
1405
1869
 
1406
- declare const createDesktopIcon: (input: DesktopIconInput) => DesktopIconEntity;
1870
+ declare const TASKBAR_HEIGHT = 48;
1871
+ declare const ICON_COLUMN_WIDTH = 80;
1872
+ declare const ICON_ROW_HEIGHT = 80;
1873
+ declare const ICON_MARGIN = 20;
1874
+ declare const DEFAULT_VIEWPORT_WIDTH: 1280;
1875
+ declare const DEFAULT_VIEWPORT_HEIGHT: 800;
1407
1876
 
1408
- declare function initializeFdeApi(): void;
1409
- declare function isFdeApiInitialized(): boolean;
1877
+ declare const APP_IDS: {
1878
+ readonly WELCOME: "welcome";
1879
+ readonly NOTEPAD: "notepad";
1880
+ readonly UPLOADER: "uploader";
1881
+ readonly FILES: "files";
1882
+ readonly SETTINGS: "settings";
1883
+ readonly PDF: "pdf";
1884
+ readonly CALENDAR: "calendar";
1885
+ readonly STORYBOOK: "storybook";
1886
+ readonly LINKEDIN: "linkedin";
1887
+ readonly GITHUB: "github";
1888
+ readonly IMAGE_VIEWER: "image-viewer";
1889
+ readonly DOS_EMULATOR: "dos-emulator";
1890
+ readonly DOOM: "doom";
1891
+ readonly TERMINAL: "terminal";
1892
+ readonly CODE_SERVER: "code-server";
1893
+ readonly DEVICE_INFO: "device-info";
1894
+ readonly MENUEDIT: "menuedit";
1895
+ };
1896
+ declare const APP_ID_TO_TRANSLATION_KEY: Record<string, string>;
1897
+ type AppId = (typeof APP_IDS)[keyof typeof APP_IDS];
1898
+ declare const DESKTOP_APPS: AppId[];
1410
1899
 
1411
- interface IWindowManager {
1412
- getAll(): WindowEntity[];
1413
- getById(id: string): WindowEntity | undefined;
1414
- open(input: WindowInput): WindowEntity;
1415
- close(id: string): void;
1416
- minimize(id: string): void;
1417
- maximize(id: string): void;
1418
- restore(id: string): void;
1419
- focus(id: string): void;
1420
- move(id: string, x: number, y: number): void;
1421
- resize(id: string, width: number, height: number): void;
1422
- loadWindows(windows: WindowEntity[]): void;
1900
+ declare const EXTRA_APPS: AppEntry[];
1901
+ declare const EXTRA_APP_IDS: string[];
1902
+
1903
+ declare const PRESET_COLORS: string[];
1904
+
1905
+ declare const DEFAULT_THEME_COLORS: Record<ThemeMode, Theme>;
1906
+
1907
+ declare const PRESET_ICONS: string[];
1908
+
1909
+ declare const CUSTOM_APPS_FOLDER_ID = "launcher-folder-custom-apps";
1910
+ declare const PREDEFINED_LAUNCHER_FOLDERS: LauncherFolder[];
1911
+ declare const DEFAULT_LAUNCHER_FOLDERS: LauncherFolder[];
1912
+
1913
+ declare const APPS: AppEntry[];
1914
+ declare const DESKTOP_APPS_ORDER: string[];
1915
+ declare function registerCustomApps(apps: AppEntry[]): void;
1916
+ declare function registerDesktopApps(appIds: string[]): void;
1917
+
1918
+ declare const GITHUB_RELEASES_REPO = "frannunpal/frannunpal.github.io";
1919
+ declare const GITHUB_LATEST_RELEASE_URL = "https://api.github.com/repos/frannunpal/frannunpal.github.io/releases/latest";
1920
+
1921
+ declare const PROFILE: {
1922
+ name: string;
1923
+ title: string;
1924
+ email: string;
1925
+ phone: string;
1926
+ location: string;
1927
+ linkedin: string;
1928
+ github: string;
1929
+ cvUrls: {
1930
+ en: string;
1931
+ es: string;
1932
+ };
1933
+ };
1934
+
1935
+ declare global {
1936
+ interface Window {
1937
+ __FDE_IN_DOCKER__?: boolean;
1938
+ }
1423
1939
  }
1940
+ declare const APP_VERSION: string;
1941
+
1942
+ declare const getVersionString: () => string;
1943
+ declare const getEnvironment: () => string;
1944
+ declare const getReleaseType: () => string;
1424
1945
 
1425
1946
  declare class WindowManagerAdapter implements IWindowManager {
1426
1947
  private windows;
1427
1948
  private nextZIndex;
1428
1949
  private assignZIndex;
1429
1950
  reset(): void;
1430
- /**
1431
- * Restores persisted windows into the adapter and synchronizes the
1432
- * nextZIndex counter so that subsequent focus/open calls always produce
1433
- * a value strictly higher than any already-persisted zIndex.
1434
- */
1435
1951
  loadWindows(windows: WindowEntity[]): void;
1436
1952
  getAll(): WindowEntity[];
1437
1953
  getById(id: string): WindowEntity | undefined;
@@ -1446,12 +1962,58 @@ declare class WindowManagerAdapter implements IWindowManager {
1446
1962
  private updateWindow;
1447
1963
  }
1448
1964
 
1965
+ declare class DefaultThemeProvider implements IThemeProvider {
1966
+ private mode;
1967
+ private customColors;
1968
+ constructor(initialMode?: ThemeMode);
1969
+ getTheme(): FdeTheme;
1970
+ setMode(mode: ThemeMode): void;
1971
+ setCustomColors(colors: CustomThemeColors | null): void;
1972
+ toggle(): void;
1973
+ }
1974
+
1449
1975
  declare const toMantineTheme: (theme: Theme) => MantineThemeOverride;
1450
1976
 
1977
+ declare function initializeFdeApi(): void;
1978
+ declare function getFdeApi(): FdeDesktopAPI;
1979
+ declare function isFdeApiInitialized(): boolean;
1980
+
1451
1981
  type AppLoader = () => Promise<unknown>;
1452
1982
  declare function prefetchApps(apps: Array<{
1453
1983
  id: string;
1454
1984
  loader: AppLoader;
1455
1985
  }>): void;
1456
1986
 
1457
- export { ANIMATION_DURATION, APPS, APP_IDS, AVAILABLE_FONTS, type AppComponent, type AppEntry, type AppMenuElement, type AppRegistration, BREAKPOINTS, CORE_APPS, CORE_APP_IDS, CUSTOM_APPS_FOLDER_ID, CalendarApp, type ClipboardAction, type ClipboardState, CodeServerApp, type CreateFolderOptions, type CustomAppState, type CustomThemeColors, DEFAULT_LAUNCHER_FOLDERS, DEFAULT_THEME_COLORS, DEFAULT_VIEWPORT_HEIGHT, DEFAULT_VIEWPORT_WIDTH, DEFAULT_WINDOW_DIMENSIONS, DESKTOP_APPS_ORDER, type DesktopIconInput, type DesktopState, DeviceInfoApp, DockerFileSystemAdapter, DoomApp, DosEmulatorApp, EASE_IN, EASE_OUT, EXTRA_APPS, EXTRA_APP_IDS, FONT_STACKS, type FSNode, type FileNode, FilesApp, type FolderNode, type FsManifest, type FsManifestFile, GOOGLE_FONTS_HREF, GithubApp, ICON_COLUMN_WIDTH, ICON_MARGIN, ICON_ROW_HEIGHT, type IFileSystem, type ISettingsState, ImageViewerApp, IndexedDBFileSystem, LinkedinApp, type LoadingState, type MenuBarBuilder, type MenuBarComponent, type MenuBarComponentProps, MenuEditApp, type MenuPosition, type MountedAppState, NotepadApp, type NotificationItem, PRESET_COLORS, PRESET_ICONS, PdfApp, SettingsApp, StorybookApp, TASKBAR_HEIGHT, TerminalApp, UploaderApp, WelcomeApp, type WindowContentProps, type WindowEntity, type WindowInput, WindowManagerAdapter, type WindowState, buildBreadcrumbs, centerWindowPosition, clearBrowserData, createDesktopIcon, createEaseIn, createEaseOut, createLauncherFolder, createMaximizeTransition, createMinimizeVariant, createPanelVariants, createRestoreVariant, createWindow, createWindowVariants, fileSystem, formatBytes, generateUUID, getAppIdForMime, getBaseUrl, getFileExtension, getFourRandomColors, getMimeTypeFromExtension, getRuntime, hashBlob, initializeFdeApi, isBrowser, isDev, isDocker, isElectron, isFdeApiInitialized, isNewerVersion, maximizeTransition, minimizeVariant, openVariants, panelVariants, prefetchApps, randomWindowPosition, registerCustomApps, registerDesktopApps, resetFileSystem, resetWindowManager, resolveUrl, restoreVariant, sortDesktopIcons, sortDesktopIconsByMode, sortNodes, toMantineTheme, updateLauncherFolder, useAdaptiveDimensions, useAnimationDuration, useAppName, useAppTempMemoryStore, useApplyFont, useClock, useCollapsible, useContextMenu, useCustomAppHMR, useCustomAppStore, useDesktopStore, useDeviceDetection, useDownload, useDynamicIcon, useFcIcon, useFdeApi, useFiIcon, useFolderName, useFontDownload, useIsDirty, useJsDos, useLanguageSync, useNotifications, useOpenApp, useResolvedUrl, useSearchFilter, useSettingsStore, useSystemTheme, useTaskbarContextMenu, useTaskbarHeight, useVscIcon, useWindowButtonRegistry, waitForContainer, windowVariants };
1987
+ /**
1988
+ * Storage Migration Utility
1989
+ *
1990
+ * Migrates legacy storage keys from 'fran-desktop' prefix to 'fde-desktop' prefix.
1991
+ * This migration is idempotent and safe to run multiple times.
1992
+ *
1993
+ * Migration includes:
1994
+ * - IndexedDB databases: fran-desktop-fs → fde-desktop-fs, fran-desktop-blobs → fde-desktop-blobs
1995
+ * - localStorage keys: fran-desktop:* → fde-desktop:*
1996
+ * - Zustand persist key: fran-desktop → fde-desktop
1997
+ */
1998
+ interface MigrationResult {
1999
+ indexedDB: {
2000
+ fs: boolean;
2001
+ blobs: boolean;
2002
+ };
2003
+ localStorage: {
2004
+ keysMigrated: number;
2005
+ };
2006
+ version: number;
2007
+ }
2008
+ /**
2009
+ * Runs the complete storage migration
2010
+ *
2011
+ * @returns MigrationResult with details about what was migrated
2012
+ */
2013
+ declare function migrateStorage(): Promise<MigrationResult>;
2014
+
2015
+ declare const SUPPORTED_LANGUAGES: readonly ["en", "es"];
2016
+ type SupportedLanguage = (typeof SUPPORTED_LANGUAGES)[number];
2017
+ declare const DEFAULT_LANGUAGE: SupportedLanguage;
2018
+
2019
+ export { ANIMATION_DURATION, APPS, APP_IDS, APP_ID_TO_TRANSLATION_KEY, APP_VERSION, AVAILABLE_FONTS, type AdaptiveDimensions, type AppComponent, AppEmptyState, type AppEntry, type AppFileHandler, AppIcon, type AppId, AppLoading, type AppLoadingProps, AppMenuBar, type AppMenuElement, type AppReadyContextValue, AppReadyProvider, type AppRegistration, type AppRegistryEntry, type AppsManifest, BREAKPOINTS, type Breadcrumb, type Breakpoint, CORE_APPS, CORE_APP_IDS, CORE_REGISTRY, CUSTOM_APPS_FOLDER_ID, CalendarApp, CalendarAppLazy, type ClearBrowserDataOptions, type ClipboardAction, type ClipboardState, CollapsibleSection, ColorPicker, ContextMenu, ContextMenuAnchor, type CreateFolderOptions, CreateItemApp, CreateItemAppLazy, CreateItemContextMenu, CustomAppLoader, CustomAppLoadingScreen, type CustomAppManifest, CustomAppNotSupported, CustomAppOffline, type CustomAppState, type CustomThemeColors, DEFAULT_FDE_THEME, DEFAULT_LANGUAGE, DEFAULT_LAUNCHER_FOLDERS, DEFAULT_THEME_COLORS, DEFAULT_VIEWPORT_HEIGHT, DEFAULT_VIEWPORT_WIDTH, DEFAULT_WINDOW_DIMENSIONS, DESKTOP_APPS, DESKTOP_APPS_ORDER, DefaultThemeProvider, Desktop, type DesktopAreaProps, type DesktopContextMenuProps, DesktopIcon, type DesktopIconEntity, type DesktopIconInput, type DesktopIconProps, type DesktopProps, type DesktopSortMode$1 as DesktopSortMode, type DesktopState, type DesktopTheme, type DeviceInfo, DeviceInfoApp, DeviceInfoAppLazy, DirtyIndicator, DockerFileSystemAdapter, DownloadProgress, type DownloadState, type DownloadStatus, DragDropProvider, type DropTargetType, DynamicMenuBarRenderer, EASE_IN, EASE_OUT, EXTRA_APPS, EXTRA_APP_IDS, ExternalLinkApp, FONT_STACKS, type FSNode, type FdeContextValue, FdeDesktop, type FdeDesktopAPI, type FdeDesktopProps, type FdeEventPayloads, type FdeEventType, FdeProvider, type FdeProviderProps, type FdeTheme, type FileDialogOptions, FileIcon, type FileIconProps, type FileNode, FilePickerApp, FilePickerModal, type FileSystemNode, type FileSystemNodeType, FilesApp, FilesAppLazy, type FolderNode, PickerModal as FolderPicker, type FontDownloadProgress, type FsManifest, type FsManifestFile, GITHUB_LATEST_RELEASE_URL, GITHUB_RELEASES_REPO, GOOGLE_FONTS_HREF, ICON_COLUMN_WIDTH, ICON_MARGIN, ICON_ROW_HEIGHT, type IFileSystem, IMAGE_MIME_TYPES, type ISettingsState, type IThemeProvider, type IWindowManager, IconColorPicker, ImageViewerApp, ImageViewerAppLazy, ImageViewerMenuBar, ImageViewerMenuBarLazy, IndexedDBFileSystem, LanguageFlag, LanguageSelector, Launcher, type LauncherFolder, type LauncherFolderInput, type LauncherProps, type LoadingProgress, type LoadingState, type MenuBarBuilder, type MenuBarComponent, type MenuBarComponentProps, MenuEditApp, MenuEditAppLazy, MenuEditMenuBar, MenuEditMenuBarLazy, type MenuItem, type MenuPosition, type MountedAppState, NotesApp, NotesAppLazy, NotesMenuBar, NotesMenuBarLazy, type NotificationItem, type NotificationOptions, type OpenAppOptions, PREDEFINED_LAUNCHER_FOLDERS, PRESET_COLORS, PRESET_ICONS, PROFILE, type PartialFdeTheme, PdfApp, PdfAppLazy, PdfMenuBar, PdfMenuBarLazy, SETTINGS_SECTIONS, SUPPORTED_LANGUAGES, type SaveDialogOptions, SettingsApp, SettingsAppLazy, SettingsMenuBar, SettingsMenuBarLazy, type SettingsSection$1 as SettingsSection, SettingsSection as SettingsSectionComponent, type SortOption, SortOptions, StorybookApp, type SupportedLanguage$2 as SupportedLanguage, TASKBAR_HEIGHT, TEXT_MIME_TYPES, Taskbar, TaskbarContextMenu, type TaskbarContextMenuProps, type TaskbarMenuType, type TaskbarTheme, type Theme, type ThemeMode, ThemeProvider, type ThemeProviderProps, UploaderApp, UploaderAppLazy, type UseCloseInterceptorOptions, type UseDownloadReturn, type UseIsDirtyOptions, VscIcon, Window, WindowButtonRegistryProvider, type WindowContentProps, type WindowEntity, type WindowInput, type WindowLoading, WindowManagerAdapter, type WindowProps, type WindowState, type WindowTheme, appendDirtyIndicator, buildBreadcrumbs, centerWindowPosition, checkHMREndpointExists, clearBrowserData, clearManifestCache, convertToAppEntry, createDesktopIcon, createEaseIn, createEaseOut, createFile, createFolder, createLauncherFolder, createMaximizeTransition, createMinimizeVariant, createPanelVariants, createPredefinedLauncherFolder, createRestoreVariant, createWindow, createWindowVariants, fetchAppManifest, fileSystem, formatBytes, generateUUID, getAppComponent, getAppIdForMime, getAppName, getBaseUrl, getCachedManifest, getCloseInterceptor, getCustomAppById, getCustomApps, getEnvironment, getFdeApi, getFileExtension, getFourRandomColors, getMenuBarBuilder, getMenuBarComponent, getMimeTypeFromExtension, getPersistedThemeMode, getReleaseType, getRuntime, getVersionString, hashBlob, initRegistry, initializeFdeApi, injectFontLink, isBrowser, isCustomApp, isDev, isDocker, isElectron, isFdeApiInitialized, isLazyApp, isNewerVersion, maximizeTransition, mergeAppsWithCustomApps, migrateStorage, minimizeVariant, openVariants, panelVariants, prefetchApps, randomWindowPosition, registerAppFileHandler, registerCloseInterceptor, registerComponents, registerCustomApps, registerDesktopApps, removeFromManifestCache, resetBaseUrlCache, resetFileSystem, resetHMRState, resetWindowManager, resolveFileUrl, resolveUrl, restoreVariant, setApiBaseUrl, setTestBaseUrl, sortDesktopIcons, sortDesktopIconsByMode, sortNodes, sortNodesByMode, syncWithServer, toMantineTheme, unregisterCloseInterceptor, updateLauncherFolder, updateManifestCache, useAdaptiveDimensions, useAnimationDuration, useAppName, useAppReady, useAppTempMemoryStore, useAppUpdate, useApplyFont, useClock, useCloseInterceptor, useCloseModalStore, useCollapsible, useContextMenu, useCustomAppHMR, useCustomAppLifecycle, useCustomAppStore, useDesktopStore, useDeviceDetection, useDownload, useDragDropState, useDraggableItem, useDroppableArea, useDynamicIcon, useDynamicIconElement, useFcIcon, useFcIconElement, useFdeApi, useFdeContext, useFiIcon, useFiIconElement, useFolderName, useFontDownload, useIsDirty, useLanguageSync, useNotifications, useOpenApp, useResolvedUrl, useSearchFilter, useSettingsStore, useSystemTheme, useTaskbarContextMenu, useTaskbarHeight, useTheme, useThemeContext, useVscIcon, useVscIconElement, useWindowButtonRegistry, waitForContainer, windowVariants };