microboard-temp 0.4.40 → 0.4.42

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.
package/dist/esm/index.js CHANGED
@@ -19486,433 +19486,6 @@ class NoOpCommand {
19486
19486
  }
19487
19487
  }
19488
19488
 
19489
- // src/isSafari.ts
19490
- function isSafari() {
19491
- if (typeof navigator === "undefined") {
19492
- return false;
19493
- }
19494
- const agent = navigator.userAgent;
19495
- const vendor = navigator.vendor;
19496
- const is = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
19497
- return is;
19498
- }
19499
-
19500
- // src/Items/Drawing/Drawing.ts
19501
- class Drawing extends BaseItem {
19502
- points;
19503
- events;
19504
- itemType = "Drawing";
19505
- parent = "Board";
19506
- transformation;
19507
- path2d = new conf.path2DFactory;
19508
- subject = new Subject;
19509
- untransformedMbr = new Mbr;
19510
- lines = [];
19511
- linkTo;
19512
- strokeWidth = 1;
19513
- borderStyle = "solid";
19514
- linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
19515
- borderOpacity = 1;
19516
- transformationRenderBlock = undefined;
19517
- constructor(board, points, events, id = "") {
19518
- super(board, id);
19519
- this.points = points;
19520
- this.events = events;
19521
- this.transformation = new Transformation(id, events);
19522
- this.linkTo = new LinkTo(this.id, this.events);
19523
- this.transformation.subject.subscribe(() => {
19524
- this.updateMbr();
19525
- this.updateLines();
19526
- this.subject.publish(this);
19527
- });
19528
- this.linkTo.subject.subscribe(() => {
19529
- this.updateMbr();
19530
- this.updateLines();
19531
- this.subject.publish(this);
19532
- });
19533
- this.updateLines();
19534
- }
19535
- serialize() {
19536
- this.optimizePoints();
19537
- const points = [];
19538
- for (const point3 of this.points) {
19539
- points.push({ x: point3.x, y: point3.y });
19540
- }
19541
- return {
19542
- itemType: "Drawing",
19543
- points,
19544
- transformation: this.transformation.serialize(),
19545
- strokeStyle: this.borderColor,
19546
- strokeWidth: this.strokeWidth,
19547
- linkTo: this.linkTo.serialize()
19548
- };
19549
- }
19550
- deserialize(data) {
19551
- this.points = [];
19552
- for (const point3 of data.points) {
19553
- this.points.push(new Point(point3.x, point3.y));
19554
- }
19555
- this.linkTo.deserialize(data.linkTo);
19556
- this.optimizePoints();
19557
- this.transformation.deserialize(data.transformation);
19558
- this.borderColor = data.strokeStyle;
19559
- this.strokeWidth = data.strokeWidth;
19560
- this.updateGeometry();
19561
- return this;
19562
- }
19563
- updateGeometry() {
19564
- this.updatePath2d();
19565
- this.updateLines();
19566
- this.updateMbr();
19567
- }
19568
- updateMbr() {
19569
- const offset = this.getStrokeWidth() / 2;
19570
- const untransformedMbr = this.untransformedMbr.copy();
19571
- untransformedMbr.left -= offset;
19572
- untransformedMbr.top -= offset;
19573
- untransformedMbr.right += offset;
19574
- untransformedMbr.bottom += offset;
19575
- const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
19576
- this.left = mbr.left;
19577
- this.top = mbr.top;
19578
- this.right = mbr.right;
19579
- this.bottom = mbr.bottom;
19580
- }
19581
- updatePath2d() {
19582
- this.path2d = new conf.path2DFactory;
19583
- const context = this.path2d;
19584
- const points = this.points;
19585
- if (points.length < 3) {
19586
- context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
19587
- context.closePath();
19588
- } else {
19589
- context.moveTo(points[0].x, points[0].y);
19590
- let j = 1;
19591
- for (;j < points.length - 2; j++) {
19592
- const cx = (points[j].x + points[j + 1].x) / 2;
19593
- const cy = (points[j].y + points[j + 1].y) / 2;
19594
- context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
19595
- }
19596
- const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
19597
- const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
19598
- context.quadraticCurveTo(points[j].x, points[j].y, x, y);
19599
- }
19600
- let left = Number.MAX_SAFE_INTEGER;
19601
- let right = Number.MIN_SAFE_INTEGER;
19602
- let top = Number.MAX_SAFE_INTEGER;
19603
- let bottom = Number.MIN_SAFE_INTEGER;
19604
- for (const { x, y } of this.points) {
19605
- if (x < left) {
19606
- left = x;
19607
- }
19608
- if (x > right) {
19609
- right = x;
19610
- }
19611
- if (y < top) {
19612
- top = y;
19613
- }
19614
- if (y > bottom) {
19615
- bottom = y;
19616
- }
19617
- }
19618
- this.untransformedMbr = new Mbr(left, top, right, bottom);
19619
- }
19620
- updateLines() {
19621
- this.lines = [];
19622
- const matrix = this.transformation.matrix;
19623
- if (this.points.length < 2) {
19624
- return;
19625
- }
19626
- for (let i = 0;i < this.points.length - 2; i++) {
19627
- const p1 = this.points[i];
19628
- const p2 = this.points[i + 1];
19629
- const line = new Line(p1.copy(), p2.copy());
19630
- line.transform(matrix);
19631
- this.lines.push(line);
19632
- }
19633
- }
19634
- optimizePoints() {
19635
- const dp = douglasPeucker(this.points, 1);
19636
- dp.push(this.points[this.points.length - 1]);
19637
- this.points = dp;
19638
- }
19639
- addPoint(point3) {
19640
- const previous2 = this.points[this.points.length - 1];
19641
- if (previous2) {
19642
- const distance = point3.getDistance(previous2);
19643
- if (distance >= 2) {
19644
- this.points.push(point3);
19645
- }
19646
- } else {
19647
- this.points.push(point3);
19648
- }
19649
- this.updateGeometry();
19650
- }
19651
- setId(id) {
19652
- this.id = id;
19653
- this.transformation.setId(id);
19654
- this.linkTo.setId(id);
19655
- return this;
19656
- }
19657
- getId() {
19658
- return this.id;
19659
- }
19660
- render(context) {
19661
- if (this.transformationRenderBlock) {
19662
- return;
19663
- }
19664
- const ctx = context.ctx;
19665
- ctx.save();
19666
- ctx.strokeStyle = this.borderColor;
19667
- ctx.lineWidth = this.strokeWidth;
19668
- ctx.lineCap = "round";
19669
- ctx.setLineDash(this.linePattern);
19670
- this.transformation.matrix.applyToContext(ctx);
19671
- ctx.stroke(this.path2d.nativePath);
19672
- ctx.restore();
19673
- if (this.getLinkTo()) {
19674
- const { top, right } = this.getMbr();
19675
- this.linkTo.render(context, top, right, this.board.camera.getScale());
19676
- }
19677
- }
19678
- renderHTML(documentFactory) {
19679
- const div = documentFactory.createElement("drawing-item");
19680
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
19681
- const mbr = this.getMbr();
19682
- const width = mbr.getWidth();
19683
- const height = mbr.getHeight();
19684
- const unscaledWidth = width / scaleX;
19685
- const unscaledHeight = height / scaleY;
19686
- const svg = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
19687
- svg.setAttribute("width", `${unscaledWidth}px`);
19688
- svg.setAttribute("height", `${unscaledHeight}px`);
19689
- svg.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
19690
- svg.setAttribute("style", "position: absolute; overflow: visible;");
19691
- const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
19692
- pathElement.setAttribute("d", this.getPathData());
19693
- pathElement.setAttribute("stroke", this.borderColor);
19694
- pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
19695
- pathElement.setAttribute("fill", "none");
19696
- svg.appendChild(pathElement);
19697
- div.appendChild(svg);
19698
- div.id = this.getId();
19699
- div.style.width = unscaledWidth + "px";
19700
- div.style.height = unscaledHeight + "px";
19701
- div.style.transformOrigin = "left top";
19702
- div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
19703
- div.style.position = "absolute";
19704
- div.setAttribute("data-link-to", this.linkTo.serialize() || "");
19705
- if (this.getLinkTo()) {
19706
- const linkElement = this.linkTo.renderHTML(documentFactory);
19707
- scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
19708
- translateElementBy(linkElement, (width - parseInt(linkElement.style.width)) / scaleX, 0);
19709
- div.appendChild(linkElement);
19710
- }
19711
- return div;
19712
- }
19713
- getPathData() {
19714
- const points = this.points;
19715
- if (points.length < 2) {
19716
- return "";
19717
- }
19718
- let pathData = `M ${points[0].x} ${points[0].y}`;
19719
- if (points.length < 3) {
19720
- pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
19721
- } else {
19722
- let j = 1;
19723
- for (;j < points.length - 2; j++) {
19724
- const cx = (points[j].x + points[j + 1].x) / 2;
19725
- const cy = (points[j].y + points[j + 1].y) / 2;
19726
- pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
19727
- }
19728
- const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
19729
- const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
19730
- pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
19731
- }
19732
- return pathData;
19733
- }
19734
- getPath() {
19735
- const { left, top, right, bottom } = this.getMbr();
19736
- const leftTop = new Point(left, top);
19737
- const rightTop = new Point(right, top);
19738
- const rightBottom = new Point(right, bottom);
19739
- const leftBottom = new Point(left, bottom);
19740
- return new Path([
19741
- new Line(leftTop, rightTop),
19742
- new Line(rightTop, rightBottom),
19743
- new Line(rightBottom, leftBottom),
19744
- new Line(leftBottom, leftTop)
19745
- ], true);
19746
- }
19747
- getSnapAnchorPoints() {
19748
- const mbr = this.getMbr();
19749
- const width = mbr.getWidth();
19750
- const height = mbr.getHeight();
19751
- return [
19752
- new Point(mbr.left + width / 2, mbr.top),
19753
- new Point(mbr.left + width / 2, mbr.bottom),
19754
- new Point(mbr.left, mbr.top + height / 2),
19755
- new Point(mbr.right, mbr.top + height / 2)
19756
- ];
19757
- }
19758
- getLines() {
19759
- return this.lines;
19760
- }
19761
- isClosed() {
19762
- return true;
19763
- }
19764
- isEnclosedOrCrossedBy(rect) {
19765
- for (const line of this.lines) {
19766
- if (line.isEnclosedOrCrossedBy(rect)) {
19767
- return true;
19768
- }
19769
- }
19770
- return false;
19771
- }
19772
- emit(operation) {
19773
- if (this.events) {
19774
- const command = new DrawingCommand([this], operation);
19775
- command.apply();
19776
- this.events.emit(operation, command);
19777
- } else {
19778
- this.apply(operation);
19779
- }
19780
- }
19781
- apply(op) {
19782
- switch (op.class) {
19783
- case "Drawing":
19784
- switch (op.method) {
19785
- case "setStrokeColor":
19786
- this.borderColor = op.color;
19787
- break;
19788
- case "setStrokeWidth":
19789
- this.strokeWidth = op.width;
19790
- this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
19791
- break;
19792
- case "setStrokeOpacity":
19793
- this.borderOpacity = op.opacity;
19794
- break;
19795
- case "setStrokeStyle":
19796
- this.borderStyle = op.style;
19797
- this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
19798
- break;
19799
- }
19800
- this.updateMbr();
19801
- break;
19802
- case "Transformation":
19803
- this.transformation.apply(op);
19804
- break;
19805
- case "LinkTo":
19806
- this.linkTo.apply(op);
19807
- break;
19808
- default:
19809
- return;
19810
- }
19811
- this.subject.publish(this);
19812
- }
19813
- setStrokeOpacity(opacity) {
19814
- this.emit({
19815
- class: "Drawing",
19816
- method: "setStrokeOpacity",
19817
- item: [this.id],
19818
- opacity
19819
- });
19820
- return this;
19821
- }
19822
- getStrokeOpacity() {
19823
- return this.borderOpacity;
19824
- }
19825
- setBorderStyle(style) {
19826
- this.emit({
19827
- class: "Drawing",
19828
- method: "setStrokeStyle",
19829
- item: [this.id],
19830
- style
19831
- });
19832
- return this;
19833
- }
19834
- getBorderStyle() {
19835
- return this.borderStyle;
19836
- }
19837
- setStrokeColor(color) {
19838
- this.emit({
19839
- class: "Drawing",
19840
- method: "setStrokeColor",
19841
- item: [this.id],
19842
- color
19843
- });
19844
- return this;
19845
- }
19846
- getStrokeColor() {
19847
- return this.borderColor;
19848
- }
19849
- setStrokeWidth(width) {
19850
- this.emit({
19851
- class: "Drawing",
19852
- method: "setStrokeWidth",
19853
- item: [this.id],
19854
- width,
19855
- prevWidth: this.strokeWidth
19856
- });
19857
- return this;
19858
- }
19859
- getLinkTo() {
19860
- return this.linkTo.link;
19861
- }
19862
- getStrokeWidth() {
19863
- return this.strokeWidth;
19864
- }
19865
- getRichText() {
19866
- return null;
19867
- }
19868
- isPointNearLine(point3, threshold = 10) {
19869
- const transformedMouseX = (point3.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
19870
- const transformedMouseY = (point3.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
19871
- const transformedMouse = new Point(transformedMouseX, transformedMouseY);
19872
- for (let i = 0;i < this.points.length - 1; i++) {
19873
- const p1 = this.points[i];
19874
- const p2 = this.points[i + 1];
19875
- const distance = getPerpendicularDistance(transformedMouse, p1, p2);
19876
- if (distance < threshold) {
19877
- return true;
19878
- }
19879
- }
19880
- return false;
19881
- }
19882
- }
19883
- function getPerpendicularDistance(point3, lineStart, lineEnd) {
19884
- const { x: px, y: py } = point3;
19885
- const { x: sx, y: sy } = lineStart;
19886
- const { x: ex, y: ey } = lineEnd;
19887
- const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
19888
- const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
19889
- return numerator / denominator;
19890
- }
19891
- function douglasPeucker(points, epsilon2) {
19892
- if (points.length < 3) {
19893
- return points;
19894
- }
19895
- const start = points[0];
19896
- const end = points[points.length - 1];
19897
- let maxDistance = 0;
19898
- let maxIndex = 0;
19899
- for (let i = 1;i < points.length - 1; i++) {
19900
- const distance = getPerpendicularDistance(points[i], start, end);
19901
- if (distance > maxDistance) {
19902
- maxDistance = distance;
19903
- maxIndex = i;
19904
- }
19905
- }
19906
- if (maxDistance > epsilon2) {
19907
- const leftSubPoints = points.slice(0, maxIndex + 1);
19908
- const rightSubPoints = points.slice(maxIndex);
19909
- const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
19910
- const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
19911
- return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
19912
- } else {
19913
- return [start, end];
19914
- }
19915
- }
19916
19489
  // src/SpatialIndex/LayeredIndex/Layers.ts
19917
19490
  class Layers {
19918
19491
  getNewLayer;
@@ -21302,12 +20875,12 @@ class Items {
21302
20875
  if (enclosed.length === 0) {
21303
20876
  enclosed = underPointer;
21304
20877
  }
21305
- if (underPointer.some((item) => item instanceof Drawing)) {
20878
+ if (underPointer.some((item) => item.itemType === "Drawing")) {
21306
20879
  enclosed = [...underPointer, ...enclosed];
21307
20880
  }
21308
20881
  const { nearest } = enclosed.reduce((acc, item) => {
21309
20882
  const area = item.getMbr().getHeight() * item.getMbr().getWidth();
21310
- if (item instanceof Drawing && !item.isPointNearLine(this.pointer.point)) {
20883
+ if (item.itemType === "Drawing" && !item.isPointNearLine(this.pointer.point)) {
21311
20884
  return acc;
21312
20885
  }
21313
20886
  const isItemTransparent = item instanceof Shape && item?.getBackgroundColor() === "none";
@@ -21442,6 +21015,7 @@ class Items {
21442
21015
  }
21443
21016
  }
21444
21017
 
21018
+ // src/SpatialIndex/SimpleSpatialIndex.ts
21445
21019
  class SimpleSpatialIndex {
21446
21020
  subject = new Subject;
21447
21021
  itemsArray = [];
@@ -42191,202 +41765,455 @@ class Placeholder extends BaseItem {
42191
41765
  renderHTML(documentFactory) {
42192
41766
  return documentFactory.createElement("div");
42193
41767
  }
42194
- getLinkTo() {
42195
- return;
41768
+ getLinkTo() {
41769
+ return;
41770
+ }
41771
+ getRichText() {
41772
+ return null;
41773
+ }
41774
+ }
41775
+ // src/Items/Image/Image.ts
41776
+ function getPlaceholderImage(board, imageDimension) {
41777
+ const placeholderCanvas = conf.documentFactory.createElement("canvas");
41778
+ const placeholderContext = placeholderCanvas.getContext("2d");
41779
+ const context = new DrawingContext(board.camera, placeholderContext);
41780
+ const placeholder = new Placeholder(board);
41781
+ if (imageDimension) {
41782
+ placeholderCanvas.width = imageDimension.width;
41783
+ placeholderCanvas.height = imageDimension.height;
41784
+ placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
41785
+ } else {
41786
+ placeholderCanvas.width = 250;
41787
+ placeholderCanvas.height = 50;
41788
+ placeholder.transformation.scaleTo(250 / 100, 50 / 100);
41789
+ }
41790
+ const placeholderImage = new Image;
41791
+ placeholderImage.src = placeholderCanvas.toDataURL();
41792
+ return placeholderImage;
41793
+ }
41794
+
41795
+ class ImageItem extends BaseItem {
41796
+ events;
41797
+ itemType = "Image";
41798
+ parent = "Board";
41799
+ image;
41800
+ transformation;
41801
+ linkTo;
41802
+ subject = new Subject;
41803
+ loadCallbacks = [];
41804
+ beforeLoadCallbacks = [];
41805
+ transformationRenderBlock = undefined;
41806
+ storageLink;
41807
+ imageDimension;
41808
+ board;
41809
+ constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
41810
+ super(board, id);
41811
+ this.events = events;
41812
+ this.linkTo = new LinkTo(this.id, events);
41813
+ this.board = board;
41814
+ this.setStorageLink(storageLink);
41815
+ this.imageDimension = imageDimension;
41816
+ this.transformation = new Transformation(id, events);
41817
+ this.image = new Image;
41818
+ this.image.crossOrigin = "anonymous";
41819
+ this.image.onload = this.onLoad;
41820
+ this.image.onerror = this.onError;
41821
+ if (typeof base64 === "string") {
41822
+ this.image.src = base64;
41823
+ }
41824
+ this.linkTo.subject.subscribe(() => {
41825
+ this.updateMbr();
41826
+ this.subject.publish(this);
41827
+ });
41828
+ this.transformation.subject.subscribe(this.onTransform);
41829
+ }
41830
+ setStorageLink(link2) {
41831
+ try {
41832
+ const url = new URL(link2);
41833
+ this.storageLink = `${window?.location.origin}${url.pathname}`;
41834
+ } catch (_) {}
41835
+ }
41836
+ getStorageId() {
41837
+ return this.storageLink.split("/").pop();
41838
+ }
41839
+ handleError = () => {
41840
+ console.error("Invalid dataUrl or image failed to load.");
41841
+ this.image = getPlaceholderImage(this.board);
41842
+ this.updateMbr();
41843
+ this.subject.publish(this);
41844
+ this.shootLoadCallbacks();
41845
+ };
41846
+ onLoad = async () => {
41847
+ this.shootBeforeLoadCallbacks();
41848
+ this.updateMbr();
41849
+ this.subject.publish(this);
41850
+ this.shootLoadCallbacks();
41851
+ };
41852
+ onError = (_error) => {
41853
+ this.image = getPlaceholderImage(this.board);
41854
+ this.updateMbr();
41855
+ this.subject.publish(this);
41856
+ this.shootLoadCallbacks();
41857
+ };
41858
+ onTransform = () => {
41859
+ this.updateMbr();
41860
+ this.subject.publish(this);
41861
+ };
41862
+ updateMbr() {
41863
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
41864
+ this.left = translateX;
41865
+ this.top = translateY;
41866
+ this.right = this.left + this.image.width * scaleX;
41867
+ this.bottom = this.top + this.image.height * scaleY;
41868
+ }
41869
+ doOnceBeforeOnLoad = (callback) => {
41870
+ this.loadCallbacks.push(callback);
41871
+ };
41872
+ doOnceOnLoad = (callback) => {
41873
+ this.loadCallbacks.push(callback);
41874
+ };
41875
+ setId(id) {
41876
+ this.id = id;
41877
+ this.transformation.setId(id);
41878
+ this.linkTo.setId(id);
41879
+ return this;
41880
+ }
41881
+ getId() {
41882
+ return this.id;
41883
+ }
41884
+ serialize() {
41885
+ return {
41886
+ itemType: "Image",
41887
+ storageLink: this.storageLink,
41888
+ imageDimension: this.imageDimension,
41889
+ transformation: this.transformation.serialize(),
41890
+ linkTo: this.linkTo.serialize()
41891
+ };
41892
+ }
41893
+ setCoordinates() {
41894
+ this.left = this.transformation.matrix.translateX;
41895
+ this.top = this.transformation.matrix.translateY;
41896
+ this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
41897
+ this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
41898
+ this.subject.publish(this);
41899
+ }
41900
+ shootBeforeLoadCallbacks() {
41901
+ while (this.beforeLoadCallbacks.length > 0) {
41902
+ this.beforeLoadCallbacks.shift()(this);
41903
+ }
41904
+ }
41905
+ shootLoadCallbacks() {
41906
+ while (this.loadCallbacks.length > 0) {
41907
+ this.loadCallbacks.shift()(this);
41908
+ }
41909
+ }
41910
+ deserialize(data) {
41911
+ if (data.transformation) {
41912
+ this.transformation.deserialize(data.transformation);
41913
+ }
41914
+ this.linkTo.deserialize(data.linkTo);
41915
+ this.image.onload = () => {
41916
+ this.setCoordinates();
41917
+ this.shootLoadCallbacks();
41918
+ };
41919
+ if (data.storageLink) {
41920
+ this.setStorageLink(data.storageLink);
41921
+ }
41922
+ if (this.image.src) {
41923
+ return this;
41924
+ }
41925
+ this.image = getPlaceholderImage(this.board, data.imageDimension);
41926
+ const storageImage = new Image;
41927
+ storageImage.onload = () => {
41928
+ this.image = storageImage;
41929
+ this.onLoad();
41930
+ };
41931
+ storageImage.onerror = this.onError;
41932
+ storageImage.src = this.storageLink;
41933
+ return this;
41934
+ }
41935
+ emit(operation) {
41936
+ if (this.events) {
41937
+ const command = new ImageCommand([this], operation);
41938
+ command.apply();
41939
+ this.events.emit(operation, command);
41940
+ } else {
41941
+ this.apply(operation);
41942
+ }
41943
+ }
41944
+ setDimensions(dim) {
41945
+ this.imageDimension = dim;
41946
+ }
41947
+ apply(op) {
41948
+ switch (op.class) {
41949
+ case "Transformation":
41950
+ this.transformation.apply(op);
41951
+ break;
41952
+ case "LinkTo":
41953
+ this.linkTo.apply(op);
41954
+ break;
41955
+ case "Image":
41956
+ if (op.data.base64) {
41957
+ this.image.src = op.data.base64;
41958
+ }
41959
+ this.setStorageLink(op.data.storageLink);
41960
+ this.setDimensions(op.data.imageDimension);
41961
+ this.subject.publish(this);
41962
+ break;
41963
+ }
41964
+ }
41965
+ render(context) {
41966
+ if (this.transformationRenderBlock) {
41967
+ return;
41968
+ }
41969
+ const ctx = context.ctx;
41970
+ ctx.save();
41971
+ this.transformation.matrix.applyToContext(ctx);
41972
+ ctx.drawImage(this.image, 0, 0);
41973
+ ctx.restore();
41974
+ if (this.getLinkTo()) {
41975
+ const { top, right } = this.getMbr();
41976
+ this.linkTo.render(context, top, right, this.board.camera.getScale());
41977
+ }
41978
+ }
41979
+ renderHTML(documentFactory) {
41980
+ const div = documentFactory.createElement("image-item");
41981
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
41982
+ const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
41983
+ div.style.backgroundImage = `url(${this.storageLink})`;
41984
+ div.id = this.getId();
41985
+ div.style.width = `${this.imageDimension.width}px`;
41986
+ div.style.height = `${this.imageDimension.height}px`;
41987
+ div.style.transformOrigin = "top left";
41988
+ div.style.transform = transform;
41989
+ div.style.position = "absolute";
41990
+ div.style.backgroundSize = "cover";
41991
+ div.setAttribute("data-link-to", this.linkTo.serialize() || "");
41992
+ if (this.getLinkTo()) {
41993
+ const linkElement = this.linkTo.renderHTML(documentFactory);
41994
+ scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
41995
+ translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
41996
+ div.appendChild(linkElement);
41997
+ }
41998
+ return div;
41999
+ }
42000
+ getPath() {
42001
+ const { left, top, right, bottom } = this.getMbr();
42002
+ const leftTop = new Point(left, top);
42003
+ const rightTop = new Point(right, top);
42004
+ const rightBottom = new Point(right, bottom);
42005
+ const leftBottom = new Point(left, bottom);
42006
+ return new Path([
42007
+ new Line(leftTop, rightTop),
42008
+ new Line(rightTop, rightBottom),
42009
+ new Line(rightBottom, leftBottom),
42010
+ new Line(leftBottom, leftTop)
42011
+ ], true);
42012
+ }
42013
+ getSnapAnchorPoints() {
42014
+ const mbr = this.getMbr();
42015
+ const width2 = mbr.getWidth();
42016
+ const height2 = mbr.getHeight();
42017
+ return [
42018
+ new Point(mbr.left + width2 / 2, mbr.top),
42019
+ new Point(mbr.left + width2 / 2, mbr.bottom),
42020
+ new Point(mbr.left, mbr.top + height2 / 2),
42021
+ new Point(mbr.right, mbr.top + height2 / 2)
42022
+ ];
42023
+ }
42024
+ isClosed() {
42025
+ return true;
42196
42026
  }
42197
42027
  getRichText() {
42198
42028
  return null;
42199
42029
  }
42030
+ getLinkTo() {
42031
+ return this.linkTo.link;
42032
+ }
42033
+ download() {
42034
+ const linkElem = document.createElement("a");
42035
+ linkElem.href = this.storageLink;
42036
+ linkElem.setAttribute("download", "");
42037
+ linkElem.click();
42038
+ }
42039
+ onRemove() {
42040
+ const storageId = this.getStorageId();
42041
+ if (storageId) {
42042
+ conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
42043
+ }
42044
+ super.onRemove();
42045
+ }
42200
42046
  }
42201
- // src/Items/Image/Image.ts
42202
- function getPlaceholderImage(board, imageDimension) {
42203
- const placeholderCanvas = conf.documentFactory.createElement("canvas");
42204
- const placeholderContext = placeholderCanvas.getContext("2d");
42205
- const context = new DrawingContext(board.camera, placeholderContext);
42206
- const placeholder = new Placeholder(board);
42207
- if (imageDimension) {
42208
- placeholderCanvas.width = imageDimension.width;
42209
- placeholderCanvas.height = imageDimension.height;
42210
- placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
42211
- } else {
42212
- placeholderCanvas.width = 250;
42213
- placeholderCanvas.height = 50;
42214
- placeholder.transformation.scaleTo(250 / 100, 50 / 100);
42047
+ // src/isSafari.ts
42048
+ function isSafari() {
42049
+ if (typeof navigator === "undefined") {
42050
+ return false;
42215
42051
  }
42216
- const placeholderImage = new Image;
42217
- placeholderImage.src = placeholderCanvas.toDataURL();
42218
- return placeholderImage;
42052
+ const agent = navigator.userAgent;
42053
+ const vendor = navigator.vendor;
42054
+ const is2 = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
42055
+ return is2;
42219
42056
  }
42220
42057
 
42221
- class ImageItem extends BaseItem {
42058
+ // src/Items/Drawing/Drawing.ts
42059
+ class Drawing extends BaseItem {
42060
+ points;
42222
42061
  events;
42223
- itemType = "Image";
42062
+ itemType = "Drawing";
42224
42063
  parent = "Board";
42225
- image;
42226
42064
  transformation;
42227
- linkTo;
42065
+ path2d = new conf.path2DFactory;
42228
42066
  subject = new Subject;
42229
- loadCallbacks = [];
42230
- beforeLoadCallbacks = [];
42067
+ untransformedMbr = new Mbr;
42068
+ lines = [];
42069
+ linkTo;
42070
+ strokeWidth = 1;
42071
+ borderStyle = "solid";
42072
+ linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
42073
+ borderOpacity = 1;
42231
42074
  transformationRenderBlock = undefined;
42232
- storageLink;
42233
- imageDimension;
42234
- board;
42235
- constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
42075
+ constructor(board, points, events, id = "") {
42236
42076
  super(board, id);
42077
+ this.points = points;
42237
42078
  this.events = events;
42238
- this.linkTo = new LinkTo(this.id, events);
42239
- this.board = board;
42240
- this.setStorageLink(storageLink);
42241
- this.imageDimension = imageDimension;
42242
42079
  this.transformation = new Transformation(id, events);
42243
- this.image = new Image;
42244
- this.image.crossOrigin = "anonymous";
42245
- this.image.onload = this.onLoad;
42246
- this.image.onerror = this.onError;
42247
- if (typeof base64 === "string") {
42248
- this.image.src = base64;
42249
- }
42080
+ this.linkTo = new LinkTo(this.id, this.events);
42081
+ this.transformation.subject.subscribe(() => {
42082
+ this.updateMbr();
42083
+ this.updateLines();
42084
+ this.subject.publish(this);
42085
+ });
42250
42086
  this.linkTo.subject.subscribe(() => {
42251
42087
  this.updateMbr();
42088
+ this.updateLines();
42252
42089
  this.subject.publish(this);
42253
42090
  });
42254
- this.transformation.subject.subscribe(this.onTransform);
42255
- }
42256
- setStorageLink(link2) {
42257
- try {
42258
- const url = new URL(link2);
42259
- this.storageLink = `${window?.location.origin}${url.pathname}`;
42260
- } catch (_) {}
42261
- }
42262
- getStorageId() {
42263
- return this.storageLink.split("/").pop();
42264
- }
42265
- handleError = () => {
42266
- console.error("Invalid dataUrl or image failed to load.");
42267
- this.image = getPlaceholderImage(this.board);
42268
- this.updateMbr();
42269
- this.subject.publish(this);
42270
- this.shootLoadCallbacks();
42271
- };
42272
- onLoad = async () => {
42273
- this.shootBeforeLoadCallbacks();
42274
- this.updateMbr();
42275
- this.subject.publish(this);
42276
- this.shootLoadCallbacks();
42277
- };
42278
- onError = (_error) => {
42279
- this.image = getPlaceholderImage(this.board);
42280
- this.updateMbr();
42281
- this.subject.publish(this);
42282
- this.shootLoadCallbacks();
42283
- };
42284
- onTransform = () => {
42285
- this.updateMbr();
42286
- this.subject.publish(this);
42287
- };
42288
- updateMbr() {
42289
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
42290
- this.left = translateX;
42291
- this.top = translateY;
42292
- this.right = this.left + this.image.width * scaleX;
42293
- this.bottom = this.top + this.image.height * scaleY;
42294
- }
42295
- doOnceBeforeOnLoad = (callback) => {
42296
- this.loadCallbacks.push(callback);
42297
- };
42298
- doOnceOnLoad = (callback) => {
42299
- this.loadCallbacks.push(callback);
42300
- };
42301
- setId(id) {
42302
- this.id = id;
42303
- this.transformation.setId(id);
42304
- this.linkTo.setId(id);
42305
- return this;
42306
- }
42307
- getId() {
42308
- return this.id;
42091
+ this.updateLines();
42309
42092
  }
42310
42093
  serialize() {
42094
+ this.optimizePoints();
42095
+ const points = [];
42096
+ for (const point5 of this.points) {
42097
+ points.push({ x: point5.x, y: point5.y });
42098
+ }
42311
42099
  return {
42312
- itemType: "Image",
42313
- storageLink: this.storageLink,
42314
- imageDimension: this.imageDimension,
42100
+ itemType: "Drawing",
42101
+ points,
42315
42102
  transformation: this.transformation.serialize(),
42103
+ strokeStyle: this.borderColor,
42104
+ strokeWidth: this.strokeWidth,
42316
42105
  linkTo: this.linkTo.serialize()
42317
42106
  };
42318
42107
  }
42319
- setCoordinates() {
42320
- this.left = this.transformation.matrix.translateX;
42321
- this.top = this.transformation.matrix.translateY;
42322
- this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
42323
- this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
42324
- this.subject.publish(this);
42325
- }
42326
- shootBeforeLoadCallbacks() {
42327
- while (this.beforeLoadCallbacks.length > 0) {
42328
- this.beforeLoadCallbacks.shift()(this);
42108
+ deserialize(data) {
42109
+ this.points = [];
42110
+ for (const point5 of data.points) {
42111
+ this.points.push(new Point(point5.x, point5.y));
42329
42112
  }
42113
+ this.linkTo.deserialize(data.linkTo);
42114
+ this.optimizePoints();
42115
+ this.transformation.deserialize(data.transformation);
42116
+ this.borderColor = data.strokeStyle;
42117
+ this.strokeWidth = data.strokeWidth;
42118
+ this.updateGeometry();
42119
+ return this;
42330
42120
  }
42331
- shootLoadCallbacks() {
42332
- while (this.loadCallbacks.length > 0) {
42333
- this.loadCallbacks.shift()(this);
42334
- }
42121
+ updateGeometry() {
42122
+ this.updatePath2d();
42123
+ this.updateLines();
42124
+ this.updateMbr();
42335
42125
  }
42336
- deserialize(data) {
42337
- if (data.transformation) {
42338
- this.transformation.deserialize(data.transformation);
42126
+ updateMbr() {
42127
+ const offset = this.getStrokeWidth() / 2;
42128
+ const untransformedMbr = this.untransformedMbr.copy();
42129
+ untransformedMbr.left -= offset;
42130
+ untransformedMbr.top -= offset;
42131
+ untransformedMbr.right += offset;
42132
+ untransformedMbr.bottom += offset;
42133
+ const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
42134
+ this.left = mbr.left;
42135
+ this.top = mbr.top;
42136
+ this.right = mbr.right;
42137
+ this.bottom = mbr.bottom;
42138
+ }
42139
+ updatePath2d() {
42140
+ this.path2d = new conf.path2DFactory;
42141
+ const context = this.path2d;
42142
+ const points = this.points;
42143
+ if (points.length < 3) {
42144
+ context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
42145
+ context.closePath();
42146
+ } else {
42147
+ context.moveTo(points[0].x, points[0].y);
42148
+ let j = 1;
42149
+ for (;j < points.length - 2; j++) {
42150
+ const cx = (points[j].x + points[j + 1].x) / 2;
42151
+ const cy = (points[j].y + points[j + 1].y) / 2;
42152
+ context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
42153
+ }
42154
+ const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
42155
+ const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
42156
+ context.quadraticCurveTo(points[j].x, points[j].y, x, y);
42339
42157
  }
42340
- this.linkTo.deserialize(data.linkTo);
42341
- this.image.onload = () => {
42342
- this.setCoordinates();
42343
- this.shootLoadCallbacks();
42344
- };
42345
- if (data.storageLink) {
42346
- this.setStorageLink(data.storageLink);
42158
+ let left = Number.MAX_SAFE_INTEGER;
42159
+ let right = Number.MIN_SAFE_INTEGER;
42160
+ let top = Number.MAX_SAFE_INTEGER;
42161
+ let bottom = Number.MIN_SAFE_INTEGER;
42162
+ for (const { x, y } of this.points) {
42163
+ if (x < left) {
42164
+ left = x;
42165
+ }
42166
+ if (x > right) {
42167
+ right = x;
42168
+ }
42169
+ if (y < top) {
42170
+ top = y;
42171
+ }
42172
+ if (y > bottom) {
42173
+ bottom = y;
42174
+ }
42347
42175
  }
42348
- if (this.image.src) {
42349
- return this;
42176
+ this.untransformedMbr = new Mbr(left, top, right, bottom);
42177
+ }
42178
+ updateLines() {
42179
+ this.lines = [];
42180
+ const matrix = this.transformation.matrix;
42181
+ if (this.points.length < 2) {
42182
+ return;
42183
+ }
42184
+ for (let i = 0;i < this.points.length - 2; i++) {
42185
+ const p1 = this.points[i];
42186
+ const p22 = this.points[i + 1];
42187
+ const line = new Line(p1.copy(), p22.copy());
42188
+ line.transform(matrix);
42189
+ this.lines.push(line);
42350
42190
  }
42351
- this.image = getPlaceholderImage(this.board, data.imageDimension);
42352
- const storageImage = new Image;
42353
- storageImage.onload = () => {
42354
- this.image = storageImage;
42355
- this.onLoad();
42356
- };
42357
- storageImage.onerror = this.onError;
42358
- storageImage.src = this.storageLink;
42359
- return this;
42360
42191
  }
42361
- emit(operation) {
42362
- if (this.events) {
42363
- const command = new ImageCommand([this], operation);
42364
- command.apply();
42365
- this.events.emit(operation, command);
42192
+ optimizePoints() {
42193
+ const dp = douglasPeucker(this.points, 1);
42194
+ dp.push(this.points[this.points.length - 1]);
42195
+ this.points = dp;
42196
+ }
42197
+ addPoint(point5) {
42198
+ const previous2 = this.points[this.points.length - 1];
42199
+ if (previous2) {
42200
+ const distance = point5.getDistance(previous2);
42201
+ if (distance >= 2) {
42202
+ this.points.push(point5);
42203
+ }
42366
42204
  } else {
42367
- this.apply(operation);
42205
+ this.points.push(point5);
42368
42206
  }
42207
+ this.updateGeometry();
42369
42208
  }
42370
- setDimensions(dim) {
42371
- this.imageDimension = dim;
42209
+ setId(id) {
42210
+ this.id = id;
42211
+ this.transformation.setId(id);
42212
+ this.linkTo.setId(id);
42213
+ return this;
42372
42214
  }
42373
- apply(op) {
42374
- switch (op.class) {
42375
- case "Transformation":
42376
- this.transformation.apply(op);
42377
- break;
42378
- case "LinkTo":
42379
- this.linkTo.apply(op);
42380
- break;
42381
- case "Image":
42382
- if (op.data.base64) {
42383
- this.image.src = op.data.base64;
42384
- }
42385
- this.setStorageLink(op.data.storageLink);
42386
- this.setDimensions(op.data.imageDimension);
42387
- this.subject.publish(this);
42388
- break;
42389
- }
42215
+ getId() {
42216
+ return this.id;
42390
42217
  }
42391
42218
  render(context) {
42392
42219
  if (this.transformationRenderBlock) {
@@ -42394,8 +42221,12 @@ class ImageItem extends BaseItem {
42394
42221
  }
42395
42222
  const ctx = context.ctx;
42396
42223
  ctx.save();
42224
+ ctx.strokeStyle = this.borderColor;
42225
+ ctx.lineWidth = this.strokeWidth;
42226
+ ctx.lineCap = "round";
42227
+ ctx.setLineDash(this.linePattern);
42397
42228
  this.transformation.matrix.applyToContext(ctx);
42398
- ctx.drawImage(this.image, 0, 0);
42229
+ ctx.stroke(this.path2d.nativePath);
42399
42230
  ctx.restore();
42400
42231
  if (this.getLinkTo()) {
42401
42232
  const { top, right } = this.getMbr();
@@ -42403,26 +42234,61 @@ class ImageItem extends BaseItem {
42403
42234
  }
42404
42235
  }
42405
42236
  renderHTML(documentFactory) {
42406
- const div = documentFactory.createElement("image-item");
42237
+ const div = documentFactory.createElement("drawing-item");
42407
42238
  const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
42408
- const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
42409
- div.style.backgroundImage = `url(${this.storageLink})`;
42239
+ const mbr = this.getMbr();
42240
+ const width2 = mbr.getWidth();
42241
+ const height2 = mbr.getHeight();
42242
+ const unscaledWidth = width2 / scaleX;
42243
+ const unscaledHeight = height2 / scaleY;
42244
+ const svg3 = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
42245
+ svg3.setAttribute("width", `${unscaledWidth}px`);
42246
+ svg3.setAttribute("height", `${unscaledHeight}px`);
42247
+ svg3.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
42248
+ svg3.setAttribute("style", "position: absolute; overflow: visible;");
42249
+ const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
42250
+ pathElement.setAttribute("d", this.getPathData());
42251
+ pathElement.setAttribute("stroke", this.borderColor);
42252
+ pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
42253
+ pathElement.setAttribute("fill", "none");
42254
+ svg3.appendChild(pathElement);
42255
+ div.appendChild(svg3);
42410
42256
  div.id = this.getId();
42411
- div.style.width = `${this.imageDimension.width}px`;
42412
- div.style.height = `${this.imageDimension.height}px`;
42413
- div.style.transformOrigin = "top left";
42414
- div.style.transform = transform;
42257
+ div.style.width = unscaledWidth + "px";
42258
+ div.style.height = unscaledHeight + "px";
42259
+ div.style.transformOrigin = "left top";
42260
+ div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
42415
42261
  div.style.position = "absolute";
42416
- div.style.backgroundSize = "cover";
42417
42262
  div.setAttribute("data-link-to", this.linkTo.serialize() || "");
42418
42263
  if (this.getLinkTo()) {
42419
42264
  const linkElement = this.linkTo.renderHTML(documentFactory);
42420
42265
  scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
42421
- translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
42266
+ translateElementBy(linkElement, (width2 - parseInt(linkElement.style.width)) / scaleX, 0);
42422
42267
  div.appendChild(linkElement);
42423
42268
  }
42424
42269
  return div;
42425
42270
  }
42271
+ getPathData() {
42272
+ const points = this.points;
42273
+ if (points.length < 2) {
42274
+ return "";
42275
+ }
42276
+ let pathData = `M ${points[0].x} ${points[0].y}`;
42277
+ if (points.length < 3) {
42278
+ pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
42279
+ } else {
42280
+ let j = 1;
42281
+ for (;j < points.length - 2; j++) {
42282
+ const cx = (points[j].x + points[j + 1].x) / 2;
42283
+ const cy = (points[j].y + points[j + 1].y) / 2;
42284
+ pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
42285
+ }
42286
+ const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
42287
+ const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
42288
+ pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
42289
+ }
42290
+ return pathData;
42291
+ }
42426
42292
  getPath() {
42427
42293
  const { left, top, right, bottom } = this.getMbr();
42428
42294
  const leftTop = new Point(left, top);
@@ -42447,27 +42313,162 @@ class ImageItem extends BaseItem {
42447
42313
  new Point(mbr.right, mbr.top + height2 / 2)
42448
42314
  ];
42449
42315
  }
42316
+ getLines() {
42317
+ return this.lines;
42318
+ }
42450
42319
  isClosed() {
42451
42320
  return true;
42452
42321
  }
42453
- getRichText() {
42454
- return null;
42322
+ isEnclosedOrCrossedBy(rect) {
42323
+ for (const line of this.lines) {
42324
+ if (line.isEnclosedOrCrossedBy(rect)) {
42325
+ return true;
42326
+ }
42327
+ }
42328
+ return false;
42329
+ }
42330
+ emit(operation) {
42331
+ if (this.events) {
42332
+ const command = new DrawingCommand([this], operation);
42333
+ command.apply();
42334
+ this.events.emit(operation, command);
42335
+ } else {
42336
+ this.apply(operation);
42337
+ }
42338
+ }
42339
+ apply(op) {
42340
+ switch (op.class) {
42341
+ case "Drawing":
42342
+ switch (op.method) {
42343
+ case "setStrokeColor":
42344
+ this.borderColor = op.color;
42345
+ break;
42346
+ case "setStrokeWidth":
42347
+ this.strokeWidth = op.width;
42348
+ this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
42349
+ break;
42350
+ case "setStrokeOpacity":
42351
+ this.borderOpacity = op.opacity;
42352
+ break;
42353
+ case "setStrokeStyle":
42354
+ this.borderStyle = op.style;
42355
+ this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
42356
+ break;
42357
+ }
42358
+ this.updateMbr();
42359
+ break;
42360
+ case "Transformation":
42361
+ this.transformation.apply(op);
42362
+ break;
42363
+ case "LinkTo":
42364
+ this.linkTo.apply(op);
42365
+ break;
42366
+ default:
42367
+ return;
42368
+ }
42369
+ this.subject.publish(this);
42370
+ }
42371
+ setStrokeOpacity(opacity) {
42372
+ this.emit({
42373
+ class: "Drawing",
42374
+ method: "setStrokeOpacity",
42375
+ item: [this.id],
42376
+ opacity
42377
+ });
42378
+ return this;
42379
+ }
42380
+ getStrokeOpacity() {
42381
+ return this.borderOpacity;
42382
+ }
42383
+ setBorderStyle(style2) {
42384
+ this.emit({
42385
+ class: "Drawing",
42386
+ method: "setStrokeStyle",
42387
+ item: [this.id],
42388
+ style: style2
42389
+ });
42390
+ return this;
42391
+ }
42392
+ getBorderStyle() {
42393
+ return this.borderStyle;
42394
+ }
42395
+ setStrokeColor(color2) {
42396
+ this.emit({
42397
+ class: "Drawing",
42398
+ method: "setStrokeColor",
42399
+ item: [this.id],
42400
+ color: color2
42401
+ });
42402
+ return this;
42403
+ }
42404
+ getStrokeColor() {
42405
+ return this.borderColor;
42406
+ }
42407
+ setStrokeWidth(width2) {
42408
+ this.emit({
42409
+ class: "Drawing",
42410
+ method: "setStrokeWidth",
42411
+ item: [this.id],
42412
+ width: width2,
42413
+ prevWidth: this.strokeWidth
42414
+ });
42415
+ return this;
42455
42416
  }
42456
42417
  getLinkTo() {
42457
42418
  return this.linkTo.link;
42458
42419
  }
42459
- download() {
42460
- const linkElem = document.createElement("a");
42461
- linkElem.href = this.storageLink;
42462
- linkElem.setAttribute("download", "");
42463
- linkElem.click();
42420
+ getStrokeWidth() {
42421
+ return this.strokeWidth;
42464
42422
  }
42465
- onRemove() {
42466
- const storageId = this.getStorageId();
42467
- if (storageId) {
42468
- conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
42423
+ getRichText() {
42424
+ return null;
42425
+ }
42426
+ isPointNearLine(point5, threshold = 10) {
42427
+ const transformedMouseX = (point5.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
42428
+ const transformedMouseY = (point5.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
42429
+ const transformedMouse = new Point(transformedMouseX, transformedMouseY);
42430
+ for (let i = 0;i < this.points.length - 1; i++) {
42431
+ const p1 = this.points[i];
42432
+ const p22 = this.points[i + 1];
42433
+ const distance = getPerpendicularDistance(transformedMouse, p1, p22);
42434
+ if (distance < threshold) {
42435
+ return true;
42436
+ }
42469
42437
  }
42470
- super.onRemove();
42438
+ return false;
42439
+ }
42440
+ }
42441
+ function getPerpendicularDistance(point5, lineStart, lineEnd) {
42442
+ const { x: px, y: py } = point5;
42443
+ const { x: sx, y: sy } = lineStart;
42444
+ const { x: ex, y: ey } = lineEnd;
42445
+ const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
42446
+ const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
42447
+ return numerator / denominator;
42448
+ }
42449
+ function douglasPeucker(points, epsilon2) {
42450
+ if (points.length < 3) {
42451
+ return points;
42452
+ }
42453
+ const start = points[0];
42454
+ const end = points[points.length - 1];
42455
+ let maxDistance = 0;
42456
+ let maxIndex = 0;
42457
+ for (let i = 1;i < points.length - 1; i++) {
42458
+ const distance = getPerpendicularDistance(points[i], start, end);
42459
+ if (distance > maxDistance) {
42460
+ maxDistance = distance;
42461
+ maxIndex = i;
42462
+ }
42463
+ }
42464
+ if (maxDistance > epsilon2) {
42465
+ const leftSubPoints = points.slice(0, maxIndex + 1);
42466
+ const rightSubPoints = points.slice(maxIndex);
42467
+ const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
42468
+ const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
42469
+ return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
42470
+ } else {
42471
+ return [start, end];
42471
42472
  }
42472
42473
  }
42473
42474
  // src/Items/Group/Group.ts