microboard-temp 0.2.5 → 0.3.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.
@@ -33554,6 +33554,7 @@ class BaseItem extends Mbr {
33554
33554
  transformationRenderBlock = undefined;
33555
33555
  board;
33556
33556
  id;
33557
+ onRemoveCallbacks = [];
33557
33558
  shouldUseCustomRender = false;
33558
33559
  shouldRenderOutsideViewRect = true;
33559
33560
  itemType = "";
@@ -33631,6 +33632,12 @@ class BaseItem extends Mbr {
33631
33632
  break;
33632
33633
  }
33633
33634
  }
33635
+ addOnRemoveCallback(cb) {
33636
+ this.onRemoveCallbacks.push(cb);
33637
+ }
33638
+ onRemove() {
33639
+ this.onRemoveCallbacks.forEach((cb) => cb());
33640
+ }
33634
33641
  render(context) {}
33635
33642
  renderHTML(documentFactory) {
33636
33643
  return documentFactory.createElement("div");
@@ -38887,6 +38894,9 @@ class VideoItem extends BaseItem {
38887
38894
  this.loadCallbacks.push(callback);
38888
38895
  };
38889
38896
  getStorageId() {
38897
+ if (!this.isStorageUrl) {
38898
+ return;
38899
+ }
38890
38900
  return this.url.split("/").pop();
38891
38901
  }
38892
38902
  getIsStorageUrl() {
@@ -39159,6 +39169,13 @@ class VideoItem extends BaseItem {
39159
39169
  linkElem.click();
39160
39170
  }
39161
39171
  }
39172
+ onRemove() {
39173
+ const storageId = this.getStorageId();
39174
+ if (storageId) {
39175
+ deleteMedia([storageId], this.board.getBoardId());
39176
+ }
39177
+ super.onRemove();
39178
+ }
39162
39179
  }
39163
39180
  // src/Items/Image/calculatePosition.ts
39164
39181
  function calculatePosition(boardImage, board) {
@@ -39589,432 +39606,122 @@ var captureFrame = (frameTime, video) => {
39589
39606
  return null;
39590
39607
  }
39591
39608
  };
