@surdeddd/wmkit 0.1.0 → 0.2.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 +14 -2
- package/README.ru.md +8 -2
- package/dist/{controller-D5zIriLg.d.ts → binder-BY-saDUB.d.cts} +9 -3
- package/dist/{controller-B0bogK9N.d.cts → binder-D9UEE1SM.d.ts} +9 -3
- package/dist/{chunk-7HHDQEBI.js → chunk-2TVOEDRG.js} +368 -247
- package/dist/chunk-2TVOEDRG.js.map +1 -0
- package/dist/{chunk-KWLI7JIY.cjs → chunk-KQCVZ2W7.cjs} +368 -247
- package/dist/chunk-KQCVZ2W7.cjs.map +1 -0
- package/dist/index.cjs +15 -15
- package/dist/index.d.cts +7 -4
- package/dist/index.d.ts +7 -4
- package/dist/index.js +1 -1
- package/dist/persist.cjs +1 -1
- package/dist/persist.cjs.map +1 -1
- package/dist/persist.d.cts +1 -1
- package/dist/persist.d.ts +1 -1
- package/dist/persist.js +1 -1
- package/dist/persist.js.map +1 -1
- package/dist/popout.cjs +1 -1
- package/dist/popout.cjs.map +1 -1
- package/dist/popout.d.cts +1 -1
- package/dist/popout.d.ts +1 -1
- package/dist/popout.js +1 -1
- package/dist/popout.js.map +1 -1
- package/dist/react.cjs +3 -3
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +1 -1
- package/dist/react.js.map +1 -1
- package/dist/solid.cjs +3 -3
- package/dist/solid.cjs.map +1 -1
- package/dist/solid.d.cts +2 -2
- package/dist/solid.d.ts +2 -2
- package/dist/solid.js +1 -1
- package/dist/solid.js.map +1 -1
- package/dist/svelte.cjs +4 -4
- package/dist/svelte.cjs.map +1 -1
- package/dist/svelte.d.cts +2 -2
- package/dist/svelte.d.ts +2 -2
- package/dist/svelte.js +2 -2
- package/dist/svelte.js.map +1 -1
- package/dist/themes/glass.css +0 -1
- package/dist/{types-CtFzL_oA.d.cts → types-Bkrq2djr.d.cts} +9 -2
- package/dist/{types-CtFzL_oA.d.ts → types-Bkrq2djr.d.ts} +9 -2
- package/dist/vue.cjs +3 -3
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +2 -2
- package/dist/vue.d.ts +2 -2
- package/dist/vue.js +1 -1
- package/dist/vue.js.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-7HHDQEBI.js.map +0 -1
- package/dist/chunk-KWLI7JIY.cjs.map +0 -1
|
@@ -141,12 +141,7 @@ function createWindowManager(options = {}) {
|
|
|
141
141
|
}
|
|
142
142
|
function commit() {
|
|
143
143
|
snapshot = null;
|
|
144
|
-
|
|
145
|
-
batchDirty = true;
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
flushEvents();
|
|
149
|
-
emitter.emit("change", { state: getState() });
|
|
144
|
+
batchDirty = true;
|
|
150
145
|
}
|
|
151
146
|
function flushEvents() {
|
|
152
147
|
while (pendingEvents.length > 0) {
|
|
@@ -155,7 +150,6 @@ function createWindowManager(options = {}) {
|
|
|
155
150
|
}
|
|
156
151
|
function queueEvent(emit) {
|
|
157
152
|
pendingEvents.push(emit);
|
|
158
|
-
if (batchDepth === 0) flushEvents();
|
|
159
153
|
}
|
|
160
154
|
function setWindow(next) {
|
|
161
155
|
windows = { ...windows, [next.id]: next };
|
|
@@ -219,7 +213,12 @@ function createWindowManager(options = {}) {
|
|
|
219
213
|
return { x: init.x ?? base.x, y: init.y ?? base.y };
|
|
220
214
|
}
|
|
221
215
|
function open(init = {}) {
|
|
222
|
-
|
|
216
|
+
let id = init.id;
|
|
217
|
+
if (id === void 0) {
|
|
218
|
+
do {
|
|
219
|
+
id = `${idPrefix}-${++idCounter}`;
|
|
220
|
+
} while (windows[id]);
|
|
221
|
+
}
|
|
223
222
|
if (windows[id]) throw new Error(`wmkit: window id "${id}" already exists`);
|
|
224
223
|
const minSize = { width: init.minWidth ?? 160, height: init.minHeight ?? 100 };
|
|
225
224
|
const maxSize = init.maxWidth !== void 0 || init.maxHeight !== void 0 ? {
|
|
@@ -297,9 +296,7 @@ function createWindowManager(options = {}) {
|
|
|
297
296
|
return true;
|
|
298
297
|
}
|
|
299
298
|
function closeAll() {
|
|
300
|
-
|
|
301
|
-
for (const id of [...order]) close(id);
|
|
302
|
-
});
|
|
299
|
+
for (const id of [...order]) close(id);
|
|
303
300
|
}
|
|
304
301
|
function focus(id) {
|
|
305
302
|
const win = windows[id];
|
|
@@ -506,6 +503,11 @@ function createWindowManager(options = {}) {
|
|
|
506
503
|
if (patch.layer && patch.layer !== win.layer) {
|
|
507
504
|
order = sortByLayer(order);
|
|
508
505
|
queueEvent(() => emitter.emit("order", { order }));
|
|
506
|
+
if (patch.layer === "modal" && topModalId() === id && focusedId !== id) {
|
|
507
|
+
const previous = focusedId;
|
|
508
|
+
focusedId = id;
|
|
509
|
+
emitFocus(finalWin, previous);
|
|
510
|
+
}
|
|
509
511
|
}
|
|
510
512
|
queueEvent(() => emitter.emit("update", { window: finalWin }));
|
|
511
513
|
if (resized) queueEvent(() => emitter.emit("resize", { window: finalWin }));
|
|
@@ -515,7 +517,7 @@ function createWindowManager(options = {}) {
|
|
|
515
517
|
function setViewport(next) {
|
|
516
518
|
if (next.width === viewport.width && next.height === viewport.height) return;
|
|
517
519
|
viewport = { ...next };
|
|
518
|
-
|
|
520
|
+
transact(() => {
|
|
519
521
|
for (const id of order) {
|
|
520
522
|
const win = windows[id];
|
|
521
523
|
if (win.stage === "maximized") {
|
|
@@ -542,10 +544,10 @@ function createWindowManager(options = {}) {
|
|
|
542
544
|
function minimized() {
|
|
543
545
|
return Object.values(windows).filter((win) => win.stage === "minimized").sort((a, b) => a.openedSeq - b.openedSeq);
|
|
544
546
|
}
|
|
545
|
-
function
|
|
547
|
+
function transact(run) {
|
|
546
548
|
batchDepth += 1;
|
|
547
549
|
try {
|
|
548
|
-
run();
|
|
550
|
+
return run();
|
|
549
551
|
} finally {
|
|
550
552
|
batchDepth -= 1;
|
|
551
553
|
if (batchDepth === 0 && batchDirty) {
|
|
@@ -564,7 +566,10 @@ function createWindowManager(options = {}) {
|
|
|
564
566
|
bounds: { ...win.bounds },
|
|
565
567
|
restoreBounds: win.restoreBounds ? { ...win.restoreBounds } : null,
|
|
566
568
|
minSize: { ...win.minSize },
|
|
567
|
-
maxSize: win.maxSize ? {
|
|
569
|
+
maxSize: win.maxSize ? {
|
|
570
|
+
width: Number.isFinite(win.maxSize.width) ? win.maxSize.width : null,
|
|
571
|
+
height: Number.isFinite(win.maxSize.height) ? win.maxSize.height : null
|
|
572
|
+
} : null,
|
|
568
573
|
meta: { ...win.meta }
|
|
569
574
|
})),
|
|
570
575
|
order: [...order],
|
|
@@ -581,6 +586,19 @@ function createWindowManager(options = {}) {
|
|
|
581
586
|
const size = value;
|
|
582
587
|
return typeof size.width === "number" && typeof size.height === "number";
|
|
583
588
|
}
|
|
589
|
+
function isSizeAxis(value) {
|
|
590
|
+
return value === null || typeof value === "number";
|
|
591
|
+
}
|
|
592
|
+
function readMaxSize(value) {
|
|
593
|
+
if (typeof value !== "object" || value === null) return null;
|
|
594
|
+
const size = value;
|
|
595
|
+
if (!isSizeAxis(size.width) || !isSizeAxis(size.height)) return null;
|
|
596
|
+
if (size.width === null && size.height === null) return null;
|
|
597
|
+
return {
|
|
598
|
+
width: size.width ?? Number.POSITIVE_INFINITY,
|
|
599
|
+
height: size.height ?? Number.POSITIVE_INFINITY
|
|
600
|
+
};
|
|
601
|
+
}
|
|
584
602
|
function isSerializedWindow(value) {
|
|
585
603
|
if (typeof value !== "object" || value === null) return false;
|
|
586
604
|
const win = value;
|
|
@@ -604,7 +622,7 @@ function createWindowManager(options = {}) {
|
|
|
604
622
|
snapZone: ZONES.includes(raw.snapZone) ? raw.snapZone : null,
|
|
605
623
|
layer: raw.layer,
|
|
606
624
|
minSize: isSize(raw.minSize) ? { ...raw.minSize } : { width: 160, height: 100 },
|
|
607
|
-
maxSize:
|
|
625
|
+
maxSize: readMaxSize(raw.maxSize),
|
|
608
626
|
openedSeq: typeof raw.openedSeq === "number" ? raw.openedSeq : ++maxSeq,
|
|
609
627
|
draggable: raw.draggable !== false,
|
|
610
628
|
resizable: raw.resizable !== false,
|
|
@@ -636,6 +654,11 @@ function createWindowManager(options = {}) {
|
|
|
636
654
|
focusedId = data.focusedId && windows[data.focusedId] ? data.focusedId : null;
|
|
637
655
|
if (focusedId && windows[focusedId]?.stage === "minimized") focusedId = null;
|
|
638
656
|
if (!focusedId) focusTop();
|
|
657
|
+
const modal = topModalId();
|
|
658
|
+
if (modal) {
|
|
659
|
+
const focusedWin = focusedId ? windows[focusedId] : null;
|
|
660
|
+
if (focusedWin?.layer !== "modal") focusedId = modal;
|
|
661
|
+
}
|
|
639
662
|
commit();
|
|
640
663
|
return true;
|
|
641
664
|
}
|
|
@@ -643,29 +666,29 @@ function createWindowManager(options = {}) {
|
|
|
643
666
|
emitter.clear();
|
|
644
667
|
}
|
|
645
668
|
return {
|
|
646
|
-
open,
|
|
647
|
-
close,
|
|
648
|
-
closeAll,
|
|
649
|
-
focus,
|
|
650
|
-
blur,
|
|
651
|
-
cycleFocus,
|
|
652
|
-
minimize,
|
|
653
|
-
maximize,
|
|
654
|
-
toggleMaximize,
|
|
655
|
-
restore,
|
|
656
|
-
restoreTo,
|
|
657
|
-
snap,
|
|
658
|
-
move,
|
|
659
|
-
moveBy,
|
|
660
|
-
resize,
|
|
661
|
-
update,
|
|
669
|
+
open: (init) => transact(() => open(init)),
|
|
670
|
+
close: (id) => transact(() => close(id)),
|
|
671
|
+
closeAll: () => transact(closeAll),
|
|
672
|
+
focus: (id) => transact(() => focus(id)),
|
|
673
|
+
blur: () => transact(blur),
|
|
674
|
+
cycleFocus: (direction) => transact(() => cycleFocus(direction)),
|
|
675
|
+
minimize: (id) => transact(() => minimize(id)),
|
|
676
|
+
maximize: (id) => transact(() => maximize(id)),
|
|
677
|
+
toggleMaximize: (id) => transact(() => toggleMaximize(id)),
|
|
678
|
+
restore: (id) => transact(() => restore(id)),
|
|
679
|
+
restoreTo: (id, bounds) => transact(() => restoreTo(id, bounds)),
|
|
680
|
+
snap: (id, zone) => transact(() => snap(id, zone)),
|
|
681
|
+
move: (id, x, y) => transact(() => move(id, x, y)),
|
|
682
|
+
moveBy: (id, dx, dy) => transact(() => moveBy(id, dx, dy)),
|
|
683
|
+
resize: (id, patch) => transact(() => resize(id, patch)),
|
|
684
|
+
update: (id, patch) => transact(() => update(id, patch)),
|
|
662
685
|
get: (id) => windows[id],
|
|
663
686
|
getState,
|
|
664
687
|
minimized,
|
|
665
|
-
setViewport,
|
|
666
|
-
batch,
|
|
688
|
+
setViewport: (next) => transact(() => setViewport(next)),
|
|
689
|
+
batch: (run) => transact(run),
|
|
667
690
|
serialize,
|
|
668
|
-
hydrate,
|
|
691
|
+
hydrate: (data) => transact(() => hydrate(data)),
|
|
669
692
|
subscribe: (listener) => emitter.on("change", ({ state }) => listener(state)),
|
|
670
693
|
on: (event, listener) => emitter.on(event, listener),
|
|
671
694
|
destroy
|
|
@@ -753,175 +776,25 @@ function createAnnouncer(wm, container, messages = {}) {
|
|
|
753
776
|
};
|
|
754
777
|
}
|
|
755
778
|
|
|
756
|
-
// src/dom/
|
|
757
|
-
var RESIZE_DIRECTIONS = ["n", "e", "s", "w", "ne", "nw", "se", "sw"];
|
|
758
|
-
var RESIZE_CURSORS = {
|
|
759
|
-
n: "ns-resize",
|
|
760
|
-
s: "ns-resize",
|
|
761
|
-
e: "ew-resize",
|
|
762
|
-
w: "ew-resize",
|
|
763
|
-
ne: "nesw-resize",
|
|
764
|
-
sw: "nesw-resize",
|
|
765
|
-
nw: "nwse-resize",
|
|
766
|
-
se: "nwse-resize"
|
|
767
|
-
};
|
|
779
|
+
// src/dom/shared.ts
|
|
768
780
|
var INTERACTIVE_SELECTOR = "button, input, select, textarea, a[href], [contenteditable], [data-wm-close], [data-wm-minimize], [data-wm-maximize]";
|
|
769
781
|
function windowOf(element) {
|
|
770
782
|
const view = element.ownerDocument.defaultView;
|
|
771
783
|
if (!view) throw new Error("wmkit: desktop element is not attached to a document");
|
|
772
784
|
return view;
|
|
773
785
|
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
const
|
|
778
|
-
|
|
779
|
-
const snapPreviewEnabled = snapOptions.preview !== false;
|
|
780
|
-
const topEdge = snapOptions.topEdge ?? "maximize";
|
|
781
|
-
const keyboardEnabled = options.keyboard !== false;
|
|
782
|
-
const keyboardOptions = typeof options.keyboard === "object" ? options.keyboard : {};
|
|
783
|
-
const moveStep = keyboardOptions.moveStep ?? 16;
|
|
784
|
-
const cycleEnabled = keyboardOptions.cycle !== false;
|
|
785
|
-
element.dataset.wmDesktop = "";
|
|
786
|
-
if (view.getComputedStyle(element).position === "static") {
|
|
787
|
-
element.style.position = "relative";
|
|
788
|
-
}
|
|
789
|
-
const registry = /* @__PURE__ */ new Map();
|
|
790
|
-
const cleanup = [];
|
|
791
|
-
let lastOrder = null;
|
|
792
|
-
let lastFocused = null;
|
|
793
|
-
let drag = null;
|
|
794
|
-
let announcer = null;
|
|
795
|
-
if (options.announce !== false) {
|
|
796
|
-
announcer = createAnnouncer(
|
|
797
|
-
wm,
|
|
798
|
-
element,
|
|
799
|
-
typeof options.announce === "object" ? options.announce : {}
|
|
800
|
-
);
|
|
801
|
-
cleanup.push(() => announcer?.destroy());
|
|
802
|
-
}
|
|
803
|
-
let preview = null;
|
|
804
|
-
function showPreview(bounds) {
|
|
805
|
-
if (!snapPreviewEnabled) return;
|
|
806
|
-
if (!preview) {
|
|
807
|
-
preview = doc.createElement("div");
|
|
808
|
-
preview.dataset.wmSnapPreview = "";
|
|
809
|
-
preview.style.cssText = "position:absolute;left:0;top:0;pointer-events:none;display:none;z-index:2147483646";
|
|
810
|
-
element.append(preview);
|
|
811
|
-
}
|
|
812
|
-
preview.style.display = "block";
|
|
813
|
-
preview.style.transform = `translate3d(${bounds.x}px, ${bounds.y}px, 0)`;
|
|
814
|
-
preview.style.width = `${bounds.width}px`;
|
|
815
|
-
preview.style.height = `${bounds.height}px`;
|
|
816
|
-
}
|
|
817
|
-
function hidePreview() {
|
|
818
|
-
if (preview) preview.style.display = "none";
|
|
819
|
-
}
|
|
820
|
-
if (options.autoViewport !== false) {
|
|
821
|
-
const applyViewport = () => wm.setViewport({ width: element.clientWidth, height: element.clientHeight });
|
|
822
|
-
applyViewport();
|
|
823
|
-
const observer = new ResizeObserver(applyViewport);
|
|
824
|
-
observer.observe(element);
|
|
825
|
-
cleanup.push(() => observer.disconnect());
|
|
826
|
-
}
|
|
827
|
-
function syncWindow(attached, win, zIndex) {
|
|
828
|
-
const el = attached.element;
|
|
829
|
-
const firstSync = attached.lastState === null;
|
|
830
|
-
if (firstSync) el.style.transition = "none";
|
|
831
|
-
if (attached.lastState !== win) {
|
|
832
|
-
el.style.transform = `translate3d(${win.bounds.x}px, ${win.bounds.y}px, 0)`;
|
|
833
|
-
el.style.width = `${win.bounds.width}px`;
|
|
834
|
-
el.style.height = `${win.bounds.height}px`;
|
|
835
|
-
el.dataset.wmStage = win.stage;
|
|
836
|
-
el.dataset.wmLayer = win.layer;
|
|
837
|
-
el.hidden = win.stage === "minimized";
|
|
838
|
-
el.setAttribute("aria-label", win.title);
|
|
839
|
-
if (win.layer === "modal") el.setAttribute("aria-modal", "true");
|
|
840
|
-
else el.removeAttribute("aria-modal");
|
|
841
|
-
for (const handle of attached.handles) {
|
|
842
|
-
handle.style.display = win.resizable && win.stage === "normal" ? "" : "none";
|
|
843
|
-
}
|
|
844
|
-
attached.lastState = win;
|
|
845
|
-
}
|
|
846
|
-
el.style.zIndex = String(zIndex + 1);
|
|
847
|
-
if (firstSync) {
|
|
848
|
-
void el.offsetWidth;
|
|
849
|
-
el.style.transition = "";
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
function syncAll() {
|
|
853
|
-
const state = wm.getState();
|
|
854
|
-
const orderChanged = state.order !== lastOrder;
|
|
855
|
-
state.order.forEach((id, index) => {
|
|
856
|
-
const attached = registry.get(id);
|
|
857
|
-
const win = state.windows[id];
|
|
858
|
-
if (!attached || !win) return;
|
|
859
|
-
if (orderChanged || attached.lastState !== win) syncWindow(attached, win, index);
|
|
860
|
-
});
|
|
861
|
-
if (state.focusedId !== lastFocused) {
|
|
862
|
-
if (lastFocused) {
|
|
863
|
-
const prev = registry.get(lastFocused);
|
|
864
|
-
if (prev) delete prev.element.dataset.wmFocused;
|
|
865
|
-
}
|
|
866
|
-
if (state.focusedId) {
|
|
867
|
-
const next = registry.get(state.focusedId);
|
|
868
|
-
if (next) next.element.dataset.wmFocused = "";
|
|
869
|
-
}
|
|
870
|
-
lastFocused = state.focusedId;
|
|
871
|
-
}
|
|
872
|
-
lastOrder = state.order;
|
|
873
|
-
}
|
|
874
|
-
cleanup.push(wm.subscribe(syncAll));
|
|
875
|
-
cleanup.push(
|
|
876
|
-
wm.on("focus", ({ window: win }) => {
|
|
877
|
-
const attached = registry.get(win.id);
|
|
878
|
-
if (!attached) return;
|
|
879
|
-
if (!attached.element.contains(doc.activeElement)) {
|
|
880
|
-
attached.element.focus({ preventScroll: true });
|
|
881
|
-
}
|
|
882
|
-
})
|
|
883
|
-
);
|
|
884
|
-
cleanup.push(
|
|
885
|
-
wm.on("modalblocked", ({ window: win }) => {
|
|
886
|
-
const attached = registry.get(win.id);
|
|
887
|
-
if (!attached) return;
|
|
888
|
-
delete attached.element.dataset.wmFlash;
|
|
889
|
-
void attached.element.offsetWidth;
|
|
890
|
-
attached.element.dataset.wmFlash = "";
|
|
891
|
-
})
|
|
892
|
-
);
|
|
893
|
-
cleanup.push(
|
|
894
|
-
wm.on("stage", ({ window: win, previous }) => {
|
|
895
|
-
if (win.stage !== "minimized" || previous === "minimized") return;
|
|
896
|
-
const attached = registry.get(win.id);
|
|
897
|
-
const target = options.minimizeTarget?.(win);
|
|
898
|
-
if (attached && target) flipToTarget(attached.element, target);
|
|
899
|
-
})
|
|
900
|
-
);
|
|
901
|
-
if (keyboardEnabled && cycleEnabled) {
|
|
902
|
-
const onDesktopKeydown = (event) => {
|
|
903
|
-
if (event.key === "F6") {
|
|
904
|
-
event.preventDefault();
|
|
905
|
-
wm.cycleFocus(event.shiftKey ? -1 : 1);
|
|
906
|
-
}
|
|
907
|
-
};
|
|
908
|
-
element.addEventListener("keydown", onDesktopKeydown);
|
|
909
|
-
cleanup.push(() => element.removeEventListener("keydown", onDesktopKeydown));
|
|
910
|
-
}
|
|
911
|
-
function desktopPoint(event) {
|
|
912
|
-
const rect = element.getBoundingClientRect();
|
|
913
|
-
return { x: event.clientX - rect.left, y: event.clientY - rect.top };
|
|
914
|
-
}
|
|
915
|
-
function endDrag(cancelled) {
|
|
916
|
-
if (drag) drag.finish(cancelled);
|
|
917
|
-
}
|
|
918
|
-
function startDrag(id, handle, event) {
|
|
786
|
+
|
|
787
|
+
// src/dom/drag.ts
|
|
788
|
+
function createDragStarter(ctx) {
|
|
789
|
+
const { wm, doc, view } = ctx;
|
|
790
|
+
return function startDrag(id, handle, event) {
|
|
919
791
|
const win = wm.get(id);
|
|
920
|
-
if (!win?.draggable || event.button !== 0 ||
|
|
792
|
+
if (!win?.draggable || event.button !== 0 || ctx.currentDrag()) return;
|
|
921
793
|
const target = event.target;
|
|
922
794
|
if (target?.closest(INTERACTIVE_SELECTOR)) return;
|
|
923
795
|
event.preventDefault();
|
|
924
|
-
const
|
|
796
|
+
const releaseRect = ctx.trackRect();
|
|
797
|
+
const point = ctx.toLocal(event);
|
|
925
798
|
const startBounds = win.bounds;
|
|
926
799
|
const session = {
|
|
927
800
|
id,
|
|
@@ -930,6 +803,9 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
930
803
|
grabDY: point.y - startBounds.y,
|
|
931
804
|
grabRatio: clamp((point.x - startBounds.x) / startBounds.width, 0.05, 0.95),
|
|
932
805
|
startBounds,
|
|
806
|
+
startStage: win.stage,
|
|
807
|
+
startZone: win.snapZone,
|
|
808
|
+
startRestoreBounds: win.restoreBounds,
|
|
933
809
|
restored: win.stage === "normal",
|
|
934
810
|
moved: false,
|
|
935
811
|
zone: null,
|
|
@@ -940,10 +816,9 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
940
816
|
finish: () => {
|
|
941
817
|
}
|
|
942
818
|
};
|
|
943
|
-
const
|
|
944
|
-
const el = attached?.element;
|
|
819
|
+
const el = ctx.windowElement(id);
|
|
945
820
|
function flush() {
|
|
946
|
-
if (!session.hasPending ||
|
|
821
|
+
if (!session.hasPending || ctx.currentDrag() !== session) return;
|
|
947
822
|
session.hasPending = false;
|
|
948
823
|
session.raf = 0;
|
|
949
824
|
const current = wm.get(id);
|
|
@@ -967,32 +842,35 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
967
842
|
return;
|
|
968
843
|
}
|
|
969
844
|
wm.move(id, session.pendingX - session.grabDX, session.pendingY - session.grabDY);
|
|
970
|
-
if (snapEnabled && current.snappable) {
|
|
845
|
+
if (ctx.snapEnabled && current.snappable) {
|
|
971
846
|
const viewport = wm.getState().viewport;
|
|
972
|
-
const rawZone = detectSnapZone(session.pendingX, session.pendingY, viewport,
|
|
847
|
+
const rawZone = detectSnapZone(session.pendingX, session.pendingY, viewport, ctx.snapDetect);
|
|
973
848
|
let zone = rawZone;
|
|
974
849
|
if (rawZone === "top") {
|
|
975
|
-
if (topEdge === "maximize") zone = current.maximizable ? "maximize" : null;
|
|
976
|
-
else if (topEdge === "none") zone = null;
|
|
850
|
+
if (ctx.topEdge === "maximize") zone = current.maximizable ? "maximize" : null;
|
|
851
|
+
else if (ctx.topEdge === "none") zone = null;
|
|
977
852
|
}
|
|
978
853
|
session.zone = zone;
|
|
979
854
|
if (zone) {
|
|
980
|
-
showPreview(
|
|
855
|
+
ctx.showPreview(
|
|
981
856
|
zone === "maximize" ? { x: 0, y: 0, width: viewport.width, height: viewport.height } : zoneBounds(zone, viewport)
|
|
982
857
|
);
|
|
983
858
|
} else {
|
|
984
|
-
hidePreview();
|
|
859
|
+
ctx.hidePreview();
|
|
985
860
|
}
|
|
986
861
|
}
|
|
987
862
|
}
|
|
988
863
|
function onMove(moveEvent) {
|
|
989
864
|
if (moveEvent.pointerId !== session.pointerId) return;
|
|
990
|
-
const movePoint =
|
|
865
|
+
const movePoint = ctx.toLocal(moveEvent);
|
|
991
866
|
if (!session.moved) {
|
|
992
867
|
const travelled = Math.abs(movePoint.x - (session.startBounds.x + session.grabDX)) + Math.abs(movePoint.y - (session.startBounds.y + session.grabDY));
|
|
993
868
|
if (travelled < 3 && session.restored) return;
|
|
994
869
|
session.moved = true;
|
|
995
|
-
if (el)
|
|
870
|
+
if (el) {
|
|
871
|
+
el.dataset.wmDragging = "";
|
|
872
|
+
el.style.willChange = "transform";
|
|
873
|
+
}
|
|
996
874
|
}
|
|
997
875
|
session.pendingX = movePoint.x;
|
|
998
876
|
session.pendingY = movePoint.y;
|
|
@@ -1014,10 +892,11 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1014
892
|
}
|
|
1015
893
|
}
|
|
1016
894
|
function finish(cancelled) {
|
|
1017
|
-
if (
|
|
1018
|
-
if (session.raf !== 0) view
|
|
895
|
+
if (ctx.currentDrag() !== session) return;
|
|
896
|
+
if (session.raf !== 0) view.cancelAnimationFrame(session.raf);
|
|
1019
897
|
if (session.hasPending && !cancelled) flush();
|
|
1020
|
-
|
|
898
|
+
ctx.releaseDrag(session);
|
|
899
|
+
releaseRect();
|
|
1021
900
|
handle.removeEventListener("pointermove", onMove);
|
|
1022
901
|
handle.removeEventListener("pointerup", onUp);
|
|
1023
902
|
handle.removeEventListener("pointercancel", onCancel);
|
|
@@ -1025,11 +904,22 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1025
904
|
if (handle.hasPointerCapture(session.pointerId)) {
|
|
1026
905
|
handle.releasePointerCapture(session.pointerId);
|
|
1027
906
|
}
|
|
1028
|
-
if (el)
|
|
1029
|
-
|
|
907
|
+
if (el) {
|
|
908
|
+
delete el.dataset.wmDragging;
|
|
909
|
+
el.style.willChange = "";
|
|
910
|
+
}
|
|
911
|
+
ctx.hidePreview();
|
|
1030
912
|
if (cancelled) {
|
|
1031
913
|
if (session.moved && session.restored) {
|
|
1032
|
-
|
|
914
|
+
if (session.startStage === "maximized") {
|
|
915
|
+
wm.restoreTo(id, session.startRestoreBounds ?? session.startBounds);
|
|
916
|
+
wm.maximize(id);
|
|
917
|
+
} else if (session.startStage === "snapped" && session.startZone) {
|
|
918
|
+
wm.restoreTo(id, session.startRestoreBounds ?? session.startBounds);
|
|
919
|
+
wm.snap(id, session.startZone);
|
|
920
|
+
} else {
|
|
921
|
+
wm.move(id, session.startBounds.x, session.startBounds.y);
|
|
922
|
+
}
|
|
1033
923
|
}
|
|
1034
924
|
return;
|
|
1035
925
|
}
|
|
@@ -1039,20 +929,37 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1039
929
|
}
|
|
1040
930
|
}
|
|
1041
931
|
session.finish = finish;
|
|
1042
|
-
|
|
932
|
+
ctx.claimDrag(session);
|
|
1043
933
|
handle.setPointerCapture(event.pointerId);
|
|
1044
934
|
handle.addEventListener("pointermove", onMove);
|
|
1045
935
|
handle.addEventListener("pointerup", onUp);
|
|
1046
936
|
handle.addEventListener("pointercancel", onCancel);
|
|
1047
937
|
doc.addEventListener("keydown", onKeydown, true);
|
|
1048
|
-
}
|
|
1049
|
-
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
// src/dom/resize.ts
|
|
942
|
+
var RESIZE_DIRECTIONS = ["n", "e", "s", "w", "ne", "nw", "se", "sw"];
|
|
943
|
+
var RESIZE_CURSORS = {
|
|
944
|
+
n: "ns-resize",
|
|
945
|
+
s: "ns-resize",
|
|
946
|
+
e: "ew-resize",
|
|
947
|
+
w: "ew-resize",
|
|
948
|
+
ne: "nesw-resize",
|
|
949
|
+
sw: "nesw-resize",
|
|
950
|
+
nw: "nwse-resize",
|
|
951
|
+
se: "nwse-resize"
|
|
952
|
+
};
|
|
953
|
+
function createResizeStarter(ctx) {
|
|
954
|
+
const { wm, doc, view } = ctx;
|
|
955
|
+
return function startResize(id, direction, event) {
|
|
1050
956
|
const win = wm.get(id);
|
|
1051
|
-
if (!win?.resizable || event.button !== 0 ||
|
|
957
|
+
if (!win?.resizable || event.button !== 0 || ctx.currentDrag()) return;
|
|
1052
958
|
event.preventDefault();
|
|
1053
959
|
event.stopPropagation();
|
|
1054
960
|
const handleEl = event.currentTarget;
|
|
1055
|
-
const
|
|
961
|
+
const releaseRect = ctx.trackRect();
|
|
962
|
+
const startPoint = ctx.toLocal(event);
|
|
1056
963
|
const start = win.bounds;
|
|
1057
964
|
const minSize = win.minSize;
|
|
1058
965
|
const maxSize = win.maxSize;
|
|
@@ -1060,8 +967,8 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1060
967
|
let pendingX = 0;
|
|
1061
968
|
let pendingY = 0;
|
|
1062
969
|
let hasPending = false;
|
|
1063
|
-
const
|
|
1064
|
-
if (
|
|
970
|
+
const el = ctx.windowElement(id);
|
|
971
|
+
if (el) el.dataset.wmResizing = direction;
|
|
1065
972
|
function clampWidth(width) {
|
|
1066
973
|
return clamp(width, minSize.width, maxSize ? maxSize.width : Number.POSITIVE_INFINITY);
|
|
1067
974
|
}
|
|
@@ -1089,15 +996,16 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1089
996
|
}
|
|
1090
997
|
function onMove(moveEvent) {
|
|
1091
998
|
if (moveEvent.pointerId !== event.pointerId) return;
|
|
1092
|
-
const movePoint =
|
|
999
|
+
const movePoint = ctx.toLocal(moveEvent);
|
|
1093
1000
|
pendingX = movePoint.x;
|
|
1094
1001
|
pendingY = movePoint.y;
|
|
1095
1002
|
hasPending = true;
|
|
1096
|
-
if (raf === 0) raf = view
|
|
1003
|
+
if (raf === 0) raf = view.requestAnimationFrame(flush);
|
|
1097
1004
|
}
|
|
1098
1005
|
function finish(cancelled) {
|
|
1099
|
-
if (raf !== 0) view
|
|
1006
|
+
if (raf !== 0) view.cancelAnimationFrame(raf);
|
|
1100
1007
|
if (hasPending && !cancelled) flush();
|
|
1008
|
+
releaseRect();
|
|
1101
1009
|
handleEl.removeEventListener("pointermove", onMove);
|
|
1102
1010
|
handleEl.removeEventListener("pointerup", onUp);
|
|
1103
1011
|
handleEl.removeEventListener("pointercancel", onCancelPointer);
|
|
@@ -1105,7 +1013,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1105
1013
|
if (handleEl.hasPointerCapture(event.pointerId)) {
|
|
1106
1014
|
handleEl.releasePointerCapture(event.pointerId);
|
|
1107
1015
|
}
|
|
1108
|
-
if (
|
|
1016
|
+
if (el) delete el.dataset.wmResizing;
|
|
1109
1017
|
if (cancelled) wm.resize(id, start);
|
|
1110
1018
|
}
|
|
1111
1019
|
function onUp(upEvent) {
|
|
@@ -1127,6 +1035,220 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1127
1035
|
handleEl.addEventListener("pointerup", onUp);
|
|
1128
1036
|
handleEl.addEventListener("pointercancel", onCancelPointer);
|
|
1129
1037
|
doc.addEventListener("keydown", onKeydown, true);
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
1040
|
+
function createResizeHandles(doc, edge, corner) {
|
|
1041
|
+
const base = "position:absolute;touch-action:none;user-select:none;-webkit-user-select:none;";
|
|
1042
|
+
const styles = {
|
|
1043
|
+
n: `top:${-edge / 2}px;left:${corner}px;right:${corner}px;height:${edge}px`,
|
|
1044
|
+
s: `bottom:${-edge / 2}px;left:${corner}px;right:${corner}px;height:${edge}px`,
|
|
1045
|
+
e: `right:${-edge / 2}px;top:${corner}px;bottom:${corner}px;width:${edge}px`,
|
|
1046
|
+
w: `left:${-edge / 2}px;top:${corner}px;bottom:${corner}px;width:${edge}px`,
|
|
1047
|
+
ne: `top:${-edge / 2}px;right:${-edge / 2}px;width:${corner}px;height:${corner}px`,
|
|
1048
|
+
nw: `top:${-edge / 2}px;left:${-edge / 2}px;width:${corner}px;height:${corner}px`,
|
|
1049
|
+
se: `bottom:${-edge / 2}px;right:${-edge / 2}px;width:${corner}px;height:${corner}px`,
|
|
1050
|
+
sw: `bottom:${-edge / 2}px;left:${-edge / 2}px;width:${corner}px;height:${corner}px`
|
|
1051
|
+
};
|
|
1052
|
+
return RESIZE_DIRECTIONS.map((direction) => {
|
|
1053
|
+
const element = doc.createElement("div");
|
|
1054
|
+
element.dataset.wmResize = direction;
|
|
1055
|
+
element.setAttribute("aria-hidden", "true");
|
|
1056
|
+
element.style.cssText = `${base}${styles[direction]};cursor:${RESIZE_CURSORS[direction]}`;
|
|
1057
|
+
return { element, direction };
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
// src/dom/controller.ts
|
|
1062
|
+
function attachDesktop(wm, element, options = {}) {
|
|
1063
|
+
const doc = element.ownerDocument;
|
|
1064
|
+
const view = windowOf(element);
|
|
1065
|
+
const coarsePointer = typeof view.matchMedia === "function" && view.matchMedia("(pointer: coarse)").matches;
|
|
1066
|
+
const snapEnabled = options.snap !== false;
|
|
1067
|
+
const snapOptions = typeof options.snap === "object" ? options.snap : {};
|
|
1068
|
+
const snapPreviewEnabled = snapOptions.preview !== false;
|
|
1069
|
+
const topEdge = snapOptions.topEdge ?? "maximize";
|
|
1070
|
+
const keyboardEnabled = options.keyboard !== false;
|
|
1071
|
+
const keyboardOptions = typeof options.keyboard === "object" ? options.keyboard : {};
|
|
1072
|
+
const moveStep = keyboardOptions.moveStep ?? 16;
|
|
1073
|
+
const cycleEnabled = keyboardOptions.cycle !== false;
|
|
1074
|
+
const hitEdge = options.hitAreas?.edge ?? (coarsePointer ? 16 : 8);
|
|
1075
|
+
const hitCorner = options.hitAreas?.corner ?? (coarsePointer ? 24 : 12);
|
|
1076
|
+
element.dataset.wmDesktop = "";
|
|
1077
|
+
if (view.getComputedStyle(element).position === "static") {
|
|
1078
|
+
element.style.position = "relative";
|
|
1079
|
+
}
|
|
1080
|
+
const registry = /* @__PURE__ */ new Map();
|
|
1081
|
+
const cleanup = [];
|
|
1082
|
+
let lastOrder = null;
|
|
1083
|
+
let lastFocused = null;
|
|
1084
|
+
let drag = null;
|
|
1085
|
+
let cachedRect = null;
|
|
1086
|
+
let rectUsers = 0;
|
|
1087
|
+
let announcer = null;
|
|
1088
|
+
if (options.announce !== false) {
|
|
1089
|
+
announcer = createAnnouncer(
|
|
1090
|
+
wm,
|
|
1091
|
+
element,
|
|
1092
|
+
typeof options.announce === "object" ? options.announce : {}
|
|
1093
|
+
);
|
|
1094
|
+
cleanup.push(() => announcer?.destroy());
|
|
1095
|
+
}
|
|
1096
|
+
let preview = null;
|
|
1097
|
+
function showPreview(bounds) {
|
|
1098
|
+
if (!snapPreviewEnabled) return;
|
|
1099
|
+
if (!preview) {
|
|
1100
|
+
preview = doc.createElement("div");
|
|
1101
|
+
preview.dataset.wmSnapPreview = "";
|
|
1102
|
+
preview.style.cssText = "position:absolute;left:0;top:0;pointer-events:none;display:none;z-index:2147483646";
|
|
1103
|
+
element.append(preview);
|
|
1104
|
+
}
|
|
1105
|
+
preview.style.display = "block";
|
|
1106
|
+
preview.style.transform = `translate3d(${bounds.x}px, ${bounds.y}px, 0)`;
|
|
1107
|
+
preview.style.width = `${bounds.width}px`;
|
|
1108
|
+
preview.style.height = `${bounds.height}px`;
|
|
1109
|
+
}
|
|
1110
|
+
function hidePreview() {
|
|
1111
|
+
if (preview) preview.style.display = "none";
|
|
1112
|
+
}
|
|
1113
|
+
const ctx = {
|
|
1114
|
+
wm,
|
|
1115
|
+
doc,
|
|
1116
|
+
view,
|
|
1117
|
+
toLocal(event) {
|
|
1118
|
+
const rect = cachedRect ?? element.getBoundingClientRect();
|
|
1119
|
+
return { x: event.clientX - rect.left, y: event.clientY - rect.top };
|
|
1120
|
+
},
|
|
1121
|
+
trackRect() {
|
|
1122
|
+
if (rectUsers === 0) {
|
|
1123
|
+
const rect = element.getBoundingClientRect();
|
|
1124
|
+
cachedRect = { left: rect.left, top: rect.top };
|
|
1125
|
+
}
|
|
1126
|
+
rectUsers += 1;
|
|
1127
|
+
let released = false;
|
|
1128
|
+
return () => {
|
|
1129
|
+
if (released) return;
|
|
1130
|
+
released = true;
|
|
1131
|
+
rectUsers -= 1;
|
|
1132
|
+
if (rectUsers === 0) cachedRect = null;
|
|
1133
|
+
};
|
|
1134
|
+
},
|
|
1135
|
+
windowElement: (id) => registry.get(id)?.element,
|
|
1136
|
+
showPreview,
|
|
1137
|
+
hidePreview,
|
|
1138
|
+
snapEnabled,
|
|
1139
|
+
snapDetect: {
|
|
1140
|
+
threshold: snapOptions.threshold ?? (coarsePointer ? 20 : 12),
|
|
1141
|
+
cornerSize: snapOptions.cornerSize ?? (coarsePointer ? 96 : 64)
|
|
1142
|
+
},
|
|
1143
|
+
topEdge,
|
|
1144
|
+
hitEdge,
|
|
1145
|
+
hitCorner,
|
|
1146
|
+
currentDrag: () => drag,
|
|
1147
|
+
claimDrag(session) {
|
|
1148
|
+
drag = session;
|
|
1149
|
+
},
|
|
1150
|
+
releaseDrag(session) {
|
|
1151
|
+
if (drag === session) drag = null;
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
const startDrag = createDragStarter(ctx);
|
|
1155
|
+
const startResize = createResizeStarter(ctx);
|
|
1156
|
+
if (options.autoViewport !== false) {
|
|
1157
|
+
const applyViewport = () => wm.setViewport({ width: element.clientWidth, height: element.clientHeight });
|
|
1158
|
+
applyViewport();
|
|
1159
|
+
const observer = new ResizeObserver(applyViewport);
|
|
1160
|
+
observer.observe(element);
|
|
1161
|
+
cleanup.push(() => observer.disconnect());
|
|
1162
|
+
}
|
|
1163
|
+
function syncWindow(attached, win, zIndex) {
|
|
1164
|
+
const el = attached.element;
|
|
1165
|
+
const firstSync = attached.lastState === null;
|
|
1166
|
+
if (firstSync) el.style.transition = "none";
|
|
1167
|
+
if (attached.lastState !== win) {
|
|
1168
|
+
el.style.transform = `translate3d(${win.bounds.x}px, ${win.bounds.y}px, 0)`;
|
|
1169
|
+
el.style.width = `${win.bounds.width}px`;
|
|
1170
|
+
el.style.height = `${win.bounds.height}px`;
|
|
1171
|
+
el.dataset.wmStage = win.stage;
|
|
1172
|
+
el.dataset.wmLayer = win.layer;
|
|
1173
|
+
el.hidden = win.stage === "minimized";
|
|
1174
|
+
el.setAttribute("aria-label", win.title);
|
|
1175
|
+
if (win.layer === "modal") el.setAttribute("aria-modal", "true");
|
|
1176
|
+
else el.removeAttribute("aria-modal");
|
|
1177
|
+
for (const handle of attached.handles) {
|
|
1178
|
+
handle.style.display = win.resizable && win.stage === "normal" ? "" : "none";
|
|
1179
|
+
}
|
|
1180
|
+
attached.lastState = win;
|
|
1181
|
+
}
|
|
1182
|
+
if (attached.lastZ !== zIndex) {
|
|
1183
|
+
el.style.zIndex = String(zIndex + 1);
|
|
1184
|
+
attached.lastZ = zIndex;
|
|
1185
|
+
}
|
|
1186
|
+
if (firstSync) {
|
|
1187
|
+
void el.offsetWidth;
|
|
1188
|
+
el.style.transition = "";
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
function syncAll() {
|
|
1192
|
+
const state = wm.getState();
|
|
1193
|
+
const orderChanged = state.order !== lastOrder;
|
|
1194
|
+
state.order.forEach((id, index) => {
|
|
1195
|
+
const attached = registry.get(id);
|
|
1196
|
+
const win = state.windows[id];
|
|
1197
|
+
if (!attached || !win) return;
|
|
1198
|
+
if (orderChanged || attached.lastState !== win) syncWindow(attached, win, index);
|
|
1199
|
+
});
|
|
1200
|
+
if (state.focusedId !== lastFocused) {
|
|
1201
|
+
if (lastFocused) {
|
|
1202
|
+
const prev = registry.get(lastFocused);
|
|
1203
|
+
if (prev) delete prev.element.dataset.wmFocused;
|
|
1204
|
+
}
|
|
1205
|
+
if (state.focusedId) {
|
|
1206
|
+
const next = registry.get(state.focusedId);
|
|
1207
|
+
if (next) next.element.dataset.wmFocused = "";
|
|
1208
|
+
}
|
|
1209
|
+
lastFocused = state.focusedId;
|
|
1210
|
+
}
|
|
1211
|
+
lastOrder = state.order;
|
|
1212
|
+
}
|
|
1213
|
+
cleanup.push(wm.subscribe(syncAll));
|
|
1214
|
+
cleanup.push(
|
|
1215
|
+
wm.on("focus", ({ window: win }) => {
|
|
1216
|
+
const attached = registry.get(win.id);
|
|
1217
|
+
if (!attached) return;
|
|
1218
|
+
if (!attached.element.contains(doc.activeElement)) {
|
|
1219
|
+
attached.element.focus({ preventScroll: true });
|
|
1220
|
+
}
|
|
1221
|
+
})
|
|
1222
|
+
);
|
|
1223
|
+
cleanup.push(
|
|
1224
|
+
wm.on("modalblocked", ({ window: win }) => {
|
|
1225
|
+
const attached = registry.get(win.id);
|
|
1226
|
+
if (!attached) return;
|
|
1227
|
+
delete attached.element.dataset.wmFlash;
|
|
1228
|
+
void attached.element.offsetWidth;
|
|
1229
|
+
attached.element.dataset.wmFlash = "";
|
|
1230
|
+
})
|
|
1231
|
+
);
|
|
1232
|
+
cleanup.push(
|
|
1233
|
+
wm.on("stage", ({ window: win, previous }) => {
|
|
1234
|
+
if (win.stage !== "minimized" || previous === "minimized") return;
|
|
1235
|
+
const attached = registry.get(win.id);
|
|
1236
|
+
const target = options.minimizeTarget?.(win);
|
|
1237
|
+
if (attached && target) flipToTarget(attached.element, target);
|
|
1238
|
+
})
|
|
1239
|
+
);
|
|
1240
|
+
if (keyboardEnabled && cycleEnabled) {
|
|
1241
|
+
const onDesktopKeydown = (event) => {
|
|
1242
|
+
if (event.key === "F6") {
|
|
1243
|
+
event.preventDefault();
|
|
1244
|
+
wm.cycleFocus(event.shiftKey ? -1 : 1);
|
|
1245
|
+
}
|
|
1246
|
+
};
|
|
1247
|
+
element.addEventListener("keydown", onDesktopKeydown);
|
|
1248
|
+
cleanup.push(() => element.removeEventListener("keydown", onDesktopKeydown));
|
|
1249
|
+
}
|
|
1250
|
+
function endDrag(cancelled) {
|
|
1251
|
+
if (drag) drag.finish(cancelled);
|
|
1130
1252
|
}
|
|
1131
1253
|
function attachWindow(id, windowElement, windowOptions = {}) {
|
|
1132
1254
|
const win = wm.get(id);
|
|
@@ -1137,6 +1259,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1137
1259
|
handle: null,
|
|
1138
1260
|
handles: [],
|
|
1139
1261
|
lastState: null,
|
|
1262
|
+
lastZ: -1,
|
|
1140
1263
|
cleanup: []
|
|
1141
1264
|
};
|
|
1142
1265
|
windowElement.dataset.wmWindow = id;
|
|
@@ -1189,24 +1312,11 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1189
1312
|
attached.cleanup.push(() => handle.removeEventListener("dblclick", onDoubleClick));
|
|
1190
1313
|
}
|
|
1191
1314
|
if (windowOptions.resizeHandles !== false) {
|
|
1192
|
-
for (const direction of
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
const size = 8;
|
|
1198
|
-
const corner = 12;
|
|
1199
|
-
const styles = {
|
|
1200
|
-
n: `top:${-size / 2}px;left:${corner}px;right:${corner}px;height:${size}px`,
|
|
1201
|
-
s: `bottom:${-size / 2}px;left:${corner}px;right:${corner}px;height:${size}px`,
|
|
1202
|
-
e: `right:${-size / 2}px;top:${corner}px;bottom:${corner}px;width:${size}px`,
|
|
1203
|
-
w: `left:${-size / 2}px;top:${corner}px;bottom:${corner}px;width:${size}px`,
|
|
1204
|
-
ne: `top:${-size / 2}px;right:${-size / 2}px;width:${corner}px;height:${corner}px`,
|
|
1205
|
-
nw: `top:${-size / 2}px;left:${-size / 2}px;width:${corner}px;height:${corner}px`,
|
|
1206
|
-
se: `bottom:${-size / 2}px;right:${-size / 2}px;width:${corner}px;height:${corner}px`,
|
|
1207
|
-
sw: `bottom:${-size / 2}px;left:${-size / 2}px;width:${corner}px;height:${corner}px`
|
|
1208
|
-
};
|
|
1209
|
-
resizeHandle.style.cssText = `${base}${styles[direction]};cursor:${RESIZE_CURSORS[direction]}`;
|
|
1315
|
+
for (const { element: resizeHandle, direction } of createResizeHandles(
|
|
1316
|
+
doc,
|
|
1317
|
+
hitEdge,
|
|
1318
|
+
hitCorner
|
|
1319
|
+
)) {
|
|
1210
1320
|
const onResizeDown = (event) => startResize(id, direction, event);
|
|
1211
1321
|
resizeHandle.addEventListener("pointerdown", onResizeDown);
|
|
1212
1322
|
attached.cleanup.push(() => resizeHandle.removeEventListener("pointerdown", onResizeDown));
|
|
@@ -1264,16 +1374,25 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1264
1374
|
};
|
|
1265
1375
|
windowElement.addEventListener("keydown", onModalTrap);
|
|
1266
1376
|
attached.cleanup.push(() => windowElement.removeEventListener("keydown", onModalTrap));
|
|
1267
|
-
|
|
1268
|
-
lastOrder = null;
|
|
1269
|
-
lastFocused = null;
|
|
1270
|
-
syncAll();
|
|
1271
|
-
return () => {
|
|
1377
|
+
const detach = () => {
|
|
1272
1378
|
if (drag?.id === id) endDrag(true);
|
|
1273
1379
|
for (const dispose of attached.cleanup) dispose();
|
|
1274
1380
|
for (const resizeHandle of attached.handles) resizeHandle.remove();
|
|
1275
1381
|
registry.delete(id);
|
|
1276
1382
|
};
|
|
1383
|
+
if (windowOptions.removeOnClose) {
|
|
1384
|
+
const stopOnClose = wm.on("close", ({ window: closed }) => {
|
|
1385
|
+
if (closed.id !== id) return;
|
|
1386
|
+
detach();
|
|
1387
|
+
windowElement.remove();
|
|
1388
|
+
});
|
|
1389
|
+
attached.cleanup.push(stopOnClose);
|
|
1390
|
+
}
|
|
1391
|
+
registry.set(id, attached);
|
|
1392
|
+
lastOrder = null;
|
|
1393
|
+
lastFocused = null;
|
|
1394
|
+
syncAll();
|
|
1395
|
+
return detach;
|
|
1277
1396
|
}
|
|
1278
1397
|
return {
|
|
1279
1398
|
element,
|
|
@@ -1292,6 +1411,8 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1292
1411
|
}
|
|
1293
1412
|
};
|
|
1294
1413
|
}
|
|
1414
|
+
|
|
1415
|
+
// src/dom/binder.ts
|
|
1295
1416
|
function createDesktopBinder(wm, options = {}) {
|
|
1296
1417
|
let controller = null;
|
|
1297
1418
|
const entries = /* @__PURE__ */ new Set();
|
|
@@ -1345,5 +1466,5 @@ exports.detectSnapZone = detectSnapZone;
|
|
|
1345
1466
|
exports.flipToTarget = flipToTarget;
|
|
1346
1467
|
exports.prefersReducedMotion = prefersReducedMotion;
|
|
1347
1468
|
exports.zoneBounds = zoneBounds;
|
|
1348
|
-
//# sourceMappingURL=chunk-
|
|
1349
|
-
//# sourceMappingURL=chunk-
|
|
1469
|
+
//# sourceMappingURL=chunk-KQCVZ2W7.cjs.map
|
|
1470
|
+
//# sourceMappingURL=chunk-KQCVZ2W7.cjs.map
|