@ue-too/board-react-adapter 0.15.0 → 0.17.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.
Files changed (3) hide show
  1. package/index.js +236 -2
  2. package/index.js.map +2 -2
  3. package/package.json +3 -3
package/index.js CHANGED
@@ -1,5 +1,239 @@
1
- import{PointCal as t}from"@ue-too/math";import{useCallback as S,useEffect as I,useRef as L}from"react";import{Board as T}from"@ue-too/board";import{createContext as U,useCallback as O,useContext as V,useEffect as $,useMemo as Y,useRef as A,useSyncExternalStore as q}from"react";import{jsxDEV as j}from"react/jsx-dev-runtime";function P(G){let H=N(),J=G==="position"?"pan":G==="zoomLevel"?"zoom":"rotate",_=A(null);return q((K)=>H.camera.on(J,K),()=>{if(G==="position"){let K=H.camera.position,Q=_.current;if(Q&&Q.x===K.x&&Q.y===K.y)return Q;let X={...K};return _.current=X,X}return H.camera[G]})}function f(){let G=N();return Y(()=>{let J=G.getCameraRig();return{panByViewPort:(_)=>{J.panByViewPort(_)},panByWorld:(_)=>{J.panByWorld(_)},panToWorld:(_)=>{J.panToWorld(_)},panToViewPort:(_)=>{J.panToViewPort(_)},zoomToAtViewPort:(_,K)=>{J.zoomToAt(_,K)},zoomToAtWorld:(_,K)=>{J.zoomToAtWorld(_,K)},zoomTo:(_)=>{J.zoomTo(_)},zoomBy:(_)=>{J.zoomBy(_)},rotateTo:(_)=>{J.rotateTo(_)},rotateBy:(_)=>{J.rotateBy(_)}}},[G])}function w(){let G=N(),H=A(null);return q((J)=>{return G.camera.on("all",J)},()=>{let J=G.camera.position,_=G.camera.rotation,K=G.camera.zoomLevel,Q=H.current;if(Q&&Q.position.x===J.x&&Q.position.y===J.y&&Q.rotation===_&&Q.zoomLevel===K)return Q;let X={position:{...J},rotation:_,zoomLevel:K};return H.current=X,X})}function v(G){let H=N();$(()=>{H.cameraMux=G},[G,H])}function b(){let G=N(),H=O((J)=>{G.inputOrchestrator.processInputEvent(J)},[G]);return $(()=>{return G.disableEventListeners(),()=>{G.enableEventListeners()}},[G]),{processInputEvent:H}}var W=U(null);function Z({children:G}){let H=Y(()=>new T,[]);return j(W.Provider,{value:H,children:G},void 0,!1,void 0,this)}function N(){let G=V(W);if(G==null)throw Error("Board Provider not found");return G}function p(){return N().camera}function u(){let G=N();return q((H)=>G.onCanvasDimensionChange(H),()=>{return G.canvasDimensions})}function h(){let G=N();return O((H)=>{return G.convertWindowPoint2WorldCoord(H)},[G])}function m(G){let H=N();$(()=>{H.kmtParser=G},[G,H])}function d(G){let H=N();$(()=>{H.touchParser=G},[G,H])}function D(G){let H=L(null);I(()=>{let J=(_)=>{G(_),H.current=requestAnimationFrame(J)};return H.current=requestAnimationFrame(J),()=>{if(H.current)cancelAnimationFrame(H.current)}},[G])}function M(G){let H=N(),J=S((_)=>{H.step(_);let K=H.context;if(K==null){console.warn("Canvas context not available");return}G?.(_,K)},[G,H]);D(J)}import{jsxDEV as NG}from"react/jsx-dev-runtime";import{CanvasProxy as z}from"@ue-too/board";import{useCallback as C,useState as y}from"react";function F(){let[G,H]=y(()=>new z);return G}function YG(){let G=F(),H=C((J)=>{if(J==null){G.tearDown();return}G.attach(J)},[G]);return{canvasProxy:G,refCallback:H}}export{d as useCustomTouchEventParser,m as useCustomKMTEventParser,b as useCustomInputHandling,v as useCustomCameraMux,h as useCoordinateConversion,YG as useCanvasProxyWithRef,F as useCanvasProxy,u as useCanvasDimension,f as useCameraInput,P as useBoardCameraState,p as useBoardCamera,N as useBoard,M as useAnimationFrameWithBoard,D as useAnimationFrame,w as useAllBoardCameraState,Z as BoardProvider};
1
+ // src/components/Board.tsx
2
+ import { PointCal } from "@ue-too/math";
2
3
 
