@pixerate/editor-react 0.20.0 → 0.22.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.
@@ -20,300 +20,313 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/canvas/index.ts
21
21
  var canvas_exports = {};
22
22
  __export(canvas_exports, {
23
- ANIMATABLE_PROPERTIES: () => import_canvas24.ANIMATABLE_PROPERTIES,
24
- ANIMATION_DATA_KEY: () => import_canvas24.ANIMATION_DATA_KEY,
25
- ANIMATION_EASING_LABELS: () => import_canvas24.ANIMATION_EASING_LABELS,
26
- ANIMATION_EASING_PRESETS: () => import_canvas24.ANIMATION_EASING_PRESETS,
27
- ANIMATION_TIME_EPSILON: () => import_canvas24.ANIMATION_TIME_EPSILON,
28
- AUTO_LAYOUT_DATA_KEY: () => import_canvas22.AUTO_LAYOUT_DATA_KEY,
23
+ ANIMATABLE_PROPERTIES: () => import_canvas26.ANIMATABLE_PROPERTIES,
24
+ ANIMATION_DATA_KEY: () => import_canvas26.ANIMATION_DATA_KEY,
25
+ ANIMATION_EASING_LABELS: () => import_canvas26.ANIMATION_EASING_LABELS,
26
+ ANIMATION_EASING_PRESETS: () => import_canvas26.ANIMATION_EASING_PRESETS,
27
+ ANIMATION_TIME_EPSILON: () => import_canvas26.ANIMATION_TIME_EPSILON,
28
+ AUTO_LAYOUT_DATA_KEY: () => import_canvas24.AUTO_LAYOUT_DATA_KEY,
29
29
  AgentPresenceLayer: () => AgentPresenceLayer,
30
- AnimationEditError: () => import_canvas24.AnimationEditError,
31
- AnimationPlayer: () => import_canvas24.AnimationPlayer,
30
+ AnimationEditError: () => import_canvas26.AnimationEditError,
31
+ AnimationPlayer: () => import_canvas26.AnimationPlayer,
32
32
  AnimationTimeline: () => AnimationTimeline,
33
- CANVAS_COMPONENT_DRAG_TYPE: () => import_canvas25.CANVAS_COMPONENT_DRAG_TYPE,
34
- CANVAS_TOKEN_PROPERTIES: () => import_canvas23.CANVAS_TOKEN_PROPERTIES,
35
- CHILD_LAYOUT_DATA_KEY: () => import_canvas22.CHILD_LAYOUT_DATA_KEY,
36
- CONNECTION_LINE_TYPES: () => import_canvas18.CONNECTION_LINE_TYPES,
37
- CSS_ANIMATION_PROPERTIES: () => import_canvas24.CSS_ANIMATION_PROPERTIES,
38
- CUBIC_BEZIER_PRESETS: () => import_canvas24.CUBIC_BEZIER_PRESETS,
33
+ CANVAS_COMPONENT_DRAG_TYPE: () => import_canvas27.CANVAS_COMPONENT_DRAG_TYPE,
34
+ CANVAS_GRADIENT_PRESETS: () => import_canvas27.CANVAS_GRADIENT_PRESETS,
35
+ CANVAS_TOKEN_PROPERTIES: () => import_canvas25.CANVAS_TOKEN_PROPERTIES,
36
+ CHILD_LAYOUT_DATA_KEY: () => import_canvas24.CHILD_LAYOUT_DATA_KEY,
37
+ CONNECTION_LINE_TYPES: () => import_canvas20.CONNECTION_LINE_TYPES,
38
+ CSS_ANIMATION_PROPERTIES: () => import_canvas26.CSS_ANIMATION_PROPERTIES,
39
+ CUBIC_BEZIER_PRESETS: () => import_canvas26.CUBIC_BEZIER_PRESETS,
39
40
  CanvasComponentsPanel: () => CanvasComponentsPanel,
41
+ CanvasDrawLayer: () => CanvasDrawLayer,
40
42
  CanvasGuidesLayer: () => CanvasGuidesLayer,
41
43
  CanvasInstanceInspector: () => CanvasInstanceInspector,
42
- CanvasScenesStore: () => import_canvas18.CanvasScenesStore,
43
- DEFAULT_ARRANGE_SHORTCUTS: () => import_canvas18.DEFAULT_ARRANGE_SHORTCUTS,
44
- MAX_KEYFRAME_REFS: () => import_canvas24.MAX_KEYFRAME_REFS,
45
- ManualClock: () => import_canvas21.ManualClock,
46
- RESIZE_HANDLES: () => import_canvas17.RESIZE_HANDLES,
47
- SHAPE_DATA_KEY: () => import_canvas19.SHAPE_DATA_KEY,
48
- SHAPE_KINDS: () => import_canvas19.SHAPE_KINDS,
49
- SHAPE_NODE_TYPE: () => import_canvas19.SHAPE_NODE_TYPE,
50
- SHAPE_OPERATIONS: () => import_canvas19.SHAPE_OPERATIONS,
44
+ CanvasScenesStore: () => import_canvas20.CanvasScenesStore,
45
+ DEFAULT_ARRANGE_SHORTCUTS: () => import_canvas20.DEFAULT_ARRANGE_SHORTCUTS,
46
+ MAX_KEYFRAME_REFS: () => import_canvas26.MAX_KEYFRAME_REFS,
47
+ ManualClock: () => import_canvas23.ManualClock,
48
+ RESIZE_HANDLES: () => import_canvas19.RESIZE_HANDLES,
49
+ SHAPE_DATA_KEY: () => import_canvas21.SHAPE_DATA_KEY,
50
+ SHAPE_KINDS: () => import_canvas21.SHAPE_KINDS,
51
+ SHAPE_NODE_TYPE: () => import_canvas21.SHAPE_NODE_TYPE,
52
+ SHAPE_OPERATIONS: () => import_canvas21.SHAPE_OPERATIONS,
51
53
  ShapeNode: () => ShapeNode,
52
- TOKEN_BINDINGS_DATA_KEY: () => import_canvas23.TOKEN_BINDINGS_DATA_KEY,
53
- TOKEN_MODES_DATA_KEY: () => import_canvas23.TOKEN_MODES_DATA_KEY,
54
+ TOKEN_BINDINGS_DATA_KEY: () => import_canvas25.TOKEN_BINDINGS_DATA_KEY,
55
+ TOKEN_MODES_DATA_KEY: () => import_canvas25.TOKEN_MODES_DATA_KEY,
54
56
  TokenBindingPicker: () => TokenBindingPicker,
55
57
  TokenModeSwitcher: () => TokenModeSwitcher,
56
- addCanvasVariant: () => import_canvas25.addCanvasVariant,
57
- addKeyframesAtTime: () => import_canvas24.addKeyframesAtTime,
58
- alignNodes: () => import_canvas18.alignNodes,
59
- animateNode: () => import_canvas24.animateNode,
60
- applyAnimation: () => import_canvas24.applyAnimation,
61
- applyAnimationOverrides: () => import_canvas24.applyAnimationOverrides,
62
- applyConstraints: () => import_canvas22.applyConstraints,
63
- applyNodeUpdates: () => import_canvas18.applyNodeUpdates,
64
- applyShapeCombination: () => import_canvas19.applyShapeCombination,
65
- applyShapeReplacement: () => import_canvas20.applyShapeReplacement,
66
- bezierPathArea: () => import_canvas20.bezierPathArea,
67
- bezierPathBounds: () => import_canvas20.bezierPathBounds,
68
- bezierPathLength: () => import_canvas20.bezierPathLength,
69
- bezierPathPointAtLength: () => import_canvas20.bezierPathPointAtLength,
70
- bezierPathSignedArea: () => import_canvas20.bezierPathSignedArea,
71
- bezierPathToSvg: () => import_canvas20.bezierPathToSvg,
72
- bindCanvasComponentProperty: () => import_canvas25.bindCanvasComponentProperty,
73
- bindCanvasToken: () => import_canvas23.bindCanvasToken,
74
- blendLayout: () => import_canvas21.blendLayout,
75
- boundsOf: () => import_canvas21.boundsOf,
76
- calculateDagreReflowDisplacement: () => import_canvas21.calculateDagreReflowDisplacement,
77
- calculateDirectionalDisplacement: () => import_canvas21.calculateDirectionalDisplacement,
78
- canCombineShapeNodes: () => import_canvas19.canCombineShapeNodes,
79
- canOffsetShapeNodes: () => import_canvas20.canOffsetShapeNodes,
80
- canOutlineShapeNodeStrokes: () => import_canvas20.canOutlineShapeNodeStrokes,
81
- canvasHeight: () => import_canvas21.canvasHeight,
82
- centerNodes: () => import_canvas21.centerNodes,
83
- centre: () => import_canvas21.centre,
84
- clampAnimationValue: () => import_canvas24.clampAnimationValue,
85
- clampLayoutSize: () => import_canvas22.clampLayoutSize,
86
- combineCanvasComponentsAsVariants: () => import_canvas25.combineCanvasComponentsAsVariants,
87
- combineShapeNodes: () => import_canvas19.combineShapeNodes,
88
- computeNodesBoundingBox: () => import_canvas21.computeNodesBoundingBox,
89
- computeSnapGuides: () => import_canvas18.computeSnapGuides,
90
- connectedOnly: () => import_canvas21.connectedOnly,
91
- copyKeyframes: () => import_canvas24.copyKeyframes,
92
- countPathSegments: () => import_canvas20.countPathSegments,
93
- createAnimationPlayer: () => import_canvas24.createAnimationPlayer,
94
- createBezierTrajectory: () => import_canvas21.createBezierTrajectory,
95
- createCanvasAnimationController: () => import_canvas24.createCanvasAnimationController,
96
- createCanvasAutoLayoutController: () => import_canvas22.createCanvasAutoLayoutController,
97
- createCanvasComponent: () => import_canvas25.createCanvasComponent,
98
- createCanvasComponentsController: () => import_canvas25.createCanvasComponentsController,
99
- createCanvasInstance: () => import_canvas25.createCanvasInstance,
100
- createCanvasScenesStore: () => import_canvas18.createCanvasScenesStore,
101
- createFanOutTrajectory: () => import_canvas21.createFanOutTrajectory,
102
- createGuideIndex: () => import_canvas18.createGuideIndex,
103
- createNodeGuideIndex: () => import_canvas18.createNodeGuideIndex,
104
- cubicBezierAt: () => import_canvas24.cubicBezierAt,
105
- cubicPointAt: () => import_canvas17.cubicPointAt,
106
- cubicsToPathData: () => import_canvas17.cubicsToPathData,
107
- dashContours: () => import_canvas20.dashContours,
108
- defaultEasing: () => import_canvas21.defaultEasing,
109
- deleteKeyframes: () => import_canvas24.deleteKeyframes,
110
- detachCanvasInstance: () => import_canvas25.detachCanvasInstance,
111
- detachTokenBindings: () => import_canvas23.detachTokenBindings,
112
- distanceToBezierPath: () => import_canvas20.distanceToBezierPath,
113
- distributeNodes: () => import_canvas18.distributeNodes,
114
- dividePaths: () => import_canvas20.dividePaths,
115
- dividePolygons: () => import_canvas19.dividePolygons,
116
- easingFromInfluence: () => import_canvas24.easingFromInfluence,
117
- easingLabel: () => import_canvas24.easingLabel,
118
- easingToCss: () => import_canvas24.easingToCss,
119
- ensureLayout: () => import_canvas21.ensureLayout,
120
- estimateCanvasHeight: () => import_canvas21.estimateCanvasHeight,
121
- estimateNodeSize: () => import_canvas21.estimateNodeSize,
122
- evaluateAnimation: () => import_canvas24.evaluateAnimation,
123
- evaluateEasing: () => import_canvas24.evaluateEasing,
124
- evaluateTrack: () => import_canvas24.evaluateTrack,
125
- excludePaths: () => import_canvas20.excludePaths,
126
- exportCssAnimation: () => import_canvas24.exportCssAnimation,
127
- findConnectorSnap: () => import_canvas18.findConnectorSnap,
128
- fitCubicRun: () => import_canvas17.fitCubicRun,
129
- fitCubics: () => import_canvas17.fitCubics,
130
- fitFreehandPath: () => import_canvas17.fitFreehandPath,
131
- fitPathData: () => import_canvas17.fitPathData,
132
- fitViewportToNodes: () => import_canvas18.fitViewportToNodes,
133
- fitViewportToRect: () => import_canvas18.fitViewportToRect,
134
- flattenSvgPath: () => import_canvas19.flattenSvgPath,
135
- flowSide: () => import_canvas21.flowSide,
136
- formatAnimationTime: () => import_canvas24.formatAnimationTime,
137
- formatOklab: () => import_canvas24.formatOklab,
138
- getAbsolutePosition: () => import_canvas18.getAbsolutePosition,
139
- getAnimatableProperty: () => import_canvas24.getAnimatableProperty,
140
- getAnimatedProperties: () => import_canvas24.getAnimatedProperties,
141
- getAnimatedValue: () => import_canvas24.getAnimatedValue,
142
- getAnimationDuration: () => import_canvas24.getAnimationDuration,
143
- getAnimationTrack: () => import_canvas24.getAnimationTrack,
144
- getAutoLayout: () => import_canvas22.getAutoLayout,
145
- getAutoLayoutGrid: () => import_canvas22.getAutoLayoutGrid,
146
- getAutoLayoutInsertTarget: () => import_canvas22.getAutoLayoutInsertTarget,
147
- getBindableTokenProperties: () => import_canvas23.getBindableTokenProperties,
148
- getCanvasComponentDragId: () => import_canvas25.getCanvasComponentDragId,
149
- getCanvasTokenProperty: () => import_canvas23.getCanvasTokenProperty,
150
- getCenteredNodePosition: () => import_canvas21.getCenteredNodePosition,
151
- getChildLayout: () => import_canvas22.getChildLayout,
152
- getComponentSourceId: () => import_canvas25.getComponentSourceId,
153
- getCssPropertyAnimations: () => import_canvas24.getCssPropertyAnimations,
154
- getEffectiveTokenModes: () => import_canvas23.getEffectiveTokenModes,
155
- getFlowChildren: () => import_canvas22.getFlowChildren,
156
- getInstanceData: () => import_canvas25.getInstanceData,
157
- getInstanceStatus: () => import_canvas25.getInstanceStatus,
158
- getKeyframeTimes: () => import_canvas24.getKeyframeTimes,
159
- getLayoutParent: () => import_canvas22.getLayoutParent,
160
- getLayoutSizing: () => import_canvas22.getLayoutSizing,
161
- getLayoutedNodes: () => import_canvas21.getLayoutedNodes,
162
- getNextVariantValues: () => import_canvas25.getNextVariantValues,
163
- getNodeAnimation: () => import_canvas24.getNodeAnimation,
164
- getNodeOverrides: () => import_canvas25.getNodeOverrides,
165
- getNodeRect: () => import_canvas18.getNodeRect,
166
- getNodeShape: () => import_canvas19.getNodeShape,
167
- getNodeSize: () => import_canvas18.getNodeSize,
168
- getNodeTokenBindings: () => import_canvas23.getNodeTokenBindings,
169
- getNodeTokenModes: () => import_canvas23.getNodeTokenModes,
170
- getResizingNodeRect: () => import_canvas17.getResizingNodeRect,
171
- getShapeRenderData: () => import_canvas19.getShapeRenderData,
172
- getShapeSvg: () => import_canvas19.getShapeSvg,
173
- getTimelineRows: () => import_canvas24.getTimelineRows,
174
- getTimelineTicks: () => import_canvas24.getTimelineTicks,
175
- getTokenPropertyScope: () => import_canvas23.getTokenPropertyScope,
176
- getTokensForProperty: () => import_canvas23.getTokensForProperty,
177
- handlePoint: () => import_canvas18.handlePoint,
178
- hasVisibleStroke: () => import_canvas20.hasVisibleStroke,
179
- inferResizeHandle: () => import_canvas17.inferResizeHandle,
180
- inspectCanvasInstance: () => import_canvas25.inspectCanvasInstance,
181
- inspectNodeTokens: () => import_canvas23.inspectNodeTokens,
182
- interpolateAnimationValue: () => import_canvas24.interpolateAnimationValue,
183
- intersectPaths: () => import_canvas20.intersectPaths,
184
- intersectPolygons: () => import_canvas19.intersectPolygons,
185
- invertNodeUpdates: () => import_canvas18.invertNodeUpdates,
186
- isAnimationEasing: () => import_canvas24.isAnimationEasing,
187
- isAnimationKeyframe: () => import_canvas24.isAnimationKeyframe,
188
- isAutoLayoutFrame: () => import_canvas22.isAutoLayoutFrame,
189
- isCanvasComponent: () => import_canvas25.isCanvasComponent,
190
- isCanvasComponentSet: () => import_canvas25.isCanvasComponentSet,
191
- isCanvasInstance: () => import_canvas25.isCanvasInstance,
192
- isCssExportExact: () => import_canvas24.isCssExportExact,
193
- isEventFromTextInput: () => import_canvas21.isEventFromTextInput,
194
- isKeyframeSelected: () => import_canvas24.isKeyframeSelected,
195
- isLocked: () => import_canvas18.isLocked,
196
- isMeasureModifierHeld: () => import_canvas17.isMeasureModifierHeld,
197
- isNodeAnimated: () => import_canvas24.isNodeAnimated,
198
- isShapeDescription: () => import_canvas19.isShapeDescription,
199
- isShapeNode: () => import_canvas19.isShapeNode,
200
- isStraightCubic: () => import_canvas17.isStraightCubic,
201
- isValidCanvasNode: () => import_canvas21.isValidCanvasNode,
202
- isValidUrl: () => import_canvas21.isValidUrl,
203
- layoutAll: () => import_canvas22.layoutAll,
204
- layoutBounds: () => import_canvas21.layoutBounds,
205
- layoutFrame: () => import_canvas22.layoutFrame,
206
- layoutUp: () => import_canvas22.layoutUp,
207
- layoutUpMany: () => import_canvas22.layoutUpMany,
208
- linearPositionTrajectory: () => import_canvas21.linearPositionTrajectory,
209
- linearTrajectory: () => import_canvas21.linearTrajectory,
210
- listCanvasComponents: () => import_canvas25.listCanvasComponents,
211
- lockNodes: () => import_canvas18.lockNodes,
212
- makeSizingCoherent: () => import_canvas22.makeSizingCoherent,
213
- matchArrangeShortcut: () => import_canvas18.matchArrangeShortcut,
214
- matchSize: () => import_canvas18.matchSize,
215
- measureBetween: () => import_canvas17.measureBetween,
216
- measureLabel: () => import_canvas17.measureLabel,
217
- measureSelection: () => import_canvas17.measureSelection,
218
- measureToLine: () => import_canvas17.measureToLine,
219
- mergeNodeUpdates: () => import_canvas22.mergeNodeUpdates,
220
- mixColorsOklab: () => import_canvas24.mixColorsOklab,
221
- moveKeyframes: () => import_canvas24.moveKeyframes,
222
- moveLayoutChild: () => import_canvas22.moveLayoutChild,
223
- multiPolygonArea: () => import_canvas19.multiPolygonArea,
224
- multiPolygonBounds: () => import_canvas19.multiPolygonBounds,
225
- nearestHandlePositions: () => import_canvas18.nearestHandlePositions,
226
- normalizeBezierPath: () => import_canvas20.normalizeBezierPath,
227
- normalizeKeyframes: () => import_canvas24.normalizeKeyframes,
228
- offsetPath: () => import_canvas20.offsetPath,
229
- offsetShapeNodes: () => import_canvas20.offsetShapeNodes,
230
- oklabToRgb: () => import_canvas24.oklabToRgb,
231
- oppositePosition: () => import_canvas18.oppositePosition,
232
- outlineShapeNodeStrokes: () => import_canvas20.outlineShapeNodeStrokes,
233
- outlineStroke: () => import_canvas20.outlineStroke,
234
- overlaps: () => import_canvas21.overlaps,
235
- parseCanvasClipboardData: () => import_canvas21.parseCanvasClipboardData,
236
- parseCanvasScenes: () => import_canvas18.parseCanvasScenes,
237
- parseCssEasing: () => import_canvas24.parseCssEasing,
238
- parseKeyframeClipboard: () => import_canvas24.parseKeyframeClipboard,
239
- parseOklab: () => import_canvas24.parseOklab,
240
- parseSvgPath: () => import_canvas19.parseSvgPath,
241
- pasteKeyframes: () => import_canvas24.pasteKeyframes,
242
- pathBoolean: () => import_canvas20.pathBoolean,
243
- placeBeside: () => import_canvas21.placeBeside,
244
- playWebAnimations: () => import_canvas24.playWebAnimations,
245
- pointInBezierPath: () => import_canvas20.pointInBezierPath,
246
- pointInMultiPolygon: () => import_canvas19.pointInMultiPolygon,
247
- pointInRings: () => import_canvas19.pointInRings,
248
- polygonArea: () => import_canvas19.polygonArea,
249
- polygonBoolean: () => import_canvas19.polygonBoolean,
250
- polygonToSvgPath: () => import_canvas19.polygonToSvgPath,
251
- positionToSide: () => import_canvas18.positionToSide,
252
- pruneCanvasTokenModes: () => import_canvas23.pruneCanvasTokenModes,
253
- pushCanvasInstanceOverrides: () => import_canvas25.pushCanvasInstanceOverrides,
254
- readAnimatableValue: () => import_canvas24.readAnimatableValue,
255
- readNodeStyleProperty: () => import_canvas23.readNodeStyleProperty,
256
- readStyleSize: () => import_canvas18.readStyleSize,
257
- realClock: () => import_canvas21.realClock,
258
- recordAnimationChanges: () => import_canvas24.recordAnimationChanges,
259
- relayoutUpdates: () => import_canvas22.relayoutUpdates,
260
- remapPastedNodes: () => import_canvas21.remapPastedNodes,
261
- removeCanvasVariant: () => import_canvas25.removeCanvasVariant,
262
- removeTrack: () => import_canvas24.removeTrack,
263
- renameCanvasVariantProperty: () => import_canvas25.renameCanvasVariantProperty,
264
- renameCanvasVariantValue: () => import_canvas25.renameCanvasVariantValue,
265
- reorderNodes: () => import_canvas18.reorderNodes,
266
- repositionNodesTo: () => import_canvas21.repositionNodesTo,
267
- resetCanvasInstanceOverrides: () => import_canvas25.resetCanvasInstanceOverrides,
268
- resizeHandleAxes: () => import_canvas17.resizeHandleAxes,
269
- resolveCanvasTokens: () => import_canvas23.resolveCanvasTokens,
270
- resolveEasing: () => import_canvas24.resolveEasing,
271
- resolvePadding: () => import_canvas22.resolvePadding,
272
- restoreCanvasMainComponent: () => import_canvas25.restoreCanvasMainComponent,
273
- revertShapeCombination: () => import_canvas19.revertShapeCombination,
274
- rgbToOklab: () => import_canvas24.rgbToOklab,
275
- ringSignedArea: () => import_canvas19.ringSignedArea,
276
- runMultiNodeTransition: () => import_canvas21.runMultiNodeTransition,
277
- sampleAnimationFrames: () => import_canvas24.sampleAnimationFrames,
278
- scaleKeyframes: () => import_canvas24.scaleKeyframes,
279
- serializeCanvasNodes: () => import_canvas21.serializeCanvasNodes,
280
- setCanvasComponentProperty: () => import_canvas25.setCanvasComponentProperty,
281
- setCanvasInstanceProperties: () => import_canvas25.setCanvasInstanceProperties,
282
- setCanvasTokenMode: () => import_canvas23.setCanvasTokenMode,
283
- setCanvasVariantProperties: () => import_canvas25.setCanvasVariantProperties,
284
- setKeyframe: () => import_canvas24.setKeyframe,
285
- setKeyframeEasing: () => import_canvas24.setKeyframeEasing,
286
- setMotionPath: () => import_canvas24.setMotionPath,
287
- setTrackEnabled: () => import_canvas24.setTrackEnabled,
288
- shapeNodeToBezierPath: () => import_canvas20.shapeNodeToBezierPath,
289
- shapeNodeToPolygon: () => import_canvas19.shapeNodeToPolygon,
290
- shapeToBezierPath: () => import_canvas20.shapeToBezierPath,
291
- shapeToPolygon: () => import_canvas19.shapeToPolygon,
292
- sideToPosition: () => import_canvas18.sideToPosition,
293
- simplifyRing: () => import_canvas19.simplifyRing,
294
- snapKeyframeDelta: () => import_canvas24.snapKeyframeDelta,
295
- snapNodeDrag: () => import_canvas18.snapNodeDrag,
296
- snapNodeResize: () => import_canvas17.snapNodeResize,
297
- snapResize: () => import_canvas17.snapResize,
298
- snapTimeToFrame: () => import_canvas24.snapTimeToFrame,
299
- snapToGrid: () => import_canvas17.snapToGrid,
300
- springAt: () => import_canvas24.springAt,
301
- strokeOutlineRings: () => import_canvas20.strokeOutlineRings,
302
- subtractPaths: () => import_canvas20.subtractPaths,
303
- subtractPolygons: () => import_canvas19.subtractPolygons,
304
- swapCanvasInstance: () => import_canvas25.swapCanvasInstance,
305
- syncAllCanvasInstances: () => import_canvas25.syncAllCanvasInstances,
306
- syncCanvasComponents: () => import_canvas25.syncCanvasComponents,
307
- syncCanvasInstance: () => import_canvas25.syncCanvasInstance,
308
- timeToX: () => import_canvas24.timeToX,
309
- toBezierPath: () => import_canvas20.toBezierPath,
310
- toWebAnimations: () => import_canvas24.toWebAnimations,
311
- toggleLockNodes: () => import_canvas18.toggleLockNodes,
312
- transformBezierPath: () => import_canvas20.transformBezierPath,
313
- unionPolygons: () => import_canvas19.unionPolygons,
314
- unitePaths: () => import_canvas20.unitePaths,
315
- unlockNodes: () => import_canvas18.unlockNodes,
316
- updateKeyframe: () => import_canvas24.updateKeyframe,
58
+ addCanvasVariant: () => import_canvas27.addCanvasVariant,
59
+ addKeyframesAtTime: () => import_canvas26.addKeyframesAtTime,
60
+ alignNodes: () => import_canvas20.alignNodes,
61
+ angleToSvgLinearCoords: () => import_canvas27.angleToSvgLinearCoords,
62
+ animateNode: () => import_canvas26.animateNode,
63
+ applyAnimation: () => import_canvas26.applyAnimation,
64
+ applyAnimationOverrides: () => import_canvas26.applyAnimationOverrides,
65
+ applyConstraints: () => import_canvas24.applyConstraints,
66
+ applyNodeUpdates: () => import_canvas20.applyNodeUpdates,
67
+ applyShapeCombination: () => import_canvas21.applyShapeCombination,
68
+ applyShapeReplacement: () => import_canvas22.applyShapeReplacement,
69
+ bezierPathArea: () => import_canvas22.bezierPathArea,
70
+ bezierPathBounds: () => import_canvas22.bezierPathBounds,
71
+ bezierPathLength: () => import_canvas22.bezierPathLength,
72
+ bezierPathPointAtLength: () => import_canvas22.bezierPathPointAtLength,
73
+ bezierPathSignedArea: () => import_canvas22.bezierPathSignedArea,
74
+ bezierPathToSvg: () => import_canvas22.bezierPathToSvg,
75
+ bindCanvasComponentProperty: () => import_canvas27.bindCanvasComponentProperty,
76
+ bindCanvasToken: () => import_canvas25.bindCanvasToken,
77
+ blendLayout: () => import_canvas23.blendLayout,
78
+ boundsOf: () => import_canvas23.boundsOf,
79
+ calculateDagreReflowDisplacement: () => import_canvas23.calculateDagreReflowDisplacement,
80
+ calculateDirectionalDisplacement: () => import_canvas23.calculateDirectionalDisplacement,
81
+ canCombineShapeNodes: () => import_canvas21.canCombineShapeNodes,
82
+ canOffsetShapeNodes: () => import_canvas22.canOffsetShapeNodes,
83
+ canOutlineShapeNodeStrokes: () => import_canvas22.canOutlineShapeNodeStrokes,
84
+ canvasHeight: () => import_canvas23.canvasHeight,
85
+ centerNodes: () => import_canvas23.centerNodes,
86
+ centre: () => import_canvas23.centre,
87
+ clampAnimationValue: () => import_canvas26.clampAnimationValue,
88
+ clampLayoutSize: () => import_canvas24.clampLayoutSize,
89
+ combineCanvasComponentsAsVariants: () => import_canvas27.combineCanvasComponentsAsVariants,
90
+ combineShapeNodes: () => import_canvas21.combineShapeNodes,
91
+ computeNodesBoundingBox: () => import_canvas23.computeNodesBoundingBox,
92
+ computeSnapGuides: () => import_canvas20.computeSnapGuides,
93
+ connectedOnly: () => import_canvas23.connectedOnly,
94
+ copyKeyframes: () => import_canvas26.copyKeyframes,
95
+ countPathSegments: () => import_canvas22.countPathSegments,
96
+ createAnimationPlayer: () => import_canvas26.createAnimationPlayer,
97
+ createBezierTrajectory: () => import_canvas23.createBezierTrajectory,
98
+ createCanvasAnimationController: () => import_canvas26.createCanvasAnimationController,
99
+ createCanvasAutoLayoutController: () => import_canvas24.createCanvasAutoLayoutController,
100
+ createCanvasComponent: () => import_canvas27.createCanvasComponent,
101
+ createCanvasComponentsController: () => import_canvas27.createCanvasComponentsController,
102
+ createCanvasDrawController: () => import_canvas27.createCanvasDrawController,
103
+ createCanvasInstance: () => import_canvas27.createCanvasInstance,
104
+ createCanvasScenesStore: () => import_canvas20.createCanvasScenesStore,
105
+ createDefaultStrokeStyle: () => import_canvas27.createDefaultStrokeStyle,
106
+ createFanOutTrajectory: () => import_canvas23.createFanOutTrajectory,
107
+ createGuideIndex: () => import_canvas20.createGuideIndex,
108
+ createNodeGuideIndex: () => import_canvas20.createNodeGuideIndex,
109
+ cubicBezierAt: () => import_canvas26.cubicBezierAt,
110
+ cubicPointAt: () => import_canvas19.cubicPointAt,
111
+ cubicsToPathData: () => import_canvas19.cubicsToPathData,
112
+ dashContours: () => import_canvas22.dashContours,
113
+ defaultEasing: () => import_canvas23.defaultEasing,
114
+ deleteKeyframes: () => import_canvas26.deleteKeyframes,
115
+ detachCanvasInstance: () => import_canvas27.detachCanvasInstance,
116
+ detachTokenBindings: () => import_canvas25.detachTokenBindings,
117
+ distanceToBezierPath: () => import_canvas22.distanceToBezierPath,
118
+ distributeNodes: () => import_canvas20.distributeNodes,
119
+ dividePaths: () => import_canvas22.dividePaths,
120
+ dividePolygons: () => import_canvas21.dividePolygons,
121
+ easingFromInfluence: () => import_canvas26.easingFromInfluence,
122
+ easingLabel: () => import_canvas26.easingLabel,
123
+ easingToCss: () => import_canvas26.easingToCss,
124
+ ensureLayout: () => import_canvas23.ensureLayout,
125
+ estimateCanvasHeight: () => import_canvas23.estimateCanvasHeight,
126
+ estimateNodeSize: () => import_canvas23.estimateNodeSize,
127
+ evaluateAnimation: () => import_canvas26.evaluateAnimation,
128
+ evaluateEasing: () => import_canvas26.evaluateEasing,
129
+ evaluateTrack: () => import_canvas26.evaluateTrack,
130
+ excludePaths: () => import_canvas22.excludePaths,
131
+ exportCssAnimation: () => import_canvas26.exportCssAnimation,
132
+ findConnectorSnap: () => import_canvas20.findConnectorSnap,
133
+ findStrokesAtPoint: () => import_canvas27.findStrokesAtPoint,
134
+ fitCubicRun: () => import_canvas19.fitCubicRun,
135
+ fitCubics: () => import_canvas19.fitCubics,
136
+ fitFreehandPath: () => import_canvas19.fitFreehandPath,
137
+ fitPathData: () => import_canvas19.fitPathData,
138
+ fitViewportToNodes: () => import_canvas20.fitViewportToNodes,
139
+ fitViewportToRect: () => import_canvas20.fitViewportToRect,
140
+ flattenSvgPath: () => import_canvas21.flattenSvgPath,
141
+ flowSide: () => import_canvas23.flowSide,
142
+ formatAnimationTime: () => import_canvas26.formatAnimationTime,
143
+ formatOklab: () => import_canvas26.formatOklab,
144
+ getAbsolutePosition: () => import_canvas20.getAbsolutePosition,
145
+ getAnimatableProperty: () => import_canvas26.getAnimatableProperty,
146
+ getAnimatedProperties: () => import_canvas26.getAnimatedProperties,
147
+ getAnimatedValue: () => import_canvas26.getAnimatedValue,
148
+ getAnimationDuration: () => import_canvas26.getAnimationDuration,
149
+ getAnimationTrack: () => import_canvas26.getAnimationTrack,
150
+ getAutoLayout: () => import_canvas24.getAutoLayout,
151
+ getAutoLayoutGrid: () => import_canvas24.getAutoLayoutGrid,
152
+ getAutoLayoutInsertTarget: () => import_canvas24.getAutoLayoutInsertTarget,
153
+ getBindableTokenProperties: () => import_canvas25.getBindableTokenProperties,
154
+ getCanvasComponentDragId: () => import_canvas27.getCanvasComponentDragId,
155
+ getCanvasTokenProperty: () => import_canvas25.getCanvasTokenProperty,
156
+ getCenteredNodePosition: () => import_canvas23.getCenteredNodePosition,
157
+ getChildLayout: () => import_canvas24.getChildLayout,
158
+ getComponentSourceId: () => import_canvas27.getComponentSourceId,
159
+ getCssPropertyAnimations: () => import_canvas26.getCssPropertyAnimations,
160
+ getEffectiveTokenModes: () => import_canvas25.getEffectiveTokenModes,
161
+ getFlowChildren: () => import_canvas24.getFlowChildren,
162
+ getInstanceData: () => import_canvas27.getInstanceData,
163
+ getInstanceStatus: () => import_canvas27.getInstanceStatus,
164
+ getKeyframeTimes: () => import_canvas26.getKeyframeTimes,
165
+ getLayoutParent: () => import_canvas24.getLayoutParent,
166
+ getLayoutSizing: () => import_canvas24.getLayoutSizing,
167
+ getLayoutedNodes: () => import_canvas23.getLayoutedNodes,
168
+ getNextVariantValues: () => import_canvas27.getNextVariantValues,
169
+ getNodeAnimation: () => import_canvas26.getNodeAnimation,
170
+ getNodeOverrides: () => import_canvas27.getNodeOverrides,
171
+ getNodeRect: () => import_canvas20.getNodeRect,
172
+ getNodeShape: () => import_canvas21.getNodeShape,
173
+ getNodeSize: () => import_canvas20.getNodeSize,
174
+ getNodeTokenBindings: () => import_canvas25.getNodeTokenBindings,
175
+ getNodeTokenModes: () => import_canvas25.getNodeTokenModes,
176
+ getResizingNodeRect: () => import_canvas19.getResizingNodeRect,
177
+ getShapeRenderData: () => import_canvas21.getShapeRenderData,
178
+ getShapeSvg: () => import_canvas21.getShapeSvg,
179
+ getTimelineRows: () => import_canvas26.getTimelineRows,
180
+ getTimelineTicks: () => import_canvas26.getTimelineTicks,
181
+ getTokenPropertyScope: () => import_canvas25.getTokenPropertyScope,
182
+ getTokensForProperty: () => import_canvas25.getTokensForProperty,
183
+ gradientToSvgDef: () => import_canvas27.gradientToSvgDef,
184
+ handlePoint: () => import_canvas20.handlePoint,
185
+ hasVisibleStroke: () => import_canvas22.hasVisibleStroke,
186
+ inferResizeHandle: () => import_canvas19.inferResizeHandle,
187
+ inspectCanvasInstance: () => import_canvas27.inspectCanvasInstance,
188
+ inspectNodeTokens: () => import_canvas25.inspectNodeTokens,
189
+ interpolateAnimationValue: () => import_canvas26.interpolateAnimationValue,
190
+ intersectPaths: () => import_canvas22.intersectPaths,
191
+ intersectPolygons: () => import_canvas21.intersectPolygons,
192
+ invertNodeUpdates: () => import_canvas20.invertNodeUpdates,
193
+ isAnimationEasing: () => import_canvas26.isAnimationEasing,
194
+ isAnimationKeyframe: () => import_canvas26.isAnimationKeyframe,
195
+ isAutoLayoutFrame: () => import_canvas24.isAutoLayoutFrame,
196
+ isCanvasComponent: () => import_canvas27.isCanvasComponent,
197
+ isCanvasComponentSet: () => import_canvas27.isCanvasComponentSet,
198
+ isCanvasGradient: () => import_canvas27.isCanvasGradient,
199
+ isCanvasInstance: () => import_canvas27.isCanvasInstance,
200
+ isCssExportExact: () => import_canvas26.isCssExportExact,
201
+ isEventFromTextInput: () => import_canvas23.isEventFromTextInput,
202
+ isKeyframeSelected: () => import_canvas26.isKeyframeSelected,
203
+ isLocked: () => import_canvas20.isLocked,
204
+ isMeasureModifierHeld: () => import_canvas19.isMeasureModifierHeld,
205
+ isNodeAnimated: () => import_canvas26.isNodeAnimated,
206
+ isShapeDescription: () => import_canvas21.isShapeDescription,
207
+ isShapeNode: () => import_canvas21.isShapeNode,
208
+ isStraightCubic: () => import_canvas19.isStraightCubic,
209
+ isValidCanvasNode: () => import_canvas23.isValidCanvasNode,
210
+ isValidUrl: () => import_canvas23.isValidUrl,
211
+ layoutAll: () => import_canvas24.layoutAll,
212
+ layoutBounds: () => import_canvas23.layoutBounds,
213
+ layoutFrame: () => import_canvas24.layoutFrame,
214
+ layoutUp: () => import_canvas24.layoutUp,
215
+ layoutUpMany: () => import_canvas24.layoutUpMany,
216
+ linearPositionTrajectory: () => import_canvas23.linearPositionTrajectory,
217
+ linearTrajectory: () => import_canvas23.linearTrajectory,
218
+ listCanvasComponents: () => import_canvas27.listCanvasComponents,
219
+ lockNodes: () => import_canvas20.lockNodes,
220
+ makeSizingCoherent: () => import_canvas24.makeSizingCoherent,
221
+ matchArrangeShortcut: () => import_canvas20.matchArrangeShortcut,
222
+ matchSize: () => import_canvas20.matchSize,
223
+ measureBetween: () => import_canvas19.measureBetween,
224
+ measureLabel: () => import_canvas19.measureLabel,
225
+ measureSelection: () => import_canvas19.measureSelection,
226
+ measureToLine: () => import_canvas19.measureToLine,
227
+ mergeNodeUpdates: () => import_canvas24.mergeNodeUpdates,
228
+ mixColorsOklab: () => import_canvas26.mixColorsOklab,
229
+ moveKeyframes: () => import_canvas26.moveKeyframes,
230
+ moveLayoutChild: () => import_canvas24.moveLayoutChild,
231
+ multiPolygonArea: () => import_canvas21.multiPolygonArea,
232
+ multiPolygonBounds: () => import_canvas21.multiPolygonBounds,
233
+ nearestHandlePositions: () => import_canvas20.nearestHandlePositions,
234
+ normalizeBezierPath: () => import_canvas22.normalizeBezierPath,
235
+ normalizeKeyframes: () => import_canvas26.normalizeKeyframes,
236
+ offsetPath: () => import_canvas22.offsetPath,
237
+ offsetShapeNodes: () => import_canvas22.offsetShapeNodes,
238
+ oklabToRgb: () => import_canvas26.oklabToRgb,
239
+ oppositePosition: () => import_canvas20.oppositePosition,
240
+ outlineShapeNodeStrokes: () => import_canvas22.outlineShapeNodeStrokes,
241
+ outlineStroke: () => import_canvas22.outlineStroke,
242
+ overlaps: () => import_canvas23.overlaps,
243
+ parseCanvasClipboardData: () => import_canvas23.parseCanvasClipboardData,
244
+ parseCanvasScenes: () => import_canvas20.parseCanvasScenes,
245
+ parseCssEasing: () => import_canvas26.parseCssEasing,
246
+ parseCssGradient: () => import_canvas27.parseCssGradient,
247
+ parseKeyframeClipboard: () => import_canvas26.parseKeyframeClipboard,
248
+ parseOklab: () => import_canvas26.parseOklab,
249
+ parseSvgPath: () => import_canvas21.parseSvgPath,
250
+ pasteKeyframes: () => import_canvas26.pasteKeyframes,
251
+ pathBoolean: () => import_canvas22.pathBoolean,
252
+ placeBeside: () => import_canvas23.placeBeside,
253
+ playWebAnimations: () => import_canvas26.playWebAnimations,
254
+ pointInBezierPath: () => import_canvas22.pointInBezierPath,
255
+ pointInMultiPolygon: () => import_canvas21.pointInMultiPolygon,
256
+ pointInRings: () => import_canvas21.pointInRings,
257
+ polygonArea: () => import_canvas21.polygonArea,
258
+ polygonBoolean: () => import_canvas21.polygonBoolean,
259
+ polygonToSvgPath: () => import_canvas21.polygonToSvgPath,
260
+ positionToSide: () => import_canvas20.positionToSide,
261
+ pruneCanvasTokenModes: () => import_canvas25.pruneCanvasTokenModes,
262
+ pushCanvasInstanceOverrides: () => import_canvas27.pushCanvasInstanceOverrides,
263
+ readAnimatableValue: () => import_canvas26.readAnimatableValue,
264
+ readNodeStyleProperty: () => import_canvas25.readNodeStyleProperty,
265
+ readStyleSize: () => import_canvas20.readStyleSize,
266
+ realClock: () => import_canvas23.realClock,
267
+ recordAnimationChanges: () => import_canvas26.recordAnimationChanges,
268
+ relayoutUpdates: () => import_canvas24.relayoutUpdates,
269
+ remapPastedNodes: () => import_canvas23.remapPastedNodes,
270
+ removeCanvasVariant: () => import_canvas27.removeCanvasVariant,
271
+ removeTrack: () => import_canvas26.removeTrack,
272
+ renameCanvasVariantProperty: () => import_canvas27.renameCanvasVariantProperty,
273
+ renameCanvasVariantValue: () => import_canvas27.renameCanvasVariantValue,
274
+ reorderNodes: () => import_canvas20.reorderNodes,
275
+ repositionNodesTo: () => import_canvas23.repositionNodesTo,
276
+ resetCanvasInstanceOverrides: () => import_canvas27.resetCanvasInstanceOverrides,
277
+ resizeHandleAxes: () => import_canvas19.resizeHandleAxes,
278
+ resolveCanvasGradient: () => import_canvas27.resolveCanvasGradient,
279
+ resolveCanvasTokens: () => import_canvas25.resolveCanvasTokens,
280
+ resolveEasing: () => import_canvas26.resolveEasing,
281
+ resolvePadding: () => import_canvas24.resolvePadding,
282
+ restoreCanvasMainComponent: () => import_canvas27.restoreCanvasMainComponent,
283
+ revertShapeCombination: () => import_canvas21.revertShapeCombination,
284
+ rgbToOklab: () => import_canvas26.rgbToOklab,
285
+ ringSignedArea: () => import_canvas21.ringSignedArea,
286
+ runMultiNodeTransition: () => import_canvas23.runMultiNodeTransition,
287
+ sampleAnimationFrames: () => import_canvas26.sampleAnimationFrames,
288
+ scaleKeyframes: () => import_canvas26.scaleKeyframes,
289
+ serializeCanvasNodes: () => import_canvas23.serializeCanvasNodes,
290
+ setCanvasComponentProperty: () => import_canvas27.setCanvasComponentProperty,
291
+ setCanvasInstanceProperties: () => import_canvas27.setCanvasInstanceProperties,
292
+ setCanvasTokenMode: () => import_canvas25.setCanvasTokenMode,
293
+ setCanvasVariantProperties: () => import_canvas27.setCanvasVariantProperties,
294
+ setKeyframe: () => import_canvas26.setKeyframe,
295
+ setKeyframeEasing: () => import_canvas26.setKeyframeEasing,
296
+ setMotionPath: () => import_canvas26.setMotionPath,
297
+ setTrackEnabled: () => import_canvas26.setTrackEnabled,
298
+ shapeNodeToBezierPath: () => import_canvas22.shapeNodeToBezierPath,
299
+ shapeNodeToPolygon: () => import_canvas21.shapeNodeToPolygon,
300
+ shapeToBezierPath: () => import_canvas22.shapeToBezierPath,
301
+ shapeToPolygon: () => import_canvas21.shapeToPolygon,
302
+ sideToPosition: () => import_canvas20.sideToPosition,
303
+ simplifyRing: () => import_canvas21.simplifyRing,
304
+ snapKeyframeDelta: () => import_canvas26.snapKeyframeDelta,
305
+ snapNodeDrag: () => import_canvas20.snapNodeDrag,
306
+ snapNodeResize: () => import_canvas19.snapNodeResize,
307
+ snapResize: () => import_canvas19.snapResize,
308
+ snapTimeToFrame: () => import_canvas26.snapTimeToFrame,
309
+ snapToGrid: () => import_canvas19.snapToGrid,
310
+ springAt: () => import_canvas26.springAt,
311
+ streamlinePoints: () => import_canvas27.streamlinePoints,
312
+ strokeOutlineRings: () => import_canvas22.strokeOutlineRings,
313
+ strokePointsToPathData: () => import_canvas27.strokePointsToPathData,
314
+ strokeToShapeNode: () => import_canvas27.strokeToShapeNode,
315
+ subtractPaths: () => import_canvas22.subtractPaths,
316
+ subtractPolygons: () => import_canvas21.subtractPolygons,
317
+ swapCanvasInstance: () => import_canvas27.swapCanvasInstance,
318
+ syncAllCanvasInstances: () => import_canvas27.syncAllCanvasInstances,
319
+ syncCanvasComponents: () => import_canvas27.syncCanvasComponents,
320
+ syncCanvasInstance: () => import_canvas27.syncCanvasInstance,
321
+ timeToX: () => import_canvas26.timeToX,
322
+ toBezierPath: () => import_canvas22.toBezierPath,
323
+ toWebAnimations: () => import_canvas26.toWebAnimations,
324
+ toggleLockNodes: () => import_canvas20.toggleLockNodes,
325
+ transformBezierPath: () => import_canvas22.transformBezierPath,
326
+ unionPolygons: () => import_canvas21.unionPolygons,
327
+ unitePaths: () => import_canvas22.unitePaths,
328
+ unlockNodes: () => import_canvas20.unlockNodes,
329
+ updateKeyframe: () => import_canvas26.updateKeyframe,
317
330
  useCanvasAnimation: () => useCanvasAnimation,
318
331
  useCanvasArrange: () => useCanvasArrange,
319
332
  useCanvasArrangeShortcuts: () => useCanvasArrangeShortcuts,
@@ -321,6 +334,7 @@ __export(canvas_exports, {
321
334
  useCanvasClipboard: () => useCanvasClipboard,
322
335
  useCanvasComponents: () => useCanvasComponents,
323
336
  useCanvasDocking: () => useCanvasDocking,
337
+ useCanvasDraw: () => useCanvasDraw,
324
338
  useCanvasExplosion: () => useCanvasExplosion,
325
339
  useCanvasGraph: () => useCanvasGraph,
326
340
  useCanvasLayout: () => useCanvasLayout,
@@ -329,13 +343,13 @@ __export(canvas_exports, {
329
343
  useCanvasShortcuts: () => useCanvasShortcuts,
330
344
  useCanvasTokens: () => useCanvasTokens,
331
345
  useStreamingCanvas: () => useStreamingCanvas,
332
- withNodeAnimation: () => import_canvas24.withNodeAnimation,
333
- withStyleSize: () => import_canvas18.withStyleSize,
334
- wouldCreateComponentCycle: () => import_canvas25.wouldCreateComponentCycle,
335
- wrapAnimationTime: () => import_canvas24.wrapAnimationTime,
336
- writeNodeStyleProperty: () => import_canvas23.writeNodeStyleProperty,
337
- xToTime: () => import_canvas24.xToTime,
338
- xorPolygons: () => import_canvas19.xorPolygons
346
+ withNodeAnimation: () => import_canvas26.withNodeAnimation,
347
+ withStyleSize: () => import_canvas20.withStyleSize,
348
+ wouldCreateComponentCycle: () => import_canvas27.wouldCreateComponentCycle,
349
+ wrapAnimationTime: () => import_canvas26.wrapAnimationTime,
350
+ writeNodeStyleProperty: () => import_canvas25.writeNodeStyleProperty,
351
+ xToTime: () => import_canvas26.xToTime,
352
+ xorPolygons: () => import_canvas21.xorPolygons
339
353
  });
340
354
  module.exports = __toCommonJS(canvas_exports);
341
355
 
@@ -1292,21 +1306,227 @@ function CanvasGuidesLayer({
1292
1306
  );
1293
1307
  }
1294
1308
 
1295
- // src/canvas/useCanvasMeasure.ts
1309
+ // src/canvas/useCanvasDraw.ts
1296
1310
  var import_react10 = require("react");
1297
1311
  var import_canvas8 = require("@pixerate/editor/canvas");
1312
+ function useCanvasDraw(options) {
1313
+ const nodesRef = (0, import_react10.useRef)(options.nodes);
1314
+ nodesRef.current = options.nodes;
1315
+ const optionsRef = (0, import_react10.useRef)(options);
1316
+ optionsRef.current = options;
1317
+ const [tool, setToolState] = (0, import_react10.useState)(options.initialTool ?? "select");
1318
+ const [activeStroke, setActiveStroke] = (0, import_react10.useState)(null);
1319
+ const controller = (0, import_react10.useMemo)(
1320
+ () => (0, import_canvas8.createCanvasDrawController)({
1321
+ getNodes: () => nodesRef.current,
1322
+ setNodes: (next) => {
1323
+ nodesRef.current = next;
1324
+ optionsRef.current.setNodes(next);
1325
+ },
1326
+ get history() {
1327
+ return optionsRef.current.history;
1328
+ },
1329
+ tool: options.initialTool ?? "select",
1330
+ style: options.initialStyle,
1331
+ drawOptions: options.drawOptions,
1332
+ generateNodeId: options.generateNodeId,
1333
+ onToolChange: setToolState,
1334
+ onStyleChange: (s) => setStyleState(s),
1335
+ onActiveStrokeChange: setActiveStroke,
1336
+ onStrokeComplete: (n) => optionsRef.current.onStrokeComplete?.(n),
1337
+ onNodesErase: (erased) => optionsRef.current.onNodesErase?.(erased)
1338
+ }),
1339
+ []
1340
+ );
1341
+ const [style, setStyleState] = (0, import_react10.useState)(controller.style);
1342
+ (0, import_react10.useEffect)(() => {
1343
+ if (options.initialTool && options.initialTool !== controller.tool) {
1344
+ controller.setTool(options.initialTool);
1345
+ }
1346
+ }, [options.initialTool, controller]);
1347
+ return (0, import_react10.useMemo)(
1348
+ () => ({
1349
+ tool,
1350
+ style,
1351
+ activeStroke,
1352
+ isDrawing: activeStroke !== null,
1353
+ setTool: controller.setTool,
1354
+ setStyle: controller.setStyle,
1355
+ startStroke: controller.startStroke,
1356
+ continueStroke: controller.continueStroke,
1357
+ endStroke: controller.endStroke,
1358
+ cancelStroke: controller.cancelStroke,
1359
+ eraseAt: controller.eraseAt
1360
+ }),
1361
+ [tool, style, activeStroke, controller]
1362
+ );
1363
+ }
1364
+
1365
+ // src/canvas/CanvasDrawLayer.tsx
1366
+ var import_react11 = require("react");
1367
+ var import_canvas9 = require("@pixerate/editor/canvas");
1368
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1369
+ var DEFAULT_VIEWPORT2 = { x: 0, y: 0, zoom: 1 };
1370
+ function CanvasDrawLayer({
1371
+ draw,
1372
+ viewport = DEFAULT_VIEWPORT2,
1373
+ className = "",
1374
+ style,
1375
+ cursor,
1376
+ eraserRadius = 12
1377
+ }) {
1378
+ const svgRef = (0, import_react11.useRef)(null);
1379
+ const [spaceHeld, setSpaceHeld] = (0, import_react11.useState)(false);
1380
+ const [eraserPos, setEraserPos] = (0, import_react11.useState)(null);
1381
+ (0, import_react11.useEffect)(() => {
1382
+ function onKeyDown(e) {
1383
+ if (e.code === "Space" && !e.repeat) {
1384
+ const tag = e.target?.tagName;
1385
+ if (tag === "INPUT" || tag === "TEXTAREA" || e.target?.isContentEditable) {
1386
+ return;
1387
+ }
1388
+ setSpaceHeld(true);
1389
+ }
1390
+ }
1391
+ function onKeyUp(e) {
1392
+ if (e.code === "Space") {
1393
+ setSpaceHeld(false);
1394
+ }
1395
+ }
1396
+ window.addEventListener("keydown", onKeyDown);
1397
+ window.addEventListener("keyup", onKeyUp);
1398
+ return () => {
1399
+ window.removeEventListener("keydown", onKeyDown);
1400
+ window.removeEventListener("keyup", onKeyUp);
1401
+ };
1402
+ }, []);
1403
+ const clientToFlow = (0, import_react11.useCallback)(
1404
+ (clientX, clientY) => {
1405
+ if (!svgRef.current) return [0, 0];
1406
+ const rect = svgRef.current.getBoundingClientRect();
1407
+ const screenX = clientX - rect.left;
1408
+ const screenY = clientY - rect.top;
1409
+ const flowX = (screenX - viewport.x) / viewport.zoom;
1410
+ const flowY = (screenY - viewport.y) / viewport.zoom;
1411
+ return [flowX, flowY];
1412
+ },
1413
+ [viewport.x, viewport.y, viewport.zoom]
1414
+ );
1415
+ const isDrawingMode = draw.tool !== "select";
1416
+ const interactive = isDrawingMode && !spaceHeld;
1417
+ const handlePointerDown = (e) => {
1418
+ if (!interactive || e.button !== 0) return;
1419
+ e.preventDefault();
1420
+ e.stopPropagation();
1421
+ e.target.setPointerCapture?.(e.pointerId);
1422
+ const flowPt = clientToFlow(e.clientX, e.clientY);
1423
+ draw.startStroke(flowPt);
1424
+ if (draw.tool === "eraser") {
1425
+ setEraserPos([e.clientX, e.clientY]);
1426
+ }
1427
+ };
1428
+ const handlePointerMove = (e) => {
1429
+ if (draw.tool === "eraser" && !spaceHeld) {
1430
+ setEraserPos([e.clientX, e.clientY]);
1431
+ }
1432
+ if (!interactive) return;
1433
+ if (e.buttons === 1) {
1434
+ e.preventDefault();
1435
+ e.stopPropagation();
1436
+ const flowPt = clientToFlow(e.clientX, e.clientY);
1437
+ draw.continueStroke(flowPt);
1438
+ }
1439
+ };
1440
+ const handlePointerUp = (e) => {
1441
+ if (!interactive || e.button !== 0) return;
1442
+ e.preventDefault();
1443
+ e.stopPropagation();
1444
+ try {
1445
+ e.target.releasePointerCapture?.(e.pointerId);
1446
+ } catch {
1447
+ }
1448
+ draw.endStroke();
1449
+ };
1450
+ const handlePointerLeave = () => {
1451
+ setEraserPos(null);
1452
+ };
1453
+ const resolvedCursor = cursor ? cursor : spaceHeld ? "grab" : draw.tool === "eraser" ? "crosshair" : draw.tool === "pen" || draw.tool === "highlighter" ? "crosshair" : "default";
1454
+ const strokePath = draw.activeStroke ? (0, import_canvas9.strokePointsToPathData)(draw.activeStroke.points) : null;
1455
+ const activeGradient = draw.activeStroke ? (0, import_canvas9.resolveCanvasGradient)(draw.activeStroke.style.gradient ?? draw.activeStroke.style.color) : null;
1456
+ const resolvedGradientDef = activeGradient ? (0, import_canvas9.gradientToSvgDef)(activeGradient, "active-draw-stroke-gradient") : null;
1457
+ const strokePaint = resolvedGradientDef ? `url(#${resolvedGradientDef.id})` : draw.activeStroke ? draw.activeStroke.style.color : "currentColor";
1458
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1459
+ "svg",
1460
+ {
1461
+ ref: svgRef,
1462
+ className: `pixerate-canvas-draw-layer ${className}`,
1463
+ style: {
1464
+ position: "absolute",
1465
+ inset: 0,
1466
+ width: "100%",
1467
+ height: "100%",
1468
+ pointerEvents: interactive ? "all" : "none",
1469
+ cursor: interactive ? resolvedCursor : void 0,
1470
+ overflow: "visible",
1471
+ zIndex: 20,
1472
+ touchAction: "none",
1473
+ ...style
1474
+ },
1475
+ onPointerDown: handlePointerDown,
1476
+ onPointerMove: handlePointerMove,
1477
+ onPointerUp: handlePointerUp,
1478
+ onPointerLeave: handlePointerLeave,
1479
+ children: [
1480
+ resolvedGradientDef && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("defs", { children: [
1481
+ resolvedGradientDef.type === "linear" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("linearGradient", { id: resolvedGradientDef.id, ...resolvedGradientDef.attrs, children: resolvedGradientDef.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) }),
1482
+ resolvedGradientDef.type === "radial" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("radialGradient", { id: resolvedGradientDef.id, ...resolvedGradientDef.attrs, children: resolvedGradientDef.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) })
1483
+ ] }),
1484
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("g", { transform: `translate(${viewport.x}, ${viewport.y}) scale(${viewport.zoom})`, children: draw.activeStroke && strokePath && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1485
+ "path",
1486
+ {
1487
+ className: "pixerate-canvas-draw-active",
1488
+ d: strokePath,
1489
+ fill: "none",
1490
+ stroke: strokePaint,
1491
+ strokeWidth: draw.activeStroke.style.width,
1492
+ opacity: draw.activeStroke.style.opacity,
1493
+ strokeLinecap: draw.activeStroke.style.cap ?? "round",
1494
+ strokeLinejoin: draw.activeStroke.style.join ?? "round"
1495
+ }
1496
+ ) }),
1497
+ draw.tool === "eraser" && eraserPos && svgRef.current && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1498
+ "circle",
1499
+ {
1500
+ cx: eraserPos[0] - svgRef.current.getBoundingClientRect().left,
1501
+ cy: eraserPos[1] - svgRef.current.getBoundingClientRect().top,
1502
+ r: eraserRadius,
1503
+ fill: "rgba(239, 68, 68, 0.15)",
1504
+ stroke: "rgba(239, 68, 68, 0.8)",
1505
+ strokeWidth: 1.5,
1506
+ strokeDasharray: "3 3",
1507
+ pointerEvents: "none"
1508
+ }
1509
+ )
1510
+ ]
1511
+ }
1512
+ );
1513
+ }
1514
+
1515
+ // src/canvas/useCanvasMeasure.ts
1516
+ var import_react12 = require("react");
1517
+ var import_canvas10 = require("@pixerate/editor/canvas");
1298
1518
  var EMPTY = { guides: [], target: null, selection: null };
