canvu-react 0.4.76 → 0.4.78

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.
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
- import { CSSProperties, ReactNode, RefObject } from 'react';
3
- import { V as VectorSceneItem, R as Rect } from './types-fJNwEnHf.js';
2
+ import { ReactNode, RefObject, CSSProperties } from 'react';
4
3
  import { S as StrokeStyle, C as Camera2D } from './shape-builders-xG3A66sv.js';
4
+ import { V as VectorSceneItem, R as Rect } from './types-fJNwEnHf.js';
5
5
  import { a as VectorViewportAssetStore, R as RasterImageCanvasRenderingOptions } from './raster-image-canvas-D3ZrySjr.js';
6
6
  import { C as CanvuLinkData } from './link-item-COoNNvCu.js';
7
7
  import { R as RemotePresencePeer, P as PresenceOverlayRenderContext } from './types-BXa2CIrc.js';
@@ -77,27 +77,6 @@ type PlacementPreview = {
77
77
  style?: StrokeStyle;
78
78
  };
79
79
 
80
- /**
81
- * Anchor presets for floating board components.
82
- *
83
- * Names are `<edge>-<position-along-edge>`:
84
- * - `top-*` / `bottom-*` anchor to the top or bottom edge.
85
- * - `left-*` / `right-*` anchor to the left or right edge.
86
- *
87
- * Corner aliases are equivalent (e.g. `top-left` and `left-top` resolve to the same anchor),
88
- * but kept distinct so callers can pick whichever reads best in their layout (a vertical
89
- * strip might prefer `left-top`; a horizontal strip prefers `top-left`).
90
- */
91
- 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";
92
- /** @deprecated Use {@link BoardComponentPosition}. */
93
- type VectorCanvasSpacePosition = BoardComponentPosition;
94
- /**
95
- * Compute absolute-position CSS for a board component anchor preset.
96
- * Returns `position`, `zIndex`, and the relevant edge offsets / transforms.
97
- * Callers merge the result with their own style/className overrides.
98
- */
99
- declare function getBoardPositionStyle(position: BoardComponentPosition, inset?: number, zIndex?: number): CSSProperties;
100
-
101
80
  /**
102
81
  * Describes one entry in {@link VectorToolbar}.
103
82
  */
@@ -118,36 +97,6 @@ type VectorToolDefinition = {
118
97
  ariaLabel?: string;
119
98
  };
120
99
 
121
- type ReadOnlyItemClickCandidateDetail = {
122
- /** The item Canvu hit-tested under the read-only click. */
123
- item: VectorSceneItem;
124
- /** World-space pointer location at press time. */
125
- worldX: number;
126
- worldY: number;
127
- /** Viewport/client pointer location at press time. */
128
- clientX: number;
129
- clientY: number;
130
- pointerType: string;
131
- shiftKey: boolean;
132
- altKey: boolean;
133
- metaKey: boolean;
134
- ctrlKey: boolean;
135
- /** Current viewport items. */
136
- items: readonly VectorSceneItem[];
137
- /** Selection snapshot before read-only activation handles the click. */
138
- selectedIds: readonly string[];
139
- };
140
- /**
141
- * Controls which items may receive select-mode click activation while
142
- * `VectorViewport` is read-only (`interactive={false}`).
143
- *
144
- * `"custom"` keeps the default high-level behavior: custom placement/tool
145
- * items with `onSelectModeItemClick` remain clickable, while regular items do
146
- * not become selectable unless the app opts in. Use `"all"` or a predicate for
147
- * read-only viewers that still need item selection or item-specific side effects.
148
- */
149
- type ReadOnlyItemClickScope = "custom" | "all" | ((detail: ReadOnlyItemClickCandidateDetail) => boolean);
150
-
151
100
  /**
152
101
  * Stable ids for Canvu's built-in shape context-menu items.
153
102
  *
@@ -287,6 +236,183 @@ type ShapeContextMenuProps = {
287
236
  */
288
237
  declare function ShapeContextMenu({ x, y, selectedIds, selectedItems, allSelectedLocked, onClose, onToggleLock, onCut, onCopy, onBringToFront, onBringForward, onSendBackward, onSendToBack, onDuplicate, onDelete, items, itemContributions, children, }: ShapeContextMenuProps): react.ReactPortal | null;
289
238
 
