canvu-react 0.4.65 → 0.4.66

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,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { c as CanvasPlugin } from './types-Bw3REwrb.cjs';
2
+ import { c as CanvasPlugin } from './types-D5d-3dvz.cjs';
3
3
  import 'react';
4
4
  import './types-fJNwEnHf.cjs';
5
5
  import './shape-builders-DzhCOuzo.cjs';
package/dist/chatbot.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { c as CanvasPlugin } from './types-BZUp3LpC.js';
2
+ import { c as CanvasPlugin } from './types-B-Jdh-n6.js';
3
3
  import 'react';
4
4
  import './types-fJNwEnHf.js';
5
5
  import './shape-builders-xG3A66sv.js';
package/dist/react.cjs CHANGED
@@ -3223,6 +3223,30 @@ function createToolPlugin(options) {
3223
3223
  }
3224
3224
  });
3225
3225
  }
3226
+
3227
+ // src/react/merge-by-id.ts
3228
+ function mergeById(baseItems, ...contributions) {
3229
+ const next = [...baseItems];
3230
+ const indexById = /* @__PURE__ */ new Map();
3231
+ for (const [index, item] of next.entries()) {
3232
+ if (!indexById.has(item.id)) {
3233
+ indexById.set(item.id, index);
3234
+ }
3235
+ }
3236
+ for (const contribution of contributions) {
3237
+ if (!contribution?.length) continue;
3238
+ for (const item of contribution) {
3239
+ const existingIndex = indexById.get(item.id);
3240
+ if (existingIndex !== void 0) {
3241
+ next[existingIndex] = item;
3242
+ continue;
3243
+ }
3244
+ indexById.set(item.id, next.length);
3245
+ next.push(item);
3246
+ }
3247
+ }
3248
+ return next;
3249
+ }
3226
3250
  var menuStyle = {
3227
3251
  position: "fixed",
3228
3252
  zIndex: 1e4,
@@ -3252,9 +3276,97 @@ var dividerStyle = {
3252
3276
  margin: "4px 8px",
3253
3277
  background: "#e2e8f0"
3254
3278
  };
3279
+ var SHAPE_CONTEXT_MENU_ITEM_IDS = {
3280
+ cut: "cut",
3281
+ copy: "copy",
3282
+ duplicate: "duplicate",
3283
+ reorderDivider: "reorder-divider",
3284
+ bringToFront: "bring-to-front",
3285
+ bringForward: "bring-forward",
3286
+ sendBackward: "send-backward",
3287
+ sendToBack: "send-to-back",
3288
+ lockDivider: "lock-divider",
3289
+ toggleLock: "toggle-lock",
3290
+ delete: "delete"
3291
+ };
3292
+ function renderAction(label, onClick, options) {
3293
+ return /* @__PURE__ */ jsxRuntime.jsx(
3294
+ "button",
3295
+ {
3296
+ type: "button",
3297
+ role: "menuitem",
3298
+ style: {
3299
+ ...itemStyle,
3300
+ ...options?.danger ? { color: "#b91c1c" } : {}
3301
+ },
3302
+ onMouseEnter: (e) => {
3303
+ e.currentTarget.style.background = options?.danger ? "#fef2f2" : "#f1f5f9";
3304
+ },
3305
+ onMouseLeave: (e) => {
3306
+ e.currentTarget.style.background = "transparent";
3307
+ },
3308
+ onClick,
3309
+ children: label
3310
+ }
3311
+ );
3312
+ }
3313
+ function renderDivider() {
3314
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, style: dividerStyle });
3315
+ }
3316
+ var DEFAULT_SHAPE_CONTEXT_MENU_ITEMS = [
3317
+ {
3318
+ id: SHAPE_CONTEXT_MENU_ITEM_IDS.cut,
3319
+ render: (ctx) => renderAction("Recortar", ctx.cut)
3320
+ },
3321
+ {
3322
+ id: SHAPE_CONTEXT_MENU_ITEM_IDS.copy,
3323
+ render: (ctx) => renderAction("Copiar", ctx.copy)
3324
+ },
3325
+ {
3326
+ id: SHAPE_CONTEXT_MENU_ITEM_IDS.duplicate,
3327
+ render: (ctx) => renderAction("Duplicar", ctx.duplicate)
3328
+ },
3329
+ {
3330
+ id: SHAPE_CONTEXT_MENU_ITEM_IDS.reorderDivider,
3331
+ render: renderDivider
3332
+ },
3333
+ {
3334
+ id: SHAPE_CONTEXT_MENU_ITEM_IDS.bringToFront,
3335
+ render: (ctx) => renderAction("Trazer para frente", ctx.bringToFront)
3336
+ },
3337
+ {
3338
+ id: SHAPE_CONTEXT_MENU_ITEM_IDS.bringForward,
3339
+ render: (ctx) => renderAction("Avancar uma camada", ctx.bringForward)
3340
+ },
3341
+ {
3342
+ id: SHAPE_CONTEXT_MENU_ITEM_IDS.sendBackward,
3343
+ render: (ctx) => renderAction("Recuar uma camada", ctx.sendBackward)
3344
+ },
3345
+ {
3346
+ id: SHAPE_CONTEXT_MENU_ITEM_IDS.sendToBack,
3347
+ render: (ctx) => renderAction("Enviar para tras", ctx.sendToBack)
3348
+ },
3349
+ {
3350
+ id: SHAPE_CONTEXT_MENU_ITEM_IDS.lockDivider,
3351
+ render: renderDivider
3352
+ },
3353
+ {
3354
+ id: SHAPE_CONTEXT_MENU_ITEM_IDS.toggleLock,
3355
+ render: (ctx) => renderAction(
3356
+ ctx.allSelectedLocked ? "Desbloquear" : "Bloquear",
3357
+ ctx.toggleLock
3358
+ )
3359
+ },
3360
+ {
3361
+ id: SHAPE_CONTEXT_MENU_ITEM_IDS.delete,
3362
+ render: (ctx) => renderAction("Apagar", ctx.delete, { danger: true })
3363
+ }
3364
+ ];
3255
3365
  function ShapeContextMenu({
3256
3366
  x,
3257
3367
  y,
3368
+ selectedIds,
3369
+ selectedItems = [],
3258
3370
  allSelectedLocked,
3259
3371
  onClose,
3260
3372
  onToggleLock,
@@ -3265,7 +3377,10 @@ function ShapeContextMenu({
3265
3377
  onSendBackward,
3266
3378
  onSendToBack,
3267
3379
  onDuplicate,
3268
- onDelete
3380
+ onDelete,
3381
+ items,
3382
+ itemContributions,
3383
+ children
3269
3384
  }) {
3270
3385
  const rootRef = react.useRef(null);
3271
3386
  react.useLayoutEffect(() => {
@@ -3305,49 +3420,43 @@ function ShapeContextMenu({
3305
3420
  document.removeEventListener("pointerdown", onPointerDown, true);
3306
3421
  };
3307
3422
  }, [onClose]);
3423
+ const menuItems = react.useMemo(
3424
+ () => mergeById(items ?? DEFAULT_SHAPE_CONTEXT_MENU_ITEMS, itemContributions),
3425
+ [itemContributions, items]
3426
+ );
3308
3427
  const run = (fn) => () => {
3309
3428
  fn();
3310
3429
  onClose();
3311
3430
  };
3312
- const renderAction = (label, onClick, options) => /* @__PURE__ */ jsxRuntime.jsx(
3313
- "button",
3314
- {
3315
- type: "button",
3316
- role: "menuitem",
3317
- style: {
3318
- ...itemStyle,
3319
- ...options?.danger ? { color: "#b91c1c" } : {}
3320
- },
3321
- onMouseEnter: (e) => {
3322
- e.currentTarget.style.background = options?.danger ? "#fef2f2" : "#f1f5f9";
3323
- },
3324
- onMouseLeave: (e) => {
3325
- e.currentTarget.style.background = "transparent";
3326
- },
3327
- onClick: run(onClick),
3328
- children: label
3329
- }
3330
- );
3331
- const menu = /* @__PURE__ */ jsxRuntime.jsxs(
3431
+ const resolvedSelectedIds = selectedIds ?? selectedItems.map((item) => item.id);
3432
+ const resolvedAllSelectedLocked = allSelectedLocked ?? (selectedItems.length > 0 && selectedItems.every((item) => item.locked));
3433
+ const menuContext = {
3434
+ position: { x, y },
3435
+ selectedIds: resolvedSelectedIds,
3436
+ selectedItems,
3437
+ allSelectedLocked: resolvedAllSelectedLocked,
3438
+ anySelectedLocked: selectedItems.some((item) => item.locked),
3439
+ close: onClose,
3440
+ cut: run(onCut),
3441
+ copy: run(onCopy),
3442
+ duplicate: run(onDuplicate),
3443
+ toggleLock: run(onToggleLock),
3444
+ bringToFront: run(onBringToFront),
3445
+ bringForward: run(onBringForward),
3446
+ sendBackward: run(onSendBackward),
3447
+ sendToBack: run(onSendToBack),
3448
+ delete: run(onDelete),
3449
+ deleteSelection: run(onDelete)
3450
+ };
3451
+ const content = typeof children === "function" ? children(menuContext) : children !== void 0 ? children : menuItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: item.render(menuContext) }, item.id));
3452
+ const menu = /* @__PURE__ */ jsxRuntime.jsx(
3332
3453
  "div",
3333
3454
  {
3334
3455
  ref: rootRef,
3335
3456
  "data-slot": "shape-context-menu",
3336
3457
  style: { ...menuStyle, left: x, top: y },
3337
3458
  role: "menu",
3338
- children: [
3339
- renderAction("Recortar", onCut),
3340
- renderAction("Copiar", onCopy),
3341
- renderAction("Duplicar", onDuplicate),
3342
- /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, style: dividerStyle }),
3343
- renderAction("Trazer para frente", onBringToFront),
3344
- renderAction("Avancar uma camada", onBringForward),
3345
- renderAction("Recuar uma camada", onSendBackward),
3346
- renderAction("Enviar para tras", onSendToBack),
3347
- /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, style: dividerStyle }),
3348
- renderAction(allSelectedLocked ? "Desbloquear" : "Bloquear", onToggleLock),
3349
- renderAction("Apagar", onDelete, { danger: true })
3350
- ]
3459
+ children: content
3351
3460
  }
