@surdeddd/wmkit 0.1.1 → 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 +3 -7
- package/README.ru.md +3 -7
- package/dist/{controller-BfUF1k04.d.cts → binder-BY-saDUB.d.cts} +9 -3
- package/dist/{controller-1uedRvQw.d.ts → binder-D9UEE1SM.d.ts} +9 -3
- package/dist/{chunk-N5KNWRKU.js → chunk-2TVOEDRG.js} +298 -211
- package/dist/chunk-2TVOEDRG.js.map +1 -0
- package/dist/{chunk-TXINVEK3.cjs → chunk-KQCVZ2W7.cjs} +298 -211
- 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-BYx7gCuT.d.cts → types-Bkrq2djr.d.cts} +1 -1
- package/dist/{types-BYx7gCuT.d.ts → types-Bkrq2djr.d.ts} +1 -1
- 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 +1 -1
- package/dist/chunk-N5KNWRKU.js.map +0 -1
- package/dist/chunk-TXINVEK3.cjs.map +0 -1
|
@@ -774,175 +774,25 @@ function createAnnouncer(wm, container, messages = {}) {
|
|
|
774
774
|
};
|
|
775
775
|
}
|
|
776
776
|
|
|
777
|
-
// src/dom/
|
|
778
|
-
var RESIZE_DIRECTIONS = ["n", "e", "s", "w", "ne", "nw", "se", "sw"];
|
|
779
|
-
var RESIZE_CURSORS = {
|
|
780
|
-
n: "ns-resize",
|
|
781
|
-
s: "ns-resize",
|
|
782
|
-
e: "ew-resize",
|
|
783
|
-
w: "ew-resize",
|
|
784
|
-
ne: "nesw-resize",
|
|
785
|
-
sw: "nesw-resize",
|
|
786
|
-
nw: "nwse-resize",
|
|
787
|
-
se: "nwse-resize"
|
|
788
|
-
};
|
|
777
|
+
// src/dom/shared.ts
|
|
789
778
|
var INTERACTIVE_SELECTOR = "button, input, select, textarea, a[href], [contenteditable], [data-wm-close], [data-wm-minimize], [data-wm-maximize]";
|
|
790
779
|
function windowOf(element) {
|
|
791
780
|
const view = element.ownerDocument.defaultView;
|
|
792
781
|
if (!view) throw new Error("wmkit: desktop element is not attached to a document");
|
|
793
782
|
return view;
|
|
794
783
|
}
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
const
|
|
799
|
-
|
|
800
|
-
const snapPreviewEnabled = snapOptions.preview !== false;
|
|
801
|
-
const topEdge = snapOptions.topEdge ?? "maximize";
|
|
802
|
-
const keyboardEnabled = options.keyboard !== false;
|
|
803
|
-
const keyboardOptions = typeof options.keyboard === "object" ? options.keyboard : {};
|
|
804
|
-
const moveStep = keyboardOptions.moveStep ?? 16;
|
|
805
|
-
const cycleEnabled = keyboardOptions.cycle !== false;
|
|
806
|
-
element.dataset.wmDesktop = "";
|
|
807
|
-
if (view.getComputedStyle(element).position === "static") {
|
|
808
|
-
element.style.position = "relative";
|
|
809
|
-
}
|
|
810
|
-
const registry = /* @__PURE__ */ new Map();
|
|
811
|
-
const cleanup = [];
|
|
812
|
-
let lastOrder = null;
|
|
813
|
-
let lastFocused = null;
|
|
814
|
-
let drag = null;
|
|
815
|
-
let announcer = null;
|
|
816
|
-
if (options.announce !== false) {
|
|
817
|
-
announcer = createAnnouncer(
|
|
818
|
-
wm,
|
|
819
|
-
element,
|
|
820
|
-
typeof options.announce === "object" ? options.announce : {}
|
|
821
|
-
);
|
|
822
|
-
cleanup.push(() => announcer?.destroy());
|
|
823
|
-
}
|
|
824
|
-
let preview = null;
|
|
825
|
-
function showPreview(bounds) {
|
|
826
|
-
if (!snapPreviewEnabled) return;
|
|
827
|
-
if (!preview) {
|
|
828
|
-
preview = doc.createElement("div");
|
|
829
|
-
preview.dataset.wmSnapPreview = "";
|
|
830
|
-
preview.style.cssText = "position:absolute;left:0;top:0;pointer-events:none;display:none;z-index:2147483646";
|
|
831
|
-
element.append(preview);
|
|
832
|
-
}
|
|
833
|
-
preview.style.display = "block";
|
|
834
|
-
preview.style.transform = `translate3d(${bounds.x}px, ${bounds.y}px, 0)`;
|
|
835
|
-
preview.style.width = `${bounds.width}px`;
|
|
836
|
-
preview.style.height = `${bounds.height}px`;
|
|
837
|
-
}
|
|
838
|
-
function hidePreview() {
|
|
839
|
-
if (preview) preview.style.display = "none";
|
|
840
|
-
}
|
|
841
|
-
if (options.autoViewport !== false) {
|
|
842
|
-
const applyViewport = () => wm.setViewport({ width: element.clientWidth, height: element.clientHeight });
|
|
843
|
-
applyViewport();
|
|
844
|
-
const observer = new ResizeObserver(applyViewport);
|
|
845
|
-
observer.observe(element);
|
|
846
|
-
cleanup.push(() => observer.disconnect());
|
|
847
|
-
}
|
|
848
|
-
function syncWindow(attached, win, zIndex) {
|
|
849
|
-
const el = attached.element;
|
|
850
|
-
const firstSync = attached.lastState === null;
|
|
851
|
-
if (firstSync) el.style.transition = "none";
|
|
852
|
-
if (attached.lastState !== win) {
|
|
853
|
-
el.style.transform = `translate3d(${win.bounds.x}px, ${win.bounds.y}px, 0)`;
|
|
854
|
-
el.style.width = `${win.bounds.width}px`;
|
|
855
|
-
el.style.height = `${win.bounds.height}px`;
|
|
856
|
-
el.dataset.wmStage = win.stage;
|
|
857
|
-
el.dataset.wmLayer = win.layer;
|
|
858
|
-
el.hidden = win.stage === "minimized";
|
|
859
|
-
el.setAttribute("aria-label", win.title);
|
|
860
|
-
if (win.layer === "modal") el.setAttribute("aria-modal", "true");
|
|
861
|
-
else el.removeAttribute("aria-modal");
|
|
862
|
-
for (const handle of attached.handles) {
|
|
863
|
-
handle.style.display = win.resizable && win.stage === "normal" ? "" : "none";
|
|
864
|
-
}
|
|
865
|
-
attached.lastState = win;
|
|
866
|
-
}
|
|
867
|
-
el.style.zIndex = String(zIndex + 1);
|
|
868
|
-
if (firstSync) {
|
|
869
|
-
void el.offsetWidth;
|
|
870
|
-
el.style.transition = "";
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
function syncAll() {
|
|
874
|
-
const state = wm.getState();
|
|
875
|
-
const orderChanged = state.order !== lastOrder;
|
|
876
|
-
state.order.forEach((id, index) => {
|
|
877
|
-
const attached = registry.get(id);
|
|
878
|
-
const win = state.windows[id];
|
|
879
|
-
if (!attached || !win) return;
|
|
880
|
-
if (orderChanged || attached.lastState !== win) syncWindow(attached, win, index);
|
|
881
|
-
});
|
|
882
|
-
if (state.focusedId !== lastFocused) {
|
|
883
|
-
if (lastFocused) {
|
|
884
|
-
const prev = registry.get(lastFocused);
|
|
885
|
-
if (prev) delete prev.element.dataset.wmFocused;
|
|
886
|
-
}
|
|
887
|
-
if (state.focusedId) {
|
|
888
|
-
const next = registry.get(state.focusedId);
|
|
889
|
-
if (next) next.element.dataset.wmFocused = "";
|
|
890
|
-
}
|
|
891
|
-
lastFocused = state.focusedId;
|
|
892
|
-
}
|
|
893
|
-
lastOrder = state.order;
|
|
894
|
-
}
|
|
895
|
-
cleanup.push(wm.subscribe(syncAll));
|
|
896
|
-
cleanup.push(
|
|
897
|
-
wm.on("focus", ({ window: win }) => {
|
|
898
|
-
const attached = registry.get(win.id);
|
|
899
|
-
if (!attached) return;
|
|
900
|
-
if (!attached.element.contains(doc.activeElement)) {
|
|
901
|
-
attached.element.focus({ preventScroll: true });
|
|
902
|
-
}
|
|
903
|
-
})
|
|
904
|
-
);
|
|
905
|
-
cleanup.push(
|
|
906
|
-
wm.on("modalblocked", ({ window: win }) => {
|
|
907
|
-
const attached = registry.get(win.id);
|
|
908
|
-
if (!attached) return;
|
|
909
|
-
delete attached.element.dataset.wmFlash;
|
|
910
|
-
void attached.element.offsetWidth;
|
|
911
|
-
attached.element.dataset.wmFlash = "";
|
|
912
|
-
})
|
|
913
|
-
);
|
|
914
|
-
cleanup.push(
|
|
915
|
-
wm.on("stage", ({ window: win, previous }) => {
|
|
916
|
-
if (win.stage !== "minimized" || previous === "minimized") return;
|
|
917
|
-
const attached = registry.get(win.id);
|
|
918
|
-
const target = options.minimizeTarget?.(win);
|
|
919
|
-
if (attached && target) flipToTarget(attached.element, target);
|
|
920
|
-
})
|
|
921
|
-
);
|
|
922
|
-
if (keyboardEnabled && cycleEnabled) {
|
|
923
|
-
const onDesktopKeydown = (event) => {
|
|
924
|
-
if (event.key === "F6") {
|
|
925
|
-
event.preventDefault();
|
|
926
|
-
wm.cycleFocus(event.shiftKey ? -1 : 1);
|
|
927
|
-
}
|
|
928
|
-
};
|
|
929
|
-
element.addEventListener("keydown", onDesktopKeydown);
|
|
930
|
-
cleanup.push(() => element.removeEventListener("keydown", onDesktopKeydown));
|
|
931
|
-
}
|
|
932
|
-
function desktopPoint(event) {
|
|
933
|
-
const rect = element.getBoundingClientRect();
|
|
934
|
-
return { x: event.clientX - rect.left, y: event.clientY - rect.top };
|
|
935
|
-
}
|
|
936
|
-
function endDrag(cancelled) {
|
|
937
|
-
if (drag) drag.finish(cancelled);
|
|
938
|
-
}
|
|
939
|
-
function startDrag(id, handle, event) {
|
|
784
|
+
|
|
785
|
+
// src/dom/drag.ts
|
|
786
|
+
function createDragStarter(ctx) {
|
|
787
|
+
const { wm, doc, view } = ctx;
|
|
788
|
+
return function startDrag(id, handle, event) {
|
|
940
789
|
const win = wm.get(id);
|
|
941
|
-
if (!win?.draggable || event.button !== 0 ||
|
|
790
|
+
if (!win?.draggable || event.button !== 0 || ctx.currentDrag()) return;
|
|
942
791
|
const target = event.target;
|
|
943
792
|
if (target?.closest(INTERACTIVE_SELECTOR)) return;
|
|
944
793
|
event.preventDefault();
|
|
945
|
-
const
|
|
794
|
+
const releaseRect = ctx.trackRect();
|
|
795
|
+
const point = ctx.toLocal(event);
|
|
946
796
|
const startBounds = win.bounds;
|
|
947
797
|
const session = {
|
|
948
798
|
id,
|
|
@@ -964,10 +814,9 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
964
814
|
finish: () => {
|
|
965
815
|
}
|
|
966
816
|
};
|
|
967
|
-
const
|
|
968
|
-
const el = attached?.element;
|
|
817
|
+
const el = ctx.windowElement(id);
|
|
969
818
|
function flush() {
|
|
970
|
-
if (!session.hasPending ||
|
|
819
|
+
if (!session.hasPending || ctx.currentDrag() !== session) return;
|
|
971
820
|
session.hasPending = false;
|
|
972
821
|
session.raf = 0;
|
|
973
822
|
const current = wm.get(id);
|
|
@@ -991,32 +840,35 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
991
840
|
return;
|
|
992
841
|
}
|
|
993
842
|
wm.move(id, session.pendingX - session.grabDX, session.pendingY - session.grabDY);
|
|
994
|
-
if (snapEnabled && current.snappable) {
|
|
843
|
+
if (ctx.snapEnabled && current.snappable) {
|
|
995
844
|
const viewport = wm.getState().viewport;
|
|
996
|
-
const rawZone = detectSnapZone(session.pendingX, session.pendingY, viewport,
|
|
845
|
+
const rawZone = detectSnapZone(session.pendingX, session.pendingY, viewport, ctx.snapDetect);
|
|
997
846
|
let zone = rawZone;
|
|
998
847
|
if (rawZone === "top") {
|
|
999
|
-
if (topEdge === "maximize") zone = current.maximizable ? "maximize" : null;
|
|
1000
|
-
else if (topEdge === "none") zone = null;
|
|
848
|
+
if (ctx.topEdge === "maximize") zone = current.maximizable ? "maximize" : null;
|
|
849
|
+
else if (ctx.topEdge === "none") zone = null;
|
|
1001
850
|
}
|
|
1002
851
|
session.zone = zone;
|
|
1003
852
|
if (zone) {
|
|
1004
|
-
showPreview(
|
|
853
|
+
ctx.showPreview(
|
|
1005
854
|
zone === "maximize" ? { x: 0, y: 0, width: viewport.width, height: viewport.height } : zoneBounds(zone, viewport)
|
|
1006
855
|
);
|
|
1007
856
|
} else {
|
|
1008
|
-
hidePreview();
|
|
857
|
+
ctx.hidePreview();
|
|
1009
858
|
}
|
|
1010
859
|
}
|
|
1011
860
|
}
|
|
1012
861
|
function onMove(moveEvent) {
|
|
1013
862
|
if (moveEvent.pointerId !== session.pointerId) return;
|
|
1014
|
-
const movePoint =
|
|
863
|
+
const movePoint = ctx.toLocal(moveEvent);
|
|
1015
864
|
if (!session.moved) {
|
|
1016
865
|
const travelled = Math.abs(movePoint.x - (session.startBounds.x + session.grabDX)) + Math.abs(movePoint.y - (session.startBounds.y + session.grabDY));
|
|
1017
866
|
if (travelled < 3 && session.restored) return;
|
|
1018
867
|
session.moved = true;
|
|
1019
|
-
if (el)
|
|
868
|
+
if (el) {
|
|
869
|
+
el.dataset.wmDragging = "";
|
|
870
|
+
el.style.willChange = "transform";
|
|
871
|
+
}
|
|
1020
872
|
}
|
|
1021
873
|
session.pendingX = movePoint.x;
|
|
1022
874
|
session.pendingY = movePoint.y;
|
|
@@ -1038,10 +890,11 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1038
890
|
}
|
|
1039
891
|
}
|
|
1040
892
|
function finish(cancelled) {
|
|
1041
|
-
if (
|
|
1042
|
-
if (session.raf !== 0) view
|
|
893
|
+
if (ctx.currentDrag() !== session) return;
|
|
894
|
+
if (session.raf !== 0) view.cancelAnimationFrame(session.raf);
|
|
1043
895
|
if (session.hasPending && !cancelled) flush();
|
|
1044
|
-
|
|
896
|
+
ctx.releaseDrag(session);
|
|
897
|
+
releaseRect();
|
|
1045
898
|
handle.removeEventListener("pointermove", onMove);
|
|
1046
899
|
handle.removeEventListener("pointerup", onUp);
|
|
1047
900
|
handle.removeEventListener("pointercancel", onCancel);
|
|
@@ -1049,8 +902,11 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1049
902
|
if (handle.hasPointerCapture(session.pointerId)) {
|
|
1050
903
|
handle.releasePointerCapture(session.pointerId);
|
|
1051
904
|
}
|
|
1052
|
-
if (el)
|
|
1053
|
-
|
|
905
|
+
if (el) {
|
|
906
|
+
delete el.dataset.wmDragging;
|
|
907
|
+
el.style.willChange = "";
|
|
908
|
+
}
|
|
909
|
+
ctx.hidePreview();
|
|
1054
910
|
if (cancelled) {
|
|
1055
911
|
if (session.moved && session.restored) {
|
|
1056
912
|
if (session.startStage === "maximized") {
|
|
@@ -1071,20 +927,37 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1071
927
|
}
|
|
1072
928
|
}
|
|
1073
929
|
session.finish = finish;
|
|
1074
|
-
|
|
930
|
+
ctx.claimDrag(session);
|
|
1075
931
|
handle.setPointerCapture(event.pointerId);
|
|
1076
932
|
handle.addEventListener("pointermove", onMove);
|
|
1077
933
|
handle.addEventListener("pointerup", onUp);
|
|
1078
934
|
handle.addEventListener("pointercancel", onCancel);
|
|
1079
935
|
doc.addEventListener("keydown", onKeydown, true);
|
|
1080
|
-
}
|
|
1081
|
-
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
// src/dom/resize.ts
|
|
940
|
+
var RESIZE_DIRECTIONS = ["n", "e", "s", "w", "ne", "nw", "se", "sw"];
|
|
941
|
+
var RESIZE_CURSORS = {
|
|
942
|
+
n: "ns-resize",
|
|
943
|
+
s: "ns-resize",
|
|
944
|
+
e: "ew-resize",
|
|
945
|
+
w: "ew-resize",
|
|
946
|
+
ne: "nesw-resize",
|
|
947
|
+
sw: "nesw-resize",
|
|
948
|
+
nw: "nwse-resize",
|
|
949
|
+
se: "nwse-resize"
|
|
950
|
+
};
|
|
951
|
+
function createResizeStarter(ctx) {
|
|
952
|
+
const { wm, doc, view } = ctx;
|
|
953
|
+
return function startResize(id, direction, event) {
|
|
1082
954
|
const win = wm.get(id);
|
|
1083
|
-
if (!win?.resizable || event.button !== 0 ||
|
|
955
|
+
if (!win?.resizable || event.button !== 0 || ctx.currentDrag()) return;
|
|
1084
956
|
event.preventDefault();
|
|
1085
957
|
event.stopPropagation();
|
|
1086
958
|
const handleEl = event.currentTarget;
|
|
1087
|
-
const
|
|
959
|
+
const releaseRect = ctx.trackRect();
|
|
960
|
+
const startPoint = ctx.toLocal(event);
|
|
1088
961
|
const start = win.bounds;
|
|
1089
962
|
const minSize = win.minSize;
|
|
1090
963
|
const maxSize = win.maxSize;
|
|
@@ -1092,8 +965,8 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1092
965
|
let pendingX = 0;
|
|
1093
966
|
let pendingY = 0;
|
|
1094
967
|
let hasPending = false;
|
|
1095
|
-
const
|
|
1096
|
-
if (
|
|
968
|
+
const el = ctx.windowElement(id);
|
|
969
|
+
if (el) el.dataset.wmResizing = direction;
|
|
1097
970
|
function clampWidth(width) {
|
|
1098
971
|
return clamp(width, minSize.width, maxSize ? maxSize.width : Number.POSITIVE_INFINITY);
|
|
1099
972
|
}
|
|
@@ -1121,15 +994,16 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1121
994
|
}
|
|
1122
995
|
function onMove(moveEvent) {
|
|
1123
996
|
if (moveEvent.pointerId !== event.pointerId) return;
|
|
1124
|
-
const movePoint =
|
|
997
|
+
const movePoint = ctx.toLocal(moveEvent);
|
|
1125
998
|
pendingX = movePoint.x;
|
|
1126
999
|
pendingY = movePoint.y;
|
|
1127
1000
|
hasPending = true;
|
|
1128
|
-
if (raf === 0) raf = view
|
|
1001
|
+
if (raf === 0) raf = view.requestAnimationFrame(flush);
|
|
1129
1002
|
}
|
|
1130
1003
|
function finish(cancelled) {
|
|
1131
|
-
if (raf !== 0) view
|
|
1004
|
+
if (raf !== 0) view.cancelAnimationFrame(raf);
|
|
1132
1005
|
if (hasPending && !cancelled) flush();
|
|
1006
|
+
releaseRect();
|
|
1133
1007
|
handleEl.removeEventListener("pointermove", onMove);
|
|
1134
1008
|
handleEl.removeEventListener("pointerup", onUp);
|
|
1135
1009
|
handleEl.removeEventListener("pointercancel", onCancelPointer);
|
|
@@ -1137,7 +1011,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1137
1011
|
if (handleEl.hasPointerCapture(event.pointerId)) {
|
|
1138
1012
|
handleEl.releasePointerCapture(event.pointerId);
|
|
1139
1013
|
}
|
|
1140
|
-
if (
|
|
1014
|
+
if (el) delete el.dataset.wmResizing;
|
|
1141
1015
|
if (cancelled) wm.resize(id, start);
|
|
1142
1016
|
}
|
|
1143
1017
|
function onUp(upEvent) {
|
|
@@ -1159,6 +1033,220 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1159
1033
|
handleEl.addEventListener("pointerup", onUp);
|
|
1160
1034
|
handleEl.addEventListener("pointercancel", onCancelPointer);
|
|
1161
1035
|
doc.addEventListener("keydown", onKeydown, true);
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
function createResizeHandles(doc, edge, corner) {
|
|
1039
|
+
const base = "position:absolute;touch-action:none;user-select:none;-webkit-user-select:none;";
|
|
1040
|
+
const styles = {
|
|
1041
|
+
n: `top:${-edge / 2}px;left:${corner}px;right:${corner}px;height:${edge}px`,
|
|
1042
|
+
s: `bottom:${-edge / 2}px;left:${corner}px;right:${corner}px;height:${edge}px`,
|
|
1043
|
+
e: `right:${-edge / 2}px;top:${corner}px;bottom:${corner}px;width:${edge}px`,
|
|
1044
|
+
w: `left:${-edge / 2}px;top:${corner}px;bottom:${corner}px;width:${edge}px`,
|
|
1045
|
+
ne: `top:${-edge / 2}px;right:${-edge / 2}px;width:${corner}px;height:${corner}px`,
|
|
1046
|
+
nw: `top:${-edge / 2}px;left:${-edge / 2}px;width:${corner}px;height:${corner}px`,
|
|
1047
|
+
se: `bottom:${-edge / 2}px;right:${-edge / 2}px;width:${corner}px;height:${corner}px`,
|
|
1048
|
+
sw: `bottom:${-edge / 2}px;left:${-edge / 2}px;width:${corner}px;height:${corner}px`
|
|
1049
|
+
};
|
|
1050
|
+
return RESIZE_DIRECTIONS.map((direction) => {
|
|
1051
|
+
const element = doc.createElement("div");
|
|
1052
|
+
element.dataset.wmResize = direction;
|
|
1053
|
+
element.setAttribute("aria-hidden", "true");
|
|
1054
|
+
element.style.cssText = `${base}${styles[direction]};cursor:${RESIZE_CURSORS[direction]}`;
|
|
1055
|
+
return { element, direction };
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
// src/dom/controller.ts
|
|
1060
|
+
function attachDesktop(wm, element, options = {}) {
|
|
1061
|
+
const doc = element.ownerDocument;
|
|
1062
|
+
const view = windowOf(element);
|
|
1063
|
+
const coarsePointer = typeof view.matchMedia === "function" && view.matchMedia("(pointer: coarse)").matches;
|
|
1064
|
+
const snapEnabled = options.snap !== false;
|
|
1065
|
+
const snapOptions = typeof options.snap === "object" ? options.snap : {};
|
|
1066
|
+
const snapPreviewEnabled = snapOptions.preview !== false;
|
|
1067
|
+
const topEdge = snapOptions.topEdge ?? "maximize";
|
|
1068
|
+
const keyboardEnabled = options.keyboard !== false;
|
|
1069
|
+
const keyboardOptions = typeof options.keyboard === "object" ? options.keyboard : {};
|
|
1070
|
+
const moveStep = keyboardOptions.moveStep ?? 16;
|
|
1071
|
+
const cycleEnabled = keyboardOptions.cycle !== false;
|
|
1072
|
+
const hitEdge = options.hitAreas?.edge ?? (coarsePointer ? 16 : 8);
|
|
1073
|
+
const hitCorner = options.hitAreas?.corner ?? (coarsePointer ? 24 : 12);
|
|
1074
|
+
element.dataset.wmDesktop = "";
|
|
1075
|
+
if (view.getComputedStyle(element).position === "static") {
|
|
1076
|
+
element.style.position = "relative";
|
|
1077
|
+
}
|
|
1078
|
+
const registry = /* @__PURE__ */ new Map();
|
|
1079
|
+
const cleanup = [];
|
|
1080
|
+
let lastOrder = null;
|
|
1081
|
+
let lastFocused = null;
|
|
1082
|
+
let drag = null;
|
|
1083
|
+
let cachedRect = null;
|
|
1084
|
+
let rectUsers = 0;
|
|
1085
|
+
let announcer = null;
|
|
1086
|
+
if (options.announce !== false) {
|
|
1087
|
+
announcer = createAnnouncer(
|
|
1088
|
+
wm,
|
|
1089
|
+
element,
|
|
1090
|
+
typeof options.announce === "object" ? options.announce : {}
|
|
1091
|
+
);
|
|
1092
|
+
cleanup.push(() => announcer?.destroy());
|
|
1093
|
+
}
|
|
1094
|
+
let preview = null;
|
|
1095
|
+
function showPreview(bounds) {
|
|
1096
|
+
if (!snapPreviewEnabled) return;
|
|
1097
|
+
if (!preview) {
|
|
1098
|
+
preview = doc.createElement("div");
|
|
1099
|
+
preview.dataset.wmSnapPreview = "";
|
|
1100
|
+
preview.style.cssText = "position:absolute;left:0;top:0;pointer-events:none;display:none;z-index:2147483646";
|
|
1101
|
+
element.append(preview);
|
|
1102
|
+
}
|
|
1103
|
+
preview.style.display = "block";
|
|
1104
|
+
preview.style.transform = `translate3d(${bounds.x}px, ${bounds.y}px, 0)`;
|
|
1105
|
+
preview.style.width = `${bounds.width}px`;
|
|
1106
|
+
preview.style.height = `${bounds.height}px`;
|
|
1107
|
+
}
|
|
1108
|
+
function hidePreview() {
|
|
1109
|
+
if (preview) preview.style.display = "none";
|
|
1110
|
+
}
|
|
1111
|
+
const ctx = {
|
|
1112
|
+
wm,
|
|
1113
|
+
doc,
|
|
1114
|
+
view,
|
|
1115
|
+
toLocal(event) {
|
|
1116
|
+
const rect = cachedRect ?? element.getBoundingClientRect();
|
|
1117
|
+
return { x: event.clientX - rect.left, y: event.clientY - rect.top };
|
|
1118
|
+
},
|
|
1119
|
+
trackRect() {
|
|
1120
|
+
if (rectUsers === 0) {
|
|
1121
|
+
const rect = element.getBoundingClientRect();
|
|
1122
|
+
cachedRect = { left: rect.left, top: rect.top };
|
|
1123
|
+
}
|
|
1124
|
+
rectUsers += 1;
|
|
1125
|
+
let released = false;
|
|
1126
|
+
return () => {
|
|
1127
|
+
if (released) return;
|
|
1128
|
+
released = true;
|
|
1129
|
+
rectUsers -= 1;
|
|
1130
|
+
if (rectUsers === 0) cachedRect = null;
|
|
1131
|
+
};
|
|
1132
|
+
},
|
|
1133
|
+
windowElement: (id) => registry.get(id)?.element,
|
|
1134
|
+
showPreview,
|
|
1135
|
+
hidePreview,
|
|
1136
|
+
snapEnabled,
|
|
1137
|
+
snapDetect: {
|
|
1138
|
+
threshold: snapOptions.threshold ?? (coarsePointer ? 20 : 12),
|
|
1139
|
+
cornerSize: snapOptions.cornerSize ?? (coarsePointer ? 96 : 64)
|
|
1140
|
+
},
|
|
1141
|
+
topEdge,
|
|
1142
|
+
hitEdge,
|
|
1143
|
+
hitCorner,
|
|
1144
|
+
currentDrag: () => drag,
|
|
1145
|
+
claimDrag(session) {
|
|
1146
|
+
drag = session;
|
|
1147
|
+
},
|
|
1148
|
+
releaseDrag(session) {
|
|
1149
|
+
if (drag === session) drag = null;
|
|
1150
|
+
}
|
|
1151
|
+
};
|
|
1152
|
+
const startDrag = createDragStarter(ctx);
|
|
1153
|
+
const startResize = createResizeStarter(ctx);
|
|
1154
|
+
if (options.autoViewport !== false) {
|
|
1155
|
+
const applyViewport = () => wm.setViewport({ width: element.clientWidth, height: element.clientHeight });
|
|
1156
|
+
applyViewport();
|
|
1157
|
+
const observer = new ResizeObserver(applyViewport);
|
|
1158
|
+
observer.observe(element);
|
|
1159
|
+
cleanup.push(() => observer.disconnect());
|
|
1160
|
+
}
|
|
1161
|
+
function syncWindow(attached, win, zIndex) {
|
|
1162
|
+
const el = attached.element;
|
|
1163
|
+
const firstSync = attached.lastState === null;
|
|
1164
|
+
if (firstSync) el.style.transition = "none";
|
|
1165
|
+
if (attached.lastState !== win) {
|
|
1166
|
+
el.style.transform = `translate3d(${win.bounds.x}px, ${win.bounds.y}px, 0)`;
|
|
1167
|
+
el.style.width = `${win.bounds.width}px`;
|
|
1168
|
+
el.style.height = `${win.bounds.height}px`;
|
|
1169
|
+
el.dataset.wmStage = win.stage;
|
|
1170
|
+
el.dataset.wmLayer = win.layer;
|
|
1171
|
+
el.hidden = win.stage === "minimized";
|
|
1172
|
+
el.setAttribute("aria-label", win.title);
|
|
1173
|
+
if (win.layer === "modal") el.setAttribute("aria-modal", "true");
|
|
1174
|
+
else el.removeAttribute("aria-modal");
|
|
1175
|
+
for (const handle of attached.handles) {
|
|
1176
|
+
handle.style.display = win.resizable && win.stage === "normal" ? "" : "none";
|
|
1177
|
+
}
|
|
1178
|
+
attached.lastState = win;
|
|
1179
|
+
}
|
|
1180
|
+
if (attached.lastZ !== zIndex) {
|
|
1181
|
+
el.style.zIndex = String(zIndex + 1);
|
|
1182
|
+
attached.lastZ = zIndex;
|
|
1183
|
+
}
|
|
1184
|
+
if (firstSync) {
|
|
1185
|
+
void el.offsetWidth;
|
|
1186
|
+
el.style.transition = "";
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
function syncAll() {
|
|
1190
|
+
const state = wm.getState();
|
|
1191
|
+
const orderChanged = state.order !== lastOrder;
|
|
1192
|
+
state.order.forEach((id, index) => {
|
|
1193
|
+
const attached = registry.get(id);
|
|
1194
|
+
const win = state.windows[id];
|
|
1195
|
+
if (!attached || !win) return;
|
|
1196
|
+
if (orderChanged || attached.lastState !== win) syncWindow(attached, win, index);
|
|
1197
|
+
});
|
|
1198
|
+
if (state.focusedId !== lastFocused) {
|
|
1199
|
+
if (lastFocused) {
|
|
1200
|
+
const prev = registry.get(lastFocused);
|
|
1201
|
+
if (prev) delete prev.element.dataset.wmFocused;
|
|
1202
|
+
}
|
|
1203
|
+
if (state.focusedId) {
|
|
1204
|
+
const next = registry.get(state.focusedId);
|
|
1205
|
+
if (next) next.element.dataset.wmFocused = "";
|
|
1206
|
+
}
|
|
1207
|
+
lastFocused = state.focusedId;
|
|
1208
|
+
}
|
|
1209
|
+
lastOrder = state.order;
|
|
1210
|
+
}
|
|
1211
|
+
cleanup.push(wm.subscribe(syncAll));
|
|
1212
|
+
cleanup.push(
|
|
1213
|
+
wm.on("focus", ({ window: win }) => {
|
|
1214
|
+
const attached = registry.get(win.id);
|
|
1215
|
+
if (!attached) return;
|
|
1216
|
+
if (!attached.element.contains(doc.activeElement)) {
|
|
1217
|
+
attached.element.focus({ preventScroll: true });
|
|
1218
|
+
}
|
|
1219
|
+
})
|
|
1220
|
+
);
|
|
1221
|
+
cleanup.push(
|
|
1222
|
+
wm.on("modalblocked", ({ window: win }) => {
|
|
1223
|
+
const attached = registry.get(win.id);
|
|
1224
|
+
if (!attached) return;
|
|
1225
|
+
delete attached.element.dataset.wmFlash;
|
|
1226
|
+
void attached.element.offsetWidth;
|
|
1227
|
+
attached.element.dataset.wmFlash = "";
|
|
1228
|
+
})
|
|
1229
|
+
);
|
|
1230
|
+
cleanup.push(
|
|
1231
|
+
wm.on("stage", ({ window: win, previous }) => {
|
|
1232
|
+
if (win.stage !== "minimized" || previous === "minimized") return;
|
|
1233
|
+
const attached = registry.get(win.id);
|
|
1234
|
+
const target = options.minimizeTarget?.(win);
|
|
1235
|
+
if (attached && target) flipToTarget(attached.element, target);
|
|
1236
|
+
})
|
|
1237
|
+
);
|
|
1238
|
+
if (keyboardEnabled && cycleEnabled) {
|
|
1239
|
+
const onDesktopKeydown = (event) => {
|
|
1240
|
+
if (event.key === "F6") {
|
|
1241
|
+
event.preventDefault();
|
|
1242
|
+
wm.cycleFocus(event.shiftKey ? -1 : 1);
|
|
1243
|
+
}
|
|
1244
|
+
};
|
|
1245
|
+
element.addEventListener("keydown", onDesktopKeydown);
|
|
1246
|
+
cleanup.push(() => element.removeEventListener("keydown", onDesktopKeydown));
|
|
1247
|
+
}
|
|
1248
|
+
function endDrag(cancelled) {
|
|
1249
|
+
if (drag) drag.finish(cancelled);
|
|
1162
1250
|
}
|
|
1163
1251
|
function attachWindow(id, windowElement, windowOptions = {}) {
|
|
1164
1252
|
const win = wm.get(id);
|
|
@@ -1169,6 +1257,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1169
1257
|
handle: null,
|
|
1170
1258
|
handles: [],
|
|
1171
1259
|
lastState: null,
|
|
1260
|
+
lastZ: -1,
|
|
1172
1261
|
cleanup: []
|
|
1173
1262
|
};
|
|
1174
1263
|
windowElement.dataset.wmWindow = id;
|
|
@@ -1221,24 +1310,11 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1221
1310
|
attached.cleanup.push(() => handle.removeEventListener("dblclick", onDoubleClick));
|
|
1222
1311
|
}
|
|
1223
1312
|
if (windowOptions.resizeHandles !== false) {
|
|
1224
|
-
for (const direction of
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
const size = 8;
|
|
1230
|
-
const corner = 12;
|
|
1231
|
-
const styles = {
|
|
1232
|
-
n: `top:${-size / 2}px;left:${corner}px;right:${corner}px;height:${size}px`,
|
|
1233
|
-
s: `bottom:${-size / 2}px;left:${corner}px;right:${corner}px;height:${size}px`,
|
|
1234
|
-
e: `right:${-size / 2}px;top:${corner}px;bottom:${corner}px;width:${size}px`,
|
|
1235
|
-
w: `left:${-size / 2}px;top:${corner}px;bottom:${corner}px;width:${size}px`,
|
|
1236
|
-
ne: `top:${-size / 2}px;right:${-size / 2}px;width:${corner}px;height:${corner}px`,
|
|
1237
|
-
nw: `top:${-size / 2}px;left:${-size / 2}px;width:${corner}px;height:${corner}px`,
|
|
1238
|
-
se: `bottom:${-size / 2}px;right:${-size / 2}px;width:${corner}px;height:${corner}px`,
|
|
1239
|
-
sw: `bottom:${-size / 2}px;left:${-size / 2}px;width:${corner}px;height:${corner}px`
|
|
1240
|
-
};
|
|
1241
|
-
resizeHandle.style.cssText = `${base}${styles[direction]};cursor:${RESIZE_CURSORS[direction]}`;
|
|
1313
|
+
for (const { element: resizeHandle, direction } of createResizeHandles(
|
|
1314
|
+
doc,
|
|
1315
|
+
hitEdge,
|
|
1316
|
+
hitCorner
|
|
1317
|
+
)) {
|
|
1242
1318
|
const onResizeDown = (event) => startResize(id, direction, event);
|
|
1243
1319
|
resizeHandle.addEventListener("pointerdown", onResizeDown);
|
|
1244
1320
|
attached.cleanup.push(() => resizeHandle.removeEventListener("pointerdown", onResizeDown));
|
|
@@ -1296,16 +1372,25 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1296
1372
|
};
|
|
1297
1373
|
windowElement.addEventListener("keydown", onModalTrap);
|
|
1298
1374
|
attached.cleanup.push(() => windowElement.removeEventListener("keydown", onModalTrap));
|
|
1299
|
-
|
|
1300
|
-
lastOrder = null;
|
|
1301
|
-
lastFocused = null;
|
|
1302
|
-
syncAll();
|
|
1303
|
-
return () => {
|
|
1375
|
+
const detach = () => {
|
|
1304
1376
|
if (drag?.id === id) endDrag(true);
|
|
1305
1377
|
for (const dispose of attached.cleanup) dispose();
|
|
1306
1378
|
for (const resizeHandle of attached.handles) resizeHandle.remove();
|
|
1307
1379
|
registry.delete(id);
|
|
1308
1380
|
};
|
|
1381
|
+
if (windowOptions.removeOnClose) {
|
|
1382
|
+
const stopOnClose = wm.on("close", ({ window: closed }) => {
|
|
1383
|
+
if (closed.id !== id) return;
|
|
1384
|
+
detach();
|
|
1385
|
+
windowElement.remove();
|
|
1386
|
+
});
|
|
1387
|
+
attached.cleanup.push(stopOnClose);
|
|
1388
|
+
}
|
|
1389
|
+
registry.set(id, attached);
|
|
1390
|
+
lastOrder = null;
|
|
1391
|
+
lastFocused = null;
|
|
1392
|
+
syncAll();
|
|
1393
|
+
return detach;
|
|
1309
1394
|
}
|
|
1310
1395
|
return {
|
|
1311
1396
|
element,
|
|
@@ -1324,6 +1409,8 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1324
1409
|
}
|
|
1325
1410
|
};
|
|
1326
1411
|
}
|
|
1412
|
+
|
|
1413
|
+
// src/dom/binder.ts
|
|
1327
1414
|
function createDesktopBinder(wm, options = {}) {
|
|
1328
1415
|
let controller = null;
|
|
1329
1416
|
const entries = /* @__PURE__ */ new Set();
|
|
@@ -1364,5 +1451,5 @@ function createDesktopBinder(wm, options = {}) {
|
|
|
1364
1451
|
}
|
|
1365
1452
|
|
|
1366
1453
|
export { attachDesktop, boundsEqual, clamp, clampSize, clampToViewport, createAnnouncer, createDesktopBinder, createEmitter, createWindowManager, defaultMessages, detectSnapZone, flipToTarget, prefersReducedMotion, zoneBounds };
|
|
1367
|
-
//# sourceMappingURL=chunk-
|
|
1368
|
-
//# sourceMappingURL=chunk-
|
|
1454
|
+
//# sourceMappingURL=chunk-2TVOEDRG.js.map
|
|
1455
|
+
//# sourceMappingURL=chunk-2TVOEDRG.js.map
|