3
- //# debugId=E2568A6219EBF3E864756E2164756E21
4
+ // src/hooks/useAnimationFrame.ts
5
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2 } from "react";
6
+
7
+ // src/hooks/useBoardify.tsx
8
+ import {
9
+ Board as Boardify
10
+ } from "@ue-too/board";
11
+ import {
12
+ createContext,
13
+ useCallback,
14
+ useContext,
15
+ useEffect,
16
+ useMemo,
17
+ useRef,
18
+ useSyncExternalStore
19
+ } from "react";
20
+ import { jsxDEV } from "react/jsx-dev-runtime";
21
+ function useBoardCameraState(state) {
22
+ const board = useBoard();
23
+ const stateKey = state === "position" ? "pan" : state === "zoomLevel" ? "zoom" : "rotate";
24
+ const cachedPositionRef = useRef(null);
25
+ return useSyncExternalStore((cb) => board.camera.on(stateKey, cb), () => {
26
+ if (state === "position") {
27
+ const currentPosition = board.camera.position;
28
+ const cached = cachedPositionRef.current;
29
+ if (cached && cached.x === currentPosition.x && cached.y === currentPosition.y) {
30
+ return cached;
31
+ }
32
+ const newPosition = { ...currentPosition };
33
+ cachedPositionRef.current = newPosition;
34
+ return newPosition;
35
+ }
36
+ return board.camera[state];
37
+ });
38
+ }
39
+ function useCameraInput() {
40
+ const board = useBoard();
41
+ const test = useMemo(() => {
42
+ const cameraRig = board.getCameraRig();
43
+ return {
44
+ panByViewPort: (delta) => {
45
+ cameraRig.panByViewPort(delta);
46
+ },
47
+ panByWorld: (delta) => {
48
+ cameraRig.panByWorld(delta);
49
+ },
50
+ panToWorld: (worldPosition) => {
51
+ cameraRig.panToWorld(worldPosition);
52
+ },
53
+ panToViewPort: (viewPortPosition) => {
54
+ cameraRig.panToViewPort(viewPortPosition);
55
+ },
56
+ zoomToAtViewPort: (zoomLevel, at) => {
57
+ cameraRig.zoomToAt(zoomLevel, at);
58
+ },
59
+ zoomToAtWorld: (zoomLevel, at) => {
60
+ cameraRig.zoomToAtWorld(zoomLevel, at);
61
+ },
62
+ zoomTo: (zoomLevel) => {
63
+ cameraRig.zoomTo(zoomLevel);
64
+ },
65
+ zoomBy: (zoomDelta) => {
66
+ cameraRig.zoomBy(zoomDelta);
67
+ },
68
+ rotateTo: (rotation) => {
69
+ cameraRig.rotateTo(rotation);
70
+ },
71
+ rotateBy: (rotationDelta) => {
72
+ cameraRig.rotateBy(rotationDelta);
73
+ }
74
+ };
75
+ }, [board]);
76
+ return test;
77
+ }
78
+ function useAllBoardCameraState() {
79
+ const board = useBoard();
80
+ const cachedSnapshotRef = useRef(null);
81
+ return useSyncExternalStore((cb) => {
82
+ return board.camera.on("all", cb);
83
+ }, () => {
84
+ const currentPosition = board.camera.position;
85
+ const currentRotation = board.camera.rotation;
86
+ const currentZoomLevel = board.camera.zoomLevel;
87
+ const cached = cachedSnapshotRef.current;
88
+ if (cached && cached.position.x === currentPosition.x && cached.position.y === currentPosition.y && cached.rotation === currentRotation && cached.zoomLevel === currentZoomLevel) {
89
+ return cached;
90
+ }
91
+ const newSnapshot = {
92
+ position: { ...currentPosition },
93
+ rotation: currentRotation,
94
+ zoomLevel: currentZoomLevel
95
+ };
96
+ cachedSnapshotRef.current = newSnapshot;
97
+ return newSnapshot;
98
+ });
99
+ }
100
+ function useCustomCameraMux(cameraMux) {
101
+ const board = useBoard();
102
+ useEffect(() => {
103
+ board.cameraMux = cameraMux;
104
+ }, [cameraMux, board]);
105
+ }
106
+ function useCustomInputHandling() {
107
+ const board = useBoard();
108
+ const processInputEvent = useCallback((input) => {
109
+ board.inputOrchestrator.processInputEvent(input);
110
+ }, [board]);
111
+ useEffect(() => {
112
+ board.disableEventListeners();
113
+ return () => {
114
+ board.enableEventListeners();
115
+ };
116
+ }, [board]);
117
+ return {
118
+ processInputEvent
119
+ };
120
+ }
121
+ var BoardContext = createContext(null);
122
+ function BoardProvider({ children }) {
123
+ const board = useMemo(() => new Boardify, []);
124
+ return /* @__PURE__ */ jsxDEV(BoardContext.Provider, {
125
+ value: board,
126
+ children
127
+ }, undefined, false, undefined, this);
128
+ }
129
+ function useBoard() {
130
+ const board = useContext(BoardContext);
131
+ if (board == null) {
132
+ throw new Error("Board Provider not found");
133
+ }
134
+ return board;
135
+ }
136
+ function useBoardCamera() {
137
+ const board = useBoard();
138
+ return board.camera;
139
+ }
140
+ function useCanvasDimension() {
141
+ const board = useBoard();
142
+ return useSyncExternalStore((cb) => board.onCanvasDimensionChange(cb), () => {
143
+ return board.canvasDimensions;
144
+ });
145
+ }
146
+ function useCoordinateConversion() {
147
+ const board = useBoard();
148
+ return useCallback((pointInWindow) => {
149
+ return board.convertWindowPoint2WorldCoord(pointInWindow);
150
+ }, [board]);
151
+ }
152
+ function useCustomKMTEventParser(eventParser) {
153
+ const board = useBoard();
154
+ useEffect(() => {
155
+ board.kmtParser = eventParser;
156
+ }, [eventParser, board]);
157
+ }
158
+ function useCustomTouchEventParser(eventParser) {
159
+ const board = useBoard();
160
+ useEffect(() => {
161
+ board.touchParser = eventParser;
162
+ }, [eventParser, board]);
163
+ }
164
+
165
+ // src/hooks/useAnimationFrame.ts
166
+ function useAnimationFrame(callback) {
167
+ const animationFrameRef = useRef2(null);
168
+ useEffect2(() => {
169
+ const step = (timestamp) => {
170
+ callback(timestamp);
171
+ animationFrameRef.current = requestAnimationFrame(step);
172
+ };
173
+ animationFrameRef.current = requestAnimationFrame(step);
174
+ return () => {
175
+ if (animationFrameRef.current) {
176
+ cancelAnimationFrame(animationFrameRef.current);
177
+ }
178
+ };
179
+ }, [callback]);
180
+ }
181
+ function useAnimationFrameWithBoard(callback) {
182
+ const board = useBoard();
183
+ const animationCallback = useCallback2((timestamp) => {
184
+ board.step(timestamp);
185
+ const ctx = board.context;
186
+ if (ctx == undefined) {
187
+ console.warn("Canvas context not available");
188
+ return;
189
+ }
190
+ callback?.(timestamp, ctx);
191
+ }, [callback, board]);
192
+ useAnimationFrame(animationCallback);
193
+ }
194
+
195
+ // src/components/Board.tsx
196
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
197
+ // src/hooks/useCanvasProxy.ts
198
+ import { CanvasProxy } from "@ue-too/board";
199
+ import { useCallback as useCallback3, useState } from "react";
200
+ function useCanvasProxy() {
201
+ const [canvasProxy, _] = useState(() => new CanvasProxy);
202
+ return canvasProxy;
203
+ }
204
+ function useCanvasProxyWithRef() {
205
+ const canvasProxy = useCanvasProxy();
206
+ const refCallback = useCallback3((canvas) => {
207
+ if (canvas == null) {
208
+ canvasProxy.tearDown();
209
+ return;
210
+ }
211
+ canvasProxy.attach(canvas);
212
+ }, [canvasProxy]);
213
+ return {
214
+ canvasProxy,
215
+ refCallback
216
+ };
217
+ }
218
+ export {
219
+ useCustomTouchEventParser,
220
+ useCustomKMTEventParser,
221
+ useCustomInputHandling,
222
+ useCustomCameraMux,
223
+ useCoordinateConversion,
224
+ useCanvasProxyWithRef,
225
+ useCanvasProxy,
226
+ useCanvasDimension,
227
+ useCameraInput,
228
+ useBoardCameraState,
229
+ useBoardCamera,
230
+ useBoard,
231
+ useAnimationFrameWithBoard,
232
+ useAnimationFrame,
233
+ useAllBoardCameraState,
234
+ BoardProvider
235
+ };
236
+
237
+ //# debugId=890627E4C552420264756E2164756E21
4
238
 
