@bwp-web/canvas 0.4.2 → 0.4.3

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/index.d.ts CHANGED
@@ -11,6 +11,8 @@ export { useCanvasTooltip } from './hooks';
11
11
  export type { UseCanvasTooltipOptions, CanvasTooltipState } from './hooks';
12
12
  export { useCanvasClick } from './hooks';
13
13
  export type { UseCanvasClickOptions } from './hooks';
14
+ export { useObjectOverlay } from './hooks';
15
+ export type { UseObjectOverlayOptions } from './hooks';
14
16
  export type { Point2D, ShapeStyleOptions, SnappingOptions, InteractionModeOptions, SnappableInteractionOptions, DragBounds, ModeSetup, } from './types';
15
17
  export { createRectangle, createRectangleAtPoint, editRectangle, } from './shapes';
16
18
  export type { RectangleOptions, RectangleAtPointOptions } from './shapes';
@@ -26,7 +28,7 @@ export type { DrawToCreateOptions } from './interactions';
26
28
  export { enableVertexEdit } from './interactions';
27
29
  export type { VertexEditOptions } from './interactions';
28
30
  export { enablePanAndZoom, resetViewport } from './viewport';
29
- export type { ViewportController, ViewportMode, PanAndZoomOptions, } from './viewport';
31
+ export type { ViewportController, ViewportMode, PanAndZoomOptions, PanToObjectOptions, } from './viewport';
30
32
  export { getSnapPoints, registerSnapPointExtractor } from './alignment';
31
33
  export type { SnapPointExtractor } from './alignment';
32
34
  export { enableObjectAlignment } from './alignment';
@@ -38,8 +40,8 @@ export type { CursorSnapResult, CursorSnapOptions, GuidelineStyle, } from './ali
38
40
  export { deleteObjects, enableKeyboardShortcuts } from './keyboard';
39
41
  export { enableScaledStrokes, serializeCanvas, loadCanvas, getBaseStrokeWidth, } from './serialization';
40
42
  export type { SerializeOptions, LoadCanvasOptions } from './serialization';
41
- export { fitViewportToBackground, setBackgroundOpacity, getBackgroundOpacity, setBackgroundInverted, getBackgroundInverted, resizeImageUrl, setBackgroundImage, } from './background';
43
+ export { fitViewportToBackground, getBackgroundSrc, setBackgroundOpacity, getBackgroundOpacity, setBackgroundInverted, getBackgroundInverted, resizeImageUrl, setBackgroundImage, } from './background';
42
44
  export type { FitViewportOptions, ResizeResult, ResizeImageOptions, SetBackgroundImageOptions, } from './background';
43
45
  export { DEFAULT_CONTROL_STYLE, DEFAULT_SHAPE_STYLE, DEFAULT_CIRCLE_STYLE, DEFAULT_DRAG_SHAPE_STYLE, DEFAULT_GUIDELINE_SHAPE_STYLE, DEFAULT_ALIGNMENT_STYLE, } from './styles';