1299
1519
  function useCanvasMeasure(options) {
1300
1520
  const { nodes, enabled = true, requireModifier = true, targetElement, rectOptions } = options;
1301
- const [hoveredId, setHoveredId] = (0, import_react10.useState)(null);
1302
- const [modifier, setModifier] = (0, import_react10.useState)(false);
1303
- const optionsRef = (0, import_react10.useRef)(options);
1521
+ const [hoveredId, setHoveredId] = (0, import_react12.useState)(null);
1522
+ const [modifier, setModifier] = (0, import_react12.useState)(false);
1523
+ const optionsRef = (0, import_react12.useRef)(options);
1304
1524
  optionsRef.current = options;
1305
- (0, import_react10.useEffect)(() => {
1525
+ (0, import_react12.useEffect)(() => {
1306
1526
  if (!enabled) return;
1307
1527
  const target = targetElement ?? (typeof window !== "undefined" ? window : null);
1308
1528
  if (!target) return;
1309
- const onKey = (event) => setModifier((0, import_canvas8.isMeasureModifierHeld)(event));
1529
+ const onKey = (event) => setModifier((0, import_canvas10.isMeasureModifierHeld)(event));
1310
1530
  const onBlur = () => setModifier(false);
1311
1531
  target.addEventListener("keydown", onKey);
1312
1532
  target.addEventListener("keyup", onKey);
@@ -1319,16 +1539,16 @@ function useCanvasMeasure(options) {
1319
1539
  };
1320
1540
  }, [enabled, targetElement]);
1321
1541
  const active = enabled && (!requireModifier || modifier);
1322
- const result = (0, import_react10.useMemo)(() => {
1542
+ const result = (0, import_react12.useMemo)(() => {
1323
1543
  if (!active) return EMPTY;
1324
1544
  const ids = optionsRef.current.getSelectedIds?.() ?? nodes.filter((n) => n.selected).map((n) => n.id);
1325
- return (0, import_canvas8.measureSelection)(nodes, ids, hoveredId, rectOptions);
1545
+ return (0, import_canvas10.measureSelection)(nodes, ids, hoveredId, rectOptions);
1326
1546
  }, [active, nodes, hoveredId, rectOptions]);
1327
- const onNodeMouseEnter = (0, import_react10.useCallback)((event, node) => {
1547
+ const onNodeMouseEnter = (0, import_react12.useCallback)((event, node) => {
1328
1548
  setHoveredId(node.id);
1329
1549
  if (event && typeof event.altKey === "boolean") setModifier(event.altKey);
1330
1550
  }, []);
1331
- const onNodeMouseLeave = (0, import_react10.useCallback)((_event, node) => {
1551
+ const onNodeMouseLeave = (0, import_react12.useCallback)((_event, node) => {
1332
1552
  setHoveredId((current) => current === node.id ? null : current);
1333
1553
  }, []);
1334
1554
  return {
@@ -1348,17 +1568,17 @@ function useCanvasMeasure(options) {
1348
1568
  }
1349
1569
 
1350
1570
  // src/canvas/index.ts
1351
- var import_canvas17 = require("@pixerate/editor/canvas");
1352
- var import_canvas18 = require("@pixerate/editor/canvas");
1571
+ var import_canvas19 = require("@pixerate/editor/canvas");
1572
+ var import_canvas20 = require("@pixerate/editor/canvas");
1353
1573
 
1354
1574
  // src/canvas/ShapeNode.tsx
1355
- var import_canvas9 = require("@pixerate/editor/canvas");
1356
- var import_jsx_runtime3 = require("react/jsx-runtime");
1357
- function ShapeNode({ data, width, height, selected, className = "", children }) {
1575
+ var import_canvas11 = require("@pixerate/editor/canvas");
1576
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1577
+ function ShapeNode({ id, data, width, height, selected, className = "", children }) {
1358
1578
  const shape = data?.shape;
1359
- if (!(0, import_canvas9.isShapeDescription)(shape)) return null;
1360
- const render = (0, import_canvas9.getShapeRenderData)(shape, { width, height });
1361
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1579
+ if (!(0, import_canvas11.isShapeDescription)(shape)) return null;
1580
+ const render = (0, import_canvas11.getShapeRenderData)(shape, { width, height }, { id: id || data?.id });
1581
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1362
1582
  "div",
1363
1583
  {
1364
1584
  className: `pixerate-shape-node ${className}`.trim(),
@@ -1366,7 +1586,7 @@ function ShapeNode({ data, width, height, selected, className = "", children })
1366
1586
  "data-selected": selected ? "true" : void 0,
1367
1587
  style: { position: "relative", width: "100%", height: "100%" },
1368
1588
  children: [
1369
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1589
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1370
1590
  "svg",
1371
1591
  {
1372
1592
  viewBox: render.viewBox,
@@ -1375,19 +1595,29 @@ function ShapeNode({ data, width, height, selected, className = "", children })
1375
1595
  height: "100%",
1376
1596
  style: { display: "block", overflow: "visible" },
1377
1597
  "aria-hidden": "true",
1378
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1379
- "path",
1380
- {
1381
- d: render.d,
1382
- transform: render.transform,
1383
- fill: render.fill,
1384
- fillRule: render.fillRule,
1385
- stroke: render.stroke,
1386
- strokeWidth: render.strokeWidth,
1387
- opacity: render.opacity,
1388
- vectorEffect: "non-scaling-stroke"
1389
- }
1390
- )
1598
+ children: [
1599
+ (render.fillGradient || render.strokeGradient) && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("defs", { children: [
1600
+ render.fillGradient && render.fillGradient.type === "linear" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("linearGradient", { id: render.fillGradient.id, ...render.fillGradient.attrs, children: render.fillGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) }),
1601
+ render.fillGradient && render.fillGradient.type === "radial" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("radialGradient", { id: render.fillGradient.id, ...render.fillGradient.attrs, children: render.fillGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) }),
1602
+ render.strokeGradient && render.strokeGradient.type === "linear" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("linearGradient", { id: render.strokeGradient.id, ...render.strokeGradient.attrs, children: render.strokeGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) }),
1603
+ render.strokeGradient && render.strokeGradient.type === "radial" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("radialGradient", { id: render.strokeGradient.id, ...render.strokeGradient.attrs, children: render.strokeGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) })
1604
+ ] }),
1605
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1606
+ "path",
1607
+ {
1608
+ d: render.d,
1609
+ transform: render.transform,
1610
+ fill: render.fill,
1611
+ fillRule: render.fillRule,
1612
+ stroke: render.stroke,
1613
+ strokeWidth: render.strokeWidth,
1614
+ strokeLinecap: render.strokeLinecap,
1615
+ strokeLinejoin: render.strokeLinejoin,
1616
+ opacity: render.opacity,
1617
+ vectorEffect: "non-scaling-stroke"
1618
+ }
1619
+ )
1620
+ ]
1391
1621
  }
1392
1622
  ),
1393
1623
  children
@@ -1397,22 +1627,22 @@ function ShapeNode({ data, width, height, selected, className = "", children })
1397
1627
  }
1398
1628
 
1399
1629
  // src/canvas/index.ts
1400
- var import_canvas19 = require("@pixerate/editor/canvas");
1401
- var import_canvas20 = require("@pixerate/editor/canvas");
1402
1630
  var import_canvas21 = require("@pixerate/editor/canvas");
1403
1631
  var import_canvas22 = require("@pixerate/editor/canvas");
1632
+ var import_canvas23 = require("@pixerate/editor/canvas");
1633
+ var import_canvas24 = require("@pixerate/editor/canvas");
1404
1634
 
1405
1635
  // src/canvas/useCanvasAutoLayout.ts
1406
- var import_react11 = require("react");
1407
- var import_canvas10 = require("@pixerate/editor/canvas");
1636
+ var import_react13 = require("react");
1637
+ var import_canvas12 = require("@pixerate/editor/canvas");
1408
1638
  function useCanvasAutoLayout(options) {
1409
- const [guides, setGuides] = (0, import_react11.useState)([]);
1410
- const nodesRef = (0, import_react11.useRef)(options.nodes);
1639
+ const [guides, setGuides] = (0, import_react13.useState)([]);
1640
+ const nodesRef = (0, import_react13.useRef)(options.nodes);
1411
1641
  nodesRef.current = options.nodes;
1412
- const optionsRef = (0, import_react11.useRef)(options);
1642
+ const optionsRef = (0, import_react13.useRef)(options);
1413
1643
  optionsRef.current = options;
1414
- const controller = (0, import_react11.useMemo)(
1415
- () => (0, import_canvas10.createCanvasAutoLayoutController)({
1644
+ const controller = (0, import_react13.useMemo)(
1645
+ () => (0, import_canvas12.createCanvasAutoLayoutController)({
1416
1646
  getNodes: () => nodesRef.current,
1417
1647
  setNodes: (next) => {
1418
1648
  nodesRef.current = next;
@@ -1437,10 +1667,10 @@ function useCanvasAutoLayout(options) {
1437
1667
  }),
1438
1668
  []
1439
1669
  );
1440
- (0, import_react11.useLayoutEffect)(() => {
1670
+ (0, import_react13.useLayoutEffect)(() => {
1441
1671
  if (controller.hasPending) controller.flush();
1442
1672
  }, [options.nodes, controller]);
1443
- return (0, import_react11.useMemo)(
1673
+ return (0, import_react13.useMemo)(
1444
1674
  () => ({
1445
1675
  ...controller,
1446
1676
  /** Drop marker of the active reorder drag (flow coordinates). */
@@ -1454,47 +1684,47 @@ function useCanvasAutoLayout(options) {
1454
1684
  }
1455
1685
 
1456
1686
  // src/canvas/useCanvasTokens.ts
1457
- var import_react12 = require("react");
1458
- var import_canvas11 = require("@pixerate/editor/canvas");
1687
+ var import_react14 = require("react");
1688
+ var import_canvas13 = require("@pixerate/editor/canvas");
1459
1689
  function useCanvasTokens(options) {
1460
1690
  const { store, nodes, setNodes, modes, properties } = options;
1461
- const state = (0, import_react12.useSyncExternalStore)(store.subscribe, store.getState, store.getState);
1462
- const latest = (0, import_react12.useRef)({ nodes, setNodes, modes, properties });
1691
+ const state = (0, import_react14.useSyncExternalStore)(store.subscribe, store.getState, store.getState);
1692
+ const latest = (0, import_react14.useRef)({ nodes, setNodes, modes, properties });
1463
1693
  latest.current = { nodes, setNodes, modes, properties };
1464
1694
  const opts = () => ({ modes: latest.current.modes, properties: latest.current.properties });
1465
- (0, import_react12.useEffect)(
1695
+ (0, import_react14.useEffect)(
1466
1696
  () => store.subscribe((event) => {
1467
1697
  if (event.deletedVariableIds.length === 0) return;
1468
- latest.current.setNodes((prev) => (0, import_canvas11.detachTokenBindings)(prev, event.previous, event.deletedVariableIds, opts()));
1698
+ latest.current.setNodes((prev) => (0, import_canvas13.detachTokenBindings)(prev, event.previous, event.deletedVariableIds, opts()));
1469
1699
  }),
1470
1700
  // eslint-disable-next-line react-hooks/exhaustive-deps
1471
1701
  [store]
1472
1702
  );
1473
1703
  const modesKey = JSON.stringify(modes ?? {});
1474
- (0, import_react12.useEffect)(() => {
1475
- const next = (0, import_canvas11.resolveCanvasTokens)(nodes, state, opts());
1704
+ (0, import_react14.useEffect)(() => {
1705
+ const next = (0, import_canvas13.resolveCanvasTokens)(nodes, state, opts());
1476
1706
  if (next !== nodes) setNodes(next);
1477
1707
  }, [nodes, state, modesKey, properties]);
1478
- const bind = (0, import_react12.useCallback)(
1708
+ const bind = (0, import_react14.useCallback)(
1479
1709
  (ids, propertyKey, variableId) => {
1480
- const next = (0, import_canvas11.bindCanvasToken)(latest.current.nodes, ids, propertyKey, variableId, store.getState(), opts());
1710
+ const next = (0, import_canvas13.bindCanvasToken)(latest.current.nodes, ids, propertyKey, variableId, store.getState(), opts());
1481
1711
  if (next !== latest.current.nodes) latest.current.setNodes(next);
1482
1712
  },
1483
1713
  // eslint-disable-next-line react-hooks/exhaustive-deps
1484
1714
  [store]
1485
1715
  );
1486
- const setMode = (0, import_react12.useCallback)(
1716
+ const setMode = (0, import_react14.useCallback)(
1487
1717
  (ids, collectionId, modeId) => {
1488
- const next = (0, import_canvas11.setCanvasTokenMode)(latest.current.nodes, ids, collectionId, modeId, store.getState(), opts());
1718
+ const next = (0, import_canvas13.setCanvasTokenMode)(latest.current.nodes, ids, collectionId, modeId, store.getState(), opts());
1489
1719
  if (next !== latest.current.nodes) latest.current.setNodes(next);
1490
1720
  },
1491
1721
  // eslint-disable-next-line react-hooks/exhaustive-deps
1492
1722
  [store]
1493
1723
  );
1494
- const modesOf = (0, import_react12.useCallback)(
1724
+ const modesOf = (0, import_react14.useCallback)(
1495
1725
  (nodeId) => {
1496
1726
  const node = latest.current.nodes.find((n) => n.id === nodeId);
1497
- return node ? (0, import_canvas11.getEffectiveTokenModes)(node, latest.current.nodes, store.getState(), opts()) : {};
1727
+ return node ? (0, import_canvas13.getEffectiveTokenModes)(node, latest.current.nodes, store.getState(), opts()) : {};
1498
1728
  },
1499
1729
  // eslint-disable-next-line react-hooks/exhaustive-deps
1500
1730
  [store]
@@ -1503,9 +1733,9 @@ function useCanvasTokens(options) {
1503
1733
  }
1504
1734
 
1505
1735
  // src/canvas/TokenBindingPicker.tsx
1506
- var import_canvas12 = require("@pixerate/editor/canvas");
1736
+ var import_canvas14 = require("@pixerate/editor/canvas");
1507
1737
  var import_tokens = require("@pixerate/editor/tokens");
1508
- var import_jsx_runtime4 = require("react/jsx-runtime");
1738
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1509
1739
  function TokenBindingPicker({
1510
1740
  state,
1511
1741
  nodes,
@@ -1519,18 +1749,18 @@ function TokenBindingPicker({
1519
1749
  const selected = nodes.filter((n) => selectedIds.includes(n.id));
1520
1750
  const first = selected[0];
1521
1751
  if (!first) return null;
1522
- let rows = (0, import_canvas12.getBindableTokenProperties)(first, options);
1752
+ let rows = (0, import_canvas14.getBindableTokenProperties)(first, options);
1523
1753
  if (properties) rows = properties.map((key) => rows.find((p) => p.key === key)).filter((p) => !!p);
1524
- const modes = (0, import_canvas12.getEffectiveTokenModes)(first, nodes, state, options);
1525
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { "data-token-binding-picker": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
1754
+ const modes = (0, import_canvas14.getEffectiveTokenModes)(first, nodes, state, options);
1755
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { "data-token-binding-picker": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
1526
1756
  rows.map((property) => {
1527
- const ids = new Set(selected.map((n) => (0, import_canvas12.getNodeTokenBindings)(n)[property.key] ?? ""));
1757
+ const ids = new Set(selected.map((n) => (0, import_canvas14.getNodeTokenBindings)(n)[property.key] ?? ""));
1528
1758
  const value = ids.size === 1 ? [...ids][0] : "__mixed";
1529
- const candidates = (0, import_canvas12.getTokensForProperty)(state, property, first);
1759
+ const candidates = (0, import_canvas14.getTokensForProperty)(state, property, first);
1530
1760
  const resolved = value && value !== "__mixed" ? (0, import_tokens.resolveToken)(state, value, modes) : null;
1531
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-2", "data-token-property": property.key, children: [
1532
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-28 shrink-0 text-muted-foreground", children: property.label }),
1533
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1761
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-2", "data-token-property": property.key, children: [
1762
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-28 shrink-0 text-muted-foreground", children: property.label }),
1763
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1534
1764
  "select",
1535
1765
  {
1536
1766
  "aria-label": `${property.label} variable`,
@@ -1539,17 +1769,17 @@ function TokenBindingPicker({
1539
1769
  onChange: (e) => {
1540
1770
  const id = e.currentTarget.value || null;
1541
1771
  try {
1542
- onChange((0, import_canvas12.bindCanvasToken)(nodes, selectedIds, property.key, id, state, options));
1772
+ onChange((0, import_canvas14.bindCanvasToken)(nodes, selectedIds, property.key, id, state, options));
1543
1773
  } catch (error) {
1544
1774
  onError?.(error);
1545
1775
  }
1546
1776
  },
1547
1777
  children: [
1548
- value === "__mixed" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "__mixed", children: "Mixed" }) : null,
1549
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: "None" }),
1778
+ value === "__mixed" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "__mixed", children: "Mixed" }) : null,
1779
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "", children: "None" }),
1550
1780
  candidates.map((v) => {
1551
1781
  const collection = state.collections.find((c) => c.id === v.collectionId);
1552
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("option", { value: v.id, children: [
1782
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("option", { value: v.id, children: [
1553
1783
  v.name,
1554
1784
  collection && state.collections.length > 1 ? ` (${collection.name})` : ""
1555
1785
  ] }, v.id);
@@ -1557,17 +1787,17 @@ function TokenBindingPicker({
1557
1787
  ]
1558
1788
  }
1559
1789
  ),
1560
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16 shrink-0 truncate text-right text-muted-foreground", "data-token-resolved": "", children: resolved?.ok ? property.type === "color" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1790
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16 shrink-0 truncate text-right text-muted-foreground", "data-token-resolved": "", children: resolved?.ok ? property.type === "color" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1561
1791
  "span",
1562
1792
  {
1563
1793
  className: "inline-block h-3 w-3 rounded border border-border align-middle",
1564
1794
  style: { background: String(resolved.value) },
1565
1795
  title: String(resolved.value)
1566
1796
  }
1567
- ) : String(resolved.value) : resolved ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { title: resolved.message, children: "\u26A0" }) : null })
1797
+ ) : String(resolved.value) : resolved ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { title: resolved.message, children: "\u26A0" }) : null })
1568
1798
  ] }, property.key);
1569
1799
  }),
1570
- state.collections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-muted-foreground", children: "No variables yet." }) : null
1800
+ state.collections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-muted-foreground", children: "No variables yet." }) : null
1571
1801
  ] });
1572
1802
  }
1573
1803
  function TokenModeSwitcher({
@@ -1581,29 +1811,29 @@ function TokenModeSwitcher({
1581
1811
  }) {
1582
1812
  const first = nodes.find((n) => nodeIds.includes(n.id));
1583
1813
  if (!first) return null;
1584
- const own = (0, import_canvas12.getNodeTokenModes)(first);
1814
+ const own = (0, import_canvas14.getNodeTokenModes)(first);
1585
1815
  const parent = first.parentId ? nodes.find((n) => n.id === first.parentId) : void 0;
1586
- const inherited = parent ? (0, import_canvas12.getEffectiveTokenModes)(parent, nodes, state, options) : { ...options.modes };
1816
+ const inherited = parent ? (0, import_canvas14.getEffectiveTokenModes)(parent, nodes, state, options) : { ...options.modes };
1587
1817
  const collections = state.collections.filter((c) => showSingleMode || c.modes.length > 1);
1588
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { "data-token-mode-switcher": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: collections.map((collection) => {
1818
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { "data-token-mode-switcher": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: collections.map((collection) => {
1589
1819
  const auto = (0, import_tokens.getCurrentMode)(collection, inherited);
1590
1820
  const explicit = collection.modes.some((m) => m.id === own[collection.id]) ? own[collection.id] : "";
1591
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-2", "data-token-collection": collection.id, children: [
1592
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-28 shrink-0 truncate text-muted-foreground", children: collection.name }),
1593
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1821
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-2", "data-token-collection": collection.id, children: [
1822
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-28 shrink-0 truncate text-muted-foreground", children: collection.name }),
1823
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1594
1824
  "select",
1595
1825
  {
1596
1826
  "aria-label": `${collection.name} mode`,
1597
1827
  className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
1598
1828
  value: explicit,
1599
- onChange: (e) => onChange((0, import_canvas12.setCanvasTokenMode)(nodes, nodeIds, collection.id, e.currentTarget.value || null, state, options)),
1829
+ onChange: (e) => onChange((0, import_canvas14.setCanvasTokenMode)(nodes, nodeIds, collection.id, e.currentTarget.value || null, state, options)),
1600
1830
  children: [
1601
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("option", { value: "", children: [
1831
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("option", { value: "", children: [
1602
1832
  "Auto (",
1603
1833
  auto.name,
1604
1834
  ")"
1605
1835
  ] }),
1606
- collection.modes.map((m) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: m.id, children: m.name }, m.id))
1836
+ collection.modes.map((m) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: m.id, children: m.name }, m.id))
1607
1837
  ]
1608
1838
  }
1609
1839
  )
@@ -1612,18 +1842,18 @@ function TokenModeSwitcher({
1612
1842
  }
1613
1843
 
1614
1844
  // src/canvas/index.ts
1615
- var import_canvas23 = require("@pixerate/editor/canvas");
1845
+ var import_canvas25 = require("@pixerate/editor/canvas");
1616
1846
 
1617
1847
  // src/canvas/useCanvasAnimation.ts
1618
- var import_react13 = require("react");
1619
- var import_canvas13 = require("@pixerate/editor/canvas");
1848
+ var import_react15 = require("react");
1849
+ var import_canvas15 = require("@pixerate/editor/canvas");
1620
1850
  function useCanvasAnimation(options) {
1621
- const nodesRef = (0, import_react13.useRef)(options.nodes);
1851
+ const nodesRef = (0, import_react15.useRef)(options.nodes);
1622
1852
  nodesRef.current = options.nodes;
1623
- const optionsRef = (0, import_react13.useRef)(options);
1853
+ const optionsRef = (0, import_react15.useRef)(options);
1624
1854
  optionsRef.current = options;
1625
- const controller = (0, import_react13.useMemo)(
1626
- () => (0, import_canvas13.createCanvasAnimationController)({
1855
+ const controller = (0, import_react15.useMemo)(
1856
+ () => (0, import_canvas15.createCanvasAnimationController)({
1627
1857
  getNodes: () => nodesRef.current,
1628
1858
  setNodes: (next) => {
1629
1859
  nodesRef.current = next;
@@ -1649,26 +1879,26 @@ function useCanvasAnimation(options) {
1649
1879
  }),
1650
1880
  []
1651
1881
  );
1652
- (0, import_react13.useEffect)(() => () => controller.destroy(), [controller]);
1653
- (0, import_react13.useEffect)(() => {
1882
+ (0, import_react15.useEffect)(() => () => controller.destroy(), [controller]);
1883
+ (0, import_react15.useEffect)(() => {
1654
1884
  if (options.loop !== void 0) controller.setLoop(options.loop);
1655
1885
  }, [controller, options.loop]);
1656
- (0, import_react13.useEffect)(() => {
1886
+ (0, import_react15.useEffect)(() => {
1657
1887
  if (options.playbackRate !== void 0) controller.setPlaybackRate(options.playbackRate);
1658
1888
  }, [controller, options.playbackRate]);
1659
- (0, import_react13.useEffect)(() => {
1889
+ (0, import_react15.useEffect)(() => {
1660
1890
  if (options.recording !== void 0) controller.setRecording(options.recording);
1661
1891
  }, [controller, options.recording]);
1662
- const state = (0, import_react13.useSyncExternalStore)(
1892
+ const state = (0, import_react15.useSyncExternalStore)(
1663
1893
  (listener) => controller.subscribe(listener),
1664
1894
  () => controller.getState(),
1665
1895
  () => controller.getState()
1666
1896
  );
1667
- (0, import_react13.useEffect)(() => {
1897
+ (0, import_react15.useEffect)(() => {
1668
1898
  controller.refresh();
1669
1899
  }, [controller, options.nodes]);
1670
- const displayNodes = (0, import_react13.useMemo)(() => controller.display(options.nodes), [controller, options.nodes, state.time]);
1671
- return (0, import_react13.useMemo)(
1900
+ const displayNodes = (0, import_react15.useMemo)(() => controller.display(options.nodes), [controller, options.nodes, state.time]);
1901
+ return (0, import_react15.useMemo)(
1672
1902
  () => ({
1673
1903
  ...controller,
1674
1904
  state,
@@ -1689,24 +1919,24 @@ function useCanvasAnimation(options) {
1689
1919
  }
1690
1920
 
1691
1921
  // src/canvas/AnimationTimeline.tsx
1692
- var import_react14 = require("react");
1693
- var import_canvas14 = require("@pixerate/editor/canvas");
1694
- var import_jsx_runtime5 = require("react/jsx-runtime");
1922
+ var import_react16 = require("react");
1923
+ var import_canvas16 = require("@pixerate/editor/canvas");
1924
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1695
1925
  var LOOP_LABELS = { none: "Once", loop: "Loop", "ping-pong": "Ping-pong" };
1696
1926
  var easingValue = (easing) => typeof easing === "string" ? easing : easing ? "custom" : "linear";
1697
1927
  function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8, labelOf, className = "" }) {
1698
1928
  const { state } = animation;
1699
1929
  const duration = state.duration;
1700
1930
  const rows = animation.timelineRows(nodeIds ?? void 0, labelOf ? { labelOf } : {});
1701
- const ticks = (0, import_canvas14.getTimelineTicks)(duration, width);
1931
+ const ticks = (0, import_canvas16.getTimelineTicks)(duration, width);
1702
1932
  const selectedEasing = (() => {
1703
1933
  const first = state.selection[0];
1704
1934
  if (!first) return "";
1705
1935
  for (const row of rows) for (const k of row.keyframes) if (k.selected && k.ref.property === first.property && k.ref.nodeId === first.nodeId) return easingValue(k.easing);
1706
1936
  return "";
1707
1937
  })();
1708
- const dragRef = (0, import_react14.useRef)(null);
1709
- (0, import_react14.useEffect)(() => {
1938
+ const dragRef = (0, import_react16.useRef)(null);
1939
+ (0, import_react16.useEffect)(() => {
1710
1940
  const onKey = (event) => {
1711
1941
  if (event.key === "Escape" && dragRef.current) {
1712
1942
  dragRef.current = null;
@@ -1719,8 +1949,8 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
1719
1949
  const onRulerDown = (event) => {
1720
1950
  const lane = event.currentTarget;
1721
1951
  const left = lane.getBoundingClientRect().left;
1722
- animation.scrub((0, import_canvas14.xToTime)(event.clientX - left, duration, width));
1723
- const move = (e) => animation.scrub((0, import_canvas14.xToTime)(e.clientX - left, duration, width));
1952
+ animation.scrub((0, import_canvas16.xToTime)(event.clientX - left, duration, width));
1953
+ const move = (e) => animation.scrub((0, import_canvas16.xToTime)(e.clientX - left, duration, width));
1724
1954
  const up = () => {
1725
1955
  window.removeEventListener("pointermove", move);
1726
1956
  window.removeEventListener("pointerup", up);
@@ -1760,12 +1990,12 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
1760
1990
  }
1761
1991
  };
1762
1992
  const btn = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-50";
1763
- const playheadX = (0, import_canvas14.timeToX)(state.time, duration, width);
1993
+ const playheadX = (0, import_canvas16.timeToX)(state.time, duration, width);
1764
1994
  const labelWidth = 120;
1765
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { "data-animation-timeline": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, tabIndex: 0, onKeyDown: onTimelineKey, children: [
1766
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "toolbar", "aria-label": "Animation", children: [
1767
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: btn, "data-action": "toggle-play", "aria-label": state.playing ? "Pause" : "Play", onClick: () => animation.toggle(), children: state.playing ? "\u275A\u275A" : "\u25B6" }),
1768
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1995
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-animation-timeline": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, tabIndex: 0, onKeyDown: onTimelineKey, children: [
1996
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "toolbar", "aria-label": "Animation", children: [
1997
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: btn, "data-action": "toggle-play", "aria-label": state.playing ? "Pause" : "Play", onClick: () => animation.toggle(), children: state.playing ? "\u275A\u275A" : "\u25B6" }),
1998
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1769
1999
  "button",
1770
2000
  {
1771
2001
  type: "button",
@@ -1777,13 +2007,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
1777
2007
  children: "\u25CF Rec"
1778
2008
  }
1779
2009
  ),
1780
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: btn, "data-action": "add-keyframe", onClick: () => animation.addKeyframe(), children: "\u25C6 Key" }),
1781
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { "data-time": "", className: "tabular-nums text-muted-foreground", children: [
1782
- (0, import_canvas14.formatAnimationTime)(state.time),
2010
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: btn, "data-action": "add-keyframe", onClick: () => animation.addKeyframe(), children: "\u25C6 Key" }),
2011
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { "data-time": "", className: "tabular-nums text-muted-foreground", children: [
2012
+ (0, import_canvas16.formatAnimationTime)(state.time),
1783
2013
  " / ",
1784
- (0, import_canvas14.formatAnimationTime)(duration)
2014
+ (0, import_canvas16.formatAnimationTime)(duration)
1785
2015
  ] }),
1786
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2016
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1787
2017
  "select",
1788
2018
  {
1789
2019
  "aria-label": "Easing",
@@ -1793,13 +2023,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
1793
2023
  disabled: state.selection.length === 0,
1794
2024
  onChange: (e) => e.target.value && e.target.value !== "custom" && animation.setEasing(e.target.value),
1795
2025
  children: [
1796
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "", children: "Easing\u2026" }),
1797
- import_canvas14.ANIMATION_EASING_PRESETS.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: preset, children: import_canvas14.ANIMATION_EASING_LABELS[preset] }, preset)),
1798
- selectedEasing === "custom" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "custom", children: "Custom" }) : null
2026
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: "Easing\u2026" }),
2027
+ import_canvas16.ANIMATION_EASING_PRESETS.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: preset, children: import_canvas16.ANIMATION_EASING_LABELS[preset] }, preset)),
2028
+ selectedEasing === "custom" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "custom", children: "Custom" }) : null
1799
2029
  ]
1800
2030
  }
1801
2031
  ),
1802
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2032
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1803
2033
  "select",
1804
2034
  {
1805
2035
  "aria-label": "Loop",
@@ -1807,13 +2037,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
1807
2037
  className: "rounded border border-border bg-background px-1 py-0.5",
1808
2038
  value: state.loop,
1809
2039
  onChange: (e) => animation.setLoop(e.target.value),
1810
- children: Object.keys(LOOP_LABELS).map((mode) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: mode, children: LOOP_LABELS[mode] }, mode))
2040
+ children: Object.keys(LOOP_LABELS).map((mode) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: mode, children: LOOP_LABELS[mode] }, mode))
1811
2041
  }
1812
2042
  )
1813
2043
  ] }),
1814
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex", children: [
1815
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: { width: labelWidth }, className: "shrink-0" }),
1816
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2044
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex", children: [
2045
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { width: labelWidth }, className: "shrink-0" }),
2046
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1817
2047
  "div",
1818
2048
  {
1819
2049
  "data-timeline-ruler": "",
@@ -1821,15 +2051,15 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
1821
2051
  style: { width },
1822
2052
  onPointerDown: onRulerDown,
1823
2053
  children: [
1824
- ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "absolute top-0 -translate-x-1/2 text-[10px] text-muted-foreground", style: { left: tick.x }, children: tick.label }, tick.time)),
1825
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { "data-playhead": "", className: "absolute top-0 h-5 w-px bg-red-500", style: { left: playheadX } })
2054
+ ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "absolute top-0 -translate-x-1/2 text-[10px] text-muted-foreground", style: { left: tick.x }, children: tick.label }, tick.time)),
2055
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-playhead": "", className: "absolute top-0 h-5 w-px bg-red-500", style: { left: playheadX } })
1826
2056
  ]
1827
2057
  }
1828
2058
  )
1829
2059
  ] }),
1830
- rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-muted-foreground", "data-timeline-empty": "", children: "Select an animated node, or press \u25C6 Key to add a keyframe." }) : rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center", "data-track": row.id, children: [
1831
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex shrink-0 items-center gap-1 truncate pr-2", style: { width: labelWidth }, title: `${row.nodeLabel} \xB7 ${row.label}`, children: [
1832
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2060
+ rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-muted-foreground", "data-timeline-empty": "", children: "Select an animated node, or press \u25C6 Key to add a keyframe." }) : rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center", "data-track": row.id, children: [
2061
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex shrink-0 items-center gap-1 truncate pr-2", style: { width: labelWidth }, title: `${row.nodeLabel} \xB7 ${row.label}`, children: [
2062
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1833
2063
  "input",
1834
2064
  {
1835
2065
  type: "checkbox",
@@ -1838,24 +2068,24 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
1838
2068
  onChange: (e) => animation.setTrackEnabled(row.nodeId, row.property, e.target.checked)
1839
2069
  }
1840
2070
  ),
1841
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "truncate", children: [
2071
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "truncate", children: [
1842
2072
  rows.filter((r) => r.nodeId === row.nodeId).length < rows.length ? `${row.nodeLabel} \xB7 ` : "",
1843
2073
  row.label
1844
2074
  ] })
1845
2075
  ] }),
1846
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { "data-lane": "", className: `relative h-5 rounded bg-muted/40 ${row.enabled ? "" : "opacity-50"}`, style: { width }, children: [
1847
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "pointer-events-none absolute top-0 h-5 w-px bg-red-500/60", style: { left: playheadX } }),
1848
- state.drag?.target != null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { "data-snap-target": "", className: "pointer-events-none absolute top-0 h-5 w-px bg-sky-400", style: { left: (0, import_canvas14.timeToX)(state.drag.target, duration, width) } }) : null,
1849
- row.keyframes.map((k) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2076
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-lane": "", className: `relative h-5 rounded bg-muted/40 ${row.enabled ? "" : "opacity-50"}`, style: { width }, children: [
2077
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "pointer-events-none absolute top-0 h-5 w-px bg-red-500/60", style: { left: playheadX } }),
2078
+ state.drag?.target != null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-snap-target": "", className: "pointer-events-none absolute top-0 h-5 w-px bg-sky-400", style: { left: (0, import_canvas16.timeToX)(state.drag.target, duration, width) } }) : null,
2079
+ row.keyframes.map((k) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1850
2080
  "button",
1851
2081
  {
1852
2082
  type: "button",
1853
2083
  "data-keyframe": k.ref.time,
1854
2084
  "aria-pressed": k.selected,
1855
- "aria-label": `${row.label} keyframe at ${(0, import_canvas14.formatAnimationTime)(k.ref.time)}`,
1856
- title: `${(0, import_canvas14.formatAnimationTime)(k.time)} \xB7 ${String(k.value)}`,
2085
+ "aria-label": `${row.label} keyframe at ${(0, import_canvas16.formatAnimationTime)(k.ref.time)}`,
2086
+ title: `${(0, import_canvas16.formatAnimationTime)(k.time)} \xB7 ${String(k.value)}`,
1857
2087
  className: `absolute top-1/2 h-2.5 w-2.5 -translate-x-1/2 -translate-y-1/2 rotate-45 border ${k.selected ? "border-sky-300 bg-sky-500" : "border-foreground/60 bg-background"} ${k.easing === "hold" ? "rounded-none" : "rounded-[1px]"}`,
1858
- style: { left: (0, import_canvas14.timeToX)(k.time, duration, width) },
2088
+ style: { left: (0, import_canvas16.timeToX)(k.time, duration, width) },
1859
2089
  onPointerDown: onKeyDown(k.ref)
1860
2090
  },
1861
2091
  k.ref.time
@@ -1866,18 +2096,18 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
1866
2096
  }
1867
2097
 
1868
2098
  // src/canvas/index.ts
1869
- var import_canvas24 = require("@pixerate/editor/canvas");
2099
+ var import_canvas26 = require("@pixerate/editor/canvas");
1870
2100
 
1871
2101
  // src/canvas/useCanvasComponents.ts
1872
- var import_react15 = require("react");
1873
- var import_canvas15 = require("@pixerate/editor/canvas");
2102
+ var import_react17 = require("react");
2103
+ var import_canvas17 = require("@pixerate/editor/canvas");
1874
2104
  function useCanvasComponents(options) {
1875
- const nodesRef = (0, import_react15.useRef)(options.nodes);
2105
+ const nodesRef = (0, import_react17.useRef)(options.nodes);
1876
2106
  nodesRef.current = options.nodes;
1877
- const optionsRef = (0, import_react15.useRef)(options);
2107
+ const optionsRef = (0, import_react17.useRef)(options);
1878
2108
  optionsRef.current = options;
1879
- const controller = (0, import_react15.useMemo)(
1880
- () => (0, import_canvas15.createCanvasComponentsController)({
2109
+ const controller = (0, import_react17.useMemo)(
2110
+ () => (0, import_canvas17.createCanvasComponentsController)({
1881
2111
  getNodes: () => nodesRef.current,
1882
2112
  setNodes: (next) => {
1883
2113
  nodesRef.current = next;
@@ -1905,18 +2135,18 @@ function useCanvasComponents(options) {
1905
2135
  }),
1906
2136
  []
1907
2137
  );
1908
- (0, import_react15.useLayoutEffect)(() => {
2138
+ (0, import_react17.useLayoutEffect)(() => {
1909
2139
  if (optionsRef.current.autoSync !== false) controller.sync();
1910
2140
  }, [options.nodes, controller]);
1911
2141
  return controller;
1912
2142
  }
1913
2143
 
1914
2144
  // src/canvas/CanvasComponentsPanel.tsx
1915
- var import_react16 = require("react");
1916
- var import_canvas16 = require("@pixerate/editor/canvas");
1917
- var import_jsx_runtime6 = require("react/jsx-runtime");
2145
+ var import_react18 = require("react");
2146
+ var import_canvas18 = require("@pixerate/editor/canvas");
2147
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1918
2148
  function InlineField({ value, label, onCommit }) {
1919
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2149
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1920
2150
  "input",
1921
2151
  {
1922
2152
  type: "text",
@@ -1947,11 +2177,11 @@ function CanvasComponentsPanel({
1947
2177
  search = true,
1948
2178
  className = ""
1949
2179
  }) {
1950
- const [query, setQuery] = (0, import_react16.useState)("");
1951
- const [propsOpen, setPropsOpen] = (0, import_react16.useState)(null);
1952
- const [menuFor, setMenuFor] = (0, import_react16.useState)(null);
1953
- const [editing, setEditing] = (0, import_react16.useState)(null);
1954
- const { components: all, sets } = (0, import_canvas16.listCanvasComponents)(nodes);
2180
+ const [query, setQuery] = (0, import_react18.useState)("");
2181
+ const [propsOpen, setPropsOpen] = (0, import_react18.useState)(null);
2182
+ const [menuFor, setMenuFor] = (0, import_react18.useState)(null);
2183
+ const [editing, setEditing] = (0, import_react18.useState)(null);
2184
+ const { components: all, sets } = (0, import_canvas18.listCanvasComponents)(nodes);
1955
2185
  const q = query.trim().toLowerCase();
1956
2186
  const match = (name) => !q || name.toLowerCase().includes(q);
1957
2187
  const lone = all.filter((c) => !c.setId && match(c.name));
@@ -1962,7 +2192,7 @@ function CanvasComponentsPanel({
1962
2192
  };
1963
2193
  const small = "shrink-0 rounded px-1 text-[10px] text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-40";
1964
2194
  const menuItem = "rounded px-2 py-0.5 text-left hover:bg-muted disabled:opacity-40";
1965
- const item = (id, name, count, extra = {}, onContextMenu) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2195
+ const item = (id, name, count, extra = {}, onContextMenu) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1966
2196
  "button",
1967
2197
  {
1968
2198
  type: "button",
@@ -1974,22 +2204,22 @@ function CanvasComponentsPanel({
1974
2204
  onClick: () => onInsert(id),
1975
2205
  onContextMenu,
1976
2206
  onDragStart: (e) => {
1977
- e.dataTransfer.setData(import_canvas16.CANVAS_COMPONENT_DRAG_TYPE, id);
2207
+ e.dataTransfer.setData(import_canvas18.CANVAS_COMPONENT_DRAG_TYPE, id);
1978
2208
  e.dataTransfer.setData("text/plain", name);
1979
2209
  e.dataTransfer.effectAllowed = "copy";
1980
2210
  },
1981
2211
  children: [
1982
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "truncate", children: [
1983
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "aria-hidden": true, className: "mr-1 text-muted-foreground", children: "\u25C7" }),
2212
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "truncate", children: [
2213
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { "aria-hidden": true, className: "mr-1 text-muted-foreground", children: "\u25C7" }),
1984
2214
  name
1985
2215
  ] }),
1986
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[10px] text-muted-foreground", "data-instance-count": "", children: count })
2216
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[10px] text-muted-foreground", "data-instance-count": "", children: count })
1987
2217
  ]
1988
2218
  },
1989
2219
  id
1990
2220
  );
1991
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-components-panel": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
1992
- search ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2221
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-components-panel": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
2222
+ search ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1993
2223
  "input",
1994
2224
  {
1995
2225
  type: "search",
@@ -1999,11 +2229,11 @@ function CanvasComponentsPanel({
1999
2229
  onInput: (e) => setQuery(e.target.value)
2000
2230
  }
2001
2231
  ) : null,
2002
- shownSets.map((set) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-component-set": set.id, className: "flex flex-col", children: [
2003
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1", children: [
2232
+ shownSets.map((set) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-component-set": set.id, className: "flex flex-col", children: [
2233
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-1", children: [
2004
2234
  item(set.id, set.name, set.variants.reduce((sum, v) => sum + v.instanceCount, 0), { "data-kind": "set" }),
2005
- components ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2006
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2235
+ components ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2236
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2007
2237
  "button",
2008
2238
  {
2009
2239
  type: "button",
@@ -2015,7 +2245,7 @@ function CanvasComponentsPanel({
2015
2245
  children: "+\xA0Variant"
2016
2246
  }
2017
2247
  ),
2018
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2248
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2019
2249
  "button",
2020
2250
  {
2021
2251
  type: "button",
@@ -2030,8 +2260,8 @@ function CanvasComponentsPanel({
2030
2260
  )
2031
2261
  ] }) : null
2032
2262
  ] }),
2033
- components && propsOpen === set.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-variant-properties": set.id, className: "ml-3 flex flex-col gap-1 border-l border-border py-1 pl-2", children: set.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-variant-option": option.name, className: "flex flex-col gap-0.5", children: [
2034
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2263
+ components && propsOpen === set.id ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-variant-properties": set.id, className: "ml-3 flex flex-col gap-1 border-l border-border py-1 pl-2", children: set.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-variant-option": option.name, className: "flex flex-col gap-0.5", children: [
2264
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2035
2265
  InlineField,
2036
2266
  {
2037
2267
  value: option.name,
@@ -2039,7 +2269,7 @@ function CanvasComponentsPanel({
2039
2269
  onCommit: (next) => report(components.renameVariantProperty(option.name, next, set.id))
2040
2270
  }
2041
2271
  ),
2042
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ml-2 flex flex-wrap gap-1", children: option.values.map((value) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2272
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "ml-2 flex flex-wrap gap-1", children: option.values.map((value) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2043
2273
  InlineField,
2044
2274
  {
2045
2275
  value,
@@ -2049,8 +2279,8 @@ function CanvasComponentsPanel({
2049
2279
  value
2050
2280
  )) })
2051
2281
  ] }, option.name)) }) : null,
2052
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ml-3 flex flex-col border-l border-border pl-1", children: set.variants.map((v) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-variant-row": v.id, className: "flex flex-col", children: [
2053
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1", children: [
2282
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "ml-3 flex flex-col border-l border-border pl-1", children: set.variants.map((v) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-variant-row": v.id, className: "flex flex-col", children: [
2283
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-1", children: [
2054
2284
  item(
2055
2285
  v.id,
2056
2286
  v.name,
@@ -2061,7 +2291,7 @@ function CanvasComponentsPanel({
2061
2291
  setMenuFor(v.id);
2062
2292
  } : void 0
2063
2293
  ),
2064
- components ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2294
+ components ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2065
2295
  "button",
2066
2296
  {
2067
2297
  type: "button",
@@ -2075,8 +2305,8 @@ function CanvasComponentsPanel({
2075
2305
  }
2076
2306
  ) : null
2077
2307
  ] }),
2078
- components && menuFor === v.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "menu", "data-variant-menu": v.id, className: "ml-2 flex flex-col rounded border border-border bg-background p-1 shadow", children: [
2079
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2308
+ components && menuFor === v.id ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "menu", "data-variant-menu": v.id, className: "ml-2 flex flex-col rounded border border-border bg-background p-1 shadow", children: [
2309
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2080
2310
  "button",
2081
2311
  {
2082
2312
  type: "button",
@@ -2090,7 +2320,7 @@ function CanvasComponentsPanel({
2090
2320
  children: "Edit values\u2026"
2091
2321
  }
2092
2322
  ),
2093
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2323
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2094
2324
  "button",
2095
2325
  {
2096
2326
  type: "button",
@@ -2104,7 +2334,7 @@ function CanvasComponentsPanel({
2104
2334
  children: "Duplicate"
2105
2335
  }
2106
2336
  ),
2107
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2337
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2108
2338
  "button",
2109
2339
  {
2110
2340
  type: "button",
@@ -2121,7 +2351,7 @@ function CanvasComponentsPanel({
2121
2351
  }
2122
2352
  )
2123
2353
  ] }) : null,
2124
- components && editing === v.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2354
+ components && editing === v.id ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2125
2355
  "form",
2126
2356
  {
2127
2357
  "data-variant-editor": v.id,
@@ -2135,9 +2365,9 @@ function CanvasComponentsPanel({
2135
2365
  if (report(components.setVariantProperties(values, v.id))) setEditing(null);
2136
2366
  },
2137
2367
  children: [
2138
- set.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-2", children: [
2139
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16 shrink-0 truncate text-muted-foreground", children: option.name }),
2140
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2368
+ set.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-2", children: [
2369
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-16 shrink-0 truncate text-muted-foreground", children: option.name }),
2370
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2141
2371
  "input",
2142
2372
  {
2143
2373
  type: "text",
@@ -2148,9 +2378,9 @@ function CanvasComponentsPanel({
2148
2378
  }
2149
2379
  )
2150
2380
  ] }, option.name)),
2151
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-1", children: [
2152
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "submit", className: "rounded border border-border px-2 py-0.5 hover:bg-muted", "data-action": "save-variant", children: "Save" }),
2153
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "rounded px-2 py-0.5 hover:bg-muted", "data-action": "cancel-variant", onClick: () => setEditing(null), children: "Cancel" })
2381
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-1", children: [
2382
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "submit", className: "rounded border border-border px-2 py-0.5 hover:bg-muted", "data-action": "save-variant", children: "Save" }),
2383
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "rounded px-2 py-0.5 hover:bg-muted", "data-action": "cancel-variant", onClick: () => setEditing(null), children: "Cancel" })
2154
2384
  ] })
