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/cjs/node.js CHANGED
@@ -22182,433 +22182,6 @@ class NoOpCommand {
22182
22182
  }
22183
22183
  }
22184
22184
 
22185
- // src/isSafari.ts
22186
- function isSafari() {
22187
- if (typeof navigator === "undefined") {
22188
- return false;
22189
- }
22190
- const agent = navigator.userAgent;
22191
- const vendor = navigator.vendor;
22192
- const is = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
22193
- return is;
22194
- }
22195
-
22196
- // src/Items/Drawing/Drawing.ts
22197
- class Drawing extends BaseItem {
22198
- points;
22199
- events;
22200
- itemType = "Drawing";
22201
- parent = "Board";
22202
- transformation;
22203
- path2d = new conf.path2DFactory;
22204
- subject = new Subject;
22205
- untransformedMbr = new Mbr;
22206
- lines = [];
22207
- linkTo;
22208
- strokeWidth = 1;
22209
- borderStyle = "solid";
22210
- linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
22211
- borderOpacity = 1;
22212
- transformationRenderBlock = undefined;
22213
- constructor(board, points, events, id = "") {
22214
- super(board, id);
22215
- this.points = points;
22216
- this.events = events;
22217
- this.transformation = new Transformation(id, events);
22218
- this.linkTo = new LinkTo(this.id, this.events);
22219
- this.transformation.subject.subscribe(() => {
22220
- this.updateMbr();
22221
- this.updateLines();
22222
- this.subject.publish(this);
22223
- });
22224
- this.linkTo.subject.subscribe(() => {
22225
- this.updateMbr();
22226
- this.updateLines();
22227
- this.subject.publish(this);
22228
- });
22229
- this.updateLines();
22230
- }
22231
- serialize() {
22232
- this.optimizePoints();
22233
- const points = [];
22234
- for (const point3 of this.points) {
22235
- points.push({ x: point3.x, y: point3.y });
22236
- }
22237
- return {
22238
- itemType: "Drawing",
22239
- points,
22240
- transformation: this.transformation.serialize(),
22241
- strokeStyle: this.borderColor,
22242
- strokeWidth: this.strokeWidth,
22243
- linkTo: this.linkTo.serialize()
22244
- };
22245
- }
22246
- deserialize(data) {
22247
- this.points = [];
22248
- for (const point3 of data.points) {
22249
- this.points.push(new Point(point3.x, point3.y));
22250
- }
22251
- this.linkTo.deserialize(data.linkTo);
22252
- this.optimizePoints();
22253
- this.transformation.deserialize(data.transformation);
22254
- this.borderColor = data.strokeStyle;
22255
- this.strokeWidth = data.strokeWidth;
22256
- this.updateGeometry();
22257
- return this;
22258
- }
22259
- updateGeometry() {
22260
- this.updatePath2d();
22261
- this.updateLines();
22262
- this.updateMbr();
22263
- }
22264
- updateMbr() {
22265
- const offset = this.getStrokeWidth() / 2;
22266
- const untransformedMbr = this.untransformedMbr.copy();
22267
- untransformedMbr.left -= offset;
22268
- untransformedMbr.top -= offset;
22269
- untransformedMbr.right += offset;
22270
- untransformedMbr.bottom += offset;
22271
- const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
22272
- this.left = mbr.left;
22273
- this.top = mbr.top;
22274
- this.right = mbr.right;
22275
- this.bottom = mbr.bottom;
22276
- }
22277
- updatePath2d() {
22278
- this.path2d = new conf.path2DFactory;
22279
- const context = this.path2d;
22280
- const points = this.points;
22281
- if (points.length < 3) {
22282
- context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
22283
- context.closePath();
22284
- } else {
22285
- context.moveTo(points[0].x, points[0].y);
22286
- let j = 1;
22287
- for (;j < points.length - 2; j++) {
22288
- const cx = (points[j].x + points[j + 1].x) / 2;
22289
- const cy = (points[j].y + points[j + 1].y) / 2;
22290
- context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
22291
- }
22292
- const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
22293
- const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
22294
- context.quadraticCurveTo(points[j].x, points[j].y, x, y);
22295
- }
22296
- let left = Number.MAX_SAFE_INTEGER;
22297
- let right = Number.MIN_SAFE_INTEGER;
22298
- let top = Number.MAX_SAFE_INTEGER;
22299
- let bottom = Number.MIN_SAFE_INTEGER;
22300
- for (const { x, y } of this.points) {
22301
- if (x < left) {
22302
- left = x;
22303
- }
22304
- if (x > right) {
22305
- right = x;
22306
- }
22307
- if (y < top) {
22308
- top = y;
22309
- }
22310
- if (y > bottom) {
22311
- bottom = y;
22312
- }
22313
- }
22314
- this.untransformedMbr = new Mbr(left, top, right, bottom);
22315
- }
22316
- updateLines() {
22317
- this.lines = [];
22318
- const matrix = this.transformation.matrix;
22319
- if (this.points.length < 2) {
22320
- return;
22321
- }
22322
- for (let i = 0;i < this.points.length - 2; i++) {
22323
- const p1 = this.points[i];
22324
- const p2 = this.points[i + 1];
22325
- const line = new Line(p1.copy(), p2.copy());
22326
- line.transform(matrix);
22327
- this.lines.push(line);
22328
- }
22329
- }
22330
- optimizePoints() {
22331
- const dp = douglasPeucker(this.points, 1);
22332
- dp.push(this.points[this.points.length - 1]);
22333
- this.points = dp;
22334
- }
22335
- addPoint(point3) {
22336
- const previous2 = this.points[this.points.length - 1];
22337
- if (previous2) {
22338
- const distance = point3.getDistance(previous2);
22339
- if (distance >= 2) {
22340
- this.points.push(point3);
22341
- }
22342
- } else {
22343
- this.points.push(point3);
22344
- }
22345
- this.updateGeometry();
22346
- }
22347
- setId(id) {
22348
- this.id = id;
22349
- this.transformation.setId(id);
22350
- this.linkTo.setId(id);
22351
- return this;
22352
- }
22353
- getId() {
22354
- return this.id;
22355
- }
22356
- render(context) {
22357
- if (this.transformationRenderBlock) {
22358
- return;
22359
- }
22360
- const ctx = context.ctx;
22361
- ctx.save();
22362
- ctx.strokeStyle = this.borderColor;
22363
- ctx.lineWidth = this.strokeWidth;
22364
- ctx.lineCap = "round";
22365
- ctx.setLineDash(this.linePattern);
22366
- this.transformation.matrix.applyToContext(ctx);
22367
- ctx.stroke(this.path2d.nativePath);
22368
- ctx.restore();
22369
- if (this.getLinkTo()) {
22370
- const { top, right } = this.getMbr();
22371
- this.linkTo.render(context, top, right, this.board.camera.getScale());
22372
- }
22373
- }
22374
- renderHTML(documentFactory) {
22375
- const div = documentFactory.createElement("drawing-item");
22376
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
22377
- const mbr = this.getMbr();
22378
- const width = mbr.getWidth();
22379
- const height = mbr.getHeight();
22380
- const unscaledWidth = width / scaleX;
22381
- const unscaledHeight = height / scaleY;
22382
- const svg = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
22383
- svg.setAttribute("width", `${unscaledWidth}px`);
22384
- svg.setAttribute("height", `${unscaledHeight}px`);
22385
- svg.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
22386
- svg.setAttribute("style", "position: absolute; overflow: visible;");
22387
- const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
22388
- pathElement.setAttribute("d", this.getPathData());
22389
- pathElement.setAttribute("stroke", this.borderColor);
22390
- pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
22391
- pathElement.setAttribute("fill", "none");
22392
- svg.appendChild(pathElement);
22393
- div.appendChild(svg);
22394
- div.id = this.getId();
22395
- div.style.width = unscaledWidth + "px";
22396
- div.style.height = unscaledHeight + "px";
22397
- div.style.transformOrigin = "left top";
22398
- div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
22399
- div.style.position = "absolute";
22400
- div.setAttribute("data-link-to", this.linkTo.serialize() || "");
22401
- if (this.getLinkTo()) {
22402
- const linkElement = this.linkTo.renderHTML(documentFactory);
22403
- scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
22404
- translateElementBy(linkElement, (width - parseInt(linkElement.style.width)) / scaleX, 0);
22405
- div.appendChild(linkElement);
22406
- }
22407
- return div;
22408
- }
22409
- getPathData() {
22410
- const points = this.points;
22411
- if (points.length < 2) {
22412
- return "";
22413
- }
22414
- let pathData = `M ${points[0].x} ${points[0].y}`;
22415
- if (points.length < 3) {
22416
- pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
22417
- } else {
22418
- let j = 1;
22419
- for (;j < points.length - 2; j++) {
22420
- const cx = (points[j].x + points[j + 1].x) / 2;
22421
- const cy = (points[j].y + points[j + 1].y) / 2;
22422
- pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
22423
- }
22424
- const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
22425
- const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
22426
- pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
22427
- }
22428
- return pathData;
22429
- }
22430
- getPath() {
22431
- const { left, top, right, bottom } = this.getMbr();
22432
- const leftTop = new Point(left, top);
22433
- const rightTop = new Point(right, top);
22434
- const rightBottom = new Point(right, bottom);
22435
- const leftBottom = new Point(left, bottom);
22436
- return new Path([
22437
- new Line(leftTop, rightTop),
22438
- new Line(rightTop, rightBottom),
22439
- new Line(rightBottom, leftBottom),
22440
- new Line(leftBottom, leftTop)
22441
- ], true);
22442
- }
22443
- getSnapAnchorPoints() {
22444
- const mbr = this.getMbr();
22445
- const width = mbr.getWidth();
22446
- const height = mbr.getHeight();
22447
- return [
22448
- new Point(mbr.left + width / 2, mbr.top),
22449
- new Point(mbr.left + width / 2, mbr.bottom),
22450
- new Point(mbr.left, mbr.top + height / 2),
22451
- new Point(mbr.right, mbr.top + height / 2)
22452
- ];
22453
- }
22454
- getLines() {
22455
- return this.lines;
22456
- }
22457
- isClosed() {
22458
- return true;
22459
- }
22460
- isEnclosedOrCrossedBy(rect) {
22461
- for (const line of this.lines) {
22462
- if (line.isEnclosedOrCrossedBy(rect)) {
22463
- return true;
22464
- }
22465
- }
22466
- return false;
22467
- }
22468
- emit(operation) {
22469
- if (this.events) {
22470
- const command = new DrawingCommand([this], operation);
22471
- command.apply();
22472
- this.events.emit(operation, command);
22473
- } else {
22474
- this.apply(operation);
22475
- }
22476
- }
22477
- apply(op) {
22478
- switch (op.class) {
22479
- case "Drawing":
22480
- switch (op.method) {
22481
- case "setStrokeColor":
22482
- this.borderColor = op.color;
22483
- break;
22484
- case "setStrokeWidth":
22485
- this.strokeWidth = op.width;
22486
- this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
22487
- break;
22488
- case "setStrokeOpacity":
22489
- this.borderOpacity = op.opacity;
22490
- break;
22491
- case "setStrokeStyle":
22492
- this.borderStyle = op.style;
22493
- this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
22494
- break;
22495
- }
22496
- this.updateMbr();
22497
- break;
22498
- case "Transformation":
22499
- this.transformation.apply(op);
22500
- break;
22501
- case "LinkTo":
22502
- this.linkTo.apply(op);
22503
- break;
22504
- default:
22505
- return;
22506
- }
22507
- this.subject.publish(this);
22508
- }
22509
- setStrokeOpacity(opacity) {
22510
- this.emit({
22511
- class: "Drawing",
22512
- method: "setStrokeOpacity",
22513
- item: [this.id],
22514
- opacity
22515
- });
22516
- return this;
22517
- }
22518
- getStrokeOpacity() {
22519
- return this.borderOpacity;
22520
- }
22521
- setBorderStyle(style) {
22522
- this.emit({
22523
- class: "Drawing",
22524
- method: "setStrokeStyle",
22525
- item: [this.id],
22526
- style
22527
- });
22528
- return this;
22529
- }
22530
- getBorderStyle() {
22531
- return this.borderStyle;
22532
- }
22533
- setStrokeColor(color) {
22534
- this.emit({
22535
- class: "Drawing",
22536
- method: "setStrokeColor",
22537
- item: [this.id],
22538
- color
22539
- });
22540
- return this;
22541
- }
22542
- getStrokeColor() {
22543
- return this.borderColor;
22544
- }
22545
- setStrokeWidth(width) {
22546
- this.emit({
22547
- class: "Drawing",
22548
- method: "setStrokeWidth",
22549
- item: [this.id],
22550
- width,
22551
- prevWidth: this.strokeWidth
22552
- });
22553
- return this;
22554
- }
22555
- getLinkTo() {
22556
- return this.linkTo.link;
22557
- }
22558
- getStrokeWidth() {
22559
- return this.strokeWidth;
22560
- }
22561
- getRichText() {
22562
- return null;
22563
- }
22564
- isPointNearLine(point3, threshold = 10) {
22565
- const transformedMouseX = (point3.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
22566
- const transformedMouseY = (point3.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
22567
- const transformedMouse = new Point(transformedMouseX, transformedMouseY);
22568
- for (let i = 0;i < this.points.length - 1; i++) {
22569
- const p1 = this.points[i];
22570
- const p2 = this.points[i + 1];
22571
- const distance = getPerpendicularDistance(transformedMouse, p1, p2);
22572
- if (distance < threshold) {
22573
- return true;
22574
- }
22575
- }
22576
- return false;
22577
- }
22578
- }
22579
- function getPerpendicularDistance(point3, lineStart, lineEnd) {
22580
- const { x: px, y: py } = point3;
22581
- const { x: sx, y: sy } = lineStart;
22582
- const { x: ex, y: ey } = lineEnd;
22583
- const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
22584
- const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
22585
- return numerator / denominator;
22586
- }
22587
- function douglasPeucker(points, epsilon2) {
22588
- if (points.length < 3) {
22589
- return points;
22590
- }
22591
- const start = points[0];
22592
- const end = points[points.length - 1];
22593
- let maxDistance = 0;
22594
- let maxIndex = 0;
22595
- for (let i = 1;i < points.length - 1; i++) {
22596
- const distance = getPerpendicularDistance(points[i], start, end);
22597
- if (distance > maxDistance) {
22598
- maxDistance = distance;
22599
- maxIndex = i;
22600
- }
22601
- }
22602
- if (maxDistance > epsilon2) {
22603
- const leftSubPoints = points.slice(0, maxIndex + 1);
22604
- const rightSubPoints = points.slice(maxIndex);
22605
- const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
22606
- const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
22607
- return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
22608
- } else {
22609
- return [start, end];
22610
- }
22611
- }
22612
22185
  // src/SpatialIndex/LayeredIndex/Layers.ts
22613
22186
  class Layers {
22614
22187
  getNewLayer;
@@ -23931,12 +23504,12 @@ class Items {
23931
23504
  if (enclosed.length === 0) {
23932
23505
  enclosed = underPointer;
23933
23506
  }
23934
- if (underPointer.some((item) => item instanceof Drawing)) {
23507
+ if (underPointer.some((item) => item.itemType === "Drawing")) {
23935
23508
  enclosed = [...underPointer, ...enclosed];
23936
23509
  }
23937
23510
  const { nearest } = enclosed.reduce((acc, item) => {
23938
23511
  const area = item.getMbr().getHeight() * item.getMbr().getWidth();
23939
- if (item instanceof Drawing && !item.isPointNearLine(this.pointer.point)) {
23512
+ if (item.itemType === "Drawing" && !item.isPointNearLine(this.pointer.point)) {
23940
23513
  return acc;
23941
23514
  }
23942
23515
  const isItemTransparent = item instanceof Shape && item?.getBackgroundColor() === "none";
@@ -44822,202 +44395,455 @@ class Placeholder extends BaseItem {
44822
44395
  renderHTML(documentFactory) {
44823
44396
  return documentFactory.createElement("div");
44824
44397
  }
44825
- getLinkTo() {
44826
- return;
44398
+ getLinkTo() {
44399
+ return;
44400
+ }
44401
+ getRichText() {
44402
+ return null;
44403
+ }
44404
+ }
44405
+ // src/Items/Image/Image.ts
44406
+ function getPlaceholderImage(board, imageDimension) {
44407
+ const placeholderCanvas = conf.documentFactory.createElement("canvas");
44408
+ const placeholderContext = placeholderCanvas.getContext("2d");
44409
+ const context = new DrawingContext(board.camera, placeholderContext);
44410
+ const placeholder = new Placeholder(board);
44411
+ if (imageDimension) {
44412
+ placeholderCanvas.width = imageDimension.width;
44413
+ placeholderCanvas.height = imageDimension.height;
44414
+ placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
44415
+ } else {
44416
+ placeholderCanvas.width = 250;
44417
+ placeholderCanvas.height = 50;
44418
+ placeholder.transformation.scaleTo(250 / 100, 50 / 100);
44419
+ }
44420
+ const placeholderImage = new Image;
44421
+ placeholderImage.src = placeholderCanvas.toDataURL();
44422
+ return placeholderImage;
44423
+ }
44424
+
44425
+ class ImageItem extends BaseItem {
44426
+ events;
44427
+ itemType = "Image";
44428
+ parent = "Board";
44429
+ image;
44430
+ transformation;
44431
+ linkTo;
44432
+ subject = new Subject;
44433
+ loadCallbacks = [];
44434
+ beforeLoadCallbacks = [];
44435
+ transformationRenderBlock = undefined;
44436
+ storageLink;
44437
+ imageDimension;
44438
+ board;
44439
+ constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
44440
+ super(board, id);
44441
+ this.events = events;
44442
+ this.linkTo = new LinkTo(this.id, events);
44443
+ this.board = board;
44444
+ this.setStorageLink(storageLink);
44445
+ this.imageDimension = imageDimension;
44446
+ this.transformation = new Transformation(id, events);
44447
+ this.image = new Image;
44448
+ this.image.crossOrigin = "anonymous";
44449
+ this.image.onload = this.onLoad;
44450
+ this.image.onerror = this.onError;
44451
+ if (typeof base64 === "string") {
44452
+ this.image.src = base64;
44453
+ }
44454
+ this.linkTo.subject.subscribe(() => {
44455
+ this.updateMbr();
44456
+ this.subject.publish(this);
44457
+ });
44458
+ this.transformation.subject.subscribe(this.onTransform);
44459
+ }
44460
+ setStorageLink(link2) {
44461
+ try {
44462
+ const url = new URL(link2);
44463
+ this.storageLink = `${window?.location.origin}${url.pathname}`;
44464
+ } catch (_) {}
44465
+ }
44466
+ getStorageId() {
44467
+ return this.storageLink.split("/").pop();
44468
+ }
44469
+ handleError = () => {
44470
+ console.error("Invalid dataUrl or image failed to load.");
44471
+ this.image = getPlaceholderImage(this.board);
44472
+ this.updateMbr();
44473
+ this.subject.publish(this);
44474
+ this.shootLoadCallbacks();
44475
+ };
44476
+ onLoad = async () => {
44477
+ this.shootBeforeLoadCallbacks();
44478
+ this.updateMbr();
44479
+ this.subject.publish(this);
44480
+ this.shootLoadCallbacks();
44481
+ };
44482
+ onError = (_error) => {
44483
+ this.image = getPlaceholderImage(this.board);
44484
+ this.updateMbr();
44485
+ this.subject.publish(this);
44486
+ this.shootLoadCallbacks();
44487
+ };
44488
+ onTransform = () => {
44489
+ this.updateMbr();
44490
+ this.subject.publish(this);
44491
+ };
44492
+ updateMbr() {
44493
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
44494
+ this.left = translateX;
44495
+ this.top = translateY;
44496
+ this.right = this.left + this.image.width * scaleX;
44497
+ this.bottom = this.top + this.image.height * scaleY;
44498
+ }
44499
+ doOnceBeforeOnLoad = (callback) => {
44500
+ this.loadCallbacks.push(callback);
44501
+ };
44502
+ doOnceOnLoad = (callback) => {
44503
+ this.loadCallbacks.push(callback);
44504
+ };
44505
+ setId(id) {
44506
+ this.id = id;
44507
+ this.transformation.setId(id);
44508
+ this.linkTo.setId(id);
44509
+ return this;
44510
+ }
44511
+ getId() {
44512
+ return this.id;
44513
+ }
44514
+ serialize() {
44515
+ return {
44516
+ itemType: "Image",
44517
+ storageLink: this.storageLink,
44518
+ imageDimension: this.imageDimension,
44519
+ transformation: this.transformation.serialize(),
44520
+ linkTo: this.linkTo.serialize()
44521
+ };
44522
+ }
44523
+ setCoordinates() {
44524
+ this.left = this.transformation.matrix.translateX;
44525
+ this.top = this.transformation.matrix.translateY;
44526
+ this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
44527
+ this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
44528
+ this.subject.publish(this);
44529
+ }
44530
+ shootBeforeLoadCallbacks() {
44531
+ while (this.beforeLoadCallbacks.length > 0) {
44532
+ this.beforeLoadCallbacks.shift()(this);
44533
+ }
44534
+ }
44535
+ shootLoadCallbacks() {
44536
+ while (this.loadCallbacks.length > 0) {
44537
+ this.loadCallbacks.shift()(this);
44538
+ }
44539
+ }
44540
+ deserialize(data) {
44541
+ if (data.transformation) {
44542
+ this.transformation.deserialize(data.transformation);
44543
+ }
44544
+ this.linkTo.deserialize(data.linkTo);
44545
+ this.image.onload = () => {
44546
+ this.setCoordinates();
44547
+ this.shootLoadCallbacks();
44548
+ };
44549
+ if (data.storageLink) {
44550
+ this.setStorageLink(data.storageLink);
44551
+ }
44552
+ if (this.image.src) {
44553
+ return this;
44554
+ }
44555
+ this.image = getPlaceholderImage(this.board, data.imageDimension);
44556
+ const storageImage = new Image;
44557
+ storageImage.onload = () => {
44558
+ this.image = storageImage;
44559
+ this.onLoad();
44560
+ };
44561
+ storageImage.onerror = this.onError;
44562
+ storageImage.src = this.storageLink;
44563
+ return this;
44564
+ }
44565
+ emit(operation) {
44566
+ if (this.events) {
44567
+ const command = new ImageCommand([this], operation);
44568
+ command.apply();
44569
+ this.events.emit(operation, command);
44570
+ } else {
44571
+ this.apply(operation);
44572
+ }
44573
+ }
44574
+ setDimensions(dim) {
44575
+ this.imageDimension = dim;
44576
+ }
44577
+ apply(op) {
44578
+ switch (op.class) {
44579
+ case "Transformation":
44580
+ this.transformation.apply(op);
44581
+ break;
44582
+ case "LinkTo":
44583
+ this.linkTo.apply(op);
44584
+ break;
44585
+ case "Image":
44586
+ if (op.data.base64) {
44587
+ this.image.src = op.data.base64;
44588
+ }
44589
+ this.setStorageLink(op.data.storageLink);
44590
+ this.setDimensions(op.data.imageDimension);
44591
+ this.subject.publish(this);
44592
+ break;
44593
+ }
44594
+ }
44595
+ render(context) {
44596
+ if (this.transformationRenderBlock) {
44597
+ return;
44598
+ }
44599
+ const ctx = context.ctx;
44600
+ ctx.save();
44601
+ this.transformation.matrix.applyToContext(ctx);
44602
+ ctx.drawImage(this.image, 0, 0);
44603
+ ctx.restore();
44604
+ if (this.getLinkTo()) {
44605
+ const { top, right } = this.getMbr();
44606
+ this.linkTo.render(context, top, right, this.board.camera.getScale());
44607
+ }
44608
+ }
44609
+ renderHTML(documentFactory) {
44610
+ const div = documentFactory.createElement("image-item");
44611
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
44612
+ const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
44613
+ div.style.backgroundImage = `url(${this.storageLink})`;
44614
+ div.id = this.getId();
44615
+ div.style.width = `${this.imageDimension.width}px`;
44616
+ div.style.height = `${this.imageDimension.height}px`;
44617
+ div.style.transformOrigin = "top left";
44618
+ div.style.transform = transform;
44619
+ div.style.position = "absolute";
44620
+ div.style.backgroundSize = "cover";
44621
+ div.setAttribute("data-link-to", this.linkTo.serialize() || "");
44622
+ if (this.getLinkTo()) {
44623
+ const linkElement = this.linkTo.renderHTML(documentFactory);
44624
+ scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
44625
+ translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
44626
+ div.appendChild(linkElement);
44627
+ }
44628
+ return div;
44629
+ }
44630
+ getPath() {
44631
+ const { left, top, right, bottom } = this.getMbr();
44632
+ const leftTop = new Point(left, top);
44633
+ const rightTop = new Point(right, top);
44634
+ const rightBottom = new Point(right, bottom);
44635
+ const leftBottom = new Point(left, bottom);
44636
+ return new Path([
44637
+ new Line(leftTop, rightTop),
44638
+ new Line(rightTop, rightBottom),
44639
+ new Line(rightBottom, leftBottom),
44640
+ new Line(leftBottom, leftTop)
44641
+ ], true);
44642
+ }
44643
+ getSnapAnchorPoints() {
44644
+ const mbr = this.getMbr();
44645
+ const width2 = mbr.getWidth();
44646
+ const height2 = mbr.getHeight();
44647
+ return [
44648
+ new Point(mbr.left + width2 / 2, mbr.top),
44649
+ new Point(mbr.left + width2 / 2, mbr.bottom),
44650
+ new Point(mbr.left, mbr.top + height2 / 2),
44651
+ new Point(mbr.right, mbr.top + height2 / 2)
44652
+ ];
44653
+ }
44654
+ isClosed() {
44655
+ return true;
44827
44656
  }
44828
44657
  getRichText() {
44829
44658
  return null;
44830
44659
  }
44660
+ getLinkTo() {
44661
+ return this.linkTo.link;
44662
+ }
44663
+ download() {
44664
+ const linkElem = document.createElement("a");
44665
+ linkElem.href = this.storageLink;
44666
+ linkElem.setAttribute("download", "");
44667
+ linkElem.click();
44668
+ }
44669
+ onRemove() {
44670
+ const storageId = this.getStorageId();
44671
+ if (storageId) {
44672
+ conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
44673
+ }
44674
+ super.onRemove();
44675
+ }
44831
44676
  }
44832
- // src/Items/Image/Image.ts
44833
- function getPlaceholderImage(board, imageDimension) {
44834
- const placeholderCanvas = conf.documentFactory.createElement("canvas");
44835
- const placeholderContext = placeholderCanvas.getContext("2d");
44836
- const context = new DrawingContext(board.camera, placeholderContext);
44837
- const placeholder = new Placeholder(board);
44838
- if (imageDimension) {
44839
- placeholderCanvas.width = imageDimension.width;
44840
- placeholderCanvas.height = imageDimension.height;
44841
- placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
44842
- } else {
44843
- placeholderCanvas.width = 250;
44844
- placeholderCanvas.height = 50;
44845
- placeholder.transformation.scaleTo(250 / 100, 50 / 100);
44677
+ // src/isSafari.ts
44678
+ function isSafari() {
44679
+ if (typeof navigator === "undefined") {
44680
+ return false;
44846
44681
  }
44847
- const placeholderImage = new Image;
44848
- placeholderImage.src = placeholderCanvas.toDataURL();
44849
- return placeholderImage;
44682
+ const agent = navigator.userAgent;
44683
+ const vendor = navigator.vendor;
44684
+ const is2 = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
44685
+ return is2;
44850
44686
  }
44851
44687
 
44852
- class ImageItem extends BaseItem {
44688
+ // src/Items/Drawing/Drawing.ts
44689
+ class Drawing extends BaseItem {
44690
+ points;
44853
44691
  events;
44854
- itemType = "Image";
44692
+ itemType = "Drawing";
44855
44693
  parent = "Board";
44856
- image;
44857
44694
  transformation;
44858
- linkTo;
44695
+ path2d = new conf.path2DFactory;
44859
44696
  subject = new Subject;
44860
- loadCallbacks = [];
44861
- beforeLoadCallbacks = [];
44697
+ untransformedMbr = new Mbr;
44698
+ lines = [];
44699
+ linkTo;
44700
+ strokeWidth = 1;
44701
+ borderStyle = "solid";
44702
+ linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
44703
+ borderOpacity = 1;
44862
44704
  transformationRenderBlock = undefined;
44863
- storageLink;
44864
- imageDimension;
44865
- board;
44866
- constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
44705
+ constructor(board, points, events, id = "") {
44867
44706
  super(board, id);
44707
+ this.points = points;
44868
44708
  this.events = events;
44869
- this.linkTo = new LinkTo(this.id, events);
44870
- this.board = board;
44871
- this.setStorageLink(storageLink);
44872
- this.imageDimension = imageDimension;
44873
44709
  this.transformation = new Transformation(id, events);
44874
- this.image = new Image;
44875
- this.image.crossOrigin = "anonymous";
44876
- this.image.onload = this.onLoad;
44877
- this.image.onerror = this.onError;
44878
- if (typeof base64 === "string") {
44879
- this.image.src = base64;
44880
- }
44710
+ this.linkTo = new LinkTo(this.id, this.events);
44711
+ this.transformation.subject.subscribe(() => {
44712
+ this.updateMbr();
44713
+ this.updateLines();
44714
+ this.subject.publish(this);
44715
+ });
44881
44716
  this.linkTo.subject.subscribe(() => {
44882
44717
  this.updateMbr();
44718
+ this.updateLines();
44883
44719
  this.subject.publish(this);
44884
44720
  });
44885
- this.transformation.subject.subscribe(this.onTransform);
44886
- }
44887
- setStorageLink(link2) {
44888
- try {
44889
- const url = new URL(link2);
44890
- this.storageLink = `${window?.location.origin}${url.pathname}`;
44891
- } catch (_) {}
44892
- }
44893
- getStorageId() {
44894
- return this.storageLink.split("/").pop();
44895
- }
44896
- handleError = () => {
44897
- console.error("Invalid dataUrl or image failed to load.");
44898
- this.image = getPlaceholderImage(this.board);
44899
- this.updateMbr();
44900
- this.subject.publish(this);
44901
- this.shootLoadCallbacks();
44902
- };
44903
- onLoad = async () => {
44904
- this.shootBeforeLoadCallbacks();
44905
- this.updateMbr();
44906
- this.subject.publish(this);
44907
- this.shootLoadCallbacks();
44908
- };
44909
- onError = (_error) => {
44910
- this.image = getPlaceholderImage(this.board);
44911
- this.updateMbr();
44912
- this.subject.publish(this);
44913
- this.shootLoadCallbacks();
44914
- };
44915
- onTransform = () => {
44916
- this.updateMbr();
44917
- this.subject.publish(this);
44918
- };
44919
- updateMbr() {
44920
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
44921
- this.left = translateX;
44922
- this.top = translateY;
44923
- this.right = this.left + this.image.width * scaleX;
44924
- this.bottom = this.top + this.image.height * scaleY;
44925
- }
44926
- doOnceBeforeOnLoad = (callback) => {
44927
- this.loadCallbacks.push(callback);
44928
- };
44929
- doOnceOnLoad = (callback) => {
44930
- this.loadCallbacks.push(callback);
44931
- };
44932
- setId(id) {
44933
- this.id = id;
44934
- this.transformation.setId(id);
44935
- this.linkTo.setId(id);
44936
- return this;
44937
- }
44938
- getId() {
44939
- return this.id;
44721
+ this.updateLines();
44940
44722
  }
44941
44723
  serialize() {
44724
+ this.optimizePoints();
44725
+ const points = [];
44726
+ for (const point5 of this.points) {
44727
+ points.push({ x: point5.x, y: point5.y });
44728
+ }
44942
44729
  return {
44943
- itemType: "Image",
44944
- storageLink: this.storageLink,
44945
- imageDimension: this.imageDimension,
44730
+ itemType: "Drawing",
44731
+ points,
44946
44732
  transformation: this.transformation.serialize(),
44733
+ strokeStyle: this.borderColor,
44734
+ strokeWidth: this.strokeWidth,
44947
44735
  linkTo: this.linkTo.serialize()
44948
44736
  };
44949
44737
  }
44950
- setCoordinates() {
44951
- this.left = this.transformation.matrix.translateX;
44952
- this.top = this.transformation.matrix.translateY;
44953
- this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
44954
- this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
44955
- this.subject.publish(this);
44956
- }
44957
- shootBeforeLoadCallbacks() {
44958
- while (this.beforeLoadCallbacks.length > 0) {
44959
- this.beforeLoadCallbacks.shift()(this);
44738
+ deserialize(data) {
44739
+ this.points = [];
44740
+ for (const point5 of data.points) {
44741
+ this.points.push(new Point(point5.x, point5.y));
44960
44742
  }
44743
+ this.linkTo.deserialize(data.linkTo);
44744
+ this.optimizePoints();
44745
+ this.transformation.deserialize(data.transformation);
44746
+ this.borderColor = data.strokeStyle;
44747
+ this.strokeWidth = data.strokeWidth;
44748
+ this.updateGeometry();
44749
+ return this;
44961
44750
  }
44962
- shootLoadCallbacks() {
44963
- while (this.loadCallbacks.length > 0) {
44964
- this.loadCallbacks.shift()(this);
44965
- }
44751
+ updateGeometry() {
44752
+ this.updatePath2d();
44753
+ this.updateLines();
44754
+ this.updateMbr();
44966
44755
  }
44967
- deserialize(data) {
44968
- if (data.transformation) {
44969
- this.transformation.deserialize(data.transformation);
44756
+ updateMbr() {
44757
+ const offset = this.getStrokeWidth() / 2;
44758
+ const untransformedMbr = this.untransformedMbr.copy();
44759
+ untransformedMbr.left -= offset;
44760
+ untransformedMbr.top -= offset;
44761
+ untransformedMbr.right += offset;
44762
+ untransformedMbr.bottom += offset;
44763
+ const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
44764
+ this.left = mbr.left;
44765
+ this.top = mbr.top;
44766
+ this.right = mbr.right;
44767
+ this.bottom = mbr.bottom;
44768
+ }
44769
+ updatePath2d() {
44770
+ this.path2d = new conf.path2DFactory;
44771
+ const context = this.path2d;
44772
+ const points = this.points;
44773
+ if (points.length < 3) {
44774
+ context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
44775
+ context.closePath();
44776
+ } else {
44777
+ context.moveTo(points[0].x, points[0].y);
44778
+ let j = 1;
44779
+ for (;j < points.length - 2; j++) {
44780
+ const cx = (points[j].x + points[j + 1].x) / 2;
44781
+ const cy = (points[j].y + points[j + 1].y) / 2;
44782
+ context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
44783
+ }
44784
+ const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
44785
+ const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
44786
+ context.quadraticCurveTo(points[j].x, points[j].y, x, y);
44970
44787
  }
44971
- this.linkTo.deserialize(data.linkTo);
44972
- this.image.onload = () => {
44973
- this.setCoordinates();
44974
- this.shootLoadCallbacks();
44975
- };
44976
- if (data.storageLink) {
44977
- this.setStorageLink(data.storageLink);
44788
+ let left = Number.MAX_SAFE_INTEGER;
44789
+ let right = Number.MIN_SAFE_INTEGER;
44790
+ let top = Number.MAX_SAFE_INTEGER;
44791
+ let bottom = Number.MIN_SAFE_INTEGER;
44792
+ for (const { x, y } of this.points) {
44793
+ if (x < left) {
44794
+ left = x;
44795
+ }
44796
+ if (x > right) {
44797
+ right = x;
44798
+ }
44799
+ if (y < top) {
44800
+ top = y;
44801
+ }
44802
+ if (y > bottom) {
44803
+ bottom = y;
44804
+ }
44978
44805
  }
44979
- if (this.image.src) {
44980
- return this;
44806
+ this.untransformedMbr = new Mbr(left, top, right, bottom);
44807
+ }
44808
+ updateLines() {
44809
+ this.lines = [];
44810
+ const matrix = this.transformation.matrix;
44811
+ if (this.points.length < 2) {
44812
+ return;
44813
+ }
44814
+ for (let i = 0;i < this.points.length - 2; i++) {
44815
+ const p1 = this.points[i];
44816
+ const p22 = this.points[i + 1];
44817
+ const line = new Line(p1.copy(), p22.copy());
44818
+ line.transform(matrix);
44819
+ this.lines.push(line);
44981
44820
  }
44982
- this.image = getPlaceholderImage(this.board, data.imageDimension);
44983
- const storageImage = new Image;
44984
- storageImage.onload = () => {
44985
- this.image = storageImage;
44986
- this.onLoad();
44987
- };
44988
- storageImage.onerror = this.onError;
44989
- storageImage.src = this.storageLink;
44990
- return this;
44991
44821
  }
44992
- emit(operation) {
44993
- if (this.events) {
44994
- const command = new ImageCommand([this], operation);
44995
- command.apply();
44996
- this.events.emit(operation, command);
44822
+ optimizePoints() {
44823
+ const dp = douglasPeucker(this.points, 1);
44824
+ dp.push(this.points[this.points.length - 1]);
44825
+ this.points = dp;
44826
+ }
44827
+ addPoint(point5) {
44828
+ const previous2 = this.points[this.points.length - 1];
44829
+ if (previous2) {
44830
+ const distance = point5.getDistance(previous2);
44831
+ if (distance >= 2) {
44832
+ this.points.push(point5);
44833
+ }
44997
44834
  } else {
44998
- this.apply(operation);
44835
+ this.points.push(point5);
44999
44836
  }
44837
+ this.updateGeometry();
45000
44838
  }
45001
- setDimensions(dim) {
45002
- this.imageDimension = dim;
44839
+ setId(id) {
44840
+ this.id = id;
44841
+ this.transformation.setId(id);
44842
+ this.linkTo.setId(id);
44843
+ return this;
45003
44844
  }
45004
- apply(op) {
45005
- switch (op.class) {
45006
- case "Transformation":
45007
- this.transformation.apply(op);
45008
- break;
45009
- case "LinkTo":
45010
- this.linkTo.apply(op);
45011
- break;
45012
- case "Image":
45013
- if (op.data.base64) {
45014
- this.image.src = op.data.base64;
45015
- }
45016
- this.setStorageLink(op.data.storageLink);
45017
- this.setDimensions(op.data.imageDimension);
45018
- this.subject.publish(this);
45019
- break;
45020
- }
44845
+ getId() {
44846
+ return this.id;
45021
44847
  }
45022
44848
  render(context) {
45023
44849
  if (this.transformationRenderBlock) {
@@ -45025,8 +44851,12 @@ class ImageItem extends BaseItem {
45025
44851
  }
45026
44852
  const ctx = context.ctx;
45027
44853
  ctx.save();
44854
+ ctx.strokeStyle = this.borderColor;
44855
+ ctx.lineWidth = this.strokeWidth;
44856
+ ctx.lineCap = "round";
44857
+ ctx.setLineDash(this.linePattern);
45028
44858
  this.transformation.matrix.applyToContext(ctx);
45029
- ctx.drawImage(this.image, 0, 0);
44859
+ ctx.stroke(this.path2d.nativePath);
45030
44860
  ctx.restore();
45031
44861
  if (this.getLinkTo()) {
45032
44862
  const { top, right } = this.getMbr();
@@ -45034,26 +44864,61 @@ class ImageItem extends BaseItem {
45034
44864
  }
45035
44865
  }
45036
44866
  renderHTML(documentFactory) {
45037
- const div = documentFactory.createElement("image-item");
44867
+ const div = documentFactory.createElement("drawing-item");
45038
44868
  const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
45039
- const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
45040
- div.style.backgroundImage = `url(${this.storageLink})`;
44869
+ const mbr = this.getMbr();
44870
+ const width2 = mbr.getWidth();
44871
+ const height2 = mbr.getHeight();
44872
+ const unscaledWidth = width2 / scaleX;
44873
+ const unscaledHeight = height2 / scaleY;
44874
+ const svg3 = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
44875
+ svg3.setAttribute("width", `${unscaledWidth}px`);
44876
+ svg3.setAttribute("height", `${unscaledHeight}px`);
44877
+ svg3.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
44878
+ svg3.setAttribute("style", "position: absolute; overflow: visible;");
44879
+ const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
44880
+ pathElement.setAttribute("d", this.getPathData());
44881
+ pathElement.setAttribute("stroke", this.borderColor);
44882
+ pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
44883
+ pathElement.setAttribute("fill", "none");
44884
+ svg3.appendChild(pathElement);
44885
+ div.appendChild(svg3);
45041
44886
  div.id = this.getId();
45042
- div.style.width = `${this.imageDimension.width}px`;
45043
- div.style.height = `${this.imageDimension.height}px`;
45044
- div.style.transformOrigin = "top left";
45045
- div.style.transform = transform;
44887
+ div.style.width = unscaledWidth + "px";
44888
+ div.style.height = unscaledHeight + "px";
44889
+ div.style.transformOrigin = "left top";
44890
+ div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
45046
44891
  div.style.position = "absolute";
45047
- div.style.backgroundSize = "cover";
45048
44892
  div.setAttribute("data-link-to", this.linkTo.serialize() || "");
45049
44893
  if (this.getLinkTo()) {
45050
44894
  const linkElement = this.linkTo.renderHTML(documentFactory);
45051
44895
  scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
45052
- translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
44896
+ translateElementBy(linkElement, (width2 - parseInt(linkElement.style.width)) / scaleX, 0);
45053
44897
  div.appendChild(linkElement);
45054
44898
  }
45055
44899
  return div;
45056
44900
  }
44901
+ getPathData() {
44902
+ const points = this.points;
44903
+ if (points.length < 2) {
44904
+ return "";
44905
+ }
44906
+ let pathData = `M ${points[0].x} ${points[0].y}`;
44907
+ if (points.length < 3) {
44908
+ pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
44909
+ } else {
44910
+ let j = 1;
44911
+ for (;j < points.length - 2; j++) {
44912
+ const cx = (points[j].x + points[j + 1].x) / 2;
44913
+ const cy = (points[j].y + points[j + 1].y) / 2;
44914
+ pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
44915
+ }
44916
+ const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
44917
+ const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
44918
+ pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
44919
+ }
44920
+ return pathData;
44921
+ }
45057
44922
  getPath() {
45058
44923
  const { left, top, right, bottom } = this.getMbr();
45059
44924
  const leftTop = new Point(left, top);
@@ -45078,27 +44943,162 @@ class ImageItem extends BaseItem {
45078
44943
  new Point(mbr.right, mbr.top + height2 / 2)
45079
44944
  ];
45080
44945
  }
44946
+ getLines() {
44947
+ return this.lines;
44948
+ }
45081
44949
  isClosed() {
45082
44950
  return true;
45083
44951
  }
45084
- getRichText() {
45085
- return null;
44952
+ isEnclosedOrCrossedBy(rect) {
44953
+ for (const line of this.lines) {
44954
+ if (line.isEnclosedOrCrossedBy(rect)) {
44955
+ return true;
44956
+ }
44957
+ }
44958
+ return false;
44959
+ }
44960
+ emit(operation) {
44961
+ if (this.events) {
44962
+ const command = new DrawingCommand([this], operation);
44963
+ command.apply();
44964
+ this.events.emit(operation, command);
44965
+ } else {
44966
+ this.apply(operation);
44967
+ }
44968
+ }
44969
+ apply(op) {
44970
+ switch (op.class) {
44971
+ case "Drawing":
44972
+ switch (op.method) {
44973
+ case "setStrokeColor":
44974
+ this.borderColor = op.color;
44975
+ break;
44976
+ case "setStrokeWidth":
44977
+ this.strokeWidth = op.width;
44978
+ this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
44979
+ break;
44980
+ case "setStrokeOpacity":
44981
+ this.borderOpacity = op.opacity;
44982
+ break;
44983
+ case "setStrokeStyle":
44984
+ this.borderStyle = op.style;
44985
+ this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
44986
+ break;
44987
+ }
44988
+ this.updateMbr();
44989
+ break;
44990
+ case "Transformation":
44991
+ this.transformation.apply(op);
44992
+ break;
44993
+ case "LinkTo":
44994
+ this.linkTo.apply(op);
44995
+ break;
44996
+ default:
44997
+ return;
44998
+ }
44999
+ this.subject.publish(this);
45000
+ }
45001
+ setStrokeOpacity(opacity) {
45002
+ this.emit({
45003
+ class: "Drawing",
45004
+ method: "setStrokeOpacity",
45005
+ item: [this.id],
45006
+ opacity
45007
+ });
45008
+ return this;
45009
+ }
45010
+ getStrokeOpacity() {
45011
+ return this.borderOpacity;
45012
+ }
45013
+ setBorderStyle(style2) {
45014
+ this.emit({
45015
+ class: "Drawing",
45016
+ method: "setStrokeStyle",
45017
+ item: [this.id],
45018
+ style: style2
45019
+ });
45020
+ return this;
45021
+ }
45022
+ getBorderStyle() {
45023
+ return this.borderStyle;
45024
+ }
45025
+ setStrokeColor(color2) {
45026
+ this.emit({
45027
+ class: "Drawing",
45028
+ method: "setStrokeColor",
45029
+ item: [this.id],
45030
+ color: color2
45031
+ });
45032
+ return this;
45033
+ }
45034
+ getStrokeColor() {
45035
+ return this.borderColor;
45036
+ }
45037
+ setStrokeWidth(width2) {
45038
+ this.emit({
45039
+ class: "Drawing",
45040
+ method: "setStrokeWidth",
45041
+ item: [this.id],
45042
+ width: width2,
45043
+ prevWidth: this.strokeWidth
45044
+ });
45045
+ return this;
45086
45046
  }
45087
45047
  getLinkTo() {
45088
45048
  return this.linkTo.link;
45089
45049
  }
45090
- download() {
45091
- const linkElem = document.createElement("a");
45092
- linkElem.href = this.storageLink;
45093
- linkElem.setAttribute("download", "");
45094
- linkElem.click();
45050
+ getStrokeWidth() {
45051
+ return this.strokeWidth;
45095
45052
  }
45096
- onRemove() {
45097
- const storageId = this.getStorageId();
45098
- if (storageId) {
45099
- conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
45053
+ getRichText() {
45054
+ return null;
45055
+ }
45056
+ isPointNearLine(point5, threshold = 10) {
45057
+ const transformedMouseX = (point5.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
45058
+ const transformedMouseY = (point5.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
45059
+ const transformedMouse = new Point(transformedMouseX, transformedMouseY);
45060
+ for (let i = 0;i < this.points.length - 1; i++) {
45061
+ const p1 = this.points[i];
45062
+ const p22 = this.points[i + 1];
45063
+ const distance = getPerpendicularDistance(transformedMouse, p1, p22);
45064
+ if (distance < threshold) {
45065
+ return true;
45066
+ }
45100
45067
  }
45101
- super.onRemove();
45068
+ return false;
45069
+ }
45070
+ }
45071
+ function getPerpendicularDistance(point5, lineStart, lineEnd) {
45072
+ const { x: px, y: py } = point5;
45073
+ const { x: sx, y: sy } = lineStart;
45074
+ const { x: ex, y: ey } = lineEnd;
45075
+ const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
45076
+ const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
45077
+ return numerator / denominator;
45078
+ }
45079
+ function douglasPeucker(points, epsilon2) {
45080
+ if (points.length < 3) {
45081
+ return points;
45082
+ }
45083
+ const start = points[0];
45084
+ const end = points[points.length - 1];
45085
+ let maxDistance = 0;
45086
+ let maxIndex = 0;
45087
+ for (let i = 1;i < points.length - 1; i++) {
45088
+ const distance = getPerpendicularDistance(points[i], start, end);
45089
+ if (distance > maxDistance) {
45090
+ maxDistance = distance;
45091
+ maxIndex = i;
45092
+ }
45093
+ }
45094
+ if (maxDistance > epsilon2) {
45095
+ const leftSubPoints = points.slice(0, maxIndex + 1);
45096
+ const rightSubPoints = points.slice(maxIndex);
45097
+ const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
45098
+ const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
45099
+ return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
45100
+ } else {
45101
+ return [start, end];
45102
45102
  }
45103
45103
  }
45104
45104
  // src/Items/Group/Group.ts