44
- export { Canvas as FabricCanvas, FabricObject, FabricImage, Rect, Polygon, } from 'fabric';
46
+ export { Canvas as FabricCanvas, FabricObject, FabricImage, Rect, Polygon, Point, util, } from 'fabric';
45
47
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -29,27 +29,56 @@ function enableKeyboardShortcuts(canvas) {
29
29
  // src/Canvas/Canvas.tsx
30
30
  import { jsx } from "react/jsx-runtime";
31
31
  function Canvas({
32
- width = 800,
33
- height = 600,
32
+ width,
33
+ height,
34
34
  className,
35
35
  style,
36
36
  onReady
37
37
  }) {
38
38
  const canvasRef = useRef(null);
39
+ const wrapperRef = useRef(null);
40
+ const isFixedSize = width !== void 0 && height !== void 0;
39
41
  useEffect(() => {
40
42
  const el = canvasRef.current;
41
- if (!el) {
42
- return;
43
- }
44
- const fabricCanvas = new FabricCanvas(el, { width, height });
43
+ const wrapper = wrapperRef.current;
44
+ if (!el || !wrapper) return;
45
+ const initialWidth = isFixedSize ? width : wrapper.clientWidth || 800;
46
+ const initialHeight = isFixedSize ? height : wrapper.clientHeight || 600;
47
+ const fabricCanvas = new FabricCanvas(el, {
48
+ width: initialWidth,
49
+ height: initialHeight
50
+ });
45
51
  onReady?.(fabricCanvas);
46
52
  const cleanupShortcuts = enableKeyboardShortcuts(fabricCanvas);
53
+ let observer;
54
+ let rafId = 0;
55
+ if (!isFixedSize) {
56
+ let currentWidth = initialWidth;
57
+ let currentHeight = initialHeight;
58
+ observer = new ResizeObserver((entries) => {
59
+ cancelAnimationFrame(rafId);
60
+ rafId = requestAnimationFrame(() => {
61
+ const entry = entries[0];
62
+ if (!entry) return;
63
+ const { width: newWidth, height: newHeight } = entry.contentRect;
64
+ if (newWidth > 0 && newHeight > 0 && (newWidth !== currentWidth || newHeight !== currentHeight)) {
65
+ currentWidth = newWidth;
66
+ currentHeight = newHeight;
67
+ fabricCanvas.setDimensions({ width: newWidth, height: newHeight });
68
+ }
69
+ });
70
+ });
71
+ observer.observe(wrapper);
72
+ }
47
73
  return () => {
74
+ cancelAnimationFrame(rafId);
75
+ observer?.disconnect();
48
76
  cleanupShortcuts();
49
77
  fabricCanvas.dispose();
50
78
  };
51
79
  }, []);
52
- return /* @__PURE__ */ jsx("div", { className, style, children: /* @__PURE__ */ jsx("canvas", { ref: canvasRef }) });
80
+ const wrapperStyle = isFixedSize ? { ...style } : { width: "100%", height: "100%", ...style };
81
+ return /* @__PURE__ */ jsx("div", { ref: wrapperRef, className, style: wrapperStyle, children: /* @__PURE__ */ jsx("canvas", { ref: canvasRef }) });
53
82
  }
54
83
 
55
84
  // src/hooks/useEditCanvas.ts
@@ -57,7 +86,9 @@ import { useCallback, useEffect as useEffect2, useRef as useRef2, useState } fro
57
86
  import { Polygon as Polygon4 } from "fabric";
58
87
 
59
88
  // src/viewport.ts
60
- import { Point } from "fabric";
89
+ import {
90
+ Point
91
+ } from "fabric";
61
92
 
62
93
  // src/constants.ts
63
94
  var DEFAULT_MIN_ZOOM = 0.2;
@@ -259,6 +290,54 @@ function enablePanAndZoom(canvas, options) {
259
290
  z
260
291
  );
261
292
  },
