@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
|
@@ -776,175 +776,25 @@ function createAnnouncer(wm, container, messages = {}) {
|
|
|
776
776
|
};
|
|
777
777
|
}
|
|
778
778
|
|
|
779
|
-
// src/dom/
|
|
780
|
-
var RESIZE_DIRECTIONS = ["n", "e", "s", "w", "ne", "nw", "se", "sw"];
|
|
781
|
-
var RESIZE_CURSORS = {
|
|
782
|
-
n: "ns-resize",
|
|
783
|
-
s: "ns-resize",
|
|
784
|
-
e: "ew-resize",
|
|
785
|
-
w: "ew-resize",
|
|
786
|
-
ne: "nesw-resize",
|
|
787
|
-
sw: "nesw-resize",
|
|
788
|
-
nw: "nwse-resize",
|
|
789
|
-
se: "nwse-resize"
|
|
790
|
-
};
|
|
779
|
+
// src/dom/shared.ts
|
|
791
780
|
var INTERACTIVE_SELECTOR = "button, input, select, textarea, a[href], [contenteditable], [data-wm-close], [data-wm-minimize], [data-wm-maximize]";
|
|
792
781
|
function windowOf(element) {
|
|
793
782
|
const view = element.ownerDocument.defaultView;
|
|
794
783
|
if (!view) throw new Error("wmkit: desktop element is not attached to a document");
|
|
795
784
|
return view;
|
|
796
785
|
}
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
const
|
|
801
|
-
|
|
802
|
-
const snapPreviewEnabled = snapOptions.preview !== false;
|
|
803
|
-
const topEdge = snapOptions.topEdge ?? "maximize";
|
|
804
|
-
const keyboardEnabled = options.keyboard !== false;
|
|
805
|
-
const keyboardOptions = typeof options.keyboard === "object" ? options.keyboard : {};
|
|
806
|
-
const moveStep = keyboardOptions.moveStep ?? 16;
|
|
807
|
-
const cycleEnabled = keyboardOptions.cycle !== false;
|
|
808
|
-
element.dataset.wmDesktop = "";
|
|
809
|
-
if (view.getComputedStyle(element).position === "static") {
|
|
810
|
-
element.style.position = "relative";
|
|
811
|
-
}
|
|
812
|
-
const registry = /* @__PURE__ */ new Map();
|
|
813
|
-
const cleanup = [];
|
|
814
|
-
let lastOrder = null;
|
|
815
|
-
let lastFocused = null;
|
|
816
|
-
let drag = null;
|
|
817
|
-
let announcer = null;
|
|
818
|
-
if (options.announce !== false) {
|
|
819
|
-
announcer = createAnnouncer(
|
|
820
|
-
wm,
|
|
821
|
-
element,
|
|
822
|
-
typeof options.announce === "object" ? options.announce : {}
|
|
823
|
-
);
|
|
824
|
-
cleanup.push(() => announcer?.destroy());
|
|
825
|
-
}
|
|
826
|
-
let preview = null;
|
|
827
|
-
function showPreview(bounds) {
|
|
828
|
-
if (!snapPreviewEnabled) return;
|
|
829
|
-
if (!preview) {
|
|
830
|
-
preview = doc.createElement("div");
|
|
831
|
-
preview.dataset.wmSnapPreview = "";
|
|
832
|
-
preview.style.cssText = "position:absolute;left:0;top:0;pointer-events:none;display:none;z-index:2147483646";
|
|
833
|
-
element.append(preview);
|
|
834
|
-
}
|
|
835
|
-
preview.style.display = "block";
|
|
836
|
-
preview.style.transform = `translate3d(${bounds.x}px, ${bounds.y}px, 0)`;
|
|
837
|
-
preview.style.width = `${bounds.width}px`;
|
|
838
|
-
preview.style.height = `${bounds.height}px`;
|
|
839
|
-
}
|
|
840
|
-
function hidePreview() {
|
|
841
|
-
if (preview) preview.style.display = "none";
|
|
842
|
-
}
|
|
843
|
-
if (options.autoViewport !== false) {
|
|
844
|
-
const applyViewport = () => wm.setViewport({ width: element.clientWidth, height: element.clientHeight });
|
|
845
|
-
applyViewport();
|
|
846
|
-
const observer = new ResizeObserver(applyViewport);
|
|
847
|
-
observer.observe(element);
|
|
848
|
-
cleanup.push(() => observer.disconnect());
|
|
849
|
-
}
|
|
850
|
-
function syncWindow(attached, win, zIndex) {
|
|
851
|
-
const el = attached.element;
|
|
852
|
-
const firstSync = attached.lastState === null;
|
|
853
|
-
if (firstSync) el.style.transition = "none";
|
|
854
|
-
if (attached.lastState !== win) {
|
|
855
|
-
el.style.transform = `translate3d(${win.bounds.x}px, ${win.bounds.y}px, 0)`;
|
|
856
|
-
el.style.width = `${win.bounds.width}px`;
|
|
857
|
-
el.style.height = `${win.bounds.height}px`;
|
|
858
|
-
el.dataset.wmStage = win.stage;
|
|
859
|
-
el.dataset.wmLayer = win.layer;
|
|
860
|
-
el.hidden = win.stage === "minimized";
|
|
861
|
-
el.setAttribute("aria-label", win.title);
|
|
862
|
-
if (win.layer === "modal") el.setAttribute("aria-modal", "true");
|
|
863
|
-
else el.removeAttribute("aria-modal");
|
|
864
|
-
for (const handle of attached.handles) {
|
|
865
|
-
handle.style.display = win.resizable && win.stage === "normal" ? "" : "none";
|
|
866
|
-
}
|
|
867
|
-
attached.lastState = win;
|
|
868
|
-
}
|
|
869
|
-
el.style.zIndex = String(zIndex + 1);
|
|
870
|
-
if (firstSync) {
|
|
871
|
-
void el.offsetWidth;
|
|
872
|
-
el.style.transition = "";
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
function syncAll() {
|
|
876
|
-
const state = wm.getState();
|
|
877
|
-
const orderChanged = state.order !== lastOrder;
|
|
878
|
-
state.order.forEach((id, index) => {
|
|
879
|
-
const attached = registry.get(id);
|
|
880
|
-
const win = state.windows[id];
|
|
881
|
-
if (!attached || !win) return;
|
|
882
|
-
if (orderChanged || attached.lastState !== win) syncWindow(attached, win, index);
|
|
883
|
-
});
|
|
884
|
-
if (state.focusedId !== lastFocused) {
|
|
885
|
-
if (lastFocused) {
|
|
886
|
-
const prev = registry.get(lastFocused);
|
|
887
|
-
if (prev) delete prev.element.dataset.wmFocused;
|
|
888
|
-
}
|
|
889
|
-
if (state.focusedId) {
|
|
890
|
-
const next = registry.get(state.focusedId);
|
|
891
|
-
if (next) next.element.dataset.wmFocused = "";
|
|
892
|
-
}
|
|
893
|
-
lastFocused = state.focusedId;
|
|
894
|
-
}
|
|
895
|
-
lastOrder = state.order;
|
|
896
|
-
}
|
|
897
|
-
cleanup.push(wm.subscribe(syncAll));
|
|
898
|
-
cleanup.push(
|
|
899
|
-
wm.on("focus", ({ window: win }) => {
|
|
900
|
-
const attached = registry.get(win.id);
|
|
901
|
-
if (!attached) return;
|
|
902
|
-
if (!attached.element.contains(doc.activeElement)) {
|
|
903
|
-
attached.element.focus({ preventScroll: true });
|
|
904
|
-
}
|
|
905
|
-
})
|
|
906
|
-
);
|
|
907
|
-
cleanup.push(
|
|
908
|
-
wm.on("modalblocked", ({ window: win }) => {
|
|
909
|
-
const attached = registry.get(win.id);
|
|
910
|
-
if (!attached) return;
|
|
911
|
-
delete attached.element.dataset.wmFlash;
|
|
912
|
-
void attached.element.offsetWidth;
|
|
913
|
-
attached.element.dataset.wmFlash = "";
|
|
914
|
-
})
|
|
915
|
-
);
|
|
916
|
-
cleanup.push(
|
|
917
|
-
wm.on("stage", ({ window: win, previous }) => {
|
|
918
|
-
if (win.stage !== "minimized" || previous === "minimized") return;
|
|
919
|
-
const attached = registry.get(win.id);
|
|
920
|
-
const target = options.minimizeTarget?.(win);
|
|
921
|
-
if (attached && target) flipToTarget(attached.element, target);
|
|
922
|
-
})
|
|
923
|
-
);
|
|
924
|
-
if (keyboardEnabled && cycleEnabled) {
|
|
925
|
-
const onDesktopKeydown = (event) => {
|
|
926
|
-
if (event.key === "F6") {
|
|
927
|
-
event.preventDefault();
|
|
928
|
-
wm.cycleFocus(event.shiftKey ? -1 : 1);
|
|
929
|
-
}
|
|
930
|
-
};
|
|
931
|
-
element.addEventListener("keydown", onDesktopKeydown);
|
|
932
|
-
cleanup.push(() => element.removeEventListener("keydown", onDesktopKeydown));
|
|
933
|
-
}
|
|
934
|
-
function desktopPoint(event) {
|
|
935
|
-
const rect = element.getBoundingClientRect();
|
|
936
|
-
return { x: event.clientX - rect.left, y: event.clientY - rect.top };
|
|
937
|
-
}
|
|
938
|
-
function endDrag(cancelled) {
|
|
939
|
-
if (drag) drag.finish(cancelled);
|
|
940
|
-
}
|
|
941
|
-
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) {
|
|
942
791
|
const win = wm.get(id);
|
|
943
|
-
if (!win?.draggable || event.button !== 0 ||
|
|
792
|
+
if (!win?.draggable || event.button !== 0 || ctx.currentDrag()) return;
|
|
944
793
|
const target = event.target;
|
|
945
794
|
if (target?.closest(INTERACTIVE_SELECTOR)) return;
|
|
946
795
|
event.preventDefault();
|
|
947
|
-
const
|
|
796
|
+
const releaseRect = ctx.trackRect();
|
|
797
|
+
const point = ctx.toLocal(event);
|
|
948
798
|
const startBounds = win.bounds;
|
|
949
799
|
const session = {
|
|
950
800
|
id,
|
|
@@ -966,10 +816,9 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
966
816
|
finish: () => {
|
|
967
817
|
}
|
|
968
818
|
};
|
|
969
|
-
const
|
|
970
|
-
const el = attached?.element;
|
|
819
|
+
const el = ctx.windowElement(id);
|
|
971
820
|
function flush() {
|
|
972
|
-
if (!session.hasPending ||
|
|
821
|
+
if (!session.hasPending || ctx.currentDrag() !== session) return;
|
|
973
822
|
session.hasPending = false;
|
|
974
823
|
session.raf = 0;
|
|
975
824
|
const current = wm.get(id);
|
|
@@ -993,32 +842,35 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
993
842
|
return;
|
|
994
843
|
}
|
|
995
844
|
wm.move(id, session.pendingX - session.grabDX, session.pendingY - session.grabDY);
|
|
996
|
-
if (snapEnabled && current.snappable) {
|
|
845
|
+
if (ctx.snapEnabled && current.snappable) {
|
|
997
846
|
const viewport = wm.getState().viewport;
|
|
998
|
-
const rawZone = detectSnapZone(session.pendingX, session.pendingY, viewport,
|
|
847
|
+
const rawZone = detectSnapZone(session.pendingX, session.pendingY, viewport, ctx.snapDetect);
|
|
999
848
|
let zone = rawZone;
|
|
1000
849
|
if (rawZone === "top") {
|
|
1001
|
-
if (topEdge === "maximize") zone = current.maximizable ? "maximize" : null;
|
|
1002
|
-
else if (topEdge === "none") zone = null;
|
|
850
|
+
if (ctx.topEdge === "maximize") zone = current.maximizable ? "maximize" : null;
|
|
851
|
+
else if (ctx.topEdge === "none") zone = null;
|
|
1003
852
|
}
|
|
1004
853
|
session.zone = zone;
|
|
1005
854
|
if (zone) {
|
|
1006
|
-
showPreview(
|
|
855
|
+
ctx.showPreview(
|
|
1007
856
|
zone === "maximize" ? { x: 0, y: 0, width: viewport.width, height: viewport.height } : zoneBounds(zone, viewport)
|
|
1008
857
|
);
|
|
1009
858
|
} else {
|
|
1010
|
-
hidePreview();
|
|
859
|
+
ctx.hidePreview();
|
|
1011
860
|
}
|
|
1012
861
|
}
|
|
1013
862
|
}
|
|
1014
863
|
function onMove(moveEvent) {
|
|
1015
864
|
if (moveEvent.pointerId !== session.pointerId) return;
|
|
1016
|
-
const movePoint =
|
|
865
|
+
const movePoint = ctx.toLocal(moveEvent);
|
|
1017
866
|
if (!session.moved) {
|
|
1018
867
|
const travelled = Math.abs(movePoint.x - (session.startBounds.x + session.grabDX)) + Math.abs(movePoint.y - (session.startBounds.y + session.grabDY));
|
|
1019
868
|
if (travelled < 3 && session.restored) return;
|
|
1020
869
|
session.moved = true;
|
|
1021
|
-
if (el)
|
|
870
|
+
if (el) {
|
|
871
|
+
el.dataset.wmDragging = "";
|
|
872
|
+
el.style.willChange = "transform";
|
|
873
|
+
}
|
|
1022
874
|
}
|
|
1023
875
|
session.pendingX = movePoint.x;
|
|
1024
876
|
session.pendingY = movePoint.y;
|
|
@@ -1040,10 +892,11 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1040
892
|
}
|
|
1041
893
|
}
|
|
1042
894
|
function finish(cancelled) {
|
|
1043
|
-
if (
|
|
1044
|
-
if (session.raf !== 0) view
|
|
895
|
+
if (ctx.currentDrag() !== session) return;
|
|
896
|
+
if (session.raf !== 0) view.cancelAnimationFrame(session.raf);
|
|
1045
897
|
if (session.hasPending && !cancelled) flush();
|
|
1046
|
-
|
|
898
|
+
ctx.releaseDrag(session);
|
|
899
|
+
releaseRect();
|
|
1047
900
|
handle.removeEventListener("pointermove", onMove);
|
|
1048
901
|
handle.removeEventListener("pointerup", onUp);
|
|
1049
902
|
handle.removeEventListener("pointercancel", onCancel);
|
|
@@ -1051,8 +904,11 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1051
904
|
if (handle.hasPointerCapture(session.pointerId)) {
|
|
1052
905
|
handle.releasePointerCapture(session.pointerId);
|
|
1053
906
|
}
|
|
1054
|
-
if (el)
|
|
1055
|
-
|
|
907
|
+
if (el) {
|
|
908
|
+
delete el.dataset.wmDragging;
|
|
909
|
+
el.style.willChange = "";
|
|
910
|
+
}
|
|
911
|
+
ctx.hidePreview();
|
|
1056
912
|
if (cancelled) {
|
|
1057
913
|
if (session.moved && session.restored) {
|
|
1058
914
|
if (session.startStage === "maximized") {
|
|
@@ -1073,20 +929,37 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1073
929
|
}
|
|
1074
930
|
}
|
|
1075
931
|
session.finish = finish;
|
|
1076
|
-
|
|
932
|
+
ctx.claimDrag(session);
|
|
1077
933
|
handle.setPointerCapture(event.pointerId);
|
|
1078
934
|
handle.addEventListener("pointermove", onMove);
|
|
1079
935
|
handle.addEventListener("pointerup", onUp);
|
|
1080
936
|
handle.addEventListener("pointercancel", onCancel);
|
|
1081
937
|
doc.addEventListener("keydown", onKeydown, true);
|
|
1082
|
-
}
|
|
1083
|
-
|
|
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) {
|
|
1084
956
|
const win = wm.get(id);
|
|
1085
|
-
if (!win?.resizable || event.button !== 0 ||
|
|
957
|
+
if (!win?.resizable || event.button !== 0 || ctx.currentDrag()) return;
|
|
1086
958
|
event.preventDefault();
|
|
1087
959
|
event.stopPropagation();
|
|
1088
960
|
const handleEl = event.currentTarget;
|
|
1089
|
-
const
|
|
961
|
+
const releaseRect = ctx.trackRect();
|
|
962
|
+
const startPoint = ctx.toLocal(event);
|
|
1090
963
|
const start = win.bounds;
|
|
1091
964
|
const minSize = win.minSize;
|
|
1092
965
|
const maxSize = win.maxSize;
|
|
@@ -1094,8 +967,8 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1094
967
|
let pendingX = 0;
|
|
1095
968
|
let pendingY = 0;
|
|
1096
969
|
let hasPending = false;
|
|
1097
|
-
const
|
|
1098
|
-
if (
|
|
970
|
+
const el = ctx.windowElement(id);
|
|
971
|
+
if (el) el.dataset.wmResizing = direction;
|
|
1099
972
|
function clampWidth(width) {
|
|
1100
973
|
return clamp(width, minSize.width, maxSize ? maxSize.width : Number.POSITIVE_INFINITY);
|
|
1101
974
|
}
|
|
@@ -1123,15 +996,16 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1123
996
|
}
|
|
1124
997
|
function onMove(moveEvent) {
|
|
1125
998
|
if (moveEvent.pointerId !== event.pointerId) return;
|
|
1126
|
-
const movePoint =
|
|
999
|
+
const movePoint = ctx.toLocal(moveEvent);
|
|
1127
1000
|
pendingX = movePoint.x;
|
|
1128
1001
|
pendingY = movePoint.y;
|
|
1129
1002
|
hasPending = true;
|
|
1130
|
-
if (raf === 0) raf = view
|
|
1003
|
+
if (raf === 0) raf = view.requestAnimationFrame(flush);
|
|
1131
1004
|
}
|
|
1132
1005
|
function finish(cancelled) {
|
|
1133
|
-
if (raf !== 0) view
|
|
1006
|
+
if (raf !== 0) view.cancelAnimationFrame(raf);
|
|
1134
1007
|
if (hasPending && !cancelled) flush();
|
|
1008
|
+
releaseRect();
|
|
1135
1009
|
handleEl.removeEventListener("pointermove", onMove);
|
|
1136
1010
|
handleEl.removeEventListener("pointerup", onUp);
|
|
1137
1011
|
handleEl.removeEventListener("pointercancel", onCancelPointer);
|
|
@@ -1139,7 +1013,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1139
1013
|
if (handleEl.hasPointerCapture(event.pointerId)) {
|
|
1140
1014
|
handleEl.releasePointerCapture(event.pointerId);
|
|
1141
1015
|
}
|
|
1142
|
-
if (
|
|
1016
|
+
if (el) delete el.dataset.wmResizing;
|
|
1143
1017
|
if (cancelled) wm.resize(id, start);
|
|
1144
1018
|
}
|
|
1145
1019
|
function onUp(upEvent) {
|
|
@@ -1161,6 +1035,220 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1161
1035
|
handleEl.addEventListener("pointerup", onUp);
|
|
1162
1036
|
handleEl.addEventListener("pointercancel", onCancelPointer);
|
|
1163
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);
|
|
1164
1252
|
}
|
|
1165
1253
|
function attachWindow(id, windowElement, windowOptions = {}) {
|
|
1166
1254
|
const win = wm.get(id);
|
|
@@ -1171,6 +1259,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1171
1259
|
handle: null,
|
|
1172
1260
|
handles: [],
|
|
1173
1261
|
lastState: null,
|
|
1262
|
+
lastZ: -1,
|
|
1174
1263
|
cleanup: []
|
|
1175
1264
|
};
|
|
1176
1265
|
windowElement.dataset.wmWindow = id;
|
|
@@ -1223,24 +1312,11 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1223
1312
|
attached.cleanup.push(() => handle.removeEventListener("dblclick", onDoubleClick));
|
|
1224
1313
|
}
|
|
1225
1314
|
if (windowOptions.resizeHandles !== false) {
|
|
1226
|
-
for (const direction of
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
const size = 8;
|
|
1232
|
-
const corner = 12;
|
|
1233
|
-
const styles = {
|
|
1234
|
-
n: `top:${-size / 2}px;left:${corner}px;right:${corner}px;height:${size}px`,
|
|
1235
|
-
s: `bottom:${-size / 2}px;left:${corner}px;right:${corner}px;height:${size}px`,
|
|
1236
|
-
e: `right:${-size / 2}px;top:${corner}px;bottom:${corner}px;width:${size}px`,
|
|
1237
|
-
w: `left:${-size / 2}px;top:${corner}px;bottom:${corner}px;width:${size}px`,
|
|
1238
|
-
ne: `top:${-size / 2}px;right:${-size / 2}px;width:${corner}px;height:${corner}px`,
|
|
1239
|
-
nw: `top:${-size / 2}px;left:${-size / 2}px;width:${corner}px;height:${corner}px`,
|
|
1240
|
-
se: `bottom:${-size / 2}px;right:${-size / 2}px;width:${corner}px;height:${corner}px`,
|
|
1241
|
-
sw: `bottom:${-size / 2}px;left:${-size / 2}px;width:${corner}px;height:${corner}px`
|
|
1242
|
-
};
|
|
1243
|
-
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
|
+
)) {
|
|
1244
1320
|
const onResizeDown = (event) => startResize(id, direction, event);
|
|
1245
1321
|
resizeHandle.addEventListener("pointerdown", onResizeDown);
|
|
1246
1322
|
attached.cleanup.push(() => resizeHandle.removeEventListener("pointerdown", onResizeDown));
|
|
@@ -1298,16 +1374,25 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1298
1374
|
};
|
|
1299
1375
|
windowElement.addEventListener("keydown", onModalTrap);
|
|
1300
1376
|
attached.cleanup.push(() => windowElement.removeEventListener("keydown", onModalTrap));
|
|
1301
|
-
|
|
1302
|
-
lastOrder = null;
|
|
1303
|
-
lastFocused = null;
|
|
1304
|
-
syncAll();
|
|
1305
|
-
return () => {
|
|
1377
|
+
const detach = () => {
|
|
1306
1378
|
if (drag?.id === id) endDrag(true);
|
|
1307
1379
|
for (const dispose of attached.cleanup) dispose();
|
|
1308
1380
|
for (const resizeHandle of attached.handles) resizeHandle.remove();
|
|
1309
1381
|
registry.delete(id);
|
|
1310
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;
|
|
1311
1396
|
}
|
|
1312
1397
|
return {
|
|
1313
1398
|
element,
|
|
@@ -1326,6 +1411,8 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1326
1411
|
}
|
|
1327
1412
|
};
|
|
1328
1413
|
}
|
|
1414
|
+
|
|
1415
|
+
// src/dom/binder.ts
|
|
1329
1416
|
function createDesktopBinder(wm, options = {}) {
|
|
1330
1417
|
let controller = null;
|
|
1331
1418
|
const entries = /* @__PURE__ */ new Set();
|
|
@@ -1379,5 +1466,5 @@ exports.detectSnapZone = detectSnapZone;
|
|
|
1379
1466
|
exports.flipToTarget = flipToTarget;
|
|
1380
1467
|
exports.prefersReducedMotion = prefersReducedMotion;
|
|
1381
1468
|
exports.zoneBounds = zoneBounds;
|
|
1382
|
-
//# sourceMappingURL=chunk-
|
|
1383
|
-
//# sourceMappingURL=chunk-
|
|
1469
|
+
//# sourceMappingURL=chunk-KQCVZ2W7.cjs.map
|
|
1470
|
+
//# sourceMappingURL=chunk-KQCVZ2W7.cjs.map
|