microboard-temp 0.13.37 → 0.13.40

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.
@@ -21073,8 +21073,8 @@ class SpatialIndex {
21073
21073
  }
21074
21074
  this.subject.publish(this.items);
21075
21075
  };
21076
- remove(item) {
21077
- if ("index" in item && item.index) {
21076
+ remove(item, preserveChildren = false) {
21077
+ if (!preserveChildren && "index" in item && item.index) {
21078
21078
  item.removeChildItems(item.index.list());
21079
21079
  }
21080
21080
  this.itemsArray.splice(this.itemsArray.indexOf(item), 1);
@@ -21314,6 +21314,9 @@ class SpatialIndex {
21314
21314
  return false;
21315
21315
  }
21316
21316
  }
21317
+ if (item.itemType === "Group") {
21318
+ return false;
21319
+ }
21317
21320
  return true;
21318
21321
  });
21319
21322
  return [...clearItems, ...children];
@@ -21635,8 +21638,8 @@ class SimpleSpatialIndex {
21635
21638
  }
21636
21639
  this.subject.publish(this.items);
21637
21640
  };
21638
- remove(item) {
21639
- if ("index" in item && item.index) {
21641
+ remove(item, preserveChildren = false) {
21642
+ if (!preserveChildren && "index" in item && item.index) {
21640
21643
  item.removeChildItems(item.index.list());
21641
21644
  }
21642
21645
  this.itemsArray.splice(this.itemsArray.indexOf(item), 1);
@@ -22019,7 +22022,7 @@ class BaseItem extends Mbr {
22019
22022
  if (this.parent !== childId && this.getId() !== childId && !this.hasAncestor(childId)) {
22020
22023
  if (!this.index?.getById(childId) && foundItem) {
22021
22024
  const localMatrix = foundItem.transformation.toMatrix().toLocalOf(containerNestingMatrix);
22022
- this.board.items.index.remove(foundItem);
22025
+ this.board.items.index.remove(foundItem, true);
22023
22026
  foundItem.parent = this.getId();
22024
22027
  foundItem.onParentChanged(this.getId());
22025
22028
  foundItem.transformation.setLocalMatrix(localMatrix);
@@ -22041,7 +22044,7 @@ class BaseItem extends Mbr {
22041
22044
  if (this.parent !== childId && this.getId() !== childId) {
22042
22045
  if (foundItem) {
22043
22046
  const worldMatrix = foundItem.transformation.toMatrix().composeWith(containerNestingMatrix);
22044
- this.index?.remove(foundItem);
22047
+ this.index?.remove(foundItem, true);
22045
22048
  foundItem.parent = "Board";
22046
22049
  foundItem.onParentChanged("Board");
22047
22050
  foundItem.transformation.setLocalMatrix(worldMatrix);
@@ -48159,8 +48162,8 @@ class Tools extends ToolContext {
48159
48162
  const zoomOffset = 25;
48160
48163
  this.board.camera.zoomToFit(frameMbr, zoomOffset, 0);
48161
48164
  this.board.selection.removeAll();
48162
- this.board.selection.items.removeAll();
48163
- this.board.selection.items.add(frames[newFrameIndex]);
48165
+ this.board.selection.add(frames[newFrameIndex]);
48166
+ this.board.selection.setContext("SelectUnderPointer");
48164
48167
  localStorage.setItem(`lastVisitedFrame`, frames[newFrameIndex].getId());
48165
48168
  this.publish();
48166
48169
  }
@@ -49310,9 +49313,9 @@ function createDeck(event, board) {
49310
49313
  const deck = new Deck(board, "");
49311
49314
  deck.transformation.setLocal(cardsOrDecks[cardsOrDecks.length - 1].left, cardsOrDecks[cardsOrDecks.length - 1].top);
49312
49315
  const addedDeck = board.add(deck);
49313
- board.selection.items.removeAll();
49316
+ board.selection.removeAll();
49314
49317
  addedDeck.addChildItems(cardsOrDecks);
49315
- board.selection.items.add(addedDeck);
49318
+ board.selection.add(addedDeck);
49316
49319
  } else {
49317
49320
  let mainDeck = null;
49318
49321
  const cards = [];
@@ -49329,9 +49332,9 @@ function createDeck(event, board) {
49329
49332
  }
49330
49333
  }
49331
49334
  });
49332
- board.selection.items.removeAll();
49335
+ board.selection.removeAll();
49333
49336
  mainDeck.addChildItems(cards);
49334
- board.selection.items.add(mainDeck);
49337
+ board.selection.add(mainDeck);
49335
49338
  }
49336
49339
  }
49337
49340
  registerHotkey({
@@ -53401,7 +53404,7 @@ class BoardSelection {
53401
53404
  selectedItems.forEach((itemId) => {
53402
53405
  const item = this.board.items.getById(itemId);
53403
53406
  if (item) {
53404
- this.items.add(item);
53407
+ this.add(item);
53405
53408
  }
53406
53409
  });
53407
53410
  }
@@ -53488,13 +53491,22 @@ class BoardSelection {
53488
53491
  };
53489
53492
  decoratedItemObserver = this.decorateObserverToScheduleUpdate(this.itemObserver);
53490
53493
  add(value) {
53491
- this.items.add(value);
53492
- if (Array.isArray(value)) {
53493
- for (const item of value) {
53494
- item.subject.subscribe(this.itemObserver);
53495
- }
53496
- } else {
53497
- value.subject.subscribe(this.itemObserver);
53494
+ const values2 = Array.isArray(value) ? value : [value];
53495
+ const nextItems = this.normalizeSelectionItems([
53496
+ ...this.items.list(),
53497
+ ...values2
53498
+ ]);
53499
+ const currentIds = new Set(this.items.ids());
53500
+ const nextIds = new Set(nextItems.map((item) => item.getId()));
53501
+ const removed = this.items.list().filter((item) => !nextIds.has(item.getId()));
53502
+ const added = nextItems.filter((item) => !currentIds.has(item.getId()));
53503
+ if (removed.length > 0) {
53504
+ this.items.remove(removed);
53505
+ removed.forEach((item) => item.subject.unsubscribe(this.itemObserver));
53506
+ }
53507
+ if (added.length > 0) {
53508
+ this.items.add(added);
53509
+ added.forEach((item) => item.subject.subscribe(this.itemObserver));
53498
53510
  }
53499
53511
  this.subject.publish(this);
53500
53512
  this.itemsSubject.publish([]);
@@ -53574,15 +53586,54 @@ class BoardSelection {
53574
53586
  if (!item) {
53575
53587
  return null;
53576
53588
  }
53577
- if (!(item instanceof BaseItem) || item.parent === "Board") {
53578
- return item;
53579
- }
53580
- const parent = this.board.items.getById(item.parent);
53581
- if (parent instanceof Group) {
53582
- return parent;
53589
+ if (item instanceof Group) {
53590
+ return null;
53583
53591
  }
53584
53592
  return item;
53585
53593
  }
53594
+ getParentItem(item) {
53595
+ const resolved = typeof item === "string" ? this.board.items.getById(item) : item || null;
53596
+ if (!resolved || !(resolved instanceof BaseItem) || resolved.parent === "Board") {
53597
+ return null;
53598
+ }
53599
+ return this.board.items.getById(resolved.parent) || null;
53600
+ }
53601
+ isAncestor(candidate, descendant) {
53602
+ if (!(descendant instanceof BaseItem)) {
53603
+ return false;
53604
+ }
53605
+ let parentId = descendant.parent;
53606
+ while (parentId && parentId !== "Board") {
53607
+ if (parentId === candidate.getId()) {
53608
+ return true;
53609
+ }
53610
+ const parent = this.board.items.getById(parentId);
53611
+ if (!parent || parent.parent === parentId) {
53612
+ return false;
53613
+ }
53614
+ parentId = parent.parent;
53615
+ }
53616
+ return false;
53617
+ }
53618
+ normalizeSelectionItems(items) {
53619
+ const normalized = [];
53620
+ for (const item of items) {
53621
+ const alreadyCovered = normalized.some((selected) => selected.getId() === item.getId() || this.isAncestor(selected, item));
53622
+ if (alreadyCovered) {
53623
+ continue;
53624
+ }
53625
+ for (let i = normalized.length - 1;i >= 0; i -= 1) {
53626
+ if (this.isAncestor(item, normalized[i])) {
53627
+ normalized.splice(i, 1);
53628
+ }
53629
+ }
53630
+ normalized.push(item);
53631
+ }
53632
+ return normalized;
53633
+ }
53634
+ getCanvasSelectableItems(items) {
53635
+ return items.filter((item) => !(item instanceof Group));
53636
+ }
53586
53637
  selectUnderPointer() {
53587
53638
  this.removeAll();
53588
53639
  const stack = this.board.items.getUnderPointer();
@@ -53720,7 +53771,7 @@ class BoardSelection {
53720
53771
  }
53721
53772
  selectEnclosedBy(rect) {
53722
53773
  this.removeAll();
53723
- const list6 = this.board.items.getEnclosed(rect.left, rect.top, rect.right, rect.bottom);
53774
+ const list6 = this.getCanvasSelectableItems(this.board.items.getEnclosed(rect.left, rect.top, rect.right, rect.bottom));
53724
53775
  if (list6.length !== 0) {
53725
53776
  this.add(list6);
53726
53777
  this.setContext("SelectByRect");
@@ -53731,7 +53782,7 @@ class BoardSelection {
53731
53782
  selectEnclosedOrCrossedBy(rect) {
53732
53783
  this.removeAll();
53733
53784
  const enclosedFrames = this.board.items.getEnclosed(rect.left, rect.top, rect.right, rect.bottom).filter((item) => !item.transformation.isLocked);
53734
- const list6 = this.board.items.getEnclosedOrCrossed(rect.left, rect.top, rect.right, rect.bottom).filter((item) => (!(item instanceof Frame2) || enclosedFrames.includes(item)) && !item.transformation.isLocked);
53785
+ const list6 = this.getCanvasSelectableItems(this.board.items.getEnclosedOrCrossed(rect.left, rect.top, rect.right, rect.bottom).filter((item) => (!(item instanceof Frame2) || enclosedFrames.includes(item)) && !item.transformation.isLocked));
53735
53786
  if (list6.length !== 0) {
53736
53787
  this.add(list6);
53737
53788
  this.setContext("SelectByRect");
@@ -53930,6 +53981,79 @@ class BoardSelection {
53930
53981
  }
53931
53982
  return this.textToEdit;
53932
53983
  }
53984
+ getParent(item) {
53985
+ return this.getParentItem(item);
53986
+ }
53987
+ getParentChain(item) {
53988
+ const chain = [];
53989
+ let parent = this.getParentItem(item);
53990
+ while (parent) {
53991
+ chain.push(parent);
53992
+ parent = this.getParentItem(parent);
53993
+ }
53994
+ return chain;
53995
+ }
53996
+ getHierarchyPath(item) {
53997
+ const resolved = typeof item === "string" ? this.board.items.getById(item) : item || null;
53998
+ if (!resolved) {
53999
+ return [];
54000
+ }
54001
+ const nodes = [...this.getParentChain(resolved).reverse(), resolved];
54002
+ return nodes.filter((node2) => node2 instanceof BaseItem).map((node2) => ({
54003
+ id: node2.getId(),
54004
+ itemType: node2.itemType,
54005
+ parentId: node2.parent === "Board" ? null : node2.parent,
54006
+ hasChildren: (node2.getChildrenIds()?.length || 0) > 0,
54007
+ isCanvasSelectable: !(node2 instanceof Group)
54008
+ }));
54009
+ }
54010
+ getSelectionHierarchyPaths() {
54011
+ return this.items.list().map((item) => this.getHierarchyPath(item));
54012
+ }
54013
+ getCommonParent() {
54014
+ const selected = this.items.list();
54015
+ if (selected.length === 0) {
54016
+ return null;
54017
+ }
54018
+ const firstParent = this.getParentItem(selected[0]);
54019
+ if (!firstParent) {
54020
+ return null;
54021
+ }
54022
+ const firstParentId = firstParent.getId();
54023
+ const hasSameParent = selected.every((item) => this.getParentItem(item)?.getId() === firstParentId);
54024
+ return hasSameParent ? firstParent : null;
54025
+ }
54026
+ canPromoteSelectionToParent() {
54027
+ return this.getCommonParent() !== null;
54028
+ }
54029
+ selectParent() {
54030
+ const parent = this.getCommonParent();
54031
+ if (!parent) {
54032
+ return null;
54033
+ }
54034
+ this.removeAll();
54035
+ this.add(parent);
54036
+ this.setContext("SelectUnderPointer");
54037
+ return parent;
54038
+ }
54039
+ selectAncestorById(ancestorId) {
54040
+ const selected = this.items.list();
54041
+ if (selected.length === 0) {
54042
+ return null;
54043
+ }
54044
+ const ancestor = this.board.items.getById(ancestorId);
54045
+ if (!(ancestor instanceof BaseItem)) {
54046
+ return null;
54047
+ }
54048
+ const isSharedAncestor = selected.every((item) => item.getId() === ancestorId || this.isAncestor(ancestor, item));
54049
+ if (!isSharedAncestor) {
54050
+ return null;
54051
+ }
54052
+ this.removeAll();
54053
+ this.add(ancestor);
54054
+ this.setContext("SelectUnderPointer");
54055
+ return ancestor;
54056
+ }
53933
54057
  nestSelectedItems(unselectedItem, checkFrames = true) {
53934
54058
  const selected = this.board.selection.items.list();
53935
54059
  if (unselectedItem && !selected.find((item) => item.getId() === unselectedItem.getId())) {
package/dist/cjs/index.js CHANGED
@@ -21073,8 +21073,8 @@ class SpatialIndex {
21073
21073
  }
21074
21074
  this.subject.publish(this.items);
21075
21075
  };
21076
- remove(item) {
21077
- if ("index" in item && item.index) {
21076
+ remove(item, preserveChildren = false) {
21077
+ if (!preserveChildren && "index" in item && item.index) {
21078
21078
  item.removeChildItems(item.index.list());
21079
21079
  }
21080
21080
  this.itemsArray.splice(this.itemsArray.indexOf(item), 1);
@@ -21314,6 +21314,9 @@ class SpatialIndex {
21314
21314
  return false;
21315
21315
  }
21316
21316
  }
21317
+ if (item.itemType === "Group") {
21318
+ return false;
21319
+ }
21317
21320
  return true;
21318
21321
  });
21319
21322
  return [...clearItems, ...children];
@@ -21635,8 +21638,8 @@ class SimpleSpatialIndex {
21635
21638
  }
21636
21639
  this.subject.publish(this.items);
21637
21640
  };
21638
- remove(item) {
21639
- if ("index" in item && item.index) {
21641
+ remove(item, preserveChildren = false) {
21642
+ if (!preserveChildren && "index" in item && item.index) {
21640
21643
  item.removeChildItems(item.index.list());
21641
21644
  }
21642
21645
  this.itemsArray.splice(this.itemsArray.indexOf(item), 1);
@@ -22019,7 +22022,7 @@ class BaseItem extends Mbr {
22019
22022
  if (this.parent !== childId && this.getId() !== childId && !this.hasAncestor(childId)) {
22020
22023
  if (!this.index?.getById(childId) && foundItem) {
22021
22024
  const localMatrix = foundItem.transformation.toMatrix().toLocalOf(containerNestingMatrix);
22022
- this.board.items.index.remove(foundItem);
22025
+ this.board.items.index.remove(foundItem, true);
22023
22026
  foundItem.parent = this.getId();
22024
22027
  foundItem.onParentChanged(this.getId());
22025
22028
  foundItem.transformation.setLocalMatrix(localMatrix);
@@ -22041,7 +22044,7 @@ class BaseItem extends Mbr {
22041
22044
  if (this.parent !== childId && this.getId() !== childId) {
22042
22045
  if (foundItem) {
22043
22046
  const worldMatrix = foundItem.transformation.toMatrix().composeWith(containerNestingMatrix);
22044
- this.index?.remove(foundItem);
22047
+ this.index?.remove(foundItem, true);
22045
22048
  foundItem.parent = "Board";
22046
22049
  foundItem.onParentChanged("Board");
22047
22050
  foundItem.transformation.setLocalMatrix(worldMatrix);
@@ -48159,8 +48162,8 @@ class Tools extends ToolContext {
48159
48162
  const zoomOffset = 25;
48160
48163
  this.board.camera.zoomToFit(frameMbr, zoomOffset, 0);
48161
48164
  this.board.selection.removeAll();
48162
- this.board.selection.items.removeAll();
48163
- this.board.selection.items.add(frames[newFrameIndex]);
48165
+ this.board.selection.add(frames[newFrameIndex]);
48166
+ this.board.selection.setContext("SelectUnderPointer");
48164
48167
  localStorage.setItem(`lastVisitedFrame`, frames[newFrameIndex].getId());
48165
48168
  this.publish();
48166
48169
  }
@@ -49310,9 +49313,9 @@ function createDeck(event, board) {
49310
49313
  const deck = new Deck(board, "");
49311
49314
  deck.transformation.setLocal(cardsOrDecks[cardsOrDecks.length - 1].left, cardsOrDecks[cardsOrDecks.length - 1].top);
49312
49315
  const addedDeck = board.add(deck);
49313
- board.selection.items.removeAll();
49316
+ board.selection.removeAll();
49314
49317
  addedDeck.addChildItems(cardsOrDecks);
49315
- board.selection.items.add(addedDeck);
49318
+ board.selection.add(addedDeck);
49316
49319
  } else {
49317
49320
  let mainDeck = null;
49318
49321
  const cards = [];
@@ -49329,9 +49332,9 @@ function createDeck(event, board) {
49329
49332
  }
49330
49333
  }
49331
49334
  });
49332
- board.selection.items.removeAll();
49335
+ board.selection.removeAll();
49333
49336
  mainDeck.addChildItems(cards);
49334
- board.selection.items.add(mainDeck);
49337
+ board.selection.add(mainDeck);
49335
49338
  }
49336
49339
  }
49337
49340
  registerHotkey({
@@ -53401,7 +53404,7 @@ class BoardSelection {
53401
53404
  selectedItems.forEach((itemId) => {
53402
53405
  const item = this.board.items.getById(itemId);
53403
53406
  if (item) {
53404
- this.items.add(item);
53407
+ this.add(item);
53405
53408
  }
53406
53409
  });
53407
53410
  }
@@ -53488,13 +53491,22 @@ class BoardSelection {
53488
53491
  };
53489
53492
  decoratedItemObserver = this.decorateObserverToScheduleUpdate(this.itemObserver);
53490
53493
  add(value) {
53491
- this.items.add(value);
53492
- if (Array.isArray(value)) {
53493
- for (const item of value) {
53494
- item.subject.subscribe(this.itemObserver);
53495
- }
53496
- } else {
53497
- value.subject.subscribe(this.itemObserver);
53494
+ const values2 = Array.isArray(value) ? value : [value];
53495
+ const nextItems = this.normalizeSelectionItems([
53496
+ ...this.items.list(),
53497
+ ...values2
53498
+ ]);
53499
+ const currentIds = new Set(this.items.ids());
53500
+ const nextIds = new Set(nextItems.map((item) => item.getId()));
53501
+ const removed = this.items.list().filter((item) => !nextIds.has(item.getId()));
53502
+ const added = nextItems.filter((item) => !currentIds.has(item.getId()));
53503
+ if (removed.length > 0) {
53504
+ this.items.remove(removed);
53505
+ removed.forEach((item) => item.subject.unsubscribe(this.itemObserver));
53506
+ }
53507
+ if (added.length > 0) {
53508
+ this.items.add(added);
53509
+ added.forEach((item) => item.subject.subscribe(this.itemObserver));
53498
53510
  }
53499
53511
  this.subject.publish(this);
53500
53512
  this.itemsSubject.publish([]);
@@ -53574,15 +53586,54 @@ class BoardSelection {
53574
53586
  if (!item) {
53575
53587
  return null;
53576
53588
  }
53577
- if (!(item instanceof BaseItem) || item.parent === "Board") {
53578
- return item;
53579
- }
53580
- const parent = this.board.items.getById(item.parent);
53581
- if (parent instanceof Group) {
53582
- return parent;
53589
+ if (item instanceof Group) {
53590
+ return null;
53583
53591
  }
53584
53592
  return item;
53585
53593
  }
53594
+ getParentItem(item) {
53595
+ const resolved = typeof item === "string" ? this.board.items.getById(item) : item || null;
53596
+ if (!resolved || !(resolved instanceof BaseItem) || resolved.parent === "Board") {
53597
+ return null;
53598
+ }
53599
+ return this.board.items.getById(resolved.parent) || null;
53600
+ }
53601
+ isAncestor(candidate, descendant) {
53602
+ if (!(descendant instanceof BaseItem)) {
53603
+ return false;
53604
+ }
53605
+ let parentId = descendant.parent;
53606
+ while (parentId && parentId !== "Board") {
53607
+ if (parentId === candidate.getId()) {
53608
+ return true;
53609
+ }
53610
+ const parent = this.board.items.getById(parentId);
53611
+ if (!parent || parent.parent === parentId) {
53612
+ return false;
53613
+ }
53614
+ parentId = parent.parent;
53615
+ }
53616
+ return false;
53617
+ }
53618
+ normalizeSelectionItems(items) {
53619
+ const normalized = [];
53620
+ for (const item of items) {
53621
+ const alreadyCovered = normalized.some((selected) => selected.getId() === item.getId() || this.isAncestor(selected, item));
53622
+ if (alreadyCovered) {
53623
+ continue;
53624
+ }
53625
+ for (let i = normalized.length - 1;i >= 0; i -= 1) {
53626
+ if (this.isAncestor(item, normalized[i])) {
53627
+ normalized.splice(i, 1);
53628
+ }
53629
+ }
53630
+ normalized.push(item);
53631
+ }
53632
+ return normalized;
53633
+ }
53634
+ getCanvasSelectableItems(items) {
53635
+ return items.filter((item) => !(item instanceof Group));
53636
+ }
53586
53637
  selectUnderPointer() {
53587
53638
  this.removeAll();
53588
53639
  const stack = this.board.items.getUnderPointer();
@@ -53720,7 +53771,7 @@ class BoardSelection {
53720
53771
  }
53721
53772
  selectEnclosedBy(rect) {
53722
53773
  this.removeAll();
53723
- const list6 = this.board.items.getEnclosed(rect.left, rect.top, rect.right, rect.bottom);
53774
+ const list6 = this.getCanvasSelectableItems(this.board.items.getEnclosed(rect.left, rect.top, rect.right, rect.bottom));
53724
53775
  if (list6.length !== 0) {
53725
53776
  this.add(list6);
53726
53777
  this.setContext("SelectByRect");
@@ -53731,7 +53782,7 @@ class BoardSelection {
53731
53782
  selectEnclosedOrCrossedBy(rect) {
53732
53783
  this.removeAll();
53733
53784
  const enclosedFrames = this.board.items.getEnclosed(rect.left, rect.top, rect.right, rect.bottom).filter((item) => !item.transformation.isLocked);
53734
- const list6 = this.board.items.getEnclosedOrCrossed(rect.left, rect.top, rect.right, rect.bottom).filter((item) => (!(item instanceof Frame2) || enclosedFrames.includes(item)) && !item.transformation.isLocked);
53785
+ const list6 = this.getCanvasSelectableItems(this.board.items.getEnclosedOrCrossed(rect.left, rect.top, rect.right, rect.bottom).filter((item) => (!(item instanceof Frame2) || enclosedFrames.includes(item)) && !item.transformation.isLocked));
53735
53786
  if (list6.length !== 0) {
53736
53787
  this.add(list6);
53737
53788
  this.setContext("SelectByRect");
@@ -53930,6 +53981,79 @@ class BoardSelection {
53930
53981
  }
53931
53982
  return this.textToEdit;
53932
53983
  }
53984
+ getParent(item) {
53985
+ return this.getParentItem(item);
53986
+ }
53987
+ getParentChain(item) {
53988
+ const chain = [];
53989
+ let parent = this.getParentItem(item);
53990
+ while (parent) {
53991
+ chain.push(parent);
53992
+ parent = this.getParentItem(parent);
53993
+ }
53994
+ return chain;
53995
+ }
53996
+ getHierarchyPath(item) {
53997
+ const resolved = typeof item === "string" ? this.board.items.getById(item) : item || null;
53998
+ if (!resolved) {
53999
+ return [];
54000
+ }
54001
+ const nodes = [...this.getParentChain(resolved).reverse(), resolved];
54002
+ return nodes.filter((node2) => node2 instanceof BaseItem).map((node2) => ({
54003
+ id: node2.getId(),
54004
+ itemType: node2.itemType,
54005
+ parentId: node2.parent === "Board" ? null : node2.parent,
54006
+ hasChildren: (node2.getChildrenIds()?.length || 0) > 0,
54007
+ isCanvasSelectable: !(node2 instanceof Group)
54008
+ }));
54009
+ }
54010
+ getSelectionHierarchyPaths() {
54011
+ return this.items.list().map((item) => this.getHierarchyPath(item));
54012
+ }
54013
+ getCommonParent() {
54014
+ const selected = this.items.list();
54015
+ if (selected.length === 0) {
54016
+ return null;
54017
+ }
54018
+ const firstParent = this.getParentItem(selected[0]);
54019
+ if (!firstParent) {
54020
+ return null;
54021
+ }
54022
+ const firstParentId = firstParent.getId();
54023
+ const hasSameParent = selected.every((item) => this.getParentItem(item)?.getId() === firstParentId);
54024
+ return hasSameParent ? firstParent : null;
54025
+ }
54026
+ canPromoteSelectionToParent() {
54027
+ return this.getCommonParent() !== null;
54028
+ }
54029
+ selectParent() {
54030
+ const parent = this.getCommonParent();
54031
+ if (!parent) {
54032
+ return null;
54033
+ }
54034
+ this.removeAll();
54035
+ this.add(parent);
54036
+ this.setContext("SelectUnderPointer");
54037
+ return parent;
54038
+ }
54039
+ selectAncestorById(ancestorId) {
54040
+ const selected = this.items.list();
54041
+ if (selected.length === 0) {
54042
+ return null;
54043
+ }
54044
+ const ancestor = this.board.items.getById(ancestorId);
54045
+ if (!(ancestor instanceof BaseItem)) {
54046
+ return null;
54047
+ }
54048
+ const isSharedAncestor = selected.every((item) => item.getId() === ancestorId || this.isAncestor(ancestor, item));
54049
+ if (!isSharedAncestor) {
54050
+ return null;
54051
+ }
54052
+ this.removeAll();
54053
+ this.add(ancestor);
54054
+ this.setContext("SelectUnderPointer");
54055
+ return ancestor;
54056
+ }
53933
54057
  nestSelectedItems(unselectedItem, checkFrames = true) {
53934
54058
  const selected = this.board.selection.items.list();
53935
54059
  if (unselectedItem && !selected.find((item) => item.getId() === unselectedItem.getId())) {