canvu-react 0.3.6 → 0.3.8

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.
@@ -0,0 +1,691 @@
1
+ import * as react from 'react';
2
+ import { CSSProperties, ReactNode, RefObject } from 'react';
3
+ import { V as VectorSceneItem, R as Rect } from './types-CB0TZZuk.js';
4
+ import { C as Camera2D } from './camera-KwCYYPhm.js';
5
+ import * as react_jsx_runtime from 'react/jsx-runtime';
6
+ import { S as StrokeStyle } from './shape-builders-DTYvub8W.js';
7
+
8
+ /**
9
+ * Kind of binary selected through the built-in canvu asset ingestion flow.
10
+ *
11
+ * Use this to branch your backend upload logic when images and PDFs should be
12
+ * stored differently.
13
+ */
14
+ type VectorViewportAssetKind = "image" | "pdf";
15
+ /**
16
+ * Original browser `File` intercepted from the built-in asset flow.
17
+ *
18
+ * This is the high-level hook for apps that want canvu to keep its native file
19
+ * UX while still uploading the raw binary to their backend or object storage.
20
+ *
21
+ * The same request shape is also reused by
22
+ * {@link ingestAssetFilesToSceneItems}, so custom import flows and the native
23
+ * viewport UX can share one backend contract.
24
+ */
25
+ type VectorViewportAssetUploadRequest = {
26
+ /** Original browser file before canvu converts it into scene items. */
27
+ file: File;
28
+ /** High-level bucket for routing image vs PDF upload behavior. */
29
+ kind: VectorViewportAssetKind;
30
+ };
31
+ /**
32
+ * Persisted metadata returned by a custom asset upload.
33
+ *
34
+ * The returned `pluginData` is shallow-merged into every `VectorSceneItem`
35
+ * created from the uploaded file, making it available to custom persistence
36
+ * adapters and later hydration flows.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * const assetStore: VectorViewportAssetStore = {
41
+ * async upload({ file, kind }) {
42
+ * const form = new FormData();
43
+ * form.append("file", file);
44
+ * form.append("kind", kind);
45
+ *
46
+ * const response = await fetch("/api/canvu/assets", {
47
+ * method: "POST",
48
+ * body: form,
49
+ * });
50
+ *
51
+ * const asset = await response.json();
52
+ * return {
53
+ * pluginData: {
54
+ * assetId: asset.id,
55
+ * assetKey: asset.key,
56
+ * mimeType: file.type,
57
+ * },
58
+ * };
59
+ * },
60
+ * async resolve({ assetIds }) {
61
+ * const response = await fetch("/api/canvu/assets/resolve", {
62
+ * method: "POST",
63
+ * headers: { "content-type": "application/json" },
64
+ * body: JSON.stringify({ assetIds }),
65
+ * });
66
+ *
67
+ * return response.json();
68
+ * },
69
+ * };
70
+ * ```
71
+ */
72
+ type VectorViewportAssetUploadResult = {
73
+ /**
74
+ * Opaque persisted metadata attached to created items.
75
+ *
76
+ * Use this for asset ids, bucket keys, original file names, or any backend
77
+ * reference needed to rehydrate the binary later from your own persistence
78
+ * adapter.
79
+ */
80
+ pluginData?: VectorSceneItem["pluginData"];
81
+ };
82
+ /**
83
+ * Request to resolve persisted asset ids back into runtime URLs.
84
+ *
85
+ * This is useful inside custom persistence adapters when you want to rehydrate
86
+ * signed URLs or CDN URLs after loading a snapshot.
87
+ */
88
+ type VectorViewportAssetResolveRequest = {
89
+ assetIds: string[];
90
+ };
91
+ /**
92
+ * Runtime URL payload returned by a custom asset resolver.
93
+ */
94
+ type VectorViewportAssetResolveResult = Record<string, {
95
+ url: string;
96
+ thumbnailUrl?: string;
97
+ }>;
98
+ /**
99
+ * High-level hook for apps that want to persist raw binaries out-of-band while
100
+ * keeping canvu's built-in file UX.
101
+ *
102
+ * `upload` is used by the built-in file picker / drag-and-drop flow and by
103
+ * {@link ingestAssetFilesToSceneItems}. `resolve` is optional for custom
104
+ * persistence adapters and future hydration flows.
105
+ */
106
+ type VectorViewportAssetStore = {
107
+ upload: (request: VectorViewportAssetUploadRequest) => Promise<VectorViewportAssetUploadResult | undefined>;
108
+ resolve?: (request: VectorViewportAssetResolveRequest) => Promise<VectorViewportAssetResolveResult>;
109
+ };
110
+
111
+ type CanvuChromeActiveToolStyle = StrokeStyle & {
112
+ toolKind: "draw" | "marker";
113
+ label?: string;
114
+ };
115
+ type CanvuChromeSelectionStyleChange = (patch: {
116
+ stroke: string;
117
+ strokeWidth: number;
118
+ strokeOpacity?: number;
119
+ }) => void;
120
+ /**
121
+ * Runtime data and handlers shared with floating board chrome (e.g. {@link NavMenu},
122
+ * {@link VectorSelectionInspector}). Populated by `VectorViewport` and consumed via
123
+ * {@link useCanvuChromeContext}.
124
+ */
125
+ type CanvuChromeContextValue = {
126
+ camera: Camera2D | null;
127
+ viewportWidth: number;
128
+ viewportHeight: number;
129
+ items: readonly VectorSceneItem[];
130
+ selectedItems: readonly VectorSceneItem[];
131
+ interactive: boolean;
132
+ canEditSelection: boolean;
133
+ activeToolStyle: CanvuChromeActiveToolStyle | null;
134
+ onSelectionStyleChange: CanvuChromeSelectionStyleChange | null;
135
+ zoomPercent: number;
136
+ onZoomIn: () => void;
137
+ onZoomOut: () => void;
138
+ onUndo: () => void;
139
+ onRedo: () => void;
140
+ canUndo: boolean;
141
+ canRedo: boolean;
142
+ onRequestRender: () => void;
143
+ };
144
+ declare const CanvuChromeContext: react.Context<CanvuChromeContextValue | null>;
145
+ /** Returns the current chrome context or `null` when used outside `VectorViewport`. */
146
+ declare function useCanvuChromeContext(): CanvuChromeContextValue | null;
147
+
148
+ type PlacementPreview = {
149
+ kind: "rect" | "ellipse";
150
+ rect: Rect;
151
+ }
152
+ /** Multi-select drag (world rect), like image crop / rubber-band selection. */
153
+ | {
154
+ kind: "marquee";
155
+ rect: Rect;
156
+ } | {
157
+ kind: "line" | "arrow";
158
+ start: {
159
+ x: number;
160
+ y: number;
161
+ };
162
+ end: {
163
+ x: number;
164
+ y: number;
165
+ };
166
+ } | {
167
+ kind: "stroke";
168
+ tool: "draw" | "marker" | "laser";
169
+ points: {
170
+ x: number;
171
+ y: number;
172
+ }[];
173
+ };
174
+
175
+ type ActiveToolStyle = StrokeStyle & {
176
+ toolKind: "draw" | "marker";
177
+ label?: string;
178
+ };
179
+ /**
180
+ * Color + stroke-width inspector for the current selection (or active drawing tool style).
181
+ * When rendered inside `VectorViewport` (e.g. via the `selectionInspector` slot), `items`,
182
+ * `activeToolStyle`, and `onChange` default to values from {@link CanvuChromeContext};
183
+ * pass any prop to override.
184
+ */
185
+ type VectorSelectionInspectorProps = {
186
+ /** Selected items that support stroke/fill styling (caller may filter). */
187
+ items?: readonly VectorSceneItem[];
188
+ /** Optional active tool style shown even without a selection. */
189
+ activeToolStyle?: ActiveToolStyle | null;
190
+ /** Apply stroke / width / opacity to every item in `items`. */
191
+ onChange?: CanvuChromeSelectionStyleChange;
192
+ /** Anchor preset. Defaults to top-left. */
193
+ position?: BoardComponentPosition;
194
+ /** Distance (px) from anchored edges. @default 12 */
195
+ inset?: number;
196
+ /** @default 24 */
197
+ zIndex?: number;
198
+ className?: string;
199
+ /** Merged on top of position-derived styles for custom tweaks. */
200
+ style?: CSSProperties;
201
+ };
202
+ /**
203
+ * Color + stroke width for the current selection. Supports multiple selected shapes: one change applies to all.
204
+ */
205
+ declare function VectorSelectionInspector({ items: itemsProp, activeToolStyle: activeToolStyleProp, onChange: onChangeProp, position, inset, zIndex, className, style, }: VectorSelectionInspectorProps): react_jsx_runtime.JSX.Element | null;
206
+
207
+ type VectorCanvasSlotProps = {
208
+ children?: ReactNode;
209
+ className?: string;
210
+ style?: CSSProperties;
211
+ };
212
+ /**
213
+ * Anchor presets for floating board components.
214
+ *
215
+ * Names are `<edge>-<position-along-edge>`:
216
+ * - `top-*` / `bottom-*` anchor to the top or bottom edge.
217
+ * - `left-*` / `right-*` anchor to the left or right edge.
218
+ *
219
+ * Corner aliases are equivalent (e.g. `top-left` and `left-top` resolve to the same anchor),
220
+ * but kept distinct so callers can pick whichever reads best in their layout (a vertical
221
+ * strip might prefer `left-top`; a horizontal strip prefers `top-left`).
222
+ */
223
+ type BoardComponentPosition = "top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right" | "left-top" | "left-center" | "left-bottom" | "right-top" | "right-center" | "right-bottom" | "center" | "fill";
224
+ /** @deprecated Use {@link BoardComponentPosition}. */
225
+ type VectorCanvasSpacePosition = BoardComponentPosition;
226
+ /**
227
+ * Compute absolute-position CSS for a board component anchor preset.
228
+ * Returns `position`, `zIndex`, and the relevant edge offsets / transforms.
229
+ * Callers merge the result with their own style/className overrides.
230
+ */
231
+ declare function getBoardPositionStyle(position: BoardComponentPosition, inset?: number, zIndex?: number): CSSProperties;
232
+ type VectorCanvasSpaceProps = VectorCanvasSlotProps & {
233
+ position?: BoardComponentPosition;
234
+ /** @default 12 */
235
+ inset?: number;
236
+ /** @default 40 */
237
+ zIndex?: number;
238
+ /** Pointer events value on the content wrapper. @default "auto" */
239
+ contentPointerEvents?: CSSProperties["pointerEvents"];
240
+ };
241
+ /**
242
+ * Full-viewport column shell for a vector canvas (header + body with stage).
243
+ * Use with {@link VectorCanvasBody}, {@link VectorCanvasMain}. Pass `toolbar` on {@link VectorViewport};
244
+ * Compose the floating tool strip with {@link VectorCanvasToolbar} around {@link VectorToolbar} (see example below).
245
+ */
246
+ declare function VectorCanvasRoot({ children, className, style, }: VectorCanvasSlotProps): react_jsx_runtime.JSX.Element;
247
+ /** Optional top chrome (title, hints, toggles). */
248
+ declare function VectorCanvasHeader({ children, className, style, }: VectorCanvasSlotProps): react_jsx_runtime.JSX.Element;
249
+ /** Fills remaining space below the header (typically one {@link VectorCanvasMain}). */
250
+ declare function VectorCanvasBody({ children, className, style, }: VectorCanvasSlotProps): react_jsx_runtime.JSX.Element;
251
+ /**
252
+ * Stretch area for {@link VectorViewport} (or any child that should fill the stage).
253
+ */
254
+ declare function VectorCanvasMain({ children, className, style, }: VectorCanvasSlotProps): react_jsx_runtime.JSX.Element;
255
+ /**
256
+ * Flex child that fills {@link VectorCanvasMain} and gives {@link VectorViewport} a bounded height
257
+ * (white surface by default). Omit if you set the background on `Main` or the viewport yourself.
258
+ */
259
+ declare function VectorCanvasViewportSurface({ children, className, style, }: VectorCanvasSlotProps): react_jsx_runtime.JSX.Element;
260
+ type VectorCanvasToolbarProps = {
261
+ children?: ReactNode;
262
+ className?: string;
263
+ style?: CSSProperties;
264
+ /** Anchor preset. @default "bottom-center" */
265
+ position?: BoardComponentPosition;
266
+ /** Distance (px) from the anchored edge(s). @default 12 */
267
+ inset?: number;
268
+ /** @default 30 */
269
+ zIndex?: number;
270
+ };
271
+ /**
272
+ * Floating strip anchor for {@link VectorToolbar} or custom controls. Defaults to bottom-center.
273
+ * Renders `pointer-events: none` on the shell and `auto` on children so the canvas keeps receiving hits outside the bar.
274
+ * Pass as the `toolbar` prop of `VectorViewport`; pick a different `position` for top / side anchoring.
275
+ * Z-index defaults to 30 so the strip stays above zoom controls.
276
+ */
277
+ declare function VectorCanvasToolbar({ children, className, style, position, inset, zIndex, }: VectorCanvasToolbarProps): react_jsx_runtime.JSX.Element;
278
+ /**
279
+ * Absolute canvas-aligned space for floating UI such as chats, rosters, inspectors, and overlays.
280
+ * Use this instead of ad-hoc wrapper divs or plugin hosts when a feature can be expressed as React nodes.
281
+ */
282
+ declare function VectorCanvasSpace({ children, className, style, position, inset, zIndex, contentPointerEvents, }: VectorCanvasSpaceProps): react_jsx_runtime.JSX.Element;
283
+ /**
284
+ * Namespaced layout primitives for composing a vector canvas shell without ad-hoc wrapper divs.
285
+ *
286
+ * @example
287
+ * ```tsx
288
+ * <VectorCanvas.Root>
289
+ * <VectorCanvas.Header>…</VectorCanvas.Header>
290
+ * <VectorCanvas.Body>
291
+ * <VectorCanvas.Main>
292
+ * <VectorCanvas.ViewportSurface>
293
+ * <VectorViewport
294
+ * toolbar={
295
+ * <VectorCanvas.Toolbar>
296
+ * <VectorToolbar … />
297
+ * </VectorCanvas.Toolbar>
298
+ * }
299
+ * …
300
+ * />
301
+ * </VectorCanvas.ViewportSurface>
302
+ * </VectorCanvas.Main>
303
+ * </VectorCanvas.Body>
304
+ * </VectorCanvas.Root>
305
+ * ```
306
+ */
307
+ declare const VectorCanvas: {
308
+ readonly Root: typeof VectorCanvasRoot;
309
+ readonly Header: typeof VectorCanvasHeader;
310
+ readonly Body: typeof VectorCanvasBody;
311
+ readonly Main: typeof VectorCanvasMain;
312
+ readonly ViewportSurface: typeof VectorCanvasViewportSurface;
313
+ readonly Toolbar: typeof VectorCanvasToolbar;
314
+ readonly Space: typeof VectorCanvasSpace;
315
+ readonly NavMenu: typeof NavMenu;
316
+ readonly SelectionInspector: typeof VectorSelectionInspector;
317
+ };
318
+
319
+ /**
320
+ * Floating bottom-bar combining zoom controls, undo/redo, and an expandable minimap.
321
+ * When rendered inside `VectorViewport` (e.g. via the `navMenu` slot), data props default
322
+ * to values from {@link CanvuChromeContext}; pass any prop to override.
323
+ */
324
+ type NavMenuProps = {
325
+ camera?: Camera2D;
326
+ viewportWidth?: number;
327
+ viewportHeight?: number;
328
+ items?: readonly VectorSceneItem[];
329
+ zoomPercent?: number;
330
+ onZoomIn?: () => void;
331
+ onZoomOut?: () => void;
332
+ onUndo?: () => void;
333
+ onRedo?: () => void;
334
+ canUndo?: boolean;
335
+ canRedo?: boolean;
336
+ onRequestRender?: () => void;
337
+ /** Anchor preset. Defaults to bottom-left. */
338
+ position?: BoardComponentPosition;
339
+ /** Distance (px) from anchored edges. @default 12 */
340
+ inset?: number;
341
+ /** @default 23 */
342
+ zIndex?: number;
343
+ className?: string;
344
+ /** Merged on top of position-derived styles for custom tweaks. */
345
+ style?: CSSProperties;
346
+ };
347
+ declare function NavMenu({ camera: cameraProp, viewportWidth: viewportWidthProp, viewportHeight: viewportHeightProp, items: itemsProp, zoomPercent: zoomPercentProp, onZoomIn: onZoomInProp, onZoomOut: onZoomOutProp, onUndo: onUndoProp, onRedo: onRedoProp, canUndo: canUndoProp, canRedo: canRedoProp, onRequestRender: onRequestRenderProp, position, inset, zIndex, className, style, }: NavMenuProps): react_jsx_runtime.JSX.Element;
348
+
349
+ /**
350
+ * Describes one entry in {@link VectorToolbar}.
351
+ */
352
+ type VectorToolDefinition = {
353
+ /** Stable id passed to `onChange` (e.g. `"hand"`, `"rect"`). */
354
+ id: string;
355
+ /** Visible label and default accessible name. */
356
+ label: string;
357
+ /**
358
+ * English (or other) name for the hover tooltip only. Defaults to {@link label}.
359
+ */
360
+ tooltipLabel?: string;
361
+ /** Optional icon; if omitted, the label text is shown. */
362
+ icon?: ReactNode;
363
+ /** Shown in `aria-keyshortcuts` when set (informational only). */
364
+ shortcutHint?: string;
365
+ /** Extra `aria-label` when you need more than `label`. */
366
+ ariaLabel?: string;
367
+ };
368
+
369
+ type RealtimeConnectionState = "connecting" | "connected" | "reconnecting" | "offline" | "error";
370
+ /**
371
+ * In-progress freehand stroke from a remote peer (before it becomes a committed `VectorSceneItem`).
372
+ */
373
+ type RemotePresenceMarkupStroke = {
374
+ readonly points: readonly {
375
+ readonly x: number;
376
+ readonly y: number;
377
+ }[];
378
+ readonly tool: "draw" | "pencil" | "brush" | "marker" | "laser";
379
+ };
380
+ /**
381
+ * One connected participant. Your WebSocket layer maps server messages → this shape;
382
+ * {@link VectorViewport} renders it in world space.
383
+ */
384
+ type RemotePresencePeer = {
385
+ readonly id: string;
386
+ /** Stable color for cursor + stroke (e.g. `#2563eb`). If omitted, a hue is derived from `id`. */
387
+ readonly color?: string;
388
+ /** Short display name near the cursor. */
389
+ readonly displayName?: string;
390
+ /** Optional profile image / avatar URL for richer collaboration UIs. */
391
+ readonly image?: string;
392
+ /** Last known pointer position in **world** units, or `null` if off-canvas / idle. */
393
+ readonly cursor: {
394
+ readonly x: number;
395
+ readonly y: number;
396
+ } | null;
397
+ /** Optional live stroke while the peer is drawing (same semantics as local placement preview). */
398
+ readonly markupStroke?: RemotePresenceMarkupStroke | null;
399
+ /** Connection-scoped id when collaboration is backed by a realtime session. */
400
+ readonly clientId?: string;
401
+ /** Stable participant identity when collaboration is backed by a realtime session. */
402
+ readonly peerId?: string;
403
+ /** Room/session id when provided by the collaboration transport. */
404
+ readonly roomId?: string;
405
+ /** Lifecycle timestamps in epoch milliseconds. */
406
+ readonly joinedAt?: number;
407
+ readonly lastSeenAt?: number;
408
+ /** Distinguishes the local participant from remote peers. */
409
+ readonly isSelf?: boolean;
410
+ /** Optional active tool hint for richer presence UIs. */
411
+ readonly activeTool?: string;
412
+ /** Session-level connection state, useful for richer rosters. */
413
+ readonly connectionState?: RealtimeConnectionState;
414
+ };
415
+ type PresenceOverlayRenderContext = {
416
+ camera: Camera2D;
417
+ /** Bumps when the camera changes so overlays stay aligned with the scene. */
418
+ cameraVersion: number;
419
+ };
420
+
421
+ type WorldPointerDownDetail = {
422
+ worldX: number;
423
+ worldY: number;
424
+ toolId: string;
425
+ pointerType: string;
426
+ };
427
+ /**
428
+ * Imperative API for pan/zoom and integrations (e.g. AI agents following a region).
429
+ * Call {@link requestRender} after mutating the {@link Camera2D} from {@link getCamera}.
430
+ */
431
+ type VectorViewportHandle = {
432
+ /** The live camera instance, or `null` before mount / after unmount. */
433
+ getCamera: () => Camera2D | null;
434
+ /**
435
+ * Re-run SVG + overlay after changing `x`, `y`, or `zoom` on the camera from {@link getCamera}.
436
+ */
437
+ requestRender: () => void;
438
+ /** CSS pixel size of the scene surface (`clientWidth` / `clientHeight`). */
439
+ getViewportSize: () => {
440
+ width: number;
441
+ height: number;
442
+ };
443
+ /**
444
+ * Sets pan/zoom so `worldRect` fits in the viewport with optional margin (fraction of rect size per side, default `0.08`).
445
+ */
446
+ fitWorldRect: (worldRect: Rect, options?: {
447
+ padding?: number;
448
+ }) => void;
449
+ };
450
+ /** Drag-to-place a custom shape (same interaction as rectangle). Use with `createCustomShapeItem` from `canvu`. */
451
+ type CustomShapePlacementOptions = {
452
+ toolId: string;
453
+ createItem: (args: {
454
+ id: string;
455
+ bounds: Rect;
456
+ }) => VectorSceneItem;
457
+ };
458
+ type VectorViewportProps = {
459
+ /** Vector items to draw (SVG fragments). */
460
+ items: readonly VectorSceneItem[];
461
+ className?: string;
462
+ /** Accessible name for the application region. */
463
+ ariaLabel: string;
464
+ /**
465
+ * When `applePencilNav` is true, used with `attachApplePencilNavigation` to decide
466
+ * when finger touches navigate (e.g. `"hand"` vs `"draw"`).
467
+ */
468
+ toolId?: string;
469
+ /** Enable Apple Pencil vs finger split (optional). */
470
+ applePencilNav?: boolean;
471
+ /**
472
+ * When true, selection, drag-to-move, resize handles, and drag-to-create shapes are enabled.
473
+ * Requires `onItemsChange` to persist mutations.
474
+ */
475
+ interactive?: boolean;
476
+ /** Selected item ids (order preserved). Empty = none. */
477
+ selectedIds?: readonly string[];
478
+ onSelectionChange?: (ids: string[]) => void;
479
+ onItemsChange?: (items: VectorSceneItem[]) => void;
480
+ /**
481
+ * Fires on primary pointer down on the viewport in **world** coordinates.
482
+ * Not called when `toolId` is `"hand"` (use that tool for panning).
483
+ * Ignored when `interactive` is true (placement uses drag-to-define).
484
+ */
485
+ onWorldPointerDown?: (detail: WorldPointerDownDetail) => void;
486
+ /**
487
+ * Floating UI above the scene. Compose with `VectorCanvas.Toolbar` + {@link VectorToolbar}
488
+ * so the strip anchors at the bottom center (`data-slot="vector-canvas-toolbar"`).
489
+ */
490
+ toolbar?: ReactNode;
491
+ /**
492
+ * Floating bottom-left zoom / undo / minimap bar. Omit to render the default `NavMenu`.
493
+ * Pass `<VectorCanvas.NavMenu position="..." />` to relocate or style it. Pass `null` to hide it.
494
+ */
495
+ navMenu?: ReactNode | null;
496
+ /**
497
+ * Floating selection / active-tool style inspector. Omit to render the default `VectorSelectionInspector`.
498
+ * Pass `<VectorCanvas.SelectionInspector position="..." />` to relocate or style it. Pass `null` to hide it.
499
+ */
500
+ selectionInspector?: ReactNode | null;
501
+ /**
502
+ * Props forwarded to the built-in {@link VectorSelectionInspector}.
503
+ *
504
+ * Use this to reposition or theme the default left-side style panel without replacing it.
505
+ */
506
+ selectionInspectorProps?: Pick<VectorSelectionInspectorProps, "className" | "style">;
507
+ /**
508
+ * Plug and play board extensions.
509
+ *
510
+ * First-party plugins such as `chatbotPlugin(...)` and `realtimeCollaborationPlugin(...)`
511
+ * should be passed here. Advanced authors can create their own plugins with `createCanvuPlugin(...)`.
512
+ */
513
+ plugins?: readonly CanvasPlugin[];
514
+ /**
515
+ * Called after the scene/camera redraw (pan, zoom, items update, or {@link VectorViewportHandle.requestRender}).
516
+ * Can fire often during gestures — throttle/debounce if needed.
517
+ */
518
+ onCameraChange?: () => void;
519
+ /**
520
+ * When `interactive` is true, enables drag (or tap) placement for `toolId`, like built-in shapes.
521
+ * Implement `createItem` with `createCustomShapeItem` from `canvu`.
522
+ */
523
+ customPlacement?: CustomShapePlacementOptions;
524
+ /**
525
+ * Multiple custom placements contributed by plugins or app code.
526
+ *
527
+ * When both `customPlacement` and `customPlacements` are provided, they are combined and the active
528
+ * placement is resolved by the current `toolId`.
529
+ */
530
+ customPlacements?: readonly CustomShapePlacementOptions[];
531
+ /**
532
+ * Optional asset persistence bridge for the built-in image/file flow.
533
+ *
534
+ * Use this when you want canvu to keep its native file picker and drag-and-drop
535
+ * behavior, while also uploading the original binary to your backend or bucket.
536
+ * Returned `pluginData` is persisted on every created item from that file.
537
+ *
538
+ * This is a high-level persistence hook. For fully custom ingestion UIs or
539
+ * imports that start outside the viewport, prefer
540
+ * `ingestAssetFilesToSceneItems(...)` so your app reuses the same pipeline as
541
+ * canvu's native file tool.
542
+ */
543
+ assetStore?: VectorViewportAssetStore;
544
+ /**
545
+ * When false (default), finishing a draw/place/erase gesture requests switching back to `autoResetToolTo`.
546
+ * Use with controlled tool state (`onToolChangeRequest`) to keep "select-after-use" behavior.
547
+ */
548
+ toolLocked?: boolean;
549
+ /** Tool id requested after one-shot actions complete. Default `"select"`. */
550
+ autoResetToolTo?: string;
551
+ /** Called when viewport requests a tool change (e.g. auto reset to select). */
552
+ onToolChangeRequest?: (toolId: string) => void;
553
+ /**
554
+ * Remote participants (cursors + optional in-progress strokes). Renders a world-space overlay
555
+ * below the local interaction layer. Transport is your app (WebSocket, party server, …).
556
+ */
557
+ remotePresence?: readonly RemotePresencePeer[];
558
+ /**
559
+ * Replace the default presence layer (e.g. custom cursors). When set, `remotePresence` is not
560
+ * rendered unless you read it from the parent closure inside this callback.
561
+ */
562
+ presenceOverlay?: (ctx: PresenceOverlayRenderContext) => ReactNode;
563
+ /**
564
+ * Throttled pointer position in **world** space while the cursor moves over the viewport
565
+ * (for broadcasting your cursor). Pair with `onWorldPointerLeave`.
566
+ */
567
+ onWorldPointerMove?: (world: {
568
+ x: number;
569
+ y: number;
570
+ }) => void;
571
+ /** Fires when the pointer leaves the viewport (clear your broadcast cursor). */
572
+ onWorldPointerLeave?: () => void;
573
+ /**
574
+ * Fires when drag placement preview updates (rect, line, freehand stroke, …). Use it to broadcast
575
+ * {@link RemotePresencePeer.markupStroke} for other participants while drawing.
576
+ */
577
+ onPlacementPreviewChange?: (preview: PlacementPreview | null) => void;
578
+ };
579
+ /**
580
+ * Full-viewport vector canvas: SVG rendering + pan/zoom/pinch + optional Apple Pencil navigation.
581
+ * Pass a `className` that includes `touch-action: none` (e.g. Tailwind `touch-none`) on the viewport.
582
+ */
583
+ declare const VectorViewport: react.ForwardRefExoticComponent<VectorViewportProps & react.RefAttributes<VectorViewportHandle>>;
584
+
585
+ type CanvasPluginRenderContext = {
586
+ /** Live viewport handle when the plugin needs camera or viewport size. */
587
+ viewportRef?: RefObject<VectorViewportHandle | null>;
588
+ };
589
+ type CanvasPluginItemsChangeMiddlewareContext = {
590
+ /** Current board items before the pending change is applied. */
591
+ currentItems: readonly VectorSceneItem[];
592
+ /** Continue the item change pipeline. */
593
+ next: NonNullable<VectorViewportProps["onItemsChange"]>;
594
+ /** Original consumer callback passed to `VectorViewport`. */
595
+ consumerOnItemsChange?: VectorViewportProps["onItemsChange"];
596
+ /** Live viewport handle for advanced integrations. */
597
+ viewportRef?: RefObject<VectorViewportHandle | null>;
598
+ };
599
+ type CanvasPluginContribution = {
600
+ /** Additional tools injected into the board toolbar/runtime. */
601
+ tools?: readonly VectorToolDefinition[];
602
+ /** Transform the resolved tool list (reorder, replace, or filter existing tools). */
603
+ toolTransform?: (tools: VectorToolDefinition[]) => VectorToolDefinition[];
604
+ /** Multiple custom placements contributed by plugins; the active one is resolved by `toolId`. */
605
+ customPlacements?: readonly CustomShapePlacementOptions[];
606
+ /** Simple viewport prop overrides owned by the plugin runtime. */
607
+ viewportProps?: Partial<Pick<VectorViewportProps, "remotePresence" | "presenceOverlay">>;
608
+ /** Event callbacks chained into the viewport without manual wiring in app code. */
609
+ callbacks?: Partial<Pick<VectorViewportProps, "onWorldPointerDown" | "onWorldPointerMove" | "onWorldPointerLeave" | "onPlacementPreviewChange" | "onCameraChange">>;
610
+ /** Middleware around `onItemsChange` for collaboration, comments, persistence, etc. */
611
+ wrapOnItemsChange?: (nextItems: VectorSceneItem[], ctx: CanvasPluginItemsChangeMiddlewareContext) => void;
612
+ };
613
+ type CanvasPluginComponentProps = {
614
+ /** Stable plugin id so the component can register contributions. */
615
+ pluginId: string;
616
+ };
617
+ type CanvasPlugin = {
618
+ /** Stable id, e.g. `canvu.plugin.chatbot`. */
619
+ id: string;
620
+ /**
621
+ * Legacy/simple rendering path for purely visual plugins.
622
+ *
623
+ * Prefer `Component` for plugins that need hooks, document integration, tools, or runtime contributions.
624
+ */
625
+ render?: (ctx: CanvasPluginRenderContext) => ReactNode;
626
+ /**
627
+ * Preferred plugin entrypoint for first-party and advanced plugins.
628
+ *
629
+ * The component can use hooks and register contributions through `useCanvuPluginContribution`.
630
+ */
631
+ Component?: (props: CanvasPluginComponentProps) => ReactNode;
632
+ };
633
+ type CanvuPluginViewportSnapshot = Pick<VectorViewportProps, "items" | "onItemsChange" | "toolId" | "interactive" | "toolLocked" | "onToolChangeRequest">;
634
+ type CanvuPluginContextValue = {
635
+ viewportRef?: RefObject<VectorViewportHandle | null>;
636
+ viewport: CanvuPluginViewportSnapshot;
637
+ resolvedTools: VectorToolDefinition[];
638
+ registerContribution: (pluginId: string, contribution: CanvasPluginContribution) => void;
639
+ unregisterContribution: (pluginId: string) => void;
640
+ };
641
+ declare const CanvuPluginContext: react.Context<CanvuPluginContextValue | null>;
642
+ /**
643
+ * Creates a typed canvu plugin descriptor.
644
+ *
645
+ * Use this helper when authoring custom plugins so your editor can infer the plugin shape
646
+ * and surface better hover documentation for the returned object.
647
+ */
648
+ declare function createCanvuPlugin(plugin: CanvasPlugin): CanvasPlugin;
649
+ /**
650
+ * Returns the low-level canvu plugin runtime context.
651
+ *
652
+ * This is an advanced API for custom plugin authors. Prefer first-party plugin factories such as
653
+ * `chatbotPlugin(...)` and `realtimeCollaborationPlugin(...)` for the common path.
654
+ */
655
+ declare function useCanvuPluginContext(): CanvuPluginContextValue;
656
+ /**
657
+ * Returns the current viewport-facing board state exposed to plugins.
658
+ *
659
+ * Use this when a custom plugin needs access to items, the active tool, or the consumer's
660
+ * `onToolChangeRequest` callback.
661
+ */
662
+ declare function useCanvuViewportContext(): {
663
+ viewportRef?: RefObject<VectorViewportHandle | null>;
664
+ viewport: CanvuPluginViewportSnapshot;
665
+ };
666
+ /**
667
+ * Returns the board document context exposed to plugins.
668
+ *
669
+ * This hook is intended for advanced plugins that need to read items or integrate with the board's
670
+ * `onItemsChange` lifecycle.
671
+ */
672
+ declare function useCanvuDocumentContext(): {
673
+ items: readonly VectorSceneItem[];
674
+ onItemsChange?: VectorViewportProps["onItemsChange"];
675
+ };
676
+ /**
677
+ * Returns the tool list already resolved by the plugin runtime.
678
+ *
679
+ * `VectorToolbar` consumes this automatically when you omit its `tools` prop, so most apps do not
680
+ * need this hook directly.
681
+ */
682
+ declare function useCanvuResolvedTools(): VectorToolDefinition[];
683
+ /**
684
+ * Registers non-visual plugin contributions with the current `VectorViewport` runtime.
685
+ *
686
+ * Use this inside `plugin.Component` when you want to inject tools, pointer/camera behavior, or
687
+ * document middleware without requiring the consumer to wire hooks manually.
688
+ */
689
+ declare function useCanvuPluginContribution(pluginId: string, contribution: CanvasPluginContribution): void;
690
+
691
+ export { VectorSelectionInspector as A, type BoardComponentPosition as B, type CanvasPlugin as C, type VectorSelectionInspectorProps as D, VectorViewport as E, type VectorViewportAssetResolveRequest as F, type VectorViewportAssetResolveResult as G, type VectorViewportAssetUploadRequest as H, type VectorViewportAssetUploadResult as I, type VectorViewportHandle as J, type VectorViewportProps as K, createCanvuPlugin as L, getBoardPositionStyle as M, NavMenu as N, useCanvuChromeContext as O, type PlacementPreview as P, useCanvuDocumentContext as Q, useCanvuPluginContext as R, useCanvuPluginContribution as S, useCanvuResolvedTools as T, useCanvuViewportContext as U, type VectorViewportAssetKind as V, type WorldPointerDownDetail as W, type RemotePresenceMarkupStroke as X, type RemotePresencePeer as Y, type RealtimeConnectionState as Z, type PresenceOverlayRenderContext as _, type VectorViewportAssetStore as a, type VectorToolDefinition as b, type CanvasPluginComponentProps as c, type CanvasPluginContribution as d, type CanvasPluginItemsChangeMiddlewareContext as e, type CanvasPluginRenderContext as f, type CanvuChromeActiveToolStyle as g, CanvuChromeContext as h, type CanvuChromeContextValue as i, type CanvuChromeSelectionStyleChange as j, CanvuPluginContext as k, type CanvuPluginContextValue as l, type CanvuPluginViewportSnapshot as m, type CustomShapePlacementOptions as n, type NavMenuProps as o, VectorCanvas as p, VectorCanvasBody as q, VectorCanvasHeader as r, VectorCanvasMain as s, VectorCanvasRoot as t, type VectorCanvasSlotProps as u, type VectorCanvasSpacePosition as v, type VectorCanvasSpaceProps as w, VectorCanvasToolbar as x, type VectorCanvasToolbarProps as y, VectorCanvasViewportSurface as z };