2155
2385
  ]
2156
2386
  }
@@ -2158,7 +2388,7 @@ function CanvasComponentsPanel({
2158
2388
  ] }, v.id)) })
2159
2389
  ] }, set.id)),
2160
2390
  lone.map((c) => item(c.id, c.name, c.instanceCount, { "data-kind": "component" })),
2161
- all.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-muted-foreground", children: "No components yet. Select a frame and choose Create Component." }) : null
2391
+ all.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-muted-foreground", children: "No components yet. Select a frame and choose Create Component." }) : null
2162
2392
  ] });
2163
2393
  }
2164
2394
  function CanvasInstanceInspector({
@@ -2168,36 +2398,36 @@ function CanvasInstanceInspector({
2168
2398
  onError,
2169
2399
  className = ""
2170
2400
  }) {
2171
- const info = nodeId ? (0, import_canvas16.inspectCanvasInstance)(nodes, nodeId) : void 0;
2401
+ const info = nodeId ? (0, import_canvas18.inspectCanvasInstance)(nodes, nodeId) : void 0;
2172
2402
  if (!info) return null;
2173
2403
  const report = (result) => {
2174
2404
  if (result && !result.ok && result.reason) onError?.(result.reason);
2175
2405
  };
2176
2406
  const setProp = (name, value) => report(components.setInstanceProperties({ [name]: value }, [info.id]));
2177
- const allComponents = (0, import_canvas16.listCanvasComponents)(nodes).components;
2407
+ const allComponents = (0, import_canvas18.listCanvasComponents)(nodes).components;
2178
2408
  const linked = info.status === "linked";
2179
2409
  const btn = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-40";
2180
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-instance-inspector": "", "data-instance-id": info.id, className: `flex flex-col gap-2 text-xs text-foreground ${className}`, children: [
2181
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
2182
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate font-medium", "data-instance-main": "", children: linked ? info.componentName : "Main component missing" }),
2183
- info.nested ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-muted-foreground", children: "Nested" }) : null
2410
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-instance-inspector": "", "data-instance-id": info.id, className: `flex flex-col gap-2 text-xs text-foreground ${className}`, children: [
2411
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
2412
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate font-medium", "data-instance-main": "", children: linked ? info.componentName : "Main component missing" }),
2413
+ info.nested ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-muted-foreground", children: "Nested" }) : null
2184
2414
  ] }),
