@leapfrog/interactive-canvas 2.0.25-beta-12 → 2.0.25-beta-13

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.
@@ -340,7 +340,6 @@ export declare abstract class AbstractInteractiveCanvas implements IInteractiveC
340
340
  * @inheritDoc
341
341
  */
342
342
  cloneObject(sourceObject: FabricObject, objectData: CanvasObjectData): Promise<void>;
343
- private redrawScheduled;
344
343
  /**
345
344
  * Redraw the canvas.
346
345
  */
@@ -232,15 +232,9 @@ class ResizeCanvasLayoutFunction {
232
232
  const targetHeight = increase.withSize(increase.width, baseDimensions.height + increase.height);
233
233
  if (currentDimensions.height !== targetHeight.height) {
234
234
  canvas.setDimensions(targetHeight);
235
- canvas.getObjectsInternal().forEach((object) => {
236
- var _a;
237
- const canvasObj = canvas.getObjectsByTypeInternal(object.type).find(o => o.getId() === object.getId());
238
- if (canvasObj && (((_a = canvasObj.isPinToBottom) === null || _a === void 0 ? void 0 : _a.call(canvasObj)) || object.top > currentDimensions.heightPx * 0.5)) {
239
- object.setCoords();
240
- }
241
- });
242
- canvas.redraw();
243
235
  }
236
+ canvas.getObjectsInternal().forEach((object) => object.setCoords());
237
+ canvas.redraw();
244
238
  }
245
239
  }
246
240
 
@@ -268,21 +262,13 @@ class AdvancedLayoutManager extends AbstractLayoutManager {
268
262
  this.repositionCutoffs = new RepositionCutoffsLayoutFunction();
269
263
  this.repositionBackgrounds = new RepositionBackgroundsLayoutFunction();
270
264
  this.resizeCanvas = new ResizeCanvasLayoutFunction();
271
- this.dimensionsLayoutScheduled = false;
272
265
  }
273
266
  onCanvasDimensionsChange() {
274
- if (this.dimensionsLayoutScheduled) {
275
- return;
276
- }
277
- this.dimensionsLayoutScheduled = true;
278
- Promise.resolve().then(() => {
279
- this.pinToBottom.execute(this.canvas);
280
- this.repositionCutoffs.execute(this.canvas);
281
- this.repositionBorders.execute(this.canvas);
282
- this.repositionBackgrounds.execute(this.canvas);
283
- this.redrawAll.execute(this.canvas);
284
- this.dimensionsLayoutScheduled = false;
285
- });
267
+ this.pinToBottom.execute(this.canvas);
268
+ this.repositionCutoffs.execute(this.canvas);
269
+ this.repositionBorders.execute(this.canvas);
270
+ this.repositionBackgrounds.execute(this.canvas);
271
+ this.redrawAll.execute(this.canvas);
286
272
  }
287
273
  onTextChange() {
288
274
  this.resizeCanvas.execute(this.canvas);
@@ -310,7 +296,7 @@ class StackObjectsLayoutFunction {
310
296
  const footerObjects = objects[0];
311
297
  const bodyObjects = objects[1];
312
298
  const bodyWidth = canvasDimensions.widthPx - canvasMargin.right - canvasMargin.left;
313
- // canvas.redraw();
299
+ canvas.redraw();
314
300
  //Make one pass and set the widths of all elements. This will force objects with dynamic heights (like text) to take on their necessary height before trying to lay them out.
315
301
  this.applyWidths(allObjects, bodyWidth);
316
302
  const bodyRows = this.getRows(bodyObjects);
@@ -397,12 +383,7 @@ class StackObjectsLayoutFunction {
397
383
  object.setPosition({
398
384
  width: actualWidth
399
385
  });
400
- //object.updateDimensions();
401
- _(objects).forEach((object) => {
402
- if (object.getType() !== ObjectType.VERTICAL_RULE) {
403
- object.updateDimensions();
404
- }
405
- });
386
+ object.updateDimensions();
406
387
  });
407
388
  }
