@leapfrog/interactive-canvas 2.0.25-beta-15 → 2.0.25-beta-16

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.
@@ -343,7 +343,6 @@ export declare abstract class AbstractInteractiveCanvas implements IInteractiveC
343
343
  private redrawScheduled;
344
344
  /**
345
345
  * Redraw the canvas.
346
- * Uses requestAnimationFrame to batch multiple redraw calls into a single render.
347
346
  */
348
347
  redraw(): void;
349
348
  syncObjectList(): void;
@@ -20,6 +20,7 @@ export declare class InteractiveCanvas extends AbstractInteractiveCanvas {
20
20
  */
21
21
  redo(): Promise<void>;
22
22
  private onFabricSelectionChanged;
23
+ private enterTextSelectionModeIfRequired;
23
24
  private onTextEditing;
24
25
  private onDoubleClick;
25
26
  }
@@ -270,6 +270,7 @@ class StackObjectsLayoutFunction {
270
270
  const footerObjects = objects[0];
271
271
  const bodyObjects = objects[1];
272
272
  const bodyWidth = canvasDimensions.widthPx - canvasMargin.right - canvasMargin.left;
273
+ // canvas.redraw();
273
274
  //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.
274
275
  this.applyWidths(allObjects, bodyWidth);
275
276
  const bodyRows = this.getRows(bodyObjects);
@@ -356,11 +357,11 @@ class StackObjectsLayoutFunction {
356
357
  object.setPosition({
357
358
  width: actualWidth
358
359
  });
359
- });
360
- _(objects).forEach((object) => {
361
- if (object.getType() !== ObjectType.VERTICAL_RULE) {
362
- object.updateDimensions();
363
- }
360
+ _(objects).forEach((object) => {
361
+ if (object.getType() !== ObjectType.VERTICAL_RULE) {
362
+ object.updateDimensions();
363
+ }
364
+ });
364
365
  });
365
366
  }
366
367
  adjustCanvasSize(canvas, requiredHeight) {
@@ -472,9 +473,7 @@ class AdvancedLayoutManager extends AbstractLayoutManager {
472
473
  dimensionChange() {
473
474
  const canvasMargin = this.canvas.getMargin();
474
475
  const canvasDimensions = this.canvas.getDimensions();
475
- const allObjects = this.canvas.getObjectsByTypesInternal(ObjectType.TEXT, ObjectType.RICH_TEXT,
476
- //ObjectType.IMAGE,
477
- ObjectType.RECTANGLE, ObjectType.VERTICAL_RULE, ObjectType.HORIZONTAL_RULE);
476
+ const allObjects = this.canvas.getObjectsByTypesInternal(ObjectType.TEXT, ObjectType.RICH_TEXT, ObjectType.RECTANGLE, ObjectType.VERTICAL_RULE, ObjectType.HORIZONTAL_RULE);
478
477
  const bodyWidth = canvasDimensions.widthPx - canvasMargin.right - canvasMargin.left;
479
478
  this.canvas.redraw();
480
479
  //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.
@@ -1117,8 +1116,7 @@ class AbstractCanvasObject {
1117
1116
  mt: options.allowScale,
1118
1117
  mr: options.allowScale,
1119
1118
  mb: options.allowScale,
1120
- mtr: options.allowRotate,
1121
- // dragControl: options.allowMove // Show drag control when movement is allowed
1119
+ mtr: options.allowRotate
1122
1120
  });
1123
1121
  }
1124
1122
  }
@@ -1857,8 +1855,6 @@ class Text extends AbstractCanvasObject {
1857
1855
  });
1858
1856
  this.fabricObject.on("changed", () => this.onTextChange());
1859
1857
  this.fabricObject.on("selection:changed", () => this.onSelectionChange());