2185
- info.variantOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-2", "data-variant-property": option.name, children: [
2186
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: option.name }),
2187
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2415
+ info.variantOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-2", "data-variant-property": option.name, children: [
2416
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: option.name }),
2417
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2188
2418
  "select",
2189
2419
  {
2190
2420
  "aria-label": `${option.name} variant`,
2191
2421
  className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
2192
2422
  value: info.variant[option.name] ?? "",
2193
2423
  onChange: (e) => setProp(option.name, e.currentTarget.value),
2194
- children: option.values.map((v) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: v, children: v }, v))
2424
+ children: option.values.map((v) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: v, children: v }, v))
2195
2425
  }
2196
2426
  )
2197
2427
  ] }, option.name)),
2198
- info.properties.map((p) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-2", "data-component-property": p.name, children: [
2199
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: p.name }),
2200
- p.type === "boolean" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { type: "checkbox", "aria-label": p.name, checked: p.value === true, onChange: (e) => setProp(p.name, e.currentTarget.checked) }) : p.type === "text" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2428
+ info.properties.map((p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-2", "data-component-property": p.name, children: [
2429
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: p.name }),
2430
+ p.type === "boolean" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "checkbox", "aria-label": p.name, checked: p.value === true, onChange: (e) => setProp(p.name, e.currentTarget.checked) }) : p.type === "text" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2201
2431
  "input",