5
239
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -12,7 +12,7 @@
12
12
  "import {\n Board as Boardify,\n KMTEventParser,\n KmtInputStateMachine,\n OutputEvent,\n TouchEventParser,\n} from '@ue-too/board';\nimport { CameraMux, CameraState } from '@ue-too/board/camera';\nimport { Point } from '@ue-too/math';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from 'react';\n\n/**\n * Maps camera state keys to their corresponding event names.\n * @internal\n */\ntype StateToEventKey<K extends keyof CameraState> = K extends 'position'\n ? 'pan'\n : K extends 'zoomLevel'\n ? 'zoom'\n : 'rotate';\n\n/**\n * Hook to subscribe to a specific camera state property with automatic re-rendering.\n *\n * @remarks\n * This hook uses React's `useSyncExternalStore` to efficiently subscribe to camera state changes.\n * It only triggers re-renders when the specified property actually changes, and uses caching\n * to maintain referential equality for object values (like position).\n *\n * **Performance**: The hook is optimized to prevent unnecessary re-renders by:\n * - Caching object values (position) to maintain referential equality\n * - Using `useSyncExternalStore` for efficient subscription management\n * - Only subscribing to the specific state property needed\n *\n * @typeParam K - Key of the camera state to subscribe to\n * @param state - The camera state property to track (\"position\", \"rotation\", or \"zoomLevel\")\n * @returns The current value of the specified camera state property\n *\n * @example\n * ```tsx\n * function CameraInfo() {\n * const position = useBoardCameraState('position');\n * const rotation = useBoardCameraState('rotation');\n * const zoomLevel = useBoardCameraState('zoomLevel');\n *\n * return (\n * <div>\n * Position: {position.x}, {position.y}<br/>\n * Rotation: {rotation}<br/>\n * Zoom: {zoomLevel}\n * </div>\n * );\n * }\n * ```\n *\n * @category Hooks\n * @see {@link useAllBoardCameraState} for subscribing to all camera state at once\n */\nexport function useBoardCameraState<K extends keyof CameraState>(\n state: K\n): CameraState[K] {\n const board = useBoard();\n const stateKey = (\n state === 'position' ? 'pan' : state === 'zoomLevel' ? 'zoom' : 'rotate'\n ) as StateToEventKey<K>;\n const cachedPositionRef = useRef<{ x: number; y: number } | null>(null);\n\n return useSyncExternalStore(\n cb => board.camera.on(stateKey, cb),\n () => {\n // For position (object), we need to cache to avoid creating new objects\n if (state === 'position') {\n const currentPosition = board.camera.position;\n const cached = cachedPositionRef.current;\n\n if (\n cached &&\n cached.x === currentPosition.x &&\n cached.y === currentPosition.y\n ) {\n // Return cached snapshot to maintain referential equality\n return cached as CameraState[K];\n }\n\n // Cache the new position object\n const newPosition = { ...currentPosition };\n cachedPositionRef.current = newPosition;\n return newPosition as CameraState[K];\n }\n\n // For primitive values (rotation, zoomLevel), return directly\n // Object.is works correctly for primitives\n return board.camera[state] as CameraState[K];\n }\n );\n}\n\n/**\n * Hook to get camera control functions for programmatic camera manipulation.\n *\n * @remarks\n * This hook provides a stable set of functions to control the camera programmatically.\n * The functions are memoized and only recreate when the board instance changes.\n *\n * All camera operations go through the camera rig, which enforces boundaries,\n * restrictions, and other constraints configured on the board.\n *\n * @returns Object containing camera control functions:\n * - `panToWorld` - Pan camera to a world position\n * - `panToViewPort` - Pan camera to a viewport position\n * - `zoomTo` - Set camera zoom to specific level\n * - `zoomBy` - Adjust camera zoom by delta\n * - `rotateTo` - Set camera rotation to specific angle\n * - `rotateBy` - Adjust camera rotation by delta\n *\n * @example\n * ```tsx\n * function CameraControls() {\n * const { panToWorld, zoomTo, rotateTo } = useCameraInput();\n *\n * return (\n * <div>\n * <button onClick={() => panToWorld({ x: 0, y: 0 })}>\n * Center Camera\n * </button>\n * <button onClick={() => zoomTo(1.0)}>\n * Reset Zoom\n * </button>\n * <button onClick={() => rotateTo(0)}>\n * Reset Rotation\n * </button>\n * </div>\n * );\n * }\n * ```\n *\n * @category Hooks\n */\nexport function useCameraInput() {\n const board = useBoard();\n\n const test = useMemo(() => {\n const cameraRig = board.getCameraRig();\n\n return {\n panByViewPort: (delta: Point) => {\n cameraRig.panByViewPort(delta);\n },\n panByWorld: (delta: Point) => {\n cameraRig.panByWorld(delta);\n },\n panToWorld: (worldPosition: Point) => {\n cameraRig.panToWorld(worldPosition);\n },\n panToViewPort: (viewPortPosition: Point) => {\n cameraRig.panToViewPort(viewPortPosition);\n },\n zoomToAtViewPort: (zoomLevel: number, at: Point) => {\n cameraRig.zoomToAt(zoomLevel, at);\n },\n zoomToAtWorld: (zoomLevel: number, at: Point) => {\n cameraRig.zoomToAtWorld(zoomLevel, at);\n },\n zoomTo: (zoomLevel: number) => {\n cameraRig.zoomTo(zoomLevel);\n },\n zoomBy: (zoomDelta: number) => {\n cameraRig.zoomBy(zoomDelta);\n },\n rotateTo: (rotation: number) => {\n cameraRig.rotateTo(rotation);\n },\n rotateBy: (rotationDelta: number) => {\n cameraRig.rotateBy(rotationDelta);\n },\n };\n }, [board]);\n\n return test;\n}\n\n/**\n * Hook to subscribe to all camera state properties with automatic re-rendering.\n *\n * @remarks\n * This hook provides a snapshot of all camera state (position, rotation, zoomLevel) and\n * re-renders only when any of these values change. It's more efficient than using multiple\n * {@link useBoardCameraState} calls when you need all state properties.\n *\n * **Performance**: The hook uses snapshot caching to maintain referential equality when\n * values haven't changed, preventing unnecessary re-renders in child components.\n *\n * @returns Object containing:\n * - `position` - Current camera position {x, y}\n * - `rotation` - Current camera rotation in radians\n * - `zoomLevel` - Current camera zoom level\n *\n * @example\n * ```tsx\n * function CameraStateDisplay() {\n * const { position, rotation, zoomLevel } = useAllBoardCameraState();\n *\n * return (\n * <div>\n * <h3>Camera State</h3>\n * <p>Position: ({position.x.toFixed(2)}, {position.y.toFixed(2)})</p>\n * <p>Rotation: {rotation.toFixed(2)} rad</p>\n * <p>Zoom: {zoomLevel.toFixed(2)}x</p>\n * </div>\n * );\n * }\n * ```\n *\n * @category Hooks\n * @see {@link useBoardCameraState} for subscribing to individual state properties\n */\nexport function useAllBoardCameraState() {\n const board = useBoard();\n const cachedSnapshotRef = useRef<{\n position: { x: number; y: number };\n rotation: number;\n zoomLevel: number;\n } | null>(null);\n\n return useSyncExternalStore(\n cb => {\n return board.camera.on('all', cb);\n },\n () => {\n const currentPosition = board.camera.position;\n const currentRotation = board.camera.rotation;\n const currentZoomLevel = board.camera.zoomLevel;\n\n // Check if values actually changed\n const cached = cachedSnapshotRef.current;\n if (\n cached &&\n cached.position.x === currentPosition.x &&\n cached.position.y === currentPosition.y &&\n cached.rotation === currentRotation &&\n cached.zoomLevel === currentZoomLevel\n ) {\n // Return cached snapshot to maintain referential equality\n return cached;\n }\n\n // Create new snapshot only when values changed\n const newSnapshot = {\n position: { ...currentPosition },\n rotation: currentRotation,\n zoomLevel: currentZoomLevel,\n };\n cachedSnapshotRef.current = newSnapshot;\n return newSnapshot;\n }\n );\n}\n\n/**\n * Hook to set a custom camera multiplexer on the board.\n *\n * @remarks\n * This hook allows you to replace the board's default camera mux with a custom implementation.\n * Useful when you need custom input coordination, animation control, or state-based input blocking.\n *\n * The camera mux is updated whenever the provided `cameraMux` instance changes.\n *\n * @param cameraMux - Custom camera mux implementation to use\n *\n * @example\n * ```tsx\n * function CustomMuxBoard() {\n * const myCustomMux = useMemo(() => {\n * return createCameraMuxWithAnimationAndLock(camera);\n * }, []);\n *\n * useCustomCameraMux(myCustomMux);\n *\n * return <Board />;\n * }\n * ```\n *\n * @category Hooks\n * @see {@link CameraMux} from @ue-too/board for camera mux interface\n */\nexport function useCustomCameraMux(cameraMux: CameraMux) {\n const board = useBoard();\n\n useEffect(() => {\n board.cameraMux = cameraMux;\n }, [cameraMux, board]);\n}\n\n/**\n * The custom input handling logic is before everything else. To use this hook, you would need to handle the event from the canvas and pass down the result to the `processInputEvent` function.\n * @returns Object containing the `processInputEvent` function\n * @example\n * ```typescript\n * const { processInputEvent } = useCustomInputHandling();\n *\n * const handlePointerDown = (e: React.PointerEvent<HTMLCanvasElement>) => {\n * // custom logic to determine the user input\n *\n * // if the user input is valid, pass it to the `processInputEvent` function\n * // e.g. pass the pan event down the input handling system\n * processInputEvent({\n * type: \"pan\",\n * delta: {\n * x: 10,\n * y: 10,\n * },\n * });\n * }\n * ```\n */\nexport function useCustomInputHandling() {\n const board = useBoard();\n\n const processInputEvent = useCallback(\n (input: OutputEvent) => {\n board.inputOrchestrator.processInputEvent(input);\n },\n [board]\n );\n\n useEffect(() => {\n board.disableEventListeners();\n\n return () => {\n board.enableEventListeners();\n };\n }, [board]);\n\n return {\n processInputEvent,\n };\n}\n\n/**\n * React context for sharing a Board instance across components.\n * @internal\n */\nconst BoardContext = createContext<Boardify | null>(null);\n\n/**\n * Provider component for sharing a Board instance across the component tree.\n *\n * @remarks\n * This component creates a single Board instance and makes it available to all child\n * components via the {@link useBoard} hook. This is the recommended way to use the\n * board in React applications when you need to access it from multiple components.\n *\n * The board instance is created once when the provider mounts and persists for the\n * lifetime of the provider.\n *\n * @param props - Component props\n * @param props.children - Child components that will have access to the board\n *\n * @example\n * ```tsx\n * function App() {\n * return (\n * <BoardProvider>\n * <Board width={800} height={600} />\n * <CameraControls />\n * <CameraStateDisplay />\n * </BoardProvider>\n * );\n * }\n * ```\n *\n * @category Components\n * @see {@link useBoard} for accessing the board instance\n */\nexport function BoardProvider({ children }: { children: React.ReactNode }) {\n const board = useMemo(() => new Boardify(), []);\n return (\n <BoardContext.Provider value={board}>{children}</BoardContext.Provider>\n );\n}\n\n/**\n * Hook to access the Board instance from context.\n *\n * @remarks\n * This hook retrieves the Board instance provided by {@link BoardProvider}.\n * It must be used within a component that is a descendant of BoardProvider,\n * otherwise it will throw an error.\n *\n * @returns The Board instance from context\n * @throws Error if used outside of BoardProvider\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const board = useBoard();\n *\n * useEffect(() => {\n * // Configure board\n * board.camera.boundaries = { min: { x: -1000, y: -1000 }, max: { x: 1000, y: 1000 } };\n * }, [board]);\n *\n * return <div>Board ready</div>;\n * }\n * ```\n *\n * @category Hooks\n * @see {@link BoardProvider} for providing the board instance\n */\nexport function useBoard() {\n const board = useContext(BoardContext);\n if (board == null) {\n throw new Error('Board Provider not found');\n }\n return board;\n}\n\n/**\n * Hook to access the camera instance from the Board context.\n *\n * @remarks\n * This is a convenience hook that returns the camera from the board instance.\n * Equivalent to calling `useBoard().camera` but more concise.\n *\n * @returns The camera instance from the board\n * @throws Error if used outside of BoardProvider\n *\n * @example\n * ```tsx\n * function CameraConfig() {\n * const camera = useBoardCamera();\n *\n * useEffect(() => {\n * camera.setMinZoomLevel(0.5);\n * camera.setMaxZoomLevel(4.0);\n * }, [camera]);\n *\n * return null;\n * }\n * ```\n *\n * @category Hooks\n * @see {@link useBoard} for accessing the full board instance\n */\nexport function useBoardCamera() {\n const board = useBoard();\n return board.camera;\n}\n\nexport function useCanvasDimension() {\n const board = useBoard();\n\n return useSyncExternalStore(\n cb => board.onCanvasDimensionChange(cb),\n () => {\n return board.canvasDimensions;\n }\n );\n}\n\nexport function useCoordinateConversion() {\n const board = useBoard();\n return useCallback(\n (pointInWindow: Point) => {\n return board.convertWindowPoint2WorldCoord(pointInWindow);\n },\n [board]\n );\n}\n\nexport function useCustomKMTEventParser(eventParser: KMTEventParser) {\n const board = useBoard();\n\n useEffect(() => {\n board.kmtParser = eventParser;\n }, [eventParser, board]);\n}\n\nexport function useCustomTouchEventParser(eventParser: TouchEventParser) {\n const board = useBoard();\n\n useEffect(() => {\n board.touchParser = eventParser;\n }, [eventParser, board]);\n}\n",