293
+ panToObject(object, panOpts) {
294
+ const zoom = canvas.getZoom();
295
+ const objectCenter = object.getCenterPoint();
296
+ const canvasCenterX = canvas.getWidth() / 2;
297
+ const canvasCenterY = canvas.getHeight() / 2;
298
+ const targetX = canvasCenterX - objectCenter.x * zoom;
299
+ const targetY = canvasCenterY - objectCenter.y * zoom;
300
+ if (!panOpts?.animate) {
301
+ const vt2 = canvas.viewportTransform;
302
+ if (!vt2) return;
303
+ canvas.setViewportTransform([
304
+ vt2[0],
305
+ vt2[1],
306
+ vt2[2],
307
+ vt2[3],
308
+ targetX,
309
+ targetY
310
+ ]);
311
+ return;
312
+ }
313
+ const duration = panOpts.duration ?? 300;
314
+ const vt = canvas.viewportTransform;
315
+ if (!vt) return;
316
+ const startX = vt[4];
317
+ const startY = vt[5];
318
+ const startTime = performance.now();
319
+ function step(now) {
320
+ const elapsed = now - startTime;
321
+ const t = Math.min(elapsed / duration, 1);
322
+ const eased = 1 - Math.pow(1 - t, 3);
323
+ const currentX = startX + (targetX - startX) * eased;
324
+ const currentY = startY + (targetY - startY) * eased;
325
+ const currentVt = canvas.viewportTransform;
326
+ if (!currentVt) return;
327
+ canvas.setViewportTransform([
328
+ currentVt[0],
329
+ currentVt[1],
330
+ currentVt[2],
331
+ currentVt[3],
332
+ currentX,
333
+ currentY
334
+ ]);
335
+ if (t < 1) {
336
+ requestAnimationFrame(step);
337
+ }
338
+ }
339
+ requestAnimationFrame(step);
340
+ },
262
341
  cleanup() {
263
342
  canvas.off("mouse:wheel", handleWheel);
264
343
  canvas.off("mouse:down", panHandlers.handleMouseDown);
@@ -277,6 +356,11 @@ import { FabricImage, filters } from "fabric";
277
356
  function getBackgroundImage(canvas) {
278
357
  return canvas.backgroundImage;
279
358
  }
359
+ function getBackgroundSrc(canvas) {
360
+ const bg = getBackgroundImage(canvas);
361
+ if (!bg) return null;
362
+ return bg.getSrc() || null;
363
+ }
280
364
  function fitViewportToBackground(canvas, options) {
281
365
  const bg = getBackgroundImage(canvas);
282
366
  if (!bg) return;
@@ -412,7 +496,10 @@ function createViewportActions(canvasRef, viewportRef, setZoom) {
412
496
  viewportRef.current?.zoomOut(step);
413
497
  syncZoom(canvasRef, setZoom);
414
498
  };
415
- return { resetViewport: resetViewport2, zoomIn, zoomOut };
499
+ const panToObject = (object, panOpts) => {
500
+ viewportRef.current?.panToObject(object, panOpts);
501
+ };
502
+ return { resetViewport: resetViewport2, zoomIn, zoomOut, panToObject };
416
503
  }
417
504
  function resolveAlignmentEnabled(enableAlignment, alignmentProp) {
418
505
  if (enableAlignment !== void 0) return enableAlignment;
@@ -1308,21 +1395,39 @@ function enableDragToCreate(canvas, factory, options) {
1308
1395
  options?.onCreated?.(obj);
1309
1396
  previewRect = null;
1310
1397
  };
1398
+ const handleKeyDown = (e) => {
1399
+ if (e.key === "Escape") {
1400
+ e.stopImmediatePropagation();
1401
+ e.preventDefault();
1402
+ cleanup("cancel");
1403
+ }
1404
+ };
1311
1405
  canvas.on("mouse:down", handleMouseDown);
1312
1406
  canvas.on("mouse:move", handleMouseMove);
1313
1407
  canvas.on("mouse:up", handleMouseUp);
1314
- return () => {
1408
+ document.addEventListener("keydown", handleKeyDown, true);
1409
+ let exited = false;
1410
+ function cleanup(reason) {
1411
+ if (exited) return;
1412
+ exited = true;
1315
1413
  canvas.off("mouse:down", handleMouseDown);
1316
1414
  canvas.off("mouse:move", handleMouseMove);
1317
1415
  canvas.off("mouse:up", handleMouseUp);
1416
+ document.removeEventListener("keydown", handleKeyDown, true);
1318
1417
  shiftTracker.cleanup();
1319
1418
  snapping.cleanup();
1320
1419
  if (isDrawing && previewRect) {
1420
+ snapping.excludeSet.delete(previewRect);
1321
1421
  canvas.remove(previewRect);
1422
+ canvas.selection = previousSelection;
1322
1423
  canvas.requestRenderAll();
1323
1424
  }
1324
1425
  restoreViewport(options?.viewport);
1325
- };
1426
+ if (reason === "cancel") {
1427
+ options?.onCancel?.();
1428
+ }
1429
+ }
1430
+ return () => cleanup();
1326
1431
  }
1327
1432
 
1328
1433
  // src/interactions/drawToCreate.ts
@@ -1602,6 +1707,9 @@ function enableDrawToCreate(canvas, options) {
1602
1707
  removePreviewElements();
1603
1708
  snapping.clearSnapResult();
1604
1709
  const polygon = createPolygonFromVertices(canvas, points, options?.style);
1710
+ if (options?.data) {
1711
+ polygon.data = options.data;
1712
+ }
1605
1713
  canvas.selection = previousSelection;
1606
1714
  canvas.requestRenderAll();
1607
1715
  restoreViewport(options?.viewport);
@@ -1996,6 +2104,7 @@ async function loadCanvas(canvas, json, options) {
1996
2104
  }
1997
2105
  });
