react-os-shell 4.2.2 → 4.4.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 +5 -0
- package/dist/{Browser-TPAIWPZX.js → Browser-YVV3HOKJ.js} +6 -6
- package/dist/{Browser-TPAIWPZX.js.map → Browser-YVV3HOKJ.js.map} +1 -1
- package/dist/{Calculator-RCNLBRHK.js → Calculator-GBC3FLAJ.js} +5 -5
- package/dist/{Calculator-RCNLBRHK.js.map → Calculator-GBC3FLAJ.js.map} +1 -1
- package/dist/ConfirmDialog-R7NZVI2V.js +4 -0
- package/dist/{ConfirmDialog-QMBUHDXK.js.map → ConfirmDialog-R7NZVI2V.js.map} +1 -1
- package/dist/{CurrencyConverter-CM5OTXWF.js → CurrencyConverter-URPZQBNV.js} +5 -5
- package/dist/{CurrencyConverter-CM5OTXWF.js.map → CurrencyConverter-URPZQBNV.js.map} +1 -1
- package/dist/{Documents-3BPIAGQT.js → Documents-5SFFQZBP.js} +6 -6
- package/dist/{Documents-3BPIAGQT.js.map → Documents-5SFFQZBP.js.map} +1 -1
- package/dist/{Files-CR3L5C2L.js → Files-YQJRHUGF.js} +8 -8
- package/dist/{Files-CR3L5C2L.js.map → Files-YQJRHUGF.js.map} +1 -1
- package/dist/{Notepad-C6JHCCF2.js → Notepad-FUQ74K4N.js} +6 -6
- package/dist/{Notepad-C6JHCCF2.js.map → Notepad-FUQ74K4N.js.map} +1 -1
- package/dist/{PomodoroTimer-EZMBYLQX.js → PomodoroTimer-QQOMBVP3.js} +6 -6
- package/dist/{PomodoroTimer-EZMBYLQX.js.map → PomodoroTimer-QQOMBVP3.js.map} +1 -1
- package/dist/{Preview-TFDEMTSH.js → Preview-OP4IUJFT.js} +6 -6
- package/dist/{Preview-TFDEMTSH.js.map → Preview-OP4IUJFT.js.map} +1 -1
- package/dist/{Sidebar-VF2IOOFX.js → Sidebar-E553SOXC.js} +4 -4
- package/dist/{Sidebar-VF2IOOFX.js.map → Sidebar-E553SOXC.js.map} +1 -1
- package/dist/{Spreadsheet-FRUPALW4.js → Spreadsheet-GADWOYDX.js} +6 -6
- package/dist/{Spreadsheet-FRUPALW4.js.map → Spreadsheet-GADWOYDX.js.map} +1 -1
- package/dist/{Stock-HL42NPTM.js → Stock-33C4U7CR.js} +5 -5
- package/dist/{Stock-HL42NPTM.js.map → Stock-33C4U7CR.js.map} +1 -1
- package/dist/{Weather-N74AKS6V.js → Weather-G3XHTB75.js} +5 -5
- package/dist/{Weather-N74AKS6V.js.map → Weather-G3XHTB75.js.map} +1 -1
- package/dist/{WorldClock-A2EDB57H.js → WorldClock-ZUVI3LBN.js} +5 -5
- package/dist/{WorldClock-A2EDB57H.js.map → WorldClock-ZUVI3LBN.js.map} +1 -1
- package/dist/apps/index.js +18 -18
- package/dist/chunk-3NZSR3ZG.js +20 -0
- package/dist/chunk-3NZSR3ZG.js.map +1 -0
- package/dist/{chunk-QJXXSMPG.js → chunk-5HCDJPX7.js} +3 -3
- package/dist/{chunk-QJXXSMPG.js.map → chunk-5HCDJPX7.js.map} +1 -1
- package/dist/{chunk-6Q4KYGMH.js → chunk-DKDD5KXG.js} +14 -3
- package/dist/chunk-DKDD5KXG.js.map +1 -0
- package/dist/{chunk-SI4XHEMM.js → chunk-EF5W3EXL.js} +285 -19
- package/dist/chunk-EF5W3EXL.js.map +1 -0
- package/dist/chunk-GDOCYHAG.js +7 -0
- package/dist/{chunk-D36OPVAT.js.map → chunk-GDOCYHAG.js.map} +1 -1
- package/dist/{chunk-CWFH34LM.js → chunk-LBY7KH2W.js} +3 -3
- package/dist/{chunk-CWFH34LM.js.map → chunk-LBY7KH2W.js.map} +1 -1
- package/dist/{chunk-5TU6DT3E.js → chunk-LSFZJZTQ.js} +3 -3
- package/dist/{chunk-5TU6DT3E.js.map → chunk-LSFZJZTQ.js.map} +1 -1
- package/dist/{chunk-RKNJSV2T.js → chunk-PZTYN2RX.js} +5 -5
- package/dist/{chunk-RKNJSV2T.js.map → chunk-PZTYN2RX.js.map} +1 -1
- package/dist/{chunk-52RFL3OQ.js → chunk-QAKURGOG.js} +3 -3
- package/dist/{chunk-52RFL3OQ.js.map → chunk-QAKURGOG.js.map} +1 -1
- package/dist/index.d.ts +493 -157
- package/dist/index.js +255 -85
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/dist/ConfirmDialog-QMBUHDXK.js +0 -4
- package/dist/chunk-6Q4KYGMH.js.map +0 -1
- package/dist/chunk-ADJ3CERD.js +0 -31
- package/dist/chunk-ADJ3CERD.js.map +0 -1
- package/dist/chunk-D36OPVAT.js +0 -7
- package/dist/chunk-SI4XHEMM.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { glassStyle, GLASS_DIVIDER, navIcons } from './chunk-
|
|
2
|
-
import { createContext, Component,
|
|
1
|
+
import { useShellAuth, glassStyle, GLASS_DIVIDER, navIcons } from './chunk-DKDD5KXG.js';
|
|
2
|
+
import { createContext, Component, useReducer, useRef, useCallback, useState, useEffect, useMemo, useContext, useId, useSyncExternalStore, useLayoutEffect, isValidElement, cloneElement, Suspense } from 'react';
|
|
3
3
|
import { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react';
|
|
4
4
|
import { XMarkIcon, ExclamationTriangleIcon } from '@heroicons/react/24/outline';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
@@ -123,6 +123,217 @@ var WindowErrorBoundary = class extends Component {
|
|
|
123
123
|
return this.props.children;
|
|
124
124
|
}
|
|
125
125
|
};
|
|
126
|
+
|
|
127
|
+
// src/hooks/undoHistory.ts
|
|
128
|
+
var UNDO_LIMIT = 100;
|
|
129
|
+
var emptyUndoState = { past: [], future: [] };
|
|
130
|
+
function undoReducer(state, action) {
|
|
131
|
+
switch (action.type) {
|
|
132
|
+
case "record": {
|
|
133
|
+
const newest = state.past[state.past.length - 1];
|
|
134
|
+
if (action.step.coalesceKey !== null && newest?.coalesceKey === action.step.coalesceKey) {
|
|
135
|
+
return state.future.length === 0 ? state : { ...state, future: [] };
|
|
136
|
+
}
|
|
137
|
+
const past = [...state.past, action.step];
|
|
138
|
+
return {
|
|
139
|
+
past: past.length > UNDO_LIMIT ? past.slice(past.length - UNDO_LIMIT) : past,
|
|
140
|
+
future: []
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
case "undo": {
|
|
144
|
+
if (state.past.length === 0) return state;
|
|
145
|
+
return {
|
|
146
|
+
past: state.past.slice(0, -1),
|
|
147
|
+
future: [action.redoStep, ...state.future]
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
case "redo": {
|
|
151
|
+
if (state.future.length === 0) return state;
|
|
152
|
+
return {
|
|
153
|
+
past: [...state.past, action.undoStep],
|
|
154
|
+
future: state.future.slice(1)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
case "clear":
|
|
158
|
+
return state.past.length === 0 && state.future.length === 0 ? state : emptyUndoState;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
var TEXT_ENTRY = /* @__PURE__ */ new Set(["INPUT", "TEXTAREA", "SELECT"]);
|
|
162
|
+
function matchUndoHotkey(e) {
|
|
163
|
+
if (!(e.metaKey || e.ctrlKey) || e.altKey) return null;
|
|
164
|
+
const key = e.key.toLowerCase();
|
|
165
|
+
const action = key === "z" ? e.shiftKey ? "redo" : "undo" : key === "y" && e.ctrlKey && !e.metaKey && !e.shiftKey ? "redo" : null;
|
|
166
|
+
if (!action) return null;
|
|
167
|
+
const target = e.target;
|
|
168
|
+
if (target?.isContentEditable) return null;
|
|
169
|
+
if (target?.tagName && TEXT_ENTRY.has(target.tagName.toUpperCase())) return null;
|
|
170
|
+
return action;
|
|
171
|
+
}
|
|
172
|
+
var UndoContext = createContext(null);
|
|
173
|
+
var RUNAWAY_LIMIT = 500;
|
|
174
|
+
var RUNAWAY_QUIET_MS = 250;
|
|
175
|
+
function UndoProvider({ children, canEdit = true, perms, windowId }) {
|
|
176
|
+
const [state, dispatch] = useReducer(undoReducer, emptyUndoState);
|
|
177
|
+
const slices = useRef(/* @__PURE__ */ new Map());
|
|
178
|
+
const { hasAnyPerm } = useShellAuth();
|
|
179
|
+
const enabled = canEdit && (perms && perms.length > 0 ? hasAnyPerm(perms) : true);
|
|
180
|
+
const pending = useRef(null);
|
|
181
|
+
const suspended = useRef(false);
|
|
182
|
+
const snapshot = useCallback(() => {
|
|
183
|
+
const values = {};
|
|
184
|
+
for (const [id, slice] of slices.current) values[id] = slice.getLast();
|
|
185
|
+
return values;
|
|
186
|
+
}, []);
|
|
187
|
+
const register = useCallback((id, slice) => {
|
|
188
|
+
slices.current.set(id, slice);
|
|
189
|
+
}, []);
|
|
190
|
+
const unregister = useCallback((id) => {
|
|
191
|
+
slices.current.delete(id);
|
|
192
|
+
}, []);
|
|
193
|
+
const runaway = useRef({ last: 0, count: 0, tripped: false });
|
|
194
|
+
const record = useCallback((label, coalesceKey) => {
|
|
195
|
+
if (!enabled || suspended.current || pending.current) return;
|
|
196
|
+
const r = runaway.current;
|
|
197
|
+
if (r.tripped) return;
|
|
198
|
+
const now = Date.now();
|
|
199
|
+
if (now - r.last > RUNAWAY_QUIET_MS) r.count = 0;
|
|
200
|
+
r.last = now;
|
|
201
|
+
if (++r.count > RUNAWAY_LIMIT) {
|
|
202
|
+
r.tripped = true;
|
|
203
|
+
console.error(
|
|
204
|
+
`[react-os-shell] UndoProvider: "${label}" recorded ${RUNAWAY_LIMIT} undo steps with no pause between them, which no user action can do. The value passed to useUndoable for this slice is almost certainly rebuilt on every render (a .map/.filter/object literal in the call) rather than held in state, so it reads as changed every time \u2014 and since recording a step re-renders the form, that is a loop. Undo recording is now off for this form to keep the tab responsive.`
|
|
205
|
+
);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
pending.current = { values: snapshot(), label, coalesceKey };
|
|
209
|
+
queueMicrotask(() => {
|
|
210
|
+
const step = pending.current;
|
|
211
|
+
pending.current = null;
|
|
212
|
+
if (step) dispatch({ type: "record", step });
|
|
213
|
+
});
|
|
214
|
+
}, [enabled, snapshot]);
|
|
215
|
+
const applyValues = useCallback((values) => {
|
|
216
|
+
for (const [id, value2] of Object.entries(values)) {
|
|
217
|
+
const slice = slices.current.get(id);
|
|
218
|
+
if (!slice) continue;
|
|
219
|
+
slice.setLast(value2);
|
|
220
|
+
slice.apply(value2);
|
|
221
|
+
}
|
|
222
|
+
}, []);
|
|
223
|
+
const undo = useCallback(() => {
|
|
224
|
+
const step = state.past[state.past.length - 1];
|
|
225
|
+
if (!step) return;
|
|
226
|
+
const redoStep = { values: snapshot(), label: step.label, coalesceKey: null };
|
|
227
|
+
applyValues(step.values);
|
|
228
|
+
dispatch({ type: "undo", redoStep });
|
|
229
|
+
}, [state.past, snapshot, applyValues]);
|
|
230
|
+
const redo = useCallback(() => {
|
|
231
|
+
const step = state.future[0];
|
|
232
|
+
if (!step) return;
|
|
233
|
+
const undoStep = { values: snapshot(), label: step.label, coalesceKey: null };
|
|
234
|
+
applyValues(step.values);
|
|
235
|
+
dispatch({ type: "redo", undoStep });
|
|
236
|
+
}, [state.future, snapshot, applyValues]);
|
|
237
|
+
const [baselineToken, setBaselineToken] = useState(0);
|
|
238
|
+
const baseline = useCallback(() => {
|
|
239
|
+
suspended.current = true;
|
|
240
|
+
pending.current = null;
|
|
241
|
+
setBaselineToken((t) => t + 1);
|
|
242
|
+
dispatch({ type: "clear" });
|
|
243
|
+
}, []);
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
if (!suspended.current) return;
|
|
246
|
+
suspended.current = false;
|
|
247
|
+
pending.current = null;
|
|
248
|
+
dispatch({ type: "clear" });
|
|
249
|
+
}, [baselineToken]);
|
|
250
|
+
const clear = baseline;
|
|
251
|
+
const canUndo = enabled && state.past.length > 0;
|
|
252
|
+
const canRedo = enabled && state.future.length > 0;
|
|
253
|
+
const isActive = useIsActiveWindow(windowId);
|
|
254
|
+
const keyed = useRef({ undo, redo, canUndo, canRedo });
|
|
255
|
+
keyed.current = { undo, redo, canUndo, canRedo };
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
if (!isActive || !enabled) return;
|
|
258
|
+
const handler = (e) => {
|
|
259
|
+
const action = matchUndoHotkey(e);
|
|
260
|
+
if (!action) return;
|
|
261
|
+
const k = keyed.current;
|
|
262
|
+
if (action === "undo" ? !k.canUndo : !k.canRedo) return;
|
|
263
|
+
e.preventDefault();
|
|
264
|
+
if (action === "undo") k.undo();
|
|
265
|
+
else k.redo();
|
|
266
|
+
};
|
|
267
|
+
window.addEventListener("keydown", handler);
|
|
268
|
+
return () => window.removeEventListener("keydown", handler);
|
|
269
|
+
}, [isActive, enabled]);
|
|
270
|
+
const value = useMemo(() => ({
|
|
271
|
+
register,
|
|
272
|
+
unregister,
|
|
273
|
+
record,
|
|
274
|
+
undo,
|
|
275
|
+
redo,
|
|
276
|
+
clear,
|
|
277
|
+
baseline,
|
|
278
|
+
canUndo,
|
|
279
|
+
canRedo,
|
|
280
|
+
enabled,
|
|
281
|
+
undoLabel: canUndo ? state.past[state.past.length - 1].label : null,
|
|
282
|
+
redoLabel: canRedo ? state.future[0].label : null
|
|
283
|
+
}), [register, unregister, record, undo, redo, clear, baseline, canUndo, canRedo, enabled, state.past, state.future]);
|
|
284
|
+
return /* @__PURE__ */ jsx(UndoContext.Provider, { value, children });
|
|
285
|
+
}
|
|
286
|
+
function useUndo() {
|
|
287
|
+
const ctx = useContext(UndoContext);
|
|
288
|
+
const noop = useCallback(() => {
|
|
289
|
+
}, []);
|
|
290
|
+
return {
|
|
291
|
+
undo: ctx?.undo ?? noop,
|
|
292
|
+
redo: ctx?.redo ?? noop,
|
|
293
|
+
clear: ctx?.clear ?? noop,
|
|
294
|
+
baseline: ctx?.baseline ?? noop,
|
|
295
|
+
canUndo: ctx?.canUndo ?? false,
|
|
296
|
+
canRedo: ctx?.canRedo ?? false,
|
|
297
|
+
undoLabel: ctx?.undoLabel ?? null,
|
|
298
|
+
redoLabel: ctx?.redoLabel ?? null,
|
|
299
|
+
enabled: ctx?.enabled ?? false
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
function useUndoable(value, apply, opts) {
|
|
303
|
+
const ctx = useContext(UndoContext);
|
|
304
|
+
const id = useId();
|
|
305
|
+
const last = useRef(value);
|
|
306
|
+
const applyRef = useRef(apply);
|
|
307
|
+
applyRef.current = apply;
|
|
308
|
+
useEffect(() => {
|
|
309
|
+
if (!ctx) return;
|
|
310
|
+
ctx.register(id, {
|
|
311
|
+
getLast: () => last.current,
|
|
312
|
+
setLast: (v) => {
|
|
313
|
+
last.current = v;
|
|
314
|
+
},
|
|
315
|
+
apply: (v) => applyRef.current(v)
|
|
316
|
+
});
|
|
317
|
+
return () => ctx.unregister(id);
|
|
318
|
+
}, [ctx, id]);
|
|
319
|
+
const { label, coalesceKey = null } = opts;
|
|
320
|
+
const ctxRef = useRef(ctx);
|
|
321
|
+
ctxRef.current = ctx;
|
|
322
|
+
const optsRef = useRef({ label, coalesceKey });
|
|
323
|
+
optsRef.current = { label, coalesceKey };
|
|
324
|
+
useEffect(() => {
|
|
325
|
+
const c = ctxRef.current;
|
|
326
|
+
if (!c) return;
|
|
327
|
+
if (Object.is(value, last.current)) return;
|
|
328
|
+
c.record(optsRef.current.label, optsRef.current.coalesceKey);
|
|
329
|
+
last.current = value;
|
|
330
|
+
}, [value]);
|
|
331
|
+
}
|
|
332
|
+
function useUndoableState(initial, opts) {
|
|
333
|
+
const [value, setValue] = useState(initial);
|
|
334
|
+
useUndoable(value, (next) => setValue(() => next), opts);
|
|
335
|
+
return [value, setValue];
|
|
336
|
+
}
|
|
126
337
|
function LoadingSpinner() {
|
|
127
338
|
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center p-8 text-sm text-gray-400", children: "Loading..." });
|
|
128
339
|
}
|
|
@@ -698,13 +909,13 @@ function seedDefaultWidgetPositions(widgets) {
|
|
|
698
909
|
}
|
|
699
910
|
}
|
|
700
911
|
function healWindowIds(items) {
|
|
701
|
-
const
|
|
702
|
-
for (const it of items)
|
|
912
|
+
const counts2 = /* @__PURE__ */ new Map();
|
|
913
|
+
for (const it of items) counts2.set(it.id, (counts2.get(it.id) ?? 0) + 1);
|
|
703
914
|
const seen = /* @__PURE__ */ new Set();
|
|
704
915
|
const out = [];
|
|
705
916
|
for (const it of items) {
|
|
706
917
|
let id = it.id;
|
|
707
|
-
if ((
|
|
918
|
+
if ((counts2.get(it.id) ?? 0) > 1 && it.type === "modal" && it.entityType && it.entityId) {
|
|
708
919
|
id = `${it.entityType}:${it.entityId}`;
|
|
709
920
|
}
|
|
710
921
|
if (seen.has(id)) continue;
|
|
@@ -850,7 +1061,7 @@ function WindowManagerProvider({ children, windowAccentForRoute }) {
|
|
|
850
1061
|
WindowErrorBoundary,
|
|
851
1062
|
{
|
|
852
1063
|
fallback: (error, reset) => /* @__PURE__ */ jsx(Modal, { open: true, onClose: () => closeEntity(item.id), title: item.label, size: "md", autoHeight: true, windowKey: item.id, children: /* @__PURE__ */ jsx(WindowCrashedFallback, { error, onReload: reset }) }),
|
|
853
|
-
children: /* @__PURE__ */ jsx(WindowShortcutProvider, { spec: shortcutSpecFor(item), children: item.type === "page" ? /* @__PURE__ */ jsx(PageWindow, { item, onClose: () => closeEntity(item.id), accentRgb }) : /* @__PURE__ */ jsx(
|
|
1064
|
+
children: /* @__PURE__ */ jsx(WindowShortcutProvider, { spec: shortcutSpecFor(item), children: /* @__PURE__ */ jsx(UndoProvider, { windowId: item.id, children: item.type === "page" ? /* @__PURE__ */ jsx(PageWindow, { item, onClose: () => closeEntity(item.id), accentRgb }) : /* @__PURE__ */ jsx(
|
|
854
1065
|
RestoredRegistryModal,
|
|
855
1066
|
{
|
|
856
1067
|
item,
|
|
@@ -859,7 +1070,7 @@ function WindowManagerProvider({ children, windowAccentForRoute }) {
|
|
|
859
1070
|
},
|
|
860
1071
|
accentRgb
|
|
861
1072
|
}
|
|
862
|
-
) })
|
|
1073
|
+
) }) })
|
|
863
1074
|
},
|
|
864
1075
|
item.id
|
|
865
1076
|
);
|
|
@@ -1029,6 +1240,41 @@ function subscribeSwipingParentKey(cb) {
|
|
|
1029
1240
|
subs.delete(cb);
|
|
1030
1241
|
};
|
|
1031
1242
|
}
|
|
1243
|
+
|
|
1244
|
+
// src/shell/perfEvents.ts
|
|
1245
|
+
var empty = () => ({ menus: 0, submenus: 0, menuKey: null, moveMs: 0, resizeMs: 0 });
|
|
1246
|
+
var collecting = false;
|
|
1247
|
+
var counts = empty();
|
|
1248
|
+
var NOOP = () => {
|
|
1249
|
+
};
|
|
1250
|
+
function setPerfCollecting(on) {
|
|
1251
|
+
collecting = on;
|
|
1252
|
+
counts = empty();
|
|
1253
|
+
}
|
|
1254
|
+
function markMenuOpen(layer, key) {
|
|
1255
|
+
if (!collecting) return;
|
|
1256
|
+
if (layer === "submenu") counts.submenus++;
|
|
1257
|
+
else counts.menus++;
|
|
1258
|
+
counts.menuKey = key;
|
|
1259
|
+
}
|
|
1260
|
+
function beginWindowGesture(kind) {
|
|
1261
|
+
if (!collecting) return NOOP;
|
|
1262
|
+
const startedAt = performance.now();
|
|
1263
|
+
let ended = false;
|
|
1264
|
+
return () => {
|
|
1265
|
+
if (ended) return;
|
|
1266
|
+
ended = true;
|
|
1267
|
+
if (!collecting) return;
|
|
1268
|
+
const elapsed = performance.now() - startedAt;
|
|
1269
|
+
if (kind === "move") counts.moveMs += elapsed;
|
|
1270
|
+
else counts.resizeMs += elapsed;
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
function drainPerfEvents() {
|
|
1274
|
+
const drained = counts;
|
|
1275
|
+
counts = empty();
|
|
1276
|
+
return drained;
|
|
1277
|
+
}
|
|
1032
1278
|
var ShellPrefsContext = createContext(null);
|
|
1033
1279
|
function ShellPrefsProvider({
|
|
1034
1280
|
value,
|
|
@@ -1205,7 +1451,7 @@ function CancelButton({ onClick, children, className }) {
|
|
|
1205
1451
|
const ctx = useContext(ModalActionsContext);
|
|
1206
1452
|
const handleClick = async () => {
|
|
1207
1453
|
if (ctx?.isDirty) {
|
|
1208
|
-
const { confirm: confirm2 } = await import('./ConfirmDialog-
|
|
1454
|
+
const { confirm: confirm2 } = await import('./ConfirmDialog-R7NZVI2V.js');
|
|
1209
1455
|
const ok = await confirm2({
|
|
1210
1456
|
title: "Discard changes?",
|
|
1211
1457
|
message: "You have unsaved changes. Are you sure you want to cancel? All changes will be lost.",
|
|
@@ -1307,6 +1553,14 @@ var windowHeightScale = {
|
|
|
1307
1553
|
};
|
|
1308
1554
|
var activationOrder = [];
|
|
1309
1555
|
var activeListeners = /* @__PURE__ */ new Set();
|
|
1556
|
+
var _activeVersion = 0;
|
|
1557
|
+
function getActiveVersion() {
|
|
1558
|
+
return _activeVersion;
|
|
1559
|
+
}
|
|
1560
|
+
function notifyActive() {
|
|
1561
|
+
_activeVersion++;
|
|
1562
|
+
activeListeners.forEach((fn) => fn());
|
|
1563
|
+
}
|
|
1310
1564
|
var _modalIdByKey = /* @__PURE__ */ new Map();
|
|
1311
1565
|
var _keyByModalId = /* @__PURE__ */ new Map();
|
|
1312
1566
|
function _insertModalIdForKey(modalId, key) {
|
|
@@ -1339,7 +1593,7 @@ function mountModal(modalId, key) {
|
|
|
1339
1593
|
_saveOrderDebounced();
|
|
1340
1594
|
}
|
|
1341
1595
|
}
|
|
1342
|
-
|
|
1596
|
+
notifyActive();
|
|
1343
1597
|
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
1344
1598
|
}
|
|
1345
1599
|
function activateModal(id) {
|
|
@@ -1353,7 +1607,7 @@ function activateModal(id) {
|
|
|
1353
1607
|
_activationOrderKeys.push(key);
|
|
1354
1608
|
_saveOrderDebounced();
|
|
1355
1609
|
}
|
|
1356
|
-
|
|
1610
|
+
notifyActive();
|
|
1357
1611
|
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
1358
1612
|
}
|
|
1359
1613
|
function _minimizeModal(modalId) {
|
|
@@ -1367,7 +1621,7 @@ function _minimizeModal(modalId) {
|
|
|
1367
1621
|
_saveOrderDebounced();
|
|
1368
1622
|
}
|
|
1369
1623
|
}
|
|
1370
|
-
|
|
1624
|
+
notifyActive();
|
|
1371
1625
|
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
1372
1626
|
}
|
|
1373
1627
|
var widgetIds = /* @__PURE__ */ new Set();
|
|
@@ -1380,7 +1634,7 @@ function deactivateAllModals() {
|
|
|
1380
1634
|
return mid != null && widgetIds.has(mid);
|
|
1381
1635
|
});
|
|
1382
1636
|
_saveOrderDebounced();
|
|
1383
|
-
|
|
1637
|
+
notifyActive();
|
|
1384
1638
|
window.dispatchEvent(new CustomEvent("modal-reorder"));
|
|
1385
1639
|
}
|
|
1386
1640
|
var EDGE_THRESHOLD = 8;
|
|
@@ -1530,7 +1784,7 @@ var RESIZE_CURSOR = {
|
|
|
1530
1784
|
w: "ew-resize"
|
|
1531
1785
|
};
|
|
1532
1786
|
var DRAG_THRESHOLD = 4;
|
|
1533
|
-
function beginPointerGesture(handle, pointerId, cursor) {
|
|
1787
|
+
function beginPointerGesture(handle, pointerId, cursor, kind) {
|
|
1534
1788
|
ensureGestureStyle();
|
|
1535
1789
|
try {
|
|
1536
1790
|
handle.setPointerCapture(pointerId);
|
|
@@ -1541,10 +1795,12 @@ function beginPointerGesture(handle, pointerId, cursor) {
|
|
|
1541
1795
|
shield.setAttribute("data-drag-shield", "");
|
|
1542
1796
|
shield.style.cssText = `position:fixed;inset:0;z-index:2147483647;cursor:${cursor};background:transparent;touch-action:none`;
|
|
1543
1797
|
document.body.appendChild(shield);
|
|
1798
|
+
const endMark = beginWindowGesture(kind);
|
|
1544
1799
|
let done = false;
|
|
1545
1800
|
return () => {
|
|
1546
1801
|
if (done) return;
|
|
1547
1802
|
done = true;
|
|
1803
|
+
endMark();
|
|
1548
1804
|
try {
|
|
1549
1805
|
handle.releasePointerCapture(pointerId);
|
|
1550
1806
|
} catch {
|
|
@@ -1588,6 +1844,16 @@ function useIsActiveModal(modalId) {
|
|
|
1588
1844
|
const activeId = useSyncExternalStore(subscribeActive, getActiveModalId);
|
|
1589
1845
|
return activationOrder.length <= 1 || activeId === modalId;
|
|
1590
1846
|
}
|
|
1847
|
+
function useIsActiveWindow(windowKey) {
|
|
1848
|
+
useSyncExternalStore(subscribeActive, getActiveVersion);
|
|
1849
|
+
const ctx = useContext(ModalActionsContext);
|
|
1850
|
+
if (activationOrder.length <= 1) return true;
|
|
1851
|
+
if (windowKey) {
|
|
1852
|
+
const modalId = _modalIdByKey.get(windowKey);
|
|
1853
|
+
if (modalId != null) return getActiveModalId() === modalId;
|
|
1854
|
+
}
|
|
1855
|
+
return ctx?.active ?? getActiveModalId() != null;
|
|
1856
|
+
}
|
|
1591
1857
|
var _exposeOn = false;
|
|
1592
1858
|
var _exposeListeners = /* @__PURE__ */ new Set();
|
|
1593
1859
|
function _notifyExpose() {
|
|
@@ -2038,7 +2304,7 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
2038
2304
|
const aidx = activationOrder.indexOf(modalId);
|
|
2039
2305
|
if (aidx !== -1) {
|
|
2040
2306
|
activationOrder.splice(aidx, 1);
|
|
2041
|
-
|
|
2307
|
+
notifyActive();
|
|
2042
2308
|
}
|
|
2043
2309
|
const cleanupKey = _keyByModalId.get(modalId);
|
|
2044
2310
|
if (cleanupKey) {
|
|
@@ -2289,7 +2555,7 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
2289
2555
|
const move = (ev) => {
|
|
2290
2556
|
if (!endGesture) {
|
|
2291
2557
|
if (Math.abs(ev.clientX - sx) < DRAG_THRESHOLD && Math.abs(ev.clientY - sy) < DRAG_THRESHOLD) return;
|
|
2292
|
-
endGesture = beginPointerGesture(dragHandle, dragPointerId, "move");
|
|
2558
|
+
endGesture = beginPointerGesture(dragHandle, dragPointerId, "move", "move");
|
|
2293
2559
|
if (panel) panel.style.transition = "none";
|
|
2294
2560
|
}
|
|
2295
2561
|
const nx = ox + ev.clientX - sx;
|
|
@@ -2399,7 +2665,7 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
2399
2665
|
const move = (ev) => {
|
|
2400
2666
|
if (!endGesture) {
|
|
2401
2667
|
if (Math.abs(ev.clientX - sx) < DRAG_THRESHOLD && Math.abs(ev.clientY - sy) < DRAG_THRESHOLD) return;
|
|
2402
|
-
endGesture = beginPointerGesture(resizeHandle, resizePointerId, RESIZE_CURSOR[corner]);
|
|
2668
|
+
endGesture = beginPointerGesture(resizeHandle, resizePointerId, RESIZE_CURSOR[corner], "resize");
|
|
2403
2669
|
}
|
|
2404
2670
|
pending = compute(ev.clientX - sx, ev.clientY - sy);
|
|
2405
2671
|
if (!raf) raf = requestAnimationFrame(flush);
|
|
@@ -3207,6 +3473,6 @@ function ConfirmProvider({ children }) {
|
|
|
3207
3473
|
] });
|
|
3208
3474
|
}
|
|
3209
3475
|
|
|
3210
|
-
export { CancelButton, ConfirmProvider, CopyButton, DocFavStar, LoadingSpinner, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, SIDEBAR_STRIP_W, ShellPrefsProvider, WINDOW_REGISTRY, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowTitle, client_default, commitExposeHighlight, confirm, confirmDestructive, exitExposeMode, forgetMaximizedWindowBoxes, getActiveModalId, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, isShellApiClientConfigured, prompt, registerModalEscapeInterceptor, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useConfirm, useIsMobile, useLocalStoragePrefs, useModalActive, useShellPrefs, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
|
|
3211
|
-
//# sourceMappingURL=chunk-
|
|
3212
|
-
//# sourceMappingURL=chunk-
|
|
3476
|
+
export { CancelButton, ConfirmProvider, CopyButton, DocFavStar, LoadingSpinner, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, SIDEBAR_STRIP_W, ShellPrefsProvider, UndoProvider, WINDOW_REGISTRY, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowTitle, beginWindowGesture, client_default, commitExposeHighlight, confirm, confirmDestructive, drainPerfEvents, exitExposeMode, forgetMaximizedWindowBoxes, getActiveModalId, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, isShellApiClientConfigured, markMenuOpen, prompt, registerModalEscapeInterceptor, setExposeHighlight, setPerfCollecting, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useConfirm, useIsActiveWindow, useIsMobile, useLocalStoragePrefs, useModalActive, useShellPrefs, useUndo, useUndoable, useUndoableState, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
|
|
3477
|
+
//# sourceMappingURL=chunk-EF5W3EXL.js.map
|
|
3478
|
+
//# sourceMappingURL=chunk-EF5W3EXL.js.map
|