1860
- // Note: Removed containsPoint override to allow Fabric's default bounding box
1861
- // detection with padding to work properly for hover detection
1862
1858
  this.fabricObject.on("mousedown", (e) => {
1863
1859
  var _a;
1864
1860
  if (!this.fabricObject.isEditing) {
@@ -2513,7 +2509,6 @@ class Text extends AbstractCanvasObject {
2513
2509
  lockMovementY: true,
2514
2510
  hasControls: false,
2515
2511
  selectable: false,
2516
- // evented: false, // Don't capture mouse events - allows clicks to pass through to textbox
2517
2512
  originX: "left",
2518
2513
  originY: "top"
2519
2514
  });
@@ -2620,16 +2615,12 @@ class Text extends AbstractCanvasObject {
2620
2615
  * @inheritDoc
2621
2616
  */
2622
2617
  updateFabricObjectBehavior() {
2623
- // DON'T call super.updateFabricObjectBehavior() for textboxes
2624
- // because it locks movement which interferes with text editing in Fabric v7
2625
2618
  super.updateFabricObjectBehavior();
2626
2619
  const profile = this.canvas.getProfile();
2627
2620
  const allowManualPositioning = !this.canvas.getLayoutManager().isEnforcedPositioning;
2628
- // For textboxes, we keep them moveable but hide all controls except drag control
2629
- // This allows text editing to work properly while still supporting drag via the icon
2630
2621
  this.fabricObject.set({
2631
2622
  lockMovementX: false, // Allow dragging
2632
- lockMovementY: false, // Allow dragging
2623
+ lockMovementY: false,
2633
2624
  lockScalingY: true,
2634
2625
  lockScalingX: this.isPinToBottom(),
2635
2626
  lockScalingFlip: true,
@@ -2655,7 +2646,6 @@ class Text extends AbstractCanvasObject {
2655
2646
  onTextChange() {
2656
2647
  this.data.userText = this.fabricObject.text;
2657
2648
  this.text$.next(this.fabricObject.text);
2658
- // Only check width bounds if text is close to canvas edge (performance optimization)
2659
2649
  const currentLeft = this.fabricObject.left || 0;
2660
2650
  const canvasWidth = this.canvas.getDimensions().widthPx;
2661
2651
  // Skip expensive getBoundingBox if object is clearly within bounds
@@ -2892,8 +2882,8 @@ class AbstractInteractiveCanvas {
2892
2882
  //Configure canvas behaviour
2893
2883
  this.fabricCanvas.stateful = true;
2894
2884
  this.fabricCanvas.preserveObjectStacking = true;
2895
- this.fabricCanvas.perPixelTargetFind = false; // Disabled for better hover tolerance in Fabric v7
2896
- this.fabricCanvas.targetFindTolerance = 0; // Increased for better hover detection in Fabric v7 (was 4)
2885
+ this.fabricCanvas.perPixelTargetFind = false;
2886
+ this.fabricCanvas.targetFindTolerance = 0;
2897
2887
  this.setBackgroundColor("#FFFFFF");
2898
2888
  }
2899
2889
  /**
@@ -3197,6 +3187,7 @@ class AbstractInteractiveCanvas {
3197
3187
  */
3198
3188
  addImageObject(imageUrl) {
3199
3189
  return __awaiter(this, void 0, void 0, function* () {
3190
+ // Don't let the image be more than half the canvas in size.
3200
3191
  const maxSizeScale = 2;
3201
3192
  const maxWidth = this.dimensions$.value.widthPx / maxSizeScale;
3202
3193
  const options = { crossOrigin: "anonymous" };
@@ -3208,6 +3199,7 @@ class AbstractInteractiveCanvas {
3208
3199
  if (curWidth > maxWidth) {
3209
3200
  newScale = maxWidth / curWidth;
3210
3201
  }
3202
+ // Set image properties and add to the canvas
3211
3203
  const fabricImage = new this.fabric.Image(image, {
3212
3204
  id: id,
3213
3205
  scaleX: newScale,
@@ -3227,6 +3219,7 @@ class AbstractInteractiveCanvas {
3227
3219
  return object;
3228
3220
  }
3229
3221
  else {
3222
+ // Browser-side logic
3230
3223
  return yield new Promise((resolve) => {
3231
3224
  this.fabric.Image.fromURL(imageUrl, options).then((fabricImage) => {
3232
3225
  const id = this.randomId();
@@ -3734,7 +3727,6 @@ class AbstractInteractiveCanvas {
3734
3727
  }
3735
3728
  /**
3736
3729
  * Redraw the canvas.
3737
- * Uses requestAnimationFrame to batch multiple redraw calls into a single render.
3738
3730
  */
3739
3731
  redraw() {
3740
3732
  if (this.redrawScheduled) {
@@ -4073,6 +4065,16 @@ class InteractiveCanvas extends AbstractInteractiveCanvas {
4073
4065
  selection.setEvent(event);
4074
4066
  }
4075
4067
  this.selection$.next(selection);
4068
+ //this.enterTextSelectionModeIfRequired();
4069
+ }
4070
+ enterTextSelectionModeIfRequired() {
4071
+ var _a, _b;
4072
+ if (!this.profile$.value.enterTextEditImmediatelyOnSelect && !this.layoutManager$.value.enterTextEditImmediatelyOnSelect)
4073
+ return;
4074
+ if (((_b = (_a = this.selection$.value) === null || _a === void 0 ? void 0 : _a.objects[0]) === null || _b === void 0 ? void 0 : _b.getType()) !== ObjectType.TEXT)
4075
+ return;
4076
+ const text = this.selection$.value.objects[0];
4077
+ text.enterEditing();
4076
4078
  }
4077
4079
  onTextEditing() {
4078
4080
  const selected = this.getFieldsByCanvasObject(this.fabricCanvas.getActiveObjects());
@@ -291,6 +291,7 @@ class StackObjectsLayoutFunction {
291
291
  const footerObjects = objects[0];
292
292
  const bodyObjects = objects[1];
293
293
  const bodyWidth = canvasDimensions.widthPx - canvasMargin.right - canvasMargin.left;
294
+ // canvas.redraw();
294
295
  //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.
295
296
  this.applyWidths(allObjects, bodyWidth);
296
297
  const bodyRows = this.getRows(bodyObjects);
@@ -377,11 +378,11 @@ class StackObjectsLayoutFunction {
377
378
  object.setPosition({
378
379
  width: actualWidth
379
380
  });
380
- });
381
- _(objects).forEach((object) => {
382
- if (object.getType() !== exports.ObjectType.VERTICAL_RULE) {
383
- object.updateDimensions();
384
- }
381
+ _(objects).forEach((object) => {
382
+ if (object.getType() !== exports.ObjectType.VERTICAL_RULE) {
383
+ object.updateDimensions();
384
+ }
385
+ });
385
386
  });
386
387
  }
387
388
  adjustCanvasSize(canvas, requiredHeight) {
@@ -493,9 +494,7 @@ class AdvancedLayoutManager extends AbstractLayoutManager {
493
494
  dimensionChange() {
494
495
  const canvasMargin = this.canvas.getMargin();
495
496
  const canvasDimensions = this.canvas.getDimensions();
496
- const allObjects = this.canvas.getObjectsByTypesInternal(exports.ObjectType.TEXT, exports.ObjectType.RICH_TEXT,
497
- //ObjectType.IMAGE,
498
- exports.ObjectType.RECTANGLE, exports.ObjectType.VERTICAL_RULE, exports.ObjectType.HORIZONTAL_RULE);
497
+ const allObjects = this.canvas.getObjectsByTypesInternal(exports.ObjectType.TEXT, exports.ObjectType.RICH_TEXT, exports.ObjectType.RECTANGLE, exports.ObjectType.VERTICAL_RULE, exports.ObjectType.HORIZONTAL_RULE);
499
498
  const bodyWidth = canvasDimensions.widthPx - canvasMargin.right - canvasMargin.left;
500
499
  this.canvas.redraw();
501
500
  //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.
@@ -1138,8 +1137,7 @@ class AbstractCanvasObject {
1138
1137
  mt: options.allowScale,
1139
1138
  mr: options.allowScale,
1140
1139
  mb: options.allowScale,
1141
- mtr: options.allowRotate,
1142
- // dragControl: options.allowMove // Show drag control when movement is allowed
1140
+ mtr: options.allowRotate
1143
1141
  });
1144
1142
  }
1145
1143
  }
@@ -1878,8 +1876,6 @@ class Text extends AbstractCanvasObject {
1878
1876
  });
1879
1877
  this.fabricObject.on("changed", () => this.onTextChange());
1880
1878
  this.fabricObject.on("selection:changed", () => this.onSelectionChange());
1881
- // Note: Removed containsPoint override to allow Fabric's default bounding box
1882
- // detection with padding to work properly for hover detection
1883
1879
  this.fabricObject.on("mousedown", (e) => {
1884
1880
  var _a;
1885
1881
  if (!this.fabricObject.isEditing) {
@@ -2534,7 +2530,6 @@ class Text extends AbstractCanvasObject {
2534
2530
  lockMovementY: true,
2535
2531
  hasControls: false,
2536
2532
  selectable: false,
2537
- // evented: false, // Don't capture mouse events - allows clicks to pass through to textbox
2538
2533
  originX: "left",
2539
2534
  originY: "top"
2540
2535
  });
@@ -2641,16 +2636,12 @@ class Text extends AbstractCanvasObject {
2641
2636
  * @inheritDoc
2642
2637
  */
2643
2638
  updateFabricObjectBehavior() {
2644
- // DON'T call super.updateFabricObjectBehavior() for textboxes
2645
- // because it locks movement which interferes with text editing in Fabric v7
2646
2639
  super.updateFabricObjectBehavior();
2647
2640
  const profile = this.canvas.getProfile();
2648
2641
  const allowManualPositioning = !this.canvas.getLayoutManager().isEnforcedPositioning;
2649
- // For textboxes, we keep them moveable but hide all controls except drag control
2650
- // This allows text editing to work properly while still supporting drag via the icon
2651
2642
  this.fabricObject.set({
2652
2643
  lockMovementX: false, // Allow dragging
2653
- lockMovementY: false, // Allow dragging
2644
+ lockMovementY: false,
2654
2645
  lockScalingY: true,
2655
2646
  lockScalingX: this.isPinToBottom(),
2656
2647
  lockScalingFlip: true,
@@ -2676,7 +2667,6 @@ class Text extends AbstractCanvasObject {
2676
2667
  onTextChange() {
2677
2668
  this.data.userText = this.fabricObject.text;
2678
2669
  this.text$.next(this.fabricObject.text);
2679
- // Only check width bounds if text is close to canvas edge (performance optimization)
2680
2670
  const currentLeft = this.fabricObject.left || 0;
2681
2671
  const canvasWidth = this.canvas.getDimensions().widthPx;
2682
2672
  // Skip expensive getBoundingBox if object is clearly within bounds
@@ -2913,8 +2903,8 @@ class AbstractInteractiveCanvas {
2913
2903
  //Configure canvas behaviour
2914
2904
  this.fabricCanvas.stateful = true;
2915
2905
  this.fabricCanvas.preserveObjectStacking = true;
2916
- this.fabricCanvas.perPixelTargetFind = false; // Disabled for better hover tolerance in Fabric v7
2917
- this.fabricCanvas.targetFindTolerance = 0; // Increased for better hover detection in Fabric v7 (was 4)
2906
+ this.fabricCanvas.perPixelTargetFind = false;
2907
+ this.fabricCanvas.targetFindTolerance = 0;
2918
2908
  this.setBackgroundColor("#FFFFFF");
2919
2909
  }
2920
2910
  /**
@@ -3218,6 +3208,7 @@ class AbstractInteractiveCanvas {
3218
3208
  */
3219
3209
  addImageObject(imageUrl) {
3220
3210
  return __awaiter(this, void 0, void 0, function* () {
3211
+ // Don't let the image be more than half the canvas in size.
3221
3212
  const maxSizeScale = 2;
3222
3213
  const maxWidth = this.dimensions$.value.widthPx / maxSizeScale;
3223
3214
  const options = { crossOrigin: "anonymous" };
@@ -3229,6 +3220,7 @@ class AbstractInteractiveCanvas {
3229
3220
  if (curWidth > maxWidth) {
3230
3221
  newScale = maxWidth / curWidth;
3231
3222
  }
3223
+ // Set image properties and add to the canvas
3232
3224
  const fabricImage = new this.fabric.Image(image, {
3233
3225
  id: id,
3234
3226
  scaleX: newScale,
@@ -3248,6 +3240,7 @@ class AbstractInteractiveCanvas {
3248
3240
  return object;
3249
3241
  }
3250
3242
  else {
3243
+ // Browser-side logic
3251
3244
  return yield new Promise((resolve) => {
3252
3245
  this.fabric.Image.fromURL(imageUrl, options).then((fabricImage) => {
3253
3246
  const id = this.randomId();
@@ -3755,7 +3748,6 @@ class AbstractInteractiveCanvas {
3755
3748
  }
3756
3749
  /**
3757
3750
  * Redraw the canvas.
3758
- * Uses requestAnimationFrame to batch multiple redraw calls into a single render.
3759
3751
  */
3760
3752
  redraw() {
3761
3753
  if (this.redrawScheduled) {
@@ -4094,6 +4086,16 @@ class InteractiveCanvas extends AbstractInteractiveCanvas {
4094
4086
  selection.setEvent(event);
4095
4087
  }
4096
4088
  this.selection$.next(selection);
4089
+ //this.enterTextSelectionModeIfRequired();
4090
+ }
4091
+ enterTextSelectionModeIfRequired() {
4092
+ var _a, _b;
4093
+ if (!this.profile$.value.enterTextEditImmediatelyOnSelect && !this.layoutManager$.value.enterTextEditImmediatelyOnSelect)
4094
+ return;
4095
+ if (((_b = (_a = this.selection$.value) === null || _a === void 0 ? void 0 : _a.objects[0]) === null || _b === void 0 ? void 0 : _b.getType()) !== exports.ObjectType.TEXT)
4096
+ return;
4097
+ const text = this.selection$.value.objects[0];
4098
+ text.enterEditing();
4097
4099
  }
4098
4100
  onTextEditing() {
4099
4101
  const selected = this.getFieldsByCanvasObject(this.fabricCanvas.getActiveObjects());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leapfrog/interactive-canvas",
3
- "version": "2.0.25-beta-15",
3
+ "version": "2.0.25-beta-16",
4
4
  "description": "Leapfrog interactive canvas",
5
5
  "files": [
6
6
  "dist"