@surdeddd/wmkit 0.9.2 → 0.11.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.
@@ -1858,6 +1858,14 @@ var SNAP_ZONES = /* @__PURE__ */ new Set([
1858
1858
  ]);
1859
1859
  var LANDMARK_TAGS = /* @__PURE__ */ new Set(["header", "footer", "aside", "nav"]);
1860
1860
  var FOCUSABLE_SELECTOR = 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
1861
+ function firedOn(event) {
1862
+ const path = event.composedPath();
1863
+ const first = path.length > 0 ? path[0] : event.target;
1864
+ return first instanceof Element ? first : null;
1865
+ }
1866
+ function findInWindow(el, selector) {
1867
+ return el.querySelector(selector) ?? el.shadowRoot?.querySelector(selector) ?? null;
1868
+ }
1861
1869
  function focusablesOf(el) {
1862
1870
  const root = el.shadowRoot;
1863
1871
  if (!root) return [...el.querySelectorAll(FOCUSABLE_SELECTOR)];
@@ -1877,8 +1885,15 @@ function focusablesOf(el) {
1877
1885
  function dragHandleAt(node, clientX, clientY) {
1878
1886
  const handle = node.closest?.("[data-wm-drag]");
1879
1887
  if (handle) return handle;
1880
- const inner = node.shadowRoot?.elementFromPoint?.(clientX, clientY) ?? null;
1881
- return inner === null || inner === node ? null : dragHandleAt(inner, clientX, clientY);
1888
+ const root = node.shadowRoot;
1889
+ if (!root) return null;
1890
+ for (const candidate of root.querySelectorAll("[data-wm-drag]")) {
1891
+ const box = candidate.getBoundingClientRect();
1892
+ if (clientX >= box.left && clientX <= box.right && clientY >= box.top && clientY <= box.bottom) {
1893
+ return candidate;
1894
+ }
1895
+ }
1896
+ return null;
1882
1897
  }
1883
1898
  function windowElementOf(node) {
1884
1899
  const found = node.closest("[data-wm-window]");
@@ -2119,7 +2134,24 @@ function attachDesktop(wm, element, options = {}) {
2119
2134
  restack(stackTarget, { base: zIndexBase, gap: zIndexGap });
2120
2135
  stackRows.length = length;
2121
2136
  }
2137
+ let syncing = false;
2138
+ let syncAgain = false;
2122
2139
  function syncAll() {
2140
+ if (syncing) {
2141
+ syncAgain = true;
2142
+ return;
2143
+ }
2144
+ syncing = true;
2145
+ try {
2146
+ do {
2147
+ syncAgain = false;
2148
+ syncPass();
2149
+ } while (syncAgain);
2150
+ } finally {
2151
+ syncing = false;
2152
+ }
2153
+ }
2154
+ function syncPass() {
2123
2155
  const state = wm.getState();
2124
2156
  const orderChanged = state.order !== lastOrder;
2125
2157
  let restyle = null;
@@ -2143,7 +2175,7 @@ function attachDesktop(wm, element, options = {}) {
2143
2175
  const attached = registry.get(id);
2144
2176
  if (attached && attached.skin !== wanted2) buildSkin(id, wanted2, attached.mountOptions);
2145
2177
  }
2146
- syncAll();
2178
+ syncAgain = true;
2147
2179
  return;
2148
2180
  }
2149
2181
  if (orderChanged) applyStacking(state.order);
@@ -2202,7 +2234,7 @@ function attachDesktop(wm, element, options = {}) {
2202
2234
  }
2203
2235
  if (!event.ctrlKey && !event.metaKey) return;
2204
2236
  if (drag) return;
2205
- const target = event.target;
2237
+ const target = firedOn(event);
2206
2238
  if (target?.closest(interactiveSelector)) return;
2207
2239
  if (historyShortcuts && (event.key === "z" || event.key === "Z")) {
2208
2240
  event.preventDefault();
@@ -2233,6 +2265,7 @@ function attachDesktop(wm, element, options = {}) {
2233
2265
  element.addEventListener("keydown", onDesktopKeydown);
2234
2266
  cleanup.push(() => element.removeEventListener("keydown", onDesktopKeydown));
2235
2267
  }
2268
+ let rebuilding = false;
2236
2269
  function endDrag(cancelled) {
2237
2270
  if (drag) drag.finish(cancelled);
2238
2271
  }
@@ -2262,12 +2295,12 @@ function attachDesktop(wm, element, options = {}) {
2262
2295
  windowElement.style.left = "0";
2263
2296
  windowElement.style.top = "0";
2264
2297
  const lightTitle = windowElement.querySelector("[data-wm-title]");
2265
- attached.title = lightTitle ?? windowElement.shadowRoot?.querySelector("[data-wm-title]") ?? null;
2298
+ attached.title = lightTitle ?? findInWindow(windowElement, "[data-wm-title]");
2266
2299
  if (lightTitle) {
2267
2300
  if (!lightTitle.id) lightTitle.id = `wmkit-title-${id}`;
2268
2301
  windowElement.setAttribute("aria-labelledby", lightTitle.id);
2269
2302
  }
2270
- const handle = typeof windowOptions.handle === "string" ? windowElement.querySelector(windowOptions.handle) : windowOptions.handle ?? windowElement.querySelector("[data-wm-drag]");
2303
+ const handle = typeof windowOptions.handle === "string" ? findInWindow(windowElement, windowOptions.handle) : windowOptions.handle ?? findInWindow(windowElement, "[data-wm-drag]");
2271
2304
  attached.handle = handle;
2272
2305
  if (handle && !handle.hasAttribute("role") && LANDMARK_TAGS.has(handle.localName)) {
2273
2306
  handle.setAttribute("role", "presentation");
@@ -2280,7 +2313,7 @@ function attachDesktop(wm, element, options = {}) {
2280
2313
  () => windowElement.removeEventListener("pointerdown", onPointerDownFocus, true)
2281
2314
  );
2282
2315
  const onClick = (event) => {
2283
- const target = event.target;
2316
+ const target = firedOn(event);
2284
2317
  if (!target) return;
2285
2318
  const current = wm.get(id);
2286
2319
  if (!current) return;
@@ -2328,7 +2361,7 @@ function attachDesktop(wm, element, options = {}) {
2328
2361
  handle.addEventListener("pointerdown", onHandleDown);
2329
2362
  attached.cleanup.push(() => handle.removeEventListener("pointerdown", onHandleDown));
2330
2363
  const onDoubleClick = (event) => {
2331
- const target = event.target;
2364
+ const target = firedOn(event);
2332
2365
  if (target?.closest(interactiveSelector)) return;
2333
2366
  const current = wm.get(id);
2334
2367
  if (current?.maximizable) wm.toggleMaximize(id);
@@ -2360,7 +2393,7 @@ function attachDesktop(wm, element, options = {}) {
2360
2393
  }
2361
2394
  }
2362
2395
  const onWindowKeydown = (event) => {
2363
- const target = event.target;
2396
+ const target = firedOn(event);
2364
2397
  if (target?.closest(interactiveSelector)) return;
2365
2398
  const current = wm.get(id);
2366
2399
  if (!current) return;
@@ -2420,7 +2453,7 @@ function attachDesktop(wm, element, options = {}) {
2420
2453
  const detach = () => {
2421
2454
  if (detached) return;
2422
2455
  detached = true;
2423
- if (drag?.id === id) endDrag(true);
2456
+ if (drag?.id === id) endDrag(!rebuilding);
2424
2457
  for (const dispose of attached.cleanup) dispose();
2425
2458
  for (const resizeHandle of attached.handles) resizeHandle.remove();
2426
2459
  registry.delete(id);
@@ -2456,15 +2489,21 @@ function attachDesktop(wm, element, options = {}) {
2456
2489
  function buildSkin(id, skin, windowOptions) {
2457
2490
  const win = wm.get(id);
2458
2491
  if (!win) throw new Error(`wmkit: cannot mount unknown window "${id}"`);
2492
+ const build = resolveSkin(skin);
2459
2493
  const standing = registry.get(id);
2460
2494
  const previous = standing?.mount ?? null;
2461
- const carried = previous === null ? [] : [...previous.content.childNodes];
2495
+ const carried = previous === null || previous.content.ownerDocument !== doc ? [] : [...previous.content.childNodes];
2462
2496
  if (previous !== null) {
2463
2497
  registry.delete(id);
2464
- standing?.release?.();
2498
+ rebuilding = true;
2499
+ try {
2500
+ standing?.release?.();
2501
+ } finally {
2502
+ rebuilding = false;
2503
+ }
2465
2504
  previous.element.remove();
2466
2505
  }
2467
- const mount = resolveSkin(skin)({ doc, id, window: win, actions: createActions(wm, id) });
2506
+ const mount = build({ doc, id, window: win, actions: createActions(wm, id) });
2468
2507
  element.append(mount.element);
2469
2508
  const release = attachWindow(id, mount.element, windowOptions);
2470
2509
  const attached = registry.get(id);
@@ -2476,10 +2515,14 @@ function attachDesktop(wm, element, options = {}) {
2476
2515
  previous?.destroy?.();
2477
2516
  return mount;
2478
2517
  }
2479
- function mountWindow(id, skin, windowOptions = {}) {
2518
+ function mountWindow(id, skin, options2 = {}) {
2519
+ const windowOptions = { removeOnClose: true, ...options2 };
2480
2520
  let last = buildSkin(id, skin, windowOptions);
2521
+ let spent = false;
2481
2522
  const live = () => {
2482
- last = registry.get(id)?.mount ?? last;
2523
+ if (spent) return last;
2524
+ const now = registry.get(id)?.mount;
2525
+ if (now) last = now;
2483
2526
  return last;
2484
2527
  };
2485
2528
  return {
@@ -2490,8 +2533,10 @@ function attachDesktop(wm, element, options = {}) {
2490
2533
  return live().content;
2491
2534
  },
2492
2535
  detach() {
2536
+ if (spent) return;
2493
2537
  const mount = live();
2494
- registry.get(id)?.release?.();
2538
+ spent = true;
2539
+ if (registry.get(id)?.mount === mount) registry.get(id)?.release?.();
2495
2540
  mount.element.remove();
2496
2541
  mount.destroy?.();
2497
2542
  }
@@ -2508,6 +2553,10 @@ function attachDesktop(wm, element, options = {}) {
2508
2553
  for (const [, attached] of registry) {
2509
2554
  for (const dispose of attached.cleanup) dispose();
2510
2555
  for (const resizeHandle of attached.handles) resizeHandle.remove();
2556
+ if (attached.mount) {
2557
+ attached.mount.element.remove();
2558
+ attached.mount.destroy?.();
2559
+ }
2511
2560
  }
2512
2561
  registry.clear();
2513
2562
  for (const dispose of cleanup) dispose();
@@ -2581,5 +2630,5 @@ exports.defaultMessages = defaultMessages;
2581
2630
  exports.flipFromTarget = flipFromTarget;
2582
2631
  exports.flipToTarget = flipToTarget;
2583
2632
  exports.prefersReducedMotion = prefersReducedMotion;
2584
- //# sourceMappingURL=chunk-ZWUVWRUS.cjs.map
2585
- //# sourceMappingURL=chunk-ZWUVWRUS.cjs.map
2633
+ //# sourceMappingURL=chunk-VHS2YX3A.cjs.map
2634
+ //# sourceMappingURL=chunk-VHS2YX3A.cjs.map