@surdeddd/wmkit 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/README.ru.md +2 -1
- 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-OOEDFA7K.js → chunk-L43XBN44.js} +290 -28
- package/dist/chunk-L43XBN44.js.map +1 -0
- package/dist/{chunk-TJ6QOOJ2.cjs → chunk-RXAMUBUJ.cjs} +290 -28
- package/dist/chunk-RXAMUBUJ.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-OOEDFA7K.js.map +0 -1
- package/dist/chunk-TJ6QOOJ2.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;
|
|
@@ -209,12 +211,13 @@ function createWindowManager(options = {}) {
|
|
|
209
211
|
let future = [];
|
|
210
212
|
let interactionDepth = 0;
|
|
211
213
|
let interactionRecorded = false;
|
|
214
|
+
let interactionMark = null;
|
|
212
215
|
let skipNextHistory = false;
|
|
213
216
|
let pendingHistory = null;
|
|
214
217
|
const layouts = /* @__PURE__ */ new Map();
|
|
215
218
|
function getState() {
|
|
216
219
|
if (!snapshot) {
|
|
217
|
-
snapshot = { windows, order, focusedId, viewport, workspace };
|
|
220
|
+
snapshot = { windows, order, focusedId, viewport, workspace, groups: buildGroups() };
|
|
218
221
|
}
|
|
219
222
|
return snapshot;
|
|
220
223
|
}
|
|
@@ -266,11 +269,54 @@ function createWindowManager(options = {}) {
|
|
|
266
269
|
function onActiveWorkspace(win) {
|
|
267
270
|
return win.workspace === workspace;
|
|
268
271
|
}
|
|
272
|
+
function membersOf(groupId) {
|
|
273
|
+
return order.filter((entry) => windows[entry].groupId === groupId);
|
|
274
|
+
}
|
|
275
|
+
function isVisibleTab(win) {
|
|
276
|
+
return win.groupId === null || activeTabs[win.groupId] === win.id;
|
|
277
|
+
}
|
|
278
|
+
function buildGroups() {
|
|
279
|
+
const result = {};
|
|
280
|
+
for (const [groupId, activeId] of Object.entries(activeTabs)) {
|
|
281
|
+
result[groupId] = { id: groupId, activeId, members: membersOf(groupId) };
|
|
282
|
+
}
|
|
283
|
+
return result;
|
|
284
|
+
}
|
|
285
|
+
function syncGroup(source) {
|
|
286
|
+
if (source.groupId === null) return;
|
|
287
|
+
for (const id of membersOf(source.groupId)) {
|
|
288
|
+
if (id === source.id) continue;
|
|
289
|
+
const member = windows[id];
|
|
290
|
+
if (boundsEqual(member.bounds, source.bounds) && member.stage === source.stage && member.snapZone === source.snapZone && member.layer === source.layer && member.workspace === source.workspace) {
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
setWindow({
|
|
294
|
+
...member,
|
|
295
|
+
bounds: source.bounds,
|
|
296
|
+
stage: source.stage,
|
|
297
|
+
snapZone: source.snapZone,
|
|
298
|
+
restoreBounds: source.restoreBounds,
|
|
299
|
+
restoreStage: source.restoreStage,
|
|
300
|
+
layer: source.layer,
|
|
301
|
+
workspace: source.workspace
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function dissolveIfOrphaned(groupId) {
|
|
306
|
+
const members = membersOf(groupId);
|
|
307
|
+
if (members.length >= 2) return;
|
|
308
|
+
for (const id of members) {
|
|
309
|
+
setWindow({ ...windows[id], groupId: null });
|
|
310
|
+
}
|
|
311
|
+
const { [groupId]: _dropped, ...rest } = activeTabs;
|
|
312
|
+
activeTabs = rest;
|
|
313
|
+
}
|
|
269
314
|
function topModalId() {
|
|
270
315
|
for (let i = order.length - 1; i >= 0; i -= 1) {
|
|
271
316
|
const win = windows[order[i]];
|
|
272
|
-
if (win.layer === "modal" && win.stage !== "minimized" && onActiveWorkspace(win))
|
|
317
|
+
if (win.layer === "modal" && win.stage !== "minimized" && onActiveWorkspace(win) && isVisibleTab(win)) {
|
|
273
318
|
return win.id;
|
|
319
|
+
}
|
|
274
320
|
}
|
|
275
321
|
return null;
|
|
276
322
|
}
|
|
@@ -278,7 +324,7 @@ function createWindowManager(options = {}) {
|
|
|
278
324
|
const modal = topModalId();
|
|
279
325
|
return order.filter((id) => {
|
|
280
326
|
const win = windows[id];
|
|
281
|
-
if (win.stage === "minimized" || !onActiveWorkspace(win)) return false;
|
|
327
|
+
if (win.stage === "minimized" || !onActiveWorkspace(win) || !isVisibleTab(win)) return false;
|
|
282
328
|
if (modal && win.layer !== "modal") return false;
|
|
283
329
|
return true;
|
|
284
330
|
});
|
|
@@ -319,7 +365,13 @@ function createWindowManager(options = {}) {
|
|
|
319
365
|
width: init.width ?? defaultSize.width,
|
|
320
366
|
height: init.height ?? defaultSize.height
|
|
321
367
|
};
|
|
322
|
-
const size = aspectRatio === null ? clampSize(requested, minSize, maxSize) : applyAspect(
|
|
368
|
+
const size = aspectRatio === null ? clampSize(requested, minSize, maxSize) : applyAspect(
|
|
369
|
+
requested,
|
|
370
|
+
aspectRatio,
|
|
371
|
+
minSize,
|
|
372
|
+
maxSize,
|
|
373
|
+
init.width === void 0 && init.height !== void 0 ? "height" : "width"
|
|
374
|
+
);
|
|
323
375
|
const position = positionForOpen(init);
|
|
324
376
|
let bounds = { ...position, ...size };
|
|
325
377
|
if (keepInViewport) bounds = clampToViewport(bounds, viewport, minVisible);
|
|
@@ -335,6 +387,7 @@ function createWindowManager(options = {}) {
|
|
|
335
387
|
snapZone: null,
|
|
336
388
|
layer: init.layer ?? "normal",
|
|
337
389
|
workspace: normalizeWorkspace(init.workspace, workspace),
|
|
390
|
+
groupId: null,
|
|
338
391
|
minSize,
|
|
339
392
|
maxSize,
|
|
340
393
|
aspectRatio,
|
|
@@ -378,6 +431,13 @@ function createWindowManager(options = {}) {
|
|
|
378
431
|
const win = windows[id];
|
|
379
432
|
if (!win) return false;
|
|
380
433
|
removeWindow(id);
|
|
434
|
+
if (win.groupId !== null) {
|
|
435
|
+
const remaining = membersOf(win.groupId);
|
|
436
|
+
if (activeTabs[win.groupId] === id && remaining[0]) {
|
|
437
|
+
activeTabs = { ...activeTabs, [win.groupId]: remaining[0] };
|
|
438
|
+
}
|
|
439
|
+
dissolveIfOrphaned(win.groupId);
|
|
440
|
+
}
|
|
381
441
|
queueEvent(() => emitter.emit("close", { window: win }));
|
|
382
442
|
if (focusedId === id) {
|
|
383
443
|
focusTop();
|
|
@@ -394,6 +454,7 @@ function createWindowManager(options = {}) {
|
|
|
394
454
|
const win = windows[id];
|
|
395
455
|
if (!win) return false;
|
|
396
456
|
if (!onActiveWorkspace(win)) setWorkspace(win.workspace);
|
|
457
|
+
if (!isVisibleTab(win)) activateTab(id);
|
|
397
458
|
const modal = topModalId();
|
|
398
459
|
if (modal && modal !== id && win.layer !== "modal") {
|
|
399
460
|
const modalWin = windows[modal];
|
|
@@ -435,7 +496,13 @@ function createWindowManager(options = {}) {
|
|
|
435
496
|
}
|
|
436
497
|
function snapBounds(win, zone) {
|
|
437
498
|
const rect = zoneBounds(zone, viewport);
|
|
438
|
-
|
|
499
|
+
const byWidth = normalizeSize(rect, win);
|
|
500
|
+
const size = byWidth.height > rect.height ? normalizeSize(rect, win, "height") : byWidth;
|
|
501
|
+
return {
|
|
502
|
+
x: Math.max(0, Math.min(rect.x, viewport.width - size.width)),
|
|
503
|
+
y: Math.max(0, Math.min(rect.y, viewport.height - size.height)),
|
|
504
|
+
...size
|
|
505
|
+
};
|
|
439
506
|
}
|
|
440
507
|
function focusUnlessBlocked(id) {
|
|
441
508
|
const modal = topModalId();
|
|
@@ -447,6 +514,7 @@ function createWindowManager(options = {}) {
|
|
|
447
514
|
const next = build(win);
|
|
448
515
|
if (!next) return false;
|
|
449
516
|
setWindow(next);
|
|
517
|
+
syncGroup(next);
|
|
450
518
|
queueEvent(() => emitter.emit("stage", { window: next, previous: win.stage }));
|
|
451
519
|
commit();
|
|
452
520
|
return true;
|
|
@@ -556,6 +624,7 @@ function createWindowManager(options = {}) {
|
|
|
556
624
|
if (boundsEqual(bounds, win.bounds)) return true;
|
|
557
625
|
const next = { ...win, bounds };
|
|
558
626
|
setWindow(next);
|
|
627
|
+
syncGroup(next);
|
|
559
628
|
queueEvent(() => emitter.emit("move", { window: next }));
|
|
560
629
|
commit();
|
|
561
630
|
return true;
|
|
@@ -577,6 +646,7 @@ function createWindowManager(options = {}) {
|
|
|
577
646
|
if (boundsEqual(bounds, win.bounds) && !becameNormal) return true;
|
|
578
647
|
const next = becameNormal ? { ...win, stage: "normal", snapZone: null, restoreBounds: null, bounds } : { ...win, bounds };
|
|
579
648
|
setWindow(next);
|
|
649
|
+
syncGroup(next);
|
|
580
650
|
if (becameNormal) queueEvent(() => emitter.emit("stage", { window: next, previous: "snapped" }));
|
|
581
651
|
queueEvent(() => emitter.emit("resize", { window: next }));
|
|
582
652
|
commit();
|
|
@@ -600,10 +670,11 @@ function createWindowManager(options = {}) {
|
|
|
600
670
|
snappable: patch.snappable ?? win.snappable,
|
|
601
671
|
meta: patch.meta ? { ...win.meta, ...patch.meta } : win.meta
|
|
602
672
|
};
|
|
603
|
-
const size = normalizeSize(next.bounds, next);
|
|
673
|
+
const size = next.stage === "maximized" ? next.bounds : normalizeSize(next.bounds, next);
|
|
604
674
|
const resized = size.width !== next.bounds.width || size.height !== next.bounds.height;
|
|
605
675
|
const finalWin = resized ? { ...next, bounds: { ...next.bounds, ...size } } : next;
|
|
606
676
|
setWindow(finalWin);
|
|
677
|
+
syncGroup(finalWin);
|
|
607
678
|
if (patch.layer && patch.layer !== win.layer) {
|
|
608
679
|
order = sortByLayer(order);
|
|
609
680
|
queueEvent(() => emitter.emit("order", { order }));
|
|
@@ -645,14 +716,90 @@ function createWindowManager(options = {}) {
|
|
|
645
716
|
if (target === win.workspace) return false;
|
|
646
717
|
const updated = { ...win, workspace: target };
|
|
647
718
|
setWindow(updated);
|
|
719
|
+
syncGroup(updated);
|
|
648
720
|
if (!onActiveWorkspace(updated) && focusedId === id) {
|
|
649
721
|
focusTop();
|
|
650
722
|
if (focusedId) emitFocus(windows[focusedId], id);
|
|
723
|
+
} else if (onActiveWorkspace(updated) && topModalId() === id && focusedId !== id) {
|
|
724
|
+
const previous = focusedId;
|
|
725
|
+
focusedId = id;
|
|
726
|
+
emitFocus(updated, previous);
|
|
651
727
|
}
|
|
652
728
|
queueEvent(() => emitter.emit("update", { window: updated }));
|
|
653
729
|
commit();
|
|
654
730
|
return true;
|
|
655
731
|
}
|
|
732
|
+
function emitGroup(groupId, previous) {
|
|
733
|
+
const members = membersOf(groupId);
|
|
734
|
+
const activeId = activeTabs[groupId];
|
|
735
|
+
queueEvent(() => emitter.emit("group", { groupId, members, activeId, previous }));
|
|
736
|
+
}
|
|
737
|
+
function group(ids) {
|
|
738
|
+
const seeds = ids.filter((id, index) => windows[id] && ids.indexOf(id) === index);
|
|
739
|
+
const host = seeds[0] ? windows[seeds[0]] : null;
|
|
740
|
+
if (!host) return null;
|
|
741
|
+
const expanded = [];
|
|
742
|
+
for (const id of seeds) {
|
|
743
|
+
const win = windows[id];
|
|
744
|
+
const siblings = win.groupId === null ? [id] : membersOf(win.groupId);
|
|
745
|
+
for (const entry of siblings) if (!expanded.includes(entry)) expanded.push(entry);
|
|
746
|
+
}
|
|
747
|
+
if (expanded.length < 2) return null;
|
|
748
|
+
const groupId = `${idPrefix}-group-${++groupCounter}`;
|
|
749
|
+
const retired = /* @__PURE__ */ new Set();
|
|
750
|
+
for (const id of expanded) {
|
|
751
|
+
const win = windows[id];
|
|
752
|
+
if (win.groupId !== null) retired.add(win.groupId);
|
|
753
|
+
setWindow({
|
|
754
|
+
...win,
|
|
755
|
+
groupId,
|
|
756
|
+
bounds: host.bounds,
|
|
757
|
+
stage: host.stage,
|
|
758
|
+
snapZone: host.snapZone,
|
|
759
|
+
restoreBounds: host.restoreBounds,
|
|
760
|
+
restoreStage: host.restoreStage,
|
|
761
|
+
layer: host.layer,
|
|
762
|
+
workspace: host.workspace
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
const next = { ...activeTabs, [groupId]: host.id };
|
|
766
|
+
for (const old of retired) delete next[old];
|
|
767
|
+
activeTabs = next;
|
|
768
|
+
raise(host.id);
|
|
769
|
+
emitGroup(groupId, null);
|
|
770
|
+
queueEvent(() => emitter.emit("order", { order }));
|
|
771
|
+
commit();
|
|
772
|
+
if (onActiveWorkspace(host) && host.stage !== "minimized") focus(host.id);
|
|
773
|
+
return groupId;
|
|
774
|
+
}
|
|
775
|
+
function ungroup(id) {
|
|
776
|
+
const win = windows[id];
|
|
777
|
+
if (!win?.groupId) return false;
|
|
778
|
+
const groupId = win.groupId;
|
|
779
|
+
const wasActive = activeTabs[groupId] === id;
|
|
780
|
+
setWindow({ ...win, groupId: null });
|
|
781
|
+
const remaining = membersOf(groupId);
|
|
782
|
+
if (wasActive) activeTabs = { ...activeTabs, [groupId]: remaining[0] };
|
|
783
|
+
dissolveIfOrphaned(groupId);
|
|
784
|
+
if (membersOf(groupId).length >= 2) emitGroup(groupId, wasActive ? id : null);
|
|
785
|
+
commit();
|
|
786
|
+
focus(id);
|
|
787
|
+
return true;
|
|
788
|
+
}
|
|
789
|
+
function activateTab(id) {
|
|
790
|
+
const win = windows[id];
|
|
791
|
+
if (!win?.groupId) return false;
|
|
792
|
+
const groupId = win.groupId;
|
|
793
|
+
const previous = activeTabs[groupId];
|
|
794
|
+
if (previous === id) return false;
|
|
795
|
+
activeTabs = { ...activeTabs, [groupId]: id };
|
|
796
|
+
emitGroup(groupId, previous);
|
|
797
|
+
commit();
|
|
798
|
+
return true;
|
|
799
|
+
}
|
|
800
|
+
function groupMembers(groupId) {
|
|
801
|
+
return membersOf(groupId).map((id) => windows[id]);
|
|
802
|
+
}
|
|
656
803
|
function sendToBack(id) {
|
|
657
804
|
const win = windows[id];
|
|
658
805
|
if (!win) return false;
|
|
@@ -684,10 +831,10 @@ function createWindowManager(options = {}) {
|
|
|
684
831
|
);
|
|
685
832
|
}
|
|
686
833
|
function minimized() {
|
|
687
|
-
return Object.values(windows).filter((win) => win.stage === "minimized" && onActiveWorkspace(win)).sort((a, b) => a.openedSeq - b.openedSeq);
|
|
834
|
+
return Object.values(windows).filter((win) => win.stage === "minimized" && onActiveWorkspace(win) && isVisibleTab(win)).sort((a, b) => a.openedSeq - b.openedSeq);
|
|
688
835
|
}
|
|
689
836
|
function captureEntry() {
|
|
690
|
-
return { windows, order, focusedId, workspace };
|
|
837
|
+
return { windows, order, focusedId, workspace, activeTabs };
|
|
691
838
|
}
|
|
692
839
|
function recordHistory() {
|
|
693
840
|
if (!historyDirty) return;
|
|
@@ -749,6 +896,7 @@ function createWindowManager(options = {}) {
|
|
|
749
896
|
windows = entry.windows;
|
|
750
897
|
order = [...entry.order];
|
|
751
898
|
focusedId = entry.focusedId;
|
|
899
|
+
activeTabs = entry.activeTabs;
|
|
752
900
|
const previousWorkspace = workspace;
|
|
753
901
|
workspace = entry.workspace;
|
|
754
902
|
if (workspace !== previousWorkspace) {
|
|
@@ -775,14 +923,20 @@ function createWindowManager(options = {}) {
|
|
|
775
923
|
}
|
|
776
924
|
function beginInteraction() {
|
|
777
925
|
interactionDepth += 1;
|
|
778
|
-
if (interactionDepth === 1)
|
|
926
|
+
if (interactionDepth === 1) {
|
|
927
|
+
interactionRecorded = false;
|
|
928
|
+
interactionMark = { past: [...past], future };
|
|
929
|
+
}
|
|
779
930
|
}
|
|
780
931
|
function endInteraction() {
|
|
781
932
|
if (interactionDepth > 0) interactionDepth -= 1;
|
|
933
|
+
if (interactionDepth === 0) interactionMark = null;
|
|
782
934
|
}
|
|
783
935
|
function abortInteraction() {
|
|
784
|
-
if (interactionDepth > 0 &&
|
|
785
|
-
past.
|
|
936
|
+
if (interactionDepth > 0 && interactionMark) {
|
|
937
|
+
past.length = 0;
|
|
938
|
+
past.push(...interactionMark.past);
|
|
939
|
+
future = interactionMark.future;
|
|
786
940
|
interactionRecorded = false;
|
|
787
941
|
}
|
|
788
942
|
endInteraction();
|
|
@@ -873,7 +1027,8 @@ function createWindowManager(options = {}) {
|
|
|
873
1027
|
})),
|
|
874
1028
|
order: [...order],
|
|
875
1029
|
focusedId,
|
|
876
|
-
workspace
|
|
1030
|
+
workspace,
|
|
1031
|
+
activeTabs: { ...activeTabs }
|
|
877
1032
|
};
|
|
878
1033
|
}
|
|
879
1034
|
function isBounds(value) {
|
|
@@ -928,6 +1083,7 @@ function createWindowManager(options = {}) {
|
|
|
928
1083
|
snapZone: ZONES.includes(raw.snapZone) ? raw.snapZone : null,
|
|
929
1084
|
layer: raw.layer,
|
|
930
1085
|
workspace: normalizeWorkspace(raw.workspace, 0),
|
|
1086
|
+
groupId: typeof raw.groupId === "string" && raw.groupId.length > 0 ? raw.groupId : null,
|
|
931
1087
|
minSize: isSize(raw.minSize) ? { ...raw.minSize } : { width: 160, height: 100 },
|
|
932
1088
|
maxSize: readMaxSize(raw.maxSize),
|
|
933
1089
|
aspectRatio: typeof raw.aspectRatio === "number" && Number.isFinite(raw.aspectRatio) && raw.aspectRatio > 0 ? raw.aspectRatio : null,
|
|
@@ -969,7 +1125,18 @@ function createWindowManager(options = {}) {
|
|
|
969
1125
|
if (focusedCandidate && (focusedCandidate.stage === "minimized" || !onActiveWorkspace(focusedCandidate))) {
|
|
970
1126
|
focusedId = null;
|
|
971
1127
|
}
|
|
972
|
-
|
|
1128
|
+
const restoredTabs = {};
|
|
1129
|
+
const rawTabs = data.activeTabs;
|
|
1130
|
+
for (const id of order) {
|
|
1131
|
+
const groupId = windows[id].groupId;
|
|
1132
|
+
if (groupId === null || restoredTabs[groupId]) continue;
|
|
1133
|
+
const wanted = typeof rawTabs === "object" && rawTabs !== null ? rawTabs[groupId] : void 0;
|
|
1134
|
+
const members = membersOf(groupId);
|
|
1135
|
+
restoredTabs[groupId] = typeof wanted === "string" && members.includes(wanted) ? wanted : members[0];
|
|
1136
|
+
}
|
|
1137
|
+
activeTabs = restoredTabs;
|
|
1138
|
+
for (const groupId of Object.keys(restoredTabs)) dissolveIfOrphaned(groupId);
|
|
1139
|
+
if (!focusedId || !isVisibleTab(windows[focusedId])) focusTop();
|
|
973
1140
|
const modal = topModalId();
|
|
974
1141
|
if (modal) {
|
|
975
1142
|
const focusedWin = focusedId ? windows[focusedId] : null;
|
|
@@ -1023,6 +1190,10 @@ function createWindowManager(options = {}) {
|
|
|
1023
1190
|
workspace: () => workspace,
|
|
1024
1191
|
setWorkspace: (next) => transact(() => setWorkspace(next)),
|
|
1025
1192
|
moveToWorkspace: (id, next) => transact(() => moveToWorkspace(id, next)),
|
|
1193
|
+
group: (ids) => transact(() => group(ids)),
|
|
1194
|
+
ungroup: (id) => transact(() => ungroup(id)),
|
|
1195
|
+
activateTab: (id) => transact(() => activateTab(id)),
|
|
1196
|
+
groupMembers,
|
|
1026
1197
|
batch: (run) => transact(run),
|
|
1027
1198
|
serialize,
|
|
1028
1199
|
hydrate: (data) => transact(() => hydrate(data)),
|
|
@@ -1130,10 +1301,8 @@ function createAnnouncer(wm, container, messages = {}) {
|
|
|
1130
1301
|
element.style.cssText = "position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0";
|
|
1131
1302
|
container.append(element);
|
|
1132
1303
|
let clearTimer;
|
|
1133
|
-
let lastMessage = "";
|
|
1134
1304
|
let detailed = false;
|
|
1135
1305
|
function announce(message) {
|
|
1136
|
-
lastMessage = message;
|
|
1137
1306
|
element.textContent = message;
|
|
1138
1307
|
if (clearTimer !== void 0) clearTimeout(clearTimer);
|
|
1139
1308
|
clearTimer = setTimeout(() => {
|
|
@@ -1141,8 +1310,14 @@ function createAnnouncer(wm, container, messages = {}) {
|
|
|
1141
1310
|
}, 2e3);
|
|
1142
1311
|
}
|
|
1143
1312
|
const unsubscribers = [
|
|
1144
|
-
wm.on("open", ({ window: win }) =>
|
|
1145
|
-
|
|
1313
|
+
wm.on("open", ({ window: win }) => {
|
|
1314
|
+
announce(dict.opened(win.title));
|
|
1315
|
+
detailed = true;
|
|
1316
|
+
}),
|
|
1317
|
+
wm.on("close", ({ window: win }) => {
|
|
1318
|
+
announce(dict.closed(win.title));
|
|
1319
|
+
detailed = true;
|
|
1320
|
+
}),
|
|
1146
1321
|
wm.on("stage", ({ window: win, previous }) => {
|
|
1147
1322
|
if (win.stage === "minimized") announce(dict.minimized(win.title));
|
|
1148
1323
|
else if (win.stage === "maximized") announce(dict.maximized(win.title));
|
|
@@ -1153,7 +1328,7 @@ function createAnnouncer(wm, container, messages = {}) {
|
|
|
1153
1328
|
detailed = true;
|
|
1154
1329
|
}),
|
|
1155
1330
|
wm.on("focus", ({ window: win, previous }) => {
|
|
1156
|
-
if (detailed || previous === null
|
|
1331
|
+
if (detailed || previous === null) return;
|
|
1157
1332
|
announce(dict.focused(win.title));
|
|
1158
1333
|
}),
|
|
1159
1334
|
wm.on("workspace", ({ workspace }) => {
|
|
@@ -1208,6 +1383,11 @@ function createDragStarter(ctx) {
|
|
|
1208
1383
|
restored: win.stage === "normal",
|
|
1209
1384
|
moved: false,
|
|
1210
1385
|
zone: null,
|
|
1386
|
+
groupTarget: null,
|
|
1387
|
+
hoverId: null,
|
|
1388
|
+
hoverTimer: 0,
|
|
1389
|
+
clientX: event.clientX,
|
|
1390
|
+
clientY: event.clientY,
|
|
1211
1391
|
raf: 0,
|
|
1212
1392
|
pendingX: 0,
|
|
1213
1393
|
pendingY: 0,
|
|
@@ -1216,6 +1396,18 @@ function createDragStarter(ctx) {
|
|
|
1216
1396
|
}
|
|
1217
1397
|
};
|
|
1218
1398
|
const el = ctx.windowElement(id);
|
|
1399
|
+
function armGroup(target2) {
|
|
1400
|
+
session.groupTarget = target2;
|
|
1401
|
+
ctx.markGroupTarget(target2);
|
|
1402
|
+
}
|
|
1403
|
+
function clearHover() {
|
|
1404
|
+
if (session.hoverTimer !== 0) {
|
|
1405
|
+
view.clearTimeout(session.hoverTimer);
|
|
1406
|
+
session.hoverTimer = 0;
|
|
1407
|
+
}
|
|
1408
|
+
session.groupTarget = null;
|
|
1409
|
+
ctx.markGroupTarget(null);
|
|
1410
|
+
}
|
|
1219
1411
|
function flush() {
|
|
1220
1412
|
if (!session.hasPending || ctx.currentDrag() !== session) return;
|
|
1221
1413
|
session.hasPending = false;
|
|
@@ -1263,6 +1455,20 @@ function createDragStarter(ctx) {
|
|
|
1263
1455
|
nextY = magnet.y;
|
|
1264
1456
|
}
|
|
1265
1457
|
wm.move(id, nextX, nextY);
|
|
1458
|
+
const candidate = ctx.groupTarget(session.clientX, session.clientY, id);
|
|
1459
|
+
if (candidate !== session.hoverId) {
|
|
1460
|
+
session.hoverId = candidate;
|
|
1461
|
+
clearHover();
|
|
1462
|
+
if (candidate) {
|
|
1463
|
+
if (ctx.groupDwell <= 0) armGroup(candidate);
|
|
1464
|
+
else session.hoverTimer = view.setTimeout(() => armGroup(candidate), ctx.groupDwell);
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
if (session.groupTarget) {
|
|
1468
|
+
session.zone = null;
|
|
1469
|
+
ctx.hidePreview();
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1266
1472
|
if (ctx.snapEnabled && current.snappable) {
|
|
1267
1473
|
const viewport = wm.getState().viewport;
|
|
1268
1474
|
const rawZone = detectSnapZone(session.pendingX, session.pendingY, viewport, ctx.snapDetect);
|
|
@@ -1295,6 +1501,8 @@ function createDragStarter(ctx) {
|
|
|
1295
1501
|
}
|
|
1296
1502
|
session.pendingX = movePoint.x;
|
|
1297
1503
|
session.pendingY = movePoint.y;
|
|
1504
|
+
session.clientX = moveEvent.clientX;
|
|
1505
|
+
session.clientY = moveEvent.clientY;
|
|
1298
1506
|
session.hasPending = true;
|
|
1299
1507
|
if (session.raf === 0) session.raf = view.requestAnimationFrame(flush);
|
|
1300
1508
|
}
|
|
@@ -1329,6 +1537,8 @@ function createDragStarter(ctx) {
|
|
|
1329
1537
|
wm.move(id, session.startBounds.x, session.startBounds.y);
|
|
1330
1538
|
}
|
|
1331
1539
|
}
|
|
1540
|
+
} else if (session.moved && session.groupTarget) {
|
|
1541
|
+
if (wm.group([session.groupTarget, id])) wm.activateTab(id);
|
|
1332
1542
|
} else if (session.moved && session.zone) {
|
|
1333
1543
|
if (session.zone === "maximize") wm.maximize(id);
|
|
1334
1544
|
else wm.snap(id, session.zone);
|
|
@@ -1348,6 +1558,8 @@ function createDragStarter(ctx) {
|
|
|
1348
1558
|
el.style.willChange = "";
|
|
1349
1559
|
}
|
|
1350
1560
|
ctx.hidePreview();
|
|
1561
|
+
if (session.hoverTimer !== 0) view.clearTimeout(session.hoverTimer);
|
|
1562
|
+
ctx.markGroupTarget(null);
|
|
1351
1563
|
if (cancelled) wm.abortInteraction();
|
|
1352
1564
|
else wm.endInteraction();
|
|
1353
1565
|
}
|
|
@@ -1400,6 +1612,7 @@ function createResizeStarter(ctx) {
|
|
|
1400
1612
|
let pendingX = 0;
|
|
1401
1613
|
let pendingY = 0;
|
|
1402
1614
|
let hasPending = false;
|
|
1615
|
+
let applied = false;
|
|
1403
1616
|
const el = ctx.windowElement(id);
|
|
1404
1617
|
if (el) el.dataset.wmResizing = direction;
|
|
1405
1618
|
function flush() {
|
|
@@ -1408,18 +1621,24 @@ function createResizeStarter(ctx) {
|
|
|
1408
1621
|
raf = 0;
|
|
1409
1622
|
const dx = pendingX - startPoint.x;
|
|
1410
1623
|
const dy = pendingY - startPoint.y;
|
|
1411
|
-
const
|
|
1624
|
+
const floor = Math.min(0, start.y);
|
|
1625
|
+
const top = direction.includes("n") ? Math.max(floor, start.y + dy) : start.y;
|
|
1412
1626
|
const raw = {
|
|
1413
1627
|
width: direction.includes("e") ? start.width + dx : direction.includes("w") ? start.width - dx : start.width,
|
|
1414
1628
|
height: direction.includes("s") ? start.height + dy : direction.includes("n") ? start.y + start.height - top : start.height
|
|
1415
1629
|
};
|
|
1416
|
-
|
|
1630
|
+
let size = aspect === null ? clampSize(raw, minSize, maxSize) : applyAspect(raw, aspect, minSize, maxSize, drive);
|
|
1631
|
+
const available = start.y + start.height - floor;
|
|
1632
|
+
if (direction.includes("n") && size.height > available) {
|
|
1633
|
+
size = applyAspect({ ...size, height: available }, aspect ?? 0, minSize, maxSize, "height");
|
|
1634
|
+
}
|
|
1417
1635
|
const next = {
|
|
1418
1636
|
x: direction.includes("w") ? start.x + start.width - size.width : start.x,
|
|
1419
1637
|
y: direction.includes("n") ? start.y + start.height - size.height : start.y,
|
|
1420
1638
|
...size
|
|
1421
1639
|
};
|
|
1422
1640
|
wm.resize(id, next);
|
|
1641
|
+
applied = true;
|
|
1423
1642
|
}
|
|
1424
1643
|
function onMove(moveEvent) {
|
|
1425
1644
|
if (moveEvent.pointerId !== event.pointerId) return;
|
|
@@ -1434,7 +1653,7 @@ function createResizeStarter(ctx) {
|
|
|
1434
1653
|
try {
|
|
1435
1654
|
if (raf !== 0) view.cancelAnimationFrame(raf);
|
|
1436
1655
|
if (hasPending && !cancelled) flush();
|
|
1437
|
-
if (cancelled) {
|
|
1656
|
+
if (cancelled && applied) {
|
|
1438
1657
|
if (startStage === "snapped" && startZone) {
|
|
1439
1658
|
wm.restoreTo(id, startRestore ?? start);
|
|
1440
1659
|
wm.snap(id, startZone);
|
|
@@ -1510,6 +1729,8 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1510
1729
|
const doc = element.ownerDocument;
|
|
1511
1730
|
const view = windowOf(element);
|
|
1512
1731
|
const coarsePointer = typeof view.matchMedia === "function" && view.matchMedia("(pointer: coarse)").matches;
|
|
1732
|
+
const groupingEnabled = options.grouping !== false;
|
|
1733
|
+
const groupDwell = (typeof options.grouping === "object" ? options.grouping.dwell : void 0) ?? 420;
|
|
1513
1734
|
const snapEnabled = options.snap !== false;
|
|
1514
1735
|
const snapOptions = typeof options.snap === "object" ? options.snap : {};
|
|
1515
1736
|
const snapPreviewEnabled = snapOptions.preview !== false;
|
|
@@ -1533,6 +1754,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1533
1754
|
let lastOrder = null;
|
|
1534
1755
|
let lastFocused = null;
|
|
1535
1756
|
let drag = null;
|
|
1757
|
+
let groupTargetId = null;
|
|
1536
1758
|
let cachedRect = null;
|
|
1537
1759
|
let rectUsers = 0;
|
|
1538
1760
|
let announcer = null;
|
|
@@ -1604,6 +1826,29 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1604
1826
|
hitEdge,
|
|
1605
1827
|
hitCorner,
|
|
1606
1828
|
magnetThreshold,
|
|
1829
|
+
groupDwell,
|
|
1830
|
+
groupTarget(clientX, clientY, selfId) {
|
|
1831
|
+
if (!groupingEnabled || typeof doc.elementsFromPoint !== "function") return null;
|
|
1832
|
+
for (const node of doc.elementsFromPoint(clientX, clientY)) {
|
|
1833
|
+
const handle = node.closest?.("[data-wm-drag]");
|
|
1834
|
+
const host = handle?.closest("[data-wm-window]");
|
|
1835
|
+
const id = host?.dataset.wmWindow;
|
|
1836
|
+
if (id && id !== selfId && registry.has(id)) return id;
|
|
1837
|
+
}
|
|
1838
|
+
return null;
|
|
1839
|
+
},
|
|
1840
|
+
markGroupTarget(id) {
|
|
1841
|
+
if (groupTargetId === id) return;
|
|
1842
|
+
if (groupTargetId) {
|
|
1843
|
+
const previous = registry.get(groupTargetId);
|
|
1844
|
+
if (previous) delete previous.element.dataset.wmTabTarget;
|
|
1845
|
+
}
|
|
1846
|
+
groupTargetId = id;
|
|
1847
|
+
if (id) {
|
|
1848
|
+
const next = registry.get(id);
|
|
1849
|
+
if (next) next.element.dataset.wmTabTarget = "";
|
|
1850
|
+
}
|
|
1851
|
+
},
|
|
1607
1852
|
currentDrag: () => drag,
|
|
1608
1853
|
claimDrag(session) {
|
|
1609
1854
|
drag = session;
|
|
@@ -1621,21 +1866,33 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1621
1866
|
observer.observe(element);
|
|
1622
1867
|
cleanup.push(() => observer.disconnect());
|
|
1623
1868
|
}
|
|
1624
|
-
function syncWindow(attached, win, zIndex, activeWorkspace) {
|
|
1869
|
+
function syncWindow(attached, win, zIndex, activeWorkspace, activeTab) {
|
|
1625
1870
|
const el = attached.element;
|
|
1626
1871
|
const firstSync = attached.lastState === null;
|
|
1627
1872
|
if (firstSync) el.style.transition = "none";
|
|
1628
|
-
if (attached.lastState !== win || attached.lastWorkspace !== activeWorkspace) {
|
|
1873
|
+
if (attached.lastState !== win || attached.lastWorkspace !== activeWorkspace || attached.lastTab !== activeTab) {
|
|
1629
1874
|
el.style.transform = `translate3d(${win.bounds.x}px, ${win.bounds.y}px, 0)`;
|
|
1630
1875
|
el.style.width = `${win.bounds.width}px`;
|
|
1631
1876
|
el.style.height = `${win.bounds.height}px`;
|
|
1632
1877
|
el.dataset.wmStage = win.stage;
|
|
1633
1878
|
el.dataset.wmLayer = win.layer;
|
|
1634
1879
|
el.dataset.wmWorkspace = String(win.workspace);
|
|
1635
|
-
|
|
1880
|
+
if (win.groupId === null) {
|
|
1881
|
+
delete el.dataset.wmGroup;
|
|
1882
|
+
delete el.dataset.wmTab;
|
|
1883
|
+
} else {
|
|
1884
|
+
el.dataset.wmGroup = win.groupId;
|
|
1885
|
+
el.dataset.wmTab = activeTab ? "active" : "inactive";
|
|
1886
|
+
}
|
|
1887
|
+
const hide = win.stage === "minimized" || win.workspace !== activeWorkspace || !activeTab;
|
|
1636
1888
|
if (hide && !el.hidden && el.contains(doc.activeElement)) {
|
|
1637
1889
|
element.focus({ preventScroll: true });
|
|
1638
1890
|
}
|
|
1891
|
+
if (!hide && el.hidden && wm.getState().focusedId === win.id) {
|
|
1892
|
+
queueMicrotask(() => {
|
|
1893
|
+
if (!el.hidden && !el.contains(doc.activeElement)) el.focus({ preventScroll: true });
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1639
1896
|
el.hidden = hide;
|
|
1640
1897
|
el.setAttribute("aria-label", win.title);
|
|
1641
1898
|
if (win.layer === "modal") el.setAttribute("aria-modal", "true");
|
|
@@ -1645,6 +1902,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1645
1902
|
}
|
|
1646
1903
|
attached.lastState = win;
|
|
1647
1904
|
attached.lastWorkspace = activeWorkspace;
|
|
1905
|
+
attached.lastTab = activeTab;
|
|
1648
1906
|
}
|
|
1649
1907
|
if (attached.lastZ !== zIndex) {
|
|
1650
1908
|
el.style.zIndex = String(zIndex + 1);
|
|
@@ -1662,8 +1920,9 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1662
1920
|
const attached = registry.get(id);
|
|
1663
1921
|
const win = state.windows[id];
|
|
1664
1922
|
if (!attached || !win) return;
|
|
1665
|
-
|
|
1666
|
-
|
|
1923
|
+
const activeTab = win.groupId === null || state.groups[win.groupId]?.activeId === win.id;
|
|
1924
|
+
if (orderChanged || attached.lastState !== win || attached.lastWorkspace !== state.workspace || attached.lastTab !== activeTab) {
|
|
1925
|
+
syncWindow(attached, win, index, state.workspace, activeTab);
|
|
1667
1926
|
}
|
|
1668
1927
|
});
|
|
1669
1928
|
if (state.focusedId !== lastFocused) {
|
|
@@ -1684,6 +1943,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1684
1943
|
wm.on("focus", ({ window: win }) => {
|
|
1685
1944
|
const attached = registry.get(win.id);
|
|
1686
1945
|
if (!attached) return;
|
|
1946
|
+
if (attached.element.hidden) syncAll();
|
|
1687
1947
|
if (!attached.element.contains(doc.activeElement)) {
|
|
1688
1948
|
attached.element.focus({ preventScroll: true });
|
|
1689
1949
|
}
|
|
@@ -1719,6 +1979,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1719
1979
|
return;
|
|
1720
1980
|
}
|
|
1721
1981
|
if (!event.ctrlKey && !event.metaKey) return;
|
|
1982
|
+
if (drag) return;
|
|
1722
1983
|
const target = event.target;
|
|
1723
1984
|
if (target?.closest(INTERACTIVE_SELECTOR)) return;
|
|
1724
1985
|
if (historyShortcuts && (event.key === "z" || event.key === "Z")) {
|
|
@@ -1764,6 +2025,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1764
2025
|
lastState: null,
|
|
1765
2026
|
lastZ: -1,
|
|
1766
2027
|
lastWorkspace: -1,
|
|
2028
|
+
lastTab: true,
|
|
1767
2029
|
cleanup: []
|
|
1768
2030
|
};
|
|
1769
2031
|
windowElement.dataset.wmWindow = id;
|
|
@@ -1987,5 +2249,5 @@ function createDesktopBinder(wm, options = {}) {
|
|
|
1987
2249
|
}
|
|
1988
2250
|
|
|
1989
2251
|
export { applyAspect, attachDesktop, boundsEqual, clamp, clampSize, clampToViewport, createAnnouncer, createDesktopBinder, createEmitter, createWindowManager, defaultMessages, detectSnapZone, flipFromTarget, flipToTarget, magnetize, prefersReducedMotion, zoneBounds };
|
|
1990
|
-
//# sourceMappingURL=chunk-
|
|
1991
|
-
//# sourceMappingURL=chunk-
|
|
2252
|
+
//# sourceMappingURL=chunk-L43XBN44.js.map
|
|
2253
|
+
//# sourceMappingURL=chunk-L43XBN44.js.map
|