microboard-temp 0.4.41 → 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";
@@ -42192,202 +41765,455 @@ class Placeholder extends BaseItem {
42192
41765
  renderHTML(documentFactory) {
42193
41766
  return documentFactory.createElement("div");
42194
41767
  }
42195
- getLinkTo() {
42196
- 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;
42197
42026
  }
42198
42027
  getRichText() {
42199
42028
  return null;
42200
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
+ }
42201
42046
  }
42202
- // src/Items/Image/Image.ts
42203
- function getPlaceholderImage(board, imageDimension) {
42204
- const placeholderCanvas = conf.documentFactory.createElement("canvas");
42205
- const placeholderContext = placeholderCanvas.getContext("2d");
42206
- const context = new DrawingContext(board.camera, placeholderContext);
42207
- const placeholder = new Placeholder(board);
42208
- if (imageDimension) {
42209
- placeholderCanvas.width = imageDimension.width;
42210
- placeholderCanvas.height = imageDimension.height;
42211
- placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
42212
- } else {
42213
- placeholderCanvas.width = 250;
42214
- placeholderCanvas.height = 50;
42215
- placeholder.transformation.scaleTo(250 / 100, 50 / 100);
42047
+ // src/isSafari.ts
42048
+ function isSafari() {
42049
+ if (typeof navigator === "undefined") {
42050
+ return false;
42216
42051
  }
42217
- const placeholderImage = new Image;
42218
- placeholderImage.src = placeholderCanvas.toDataURL();
42219
- 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;
42220
42056
  }
42221
42057
 
42222
- class ImageItem extends BaseItem {
42058
+ // src/Items/Drawing/Drawing.ts
42059
+ class Drawing extends BaseItem {
42060
+ points;
42223
42061
  events;
42224
- itemType = "Image";
42062
+ itemType = "Drawing";
42225
42063
  parent = "Board";
42226
- image;
42227
42064
  transformation;
42228
- linkTo;
42065
+ path2d = new conf.path2DFactory;
42229
42066
  subject = new Subject;
42230
- loadCallbacks = [];
42231
- 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;
42232
42074
  transformationRenderBlock = undefined;
42233
- storageLink;
42234
- imageDimension;
42235
- board;
42236
- constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
42075
+ constructor(board, points, events, id = "") {
42237
42076
  super(board, id);
42077
+ this.points = points;
42238
42078
  this.events = events;
42239
- this.linkTo = new LinkTo(this.id, events);
42240
- this.board = board;
42241
- this.setStorageLink(storageLink);
42242
- this.imageDimension = imageDimension;
42243
42079
  this.transformation = new Transformation(id, events);
42244
- this.image = new Image;
42245
- this.image.crossOrigin = "anonymous";
42246
- this.image.onload = this.onLoad;
42247
- this.image.onerror = this.onError;
42248
- if (typeof base64 === "string") {
42249
- this.image.src = base64;
42250
- }
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
+ });
42251
42086
  this.linkTo.subject.subscribe(() => {
42252
42087
  this.updateMbr();
42088
+ this.updateLines();
42253
42089
  this.subject.publish(this);
42254
42090
  });
42255
- this.transformation.subject.subscribe(this.onTransform);
42256
- }
42257
- setStorageLink(link2) {
42258
- try {
42259
- const url = new URL(link2);
42260
- this.storageLink = `${window?.location.origin}${url.pathname}`;
42261
- } catch (_) {}
42262
- }
42263
- getStorageId() {
42264
- return this.storageLink.split("/").pop();
42265
- }
42266
- handleError = () => {
42267
- console.error("Invalid dataUrl or image failed to load.");
42268
- this.image = getPlaceholderImage(this.board);
42269
- this.updateMbr();
42270
- this.subject.publish(this);
42271
- this.shootLoadCallbacks();
42272
- };
42273
- onLoad = async () => {
42274
- this.shootBeforeLoadCallbacks();
42275
- this.updateMbr();
42276
- this.subject.publish(this);
42277
- this.shootLoadCallbacks();
42278
- };
42279
- onError = (_error) => {
42280
- this.image = getPlaceholderImage(this.board);
42281
- this.updateMbr();
42282
- this.subject.publish(this);
42283
- this.shootLoadCallbacks();
42284
- };
42285
- onTransform = () => {
42286
- this.updateMbr();
42287
- this.subject.publish(this);
42288
- };
42289
- updateMbr() {
42290
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
42291
- this.left = translateX;
42292
- this.top = translateY;
42293
- this.right = this.left + this.image.width * scaleX;
42294
- this.bottom = this.top + this.image.height * scaleY;
42295
- }
42296
- doOnceBeforeOnLoad = (callback) => {
42297
- this.loadCallbacks.push(callback);
42298
- };
42299
- doOnceOnLoad = (callback) => {
42300
- this.loadCallbacks.push(callback);
42301
- };
42302
- setId(id) {
42303
- this.id = id;
42304
- this.transformation.setId(id);
42305
- this.linkTo.setId(id);
42306
- return this;
42307
- }
42308
- getId() {
42309
- return this.id;
42091
+ this.updateLines();
42310
42092
  }
42311
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
+ }
42312
42099
  return {
42313
- itemType: "Image",
42314
- storageLink: this.storageLink,
42315
- imageDimension: this.imageDimension,
42100
+ itemType: "Drawing",
42101
+ points,
42316
42102
  transformation: this.transformation.serialize(),
42103
+ strokeStyle: this.borderColor,
42104
+ strokeWidth: this.strokeWidth,
42317
42105
  linkTo: this.linkTo.serialize()
42318
42106
  };
42319
42107
  }
