react-os-shell 0.2.67 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -15
- package/dist/{Browser-OH3E6TIZ.js → Browser-H5KDP5OH.js} +3 -3
- package/dist/{Browser-OH3E6TIZ.js.map → Browser-H5KDP5OH.js.map} +1 -1
- package/dist/{Calculator-DBSWD2RM.js → Calculator-QQ7NF53Q.js} +4 -4
- package/dist/{Calculator-DBSWD2RM.js.map → Calculator-QQ7NF53Q.js.map} +1 -1
- package/dist/{Calendar-5S3MOTVB.js → Calendar-J6L7FGHS.js} +175 -108
- package/dist/Calendar-J6L7FGHS.js.map +1 -0
- package/dist/{CurrencyConverter-TDAW7VME.js → CurrencyConverter-YHOGBUPH.js} +4 -4
- package/dist/{CurrencyConverter-TDAW7VME.js.map → CurrencyConverter-YHOGBUPH.js.map} +1 -1
- package/dist/{Documents-R4DZLBJU.js → Documents-6DYALASM.js} +3 -3
- package/dist/{Documents-R4DZLBJU.js.map → Documents-6DYALASM.js.map} +1 -1
- package/dist/Email-U2U5Z4DL.js +475 -0
- package/dist/Email-U2U5Z4DL.js.map +1 -0
- package/dist/Files-T62M4V5I.js +11 -0
- package/dist/{Files-XD7SWQSG.js.map → Files-T62M4V5I.js.map} +1 -1
- package/dist/{Minesweeper-YWYMJQN6.js → Minesweeper-S2JHXYLX.js} +3 -3
- package/dist/{Minesweeper-YWYMJQN6.js.map → Minesweeper-S2JHXYLX.js.map} +1 -1
- package/dist/{Notepad-F3BJYZJL.js → Notepad-2YF7X3XO.js} +3 -3
- package/dist/{Notepad-F3BJYZJL.js.map → Notepad-2YF7X3XO.js.map} +1 -1
- package/dist/{PomodoroTimer-VLPDNV7W.js → PomodoroTimer-3J7Z3NVQ.js} +4 -4
- package/dist/{PomodoroTimer-VLPDNV7W.js.map → PomodoroTimer-3J7Z3NVQ.js.map} +1 -1
- package/dist/Preview-WM6ZP5PZ.js +8 -0
- package/dist/{Preview-XOCYZM4T.js.map → Preview-WM6ZP5PZ.js.map} +1 -1
- package/dist/Spreadsheet-ZIE2SXAF.js +6 -0
- package/dist/{Spreadsheet-7NEC5RBR.js.map → Spreadsheet-ZIE2SXAF.js.map} +1 -1
- package/dist/{TodoList-7JZ2SLDI.js → TodoList-QGXCDEIE.js} +18 -204
- package/dist/TodoList-QGXCDEIE.js.map +1 -0
- package/dist/{Weather-HLXHNBM4.js → Weather-2GFPSZ5V.js} +4 -4
- package/dist/{Weather-HLXHNBM4.js.map → Weather-2GFPSZ5V.js.map} +1 -1
- package/dist/{WorldClock-HIWKHF6U.js → WorldClock-P4JR5I6X.js} +4 -4
- package/dist/{WorldClock-HIWKHF6U.js.map → WorldClock-P4JR5I6X.js.map} +1 -1
- package/dist/apps/index.d.ts +2 -5
- package/dist/apps/index.js +23 -26
- package/dist/apps/index.js.map +1 -1
- package/dist/chunk-57B3WALN.js +114 -0
- package/dist/chunk-57B3WALN.js.map +1 -0
- package/dist/{chunk-GAC6D4LN.js → chunk-62FC2FHC.js} +94 -23
- package/dist/chunk-62FC2FHC.js.map +1 -0
- package/dist/{chunk-HAUVCQNK.js → chunk-ATQVRDDQ.js} +3 -3
- package/dist/{chunk-HAUVCQNK.js.map → chunk-ATQVRDDQ.js.map} +1 -1
- package/dist/{chunk-GP4Y3VCB.js → chunk-KMGWSDEI.js} +480 -4
- package/dist/chunk-KMGWSDEI.js.map +1 -0
- package/dist/{chunk-KFRHMW57.js → chunk-O6FJZAFM.js} +3 -3
- package/dist/{chunk-KFRHMW57.js.map → chunk-O6FJZAFM.js.map} +1 -1
- package/dist/{chunk-VG5ZM3QD.js → chunk-SEV7UXGN.js} +4 -4
- package/dist/{chunk-VG5ZM3QD.js.map → chunk-SEV7UXGN.js.map} +1 -1
- package/dist/{chunk-EXYMMWOS.js → chunk-ZBRFMK3E.js} +4 -4
- package/dist/{chunk-EXYMMWOS.js.map → chunk-ZBRFMK3E.js.map} +1 -1
- package/dist/index.d.ts +55 -1
- package/dist/index.js +242 -136
- package/dist/index.js.map +1 -1
- package/package.json +10 -3
- package/dist/Calendar-5S3MOTVB.js.map +0 -1
- package/dist/Email-OAQ76CET.js +0 -1883
- package/dist/Email-OAQ76CET.js.map +0 -1
- package/dist/Files-XD7SWQSG.js +0 -12
- package/dist/GeminiChat-XTEBZIVK.js +0 -184
- package/dist/GeminiChat-XTEBZIVK.js.map +0 -1
- package/dist/Preview-XOCYZM4T.js +0 -8
- package/dist/Spreadsheet-7NEC5RBR.js +0 -7
- package/dist/TodoList-7JZ2SLDI.js.map +0 -1
- package/dist/chunk-5VXRBUEH.js +0 -104
- package/dist/chunk-5VXRBUEH.js.map +0 -1
- package/dist/chunk-62EP7CNW.js +0 -485
- package/dist/chunk-62EP7CNW.js.map +0 -1
- package/dist/chunk-GAC6D4LN.js.map +0 -1
- package/dist/chunk-GP4Y3VCB.js.map +0 -1
- package/dist/chunk-MVWEL34Y.js +0 -209
- package/dist/chunk-MVWEL34Y.js.map +0 -1
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
3
|
+
|
|
4
|
+
// src/api/mailClient.ts
|
|
5
|
+
var DEFAULT_BASE_URL = "http://localhost:3001";
|
|
6
|
+
var _client = null;
|
|
7
|
+
var _baseUrl = DEFAULT_BASE_URL;
|
|
8
|
+
function setShellMailServer(input) {
|
|
9
|
+
if (typeof input === "string") {
|
|
10
|
+
_baseUrl = input;
|
|
11
|
+
_client = axios.create({ baseURL: input, withCredentials: true, timeout: 6e4 });
|
|
12
|
+
} else {
|
|
13
|
+
_client = input;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function getMailClient() {
|
|
17
|
+
if (!_client) {
|
|
18
|
+
_client = axios.create({ baseURL: _baseUrl, withCredentials: true, timeout: 6e4 });
|
|
19
|
+
}
|
|
20
|
+
return _client;
|
|
21
|
+
}
|
|
22
|
+
var SESSION_FLAG = "mail_session_known";
|
|
23
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
24
|
+
var cached = {
|
|
25
|
+
user: null,
|
|
26
|
+
capabilities: null,
|
|
27
|
+
checked: false,
|
|
28
|
+
serverReachable: null
|
|
29
|
+
};
|
|
30
|
+
function broadcast() {
|
|
31
|
+
listeners.forEach((fn) => fn());
|
|
32
|
+
}
|
|
33
|
+
async function fetchMe() {
|
|
34
|
+
const client = getMailClient();
|
|
35
|
+
try {
|
|
36
|
+
const res = await client.get("/api/auth/me");
|
|
37
|
+
cached = { user: res.data.user, capabilities: res.data.capabilities, checked: true, serverReachable: true };
|
|
38
|
+
} catch (err) {
|
|
39
|
+
const status = err?.response?.status;
|
|
40
|
+
if (status === 401) {
|
|
41
|
+
localStorage.removeItem(SESSION_FLAG);
|
|
42
|
+
cached = { user: null, capabilities: null, checked: true, serverReachable: true };
|
|
43
|
+
} else {
|
|
44
|
+
cached = { user: null, capabilities: null, checked: true, serverReachable: false };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
broadcast();
|
|
48
|
+
}
|
|
49
|
+
function useMailAuth() {
|
|
50
|
+
const [, force] = useState(0);
|
|
51
|
+
const [loading, setLoading] = useState(false);
|
|
52
|
+
const [error, setError] = useState(null);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
const sub = () => force((n) => n + 1);
|
|
55
|
+
listeners.add(sub);
|
|
56
|
+
if (!cached.checked && localStorage.getItem(SESSION_FLAG) === "true") {
|
|
57
|
+
fetchMe();
|
|
58
|
+
} else if (!cached.checked) {
|
|
59
|
+
cached.checked = true;
|
|
60
|
+
cached.serverReachable = null;
|
|
61
|
+
broadcast();
|
|
62
|
+
}
|
|
63
|
+
return () => {
|
|
64
|
+
listeners.delete(sub);
|
|
65
|
+
};
|
|
66
|
+
}, []);
|
|
67
|
+
const login = useCallback(async (payload) => {
|
|
68
|
+
setLoading(true);
|
|
69
|
+
setError(null);
|
|
70
|
+
try {
|
|
71
|
+
const client = getMailClient();
|
|
72
|
+
const res = await client.post("/api/auth/login", payload);
|
|
73
|
+
localStorage.setItem(SESSION_FLAG, "true");
|
|
74
|
+
cached = { user: res.data.user, capabilities: res.data.capabilities, checked: true, serverReachable: true };
|
|
75
|
+
broadcast();
|
|
76
|
+
} catch (err) {
|
|
77
|
+
const msg = err?.response?.data?.error || err?.message || "Login failed";
|
|
78
|
+
setError(msg);
|
|
79
|
+
throw err;
|
|
80
|
+
} finally {
|
|
81
|
+
setLoading(false);
|
|
82
|
+
}
|
|
83
|
+
}, []);
|
|
84
|
+
const logout = useCallback(async () => {
|
|
85
|
+
setLoading(true);
|
|
86
|
+
try {
|
|
87
|
+
const client = getMailClient();
|
|
88
|
+
await client.post("/api/auth/logout").catch(() => void 0);
|
|
89
|
+
} finally {
|
|
90
|
+
localStorage.removeItem(SESSION_FLAG);
|
|
91
|
+
cached = { user: null, capabilities: null, checked: true, serverReachable: cached.serverReachable };
|
|
92
|
+
setLoading(false);
|
|
93
|
+
broadcast();
|
|
94
|
+
}
|
|
95
|
+
}, []);
|
|
96
|
+
const refresh = useCallback(async () => {
|
|
97
|
+
await fetchMe();
|
|
98
|
+
}, []);
|
|
99
|
+
return {
|
|
100
|
+
loading,
|
|
101
|
+
serverReachable: cached.serverReachable,
|
|
102
|
+
isConnected: !!cached.user,
|
|
103
|
+
user: cached.user,
|
|
104
|
+
capabilities: cached.capabilities,
|
|
105
|
+
error,
|
|
106
|
+
login,
|
|
107
|
+
logout,
|
|
108
|
+
refresh
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { getMailClient, setShellMailServer, useMailAuth };
|
|
113
|
+
//# sourceMappingURL=chunk-57B3WALN.js.map
|
|
114
|
+
//# sourceMappingURL=chunk-57B3WALN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/mailClient.ts","../src/hooks/useMailAuth.ts"],"names":[],"mappings":"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","file":"chunk-57B3WALN.js","sourcesContent":["import axios, { type AxiosInstance } from 'axios';\n\nconst DEFAULT_BASE_URL = 'http://localhost:3001';\nlet _client: AxiosInstance | null = null;\nlet _baseUrl: string = DEFAULT_BASE_URL;\n\nexport function setShellMailServer(input: string | AxiosInstance): void {\n if (typeof input === 'string') {\n _baseUrl = input;\n _client = axios.create({ baseURL: input, withCredentials: true, timeout: 60_000 });\n } else {\n _client = input;\n }\n}\n\nexport function getMailClient(): AxiosInstance {\n if (!_client) {\n _client = axios.create({ baseURL: _baseUrl, withCredentials: true, timeout: 60_000 });\n }\n return _client;\n}\n\nexport function getMailServerBaseUrl(): string {\n return _baseUrl;\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { getMailClient } from '../api/mailClient';\n\nconst SESSION_FLAG = 'mail_session_known';\n\nexport interface MailUser {\n email: string;\n displayName: string;\n}\n\nexport interface MailCapabilities {\n imap: { thread: boolean; condstore: boolean; idle: boolean };\n smtp: boolean;\n caldav: boolean;\n}\n\nexport interface LoginPayload {\n imap: { host: string; port: number; secure: boolean; user: string; pass: string };\n smtp: { host: string; port: number; secure: boolean; user: string; pass: string };\n caldav?: { serverUrl: string; user: string; pass: string };\n}\n\ninterface MailAuthState {\n loading: boolean;\n serverReachable: boolean | null;\n isConnected: boolean;\n user: MailUser | null;\n capabilities: MailCapabilities | null;\n error: string | null;\n login: (payload: LoginPayload) => Promise<void>;\n logout: () => Promise<void>;\n refresh: () => Promise<void>;\n}\n\nconst listeners = new Set<() => void>();\nlet cached: { user: MailUser | null; capabilities: MailCapabilities | null; checked: boolean; serverReachable: boolean | null } = {\n user: null,\n capabilities: null,\n checked: false,\n serverReachable: null,\n};\n\nfunction broadcast(): void {\n listeners.forEach(fn => fn());\n}\n\nasync function fetchMe(): Promise<void> {\n const client = getMailClient();\n try {\n const res = await client.get('/api/auth/me');\n cached = { user: res.data.user, capabilities: res.data.capabilities, checked: true, serverReachable: true };\n } catch (err) {\n const status = (err as { response?: { status?: number } })?.response?.status;\n if (status === 401) {\n localStorage.removeItem(SESSION_FLAG);\n cached = { user: null, capabilities: null, checked: true, serverReachable: true };\n } else {\n cached = { user: null, capabilities: null, checked: true, serverReachable: false };\n }\n }\n broadcast();\n}\n\nexport default function useMailAuth(): MailAuthState {\n const [, force] = useState(0);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const sub = () => force(n => n + 1);\n listeners.add(sub);\n if (!cached.checked && localStorage.getItem(SESSION_FLAG) === 'true') {\n fetchMe();\n } else if (!cached.checked) {\n cached.checked = true;\n cached.serverReachable = null;\n broadcast();\n }\n return () => {\n listeners.delete(sub);\n };\n }, []);\n\n const login = useCallback(async (payload: LoginPayload) => {\n setLoading(true);\n setError(null);\n try {\n const client = getMailClient();\n const res = await client.post('/api/auth/login', payload);\n localStorage.setItem(SESSION_FLAG, 'true');\n cached = { user: res.data.user, capabilities: res.data.capabilities, checked: true, serverReachable: true };\n broadcast();\n } catch (err) {\n const msg = (err as { response?: { data?: { error?: string } }; message?: string })?.response?.data?.error\n || (err as { message?: string })?.message\n || 'Login failed';\n setError(msg);\n throw err;\n } finally {\n setLoading(false);\n }\n }, []);\n\n const logout = useCallback(async () => {\n setLoading(true);\n try {\n const client = getMailClient();\n await client.post('/api/auth/logout').catch(() => undefined);\n } finally {\n localStorage.removeItem(SESSION_FLAG);\n cached = { user: null, capabilities: null, checked: true, serverReachable: cached.serverReachable };\n setLoading(false);\n broadcast();\n }\n }, []);\n\n const refresh = useCallback(async () => {\n await fetchMe();\n }, []);\n\n return {\n loading,\n serverReachable: cached.serverReachable,\n isConnected: !!cached.user,\n user: cached.user,\n capabilities: cached.capabilities,\n error,\n login,\n logout,\n refresh,\n };\n}\n"]}
|
|
@@ -371,6 +371,24 @@ function _savePositionsDebounced() {
|
|
|
371
371
|
}
|
|
372
372
|
}, 500);
|
|
373
373
|
}
|
|
374
|
+
var AO_KEY = "erp_activation_order";
|
|
375
|
+
var _activationOrderKeys = [];
|
|
376
|
+
try {
|
|
377
|
+
const stored = localStorage.getItem(AO_KEY);
|
|
378
|
+
const parsed = stored ? JSON.parse(stored) : null;
|
|
379
|
+
if (Array.isArray(parsed) && parsed.every((k) => typeof k === "string")) _activationOrderKeys = parsed;
|
|
380
|
+
} catch {
|
|
381
|
+
}
|
|
382
|
+
var _saveOrderTimer = null;
|
|
383
|
+
function _saveOrderDebounced() {
|
|
384
|
+
if (_saveOrderTimer) clearTimeout(_saveOrderTimer);
|
|
385
|
+
_saveOrderTimer = setTimeout(() => {
|
|
386
|
+
try {
|
|
387
|
+
localStorage.setItem(AO_KEY, JSON.stringify(_activationOrderKeys));
|
|
388
|
+
} catch {
|
|
389
|
+
}
|
|
390
|
+
}, 500);
|
|
391
|
+
}
|
|
374
392
|
function setWindowDefaultPosition(key, pos) {
|
|
375
393
|
if (_windowPositions[key]) return;
|
|
376
394
|
_windowPositions[key] = pos;
|
|
@@ -385,10 +403,66 @@ var sizeDefaults = {
|
|
|
385
403
|
};
|
|
386
404
|
var activationOrder = [];
|
|
387
405
|
var activeListeners = /* @__PURE__ */ new Set();
|
|
406
|
+
var _modalIdByKey = /* @__PURE__ */ new Map();
|
|
407
|
+
var _keyByModalId = /* @__PURE__ */ new Map();
|
|
408
|
+
function _insertModalIdForKey(modalId, key) {
|
|
409
|
+
const savedIdx = _activationOrderKeys.indexOf(key);
|
|
410
|
+
if (savedIdx === -1) {
|
|
411
|
+
activationOrder.push(modalId);
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
let insertAt = activationOrder.length;
|
|
415
|
+
for (let i = 0; i < activationOrder.length; i++) {
|
|
416
|
+
const otherKey = _keyByModalId.get(activationOrder[i]);
|
|
417
|
+
if (!otherKey) continue;
|
|
418
|
+
const otherIdx = _activationOrderKeys.indexOf(otherKey);
|
|
419
|
+
if (otherIdx > savedIdx) {
|
|
420
|
+
insertAt = i;
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
activationOrder.splice(insertAt, 0, modalId);
|
|
425
|
+
}
|
|
426
|
+
function mountModal(modalId, key) {
|
|
427
|
+
if (!key) {
|
|
428
|
+
activationOrder.push(modalId);
|
|
429
|
+
} else {
|
|
430
|
+
_modalIdByKey.set(key, modalId);
|
|
431
|
+
_keyByModalId.set(modalId, key);
|
|
432
|
+
_insertModalIdForKey(modalId, key);
|
|
433
|
+
if (_activationOrderKeys.indexOf(key) === -1) {
|
|
434
|
+
_activationOrderKeys.push(key);
|
|
435
|
+
_saveOrderDebounced();
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
activeListeners.forEach((fn) => fn());
|
|
439
|
+
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
440
|
+
}
|
|
388
441
|
function activateModal(id) {
|
|
389
442
|
const idx = activationOrder.indexOf(id);
|
|
390
443
|
if (idx !== -1) activationOrder.splice(idx, 1);
|
|
391
444
|
activationOrder.push(id);
|
|
445
|
+
const key = _keyByModalId.get(id);
|
|
446
|
+
if (key) {
|
|
447
|
+
const kidx = _activationOrderKeys.indexOf(key);
|
|
448
|
+
if (kidx !== -1) _activationOrderKeys.splice(kidx, 1);
|
|
449
|
+
_activationOrderKeys.push(key);
|
|
450
|
+
_saveOrderDebounced();
|
|
451
|
+
}
|
|
452
|
+
activeListeners.forEach((fn) => fn());
|
|
453
|
+
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
454
|
+
}
|
|
455
|
+
function _minimizeModal(modalId) {
|
|
456
|
+
const idx = activationOrder.indexOf(modalId);
|
|
457
|
+
if (idx !== -1) activationOrder.splice(idx, 1);
|
|
458
|
+
const key = _keyByModalId.get(modalId);
|
|
459
|
+
if (key) {
|
|
460
|
+
const kidx = _activationOrderKeys.indexOf(key);
|
|
461
|
+
if (kidx !== -1) {
|
|
462
|
+
_activationOrderKeys.splice(kidx, 1);
|
|
463
|
+
_saveOrderDebounced();
|
|
464
|
+
}
|
|
465
|
+
}
|
|
392
466
|
activeListeners.forEach((fn) => fn());
|
|
393
467
|
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
394
468
|
}
|
|
@@ -397,6 +471,11 @@ function deactivateAllModals() {
|
|
|
397
471
|
for (let i = activationOrder.length - 1; i >= 0; i--) {
|
|
398
472
|
if (!widgetIds.has(activationOrder[i])) activationOrder.splice(i, 1);
|
|
399
473
|
}
|
|
474
|
+
_activationOrderKeys = _activationOrderKeys.filter((k) => {
|
|
475
|
+
const mid = _modalIdByKey.get(k);
|
|
476
|
+
return mid != null && widgetIds.has(mid);
|
|
477
|
+
});
|
|
478
|
+
_saveOrderDebounced();
|
|
400
479
|
activeListeners.forEach((fn) => fn());
|
|
401
480
|
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
402
481
|
}
|
|
@@ -875,9 +954,10 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
875
954
|
}, [size]);
|
|
876
955
|
const interceptedRef = useRef(false);
|
|
877
956
|
if (!open) interceptedRef.current = false;
|
|
957
|
+
const boxKey = windowKey || copyText || null;
|
|
878
958
|
useEffect(() => {
|
|
879
959
|
if (!open) return;
|
|
880
|
-
|
|
960
|
+
mountModal(modalId, boxKey);
|
|
881
961
|
isNested.current = false;
|
|
882
962
|
setZIndex(getZForModal(modalId));
|
|
883
963
|
const onReorder = () => {
|
|
@@ -923,14 +1003,18 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
923
1003
|
activationOrder.splice(aidx, 1);
|
|
924
1004
|
activeListeners.forEach((fn) => fn());
|
|
925
1005
|
}
|
|
1006
|
+
const cleanupKey = _keyByModalId.get(modalId);
|
|
1007
|
+
if (cleanupKey) {
|
|
1008
|
+
_keyByModalId.delete(modalId);
|
|
1009
|
+
_modalIdByKey.delete(cleanupKey);
|
|
1010
|
+
}
|
|
926
1011
|
window.removeEventListener("modal-reorder", onReorder);
|
|
927
1012
|
window.removeEventListener("modal-split-view", onSplitView);
|
|
928
1013
|
window.removeEventListener("modal-center", onCenter);
|
|
929
1014
|
window.removeEventListener("modal-context-menu", onCtxMenu);
|
|
930
1015
|
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
931
1016
|
};
|
|
932
|
-
}, [open, modalId, calcMaximized]);
|
|
933
|
-
const boxKey = windowKey || copyText || null;
|
|
1017
|
+
}, [open, modalId, boxKey, calcMaximized]);
|
|
934
1018
|
const [box, setBox] = useState(() => {
|
|
935
1019
|
if (boxKey && _windowPositions[boxKey]) {
|
|
936
1020
|
const saved = { ..._windowPositions[boxKey] };
|
|
@@ -1416,12 +1500,7 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
1416
1500
|
children: /* @__PURE__ */ jsx("svg", { className: "h-3 w-3", fill: pinnedOnTop ? "currentColor" : "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" }) })
|
|
1417
1501
|
}
|
|
1418
1502
|
),
|
|
1419
|
-
/* @__PURE__ */ jsx("button", { onClick: () =>
|
|
1420
|
-
const idx = activationOrder.indexOf(modalId);
|
|
1421
|
-
if (idx !== -1) activationOrder.splice(idx, 1);
|
|
1422
|
-
activeListeners.forEach((fn) => fn());
|
|
1423
|
-
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
1424
|
-
}, title: "Minimize", className: "text-gray-400 hover:text-gray-600 px-1 py-0.5 rounded hover:bg-gray-200 text-xs leading-none", children: "\u2500" }),
|
|
1503
|
+
/* @__PURE__ */ jsx("button", { onClick: () => _minimizeModal(modalId), title: "Minimize", className: "text-gray-400 hover:text-gray-600 px-1 py-0.5 rounded hover:bg-gray-200 text-xs leading-none", children: "\u2500" }),
|
|
1425
1504
|
!alwaysMaximized && /* @__PURE__ */ jsx("button", { onClick: () => {
|
|
1426
1505
|
if (maximized) {
|
|
1427
1506
|
setMaximized(false);
|
|
@@ -1462,12 +1541,7 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
1462
1541
|
children: /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5", fill: pinnedOnTop ? "currentColor" : "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" }) })
|
|
1463
1542
|
}
|
|
1464
1543
|
),
|
|
1465
|
-
/* @__PURE__ */ jsx("button", { onClick: () =>
|
|
1466
|
-
const idx = activationOrder.indexOf(modalId);
|
|
1467
|
-
if (idx !== -1) activationOrder.splice(idx, 1);
|
|
1468
|
-
activeListeners.forEach((fn) => fn());
|
|
1469
|
-
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
1470
|
-
}, title: "Minimize", className: "text-gray-400 hover:text-gray-600 text-xs px-2 py-1 rounded hover:bg-gray-200", children: "\u2500" }),
|
|
1544
|
+
/* @__PURE__ */ jsx("button", { onClick: () => _minimizeModal(modalId), title: "Minimize", className: "text-gray-400 hover:text-gray-600 text-xs px-2 py-1 rounded hover:bg-gray-200", children: "\u2500" }),
|
|
1471
1545
|
!alwaysMaximized && /* @__PURE__ */ jsx("button", { onClick: () => {
|
|
1472
1546
|
if (maximized) {
|
|
1473
1547
|
setMaximized(false);
|
|
@@ -1589,10 +1663,7 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
1589
1663
|
const windowMenuEl = windowMenu && /* @__PURE__ */ jsxs(PopupMenu, { style: { left: windowMenu.x, top: windowMenu.y }, onClose: () => setWindowMenu(null), minWidth: 160, children: [
|
|
1590
1664
|
!widget && !compact && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1591
1665
|
/* @__PURE__ */ jsxs(PopupMenuItem, { onClick: () => {
|
|
1592
|
-
|
|
1593
|
-
if (idx !== -1) activationOrder.splice(idx, 1);
|
|
1594
|
-
activeListeners.forEach((fn) => fn());
|
|
1595
|
-
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
1666
|
+
_minimizeModal(modalId);
|
|
1596
1667
|
setWindowMenu(null);
|
|
1597
1668
|
}, children: [
|
|
1598
1669
|
/* @__PURE__ */ jsx("svg", { className: "h-4 w-4 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19.5 12h-15" }) }),
|
|
@@ -1857,7 +1928,7 @@ function ThumbCard({ id, label, maxW, maxH, titleAbove = false, onClick, onClose
|
|
|
1857
1928
|
"div",
|
|
1858
1929
|
{
|
|
1859
1930
|
style: { width: size.w, height: size.h },
|
|
1860
|
-
className: "relative rounded-md overflow-hidden bg-white/95 border border-gray-300 shadow-md cursor-pointer
|
|
1931
|
+
className: "relative rounded-md overflow-hidden bg-white/95 border border-gray-300 shadow-md cursor-pointer ring-2 ring-transparent group-hover:ring-blue-400 transition shrink-0",
|
|
1861
1932
|
onClick,
|
|
1862
1933
|
children: [
|
|
1863
1934
|
/* @__PURE__ */ jsx("div", { ref: previewRef, className: "absolute inset-0 overflow-hidden" }),
|
|
@@ -1934,7 +2005,7 @@ function TaskbarTabPreview({ items, anchorEl, onActivate, onClose, onMouseEnter,
|
|
|
1934
2005
|
onMouseEnter,
|
|
1935
2006
|
onMouseLeave,
|
|
1936
2007
|
children: items.map((it) => /* @__PURE__ */ jsxs("div", { className: "group flex flex-col items-center", children: [
|
|
1937
|
-
/* @__PURE__ */ jsx("span", { className: "mb-1 max-w-[240px] truncate text-[11px] font-medium text-gray-900 bg-white/80 px-2 py-0.5 rounded shadow-sm ring-
|
|
2008
|
+
/* @__PURE__ */ jsx("span", { className: "mb-1 max-w-[240px] truncate text-[11px] font-medium text-gray-900 bg-white/80 px-2 py-0.5 rounded shadow-sm ring-2 ring-transparent transition group-hover:ring-blue-400", children: it.label }),
|
|
1938
2009
|
/* @__PURE__ */ jsx(
|
|
1939
2010
|
ThumbCard,
|
|
1940
2011
|
{
|
|
@@ -2273,5 +2344,5 @@ function WindowManagerProvider({ children }) {
|
|
|
2273
2344
|
}
|
|
2274
2345
|
|
|
2275
2346
|
export { CancelButton, CopyButton, DocFavStar, LoadingSpinner, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ThumbCard, WINDOW_REGISTRY, WindowManagerProvider, WindowTitle, activateModal, client_default, commitExposeHighlight, exitExposeMode, getActiveModalId, getActiveWindowRoute, getExposeHighlight, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, subscribeExposeHighlight, toggleExposeMode, useIsMobile, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
|
|
2276
|
-
//# sourceMappingURL=chunk-
|
|
2277
|
-
//# sourceMappingURL=chunk-
|
|
2347
|
+
//# sourceMappingURL=chunk-62FC2FHC.js.map
|
|
2348
|
+
//# sourceMappingURL=chunk-62FC2FHC.js.map
|