microboard-temp 0.10.2 → 0.11.1

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.
@@ -1230,6 +1230,24 @@ class Matrix {
1230
1230
  const { translateX, translateY, scaleX, scaleY, shearX, shearY } = matrix;
1231
1231
  return this.translateX === translateX && this.translateY === translateY && this.scaleX === scaleX && this.scaleY === scaleY && this.shearX === shearX && this.shearY === shearY;
1232
1232
  }
1233
+ composeWith(parent) {
1234
+ const result = parent.copy();
1235
+ result.multiplyByMatrix(this);
1236
+ return result;
1237
+ }
1238
+ toLocalOf(parent) {
1239
+ const result = parent.getInverse();
1240
+ result.multiplyByMatrix(this);
1241
+ return result;
1242
+ }
1243
+ applyInverseLinear(dx, dy) {
1244
+ const { scaleX, scaleY, shearX, shearY } = this;
1245
+ const denom = scaleX * scaleY - shearX * shearY;
1246
+ return {
1247
+ x: (scaleY * dx - shearX * dy) / denom,
1248
+ y: (-shearY * dx + scaleX * dy) / denom
1249
+ };
1250
+ }
1233
1251
  }
1234
1252
 
1235
1253
  // src/Subject.ts
@@ -17966,6 +17984,15 @@ class Transformation {
17966
17984
  getRotation() {
17967
17985
  return this.rotate;
17968
17986
  }
17987
+ setLocalMatrix(matrix) {
17988
+ this.previous = this._matrix.copy();
17989
+ this._matrix = matrix.copy();
17990
+ this.subject.publish(this, {
17991
+ class: "Transformation",
17992
+ method: "applyMatrix",
17993
+ items: [{ id: this.id, matrix: this.getMatrixData() }]
17994
+ });
17995
+ }
17969
17996
  setLocal(xOrData, y, scaleX, scaleY) {
17970
17997
  this.previous = this._matrix.copy();
17971
17998
  if (typeof xOrData === "object") {
@@ -20888,6 +20915,24 @@ class LayeredIndex {
20888
20915
  }
20889
20916
 
20890
20917
  // src/SpatialIndex/SpacialIndex.ts
20918
+ function worldBoundsToLocal(container, left, top, right, bottom) {
20919
+ const inv = container.getWorldMatrix().getInverse();
20920
+ const corners = [
20921
+ new Point(left, top),
20922
+ new Point(right, top),
20923
+ new Point(right, bottom),
20924
+ new Point(left, bottom)
20925
+ ];
20926
+ for (const c of corners)
20927
+ inv.apply(c);
20928
+ return {
20929
+ left: Math.min(corners[0].x, corners[1].x, corners[2].x, corners[3].x),
20930
+ top: Math.min(corners[0].y, corners[1].y, corners[2].y, corners[3].y),
20931
+ right: Math.max(corners[0].x, corners[1].x, corners[2].x, corners[3].x),
20932
+ bottom: Math.max(corners[0].y, corners[1].y, corners[2].y, corners[3].y)
20933
+ };
20934
+ }
20935
+
20891
20936
  class SpatialIndex {
20892
20937
  subject = new Subject;
20893
20938
  itemsArray = [];
@@ -20939,6 +20984,8 @@ class SpatialIndex {
20939
20984
  if (item.parent !== "Board") {
20940
20985
  const parentFrame = this.items.getById(item.parent);
20941
20986
  parentFrame?.removeChildItems(item);
20987
+ this.subject.publish(this.items);
20988
+ return;
20942
20989
  }
20943
20990
  this.itemsArray.splice(this.itemsArray.indexOf(item), 1);
20944
20991
  this.itemsIndex.remove(item);
@@ -20953,10 +21000,20 @@ class SpatialIndex {
20953
21000
  this.subject.publish(this.items);
20954
21001
  }
20955
21002
  copy() {
20956
- return this.getItemsWithIncludedChildren(this.itemsArray).map((item) => ({
20957
- ...item.serialize(true),
20958
- id: item.getId()
20959
- }));
21003
+ return this.getItemsWithIncludedChildren(this.itemsArray).map((item) => {
21004
+ const serialized = { ...item.serialize(true), id: item.getId() };
21005
+ if (item.parent !== "Board" && item.getWorldMatrix) {
21006
+ const worldMatrix = item.getWorldMatrix();
21007
+ serialized.transformation = {
21008
+ ...serialized.transformation,
21009
+ translateX: worldMatrix.translateX,
21010
+ translateY: worldMatrix.translateY,
21011
+ scaleX: worldMatrix.scaleX,
21012
+ scaleY: worldMatrix.scaleY
21013
+ };
21014
+ }
21015
+ return serialized;
21016
+ });
20960
21017
  }
20961
21018
  getItemsWithIncludedChildren(items) {
20962
21019
  return items.flatMap((item) => {
@@ -21122,7 +21179,8 @@ class SpatialIndex {
21122
21179
  const children = [];
21123
21180
  const clearItems = items.filter((item) => {
21124
21181
  if ("index" in item && item.index) {
21125
- children.push(...item.index.getEnclosed(left, top, right, bottom));
21182
+ const local = worldBoundsToLocal(item, left, top, right, bottom);
21183
+ children.push(...item.index.getEnclosed(local.left, local.top, local.right, local.bottom));
21126
21184
  if (!item.getMbr().isEnclosedBy(mbr)) {
21127
21185
  return false;
21128
21186
  }
@@ -21137,7 +21195,8 @@ class SpatialIndex {
21137
21195
  const children = [];
21138
21196
  const clearItems = items.filter((item) => {
21139
21197
  if ("index" in item && item.index) {
21140
- children.push(...item.index.getEnclosedOrCrossed(left, top, right, bottom));
21198
+ const local = worldBoundsToLocal(item, left, top, right, bottom);
21199
+ children.push(...item.index.getEnclosedOrCrossed(local.left, local.top, local.right, local.bottom));
21141
21200
  if (!item.getMbr().isEnclosedOrCrossedBy(mbr)) {
21142
21201
  return false;
21143
21202
  }
@@ -21151,7 +21210,9 @@ class SpatialIndex {
21151
21210
  const children = [];
21152
21211
  const clearItems = items.filter((item) => {
21153
21212
  if ("index" in item && item.index) {
21154
- children.push(...item.index.getUnderPoint(point3, tolerance));
21213
+ const localPt = new Point(point3.x, point3.y);
21214
+ item.getWorldMatrix().getInverse().apply(localPt);
21215
+ children.push(...item.index.getUnderPoint(localPt, tolerance));
21155
21216
  if (!item.getMbr().isUnderPoint(point3)) {
21156
21217
  return false;
21157
21218
  }
@@ -21166,7 +21227,8 @@ class SpatialIndex {
21166
21227
  const children = [];
21167
21228
  const clearItems = items.filter((item) => {
21168
21229
  if ("index" in item && item.index) {
21169
- children.push(...item.index.getEnclosedOrCrossed(left, top, right, bottom));
21230
+ const local = worldBoundsToLocal(item, left, top, right, bottom);
21231
+ children.push(...item.index.getEnclosedOrCrossed(local.left, local.top, local.right, local.bottom));
21170
21232
  if (!item.getMbr().isEnclosedOrCrossedBy(mbr)) {
21171
21233
  return false;
21172
21234
  }
@@ -21629,6 +21691,49 @@ class SimpleSpatialIndex {
21629
21691
  }
21630
21692
 
21631
21693
  // src/Items/BaseItem/BaseItem.ts
21694
+ function toLocalTransformOp(op, containerMatrix, itemId) {
21695
+ switch (op.method) {
21696
+ case "applyMatrix": {
21697
+ const converted = op.items.map((item) => {
21698
+ const local = containerMatrix.applyInverseLinear(item.matrix.translateX, item.matrix.translateY);
21699
+ return { ...item, matrix: { ...item.matrix, translateX: local.x, translateY: local.y } };
21700
+ });
21701
+ return { ...op, items: converted };
21702
+ }
21703
+ case "translateBy": {
21704
+ const local = containerMatrix.applyInverseLinear(op.x, op.y);
21705
+ return { ...op, x: local.x, y: local.y };
21706
+ }
21707
+ case "translateTo": {
21708
+ const pt = new Point(op.x, op.y);
21709
+ containerMatrix.getInverse().apply(pt);
21710
+ return { ...op, x: pt.x, y: pt.y };
21711
+ }
21712
+ case "scaleTo": {
21713
+ return { ...op, x: op.x / containerMatrix.scaleX, y: op.y / containerMatrix.scaleY };
21714
+ }
21715
+ case "scaleByTranslateBy": {
21716
+ const local = containerMatrix.applyInverseLinear(op.translate.x, op.translate.y);
21717
+ return { ...op, translate: { x: local.x, y: local.y } };
21718
+ }
21719
+ case "scaleByRelativeTo":
21720
+ case "scaleToRelativeTo": {
21721
+ const pt = new Point(op.point.x, op.point.y);
21722
+ containerMatrix.getInverse().apply(pt);
21723
+ return { ...op, point: pt };
21724
+ }
21725
+ case "transformMany": {
21726
+ if (!itemId || !op.items[itemId])
21727
+ return op;
21728
+ const subOp = op.items[itemId];
21729
+ const localSubOp = toLocalTransformOp(subOp, containerMatrix);
21730
+ return { ...op, items: { ...op.items, [itemId]: localSubOp } };
21731
+ }
21732
+ default:
21733
+ return op;
21734
+ }
21735
+ }
21736
+
21632
21737
  class BaseItem extends Mbr {
21633
21738
  defaultItemData;
21634
21739
  transformation;
@@ -21673,6 +21778,16 @@ class BaseItem extends Mbr {
21673
21778
  getId() {
21674
21779
  return this.id;
21675
21780
  }
21781
+ getWorldMatrix() {
21782
+ if (this.parent === "Board") {
21783
+ return this.transformation.toMatrix();
21784
+ }
21785
+ const container = this.board.items.getById(this.parent);
21786
+ if (!container) {
21787
+ return this.transformation.toMatrix();
21788
+ }
21789
+ return this.transformation.toMatrix().composeWith(container.getWorldMatrix());
21790
+ }
21676
21791
  setId(id) {
21677
21792
  this.id = id;
21678
21793
  this.transformation.setId(id);
@@ -21747,16 +21862,39 @@ class BaseItem extends Mbr {
21747
21862
  getMbr() {
21748
21863
  return new Mbr(this.left, this.top, this.right, this.bottom);
21749
21864
  }
21865
+ getWorldMbr() {
21866
+ if (this.parent === "Board" || !this.parent || !this.board?.items) {
21867
+ return this.getMbr();
21868
+ }
21869
+ const container = this.board.items.getById(this.parent);
21870
+ if (!container) {
21871
+ return this.getMbr();
21872
+ }
21873
+ const containerWorldMatrix = container.getWorldMatrix();
21874
+ const local = this.getMbr();
21875
+ const corners = [
21876
+ new Point(local.left, local.top),
21877
+ new Point(local.right, local.top),
21878
+ new Point(local.right, local.bottom),
21879
+ new Point(local.left, local.bottom)
21880
+ ];
21881
+ for (const c of corners)
21882
+ containerWorldMatrix.apply(c);
21883
+ return new Mbr(Math.min(corners[0].x, corners[1].x, corners[2].x, corners[3].x), Math.min(corners[0].y, corners[1].y, corners[2].y, corners[3].y), Math.max(corners[0].x, corners[1].x, corners[2].x, corners[3].x), Math.max(corners[0].y, corners[1].y, corners[2].y, corners[3].y));
21884
+ }
21750
21885
  applyAddChildren(childIds) {
21751
21886
  if (!this.index) {
21752
21887
  return;
21753
21888
  }
21889
+ const containerWorldMatrix = this.getWorldMatrix();
21754
21890
  childIds.forEach((childId) => {
21755
21891
  const foundItem = this.board.items.getById(childId);
21756
21892
  if (this.parent !== childId && this.getId() !== childId) {
21757
21893
  if (!this.index?.getById(childId) && foundItem) {
21894
+ const localMatrix = foundItem.transformation.toMatrix().toLocalOf(containerWorldMatrix);
21758
21895
  this.board.items.index.remove(foundItem);
21759
21896
  foundItem.parent = this.getId();
21897
+ foundItem.transformation.setLocalMatrix(localMatrix);
21760
21898
  this.index?.insert(foundItem);
21761
21899
  }
21762
21900
  }
@@ -21769,12 +21907,15 @@ class BaseItem extends Mbr {
21769
21907
  if (!this.index) {
21770
21908
  return;
21771
21909
  }
21910
+ const containerWorldMatrix = this.getWorldMatrix();
21772
21911
  childIds.forEach((childId) => {
21773
21912
  const foundItem = this.index?.getById(childId);
21774
21913
  if (this.parent !== childId && this.getId() !== childId) {
21775
21914
  if (foundItem) {
21915
+ const worldMatrix = foundItem.transformation.toMatrix().composeWith(containerWorldMatrix);
21776
21916
  this.index?.remove(foundItem);
21777
21917
  foundItem.parent = "Board";
21918
+ foundItem.transformation.setLocalMatrix(worldMatrix);
21778
21919
  this.board.items.index.insert(foundItem);
21779
21920
  }
21780
21921
  }
@@ -21886,9 +22027,17 @@ class BaseItem extends Mbr {
21886
22027
  apply(op) {
21887
22028
  op = op;
21888
22029
  switch (op.class) {
21889
- case "Transformation":
21890
- this.transformation.apply(op);
22030
+ case "Transformation": {
22031
+ let transformOp = op;
22032
+ if (this.parent !== "Board") {
22033
+ const container = this.board.items.getById(this.parent);
22034
+ if (container?.transformation) {
22035
+ transformOp = toLocalTransformOp(transformOp, container.getWorldMatrix(), this.id);
22036
+ }
22037
+ }
22038
+ this.transformation.apply(transformOp);
21891
22039
  break;
22040
+ }
21892
22041
  case "LinkTo":
21893
22042
  this.linkTo.apply(op);
21894
22043
  break;
@@ -22009,6 +22158,7 @@ class RichText extends BaseItem {
22009
22158
  _onLimitReached = () => {};
22010
22159
  shrinkWidth = false;
22011
22160
  prevMbr = null;
22161
+ worldMatrixGetter;
22012
22162
  rtCounter = 0;
22013
22163
  constructor(board, container, id = "", transformation = new Transformation(id, board.events), linkTo, placeholderText = conf.i18n?.t("board.textPlaceholder"), isInShape = false, autoSize = false, insideOf, initialTextStyles = conf.DEFAULT_TEXT_STYLES) {
22014
22164
  super(board, id);
@@ -22178,7 +22328,7 @@ class RichText extends BaseItem {
22178
22328
  };
22179
22329
  calcAutoSize(blockNodes) {
22180
22330
  const nodes = blockNodes ? blockNodes : this.getBlockNodes();
22181
- const container = this.getTransformedContainer();
22331
+ const container = this.getLayoutContainer();
22182
22332
  const containerWidth = container.getWidth();
22183
22333
  const containerHeight = container.getHeight();
22184
22334
  const optimal = findOptimalMaxWidthForTextAutoSize(nodes, containerWidth, containerHeight, containerWidth);
@@ -22186,7 +22336,7 @@ class RichText extends BaseItem {
22186
22336
  }
22187
22337
  applyAutoSizeScale(textScale, blockNodes) {
22188
22338
  const nodes = blockNodes ? blockNodes : this.getBlockNodes();
22189
- const container = this.getTransformedContainer();
22339
+ const container = this.getLayoutContainer();
22190
22340
  const containerWidth = container.getWidth();
22191
22341
  const containerHeight = container.getHeight();
22192
22342
  this.layoutNodes = getBlockNodes(nodes, containerWidth / textScale);
@@ -22308,6 +22458,13 @@ class RichText extends BaseItem {
22308
22458
  }
22309
22459
  return this.container.getTransformed(this.transformation.toMatrix());
22310
22460
  }
22461
+ getLayoutContainer() {
22462
+ if (this.insideOf === "Frame") {
22463
+ return this.getTransformedContainer();
22464
+ }
22465
+ const matrix = this.worldMatrixGetter ? this.worldMatrixGetter() : this.transformation.toMatrix();
22466
+ return this.container.getTransformed(matrix);
22467
+ }
22311
22468
  emitWithoutApplying = (op) => {
22312
22469
  if (this.board.events) {
22313
22470
  this.board.events.emit(op);
@@ -36274,6 +36431,7 @@ class AINode extends BaseItem {
36274
36431
  this.subject.publish(this);
36275
36432
  });
36276
36433
  this.text.insideOf = "AINode";
36434
+ this.text.worldMatrixGetter = () => this.getWorldMatrix();
36277
36435
  this.transformPath();
36278
36436
  }
36279
36437
  transformPath() {
@@ -36365,7 +36523,7 @@ class AINode extends BaseItem {
36365
36523
  this.text.apply(op);
36366
36524
  break;
36367
36525
  case "Transformation":
36368
- this.text.transformation.apply(op);
36526
+ super.apply(op);
36369
36527
  break;
36370
36528
  case "LinkTo":
36371
36529
  this.linkTo.apply(op);
@@ -36693,14 +36851,20 @@ function getControlPoint(data, findItem2) {
36693
36851
  }
36694
36852
  }
36695
36853
  }
36854
+ function getItemWorldMatrix(item) {
36855
+ if (item instanceof BaseItem && item.parent !== "Board") {
36856
+ return item.getWorldMatrix();
36857
+ }
36858
+ return item.transformation?.toMatrix() ?? new Matrix;
36859
+ }
36696
36860
  function toRelativePoint(point5, item) {
36697
- const inverse = item.transformation ? item.transformation.getInverse().toMatrix() : new Matrix;
36861
+ const inverse = getItemWorldMatrix(item).getInverse();
36698
36862
  point5 = point5.copy();
36699
36863
  point5.transform(inverse);
36700
36864
  return point5;
36701
36865
  }
36702
36866
  function fromRelativePoint(relativePoint, item, edge) {
36703
- const matrix = item.transformation?.toMatrix() ?? new Matrix;
36867
+ const matrix = getItemWorldMatrix(item);
36704
36868
  const point5 = relativePoint.copy();
36705
36869
  point5.transform(matrix);
36706
36870
  if (item instanceof RichText || item instanceof AINode) {
@@ -40289,6 +40453,7 @@ class Sticker extends BaseItem {
40289
40453
  this.linkTo = new LinkTo(this.id, this.board.events);
40290
40454
  this.transformation = new Transformation(this.id, this.board.events);
40291
40455
  this.text = new RichText(board, this.textContainer, this.id, this.transformation, this.linkTo, " ", false, true, this.itemType);
40456
+ this.text.worldMatrixGetter = () => this.getWorldMatrix();
40292
40457
  this.transformation.subject.subscribe((_subject, op) => {
40293
40458
  this.transformPath();
40294
40459
  if (op.method === "applyMatrix") {
@@ -40392,7 +40557,7 @@ class Sticker extends BaseItem {
40392
40557
  this.text.apply(op);
40393
40558
  break;
40394
40559
  case "Transformation":
40395
- this.transformation.apply(op);
40560
+ super.apply(op);
40396
40561
  break;
40397
40562
  case "LinkTo":
40398
40563
  this.linkTo.apply(op);
@@ -41175,7 +41340,13 @@ class Frame2 extends BaseItem {
41175
41340
  return;
41176
41341
  }
41177
41342
  this.renderPath(context);
41178
- super.render(context);
41343
+ const ctx = context.ctx;
41344
+ ctx.save();
41345
+ this.transformation.applyToContext(ctx);
41346
+ for (const child of this.index.list()) {
41347
+ child.render(context);
41348
+ }
41349
+ ctx.restore();
41179
41350
  this.renderBorders(context);
41180
41351
  this.renderName(context);
41181
41352
  }
@@ -43283,25 +43454,24 @@ function douglasPeucker(points, epsilon2) {
43283
43454
  // src/Items/Group/Group.ts
43284
43455
  class Group extends BaseItem {
43285
43456
  events;
43286
- children;
43287
43457
  linkTo;
43288
43458
  itemType = "Group";
43289
43459
  parent = "Board";
43290
43460
  transformation;
43291
43461
  subject = new Subject;
43292
- mbr = new Mbr;
43293
43462
  transformationRenderBlock = undefined;
43294
43463
  constructor(board, events, children = [], id = "") {
43295
- super(board, id);
43464
+ super(board, id, undefined, true);
43296
43465
  this.events = events;
43297
- this.children = children;
43298
43466
  this.linkTo = new LinkTo(this.id, this.events);
43299
43467
  this.transformation = new Transformation(this.id, this.events);
43300
- this.children = children;
43301
43468
  this.transformation.subject.subscribe(() => {
43302
43469
  this.updateMbr();
43303
43470
  this.subject.publish(this);
43304
43471
  });
43472
+ if (children.length > 0) {
43473
+ this.applyAddChildren(children);
43474
+ }
43305
43475
  }
43306
43476
  isClosed() {
43307
43477
  return false;
@@ -43309,45 +43479,17 @@ class Group extends BaseItem {
43309
43479
  getRichText() {
43310
43480
  return null;
43311
43481
  }
43312
- addChild(childId) {
43313
- this.emit({
43314
- class: "Group",
43315
- method: "addChild",
43316
- item: [this.getId()],
43317
- childId
43318
- });
43319
- }
43320
- applyAddChild(childId) {
43321
- if (!this.children.includes(childId)) {
43322
- this.children.push(childId);
43323
- this.updateMbr();
43324
- this.subject.publish(this);
43325
- }
43326
- }
43327
- applyRemoveChild(childId) {
43328
- this.children = this.children.filter((currChild) => currChild !== childId);
43329
- this.updateMbr();
43330
- this.subject.publish(this);
43331
- }
43332
- removeChild(childId) {
43333
- this.emit({
43334
- class: "Group",
43335
- method: "removeChild",
43336
- item: [this.getId()],
43337
- childId
43338
- });
43339
- }
43340
- emitRemoveChild(child) {
43341
- this.removeChild(child.getId());
43342
- child.parent = "Board";
43343
- }
43344
43482
  apply(op) {
43345
43483
  switch (op.class) {
43346
43484
  case "Group":
43347
43485
  if (op.method === "addChild") {
43348
- this.applyAddChild(op.childId);
43486
+ this.applyAddChildren([op.childId]);
43349
43487
  } else if (op.method === "removeChild") {
43350
- this.applyRemoveChild(op.childId);
43488
+ this.applyRemoveChildren([op.childId]);
43489
+ } else if (op.method === "addChildren") {
43490
+ this.applyAddChildren(op.newData.childIds);
43491
+ } else if (op.method === "removeChildren") {
43492
+ this.applyRemoveChildren(op.newData.childIds);
43351
43493
  }
43352
43494
  break;
43353
43495
  case "Transformation":
@@ -43372,24 +43514,69 @@ class Group extends BaseItem {
43372
43514
  this.transformation.setId(id);
43373
43515
  return this;
43374
43516
  }
43517
+ getMbr() {
43518
+ const children = this.index.list();
43519
+ if (children.length === 0) {
43520
+ return new Mbr(this.left, this.top, this.right, this.bottom);
43521
+ }
43522
+ const groupWorldMatrix = this.getWorldMatrix();
43523
+ let left = Number.MAX_SAFE_INTEGER;
43524
+ let top = Number.MAX_SAFE_INTEGER;
43525
+ let right = Number.MIN_SAFE_INTEGER;
43526
+ let bottom = Number.MIN_SAFE_INTEGER;
43527
+ for (const child of children) {
43528
+ const childLocalMbr = child.getMbr();
43529
+ const corners = [
43530
+ { x: childLocalMbr.left, y: childLocalMbr.top },
43531
+ { x: childLocalMbr.right, y: childLocalMbr.top },
43532
+ { x: childLocalMbr.right, y: childLocalMbr.bottom },
43533
+ { x: childLocalMbr.left, y: childLocalMbr.bottom }
43534
+ ];
43535
+ for (const corner of corners) {
43536
+ groupWorldMatrix.apply(corner);
43537
+ if (corner.x < left)
43538
+ left = corner.x;
43539
+ if (corner.y < top)
43540
+ top = corner.y;
43541
+ if (corner.x > right)
43542
+ right = corner.x;
43543
+ if (corner.y > bottom)
43544
+ bottom = corner.y;
43545
+ }
43546
+ }
43547
+ const mbr = new Mbr(left, top, right, bottom);
43548
+ this.left = left;
43549
+ this.top = top;
43550
+ this.right = right;
43551
+ this.bottom = bottom;
43552
+ return mbr;
43553
+ }
43554
+ updateMbr() {
43555
+ this.getMbr();
43556
+ }
43557
+ getChildrenIds() {
43558
+ return this.index.list().map((item) => item.getId());
43559
+ }
43560
+ getChildren() {
43561
+ return this.index.list();
43562
+ }
43563
+ getLinkTo() {
43564
+ return this.linkTo.link;
43565
+ }
43375
43566
  serialize() {
43376
43567
  return {
43377
43568
  itemType: "Group",
43378
- children: this.children,
43569
+ children: this.getChildrenIds(),
43379
43570
  transformation: this.transformation.serialize()
43380
43571
  };
43381
43572
  }
43382
43573
  deserialize(data) {
43383
- if (data.children) {
43384
- data.children.forEach((childId) => {
43385
- this.applyAddChild(childId);
43386
- const item = this.board.items.getById(childId);
43387
- if (item) {
43388
- item.parent = this.getId();
43389
- }
43390
- });
43574
+ if (data.transformation) {
43575
+ this.transformation.deserialize(data.transformation);
43576
+ }
43577
+ if (data.children && data.children.length > 0) {
43578
+ this.applyAddChildren(data.children);
43391
43579
  }
43392
- this.transformation.deserialize(data.transformation);
43393
43580
  this.subject.publish(this);
43394
43581
  return this;
43395
43582
  }
@@ -43399,99 +43586,25 @@ class Group extends BaseItem {
43399
43586
  getIntersectionPoints(segment) {
43400
43587
  const lines = this.getMbr().getLines();
43401
43588
  const initPoints = [];
43402
- const points = lines.reduce((acc, line) => {
43589
+ return lines.reduce((acc, line) => {
43403
43590
  const intersections = line.getIntersectionPoints(segment);
43404
43591
  if (intersections.length > 0) {
43405
43592
  acc.push(...intersections);
43406
43593
  }
43407
43594
  return acc;
43408
43595
  }, initPoints);
43409
- return points;
43410
- }
43411
- getMbr() {
43412
- const mbr = new Mbr;
43413
- let left = Number.MAX_SAFE_INTEGER;
43414
- let top = Number.MAX_SAFE_INTEGER;
43415
- let right = Number.MIN_SAFE_INTEGER;
43416
- let bottom = Number.MIN_SAFE_INTEGER;
43417
- const mbrs = this.children.flatMap((childId) => {
43418
- const item = this.board.items.getById(childId);
43419
- if (!item) {
43420
- return [];
43421
- }
43422
- const mbr2 = item.getMbr();
43423
- if (!mbr2) {
43424
- return [];
43425
- }
43426
- if (left > mbr2.left) {
43427
- left = mbr2.left;
43428
- }
43429
- if (top > mbr2.top) {
43430
- top = mbr2.top;
43431
- }
43432
- if (right < mbr2.right) {
43433
- right = mbr2.right;
43434
- }
43435
- if (bottom < mbr2.bottom) {
43436
- bottom = mbr2.bottom;
43437
- }
43438
- return [mbr2];
43439
- });
43440
- if (mbrs.length) {
43441
- mbr.combine(mbrs);
43442
- mbr.left = left !== Number.MAX_SAFE_INTEGER ? left : 0;
43443
- mbr.top = top !== Number.MAX_SAFE_INTEGER ? top : 0;
43444
- mbr.right = right !== Number.MIN_SAFE_INTEGER ? right : 0;
43445
- mbr.bottom = bottom !== Number.MIN_SAFE_INTEGER ? bottom : 0;
43446
- this.left = mbr.left;
43447
- this.bottom = mbr.bottom;
43448
- this.right = mbr.right;
43449
- this.top = mbr.top;
43450
- }
43451
- return mbr;
43452
- }
43453
- getChildrenIds() {
43454
- return this.children;
43455
- }
43456
- getChildren() {
43457
- return this.children.map((itemId) => this.board.items.getById(itemId)).filter((item) => item !== undefined);
43458
- }
43459
- updateMbr() {
43460
- const rect = this.getMbr();
43461
- this.mbr = rect;
43462
- this.mbr.borderColor = "transparent";
43463
- }
43464
- setBoard(board) {
43465
- this.board = board;
43466
- }
43467
- setChildren(items) {
43468
- items.forEach((itemId) => {
43469
- this.addChild(itemId);
43470
- const item = this.board.items.getById(itemId);
43471
- if (item) {
43472
- item.parent = this.getId();
43473
- }
43474
- });
43475
- this.updateMbr();
43476
- }
43477
- removeChildren() {
43478
- this.children.forEach((itemId) => {
43479
- this.removeChild(itemId);
43480
- const item = this.board.items.getById(itemId);
43481
- if (item) {
43482
- item.parent = this.parent;
43483
- }
43484
- });
43485
- this.updateMbr();
43486
- }
43487
- getLinkTo() {
43488
- return this.linkTo.link;
43489
43596
  }
43490
43597
  render(context) {
43491
43598
  if (this.transformationRenderBlock) {
43492
43599
  return;
43493
43600
  }
43494
- this.mbr.render(context);
43601
+ const ctx = context.ctx;
43602
+ ctx.save();
43603
+ this.transformation.applyToContext(ctx);
43604
+ for (const child of this.index.list()) {
43605
+ child.render(context);
43606
+ }
43607
+ ctx.restore();
43495
43608
  }
43496
43609
  renderHTML(documentFactory) {
43497
43610
  return documentFactory.createElement("div");
@@ -46208,13 +46321,13 @@ class AlignmentHelper {
46208
46321
  return baseThickness / (zoom / 100);
46209
46322
  }
46210
46323
  combineMBRs(items) {
46324
+ const worldMbr = (item) => item instanceof BaseItem ? item.getWorldMbr() : item.getMbr();
46211
46325
  return items.reduce((acc, item, i) => {
46212
46326
  if (i === 0) {
46213
46327
  return acc;
46214
46328
  }
46215
- const itemMbr = item.getPathMbr();
46216
- return acc.combine(itemMbr);
46217
- }, items[0].getMbr());
46329
+ return acc.combine(worldMbr(item));
46330
+ }, worldMbr(items[0]));
46218
46331
  }
46219
46332
  checkAlignment(movingItem, excludeItems = []) {
46220
46333
  if (!Array.isArray(movingItem) && movingItem.itemType === "Comment") {
@@ -51908,8 +52021,9 @@ class SelectionItems {
51908
52021
  if (items.length === 0) {
51909
52022
  return;
51910
52023
  }
51911
- const mbr = items[0].getMbr();
51912
- items.slice(1).forEach((item) => mbr.combine(item.getMbr()));
52024
+ const worldMbr = (item) => item instanceof BaseItem ? item.getWorldMbr() : item.getMbr();
52025
+ const mbr = worldMbr(items[0]);
52026
+ items.slice(1).forEach((item) => mbr.combine(worldMbr(item)));
51913
52027
  return mbr;
51914
52028
  }
51915
52029
  }
@@ -52118,18 +52232,27 @@ function handleMultipleItemsResize({
52118
52232
  }) {
52119
52233
  const { matrix } = resize;
52120
52234
  const result = [];
52121
- const items = itemsToResize ? itemsToResize : board.selection.items.list();
52235
+ const rawItems = itemsToResize ? itemsToResize : board.selection.items.list();
52122
52236
  board.items.getComments().forEach((comment2) => {
52123
- if (items.some((item) => item.getId() === comment2.getItemToFollow())) {
52124
- items.push(comment2);
52237
+ if (rawItems.some((item) => item.getId() === comment2.getItemToFollow())) {
52238
+ rawItems.push(comment2);
52125
52239
  }
52126
52240
  });
52241
+ const selectedIds = new Set(rawItems.map((i) => i.getId()));
52242
+ const items = rawItems.filter((item) => item.parent === "Board" || !selectedIds.has(item.parent));
52127
52243
  for (const item of items) {
52128
- let itemX = item.getMbr().left;
52129
- let itemY = item.getMbr().top;
52244
+ const worldMbr = item instanceof BaseItem ? item.getWorldMbr() : item.getMbr();
52245
+ let itemX = worldMbr.left;
52246
+ let itemY = worldMbr.top;
52130
52247
  if (item.itemType === "Drawing") {
52131
- itemX = item.transformation.getMatrixData().translateX;
52132
- itemY = item.transformation.getMatrixData().translateY;
52248
+ if (item instanceof BaseItem && item.parent !== "Board") {
52249
+ const worldMatrix = item.getWorldMatrix();
52250
+ itemX = worldMatrix.translateX;
52251
+ itemY = worldMatrix.translateY;
52252
+ } else {
52253
+ itemX = item.transformation.getMatrixData().translateX;
52254
+ itemY = item.transformation.getMatrixData().translateY;
52255
+ }
52133
52256
  }
52134
52257
  const deltaX = itemX - initMbr.left;
52135
52258
  const translateX = deltaX * matrix.scaleX - deltaX + matrix.translateX;
@@ -53053,10 +53176,6 @@ class BoardSelection {
53053
53176
  if (!this.board.events) {
53054
53177
  return;
53055
53178
  }
53056
- if (operation.method === "transformMany") {
53057
- console.error("[DEBUG] transformMany emitted!", JSON.stringify(operation));
53058
- console.trace("[DEBUG] transformMany stack trace");
53059
- }
53060
53179
  const command = createCommand(this.board, operation);
53061
53180
  command.apply();
53062
53181
  this.board.events.emit(operation, command);
@@ -53599,17 +53718,12 @@ class BoardSelection {
53599
53718
  const addItem = (itemId) => {
53600
53719
  items.push({ id: itemId, matrix: { translateX: x, translateY: y, scaleX: 1, scaleY: 1, shearX: 0, shearY: 0 } });
53601
53720
  };
53602
- const tryToAddFrameChildren = (selectedItem) => {
53603
- if (!("index" in selectedItem) || !selectedItem.index) {
53721
+ const selectedIds = new Set(unselectedItem ? [unselectedItem.getId()] : this.board.selection.list().map((i) => i.getId()));
53722
+ const addWithComments = (item) => {
53723
+ if (item.parent !== "Board" && selectedIds.has(item.parent)) {
53604
53724
  return;
53605
53725
  }
53606
- for (const childId of selectedItem.getChildrenIds()) {
53607
- addItem(childId);
53608
- }
53609
- };
53610
- const addWithComments = (item) => {
53611
53726
  addItem(item.getId());
53612
- tryToAddFrameChildren(item);
53613
53727
  const followedComments = this.board.items.getComments().filter((comment2) => comment2.getItemToFollow() === item.getId());
53614
53728
  for (const comment2 of followedComments) {
53615
53729
  addItem(comment2.getId());
@@ -54441,6 +54555,28 @@ class Board {
54441
54555
  item: [item.getId()]
54442
54556
  });
54443
54557
  }
54558
+ group(items) {
54559
+ const id = this.getNewItemId();
54560
+ const groupData = {
54561
+ itemType: "Group",
54562
+ children: items.map((i) => i.getId()),
54563
+ transformation: { translateX: 0, translateY: 0, scaleX: 1, scaleY: 1, shearX: 0, shearY: 0 }
54564
+ };
54565
+ this.emit({
54566
+ class: "Board",
54567
+ method: "addLockedGroup",
54568
+ item: id,
54569
+ data: groupData
54570
+ });
54571
+ return this.items.getById(id);
54572
+ }
54573
+ ungroup(group) {
54574
+ this.emit({
54575
+ class: "Board",
54576
+ method: "removeLockedGroup",
54577
+ item: [group.getId()]
54578
+ });
54579
+ }
54444
54580
  getByZIndex(index2) {
54445
54581
  return this.index.getByZIndex(index2);
54446
54582
  }