@surdeddd/wmkit 0.4.2 → 0.5.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.
Files changed (41) hide show
  1. package/README.md +1 -0
  2. package/README.ru.md +1 -0
  3. package/dist/angular.cjs +3 -3
  4. package/dist/angular.d.cts +2 -2
  5. package/dist/angular.d.ts +2 -2
  6. package/dist/angular.js +1 -1
  7. package/dist/{binder-B2A2IZGh.d.ts → binder-Ca3GOfZX.d.ts} +5 -1
  8. package/dist/{binder-Dl07SXIM.d.cts → binder-EBroZTRw.d.cts} +5 -1
  9. package/dist/{chunk-GGDF2EWV.js → chunk-L43XBN44.js} +235 -14
  10. package/dist/chunk-L43XBN44.js.map +1 -0
  11. package/dist/{chunk-GLBVT4AQ.cjs → chunk-RXAMUBUJ.cjs} +235 -14
  12. package/dist/chunk-RXAMUBUJ.cjs.map +1 -0
  13. package/dist/index.cjs +18 -18
  14. package/dist/index.d.cts +4 -4
  15. package/dist/index.d.ts +4 -4
  16. package/dist/index.js +1 -1
  17. package/dist/persist.d.cts +1 -1
  18. package/dist/persist.d.ts +1 -1
  19. package/dist/popout.d.cts +1 -1
  20. package/dist/popout.d.ts +1 -1
  21. package/dist/react.cjs +3 -3
  22. package/dist/react.d.cts +2 -2
  23. package/dist/react.d.ts +2 -2
  24. package/dist/react.js +1 -1
  25. package/dist/solid.cjs +3 -3
  26. package/dist/solid.d.cts +2 -2
  27. package/dist/solid.d.ts +2 -2
  28. package/dist/solid.js +1 -1
  29. package/dist/svelte.cjs +3 -3
  30. package/dist/svelte.d.cts +2 -2
  31. package/dist/svelte.d.ts +2 -2
  32. package/dist/svelte.js +1 -1
  33. package/dist/{types-t6pyVYKN.d.cts → types-LP7Inhxx.d.cts} +18 -0
  34. package/dist/{types-t6pyVYKN.d.ts → types-LP7Inhxx.d.ts} +18 -0
  35. package/dist/vue.cjs +3 -3
  36. package/dist/vue.d.cts +2 -2
  37. package/dist/vue.d.ts +2 -2
  38. package/dist/vue.js +1 -1
  39. package/package.json +7 -7
  40. package/dist/chunk-GGDF2EWV.js.map +0 -1
  41. package/dist/chunk-GLBVT4AQ.cjs.map +0 -1