239
+ type CanvasPluginRenderContext = {
240
+ /** Live viewport handle when the plugin needs camera or viewport size. */
241
+ viewportRef?: RefObject<VectorViewportHandle | null>;
242
+ };
243
+ type CanvasPluginItemsChangeMiddlewareContext = {
244
+ /** Current board items before the pending change is applied. */
245
+ currentItems: readonly VectorSceneItem[];
246
+ /** Continue the item change pipeline. Forward `info` when preserving motive metadata. */
247
+ next: NonNullable<VectorViewportProps["onItemsChange"]>;
248
+ /** Original consumer callback passed to `VectorViewport`. */
249
+ consumerOnItemsChange?: VectorViewportProps["onItemsChange"];
250
+ /** Live viewport handle for advanced integrations. */
251
+ viewportRef?: RefObject<VectorViewportHandle | null>;
252
+ };
253
+ type CanvasPluginContribution = {
254
+ /** Additional tools injected into the board toolbar/runtime. */
255
+ tools?: readonly VectorToolDefinition[];
256
+ /** Transform the resolved tool list (reorder, replace, or filter existing tools). */
257
+ toolTransform?: (tools: VectorToolDefinition[]) => VectorToolDefinition[];
258
+ /**
259
+ * Additional shape context-menu items merged by id after Canvu's built-ins.
260
+ *
261
+ * Matching ids replace existing items in place, new ids append, and plugin order
262
+ * determines tie-breaking before app-level `VectorViewport.contextMenuItems`.
263
+ */
264
+ contextMenuItems?: readonly ShapeContextMenuItem[];
265
+ /** Multiple custom placements contributed by plugins; the active one is resolved by `toolId`. */
266
+ customPlacements?: readonly CustomShapePlacementOptions[];
267
+ /** Simple viewport prop overrides owned by the plugin runtime. */
268
+ viewportProps?: Partial<Pick<VectorViewportProps, "remotePresence" | "presenceOverlay">>;
269
+ /** Event callbacks chained into the viewport without manual wiring in app code. */
270
+ callbacks?: Partial<Pick<VectorViewportProps, "onWorldPointerDown" | "onWorldPointerMove" | "onWorldPointerLeave" | "onPlacementPreviewChange" | "onCameraChange">>;
271
+ /**
272
+ * Hooks around Canvu-owned pointer interactions.
273
+ *
274
+ * Use these for custom tool behavior that needs to observe or claim a gesture
275
+ * before the viewport mutates state. Use `wrapOnItemsChange` for exact item
276
+ * mutation middleware.
277
+ */
278
+ interactionHooks?: {
279
+ /** Return `"handled"` to claim the gesture and skip Canvu's built-in behavior. */
280
+ onBeforeInteraction?: CanvuBeforeInteractionHook;
281
+ /** Runs once when an accepted gesture completes or is cancelled. */
282
+ onAfterInteraction?: CanvuAfterInteractionHook;
283
+ };
284
+ /** Middleware around `onItemsChange` for collaboration, comments, persistence, etc. */
285
+ wrapOnItemsChange?: (nextItems: VectorSceneItem[], ctx: CanvasPluginItemsChangeMiddlewareContext, info?: VectorItemsChangeInfo) => void;
286
+ };
287
+ type CanvasPluginComponentProps = {
288
+ /** Stable plugin id so the component can register contributions. */
289
+ pluginId: string;
290
+ };
291
+ type CanvasPlugin = {
292
+ /** Stable id, e.g. `canvu.plugin.chatbot`. */
293
+ id: string;
294
+ /**
295
+ * Legacy/simple rendering path for purely visual plugins.
296
+ *
297
+ * Prefer `Component` for plugins that need hooks, document integration, tools, or runtime contributions.
298
+ */
299
+ render?: (ctx: CanvasPluginRenderContext) => ReactNode;
300
+ /**
301
+ * Preferred plugin entrypoint for first-party and advanced plugins.
302
+ *
303
+ * The component can use hooks and register contributions through `useCanvuPluginContribution`.
304
+ */
305
+ Component?: (props: CanvasPluginComponentProps) => ReactNode;
306
+ };
307
+ type CanvuPluginViewportSnapshot = Pick<VectorViewportProps, "items" | "onItemsChange" | "toolId" | "interactive" | "toolLocked" | "onToolChangeRequest">;
308
+ type CanvuPluginContextValue = {
309
+ viewportRef?: RefObject<VectorViewportHandle | null>;
310
+ viewport: CanvuPluginViewportSnapshot;
311
+ resolvedTools: VectorToolDefinition[];
312
+ registerContribution: (pluginId: string, contribution: CanvasPluginContribution) => void;
313
+ unregisterContribution: (pluginId: string) => void;
314
+ };
315
+ declare const CanvuPluginContext: react.Context<CanvuPluginContextValue | null>;
316
+ /**
317
+ * Creates a typed canvu plugin descriptor.
318
+ *
319
+ * Use this helper when authoring custom plugins so your editor can infer the plugin shape
320
+ * and surface better hover documentation for the returned object.
321
+ */
322
+ declare function createCanvuPlugin(plugin: CanvasPlugin): CanvasPlugin;
323
+ /**
324
+ * Returns the low-level canvu plugin runtime context.
325
+ *
326
+ * This is an advanced API for custom plugin authors. Prefer first-party plugin factories such as
327
+ * `chatbotPlugin(...)` and `realtimeCollaborationPlugin(...)` for the common path.
328
+ */
329
+ declare function useCanvuPluginContext(): CanvuPluginContextValue;
330
+ /**
331
+ * Returns the current viewport-facing board state exposed to plugins.
332
+ *
333
+ * Use this when a custom plugin needs access to items, the active tool, or the consumer's
334
+ * `onToolChangeRequest` callback.
335
+ */
336
+ declare function useCanvuViewportContext(): {
337
+ viewportRef?: RefObject<VectorViewportHandle | null>;
338
+ viewport: CanvuPluginViewportSnapshot;
339
+ };
340
+ /**
341
+ * Returns the board document context exposed to plugins.
342
+ *
343
+ * This hook is intended for advanced plugins that need to read items or integrate with the board's
344
+ * `onItemsChange` lifecycle.
345
+ */
346
+ declare function useCanvuDocumentContext(): {
347
+ items: readonly VectorSceneItem[];
348
+ onItemsChange?: VectorViewportProps["onItemsChange"];
349
+ };
350
+ /**
351
+ * Returns the tool list already resolved by the plugin runtime.
352
+ *
353
+ * `VectorToolbar` consumes this automatically when you omit its `tools` prop, so most apps do not
354
+ * need this hook directly.
355
+ */
356
+ declare function useCanvuResolvedTools(): VectorToolDefinition[];
357
+ /**
358
+ * Registers non-visual plugin contributions with the current `VectorViewport` runtime.
359
+ *
360
+ * Use this inside `plugin.Component` when you want to inject tools, pointer/camera behavior, or
361
+ * document middleware without requiring the consumer to wire hooks manually.
362
+ */
363
+ declare function useCanvuPluginContribution(pluginId: string, contribution: CanvasPluginContribution): void;
364
+
365
+ type ReadOnlyItemClickCandidateDetail = {
366
+ /** The item Canvu hit-tested under the read-only click. */
367
+ item: VectorSceneItem;
368
+ /** World-space pointer location at press time. */
369
+ worldX: number;
370
+ worldY: number;
371
+ /** Viewport/client pointer location at press time. */
372
+ clientX: number;
373
+ clientY: number;
374
+ pointerType: string;
375
+ shiftKey: boolean;
376
+ altKey: boolean;
377
+ metaKey: boolean;
378
+ ctrlKey: boolean;
379
+ /** Current viewport items. */
380
+ items: readonly VectorSceneItem[];
381
+ /** Selection snapshot before read-only activation handles the click. */
382
+ selectedIds: readonly string[];
383
+ };
384
+ /**
385
+ * Controls which items may receive select-mode click activation while
386
+ * `VectorViewport` is read-only (`interactive={false}`).
387
+ *
388
+ * `"custom"` keeps the default high-level behavior: custom placement/tool
389
+ * items with `onSelectModeItemClick` remain clickable, while regular items do
390
+ * not become selectable unless the app opts in. Use `"all"` or a predicate for
391
+ * read-only viewers that still need item selection or item-specific side effects.
392
+ */
393
+ type ReadOnlyItemClickScope = "custom" | "all" | ((detail: ReadOnlyItemClickCandidateDetail) => boolean);
394
+
395
+ /**
396
+ * Anchor presets for floating board components.
397
+ *
398
+ * Names are `<edge>-<position-along-edge>`:
399
+ * - `top-*` / `bottom-*` anchor to the top or bottom edge.
400
+ * - `left-*` / `right-*` anchor to the left or right edge.
401
+ *
402
+ * Corner aliases are equivalent (e.g. `top-left` and `left-top` resolve to the same anchor),
403
+ * but kept distinct so callers can pick whichever reads best in their layout (a vertical
404
+ * strip might prefer `left-top`; a horizontal strip prefers `top-left`).
405
+ */
406
+ 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";
407
+ /** @deprecated Use {@link BoardComponentPosition}. */
408
+ type VectorCanvasSpacePosition = BoardComponentPosition;
409
+ /**
410
+ * Compute absolute-position CSS for a board component anchor preset.
411
+ * Returns `position`, `zIndex`, and the relevant edge offsets / transforms.
412
+ * Callers merge the result with their own style/className overrides.
413
+ */
414
+ declare function getBoardPositionStyle(position: BoardComponentPosition, inset?: number, zIndex?: number): CSSProperties;
415
+
290
416
  type ActiveToolStyle = StrokeStyle & {
291
417
  toolKind: "draw" | "marker" | "text" | "rect" | "ellipse" | "architectural-cloud" | "line" | "arrow";
292
418
  label?: string;
@@ -756,130 +882,4 @@ type VectorViewportProps = {
756
882
  */
757
883
  declare const VectorViewport: react.ForwardRefExoticComponent<VectorViewportProps & react.RefAttributes<VectorViewportHandle>>;
758
884
 
759
- type CanvasPluginRenderContext = {
760
- /** Live viewport handle when the plugin needs camera or viewport size. */
761
- viewportRef?: RefObject<VectorViewportHandle | null>;
762
- };
763
- type CanvasPluginItemsChangeMiddlewareContext = {
764
- /** Current board items before the pending change is applied. */
765
- currentItems: readonly VectorSceneItem[];
766
- /** Continue the item change pipeline. Forward `info` when preserving motive metadata. */
767
- next: NonNullable<VectorViewportProps["onItemsChange"]>;
768
- /** Original consumer callback passed to `VectorViewport`. */
769
- consumerOnItemsChange?: VectorViewportProps["onItemsChange"];
770
- /** Live viewport handle for advanced integrations. */
771
- viewportRef?: RefObject<VectorViewportHandle | null>;
772
- };
773
- type CanvasPluginContribution = {
774
- /** Additional tools injected into the board toolbar/runtime. */
775
- tools?: readonly VectorToolDefinition[];
776
- /** Transform the resolved tool list (reorder, replace, or filter existing tools). */
777
- toolTransform?: (tools: VectorToolDefinition[]) => VectorToolDefinition[];
778
- /**
779
- * Additional shape context-menu items merged by id after Canvu's built-ins.
780
- *
781
- * Matching ids replace existing items in place, new ids append, and plugin order
782
- * determines tie-breaking before app-level `VectorViewport.contextMenuItems`.
783
- */
784
- contextMenuItems?: readonly ShapeContextMenuItem[];
785
- /** Multiple custom placements contributed by plugins; the active one is resolved by `toolId`. */
786
- customPlacements?: readonly CustomShapePlacementOptions[];
787
- /** Simple viewport prop overrides owned by the plugin runtime. */
788
- viewportProps?: Partial<Pick<VectorViewportProps, "remotePresence" | "presenceOverlay">>;
789
- /** Event callbacks chained into the viewport without manual wiring in app code. */
790
- callbacks?: Partial<Pick<VectorViewportProps, "onWorldPointerDown" | "onWorldPointerMove" | "onWorldPointerLeave" | "onPlacementPreviewChange" | "onCameraChange">>;
791
- /**
792
- * Hooks around Canvu-owned pointer interactions.
793
- *
794
- * Use these for custom tool behavior that needs to observe or claim a gesture
795
- * before the viewport mutates state. Use `wrapOnItemsChange` for exact item
796
- * mutation middleware.
797
- */
798
- interactionHooks?: {
799
- /** Return `"handled"` to claim the gesture and skip Canvu's built-in behavior. */
800
- onBeforeInteraction?: CanvuBeforeInteractionHook;
801
- /** Runs once when an accepted gesture completes or is cancelled. */
802
- onAfterInteraction?: CanvuAfterInteractionHook;
803
- };
804
- /** Middleware around `onItemsChange` for collaboration, comments, persistence, etc. */
805
- wrapOnItemsChange?: (nextItems: VectorSceneItem[], ctx: CanvasPluginItemsChangeMiddlewareContext, info?: VectorItemsChangeInfo) => void;
806
- };
807
- type CanvasPluginComponentProps = {
808
- /** Stable plugin id so the component can register contributions. */
809
- pluginId: string;
810
- };
811
- type CanvasPlugin = {
812
- /** Stable id, e.g. `canvu.plugin.chatbot`. */
813
- id: string;
814
- /**
815
- * Legacy/simple rendering path for purely visual plugins.
816
- *
817
- * Prefer `Component` for plugins that need hooks, document integration, tools, or runtime contributions.
818
- */
819
- render?: (ctx: CanvasPluginRenderContext) => ReactNode;
820
- /**
821
- * Preferred plugin entrypoint for first-party and advanced plugins.
822
- *
823
- * The component can use hooks and register contributions through `useCanvuPluginContribution`.
824
- */
825
- Component?: (props: CanvasPluginComponentProps) => ReactNode;
826
- };
827
- type CanvuPluginViewportSnapshot = Pick<VectorViewportProps, "items" | "onItemsChange" | "toolId" | "interactive" | "toolLocked" | "onToolChangeRequest">;
828
- type CanvuPluginContextValue = {
829
- viewportRef?: RefObject<VectorViewportHandle | null>;
830
- viewport: CanvuPluginViewportSnapshot;
831
- resolvedTools: VectorToolDefinition[];
832
- registerContribution: (pluginId: string, contribution: CanvasPluginContribution) => void;
833
- unregisterContribution: (pluginId: string) => void;
834
- };
835
- declare const CanvuPluginContext: react.Context<CanvuPluginContextValue | null>;
836
- /**
837
- * Creates a typed canvu plugin descriptor.
838
- *
839
- * Use this helper when authoring custom plugins so your editor can infer the plugin shape
840
- * and surface better hover documentation for the returned object.
841
- */
842
- declare function createCanvuPlugin(plugin: CanvasPlugin): CanvasPlugin;
843
- /**
844
- * Returns the low-level canvu plugin runtime context.
845
- *
846
- * This is an advanced API for custom plugin authors. Prefer first-party plugin factories such as
847
- * `chatbotPlugin(...)` and `realtimeCollaborationPlugin(...)` for the common path.
848
- */
849
- declare function useCanvuPluginContext(): CanvuPluginContextValue;
850
- /**
851
- * Returns the current viewport-facing board state exposed to plugins.
852
- *
853
- * Use this when a custom plugin needs access to items, the active tool, or the consumer's
854
- * `onToolChangeRequest` callback.
855
- */
856
- declare function useCanvuViewportContext(): {
857
- viewportRef?: RefObject<VectorViewportHandle | null>;
858
- viewport: CanvuPluginViewportSnapshot;
859
- };
860
- /**
861
- * Returns the board document context exposed to plugins.
862
- *
863
- * This hook is intended for advanced plugins that need to read items or integrate with the board's
864
- * `onItemsChange` lifecycle.
865
- */
866
- declare function useCanvuDocumentContext(): {
867
- items: readonly VectorSceneItem[];
868
- onItemsChange?: VectorViewportProps["onItemsChange"];
869
- };
870
- /**
871
- * Returns the tool list already resolved by the plugin runtime.
872
- *
873
- * `VectorToolbar` consumes this automatically when you omit its `tools` prop, so most apps do not
874
- * need this hook directly.
875
- */
876
- declare function useCanvuResolvedTools(): VectorToolDefinition[];
877
- /**
878
- * Registers non-visual plugin contributions with the current `VectorViewport` runtime.
879
- *
880
- * Use this inside `plugin.Component` when you want to inject tools, pointer/camera behavior, or
881
- * document middleware without requiring the consumer to wire hooks manually.
882
- */
883
- declare function useCanvuPluginContribution(pluginId: string, contribution: CanvasPluginContribution): void;
884
-
885
- export { type ShapeContextMenuItem as A, type BoardComponentPosition as B, type CustomShapePlacementOptions as C, type ShapeContextMenuProps as D, type ShapeContextMenuRenderContext as E, type VectorCanvasSpacePosition as F, type VectorItemsChangeInfo as G, type VectorItemsChangeMotive as H, type VectorSelectionInspectorProps as I, VectorViewport as J, type VectorViewportHandle as K, type VectorViewportProps as L, createCanvuPlugin as M, getBoardPositionStyle as N, useCanvuChromeContext as O, type PlacementPreview as P, useCanvuDocumentContext as Q, type ReadOnlyInteractionOptions as R, SHAPE_CONTEXT_MENU_ITEM_IDS as S, useCanvuPluginContext as T, useCanvuPluginContribution as U, type VectorToolDefinition as V, type WorldPointerDownDetail as W, useCanvuResolvedTools as X, useCanvuViewportContext as Y, type CanvuBeforeInteractionHook as a, type CanvuAfterInteractionHook as b, type CanvasPlugin as c, VectorSelectionInspector as d, type CanvasPluginComponentProps as e, type CanvasPluginContribution as f, type CanvasPluginItemsChangeMiddlewareContext as g, type CanvasPluginRenderContext as h, type CanvuAfterInteractionDetail as i, type CanvuBeforeInteractionResult as j, type CanvuChromeActiveToolStyle as k, CanvuChromeContext as l, type CanvuChromeContextValue as m, type CanvuChromeSelectionStyleChange as n, type CanvuInteractionDetail as o, type CanvuInteractionKind as p, type CanvuInteractionOutcome as q, type CanvuInteractionPoint as r, CanvuPluginContext as s, type CanvuPluginContextValue as t, type CanvuPluginViewportSnapshot as u, type ReadOnlyItemClickCandidateDetail as v, type ReadOnlyItemClickScope as w, type SelectModeItemClickDetail as x, type SelectModeItemClickResult as y, ShapeContextMenu as z };
885
+ export { ShapeContextMenu as A, type BoardComponentPosition as B, type CustomShapePlacementOptions as C, type ShapeContextMenuItem as D, type ShapeContextMenuProps as E, type ShapeContextMenuRenderContext as F, type VectorCanvasSpacePosition as G, type VectorItemsChangeMotive as H, type VectorSelectionInspectorProps as I, VectorViewport as J, type VectorViewportHandle as K, type VectorViewportProps as L, createCanvuPlugin as M, getBoardPositionStyle as N, useCanvuChromeContext as O, type PlacementPreview as P, useCanvuDocumentContext as Q, type ReadOnlyInteractionOptions as R, SHAPE_CONTEXT_MENU_ITEM_IDS as S, useCanvuPluginContext as T, useCanvuPluginContribution as U, type VectorToolDefinition as V, type WorldPointerDownDetail as W, useCanvuResolvedTools as X, useCanvuViewportContext as Y, type CanvuBeforeInteractionHook as a, type CanvuAfterInteractionHook as b, type CanvasPlugin as c, type VectorItemsChangeInfo as d, VectorSelectionInspector as e, type CanvasPluginComponentProps as f, type CanvasPluginContribution as g, type CanvasPluginItemsChangeMiddlewareContext as h, type CanvasPluginRenderContext as i, type CanvuAfterInteractionDetail as j, type CanvuBeforeInteractionResult as k, type CanvuChromeActiveToolStyle as l, CanvuChromeContext as m, type CanvuChromeContextValue as n, type CanvuChromeSelectionStyleChange as o, type CanvuInteractionDetail as p, type CanvuInteractionKind as q, type CanvuInteractionOutcome as r, type CanvuInteractionPoint as s, CanvuPluginContext as t, type CanvuPluginContextValue as u, type CanvuPluginViewportSnapshot as v, type ReadOnlyItemClickCandidateDetail as w, type ReadOnlyItemClickScope as x, type SelectModeItemClickDetail as y, type SelectModeItemClickResult as z };
@@ -1,8 +1,8 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { c as CanvasPlugin } from './types-DOUBapS4.cjs';
2
+ import { c as CanvasPlugin } from './VectorViewport-MlKilYoG.cjs';
3
3
  import 'react';
4
- import './types-fJNwEnHf.cjs';
5
4
  import './shape-builders-DzhCOuzo.cjs';
5
+ import './types-fJNwEnHf.cjs';
6
6
  import './raster-image-canvas-ByaCKEVw.cjs';
7
7
  import './link-item-BMV3VUCr.cjs';
8
8
  import './types-DqsqQQVf.cjs';
package/dist/chatbot.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { c as CanvasPlugin } from './types-C5wxwquF.js';
2
+ import { c as CanvasPlugin } from './VectorViewport-bSpT1CrU.js';
3
3
  import 'react';
4
- import './types-fJNwEnHf.js';
5
4
  import './shape-builders-xG3A66sv.js';
5
+ import './types-fJNwEnHf.js';
6
6
  import './raster-image-canvas-D3ZrySjr.js';
7
7
  import './link-item-COoNNvCu.js';
8
8
  import './types-BXa2CIrc.js';
package/dist/react.cjs CHANGED
@@ -2255,6 +2255,10 @@ var defaultLabels = {
2255
2255
  collapse: "Collapse images menu",
2256
2256
  expand: "Open images menu"
2257
2257
  };
2258
+ function getAddedItemIds(before, after) {
2259
+ const beforeIds = new Set(before.map((item) => item.id));
2260
+ return after.filter((item) => !beforeIds.has(item.id)).map((item) => item.id);
2261
+ }
2258
2262
  function ImagesMenu({
2259
2263
  items,
2260
2264
  onItemsChange,
@@ -2313,12 +2317,17 @@ function ImagesMenu({
2313
2317
  const onDragEnd = (event) => {
2314
2318
  const { active, over } = event;
2315
2319
  if (!over || active.id === over.id) return;
2316
- const oldIndex = managed.findIndex((i) => i.id === active.id);
2317
- const newIndex = managed.findIndex((i) => i.id === over.id);
2320
+ const activeId = String(active.id);
2321
+ const overId = String(over.id);
2322
+ const oldIndex = managed.findIndex((i) => i.id === activeId);
2323
+ const newIndex = managed.findIndex((i) => i.id === overId);
2318
2324
  if (oldIndex < 0 || newIndex < 0) return;
2319
2325
  const reorderedManaged = sortable.arrayMove(managed, oldIndex, newIndex);
2320
2326
  const orderedIds = reorderedManaged.map((i) => i.id);
2321
- onItemsChange(reorderManagedImages(items, orderedIds));
2327
+ onItemsChange(reorderManagedImages(items, orderedIds), {
2328
+ motive: "reorder",
2329
+ itemIds: [activeId]
2330
+ });
2322
2331
  };
2323
2332
  return /* @__PURE__ */ jsxRuntime.jsxs(
2324
2333
  "section",
@@ -2356,9 +2365,22 @@ function ImagesMenu({
2356
2365
  labels: resolvedLabels,
2357
2366
  hiddenActionSet,
2358
2367
  onFocus: onFocusItem ? () => onFocusItem(item) : void 0,
2359
- onCopy: () => onItemsChange(copyManagedImage(items, item.id)),
2360
- onRotate: () => onItemsChange(rotateManagedImage(items, item.id)),
2361
- onDelete: () => onItemsChange(deleteManagedImage(items, item.id))
2368
+ onCopy: () => {
2369
+ const next = copyManagedImage(items, item.id);
2370
+ const addedIds = getAddedItemIds(items, next);
2371
+ onItemsChange(next, {
2372
+ motive: "duplicate",
2373
+ itemIds: addedIds.length > 0 ? addedIds : [item.id]
2374
+ });
2375
+ },
2376
+ onRotate: () => onItemsChange(rotateManagedImage(items, item.id), {
2377
+ motive: "rotate",
2378
+ itemIds: [item.id]
2379
+ }),
2380
+ onDelete: () => onItemsChange(deleteManagedImage(items, item.id), {
2381
+ motive: "delete",
2382
+ itemIds: [item.id]
2383
+ })
2362
2384
  },
2363
2385
  item.id
2364
2386
  )) })
@@ -8551,6 +8573,42 @@ function didReadOnlyActivationMovePastTap(session, pointer, tapPx) {
8551
8573
  return Math.hypot(dx, dy) > tapPx;
8552
8574
  }
8553
8575
 
8576
+ // src/react/render-scheduler.ts
8577
+ var getDefaultAnimationFrameRuntime = () => typeof window === "undefined" ? {} : window;
8578
+ function createAnimationFrameRenderScheduler({
8579
+ render,
8580
+ runtime = getDefaultAnimationFrameRuntime()
8581
+ }) {
8582
+ let frameId = null;
8583
+ const canceledFrameIds = /* @__PURE__ */ new Set();
8584
+ const request = () => {
8585
+ if (frameId != null) return;
8586
+ if (typeof runtime.requestAnimationFrame !== "function") {
8587
+ render();
8588
+ return;
8589
+ }
8590
+ const scheduledFrameId = runtime.requestAnimationFrame(() => {
8591
+ const currentFrameId = scheduledFrameId;
8592
+ if (canceledFrameIds.has(currentFrameId)) {
8593
+ canceledFrameIds.delete(currentFrameId);
8594
+ return;
8595
+ }
8596
+ if (frameId === currentFrameId) {
8597
+ frameId = null;
8598
+ }
8599
+ render();
8600
+ });
8601
+ frameId = scheduledFrameId;
8602
+ };
8603
+ const cancel = () => {
8604
+ if (frameId == null) return;
8605
+ canceledFrameIds.add(frameId);
8606
+ runtime.cancelAnimationFrame?.(frameId);
8607
+ frameId = null;
8608
+ };
8609
+ return { request, cancel };
8610
+ }
8611
+
8554
8612
  // src/react/stable-selection.ts
8555
8613
  function shallowEqualStringArray(a, b) {
8556
8614
  if (a === b) return true;
@@ -9563,6 +9621,9 @@ var VectorViewport = react.forwardRef(
9563
9621
  reducedMotionRef.current = reducedMotion;
9564
9622
  const [zoomPercent, setZoomPercent] = react.useState(100);
9565
9623
  const [cameraTick, setCameraTick] = react.useState(0);
9624
+ const renderFrameSchedulerRef = react.useRef(
9625
+ null
9626
+ );
9566
9627
  const [placementPreview, setPlacementPreview] = react.useState(null);
9567
9628
  const [eraserTrail, setEraserTrail] = react.useState([]);
9568
9629
  const [laserTrail, setLaserTrail] = react.useState([]);
@@ -9943,7 +10004,7 @@ var VectorViewport = react.forwardRef(
9943
10004
  renderSceneWithLivePenStroke
9944
10005
  ]
9945
10006
  );
9946
- const renderFrame = react.useCallback(() => {
10007
+ const renderFrameNow = react.useCallback(() => {
9947
10008
  const renderer = rendererRef.current;
9948
10009
  const cam = cameraRef.current;
9949
10010
  if (!renderer || !cam) return;
@@ -9956,6 +10017,14 @@ var VectorViewport = react.forwardRef(
9956
10017
  }
9957
10018
  onCameraChangeRef.current?.();
9958
10019
  }, []);
10020
+ const renderFrame = react.useCallback(() => {
10021
+ const scheduler = renderFrameSchedulerRef.current;
10022
+ if (!scheduler) {
10023
+ renderFrameNow();
10024
+ return;
10025
+ }
10026
+ scheduler.request();
10027
+ }, [renderFrameNow]);
9959
10028
  react.useEffect(() => {
9960
10029
  const el = sceneContainerRef.current;
9961
10030
  const interactionEl = interactionRootRef.current;
@@ -9974,6 +10043,9 @@ var VectorViewport = react.forwardRef(
9974
10043
  rasterImageCanvas: imageCanvasRenderingRef.current
9975
10044
  });
9976
10045
  rendererRef.current = renderer;
10046
+ renderFrameSchedulerRef.current = createAnimationFrameRenderScheduler({
10047
+ render: renderFrameNow
10048
+ });
9977
10049
  renderer.setInteractionState({
9978
10050
  selectedIds: effectiveSelectedIdsRef.current,
9979
10051
  hoveredItemId: hoveredItemIdRef.current
@@ -10008,6 +10080,8 @@ var VectorViewport = react.forwardRef(
10008
10080
  });
10009
10081
  }
10010
10082
  return () => {
10083
+ renderFrameSchedulerRef.current?.cancel();
10084
+ renderFrameSchedulerRef.current = null;
10011
10085
  detachInput();
10012
10086
  detachPencil?.();
10013
10087
  renderer.destroy();
@@ -10016,7 +10090,7 @@ var VectorViewport = react.forwardRef(
10016
10090
  cameraRef.current = null;
10017
10091
  setCameraForOverlay(null);
10018
10092
  };
10019
- }, [applePencilNav, renderFrame, resolveReadOnlyActivation]);
10093
+ }, [applePencilNav, renderFrame, renderFrameNow, resolveReadOnlyActivation]);
10020
10094
  react.useEffect(() => {
10021
10095
  rendererRef.current?.setInteractionState({
10022
10096
  selectedIds: effectiveSelectedIds,
@@ -10144,10 +10218,10 @@ var VectorViewport = react.forwardRef(
10144
10218
  livePenStrokeItemRef.current = null;
10145
10219
  }
10146
10220
  scene.setItems(resolvedSceneItems);
10147
- renderFrame();
10221
+ renderFrameNow();
10148
10222
  renderer?.renderLiveItem(livePenStrokeItemRef.current);
10149
10223
  }
10150
- }, [resolvedSceneItems, renderFrame]);
10224
+ }, [resolvedSceneItems, renderFrameNow]);
10151
10225
  react.useEffect(() => {
10152
10226
  const ids = effectiveSelectedIds;
10153
10227
  const valid = ids.filter((id) => items.some((i) => i.id === id));