39592
- // src/Items/Audio/Audio.ts
39593
- class AudioItem extends BaseItem {
39609
+ // src/Items/Placeholder/Placeholder.ts
39610
+ var PlaceholderImg = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
39611
+ <path d="M5 11.1L7 9.1L12.5 14.6L16 11.1L19 14.1V5H5V11.1ZM4 3H20C20.2652 3 20.5196 3.10536 20.7071 3.29289C20.8946 3.48043 21 3.73478 21 4V20C21 20.2652 20.8946 20.5196 20.7071 20.7071C20.5196 20.8946 20.2652 21 20 21H4C3.73478 21 3.48043 20.8946 3.29289 20.7071C3.10536 20.5196 3 20.2652 3 20V4C3 3.73478 3.10536 3.48043 3.29289 3.29289C3.48043 3.10536 3.73478 3 4 3ZM15.5 10C15.1022 10 14.7206 9.84196 14.4393 9.56066C14.158 9.27936 14 8.89782 14 8.5C14 8.10218 14.158 7.72064 14.4393 7.43934C14.7206 7.15804 15.1022 7 15.5 7C15.8978 7 16.2794 7.15804 16.5607 7.43934C16.842 7.72064 17 8.10218 17 8.5C17 8.89782 16.842 9.27936 16.5607 9.56066C16.2794 9.84196 15.8978 10 15.5 10Z" fill="white" fill-opacity="0.6"/>
39612
+ </svg>`;
39613
+
39614
+ class Placeholder extends BaseItem {
39594
39615
  events;
39595
- extension;
39596
- itemType = "Audio";
39616
+ miroData;
39617
+ backgroundColor;
39618
+ icon;
39619
+ itemType = "Placeholder";
39620
+ shapeType = "Rectangle";
39597
39621
  parent = "Board";
39598
39622
  transformation;
39599
- linkTo;
39623
+ path = Shapes[this.shapeType].path.copy();
39624
+ mbr = Shapes[this.shapeType].path.getMbr().copy();
39600
39625
  subject = new Subject;
39601
- loadCallbacks = [];
39602
- beforeLoadCallbacks = [];
39603
39626
  transformationRenderBlock = undefined;
39604
- url = "";
39605
- isPlaying = false;
39606
- currentTime = 0;
39607
- isStorageUrl = true;
39608
- constructor(board, isStorageUrl, url, events, id = "", extension2) {
39627
+ iconImage;
39628
+ constructor(board, events, miroData, id = "", backgroundColor = "#E5E5EA", icon = PlaceholderImg?.toString() || "") {
39609
39629
  super(board, id);
39610
39630
  this.events = events;
39611
- this.extension = extension2;
39612
- this.linkTo = new LinkTo(this.id, events);
39613
- this.board = board;
39614
- this.isStorageUrl = isStorageUrl;
39615
- if (url) {
39616
- this.applyUrl(url);
39617
- }
39618
- this.transformation = new Transformation(id, events);
39619
- this.linkTo.subject.subscribe(() => {
39631
+ this.miroData = miroData;
39632
+ this.backgroundColor = backgroundColor;
39633
+ this.icon = icon;
39634
+ this.transformation = new Transformation(this.id, this.events);
39635
+ this.transformation.subject.subscribe((_subject) => {
39636
+ this.transformPath();
39620
39637
  this.updateMbr();
39621
39638
  this.subject.publish(this);
39622
39639
  });
39623
- this.transformation.subject.subscribe(this.onTransform);
39624
- this.right = this.left + conf.AUDIO_DIMENSIONS.width;
39625
- this.bottom = this.top + conf.AUDIO_DIMENSIONS.height;
39626
- this.shouldUseCustomRender = true;
39627
- }
39628
- setCurrentTime(time) {
39629
- this.currentTime = time;
39630
- }
39631
- getCurrentTime() {
39632
- return this.currentTime;
39633
- }
39634
- getIsStorageUrl() {
39635
- return this.isStorageUrl;
39636
- }
39637
- onTransform = () => {
39638
39640
  this.updateMbr();
39639
- this.subject.publish(this);
39640
- };
39641
- doOnceBeforeOnLoad = (callback) => {
39642
- this.loadCallbacks.push(callback);
39643
- };
39644
- doOnceOnLoad = (callback) => {
39645
- this.loadCallbacks.push(callback);
39646
- };
39647
- setIsPlaying(isPlaying) {
39648
- this.isPlaying = isPlaying;
39649
- this.shouldRenderOutsideViewRect = isPlaying;
39650
- this.subject.publish(this);
39651
- }
39652
- getIsPlaying() {
39653
- return this.isPlaying;
39641
+ this.loadIconImage();
39654
39642
  }
39655
- applyUrl(url) {
39656
- if (this.isStorageUrl) {
39657
- try {
39658
- const newUrl = new URL(url);
39659
- this.url = `${window.location.origin}${newUrl.pathname}`;
39660
- } catch (_) {}
39643
+ emit(operation) {
39644
+ if (this.events) {
39645
+ const command = new PlaceholderCommand([this], operation);
39646
+ command.apply();
39647
+ this.events.emit(operation, command);
39661
39648
  } else {
39662
- this.url = url;
39663
- }
39664
- }
39665
- setUrl(url) {
39666
- this.emit({
39667
- class: "Audio",
39668
- method: "setUrl",
39669
- item: [this.getId()],
39670
- url
39671
- });
39672
- }
39673
- getStorageId() {
39674
- return this.url.split("/").pop();
39675
- }
39676
- getUrl() {
39677
- return this.url;
39678
- }
39679
- onLoad = async () => {
39680
- this.shootBeforeLoadCallbacks();
39681
- this.updateMbr();
39682
- this.subject.publish(this);
39683
- this.shootLoadCallbacks();
39684
- };
39685
- onError = (_error) => {
39686
- this.updateMbr();
39687
- this.subject.publish(this);
39688
- this.shootLoadCallbacks();
39689
- };
39690
- updateMbr() {
39691
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
39692
- this.left = translateX;
39693
- this.top = translateY;
39694
- this.right = this.left + conf.AUDIO_DIMENSIONS.width * scaleX;
39695
- this.bottom = this.top + conf.AUDIO_DIMENSIONS.height * scaleY;
39696
- }
39697
- render(context) {
39698
- if (this.transformationRenderBlock) {
39699
- return;
39700
- }
39701
- const ctx = context.ctx;
39702
- const radius = 12 * this.transformation.getScale().x;
39703
- ctx.save();
39704
- ctx.globalCompositeOperation = "destination-out";
39705
- ctx.beginPath();
39706
- ctx.moveTo(this.left + radius, this.top);
39707
- ctx.lineTo(this.left + this.getWidth() - radius, this.top);
39708
- ctx.quadraticCurveTo(this.left + this.getWidth(), this.top, this.left + this.getWidth(), this.top + radius);
39709
- ctx.lineTo(this.left + this.getWidth(), this.top + this.getHeight() - radius);
39710
- ctx.quadraticCurveTo(this.left + this.getWidth(), this.top + this.getHeight(), this.left + this.getWidth() - radius, this.top + this.getHeight());
39711
- ctx.lineTo(this.left + radius, this.top + this.getHeight());
39712
- ctx.quadraticCurveTo(this.left, this.top + this.getHeight(), this.left, this.top + this.getHeight() - radius);
39713
- ctx.lineTo(this.left, this.top + radius);
39714
- ctx.quadraticCurveTo(this.left, this.top, this.left + radius, this.top);
39715
- ctx.closePath();
39716
- ctx.fill();
39717
- ctx.restore();
39718
- }
39719
- renderHTML(documentFactory) {
39720
- const div = documentFactory.createElement("audio-item");
39721
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
39722
- const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
39723
- div.id = this.getId();
39724
- div.style.width = `${conf.AUDIO_DIMENSIONS.width}px`;
39725
- div.style.height = `${conf.AUDIO_DIMENSIONS.height}px`;
39726
- div.style.transformOrigin = "top left";
39727
- div.style.transform = transform;
39728
- div.style.position = "absolute";
39729
- div.setAttribute("audio-url", this.getUrl());
39730
- if (this.extension) {
39731
- div.setAttribute("extension", this.extension);
39732
- }
39733
- if (this.isStorageUrl) {
39734
- div.setAttribute("is-storage-url", "true");
39649
+ this.apply(operation);
39735
39650
  }
39736
- div.setAttribute("data-link-to", "");
39737
- return div;
39738
39651
  }
39739
39652
  serialize() {
39740
39653
  return {
39741
- itemType: "Audio",
39742
- url: this.url,
39654
+ itemType: "Placeholder",
39655
+ backgroundColor: this.backgroundColor,
39656
+ icon: this.icon,
39743
39657
  transformation: this.transformation.serialize(),
39744
- isStorageUrl: this.isStorageUrl,
39745
- extension: this.extension
39658
+ miroData: this.miroData
39746
39659
  };
39747
39660
  }
39748
39661
  deserialize(data) {
39749
- if (data.isStorageUrl) {
39750
- this.isStorageUrl = data.isStorageUrl;
39751
- }
39662
+ this.initPath();
39663
+ this.backgroundColor = data.backgroundColor ?? this.backgroundColor;
39664
+ this.icon = data.icon ?? this.icon;
39665
+ this.miroData = data.miroData;
39752
39666
  if (data.transformation) {
39753
39667
  this.transformation.deserialize(data.transformation);
39668
+ this.transformPath();
39754
39669
  }
39755
- if (data.url) {
39756
- this.setUrl(data.url);
39757
- }
39758
- if (data.extension) {
39759
- this.extension = data.extension;
39760
- }
39670
+ this.subject.publish(this);
39671
+ return this;
39672
+ }
39673
+ setId(id) {
39674
+ this.id = id;
39675
+ this.transformation.setId(id);
39761
39676
  return this;
39762
39677
  }
39678
+ getId() {
39679
+ return this.id;
39680
+ }
39763
39681
  apply(op) {
39764
39682
  switch (op.class) {
39683
+ case "Placeholder":
39684
+ this.applyPlaceholder(op);
39685
+ this.updateMbr();
39686
+ break;
39765
39687
  case "Transformation":
39766
39688
  this.transformation.apply(op);
39767
39689
  break;
39768
- case "LinkTo":
39769
- this.linkTo.apply(op);
39690
+ default:
39691
+ return;
39692
+ }
39693
+ this.subject.publish(this);
39694
+ }
39695
+ applyPlaceholder(op) {
39696
+ switch (op.method) {
39697
+ case "setBackgroundColor":
39698
+ this.applyBackgroundColor(op.backgroundColor);
39770
39699
  break;
39771
- case "Audio":
39772
- if (op.method === "setUrl") {
39773
- this.applyUrl(op.url);
39774
- }
39775
- this.subject.publish(this);
39700
+ case "setIcon":
39701
+ this.applyIcon(op.icon);
39702
+ break;
39703
+ case "setMiroData":
39704
+ this.applyMiroData(op.miroData);
39776
39705
  break;
39777
39706
  }
39778
39707
  }
39779
- emit(operation) {
39780
- if (this.events) {
39781
- const command = new AudioCommand([this], operation);
39782
- command.apply();
39783
- this.events.emit(operation, command);
39784
- } else {
39785
- this.apply(operation);
39786
- }
39708
+ getBackgroundColor() {
39709
+ return this.backgroundColor;
39787
39710
  }
39788
- setId(id) {
39789
- this.id = id;
39790
- this.transformation.setId(id);
39791
- return this;
39711
+ applyBackgroundColor(backgroundColor) {
39712
+ this.backgroundColor = backgroundColor;
39713
+ this.path.setBackgroundColor(backgroundColor);
39792
39714
  }
39793
- getId() {
39794
- return this.id;
39715
+ setBackgroundColor(backgroundColor) {
39716
+ this.emit({
39717
+ class: "Placeholder",
39718
+ method: "setBackgroundColor",
39719
+ item: [this.getId()],
39720
+ backgroundColor
39721
+ });
39795
39722
  }
39796
- shootLoadCallbacks() {
39797
- while (this.loadCallbacks.length > 0) {
39798
- this.loadCallbacks.shift()(this);
39799
- }
39800
- }
39801
- shootBeforeLoadCallbacks() {
39802
- while (this.beforeLoadCallbacks.length > 0) {
39803
- this.beforeLoadCallbacks.shift()(this);
39804
- }
39805
- }
39806
- getPath() {
39807
- const { left, top, right, bottom } = this.getMbr();
39808
- const leftTop = new Point(left, top);
39809
- const rightTop = new Point(right, top);
39810
- const rightBottom = new Point(right, bottom);
39811
- const leftBottom = new Point(left, bottom);
39812
- return new Path([
39813
- new Line(leftTop, rightTop),
39814
- new Line(rightTop, rightBottom),
39815
- new Line(rightBottom, leftBottom),
39816
- new Line(leftBottom, leftTop)
39817
- ], true);
39818
- }
39819
- getSnapAnchorPoints() {
39820
- const mbr = this.getMbr();
39821
- const width2 = mbr.getWidth();
39822
- const height2 = mbr.getHeight();
39823
- return [
39824
- new Point(mbr.left + width2 / 2, mbr.top),
39825
- new Point(mbr.left + width2 / 2, mbr.bottom),
39826
- new Point(mbr.left, mbr.top + height2 / 2),
39827
- new Point(mbr.right, mbr.top + height2 / 2)
39828
- ];
39829
- }
39830
- isClosed() {
39831
- return true;
39832
- }
39833
- getRichText() {
39834
- return null;
39835
- }
39836
- getLinkTo() {
39837
- return;
39838
- }
39839
- getExtension() {
39840
- return this.extension;
39841
- }
39842
- download() {
39843
- if (this.extension) {
39844
- const linkElem = conf.documentFactory.createElement("a");
39845
- linkElem.href = this.url;
39846
- linkElem.setAttribute("download", `${this.board.getBoardId()}.${this.extension}`);
39847
- linkElem.click();
39848
- }
39849
- }
39850
- }
39851
- // src/Items/Audio/AudioHelpers.ts
39852
- var uploadAudioToStorage = async (hash, audioBlob, accessToken, boardId) => {
39853
- return new Promise((resolve2, reject) => {
39854
- fetch(`${window.location.origin}/api/v1/media/audio/${boardId}`, {
39855
- method: "POST",
39856
- headers: {
39857
- "Content-Type": audioBlob.type,
39858
- "x-audio-id": hash,
39859
- Authorization: `Bearer ${accessToken}`
39860
- },
39861
- body: audioBlob
39862
- }).then(async (response) => {
39863
- if (response.status !== 200) {
39864
- return catchErrorResponse(response, "audio");
39865
- }
39866
- return response.json();
39867
- }).then((data) => {
39868
- console.log(data);
39869
- resolve2(data.src);
39870
- }).catch((error) => {
39871
- console.error("Media storage error:", error);
39872
- reject(error);
39873
- });
39874
- });
39875
- };
39876
- var prepareAudio = (file, accessToken, boardId) => {
39877
- return new Promise((resolve2, reject) => {
39878
- const audio = document.createElement("audio");
39879
- audio.src = URL.createObjectURL(file);
39880
- audio.onloadedmetadata = () => {
39881
- fileTosha256(file).then((hash) => {
39882
- uploadAudioToStorage(hash, file, accessToken, boardId).then((url) => {
39883
- resolve2(url);
39884
- }).catch(reject);
39885
- }).catch(() => {
39886
- reject(new Error("Failed to generate hash"));
39887
- });
39888
- };
39889
- audio.onerror = () => {
39890
- reject(new Error("Failed to load audio"));
39891
- };
39892
- });
39893
- };
39894
- var calculateAudioPosition = (board, audioItem) => {
39895
- const cameraMbr = board.camera.getMbr();
39896
- const cameraWidth = cameraMbr.getWidth();
39897
- const translateX = cameraMbr.left + cameraWidth * 0.34;
39898
- const translateY = cameraMbr.getCenter().y - audioItem.getHeight() / 2;
39899
- const scale = cameraWidth * 0.32 / audioItem.getWidth();
39900
- return new Matrix2(translateX, translateY, scale, scale);
39901
- };
39902
- // src/Items/Placeholder/Placeholder.ts
39903
- var PlaceholderImg = `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
39904
- <path d="M5 11.1L7 9.1L12.5 14.6L16 11.1L19 14.1V5H5V11.1ZM4 3H20C20.2652 3 20.5196 3.10536 20.7071 3.29289C20.8946 3.48043 21 3.73478 21 4V20C21 20.2652 20.8946 20.5196 20.7071 20.7071C20.5196 20.8946 20.2652 21 20 21H4C3.73478 21 3.48043 20.8946 3.29289 20.7071C3.10536 20.5196 3 20.2652 3 20V4C3 3.73478 3.10536 3.48043 3.29289 3.29289C3.48043 3.10536 3.73478 3 4 3ZM15.5 10C15.1022 10 14.7206 9.84196 14.4393 9.56066C14.158 9.27936 14 8.89782 14 8.5C14 8.10218 14.158 7.72064 14.4393 7.43934C14.7206 7.15804 15.1022 7 15.5 7C15.8978 7 16.2794 7.15804 16.5607 7.43934C16.842 7.72064 17 8.10218 17 8.5C17 8.89782 16.842 9.27936 16.5607 9.56066C16.2794 9.84196 15.8978 10 15.5 10Z" fill="white" fill-opacity="0.6"/>
39905
- </svg>`;
39906
-
39907
- class Placeholder extends BaseItem {
39908
- events;
39909
- miroData;
39910
- backgroundColor;
39911
- icon;
39912
- itemType = "Placeholder";
39913
- shapeType = "Rectangle";
39914
- parent = "Board";
39915
- transformation;
39916
- path = Shapes[this.shapeType].path.copy();
39917
- mbr = Shapes[this.shapeType].path.getMbr().copy();
39918
- subject = new Subject;
39919
- transformationRenderBlock = undefined;
39920
- iconImage;
39921
- constructor(board, events, miroData, id = "", backgroundColor = "#E5E5EA", icon = PlaceholderImg?.toString() || "") {
39922
- super(board, id);
39923
- this.events = events;
39924
- this.miroData = miroData;
39925
- this.backgroundColor = backgroundColor;
39926
- this.icon = icon;
39927
- this.transformation = new Transformation(this.id, this.events);
39928
- this.transformation.subject.subscribe((_subject) => {
39929
- this.transformPath();
39930
- this.updateMbr();
39931
- this.subject.publish(this);
39932
- });
39933
- this.updateMbr();
39934
- this.loadIconImage();
39935
- }
39936
- emit(operation) {
39937
- if (this.events) {
39938
- const command = new PlaceholderCommand([this], operation);
39939
- command.apply();
39940
- this.events.emit(operation, command);
39941
- } else {
39942
- this.apply(operation);
39943
- }
39944
- }
39945
- serialize() {
39946
- return {
39947
- itemType: "Placeholder",
39948
- backgroundColor: this.backgroundColor,
39949
- icon: this.icon,
39950
- transformation: this.transformation.serialize(),
39951
- miroData: this.miroData
39952
- };
39953
- }
39954
- deserialize(data) {
39955
- this.initPath();
39956
- this.backgroundColor = data.backgroundColor ?? this.backgroundColor;
39957
- this.icon = data.icon ?? this.icon;
39958
- this.miroData = data.miroData;
39959
- if (data.transformation) {
39960
- this.transformation.deserialize(data.transformation);
39961
- this.transformPath();
39962
- }
39963
- this.subject.publish(this);
39964
- return this;
39965
- }
39966
- setId(id) {
39967
- this.id = id;
39968
- this.transformation.setId(id);
39969
- return this;
39970
- }
39971
- getId() {
39972
- return this.id;
39973
- }
39974
- apply(op) {
39975
- switch (op.class) {
39976
- case "Placeholder":
39977
- this.applyPlaceholder(op);
39978
- this.updateMbr();
39979
- break;
39980
- case "Transformation":
39981
- this.transformation.apply(op);
39982
- break;
39983
- default:
39984
- return;
39985
- }
39986
- this.subject.publish(this);
39987
- }
39988
- applyPlaceholder(op) {
39989
- switch (op.method) {
39990
- case "setBackgroundColor":
39991
- this.applyBackgroundColor(op.backgroundColor);
39992
- break;
39993
- case "setIcon":
39994
- this.applyIcon(op.icon);
39995
- break;
39996
- case "setMiroData":
39997
- this.applyMiroData(op.miroData);
39998
- break;
39999
- }
40000
- }
40001
- getBackgroundColor() {
40002
- return this.backgroundColor;
40003
- }
40004
- applyBackgroundColor(backgroundColor) {
40005
- this.backgroundColor = backgroundColor;
40006
- this.path.setBackgroundColor(backgroundColor);
40007
- }
40008
- setBackgroundColor(backgroundColor) {
40009
- this.emit({
40010
- class: "Placeholder",
40011
- method: "setBackgroundColor",
40012
- item: [this.getId()],
40013
- backgroundColor
40014
- });
40015
- }
40016
- getIcon() {
40017
- return this.icon;
39723
+ getIcon() {
39724
+ return this.icon;
40018
39725
  }
40019
39726
  applyIcon(icon) {
40020
39727
  this.icon = icon;
@@ -40258,100 +39965,374 @@ class ImageItem extends BaseItem {
40258
39965
  this.shootLoadCallbacks();
40259
39966
  };
40260
39967
  onError = (_error) => {
40261
- this.image = getPlaceholderImage(this.board);
39968
+ this.image = getPlaceholderImage(this.board);
39969
+ this.updateMbr();
39970
+ this.subject.publish(this);
39971
+ this.shootLoadCallbacks();
39972
+ };
39973
+ onTransform = () => {
39974
+ this.updateMbr();
39975
+ this.subject.publish(this);
39976
+ };
39977
+ updateMbr() {
39978
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
39979
+ this.left = translateX;
39980
+ this.top = translateY;
39981
+ this.right = this.left + this.image.width * scaleX;
39982
+ this.bottom = this.top + this.image.height * scaleY;
39983
+ }
39984
+ doOnceBeforeOnLoad = (callback) => {
39985
+ this.loadCallbacks.push(callback);
39986
+ };
39987
+ doOnceOnLoad = (callback) => {
39988
+ this.loadCallbacks.push(callback);
39989
+ };
39990
+ setId(id) {
39991
+ this.id = id;
39992
+ this.transformation.setId(id);
39993
+ this.linkTo.setId(id);
39994
+ return this;
39995
+ }
39996
+ getId() {
39997
+ return this.id;
39998
+ }
39999
+ serialize() {
40000
+ return {
40001
+ itemType: "Image",
40002
+ storageLink: this.storageLink,
40003
+ imageDimension: this.imageDimension,
40004
+ transformation: this.transformation.serialize(),
40005
+ linkTo: this.linkTo.serialize()
40006
+ };
40007
+ }
40008
+ setCoordinates() {
40009
+ this.left = this.transformation.matrix.translateX;
40010
+ this.top = this.transformation.matrix.translateY;
40011
+ this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
40012
+ this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
40013
+ this.subject.publish(this);
40014
+ }
40015
+ shootBeforeLoadCallbacks() {
40016
+ while (this.beforeLoadCallbacks.length > 0) {
40017
+ this.beforeLoadCallbacks.shift()(this);
40018
+ }
40019
+ }
40020
+ shootLoadCallbacks() {
40021
+ while (this.loadCallbacks.length > 0) {
40022
+ this.loadCallbacks.shift()(this);
40023
+ }
40024
+ }
40025
+ deserialize(data) {
40026
+ if (data.transformation) {
40027
+ this.transformation.deserialize(data.transformation);
40028
+ }
40029
+ this.linkTo.deserialize(data.linkTo);
40030
+ this.image.onload = () => {
40031
+ this.setCoordinates();
40032
+ this.shootLoadCallbacks();
40033
+ };
40034
+ if (data.storageLink) {
40035
+ this.setStorageLink(data.storageLink);
40036
+ }
40037
+ if (this.image.src) {
40038
+ return this;
40039
+ }
40040
+ this.image = getPlaceholderImage(this.board, data.imageDimension);
40041
+ const storageImage = new Image;
40042
+ storageImage.onload = () => {
40043
+ this.image = storageImage;
40044
+ this.onLoad();
40045
+ };
40046
+ storageImage.onerror = this.onError;
40047
+ storageImage.src = this.storageLink;
40048
+ return this;
40049
+ }
40050
+ emit(operation) {
40051
+ if (this.events) {
40052
+ const command = new ImageCommand([this], operation);
40053
+ command.apply();
40054
+ this.events.emit(operation, command);
40055
+ } else {
40056
+ this.apply(operation);
40057
+ }
40058
+ }
40059
+ setDimensions(dim) {
40060
+ this.imageDimension = dim;
40061
+ }
40062
+ apply(op) {
40063
+ switch (op.class) {
40064
+ case "Transformation":
40065
+ this.transformation.apply(op);
40066
+ break;
40067
+ case "LinkTo":
40068
+ this.linkTo.apply(op);
40069
+ break;
40070
+ case "Image":
40071
+ if (op.data.base64) {
40072
+ this.image.src = op.data.base64;
40073
+ }
40074
+ this.setStorageLink(op.data.storageLink);
40075
+ this.setDimensions(op.data.imageDimension);
40076
+ this.subject.publish(this);
40077
+ break;
40078
+ }
40079
+ }
40080
+ render(context) {
40081
+ if (this.transformationRenderBlock) {
40082
+ return;
40083
+ }
40084
+ const ctx = context.ctx;
40085
+ ctx.save();
40086
+ this.transformation.matrix.applyToContext(ctx);
40087
+ ctx.drawImage(this.image, 0, 0);
40088
+ ctx.restore();
40089
+ if (this.getLinkTo()) {
40090
+ const { top, right } = this.getMbr();
40091
+ this.linkTo.render(context, top, right, this.board.camera.getScale());
40092
+ }
40093
+ }
40094
+ renderHTML(documentFactory) {
40095
+ const div = documentFactory.createElement("image-item");
40096
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
40097
+ const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
40098
+ div.style.backgroundImage = `url(${this.storageLink})`;
40099
+ div.id = this.getId();
40100
+ div.style.width = `${this.imageDimension.width}px`;
40101
+ div.style.height = `${this.imageDimension.height}px`;
40102
+ div.style.transformOrigin = "top left";
40103
+ div.style.transform = transform;
40104
+ div.style.position = "absolute";
40105
+ div.style.backgroundSize = "cover";
40106
+ div.setAttribute("data-link-to", this.linkTo.serialize() || "");
40107
+ if (this.getLinkTo()) {
40108
+ const linkElement = this.linkTo.renderHTML(documentFactory);
40109
+ scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
40110
+ translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
40111
+ div.appendChild(linkElement);
40112
+ }
40113
+ return div;
40114
+ }
40115
+ getPath() {
40116
+ const { left, top, right, bottom } = this.getMbr();
40117
+ const leftTop = new Point(left, top);
40118
+ const rightTop = new Point(right, top);
40119
+ const rightBottom = new Point(right, bottom);
40120
+ const leftBottom = new Point(left, bottom);
40121
+ return new Path([
40122
+ new Line(leftTop, rightTop),
40123
+ new Line(rightTop, rightBottom),
40124
+ new Line(rightBottom, leftBottom),
40125
+ new Line(leftBottom, leftTop)
40126
+ ], true);
40127
+ }
40128
+ getSnapAnchorPoints() {
40129
+ const mbr = this.getMbr();
40130
+ const width2 = mbr.getWidth();
40131
+ const height2 = mbr.getHeight();
40132
+ return [
40133
+ new Point(mbr.left + width2 / 2, mbr.top),
40134
+ new Point(mbr.left + width2 / 2, mbr.bottom),
40135
+ new Point(mbr.left, mbr.top + height2 / 2),
40136
+ new Point(mbr.right, mbr.top + height2 / 2)
40137
+ ];
40138
+ }
40139
+ isClosed() {
40140
+ return true;
40141
+ }
40142
+ getRichText() {
40143
+ return null;
40144
+ }
40145
+ getLinkTo() {
40146
+ return this.linkTo.link;
40147
+ }
40148
+ download() {
40149
+ const linkElem = document.createElement("a");
40150
+ linkElem.href = this.storageLink;
40151
+ linkElem.setAttribute("download", "");
40152
+ linkElem.click();
40153
+ }
40154
+ onRemove() {
40155
+ const storageId = this.getStorageId();
40156
+ if (storageId) {
40157
+ deleteMedia([storageId], this.board.getBoardId());
40158
+ }
40159
+ super.onRemove();
40160
+ }
40161
+ }
40162
+ // src/Items/Audio/Audio.ts
40163
+ class AudioItem extends BaseItem {
40164
+ events;
40165
+ extension;
40166
+ itemType = "Audio";
40167
+ parent = "Board";
40168
+ transformation;
40169
+ linkTo;
40170
+ subject = new Subject;
40171
+ loadCallbacks = [];
40172
+ beforeLoadCallbacks = [];
40173
+ transformationRenderBlock = undefined;
40174
+ url = "";
40175
+ isPlaying = false;
40176
+ currentTime = 0;
40177
+ isStorageUrl = true;
40178
+ constructor(board, isStorageUrl, url, events, id = "", extension2) {
40179
+ super(board, id);
40180
+ this.events = events;
40181
+ this.extension = extension2;
40182
+ this.linkTo = new LinkTo(this.id, events);
40183
+ this.board = board;
40184
+ this.isStorageUrl = isStorageUrl;
40185
+ if (url) {
40186
+ this.applyUrl(url);
40187
+ }
40188
+ this.transformation = new Transformation(id, events);
40189
+ this.linkTo.subject.subscribe(() => {
40190
+ this.updateMbr();
40191
+ this.subject.publish(this);
40192
+ });
40193
+ this.transformation.subject.subscribe(this.onTransform);
40194
+ this.right = this.left + conf.AUDIO_DIMENSIONS.width;
40195
+ this.bottom = this.top + conf.AUDIO_DIMENSIONS.height;
40196
+ this.shouldUseCustomRender = true;
40197
+ }
40198
+ setCurrentTime(time) {
40199
+ this.currentTime = time;
40200
+ }
40201
+ getCurrentTime() {
40202
+ return this.currentTime;
40203
+ }
40204
+ getIsStorageUrl() {
40205
+ return this.isStorageUrl;
40206
+ }
40207
+ onTransform = () => {
40208
+ this.updateMbr();
40209
+ this.subject.publish(this);
40210
+ };
40211
+ doOnceBeforeOnLoad = (callback) => {
40212
+ this.loadCallbacks.push(callback);
40213
+ };
40214
+ doOnceOnLoad = (callback) => {
40215
+ this.loadCallbacks.push(callback);
40216
+ };
40217
+ setIsPlaying(isPlaying) {
40218
+ this.isPlaying = isPlaying;
40219
+ this.shouldRenderOutsideViewRect = isPlaying;
40220
+ this.subject.publish(this);
40221
+ }
40222
+ getIsPlaying() {
40223
+ return this.isPlaying;
40224
+ }
40225
+ applyUrl(url) {
40226
+ if (this.isStorageUrl) {
40227
+ try {
40228
+ const newUrl = new URL(url);
40229
+ this.url = `${window.location.origin}${newUrl.pathname}`;
40230
+ } catch (_) {}
40231
+ } else {
40232
+ this.url = url;
40233
+ }
40234
+ }
40235
+ setUrl(url) {
40236
+ this.emit({
40237
+ class: "Audio",
40238
+ method: "setUrl",
40239
+ item: [this.getId()],
40240
+ url
40241
+ });
40242
+ }
40243
+ getStorageId() {
40244
+ if (!this.isStorageUrl) {
40245
+ return;
40246
+ }
40247
+ return this.url.split("/").pop();
40248
+ }
40249
+ getUrl() {
40250
+ return this.url;
40251
+ }
40252
+ onLoad = async () => {
40253
+ this.shootBeforeLoadCallbacks();
40254
+ this.updateMbr();
40255
+ this.subject.publish(this);
40256
+ this.shootLoadCallbacks();
40257
+ };
40258
+ onError = (_error) => {
40262
40259
  this.updateMbr();
40263
40260
  this.subject.publish(this);
40264
40261
  this.shootLoadCallbacks();
40265
40262
  };
40266
- onTransform = () => {
40267
- this.updateMbr();
40268
- this.subject.publish(this);
40269
- };
40270
40263
  updateMbr() {
40271
40264
  const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
40272
40265
  this.left = translateX;
40273
40266
  this.top = translateY;
40274
- this.right = this.left + this.image.width * scaleX;
40275
- this.bottom = this.top + this.image.height * scaleY;
40267
+ this.right = this.left + conf.AUDIO_DIMENSIONS.width * scaleX;
40268
+ this.bottom = this.top + conf.AUDIO_DIMENSIONS.height * scaleY;
40276
40269
  }
40277
- doOnceBeforeOnLoad = (callback) => {
40278
- this.loadCallbacks.push(callback);
40279
- };
40280
- doOnceOnLoad = (callback) => {
40281
- this.loadCallbacks.push(callback);
40282
- };
40283
- setId(id) {
40284
- this.id = id;
40285
- this.transformation.setId(id);
40286
- this.linkTo.setId(id);
40287
- return this;
40270
+ render(context) {
40271
+ if (this.transformationRenderBlock) {
40272
+ return;
40273
+ }
40274
+ const ctx = context.ctx;
40275
+ const radius = 12 * this.transformation.getScale().x;
40276
+ ctx.save();
40277
+ ctx.globalCompositeOperation = "destination-out";
40278
+ ctx.beginPath();
40279
+ ctx.moveTo(this.left + radius, this.top);
40280
+ ctx.lineTo(this.left + this.getWidth() - radius, this.top);
40281
+ ctx.quadraticCurveTo(this.left + this.getWidth(), this.top, this.left + this.getWidth(), this.top + radius);
40282
+ ctx.lineTo(this.left + this.getWidth(), this.top + this.getHeight() - radius);
40283
+ ctx.quadraticCurveTo(this.left + this.getWidth(), this.top + this.getHeight(), this.left + this.getWidth() - radius, this.top + this.getHeight());
40284
+ ctx.lineTo(this.left + radius, this.top + this.getHeight());
40285
+ ctx.quadraticCurveTo(this.left, this.top + this.getHeight(), this.left, this.top + this.getHeight() - radius);
40286
+ ctx.lineTo(this.left, this.top + radius);
40287
+ ctx.quadraticCurveTo(this.left, this.top, this.left + radius, this.top);
40288
+ ctx.closePath();
40289
+ ctx.fill();
40290
+ ctx.restore();
40288
40291
  }
40289
- getId() {
40290
- return this.id;
40292
+ renderHTML(documentFactory) {
40293
+ const div = documentFactory.createElement("audio-item");
40294
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
40295
+ const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
40296
+ div.id = this.getId();
40297
+ div.style.width = `${conf.AUDIO_DIMENSIONS.width}px`;
40298
+ div.style.height = `${conf.AUDIO_DIMENSIONS.height}px`;
40299
+ div.style.transformOrigin = "top left";
40300
+ div.style.transform = transform;
40301
+ div.style.position = "absolute";
40302
+ div.setAttribute("audio-url", this.getUrl());
40303
+ if (this.extension) {
40304
+ div.setAttribute("extension", this.extension);
40305
+ }
40306
+ if (this.isStorageUrl) {
40307
+ div.setAttribute("is-storage-url", "true");
40308
+ }
40309
+ div.setAttribute("data-link-to", "");
40310
+ return div;
40291
40311
  }
40292
40312
  serialize() {
40293
40313
  return {
40294
- itemType: "Image",
40295
- storageLink: this.storageLink,
40296
- imageDimension: this.imageDimension,
40314
+ itemType: "Audio",
40315
+ url: this.url,
40297
40316
  transformation: this.transformation.serialize(),
40298
- linkTo: this.linkTo.serialize()
40317
+ isStorageUrl: this.isStorageUrl,
40318
+ extension: this.extension
40299
40319
  };
40300
40320
  }
40301
- setCoordinates() {
40302
- this.left = this.transformation.matrix.translateX;
40303
- this.top = this.transformation.matrix.translateY;
40304
- this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
40305
- this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
40306
- this.subject.publish(this);
40307
- }
40308
- shootBeforeLoadCallbacks() {
40309
- while (this.beforeLoadCallbacks.length > 0) {
40310
- this.beforeLoadCallbacks.shift()(this);
40311
- }
40312
- }
40313
- shootLoadCallbacks() {
40314
- while (this.loadCallbacks.length > 0) {
40315
- this.loadCallbacks.shift()(this);
40316
- }
40317
- }
40318
40321
  deserialize(data) {
40322
+ if (data.isStorageUrl) {
40323
+ this.isStorageUrl = data.isStorageUrl;
40324
+ }
40319
40325
  if (data.transformation) {
40320
40326
  this.transformation.deserialize(data.transformation);
40321
40327
  }
40322
- this.linkTo.deserialize(data.linkTo);
40323
- this.image.onload = () => {
40324
- this.setCoordinates();
40325
- this.shootLoadCallbacks();
40326
- };
40327
- if (data.storageLink) {
40328
- this.setStorageLink(data.storageLink);
40328
+ if (data.url) {
40329
+ this.setUrl(data.url);
40329
40330
  }
40330
- if (this.image.src) {
40331
- return this;
40331
+ if (data.extension) {
40332
+ this.extension = data.extension;
40332
40333
  }
40333
- this.image = getPlaceholderImage(this.board, data.imageDimension);
40334
- const storageImage = new Image;
40335
- storageImage.onload = () => {
40336
- this.image = storageImage;
40337
- this.onLoad();
40338
- };
40339
- storageImage.onerror = this.onError;
40340
- storageImage.src = this.storageLink;
40341
40334
  return this;
40342
40335
  }
40343
- emit(operation) {
40344
- if (this.events) {
40345
- const command = new ImageCommand([this], operation);
40346
- command.apply();
40347
- this.events.emit(operation, command);
40348
- } else {
40349
- this.apply(operation);
40350
- }
40351
- }
40352
- setDimensions(dim) {
40353
- this.imageDimension = dim;
40354
- }
40355
40336
  apply(op) {
40356
40337
  switch (op.class) {
40357
40338
  case "Transformation":
@@ -40360,50 +40341,40 @@ class ImageItem extends BaseItem {
40360
40341
  case "LinkTo":
40361
40342
  this.linkTo.apply(op);
40362
40343
  break;
40363
- case "Image":
40364
- if (op.data.base64) {
40365
- this.image.src = op.data.base64;
40344
+ case "Audio":
40345
+ if (op.method === "setUrl") {
40346
+ this.applyUrl(op.url);
40366
40347
  }
40367
- this.setStorageLink(op.data.storageLink);
40368
- this.setDimensions(op.data.imageDimension);
40369
40348
  this.subject.publish(this);
40370
40349
  break;
40371
40350
  }
40372
40351
  }
40373
- render(context) {
40374
- if (this.transformationRenderBlock) {
40375
- return;
40352
+ emit(operation) {
40353
+ if (this.events) {
40354
+ const command = new AudioCommand([this], operation);
40355
+ command.apply();
40356
+ this.events.emit(operation, command);
40357
+ } else {
40358
+ this.apply(operation);
40376
40359
  }
40377
- const ctx = context.ctx;
40378
- ctx.save();
40379
- this.transformation.matrix.applyToContext(ctx);
40380
- ctx.drawImage(this.image, 0, 0);
40381
- ctx.restore();
40382
- if (this.getLinkTo()) {
40383
- const { top, right } = this.getMbr();
40384
- this.linkTo.render(context, top, right, this.board.camera.getScale());
40360
+ }
40361
+ setId(id) {
40362
+ this.id = id;
40363
+ this.transformation.setId(id);
40364
+ return this;
40365
+ }
40366
+ getId() {
40367
+ return this.id;
40368
+ }
40369
+ shootLoadCallbacks() {
40370
+ while (this.loadCallbacks.length > 0) {
40371
+ this.loadCallbacks.shift()(this);
40385
40372
  }
40386
40373
  }
40387
- renderHTML(documentFactory) {
40388
- const div = documentFactory.createElement("image-item");
40389
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
40390
- const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
40391
- div.style.backgroundImage = `url(${this.storageLink})`;
40392
- div.id = this.getId();
40393
- div.style.width = `${this.imageDimension.width}px`;
40394
- div.style.height = `${this.imageDimension.height}px`;
40395
- div.style.transformOrigin = "top left";
40396
- div.style.transform = transform;
40397
- div.style.position = "absolute";
40398
- div.style.backgroundSize = "cover";
40399
- div.setAttribute("data-link-to", this.linkTo.serialize() || "");
40400
- if (this.getLinkTo()) {
40401
- const linkElement = this.linkTo.renderHTML(documentFactory);
40402
- scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
40403
- translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
40404
- div.appendChild(linkElement);
40374
+ shootBeforeLoadCallbacks() {
40375
+ while (this.beforeLoadCallbacks.length > 0) {
40376
+ this.beforeLoadCallbacks.shift()(this);
40405
40377
  }
40406
- return div;
40407
40378
  }
40408
40379
  getPath() {
40409
40380
  const { left, top, right, bottom } = this.getMbr();
@@ -40436,15 +40407,78 @@ class ImageItem extends BaseItem {
40436
40407
  return null;
40437
40408
  }
40438
40409
  getLinkTo() {
40439
- return this.linkTo.link;
40410
+ return;
40411
+ }
40412
+ getExtension() {
40413
+ return this.extension;
40440
40414
  }
40441
40415
  download() {
40442
- const linkElem = document.createElement("a");
40443
- linkElem.href = this.storageLink;
40444
- linkElem.setAttribute("download", "");
40445
- linkElem.click();
40416
+ if (this.extension) {
40417
+ const linkElem = conf.documentFactory.createElement("a");
40418
+ linkElem.href = this.url;
40419
+ linkElem.setAttribute("download", `${this.board.getBoardId()}.${this.extension}`);
40420
+ linkElem.click();
40421
+ }
40422
+ }
40423
+ onRemove() {
40424
+ const storageId = this.getStorageId();
40425
+ if (storageId) {
40426
+ deleteMedia([storageId], this.board.getBoardId());
40427
+ }
40428
+ super.onRemove();
40446
40429
  }
40447
40430
  }
40431
+ // src/Items/Audio/AudioHelpers.ts
40432
+ var uploadAudioToStorage = async (hash, audioBlob, accessToken, boardId) => {
40433
+ return new Promise((resolve2, reject) => {
40434
+ fetch(`${window.location.origin}/api/v1/media/audio/${boardId}`, {
40435
+ method: "POST",
40436
+ headers: {
40437
+ "Content-Type": audioBlob.type,
40438
+ "x-audio-id": hash,
40439
+ Authorization: `Bearer ${accessToken}`
40440
+ },
40441
+ body: audioBlob
40442
+ }).then(async (response) => {
40443
+ if (response.status !== 200) {
40444
+ return catchErrorResponse(response, "audio");
40445
+ }
40446
+ return response.json();
40447
+ }).then((data) => {
40448
+ console.log(data);
40449
+ resolve2(data.src);
40450
+ }).catch((error) => {
40451
+ console.error("Media storage error:", error);
40452
+ reject(error);
40453
+ });
40454
+ });
40455
+ };
40456
+ var prepareAudio = (file, accessToken, boardId) => {
40457
+ return new Promise((resolve2, reject) => {
40458
+ const audio = document.createElement("audio");
40459
+ audio.src = URL.createObjectURL(file);
40460
+ audio.onloadedmetadata = () => {
40461
+ fileTosha256(file).then((hash) => {
40462
+ uploadAudioToStorage(hash, file, accessToken, boardId).then((url) => {
40463
+ resolve2(url);
40464
+ }).catch(reject);
40465
+ }).catch(() => {
40466
+ reject(new Error("Failed to generate hash"));
40467
+ });
40468
+ };
40469
+ audio.onerror = () => {
40470
+ reject(new Error("Failed to load audio"));
40471
+ };
40472
+ });
40473
+ };
40474
+ var calculateAudioPosition = (board, audioItem) => {
40475
+ const cameraMbr = board.camera.getMbr();
40476
+ const cameraWidth = cameraMbr.getWidth();
40477
+ const translateX = cameraMbr.left + cameraWidth * 0.34;
40478
+ const translateY = cameraMbr.getCenter().y - audioItem.getHeight() / 2;
40479
+ const scale = cameraWidth * 0.32 / audioItem.getWidth();
40480
+ return new Matrix2(translateX, translateY, scale, scale);
40481
+ };
40448
40482
  // src/isSafari.ts
40449
40483
  function isSafari() {
40450
40484
  if (typeof navigator === "undefined") {
@@ -52296,9 +52330,8 @@ class Board {
52296
52330
  if (withConnectors) {
52297
52331
  connectors = this.items.getLinkedConnectorsById(item.getId()).map((connector) => connector.getId());
52298
52332
  }
52299
- const shouldClearStorageUsage = item.itemType === "Image" || item.itemType === "Video" && item.getIsStorageUrl() || item.itemType === "Audio" && item.getIsStorageUrl();
52300
- if (shouldClearStorageUsage) {
52301
- deleteMedia([item.getStorageId()], this.boardId);
52333
+ if ("onRemove" in item) {
52334
+ item.onRemove();
52302
52335
  }
52303
52336
  this.emit({
52304
52337
  class: "Board",
@@ -52441,7 +52474,7 @@ class Board {
52441
52474
  const created = this.createItem(this.getNewItemId(), childData);
52442
52475
  const added = this.add(created);
52443
52476
  idsMap[childData.id] = added.getId();
52444
- if (added.itemType === "Connector") {
52477
+ if (added instanceof Connector2) {
52445
52478
  addedConnectors.push({
52446
52479
  item: added,
52447
52480
  data: childData
@@ -52454,7 +52487,7 @@ class Board {
52454
52487
  idsMap[parsedData.data.id] = addedFrame.getId();
52455
52488
  } else {
52456
52489
  const added = this.add(this.createItem(this.getNewItemId(), parsedData));
52457
- if (added.itemType === "Connector") {
52490
+ if (added instanceof Connector2) {
52458
52491
  addedConnectors.push({
52459
52492
  item: added,
52460
52493
  data: parsedData
@@ -52492,10 +52525,10 @@ class Board {
52492
52525
  const createdFrames = {};
52493
52526
  const addItem = (itemData) => {
52494
52527
  const item = this.createItem(itemData.id, itemData);
52495
- if (item.itemType === "Connector") {
52528
+ if (item instanceof Connector2) {
52496
52529
  createdConnectors[itemData.id] = { item, itemData };
52497
52530
  }
52498
- if (item.itemType === "Frame") {
52531
+ if (item instanceof Frame) {
52499
52532
  createdFrames[item.getId()] = { item, itemData };
52500
52533
  }
52501
52534
  this.index.insert(item);
@@ -52527,10 +52560,10 @@ class Board {
52527
52560
  if (Array.isArray(items)) {
52528
52561
  for (const itemData of items) {
52529
52562
  const item = this.createItem(itemData.id, itemData);
52530
- if (item.itemType === "Connector") {
52563
+ if (item instanceof Connector2) {
52531
52564
  createdConnectors[itemData.id] = { item, itemData };
52532
52565
  }
52533
- if (item.itemType === "Frame") {
52566
+ if (item instanceof Frame) {
52534
52567
  createdFrames[item.getId()] = { item, itemData };
52535
52568
  }
52536
52569
  this.index.insert(item);
@@ -52539,7 +52572,7 @@ class Board {
52539
52572
  for (const key in items) {
52540
52573
  const itemData = items[key];
52541
52574
  const item = this.createItem(key, itemData);
52542
- if (item.itemType === "Connector") {
52575
+ if (item instanceof Connector2) {
52543
52576
  createdConnectors[key] = { item, itemData };
52544
52577
  }
52545
52578
  this.index.insert(item);