1998
2106
  canvas.requestRenderAll();
2107
+ return canvas.getObjects();
1999
2108
  }
2000
2109
 
2001
2110
  // src/hooks/useEditCanvas.ts
@@ -2141,7 +2250,7 @@ function useEditCanvas(options) {
2141
2250
  viewportRef.current?.setMode(mode);
2142
2251
  setViewportModeState(mode);
2143
2252
  }, []);
2144
- const { resetViewport: resetViewport2, zoomIn, zoomOut } = createViewportActions(
2253
+ const { resetViewport: resetViewport2, zoomIn, zoomOut, panToObject } = createViewportActions(
2145
2254
  canvasRef,
2146
2255
  viewportRef,
2147
2256
  setZoom
@@ -2181,7 +2290,9 @@ function useEditCanvas(options) {
2181
2290
  /** Zoom in toward the canvas center. Default step: 0.2. */
2182
2291
  zoomIn,
2183
2292
  /** Zoom out from the canvas center. Default step: 0.2. */
2184
- zoomOut
2293
+ zoomOut,
2294
+ /** Pan the viewport to center on a specific object. */
2295
+ panToObject
2185
2296
  },
2186
2297
  /** Whether vertex edit mode is currently active (reactive). */
2187
2298
  isEditingVertices,
@@ -2271,7 +2382,7 @@ function useViewCanvas(options) {
2271
2382
  // eslint-disable-next-line react-hooks/exhaustive-deps
2272
2383
  []
2273
2384
  );
2274
- const { resetViewport: resetViewport2, zoomIn, zoomOut } = createViewportActions(
2385
+ const { resetViewport: resetViewport2, zoomIn, zoomOut, panToObject } = createViewportActions(
2275
2386
  canvasRef,
2276
2387
  viewportRef,
2277
2388
  setZoom
@@ -2337,7 +2448,9 @@ function useViewCanvas(options) {
2337
2448
  /** Zoom in toward the canvas center. Default step: 0.2. */
2338
2449
  zoomIn,
2339
2450
  /** Zoom out from the canvas center. Default step: 0.2. */
2340
- zoomOut
2451
+ zoomOut,
2452
+ /** Pan the viewport to center on a specific object. */
2453
+ panToObject
2341
2454
  },
2342
2455
  /** Update a single object's visual style by its `data.id`. */
2343
2456
  setObjectStyle,
@@ -2488,13 +2601,75 @@ function useCanvasClick(canvasRef, onClick, options) {
2488
2601
  }, [canvasRef]);
2489
2602
  }
2490
2603
 
2604
+ // src/hooks/useObjectOverlay.ts
2605
+ import { useEffect as useEffect6, useRef as useRef7 } from "react";
2606
+ import { util as util4 } from "fabric";
2607
+ function useObjectOverlay(canvasRef, object, options) {
2608
+ const containerRef = useRef7(null);
2609
+ const optionsRef = useRef7(options);
2610
+ optionsRef.current = options;
2611
+ useEffect6(() => {
2612
+ const canvas = canvasRef.current;
2613
+ if (!canvas || !object) return;
2614
+ function update() {
2615
+ const el = containerRef.current;
2616
+ if (!el || !canvas || !object) return;
2617
+ const zoom = canvas.getZoom();
2618
+ const vt = canvas.viewportTransform;
2619
+ if (!vt) return;
2620
+ const center = object.getCenterPoint();
2621
+ const actualWidth = (object.width ?? 0) * (object.scaleX ?? 1);
2622
+ const actualHeight = (object.height ?? 0) * (object.scaleY ?? 1);
2623
+ const screenCoords = util4.transformPoint(center, vt);
2624
+ const screenWidth = actualWidth * zoom;
2625
+ const screenHeight = actualHeight * zoom;
2626
+ el.style.left = `${screenCoords.x - screenWidth / 2}px`;
2627
+ el.style.top = `${screenCoords.y - screenHeight / 2}px`;
2628
+ el.style.width = `${screenWidth}px`;
2629
+ el.style.height = `${screenHeight}px`;
2630
+ const angle = object.angle ?? 0;
2631
+ el.style.rotate = angle !== 0 ? `${angle}deg` : "";
2632
+ const opts = optionsRef.current;
2633
+ if (opts?.autoScaleContent) {
2634
+ const contentScale = Math.min(screenWidth, screenHeight) / 100;
2635
+ const clampedScale = Math.max(0.1, Math.min(contentScale, 2));
2636
+ el.style.setProperty("--overlay-scale", String(clampedScale));
2637
+ if (opts.textSelector) {
2638
+ const textMinScale = opts.textMinScale ?? 0.5;
2639
+ const textEls = el.querySelectorAll(opts.textSelector);
2640
+ const display = clampedScale < textMinScale ? "none" : "";
2641
+ textEls.forEach((t) => {
2642
+ t.style.display = display;
2643
+ });
2644
+ }
2645
+ }
2646
+ }
2647
+ update();
2648
+ canvas.on("after:render", update);
2649
+ canvas.on("mouse:wheel", update);
2650
+ object.on("moving", update);
2651
+ object.on("scaling", update);
2652
+ object.on("rotating", update);
2653
+ return () => {
2654
+ canvas.off("after:render", update);
2655
+ canvas.off("mouse:wheel", update);
2656
+ object.off("moving", update);
2657
+ object.off("scaling", update);
2658
+ object.off("rotating", update);
2659
+ };
2660
+ }, [canvasRef, object]);
2661
+ return containerRef;
2662
+ }
2663
+
2491
2664
  // src/index.ts
2492
2665
  import {
2493
2666
  Canvas as Canvas2,
2494
2667
  FabricObject as FabricObject5,
2495
2668
  FabricImage as FabricImage2,
2496
2669
  Rect as Rect7,
2497
- Polygon as Polygon5
2670
+ Polygon as Polygon5,
2671
+ Point as Point9,
2672
+ util as util5
2498
2673
  } from "fabric";
2499
2674
  export {
2500
2675
  Canvas,
@@ -2507,6 +2682,7 @@ export {
2507
2682
  Canvas2 as FabricCanvas,
2508
2683
  FabricImage2 as FabricImage,
2509
2684
  FabricObject5 as FabricObject,
2685
+ Point9 as Point,
2510
2686
  Polygon5 as Polygon,
2511
2687
  Rect7 as Rect,
2512
2688
  createCircle,
@@ -2533,6 +2709,7 @@ export {
2533
2709
  fitViewportToBackground,
2534
2710
  getBackgroundInverted,
2535
2711
  getBackgroundOpacity,
2712
+ getBackgroundSrc,
2536
2713
  getBaseStrokeWidth,
2537
2714
  getSnapPoints,
2538
2715
  loadCanvas,
@@ -2548,6 +2725,8 @@ export {
2548
2725
  useCanvasEvents,
2549
2726
  useCanvasTooltip,
2550
2727
  useEditCanvas,
2551
- useViewCanvas
2728
+ useObjectOverlay,
2729
+ useViewCanvas,
2730
+ util5 as util
2552
2731
  };
2553
2732
  //# sourceMappingURL=index.js.map