42320
- setCoordinates() {
42321
- this.left = this.transformation.matrix.translateX;
42322
- this.top = this.transformation.matrix.translateY;
42323
- this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
42324
- this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
42325
- this.subject.publish(this);
42326
- }
42327
- shootBeforeLoadCallbacks() {
42328
- while (this.beforeLoadCallbacks.length > 0) {
42329
- 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));
42330
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;
42331
42120
  }
42332
- shootLoadCallbacks() {
42333
- while (this.loadCallbacks.length > 0) {
42334
- this.loadCallbacks.shift()(this);
42335
- }
42121
+ updateGeometry() {
42122
+ this.updatePath2d();
42123
+ this.updateLines();
42124
+ this.updateMbr();
42336
42125
  }
42337
- deserialize(data) {
42338
- if (data.transformation) {
42339
- 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);
42340
42157
  }
42341
- this.linkTo.deserialize(data.linkTo);
42342
- this.image.onload = () => {
42343
- this.setCoordinates();
42344
- this.shootLoadCallbacks();
42345
- };
42346
- if (data.storageLink) {
42347
- 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
+ }
42348
42175
  }
42349
- if (this.image.src) {
42350
- 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);
42351
42190
  }
42352
- this.image = getPlaceholderImage(this.board, data.imageDimension);
42353
- const storageImage = new Image;
42354
- storageImage.onload = () => {
42355
- this.image = storageImage;
42356
- this.onLoad();
42357
- };
42358
- storageImage.onerror = this.onError;
42359
- storageImage.src = this.storageLink;
42360
- return this;
42361
42191
  }
42362
- emit(operation) {
42363
- if (this.events) {
42364
- const command = new ImageCommand([this], operation);
42365
- command.apply();
42366
- 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
+ }
42367
42204
  } else {
42368
- this.apply(operation);
42205
+ this.points.push(point5);
42369
42206
  }
42207
+ this.updateGeometry();
42370
42208
  }
