@surdeddd/wmkit 0.4.2 → 0.5.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.
- package/README.md +1 -0
- package/README.ru.md +1 -0
- package/dist/angular.cjs +3 -3
- package/dist/angular.d.cts +2 -2
- package/dist/angular.d.ts +2 -2
- package/dist/angular.js +1 -1
- package/dist/{binder-B2A2IZGh.d.ts → binder-Ca3GOfZX.d.ts} +5 -1
- package/dist/{binder-Dl07SXIM.d.cts → binder-EBroZTRw.d.cts} +5 -1
- package/dist/{chunk-GGDF2EWV.js → chunk-2WQHHYYR.js} +280 -23
- package/dist/chunk-2WQHHYYR.js.map +1 -0
- package/dist/{chunk-GLBVT4AQ.cjs → chunk-C2UHNBSA.cjs} +280 -23
- package/dist/chunk-C2UHNBSA.cjs.map +1 -0
- package/dist/index.cjs +18 -18
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/persist.d.cts +1 -1
- package/dist/persist.d.ts +1 -1
- package/dist/popout.d.cts +1 -1
- package/dist/popout.d.ts +1 -1
- package/dist/react.cjs +3 -3
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +1 -1
- package/dist/solid.cjs +3 -3
- package/dist/solid.d.cts +2 -2
- package/dist/solid.d.ts +2 -2
- package/dist/solid.js +1 -1
- package/dist/svelte.cjs +3 -3
- package/dist/svelte.d.cts +2 -2
- package/dist/svelte.d.ts +2 -2
- package/dist/svelte.js +1 -1
- package/dist/{types-t6pyVYKN.d.cts → types-LP7Inhxx.d.cts} +18 -0
- package/dist/{types-t6pyVYKN.d.ts → types-LP7Inhxx.d.ts} +18 -0
- package/dist/vue.cjs +3 -3
- package/dist/vue.d.cts +2 -2
- package/dist/vue.d.ts +2 -2
- package/dist/vue.js +1 -1
- package/package.json +7 -7
- package/dist/chunk-GGDF2EWV.js.map +0 -1
- package/dist/chunk-GLBVT4AQ.cjs.map +0 -1
|
@@ -199,6 +199,8 @@ function createWindowManager(options = {}) {
|
|
|
199
199
|
let focusedId = null;
|
|
200
200
|
let viewport = options.viewport ?? { width: 0, height: 0 };
|
|
201
201
|
let workspace = normalizeWorkspace(options.workspace, 0);
|
|
202
|
+
let activeTabs = {};
|
|
203
|
+
let groupCounter = 0;
|
|
202
204
|
let seq = 0;
|
|
203
205
|
let idCounter = 0;
|
|
204
206
|
let cascadeIndex = 0;
|
|
@@ -217,7 +219,7 @@ function createWindowManager(options = {}) {
|
|
|
217
219
|
const layouts = /* @__PURE__ */ new Map();
|
|
218
220
|
function getState() {
|
|
219
221
|
if (!snapshot) {
|
|
220
|
-
snapshot = { windows, order, focusedId, viewport, workspace };
|
|
222
|
+
snapshot = { windows, order, focusedId, viewport, workspace, groups: buildGroups() };
|
|
221
223
|
}
|
|
222
224
|
return snapshot;
|
|
223
225
|
}
|
|
@@ -252,16 +254,22 @@ function createWindowManager(options = {}) {
|
|
|
252
254
|
function sortByLayer(ids) {
|
|
253
255
|
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
256
|
}
|
|
257
|
+
function blockOf(id) {
|
|
258
|
+
const win = windows[id];
|
|
259
|
+
if (win.groupId === null) return [id];
|
|
260
|
+
return [...membersOf(win.groupId).filter((entry) => entry !== id), id];
|
|
261
|
+
}
|
|
255
262
|
function raise(id) {
|
|
256
263
|
const win = windows[id];
|
|
257
|
-
const
|
|
264
|
+
const block = blockOf(id);
|
|
265
|
+
const without = order.filter((entry) => !block.includes(entry));
|
|
258
266
|
const rank = LAYER_RANK[win.layer];
|
|
259
267
|
let insertAt = without.length;
|
|
260
268
|
for (let i = without.length - 1; i >= 0; i -= 1) {
|
|
261
269
|
if (layerRankOf(without[i]) > rank) insertAt = i;
|
|
262
270
|
else break;
|
|
263
271
|
}
|
|
264
|
-
const next = [...without.slice(0, insertAt),
|
|
272
|
+
const next = [...without.slice(0, insertAt), ...block, ...without.slice(insertAt)];
|
|
265
273
|
const changed = next.length !== order.length || next.some((entry, i) => entry !== order[i]);
|
|
266
274
|
order = next;
|
|
267
275
|
return changed;
|
|
@@ -269,11 +277,54 @@ function createWindowManager(options = {}) {
|
|
|
269
277
|
function onActiveWorkspace(win) {
|
|
270
278
|
return win.workspace === workspace;
|
|
271
279
|
}
|
|
280
|
+
function membersOf(groupId) {
|
|
281
|
+
return order.filter((entry) => windows[entry].groupId === groupId);
|
|
282
|
+
}
|
|
283
|
+
function isVisibleTab(win) {
|
|
284
|
+
return win.groupId === null || activeTabs[win.groupId] === win.id;
|
|
285
|
+
}
|
|
286
|
+
function buildGroups() {
|
|
287
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
288
|
+
for (const [groupId, activeId] of Object.entries(activeTabs)) {
|
|
289
|
+
result[groupId] = { id: groupId, activeId, members: membersOf(groupId) };
|
|
290
|
+
}
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
function syncGroup(source) {
|
|
294
|
+
if (source.groupId === null) return;
|
|
295
|
+
for (const id of membersOf(source.groupId)) {
|
|
296
|
+
if (id === source.id) continue;
|
|
297
|
+
const member = windows[id];
|
|
298
|
+
if (boundsEqual(member.bounds, source.bounds) && member.stage === source.stage && member.snapZone === source.snapZone && member.layer === source.layer && member.workspace === source.workspace) {
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
setWindow({
|
|
302
|
+
...member,
|
|
303
|
+
bounds: source.bounds,
|
|
304
|
+
stage: source.stage,
|
|
305
|
+
snapZone: source.snapZone,
|
|
306
|
+
restoreBounds: source.restoreBounds,
|
|
307
|
+
restoreStage: source.restoreStage,
|
|
308
|
+
layer: source.layer,
|
|
309
|
+
workspace: source.workspace
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
function dissolveIfOrphaned(groupId) {
|
|
314
|
+
const members = membersOf(groupId);
|
|
315
|
+
if (members.length >= 2) return;
|
|
316
|
+
for (const id of members) {
|
|
317
|
+
setWindow({ ...windows[id], groupId: null });
|
|
318
|
+
}
|
|
319
|
+
const { [groupId]: _dropped, ...rest } = activeTabs;
|
|
320
|
+
activeTabs = rest;
|
|
321
|
+
}
|
|
272
322
|
function topModalId() {
|
|
273
323
|
for (let i = order.length - 1; i >= 0; i -= 1) {
|
|
274
324
|
const win = windows[order[i]];
|
|
275
|
-
if (win.layer === "modal" && win.stage !== "minimized" && onActiveWorkspace(win))
|
|
325
|
+
if (win.layer === "modal" && win.stage !== "minimized" && onActiveWorkspace(win) && isVisibleTab(win)) {
|
|
276
326
|
return win.id;
|
|
327
|
+
}
|
|
277
328
|
}
|
|
278
329
|
return null;
|
|
279
330
|
}
|
|
@@ -281,7 +332,7 @@ function createWindowManager(options = {}) {
|
|
|
281
332
|
const modal = topModalId();
|
|
282
333
|
return order.filter((id) => {
|
|
283
334
|
const win = windows[id];
|
|
284
|
-
if (win.stage === "minimized" || !onActiveWorkspace(win)) return false;
|
|
335
|
+
if (win.stage === "minimized" || !onActiveWorkspace(win) || !isVisibleTab(win)) return false;
|
|
285
336
|
if (modal && win.layer !== "modal") return false;
|
|
286
337
|
return true;
|
|
287
338
|
});
|
|
@@ -290,6 +341,14 @@ function createWindowManager(options = {}) {
|
|
|
290
341
|
const targets = focusTargets();
|
|
291
342
|
focusedId = targets.length > 0 ? targets[targets.length - 1] : null;
|
|
292
343
|
}
|
|
344
|
+
function reconcileFocus() {
|
|
345
|
+
if (focusedId === null) return;
|
|
346
|
+
const win = windows[focusedId];
|
|
347
|
+
if (win && win.stage !== "minimized" && onActiveWorkspace(win) && isVisibleTab(win)) return;
|
|
348
|
+
const previous = focusedId;
|
|
349
|
+
focusTop();
|
|
350
|
+
if (focusedId) emitFocus(windows[focusedId], previous);
|
|
351
|
+
}
|
|
293
352
|
function emitFocus(win, previous) {
|
|
294
353
|
queueEvent(() => emitter.emit("focus", { window: win, previous }));
|
|
295
354
|
}
|
|
@@ -344,6 +403,7 @@ function createWindowManager(options = {}) {
|
|
|
344
403
|
snapZone: null,
|
|
345
404
|
layer: init.layer ?? "normal",
|
|
346
405
|
workspace: normalizeWorkspace(init.workspace, workspace),
|
|
406
|
+
groupId: null,
|
|
347
407
|
minSize,
|
|
348
408
|
maxSize,
|
|
349
409
|
aspectRatio,
|
|
@@ -387,6 +447,13 @@ function createWindowManager(options = {}) {
|
|
|
387
447
|
const win = windows[id];
|
|
388
448
|
if (!win) return false;
|
|
389
449
|
removeWindow(id);
|
|
450
|
+
if (win.groupId !== null) {
|
|
451
|
+
const remaining = membersOf(win.groupId);
|
|
452
|
+
if (activeTabs[win.groupId] === id && remaining[0]) {
|
|
453
|
+
activeTabs = { ...activeTabs, [win.groupId]: remaining[0] };
|
|
454
|
+
}
|
|
455
|
+
dissolveIfOrphaned(win.groupId);
|
|
456
|
+
}
|
|
390
457
|
queueEvent(() => emitter.emit("close", { window: win }));
|
|
391
458
|
if (focusedId === id) {
|
|
392
459
|
focusTop();
|
|
@@ -410,6 +477,7 @@ function createWindowManager(options = {}) {
|
|
|
410
477
|
commitQuiet();
|
|
411
478
|
return false;
|
|
412
479
|
}
|
|
480
|
+
if (!isVisibleTab(win)) activateTab(id);
|
|
413
481
|
if (win.stage === "minimized") {
|
|
414
482
|
restore(id);
|
|
415
483
|
return focusedId === id;
|
|
@@ -462,7 +530,9 @@ function createWindowManager(options = {}) {
|
|
|
462
530
|
const next = build(win);
|
|
463
531
|
if (!next) return false;
|
|
464
532
|
setWindow(next);
|
|
533
|
+
syncGroup(next);
|
|
465
534
|
queueEvent(() => emitter.emit("stage", { window: next, previous: win.stage }));
|
|
535
|
+
if (next.groupId !== null) reconcileFocus();
|
|
466
536
|
commit();
|
|
467
537
|
return true;
|
|
468
538
|
}
|
|
@@ -571,6 +641,7 @@ function createWindowManager(options = {}) {
|
|
|
571
641
|
if (boundsEqual(bounds, win.bounds)) return true;
|
|
572
642
|
const next = { ...win, bounds };
|
|
573
643
|
setWindow(next);
|
|
644
|
+
syncGroup(next);
|
|
574
645
|
queueEvent(() => emitter.emit("move", { window: next }));
|
|
575
646
|
commit();
|
|
576
647
|
return true;
|
|
@@ -592,6 +663,7 @@ function createWindowManager(options = {}) {
|
|
|
592
663
|
if (boundsEqual(bounds, win.bounds) && !becameNormal) return true;
|
|
593
664
|
const next = becameNormal ? { ...win, stage: "normal", snapZone: null, restoreBounds: null, bounds } : { ...win, bounds };
|
|
594
665
|
setWindow(next);
|
|
666
|
+
syncGroup(next);
|
|
595
667
|
if (becameNormal) queueEvent(() => emitter.emit("stage", { window: next, previous: "snapped" }));
|
|
596
668
|
queueEvent(() => emitter.emit("resize", { window: next }));
|
|
597
669
|
commit();
|
|
@@ -619,6 +691,7 @@ function createWindowManager(options = {}) {
|
|
|
619
691
|
const resized = size.width !== next.bounds.width || size.height !== next.bounds.height;
|
|
620
692
|
const finalWin = resized ? { ...next, bounds: { ...next.bounds, ...size } } : next;
|
|
621
693
|
setWindow(finalWin);
|
|
694
|
+
syncGroup(finalWin);
|
|
622
695
|
if (patch.layer && patch.layer !== win.layer) {
|
|
623
696
|
order = sortByLayer(order);
|
|
624
697
|
queueEvent(() => emitter.emit("order", { order }));
|
|
@@ -660,9 +733,12 @@ function createWindowManager(options = {}) {
|
|
|
660
733
|
if (target === win.workspace) return false;
|
|
661
734
|
const updated = { ...win, workspace: target };
|
|
662
735
|
setWindow(updated);
|
|
736
|
+
syncGroup(updated);
|
|
663
737
|
if (!onActiveWorkspace(updated) && focusedId === id) {
|
|
664
738
|
focusTop();
|
|
665
739
|
if (focusedId) emitFocus(windows[focusedId], id);
|
|
740
|
+
} else if (updated.groupId !== null && !onActiveWorkspace(updated)) {
|
|
741
|
+
reconcileFocus();
|
|
666
742
|
} else if (onActiveWorkspace(updated) && topModalId() === id && focusedId !== id) {
|
|
667
743
|
const previous = focusedId;
|
|
668
744
|
focusedId = id;
|
|
@@ -672,17 +748,104 @@ function createWindowManager(options = {}) {
|
|
|
672
748
|
commit();
|
|
673
749
|
return true;
|
|
674
750
|
}
|
|
751
|
+
function emitGroup(groupId, previous) {
|
|
752
|
+
const members = membersOf(groupId);
|
|
753
|
+
const activeId = activeTabs[groupId];
|
|
754
|
+
queueEvent(() => emitter.emit("group", { groupId, members, activeId, previous }));
|
|
755
|
+
}
|
|
756
|
+
function group(ids) {
|
|
757
|
+
const seeds = ids.filter((id, index) => windows[id] && ids.indexOf(id) === index);
|
|
758
|
+
const host = seeds[0] ? windows[seeds[0]] : null;
|
|
759
|
+
if (!host) return null;
|
|
760
|
+
const expanded = [];
|
|
761
|
+
for (const id of seeds) {
|
|
762
|
+
const win = windows[id];
|
|
763
|
+
const siblings = win.groupId === null ? [id] : membersOf(win.groupId);
|
|
764
|
+
for (const entry of siblings) if (!expanded.includes(entry)) expanded.push(entry);
|
|
765
|
+
}
|
|
766
|
+
if (expanded.length < 2) return null;
|
|
767
|
+
let groupId = `${idPrefix}-group-${++groupCounter}`;
|
|
768
|
+
while (activeTabs[groupId]) groupId = `${idPrefix}-group-${++groupCounter}`;
|
|
769
|
+
const shared = expanded.reduce(
|
|
770
|
+
(size, id) => {
|
|
771
|
+
const fit = normalizeSize(size, windows[id]);
|
|
772
|
+
return { width: Math.max(size.width, fit.width), height: Math.max(size.height, fit.height) };
|
|
773
|
+
},
|
|
774
|
+
{ width: host.bounds.width, height: host.bounds.height }
|
|
775
|
+
);
|
|
776
|
+
const bounds = { x: host.bounds.x, y: host.bounds.y, ...shared };
|
|
777
|
+
const retired = /* @__PURE__ */ new Set();
|
|
778
|
+
for (const id of expanded) {
|
|
779
|
+
const win = windows[id];
|
|
780
|
+
if (win.groupId !== null) retired.add(win.groupId);
|
|
781
|
+
setWindow({
|
|
782
|
+
...win,
|
|
783
|
+
groupId,
|
|
784
|
+
bounds,
|
|
785
|
+
stage: host.stage,
|
|
786
|
+
snapZone: host.snapZone,
|
|
787
|
+
restoreBounds: host.restoreBounds,
|
|
788
|
+
restoreStage: host.restoreStage,
|
|
789
|
+
layer: host.layer,
|
|
790
|
+
workspace: host.workspace
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
const next = { ...activeTabs, [groupId]: host.id };
|
|
794
|
+
for (const old of retired) delete next[old];
|
|
795
|
+
activeTabs = next;
|
|
796
|
+
raise(host.id);
|
|
797
|
+
emitGroup(groupId, null);
|
|
798
|
+
queueEvent(() => emitter.emit("order", { order }));
|
|
799
|
+
const hostVisible = onActiveWorkspace(host) && host.stage !== "minimized";
|
|
800
|
+
if (!hostVisible) reconcileFocus();
|
|
801
|
+
commit();
|
|
802
|
+
if (hostVisible) focus(host.id);
|
|
803
|
+
return groupId;
|
|
804
|
+
}
|
|
805
|
+
function ungroup(id) {
|
|
806
|
+
const win = windows[id];
|
|
807
|
+
if (!win?.groupId) return false;
|
|
808
|
+
const groupId = win.groupId;
|
|
809
|
+
const wasActive = activeTabs[groupId] === id;
|
|
810
|
+
setWindow({ ...win, groupId: null });
|
|
811
|
+
const remaining = membersOf(groupId);
|
|
812
|
+
if (wasActive) activeTabs = { ...activeTabs, [groupId]: remaining[0] };
|
|
813
|
+
dissolveIfOrphaned(groupId);
|
|
814
|
+
if (membersOf(groupId).length >= 2) emitGroup(groupId, wasActive ? id : null);
|
|
815
|
+
commit();
|
|
816
|
+
if (onActiveWorkspace(win) && win.stage !== "minimized") focus(id);
|
|
817
|
+
return true;
|
|
818
|
+
}
|
|
819
|
+
function activateTab(id) {
|
|
820
|
+
const win = windows[id];
|
|
821
|
+
if (!win?.groupId) return false;
|
|
822
|
+
const groupId = win.groupId;
|
|
823
|
+
const previous = activeTabs[groupId];
|
|
824
|
+
if (previous === id) return false;
|
|
825
|
+
activeTabs = { ...activeTabs, [groupId]: id };
|
|
826
|
+
if (focusedId === previous) {
|
|
827
|
+
focusedId = id;
|
|
828
|
+
emitFocus(win, previous);
|
|
829
|
+
}
|
|
830
|
+
emitGroup(groupId, previous);
|
|
831
|
+
commit();
|
|
832
|
+
return true;
|
|
833
|
+
}
|
|
834
|
+
function groupMembers(groupId) {
|
|
835
|
+
return membersOf(groupId).map((id) => windows[id]);
|
|
836
|
+
}
|
|
675
837
|
function sendToBack(id) {
|
|
676
838
|
const win = windows[id];
|
|
677
839
|
if (!win) return false;
|
|
678
|
-
const
|
|
840
|
+
const block = blockOf(id);
|
|
841
|
+
const without = order.filter((entry) => !block.includes(entry));
|
|
679
842
|
const rank = LAYER_RANK[win.layer];
|
|
680
843
|
let insertAt = 0;
|
|
681
844
|
for (const entry of without) {
|
|
682
845
|
if (layerRankOf(entry) < rank) insertAt += 1;
|
|
683
846
|
else break;
|
|
684
847
|
}
|
|
685
|
-
const next = [...without.slice(0, insertAt),
|
|
848
|
+
const next = [...without.slice(0, insertAt), ...block, ...without.slice(insertAt)];
|
|
686
849
|
if (next.every((entry, i) => entry === order[i])) return false;
|
|
687
850
|
order = next;
|
|
688
851
|
queueEvent(() => emitter.emit("order", { order }));
|
|
@@ -703,10 +866,10 @@ function createWindowManager(options = {}) {
|
|
|
703
866
|
);
|
|
704
867
|
}
|
|
705
868
|
function minimized() {
|
|
706
|
-
return Object.values(windows).filter((win) => win.stage === "minimized" && onActiveWorkspace(win)).sort((a, b) => a.openedSeq - b.openedSeq);
|
|
869
|
+
return Object.values(windows).filter((win) => win.stage === "minimized" && onActiveWorkspace(win) && isVisibleTab(win)).sort((a, b) => a.openedSeq - b.openedSeq);
|
|
707
870
|
}
|
|
708
871
|
function captureEntry() {
|
|
709
|
-
return { windows, order, focusedId, workspace };
|
|
872
|
+
return { windows, order, focusedId, workspace, activeTabs };
|
|
710
873
|
}
|
|
711
874
|
function recordHistory() {
|
|
712
875
|
if (!historyDirty) return;
|
|
@@ -746,19 +909,23 @@ function createWindowManager(options = {}) {
|
|
|
746
909
|
function reflowViewport() {
|
|
747
910
|
for (const id of order) {
|
|
748
911
|
const win = windows[id];
|
|
912
|
+
if (!isVisibleTab(win)) continue;
|
|
749
913
|
if (win.stage === "maximized") {
|
|
750
914
|
const updated = { ...win, bounds: fullBounds() };
|
|
751
915
|
setWindow(updated);
|
|
916
|
+
syncGroup(updated);
|
|
752
917
|
queueEvent(() => emitter.emit("resize", { window: updated }));
|
|
753
918
|
} else if (win.stage === "snapped" && win.snapZone) {
|
|
754
919
|
const updated = { ...win, bounds: snapBounds(win, win.snapZone) };
|
|
755
920
|
setWindow(updated);
|
|
921
|
+
syncGroup(updated);
|
|
756
922
|
queueEvent(() => emitter.emit("resize", { window: updated }));
|
|
757
923
|
} else if (win.stage === "normal" && keepInViewport) {
|
|
758
924
|
const bounds = clampToViewport(win.bounds, viewport, minVisible);
|
|
759
925
|
if (!boundsEqual(bounds, win.bounds)) {
|
|
760
926
|
const updated = { ...win, bounds };
|
|
761
927
|
setWindow(updated);
|
|
928
|
+
syncGroup(updated);
|
|
762
929
|
queueEvent(() => emitter.emit("move", { window: updated }));
|
|
763
930
|
}
|
|
764
931
|
}
|
|
@@ -768,6 +935,7 @@ function createWindowManager(options = {}) {
|
|
|
768
935
|
windows = entry.windows;
|
|
769
936
|
order = [...entry.order];
|
|
770
937
|
focusedId = entry.focusedId;
|
|
938
|
+
activeTabs = entry.activeTabs;
|
|
771
939
|
const previousWorkspace = workspace;
|
|
772
940
|
workspace = entry.workspace;
|
|
773
941
|
if (workspace !== previousWorkspace) {
|
|
@@ -844,7 +1012,7 @@ function createWindowManager(options = {}) {
|
|
|
844
1012
|
function arrange(mode) {
|
|
845
1013
|
const ids = order.filter((id) => {
|
|
846
1014
|
const win = windows[id];
|
|
847
|
-
return win.stage !== "minimized" && onActiveWorkspace(win);
|
|
1015
|
+
return win.stage !== "minimized" && onActiveWorkspace(win) && isVisibleTab(win);
|
|
848
1016
|
});
|
|
849
1017
|
if (ids.length === 0) return;
|
|
850
1018
|
if (mode === "cascade") {
|
|
@@ -876,7 +1044,8 @@ function createWindowManager(options = {}) {
|
|
|
876
1044
|
}
|
|
877
1045
|
function minimizeAll() {
|
|
878
1046
|
for (const id of [...order]) {
|
|
879
|
-
|
|
1047
|
+
const win = windows[id];
|
|
1048
|
+
if (onActiveWorkspace(win) && isVisibleTab(win)) minimize(id);
|
|
880
1049
|
}
|
|
881
1050
|
}
|
|
882
1051
|
function restoreAll() {
|
|
@@ -898,7 +1067,8 @@ function createWindowManager(options = {}) {
|
|
|
898
1067
|
})),
|
|
899
1068
|
order: [...order],
|
|
900
1069
|
focusedId,
|
|
901
|
-
workspace
|
|
1070
|
+
workspace,
|
|
1071
|
+
activeTabs: { ...activeTabs }
|
|
902
1072
|
};
|
|
903
1073
|
}
|
|
904
1074
|
function isBounds(value) {
|
|
@@ -953,6 +1123,7 @@ function createWindowManager(options = {}) {
|
|
|
953
1123
|
snapZone: ZONES.includes(raw.snapZone) ? raw.snapZone : null,
|
|
954
1124
|
layer: raw.layer,
|
|
955
1125
|
workspace: normalizeWorkspace(raw.workspace, 0),
|
|
1126
|
+
groupId: typeof raw.groupId === "string" && raw.groupId.length > 0 ? raw.groupId : null,
|
|
956
1127
|
minSize: isSize(raw.minSize) ? { ...raw.minSize } : { width: 160, height: 100 },
|
|
957
1128
|
maxSize: readMaxSize(raw.maxSize),
|
|
958
1129
|
aspectRatio: typeof raw.aspectRatio === "number" && Number.isFinite(raw.aspectRatio) && raw.aspectRatio > 0 ? raw.aspectRatio : null,
|
|
@@ -994,7 +1165,18 @@ function createWindowManager(options = {}) {
|
|
|
994
1165
|
if (focusedCandidate && (focusedCandidate.stage === "minimized" || !onActiveWorkspace(focusedCandidate))) {
|
|
995
1166
|
focusedId = null;
|
|
996
1167
|
}
|
|
997
|
-
|
|
1168
|
+
const restoredTabs = /* @__PURE__ */ Object.create(null);
|
|
1169
|
+
const rawTabs = data.activeTabs;
|
|
1170
|
+
for (const id of order) {
|
|
1171
|
+
const groupId = windows[id].groupId;
|
|
1172
|
+
if (groupId === null || restoredTabs[groupId]) continue;
|
|
1173
|
+
const wanted = typeof rawTabs === "object" && rawTabs !== null ? rawTabs[groupId] : void 0;
|
|
1174
|
+
const members = membersOf(groupId);
|
|
1175
|
+
restoredTabs[groupId] = typeof wanted === "string" && members.includes(wanted) ? wanted : members[0];
|
|
1176
|
+
}
|
|
1177
|
+
activeTabs = restoredTabs;
|
|
1178
|
+
for (const groupId of Object.keys(restoredTabs)) dissolveIfOrphaned(groupId);
|
|
1179
|
+
if (!focusedId || !isVisibleTab(windows[focusedId])) focusTop();
|
|
998
1180
|
const modal = topModalId();
|
|
999
1181
|
if (modal) {
|
|
1000
1182
|
const focusedWin = focusedId ? windows[focusedId] : null;
|
|
@@ -1048,6 +1230,10 @@ function createWindowManager(options = {}) {
|
|
|
1048
1230
|
workspace: () => workspace,
|
|
1049
1231
|
setWorkspace: (next) => transact(() => setWorkspace(next)),
|
|
1050
1232
|
moveToWorkspace: (id, next) => transact(() => moveToWorkspace(id, next)),
|
|
1233
|
+
group: (ids) => transact(() => group(ids)),
|
|
1234
|
+
ungroup: (id) => transact(() => ungroup(id)),
|
|
1235
|
+
activateTab: (id) => transact(() => activateTab(id)),
|
|
1236
|
+
groupMembers,
|
|
1051
1237
|
batch: (run) => transact(run),
|
|
1052
1238
|
serialize,
|
|
1053
1239
|
hydrate: (data) => transact(() => hydrate(data)),
|
|
@@ -1237,6 +1423,11 @@ function createDragStarter(ctx) {
|
|
|
1237
1423
|
restored: win.stage === "normal",
|
|
1238
1424
|
moved: false,
|
|
1239
1425
|
zone: null,
|
|
1426
|
+
groupTarget: null,
|
|
1427
|
+
hoverId: null,
|
|
1428
|
+
hoverTimer: 0,
|
|
1429
|
+
clientX: event.clientX,
|
|
1430
|
+
clientY: event.clientY,
|
|
1240
1431
|
raf: 0,
|
|
1241
1432
|
pendingX: 0,
|
|
1242
1433
|
pendingY: 0,
|
|
@@ -1245,6 +1436,20 @@ function createDragStarter(ctx) {
|
|
|
1245
1436
|
}
|
|
1246
1437
|
};
|
|
1247
1438
|
const el = ctx.windowElement(id);
|
|
1439
|
+
function armGroup(target2) {
|
|
1440
|
+
session.groupTarget = target2;
|
|
1441
|
+
session.zone = null;
|
|
1442
|
+
ctx.hidePreview();
|
|
1443
|
+
ctx.markGroupTarget(target2);
|
|
1444
|
+
}
|
|
1445
|
+
function clearHover() {
|
|
1446
|
+
if (session.hoverTimer !== 0) {
|
|
1447
|
+
view.clearTimeout(session.hoverTimer);
|
|
1448
|
+
session.hoverTimer = 0;
|
|
1449
|
+
}
|
|
1450
|
+
session.groupTarget = null;
|
|
1451
|
+
ctx.markGroupTarget(null);
|
|
1452
|
+
}
|
|
1248
1453
|
function flush() {
|
|
1249
1454
|
if (!session.hasPending || ctx.currentDrag() !== session) return;
|
|
1250
1455
|
session.hasPending = false;
|
|
@@ -1279,9 +1484,9 @@ function createDragStarter(ctx) {
|
|
|
1279
1484
|
for (const otherId of state.order) {
|
|
1280
1485
|
if (otherId === id) continue;
|
|
1281
1486
|
const other = state.windows[otherId];
|
|
1282
|
-
if (other
|
|
1283
|
-
|
|
1284
|
-
|
|
1487
|
+
if (!other || other.stage === "minimized" || other.workspace !== state.workspace) continue;
|
|
1488
|
+
if (other.groupId !== null && state.groups[other.groupId]?.activeId !== otherId) continue;
|
|
1489
|
+
targets.push(other.bounds);
|
|
1285
1490
|
}
|
|
1286
1491
|
const magnet = magnetize(
|
|
1287
1492
|
{ x: nextX, y: nextY, width: current.bounds.width, height: current.bounds.height },
|
|
@@ -1292,6 +1497,20 @@ function createDragStarter(ctx) {
|
|
|
1292
1497
|
nextY = magnet.y;
|
|
1293
1498
|
}
|
|
1294
1499
|
wm.move(id, nextX, nextY);
|
|
1500
|
+
const candidate = ctx.groupTarget(session.clientX, session.clientY, id);
|
|
1501
|
+
if (candidate !== session.hoverId) {
|
|
1502
|
+
session.hoverId = candidate;
|
|
1503
|
+
clearHover();
|
|
1504
|
+
if (candidate) {
|
|
1505
|
+
if (ctx.groupDwell <= 0) armGroup(candidate);
|
|
1506
|
+
else session.hoverTimer = view.setTimeout(() => armGroup(candidate), ctx.groupDwell);
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
if (session.groupTarget) {
|
|
1510
|
+
session.zone = null;
|
|
1511
|
+
ctx.hidePreview();
|
|
1512
|
+
return;
|
|
1513
|
+
}
|
|
1295
1514
|
if (ctx.snapEnabled && current.snappable) {
|
|
1296
1515
|
const viewport = wm.getState().viewport;
|
|
1297
1516
|
const rawZone = detectSnapZone(session.pendingX, session.pendingY, viewport, ctx.snapDetect);
|
|
@@ -1324,6 +1543,8 @@ function createDragStarter(ctx) {
|
|
|
1324
1543
|
}
|
|
1325
1544
|
session.pendingX = movePoint.x;
|
|
1326
1545
|
session.pendingY = movePoint.y;
|
|
1546
|
+
session.clientX = moveEvent.clientX;
|
|
1547
|
+
session.clientY = moveEvent.clientY;
|
|
1327
1548
|
session.hasPending = true;
|
|
1328
1549
|
if (session.raf === 0) session.raf = view.requestAnimationFrame(flush);
|
|
1329
1550
|
}
|
|
@@ -1358,6 +1579,8 @@ function createDragStarter(ctx) {
|
|
|
1358
1579
|
wm.move(id, session.startBounds.x, session.startBounds.y);
|
|
1359
1580
|
}
|
|
1360
1581
|
}
|
|
1582
|
+
} else if (session.moved && session.groupTarget) {
|
|
1583
|
+
if (wm.group([session.groupTarget, id])) wm.activateTab(id);
|
|
1361
1584
|
} else if (session.moved && session.zone) {
|
|
1362
1585
|
if (session.zone === "maximize") wm.maximize(id);
|
|
1363
1586
|
else wm.snap(id, session.zone);
|
|
@@ -1377,6 +1600,8 @@ function createDragStarter(ctx) {
|
|
|
1377
1600
|
el.style.willChange = "";
|
|
1378
1601
|
}
|
|
1379
1602
|
ctx.hidePreview();
|
|
1603
|
+
if (session.hoverTimer !== 0) view.clearTimeout(session.hoverTimer);
|
|
1604
|
+
ctx.markGroupTarget(null);
|
|
1380
1605
|
if (cancelled) wm.abortInteraction();
|
|
1381
1606
|
else wm.endInteraction();
|
|
1382
1607
|
}
|
|
@@ -1546,6 +1771,8 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1546
1771
|
const doc = element.ownerDocument;
|
|
1547
1772
|
const view = windowOf(element);
|
|
1548
1773
|
const coarsePointer = typeof view.matchMedia === "function" && view.matchMedia("(pointer: coarse)").matches;
|
|
1774
|
+
const groupingEnabled = options.grouping !== false;
|
|
1775
|
+
const groupDwell = (typeof options.grouping === "object" ? options.grouping.dwell : void 0) ?? 420;
|
|
1549
1776
|
const snapEnabled = options.snap !== false;
|
|
1550
1777
|
const snapOptions = typeof options.snap === "object" ? options.snap : {};
|
|
1551
1778
|
const snapPreviewEnabled = snapOptions.preview !== false;
|
|
@@ -1569,6 +1796,8 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1569
1796
|
let lastOrder = null;
|
|
1570
1797
|
let lastFocused = null;
|
|
1571
1798
|
let drag = null;
|
|
1799
|
+
let groupTargetId = null;
|
|
1800
|
+
let groupTargetEl = null;
|
|
1572
1801
|
let cachedRect = null;
|
|
1573
1802
|
let rectUsers = 0;
|
|
1574
1803
|
let announcer = null;
|
|
@@ -1640,6 +1869,24 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1640
1869
|
hitEdge,
|
|
1641
1870
|
hitCorner,
|
|
1642
1871
|
magnetThreshold,
|
|
1872
|
+
groupDwell,
|
|
1873
|
+
groupTarget(clientX, clientY, selfId) {
|
|
1874
|
+
if (!groupingEnabled || typeof doc.elementsFromPoint !== "function") return null;
|
|
1875
|
+
for (const node of doc.elementsFromPoint(clientX, clientY)) {
|
|
1876
|
+
const handle = node.closest?.("[data-wm-drag]");
|
|
1877
|
+
const host = handle?.closest("[data-wm-window]");
|
|
1878
|
+
const id = host?.dataset.wmWindow;
|
|
1879
|
+
if (id && id !== selfId && registry.get(id)?.element === host) return id;
|
|
1880
|
+
}
|
|
1881
|
+
return null;
|
|
1882
|
+
},
|
|
1883
|
+
markGroupTarget(id) {
|
|
1884
|
+
if (groupTargetId === id) return;
|
|
1885
|
+
if (groupTargetEl) delete groupTargetEl.dataset.wmTabTarget;
|
|
1886
|
+
groupTargetId = id;
|
|
1887
|
+
groupTargetEl = id ? registry.get(id)?.element ?? null : null;
|
|
1888
|
+
if (groupTargetEl) groupTargetEl.dataset.wmTabTarget = "";
|
|
1889
|
+
},
|
|
1643
1890
|
currentDrag: () => drag,
|
|
1644
1891
|
claimDrag(session) {
|
|
1645
1892
|
drag = session;
|
|
@@ -1657,18 +1904,25 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1657
1904
|
observer.observe(element);
|
|
1658
1905
|
cleanup.push(() => observer.disconnect());
|
|
1659
1906
|
}
|
|
1660
|
-
function syncWindow(attached, win, zIndex, activeWorkspace) {
|
|
1907
|
+
function syncWindow(attached, win, zIndex, activeWorkspace, activeTab) {
|
|
1661
1908
|
const el = attached.element;
|
|
1662
1909
|
const firstSync = attached.lastState === null;
|
|
1663
1910
|
if (firstSync) el.style.transition = "none";
|
|
1664
|
-
if (attached.lastState !== win || attached.lastWorkspace !== activeWorkspace) {
|
|
1911
|
+
if (attached.lastState !== win || attached.lastWorkspace !== activeWorkspace || attached.lastTab !== activeTab) {
|
|
1665
1912
|
el.style.transform = `translate3d(${win.bounds.x}px, ${win.bounds.y}px, 0)`;
|
|
1666
1913
|
el.style.width = `${win.bounds.width}px`;
|
|
1667
1914
|
el.style.height = `${win.bounds.height}px`;
|
|
1668
1915
|
el.dataset.wmStage = win.stage;
|
|
1669
1916
|
el.dataset.wmLayer = win.layer;
|
|
1670
1917
|
el.dataset.wmWorkspace = String(win.workspace);
|
|
1671
|
-
|
|
1918
|
+
if (win.groupId === null) {
|
|
1919
|
+
delete el.dataset.wmGroup;
|
|
1920
|
+
delete el.dataset.wmTab;
|
|
1921
|
+
} else {
|
|
1922
|
+
el.dataset.wmGroup = win.groupId;
|
|
1923
|
+
el.dataset.wmTab = activeTab ? "active" : "inactive";
|
|
1924
|
+
}
|
|
1925
|
+
const hide = win.stage === "minimized" || win.workspace !== activeWorkspace || !activeTab;
|
|
1672
1926
|
if (hide && !el.hidden && el.contains(doc.activeElement)) {
|
|
1673
1927
|
element.focus({ preventScroll: true });
|
|
1674
1928
|
}
|
|
@@ -1686,6 +1940,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1686
1940
|
}
|
|
1687
1941
|
attached.lastState = win;
|
|
1688
1942
|
attached.lastWorkspace = activeWorkspace;
|
|
1943
|
+
attached.lastTab = activeTab;
|
|
1689
1944
|
}
|
|
1690
1945
|
if (attached.lastZ !== zIndex) {
|
|
1691
1946
|
el.style.zIndex = String(zIndex + 1);
|
|
@@ -1703,8 +1958,9 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1703
1958
|
const attached = registry.get(id);
|
|
1704
1959
|
const win = state.windows[id];
|
|
1705
1960
|
if (!attached || !win) return;
|
|
1706
|
-
|
|
1707
|
-
|
|
1961
|
+
const activeTab = win.groupId === null || state.groups[win.groupId]?.activeId === win.id;
|
|
1962
|
+
if (orderChanged || attached.lastState !== win || attached.lastWorkspace !== state.workspace || attached.lastTab !== activeTab) {
|
|
1963
|
+
syncWindow(attached, win, index, state.workspace, activeTab);
|
|
1708
1964
|
}
|
|
1709
1965
|
});
|
|
1710
1966
|
if (state.focusedId !== lastFocused) {
|
|
@@ -1807,6 +2063,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1807
2063
|
lastState: null,
|
|
1808
2064
|
lastZ: -1,
|
|
1809
2065
|
lastWorkspace: -1,
|
|
2066
|
+
lastTab: true,
|
|
1810
2067
|
cleanup: []
|
|
1811
2068
|
};
|
|
1812
2069
|
windowElement.dataset.wmWindow = id;
|
|
@@ -2046,5 +2303,5 @@ exports.flipToTarget = flipToTarget;
|
|
|
2046
2303
|
exports.magnetize = magnetize;
|
|
2047
2304
|
exports.prefersReducedMotion = prefersReducedMotion;
|
|
2048
2305
|
exports.zoneBounds = zoneBounds;
|
|
2049
|
-
//# sourceMappingURL=chunk-
|
|
2050
|
-
//# sourceMappingURL=chunk-
|
|
2306
|
+
//# sourceMappingURL=chunk-C2UHNBSA.cjs.map
|
|
2307
|
+
//# sourceMappingURL=chunk-C2UHNBSA.cjs.map
|