408
389
  adjustCanvasSize(canvas, requiredHeight) {
@@ -475,7 +456,6 @@ class StandardLayoutManager extends AbstractLayoutManager {
475
456
  this.repositionBackgrounds = new RepositionBackgroundsLayoutFunction();
476
457
  this.stackObjects = new StackObjectsLayoutFunction();
477
458
  this.updateObjectDimensions = new UpdateObjectDimensionsLayoutFunction();
478
- this.layoutBatchScheduled = false;
479
459
  }
480
460
  /**
481
461
  * @override
@@ -517,19 +497,12 @@ class StandardLayoutManager extends AbstractLayoutManager {
517
497
  this.stackAndRedraw();
518
498
  }
519
499
  stackAndRedraw() {
520
- if (this.layoutBatchScheduled) {
521
- return;
522
- }
523
- this.layoutBatchScheduled = true;
524
- Promise.resolve().then(() => {
525
- this.stackObjects.execute(this.canvas);
526
- this.repositionCutoffs.execute(this.canvas);
527
- this.repositionBorders.execute(this.canvas);
528
- this.repositionBackgrounds.execute(this.canvas);
529
- this.updateObjectDimensions.execute(this.canvas);
530
- this.redrawAll.execute(this.canvas);
531
- this.layoutBatchScheduled = false;
532
- });
500
+ this.stackObjects.execute(this.canvas);
501
+ this.repositionCutoffs.execute(this.canvas);
502
+ this.repositionBorders.execute(this.canvas);
503
+ this.repositionBackgrounds.execute(this.canvas);
504
+ this.updateObjectDimensions.execute(this.canvas);
505
+ this.redrawAll.execute(this.canvas);
533
506
  }
534
507
  }
535
508
 
@@ -1807,43 +1780,15 @@ var ObjectType;
1807
1780
  class Text extends AbstractCanvasObject {
1808
1781
  constructor(canvas, fabricObject, persistedField) {
1809
1782
  super(ObjectType.TEXT, canvas, fabricObject, persistedField);
1810
- this.notifyCanvasTimeout = null;
1811
- this.NOTIFY_DELAY_MS = 150;
1812
1783
  this.canvas = canvas;
1813
1784
  this.fontLibrary = canvas.getFontLibrary();
1814
1785
  this.baseComponentHeight = this.fabricObject.height;
1815
1786
  this.text$ = new BehaviorSubject(this.fabricObject.text);
1816
1787
  this.data.userText = this.fabricObject.text;
1817
1788
  this.textSelection$ = new BehaviorSubject(new TextSelection(this.fabricObject, this.fontLibrary));
1818
- //this.fabricObject.set({strokeWidth: 0});
1819
- this.fabricObject.set({
1820
- strokeWidth: 0,
1821
- perPixelTargetFind: false // Disable per-pixel detection for this object
1822
- });
1789
+ this.fabricObject.set({ strokeWidth: 0 });
1823
1790
  this.fabricObject.on("changed", () => this.onTextChange());
1824
1791
  this.fabricObject.on("selection:changed", () => this.onSelectionChange());
1825
- this.fabricObject.containsPoint.bind(this.fabricObject);
1826
- this.fabricObject.containsPoint = function (point) {
1827
- const coords = this.getCoords();
1828
- if (coords.length !== 4)
1829
- return false;
1830
- let inside = false;
1831
- for (let i = 0, j = coords.length - 1; i < coords.length; j = i++) {
1832
- const xi = coords[i].x, yi = coords[i].y;
1833
- const xj = coords[j].x, yj = coords[j].y;
1834
- const intersect = ((yi > point.y) !== (yj > point.y))
1835
- && (point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi);
1836
- if (intersect)
1837
- inside = !inside;
1838
- }
1839
- return inside;
1840
- };
1841
- this.fabricObject.on("mousedown", (e) => {
1842
- var _a;
1843
- if (!this.fabricObject.isEditing) {
1844
- (_a = e.e) === null || _a === void 0 ? void 0 : _a.preventDefault();
1845
- }
1846
- });
1847
1792
  this.applyBulletListMonkeyPatches();
1848
1793
  }
1849
1794
  /**
@@ -2192,87 +2137,27 @@ class Text extends AbstractCanvasObject {
2192
2137
  * @override
2193
2138
  * @inheritDoc
2194
2139
  */
2195
- /*public getBulletMargin(): number {
2196
- if (!this.isBulleted()) return 0;
2197
-
2140
+ getBulletMargin() {
2141
+ if (!this.isBulleted())
2142
+ return 0;
2198
2143
  let fontSize = 0;
2199
- each(this.fabricObject._textLines, (textLine: string[], lineIndex: number) => {
2144
+ each(this.fabricObject._textLines, (textLine, lineIndex) => {
2200
2145
  fontSize = Math.max(fontSize, this.fabricObject.getValueOfPropertyAt(lineIndex, 0, "fontSize"));
2201
2146
  });
2202
-
2203
2147
  return fontSize * 0.6;
2204
- }*/
2205
- getBulletMargin() {
2206
- if (!this.isBulleted())
2207
- return 0;
2208
- try {
2209
- let fontSize = 0;
2210
- each(this.fabricObject._textLines, (textLine, lineIndex) => {
2211
- const size = this.fabricObject.getValueOfPropertyAt(lineIndex, 0, "fontSize");
2212
- // Sanity check fontSize
2213
- if (isFinite(size) && size > 0 && size < 1000) {
2214
- fontSize = Math.max(fontSize, size);
2215
- }
2216
- });
2217
- // Additional safety check
2218
- if (!isFinite(fontSize) || fontSize < 0 || fontSize > 1000) {
2219
- return 0;
2220
- }
2221
- return fontSize * 0.6;
2222
- }
2223
- catch (e) {
2224
- console.warn('Error calculating bullet margin:', e);
2225
- return 0;
2226
- }
2227
2148
  }
2228
2149
  /**
2229
2150
  * @override
2230
2151
  * @inheritDoc
2231
2152
  */
2232
- /*public getOrderedListMargin(): number {
2233
- if (!this.isOrderedList()) return 0;
2234
-
2235
- const orderedListMarkerEntities = this.fabricObject._orderedListMarkerEntities;
2236
- let maxValue = max(
2237
- (orderedListMarkerEntities ?? [])
2238
- .filter((x: Textbox) => !!x)
2239
- .map((x: fabric.Textbox) => x.getBoundingRect().width)
2240
- );
2241
- return maxValue ? (maxValue * 1.2) : 0;
2242
- }*/
2243
2153
  getOrderedListMargin() {
2244
2154
  if (!this.isOrderedList())
2245
2155
  return 0;
2246
2156
  const orderedListMarkerEntities = this.fabricObject._orderedListMarkerEntities;
2247
- try {
2248
- const widths = (orderedListMarkerEntities !== null && orderedListMarkerEntities !== void 0 ? orderedListMarkerEntities : [])
2249
- .filter((x) => !!x)
2250
- .map((x) => {
2251
- var _a;
2252
- try {
2253
- const rect = x.getBoundingRect();
2254
- const width = (_a = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _a !== void 0 ? _a : 0;
2255
- // Sanity check: if width is invalid, return 0
2256
- if (!isFinite(width) || width < 0 || width > 1000) {
2257
- return 0;
2258
- }
2259
- return width;
2260
- }
2261
- catch (e) {
2262
- return 0;
2263
- }
2264
- });
2265
- const maxValue = max(widths);
2266
- // Additional safety: ensure maxValue is a valid number
2267
- if (!maxValue || !isFinite(maxValue) || maxValue < 0 || maxValue > 1000) {
2268
- return 0;
2269
- }
2270
- return maxValue * 1.2;
2271
- }
2272
- catch (e) {
2273
- console.warn('Error calculating ordered list margin:', e);
2274
- return 0;
2275
- }
2157
+ let maxValue = max((orderedListMarkerEntities !== null && orderedListMarkerEntities !== void 0 ? orderedListMarkerEntities : [])
2158
+ .filter((x) => !!x)
2159
+ .map((x) => x.getBoundingRect().width));
2160
+ return maxValue ? (maxValue * 1.2) : 0;
2276
2161
  }
2277
2162
  /**
2278
2163
  * @override
@@ -2607,10 +2492,7 @@ class Text extends AbstractCanvasObject {
2607
2492
  text: `${lineNumber}.`
2608
2493
  });
2609
2494
  }
2610
- /* if (method === "fillText" && this.fabricObject.left <= 3) {
2611
- left = left + this.getOrderedListMargin();
2612
- }*/
2613
- if (method === "fillText" && this.isOrderedList() && this.fabricObject.left <= 3) {
2495
+ if (method === "fillText" && this.fabricObject.left <= 3) {
2614
2496
  left = left + this.getOrderedListMargin();
2615
2497
  }
2616
2498
  this.fabricObject.dirty = true;
@@ -2626,16 +2508,9 @@ class Text extends AbstractCanvasObject {
2626
2508
  const profile = this.canvas.getProfile();
2627
2509
  const allowManualPositioning = !this.canvas.getLayoutManager().isEnforcedPositioning;
2628
2510
  this.fabricObject.set({
2629
- lockMovementX: false,
2630
- lockMovementY: false,
2631
2511
  lockScalingY: true,
2632
2512
  lockScalingX: this.isPinToBottom(),
2633
- lockScalingFlip: true,
2634
- lockRotation: true,
2635
- selectable: true,
2636
- editable: false, // Only enable on double-click
2637
- hoverCursor: "move", // Show move cursor by default
2638
- moveCursor: "move",
2513
+ lockScalingFlip: true
2639
2514
  });
2640
2515
  this.fabricObject.setControlsVisibility({
2641
2516
  tl: false,
@@ -2645,49 +2520,35 @@ class Text extends AbstractCanvasObject {
2645
2520
  ml: allowManualPositioning && profile.allowScale && !this.isPinToBottom(),
2646
2521
  mt: false,
2647
2522
  mr: allowManualPositioning && profile.allowScale && !this.isPinToBottom(),
2648
- mb: false,
2649
- mtr: false
2523
+ mb: false
2650
2524
  });
2651
2525
  this.redraw();
2652
2526
  }
2653
2527
  onTextChange() {
2654
2528
  this.data.userText = this.fabricObject.text;
2655
2529
  this.text$.next(this.fabricObject.text);
2656
- const currentLeft = this.fabricObject.left || 0;
2657
- const canvasWidth = this.canvas.getDimensions().widthPx;
2658
- // Skip expensive getBoundingBox if object is clearly within bounds
2659
- if (currentLeft + (this.fabricObject.width || 0) > canvasWidth * 0.9) {
2660
- if (this.getBoundingBox().width > canvasWidth) {
2661
- this.fabricObject.set({ left: 0, width: canvasWidth });
2662
- this.redraw();
2663
- }
2530
+ if (this.getBoundingBox().width > this.canvas.getDimensions().widthPx) {
2531
+ this.fabricObject.set({ left: 0, width: this.canvas.getDimensions().widthPx });
2532
+ this.redraw();
2664
2533
  }
2665
2534
  }
2666
2535
  onDelete() {
2667
2536
  this.removeBullets();
2668
2537
  }
2669
2538
  onSelectionChange() {
2670
- this.updateTextSelection(false);
2539
+ this.updateTextSelection();
2671
2540
  }
2672
2541
  hasTextSelection() {
2673
2542
  return this.canvas.getSelection().isText && this.textSelection$.value.length > 0;
2674
2543
  }
2675
- updateTextSelection(notifyCanvas = true) {
2544
+ updateTextSelection() {
2676
2545
  if (this.canvas.headless)
2677
2546
  return;
2678
2547
  this.textSelection$.next(new TextSelection(this.fabricObject, this.fontLibrary));
2679
- if (notifyCanvas) {
2680
- this.notifyCanvasOfTextChanges();
2681
- }
2548
+ this.notifyCanvasOfTextChanges();
2682
2549
  }
2683
2550
  notifyCanvasOfTextChanges() {
2684
- if (this.notifyCanvasTimeout) {
2685
- clearTimeout(this.notifyCanvasTimeout);
2686
- }
2687
- this.notifyCanvasTimeout = setTimeout(() => {
2688
- this.canvas.notifyTextChanged();
2689
- this.notifyCanvasTimeout = null;
2690
- }, this.NOTIFY_DELAY_MS);
2551
+ this.canvas.notifyTextChanged();
2691
2552
  }
2692
2553
  }
2693
2554
  Text.NEW_LINE = "\n";
@@ -2853,7 +2714,6 @@ class AbstractInteractiveCanvas {
2853
2714
  this.devicePixelRatio = devicePixelRatio;
2854
2715
  this.fontLibrary = new FontLibrary();
2855
2716
  this.dimensionChangeRejections$ = new Subject();
2856
- this.redrawScheduled = false;
2857
2717
  this.IMAGE_CAPTURE_COEFFICIENT = this.calculateImageCaptureCoefficient();
2858
2718
  /**
2859
2719
  * Fabric defaults to only 2 decimal places when saving, which causes havoc on the scaling of large images.
@@ -3272,7 +3132,6 @@ class AbstractInteractiveCanvas {
3272
3132
  targetFindTolerance: 4,
3273
3133
  splitByGrapheme: true,
3274
3134
  editable: false, // Only enable on double-click
3275
- editingBorderColor: '#2196F3',
3276
3135
  padding: 0,
3277
3136
  cornerSize: 8,
3278
3137
  touchCornerSize: 12
@@ -3724,14 +3583,7 @@ class AbstractInteractiveCanvas {
3724
3583
  * Redraw the canvas.
3725
3584
  */
3726
3585
  redraw() {
3727
- if (this.redrawScheduled) {
3728
- return;
3729
- }
3730
- this.redrawScheduled = true;
3731
- requestAnimationFrame(() => {
3732
- this.fabricCanvas.requestRenderAll();
3733
- this.redrawScheduled = false;
3734
- });
3586
+ this.fabricCanvas.requestRenderAll();
3735
3587
  }
3736
3588
  syncObjectList() {
3737
3589
  const newObjectList = _(this.fabricCanvas.getObjects())
@@ -3857,7 +3709,7 @@ class AbstractInteractiveCanvas {
3857
3709
  * Update the actual dimensions of the canvas by multiplying the requested dimensions by the current zoom factor.
3858
3710
  */
3859
3711
  updateCanvasDimensions(dims, zoom) {
3860
- const oldWidth = this.fabricCanvas.getWidth();
3712
+ this.fabricCanvas.getWidth();
3861
3713
  const width = dims.widthPx * zoom;
3862
3714
  const height = dims.heightPx * zoom;
3863
3715
  this.fabricCanvas.setZoom(zoom);
@@ -3865,34 +3717,37 @@ class AbstractInteractiveCanvas {
3865
3717
  width,
3866
3718
  height
3867
3719
  });
3868
- const scaleFactor = width / oldWidth;
3869
- const objects = this.fabricCanvas.getObjects();
3870
- objects.forEach((obj) => {
3871
- obj.set({
3872
- left: obj.left * scaleFactor,
3873
- });
3874
- if (obj.type === "textbox" || obj.type === "text") {
3875
- obj.set({
3876
- scaleX: 1,
3877
- scaleY: 1,
3878
- width: obj.width * scaleFactor,
3879
- });
3880
- }
3881
- else if (obj.type === "border" || obj.type === "rect") {
3882
- obj.set({
3883
- width: obj.width * scaleFactor,
3884
- scaleX: 1,
3885
- strokeUniform: true,
3886
- });
3887
- }
3888
- else {
3889
- obj.set({
3890
- scaleX: obj.scaleX * scaleFactor,
3891
- });
3892
- }
3893
- obj.setCoords();
3894
- });
3895
- this.fabricCanvas.requestRenderAll();
3720
+ /* if (this.layoutManager$.value instanceof AdvancedLayoutManager) {
3721
+ const scaleFactor = width / oldWidth;
3722
+ this.fabricCanvas.calcOffset();
3723
+ const objects = this.fabricCanvas.getObjects();
3724
+ objects.forEach((obj: any) => {
3725
+ obj.set({
3726
+ left: obj.left * scaleFactor,
3727
+ });
3728
+ if (obj.type === "textbox" || obj.type === "text") {
3729
+ obj.set({
3730
+ scaleX: 1,
3731
+ scaleY: 1,
3732
+ width: obj.width * scaleFactor,
3733
+ });
3734
+ obj.initDimensions();
3735
+ } else if (obj.type === "border" || obj.type === "rect") {
3736
+ obj.set({
3737
+ width: obj.width * scaleFactor,
3738
+ scaleX: 1,
3739
+ strokeUniform: true,
3740
+ strokeAlign: "inner",
3741
+ });
3742
+ } else {
3743
+ obj.set({
3744
+ scaleX: obj.scaleX * scaleFactor,
3745
+ });
3746
+ }
3747
+ obj.setCoords();
3748
+ });
3749
+ this.fabricCanvas.requestRenderAll();
3750
+ }*/
3896
3751
  }
3897
3752
  onProfileChanged(profile) {
3898
3753
  this.setMultiSelect(profile.allowMultiSelect);
@@ -4047,7 +3902,7 @@ class InteractiveCanvas extends AbstractInteractiveCanvas {
4047
3902
  this.fabricCanvas.on("selection:created", (event) => this.onFabricSelectionChanged(event));
4048
3903
  this.fabricCanvas.on("selection:cleared", (event) => this.onFabricSelectionChanged(event));
4049
3904
  this.fabricCanvas.on("text:editing:entered", () => this.onTextEditing());
4050
- //this.fabricCanvas.on("text:editing:exited", () => this.onTextEditing());
3905
+ this.fabricCanvas.on("text:editing:exited", () => this.onTextEditing());
4051
3906
  this.fabricCanvas.on("text:editing:exited", (event) => {
4052
3907
  this.onTextEditing();
4053
3908
  const target = event.target;
@@ -253,15 +253,9 @@ class ResizeCanvasLayoutFunction {
253
253
  const targetHeight = increase.withSize(increase.width, baseDimensions.height + increase.height);
254
254
  if (currentDimensions.height !== targetHeight.height) {
255
255
  canvas.setDimensions(targetHeight);
256
- canvas.getObjectsInternal().forEach((object) => {
257
- var _a;
258
- const canvasObj = canvas.getObjectsByTypeInternal(object.type).find(o => o.getId() === object.getId());
259
- if (canvasObj && (((_a = canvasObj.isPinToBottom) === null || _a === void 0 ? void 0 : _a.call(canvasObj)) || object.top > currentDimensions.heightPx * 0.5)) {
260
- object.setCoords();
261
- }
262
- });
263
- canvas.redraw();
264
256
  }
257
+ canvas.getObjectsInternal().forEach((object) => object.setCoords());
258
+ canvas.redraw();
265
259
  }
266
260
  }
267
261
 
@@ -289,21 +283,13 @@ class AdvancedLayoutManager extends AbstractLayoutManager {
289
283
  this.repositionCutoffs = new RepositionCutoffsLayoutFunction();
290
284
  this.repositionBackgrounds = new RepositionBackgroundsLayoutFunction();
291
285
  this.resizeCanvas = new ResizeCanvasLayoutFunction();
292
- this.dimensionsLayoutScheduled = false;
293
286
  }
294
287
  onCanvasDimensionsChange() {
295
- if (this.dimensionsLayoutScheduled) {
296
- return;
297
- }
298
- this.dimensionsLayoutScheduled = true;
299
- Promise.resolve().then(() => {
300
- this.pinToBottom.execute(this.canvas);
301
- this.repositionCutoffs.execute(this.canvas);
302
- this.repositionBorders.execute(this.canvas);
303
- this.repositionBackgrounds.execute(this.canvas);
304
- this.redrawAll.execute(this.canvas);
305
- this.dimensionsLayoutScheduled = false;
306
- });
288
+ this.pinToBottom.execute(this.canvas);
289
+ this.repositionCutoffs.execute(this.canvas);
290
+ this.repositionBorders.execute(this.canvas);
291
+ this.repositionBackgrounds.execute(this.canvas);
292
+ this.redrawAll.execute(this.canvas);
307
293
  }
308
294
  onTextChange() {
309
295
  this.resizeCanvas.execute(this.canvas);
@@ -331,7 +317,7 @@ class StackObjectsLayoutFunction {
331
317
  const footerObjects = objects[0];
332
318
  const bodyObjects = objects[1];
333
319
  const bodyWidth = canvasDimensions.widthPx - canvasMargin.right - canvasMargin.left;
334
- // canvas.redraw();
320
+ canvas.redraw();
335
321
  //Make one pass and set the widths of all elements. This will force objects with dynamic heights (like text) to take on their necessary height before trying to lay them out.
336
322
  this.applyWidths(allObjects, bodyWidth);
337
323
  const bodyRows = this.getRows(bodyObjects);
@@ -418,12 +404,7 @@ class StackObjectsLayoutFunction {
418
404
  object.setPosition({
419
405
  width: actualWidth
420
406
  });
421
- //object.updateDimensions();
422
- _(objects).forEach((object) => {
423
- if (object.getType() !== exports.ObjectType.VERTICAL_RULE) {
424
- object.updateDimensions();
425
- }
426
- });
407
+ object.updateDimensions();
427
408
  });
428
409
  }
429
410
  adjustCanvasSize(canvas, requiredHeight) {
@@ -496,7 +477,6 @@ class StandardLayoutManager extends AbstractLayoutManager {
496
477
  this.repositionBackgrounds = new RepositionBackgroundsLayoutFunction();
497
478
  this.stackObjects = new StackObjectsLayoutFunction();
498
479
  this.updateObjectDimensions = new UpdateObjectDimensionsLayoutFunction();
499
- this.layoutBatchScheduled = false;
500
480
  }
501
481
  /**
502
482
  * @override
@@ -538,19 +518,12 @@ class StandardLayoutManager extends AbstractLayoutManager {
538
518
  this.stackAndRedraw();
539
519
  }
540
520
  stackAndRedraw() {
541
- if (this.layoutBatchScheduled) {
542
- return;
543
- }
544
- this.layoutBatchScheduled = true;
545
- Promise.resolve().then(() => {
546
- this.stackObjects.execute(this.canvas);
547
- this.repositionCutoffs.execute(this.canvas);
548
- this.repositionBorders.execute(this.canvas);
549
- this.repositionBackgrounds.execute(this.canvas);
550
- this.updateObjectDimensions.execute(this.canvas);
551
- this.redrawAll.execute(this.canvas);
552
- this.layoutBatchScheduled = false;
553
- });
521
+ this.stackObjects.execute(this.canvas);
522
+ this.repositionCutoffs.execute(this.canvas);
523
+ this.repositionBorders.execute(this.canvas);
524
+ this.repositionBackgrounds.execute(this.canvas);
525
+ this.updateObjectDimensions.execute(this.canvas);
526
+ this.redrawAll.execute(this.canvas);
554
527
  }
555
528
  }
556
529
 
@@ -1828,43 +1801,15 @@ exports.ObjectType = void 0;
1828
1801
  class Text extends AbstractCanvasObject {
1829
1802
  constructor(canvas, fabricObject, persistedField) {
1830
1803
  super(exports.ObjectType.TEXT, canvas, fabricObject, persistedField);
1831
- this.notifyCanvasTimeout = null;
1832
- this.NOTIFY_DELAY_MS = 150;
1833
1804
  this.canvas = canvas;
1834
1805
  this.fontLibrary = canvas.getFontLibrary();
1835
1806
  this.baseComponentHeight = this.fabricObject.height;
1836
1807
  this.text$ = new rxjs.BehaviorSubject(this.fabricObject.text);
1837
1808
  this.data.userText = this.fabricObject.text;
1838
1809
  this.textSelection$ = new rxjs.BehaviorSubject(new TextSelection(this.fabricObject, this.fontLibrary));
1839
- //this.fabricObject.set({strokeWidth: 0});
1840
- this.fabricObject.set({
1841
- strokeWidth: 0,
1842
- perPixelTargetFind: false // Disable per-pixel detection for this object
1843
- });
1810
+ this.fabricObject.set({ strokeWidth: 0 });
1844
1811
  this.fabricObject.on("changed", () => this.onTextChange());
1845
1812
  this.fabricObject.on("selection:changed", () => this.onSelectionChange());
1846
- this.fabricObject.containsPoint.bind(this.fabricObject);
1847
- this.fabricObject.containsPoint = function (point) {
1848
- const coords = this.getCoords();
1849
- if (coords.length !== 4)
1850
- return false;
1851
- let inside = false;
1852
- for (let i = 0, j = coords.length - 1; i < coords.length; j = i++) {
1853
- const xi = coords[i].x, yi = coords[i].y;
1854
- const xj = coords[j].x, yj = coords[j].y;
1855
- const intersect = ((yi > point.y) !== (yj > point.y))
1856
- && (point.x < (xj - xi) * (point.y - yi) / (yj - yi) + xi);
1857
- if (intersect)
1858
- inside = !inside;
1859
- }
1860
- return inside;
1861
- };
1862
- this.fabricObject.on("mousedown", (e) => {
1863
- var _a;
1864
- if (!this.fabricObject.isEditing) {
1865
- (_a = e.e) === null || _a === void 0 ? void 0 : _a.preventDefault();
1866
- }
1867
- });
1868
1813
  this.applyBulletListMonkeyPatches();
1869
1814
  }
1870
1815
  /**
@@ -2213,87 +2158,27 @@ class Text extends AbstractCanvasObject {
2213
2158
  * @override
2214
2159
  * @inheritDoc
2215
2160
  */
2216
- /*public getBulletMargin(): number {
2217
- if (!this.isBulleted()) return 0;
2218
-
2161
+ getBulletMargin() {
2162
+ if (!this.isBulleted())
2163
+ return 0;
2219
2164
  let fontSize = 0;
2220
- each(this.fabricObject._textLines, (textLine: string[], lineIndex: number) => {
2165
+ _.each(this.fabricObject._textLines, (textLine, lineIndex) => {
2221
2166
  fontSize = Math.max(fontSize, this.fabricObject.getValueOfPropertyAt(lineIndex, 0, "fontSize"));
2222
2167
  });
2223
-
2224
2168
  return fontSize * 0.6;
2225
- }*/
2226
- getBulletMargin() {
2227
- if (!this.isBulleted())
2228
- return 0;
2229
- try {
2230
- let fontSize = 0;
2231
- _.each(this.fabricObject._textLines, (textLine, lineIndex) => {
2232
- const size = this.fabricObject.getValueOfPropertyAt(lineIndex, 0, "fontSize");
2233
- // Sanity check fontSize
2234
- if (isFinite(size) && size > 0 && size < 1000) {
2235
- fontSize = Math.max(fontSize, size);
2236
- }
2237
- });
2238
- // Additional safety check
2239
- if (!isFinite(fontSize) || fontSize < 0 || fontSize > 1000) {
2240
- return 0;
2241
- }
2242
- return fontSize * 0.6;
2243
- }
2244
- catch (e) {
2245
- console.warn('Error calculating bullet margin:', e);
2246
- return 0;
2247
- }
2248
2169
  }
2249
2170
  /**
2250
2171
  * @override
2251
2172
  * @inheritDoc
2252
2173
  */
2253
- /*public getOrderedListMargin(): number {
2254
- if (!this.isOrderedList()) return 0;
2255
-
2256
- const orderedListMarkerEntities = this.fabricObject._orderedListMarkerEntities;
2257
- let maxValue = max(
2258
- (orderedListMarkerEntities ?? [])
2259
- .filter((x: Textbox) => !!x)
2260
- .map((x: fabric.Textbox) => x.getBoundingRect().width)
2261
- );
2262
- return maxValue ? (maxValue * 1.2) : 0;
2263
- }*/
2264
2174
  getOrderedListMargin() {
2265
2175
  if (!this.isOrderedList())
2266
2176
  return 0;
2267
2177
  const orderedListMarkerEntities = this.fabricObject._orderedListMarkerEntities;
2268
- try {
2269
- const widths = (orderedListMarkerEntities !== null && orderedListMarkerEntities !== void 0 ? orderedListMarkerEntities : [])
2270
- .filter((x) => !!x)
2271
- .map((x) => {
2272
- var _a;
2273
- try {
2274
- const rect = x.getBoundingRect();
2275
- const width = (_a = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _a !== void 0 ? _a : 0;
2276
- // Sanity check: if width is invalid, return 0
2277
- if (!isFinite(width) || width < 0 || width > 1000) {
2278
- return 0;
2279
- }
2280
- return width;
2281
- }
2282
- catch (e) {
2283
- return 0;
2284
- }
2285
- });
2286
- const maxValue = _.max(widths);
2287
- // Additional safety: ensure maxValue is a valid number
2288
- if (!maxValue || !isFinite(maxValue) || maxValue < 0 || maxValue > 1000) {
2289
- return 0;
2290
- }
2291
- return maxValue * 1.2;
2292
- }
2293
- catch (e) {
2294
- console.warn('Error calculating ordered list margin:', e);
2295
- return 0;
2296
- }
2178
+ let maxValue = _.max((orderedListMarkerEntities !== null && orderedListMarkerEntities !== void 0 ? orderedListMarkerEntities : [])
2179
+ .filter((x) => !!x)
2180
+ .map((x) => x.getBoundingRect().width));
2181
+ return maxValue ? (maxValue * 1.2) : 0;
2297
2182
  }
2298
2183
  /**
2299
2184
  * @override
@@ -2628,10 +2513,7 @@ class Text extends AbstractCanvasObject {
2628
2513
  text: `${lineNumber}.`
2629
2514
  });
2630
2515
  }
2631
- /* if (method === "fillText" && this.fabricObject.left <= 3) {
2632
- left = left + this.getOrderedListMargin();
2633
- }*/
2634
- if (method === "fillText" && this.isOrderedList() && this.fabricObject.left <= 3) {
2516
+ if (method === "fillText" && this.fabricObject.left <= 3) {
2635
2517
  left = left + this.getOrderedListMargin();
2636
2518
  }
2637
2519
  this.fabricObject.dirty = true;
@@ -2647,16 +2529,9 @@ class Text extends AbstractCanvasObject {
2647
2529
  const profile = this.canvas.getProfile();
2648
2530
  const allowManualPositioning = !this.canvas.getLayoutManager().isEnforcedPositioning;
2649
2531
  this.fabricObject.set({
2650
- lockMovementX: false,
2651
- lockMovementY: false,
2652
2532
  lockScalingY: true,
2653
2533
  lockScalingX: this.isPinToBottom(),
2654
- lockScalingFlip: true,
2655
- lockRotation: true,
2656
- selectable: true,
2657
- editable: false, // Only enable on double-click
2658
- hoverCursor: "move", // Show move cursor by default
2659
- moveCursor: "move",
2534
+ lockScalingFlip: true
2660
2535
  });
2661
2536
  this.fabricObject.setControlsVisibility({
2662
2537
  tl: false,
@@ -2666,49 +2541,35 @@ class Text extends AbstractCanvasObject {
2666
2541
  ml: allowManualPositioning && profile.allowScale && !this.isPinToBottom(),
2667
2542
  mt: false,
2668
2543
  mr: allowManualPositioning && profile.allowScale && !this.isPinToBottom(),
2669
- mb: false,
2670
- mtr: false
2544
+ mb: false
2671
2545
  });
2672
2546
  this.redraw();
2673
2547
  }
2674
2548
  onTextChange() {
2675
2549
  this.data.userText = this.fabricObject.text;
2676
2550
  this.text$.next(this.fabricObject.text);
2677
- const currentLeft = this.fabricObject.left || 0;
2678
- const canvasWidth = this.canvas.getDimensions().widthPx;
2679
- // Skip expensive getBoundingBox if object is clearly within bounds
2680
- if (currentLeft + (this.fabricObject.width || 0) > canvasWidth * 0.9) {
2681
- if (this.getBoundingBox().width > canvasWidth) {
2682
- this.fabricObject.set({ left: 0, width: canvasWidth });
2683
- this.redraw();
2684
- }
2551
+ if (this.getBoundingBox().width > this.canvas.getDimensions().widthPx) {
2552
+ this.fabricObject.set({ left: 0, width: this.canvas.getDimensions().widthPx });
2553
+ this.redraw();
2685
2554
  }
2686
2555
  }
2687
2556
  onDelete() {
2688
2557
  this.removeBullets();
2689
2558
  }
2690
2559
  onSelectionChange() {
2691
- this.updateTextSelection(false);
2560
+ this.updateTextSelection();
2692
2561
  }
2693
2562
  hasTextSelection() {
2694
2563
  return this.canvas.getSelection().isText && this.textSelection$.value.length > 0;
2695
2564
  }
2696
- updateTextSelection(notifyCanvas = true) {
2565
+ updateTextSelection() {
2697
2566
  if (this.canvas.headless)
2698
2567
  return;
2699
2568
  this.textSelection$.next(new TextSelection(this.fabricObject, this.fontLibrary));
2700
- if (notifyCanvas) {
2701
- this.notifyCanvasOfTextChanges();
2702
- }
2569
+ this.notifyCanvasOfTextChanges();
2703
2570
  }
2704
2571
  notifyCanvasOfTextChanges() {
2705
- if (this.notifyCanvasTimeout) {
2706
- clearTimeout(this.notifyCanvasTimeout);
2707
- }
2708
- this.notifyCanvasTimeout = setTimeout(() => {
2709
- this.canvas.notifyTextChanged();
2710
- this.notifyCanvasTimeout = null;
2711
- }, this.NOTIFY_DELAY_MS);
2572
+ this.canvas.notifyTextChanged();
2712
2573
  }
2713
2574
  }
2714
2575
  Text.NEW_LINE = "\n";
@@ -2874,7 +2735,6 @@ class AbstractInteractiveCanvas {
2874
2735
  this.devicePixelRatio = devicePixelRatio;
2875
2736
  this.fontLibrary = new FontLibrary();
2876
2737
  this.dimensionChangeRejections$ = new rxjs.Subject();
2877
- this.redrawScheduled = false;
2878
2738
  this.IMAGE_CAPTURE_COEFFICIENT = this.calculateImageCaptureCoefficient();
2879
2739
  /**
2880
2740
  * Fabric defaults to only 2 decimal places when saving, which causes havoc on the scaling of large images.
@@ -3293,7 +3153,6 @@ class AbstractInteractiveCanvas {
3293
3153
  targetFindTolerance: 4,
3294
3154
  splitByGrapheme: true,
3295
3155
  editable: false, // Only enable on double-click
3296
- editingBorderColor: '#2196F3',
3297
3156
  padding: 0,
3298
3157
  cornerSize: 8,
3299
3158
  touchCornerSize: 12
@@ -3745,14 +3604,7 @@ class AbstractInteractiveCanvas {
3745
3604
  * Redraw the canvas.
3746
3605
  */
3747
3606
  redraw() {
3748
- if (this.redrawScheduled) {
3749
- return;
3750
- }
3751
- this.redrawScheduled = true;
3752
- requestAnimationFrame(() => {
3753
- this.fabricCanvas.requestRenderAll();
3754
- this.redrawScheduled = false;
3755
- });
3607
+ this.fabricCanvas.requestRenderAll();
3756
3608
  }
3757
3609
  syncObjectList() {
3758
3610
  const newObjectList = _(this.fabricCanvas.getObjects())
@@ -3878,7 +3730,7 @@ class AbstractInteractiveCanvas {
3878
3730
  * Update the actual dimensions of the canvas by multiplying the requested dimensions by the current zoom factor.
3879
3731
  */
3880
3732
  updateCanvasDimensions(dims, zoom) {
3881
- const oldWidth = this.fabricCanvas.getWidth();
3733
+ this.fabricCanvas.getWidth();
3882
3734
  const width = dims.widthPx * zoom;
3883
3735
  const height = dims.heightPx * zoom;
3884
3736
  this.fabricCanvas.setZoom(zoom);
@@ -3886,34 +3738,37 @@ class AbstractInteractiveCanvas {
3886
3738
  width,
3887
3739
  height
3888
3740
  });
3889
- const scaleFactor = width / oldWidth;
3890
- const objects = this.fabricCanvas.getObjects();
3891
- objects.forEach((obj) => {
3892
- obj.set({
3893
- left: obj.left * scaleFactor,
3894
- });
3895
- if (obj.type === "textbox" || obj.type === "text") {
3896
- obj.set({
3897
- scaleX: 1,
3898
- scaleY: 1,
3899
- width: obj.width * scaleFactor,
3900
- });
3901
- }
3902
- else if (obj.type === "border" || obj.type === "rect") {
3903
- obj.set({
3904
- width: obj.width * scaleFactor,
3905
- scaleX: 1,
3906
- strokeUniform: true,
3907
- });
3908
- }
3909
- else {
3910
- obj.set({
3911
- scaleX: obj.scaleX * scaleFactor,
3912
- });
3913
- }
3914
- obj.setCoords();
3915
- });
3916
- this.fabricCanvas.requestRenderAll();
3741
+ /* if (this.layoutManager$.value instanceof AdvancedLayoutManager) {
3742
+ const scaleFactor = width / oldWidth;
3743
+ this.fabricCanvas.calcOffset();
3744
+ const objects = this.fabricCanvas.getObjects();
3745
+ objects.forEach((obj: any) => {
3746
+ obj.set({
3747
+ left: obj.left * scaleFactor,
3748
+ });
3749
+ if (obj.type === "textbox" || obj.type === "text") {
3750
+ obj.set({
3751
+ scaleX: 1,
3752
+ scaleY: 1,
3753
+ width: obj.width * scaleFactor,
3754
+ });
3755
+ obj.initDimensions();
3756
+ } else if (obj.type === "border" || obj.type === "rect") {
3757
+ obj.set({
3758
+ width: obj.width * scaleFactor,
3759
+ scaleX: 1,
3760
+ strokeUniform: true,
3761
+ strokeAlign: "inner",
3762
+ });
3763
+ } else {
3764
+ obj.set({
3765
+ scaleX: obj.scaleX * scaleFactor,
3766
+ });
3767
+ }
3768
+ obj.setCoords();
3769
+ });
3770
+ this.fabricCanvas.requestRenderAll();
3771
+ }*/
3917
3772
  }
3918
3773
  onProfileChanged(profile) {
3919
3774
  this.setMultiSelect(profile.allowMultiSelect);
@@ -4068,7 +3923,7 @@ class InteractiveCanvas extends AbstractInteractiveCanvas {
4068
3923
  this.fabricCanvas.on("selection:created", (event) => this.onFabricSelectionChanged(event));
4069
3924
  this.fabricCanvas.on("selection:cleared", (event) => this.onFabricSelectionChanged(event));
4070
3925
  this.fabricCanvas.on("text:editing:entered", () => this.onTextEditing());
4071
- //this.fabricCanvas.on("text:editing:exited", () => this.onTextEditing());
3926
+ this.fabricCanvas.on("text:editing:exited", () => this.onTextEditing());
4072
3927
  this.fabricCanvas.on("text:editing:exited", (event) => {
4073
3928
  this.onTextEditing();
4074
3929
  const target = event.target;
@@ -9,7 +9,6 @@ export declare class AdvancedLayoutManager extends AbstractLayoutManager {
9
9
  private repositionCutoffs;
10
10
  private repositionBackgrounds;
11
11
  private resizeCanvas;
12
- private dimensionsLayoutScheduled;
13
12
  constructor(canvas: IInteractiveCanvas);
14
13
  onCanvasDimensionsChange(): void;
15
14
  onTextChange(): void;
@@ -36,6 +36,5 @@ export declare class StandardLayoutManager extends AbstractLayoutManager {
36
36
  * @override
37
37
  */
38
38
  onMarginChange(): void;
39
- private layoutBatchScheduled;
40
39
  private stackAndRedraw;
41
40
  }
@@ -63,8 +63,6 @@ export declare class Text extends AbstractCanvasObject<ExtendedFabricTextbox> im
63
63
  private readonly text$;
64
64
  private readonly textSelection$;
65
65
  static readonly NEW_LINE: string;
66
- private notifyCanvasTimeout;
67
- private readonly NOTIFY_DELAY_MS;
68
66
  constructor(canvas: IInteractiveCanvas, fabricObject: fabric.Textbox, persistedField?: CanvasObjectData);
69
67
  /**
70
68
  * @override
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leapfrog/interactive-canvas",
3
- "version": "2.0.25-beta-12",
3
+ "version": "2.0.25-beta-13",
4
4
  "description": "Leapfrog interactive canvas",
5
5
  "files": [
6
6
  "dist"
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "canvas": "^3.2.3",
22
- "fabric": "7.4.0",
22
+ "fabric": "^7.2.0",
23
23
  "lodash": "^4.18.1",
24
24
  "rollup": "^4.60.3",
25
25
  "rollup-plugin-typescript2": "^0.37.0",