13
13
  "import { CanvasProxy } from '@ue-too/board';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\nexport function useCanvasProxy() {\n const [canvasProxy, _] = useState(() => new CanvasProxy());\n\n return canvasProxy;\n}\n\nexport function useCanvasProxyWithRef() {\n const canvasProxy = useCanvasProxy();\n const refCallback = useCallback(\n (canvas: HTMLCanvasElement | null) => {\n if (canvas == null) {\n canvasProxy.tearDown();\n return;\n }\n canvasProxy.attach(canvas);\n },\n [canvasProxy]\n );\n\n return {\n canvasProxy,\n refCallback,\n };\n}\n"
14
14
  ],
15
- "mappings": "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",
16
- "debugId": "E2568A6219EBF3E864756E2164756E21",
15
+ "mappings": "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",
16
+ "debugId": "890627E4C552420264756E2164756E21",
17
17
  "names": []
18
18
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ue-too/board-react-adapter",
3
3
  "type": "module",
4
- "version": "0.15.0",
4
+ "version": "0.17.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/ue-too/ue-too.git"
@@ -23,8 +23,8 @@
23
23
  "types": "./index.d.ts",
24
24
  "module": "./index.js",
25
25
  "dependencies": {
26
- "@ue-too/board": "^0.15.0",
27
- "@ue-too/math": "^0.15.0"
26
+ "@ue-too/board": "^0.17.0",
27
+ "@ue-too/math": "^0.17.0"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "react": "^19.0.1",