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/node.js CHANGED
@@ -22020,433 +22020,6 @@ class NoOpCommand {
22020
22020
  }
22021
22021
  }
22022
22022
 
22023
- // src/isSafari.ts
22024
- function isSafari() {
22025
- if (typeof navigator === "undefined") {
22026
- return false;
22027
- }
22028
- const agent = navigator.userAgent;
22029
- const vendor = navigator.vendor;
22030
- const is = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
22031
- return is;
22032
- }
22033
-
22034
- // src/Items/Drawing/Drawing.ts
22035
- class Drawing extends BaseItem {
22036
- points;
22037
- events;
22038
- itemType = "Drawing";
22039
- parent = "Board";
22040
- transformation;
22041
- path2d = new conf.path2DFactory;
22042
- subject = new Subject;
22043
- untransformedMbr = new Mbr;
22044
- lines = [];
22045
- linkTo;
22046
- strokeWidth = 1;
22047
- borderStyle = "solid";
22048
- linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
22049
- borderOpacity = 1;
22050
- transformationRenderBlock = undefined;
22051
- constructor(board, points, events, id = "") {
22052
- super(board, id);
22053
- this.points = points;
22054
- this.events = events;
22055
- this.transformation = new Transformation(id, events);
22056
- this.linkTo = new LinkTo(this.id, this.events);
22057
- this.transformation.subject.subscribe(() => {
22058
- this.updateMbr();
22059
- this.updateLines();
22060
- this.subject.publish(this);
22061
- });
22062
- this.linkTo.subject.subscribe(() => {
22063
- this.updateMbr();
22064
- this.updateLines();
22065
- this.subject.publish(this);
22066
- });
22067
- this.updateLines();
22068
- }
22069
- serialize() {
22070
- this.optimizePoints();
22071
- const points = [];
22072
- for (const point3 of this.points) {
22073
- points.push({ x: point3.x, y: point3.y });
22074
- }
22075
- return {
22076
- itemType: "Drawing",
22077
- points,
22078
- transformation: this.transformation.serialize(),
22079
- strokeStyle: this.borderColor,
22080
- strokeWidth: this.strokeWidth,
22081
- linkTo: this.linkTo.serialize()
22082
- };
22083
- }
22084
- deserialize(data) {
22085
- this.points = [];
22086
- for (const point3 of data.points) {
22087
- this.points.push(new Point(point3.x, point3.y));
22088
- }
22089
- this.linkTo.deserialize(data.linkTo);
22090
- this.optimizePoints();
22091
- this.transformation.deserialize(data.transformation);
22092
- this.borderColor = data.strokeStyle;
22093
- this.strokeWidth = data.strokeWidth;
22094
- this.updateGeometry();
22095
- return this;
22096
- }
22097
- updateGeometry() {
22098
- this.updatePath2d();
22099
- this.updateLines();
22100
- this.updateMbr();
22101
- }
22102
- updateMbr() {
22103
- const offset = this.getStrokeWidth() / 2;
22104
- const untransformedMbr = this.untransformedMbr.copy();
22105
- untransformedMbr.left -= offset;
22106
- untransformedMbr.top -= offset;
22107
- untransformedMbr.right += offset;
22108
- untransformedMbr.bottom += offset;
22109
- const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
22110
- this.left = mbr.left;
22111
- this.top = mbr.top;
22112
- this.right = mbr.right;
22113
- this.bottom = mbr.bottom;
22114
- }
22115
- updatePath2d() {
22116
- this.path2d = new conf.path2DFactory;
22117
- const context = this.path2d;
22118
- const points = this.points;
22119
- if (points.length < 3) {
22120
- context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
22121
- context.closePath();
22122
- } else {
22123
- context.moveTo(points[0].x, points[0].y);
22124
- let j = 1;
22125
- for (;j < points.length - 2; j++) {
22126
- const cx = (points[j].x + points[j + 1].x) / 2;
22127
- const cy = (points[j].y + points[j + 1].y) / 2;
22128
- context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
22129
- }
22130
- const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
22131
- const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
22132
- context.quadraticCurveTo(points[j].x, points[j].y, x, y);
22133
- }
22134
- let left = Number.MAX_SAFE_INTEGER;
22135
- let right = Number.MIN_SAFE_INTEGER;
22136
- let top = Number.MAX_SAFE_INTEGER;
22137
- let bottom = Number.MIN_SAFE_INTEGER;
22138
- for (const { x, y } of this.points) {
22139
- if (x < left) {
22140
- left = x;
22141
- }
22142
- if (x > right) {
22143
- right = x;
22144
- }
22145
- if (y < top) {
22146
- top = y;
22147
- }
22148
- if (y > bottom) {
22149
- bottom = y;
22150
- }
22151
- }
22152
- this.untransformedMbr = new Mbr(left, top, right, bottom);
22153
- }
22154
- updateLines() {
22155
- this.lines = [];
22156
- const matrix = this.transformation.matrix;
22157
- if (this.points.length < 2) {
22158
- return;
22159
- }
22160
- for (let i = 0;i < this.points.length - 2; i++) {
22161
- const p1 = this.points[i];
22162
- const p2 = this.points[i + 1];
22163
- const line = new Line(p1.copy(), p2.copy());
22164
- line.transform(matrix);
22165
- this.lines.push(line);
22166
- }
22167
- }
22168
- optimizePoints() {
22169
- const dp = douglasPeucker(this.points, 1);
22170
- dp.push(this.points[this.points.length - 1]);
22171
- this.points = dp;
22172
- }
22173
- addPoint(point3) {
22174
- const previous2 = this.points[this.points.length - 1];
22175
- if (previous2) {
22176
- const distance = point3.getDistance(previous2);
22177
- if (distance >= 2) {
22178
- this.points.push(point3);
22179
- }
22180
- } else {
22181
- this.points.push(point3);
22182
- }
22183
- this.updateGeometry();
22184
- }
22185
- setId(id) {
22186
- this.id = id;
22187
- this.transformation.setId(id);
22188
- this.linkTo.setId(id);
22189
- return this;
22190
- }
22191
- getId() {
22192
- return this.id;
22193
- }
22194
- render(context) {
22195
- if (this.transformationRenderBlock) {
22196
- return;
22197
- }
22198
- const ctx = context.ctx;
22199
- ctx.save();
22200
- ctx.strokeStyle = this.borderColor;
22201
- ctx.lineWidth = this.strokeWidth;
22202
- ctx.lineCap = "round";
22203
- ctx.setLineDash(this.linePattern);
22204
- this.transformation.matrix.applyToContext(ctx);
22205
- ctx.stroke(this.path2d.nativePath);
22206
- ctx.restore();
22207
- if (this.getLinkTo()) {
22208
- const { top, right } = this.getMbr();
22209
- this.linkTo.render(context, top, right, this.board.camera.getScale());
22210
- }
22211
- }
22212
- renderHTML(documentFactory) {
22213
- const div = documentFactory.createElement("drawing-item");
22214
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
22215
- const mbr = this.getMbr();
22216
- const width = mbr.getWidth();
22217
- const height = mbr.getHeight();
22218
- const unscaledWidth = width / scaleX;
22219
- const unscaledHeight = height / scaleY;
22220
- const svg = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
22221
- svg.setAttribute("width", `${unscaledWidth}px`);
22222
- svg.setAttribute("height", `${unscaledHeight}px`);
22223
- svg.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
22224
- svg.setAttribute("style", "position: absolute; overflow: visible;");
22225
- const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
22226
- pathElement.setAttribute("d", this.getPathData());
22227
- pathElement.setAttribute("stroke", this.borderColor);
22228
- pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
22229
- pathElement.setAttribute("fill", "none");
22230
- svg.appendChild(pathElement);
22231
- div.appendChild(svg);
22232
- div.id = this.getId();
22233
- div.style.width = unscaledWidth + "px";
22234
- div.style.height = unscaledHeight + "px";
22235
- div.style.transformOrigin = "left top";
22236
- div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
22237
- div.style.position = "absolute";
22238
- div.setAttribute("data-link-to", this.linkTo.serialize() || "");
22239
- if (this.getLinkTo()) {
22240
- const linkElement = this.linkTo.renderHTML(documentFactory);
22241
- scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
22242
- translateElementBy(linkElement, (width - parseInt(linkElement.style.width)) / scaleX, 0);
22243
- div.appendChild(linkElement);
22244
- }
22245
- return div;
22246
- }
22247
- getPathData() {
22248
- const points = this.points;
22249
- if (points.length < 2) {
22250
- return "";
22251
- }
22252
- let pathData = `M ${points[0].x} ${points[0].y}`;
22253
- if (points.length < 3) {
22254
- pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
22255
- } else {
22256
- let j = 1;
22257
- for (;j < points.length - 2; j++) {
22258
- const cx = (points[j].x + points[j + 1].x) / 2;
22259
- const cy = (points[j].y + points[j + 1].y) / 2;
22260
- pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
22261
- }
22262
- const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
22263
- const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
22264
- pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
22265
- }
22266
- return pathData;
22267
- }
22268
- getPath() {
22269
- const { left, top, right, bottom } = this.getMbr();
22270
- const leftTop = new Point(left, top);
22271
- const rightTop = new Point(right, top);
22272
- const rightBottom = new Point(right, bottom);
22273
- const leftBottom = new Point(left, bottom);
22274
- return new Path([
22275
- new Line(leftTop, rightTop),
22276
- new Line(rightTop, rightBottom),
22277
- new Line(rightBottom, leftBottom),
22278
- new Line(leftBottom, leftTop)
22279
- ], true);
22280
- }
22281
- getSnapAnchorPoints() {
22282
- const mbr = this.getMbr();
22283
- const width = mbr.getWidth();
22284
- const height = mbr.getHeight();
22285
- return [
22286
- new Point(mbr.left + width / 2, mbr.top),
22287
- new Point(mbr.left + width / 2, mbr.bottom),
22288
- new Point(mbr.left, mbr.top + height / 2),
22289
- new Point(mbr.right, mbr.top + height / 2)
22290
- ];
22291
- }
22292
- getLines() {
22293
- return this.lines;
22294
- }
22295
- isClosed() {
22296
- return true;
22297
- }
22298
- isEnclosedOrCrossedBy(rect) {
22299
- for (const line of this.lines) {
22300
- if (line.isEnclosedOrCrossedBy(rect)) {
22301
- return true;
22302
- }
22303
- }
22304
- return false;
22305
- }
22306
- emit(operation) {
22307
- if (this.events) {
22308
- const command = new DrawingCommand([this], operation);
22309
- command.apply();
22310
- this.events.emit(operation, command);
22311
- } else {
22312
- this.apply(operation);
22313
- }
22314
- }
22315
- apply(op) {
22316
- switch (op.class) {
22317
- case "Drawing":
22318
- switch (op.method) {
22319
- case "setStrokeColor":
22320
- this.borderColor = op.color;
22321
- break;
22322
- case "setStrokeWidth":
22323
- this.strokeWidth = op.width;
22324
- this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
22325
- break;
22326
- case "setStrokeOpacity":
22327
- this.borderOpacity = op.opacity;
22328
- break;
22329
- case "setStrokeStyle":
22330
- this.borderStyle = op.style;
22331
- this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
22332
- break;
22333
- }
22334
- this.updateMbr();
22335
- break;
22336
- case "Transformation":
22337
- this.transformation.apply(op);
22338
- break;
22339
- case "LinkTo":
22340
- this.linkTo.apply(op);
22341
- break;
22342
- default:
22343
- return;
22344
- }
22345
- this.subject.publish(this);
22346
- }
22347
- setStrokeOpacity(opacity) {
22348
- this.emit({
22349
- class: "Drawing",
22350
- method: "setStrokeOpacity",
22351
- item: [this.id],
22352
- opacity
22353
- });
22354
- return this;
22355
- }
22356
- getStrokeOpacity() {
22357
- return this.borderOpacity;
22358
- }
22359
- setBorderStyle(style) {
22360
- this.emit({
22361
- class: "Drawing",
22362
- method: "setStrokeStyle",
22363
- item: [this.id],
22364
- style
22365
- });
22366
- return this;
22367
- }
22368
- getBorderStyle() {
22369
- return this.borderStyle;
22370
- }
22371
- setStrokeColor(color) {
22372
- this.emit({
22373
- class: "Drawing",
22374
- method: "setStrokeColor",
22375
- item: [this.id],
22376
- color
22377
- });
22378
- return this;
22379
- }
22380
- getStrokeColor() {
22381
- return this.borderColor;
22382
- }
22383
- setStrokeWidth(width) {
22384
- this.emit({
22385
- class: "Drawing",
22386
- method: "setStrokeWidth",
22387
- item: [this.id],
22388
- width,
22389
- prevWidth: this.strokeWidth
22390
- });
22391
- return this;
22392
- }
22393
- getLinkTo() {
22394
- return this.linkTo.link;
22395
- }
22396
- getStrokeWidth() {
22397
- return this.strokeWidth;
22398
- }
22399
- getRichText() {
22400
- return null;
22401
- }
22402
- isPointNearLine(point3, threshold = 10) {
22403
- const transformedMouseX = (point3.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
22404
- const transformedMouseY = (point3.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
22405
- const transformedMouse = new Point(transformedMouseX, transformedMouseY);
22406
- for (let i = 0;i < this.points.length - 1; i++) {
22407
- const p1 = this.points[i];
22408
- const p2 = this.points[i + 1];
22409
- const distance = getPerpendicularDistance(transformedMouse, p1, p2);
22410
- if (distance < threshold) {
22411
- return true;
22412
- }
22413
- }
22414
- return false;
22415
- }
22416
- }
22417
- function getPerpendicularDistance(point3, lineStart, lineEnd) {
22418
- const { x: px, y: py } = point3;
22419
- const { x: sx, y: sy } = lineStart;
22420
- const { x: ex, y: ey } = lineEnd;
22421
- const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
22422
- const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
22423
- return numerator / denominator;
22424
- }
22425
- function douglasPeucker(points, epsilon2) {
22426
- if (points.length < 3) {
22427
- return points;
22428
- }
22429
- const start = points[0];
22430
- const end = points[points.length - 1];
22431
- let maxDistance = 0;
22432
- let maxIndex = 0;
22433
- for (let i = 1;i < points.length - 1; i++) {
22434
- const distance = getPerpendicularDistance(points[i], start, end);
22435
- if (distance > maxDistance) {
22436
- maxDistance = distance;
22437
- maxIndex = i;
22438
- }
22439
- }
22440
- if (maxDistance > epsilon2) {
22441
- const leftSubPoints = points.slice(0, maxIndex + 1);
22442
- const rightSubPoints = points.slice(maxIndex);
22443
- const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
22444
- const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
22445
- return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
22446
- } else {
22447
- return [start, end];
22448
- }
22449
- }
22450
22023
  // src/SpatialIndex/LayeredIndex/Layers.ts
22451
22024
  class Layers {
22452
22025
  getNewLayer;
@@ -23769,12 +23342,12 @@ class Items {
23769
23342
  if (enclosed.length === 0) {
23770
23343
  enclosed = underPointer;
23771
23344
  }
23772
- if (underPointer.some((item) => item instanceof Drawing)) {
23345
+ if (underPointer.some((item) => item.itemType === "Drawing")) {
23773
23346
  enclosed = [...underPointer, ...enclosed];
23774
23347
  }
23775
23348
  const { nearest } = enclosed.reduce((acc, item) => {
23776
23349
  const area = item.getMbr().getHeight() * item.getMbr().getWidth();
23777
- if (item instanceof Drawing && !item.isPointNearLine(this.pointer.point)) {
23350
+ if (item.itemType === "Drawing" && !item.isPointNearLine(this.pointer.point)) {
23778
23351
  return acc;
23779
23352
  }
23780
23353
  const isItemTransparent = item instanceof Shape && item?.getBackgroundColor() === "none";
@@ -44660,202 +44233,455 @@ class Placeholder extends BaseItem {
44660
44233
  renderHTML(documentFactory) {
44661
44234
  return documentFactory.createElement("div");
44662
44235
  }
44663
- getLinkTo() {
44664
- return;
44236
+ getLinkTo() {
44237
+ return;
44238
+ }
44239
+ getRichText() {
44240
+ return null;
44241
+ }
44242
+ }
44243
+ // src/Items/Image/Image.ts
44244
+ function getPlaceholderImage(board, imageDimension) {
44245
+ const placeholderCanvas = conf.documentFactory.createElement("canvas");
44246
+ const placeholderContext = placeholderCanvas.getContext("2d");
44247
+ const context = new DrawingContext(board.camera, placeholderContext);
44248
+ const placeholder = new Placeholder(board);
44249
+ if (imageDimension) {
44250
+ placeholderCanvas.width = imageDimension.width;
44251
+ placeholderCanvas.height = imageDimension.height;
44252
+ placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
44253
+ } else {
44254
+ placeholderCanvas.width = 250;
44255
+ placeholderCanvas.height = 50;
44256
+ placeholder.transformation.scaleTo(250 / 100, 50 / 100);
44257
+ }
44258
+ const placeholderImage = new Image;
44259
+ placeholderImage.src = placeholderCanvas.toDataURL();
44260
+ return placeholderImage;
44261
+ }
44262
+
44263
+ class ImageItem extends BaseItem {
44264
+ events;
44265
+ itemType = "Image";
44266
+ parent = "Board";
44267
+ image;
44268
+ transformation;
44269
+ linkTo;
44270
+ subject = new Subject;
44271
+ loadCallbacks = [];
44272
+ beforeLoadCallbacks = [];
44273
+ transformationRenderBlock = undefined;
44274
+ storageLink;
44275
+ imageDimension;
44276
+ board;
44277
+ constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
44278
+ super(board, id);
44279
+ this.events = events;
44280
+ this.linkTo = new LinkTo(this.id, events);
44281
+ this.board = board;
44282
+ this.setStorageLink(storageLink);
44283
+ this.imageDimension = imageDimension;
44284
+ this.transformation = new Transformation(id, events);
44285
+ this.image = new Image;
44286
+ this.image.crossOrigin = "anonymous";
44287
+ this.image.onload = this.onLoad;
44288
+ this.image.onerror = this.onError;
44289
+ if (typeof base64 === "string") {
44290
+ this.image.src = base64;
44291
+ }
44292
+ this.linkTo.subject.subscribe(() => {
44293
+ this.updateMbr();
44294
+ this.subject.publish(this);
44295
+ });
44296
+ this.transformation.subject.subscribe(this.onTransform);
44297
+ }
44298
+ setStorageLink(link2) {
44299
+ try {
44300
+ const url = new URL(link2);
44301
+ this.storageLink = `${window?.location.origin}${url.pathname}`;
44302
+ } catch (_) {}
44303
+ }
44304
+ getStorageId() {
44305
+ return this.storageLink.split("/").pop();
44306
+ }
44307
+ handleError = () => {
44308
+ console.error("Invalid dataUrl or image failed to load.");
44309
+ this.image = getPlaceholderImage(this.board);
44310
+ this.updateMbr();
44311
+ this.subject.publish(this);
44312
+ this.shootLoadCallbacks();
44313
+ };
44314
+ onLoad = async () => {
44315
+ this.shootBeforeLoadCallbacks();
44316
+ this.updateMbr();
44317
+ this.subject.publish(this);
44318
+ this.shootLoadCallbacks();
44319
+ };
44320
+ onError = (_error) => {
44321
+ this.image = getPlaceholderImage(this.board);
44322
+ this.updateMbr();
44323
+ this.subject.publish(this);
44324
+ this.shootLoadCallbacks();
44325
+ };
44326
+ onTransform = () => {
44327
+ this.updateMbr();
44328
+ this.subject.publish(this);
44329
+ };
44330
+ updateMbr() {
44331
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
44332
+ this.left = translateX;
44333
+ this.top = translateY;
44334
+ this.right = this.left + this.image.width * scaleX;
44335
+ this.bottom = this.top + this.image.height * scaleY;
44336
+ }
44337
+ doOnceBeforeOnLoad = (callback) => {
44338
+ this.loadCallbacks.push(callback);
44339
+ };
44340
+ doOnceOnLoad = (callback) => {
44341
+ this.loadCallbacks.push(callback);
44342
+ };
44343
+ setId(id) {
44344
+ this.id = id;
44345
+ this.transformation.setId(id);
44346
+ this.linkTo.setId(id);
44347
+ return this;
44348
+ }
44349
+ getId() {
44350
+ return this.id;
44351
+ }
44352
+ serialize() {
44353
+ return {
44354
+ itemType: "Image",
44355
+ storageLink: this.storageLink,
44356
+ imageDimension: this.imageDimension,
44357
+ transformation: this.transformation.serialize(),
44358
+ linkTo: this.linkTo.serialize()
44359
+ };
44360
+ }
44361
+ setCoordinates() {
44362
+ this.left = this.transformation.matrix.translateX;
44363
+ this.top = this.transformation.matrix.translateY;
44364
+ this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
44365
+ this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
44366
+ this.subject.publish(this);
44367
+ }
44368
+ shootBeforeLoadCallbacks() {
44369
+ while (this.beforeLoadCallbacks.length > 0) {
44370
+ this.beforeLoadCallbacks.shift()(this);
44371
+ }
44372
+ }
44373
+ shootLoadCallbacks() {
44374
+ while (this.loadCallbacks.length > 0) {
44375
+ this.loadCallbacks.shift()(this);
44376
+ }
44377
+ }
44378
+ deserialize(data) {
44379
+ if (data.transformation) {
44380
+ this.transformation.deserialize(data.transformation);
44381
+ }
44382
+ this.linkTo.deserialize(data.linkTo);
44383
+ this.image.onload = () => {
44384
+ this.setCoordinates();
44385
+ this.shootLoadCallbacks();
44386
+ };
44387
+ if (data.storageLink) {
44388
+ this.setStorageLink(data.storageLink);
44389
+ }
44390
+ if (this.image.src) {
44391
+ return this;
44392
+ }
44393
+ this.image = getPlaceholderImage(this.board, data.imageDimension);
44394
+ const storageImage = new Image;
44395
+ storageImage.onload = () => {
44396
+ this.image = storageImage;
44397
+ this.onLoad();
44398
+ };
44399
+ storageImage.onerror = this.onError;
44400
+ storageImage.src = this.storageLink;
44401
+ return this;
44402
+ }
44403
+ emit(operation) {
44404
+ if (this.events) {
44405
+ const command = new ImageCommand([this], operation);
44406
+ command.apply();
44407
+ this.events.emit(operation, command);
44408
+ } else {
44409
+ this.apply(operation);
44410
+ }
44411
+ }
44412
+ setDimensions(dim) {
44413
+ this.imageDimension = dim;
44414
+ }
44415
+ apply(op) {
44416
+ switch (op.class) {
44417
+ case "Transformation":
44418
+ this.transformation.apply(op);
44419
+ break;
44420
+ case "LinkTo":
44421
+ this.linkTo.apply(op);
44422
+ break;
44423
+ case "Image":
44424
+ if (op.data.base64) {
44425
+ this.image.src = op.data.base64;
44426
+ }
44427
+ this.setStorageLink(op.data.storageLink);
44428
+ this.setDimensions(op.data.imageDimension);
44429
+ this.subject.publish(this);
44430
+ break;
44431
+ }
44432
+ }
44433
+ render(context) {
44434
+ if (this.transformationRenderBlock) {
44435
+ return;
44436
+ }
44437
+ const ctx = context.ctx;
44438
+ ctx.save();
44439
+ this.transformation.matrix.applyToContext(ctx);
44440
+ ctx.drawImage(this.image, 0, 0);
44441
+ ctx.restore();
44442
+ if (this.getLinkTo()) {
44443
+ const { top, right } = this.getMbr();
44444
+ this.linkTo.render(context, top, right, this.board.camera.getScale());
44445
+ }
44446
+ }
44447
+ renderHTML(documentFactory) {
44448
+ const div = documentFactory.createElement("image-item");
44449
+ const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
44450
+ const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
44451
+ div.style.backgroundImage = `url(${this.storageLink})`;
44452
+ div.id = this.getId();
44453
+ div.style.width = `${this.imageDimension.width}px`;
44454
+ div.style.height = `${this.imageDimension.height}px`;
44455
+ div.style.transformOrigin = "top left";
44456
+ div.style.transform = transform;
44457
+ div.style.position = "absolute";
44458
+ div.style.backgroundSize = "cover";
44459
+ div.setAttribute("data-link-to", this.linkTo.serialize() || "");
44460
+ if (this.getLinkTo()) {
44461
+ const linkElement = this.linkTo.renderHTML(documentFactory);
44462
+ scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
44463
+ translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
44464
+ div.appendChild(linkElement);
44465
+ }
44466
+ return div;
44467
+ }
44468
+ getPath() {
44469
+ const { left, top, right, bottom } = this.getMbr();
44470
+ const leftTop = new Point(left, top);
44471
+ const rightTop = new Point(right, top);
44472
+ const rightBottom = new Point(right, bottom);
44473
+ const leftBottom = new Point(left, bottom);
44474
+ return new Path([
44475
+ new Line(leftTop, rightTop),
44476
+ new Line(rightTop, rightBottom),
44477
+ new Line(rightBottom, leftBottom),
44478
+ new Line(leftBottom, leftTop)
44479
+ ], true);
44480
+ }
44481
+ getSnapAnchorPoints() {
44482
+ const mbr = this.getMbr();
44483
+ const width2 = mbr.getWidth();
44484
+ const height2 = mbr.getHeight();
44485
+ return [
44486
+ new Point(mbr.left + width2 / 2, mbr.top),
44487
+ new Point(mbr.left + width2 / 2, mbr.bottom),
44488
+ new Point(mbr.left, mbr.top + height2 / 2),
44489
+ new Point(mbr.right, mbr.top + height2 / 2)
44490
+ ];
44491
+ }
44492
+ isClosed() {
44493
+ return true;
44665
44494
  }
44666
44495
  getRichText() {
44667
44496
  return null;
44668
44497
  }
44498
+ getLinkTo() {
44499
+ return this.linkTo.link;
44500
+ }
44501
+ download() {
44502
+ const linkElem = document.createElement("a");
44503
+ linkElem.href = this.storageLink;
44504
+ linkElem.setAttribute("download", "");
44505
+ linkElem.click();
44506
+ }
44507
+ onRemove() {
44508
+ const storageId = this.getStorageId();
44509
+ if (storageId) {
44510
+ conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
44511
+ }
44512
+ super.onRemove();
44513
+ }
44669
44514
  }
44670
- // src/Items/Image/Image.ts
44671
- function getPlaceholderImage(board, imageDimension) {
44672
- const placeholderCanvas = conf.documentFactory.createElement("canvas");
44673
- const placeholderContext = placeholderCanvas.getContext("2d");
44674
- const context = new DrawingContext(board.camera, placeholderContext);
44675
- const placeholder = new Placeholder(board);
44676
- if (imageDimension) {
44677
- placeholderCanvas.width = imageDimension.width;
44678
- placeholderCanvas.height = imageDimension.height;
44679
- placeholder.transformation.scaleTo(imageDimension.width / 100, imageDimension.height / 100);
44680
- } else {
44681
- placeholderCanvas.width = 250;
44682
- placeholderCanvas.height = 50;
44683
- placeholder.transformation.scaleTo(250 / 100, 50 / 100);
44515
+ // src/isSafari.ts
44516
+ function isSafari() {
44517
+ if (typeof navigator === "undefined") {
44518
+ return false;
44684
44519
  }
44685
- const placeholderImage = new Image;
44686
- placeholderImage.src = placeholderCanvas.toDataURL();
44687
- return placeholderImage;
44520
+ const agent = navigator.userAgent;
44521
+ const vendor = navigator.vendor;
44522
+ const is2 = vendor !== undefined && vendor.includes("Apple") && agent !== undefined && !agent.includes("CriOS") && !agent.includes("FxiOS");
44523
+ return is2;
44688
44524
  }
44689
44525
 
44690
- class ImageItem extends BaseItem {
44526
+ // src/Items/Drawing/Drawing.ts
44527
+ class Drawing extends BaseItem {
44528
+ points;
44691
44529
  events;
44692
- itemType = "Image";
44530
+ itemType = "Drawing";
44693
44531
  parent = "Board";
44694
- image;
44695
44532
  transformation;
44696
- linkTo;
44533
+ path2d = new conf.path2DFactory;
44697
44534
  subject = new Subject;
44698
- loadCallbacks = [];
44699
- beforeLoadCallbacks = [];
44535
+ untransformedMbr = new Mbr;
44536
+ lines = [];
44537
+ linkTo;
44538
+ strokeWidth = 1;
44539
+ borderStyle = "solid";
44540
+ linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
44541
+ borderOpacity = 1;
44700
44542
  transformationRenderBlock = undefined;
44701
- storageLink;
44702
- imageDimension;
44703
- board;
44704
- constructor({ base64, storageLink, imageDimension }, board, events, id = "") {
44543
+ constructor(board, points, events, id = "") {
44705
44544
  super(board, id);
44545
+ this.points = points;
44706
44546
  this.events = events;
44707
- this.linkTo = new LinkTo(this.id, events);
44708
- this.board = board;
44709
- this.setStorageLink(storageLink);
44710
- this.imageDimension = imageDimension;
44711
44547
  this.transformation = new Transformation(id, events);
44712
- this.image = new Image;
44713
- this.image.crossOrigin = "anonymous";
44714
- this.image.onload = this.onLoad;
44715
- this.image.onerror = this.onError;
44716
- if (typeof base64 === "string") {
44717
- this.image.src = base64;
44718
- }
44548
+ this.linkTo = new LinkTo(this.id, this.events);
44549
+ this.transformation.subject.subscribe(() => {
44550
+ this.updateMbr();
44551
+ this.updateLines();
44552
+ this.subject.publish(this);
44553
+ });
44719
44554
  this.linkTo.subject.subscribe(() => {
44720
44555
  this.updateMbr();
44556
+ this.updateLines();
44721
44557
  this.subject.publish(this);
44722
44558
  });
44723
- this.transformation.subject.subscribe(this.onTransform);
44724
- }
44725
- setStorageLink(link2) {
44726
- try {
44727
- const url = new URL(link2);
44728
- this.storageLink = `${window?.location.origin}${url.pathname}`;
44729
- } catch (_) {}
44730
- }
44731
- getStorageId() {
44732
- return this.storageLink.split("/").pop();
44733
- }
44734
- handleError = () => {
44735
- console.error("Invalid dataUrl or image failed to load.");
44736
- this.image = getPlaceholderImage(this.board);
44737
- this.updateMbr();
44738
- this.subject.publish(this);
44739
- this.shootLoadCallbacks();
44740
- };
44741
- onLoad = async () => {
44742
- this.shootBeforeLoadCallbacks();
44743
- this.updateMbr();
44744
- this.subject.publish(this);
44745
- this.shootLoadCallbacks();
44746
- };
44747
- onError = (_error) => {
44748
- this.image = getPlaceholderImage(this.board);
44749
- this.updateMbr();
44750
- this.subject.publish(this);
44751
- this.shootLoadCallbacks();
44752
- };
44753
- onTransform = () => {
44754
- this.updateMbr();
44755
- this.subject.publish(this);
44756
- };
44757
- updateMbr() {
44758
- const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
44759
- this.left = translateX;
44760
- this.top = translateY;
44761
- this.right = this.left + this.image.width * scaleX;
44762
- this.bottom = this.top + this.image.height * scaleY;
44763
- }
44764
- doOnceBeforeOnLoad = (callback) => {
44765
- this.loadCallbacks.push(callback);
44766
- };
44767
- doOnceOnLoad = (callback) => {
44768
- this.loadCallbacks.push(callback);
44769
- };
44770
- setId(id) {
44771
- this.id = id;
44772
- this.transformation.setId(id);
44773
- this.linkTo.setId(id);
44774
- return this;
44775
- }
44776
- getId() {
44777
- return this.id;
44559
+ this.updateLines();
44778
44560
  }
44779
44561
  serialize() {
44562
+ this.optimizePoints();
44563
+ const points = [];
44564
+ for (const point5 of this.points) {
44565
+ points.push({ x: point5.x, y: point5.y });
44566
+ }
44780
44567
  return {
44781
- itemType: "Image",
44782
- storageLink: this.storageLink,
44783
- imageDimension: this.imageDimension,
44568
+ itemType: "Drawing",
44569
+ points,
44784
44570
  transformation: this.transformation.serialize(),
44571
+ strokeStyle: this.borderColor,
44572
+ strokeWidth: this.strokeWidth,
44785
44573
  linkTo: this.linkTo.serialize()
44786
44574
  };
44787
44575
  }
44788
- setCoordinates() {
44789
- this.left = this.transformation.matrix.translateX;
44790
- this.top = this.transformation.matrix.translateY;
44791
- this.right = this.left + this.image.width * this.transformation.matrix.scaleX;
44792
- this.bottom = this.top + this.image.height * this.transformation.matrix.scaleY;
44793
- this.subject.publish(this);
44794
- }
44795
- shootBeforeLoadCallbacks() {
44796
- while (this.beforeLoadCallbacks.length > 0) {
44797
- this.beforeLoadCallbacks.shift()(this);
44576
+ deserialize(data) {
44577
+ this.points = [];
44578
+ for (const point5 of data.points) {
44579
+ this.points.push(new Point(point5.x, point5.y));
44798
44580
  }
44581
+ this.linkTo.deserialize(data.linkTo);
44582
+ this.optimizePoints();
44583
+ this.transformation.deserialize(data.transformation);
44584
+ this.borderColor = data.strokeStyle;
44585
+ this.strokeWidth = data.strokeWidth;
44586
+ this.updateGeometry();
44587
+ return this;
44799
44588
  }
44800
- shootLoadCallbacks() {
44801
- while (this.loadCallbacks.length > 0) {
44802
- this.loadCallbacks.shift()(this);
44803
- }
44589
+ updateGeometry() {
44590
+ this.updatePath2d();
44591
+ this.updateLines();
44592
+ this.updateMbr();
44804
44593
  }
44805
- deserialize(data) {
44806
- if (data.transformation) {
44807
- this.transformation.deserialize(data.transformation);
44594
+ updateMbr() {
44595
+ const offset = this.getStrokeWidth() / 2;
44596
+ const untransformedMbr = this.untransformedMbr.copy();
44597
+ untransformedMbr.left -= offset;
44598
+ untransformedMbr.top -= offset;
44599
+ untransformedMbr.right += offset;
44600
+ untransformedMbr.bottom += offset;
44601
+ const mbr = untransformedMbr.getTransformed(this.transformation.matrix);
44602
+ this.left = mbr.left;
44603
+ this.top = mbr.top;
44604
+ this.right = mbr.right;
44605
+ this.bottom = mbr.bottom;
44606
+ }
44607
+ updatePath2d() {
44608
+ this.path2d = new conf.path2DFactory;
44609
+ const context = this.path2d;
44610
+ const points = this.points;
44611
+ if (points.length < 3) {
44612
+ context.arc(points[0].x, points[0].y, 0.5, 0, Math.PI * 2, true);
44613
+ context.closePath();
44614
+ } else {
44615
+ context.moveTo(points[0].x, points[0].y);
44616
+ let j = 1;
44617
+ for (;j < points.length - 2; j++) {
44618
+ const cx = (points[j].x + points[j + 1].x) / 2;
44619
+ const cy = (points[j].y + points[j + 1].y) / 2;
44620
+ context.quadraticCurveTo(points[j].x, points[j].y, cx, cy);
44621
+ }
44622
+ const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
44623
+ const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
44624
+ context.quadraticCurveTo(points[j].x, points[j].y, x, y);
44808
44625
  }
44809
- this.linkTo.deserialize(data.linkTo);
44810
- this.image.onload = () => {
44811
- this.setCoordinates();
44812
- this.shootLoadCallbacks();
44813
- };
44814
- if (data.storageLink) {
44815
- this.setStorageLink(data.storageLink);
44626
+ let left = Number.MAX_SAFE_INTEGER;
44627
+ let right = Number.MIN_SAFE_INTEGER;
44628
+ let top = Number.MAX_SAFE_INTEGER;
44629
+ let bottom = Number.MIN_SAFE_INTEGER;
44630
+ for (const { x, y } of this.points) {
44631
+ if (x < left) {
44632
+ left = x;
44633
+ }
44634
+ if (x > right) {
44635
+ right = x;
44636
+ }
44637
+ if (y < top) {
44638
+ top = y;
44639
+ }
44640
+ if (y > bottom) {
44641
+ bottom = y;
44642
+ }
44816
44643
  }
44817
- if (this.image.src) {
44818
- return this;
44644
+ this.untransformedMbr = new Mbr(left, top, right, bottom);
44645
+ }
44646
+ updateLines() {
44647
+ this.lines = [];
44648
+ const matrix = this.transformation.matrix;
44649
+ if (this.points.length < 2) {
44650
+ return;
44651
+ }
44652
+ for (let i = 0;i < this.points.length - 2; i++) {
44653
+ const p1 = this.points[i];
44654
+ const p22 = this.points[i + 1];
44655
+ const line = new Line(p1.copy(), p22.copy());
44656
+ line.transform(matrix);
44657
+ this.lines.push(line);
44819
44658
  }
44820
- this.image = getPlaceholderImage(this.board, data.imageDimension);
44821
- const storageImage = new Image;
44822
- storageImage.onload = () => {
44823
- this.image = storageImage;
44824
- this.onLoad();
44825
- };
44826
- storageImage.onerror = this.onError;
44827
- storageImage.src = this.storageLink;
44828
- return this;
44829
44659
  }
44830
- emit(operation) {
44831
- if (this.events) {
44832
- const command = new ImageCommand([this], operation);
44833
- command.apply();
44834
- this.events.emit(operation, command);
44660
+ optimizePoints() {
44661
+ const dp = douglasPeucker(this.points, 1);
44662
+ dp.push(this.points[this.points.length - 1]);
44663
+ this.points = dp;
44664
+ }
44665
+ addPoint(point5) {
44666
+ const previous2 = this.points[this.points.length - 1];
44667
+ if (previous2) {
44668
+ const distance = point5.getDistance(previous2);
44669
+ if (distance >= 2) {
44670
+ this.points.push(point5);
44671
+ }
44835
44672
  } else {
44836
- this.apply(operation);
44673
+ this.points.push(point5);
44837
44674
  }
44675
+ this.updateGeometry();
44838
44676
  }
44839
- setDimensions(dim) {
44840
- this.imageDimension = dim;
44677
+ setId(id) {
44678
+ this.id = id;
44679
+ this.transformation.setId(id);
44680
+ this.linkTo.setId(id);
44681
+ return this;
44841
44682
  }
44842
- apply(op) {
44843
- switch (op.class) {
44844
- case "Transformation":
44845
- this.transformation.apply(op);
44846
- break;
44847
- case "LinkTo":
44848
- this.linkTo.apply(op);
44849
- break;
44850
- case "Image":
44851
- if (op.data.base64) {
44852
- this.image.src = op.data.base64;
44853
- }
44854
- this.setStorageLink(op.data.storageLink);
44855
- this.setDimensions(op.data.imageDimension);
44856
- this.subject.publish(this);
44857
- break;
44858
- }
44683
+ getId() {
44684
+ return this.id;
44859
44685
  }
44860
44686
  render(context) {
44861
44687
  if (this.transformationRenderBlock) {
@@ -44863,8 +44689,12 @@ class ImageItem extends BaseItem {
44863
44689
  }
44864
44690
  const ctx = context.ctx;
44865
44691
  ctx.save();
44692
+ ctx.strokeStyle = this.borderColor;
44693
+ ctx.lineWidth = this.strokeWidth;
44694
+ ctx.lineCap = "round";
44695
+ ctx.setLineDash(this.linePattern);
44866
44696
  this.transformation.matrix.applyToContext(ctx);
44867
- ctx.drawImage(this.image, 0, 0);
44697
+ ctx.stroke(this.path2d.nativePath);
44868
44698
  ctx.restore();
44869
44699
  if (this.getLinkTo()) {
44870
44700
  const { top, right } = this.getMbr();
@@ -44872,26 +44702,61 @@ class ImageItem extends BaseItem {
44872
44702
  }
44873
44703
  }
44874
44704
  renderHTML(documentFactory) {
44875
- const div = documentFactory.createElement("image-item");
44705
+ const div = documentFactory.createElement("drawing-item");
44876
44706
  const { translateX, translateY, scaleX, scaleY } = this.transformation.matrix;
44877
- const transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
44878
- div.style.backgroundImage = `url(${this.storageLink})`;
44707
+ const mbr = this.getMbr();
44708
+ const width2 = mbr.getWidth();
44709
+ const height2 = mbr.getHeight();
44710
+ const unscaledWidth = width2 / scaleX;
44711
+ const unscaledHeight = height2 / scaleY;
44712
+ const svg3 = documentFactory.createElementNS("http://www.w3.org/2000/svg", "svg");
44713
+ svg3.setAttribute("width", `${unscaledWidth}px`);
44714
+ svg3.setAttribute("height", `${unscaledHeight}px`);
44715
+ svg3.setAttribute("viewBox", `0 0 ${unscaledWidth} ${unscaledHeight}`);
44716
+ svg3.setAttribute("style", "position: absolute; overflow: visible;");
44717
+ const pathElement = documentFactory.createElementNS("http://www.w3.org/2000/svg", "path");
44718
+ pathElement.setAttribute("d", this.getPathData());
44719
+ pathElement.setAttribute("stroke", this.borderColor);
44720
+ pathElement.setAttribute("stroke-width", `${this.strokeWidth}`);
44721
+ pathElement.setAttribute("fill", "none");
44722
+ svg3.appendChild(pathElement);
44723
+ div.appendChild(svg3);
44879
44724
  div.id = this.getId();
44880
- div.style.width = `${this.imageDimension.width}px`;
44881
- div.style.height = `${this.imageDimension.height}px`;
44882
- div.style.transformOrigin = "top left";
44883
- div.style.transform = transform;
44725
+ div.style.width = unscaledWidth + "px";
44726
+ div.style.height = unscaledHeight + "px";
44727
+ div.style.transformOrigin = "left top";
44728
+ div.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scaleX}, ${scaleY})`;
44884
44729
  div.style.position = "absolute";
44885
- div.style.backgroundSize = "cover";
44886
44730
  div.setAttribute("data-link-to", this.linkTo.serialize() || "");
44887
44731
  if (this.getLinkTo()) {
44888
44732
  const linkElement = this.linkTo.renderHTML(documentFactory);
44889
44733
  scaleElementBy(linkElement, 1 / scaleX, 1 / scaleY);
44890
- translateElementBy(linkElement, (this.getMbr().getWidth() - parseInt(linkElement.style.width)) / scaleX, 0);
44734
+ translateElementBy(linkElement, (width2 - parseInt(linkElement.style.width)) / scaleX, 0);
44891
44735
  div.appendChild(linkElement);
44892
44736
  }
44893
44737
  return div;
44894
44738
  }
44739
+ getPathData() {
44740
+ const points = this.points;
44741
+ if (points.length < 2) {
44742
+ return "";
44743
+ }
44744
+ let pathData = `M ${points[0].x} ${points[0].y}`;
44745
+ if (points.length < 3) {
44746
+ pathData += ` L ${points[0].x + 0.5} ${points[0].y}`;
44747
+ } else {
44748
+ let j = 1;
44749
+ for (;j < points.length - 2; j++) {
44750
+ const cx = (points[j].x + points[j + 1].x) / 2;
44751
+ const cy = (points[j].y + points[j + 1].y) / 2;
44752
+ pathData += ` Q ${points[j].x} ${points[j].y} ${cx} ${cy}`;
44753
+ }
44754
+ const x = points[j].x === points[j + 1].x && isSafari() ? points[j + 1].x + 0.01 : points[j + 1].x;
44755
+ const y = points[j].y === points[j + 1].y && isSafari() ? points[j + 1].y + 0.01 : points[j + 1].y;
44756
+ pathData += ` Q ${points[j].x} ${points[j].y} ${x} ${y}`;
44757
+ }
44758
+ return pathData;
44759
+ }
44895
44760
  getPath() {
44896
44761
  const { left, top, right, bottom } = this.getMbr();
44897
44762
  const leftTop = new Point(left, top);
@@ -44916,27 +44781,162 @@ class ImageItem extends BaseItem {
44916
44781
  new Point(mbr.right, mbr.top + height2 / 2)
44917
44782
  ];
44918
44783
  }
44784
+ getLines() {
44785
+ return this.lines;
44786
+ }
44919
44787
  isClosed() {
44920
44788
  return true;
44921
44789
  }
44922
- getRichText() {
44923
- return null;
44790
+ isEnclosedOrCrossedBy(rect) {
44791
+ for (const line of this.lines) {
44792
+ if (line.isEnclosedOrCrossedBy(rect)) {
44793
+ return true;
44794
+ }
44795
+ }
44796
+ return false;
44797
+ }
44798
+ emit(operation) {
44799
+ if (this.events) {
44800
+ const command = new DrawingCommand([this], operation);
44801
+ command.apply();
44802
+ this.events.emit(operation, command);
44803
+ } else {
44804
+ this.apply(operation);
44805
+ }
44806
+ }
44807
+ apply(op) {
44808
+ switch (op.class) {
44809
+ case "Drawing":
44810
+ switch (op.method) {
44811
+ case "setStrokeColor":
44812
+ this.borderColor = op.color;
44813
+ break;
44814
+ case "setStrokeWidth":
44815
+ this.strokeWidth = op.width;
44816
+ this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
44817
+ break;
44818
+ case "setStrokeOpacity":
44819
+ this.borderOpacity = op.opacity;
44820
+ break;
44821
+ case "setStrokeStyle":
44822
+ this.borderStyle = op.style;
44823
+ this.linePattern = scalePatterns(this.strokeWidth)[this.borderStyle];
44824
+ break;
44825
+ }
44826
+ this.updateMbr();
44827
+ break;
44828
+ case "Transformation":
44829
+ this.transformation.apply(op);
44830
+ break;
44831
+ case "LinkTo":
44832
+ this.linkTo.apply(op);
44833
+ break;
44834
+ default:
44835
+ return;
44836
+ }
44837
+ this.subject.publish(this);
44838
+ }
44839
+ setStrokeOpacity(opacity) {
44840
+ this.emit({
44841
+ class: "Drawing",
44842
+ method: "setStrokeOpacity",
44843
+ item: [this.id],
44844
+ opacity
44845
+ });
44846
+ return this;
44847
+ }
44848
+ getStrokeOpacity() {
44849
+ return this.borderOpacity;
44850
+ }
44851
+ setBorderStyle(style2) {
44852
+ this.emit({
44853
+ class: "Drawing",
44854
+ method: "setStrokeStyle",
44855
+ item: [this.id],
44856
+ style: style2
44857
+ });
44858
+ return this;
44859
+ }
44860
+ getBorderStyle() {
44861
+ return this.borderStyle;
44862
+ }
44863
+ setStrokeColor(color2) {
44864
+ this.emit({
44865
+ class: "Drawing",
44866
+ method: "setStrokeColor",
44867
+ item: [this.id],
44868
+ color: color2
44869
+ });
44870
+ return this;
44871
+ }
44872
+ getStrokeColor() {
44873
+ return this.borderColor;
44874
+ }
44875
+ setStrokeWidth(width2) {
44876
+ this.emit({
44877
+ class: "Drawing",
44878
+ method: "setStrokeWidth",
44879
+ item: [this.id],
44880
+ width: width2,
44881
+ prevWidth: this.strokeWidth
44882
+ });
44883
+ return this;
44924
44884
  }
44925
44885
  getLinkTo() {
44926
44886
  return this.linkTo.link;
44927
44887
  }
44928
- download() {
44929
- const linkElem = document.createElement("a");
44930
- linkElem.href = this.storageLink;
44931
- linkElem.setAttribute("download", "");
44932
- linkElem.click();
44888
+ getStrokeWidth() {
44889
+ return this.strokeWidth;
44933
44890
  }
44934
- onRemove() {
44935
- const storageId = this.getStorageId();
44936
- if (storageId) {
44937
- conf.hooks.beforeMediaRemove([storageId], this.board.getBoardId());
44891
+ getRichText() {
44892
+ return null;
44893
+ }
44894
+ isPointNearLine(point5, threshold = 10) {
44895
+ const transformedMouseX = (point5.x - this.transformation.matrix.translateX) / this.transformation.matrix.scaleX;
44896
+ const transformedMouseY = (point5.y - this.transformation.matrix.translateY) / this.transformation.matrix.scaleY;
44897
+ const transformedMouse = new Point(transformedMouseX, transformedMouseY);
44898
+ for (let i = 0;i < this.points.length - 1; i++) {
44899
+ const p1 = this.points[i];
44900
+ const p22 = this.points[i + 1];
44901
+ const distance = getPerpendicularDistance(transformedMouse, p1, p22);
44902
+ if (distance < threshold) {
44903
+ return true;
44904
+ }
44938
44905
  }
44939
- super.onRemove();
44906
+ return false;
44907
+ }
44908
+ }
44909
+ function getPerpendicularDistance(point5, lineStart, lineEnd) {
44910
+ const { x: px, y: py } = point5;
44911
+ const { x: sx, y: sy } = lineStart;
44912
+ const { x: ex, y: ey } = lineEnd;
44913
+ const numerator = Math.abs((ey - sy) * px - (ex - sx) * py + ex * sy - ey * sx);
44914
+ const denominator = Math.sqrt(Math.pow(ey - sy, 2) + Math.pow(ex - sx, 2));
44915
+ return numerator / denominator;
44916
+ }
44917
+ function douglasPeucker(points, epsilon2) {
44918
+ if (points.length < 3) {
44919
+ return points;
44920
+ }
44921
+ const start = points[0];
44922
+ const end = points[points.length - 1];
44923
+ let maxDistance = 0;
44924
+ let maxIndex = 0;
44925
+ for (let i = 1;i < points.length - 1; i++) {
44926
+ const distance = getPerpendicularDistance(points[i], start, end);
44927
+ if (distance > maxDistance) {
44928
+ maxDistance = distance;
44929
+ maxIndex = i;
44930
+ }
44931
+ }
44932
+ if (maxDistance > epsilon2) {
44933
+ const leftSubPoints = points.slice(0, maxIndex + 1);
44934
+ const rightSubPoints = points.slice(maxIndex);
44935
+ const leftRecursiveResult = douglasPeucker(leftSubPoints, epsilon2);
44936
+ const rightRecursiveResult = douglasPeucker(rightSubPoints, epsilon2);
44937
+ return leftRecursiveResult.slice(0, -1).concat(rightRecursiveResult);
44938
+ } else {
44939
+ return [start, end];
44940
44940
  }
44941
44941
  }
44942
44942
  // src/Items/Group/Group.ts