@surdeddd/wmkit 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.ru.md +1 -1
- package/dist/angular.cjs +3 -3
- package/dist/angular.js +1 -1
- package/dist/{chunk-OOEDFA7K.js → chunk-GGDF2EWV.js} +57 -16
- package/dist/chunk-GGDF2EWV.js.map +1 -0
- package/dist/{chunk-TJ6QOOJ2.cjs → chunk-GLBVT4AQ.cjs} +57 -16
- package/dist/chunk-GLBVT4AQ.cjs.map +1 -0
- package/dist/index.cjs +18 -18
- package/dist/index.js +1 -1
- package/dist/react.cjs +3 -3
- package/dist/react.js +1 -1
- package/dist/solid.cjs +3 -3
- package/dist/solid.js +1 -1
- package/dist/svelte.cjs +3 -3
- package/dist/svelte.js +1 -1
- package/dist/vue.cjs +3 -3
- package/dist/vue.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-OOEDFA7K.js.map +0 -1
- package/dist/chunk-TJ6QOOJ2.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -376,7 +376,7 @@ This README is the tour. The reference lives in [`docs/`](./docs/README.md):
|
|
|
376
376
|
|
|
377
377
|
## Quality
|
|
378
378
|
|
|
379
|
-
-
|
|
379
|
+
- 250 unit tests: **100%** line/branch/function/statement coverage on the core state machine and persistence, with enforced floors on the DOM layer and the adapters
|
|
380
380
|
- 190+ Playwright scenarios on Chromium, WebKit and mobile emulation: drag, 8-way resize, snap, magnetism, workspaces, undo after drag, keyboard, touch, persistence across reloads, 50-window stress, modal traps, axe accessibility scans, visual regression screenshots
|
|
381
381
|
- performance benchmarks run in CI on every push (`vitest bench`): 1 000 windows open in ~150 ms, a move among 50 windows costs ~1.2 µs, a full 100-step undo/redo sweep ~52 µs
|
|
382
382
|
- `publint` + `@arethetypeswrong/cli` validate the published package, `size-limit` guards bundle budgets
|
package/README.ru.md
CHANGED
|
@@ -273,7 +273,7 @@ if (isPopoutSupported()) await popout(wm, 'docs', contentElement)
|
|
|
273
273
|
|
|
274
274
|
## Качество
|
|
275
275
|
|
|
276
|
-
-
|
|
276
|
+
- 250 юнит-тестов: **100%** покрытие стейт-машины и persist по строкам/веткам/функциям, плюс обязательные пороги на DOM-слой и адаптеры
|
|
277
277
|
- 190+ Playwright-сценариев на Chromium, WebKit и мобильной эмуляции: drag, ресайз во все стороны, снэп, магнетизм, рабочие столы, undo после drag, клавиатура, touch, персист через перезагрузку, стресс на 50 окон, модальные ловушки, axe-аудиты доступности, визуальная регрессия по скриншотам
|
|
278
278
|
- перф-бенчмарки в CI на каждый push (`vitest bench`): 1 000 окон открываются за ~150 мс, move среди 50 окон ~1.2 мкс, полный undo/redo-проход на 100 шагов ~52 мкс
|
|
279
279
|
- `publint` + `@arethetypeswrong/cli` проверяют валидность пакета, `size-limit` следит за бюджетами
|
package/dist/angular.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkGLBVT4AQ_cjs = require('./chunk-GLBVT4AQ.cjs');
|
|
4
4
|
var core = require('@angular/core');
|
|
5
5
|
|
|
6
6
|
function onDestroy(dispose) {
|
|
@@ -13,7 +13,7 @@ function onDestroy(dispose) {
|
|
|
13
13
|
destroyRef?.onDestroy(dispose);
|
|
14
14
|
}
|
|
15
15
|
function useWindowManager(options) {
|
|
16
|
-
const wm =
|
|
16
|
+
const wm = chunkGLBVT4AQ_cjs.createWindowManager(options);
|
|
17
17
|
onDestroy(() => wm.destroy());
|
|
18
18
|
return wm;
|
|
19
19
|
}
|
|
@@ -28,7 +28,7 @@ function useWmWindow(wm, id) {
|
|
|
28
28
|
return core.computed(() => state().windows[id]);
|
|
29
29
|
}
|
|
30
30
|
function createDesktop(wm, options) {
|
|
31
|
-
const binder =
|
|
31
|
+
const binder = chunkGLBVT4AQ_cjs.createDesktopBinder(wm, options);
|
|
32
32
|
onDestroy(() => binder.destroy());
|
|
33
33
|
return {
|
|
34
34
|
binder,
|
package/dist/angular.js
CHANGED
|
@@ -209,6 +209,7 @@ function createWindowManager(options = {}) {
|
|
|
209
209
|
let future = [];
|
|
210
210
|
let interactionDepth = 0;
|
|
211
211
|
let interactionRecorded = false;
|
|
212
|
+
let interactionMark = null;
|
|
212
213
|
let skipNextHistory = false;
|
|
213
214
|
let pendingHistory = null;
|
|
214
215
|
const layouts = /* @__PURE__ */ new Map();
|
|
@@ -319,7 +320,13 @@ function createWindowManager(options = {}) {
|
|
|
319
320
|
width: init.width ?? defaultSize.width,
|
|
320
321
|
height: init.height ?? defaultSize.height
|
|
321
322
|
};
|
|
322
|
-
const size = aspectRatio === null ? clampSize(requested, minSize, maxSize) : applyAspect(
|
|
323
|
+
const size = aspectRatio === null ? clampSize(requested, minSize, maxSize) : applyAspect(
|
|
324
|
+
requested,
|
|
325
|
+
aspectRatio,
|
|
326
|
+
minSize,
|
|
327
|
+
maxSize,
|
|
328
|
+
init.width === void 0 && init.height !== void 0 ? "height" : "width"
|
|
329
|
+
);
|
|
323
330
|
const position = positionForOpen(init);
|
|
324
331
|
let bounds = { ...position, ...size };
|
|
325
332
|
if (keepInViewport) bounds = clampToViewport(bounds, viewport, minVisible);
|
|
@@ -435,7 +442,13 @@ function createWindowManager(options = {}) {
|
|
|
435
442
|
}
|
|
436
443
|
function snapBounds(win, zone) {
|
|
437
444
|
const rect = zoneBounds(zone, viewport);
|
|
438
|
-
|
|
445
|
+
const byWidth = normalizeSize(rect, win);
|
|
446
|
+
const size = byWidth.height > rect.height ? normalizeSize(rect, win, "height") : byWidth;
|
|
447
|
+
return {
|
|
448
|
+
x: Math.max(0, Math.min(rect.x, viewport.width - size.width)),
|
|
449
|
+
y: Math.max(0, Math.min(rect.y, viewport.height - size.height)),
|
|
450
|
+
...size
|
|
451
|
+
};
|
|
439
452
|
}
|
|
440
453
|
function focusUnlessBlocked(id) {
|
|
441
454
|
const modal = topModalId();
|
|
@@ -600,7 +613,7 @@ function createWindowManager(options = {}) {
|
|
|
600
613
|
snappable: patch.snappable ?? win.snappable,
|
|
601
614
|
meta: patch.meta ? { ...win.meta, ...patch.meta } : win.meta
|
|
602
615
|
};
|
|
603
|
-
const size = normalizeSize(next.bounds, next);
|
|
616
|
+
const size = next.stage === "maximized" ? next.bounds : normalizeSize(next.bounds, next);
|
|
604
617
|
const resized = size.width !== next.bounds.width || size.height !== next.bounds.height;
|
|
605
618
|
const finalWin = resized ? { ...next, bounds: { ...next.bounds, ...size } } : next;
|
|
606
619
|
setWindow(finalWin);
|
|
@@ -648,6 +661,10 @@ function createWindowManager(options = {}) {
|
|
|
648
661
|
if (!onActiveWorkspace(updated) && focusedId === id) {
|
|
649
662
|
focusTop();
|
|
650
663
|
if (focusedId) emitFocus(windows[focusedId], id);
|
|
664
|
+
} else if (onActiveWorkspace(updated) && topModalId() === id && focusedId !== id) {
|
|
665
|
+
const previous = focusedId;
|
|
666
|
+
focusedId = id;
|
|
667
|
+
emitFocus(updated, previous);
|
|
651
668
|
}
|
|
652
669
|
queueEvent(() => emitter.emit("update", { window: updated }));
|
|
653
670
|
commit();
|
|
@@ -775,14 +792,20 @@ function createWindowManager(options = {}) {
|
|
|
775
792
|
}
|
|
776
793
|
function beginInteraction() {
|
|
777
794
|
interactionDepth += 1;
|
|
778
|
-
if (interactionDepth === 1)
|
|
795
|
+
if (interactionDepth === 1) {
|
|
796
|
+
interactionRecorded = false;
|
|
797
|
+
interactionMark = { past: [...past], future };
|
|
798
|
+
}
|
|
779
799
|
}
|
|
780
800
|
function endInteraction() {
|
|
781
801
|
if (interactionDepth > 0) interactionDepth -= 1;
|
|
802
|
+
if (interactionDepth === 0) interactionMark = null;
|
|
782
803
|
}
|
|
783
804
|
function abortInteraction() {
|
|
784
|
-
if (interactionDepth > 0 &&
|
|
785
|
-
past.
|
|
805
|
+
if (interactionDepth > 0 && interactionMark) {
|
|
806
|
+
past.length = 0;
|
|
807
|
+
past.push(...interactionMark.past);
|
|
808
|
+
future = interactionMark.future;
|
|
786
809
|
interactionRecorded = false;
|
|
787
810
|
}
|
|
788
811
|
endInteraction();
|
|
@@ -1130,10 +1153,8 @@ function createAnnouncer(wm, container, messages = {}) {
|
|
|
1130
1153
|
element.style.cssText = "position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0";
|
|
1131
1154
|
container.append(element);
|
|
1132
1155
|
let clearTimer;
|
|
1133
|
-
let lastMessage = "";
|
|
1134
1156
|
let detailed = false;
|
|
1135
1157
|
function announce(message) {
|
|
1136
|
-
lastMessage = message;
|
|
1137
1158
|
element.textContent = message;
|
|
1138
1159
|
if (clearTimer !== void 0) clearTimeout(clearTimer);
|
|
1139
1160
|
clearTimer = setTimeout(() => {
|
|
@@ -1141,8 +1162,14 @@ function createAnnouncer(wm, container, messages = {}) {
|
|
|
1141
1162
|
}, 2e3);
|
|
1142
1163
|
}
|
|
1143
1164
|
const unsubscribers = [
|
|
1144
|
-
wm.on("open", ({ window: win }) =>
|
|
1145
|
-
|
|
1165
|
+
wm.on("open", ({ window: win }) => {
|
|
1166
|
+
announce(dict.opened(win.title));
|
|
1167
|
+
detailed = true;
|
|
1168
|
+
}),
|
|
1169
|
+
wm.on("close", ({ window: win }) => {
|
|
1170
|
+
announce(dict.closed(win.title));
|
|
1171
|
+
detailed = true;
|
|
1172
|
+
}),
|
|
1146
1173
|
wm.on("stage", ({ window: win, previous }) => {
|
|
1147
1174
|
if (win.stage === "minimized") announce(dict.minimized(win.title));
|
|
1148
1175
|
else if (win.stage === "maximized") announce(dict.maximized(win.title));
|
|
@@ -1153,7 +1180,7 @@ function createAnnouncer(wm, container, messages = {}) {
|
|
|
1153
1180
|
detailed = true;
|
|
1154
1181
|
}),
|
|
1155
1182
|
wm.on("focus", ({ window: win, previous }) => {
|
|
1156
|
-
if (detailed || previous === null
|
|
1183
|
+
if (detailed || previous === null) return;
|
|
1157
1184
|
announce(dict.focused(win.title));
|
|
1158
1185
|
}),
|
|
1159
1186
|
wm.on("workspace", ({ workspace }) => {
|
|
@@ -1400,6 +1427,7 @@ function createResizeStarter(ctx) {
|
|
|
1400
1427
|
let pendingX = 0;
|
|
1401
1428
|
let pendingY = 0;
|
|
1402
1429
|
let hasPending = false;
|
|
1430
|
+
let applied = false;
|
|
1403
1431
|
const el = ctx.windowElement(id);
|
|
1404
1432
|
if (el) el.dataset.wmResizing = direction;
|
|
1405
1433
|
function flush() {
|
|
@@ -1408,18 +1436,24 @@ function createResizeStarter(ctx) {
|
|
|
1408
1436
|
raf = 0;
|
|
1409
1437
|
const dx = pendingX - startPoint.x;
|
|
1410
1438
|
const dy = pendingY - startPoint.y;
|
|
1411
|
-
const
|
|
1439
|
+
const floor = Math.min(0, start.y);
|
|
1440
|
+
const top = direction.includes("n") ? Math.max(floor, start.y + dy) : start.y;
|
|
1412
1441
|
const raw = {
|
|
1413
1442
|
width: direction.includes("e") ? start.width + dx : direction.includes("w") ? start.width - dx : start.width,
|
|
1414
1443
|
height: direction.includes("s") ? start.height + dy : direction.includes("n") ? start.y + start.height - top : start.height
|
|
1415
1444
|
};
|
|
1416
|
-
|
|
1445
|
+
let size = aspect === null ? clampSize(raw, minSize, maxSize) : applyAspect(raw, aspect, minSize, maxSize, drive);
|
|
1446
|
+
const available = start.y + start.height - floor;
|
|
1447
|
+
if (direction.includes("n") && size.height > available) {
|
|
1448
|
+
size = applyAspect({ ...size, height: available }, aspect ?? 0, minSize, maxSize, "height");
|
|
1449
|
+
}
|
|
1417
1450
|
const next = {
|
|
1418
1451
|
x: direction.includes("w") ? start.x + start.width - size.width : start.x,
|
|
1419
1452
|
y: direction.includes("n") ? start.y + start.height - size.height : start.y,
|
|
1420
1453
|
...size
|
|
1421
1454
|
};
|
|
1422
1455
|
wm.resize(id, next);
|
|
1456
|
+
applied = true;
|
|
1423
1457
|
}
|
|
1424
1458
|
function onMove(moveEvent) {
|
|
1425
1459
|
if (moveEvent.pointerId !== event.pointerId) return;
|
|
@@ -1434,7 +1468,7 @@ function createResizeStarter(ctx) {
|
|
|
1434
1468
|
try {
|
|
1435
1469
|
if (raf !== 0) view.cancelAnimationFrame(raf);
|
|
1436
1470
|
if (hasPending && !cancelled) flush();
|
|
1437
|
-
if (cancelled) {
|
|
1471
|
+
if (cancelled && applied) {
|
|
1438
1472
|
if (startStage === "snapped" && startZone) {
|
|
1439
1473
|
wm.restoreTo(id, startRestore ?? start);
|
|
1440
1474
|
wm.snap(id, startZone);
|
|
@@ -1636,6 +1670,11 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1636
1670
|
if (hide && !el.hidden && el.contains(doc.activeElement)) {
|
|
1637
1671
|
element.focus({ preventScroll: true });
|
|
1638
1672
|
}
|
|
1673
|
+
if (!hide && el.hidden && wm.getState().focusedId === win.id) {
|
|
1674
|
+
queueMicrotask(() => {
|
|
1675
|
+
if (!el.hidden && !el.contains(doc.activeElement)) el.focus({ preventScroll: true });
|
|
1676
|
+
});
|
|
1677
|
+
}
|
|
1639
1678
|
el.hidden = hide;
|
|
1640
1679
|
el.setAttribute("aria-label", win.title);
|
|
1641
1680
|
if (win.layer === "modal") el.setAttribute("aria-modal", "true");
|
|
@@ -1684,6 +1723,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1684
1723
|
wm.on("focus", ({ window: win }) => {
|
|
1685
1724
|
const attached = registry.get(win.id);
|
|
1686
1725
|
if (!attached) return;
|
|
1726
|
+
if (attached.element.hidden) syncAll();
|
|
1687
1727
|
if (!attached.element.contains(doc.activeElement)) {
|
|
1688
1728
|
attached.element.focus({ preventScroll: true });
|
|
1689
1729
|
}
|
|
@@ -1719,6 +1759,7 @@ function attachDesktop(wm, element, options = {}) {
|
|
|
1719
1759
|
return;
|
|
1720
1760
|
}
|
|
1721
1761
|
if (!event.ctrlKey && !event.metaKey) return;
|
|
1762
|
+
if (drag) return;
|
|
1722
1763
|
const target = event.target;
|
|
1723
1764
|
if (target?.closest(INTERACTIVE_SELECTOR)) return;
|
|
1724
1765
|
if (historyShortcuts && (event.key === "z" || event.key === "Z")) {
|
|
@@ -1987,5 +2028,5 @@ function createDesktopBinder(wm, options = {}) {
|
|
|
1987
2028
|
}
|
|
1988
2029
|
|
|
1989
2030
|
export { applyAspect, attachDesktop, boundsEqual, clamp, clampSize, clampToViewport, createAnnouncer, createDesktopBinder, createEmitter, createWindowManager, defaultMessages, detectSnapZone, flipFromTarget, flipToTarget, magnetize, prefersReducedMotion, zoneBounds };
|
|
1990
|
-
//# sourceMappingURL=chunk-
|
|
1991
|
-
//# sourceMappingURL=chunk-
|
|
2031
|
+
//# sourceMappingURL=chunk-GGDF2EWV.js.map
|
|
2032
|
+
//# sourceMappingURL=chunk-GGDF2EWV.js.map
|