42371
- setDimensions(dim) {
42372
- this.imageDimension = dim;
42209
+ setId(id) {
42210
+ this.id = id;
42211
+ this.transformation.setId(id);
42212
+ this.linkTo.setId(id);
42213
+ return this;
42373
42214
  }
42374
- apply(op) {
42375
- switch (op.class) {
42376
- case "Transformation":
42377
- this.transformation.apply(op);
42378
- break;
42379
- case "LinkTo":
42380
- this.linkTo.apply(op);
42381
- break;
42382
- case "Image":
42383
- if (op.data.base64) {
42384
- this.image.src = op.data.base64;
42385
- }
42386
- this.setStorageLink(op.data.storageLink);
42387
- this.setDimensions(op.data.imageDimension);
42388
- this.subject.publish(this);
42389
- break;
42390
- }
42215
+ getId() {
42216
+ return this.id;
42391
42217
  }
42392
42218
  render(context) {
42393
42219
  if (this.transformationRenderBlock) {
@@ -42395,8 +42221,12 @@ class ImageItem extends BaseItem {
42395
42221
  }
42396
42222
  const ctx = context.ctx;
42397
42223
  ctx.save();
42224
+ ctx.strokeStyle = this.borderColor;
42225
+ ctx.lineWidth = this.strokeWidth;
42226
+ ctx.lineCap = "round";
42227
+ ctx.setLineDash(this.linePattern);
42398
42228
  this.transformation.matrix.applyToContext(ctx);
42399
- ctx.drawImage(this.image, 0, 0);
42229
+ ctx.stroke(this.path2d.nativePath);
42400
42230
  ctx.restore();
42401
42231
  if (this.getLinkTo()) {
42402
42232
  const { top, right } = this.getMbr();
@@ -42404,26 +42234,61 @@ class ImageItem extends BaseItem {
42404
42234
  }
42405
42235
  }
42406
42236
  renderHTML(documentFactory) {
42407
- const div = documentFactory.createElement("image-item");
42237
+ const div = documentFactory.createElement("drawing-item");
42408
42238
  const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
42409
- const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
42410
- 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);
42411
42256
  div.id = this.getId();
42412
- div.style.width = `${this.imageDimension.width}px`;
42413
- div.style.height = `${this.imageDimension.height}px`;
42414
- div.style.transformOrigin = "top left";
42415
- 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})`;
42416
42261
  div.style.position = "absolute";
42417
- div.style.backgroundSize = "cover";
42418
42262
  div.setAttribute("data-link-to", this.linkTo.serialize() || "");
42419
42263
  if (this.getLinkTo()) {
42420
42264
  const linkElement = this.linkTo.renderHTML(documentFactory);
42421
42265
  scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
42422
- translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
42266
+ translateElementBy(linkElement, (width2 - parseInt(linkElement.style.width)) / scaleX, 0);
42423
42267
  div.appendChild(linkElement);
42424
42268
  }
42425
42269
  return div;
42426
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
+ }
42427
42292
  getPath() {
42428
42293
  const { left, top, right, bottom } = this.getMbr();
42429
42294
  const leftTop = new Point(left, top);
@@ -42448,27 +42313,162 @@ class ImageItem extends BaseItem {
42448
42313
  new Point(mbr.right, mbr.top + height2 / 2)
42449
42314
  ];
42450
42315
  }
42316
+ getLines() {
42317
+ return this.lines;
42318
+ }
42451
42319
  isClosed() {
42452
42320
  return true;
42453
42321
  }
42454
- getRichText() {
42455
- 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;
42456
42416
  }
42457
42417
  getLinkTo() {
42458
42418
  return this.linkTo.link;
42459
42419
  }
42460
- download() {
42461
- const linkElem = document.createElement("a");
42462
- linkElem.href = this.storageLink;
42463
- linkElem.setAttribute("download", "");
42464
- linkElem.click();
42420
+ getStrokeWidth() {
42421
+ return this.strokeWidth;
42465
42422
  }
42466
- onRemove() {
42467
- const storageId = this.getStorageId();
42468
- if (storageId) {
42469
- 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
+ }
42470
42437
  }
42471
- 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];
42472
42472
  }
42473
42473
  }
42474
42474
  // src/Items/Group/Group.ts