2202
2432
  {
2203
2433
  type: "text",
@@ -2212,22 +2442,22 @@ function CanvasInstanceInspector({
2212
2442
  }
2213
2443
  },
2214
2444
  String(p.value)
2215
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2445
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2216
2446
  "select",
2217
2447
  {
2218
2448
  "aria-label": p.name,
2219
2449
  className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
2220
2450
  value: String(p.value),
2221
2451
  onChange: (e) => setProp(p.name, e.currentTarget.value),
2222
- children: allComponents.filter((c) => !p.preferred?.length || p.preferred.includes(c.id) || c.id === p.value).map((c) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: c.id, children: c.name }, c.id))
2452
+ children: allComponents.filter((c) => !p.preferred?.length || p.preferred.includes(c.id) || c.id === p.value).map((c) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: c.id, children: c.name }, c.id))
2223
2453
  }
2224
2454
  )
2225
2455
  ] }, p.name)),
2226
- info.overrides.length ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col gap-1", "data-instance-overrides": "", children: [
2227
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-muted-foreground", children: "Overrides" }),
2228
- info.overrides.map((o) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-center gap-1", "data-override-layer": o.id, children: [
2229
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mr-1 truncate", children: o.name }),
2230
- o.groups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2456
+ info.overrides.length ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-1", "data-instance-overrides": "", children: [
2457
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-muted-foreground", children: "Overrides" }),
2458
+ info.overrides.map((o) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap items-center gap-1", "data-override-layer": o.id, children: [
2459
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "mr-1 truncate", children: o.name }),
2460
+ o.groups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2231
2461
  "button",
