@canvas-harness/react 0.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/dist/index.cjs +1675 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +462 -0
- package/dist/index.d.ts +462 -0
- package/dist/index.js +1653 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as _canvas_harness_core from '@canvas-harness/core';
|
|
3
|
+
import { Node, CanvasStore, EditorAdapterFactory, Renderer, CanvasBackground, NodeId, EdgeId, Edge, CameraState, PointerInfo, InteractionMode, InteractionState, PresenceState, ClientId } from '@canvas-harness/core';
|
|
4
|
+
import { ReactNode, CSSProperties } from 'react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Defaults applied to every edge the arrow tool creates. Lets a
|
|
8
|
+
* consumer (e.g. a style-memory hook) inject the user's last-used
|
|
9
|
+
* pathStyle / arrowheads / style without forcing every edge through
|
|
10
|
+
* a custom factory.
|
|
11
|
+
*/
|
|
12
|
+
type ArrowToolDefaults = {
|
|
13
|
+
pathStyle?: _canvas_harness_core.PathStyle;
|
|
14
|
+
style?: _canvas_harness_core.EdgeStyle;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Theme resolver — see ARCHITECTURE.md §13.10. Returns a color string
|
|
19
|
+
* (or undefined to fall back to the built-in defaults) for a given
|
|
20
|
+
* design-system token + context.
|
|
21
|
+
*/
|
|
22
|
+
type ThemeResolver = (token: string, ctx?: {
|
|
23
|
+
node?: Node;
|
|
24
|
+
state?: 'idle' | 'hover' | 'selected' | 'drag';
|
|
25
|
+
}) => string | undefined;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Pointer info passed to `onClick` / `onDoubleClick`. Includes the
|
|
29
|
+
* point in both screen space and world space so consumers don't have
|
|
30
|
+
* to convert.
|
|
31
|
+
*/
|
|
32
|
+
type CanvasPointerEvent = {
|
|
33
|
+
/** Position relative to the canvas element. */
|
|
34
|
+
screen: {
|
|
35
|
+
x: number;
|
|
36
|
+
y: number;
|
|
37
|
+
};
|
|
38
|
+
/** Position in scene coordinates (camera-adjusted). */
|
|
39
|
+
world: {
|
|
40
|
+
x: number;
|
|
41
|
+
y: number;
|
|
42
|
+
};
|
|
43
|
+
/** Tool active when the event fired. */
|
|
44
|
+
tool: string;
|
|
45
|
+
/** The native MouseEvent — read modifiers, button, etc. */
|
|
46
|
+
native: MouseEvent;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Fired on pointerup after a drag-to-create gesture (non-select tool,
|
|
50
|
+
* drag larger than ~5px). The consumer maps the rect into a new node
|
|
51
|
+
* (defaults, type, style — all consumer policy).
|
|
52
|
+
*/
|
|
53
|
+
type CanvasCreateDragEvent = {
|
|
54
|
+
/** Bounding rect of the drag, in world coordinates. */
|
|
55
|
+
rect: {
|
|
56
|
+
x: number;
|
|
57
|
+
y: number;
|
|
58
|
+
w: number;
|
|
59
|
+
h: number;
|
|
60
|
+
};
|
|
61
|
+
/** Tool active when the gesture ended. */
|
|
62
|
+
tool: string;
|
|
63
|
+
native: PointerEvent;
|
|
64
|
+
};
|
|
65
|
+
type CanvasProps = {
|
|
66
|
+
/**
|
|
67
|
+
* Optional — when omitted, the component reads the store from
|
|
68
|
+
* `<CanvasProvider>` context. Pass directly for tests or
|
|
69
|
+
* standalone-canvas use.
|
|
70
|
+
*/
|
|
71
|
+
store?: CanvasStore;
|
|
72
|
+
/**
|
|
73
|
+
* Current tool. The library handles `'select'` and `'arrow'`
|
|
74
|
+
* internally; any other string passes through to `onClick` /
|
|
75
|
+
* `onCreateDrag` so consumers can wire their own shape-create /
|
|
76
|
+
* text-tool / lasso / ... logic.
|
|
77
|
+
*/
|
|
78
|
+
tool: string;
|
|
79
|
+
/** Theme resolver — see ARCHITECTURE.md §13.10 for the token catalog. */
|
|
80
|
+
theme?: ThemeResolver;
|
|
81
|
+
/**
|
|
82
|
+
* Pluggable in-place editor factory; defaults to the built-in
|
|
83
|
+
* `<textarea>`. Implement to swap in Lexical / ProseMirror / TipTap.
|
|
84
|
+
*/
|
|
85
|
+
editorAdapter?: EditorAdapterFactory;
|
|
86
|
+
/** Called once when the renderer is mounted. Useful for perf overlays. */
|
|
87
|
+
onRenderer?: (r: Renderer) => void;
|
|
88
|
+
/** Click on the canvas surface (not over a node handle). */
|
|
89
|
+
onClick?: (e: CanvasPointerEvent) => void;
|
|
90
|
+
/** Double-click on the surface. The library has already triggered
|
|
91
|
+
* `beginEdit` if the click landed on a node body. */
|
|
92
|
+
onDoubleClick?: (e: CanvasPointerEvent) => void;
|
|
93
|
+
/**
|
|
94
|
+
* Drag-to-create — fires on pointerup when the user dragged with a
|
|
95
|
+
* non-select tool. Sub-threshold drags fall through to `onClick`.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* onCreateDrag={({ rect, tool }) => {
|
|
99
|
+
* if (tool === 'rect') store.addNode({ ...rect, type: 'rect', ... })
|
|
100
|
+
* }}
|
|
101
|
+
*/
|
|
102
|
+
onCreateDrag?: (e: CanvasCreateDragEvent) => void;
|
|
103
|
+
/**
|
|
104
|
+
* Defaults applied to every edge the built-in arrow tool creates.
|
|
105
|
+
* Lets a consumer remember the user's last-used pathStyle / style /
|
|
106
|
+
* arrowheads. Shape + text tools route through `onClick` /
|
|
107
|
+
* `onCreateDrag` so consumer controls those defaults directly.
|
|
108
|
+
*/
|
|
109
|
+
arrowDefaults?: ArrowToolDefaults;
|
|
110
|
+
/**
|
|
111
|
+
* Page background + optional infinite dot/grid pattern. Local-only
|
|
112
|
+
* (not part of the synced scene). Update by changing the prop —
|
|
113
|
+
* `<Canvas>` calls `renderer.setBackground` and forces a repaint.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* <Canvas background={{ color: '#fffaf3', pattern: 'dots', gap: 24 }} />
|
|
117
|
+
*/
|
|
118
|
+
background?: CanvasBackground;
|
|
119
|
+
/**
|
|
120
|
+
* Render a custom node's React subtree. Called once per
|
|
121
|
+
* library-mounted custom-node id; positioning is handled by the
|
|
122
|
+
* overlay container (consumer fills the slot).
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* renderCustomNodeView={id => {
|
|
126
|
+
* const node = store.getNode(id)
|
|
127
|
+
* if (node?.type === 'chart-card') return <ChartCardView node={node} />
|
|
128
|
+
* return null
|
|
129
|
+
* }}
|
|
130
|
+
*/
|
|
131
|
+
renderCustomNodeView?: (id: NodeId) => ReactNode;
|
|
132
|
+
/** Extra content rendered inside the canvas absolute container. */
|
|
133
|
+
children?: ReactNode;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Mounts the canvas surface (static + interactive layers + DOM overlay
|
|
137
|
+
* for custom-node views + in-place editor mount). Owns the renderer
|
|
138
|
+
* lifecycle, gesture hooks, resize observer.
|
|
139
|
+
*
|
|
140
|
+
* Use inside a {@link CanvasProvider} (or pass `store` directly).
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* function App() {
|
|
144
|
+
* const store = useRef(createCanvasStore()).current
|
|
145
|
+
* const [tool, setTool] = useState('select')
|
|
146
|
+
* return (
|
|
147
|
+
* <CanvasProvider store={store}>
|
|
148
|
+
* <Canvas
|
|
149
|
+
* tool={tool}
|
|
150
|
+
* onClick={e => console.log('click at', e.world)}
|
|
151
|
+
* onCreateDrag={e => {
|
|
152
|
+
* store.addNode({ id: asNodeId(store.generateId()), type: e.tool, ...e.rect, angle: 0, z: 0, groups: [] })
|
|
153
|
+
* }}
|
|
154
|
+
* />
|
|
155
|
+
* <Toolbar onSelect={setTool} />
|
|
156
|
+
* </CanvasProvider>
|
|
157
|
+
* )
|
|
158
|
+
* }
|
|
159
|
+
*/
|
|
160
|
+
declare function Canvas(props: CanvasProps): react_jsx_runtime.JSX.Element;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Bird's-eye overview of the entire scene + a viewport rectangle
|
|
164
|
+
* showing where the camera is. Click or drag inside to pan.
|
|
165
|
+
*
|
|
166
|
+
* Perf model — see IMPROVEMENTS.md and core/render/minimap.ts:
|
|
167
|
+
* - Scene content is rendered into an offscreen-canvas cache **once
|
|
168
|
+
* per committed batch** (`'change'` event). Cost: O(N) per
|
|
169
|
+
* commit, not per frame.
|
|
170
|
+
* - On camera changes (pan/zoom), only the viewport rectangle is
|
|
171
|
+
* redrawn over the cached image. Cost: O(1) per frame.
|
|
172
|
+
* - Above `maxNodes`, the content render is skipped and a small
|
|
173
|
+
* placeholder text is shown instead.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* <Minimap width={200} height={150} position="bottom-right" />
|
|
177
|
+
*/
|
|
178
|
+
type MinimapProps = {
|
|
179
|
+
/** Map width in CSS px. Default 200. */
|
|
180
|
+
width?: number;
|
|
181
|
+
/** Map height in CSS px. Default 150. */
|
|
182
|
+
height?: number;
|
|
183
|
+
/** Above this many nodes, content render is skipped (placeholder
|
|
184
|
+
* shown instead). Default 5000. */
|
|
185
|
+
maxNodes?: number;
|
|
186
|
+
/** Fixed-position corner shortcut. Use `style` for custom placement. */
|
|
187
|
+
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
188
|
+
/** Override container styles entirely (skip `position`). */
|
|
189
|
+
style?: CSSProperties;
|
|
190
|
+
/** Color of the viewport rect overlay. Default brand blue. */
|
|
191
|
+
viewportColor?: string;
|
|
192
|
+
/** Background color drawn behind the cached content + applied to the
|
|
193
|
+
* default container background. Default white. */
|
|
194
|
+
backgroundColor?: string;
|
|
195
|
+
/** Container border color (the surrounding chip). Default light slate. */
|
|
196
|
+
borderColor?: string;
|
|
197
|
+
/** Fallback node color when a node has no `style.backgroundColor`.
|
|
198
|
+
* Default neutral slate. */
|
|
199
|
+
defaultNodeColor?: string;
|
|
200
|
+
};
|
|
201
|
+
declare function Minimap({ width, height, maxNodes, position, style, viewportColor, backgroundColor, borderColor, defaultNodeColor, }: MinimapProps): react_jsx_runtime.JSX.Element;
|
|
202
|
+
|
|
203
|
+
type CanvasProviderProps = {
|
|
204
|
+
store: CanvasStore;
|
|
205
|
+
children: ReactNode;
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Provides a {@link CanvasStore} to descendant hooks via context.
|
|
209
|
+
* Wrap your app (or just the canvas + its panels) once at the top
|
|
210
|
+
* level. `<Canvas>` reads the same store from context.
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* const store = useRef(createCanvasStore()).current
|
|
214
|
+
* <CanvasProvider store={store}>
|
|
215
|
+
* <Toolbar />
|
|
216
|
+
* <Canvas tool="select" />
|
|
217
|
+
* <Sidebar />
|
|
218
|
+
* </CanvasProvider>
|
|
219
|
+
*/
|
|
220
|
+
declare function CanvasProvider({ store, children }: CanvasProviderProps): react_jsx_runtime.JSX.Element;
|
|
221
|
+
/**
|
|
222
|
+
* Returns the {@link CanvasStore} from context. Use this when you need
|
|
223
|
+
* to mutate the store from event handlers (e.g. tool buttons, side
|
|
224
|
+
* panels). For reactive reads, prefer the more specific hooks
|
|
225
|
+
* (`useNode`, `useSelection`, `useCamera`, ...).
|
|
226
|
+
*
|
|
227
|
+
* Throws if called outside a `<CanvasProvider>`.
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* function ClearButton() {
|
|
231
|
+
* const store = useCanvasStore()
|
|
232
|
+
* return <button onClick={() => store.batch(() => {
|
|
233
|
+
* for (const n of store.getAllNodes()) store.removeNode(n.id)
|
|
234
|
+
* })}>Clear</button>
|
|
235
|
+
* }
|
|
236
|
+
*/
|
|
237
|
+
declare function useCanvasStore(): CanvasStore;
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Subscribes to a single node. Re-renders **only** when that node
|
|
241
|
+
* changes — moves on other nodes are free.
|
|
242
|
+
*
|
|
243
|
+
* The recommended hook for custom-node React views, layer panels keyed
|
|
244
|
+
* by id, and any per-node UI.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* function StickyView({ id }: { id: NodeId }) {
|
|
248
|
+
* const node = useNode(id)
|
|
249
|
+
* if (!node) return null
|
|
250
|
+
* return <div>{node.content ?? 'empty'}</div>
|
|
251
|
+
* }
|
|
252
|
+
*/
|
|
253
|
+
declare function useNode(id: NodeId): Node | undefined;
|
|
254
|
+
/**
|
|
255
|
+
* Returns every node (optionally filtered). Re-renders on **every**
|
|
256
|
+
* committed batch — expensive. Use for sidebars / minimaps / layer
|
|
257
|
+
* panels that legitimately see all nodes; never inside per-node
|
|
258
|
+
* components.
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* // Layer panel: list every node grouped by type.
|
|
262
|
+
* function Layers() {
|
|
263
|
+
* const nodes = useNodes()
|
|
264
|
+
* return <ul>{nodes.map(n => <li key={n.id}>{n.type}</li>)}</ul>
|
|
265
|
+
* }
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* // Filtered: only text nodes.
|
|
269
|
+
* const textNodes = useNodes(n => n.type === 'text')
|
|
270
|
+
*/
|
|
271
|
+
declare function useNodes(predicate?: (n: Node) => boolean): Node[];
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Subscribes to a single edge. Re-renders only when that edge mutates
|
|
275
|
+
* (style change, endpoint reconnect, etc.). Use inside per-edge UI
|
|
276
|
+
* like a label component or an inspector panel.
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* function EdgeLabel({ id }: { id: EdgeId }) {
|
|
280
|
+
* const edge = useEdge(id)
|
|
281
|
+
* return <span>{edge?.style?.strokeColor ?? 'default'}</span>
|
|
282
|
+
* }
|
|
283
|
+
*/
|
|
284
|
+
declare function useEdge(id: EdgeId): Edge | undefined;
|
|
285
|
+
/**
|
|
286
|
+
* Returns every edge (optionally filtered). Re-renders on every
|
|
287
|
+
* committed batch — expensive. Use for inspector panels or minimaps;
|
|
288
|
+
* never inside per-edge components.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* const dashed = useEdges(e => e.style?.strokeStyle === 'dashed')
|
|
292
|
+
*/
|
|
293
|
+
declare function useEdges(predicate?: (e: Edge) => boolean): Edge[];
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Returns the current selection — an array of node and/or edge ids.
|
|
297
|
+
* Re-renders only when the selection changes.
|
|
298
|
+
*
|
|
299
|
+
* @example
|
|
300
|
+
* function DeleteButton() {
|
|
301
|
+
* const store = useCanvasStore()
|
|
302
|
+
* const selection = useSelection()
|
|
303
|
+
* return (
|
|
304
|
+
* <button disabled={selection.length === 0} onClick={() => {
|
|
305
|
+
* for (const id of selection) {
|
|
306
|
+
* if (store.getNode(id as NodeId)) store.removeNode(id as NodeId)
|
|
307
|
+
* else store.removeEdge(id as EdgeId)
|
|
308
|
+
* }
|
|
309
|
+
* }}>
|
|
310
|
+
* Delete ({selection.length})
|
|
311
|
+
* </button>
|
|
312
|
+
* )
|
|
313
|
+
* }
|
|
314
|
+
*/
|
|
315
|
+
declare function useSelection(): (NodeId | EdgeId)[];
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Returns the current camera (`{ x, y, z }`). Re-renders on every
|
|
319
|
+
* camera change — pan / zoom / `store.setCamera(...)`.
|
|
320
|
+
*
|
|
321
|
+
* Useful for status bars, minimaps, or positioning overlays in world
|
|
322
|
+
* coordinates.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* function ZoomReadout() {
|
|
326
|
+
* const { z } = useCamera()
|
|
327
|
+
* return <span>{Math.round(z * 100)}%</span>
|
|
328
|
+
* }
|
|
329
|
+
*/
|
|
330
|
+
declare function useCamera(): CameraState;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Full interaction state. Fires on **any** change — mode flips,
|
|
334
|
+
* pointermoves, drag delta updates, marquee rect updates, ...
|
|
335
|
+
*
|
|
336
|
+
* Most consumers want a narrower hook (`useInteractionMode`,
|
|
337
|
+
* `useCursor`, `useIsMoving`, `useDraggedIds`). Reach for this one only
|
|
338
|
+
* if you need multiple fields together.
|
|
339
|
+
*
|
|
340
|
+
* @example
|
|
341
|
+
* const state = useInteractionState()
|
|
342
|
+
* if (state.mode === 'marqueeing') drawMarqueeOverlay(state.marqueeRect)
|
|
343
|
+
*/
|
|
344
|
+
declare function useInteractionState(): InteractionState;
|
|
345
|
+
/**
|
|
346
|
+
* Just the interaction mode. Re-renders only on mode transitions,
|
|
347
|
+
* never on pointermove.
|
|
348
|
+
*
|
|
349
|
+
* Use to gate heavy effects ("only run X when mode === 'idle'") or
|
|
350
|
+
* disable UI affordances during a drag.
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* const mode = useInteractionMode()
|
|
354
|
+
* <button disabled={mode !== 'idle'}>Run AI suggestion</button>
|
|
355
|
+
*/
|
|
356
|
+
declare function useInteractionMode(): InteractionMode;
|
|
357
|
+
/**
|
|
358
|
+
* Latest pointer info — `worldX/Y`, `screenX/Y`, `pointerType`,
|
|
359
|
+
* optional `pressure` (for pens). Updated on every pointermove.
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* const cursor = useCursor()
|
|
363
|
+
* <div>x: {cursor?.worldX.toFixed(1)}</div>
|
|
364
|
+
*/
|
|
365
|
+
declare function useCursor(): PointerInfo | null;
|
|
366
|
+
/**
|
|
367
|
+
* `true` while the user is panning, zooming, dragging, resizing, or
|
|
368
|
+
* rotating. Derived from {@link useInteractionMode}.
|
|
369
|
+
*
|
|
370
|
+
* Useful for skipping expensive renders during motion (the library
|
|
371
|
+
* does this internally for the bitmap cache; consumers can do the same
|
|
372
|
+
* for custom-node React views).
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* const isMoving = useIsMoving()
|
|
376
|
+
* return isMoving ? <Skeleton /> : <ExpensiveChart />
|
|
377
|
+
*/
|
|
378
|
+
declare function useIsMoving(): boolean;
|
|
379
|
+
declare function useDraggedIds(): readonly (NodeId | EdgeId)[];
|
|
380
|
+
/**
|
|
381
|
+
* `true` when the most recent pointer was a stylus. Falls back to
|
|
382
|
+
* `false` before any pointer event has fired.
|
|
383
|
+
*
|
|
384
|
+
* Use to surface pen-specific UI (pressure-aware tools, ink hints).
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* const isPen = useIsPenActive()
|
|
388
|
+
* {isPen && <PressureToolbar />}
|
|
389
|
+
*/
|
|
390
|
+
declare function useIsPenActive(): boolean;
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* This client's own presence — cursor / selection / editing / color /
|
|
394
|
+
* name. Re-renders when local presence updates.
|
|
395
|
+
*
|
|
396
|
+
* Set local presence via `store.presence.setLocal({...})`. The library
|
|
397
|
+
* forwards it through the attached `SyncAdapter` automatically.
|
|
398
|
+
*
|
|
399
|
+
* @example
|
|
400
|
+
* const me = useLocalPresence()
|
|
401
|
+
* <div>signed in as {me.name}</div>
|
|
402
|
+
*/
|
|
403
|
+
declare function useLocalPresence(): PresenceState;
|
|
404
|
+
/**
|
|
405
|
+
* Reads remote presence.
|
|
406
|
+
*
|
|
407
|
+
* - `usePresence(clientId)` — one remote client's state, or
|
|
408
|
+
* `undefined` if they've left.
|
|
409
|
+
* - `usePresence()` — map of every remote client. Re-renders on every
|
|
410
|
+
* remote update (join / leave / cursor move). Use sparingly.
|
|
411
|
+
*
|
|
412
|
+
* @example
|
|
413
|
+
* // Paint every remote cursor.
|
|
414
|
+
* const remotes = usePresence()
|
|
415
|
+
* for (const p of remotes.values()) drawCursor(p)
|
|
416
|
+
*
|
|
417
|
+
* @example
|
|
418
|
+
* // Just one peer.
|
|
419
|
+
* const peer = usePresence(asClientId('alice'))
|
|
420
|
+
*/
|
|
421
|
+
declare function usePresence(clientId: ClientId): PresenceState | undefined;
|
|
422
|
+
declare function usePresence(): ReadonlyMap<ClientId, PresenceState>;
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* `true` when there's something to undo. Updates after every committed
|
|
426
|
+
* batch (the only thing that changes the stack).
|
|
427
|
+
*
|
|
428
|
+
* @example
|
|
429
|
+
* const canUndo = useCanUndo()
|
|
430
|
+
* <button disabled={!canUndo} onClick={() => store.undo()}>Undo</button>
|
|
431
|
+
*/
|
|
432
|
+
declare function useCanUndo(): boolean;
|
|
433
|
+
/**
|
|
434
|
+
* `true` when there's something to redo. See {@link useCanUndo}.
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* const canRedo = useCanRedo()
|
|
438
|
+
* <button disabled={!canRedo} onClick={() => store.redo()}>Redo</button>
|
|
439
|
+
*/
|
|
440
|
+
declare function useCanRedo(): boolean;
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* useInteraction — owns the gesture state machine for the Select tool.
|
|
444
|
+
*
|
|
445
|
+
* Handles click-select, shift-toggle, marquee, drag, resize. Talks to the
|
|
446
|
+
* store via setInteractionState (transient) and applyOp/updateNode (commits).
|
|
447
|
+
*
|
|
448
|
+
* The pan/zoom hook (usePanZoom) handles middle-button pan and wheel/pinch
|
|
449
|
+
* zoom; this hook handles primary-button gestures only.
|
|
450
|
+
*/
|
|
451
|
+
|
|
452
|
+
type InteractionTool = 'select' | 'rect' | 'ellipse' | 'diamond' | 'capsule' | 'arrow' | 'text';
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* @canvas-harness/react
|
|
456
|
+
*
|
|
457
|
+
* React bindings: `<Canvas>` component + data/interaction/presence/history hooks.
|
|
458
|
+
* See ARCHITECTURE.md §13 and IMPLEMENTATION.md Phase 9.
|
|
459
|
+
*/
|
|
460
|
+
declare const VERSION = "0.0.0";
|
|
461
|
+
|
|
462
|
+
export { type ArrowToolDefaults, Canvas, type CanvasCreateDragEvent, type CanvasPointerEvent, type CanvasProps, CanvasProvider, type CanvasProviderProps, type InteractionTool, Minimap, type MinimapProps, type ThemeResolver, VERSION, useCamera, useCanRedo, useCanUndo, useCanvasStore, useCursor, useDraggedIds, useEdge, useEdges, useInteractionMode, useInteractionState, useIsMoving, useIsPenActive, useLocalPresence, useNode, useNodes, usePresence, useSelection };
|