3352
3461
  );
3353
3462
  if (typeof document === "undefined") {
@@ -5062,6 +5171,7 @@ function VectorToolbarComponent({
5062
5171
  value,
5063
5172
  onChange,
5064
5173
  tools,
5174
+ toolContributions,
5065
5175
  overflowToolIds = DEFAULT_OVERFLOW_TOOL_IDS,
5066
5176
  overflowMenuAriaLabel = "More tools",
5067
5177
  "aria-label": ariaLabel = "Canvas tools",
@@ -5079,7 +5189,10 @@ function VectorToolbarComponent({
5079
5189
  }) {
5080
5190
  const pluginContext = react.useContext(CanvuPluginContext);
5081
5191
  const runtimeTools = pluginContext?.resolvedTools;
5082
- const resolvedTools = tools ?? runtimeTools ?? DEFAULT_VECTOR_TOOLS;
5192
+ const resolvedTools = react.useMemo(
5193
+ () => mergeById(tools ?? runtimeTools ?? DEFAULT_VECTOR_TOOLS, toolContributions),
5194
+ [runtimeTools, toolContributions, tools]
5195
+ );
5083
5196
  const { primary: primaryTools, overflow: overflowTools } = splitToolbarTools(
5084
5197
  resolvedTools,
5085
5198
  overflowToolIds
@@ -8117,18 +8230,6 @@ function isDefaultMarkerToolStyle(style) {
8117
8230
  function tagCustomPlacementItem(item, toolId) {
8118
8231
  return item.customToolId === toolId ? item : { ...item, customToolId: toolId };
8119
8232
  }
8120
- function mergeToolListById(baseTools, pluginTools) {
8121
- const next = [...baseTools];
8122
- for (const tool of pluginTools) {
8123
- const index = next.findIndex((candidate) => candidate.id === tool.id);
8124
- if (index >= 0) {
8125
- next[index] = tool;
8126
- continue;
8127
- }
8128
- next.push(tool);
8129
- }
8130
- return next;
8131
- }
8132
8233
  function composePluginEvent(consumerHandler, pluginHandlers) {
8133
8234
  const activePluginHandlers = pluginHandlers.filter(
8134
8235
  (handler) => handler != null
@@ -8256,6 +8357,8 @@ var VectorViewport = react.forwardRef(
8256
8357
  navMenu,
8257
8358
  selectionInspector,
8258
8359
  selectionInspectorProps,
8360
+ contextMenu: renderContextMenu,
8361
+ contextMenuItems: consumerContextMenuItems,
8259
8362
  plugins = [],
8260
8363
  onCameraChange: consumerOnCameraChange,
8261
8364
  customPlacement: consumerCustomPlacement,
@@ -8314,7 +8417,7 @@ var VectorViewport = react.forwardRef(
8314
8417
  let nextTools = [...DEFAULT_VECTOR_TOOLS];
8315
8418
  for (const contribution of orderedPluginContributions) {
8316
8419
  if (contribution.tools?.length) {
8317
- nextTools = mergeToolListById(nextTools, contribution.tools);
8420
+ nextTools = mergeById(nextTools, contribution.tools);
8318
8421
  }
8319
8422
  if (contribution.toolTransform) {
8320
8423
  nextTools = contribution.toolTransform(nextTools);
@@ -8322,6 +8425,16 @@ var VectorViewport = react.forwardRef(
8322
8425
  }
8323
8426
  return nextTools;
8324
8427
  }, [orderedPluginContributions]);
8428
+ const resolvedContextMenuItems = react.useMemo(
8429
+ () => mergeById(
8430
+ DEFAULT_SHAPE_CONTEXT_MENU_ITEMS,
8431
+ ...orderedPluginContributions.map(
8432
+ (contribution) => contribution.contextMenuItems
8433
+ ),
8434
+ consumerContextMenuItems
8435
+ ),
8436
+ [consumerContextMenuItems, orderedPluginContributions]
8437
+ );
8325
8438
  const allCustomPlacements = react.useMemo(() => {
8326
8439
  const placements = [];
8327
8440
  if (consumerCustomPlacement) placements.push(consumerCustomPlacement);
@@ -8501,7 +8614,7 @@ var VectorViewport = react.forwardRef(
8501
8614
  isUndoingRef.current = true;
8502
8615
  onItemsChangeRef.current?.(next, { motive: "redo" });
8503
8616
  }, []);
8504
- const [contextMenu, setContextMenu] = react.useState(null);
8617
+ const [contextMenuState, setContextMenuState] = react.useState(null);
8505
8618
  const [uncontrolledSel, setUncontrolledSel] = react.useState([]);
8506
8619
  const isSelectionControlled = onSelectionChange !== void 0;
8507
8620
  const controlledSelectedKey = JSON.stringify(selectedIdsProp ?? []);
@@ -9673,7 +9786,7 @@ var VectorViewport = react.forwardRef(
9673
9786
  ignoreLocked: true
9674
9787
  });
9675
9788
  if (!hit) {
9676
- setContextMenu(null);
9789
+ setContextMenuState(null);
9677
9790
  return;
9678
9791
  }
9679
9792
  const cur = effectiveSelectedIdsRef.current;
@@ -9684,7 +9797,7 @@ var VectorViewport = react.forwardRef(
9684
9797
  } else {
9685
9798
  nextIds = cur;
9686
9799
  }
9687
- setContextMenu({
9800
+ setContextMenuState({
9688
9801
  x: e.clientX,
9689
9802
  y: e.clientY,
9690
9803
  itemIds: nextIds
@@ -10234,7 +10347,7 @@ var VectorViewport = react.forwardRef(
10234
10347
  if (e.button !== 0) return;
10235
10348
  if (editingTextIdRef.current) return;
10236
10349
  wrapperRef.current?.focus({ preventScroll: true });
10237
- setContextMenu(null);
10350
+ setContextMenuState(null);
10238
10351
  const tool = toolIdRef.current;
10239
10352
  if (tool === "hand") return;
10240
10353
  if (applePencilNav && e.pointerType === "pen" && navigator.maxTouchPoints > 0 && (tool === "draw" || tool === "marker")) {
@@ -10654,7 +10767,7 @@ var VectorViewport = react.forwardRef(
10654
10767
  return;
10655
10768
  }
10656
10769
  wrapperRef.current?.focus({ preventScroll: true });
10657
- setContextMenu(null);
10770
+ setContextMenuState(null);
10658
10771
  const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, e.clientX, e.clientY) : void 0;
10659
10772
  const itemId = createShapeId();
10660
10773
  const item = createFreehandStrokeItem(
@@ -10777,7 +10890,7 @@ var VectorViewport = react.forwardRef(
10777
10890
  return;
10778
10891
  }
10779
10892
  wrapperRef.current?.focus({ preventScroll: true });
10780
- setContextMenu(null);
10893
+ setContextMenuState(null);
10781
10894
  penDetectedRef.current = true;
10782
10895
  const straightLine = tool === "draw" ? createStraightStrokeState(startPoint, touch.clientX, touch.clientY) : void 0;
10783
10896
  const itemId = createShapeId();
@@ -11817,6 +11930,66 @@ var VectorViewport = react.forwardRef(
11817
11930
  const defaultNavMenu = cameraForOverlay ? /* @__PURE__ */ jsxRuntime.jsx(NavMenu, {}) : null;
11818
11931
  const resolvedSelectionInspector = selectionInspector === void 0 ? defaultSelectionInspector : selectionInspector;
11819
11932
  const resolvedNavMenu = navMenu === void 0 ? defaultNavMenu : navMenu;
11933
+ const contextMenuItemIds = contextMenuState?.itemIds ?? [];
11934
+ const contextMenuSelectedItems = contextMenuState ? contextMenuItemIds.map((id) => items.find((item) => item.id === id)).filter((item) => item != null) : [];
11935
+ const allContextMenuSelectedLocked = contextMenuItemIds.length > 0 && contextMenuItemIds.every((id) => items.find((item) => item.id === id)?.locked);
11936
+ const closeContextMenu = () => setContextMenuState(null);
11937
+ const runContextMenuAction = (fn) => () => {
11938
+ fn();
11939
+ closeContextMenu();
11940
+ };
11941
+ const contextMenuRenderContext = contextMenuState ? {
11942
+ position: { x: contextMenuState.x, y: contextMenuState.y },
11943
+ selectedIds: contextMenuItemIds,
11944
+ selectedItems: contextMenuSelectedItems,
11945
+ allSelectedLocked: allContextMenuSelectedLocked,
11946
+ anySelectedLocked: contextMenuSelectedItems.some((item) => item.locked),
11947
+ close: closeContextMenu,
11948
+ cut: runContextMenuAction(() => cutIds(contextMenuItemIds)),
11949
+ copy: runContextMenuAction(
11950
+ () => copyIdsToInternalClipboard(contextMenuItemIds)
11951
+ ),
11952
+ duplicate: runContextMenuAction(() => duplicateIds(contextMenuItemIds)),
11953
+ toggleLock: runContextMenuAction(
11954
+ () => setLockedOnIds(contextMenuItemIds, !allContextMenuSelectedLocked)
11955
+ ),
11956
+ bringToFront: runContextMenuAction(
11957
+ () => reorderIds(contextMenuItemIds, "front")
11958
+ ),
11959
+ bringForward: runContextMenuAction(
11960
+ () => reorderIds(contextMenuItemIds, "forward")
11961
+ ),
11962
+ sendBackward: runContextMenuAction(
11963
+ () => reorderIds(contextMenuItemIds, "backward")
11964
+ ),
11965
+ sendToBack: runContextMenuAction(
11966
+ () => reorderIds(contextMenuItemIds, "back")
11967
+ ),
11968
+ delete: runContextMenuAction(() => deleteIds(contextMenuItemIds)),
11969
+ deleteSelection: runContextMenuAction(() => deleteIds(contextMenuItemIds)),
11970
+ items: resolvedContextMenuItems
11971
+ } : null;
11972
+ const resolvedContextMenu = interactive && onItemsChange && contextMenuState && contextMenuRenderContext && renderContextMenu !== null ? renderContextMenu ? renderContextMenu(contextMenuRenderContext) : /* @__PURE__ */ jsxRuntime.jsx(
11973
+ ShapeContextMenu,
11974
+ {
11975
+ x: contextMenuState.x,
11976
+ y: contextMenuState.y,
11977
+ selectedIds: contextMenuItemIds,
11978
+ selectedItems: contextMenuSelectedItems,
11979
+ allSelectedLocked: allContextMenuSelectedLocked,
11980
+ items: resolvedContextMenuItems,
11981
+ onClose: closeContextMenu,
11982
+ onToggleLock: () => setLockedOnIds(contextMenuItemIds, !allContextMenuSelectedLocked),
11983
+ onCut: () => cutIds(contextMenuItemIds),
11984
+ onCopy: () => copyIdsToInternalClipboard(contextMenuItemIds),
11985
+ onBringToFront: () => reorderIds(contextMenuItemIds, "front"),
11986
+ onBringForward: () => reorderIds(contextMenuItemIds, "forward"),
11987
+ onSendBackward: () => reorderIds(contextMenuItemIds, "backward"),
11988
+ onSendToBack: () => reorderIds(contextMenuItemIds, "back"),
11989
+ onDuplicate: () => duplicateIds(contextMenuItemIds),
11990
+ onDelete: () => deleteIds(contextMenuItemIds)
11991
+ }
11992
+ ) : null;
11820
11993
  return /* @__PURE__ */ jsxRuntime.jsx(CanvuPluginContext.Provider, { value: pluginContextValue, children: /* @__PURE__ */ jsxRuntime.jsx(CanvuChromeContext.Provider, { value: chromeContextValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
11821
11994
  "div",
11822
11995
  {
@@ -11970,30 +12143,7 @@ var VectorViewport = react.forwardRef(
11970
12143
  }
11971
12144
  ),
11972
12145
  resolvedSelectionInspector,
11973
- interactive && onItemsChange && contextMenu && /* @__PURE__ */ jsxRuntime.jsx(
11974
- ShapeContextMenu,
11975
- {
11976
- x: contextMenu.x,
11977
- y: contextMenu.y,
11978
- allSelectedLocked: contextMenu.itemIds.length > 0 && contextMenu.itemIds.every(
11979
- (id) => items.find((i) => i.id === id)?.locked
11980
- ),
11981
- onClose: () => setContextMenu(null),
11982
- onToggleLock: () => {
11983
- const ids = contextMenu.itemIds;
11984
- const allLocked = ids.length > 0 && ids.every((id) => items.find((i) => i.id === id)?.locked);
11985
- setLockedOnIds(ids, !allLocked);
11986
- },
11987
- onCut: () => cutIds(contextMenu.itemIds),
11988
- onCopy: () => copyIdsToInternalClipboard(contextMenu.itemIds),
11989
- onBringToFront: () => reorderIds(contextMenu.itemIds, "front"),
11990
- onBringForward: () => reorderIds(contextMenu.itemIds, "forward"),
11991
- onSendBackward: () => reorderIds(contextMenu.itemIds, "backward"),
11992
- onSendToBack: () => reorderIds(contextMenu.itemIds, "back"),
11993
- onDuplicate: () => duplicateIds(contextMenu.itemIds),
11994
- onDelete: () => deleteIds(contextMenu.itemIds)
11995
- }
11996
- ),
12146
+ resolvedContextMenu,
11997
12147
  resolvedNavMenu,
11998
12148
  /* @__PURE__ */ jsxRuntime.jsx(
11999
12149
  "div",
@@ -12030,6 +12180,7 @@ exports.IconSelect = IconSelect;
12030
12180
  exports.IconText = IconText;
12031
12181
  exports.ImagesMenu = ImagesMenu;
12032
12182
  exports.NavMenu = NavMenu;
12183
+ exports.SHAPE_CONTEXT_MENU_ITEM_IDS = SHAPE_CONTEXT_MENU_ITEM_IDS;
12033
12184
  exports.ShapeContextMenu = ShapeContextMenu;
12034
12185
  exports.VectorCanvas = VectorCanvas;
12035
12186
  exports.VectorCanvasBody = VectorCanvasBody;