2232
2462
  {
2233
2463
  type: "button",
@@ -2244,11 +2474,11 @@ function CanvasInstanceInspector({
2244
2474
  ))
2245
2475
  ] }, o.id))
2246
2476
  ] }) : null,
2247
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
2248
- linked ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2249
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: btn, "data-action": "reset", onClick: () => report(components.resetOverrides(info.id)), children: "Reset all" }),
2250
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: btn, "data-action": "go-to-main", onClick: () => components.goToMainComponent(info.id), children: "Go to main" }),
2251
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2477
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
2478
+ linked ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2479
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: btn, "data-action": "reset", onClick: () => report(components.resetOverrides(info.id)), children: "Reset all" }),
2480
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: btn, "data-action": "go-to-main", onClick: () => components.goToMainComponent(info.id), children: "Go to main" }),
2481
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2252
2482
  "button",
2253
2483
  {
2254
2484
  type: "button",
@@ -2259,8 +2489,8 @@ function CanvasInstanceInspector({
2259
2489
  children: "Push changes"
2260
2490
  }
2261
2491
  )
2262
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: btn, "data-action": "restore", onClick: () => report(components.restoreMainComponent(info.rootId)), children: "Restore main component" }),
2263
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2492
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: btn, "data-action": "restore", onClick: () => report(components.restoreMainComponent(info.rootId)), children: "Restore main component" }),
2493
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2264
2494
  "button",
