@surdeddd/wmkit 0.5.0 → 0.6.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/dist/angular.cjs +3 -3
- package/dist/angular.d.cts +1 -1
- package/dist/angular.d.ts +1 -1
- package/dist/angular.js +1 -1
- package/dist/{binder-EBroZTRw.d.cts → binder-CQzQJdVj.d.cts} +13 -0
- package/dist/{binder-Ca3GOfZX.d.ts → binder-CkmOoo1U.d.ts} +13 -0
- package/dist/{chunk-L43XBN44.js → chunk-3HLKVOSI.js} +301 -80
- package/dist/chunk-3HLKVOSI.js.map +1 -0
- package/dist/{chunk-RXAMUBUJ.cjs → chunk-DYZQY3BE.cjs} +301 -80
- package/dist/chunk-DYZQY3BE.cjs.map +1 -0
- package/dist/index.cjs +18 -18
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/react.cjs +3 -3
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/solid.cjs +3 -3
- package/dist/solid.d.cts +1 -1
- package/dist/solid.d.ts +1 -1
- package/dist/solid.js +1 -1
- package/dist/svelte.cjs +3 -3
- package/dist/svelte.d.cts +1 -1
- package/dist/svelte.d.ts +1 -1
- package/dist/svelte.js +1 -1
- package/dist/themes/glass.css +68 -2
- package/dist/themes/light.css +68 -2
- package/dist/themes/retro.css +46 -1
- package/dist/vue.cjs +3 -3
- package/dist/vue.d.cts +1 -1
- package/dist/vue.d.ts +1 -1
- package/dist/vue.js +1 -1
- package/package.json +7 -7
- package/dist/chunk-L43XBN44.js.map +0 -1
- package/dist/chunk-RXAMUBUJ.cjs.map +0 -1
|
@@ -193,6 +193,12 @@ function createWindowManager(options = {}) {
|
|
|
193
193
|
const idPrefix = options.idPrefix ?? "wm";
|
|
194
194
|
const historyLimit = options.historyLimit ?? 50;
|
|
195
195
|
let windows = {};
|
|
196
|
+
let windowsShared = false;
|
|
197
|
+
let modalCount = 0;
|
|
198
|
+
let cachedGroups = null;
|
|
199
|
+
let cachedOrder = null;
|
|
200
|
+
let cachedTabs = null;
|
|
201
|
+
let groupsDirty = false;
|
|
196
202
|
let order = [];
|
|
197
203
|
let focusedId = null;
|
|
198
204
|
let viewport = options.viewport ?? { width: 0, height: 0 };
|
|
@@ -217,6 +223,7 @@ function createWindowManager(options = {}) {
|
|
|
217
223
|
const layouts = /* @__PURE__ */ new Map();
|
|
218
224
|
function getState() {
|
|
219
225
|
if (!snapshot) {
|
|
226
|
+
windowsShared = true;
|
|
220
227
|
snapshot = { windows, order, focusedId, viewport, workspace, groups: buildGroups() };
|
|
221
228
|
}
|
|
222
229
|
return snapshot;
|
|
@@ -238,30 +245,58 @@ function createWindowManager(options = {}) {
|
|
|
238
245
|
function queueEvent(emit) {
|
|
239
246
|
pendingEvents.push(emit);
|
|
240
247
|
}
|
|
248
|
+
function ownWindows() {
|
|
249
|
+
if (windowsShared) {
|
|
250
|
+
windows = { ...windows };
|
|
251
|
+
windowsShared = false;
|
|
252
|
+
}
|
|
253
|
+
return windows;
|
|
254
|
+
}
|
|
241
255
|
function setWindow(next) {
|
|
242
|
-
|
|
256
|
+
const map = ownWindows();
|
|
257
|
+
const previous = map[next.id];
|
|
258
|
+
const wasModal = previous?.layer === "modal";
|
|
259
|
+
if (wasModal !== (next.layer === "modal")) modalCount += wasModal ? -1 : 1;
|
|
260
|
+
if (previous?.groupId !== next.groupId) groupsDirty = true;
|
|
261
|
+
map[next.id] = next;
|
|
243
262
|
}
|
|
244
263
|
function removeWindow(id) {
|
|
245
|
-
const
|
|
246
|
-
|
|
264
|
+
const map = ownWindows();
|
|
265
|
+
const previous = map[id];
|
|
266
|
+
if (previous?.layer === "modal") modalCount -= 1;
|
|
267
|
+
if (previous?.groupId != null) groupsDirty = true;
|
|
268
|
+
delete map[id];
|
|
247
269
|
order = order.filter((entry) => entry !== id);
|
|
248
270
|
}
|
|
271
|
+
function countModals() {
|
|
272
|
+
let total = 0;
|
|
273
|
+
for (const id of order) {
|
|
274
|
+
if (windows[id].layer === "modal") total += 1;
|
|
275
|
+
}
|
|
276
|
+
return total;
|
|
277
|
+
}
|
|
249
278
|
function layerRankOf(id) {
|
|
250
279
|
return LAYER_RANK[windows[id].layer];
|
|
251
280
|
}
|
|
252
281
|
function sortByLayer(ids) {
|
|
253
282
|
return ids.map((id, index) => ({ id, index, rank: layerRankOf(id) })).sort((a, b) => a.rank !== b.rank ? a.rank - b.rank : a.index - b.index).map((entry) => entry.id);
|
|
254
283
|
}
|
|
284
|
+
function blockOf(id) {
|
|
285
|
+
const win = windows[id];
|
|
286
|
+
if (win.groupId === null) return [id];
|
|
287
|
+
return [...membersOf(win.groupId).filter((entry) => entry !== id), id];
|
|
288
|
+
}
|
|
255
289
|
function raise(id) {
|
|
256
290
|
const win = windows[id];
|
|
257
|
-
const
|
|
291
|
+
const block = blockOf(id);
|
|
292
|
+
const without = order.filter((entry) => !block.includes(entry));
|
|
258
293
|
const rank = LAYER_RANK[win.layer];
|
|
259
294
|
let insertAt = without.length;
|
|
260
295
|
for (let i = without.length - 1; i >= 0; i -= 1) {
|
|
261
296
|
if (layerRankOf(without[i]) > rank) insertAt = i;
|
|
262
297
|
else break;
|
|
263
298
|
}
|
|
264
|
-
const next = [...without.slice(0, insertAt),
|
|
299
|
+
const next = [...without.slice(0, insertAt), ...block, ...without.slice(insertAt)];
|
|
265
300
|
const changed = next.length !== order.length || next.some((entry, i) => entry !== order[i]);
|
|
266
301
|
order = next;
|
|
267
302
|
return changed;
|
|
@@ -276,31 +311,57 @@ function createWindowManager(options = {}) {
|
|
|
276
311
|
return win.groupId === null || activeTabs[win.groupId] === win.id;
|
|
277
312
|
}
|
|
278
313
|
function buildGroups() {
|
|
279
|
-
|
|
314
|
+
if (cachedGroups && !groupsDirty && cachedOrder === order && cachedTabs === activeTabs) {
|
|
315
|
+
return cachedGroups;
|
|
316
|
+
}
|
|
317
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
280
318
|
for (const [groupId, activeId] of Object.entries(activeTabs)) {
|
|
281
319
|
result[groupId] = { id: groupId, activeId, members: membersOf(groupId) };
|
|
282
320
|
}
|
|
321
|
+
cachedGroups = result;
|
|
322
|
+
cachedOrder = order;
|
|
323
|
+
cachedTabs = activeTabs;
|
|
324
|
+
groupsDirty = false;
|
|
283
325
|
return result;
|
|
284
326
|
}
|
|
327
|
+
function sharedSize(ids, size) {
|
|
328
|
+
let shared = size;
|
|
329
|
+
for (const id of ids) {
|
|
330
|
+
const fit = normalizeSize(shared, windows[id]);
|
|
331
|
+
shared = {
|
|
332
|
+
width: Math.max(shared.width, fit.width),
|
|
333
|
+
height: Math.max(shared.height, fit.height)
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
return shared;
|
|
337
|
+
}
|
|
285
338
|
function syncGroup(source) {
|
|
286
|
-
if (source.groupId === null) return;
|
|
287
|
-
|
|
288
|
-
|
|
339
|
+
if (source.groupId === null) return source;
|
|
340
|
+
const members = membersOf(source.groupId);
|
|
341
|
+
const fitted = sharedSize(members, source.bounds);
|
|
342
|
+
let effective = source;
|
|
343
|
+
if (fitted.width !== source.bounds.width || fitted.height !== source.bounds.height) {
|
|
344
|
+
effective = { ...source, bounds: { ...source.bounds, ...fitted } };
|
|
345
|
+
setWindow(effective);
|
|
346
|
+
}
|
|
347
|
+
for (const id of members) {
|
|
348
|
+
if (id === effective.id) continue;
|
|
289
349
|
const member = windows[id];
|
|
290
|
-
if (boundsEqual(member.bounds,
|
|
350
|
+
if (boundsEqual(member.bounds, effective.bounds) && member.stage === effective.stage && member.snapZone === effective.snapZone && member.layer === effective.layer && member.workspace === effective.workspace) {
|
|
291
351
|
continue;
|
|
292
352
|
}
|
|
293
353
|
setWindow({
|
|
294
354
|
...member,
|
|
295
|
-
bounds:
|
|
296
|
-
stage:
|
|
297
|
-
snapZone:
|
|
298
|
-
restoreBounds:
|
|
299
|
-
restoreStage:
|
|
300
|
-
layer:
|
|
301
|
-
workspace:
|
|
355
|
+
bounds: effective.bounds,
|
|
356
|
+
stage: effective.stage,
|
|
357
|
+
snapZone: effective.snapZone,
|
|
358
|
+
restoreBounds: effective.restoreBounds,
|
|
359
|
+
restoreStage: effective.restoreStage,
|
|
360
|
+
layer: effective.layer,
|
|
361
|
+
workspace: effective.workspace
|
|
302
362
|
});
|
|
303
363
|
}
|
|
364
|
+
return effective;
|
|
304
365
|
}
|
|
305
366
|
function dissolveIfOrphaned(groupId) {
|
|
306
367
|
const members = membersOf(groupId);
|
|
@@ -312,6 +373,7 @@ function createWindowManager(options = {}) {
|
|
|
312
373
|
activeTabs = rest;
|
|
313
374
|
}
|
|
314
375
|
function topModalId() {
|
|
376
|
+
if (modalCount === 0) return null;
|
|
315
377
|
for (let i = order.length - 1; i >= 0; i -= 1) {
|
|
316
378
|
const win = windows[order[i]];
|
|
317
379
|
if (win.layer === "modal" && win.stage !== "minimized" && onActiveWorkspace(win) && isVisibleTab(win)) {
|
|
@@ -330,8 +392,21 @@ function createWindowManager(options = {}) {
|
|
|
330
392
|
});
|
|
331
393
|
}
|
|
332
394
|
function focusTop() {
|
|
333
|
-
|
|
334
|
-
|
|
395
|
+
for (let i = order.length - 1; i >= 0; i -= 1) {
|
|
396
|
+
const win = windows[order[i]];
|
|
397
|
+
if (win.stage === "minimized" || !onActiveWorkspace(win) || !isVisibleTab(win)) continue;
|
|
398
|
+
focusedId = win.id;
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
focusedId = null;
|
|
402
|
+
}
|
|
403
|
+
function reconcileFocus() {
|
|
404
|
+
if (focusedId === null) return;
|
|
405
|
+
const win = windows[focusedId];
|
|
406
|
+
if (win && win.stage !== "minimized" && onActiveWorkspace(win) && isVisibleTab(win)) return;
|
|
407
|
+
const previous = focusedId;
|
|
408
|
+
focusTop();
|
|
409
|
+
if (focusedId) emitFocus(windows[focusedId], previous);
|
|
335
410
|
}
|
|
336
411
|
function emitFocus(win, previous) {
|
|
337
412
|
queueEvent(() => emitter.emit("focus", { window: win, previous }));
|
|
@@ -454,7 +529,6 @@ function createWindowManager(options = {}) {
|
|
|
454
529
|
const win = windows[id];
|
|
455
530
|
if (!win) return false;
|
|
456
531
|
if (!onActiveWorkspace(win)) setWorkspace(win.workspace);
|
|
457
|
-
if (!isVisibleTab(win)) activateTab(id);
|
|
458
532
|
const modal = topModalId();
|
|
459
533
|
if (modal && modal !== id && win.layer !== "modal") {
|
|
460
534
|
const modalWin = windows[modal];
|
|
@@ -462,6 +536,7 @@ function createWindowManager(options = {}) {
|
|
|
462
536
|
commitQuiet();
|
|
463
537
|
return false;
|
|
464
538
|
}
|
|
539
|
+
if (!isVisibleTab(win)) activateTab(id);
|
|
465
540
|
if (win.stage === "minimized") {
|
|
466
541
|
restore(id);
|
|
467
542
|
return focusedId === id;
|
|
@@ -514,8 +589,9 @@ function createWindowManager(options = {}) {
|
|
|
514
589
|
const next = build(win);
|
|
515
590
|
if (!next) return false;
|
|
516
591
|
setWindow(next);
|
|
517
|
-
syncGroup(next);
|
|
518
|
-
queueEvent(() => emitter.emit("stage", { window:
|
|
592
|
+
const synced = syncGroup(next);
|
|
593
|
+
queueEvent(() => emitter.emit("stage", { window: synced, previous: win.stage }));
|
|
594
|
+
if (next.groupId !== null) reconcileFocus();
|
|
519
595
|
commit();
|
|
520
596
|
return true;
|
|
521
597
|
}
|
|
@@ -646,9 +722,11 @@ function createWindowManager(options = {}) {
|
|
|
646
722
|
if (boundsEqual(bounds, win.bounds) && !becameNormal) return true;
|
|
647
723
|
const next = becameNormal ? { ...win, stage: "normal", snapZone: null, restoreBounds: null, bounds } : { ...win, bounds };
|
|
648
724
|
setWindow(next);
|
|
649
|
-
syncGroup(next);
|
|
650
|
-
if (becameNormal)
|
|
651
|
-
|
|
725
|
+
const synced = syncGroup(next);
|
|
726
|
+
if (becameNormal) {
|
|
727
|
+
queueEvent(() => emitter.emit("stage", { window: synced, previous: "snapped" }));
|
|
728
|
+
}
|
|
729
|
+
queueEvent(() => emitter.emit("resize", { window: synced }));
|
|
652
730
|
commit();
|
|
653
731
|
return true;
|
|
654
732
|
}
|
|
@@ -674,18 +752,18 @@ function createWindowManager(options = {}) {
|
|
|
674
752
|
const resized = size.width !== next.bounds.width || size.height !== next.bounds.height;
|
|
675
753
|
const finalWin = resized ? { ...next, bounds: { ...next.bounds, ...size } } : next;
|
|
676
754
|
setWindow(finalWin);
|
|
677
|
-
syncGroup(finalWin);
|
|
755
|
+
const synced = syncGroup(finalWin);
|
|
678
756
|
if (patch.layer && patch.layer !== win.layer) {
|
|
679
757
|
order = sortByLayer(order);
|
|
680
758
|
queueEvent(() => emitter.emit("order", { order }));
|
|
681
759
|
if (patch.layer === "modal" && topModalId() === id && focusedId !== id) {
|
|
682
760
|
const previous = focusedId;
|
|
683
761
|
focusedId = id;
|
|
684
|
-
emitFocus(
|
|
762
|
+
emitFocus(synced, previous);
|
|
685
763
|
}
|
|
686
764
|
}
|
|
687
|
-
queueEvent(() => emitter.emit("update", { window:
|
|
688
|
-
if (resized) queueEvent(() => emitter.emit("resize", { window:
|
|
765
|
+
queueEvent(() => emitter.emit("update", { window: synced }));
|
|
766
|
+
if (resized) queueEvent(() => emitter.emit("resize", { window: synced }));
|
|
689
767
|
commit();
|
|
690
768
|
return true;
|
|
691
769
|
}
|
|
@@ -720,6 +798,8 @@ function createWindowManager(options = {}) {
|
|
|
720
798
|
if (!onActiveWorkspace(updated) && focusedId === id) {
|
|
721
799
|
focusTop();
|
|
722
800
|
if (focusedId) emitFocus(windows[focusedId], id);
|
|
801
|
+
} else if (updated.groupId !== null && !onActiveWorkspace(updated)) {
|
|
802
|
+
reconcileFocus();
|
|
723
803
|
} else if (onActiveWorkspace(updated) && topModalId() === id && focusedId !== id) {
|
|
724
804
|
const previous = focusedId;
|
|
725
805
|
focusedId = id;
|
|
@@ -745,7 +825,16 @@ function createWindowManager(options = {}) {
|
|
|
745
825
|
for (const entry of siblings) if (!expanded.includes(entry)) expanded.push(entry);
|
|
746
826
|
}
|
|
747
827
|
if (expanded.length < 2) return null;
|
|
748
|
-
|
|
828
|
+
let groupId = `${idPrefix}-group-${++groupCounter}`;
|
|
829
|
+
while (activeTabs[groupId]) groupId = `${idPrefix}-group-${++groupCounter}`;
|
|
830
|
+
const shared = expanded.reduce(
|
|
831
|
+
(size, id) => {
|
|
832
|
+
const fit = normalizeSize(size, windows[id]);
|
|
833
|
+
return { width: Math.max(size.width, fit.width), height: Math.max(size.height, fit.height) };
|
|
834
|
+
},
|
|
835
|
+
{ width: host.bounds.width, height: host.bounds.height }
|
|
836
|
+
);
|
|
837
|
+
const bounds = { x: host.bounds.x, y: host.bounds.y, ...shared };
|
|
749
838
|
const retired = /* @__PURE__ */ new Set();
|
|
750
839
|
for (const id of expanded) {
|
|
751
840
|
const win = windows[id];
|
|
@@ -753,7 +842,7 @@ function createWindowManager(options = {}) {
|
|
|
753
842
|
setWindow({
|
|
754
843
|
...win,
|
|
755
844
|
groupId,
|
|
756
|
-
bounds
|
|
845
|
+
bounds,
|
|
757
846
|
stage: host.stage,
|
|
758
847
|
snapZone: host.snapZone,
|
|
759
848
|
restoreBounds: host.restoreBounds,
|
|
@@ -768,8 +857,11 @@ function createWindowManager(options = {}) {
|
|
|
768
857
|
raise(host.id);
|
|
769
858
|
emitGroup(groupId, null);
|
|
770
859
|
queueEvent(() => emitter.emit("order", { order }));
|
|
860
|
+
const hostVisible = onActiveWorkspace(host) && host.stage !== "minimized";
|
|
861
|
+
commit();
|
|
862
|
+
if (hostVisible) focus(host.id);
|
|
863
|
+
reconcileFocus();
|
|
771
864
|
commit();
|
|
772
|
-
if (onActiveWorkspace(host) && host.stage !== "minimized") focus(host.id);
|
|
773
865
|
return groupId;
|
|
774
866
|
}
|
|
775
867
|
function ungroup(id) {
|
|
@@ -783,7 +875,7 @@ function createWindowManager(options = {}) {
|
|
|
783
875
|
dissolveIfOrphaned(groupId);
|
|
784
876
|
if (membersOf(groupId).length >= 2) emitGroup(groupId, wasActive ? id : null);
|
|
785
877
|
commit();
|
|
786
|
-
focus(id);
|
|
878
|
+
if (onActiveWorkspace(win) && win.stage !== "minimized") focus(id);
|
|
787
879
|
return true;
|
|
788
880
|
}
|
|
789
881
|
function activateTab(id) {
|
|
@@ -793,6 +885,10 @@ function createWindowManager(options = {}) {
|
|
|
793
885
|
const previous = activeTabs[groupId];
|
|
794
886
|
if (previous === id) return false;
|
|
795
887
|
activeTabs = { ...activeTabs, [groupId]: id };
|
|
888
|
+
if (focusedId === previous) {
|
|
889
|
+
focusedId = id;
|
|
890
|
+
emitFocus(win, previous);
|
|
891
|
+
}
|
|
796
892
|
emitGroup(groupId, previous);
|
|
797
893
|
commit();
|
|
798
894
|
return true;
|
|
@@ -803,14 +899,15 @@ function createWindowManager(options = {}) {
|
|
|
803
899
|
function sendToBack(id) {
|
|
804
900
|
const win = windows[id];
|
|
805
901
|
if (!win) return false;
|
|
806
|
-
const
|
|
902
|
+
const block = blockOf(id);
|
|
903
|
+
const without = order.filter((entry) => !block.includes(entry));
|
|
807
904
|
const rank = LAYER_RANK[win.layer];
|
|
808
905
|
let insertAt = 0;
|
|
809
906
|
for (const entry of without) {
|
|
810
907
|
if (layerRankOf(entry) < rank) insertAt += 1;
|
|
811
908
|
else break;
|
|
812
909
|
}
|
|
813
|
-
const next = [...without.slice(0, insertAt),
|
|
910
|
+
const next = [...without.slice(0, insertAt), ...block, ...without.slice(insertAt)];
|
|
814
911
|
if (next.every((entry, i) => entry === order[i])) return false;
|
|
815
912
|
order = next;
|
|
816
913
|
queueEvent(() => emitter.emit("order", { order }));
|
|
@@ -834,6 +931,7 @@ function createWindowManager(options = {}) {
|
|
|
834
931
|
return Object.values(windows).filter((win) => win.stage === "minimized" && onActiveWorkspace(win) && isVisibleTab(win)).sort((a, b) => a.openedSeq - b.openedSeq);
|
|
835
932
|
}
|
|
836
933
|
function captureEntry() {
|
|
934
|
+
windowsShared = true;
|
|
837
935
|
return { windows, order, focusedId, workspace, activeTabs };
|
|
838
936
|
}
|
|
839
937
|
function recordHistory() {
|
|
@@ -874,19 +972,23 @@ function createWindowManager(options = {}) {
|
|
|
874
972
|
function reflowViewport() {
|
|
875
973
|
for (const id of order) {
|
|
876
974
|
const win = windows[id];
|
|
975
|
+
if (!isVisibleTab(win)) continue;
|
|
877
976
|
if (win.stage === "maximized") {
|
|
878
977
|
const updated = { ...win, bounds: fullBounds() };
|
|
879
978
|
setWindow(updated);
|
|
880
|
-
|
|
979
|
+
const synced = syncGroup(updated);
|
|
980
|
+
queueEvent(() => emitter.emit("resize", { window: synced }));
|
|
881
981
|
} else if (win.stage === "snapped" && win.snapZone) {
|
|
882
982
|
const updated = { ...win, bounds: snapBounds(win, win.snapZone) };
|
|
883
983
|
setWindow(updated);
|
|
884
|
-
|
|
984
|
+
const synced = syncGroup(updated);
|
|
985
|
+
queueEvent(() => emitter.emit("resize", { window: synced }));
|
|
885
986
|
} else if (win.stage === "normal" && keepInViewport) {
|
|
886
987
|
const bounds = clampToViewport(win.bounds, viewport, minVisible);
|
|
887
988
|
if (!boundsEqual(bounds, win.bounds)) {
|
|
888
989
|
const updated = { ...win, bounds };
|
|
889
990
|
setWindow(updated);
|
|
991
|
+
syncGroup(updated);
|
|
890
992
|
queueEvent(() => emitter.emit("move", { window: updated }));
|
|
891
993
|
}
|
|
892
994
|
}
|
|
@@ -895,6 +997,8 @@ function createWindowManager(options = {}) {
|
|
|
895
997
|
function applyEntry(entry) {
|
|
896
998
|
windows = entry.windows;
|
|
897
999
|
order = [...entry.order];
|
|
1000
|
+
modalCount = countModals();
|
|
1001
|
+
groupsDirty = true;
|
|
898
1002
|
focusedId = entry.focusedId;
|
|
899
1003
|
activeTabs = entry.activeTabs;
|
|
900
1004
|
const previousWorkspace = workspace;
|
|
@@ -973,7 +1077,7 @@ function createWindowManager(options = {}) {
|
|
|
973
1077
|
function arrange(mode) {
|
|
974
1078
|
const ids = order.filter((id) => {
|
|
975
1079
|
const win = windows[id];
|
|
976
|
-
return win.stage !== "minimized" && onActiveWorkspace(win);
|
|
1080
|
+
return win.stage !== "minimized" && onActiveWorkspace(win) && isVisibleTab(win);
|
|
977
1081
|
});
|
|
978
1082
|
if (ids.length === 0) return;
|
|
979
1083
|
if (mode === "cascade") {
|
|
@@ -1005,7 +1109,8 @@ function createWindowManager(options = {}) {
|
|
|
1005
1109
|
}
|
|
1006
1110
|
function minimizeAll() {
|
|
1007
1111
|
for (const id of [...order]) {
|
|
1008
|
-
|
|
1112
|
+
const win = windows[id];
|
|
1113
|
+
if (onActiveWorkspace(win) && isVisibleTab(win)) minimize(id);
|
|
1009
1114
|
}
|
|
1010
1115
|
}
|
|
1011
1116
|
function restoreAll() {
|
|
@@ -1112,8 +1217,11 @@ function createWindowManager(options = {}) {
|
|
|
1112
1217
|
if (!seen.has(id)) nextOrder.push(id);
|
|
1113
1218
|
}
|
|
1114
1219
|
windows = nextWindows;
|
|
1220
|
+
windowsShared = false;
|
|
1115
1221
|
order = nextOrder;
|
|
1116
1222
|
order = sortByLayer(order);
|
|
1223
|
+
modalCount = countModals();
|
|
1224
|
+
groupsDirty = true;
|
|
1117
1225
|
seq = maxSeq;
|
|
1118
1226
|
const previousWorkspace = workspace;
|
|
1119
1227
|
workspace = normalizeWorkspace(data.workspace, 0);
|
|
@@ -1125,7 +1233,7 @@ function createWindowManager(options = {}) {
|
|
|
1125
1233
|
if (focusedCandidate && (focusedCandidate.stage === "minimized" || !onActiveWorkspace(focusedCandidate))) {
|
|
1126
1234
|
focusedId = null;
|
|
1127
1235
|
}
|
|
1128
|
-
const restoredTabs =
|
|
1236
|
+
const restoredTabs = /* @__PURE__ */ Object.create(null);
|
|
1129
1237
|
const rawTabs = data.activeTabs;
|
|
1130
1238
|
for (const id of order) {
|
|
1131
1239
|
const groupId = windows[id].groupId;
|
|
@@ -1222,6 +1330,7 @@ function createWindowManager(options = {}) {
|
|
|
1222
1330
|
|
|
1223
1331
|
// src/dom/animate.ts
|
|
1224
1332
|
function prefersReducedMotion(win) {
|
|
1333
|
+
if (typeof win.matchMedia !== "function") return false;
|
|
1225
1334
|
return win.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1226
1335
|
}
|
|
1227
1336
|
function flipFromTarget(source, target, options = {}) {
|
|
@@ -1350,14 +1459,6 @@ function createAnnouncer(wm, container, messages = {}) {
|
|
|
1350
1459
|
};
|
|
1351
1460
|
}
|
|
1352
1461
|
|
|
1353
|
-
// src/dom/shared.ts
|
|
1354
|
-
var INTERACTIVE_SELECTOR = "button, input, select, textarea, a[href], [contenteditable], [data-wm-close], [data-wm-minimize], [data-wm-maximize]";
|
|
1355
|
-
function windowOf(element) {
|
|
1356
|
-
const view = element.ownerDocument.defaultView;
|
|
1357
|
-
if (!view) throw new Error("wmkit: desktop element is not attached to a document");
|
|
1358
|
-
return view;
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
1462
|
// src/dom/drag.ts
|
|
1362
1463
|
function createDragStarter(ctx) {
|
|
1363
1464
|
const { wm, doc, view } = ctx;
|
|
@@ -1365,7 +1466,7 @@ function createDragStarter(ctx) {
|
|
|
1365
1466
|
const win = wm.get(id);
|
|
1366
1467
|
if (!win?.draggable || event.button !== 0 || ctx.currentDrag()) return;
|
|
1367
1468
|
const target = event.target;
|
|
1368
|
-
if (target?.closest(
|
|
1469
|
+
if (target?.closest(ctx.interactiveSelector)) return;
|
|
1369
1470
|
event.preventDefault();
|
|
1370
1471
|
const releaseRect = ctx.trackRect();
|
|
1371
1472
|
const point = ctx.toLocal(event);
|
|
@@ -1398,6 +1499,8 @@ function createDragStarter(ctx) {
|
|
|
1398
1499
|
const el = ctx.windowElement(id);
|
|
1399
1500
|
function armGroup(target2) {
|
|
1400
1501
|
session.groupTarget = target2;
|
|
1502
|
+
session.zone = null;
|
|
1503
|
+
ctx.hidePreview();
|
|
1401
1504
|
ctx.markGroupTarget(target2);
|
|
1402
1505
|
}
|
|
1403
1506
|
function clearHover() {
|
|
@@ -1442,9 +1545,9 @@ function createDragStarter(ctx) {
|
|
|
1442
1545
|
for (const otherId of state.order) {
|
|
1443
1546
|
if (otherId === id) continue;
|
|
1444
1547
|
const other = state.windows[otherId];
|
|
1445
|
-
if (other
|
|
1446
|
-
|
|
1447
|
-
|
|
1548
|
+
if (!other || other.stage === "minimized" || other.workspace !== state.workspace) continue;
|
|
1549
|
+
if (other.groupId !== null && state.groups[other.groupId]?.activeId !== otherId) continue;
|
|
1550
|
+
targets.push(other.bounds);
|
|
1448
1551
|
}
|
|
1449
1552
|
const magnet = magnetize(
|
|
1450
1553
|
{ x: nextX, y: nextY, width: current.bounds.width, height: current.bounds.height },
|
|
@@ -1718,6 +1821,99 @@ function createResizeHandles(doc, edge, corner) {
|
|
|
1718
1821
|
});
|
|
1719
1822
|
}
|
|
1720
1823
|
|
|
1824
|
+
// src/dom/shared.ts
|
|
1825
|
+
var INTERACTIVE_SELECTOR = "button, input, select, textarea, a[href], [contenteditable], [data-wm-close], [data-wm-minimize], [data-wm-maximize]";
|
|
1826
|
+
function windowOf(element) {
|
|
1827
|
+
const view = element.ownerDocument.defaultView;
|
|
1828
|
+
if (!view) throw new Error("wmkit: desktop element is not attached to a document");
|
|
1829
|
+
return view;
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
// src/dom/stacking.ts
|
|
1833
|
+
var UNASSIGNED = Number.NEGATIVE_INFINITY;
|
|
1834
|
+
var tails = new Int32Array(0);
|
|
1835
|
+
var parents = new Int32Array(0);
|
|
1836
|
+
var kept = new Uint8Array(0);
|
|
1837
|
+
function reserve(length) {
|
|
1838
|
+
if (tails.length >= length) return;
|
|
1839
|
+
const size = Math.max(length, 64);
|
|
1840
|
+
tails = new Int32Array(size);
|
|
1841
|
+
parents = new Int32Array(size);
|
|
1842
|
+
kept = new Uint8Array(size);
|
|
1843
|
+
}
|
|
1844
|
+
function markLongestIncreasing(target) {
|
|
1845
|
+
const length = target.length;
|
|
1846
|
+
reserve(length);
|
|
1847
|
+
kept.fill(0, 0, length);
|
|
1848
|
+
let size = 0;
|
|
1849
|
+
for (let i = 0; i < length; i += 1) {
|
|
1850
|
+
const value = target.zAt(i);
|
|
1851
|
+
parents[i] = -1;
|
|
1852
|
+
if (!Number.isFinite(value)) continue;
|
|
1853
|
+
let low = 0;
|
|
1854
|
+
let high = size;
|
|
1855
|
+
while (low < high) {
|
|
1856
|
+
const mid = low + high >> 1;
|
|
1857
|
+
if (target.zAt(tails[mid]) < value) low = mid + 1;
|
|
1858
|
+
else high = mid;
|
|
1859
|
+
}
|
|
1860
|
+
if (low > 0) parents[i] = tails[low - 1];
|
|
1861
|
+
tails[low] = i;
|
|
1862
|
+
if (low === size) size += 1;
|
|
1863
|
+
}
|
|
1864
|
+
let cursor = size > 0 ? tails[size - 1] : -1;
|
|
1865
|
+
let count = 0;
|
|
1866
|
+
while (cursor !== -1) {
|
|
1867
|
+
kept[cursor] = 1;
|
|
1868
|
+
count += 1;
|
|
1869
|
+
cursor = parents[cursor];
|
|
1870
|
+
}
|
|
1871
|
+
return count;
|
|
1872
|
+
}
|
|
1873
|
+
function between(low, high, base, gap) {
|
|
1874
|
+
if (!Number.isFinite(high)) return Number.isFinite(low) ? low + gap : base + gap;
|
|
1875
|
+
if (!Number.isFinite(low)) {
|
|
1876
|
+
const candidate2 = high - gap > base ? high - gap : Math.floor((base + high) / 2);
|
|
1877
|
+
return candidate2 > base && candidate2 < high ? candidate2 : null;
|
|
1878
|
+
}
|
|
1879
|
+
const candidate = Math.floor((low + high) / 2);
|
|
1880
|
+
return candidate > low && candidate < high ? candidate : null;
|
|
1881
|
+
}
|
|
1882
|
+
function renormalize(target, base, gap) {
|
|
1883
|
+
let writes = 0;
|
|
1884
|
+
for (let i = 0; i < target.length; i += 1) {
|
|
1885
|
+
const z = base + (i + 1) * gap;
|
|
1886
|
+
if (target.zAt(i) === z) continue;
|
|
1887
|
+
target.assign(i, z);
|
|
1888
|
+
writes += 1;
|
|
1889
|
+
}
|
|
1890
|
+
return writes;
|
|
1891
|
+
}
|
|
1892
|
+
function restack(target, options = {}) {
|
|
1893
|
+
const base = options.base ?? 0;
|
|
1894
|
+
const gap = options.gap ?? 32;
|
|
1895
|
+
const length = target.length;
|
|
1896
|
+
if (length === 0) return 0;
|
|
1897
|
+
const keepCount = markLongestIncreasing(target);
|
|
1898
|
+
if (length - keepCount > length / 3) return renormalize(target, base, gap);
|
|
1899
|
+
let writes = 0;
|
|
1900
|
+
for (let i = 0; i < length; i += 1) {
|
|
1901
|
+
if (kept[i] === 1) continue;
|
|
1902
|
+
const low = i > 0 ? target.zAt(i - 1) : UNASSIGNED;
|
|
1903
|
+
let high = Number.POSITIVE_INFINITY;
|
|
1904
|
+
for (let j = i + 1; j < length; j += 1) {
|
|
1905
|
+
if (kept[j] !== 1) continue;
|
|
1906
|
+
high = target.zAt(j);
|
|
1907
|
+
break;
|
|
1908
|
+
}
|
|
1909
|
+
const z = between(low, high, base, gap);
|
|
1910
|
+
if (z === null) return renormalize(target, base, gap);
|
|
1911
|
+
target.assign(i, z);
|
|
1912
|
+
writes += 1;
|
|
1913
|
+
}
|
|
1914
|
+
return writes;
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1721
1917
|
// src/dom/controller.ts
|
|
1722
1918
|
var SNAP_SHORTCUTS = {
|
|
1723
1919
|
ArrowLeft: "left",
|
|
@@ -1744,17 +1940,24 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1744
1940
|
const hitEdge = options.hitAreas?.edge ?? (coarsePointer ? 16 : 8);
|
|
1745
1941
|
const hitCorner = options.hitAreas?.corner ?? (coarsePointer ? 24 : 12);
|
|
1746
1942
|
const magnetThreshold = options.magnetism === false ? 0 : (typeof options.magnetism === "object" ? options.magnetism.threshold : void 0) ?? (coarsePointer ? 12 : 8);
|
|
1943
|
+
const zIndexBase = options.stacking?.base ?? 0;
|
|
1944
|
+
const zIndexGap = options.stacking?.gap ?? 32;
|
|
1945
|
+
const interactiveSelector = options.interactiveSelector ?? INTERACTIVE_SELECTOR;
|
|
1946
|
+
const animationEnabled = options.animation !== false;
|
|
1947
|
+
const animationOptions = typeof options.animation === "object" ? options.animation : {};
|
|
1747
1948
|
element.dataset.wmDesktop = "";
|
|
1748
1949
|
element.tabIndex = -1;
|
|
1749
1950
|
if (view.getComputedStyle(element).position === "static") {
|
|
1750
1951
|
element.style.position = "relative";
|
|
1751
1952
|
}
|
|
1953
|
+
if (options.stacking?.isolate !== false) element.style.isolation = "isolate";
|
|
1752
1954
|
const registry = /* @__PURE__ */ new Map();
|
|
1753
1955
|
const cleanup = [];
|
|
1754
1956
|
let lastOrder = null;
|
|
1755
1957
|
let lastFocused = null;
|
|
1756
1958
|
let drag = null;
|
|
1757
1959
|
let groupTargetId = null;
|
|
1960
|
+
let groupTargetEl = null;
|
|
1758
1961
|
let cachedRect = null;
|
|
1759
1962
|
let rectUsers = 0;
|
|
1760
1963
|
let announcer = null;
|
|
@@ -1825,6 +2028,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1825
2028
|
topEdge,
|
|
1826
2029
|
hitEdge,
|
|
1827
2030
|
hitCorner,
|
|
2031
|
+
interactiveSelector,
|
|
1828
2032
|
magnetThreshold,
|
|
1829
2033
|
groupDwell,
|
|
1830
2034
|
groupTarget(clientX, clientY, selfId) {
|
|
@@ -1833,21 +2037,16 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1833
2037
|
const handle = node.closest?.("[data-wm-drag]");
|
|
1834
2038
|
const host = handle?.closest("[data-wm-window]");
|
|
1835
2039
|
const id = host?.dataset.wmWindow;
|
|
1836
|
-
if (id && id !== selfId && registry.
|
|
2040
|
+
if (id && id !== selfId && registry.get(id)?.element === host) return id;
|
|
1837
2041
|
}
|
|
1838
2042
|
return null;
|
|
1839
2043
|
},
|
|
1840
2044
|
markGroupTarget(id) {
|
|
1841
2045
|
if (groupTargetId === id) return;
|
|
1842
|
-
if (
|
|
1843
|
-
const previous = registry.get(groupTargetId);
|
|
1844
|
-
if (previous) delete previous.element.dataset.wmTabTarget;
|
|
1845
|
-
}
|
|
2046
|
+
if (groupTargetEl) delete groupTargetEl.dataset.wmTabTarget;
|
|
1846
2047
|
groupTargetId = id;
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
if (next) next.element.dataset.wmTabTarget = "";
|
|
1850
|
-
}
|
|
2048
|
+
groupTargetEl = id ? registry.get(id)?.element ?? null : null;
|
|
2049
|
+
if (groupTargetEl) groupTargetEl.dataset.wmTabTarget = "";
|
|
1851
2050
|
},
|
|
1852
2051
|
currentDrag: () => drag,
|
|
1853
2052
|
claimDrag(session) {
|
|
@@ -1866,7 +2065,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1866
2065
|
observer.observe(element);
|
|
1867
2066
|
cleanup.push(() => observer.disconnect());
|
|
1868
2067
|
}
|
|
1869
|
-
function syncWindow(attached, win,
|
|
2068
|
+
function syncWindow(attached, win, activeWorkspace, activeTab) {
|
|
1870
2069
|
const el = attached.element;
|
|
1871
2070
|
const firstSync = attached.lastState === null;
|
|
1872
2071
|
if (firstSync) el.style.transition = "none";
|
|
@@ -1904,27 +2103,44 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1904
2103
|
attached.lastWorkspace = activeWorkspace;
|
|
1905
2104
|
attached.lastTab = activeTab;
|
|
1906
2105
|
}
|
|
1907
|
-
if (attached.lastZ !== zIndex) {
|
|
1908
|
-
el.style.zIndex = String(zIndex + 1);
|
|
1909
|
-
attached.lastZ = zIndex;
|
|
1910
|
-
}
|
|
1911
2106
|
if (firstSync) {
|
|
1912
2107
|
void el.offsetWidth;
|
|
1913
2108
|
el.style.transition = "";
|
|
1914
2109
|
}
|
|
1915
2110
|
}
|
|
2111
|
+
const stackRows = [];
|
|
2112
|
+
const stackTarget = {
|
|
2113
|
+
length: 0,
|
|
2114
|
+
zAt: (index) => stackRows[index].lastZ,
|
|
2115
|
+
assign(index, z) {
|
|
2116
|
+
const attached = stackRows[index];
|
|
2117
|
+
attached.lastZ = z;
|
|
2118
|
+
attached.element.style.zIndex = String(z);
|
|
2119
|
+
}
|
|
2120
|
+
};
|
|
2121
|
+
function applyStacking(order) {
|
|
2122
|
+
let length = 0;
|
|
2123
|
+
for (const id of order) {
|
|
2124
|
+
const attached = registry.get(id);
|
|
2125
|
+
if (attached) stackRows[length++] = attached;
|
|
2126
|
+
}
|
|
2127
|
+
stackTarget.length = length;
|
|
2128
|
+
restack(stackTarget, { base: zIndexBase, gap: zIndexGap });
|
|
2129
|
+
stackRows.length = length;
|
|
2130
|
+
}
|
|
1916
2131
|
function syncAll() {
|
|
1917
2132
|
const state = wm.getState();
|
|
1918
2133
|
const orderChanged = state.order !== lastOrder;
|
|
1919
|
-
state.order
|
|
2134
|
+
for (const id of state.order) {
|
|
1920
2135
|
const attached = registry.get(id);
|
|
1921
2136
|
const win = state.windows[id];
|
|
1922
|
-
if (!attached || !win)
|
|
2137
|
+
if (!attached || !win) continue;
|
|
1923
2138
|
const activeTab = win.groupId === null || state.groups[win.groupId]?.activeId === win.id;
|
|
1924
|
-
if (
|
|
1925
|
-
syncWindow(attached, win,
|
|
2139
|
+
if (attached.lastState !== win || attached.lastWorkspace !== state.workspace || attached.lastTab !== activeTab) {
|
|
2140
|
+
syncWindow(attached, win, state.workspace, activeTab);
|
|
1926
2141
|
}
|
|
1927
|
-
}
|
|
2142
|
+
}
|
|
2143
|
+
if (orderChanged) applyStacking(state.order);
|
|
1928
2144
|
if (state.focusedId !== lastFocused) {
|
|
1929
2145
|
if (lastFocused) {
|
|
1930
2146
|
const prev = registry.get(lastFocused);
|
|
@@ -1962,12 +2178,17 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1962
2178
|
wm.on("stage", ({ window: win, previous }) => {
|
|
1963
2179
|
const attached = registry.get(win.id);
|
|
1964
2180
|
if (!attached) return;
|
|
2181
|
+
if (!animationEnabled) return;
|
|
1965
2182
|
if (win.stage === "minimized" && previous !== "minimized") {
|
|
1966
2183
|
const target = options.minimizeTarget?.(win);
|
|
1967
|
-
if (target) flipToTarget(attached.element, target);
|
|
2184
|
+
if (target) flipToTarget(attached.element, target, animationOptions);
|
|
1968
2185
|
} else if (previous === "minimized" && win.stage !== "minimized") {
|
|
1969
2186
|
const target = options.minimizeTarget?.(win);
|
|
1970
|
-
if (target)
|
|
2187
|
+
if (target) {
|
|
2188
|
+
view.requestAnimationFrame(
|
|
2189
|
+
() => flipFromTarget(attached.element, target, animationOptions)
|
|
2190
|
+
);
|
|
2191
|
+
}
|
|
1971
2192
|
}
|
|
1972
2193
|
})
|
|
1973
2194
|
);
|
|
@@ -1981,7 +2202,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1981
2202
|
if (!event.ctrlKey && !event.metaKey) return;
|
|
1982
2203
|
if (drag) return;
|
|
1983
2204
|
const target = event.target;
|
|
1984
|
-
if (target?.closest(
|
|
2205
|
+
if (target?.closest(interactiveSelector)) return;
|
|
1985
2206
|
if (historyShortcuts && (event.key === "z" || event.key === "Z")) {
|
|
1986
2207
|
event.preventDefault();
|
|
1987
2208
|
if (event.shiftKey) wm.redo();
|
|
@@ -2023,7 +2244,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
2023
2244
|
handle: null,
|
|
2024
2245
|
handles: [],
|
|
2025
2246
|
lastState: null,
|
|
2026
|
-
lastZ:
|
|
2247
|
+
lastZ: UNASSIGNED,
|
|
2027
2248
|
lastWorkspace: -1,
|
|
2028
2249
|
lastTab: true,
|
|
2029
2250
|
cleanup: []
|
|
@@ -2057,7 +2278,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
2057
2278
|
const current = wm.get(id);
|
|
2058
2279
|
if (!current) return;
|
|
2059
2280
|
if (target.closest("[data-wm-close]")) {
|
|
2060
|
-
if (current.closable) wm.close(id);
|
|
2281
|
+
if (current.closable && options.beforeClose?.(current) !== false) wm.close(id);
|
|
2061
2282
|
} else if (target.closest("[data-wm-minimize]")) {
|
|
2062
2283
|
if (current.minimizable) wm.minimize(id);
|
|
2063
2284
|
} else if (target.closest("[data-wm-maximize]")) {
|
|
@@ -2073,7 +2294,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
2073
2294
|
attached.cleanup.push(() => handle.removeEventListener("pointerdown", onHandleDown));
|
|
2074
2295
|
const onDoubleClick = (event) => {
|
|
2075
2296
|
const target = event.target;
|
|
2076
|
-
if (target?.closest(
|
|
2297
|
+
if (target?.closest(interactiveSelector)) return;
|
|
2077
2298
|
const current = wm.get(id);
|
|
2078
2299
|
if (current?.maximizable) wm.toggleMaximize(id);
|
|
2079
2300
|
};
|
|
@@ -2105,7 +2326,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
2105
2326
|
}
|
|
2106
2327
|
const onWindowKeydown = (event) => {
|
|
2107
2328
|
const target = event.target;
|
|
2108
|
-
if (target?.closest(
|
|
2329
|
+
if (target?.closest(interactiveSelector)) return;
|
|
2109
2330
|
const current = wm.get(id);
|
|
2110
2331
|
if (!current) return;
|
|
2111
2332
|
const arrows = {
|
|
@@ -2249,5 +2470,5 @@ function createDesktopBinder(wm, options = {}) {
|
|
|
2249
2470
|
}
|
|
2250
2471
|
|
|
2251
2472
|
export { applyAspect, attachDesktop, boundsEqual, clamp, clampSize, clampToViewport, createAnnouncer, createDesktopBinder, createEmitter, createWindowManager, defaultMessages, detectSnapZone, flipFromTarget, flipToTarget, magnetize, prefersReducedMotion, zoneBounds };
|
|
2252
|
-
//# sourceMappingURL=chunk-
|
|
2253
|
-
//# sourceMappingURL=chunk-
|
|
2473
|
+
//# sourceMappingURL=chunk-3HLKVOSI.js.map
|
|
2474
|
+
//# sourceMappingURL=chunk-3HLKVOSI.js.map
|