@markup-canvas/react 1.0.0

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/README.md ADDED
@@ -0,0 +1,162 @@
1
+ # @markup-canvas/react
2
+
3
+ React component and hook for `@markup-canvas/core`.
4
+
5
+ ## ✨ Live Demo
6
+
7
+ Check out the live demo: [https://markup-canvas.vercel.app/](https://markup-canvas.vercel.app/)
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @markup-canvas/react @markup-canvas/core
13
+ # or
14
+ pnpm add @markup-canvas/react @markup-canvas/core
15
+ # or
16
+ yarn add @markup-canvas/react @markup-canvas/core
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### Component API
22
+
23
+ ```tsx
24
+ import { useRef } from 'react';
25
+ import { MarkupCanvas, type MarkupCanvasRef } from '@markup-canvas/react';
26
+
27
+ function App() {
28
+ const canvasRef = useRef<MarkupCanvasRef>(null);
29
+
30
+ return (
31
+ <div style={{ width: '100vw', height: '100vh' }}>
32
+ <button onClick={() => canvasRef.current?.zoomIn()}>Zoom In</button>
33
+ <button onClick={() => canvasRef.current?.zoomOut()}>Zoom Out</button>
34
+
35
+ <MarkupCanvas
36
+ ref={canvasRef}
37
+ width={20000}
38
+ height={15000}
39
+ enableZoom={true}
40
+ enablePan={true}
41
+ enableKeyboard={true}
42
+ onZoomChange={(zoom) => console.log('Zoom:', zoom)}
43
+ onReady={(canvas) => console.log('Canvas ready:', canvas)}
44
+ >
45
+ <div style={{ position: 'absolute', top: 100, left: 100 }}>
46
+ <h1>Zoomable Content</h1>
47
+ <p>This content can be panned and zoomed!</p>
48
+ </div>
49
+ </MarkupCanvas>
50
+ </div>
51
+ );
52
+ }
53
+ ```
54
+
55
+ ### Hook API
56
+
57
+ The `useMarkupCanvas` hook provides convenient access to canvas methods.
58
+ **Important:** You must pass `initCanvasUtils` to the `onReady` prop for the hook to work properly.
59
+
60
+ ```tsx
61
+ import { useRef } from 'react';
62
+ import { MarkupCanvas, type MarkupCanvasRef, useMarkupCanvas } from '@markup-canvas/react';
63
+
64
+ function App() {
65
+ const canvasRef = useRef<MarkupCanvasRef>(null);
66
+
67
+ const { initCanvasUtils, zoom, zoomIn, zoomOut, fitToContent, resetZoom } = useMarkupCanvas(canvasRef);
68
+
69
+ return (
70
+ <div style={{ width: '100vw', height: '100vh' }}>
71
+ <button onClick={() => zoomIn()}>Zoom In</button>
72
+ <button onClick={() => zoomOut()}>Zoom Out</button>
73
+ <button onClick={() => fitToContent()}>Fit to Content</button>
74
+ <span>Current zoom: {zoom.toFixed(2)}</span>
75
+
76
+ <MarkupCanvas
77
+ ref={canvasRef}
78
+ width={20000}
79
+ height={15000}
80
+ enableZoom={true}
81
+ enablePan={true}
82
+ onReady={initCanvasUtils} // Required for hook to work
83
+ >
84
+ <div style={{ position: 'absolute', top: 100, left: 100 }}>
85
+ <h1>Zoomable Content</h1>
86
+ </div>
87
+ </MarkupCanvas>
88
+ </div>
89
+ );
90
+ }
91
+ ```
92
+
93
+ ## API
94
+
95
+ ### Component Props
96
+
97
+ #### Canvas Dimensions
98
+ - `width?: number` - Canvas width in pixels
99
+ - `height?: number` - Canvas height in pixels
100
+ - `enableAcceleration?: boolean` - Enable hardware acceleration
101
+
102
+ #### Interaction Controls
103
+ - `enableZoom?: boolean` - Enable zoom functionality
104
+ - `enablePan?: boolean` - Enable pan functionality
105
+ - `enableTouch?: boolean` - Enable touch gestures
106
+ - `enableKeyboard?: boolean` - Enable keyboard controls
107
+ - `limitKeyboardEventsToCanvas?: boolean` - Limit keyboard events to when canvas is focused
108
+
109
+ #### Zoom Behavior
110
+ - `zoomSpeed?: number` - Zoom speed factor
111
+ - `minZoom?: number` - Minimum zoom level
112
+ - `maxZoom?: number` - Maximum zoom level
113
+ - `enableTransition?: boolean` - Enable smooth transitions
114
+ - `transitionDuration?: number` - Transition duration in ms
115
+ - `enableAdaptiveSpeed?: boolean` - Enable adaptive zoom speed
116
+
117
+ #### Pan Behavior
118
+ - `enableLeftDrag?: boolean` - Enable left mouse button drag
119
+ - `enableMiddleDrag?: boolean` - Enable middle mouse button drag
120
+ - `requireSpaceForMouseDrag?: boolean` - Require space key for mouse drag
121
+ - `keyboardPanStep?: number` - Keyboard pan step size
122
+ - `keyboardFastMultiplier?: number` - Fast pan multiplier (with shift)
123
+ - `keyboardZoomStep?: number` - Keyboard zoom step size
124
+
125
+ #### Click-to-Zoom
126
+ - `enableClickToZoom?: boolean` - Enable click to zoom
127
+ - `clickZoomLevel?: number` - Target zoom level for click-to-zoom
128
+ - `requireOptionForClickZoom?: boolean` - Require Option/Alt key for click-to-zoom
129
+
130
+ #### Visual Elements
131
+ - `enableRulers?: boolean` - Show rulers
132
+ - `enableGrid?: boolean` - Show background grid
133
+ - `gridColor?: string` - Grid line color
134
+
135
+ #### Ruler Styling
136
+ - `rulerBackgroundColor?: string` - Ruler background color
137
+ - `rulerBorderColor?: string` - Ruler border color
138
+ - `rulerTextColor?: string` - Ruler text color
139
+ - `rulerMajorTickColor?: string` - Major tick mark color
140
+ - `rulerMinorTickColor?: string` - Minor tick mark color
141
+ - `rulerFontSize?: number` - Ruler font size
142
+ - `rulerFontFamily?: string` - Ruler font family
143
+ - `rulerUnits?: string` - Ruler units label
144
+
145
+ #### React-Specific Props
146
+ - `children?: ReactNode` - Content to render inside the canvas
147
+ - `className?: string` - CSS class name
148
+ - `style?: CSSProperties` - Inline styles
149
+
150
+ #### Callbacks
151
+ - `onTransformUpdate?: (transform: Transform) => void` - Called on transform update
152
+ - `onTransformChange?: (transform: Transform) => void` - Called on transform change
153
+ - `onZoomChange?: (zoom: number) => void` - Called on zoom change
154
+ - `onPanChange?: (pan: { x: number; y: number }) => void` - Called on pan change
155
+ - `onReady?: (canvas: MarkupCanvas) => void` - Called when canvas is ready
156
+
157
+ ## License
158
+
159
+ **CC BY-NC 4.0** - Creative Commons Attribution-NonCommercial 4.0 International
160
+
161
+ This project is licensed for non-commercial use only. See the [LICENSE](../../LICENSE) file for details.
162
+
@@ -0,0 +1,16 @@
1
+ import { MarkupCanvas as CoreMarkupCanvas, type MarkupCanvasConfig, type Transform } from "@markup-canvas/core";
2
+ import { type CSSProperties, type ReactNode } from "react";
3
+ import type { MarkupCanvasRef } from "../types/index.js";
4
+ export interface MarkupCanvasProps extends Omit<MarkupCanvasConfig, "container"> {
5
+ children?: ReactNode;
6
+ className?: string;
7
+ style?: CSSProperties;
8
+ onTransformChange?: (transform: Transform) => void;
9
+ onZoomChange?: (zoom: number) => void;
10
+ onPanChange?: (pan: {
11
+ x: number;
12
+ y: number;
13
+ }) => void;
14
+ onReady?: (canvas: CoreMarkupCanvas) => void;
15
+ }
16
+ export declare const MarkupCanvas: import("react").ForwardRefExoticComponent<MarkupCanvasProps & import("react").RefAttributes<MarkupCanvasRef>>;
@@ -0,0 +1,2 @@
1
+ export type { MarkupCanvasProps } from "./MarkupCanvas.js";
2
+ export { MarkupCanvas } from "./MarkupCanvas.js";
@@ -0,0 +1 @@
1
+ export { useMarkupCanvas } from "./useMarkupCanvas.js";
@@ -0,0 +1,22 @@
1
+ import type { MarkupCanvas, Transform } from "@markup-canvas/core";
2
+ import { type RefObject } from "react";
3
+ import type { MarkupCanvasRef, UseMarkupCanvasOptions } from "../types/index.js";
4
+ export declare function useMarkupCanvas(canvasRef: RefObject<MarkupCanvasRef | null>, options?: UseMarkupCanvasOptions): {
5
+ canvas: MarkupCanvas | null;
6
+ initCanvasUtils: (canvas: MarkupCanvas) => void;
7
+ transform: Transform;
8
+ zoom: number;
9
+ pan: {
10
+ x: number;
11
+ y: number;
12
+ };
13
+ isReady: boolean;
14
+ zoomIn: (factor?: number) => void;
15
+ zoomOut: (factor?: number) => void;
16
+ resetZoom: () => void;
17
+ panTo: (x: number, y: number) => void;
18
+ fitToContent: () => void;
19
+ centerContent: () => void;
20
+ setTransitionMode: (enabled: boolean) => void;
21
+ toggleTransitionMode: () => boolean;
22
+ };
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Markup Canvas React
3
+ * React components and hooks for markup-canvas
4
+ * @version 1.0.0
5
+ */
6
+ 'use strict';
7
+
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+ var core = require('@markup-canvas/core');
10
+ var react = require('react');
11
+
12
+ const MarkupCanvas = react.forwardRef(({ children, className, style, onTransformChange, onZoomChange, onPanChange, onReady, ...options }, ref) => {
13
+ const containerRef = react.useRef(null);
14
+ const [canvasInstance, setCanvasInstance] = react.useState(null);
15
+ react.useImperativeHandle(ref, () => ({
16
+ canvas: canvasInstance,
17
+ zoomIn: (factor = 0.1) => canvasInstance?.zoomIn(factor),
18
+ zoomOut: (factor = 0.1) => canvasInstance?.zoomOut(factor),
19
+ resetZoom: () => canvasInstance?.resetZoom(),
20
+ panTo: (x, y) => canvasInstance?.scrollToPoint(x, y),
21
+ fitToContent: () => canvasInstance?.fitToScreen(),
22
+ centerContent: () => canvasInstance?.centerContent(),
23
+ getTransform: () => canvasInstance?.transform || { scale: 1, translateX: 0, translateY: 0 },
24
+ getZoom: () => canvasInstance?.transform?.scale || 1,
25
+ }), [canvasInstance]);
26
+ const onTransformChangeRef = react.useRef(onTransformChange);
27
+ const onZoomChangeRef = react.useRef(onZoomChange);
28
+ const onPanChangeRef = react.useRef(onPanChange);
29
+ const onReadyRef = react.useRef(onReady);
30
+ onTransformChangeRef.current = onTransformChange;
31
+ onZoomChangeRef.current = onZoomChange;
32
+ onPanChangeRef.current = onPanChange;
33
+ onReadyRef.current = onReady;
34
+ const handleTransformChange = react.useCallback((transform) => {
35
+ onTransformChangeRef.current?.(transform);
36
+ }, []);
37
+ const handleZoomChange = react.useCallback((zoom) => {
38
+ onZoomChangeRef.current?.(zoom);
39
+ }, []);
40
+ const handlePanChange = react.useCallback((pan) => {
41
+ onPanChangeRef.current?.(pan);
42
+ }, []);
43
+ const handleReady = react.useCallback((canvas) => {
44
+ onReadyRef.current?.(canvas);
45
+ }, []);
46
+ const stableOptions = react.useMemo(() => options, Object.values(options));
47
+ react.useEffect(() => {
48
+ if (!containerRef.current)
49
+ return;
50
+ const canvas = new core.MarkupCanvas(containerRef.current, stableOptions);
51
+ setCanvasInstance(canvas);
52
+ canvas.on("transform", handleTransformChange);
53
+ canvas.on("zoom", handleZoomChange);
54
+ canvas.on("pan", handlePanChange);
55
+ canvas.on("ready", handleReady);
56
+ if (canvas.isReady) {
57
+ handleReady(canvas);
58
+ }
59
+ if (canvas.container && typeof canvas.container.focus === "function") {
60
+ canvas.container.focus();
61
+ }
62
+ return () => {
63
+ canvas.off("transform", handleTransformChange);
64
+ canvas.off("zoom", handleZoomChange);
65
+ canvas.off("pan", handlePanChange);
66
+ canvas.off("ready", handleReady);
67
+ canvas.cleanup();
68
+ setCanvasInstance(null);
69
+ };
70
+ }, [stableOptions, handleTransformChange, handleZoomChange, handlePanChange, handleReady]);
71
+ return (jsxRuntime.jsx("div", { ref: containerRef, className: className, style: { width: "100%", height: "100%", ...style }, children: children }));
72
+ });
73
+ MarkupCanvas.displayName = "MarkupCanvas";
74
+
75
+ function useMarkupCanvas(canvasRef, options = {}) {
76
+ const [canvasInstance, setCanvasInstance] = react.useState(null);
77
+ const [transform, setTransform] = react.useState({ scale: 1, translateX: 0, translateY: 0 });
78
+ const [zoom, setZoom] = react.useState(1);
79
+ const [pan, setPan] = react.useState({ x: 0, y: 0 });
80
+ const [isReady, setIsReady] = react.useState(false);
81
+ const optionsRef = react.useRef(options);
82
+ optionsRef.current = options;
83
+ const handleCanvasInstance = react.useCallback((canvas) => {
84
+ setCanvasInstance(canvas);
85
+ optionsRef.current.onReady?.(canvas);
86
+ }, []);
87
+ const handleTransform = react.useCallback((newTransform) => {
88
+ setTransform(newTransform);
89
+ optionsRef.current.onTransformChange?.(newTransform);
90
+ }, []);
91
+ const handleZoom = react.useCallback((newZoom) => {
92
+ setZoom(newZoom);
93
+ optionsRef.current.onZoomChange?.(newZoom);
94
+ }, []);
95
+ const handlePan = react.useCallback((newPan) => {
96
+ setPan(newPan);
97
+ optionsRef.current.onPanChange?.(newPan);
98
+ }, []);
99
+ const handleReady = react.useCallback((canvas) => {
100
+ setIsReady(true);
101
+ optionsRef.current.onReady?.(canvas);
102
+ }, []);
103
+ react.useEffect(() => {
104
+ console.log("useEffect", canvasInstance);
105
+ if (!canvasInstance) {
106
+ return;
107
+ }
108
+ canvasInstance.on("transform", handleTransform);
109
+ canvasInstance.on("zoom", handleZoom);
110
+ canvasInstance.on("pan", handlePan);
111
+ canvasInstance.on("ready", handleReady);
112
+ if (canvasInstance.transform) {
113
+ setTransform(canvasInstance.transform);
114
+ setZoom(canvasInstance.transform.scale);
115
+ setPan({ x: canvasInstance.transform.translateX, y: canvasInstance.transform.translateY });
116
+ }
117
+ if (canvasInstance.isReady) {
118
+ setIsReady(true);
119
+ optionsRef.current.onReady?.(canvasInstance);
120
+ }
121
+ return () => {
122
+ canvasInstance.off("transform", handleTransform);
123
+ canvasInstance.off("zoom", handleZoom);
124
+ canvasInstance.off("pan", handlePan);
125
+ canvasInstance.off("ready", handleReady);
126
+ };
127
+ }, [canvasInstance]);
128
+ const zoomIn = react.useCallback((factor = 0.5) => {
129
+ canvasRef.current?.zoomIn(factor);
130
+ }, [canvasRef]);
131
+ const zoomOut = react.useCallback((factor = 0.5) => {
132
+ canvasRef.current?.zoomOut(factor);
133
+ }, [canvasRef]);
134
+ const resetZoom = react.useCallback(() => {
135
+ canvasRef.current?.resetZoom();
136
+ }, [canvasRef]);
137
+ const panTo = react.useCallback((x, y) => {
138
+ canvasRef.current?.panTo(x, y);
139
+ }, [canvasRef]);
140
+ const fitToContent = react.useCallback(() => {
141
+ canvasRef.current?.fitToContent();
142
+ }, [canvasRef]);
143
+ const centerContent = react.useCallback(() => {
144
+ canvasRef.current?.centerContent();
145
+ }, [canvasRef]);
146
+ const setTransitionMode = react.useCallback((enabled) => {
147
+ if (canvasRef.current?.canvas) {
148
+ canvasRef.current.canvas.updateConfig({ enableTransition: enabled });
149
+ }
150
+ }, [canvasRef]);
151
+ const toggleTransitionMode = react.useCallback(() => {
152
+ if (canvasRef.current?.canvas) {
153
+ const currentConfig = canvasRef.current.canvas.getConfig();
154
+ const newEnableTransition = !currentConfig.enableTransition;
155
+ canvasRef.current.canvas.updateConfig({ enableTransition: newEnableTransition });
156
+ return newEnableTransition;
157
+ }
158
+ return false;
159
+ }, [canvasRef]);
160
+ return {
161
+ canvas: canvasRef.current?.canvas || null,
162
+ initCanvasUtils: handleCanvasInstance,
163
+ transform,
164
+ zoom,
165
+ pan,
166
+ isReady,
167
+ zoomIn,
168
+ zoomOut,
169
+ resetZoom,
170
+ panTo,
171
+ fitToContent,
172
+ centerContent,
173
+ setTransitionMode,
174
+ toggleTransitionMode,
175
+ };
176
+ }
177
+
178
+ exports.MarkupCanvas = MarkupCanvas;
179
+ exports.useMarkupCanvas = useMarkupCanvas;
180
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/components/MarkupCanvas.tsx","../src/hooks/useMarkupCanvas.ts"],"sourcesContent":[null,null],"names":["forwardRef","useRef","useState","useImperativeHandle","useCallback","useMemo","useEffect","CoreMarkupCanvas","_jsx"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export type { MarkupCanvas as CoreMarkupCanvas, MarkupCanvasConfig, Transform } from "@markup-canvas/core";
2
+ export type { MarkupCanvasProps } from "./components/index.js";
3
+ export { MarkupCanvas } from "./components/index.js";
4
+ export { useMarkupCanvas } from "./hooks/index.js";
5
+ export type { CanvasEventHandlers, MarkupCanvasRef, UseMarkupCanvasOptions } from "./types/index.js";
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Markup Canvas React
3
+ * React components and hooks for markup-canvas
4
+ * @version 1.0.0
5
+ */
6
+ import { jsx } from 'react/jsx-runtime';
7
+ import { MarkupCanvas as MarkupCanvas$1 } from '@markup-canvas/core';
8
+ import { forwardRef, useRef, useState, useImperativeHandle, useCallback, useMemo, useEffect } from 'react';
9
+
10
+ const MarkupCanvas = forwardRef(({ children, className, style, onTransformChange, onZoomChange, onPanChange, onReady, ...options }, ref) => {
11
+ const containerRef = useRef(null);
12
+ const [canvasInstance, setCanvasInstance] = useState(null);
13
+ useImperativeHandle(ref, () => ({
14
+ canvas: canvasInstance,
15
+ zoomIn: (factor = 0.1) => canvasInstance?.zoomIn(factor),
16
+ zoomOut: (factor = 0.1) => canvasInstance?.zoomOut(factor),
17
+ resetZoom: () => canvasInstance?.resetZoom(),
18
+ panTo: (x, y) => canvasInstance?.scrollToPoint(x, y),
19
+ fitToContent: () => canvasInstance?.fitToScreen(),
20
+ centerContent: () => canvasInstance?.centerContent(),
21
+ getTransform: () => canvasInstance?.transform || { scale: 1, translateX: 0, translateY: 0 },
22
+ getZoom: () => canvasInstance?.transform?.scale || 1,
23
+ }), [canvasInstance]);
24
+ const onTransformChangeRef = useRef(onTransformChange);
25
+ const onZoomChangeRef = useRef(onZoomChange);
26
+ const onPanChangeRef = useRef(onPanChange);
27
+ const onReadyRef = useRef(onReady);
28
+ onTransformChangeRef.current = onTransformChange;
29
+ onZoomChangeRef.current = onZoomChange;
30
+ onPanChangeRef.current = onPanChange;
31
+ onReadyRef.current = onReady;
32
+ const handleTransformChange = useCallback((transform) => {
33
+ onTransformChangeRef.current?.(transform);
34
+ }, []);
35
+ const handleZoomChange = useCallback((zoom) => {
36
+ onZoomChangeRef.current?.(zoom);
37
+ }, []);
38
+ const handlePanChange = useCallback((pan) => {
39
+ onPanChangeRef.current?.(pan);
40
+ }, []);
41
+ const handleReady = useCallback((canvas) => {
42
+ onReadyRef.current?.(canvas);
43
+ }, []);
44
+ const stableOptions = useMemo(() => options, Object.values(options));
45
+ useEffect(() => {
46
+ if (!containerRef.current)
47
+ return;
48
+ const canvas = new MarkupCanvas$1(containerRef.current, stableOptions);
49
+ setCanvasInstance(canvas);
50
+ canvas.on("transform", handleTransformChange);
51
+ canvas.on("zoom", handleZoomChange);
52
+ canvas.on("pan", handlePanChange);
53
+ canvas.on("ready", handleReady);
54
+ if (canvas.isReady) {
55
+ handleReady(canvas);
56
+ }
57
+ if (canvas.container && typeof canvas.container.focus === "function") {
58
+ canvas.container.focus();
59
+ }
60
+ return () => {
61
+ canvas.off("transform", handleTransformChange);
62
+ canvas.off("zoom", handleZoomChange);
63
+ canvas.off("pan", handlePanChange);
64
+ canvas.off("ready", handleReady);
65
+ canvas.cleanup();
66
+ setCanvasInstance(null);
67
+ };
68
+ }, [stableOptions, handleTransformChange, handleZoomChange, handlePanChange, handleReady]);
69
+ return (jsx("div", { ref: containerRef, className: className, style: { width: "100%", height: "100%", ...style }, children: children }));
70
+ });
71
+ MarkupCanvas.displayName = "MarkupCanvas";
72
+
73
+ function useMarkupCanvas(canvasRef, options = {}) {
74
+ const [canvasInstance, setCanvasInstance] = useState(null);
75
+ const [transform, setTransform] = useState({ scale: 1, translateX: 0, translateY: 0 });
76
+ const [zoom, setZoom] = useState(1);
77
+ const [pan, setPan] = useState({ x: 0, y: 0 });
78
+ const [isReady, setIsReady] = useState(false);
79
+ const optionsRef = useRef(options);
80
+ optionsRef.current = options;
81
+ const handleCanvasInstance = useCallback((canvas) => {
82
+ setCanvasInstance(canvas);
83
+ optionsRef.current.onReady?.(canvas);
84
+ }, []);
85
+ const handleTransform = useCallback((newTransform) => {
86
+ setTransform(newTransform);
87
+ optionsRef.current.onTransformChange?.(newTransform);
88
+ }, []);
89
+ const handleZoom = useCallback((newZoom) => {
90
+ setZoom(newZoom);
91
+ optionsRef.current.onZoomChange?.(newZoom);
92
+ }, []);
93
+ const handlePan = useCallback((newPan) => {
94
+ setPan(newPan);
95
+ optionsRef.current.onPanChange?.(newPan);
96
+ }, []);
97
+ const handleReady = useCallback((canvas) => {
98
+ setIsReady(true);
99
+ optionsRef.current.onReady?.(canvas);
100
+ }, []);
101
+ useEffect(() => {
102
+ console.log("useEffect", canvasInstance);
103
+ if (!canvasInstance) {
104
+ return;
105
+ }
106
+ canvasInstance.on("transform", handleTransform);
107
+ canvasInstance.on("zoom", handleZoom);
108
+ canvasInstance.on("pan", handlePan);
109
+ canvasInstance.on("ready", handleReady);
110
+ if (canvasInstance.transform) {
111
+ setTransform(canvasInstance.transform);
112
+ setZoom(canvasInstance.transform.scale);
113
+ setPan({ x: canvasInstance.transform.translateX, y: canvasInstance.transform.translateY });
114
+ }
115
+ if (canvasInstance.isReady) {
116
+ setIsReady(true);
117
+ optionsRef.current.onReady?.(canvasInstance);
118
+ }
119
+ return () => {
120
+ canvasInstance.off("transform", handleTransform);
121
+ canvasInstance.off("zoom", handleZoom);
122
+ canvasInstance.off("pan", handlePan);
123
+ canvasInstance.off("ready", handleReady);
124
+ };
125
+ }, [canvasInstance]);
126
+ const zoomIn = useCallback((factor = 0.5) => {
127
+ canvasRef.current?.zoomIn(factor);
128
+ }, [canvasRef]);
129
+ const zoomOut = useCallback((factor = 0.5) => {
130
+ canvasRef.current?.zoomOut(factor);
131
+ }, [canvasRef]);
132
+ const resetZoom = useCallback(() => {
133
+ canvasRef.current?.resetZoom();
134
+ }, [canvasRef]);
135
+ const panTo = useCallback((x, y) => {
136
+ canvasRef.current?.panTo(x, y);
137
+ }, [canvasRef]);
138
+ const fitToContent = useCallback(() => {
139
+ canvasRef.current?.fitToContent();
140
+ }, [canvasRef]);
141
+ const centerContent = useCallback(() => {
142
+ canvasRef.current?.centerContent();
143
+ }, [canvasRef]);
144
+ const setTransitionMode = useCallback((enabled) => {
145
+ if (canvasRef.current?.canvas) {
146
+ canvasRef.current.canvas.updateConfig({ enableTransition: enabled });
147
+ }
148
+ }, [canvasRef]);
149
+ const toggleTransitionMode = useCallback(() => {
150
+ if (canvasRef.current?.canvas) {
151
+ const currentConfig = canvasRef.current.canvas.getConfig();
152
+ const newEnableTransition = !currentConfig.enableTransition;
153
+ canvasRef.current.canvas.updateConfig({ enableTransition: newEnableTransition });
154
+ return newEnableTransition;
155
+ }
156
+ return false;
157
+ }, [canvasRef]);
158
+ return {
159
+ canvas: canvasRef.current?.canvas || null,
160
+ initCanvasUtils: handleCanvasInstance,
161
+ transform,
162
+ zoom,
163
+ pan,
164
+ isReady,
165
+ zoomIn,
166
+ zoomOut,
167
+ resetZoom,
168
+ panTo,
169
+ fitToContent,
170
+ centerContent,
171
+ setTransitionMode,
172
+ toggleTransitionMode,
173
+ };
174
+ }
175
+
176
+ export { MarkupCanvas, useMarkupCanvas };
177
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/components/MarkupCanvas.tsx","../src/hooks/useMarkupCanvas.ts"],"sourcesContent":[null,null],"names":["CoreMarkupCanvas","_jsx"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { MarkupCanvas as CoreMarkupCanvas, Transform } from "@markup-canvas/core";
2
+ export interface MarkupCanvasRef {
3
+ canvas: CoreMarkupCanvas | null;
4
+ zoomIn: (factor?: number) => void;
5
+ zoomOut: (factor?: number) => void;
6
+ resetZoom: () => void;
7
+ panTo: (x: number, y: number) => void;
8
+ fitToContent: () => void;
9
+ centerContent: () => void;
10
+ getTransform: () => Transform;
11
+ getZoom: () => number;
12
+ }
13
+ export interface UseMarkupCanvasOptions {
14
+ onTransformChange?: (transform: Transform) => void;
15
+ onZoomChange?: (zoom: number) => void;
16
+ onPanChange?: (pan: {
17
+ x: number;
18
+ y: number;
19
+ }) => void;
20
+ onReady?: (canvas: CoreMarkupCanvas) => void;
21
+ }
22
+ export interface CanvasEventHandlers {
23
+ onZoom?: (zoom: number) => void;
24
+ onPan?: (pan: {
25
+ x: number;
26
+ y: number;
27
+ }) => void;
28
+ onTransform?: (transform: Transform) => void;
29
+ onReady?: (canvas: CoreMarkupCanvas) => void;
30
+ }
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@markup-canvas/react",
3
+ "version": "1.0.0",
4
+ "description": "React components and hooks for markup-canvas",
5
+ "type": "module",
6
+ "main": "dist/index.cjs.js",
7
+ "module": "dist/index.esm.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "dist/",
11
+ "src/"
12
+ ],
13
+ "scripts": {
14
+ "build": "rollup -c",
15
+ "dev": "rollup -c -w",
16
+ "clean": "rm -rf dist",
17
+ "lint": "biome check .",
18
+ "format": "biome format --write .",
19
+ "prepublishOnly": "npm run clean && npm run build"
20
+ },
21
+ "peerDependencies": {
22
+ "react": ">=18.0.0",
23
+ "react-dom": ">=18.0.0",
24
+ "@markup-canvas/core": "^1.0.0"
25
+ },
26
+ "devDependencies": {
27
+ "@biomejs/biome": "2.2.6",
28
+ "@rollup/plugin-node-resolve": "^16.0.3",
29
+ "@rollup/plugin-typescript": "^12.1.4",
30
+ "@types/react": "^19.2.2",
31
+ "@types/react-dom": "^19.2.2",
32
+ "react": "^19.2.0",
33
+ "react-dom": "^19.2.0",
34
+ "rollup": "^4.52.4",
35
+ "rollup-plugin-peer-deps-external": "^2.2.4",
36
+ "typescript": "^5.9.3",
37
+ "tslib": "^2.8.1"
38
+ },
39
+ "keywords": [
40
+ "react",
41
+ "zoom",
42
+ "pan",
43
+ "canvas",
44
+ "component",
45
+ "hook"
46
+ ],
47
+ "author": "Fritz Benning <mail@fritzbenning.de>",
48
+ "license": "CC-BY-NC-4.0",
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "https://github.com/fritzbenning/markup-canvas"
52
+ },
53
+ "bugs": {
54
+ "url": "https://github.com/fritzbenning/markup-canvas/issues"
55
+ },
56
+ "homepage": "https://github.com/fritzbenning/markup-canvas#readme"
57
+ }
@@ -0,0 +1,111 @@
1
+ import { MarkupCanvas as CoreMarkupCanvas, type MarkupCanvasConfig, type Transform } from "@markup-canvas/core";
2
+ import {
3
+ type CSSProperties,
4
+ forwardRef,
5
+ type ReactNode,
6
+ useCallback,
7
+ useEffect,
8
+ useImperativeHandle,
9
+ useMemo,
10
+ useRef,
11
+ useState,
12
+ } from "react";
13
+ import type { MarkupCanvasRef } from "../types/index.js";
14
+
15
+ export interface MarkupCanvasProps extends Omit<MarkupCanvasConfig, "container"> {
16
+ children?: ReactNode;
17
+ className?: string;
18
+ style?: CSSProperties;
19
+ onTransformChange?: (transform: Transform) => void;
20
+ onZoomChange?: (zoom: number) => void;
21
+ onPanChange?: (pan: { x: number; y: number }) => void;
22
+ onReady?: (canvas: CoreMarkupCanvas) => void;
23
+ }
24
+
25
+ export const MarkupCanvas = forwardRef<MarkupCanvasRef, MarkupCanvasProps>(
26
+ ({ children, className, style, onTransformChange, onZoomChange, onPanChange, onReady, ...options }, ref) => {
27
+ const containerRef = useRef<HTMLDivElement>(null);
28
+ const [canvasInstance, setCanvasInstance] = useState<CoreMarkupCanvas | null>(null);
29
+
30
+ useImperativeHandle(
31
+ ref,
32
+ () => ({
33
+ canvas: canvasInstance,
34
+ zoomIn: (factor = 0.1) => canvasInstance?.zoomIn(factor),
35
+ zoomOut: (factor = 0.1) => canvasInstance?.zoomOut(factor),
36
+ resetZoom: () => canvasInstance?.resetZoom(),
37
+ panTo: (x, y) => canvasInstance?.scrollToPoint(x, y),
38
+ fitToContent: () => canvasInstance?.fitToScreen(),
39
+ centerContent: () => canvasInstance?.centerContent(),
40
+ getTransform: () => canvasInstance?.transform || { scale: 1, translateX: 0, translateY: 0 },
41
+ getZoom: () => canvasInstance?.transform?.scale || 1,
42
+ }),
43
+ [canvasInstance]
44
+ );
45
+
46
+ const onTransformChangeRef = useRef(onTransformChange);
47
+ const onZoomChangeRef = useRef(onZoomChange);
48
+ const onPanChangeRef = useRef(onPanChange);
49
+ const onReadyRef = useRef(onReady);
50
+
51
+ onTransformChangeRef.current = onTransformChange;
52
+ onZoomChangeRef.current = onZoomChange;
53
+ onPanChangeRef.current = onPanChange;
54
+ onReadyRef.current = onReady;
55
+
56
+ const handleTransformChange = useCallback((transform: Transform) => {
57
+ onTransformChangeRef.current?.(transform);
58
+ }, []);
59
+
60
+ const handleZoomChange = useCallback((zoom: number) => {
61
+ onZoomChangeRef.current?.(zoom);
62
+ }, []);
63
+
64
+ const handlePanChange = useCallback((pan: { x: number; y: number }) => {
65
+ onPanChangeRef.current?.(pan);
66
+ }, []);
67
+
68
+ const handleReady = useCallback((canvas: CoreMarkupCanvas) => {
69
+ onReadyRef.current?.(canvas);
70
+ }, []);
71
+
72
+ const stableOptions = useMemo(() => options, Object.values(options));
73
+
74
+ useEffect(() => {
75
+ if (!containerRef.current) return;
76
+
77
+ const canvas = new CoreMarkupCanvas(containerRef.current, stableOptions);
78
+ setCanvasInstance(canvas);
79
+
80
+ canvas.on("transform", handleTransformChange);
81
+ canvas.on("zoom", handleZoomChange);
82
+ canvas.on("pan", handlePanChange);
83
+ canvas.on("ready", handleReady);
84
+
85
+ if (canvas.isReady) {
86
+ handleReady(canvas);
87
+ }
88
+
89
+ if (canvas.container && typeof canvas.container.focus === "function") {
90
+ canvas.container.focus();
91
+ }
92
+
93
+ return () => {
94
+ canvas.off("transform", handleTransformChange);
95
+ canvas.off("zoom", handleZoomChange);
96
+ canvas.off("pan", handlePanChange);
97
+ canvas.off("ready", handleReady);
98
+ canvas.cleanup();
99
+ setCanvasInstance(null);
100
+ };
101
+ }, [stableOptions, handleTransformChange, handleZoomChange, handlePanChange, handleReady]);
102
+
103
+ return (
104
+ <div ref={containerRef} className={className} style={{ width: "100%", height: "100%", ...style }}>
105
+ {children}
106
+ </div>
107
+ );
108
+ }
109
+ );
110
+
111
+ MarkupCanvas.displayName = "MarkupCanvas";
@@ -0,0 +1,2 @@
1
+ export type { MarkupCanvasProps } from "./MarkupCanvas.js";
2
+ export { MarkupCanvas } from "./MarkupCanvas.js";
@@ -0,0 +1 @@
1
+ export { useMarkupCanvas } from "./useMarkupCanvas.js";
@@ -0,0 +1,139 @@
1
+ import type { MarkupCanvas, Transform } from "@markup-canvas/core";
2
+ import { type RefObject, useCallback, useEffect, useRef, useState } from "react";
3
+ import type { MarkupCanvasRef, UseMarkupCanvasOptions } from "../types/index.js";
4
+
5
+ export function useMarkupCanvas(canvasRef: RefObject<MarkupCanvasRef | null>, options: UseMarkupCanvasOptions = {}) {
6
+ const [canvasInstance, setCanvasInstance] = useState<MarkupCanvas | null>(null);
7
+ const [transform, setTransform] = useState<Transform>({ scale: 1, translateX: 0, translateY: 0 });
8
+ const [zoom, setZoom] = useState(1);
9
+ const [pan, setPan] = useState({ x: 0, y: 0 });
10
+ const [isReady, setIsReady] = useState(false);
11
+
12
+ const optionsRef = useRef(options);
13
+ optionsRef.current = options;
14
+
15
+ const handleCanvasInstance = useCallback((canvas: MarkupCanvas) => {
16
+ setCanvasInstance(canvas);
17
+ optionsRef.current.onReady?.(canvas);
18
+ }, []);
19
+
20
+ const handleTransform = useCallback((newTransform: Transform) => {
21
+ setTransform(newTransform);
22
+ optionsRef.current.onTransformChange?.(newTransform);
23
+ }, []);
24
+
25
+ const handleZoom = useCallback((newZoom: number) => {
26
+ setZoom(newZoom);
27
+ optionsRef.current.onZoomChange?.(newZoom);
28
+ }, []);
29
+
30
+ const handlePan = useCallback((newPan: { x: number; y: number }) => {
31
+ setPan(newPan);
32
+ optionsRef.current.onPanChange?.(newPan);
33
+ }, []);
34
+
35
+ const handleReady = useCallback((canvas: MarkupCanvas) => {
36
+ setIsReady(true);
37
+ optionsRef.current.onReady?.(canvas);
38
+ }, []);
39
+
40
+ useEffect(() => {
41
+ console.log("useEffect", canvasInstance);
42
+
43
+ if (!canvasInstance) {
44
+ return;
45
+ }
46
+
47
+ canvasInstance.on("transform", handleTransform);
48
+ canvasInstance.on("zoom", handleZoom);
49
+ canvasInstance.on("pan", handlePan);
50
+ canvasInstance.on("ready", handleReady);
51
+
52
+ if (canvasInstance.transform) {
53
+ setTransform(canvasInstance.transform);
54
+ setZoom(canvasInstance.transform.scale);
55
+ setPan({ x: canvasInstance.transform.translateX, y: canvasInstance.transform.translateY });
56
+ }
57
+
58
+ if (canvasInstance.isReady) {
59
+ setIsReady(true);
60
+ optionsRef.current.onReady?.(canvasInstance);
61
+ }
62
+
63
+ return () => {
64
+ canvasInstance.off("transform", handleTransform);
65
+ canvasInstance.off("zoom", handleZoom);
66
+ canvasInstance.off("pan", handlePan);
67
+ canvasInstance.off("ready", handleReady);
68
+ };
69
+ }, [canvasInstance]);
70
+
71
+ const zoomIn = useCallback(
72
+ (factor = 0.5) => {
73
+ canvasRef.current?.zoomIn(factor);
74
+ },
75
+ [canvasRef]
76
+ );
77
+
78
+ const zoomOut = useCallback(
79
+ (factor = 0.5) => {
80
+ canvasRef.current?.zoomOut(factor);
81
+ },
82
+ [canvasRef]
83
+ );
84
+
85
+ const resetZoom = useCallback(() => {
86
+ canvasRef.current?.resetZoom();
87
+ }, [canvasRef]);
88
+
89
+ const panTo = useCallback(
90
+ (x: number, y: number) => {
91
+ canvasRef.current?.panTo(x, y);
92
+ },
93
+ [canvasRef]
94
+ );
95
+
96
+ const fitToContent = useCallback(() => {
97
+ canvasRef.current?.fitToContent();
98
+ }, [canvasRef]);
99
+
100
+ const centerContent = useCallback(() => {
101
+ canvasRef.current?.centerContent();
102
+ }, [canvasRef]);
103
+
104
+ const setTransitionMode = useCallback(
105
+ (enabled: boolean) => {
106
+ if (canvasRef.current?.canvas) {
107
+ canvasRef.current.canvas.updateConfig({ enableTransition: enabled });
108
+ }
109
+ },
110
+ [canvasRef]
111
+ );
112
+
113
+ const toggleTransitionMode = useCallback(() => {
114
+ if (canvasRef.current?.canvas) {
115
+ const currentConfig = canvasRef.current.canvas.getConfig();
116
+ const newEnableTransition = !currentConfig.enableTransition;
117
+ canvasRef.current.canvas.updateConfig({ enableTransition: newEnableTransition });
118
+ return newEnableTransition;
119
+ }
120
+ return false;
121
+ }, [canvasRef]);
122
+
123
+ return {
124
+ canvas: canvasRef.current?.canvas || null,
125
+ initCanvasUtils: handleCanvasInstance,
126
+ transform,
127
+ zoom,
128
+ pan,
129
+ isReady,
130
+ zoomIn,
131
+ zoomOut,
132
+ resetZoom,
133
+ panTo,
134
+ fitToContent,
135
+ centerContent,
136
+ setTransitionMode,
137
+ toggleTransitionMode,
138
+ };
139
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ // Core
2
+ export type { MarkupCanvas as CoreMarkupCanvas, MarkupCanvasConfig, Transform } from "@markup-canvas/core";
3
+ export type { MarkupCanvasProps } from "./components/index.js";
4
+ export { MarkupCanvas } from "./components/index.js";
5
+ // Hooks
6
+ export { useMarkupCanvas } from "./hooks/index.js";
7
+ // Types
8
+ export type { CanvasEventHandlers, MarkupCanvasRef, UseMarkupCanvasOptions } from "./types/index.js";
@@ -0,0 +1,27 @@
1
+ import type { MarkupCanvas as CoreMarkupCanvas, Transform } from "@markup-canvas/core";
2
+
3
+ export interface MarkupCanvasRef {
4
+ canvas: CoreMarkupCanvas | null;
5
+ zoomIn: (factor?: number) => void;
6
+ zoomOut: (factor?: number) => void;
7
+ resetZoom: () => void;
8
+ panTo: (x: number, y: number) => void;
9
+ fitToContent: () => void;
10
+ centerContent: () => void;
11
+ getTransform: () => Transform;
12
+ getZoom: () => number;
13
+ }
14
+
15
+ export interface UseMarkupCanvasOptions {
16
+ onTransformChange?: (transform: Transform) => void;
17
+ onZoomChange?: (zoom: number) => void;
18
+ onPanChange?: (pan: { x: number; y: number }) => void;
19
+ onReady?: (canvas: CoreMarkupCanvas) => void;
20
+ }
21
+
22
+ export interface CanvasEventHandlers {
23
+ onZoom?: (zoom: number) => void;
24
+ onPan?: (pan: { x: number; y: number }) => void;
25
+ onTransform?: (transform: Transform) => void;
26
+ onReady?: (canvas: CoreMarkupCanvas) => void;
27
+ }