2265
2495
  {
2266
2496
  type: "button",
@@ -2277,7 +2507,7 @@ function CanvasInstanceInspector({
2277
2507
  }
2278
2508
 
2279
2509
  // src/canvas/index.ts
2280
- var import_canvas25 = require("@pixerate/editor/canvas");
2510
+ var import_canvas27 = require("@pixerate/editor/canvas");
2281
2511
  // Annotate the CommonJS export names for ESM import in node:
2282
2512
  0 && (module.exports = {
2283
2513
  ANIMATABLE_PROPERTIES,
@@ -2291,12 +2521,14 @@ var import_canvas25 = require("@pixerate/editor/canvas");
2291
2521
  AnimationPlayer,
2292
2522
  AnimationTimeline,
2293
2523
  CANVAS_COMPONENT_DRAG_TYPE,
2524
+ CANVAS_GRADIENT_PRESETS,
2294
2525
  CANVAS_TOKEN_PROPERTIES,
2295
2526
  CHILD_LAYOUT_DATA_KEY,
2296
2527
  CONNECTION_LINE_TYPES,
2297
2528
  CSS_ANIMATION_PROPERTIES,
2298
2529
  CUBIC_BEZIER_PRESETS,
2299
2530
  CanvasComponentsPanel,
2531
+ CanvasDrawLayer,
2300
2532
  CanvasGuidesLayer,
2301
2533
  CanvasInstanceInspector,
2302
2534
  CanvasScenesStore,
@@ -2316,6 +2548,7 @@ var import_canvas25 = require("@pixerate/editor/canvas");
2316
2548
  addCanvasVariant,
2317
2549
  addKeyframesAtTime,
2318
2550
  alignNodes,
2551
+ angleToSvgLinearCoords,
2319
2552
  animateNode,
2320
2553
  applyAnimation,
2321
2554
  applyAnimationOverrides,
@@ -2356,8 +2589,10 @@ var import_canvas25 = require("@pixerate/editor/canvas");
2356
2589
  createCanvasAutoLayoutController,
2357
2590
  createCanvasComponent,
2358
2591
  createCanvasComponentsController,
2592
+ createCanvasDrawController,
2359
2593
  createCanvasInstance,
2360
2594
  createCanvasScenesStore,
2595
+ createDefaultStrokeStyle,
2361
2596
  createFanOutTrajectory,
2362
2597
  createGuideIndex,
2363
2598
  createNodeGuideIndex,
@@ -2385,6 +2620,7 @@ var import_canvas25 = require("@pixerate/editor/canvas");
2385
2620
  excludePaths,
2386
2621
  exportCssAnimation,
2387
2622
  findConnectorSnap,
2623
+ findStrokesAtPoint,
2388
2624
  fitCubicRun,
2389
2625
  fitCubics,
2390
2626
  fitFreehandPath,
@@ -2434,6 +2670,7 @@ var import_canvas25 = require("@pixerate/editor/canvas");
2434
2670
  getTimelineTicks,
2435
2671
  getTokenPropertyScope,
2436
2672
  getTokensForProperty,
2673
+ gradientToSvgDef,
2437
2674
  handlePoint,
2438
2675
  hasVisibleStroke,
2439
2676
  inferResizeHandle,
@@ -2448,6 +2685,7 @@ var import_canvas25 = require("@pixerate/editor/canvas");
2448
2685
  isAutoLayoutFrame,
2449
2686
  isCanvasComponent,
2450
2687
  isCanvasComponentSet,
2688
+ isCanvasGradient,
2451
2689
  isCanvasInstance,
2452
2690
  isCssExportExact,
2453
2691
  isEventFromTextInput,
@@ -2495,6 +2733,7 @@ var import_canvas25 = require("@pixerate/editor/canvas");
2495
2733
  parseCanvasClipboardData,
2496
2734
  parseCanvasScenes,
2497
2735
  parseCssEasing,
2736
+ parseCssGradient,
2498
2737
  parseKeyframeClipboard,
2499
2738
  parseOklab,
2500
2739
  parseSvgPath,
@@ -2526,6 +2765,7 @@ var import_canvas25 = require("@pixerate/editor/canvas");
2526
2765
  repositionNodesTo,
2527
2766
  resetCanvasInstanceOverrides,
2528
2767
  resizeHandleAxes,
2768
+ resolveCanvasGradient,
2529
2769
  resolveCanvasTokens,
2530
2770
  resolveEasing,
2531
2771
  resolvePadding,
@@ -2558,7 +2798,10 @@ var import_canvas25 = require("@pixerate/editor/canvas");
2558
2798
  snapTimeToFrame,
2559
2799
  snapToGrid,
2560
2800
  springAt,
2801
+ streamlinePoints,
2561
2802
  strokeOutlineRings,
2803
+ strokePointsToPathData,
2804
+ strokeToShapeNode,
2562
2805
  subtractPaths,
2563
2806
  subtractPolygons,
2564
2807
  swapCanvasInstance,
@@ -2581,6 +2824,7 @@ var import_canvas25 = require("@pixerate/editor/canvas");
2581
2824
  useCanvasClipboard,
2582
2825
  useCanvasComponents,
2583
2826
  useCanvasDocking,
2827
+ useCanvasDraw,
2584
2828
  useCanvasExplosion,
2585
2829
  useCanvasGraph,
2586
2830
  useCanvasLayout,