@@ -199,6 +199,8 @@ function createWindowManager(options = {}) {
199
199
  let focusedId = null;
200
200
  let viewport = options.viewport ?? { width: 0, height: 0 };
201
201
  let workspace = normalizeWorkspace(options.workspace, 0);
202
+ let activeTabs = {};
203
+ let groupCounter = 0;
202
204
  let seq = 0;
203
205
  let idCounter = 0;
204
206
  let cascadeIndex = 0;
@@ -217,7 +219,7 @@ function createWindowManager(options = {}) {
217
219
  const layouts = /* @__PURE__ */ new Map();
218
220
  function getState() {
219
221
  if (!snapshot) {
220
- snapshot = { windows, order, focusedId, viewport, workspace };
222
+ snapshot = { windows, order, focusedId, viewport, workspace, groups: buildGroups() };
221
223
  }
222
224
  return snapshot;
223
225
  }
@@ -269,11 +271,54 @@ function createWindowManager(options = {}) {
269
271
  function onActiveWorkspace(win) {
270
272
  return win.workspace === workspace;
271
273
  }
274
+ function membersOf(groupId) {
275
+ return order.filter((entry) => windows[entry].groupId === groupId);
276
+ }
277
+ function isVisibleTab(win) {
278
+ return win.groupId === null || activeTabs[win.groupId] === win.id;
279
+ }
280
+ function buildGroups() {
281
+ const result = {};
282
+ for (const [groupId, activeId] of Object.entries(activeTabs)) {
283
+ result[groupId] = { id: groupId, activeId, members: membersOf(groupId) };
284
+ }
285
+ return result;
286
+ }
287
+ function syncGroup(source) {
288
+ if (source.groupId === null) return;
289
+ for (const id of membersOf(source.groupId)) {
290
+ if (id === source.id) continue;
291
+ const member = windows[id];
292
+ if (boundsEqual(member.bounds, source.bounds) && member.stage === source.stage && member.snapZone === source.snapZone && member.layer === source.layer && member.workspace === source.workspace) {
293
+ continue;
294
+ }
295
+ setWindow({
296
+ ...member,
297
+ bounds: source.bounds,
298
+ stage: source.stage,
299
+ snapZone: source.snapZone,
300
+ restoreBounds: source.restoreBounds,
301
+ restoreStage: source.restoreStage,
302
+ layer: source.layer,
303
+ workspace: source.workspace
304
+ });
305
+ }
306
+ }
307
+ function dissolveIfOrphaned(groupId) {
308
+ const members = membersOf(groupId);
309
+ if (members.length >= 2) return;
310
+ for (const id of members) {
311
+ setWindow({ ...windows[id], groupId: null });
312
+ }
313
+ const { [groupId]: _dropped, ...rest } = activeTabs;
314
+ activeTabs = rest;
315
+ }
272
316
  function topModalId() {
273
317
  for (let i = order.length - 1; i >= 0; i -= 1) {
274
318
  const win = windows[order[i]];
275
- if (win.layer === "modal" && win.stage !== "minimized" && onActiveWorkspace(win))
319
+ if (win.layer === "modal" && win.stage !== "minimized" && onActiveWorkspace(win) && isVisibleTab(win)) {
276
320
  return win.id;
321
+ }
277
322
  }
278
323
  return null;
279
324
  }
@@ -281,7 +326,7 @@ function createWindowManager(options = {}) {
281
326
  const modal = topModalId();
282
327
  return order.filter((id) => {
283
328
  const win = windows[id];
284
- if (win.stage === "minimized" || !onActiveWorkspace(win)) return false;
329
+ if (win.stage === "minimized" || !onActiveWorkspace(win) || !isVisibleTab(win)) return false;
285
330
  if (modal && win.layer !== "modal") return false;
286
331
  return true;
287
332
  });
@@ -344,6 +389,7 @@ function createWindowManager(options = {}) {
344
389
  snapZone: null,
345
390
  layer: init.layer ?? "normal",
346
391
  workspace: normalizeWorkspace(init.workspace, workspace),
392
+ groupId: null,
347
393
  minSize,
348
394
  maxSize,
349
395
  aspectRatio,
@@ -387,6 +433,13 @@ function createWindowManager(options = {}) {
387
433
  const win = windows[id];
388
434
  if (!win) return false;
389
435
  removeWindow(id);
436
+ if (win.groupId !== null) {
437
+ const remaining = membersOf(win.groupId);
438
+ if (activeTabs[win.groupId] === id && remaining[0]) {
439
+ activeTabs = { ...activeTabs, [win.groupId]: remaining[0] };
440
+ }
441
+ dissolveIfOrphaned(win.groupId);
442
+ }
390
443
  queueEvent(() => emitter.emit("close", { window: win }));
391
444
  if (focusedId === id) {
392
445
  focusTop();
@@ -403,6 +456,7 @@ function createWindowManager(options = {}) {
403
456
  const win = windows[id];
404
457
  if (!win) return false;
405
458
  if (!onActiveWorkspace(win)) setWorkspace(win.workspace);
459
+ if (!isVisibleTab(win)) activateTab(id);
406
460
  const modal = topModalId();
407
461
  if (modal && modal !== id && win.layer !== "modal") {
408
462
  const modalWin = windows[modal];
@@ -462,6 +516,7 @@ function createWindowManager(options = {}) {
462
516
  const next = build(win);
463
517
  if (!next) return false;
464
518
  setWindow(next);
519
+ syncGroup(next);
465
520
  queueEvent(() => emitter.emit("stage", { window: next, previous: win.stage }));
466
521
  commit();
467
522
  return true;
@@ -571,6 +626,7 @@ function createWindowManager(options = {}) {
571
626
  if (boundsEqual(bounds, win.bounds)) return true;
572
627
  const next = { ...win, bounds };
573
628
  setWindow(next);
629
+ syncGroup(next);
574
630
  queueEvent(() => emitter.emit("move", { window: next }));
575
631
  commit();
576
632
  return true;
@@ -592,6 +648,7 @@ function createWindowManager(options = {}) {
592
648
  if (boundsEqual(bounds, win.bounds) && !becameNormal) return true;
593
649
  const next = becameNormal ? { ...win, stage: "normal", snapZone: null, restoreBounds: null, bounds } : { ...win, bounds };
594
650
  setWindow(next);
651
+ syncGroup(next);
595
652
  if (becameNormal) queueEvent(() => emitter.emit("stage", { window: next, previous: "snapped" }));
596
653
  queueEvent(() => emitter.emit("resize", { window: next }));
597
654
  commit();
@@ -619,6 +676,7 @@ function createWindowManager(options = {}) {
619
676
  const resized = size.width !== next.bounds.width || size.height !== next.bounds.height;
620
677
  const finalWin = resized ? { ...next, bounds: { ...next.bounds, ...size } } : next;
621
678
  setWindow(finalWin);
679
+ syncGroup(finalWin);
622
680
  if (patch.layer && patch.layer !== win.layer) {
623
681
  order = sortByLayer(order);
624
682
  queueEvent(() => emitter.emit("order", { order }));
@@ -660,6 +718,7 @@ function createWindowManager(options = {}) {
660
718
  if (target === win.workspace) return false;
661
719
  const updated = { ...win, workspace: target };
662
720
  setWindow(updated);
721
+ syncGroup(updated);
663
722
  if (!onActiveWorkspace(updated) && focusedId === id) {
664
723
  focusTop();
665
724
  if (focusedId) emitFocus(windows[focusedId], id);
@@ -672,6 +731,77 @@ function createWindowManager(options = {}) {
672
731
  commit();
673
732
  return true;
674
733
  }
734
+ function emitGroup(groupId, previous) {
735
+ const members = membersOf(groupId);
736
+ const activeId = activeTabs[groupId];
737
+ queueEvent(() => emitter.emit("group", { groupId, members, activeId, previous }));
738
+ }
739
+ function group(ids) {
740
+ const seeds = ids.filter((id, index) => windows[id] && ids.indexOf(id) === index);
741
+ const host = seeds[0] ? windows[seeds[0]] : null;
742
+ if (!host) return null;
743
+ const expanded = [];
744
+ for (const id of seeds) {
745
+ const win = windows[id];
746
+ const siblings = win.groupId === null ? [id] : membersOf(win.groupId);
747
+ for (const entry of siblings) if (!expanded.includes(entry)) expanded.push(entry);
748
+ }
749
+ if (expanded.length < 2) return null;
750
+ const groupId = `${idPrefix}-group-${++groupCounter}`;
751
+ const retired = /* @__PURE__ */ new Set();
752
+ for (const id of expanded) {
753
+ const win = windows[id];
754
+ if (win.groupId !== null) retired.add(win.groupId);
755
+ setWindow({
756
+ ...win,
757
+ groupId,
758
+ bounds: host.bounds,
759
+ stage: host.stage,
760
+ snapZone: host.snapZone,
761
+ restoreBounds: host.restoreBounds,
762
+ restoreStage: host.restoreStage,
763
+ layer: host.layer,
764
+ workspace: host.workspace
765
+ });
766
+ }
767
+ const next = { ...activeTabs, [groupId]: host.id };
768
+ for (const old of retired) delete next[old];
769
+ activeTabs = next;
770
+ raise(host.id);
771
+ emitGroup(groupId, null);
772
+ queueEvent(() => emitter.emit("order", { order }));
773
+ commit();
774
+ if (onActiveWorkspace(host) && host.stage !== "minimized") focus(host.id);
775
+ return groupId;
776
+ }
777
+ function ungroup(id) {
778
+ const win = windows[id];
779
+ if (!win?.groupId) return false;
780
+ const groupId = win.groupId;
781
+ const wasActive = activeTabs[groupId] === id;
782
+ setWindow({ ...win, groupId: null });
783
+ const remaining = membersOf(groupId);
784
+ if (wasActive) activeTabs = { ...activeTabs, [groupId]: remaining[0] };
785
+ dissolveIfOrphaned(groupId);
786
+ if (membersOf(groupId).length >= 2) emitGroup(groupId, wasActive ? id : null);
787
+ commit();
788
+ focus(id);
789
+ return true;
790
+ }
791
+ function activateTab(id) {
792
+ const win = windows[id];
793
+ if (!win?.groupId) return false;
794
+ const groupId = win.groupId;
795
+ const previous = activeTabs[groupId];
796
+ if (previous === id) return false;
797
+ activeTabs = { ...activeTabs, [groupId]: id };
798
+ emitGroup(groupId, previous);
799
+ commit();
800
+ return true;
801
+ }
802
+ function groupMembers(groupId) {
803
+ return membersOf(groupId).map((id) => windows[id]);
804
+ }
675
805
  function sendToBack(id) {
676
806
  const win = windows[id];
677
807
  if (!win) return false;
@@ -703,10 +833,10 @@ function createWindowManager(options = {}) {
703
833
  );
704
834
  }
705
835
  function minimized() {
706
- return Object.values(windows).filter((win) => win.stage === "minimized" && onActiveWorkspace(win)).sort((a, b) => a.openedSeq - b.openedSeq);
836
+ return Object.values(windows).filter((win) => win.stage === "minimized" && onActiveWorkspace(win) && isVisibleTab(win)).sort((a, b) => a.openedSeq - b.openedSeq);
707
837
  }
708
838
  function captureEntry() {
709
- return { windows, order, focusedId, workspace };
839
+ return { windows, order, focusedId, workspace, activeTabs };
710
840
  }
711
841
  function recordHistory() {
712
842
  if (!historyDirty) return;
@@ -768,6 +898,7 @@ function createWindowManager(options = {}) {
768
898
  windows = entry.windows;
769
899
  order = [...entry.order];
770
900
  focusedId = entry.focusedId;
901
+ activeTabs = entry.activeTabs;
771
902
  const previousWorkspace = workspace;
772
903
  workspace = entry.workspace;
773
904
  if (workspace !== previousWorkspace) {
@@ -898,7 +1029,8 @@ function createWindowManager(options = {}) {
898
1029
  })),
899
1030
  order: [...order],
900
1031
  focusedId,
901
- workspace
1032
+ workspace,
1033
+ activeTabs: { ...activeTabs }
902
1034
  };
903
1035
  }
904
1036
  function isBounds(value) {
@@ -953,6 +1085,7 @@ function createWindowManager(options = {}) {
953
1085
  snapZone: ZONES.includes(raw.snapZone) ? raw.snapZone : null,
954
1086
  layer: raw.layer,
955
1087
  workspace: normalizeWorkspace(raw.workspace, 0),
1088
+ groupId: typeof raw.groupId === "string" && raw.groupId.length > 0 ? raw.groupId : null,
956
1089
  minSize: isSize(raw.minSize) ? { ...raw.minSize } : { width: 160, height: 100 },
957
1090
  maxSize: readMaxSize(raw.maxSize),
958
1091
  aspectRatio: typeof raw.aspectRatio === "number" && Number.isFinite(raw.aspectRatio) && raw.aspectRatio > 0 ? raw.aspectRatio : null,
@@ -994,7 +1127,18 @@ function createWindowManager(options = {}) {
994
1127
  if (focusedCandidate && (focusedCandidate.stage === "minimized" || !onActiveWorkspace(focusedCandidate))) {
995
1128
  focusedId = null;
996
1129
  }
997
- if (!focusedId) focusTop();
1130
+ const restoredTabs = {};
1131
+ const rawTabs = data.activeTabs;
1132
+ for (const id of order) {
1133
+ const groupId = windows[id].groupId;
1134
+ if (groupId === null || restoredTabs[groupId]) continue;
1135
+ const wanted = typeof rawTabs === "object" && rawTabs !== null ? rawTabs[groupId] : void 0;
1136
+ const members = membersOf(groupId);
1137
+ restoredTabs[groupId] = typeof wanted === "string" && members.includes(wanted) ? wanted : members[0];
1138
+ }
1139
+ activeTabs = restoredTabs;
1140
+ for (const groupId of Object.keys(restoredTabs)) dissolveIfOrphaned(groupId);
1141
+ if (!focusedId || !isVisibleTab(windows[focusedId])) focusTop();
998
1142
  const modal = topModalId();
999
1143
  if (modal) {
1000
1144
  const focusedWin = focusedId ? windows[focusedId] : null;
@@ -1048,6 +1192,10 @@ function createWindowManager(options = {}) {
1048
1192
  workspace: () => workspace,
1049
1193
  setWorkspace: (next) => transact(() => setWorkspace(next)),
1050
1194
  moveToWorkspace: (id, next) => transact(() => moveToWorkspace(id, next)),
1195
+ group: (ids) => transact(() => group(ids)),
1196
+ ungroup: (id) => transact(() => ungroup(id)),
1197
+ activateTab: (id) => transact(() => activateTab(id)),
1198
+ groupMembers,
1051
1199
  batch: (run) => transact(run),
1052
1200
  serialize,
1053
1201
  hydrate: (data) => transact(() => hydrate(data)),
@@ -1237,6 +1385,11 @@ function createDragStarter(ctx) {
1237
1385
  restored: win.stage === "normal",
1238
1386
  moved: false,
1239
1387
  zone: null,
1388
+ groupTarget: null,
1389
+ hoverId: null,
1390
+ hoverTimer: 0,
1391
+ clientX: event.clientX,
1392
+ clientY: event.clientY,
1240
1393
  raf: 0,
1241
1394
  pendingX: 0,
1242
1395
  pendingY: 0,
@@ -1245,6 +1398,18 @@ function createDragStarter(ctx) {
1245
1398
  }
1246
1399
  };
1247
1400
  const el = ctx.windowElement(id);
1401
+ function armGroup(target2) {
1402
+ session.groupTarget = target2;
1403
+ ctx.markGroupTarget(target2);
1404
+ }
1405
+ function clearHover() {
1406
+ if (session.hoverTimer !== 0) {
1407
+ view.clearTimeout(session.hoverTimer);
1408
+ session.hoverTimer = 0;
1409
+ }
1410
+ session.groupTarget = null;
1411
+ ctx.markGroupTarget(null);
1412
+ }
1248
1413
  function flush() {
1249
1414
  if (!session.hasPending || ctx.currentDrag() !== session) return;
1250
1415
  session.hasPending = false;
@@ -1292,6 +1457,20 @@ function createDragStarter(ctx) {
1292
1457
  nextY = magnet.y;
1293
1458
  }
1294
1459
  wm.move(id, nextX, nextY);
1460
+ const candidate = ctx.groupTarget(session.clientX, session.clientY, id);
1461
+ if (candidate !== session.hoverId) {
1462
+ session.hoverId = candidate;
1463
+ clearHover();
1464
+ if (candidate) {
1465
+ if (ctx.groupDwell <= 0) armGroup(candidate);
1466
+ else session.hoverTimer = view.setTimeout(() => armGroup(candidate), ctx.groupDwell);
1467
+ }
1468
+ }
1469
+ if (session.groupTarget) {
1470
+ session.zone = null;
1471
+ ctx.hidePreview();
1472
+ return;
1473
+ }
1295
1474
  if (ctx.snapEnabled && current.snappable) {
1296
1475
  const viewport = wm.getState().viewport;
1297
1476
  const rawZone = detectSnapZone(session.pendingX, session.pendingY, viewport, ctx.snapDetect);
@@ -1324,6 +1503,8 @@ function createDragStarter(ctx) {
1324
1503
  }
1325
1504
  session.pendingX = movePoint.x;
1326
1505
  session.pendingY = movePoint.y;
1506
+ session.clientX = moveEvent.clientX;
1507
+ session.clientY = moveEvent.clientY;
1327
1508
  session.hasPending = true;
1328
1509
  if (session.raf === 0) session.raf = view.requestAnimationFrame(flush);
1329
1510
  }
@@ -1358,6 +1539,8 @@ function createDragStarter(ctx) {
1358
1539
  wm.move(id, session.startBounds.x, session.startBounds.y);
1359
1540
  }
1360
1541
  }
1542
+ } else if (session.moved && session.groupTarget) {
1543
+ if (wm.group([session.groupTarget, id])) wm.activateTab(id);
1361
1544
  } else if (session.moved && session.zone) {
1362
1545
  if (session.zone === "maximize") wm.maximize(id);
1363
1546
  else wm.snap(id, session.zone);
@@ -1377,6 +1560,8 @@ function createDragStarter(ctx) {
1377
1560
  el.style.willChange = "";
1378
1561
  }
1379
1562
  ctx.hidePreview();
1563
+ if (session.hoverTimer !== 0) view.clearTimeout(session.hoverTimer);
1564
+ ctx.markGroupTarget(null);
1380
1565
  if (cancelled) wm.abortInteraction();
1381
1566
  else wm.endInteraction();
1382
1567
  }
@@ -1546,6 +1731,8 @@ function attachDesktop(wm, element, options = {}) {
1546
1731
  const doc = element.ownerDocument;
1547
1732
  const view = windowOf(element);
1548
1733
  const coarsePointer = typeof view.matchMedia === "function" && view.matchMedia("(pointer: coarse)").matches;
1734
+ const groupingEnabled = options.grouping !== false;
1735
+ const groupDwell = (typeof options.grouping === "object" ? options.grouping.dwell : void 0) ?? 420;
1549
1736
  const snapEnabled = options.snap !== false;
1550
1737
  const snapOptions = typeof options.snap === "object" ? options.snap : {};
1551
1738
  const snapPreviewEnabled = snapOptions.preview !== false;
@@ -1569,6 +1756,7 @@ function attachDesktop(wm, element, options = {}) {
1569
1756
  let lastOrder = null;
1570
1757
  let lastFocused = null;
1571
1758
  let drag = null;
1759
+ let groupTargetId = null;
1572
1760
  let cachedRect = null;
1573
1761
  let rectUsers = 0;
1574
1762
  let announcer = null;
@@ -1640,6 +1828,29 @@ function attachDesktop(wm, element, options = {}) {
1640
1828
  hitEdge,
1641
1829
  hitCorner,
1642
1830
  magnetThreshold,
1831
+ groupDwell,
1832
+ groupTarget(clientX, clientY, selfId) {
1833
+ if (!groupingEnabled || typeof doc.elementsFromPoint !== "function") return null;
1834
+ for (const node of doc.elementsFromPoint(clientX, clientY)) {
1835
+ const handle = node.closest?.("[data-wm-drag]");
1836
+ const host = handle?.closest("[data-wm-window]");
1837
+ const id = host?.dataset.wmWindow;
1838
+ if (id && id !== selfId && registry.has(id)) return id;
1839
+ }
1840
+ return null;
1841
+ },
1842
+ markGroupTarget(id) {
1843
+ if (groupTargetId === id) return;
1844
+ if (groupTargetId) {
1845
+ const previous = registry.get(groupTargetId);
1846
+ if (previous) delete previous.element.dataset.wmTabTarget;
1847
+ }
1848
+ groupTargetId = id;
1849
+ if (id) {
1850
+ const next = registry.get(id);
1851
+ if (next) next.element.dataset.wmTabTarget = "";
1852
+ }
1853
+ },
1643
1854
  currentDrag: () => drag,
1644
1855
  claimDrag(session) {
1645
1856
  drag = session;
@@ -1657,18 +1868,25 @@ function attachDesktop(wm, element, options = {}) {
1657
1868
  observer.observe(element);
1658
1869
  cleanup.push(() => observer.disconnect());
1659
1870
  }
1660
- function syncWindow(attached, win, zIndex, activeWorkspace) {
1871
+ function syncWindow(attached, win, zIndex, activeWorkspace, activeTab) {
1661
1872
  const el = attached.element;
1662
1873
  const firstSync = attached.lastState === null;
1663
1874
  if (firstSync) el.style.transition = "none";
1664
- if (attached.lastState !== win || attached.lastWorkspace !== activeWorkspace) {
1875
+ if (attached.lastState !== win || attached.lastWorkspace !== activeWorkspace || attached.lastTab !== activeTab) {
1665
1876
  el.style.transform = `translate3d(${win.bounds.x}px, ${win.bounds.y}px, 0)`;
1666
1877
  el.style.width = `${win.bounds.width}px`;
1667
1878
  el.style.height = `${win.bounds.height}px`;
1668
1879
  el.dataset.wmStage = win.stage;
1669
1880
  el.dataset.wmLayer = win.layer;
1670
1881
  el.dataset.wmWorkspace = String(win.workspace);
1671
- const hide = win.stage === "minimized" || win.workspace !== activeWorkspace;
1882
+ if (win.groupId === null) {
1883
+ delete el.dataset.wmGroup;
1884
+ delete el.dataset.wmTab;
1885
+ } else {
1886
+ el.dataset.wmGroup = win.groupId;
1887
+ el.dataset.wmTab = activeTab ? "active" : "inactive";
1888
+ }
1889
+ const hide = win.stage === "minimized" || win.workspace !== activeWorkspace || !activeTab;
1672
1890
  if (hide && !el.hidden && el.contains(doc.activeElement)) {
1673
1891
  element.focus({ preventScroll: true });
1674
1892
  }
@@ -1686,6 +1904,7 @@ function attachDesktop(wm, element, options = {}) {
1686
1904
  }
1687
1905
  attached.lastState = win;
1688
1906
  attached.lastWorkspace = activeWorkspace;
1907
+ attached.lastTab = activeTab;
1689
1908
  }
1690
1909
  if (attached.lastZ !== zIndex) {
1691
1910
  el.style.zIndex = String(zIndex + 1);
@@ -1703,8 +1922,9 @@ function attachDesktop(wm, element, options = {}) {
1703
1922
  const attached = registry.get(id);
1704
1923
  const win = state.windows[id];
1705
1924
  if (!attached || !win) return;
1706
- if (orderChanged || attached.lastState !== win || attached.lastWorkspace !== state.workspace) {
1707
- syncWindow(attached, win, index, state.workspace);
1925
+ const activeTab = win.groupId === null || state.groups[win.groupId]?.activeId === win.id;
1926
+ if (orderChanged || attached.lastState !== win || attached.lastWorkspace !== state.workspace || attached.lastTab !== activeTab) {
1927
+ syncWindow(attached, win, index, state.workspace, activeTab);
1708
1928
  }
1709
1929
  });
1710
1930
  if (state.focusedId !== lastFocused) {
@@ -1807,6 +2027,7 @@ function attachDesktop(wm, element, options = {}) {
1807
2027
  lastState: null,
1808
2028
  lastZ: -1,
1809
2029
  lastWorkspace: -1,
2030
+ lastTab: true,
1810
2031
  cleanup: []
1811
2032
  };
1812
2033
  windowElement.dataset.wmWindow = id;
@@ -2046,5 +2267,5 @@ exports.flipToTarget = flipToTarget;
2046
2267
  exports.magnetize = magnetize;
2047
2268
  exports.prefersReducedMotion = prefersReducedMotion;
2048
2269
  exports.zoneBounds = zoneBounds;
2049
- //# sourceMappingURL=chunk-GLBVT4AQ.cjs.map
2050
- //# sourceMappingURL=chunk-GLBVT4AQ.cjs.map
2270
+ //# sourceMappingURL=chunk-RXAMUBUJ.cjs.map
2271
+ //# sourceMappingURL=chunk-RXAMUBUJ.cjs.map