@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
|
@@ -197,6 +197,8 @@ function createWindowManager(options = {}) {
|
|
|
197
197
|
let focusedId = null;
|
|
198
198
|
let viewport = options.viewport ?? { width: 0, height: 0 };
|
|
199
199
|
let workspace = normalizeWorkspace(options.workspace, 0);
|
|
200
|
+
let activeTabs = {};
|
|
201
|
+
let groupCounter = 0;
|
|
200
202
|
let seq = 0;
|
|
201
203
|
let idCounter = 0;
|
|
202
204
|
let cascadeIndex = 0;
|
|
@@ -215,7 +217,7 @@ function createWindowManager(options = {}) {
|
|
|
215
217
|
const layouts = /* @__PURE__ */ new Map();
|
|
216
218
|
function getState() {
|
|
217
219
|
if (!snapshot) {
|
|
218
|
-
snapshot = { windows, order, focusedId, viewport, workspace };
|
|
220
|
+
snapshot = { windows, order, focusedId, viewport, workspace, groups: buildGroups() };
|
|
219
221
|
}
|
|
220
222
|
return snapshot;
|
|
221
223
|
}
|
|
@@ -250,16 +252,22 @@ function createWindowManager(options = {}) {
|
|
|
250
252
|
function sortByLayer(ids) {
|
|
251
253
|
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);
|
|
252
254
|
}
|
|
255
|
+
function blockOf(id) {
|
|
256
|
+
const win = windows[id];
|
|
257
|
+
if (win.groupId === null) return [id];
|
|
258
|
+
return [...membersOf(win.groupId).filter((entry) => entry !== id), id];
|
|
259
|
+
}
|
|
253
260
|
function raise(id) {
|
|
254
261
|
const win = windows[id];
|
|
255
|
-
const
|
|
262
|
+
const block = blockOf(id);
|
|
263
|
+
const without = order.filter((entry) => !block.includes(entry));
|
|
256
264
|
const rank = LAYER_RANK[win.layer];
|
|
257
265
|
let insertAt = without.length;
|
|
258
266
|
for (let i = without.length - 1; i >= 0; i -= 1) {
|
|
259
267
|
if (layerRankOf(without[i]) > rank) insertAt = i;
|
|
260
268
|
else break;
|
|
261
269
|
}
|
|
262
|
-
const next = [...without.slice(0, insertAt),
|
|
270
|
+
const next = [...without.slice(0, insertAt), ...block, ...without.slice(insertAt)];
|
|
263
271
|
const changed = next.length !== order.length || next.some((entry, i) => entry !== order[i]);
|
|
264
272
|
order = next;
|
|
265
273
|
return changed;
|
|
@@ -267,11 +275,54 @@ function createWindowManager(options = {}) {
|
|
|
267
275
|
function onActiveWorkspace(win) {
|
|
268
276
|
return win.workspace === workspace;
|
|
269
277
|
}
|
|
278
|
+
function membersOf(groupId) {
|
|
279
|
+
return order.filter((entry) => windows[entry].groupId === groupId);
|
|
280
|
+
}
|
|
281
|
+
function isVisibleTab(win) {
|
|
282
|
+
return win.groupId === null || activeTabs[win.groupId] === win.id;
|
|
283
|
+
}
|
|
284
|
+
function buildGroups() {
|
|
285
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
286
|
+
for (const [groupId, activeId] of Object.entries(activeTabs)) {
|
|
287
|
+
result[groupId] = { id: groupId, activeId, members: membersOf(groupId) };
|
|
288
|
+
}
|
|
289
|
+
return result;
|
|
290
|
+
}
|
|
291
|
+
function syncGroup(source) {
|
|
292
|
+
if (source.groupId === null) return;
|
|
293
|
+
for (const id of membersOf(source.groupId)) {
|
|
294
|
+
if (id === source.id) continue;
|
|
295
|
+
const member = windows[id];
|
|
296
|
+
if (boundsEqual(member.bounds, source.bounds) && member.stage === source.stage && member.snapZone === source.snapZone && member.layer === source.layer && member.workspace === source.workspace) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
setWindow({
|
|
300
|
+
...member,
|
|
301
|
+
bounds: source.bounds,
|
|
302
|
+
stage: source.stage,
|
|
303
|
+
snapZone: source.snapZone,
|
|
304
|
+
restoreBounds: source.restoreBounds,
|
|
305
|
+
restoreStage: source.restoreStage,
|
|
306
|
+
layer: source.layer,
|
|
307
|
+
workspace: source.workspace
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function dissolveIfOrphaned(groupId) {
|
|
312
|
+
const members = membersOf(groupId);
|
|
313
|
+
if (members.length >= 2) return;
|
|
314
|
+
for (const id of members) {
|
|
315
|
+
setWindow({ ...windows[id], groupId: null });
|
|
316
|
+
}
|
|
317
|
+
const { [groupId]: _dropped, ...rest } = activeTabs;
|
|
318
|
+
activeTabs = rest;
|
|
319
|
+
}
|
|
270
320
|
function topModalId() {
|
|
271
321
|
for (let i = order.length - 1; i >= 0; i -= 1) {
|
|
272
322
|
const win = windows[order[i]];
|
|
273
|
-
if (win.layer === "modal" && win.stage !== "minimized" && onActiveWorkspace(win))
|
|
323
|
+
if (win.layer === "modal" && win.stage !== "minimized" && onActiveWorkspace(win) && isVisibleTab(win)) {
|
|
274
324
|
return win.id;
|
|
325
|
+
}
|
|
275
326
|
}
|
|
276
327
|
return null;
|
|
277
328
|
}
|
|
@@ -279,7 +330,7 @@ function createWindowManager(options = {}) {
|
|
|
279
330
|
const modal = topModalId();
|
|
280
331
|
return order.filter((id) => {
|
|
281
332
|
const win = windows[id];
|
|
282
|
-
if (win.stage === "minimized" || !onActiveWorkspace(win)) return false;
|
|
333
|
+
if (win.stage === "minimized" || !onActiveWorkspace(win) || !isVisibleTab(win)) return false;
|
|
283
334
|
if (modal && win.layer !== "modal") return false;
|
|
284
335
|
return true;
|
|
285
336
|
});
|
|
@@ -288,6 +339,14 @@ function createWindowManager(options = {}) {
|
|
|
288
339
|
const targets = focusTargets();
|
|
289
340
|
focusedId = targets.length > 0 ? targets[targets.length - 1] : null;
|
|
290
341
|
}
|
|
342
|
+
function reconcileFocus() {
|
|
343
|
+
if (focusedId === null) return;
|
|
344
|
+
const win = windows[focusedId];
|
|
345
|
+
if (win && win.stage !== "minimized" && onActiveWorkspace(win) && isVisibleTab(win)) return;
|
|
346
|
+
const previous = focusedId;
|
|
347
|
+
focusTop();
|
|
348
|
+
if (focusedId) emitFocus(windows[focusedId], previous);
|
|
349
|
+
}
|
|
291
350
|
function emitFocus(win, previous) {
|
|
292
351
|
queueEvent(() => emitter.emit("focus", { window: win, previous }));
|
|
293
352
|
}
|
|
@@ -342,6 +401,7 @@ function createWindowManager(options = {}) {
|
|
|
342
401
|
snapZone: null,
|
|
343
402
|
layer: init.layer ?? "normal",
|
|
344
403
|
workspace: normalizeWorkspace(init.workspace, workspace),
|
|
404
|
+
groupId: null,
|
|
345
405
|
minSize,
|
|
346
406
|
maxSize,
|
|
347
407
|
aspectRatio,
|
|
@@ -385,6 +445,13 @@ function createWindowManager(options = {}) {
|
|
|
385
445
|
const win = windows[id];
|
|
386
446
|
if (!win) return false;
|
|
387
447
|
removeWindow(id);
|
|
448
|
+
if (win.groupId !== null) {
|
|
449
|
+
const remaining = membersOf(win.groupId);
|
|
450
|
+
if (activeTabs[win.groupId] === id && remaining[0]) {
|
|
451
|
+
activeTabs = { ...activeTabs, [win.groupId]: remaining[0] };
|
|
452
|
+
}
|
|
453
|
+
dissolveIfOrphaned(win.groupId);
|
|
454
|
+
}
|
|
388
455
|
queueEvent(() => emitter.emit("close", { window: win }));
|
|
389
456
|
if (focusedId === id) {
|
|
390
457
|
focusTop();
|
|
@@ -408,6 +475,7 @@ function createWindowManager(options = {}) {
|
|
|
408
475
|
commitQuiet();
|
|
409
476
|
return false;
|
|
410
477
|
}
|
|
478
|
+
if (!isVisibleTab(win)) activateTab(id);
|
|
411
479
|
if (win.stage === "minimized") {
|
|
412
480
|
restore(id);
|
|
413
481
|
return focusedId === id;
|
|
@@ -460,7 +528,9 @@ function createWindowManager(options = {}) {
|
|
|
460
528
|
const next = build(win);
|
|
461
529
|
if (!next) return false;
|
|
462
530
|
setWindow(next);
|
|
531
|
+
syncGroup(next);
|
|
463
532
|
queueEvent(() => emitter.emit("stage", { window: next, previous: win.stage }));
|
|
533
|
+
if (next.groupId !== null) reconcileFocus();
|
|
464
534
|
commit();
|
|
465
535
|
return true;
|
|
466
536
|
}
|
|
@@ -569,6 +639,7 @@ function createWindowManager(options = {}) {
|
|
|
569
639
|
if (boundsEqual(bounds, win.bounds)) return true;
|
|
570
640
|
const next = { ...win, bounds };
|
|
571
641
|
setWindow(next);
|
|
642
|
+
syncGroup(next);
|
|
572
643
|
queueEvent(() => emitter.emit("move", { window: next }));
|
|
573
644
|
commit();
|
|
574
645
|
return true;
|
|
@@ -590,6 +661,7 @@ function createWindowManager(options = {}) {
|
|
|
590
661
|
if (boundsEqual(bounds, win.bounds) && !becameNormal) return true;
|
|
591
662
|
const next = becameNormal ? { ...win, stage: "normal", snapZone: null, restoreBounds: null, bounds } : { ...win, bounds };
|
|
592
663
|
setWindow(next);
|
|
664
|
+
syncGroup(next);
|
|
593
665
|
if (becameNormal) queueEvent(() => emitter.emit("stage", { window: next, previous: "snapped" }));
|
|
594
666
|
queueEvent(() => emitter.emit("resize", { window: next }));
|
|
595
667
|
commit();
|
|
@@ -617,6 +689,7 @@ function createWindowManager(options = {}) {
|
|
|
617
689
|
const resized = size.width !== next.bounds.width || size.height !== next.bounds.height;
|
|
618
690
|
const finalWin = resized ? { ...next, bounds: { ...next.bounds, ...size } } : next;
|
|
619
691
|
setWindow(finalWin);
|
|
692
|
+
syncGroup(finalWin);
|
|
620
693
|
if (patch.layer && patch.layer !== win.layer) {
|
|
621
694
|
order = sortByLayer(order);
|
|
622
695
|
queueEvent(() => emitter.emit("order", { order }));
|
|
@@ -658,9 +731,12 @@ function createWindowManager(options = {}) {
|
|
|
658
731
|
if (target === win.workspace) return false;
|
|
659
732
|
const updated = { ...win, workspace: target };
|
|
660
733
|
setWindow(updated);
|
|
734
|
+
syncGroup(updated);
|
|
661
735
|
if (!onActiveWorkspace(updated) && focusedId === id) {
|
|
662
736
|
focusTop();
|
|
663
737
|
if (focusedId) emitFocus(windows[focusedId], id);
|
|
738
|
+
} else if (updated.groupId !== null && !onActiveWorkspace(updated)) {
|
|
739
|
+
reconcileFocus();
|
|
664
740
|
} else if (onActiveWorkspace(updated) && topModalId() === id && focusedId !== id) {
|
|
665
741
|
const previous = focusedId;
|
|
666
742
|
focusedId = id;
|
|
@@ -670,17 +746,104 @@ function createWindowManager(options = {}) {
|
|
|
670
746
|
commit();
|
|
671
747
|
return true;
|
|
672
748
|
}
|
|
749
|
+
function emitGroup(groupId, previous) {
|
|
750
|
+
const members = membersOf(groupId);
|
|
751
|
+
const activeId = activeTabs[groupId];
|
|
752
|
+
queueEvent(() => emitter.emit("group", { groupId, members, activeId, previous }));
|
|
753
|
+
}
|
|
754
|
+
function group(ids) {
|
|
755
|
+
const seeds = ids.filter((id, index) => windows[id] && ids.indexOf(id) === index);
|
|
756
|
+
const host = seeds[0] ? windows[seeds[0]] : null;
|
|
757
|
+
if (!host) return null;
|
|
758
|
+
const expanded = [];
|
|
759
|
+
for (const id of seeds) {
|
|
760
|
+
const win = windows[id];
|
|
761
|
+
const siblings = win.groupId === null ? [id] : membersOf(win.groupId);
|
|
762
|
+
for (const entry of siblings) if (!expanded.includes(entry)) expanded.push(entry);
|
|
763
|
+
}
|
|
764
|
+
if (expanded.length < 2) return null;
|
|
765
|
+
let groupId = `${idPrefix}-group-${++groupCounter}`;
|
|
766
|
+
while (activeTabs[groupId]) groupId = `${idPrefix}-group-${++groupCounter}`;
|
|
767
|
+
const shared = expanded.reduce(
|
|
768
|
+
(size, id) => {
|
|
769
|
+
const fit = normalizeSize(size, windows[id]);
|
|
770
|
+
return { width: Math.max(size.width, fit.width), height: Math.max(size.height, fit.height) };
|
|
771
|
+
},
|
|
772
|
+
{ width: host.bounds.width, height: host.bounds.height }
|
|
773
|
+
);
|
|
774
|
+
const bounds = { x: host.bounds.x, y: host.bounds.y, ...shared };
|
|
775
|
+
const retired = /* @__PURE__ */ new Set();
|
|
776
|
+
for (const id of expanded) {
|
|
777
|
+
const win = windows[id];
|
|
778
|
+
if (win.groupId !== null) retired.add(win.groupId);
|
|
779
|
+
setWindow({
|
|
780
|
+
...win,
|
|
781
|
+
groupId,
|
|
782
|
+
bounds,
|
|
783
|
+
stage: host.stage,
|
|
784
|
+
snapZone: host.snapZone,
|
|
785
|
+
restoreBounds: host.restoreBounds,
|
|
786
|
+
restoreStage: host.restoreStage,
|
|
787
|
+
layer: host.layer,
|
|
788
|
+
workspace: host.workspace
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
const next = { ...activeTabs, [groupId]: host.id };
|
|
792
|
+
for (const old of retired) delete next[old];
|
|
793
|
+
activeTabs = next;
|
|
794
|
+
raise(host.id);
|
|
795
|
+
emitGroup(groupId, null);
|
|
796
|
+
queueEvent(() => emitter.emit("order", { order }));
|
|
797
|
+
const hostVisible = onActiveWorkspace(host) && host.stage !== "minimized";
|
|
798
|
+
if (!hostVisible) reconcileFocus();
|
|
799
|
+
commit();
|
|
800
|
+
if (hostVisible) focus(host.id);
|
|
801
|
+
return groupId;
|
|
802
|
+
}
|
|
803
|
+
function ungroup(id) {
|
|
804
|
+
const win = windows[id];
|
|
805
|
+
if (!win?.groupId) return false;
|
|
806
|
+
const groupId = win.groupId;
|
|
807
|
+
const wasActive = activeTabs[groupId] === id;
|
|
808
|
+
setWindow({ ...win, groupId: null });
|
|
809
|
+
const remaining = membersOf(groupId);
|
|
810
|
+
if (wasActive) activeTabs = { ...activeTabs, [groupId]: remaining[0] };
|
|
811
|
+
dissolveIfOrphaned(groupId);
|
|
812
|
+
if (membersOf(groupId).length >= 2) emitGroup(groupId, wasActive ? id : null);
|
|
813
|
+
commit();
|
|
814
|
+
if (onActiveWorkspace(win) && win.stage !== "minimized") focus(id);
|
|
815
|
+
return true;
|
|
816
|
+
}
|
|
817
|
+
function activateTab(id) {
|
|
818
|
+
const win = windows[id];
|
|
819
|
+
if (!win?.groupId) return false;
|
|
820
|
+
const groupId = win.groupId;
|
|
821
|
+
const previous = activeTabs[groupId];
|
|
822
|
+
if (previous === id) return false;
|
|
823
|
+
activeTabs = { ...activeTabs, [groupId]: id };
|
|
824
|
+
if (focusedId === previous) {
|
|
825
|
+
focusedId = id;
|
|
826
|
+
emitFocus(win, previous);
|
|
827
|
+
}
|
|
828
|
+
emitGroup(groupId, previous);
|
|
829
|
+
commit();
|
|
830
|
+
return true;
|
|
831
|
+
}
|
|
832
|
+
function groupMembers(groupId) {
|
|
833
|
+
return membersOf(groupId).map((id) => windows[id]);
|
|
834
|
+
}
|
|
673
835
|
function sendToBack(id) {
|
|
674
836
|
const win = windows[id];
|
|
675
837
|
if (!win) return false;
|
|
676
|
-
const
|
|
838
|
+
const block = blockOf(id);
|
|
839
|
+
const without = order.filter((entry) => !block.includes(entry));
|
|
677
840
|
const rank = LAYER_RANK[win.layer];
|
|
678
841
|
let insertAt = 0;
|
|
679
842
|
for (const entry of without) {
|
|
680
843
|
if (layerRankOf(entry) < rank) insertAt += 1;
|
|
681
844
|
else break;
|
|
682
845
|
}
|
|
683
|
-
const next = [...without.slice(0, insertAt),
|
|
846
|
+
const next = [...without.slice(0, insertAt), ...block, ...without.slice(insertAt)];
|
|
684
847
|
if (next.every((entry, i) => entry === order[i])) return false;
|
|
685
848
|
order = next;
|
|
686
849
|
queueEvent(() => emitter.emit("order", { order }));
|
|
@@ -701,10 +864,10 @@ function createWindowManager(options = {}) {
|
|
|
701
864
|
);
|
|
702
865
|
}
|
|
703
866
|
function minimized() {
|
|
704
|
-
return Object.values(windows).filter((win) => win.stage === "minimized" && onActiveWorkspace(win)).sort((a, b) => a.openedSeq - b.openedSeq);
|
|
867
|
+
return Object.values(windows).filter((win) => win.stage === "minimized" && onActiveWorkspace(win) && isVisibleTab(win)).sort((a, b) => a.openedSeq - b.openedSeq);
|
|
705
868
|
}
|
|
706
869
|
function captureEntry() {
|
|
707
|
-
return { windows, order, focusedId, workspace };
|
|
870
|
+
return { windows, order, focusedId, workspace, activeTabs };
|
|
708
871
|
}
|
|
709
872
|
function recordHistory() {
|
|
710
873
|
if (!historyDirty) return;
|
|
@@ -744,19 +907,23 @@ function createWindowManager(options = {}) {
|
|
|
744
907
|
function reflowViewport() {
|
|
745
908
|
for (const id of order) {
|
|
746
909
|
const win = windows[id];
|
|
910
|
+
if (!isVisibleTab(win)) continue;
|
|
747
911
|
if (win.stage === "maximized") {
|
|
748
912
|
const updated = { ...win, bounds: fullBounds() };
|
|
749
913
|
setWindow(updated);
|
|
914
|
+
syncGroup(updated);
|
|
750
915
|
queueEvent(() => emitter.emit("resize", { window: updated }));
|
|
751
916
|
} else if (win.stage === "snapped" && win.snapZone) {
|
|
752
917
|
const updated = { ...win, bounds: snapBounds(win, win.snapZone) };
|
|
753
918
|
setWindow(updated);
|
|
919
|
+
syncGroup(updated);
|
|
754
920
|
queueEvent(() => emitter.emit("resize", { window: updated }));
|
|
755
921
|
} else if (win.stage === "normal" && keepInViewport) {
|
|
756
922
|
const bounds = clampToViewport(win.bounds, viewport, minVisible);
|
|
757
923
|
if (!boundsEqual(bounds, win.bounds)) {
|
|
758
924
|
const updated = { ...win, bounds };
|
|
759
925
|
setWindow(updated);
|
|
926
|
+
syncGroup(updated);
|
|
760
927
|
queueEvent(() => emitter.emit("move", { window: updated }));
|
|
761
928
|
}
|
|
762
929
|
}
|
|
@@ -766,6 +933,7 @@ function createWindowManager(options = {}) {
|
|
|
766
933
|
windows = entry.windows;
|
|
767
934
|
order = [...entry.order];
|
|
768
935
|
focusedId = entry.focusedId;
|
|
936
|
+
activeTabs = entry.activeTabs;
|
|
769
937
|
const previousWorkspace = workspace;
|
|
770
938
|
workspace = entry.workspace;
|
|
771
939
|
if (workspace !== previousWorkspace) {
|
|
@@ -842,7 +1010,7 @@ function createWindowManager(options = {}) {
|
|
|
842
1010
|
function arrange(mode) {
|
|
843
1011
|
const ids = order.filter((id) => {
|
|
844
1012
|
const win = windows[id];
|
|
845
|
-
return win.stage !== "minimized" && onActiveWorkspace(win);
|
|
1013
|
+
return win.stage !== "minimized" && onActiveWorkspace(win) && isVisibleTab(win);
|
|
846
1014
|
});
|
|
847
1015
|
if (ids.length === 0) return;
|
|
848
1016
|
if (mode === "cascade") {
|
|
@@ -874,7 +1042,8 @@ function createWindowManager(options = {}) {
|
|
|
874
1042
|
}
|
|
875
1043
|
function minimizeAll() {
|
|
876
1044
|
for (const id of [...order]) {
|
|
877
|
-
|
|
1045
|
+
const win = windows[id];
|
|
1046
|
+
if (onActiveWorkspace(win) && isVisibleTab(win)) minimize(id);
|
|
878
1047
|
}
|
|
879
1048
|
}
|
|
880
1049
|
function restoreAll() {
|
|
@@ -896,7 +1065,8 @@ function createWindowManager(options = {}) {
|
|
|
896
1065
|
})),
|
|
897
1066
|
order: [...order],
|
|
898
1067
|
focusedId,
|
|
899
|
-
workspace
|
|
1068
|
+
workspace,
|
|
1069
|
+
activeTabs: { ...activeTabs }
|
|
900
1070
|
};
|
|
901
1071
|
}
|
|
902
1072
|
function isBounds(value) {
|
|
@@ -951,6 +1121,7 @@ function createWindowManager(options = {}) {
|
|
|
951
1121
|
snapZone: ZONES.includes(raw.snapZone) ? raw.snapZone : null,
|
|
952
1122
|
layer: raw.layer,
|
|
953
1123
|
workspace: normalizeWorkspace(raw.workspace, 0),
|
|
1124
|
+
groupId: typeof raw.groupId === "string" && raw.groupId.length > 0 ? raw.groupId : null,
|
|
954
1125
|
minSize: isSize(raw.minSize) ? { ...raw.minSize } : { width: 160, height: 100 },
|
|
955
1126
|
maxSize: readMaxSize(raw.maxSize),
|
|
956
1127
|
aspectRatio: typeof raw.aspectRatio === "number" && Number.isFinite(raw.aspectRatio) && raw.aspectRatio > 0 ? raw.aspectRatio : null,
|
|
@@ -992,7 +1163,18 @@ function createWindowManager(options = {}) {
|
|
|
992
1163
|
if (focusedCandidate && (focusedCandidate.stage === "minimized" || !onActiveWorkspace(focusedCandidate))) {
|
|
993
1164
|
focusedId = null;
|
|
994
1165
|
}
|
|
995
|
-
|
|
1166
|
+
const restoredTabs = /* @__PURE__ */ Object.create(null);
|
|
1167
|
+
const rawTabs = data.activeTabs;
|
|
1168
|
+
for (const id of order) {
|
|
1169
|
+
const groupId = windows[id].groupId;
|
|
1170
|
+
if (groupId === null || restoredTabs[groupId]) continue;
|
|
1171
|
+
const wanted = typeof rawTabs === "object" && rawTabs !== null ? rawTabs[groupId] : void 0;
|
|
1172
|
+
const members = membersOf(groupId);
|
|
1173
|
+
restoredTabs[groupId] = typeof wanted === "string" && members.includes(wanted) ? wanted : members[0];
|
|
1174
|
+
}
|
|
1175
|
+
activeTabs = restoredTabs;
|
|
1176
|
+
for (const groupId of Object.keys(restoredTabs)) dissolveIfOrphaned(groupId);
|
|
1177
|
+
if (!focusedId || !isVisibleTab(windows[focusedId])) focusTop();
|
|
996
1178
|
const modal = topModalId();
|
|
997
1179
|
if (modal) {
|
|
998
1180
|
const focusedWin = focusedId ? windows[focusedId] : null;
|
|
@@ -1046,6 +1228,10 @@ function createWindowManager(options = {}) {
|
|
|
1046
1228
|
workspace: () => workspace,
|
|
1047
1229
|
setWorkspace: (next) => transact(() => setWorkspace(next)),
|
|
1048
1230
|
moveToWorkspace: (id, next) => transact(() => moveToWorkspace(id, next)),
|
|
1231
|
+
group: (ids) => transact(() => group(ids)),
|
|
1232
|
+
ungroup: (id) => transact(() => ungroup(id)),
|
|
1233
|
+
activateTab: (id) => transact(() => activateTab(id)),
|
|
1234
|
+
groupMembers,
|
|
1049
1235
|
batch: (run) => transact(run),
|
|
1050
1236
|
serialize,
|
|
1051
1237
|
hydrate: (data) => transact(() => hydrate(data)),
|
|
@@ -1235,6 +1421,11 @@ function createDragStarter(ctx) {
|
|
|
1235
1421
|
restored: win.stage === "normal",
|
|
1236
1422
|
moved: false,
|
|
1237
1423
|
zone: null,
|
|
1424
|
+
groupTarget: null,
|
|
1425
|
+
hoverId: null,
|
|
1426
|
+
hoverTimer: 0,
|
|
1427
|
+
clientX: event.clientX,
|
|
1428
|
+
clientY: event.clientY,
|
|
1238
1429
|
raf: 0,
|
|
1239
1430
|
pendingX: 0,
|
|
1240
1431
|
pendingY: 0,
|
|
@@ -1243,6 +1434,20 @@ function createDragStarter(ctx) {
|
|
|
1243
1434
|
}
|
|
1244
1435
|
};
|
|
1245
1436
|
const el = ctx.windowElement(id);
|
|
1437
|
+
function armGroup(target2) {
|
|
1438
|
+
session.groupTarget = target2;
|
|
1439
|
+
session.zone = null;
|
|
1440
|
+
ctx.hidePreview();
|
|
1441
|
+
ctx.markGroupTarget(target2);
|
|
1442
|
+
}
|
|
1443
|
+
function clearHover() {
|
|
1444
|
+
if (session.hoverTimer !== 0) {
|
|
1445
|
+
view.clearTimeout(session.hoverTimer);
|
|
1446
|
+
session.hoverTimer = 0;
|
|
1447
|
+
}
|
|
1448
|
+
session.groupTarget = null;
|
|
1449
|
+
ctx.markGroupTarget(null);
|
|
1450
|
+
}
|
|
1246
1451
|
function flush() {
|
|
1247
1452
|
if (!session.hasPending || ctx.currentDrag() !== session) return;
|
|
1248
1453
|
session.hasPending = false;
|
|
@@ -1277,9 +1482,9 @@ function createDragStarter(ctx) {
|
|
|
1277
1482
|
for (const otherId of state.order) {
|
|
1278
1483
|
if (otherId === id) continue;
|
|
1279
1484
|
const other = state.windows[otherId];
|
|
1280
|
-
if (other
|
|
1281
|
-
|
|
1282
|
-
|
|
1485
|
+
if (!other || other.stage === "minimized" || other.workspace !== state.workspace) continue;
|
|
1486
|
+
if (other.groupId !== null && state.groups[other.groupId]?.activeId !== otherId) continue;
|
|
1487
|
+
targets.push(other.bounds);
|
|
1283
1488
|
}
|
|
1284
1489
|
const magnet = magnetize(
|
|
1285
1490
|
{ x: nextX, y: nextY, width: current.bounds.width, height: current.bounds.height },
|
|
@@ -1290,6 +1495,20 @@ function createDragStarter(ctx) {
|
|
|
1290
1495
|
nextY = magnet.y;
|
|
1291
1496
|
}
|
|
1292
1497
|
wm.move(id, nextX, nextY);
|
|
1498
|
+
const candidate = ctx.groupTarget(session.clientX, session.clientY, id);
|
|
1499
|
+
if (candidate !== session.hoverId) {
|
|
1500
|
+
session.hoverId = candidate;
|
|
1501
|
+
clearHover();
|
|
1502
|
+
if (candidate) {
|
|
1503
|
+
if (ctx.groupDwell <= 0) armGroup(candidate);
|
|
1504
|
+
else session.hoverTimer = view.setTimeout(() => armGroup(candidate), ctx.groupDwell);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
if (session.groupTarget) {
|
|
1508
|
+
session.zone = null;
|
|
1509
|
+
ctx.hidePreview();
|
|
1510
|
+
return;
|
|
1511
|
+
}
|
|
1293
1512
|
if (ctx.snapEnabled && current.snappable) {
|
|
1294
1513
|
const viewport = wm.getState().viewport;
|
|
1295
1514
|
const rawZone = detectSnapZone(session.pendingX, session.pendingY, viewport, ctx.snapDetect);
|
|
@@ -1322,6 +1541,8 @@ function createDragStarter(ctx) {
|
|
|
1322
1541
|
}
|
|
1323
1542
|
session.pendingX = movePoint.x;
|
|
1324
1543
|
session.pendingY = movePoint.y;
|
|
1544
|
+
session.clientX = moveEvent.clientX;
|
|
1545
|
+
session.clientY = moveEvent.clientY;
|
|
1325
1546
|
session.hasPending = true;
|
|
1326
1547
|
if (session.raf === 0) session.raf = view.requestAnimationFrame(flush);
|
|
1327
1548
|
}
|
|
@@ -1356,6 +1577,8 @@ function createDragStarter(ctx) {
|
|
|
1356
1577
|
wm.move(id, session.startBounds.x, session.startBounds.y);
|
|
1357
1578
|
}
|
|
1358
1579
|
}
|
|
1580
|
+
} else if (session.moved && session.groupTarget) {
|
|
1581
|
+
if (wm.group([session.groupTarget, id])) wm.activateTab(id);
|
|
1359
1582
|
} else if (session.moved && session.zone) {
|
|
1360
1583
|
if (session.zone === "maximize") wm.maximize(id);
|
|
1361
1584
|
else wm.snap(id, session.zone);
|
|
@@ -1375,6 +1598,8 @@ function createDragStarter(ctx) {
|
|
|
1375
1598
|
el.style.willChange = "";
|
|
1376
1599
|
}
|
|
1377
1600
|
ctx.hidePreview();
|
|
1601
|
+
if (session.hoverTimer !== 0) view.clearTimeout(session.hoverTimer);
|
|
1602
|
+
ctx.markGroupTarget(null);
|
|
1378
1603
|
if (cancelled) wm.abortInteraction();
|
|
1379
1604
|
else wm.endInteraction();
|
|
1380
1605
|
}
|
|
@@ -1544,6 +1769,8 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1544
1769
|
const doc = element.ownerDocument;
|
|
1545
1770
|
const view = windowOf(element);
|
|
1546
1771
|
const coarsePointer = typeof view.matchMedia === "function" && view.matchMedia("(pointer: coarse)").matches;
|
|
1772
|
+
const groupingEnabled = options.grouping !== false;
|
|
1773
|
+
const groupDwell = (typeof options.grouping === "object" ? options.grouping.dwell : void 0) ?? 420;
|
|
1547
1774
|
const snapEnabled = options.snap !== false;
|
|
1548
1775
|
const snapOptions = typeof options.snap === "object" ? options.snap : {};
|
|
1549
1776
|
const snapPreviewEnabled = snapOptions.preview !== false;
|
|
@@ -1567,6 +1794,8 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1567
1794
|
let lastOrder = null;
|
|
1568
1795
|
let lastFocused = null;
|
|
1569
1796
|
let drag = null;
|
|
1797
|
+
let groupTargetId = null;
|
|
1798
|
+
let groupTargetEl = null;
|
|
1570
1799
|
let cachedRect = null;
|
|
1571
1800
|
let rectUsers = 0;
|
|
1572
1801
|
let announcer = null;
|
|
@@ -1638,6 +1867,24 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1638
1867
|
hitEdge,
|
|
1639
1868
|
hitCorner,
|
|
1640
1869
|
magnetThreshold,
|
|
1870
|
+
groupDwell,
|
|
1871
|
+
groupTarget(clientX, clientY, selfId) {
|
|
1872
|
+
if (!groupingEnabled || typeof doc.elementsFromPoint !== "function") return null;
|
|
1873
|
+
for (const node of doc.elementsFromPoint(clientX, clientY)) {
|
|
1874
|
+
const handle = node.closest?.("[data-wm-drag]");
|
|
1875
|
+
const host = handle?.closest("[data-wm-window]");
|
|
1876
|
+
const id = host?.dataset.wmWindow;
|
|
1877
|
+
if (id && id !== selfId && registry.get(id)?.element === host) return id;
|
|
1878
|
+
}
|
|
1879
|
+
return null;
|
|
1880
|
+
},
|
|
1881
|
+
markGroupTarget(id) {
|
|
1882
|
+
if (groupTargetId === id) return;
|
|
1883
|
+
if (groupTargetEl) delete groupTargetEl.dataset.wmTabTarget;
|
|
1884
|
+
groupTargetId = id;
|
|
1885
|
+
groupTargetEl = id ? registry.get(id)?.element ?? null : null;
|
|
1886
|
+
if (groupTargetEl) groupTargetEl.dataset.wmTabTarget = "";
|
|
1887
|
+
},
|
|
1641
1888
|
currentDrag: () => drag,
|
|
1642
1889
|
claimDrag(session) {
|
|
1643
1890
|
drag = session;
|
|
@@ -1655,18 +1902,25 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1655
1902
|
observer.observe(element);
|
|
1656
1903
|
cleanup.push(() => observer.disconnect());
|
|
1657
1904
|
}
|
|
1658
|
-
function syncWindow(attached, win, zIndex, activeWorkspace) {
|
|
1905
|
+
function syncWindow(attached, win, zIndex, activeWorkspace, activeTab) {
|
|
1659
1906
|
const el = attached.element;
|
|
1660
1907
|
const firstSync = attached.lastState === null;
|
|
1661
1908
|
if (firstSync) el.style.transition = "none";
|
|
1662
|
-
if (attached.lastState !== win || attached.lastWorkspace !== activeWorkspace) {
|
|
1909
|
+
if (attached.lastState !== win || attached.lastWorkspace !== activeWorkspace || attached.lastTab !== activeTab) {
|
|
1663
1910
|
el.style.transform = `translate3d(${win.bounds.x}px, ${win.bounds.y}px, 0)`;
|
|
1664
1911
|
el.style.width = `${win.bounds.width}px`;
|
|
1665
1912
|
el.style.height = `${win.bounds.height}px`;
|
|
1666
1913
|
el.dataset.wmStage = win.stage;
|
|
1667
1914
|
el.dataset.wmLayer = win.layer;
|
|
1668
1915
|
el.dataset.wmWorkspace = String(win.workspace);
|
|
1669
|
-
|
|
1916
|
+
if (win.groupId === null) {
|
|
1917
|
+
delete el.dataset.wmGroup;
|
|
1918
|
+
delete el.dataset.wmTab;
|
|
1919
|
+
} else {
|
|
1920
|
+
el.dataset.wmGroup = win.groupId;
|
|
1921
|
+
el.dataset.wmTab = activeTab ? "active" : "inactive";
|
|
1922
|
+
}
|
|
1923
|
+
const hide = win.stage === "minimized" || win.workspace !== activeWorkspace || !activeTab;
|
|
1670
1924
|
if (hide && !el.hidden && el.contains(doc.activeElement)) {
|
|
1671
1925
|
element.focus({ preventScroll: true });
|
|
1672
1926
|
}
|
|
@@ -1684,6 +1938,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1684
1938
|
}
|
|
1685
1939
|
attached.lastState = win;
|
|
1686
1940
|
attached.lastWorkspace = activeWorkspace;
|
|
1941
|
+
attached.lastTab = activeTab;
|
|
1687
1942
|
}
|
|
1688
1943
|
if (attached.lastZ !== zIndex) {
|
|
1689
1944
|
el.style.zIndex = String(zIndex + 1);
|
|
@@ -1701,8 +1956,9 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1701
1956
|
const attached = registry.get(id);
|
|
1702
1957
|
const win = state.windows[id];
|
|
1703
1958
|
if (!attached || !win) return;
|
|
1704
|
-
|
|
1705
|
-
|
|
1959
|
+
const activeTab = win.groupId === null || state.groups[win.groupId]?.activeId === win.id;
|
|
1960
|
+
if (orderChanged || attached.lastState !== win || attached.lastWorkspace !== state.workspace || attached.lastTab !== activeTab) {
|
|
1961
|
+
syncWindow(attached, win, index, state.workspace, activeTab);
|
|
1706
1962
|
}
|
|
1707
1963
|
});
|
|
1708
1964
|
if (state.focusedId !== lastFocused) {
|
|
@@ -1805,6 +2061,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1805
2061
|
lastState: null,
|
|
1806
2062
|
lastZ: -1,
|
|
1807
2063
|
lastWorkspace: -1,
|
|
2064
|
+
lastTab: true,
|
|
1808
2065
|
cleanup: []
|
|
1809
2066
|
};
|
|
1810
2067
|
windowElement.dataset.wmWindow = id;
|
|
@@ -2028,5 +2285,5 @@ function createDesktopBinder(wm, options = {}) {
|
|
|
2028
2285
|
}
|
|
2029
2286
|
|
|
2030
2287
|
export { applyAspect, attachDesktop, boundsEqual, clamp, clampSize, clampToViewport, createAnnouncer, createDesktopBinder, createEmitter, createWindowManager, defaultMessages, detectSnapZone, flipFromTarget, flipToTarget, magnetize, prefersReducedMotion, zoneBounds };
|
|
2031
|
-
//# sourceMappingURL=chunk-
|
|
2032
|
-
//# sourceMappingURL=chunk-
|
|
2288
|
+
//# sourceMappingURL=chunk-2WQHHYYR.js.map
|
|
2289
|
+
//# sourceMappingURL=chunk-2WQHHYYR.js.map
|