@pixerate/editor-react 0.79.0 → 0.81.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.
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,336 +17,347 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/canvas/index.ts
21
31
  var canvas_exports = {};
22
32
  __export(canvas_exports, {
23
- ANIMATABLE_PROPERTIES: () => import_canvas32.ANIMATABLE_PROPERTIES,
24
- ANIMATION_DATA_KEY: () => import_canvas32.ANIMATION_DATA_KEY,
25
- ANIMATION_EASING_LABELS: () => import_canvas32.ANIMATION_EASING_LABELS,
26
- ANIMATION_EASING_PRESETS: () => import_canvas32.ANIMATION_EASING_PRESETS,
27
- ANIMATION_TIME_EPSILON: () => import_canvas32.ANIMATION_TIME_EPSILON,
28
- AUTO_LAYOUT_DATA_KEY: () => import_canvas30.AUTO_LAYOUT_DATA_KEY,
33
+ ANIMATABLE_PROPERTIES: () => import_canvas33.ANIMATABLE_PROPERTIES,
34
+ ANIMATION_DATA_KEY: () => import_canvas33.ANIMATION_DATA_KEY,
35
+ ANIMATION_EASING_LABELS: () => import_canvas33.ANIMATION_EASING_LABELS,
36
+ ANIMATION_EASING_PRESETS: () => import_canvas33.ANIMATION_EASING_PRESETS,
37
+ ANIMATION_TIME_EPSILON: () => import_canvas33.ANIMATION_TIME_EPSILON,
38
+ AUTO_LAYOUT_DATA_KEY: () => import_canvas31.AUTO_LAYOUT_DATA_KEY,
29
39
  AgentPresenceLayer: () => AgentPresenceLayer,
30
- AnimationEditError: () => import_canvas32.AnimationEditError,
31
- AnimationPlayer: () => import_canvas32.AnimationPlayer,
40
+ AnimationEditError: () => import_canvas33.AnimationEditError,
41
+ AnimationPlayer: () => import_canvas33.AnimationPlayer,
32
42
  AnimationTimeline: () => AnimationTimeline,
33
- CANVAS_COMPONENT_DRAG_TYPE: () => import_canvas33.CANVAS_COMPONENT_DRAG_TYPE,
34
- CANVAS_GRADIENT_PRESETS: () => import_canvas33.CANVAS_GRADIENT_PRESETS,
35
- CANVAS_TOKEN_PROPERTIES: () => import_canvas31.CANVAS_TOKEN_PROPERTIES,
36
- CHILD_LAYOUT_DATA_KEY: () => import_canvas30.CHILD_LAYOUT_DATA_KEY,
37
- CONNECTION_LINE_TYPES: () => import_canvas26.CONNECTION_LINE_TYPES,
38
- CSS_ANIMATION_PROPERTIES: () => import_canvas32.CSS_ANIMATION_PROPERTIES,
39
- CUBIC_BEZIER_PRESETS: () => import_canvas32.CUBIC_BEZIER_PRESETS,
43
+ CANVAS_COMPONENT_DRAG_TYPE: () => import_canvas34.CANVAS_COMPONENT_DRAG_TYPE,
44
+ CANVAS_GRADIENT_PRESETS: () => import_canvas34.CANVAS_GRADIENT_PRESETS,
45
+ CANVAS_TOKEN_PROPERTIES: () => import_canvas32.CANVAS_TOKEN_PROPERTIES,
46
+ CHILD_LAYOUT_DATA_KEY: () => import_canvas31.CHILD_LAYOUT_DATA_KEY,
47
+ CONNECTION_LINE_TYPES: () => import_canvas27.CONNECTION_LINE_TYPES,
48
+ CSS_ANIMATION_PROPERTIES: () => import_canvas33.CSS_ANIMATION_PROPERTIES,
49
+ CUBIC_BEZIER_PRESETS: () => import_canvas33.CUBIC_BEZIER_PRESETS,
40
50
  CanvasComponentsPanel: () => CanvasComponentsPanel,
41
51
  CanvasDrawLayer: () => CanvasDrawLayer,
52
+ CanvasEffectsPanel: () => CanvasEffectsPanel,
53
+ CanvasEffectsProvider: () => CanvasEffectsProvider,
42
54
  CanvasGuidesLayer: () => CanvasGuidesLayer,
43
55
  CanvasInstanceInspector: () => CanvasInstanceInspector,
44
- CanvasScenesStore: () => import_canvas26.CanvasScenesStore,
45
- DEFAULT_ARRANGE_SHORTCUTS: () => import_canvas26.DEFAULT_ARRANGE_SHORTCUTS,
56
+ CanvasNodeEffectLayer: () => CanvasNodeEffectLayer,
57
+ CanvasScenesStore: () => import_canvas27.CanvasScenesStore,
58
+ DEFAULT_ARRANGE_SHORTCUTS: () => import_canvas27.DEFAULT_ARRANGE_SHORTCUTS,
46
59
  DiagramPresenceLayer: () => DiagramPresenceLayer,
47
- MAX_KEYFRAME_REFS: () => import_canvas32.MAX_KEYFRAME_REFS,
48
- ManualClock: () => import_canvas29.ManualClock,
60
+ MAX_KEYFRAME_REFS: () => import_canvas33.MAX_KEYFRAME_REFS,
61
+ ManualClock: () => import_canvas30.ManualClock,
49
62
  MermaidDiagramGroup: () => MermaidDiagramGroup,
50
63
  MermaidDiagramNode: () => MermaidDiagramNode,
51
64
  MermaidFamilyScene: () => MermaidFamilyScene,
52
65
  MermaidThumbnail: () => MermaidThumbnail,
53
- RESIZE_HANDLES: () => import_canvas25.RESIZE_HANDLES,
54
- SHAPE_DATA_KEY: () => import_canvas27.SHAPE_DATA_KEY,
55
- SHAPE_KINDS: () => import_canvas27.SHAPE_KINDS,
56
- SHAPE_NODE_TYPE: () => import_canvas27.SHAPE_NODE_TYPE,
57
- SHAPE_OPERATIONS: () => import_canvas27.SHAPE_OPERATIONS,
66
+ RESIZE_HANDLES: () => import_canvas26.RESIZE_HANDLES,
67
+ SHAPE_DATA_KEY: () => import_canvas28.SHAPE_DATA_KEY,
68
+ SHAPE_KINDS: () => import_canvas28.SHAPE_KINDS,
69
+ SHAPE_NODE_TYPE: () => import_canvas28.SHAPE_NODE_TYPE,
70
+ SHAPE_OPERATIONS: () => import_canvas28.SHAPE_OPERATIONS,
58
71
  ShapeNode: () => ShapeNode,
59
72
  ShapeNodeZoomContext: () => ShapeNodeZoomContext,
60
73
  ShapeNodeZoomProvider: () => ShapeNodeZoomProvider,
61
- TOKEN_BINDINGS_DATA_KEY: () => import_canvas31.TOKEN_BINDINGS_DATA_KEY,
62
- TOKEN_MODES_DATA_KEY: () => import_canvas31.TOKEN_MODES_DATA_KEY,
74
+ TOKEN_BINDINGS_DATA_KEY: () => import_canvas32.TOKEN_BINDINGS_DATA_KEY,
75
+ TOKEN_MODES_DATA_KEY: () => import_canvas32.TOKEN_MODES_DATA_KEY,
63
76
  TokenBindingPicker: () => TokenBindingPicker,
64
77
  TokenModeSwitcher: () => TokenModeSwitcher,
65
- addCanvasVariant: () => import_canvas33.addCanvasVariant,
66
- addKeyframesAtTime: () => import_canvas32.addKeyframesAtTime,
67
- alignNodes: () => import_canvas26.alignNodes,
68
- angleToSvgLinearCoords: () => import_canvas33.angleToSvgLinearCoords,
69
- animateNode: () => import_canvas32.animateNode,
70
- applyAnimation: () => import_canvas32.applyAnimation,
71
- applyAnimationOverrides: () => import_canvas32.applyAnimationOverrides,
72
- applyConstraints: () => import_canvas30.applyConstraints,
73
- applyNodeUpdates: () => import_canvas26.applyNodeUpdates,
74
- applyShapeCombination: () => import_canvas27.applyShapeCombination,
75
- applyShapeReplacement: () => import_canvas28.applyShapeReplacement,
76
- bezierPathArea: () => import_canvas28.bezierPathArea,
77
- bezierPathBounds: () => import_canvas28.bezierPathBounds,
78
- bezierPathLength: () => import_canvas28.bezierPathLength,
79
- bezierPathPointAtLength: () => import_canvas28.bezierPathPointAtLength,
80
- bezierPathSignedArea: () => import_canvas28.bezierPathSignedArea,
81
- bezierPathToSvg: () => import_canvas28.bezierPathToSvg,
82
- bindCanvasComponentProperty: () => import_canvas33.bindCanvasComponentProperty,
83
- bindCanvasToken: () => import_canvas31.bindCanvasToken,
84
- blendLayout: () => import_canvas29.blendLayout,
85
- boundsOf: () => import_canvas29.boundsOf,
86
- brushstrokeScaleBucket: () => import_canvas33.brushstrokeScaleBucket,
87
- calculateDagreReflowDisplacement: () => import_canvas29.calculateDagreReflowDisplacement,
88
- calculateDirectionalDisplacement: () => import_canvas29.calculateDirectionalDisplacement,
89
- canCombineShapeNodes: () => import_canvas27.canCombineShapeNodes,
90
- canOffsetShapeNodes: () => import_canvas28.canOffsetShapeNodes,
91
- canOutlineShapeNodeStrokes: () => import_canvas28.canOutlineShapeNodeStrokes,
92
- canvasHeight: () => import_canvas29.canvasHeight,
93
- centerNodes: () => import_canvas29.centerNodes,
94
- centre: () => import_canvas29.centre,
95
- clampAnimationValue: () => import_canvas32.clampAnimationValue,
96
- clampLayoutSize: () => import_canvas30.clampLayoutSize,
97
- combineCanvasComponentsAsVariants: () => import_canvas33.combineCanvasComponentsAsVariants,
98
- combineShapeNodes: () => import_canvas27.combineShapeNodes,
99
- computeNodesBoundingBox: () => import_canvas29.computeNodesBoundingBox,
100
- computeSnapGuides: () => import_canvas26.computeSnapGuides,
101
- connectedOnly: () => import_canvas29.connectedOnly,
102
- copyKeyframes: () => import_canvas32.copyKeyframes,
103
- countPathSegments: () => import_canvas28.countPathSegments,
104
- createAnimationPlayer: () => import_canvas32.createAnimationPlayer,
105
- createBezierTrajectory: () => import_canvas29.createBezierTrajectory,
106
- createCanvasAnimationController: () => import_canvas32.createCanvasAnimationController,
107
- createCanvasAutoLayoutController: () => import_canvas30.createCanvasAutoLayoutController,
108
- createCanvasComponent: () => import_canvas33.createCanvasComponent,
109
- createCanvasComponentsController: () => import_canvas33.createCanvasComponentsController,
110
- createCanvasDrawController: () => import_canvas33.createCanvasDrawController,
111
- createCanvasInstance: () => import_canvas33.createCanvasInstance,
112
- createCanvasScenesStore: () => import_canvas26.createCanvasScenesStore,
113
- createDefaultStrokeStyle: () => import_canvas33.createDefaultStrokeStyle,
114
- createFanOutTrajectory: () => import_canvas29.createFanOutTrajectory,
115
- createGuideIndex: () => import_canvas26.createGuideIndex,
116
- createNodeGuideIndex: () => import_canvas26.createNodeGuideIndex,
117
- cubicBezierAt: () => import_canvas32.cubicBezierAt,
118
- cubicPointAt: () => import_canvas25.cubicPointAt,
119
- cubicsToPathData: () => import_canvas25.cubicsToPathData,
120
- dashContours: () => import_canvas28.dashContours,
121
- defaultEasing: () => import_canvas29.defaultEasing,
122
- deleteKeyframes: () => import_canvas32.deleteKeyframes,
123
- detachCanvasInstance: () => import_canvas33.detachCanvasInstance,
124
- detachTokenBindings: () => import_canvas31.detachTokenBindings,
125
- distanceToBezierPath: () => import_canvas28.distanceToBezierPath,
126
- distributeNodes: () => import_canvas26.distributeNodes,
127
- dividePaths: () => import_canvas28.dividePaths,
128
- dividePolygons: () => import_canvas27.dividePolygons,
129
- easingFromInfluence: () => import_canvas32.easingFromInfluence,
130
- easingLabel: () => import_canvas32.easingLabel,
131
- easingToCss: () => import_canvas32.easingToCss,
132
- ensureLayout: () => import_canvas29.ensureLayout,
133
- estimateCanvasHeight: () => import_canvas29.estimateCanvasHeight,
134
- estimateNodeSize: () => import_canvas29.estimateNodeSize,
135
- evaluateAnimation: () => import_canvas32.evaluateAnimation,
136
- evaluateEasing: () => import_canvas32.evaluateEasing,
137
- evaluateTrack: () => import_canvas32.evaluateTrack,
138
- excludePaths: () => import_canvas28.excludePaths,
139
- exportCssAnimation: () => import_canvas32.exportCssAnimation,
140
- findConnectorSnap: () => import_canvas26.findConnectorSnap,
141
- findStrokesAtPoint: () => import_canvas33.findStrokesAtPoint,
142
- fitCubicRun: () => import_canvas25.fitCubicRun,
143
- fitCubics: () => import_canvas25.fitCubics,
144
- fitFreehandPath: () => import_canvas25.fitFreehandPath,
145
- fitPathData: () => import_canvas25.fitPathData,
146
- fitViewportToNodes: () => import_canvas26.fitViewportToNodes,
147
- fitViewportToRect: () => import_canvas26.fitViewportToRect,
148
- flattenSvgPath: () => import_canvas27.flattenSvgPath,
149
- flowSide: () => import_canvas29.flowSide,
150
- formatAnimationTime: () => import_canvas32.formatAnimationTime,
151
- formatOklab: () => import_canvas32.formatOklab,
152
- freehandBrushstroke: () => import_canvas33.freehandBrushstroke,
153
- getAbsolutePosition: () => import_canvas26.getAbsolutePosition,
154
- getAnimatableProperty: () => import_canvas32.getAnimatableProperty,
155
- getAnimatedProperties: () => import_canvas32.getAnimatedProperties,
156
- getAnimatedValue: () => import_canvas32.getAnimatedValue,
157
- getAnimationDuration: () => import_canvas32.getAnimationDuration,
158
- getAnimationTrack: () => import_canvas32.getAnimationTrack,
159
- getAutoLayout: () => import_canvas30.getAutoLayout,
160
- getAutoLayoutGrid: () => import_canvas30.getAutoLayoutGrid,
161
- getAutoLayoutInsertTarget: () => import_canvas30.getAutoLayoutInsertTarget,
162
- getBindableTokenProperties: () => import_canvas31.getBindableTokenProperties,
163
- getBrushedShapeSvg: () => import_canvas33.getBrushedShapeSvg,
164
- getCanvasComponentDragId: () => import_canvas33.getCanvasComponentDragId,
165
- getCanvasTokenProperty: () => import_canvas31.getCanvasTokenProperty,
166
- getCenteredNodePosition: () => import_canvas29.getCenteredNodePosition,
167
- getChildLayout: () => import_canvas30.getChildLayout,
168
- getComponentSourceId: () => import_canvas33.getComponentSourceId,
169
- getCssPropertyAnimations: () => import_canvas32.getCssPropertyAnimations,
170
- getEffectiveTokenModes: () => import_canvas31.getEffectiveTokenModes,
171
- getFlowChildren: () => import_canvas30.getFlowChildren,
172
- getInstanceData: () => import_canvas33.getInstanceData,
173
- getInstanceStatus: () => import_canvas33.getInstanceStatus,
174
- getKeyframeTimes: () => import_canvas32.getKeyframeTimes,
175
- getLayoutParent: () => import_canvas30.getLayoutParent,
176
- getLayoutSizing: () => import_canvas30.getLayoutSizing,
177
- getLayoutedNodes: () => import_canvas29.getLayoutedNodes,
178
- getNextVariantValues: () => import_canvas33.getNextVariantValues,
179
- getNodeAnimation: () => import_canvas32.getNodeAnimation,
180
- getNodeOverrides: () => import_canvas33.getNodeOverrides,
181
- getNodeRect: () => import_canvas26.getNodeRect,
182
- getNodeShape: () => import_canvas27.getNodeShape,
183
- getNodeSize: () => import_canvas26.getNodeSize,
184
- getNodeTokenBindings: () => import_canvas31.getNodeTokenBindings,
185
- getNodeTokenModes: () => import_canvas31.getNodeTokenModes,
186
- getResizingNodeRect: () => import_canvas25.getResizingNodeRect,
187
- getShapeRenderData: () => import_canvas27.getShapeRenderData,
188
- getShapeSvg: () => import_canvas27.getShapeSvg,
189
- getTimelineRows: () => import_canvas32.getTimelineRows,
190
- getTimelineTicks: () => import_canvas32.getTimelineTicks,
191
- getTokenPropertyScope: () => import_canvas31.getTokenPropertyScope,
192
- getTokensForProperty: () => import_canvas31.getTokensForProperty,
193
- gradientToSvgDef: () => import_canvas33.gradientToSvgDef,
194
- handlePoint: () => import_canvas26.handlePoint,
195
- hasVisibleStroke: () => import_canvas28.hasVisibleStroke,
196
- inferResizeHandle: () => import_canvas25.inferResizeHandle,
197
- inspectCanvasInstance: () => import_canvas33.inspectCanvasInstance,
198
- inspectNodeTokens: () => import_canvas31.inspectNodeTokens,
199
- interpolateAnimationValue: () => import_canvas32.interpolateAnimationValue,
200
- intersectPaths: () => import_canvas28.intersectPaths,
201
- intersectPolygons: () => import_canvas27.intersectPolygons,
202
- invertNodeUpdates: () => import_canvas26.invertNodeUpdates,
203
- isAnimationEasing: () => import_canvas32.isAnimationEasing,
204
- isAnimationKeyframe: () => import_canvas32.isAnimationKeyframe,
205
- isAutoLayoutFrame: () => import_canvas30.isAutoLayoutFrame,
206
- isBrushedShape: () => import_canvas33.isBrushedShape,
207
- isCanvasComponent: () => import_canvas33.isCanvasComponent,
208
- isCanvasComponentSet: () => import_canvas33.isCanvasComponentSet,
209
- isCanvasGradient: () => import_canvas33.isCanvasGradient,
210
- isCanvasInstance: () => import_canvas33.isCanvasInstance,
211
- isCssExportExact: () => import_canvas32.isCssExportExact,
212
- isEventFromTextInput: () => import_canvas29.isEventFromTextInput,
213
- isKeyframeSelected: () => import_canvas32.isKeyframeSelected,
214
- isLocked: () => import_canvas26.isLocked,
215
- isMeasureModifierHeld: () => import_canvas25.isMeasureModifierHeld,
216
- isNodeAnimated: () => import_canvas32.isNodeAnimated,
217
- isShapeDescription: () => import_canvas27.isShapeDescription,
218
- isShapeNode: () => import_canvas27.isShapeNode,
219
- isStraightCubic: () => import_canvas25.isStraightCubic,
220
- isValidCanvasNode: () => import_canvas29.isValidCanvasNode,
221
- isValidUrl: () => import_canvas29.isValidUrl,
222
- layoutAll: () => import_canvas30.layoutAll,
223
- layoutBounds: () => import_canvas29.layoutBounds,
224
- layoutFrame: () => import_canvas30.layoutFrame,
225
- layoutUp: () => import_canvas30.layoutUp,
226
- layoutUpMany: () => import_canvas30.layoutUpMany,
227
- linearPositionTrajectory: () => import_canvas29.linearPositionTrajectory,
228
- linearTrajectory: () => import_canvas29.linearTrajectory,
229
- listCanvasBrushes: () => import_canvas33.listCanvasBrushes,
230
- listCanvasComponents: () => import_canvas33.listCanvasComponents,
231
- loadCanvasBrushstrokeRenderer: () => import_canvas33.loadCanvasBrushstrokeRenderer,
232
- lockNodes: () => import_canvas26.lockNodes,
233
- makeSizingCoherent: () => import_canvas30.makeSizingCoherent,
234
- matchArrangeShortcut: () => import_canvas26.matchArrangeShortcut,
235
- matchSize: () => import_canvas26.matchSize,
236
- measureBetween: () => import_canvas25.measureBetween,
237
- measureLabel: () => import_canvas25.measureLabel,
238
- measureSelection: () => import_canvas25.measureSelection,
239
- measureToLine: () => import_canvas25.measureToLine,
240
- mergeNodeUpdates: () => import_canvas30.mergeNodeUpdates,
78
+ addCanvasVariant: () => import_canvas34.addCanvasVariant,
79
+ addKeyframesAtTime: () => import_canvas33.addKeyframesAtTime,
80
+ alignNodes: () => import_canvas27.alignNodes,
81
+ angleToSvgLinearCoords: () => import_canvas34.angleToSvgLinearCoords,
82
+ animateNode: () => import_canvas33.animateNode,
83
+ applyAnimation: () => import_canvas33.applyAnimation,
84
+ applyAnimationOverrides: () => import_canvas33.applyAnimationOverrides,
85
+ applyConstraints: () => import_canvas31.applyConstraints,
86
+ applyNodeUpdates: () => import_canvas27.applyNodeUpdates,
87
+ applyShapeCombination: () => import_canvas28.applyShapeCombination,
88
+ applyShapeReplacement: () => import_canvas29.applyShapeReplacement,
89
+ bezierPathArea: () => import_canvas29.bezierPathArea,
90
+ bezierPathBounds: () => import_canvas29.bezierPathBounds,
91
+ bezierPathLength: () => import_canvas29.bezierPathLength,
92
+ bezierPathPointAtLength: () => import_canvas29.bezierPathPointAtLength,
93
+ bezierPathSignedArea: () => import_canvas29.bezierPathSignedArea,
94
+ bezierPathToSvg: () => import_canvas29.bezierPathToSvg,
95
+ bindCanvasComponentProperty: () => import_canvas34.bindCanvasComponentProperty,
96
+ bindCanvasToken: () => import_canvas32.bindCanvasToken,
97
+ blendLayout: () => import_canvas30.blendLayout,
98
+ boundsOf: () => import_canvas30.boundsOf,
99
+ brushstrokeScaleBucket: () => import_canvas34.brushstrokeScaleBucket,
100
+ calculateDagreReflowDisplacement: () => import_canvas30.calculateDagreReflowDisplacement,
101
+ calculateDirectionalDisplacement: () => import_canvas30.calculateDirectionalDisplacement,
102
+ canCombineShapeNodes: () => import_canvas28.canCombineShapeNodes,
103
+ canOffsetShapeNodes: () => import_canvas29.canOffsetShapeNodes,
104
+ canOutlineShapeNodeStrokes: () => import_canvas29.canOutlineShapeNodeStrokes,
105
+ canvasHeight: () => import_canvas30.canvasHeight,
106
+ centerNodes: () => import_canvas30.centerNodes,
107
+ centre: () => import_canvas30.centre,
108
+ clampAnimationValue: () => import_canvas33.clampAnimationValue,
109
+ clampLayoutSize: () => import_canvas31.clampLayoutSize,
110
+ combineCanvasComponentsAsVariants: () => import_canvas34.combineCanvasComponentsAsVariants,
111
+ combineShapeNodes: () => import_canvas28.combineShapeNodes,
112
+ computeNodesBoundingBox: () => import_canvas30.computeNodesBoundingBox,
113
+ computeSnapGuides: () => import_canvas27.computeSnapGuides,
114
+ connectedOnly: () => import_canvas30.connectedOnly,
115
+ copyKeyframes: () => import_canvas33.copyKeyframes,
116
+ countPathSegments: () => import_canvas29.countPathSegments,
117
+ createAnimationPlayer: () => import_canvas33.createAnimationPlayer,
118
+ createBezierTrajectory: () => import_canvas30.createBezierTrajectory,
119
+ createCanvasAnimationController: () => import_canvas33.createCanvasAnimationController,
120
+ createCanvasAutoLayoutController: () => import_canvas31.createCanvasAutoLayoutController,
121
+ createCanvasComponent: () => import_canvas34.createCanvasComponent,
122
+ createCanvasComponentsController: () => import_canvas34.createCanvasComponentsController,
123
+ createCanvasDrawController: () => import_canvas34.createCanvasDrawController,
124
+ createCanvasInstance: () => import_canvas34.createCanvasInstance,
125
+ createCanvasScenesStore: () => import_canvas27.createCanvasScenesStore,
126
+ createDefaultStrokeStyle: () => import_canvas34.createDefaultStrokeStyle,
127
+ createFanOutTrajectory: () => import_canvas30.createFanOutTrajectory,
128
+ createGuideIndex: () => import_canvas27.createGuideIndex,
129
+ createNodeGuideIndex: () => import_canvas27.createNodeGuideIndex,
130
+ cubicBezierAt: () => import_canvas33.cubicBezierAt,
131
+ cubicPointAt: () => import_canvas26.cubicPointAt,
132
+ cubicsToPathData: () => import_canvas26.cubicsToPathData,
133
+ dashContours: () => import_canvas29.dashContours,
134
+ defaultEasing: () => import_canvas30.defaultEasing,
135
+ deleteKeyframes: () => import_canvas33.deleteKeyframes,
136
+ detachCanvasInstance: () => import_canvas34.detachCanvasInstance,
137
+ detachTokenBindings: () => import_canvas32.detachTokenBindings,
138
+ distanceToBezierPath: () => import_canvas29.distanceToBezierPath,
139
+ distributeNodes: () => import_canvas27.distributeNodes,
140
+ dividePaths: () => import_canvas29.dividePaths,
141
+ dividePolygons: () => import_canvas28.dividePolygons,
142
+ easingFromInfluence: () => import_canvas33.easingFromInfluence,
143
+ easingLabel: () => import_canvas33.easingLabel,
144
+ easingToCss: () => import_canvas33.easingToCss,
145
+ ensureLayout: () => import_canvas30.ensureLayout,
146
+ estimateCanvasHeight: () => import_canvas30.estimateCanvasHeight,
147
+ estimateNodeSize: () => import_canvas30.estimateNodeSize,
148
+ evaluateAnimation: () => import_canvas33.evaluateAnimation,
149
+ evaluateEasing: () => import_canvas33.evaluateEasing,
150
+ evaluateTrack: () => import_canvas33.evaluateTrack,
151
+ excludePaths: () => import_canvas29.excludePaths,
152
+ exportCssAnimation: () => import_canvas33.exportCssAnimation,
153
+ findConnectorSnap: () => import_canvas27.findConnectorSnap,
154
+ findStrokesAtPoint: () => import_canvas34.findStrokesAtPoint,
155
+ fitCubicRun: () => import_canvas26.fitCubicRun,
156
+ fitCubics: () => import_canvas26.fitCubics,
157
+ fitFreehandPath: () => import_canvas26.fitFreehandPath,
158
+ fitPathData: () => import_canvas26.fitPathData,
159
+ fitViewportToNodes: () => import_canvas27.fitViewportToNodes,
160
+ fitViewportToRect: () => import_canvas27.fitViewportToRect,
161
+ flattenSvgPath: () => import_canvas28.flattenSvgPath,
162
+ flowSide: () => import_canvas30.flowSide,
163
+ formatAnimationTime: () => import_canvas33.formatAnimationTime,
164
+ formatOklab: () => import_canvas33.formatOklab,
165
+ freehandBrushstroke: () => import_canvas34.freehandBrushstroke,
166
+ getAbsolutePosition: () => import_canvas27.getAbsolutePosition,
167
+ getAnimatableProperty: () => import_canvas33.getAnimatableProperty,
168
+ getAnimatedProperties: () => import_canvas33.getAnimatedProperties,
169
+ getAnimatedValue: () => import_canvas33.getAnimatedValue,
170
+ getAnimationDuration: () => import_canvas33.getAnimationDuration,
171
+ getAnimationTrack: () => import_canvas33.getAnimationTrack,
172
+ getAutoLayout: () => import_canvas31.getAutoLayout,
173
+ getAutoLayoutGrid: () => import_canvas31.getAutoLayoutGrid,
174
+ getAutoLayoutInsertTarget: () => import_canvas31.getAutoLayoutInsertTarget,
175
+ getBindableTokenProperties: () => import_canvas32.getBindableTokenProperties,
176
+ getBrushedShapeSvg: () => import_canvas34.getBrushedShapeSvg,
177
+ getCanvasComponentDragId: () => import_canvas34.getCanvasComponentDragId,
178
+ getCanvasTokenProperty: () => import_canvas32.getCanvasTokenProperty,
179
+ getCenteredNodePosition: () => import_canvas30.getCenteredNodePosition,
180
+ getChildLayout: () => import_canvas31.getChildLayout,
181
+ getComponentSourceId: () => import_canvas34.getComponentSourceId,
182
+ getCssPropertyAnimations: () => import_canvas33.getCssPropertyAnimations,
183
+ getEffectiveTokenModes: () => import_canvas32.getEffectiveTokenModes,
184
+ getFlowChildren: () => import_canvas31.getFlowChildren,
185
+ getInstanceData: () => import_canvas34.getInstanceData,
186
+ getInstanceStatus: () => import_canvas34.getInstanceStatus,
187
+ getKeyframeTimes: () => import_canvas33.getKeyframeTimes,
188
+ getLayoutParent: () => import_canvas31.getLayoutParent,
189
+ getLayoutSizing: () => import_canvas31.getLayoutSizing,
190
+ getLayoutedNodes: () => import_canvas30.getLayoutedNodes,
191
+ getNextVariantValues: () => import_canvas34.getNextVariantValues,
192
+ getNodeAnimation: () => import_canvas33.getNodeAnimation,
193
+ getNodeOverrides: () => import_canvas34.getNodeOverrides,
194
+ getNodeRect: () => import_canvas27.getNodeRect,
195
+ getNodeShape: () => import_canvas28.getNodeShape,
196
+ getNodeSize: () => import_canvas27.getNodeSize,
197
+ getNodeTokenBindings: () => import_canvas32.getNodeTokenBindings,
198
+ getNodeTokenModes: () => import_canvas32.getNodeTokenModes,
199
+ getResizingNodeRect: () => import_canvas26.getResizingNodeRect,
200
+ getShapeRenderData: () => import_canvas28.getShapeRenderData,
201
+ getShapeSvg: () => import_canvas28.getShapeSvg,
202
+ getTimelineRows: () => import_canvas33.getTimelineRows,
203
+ getTimelineTicks: () => import_canvas33.getTimelineTicks,
204
+ getTokenPropertyScope: () => import_canvas32.getTokenPropertyScope,
205
+ getTokensForProperty: () => import_canvas32.getTokensForProperty,
206
+ gradientToSvgDef: () => import_canvas34.gradientToSvgDef,
207
+ handlePoint: () => import_canvas27.handlePoint,
208
+ hasVisibleStroke: () => import_canvas29.hasVisibleStroke,
209
+ inferResizeHandle: () => import_canvas26.inferResizeHandle,
210
+ inspectCanvasInstance: () => import_canvas34.inspectCanvasInstance,
211
+ inspectNodeTokens: () => import_canvas32.inspectNodeTokens,
212
+ interpolateAnimationValue: () => import_canvas33.interpolateAnimationValue,
213
+ intersectPaths: () => import_canvas29.intersectPaths,
214
+ intersectPolygons: () => import_canvas28.intersectPolygons,
215
+ invertNodeUpdates: () => import_canvas27.invertNodeUpdates,
216
+ isAnimationEasing: () => import_canvas33.isAnimationEasing,
217
+ isAnimationKeyframe: () => import_canvas33.isAnimationKeyframe,
218
+ isAutoLayoutFrame: () => import_canvas31.isAutoLayoutFrame,
219
+ isBrushedShape: () => import_canvas34.isBrushedShape,
220
+ isCanvasComponent: () => import_canvas34.isCanvasComponent,
221
+ isCanvasComponentSet: () => import_canvas34.isCanvasComponentSet,
222
+ isCanvasGradient: () => import_canvas34.isCanvasGradient,
223
+ isCanvasInstance: () => import_canvas34.isCanvasInstance,
224
+ isCssExportExact: () => import_canvas33.isCssExportExact,
225
+ isEventFromTextInput: () => import_canvas30.isEventFromTextInput,
226
+ isKeyframeSelected: () => import_canvas33.isKeyframeSelected,
227
+ isLocked: () => import_canvas27.isLocked,
228
+ isMeasureModifierHeld: () => import_canvas26.isMeasureModifierHeld,
229
+ isNodeAnimated: () => import_canvas33.isNodeAnimated,
230
+ isShapeDescription: () => import_canvas28.isShapeDescription,
231
+ isShapeNode: () => import_canvas28.isShapeNode,
232
+ isStraightCubic: () => import_canvas26.isStraightCubic,
233
+ isValidCanvasNode: () => import_canvas30.isValidCanvasNode,
234
+ isValidUrl: () => import_canvas30.isValidUrl,
235
+ layoutAll: () => import_canvas31.layoutAll,
236
+ layoutBounds: () => import_canvas30.layoutBounds,
237
+ layoutFrame: () => import_canvas31.layoutFrame,
238
+ layoutUp: () => import_canvas31.layoutUp,
239
+ layoutUpMany: () => import_canvas31.layoutUpMany,
240
+ linearPositionTrajectory: () => import_canvas30.linearPositionTrajectory,
241
+ linearTrajectory: () => import_canvas30.linearTrajectory,
242
+ listCanvasBrushes: () => import_canvas34.listCanvasBrushes,
243
+ listCanvasComponents: () => import_canvas34.listCanvasComponents,
244
+ loadCanvasBrushstrokeRenderer: () => import_canvas34.loadCanvasBrushstrokeRenderer,
245
+ lockNodes: () => import_canvas27.lockNodes,
246
+ makeSizingCoherent: () => import_canvas31.makeSizingCoherent,
247
+ matchArrangeShortcut: () => import_canvas27.matchArrangeShortcut,
248
+ matchSize: () => import_canvas27.matchSize,
249
+ measureBetween: () => import_canvas26.measureBetween,
250
+ measureLabel: () => import_canvas26.measureLabel,
251
+ measureSelection: () => import_canvas26.measureSelection,
252
+ measureToLine: () => import_canvas26.measureToLine,
253
+ mergeNodeUpdates: () => import_canvas31.mergeNodeUpdates,
241
254
  mermaidNodeStyle: () => mermaidNodeStyle,
242
- mixColorsOklab: () => import_canvas32.mixColorsOklab,
243
- moveKeyframes: () => import_canvas32.moveKeyframes,
244
- moveLayoutChild: () => import_canvas30.moveLayoutChild,
245
- multiPolygonArea: () => import_canvas27.multiPolygonArea,
246
- multiPolygonBounds: () => import_canvas27.multiPolygonBounds,
247
- nearestHandlePositions: () => import_canvas26.nearestHandlePositions,
248
- normalizeBezierPath: () => import_canvas28.normalizeBezierPath,
249
- normalizeKeyframes: () => import_canvas32.normalizeKeyframes,
250
- offsetPath: () => import_canvas28.offsetPath,
251
- offsetShapeNodes: () => import_canvas28.offsetShapeNodes,
252
- oklabToRgb: () => import_canvas32.oklabToRgb,
253
- oppositePosition: () => import_canvas26.oppositePosition,
254
- outlineShapeNodeStrokes: () => import_canvas28.outlineShapeNodeStrokes,
255
- outlineStroke: () => import_canvas28.outlineStroke,
256
- overlaps: () => import_canvas29.overlaps,
257
- parseCanvasClipboardData: () => import_canvas29.parseCanvasClipboardData,
258
- parseCanvasScenes: () => import_canvas26.parseCanvasScenes,
259
- parseCssEasing: () => import_canvas32.parseCssEasing,
260
- parseCssGradient: () => import_canvas33.parseCssGradient,
261
- parseKeyframeClipboard: () => import_canvas32.parseKeyframeClipboard,
262
- parseOklab: () => import_canvas32.parseOklab,
263
- parseSvgPath: () => import_canvas27.parseSvgPath,
264
- pasteKeyframes: () => import_canvas32.pasteKeyframes,
265
- pathBoolean: () => import_canvas28.pathBoolean,
266
- pathDataToPolyline: () => import_canvas33.pathDataToPolyline,
267
- placeBeside: () => import_canvas29.placeBeside,
268
- playWebAnimations: () => import_canvas32.playWebAnimations,
269
- pointInBezierPath: () => import_canvas28.pointInBezierPath,
270
- pointInMultiPolygon: () => import_canvas27.pointInMultiPolygon,
271
- pointInRings: () => import_canvas27.pointInRings,
272
- pointerPenSample: () => import_canvas33.pointerPenSample,
273
- polygonArea: () => import_canvas27.polygonArea,
274
- polygonBoolean: () => import_canvas27.polygonBoolean,
275
- polygonToSvgPath: () => import_canvas27.polygonToSvgPath,
276
- positionToSide: () => import_canvas26.positionToSide,
277
- profileAlongPolyline: () => import_canvas33.profileAlongPolyline,
278
- pruneCanvasTokenModes: () => import_canvas31.pruneCanvasTokenModes,
279
- pushCanvasInstanceOverrides: () => import_canvas33.pushCanvasInstanceOverrides,
280
- readAnimatableValue: () => import_canvas32.readAnimatableValue,
281
- readNodeStyleProperty: () => import_canvas31.readNodeStyleProperty,
282
- readStyleSize: () => import_canvas26.readStyleSize,
283
- realClock: () => import_canvas29.realClock,
284
- recordAnimationChanges: () => import_canvas32.recordAnimationChanges,
285
- relayoutUpdates: () => import_canvas30.relayoutUpdates,
286
- remapPastedNodes: () => import_canvas29.remapPastedNodes,
287
- removeCanvasVariant: () => import_canvas33.removeCanvasVariant,
288
- removeTrack: () => import_canvas32.removeTrack,
289
- renameCanvasVariantProperty: () => import_canvas33.renameCanvasVariantProperty,
290
- renameCanvasVariantValue: () => import_canvas33.renameCanvasVariantValue,
291
- renderShapeBrushstroke: () => import_canvas33.renderShapeBrushstroke,
292
- reorderNodes: () => import_canvas26.reorderNodes,
293
- repositionNodesTo: () => import_canvas29.repositionNodesTo,
294
- resetCanvasInstanceOverrides: () => import_canvas33.resetCanvasInstanceOverrides,
295
- resizeHandleAxes: () => import_canvas25.resizeHandleAxes,
296
- resolveCanvasGradient: () => import_canvas33.resolveCanvasGradient,
297
- resolveCanvasTokens: () => import_canvas31.resolveCanvasTokens,
298
- resolveEasing: () => import_canvas32.resolveEasing,
299
- resolvePadding: () => import_canvas30.resolvePadding,
300
- restoreCanvasMainComponent: () => import_canvas33.restoreCanvasMainComponent,
301
- revertShapeCombination: () => import_canvas27.revertShapeCombination,
302
- rgbToOklab: () => import_canvas32.rgbToOklab,
303
- ringSignedArea: () => import_canvas27.ringSignedArea,
304
- runMultiNodeTransition: () => import_canvas29.runMultiNodeTransition,
305
- sampleAnimationFrames: () => import_canvas32.sampleAnimationFrames,
306
- scaleKeyframes: () => import_canvas32.scaleKeyframes,
307
- serializeCanvasNodes: () => import_canvas29.serializeCanvasNodes,
308
- setCanvasComponentProperty: () => import_canvas33.setCanvasComponentProperty,
309
- setCanvasInstanceProperties: () => import_canvas33.setCanvasInstanceProperties,
310
- setCanvasTokenMode: () => import_canvas31.setCanvasTokenMode,
311
- setCanvasVariantProperties: () => import_canvas33.setCanvasVariantProperties,
312
- setKeyframe: () => import_canvas32.setKeyframe,
313
- setKeyframeEasing: () => import_canvas32.setKeyframeEasing,
314
- setMotionPath: () => import_canvas32.setMotionPath,
315
- setTrackEnabled: () => import_canvas32.setTrackEnabled,
316
- shapeNodeToBezierPath: () => import_canvas28.shapeNodeToBezierPath,
317
- shapeNodeToPolygon: () => import_canvas27.shapeNodeToPolygon,
318
- shapeToBezierPath: () => import_canvas28.shapeToBezierPath,
319
- shapeToPolygon: () => import_canvas27.shapeToPolygon,
320
- sideToPosition: () => import_canvas26.sideToPosition,
321
- simplifyRing: () => import_canvas27.simplifyRing,
322
- snapKeyframeDelta: () => import_canvas32.snapKeyframeDelta,
323
- snapNodeDrag: () => import_canvas26.snapNodeDrag,
324
- snapNodeResize: () => import_canvas25.snapNodeResize,
325
- snapResize: () => import_canvas25.snapResize,
326
- snapTimeToFrame: () => import_canvas32.snapTimeToFrame,
327
- snapToGrid: () => import_canvas25.snapToGrid,
328
- springAt: () => import_canvas32.springAt,
329
- streamlinePoints: () => import_canvas33.streamlinePoints,
330
- strokeOutlineRings: () => import_canvas28.strokeOutlineRings,
331
- strokePointsToPathData: () => import_canvas33.strokePointsToPathData,
332
- strokeToShapeNode: () => import_canvas33.strokeToShapeNode,
333
- subtractPaths: () => import_canvas28.subtractPaths,
334
- subtractPolygons: () => import_canvas27.subtractPolygons,
335
- swapCanvasInstance: () => import_canvas33.swapCanvasInstance,
336
- syncAllCanvasInstances: () => import_canvas33.syncAllCanvasInstances,
337
- syncCanvasComponents: () => import_canvas33.syncCanvasComponents,
338
- syncCanvasInstance: () => import_canvas33.syncCanvasInstance,
339
- timeToX: () => import_canvas32.timeToX,
340
- toBezierPath: () => import_canvas28.toBezierPath,
341
- toWebAnimations: () => import_canvas32.toWebAnimations,
342
- toggleLockNodes: () => import_canvas26.toggleLockNodes,
343
- transformBezierPath: () => import_canvas28.transformBezierPath,
344
- unionPolygons: () => import_canvas27.unionPolygons,
345
- unitePaths: () => import_canvas28.unitePaths,
346
- unlockNodes: () => import_canvas26.unlockNodes,
347
- updateKeyframe: () => import_canvas32.updateKeyframe,
255
+ mixColorsOklab: () => import_canvas33.mixColorsOklab,
256
+ moveKeyframes: () => import_canvas33.moveKeyframes,
257
+ moveLayoutChild: () => import_canvas31.moveLayoutChild,
258
+ multiPolygonArea: () => import_canvas28.multiPolygonArea,
259
+ multiPolygonBounds: () => import_canvas28.multiPolygonBounds,
260
+ nearestHandlePositions: () => import_canvas27.nearestHandlePositions,
261
+ normalizeBezierPath: () => import_canvas29.normalizeBezierPath,
262
+ normalizeKeyframes: () => import_canvas33.normalizeKeyframes,
263
+ offsetPath: () => import_canvas29.offsetPath,
264
+ offsetShapeNodes: () => import_canvas29.offsetShapeNodes,
265
+ oklabToRgb: () => import_canvas33.oklabToRgb,
266
+ oppositePosition: () => import_canvas27.oppositePosition,
267
+ outlineShapeNodeStrokes: () => import_canvas29.outlineShapeNodeStrokes,
268
+ outlineStroke: () => import_canvas29.outlineStroke,
269
+ overlaps: () => import_canvas30.overlaps,
270
+ parseCanvasClipboardData: () => import_canvas30.parseCanvasClipboardData,
271
+ parseCanvasScenes: () => import_canvas27.parseCanvasScenes,
272
+ parseCssEasing: () => import_canvas33.parseCssEasing,
273
+ parseCssGradient: () => import_canvas34.parseCssGradient,
274
+ parseKeyframeClipboard: () => import_canvas33.parseKeyframeClipboard,
275
+ parseOklab: () => import_canvas33.parseOklab,
276
+ parseSvgPath: () => import_canvas28.parseSvgPath,
277
+ pasteKeyframes: () => import_canvas33.pasteKeyframes,
278
+ pathBoolean: () => import_canvas29.pathBoolean,
279
+ pathDataToPolyline: () => import_canvas34.pathDataToPolyline,
280
+ placeBeside: () => import_canvas30.placeBeside,
281
+ playWebAnimations: () => import_canvas33.playWebAnimations,
282
+ pointInBezierPath: () => import_canvas29.pointInBezierPath,
283
+ pointInMultiPolygon: () => import_canvas28.pointInMultiPolygon,
284
+ pointInRings: () => import_canvas28.pointInRings,
285
+ pointerPenSample: () => import_canvas34.pointerPenSample,
286
+ polygonArea: () => import_canvas28.polygonArea,
287
+ polygonBoolean: () => import_canvas28.polygonBoolean,
288
+ polygonToSvgPath: () => import_canvas28.polygonToSvgPath,
289
+ positionToSide: () => import_canvas27.positionToSide,
290
+ profileAlongPolyline: () => import_canvas34.profileAlongPolyline,
291
+ pruneCanvasTokenModes: () => import_canvas32.pruneCanvasTokenModes,
292
+ pushCanvasInstanceOverrides: () => import_canvas34.pushCanvasInstanceOverrides,
293
+ readAnimatableValue: () => import_canvas33.readAnimatableValue,
294
+ readNodeStyleProperty: () => import_canvas32.readNodeStyleProperty,
295
+ readStyleSize: () => import_canvas27.readStyleSize,
296
+ realClock: () => import_canvas30.realClock,
297
+ recordAnimationChanges: () => import_canvas33.recordAnimationChanges,
298
+ relayoutUpdates: () => import_canvas31.relayoutUpdates,
299
+ remapPastedNodes: () => import_canvas30.remapPastedNodes,
300
+ removeCanvasVariant: () => import_canvas34.removeCanvasVariant,
301
+ removeTrack: () => import_canvas33.removeTrack,
302
+ renameCanvasVariantProperty: () => import_canvas34.renameCanvasVariantProperty,
303
+ renameCanvasVariantValue: () => import_canvas34.renameCanvasVariantValue,
304
+ renderShapeBrushstroke: () => import_canvas34.renderShapeBrushstroke,
305
+ reorderNodes: () => import_canvas27.reorderNodes,
306
+ repositionNodesTo: () => import_canvas30.repositionNodesTo,
307
+ resetCanvasInstanceOverrides: () => import_canvas34.resetCanvasInstanceOverrides,
308
+ resizeHandleAxes: () => import_canvas26.resizeHandleAxes,
309
+ resolveCanvasGradient: () => import_canvas34.resolveCanvasGradient,
310
+ resolveCanvasTokens: () => import_canvas32.resolveCanvasTokens,
311
+ resolveEasing: () => import_canvas33.resolveEasing,
312
+ resolvePadding: () => import_canvas31.resolvePadding,
313
+ restoreCanvasMainComponent: () => import_canvas34.restoreCanvasMainComponent,
314
+ revertShapeCombination: () => import_canvas28.revertShapeCombination,
315
+ rgbToOklab: () => import_canvas33.rgbToOklab,
316
+ ringSignedArea: () => import_canvas28.ringSignedArea,
317
+ runMultiNodeTransition: () => import_canvas30.runMultiNodeTransition,
318
+ sampleAnimationFrames: () => import_canvas33.sampleAnimationFrames,
319
+ scaleKeyframes: () => import_canvas33.scaleKeyframes,
320
+ serializeCanvasNodes: () => import_canvas30.serializeCanvasNodes,
321
+ setCanvasComponentProperty: () => import_canvas34.setCanvasComponentProperty,
322
+ setCanvasInstanceProperties: () => import_canvas34.setCanvasInstanceProperties,
323
+ setCanvasTokenMode: () => import_canvas32.setCanvasTokenMode,
324
+ setCanvasVariantProperties: () => import_canvas34.setCanvasVariantProperties,
325
+ setKeyframe: () => import_canvas33.setKeyframe,
326
+ setKeyframeEasing: () => import_canvas33.setKeyframeEasing,
327
+ setMotionPath: () => import_canvas33.setMotionPath,
328
+ setTrackEnabled: () => import_canvas33.setTrackEnabled,
329
+ shapeNodeToBezierPath: () => import_canvas29.shapeNodeToBezierPath,
330
+ shapeNodeToPolygon: () => import_canvas28.shapeNodeToPolygon,
331
+ shapeToBezierPath: () => import_canvas29.shapeToBezierPath,
332
+ shapeToPolygon: () => import_canvas28.shapeToPolygon,
333
+ sideToPosition: () => import_canvas27.sideToPosition,
334
+ simplifyRing: () => import_canvas28.simplifyRing,
335
+ snapKeyframeDelta: () => import_canvas33.snapKeyframeDelta,
336
+ snapNodeDrag: () => import_canvas27.snapNodeDrag,
337
+ snapNodeResize: () => import_canvas26.snapNodeResize,
338
+ snapResize: () => import_canvas26.snapResize,
339
+ snapTimeToFrame: () => import_canvas33.snapTimeToFrame,
340
+ snapToGrid: () => import_canvas26.snapToGrid,
341
+ springAt: () => import_canvas33.springAt,
342
+ streamlinePoints: () => import_canvas34.streamlinePoints,
343
+ strokeOutlineRings: () => import_canvas29.strokeOutlineRings,
344
+ strokePointsToPathData: () => import_canvas34.strokePointsToPathData,
345
+ strokeToShapeNode: () => import_canvas34.strokeToShapeNode,
346
+ subtractPaths: () => import_canvas29.subtractPaths,
347
+ subtractPolygons: () => import_canvas28.subtractPolygons,
348
+ swapCanvasInstance: () => import_canvas34.swapCanvasInstance,
349
+ syncAllCanvasInstances: () => import_canvas34.syncAllCanvasInstances,
350
+ syncCanvasComponents: () => import_canvas34.syncCanvasComponents,
351
+ syncCanvasInstance: () => import_canvas34.syncCanvasInstance,
352
+ timeToX: () => import_canvas33.timeToX,
353
+ toBezierPath: () => import_canvas29.toBezierPath,
354
+ toWebAnimations: () => import_canvas33.toWebAnimations,
355
+ toggleLockNodes: () => import_canvas27.toggleLockNodes,
356
+ transformBezierPath: () => import_canvas29.transformBezierPath,
357
+ unionPolygons: () => import_canvas28.unionPolygons,
358
+ unitePaths: () => import_canvas29.unitePaths,
359
+ unlockNodes: () => import_canvas27.unlockNodes,
360
+ updateKeyframe: () => import_canvas33.updateKeyframe,
348
361
  useCanvasAnimation: () => useCanvasAnimation,
349
362
  useCanvasArrange: () => useCanvasArrange,
350
363
  useCanvasArrangeShortcuts: () => useCanvasArrangeShortcuts,
@@ -355,6 +368,9 @@ __export(canvas_exports, {
355
368
  useCanvasComponents: () => useCanvasComponents,
356
369
  useCanvasDocking: () => useCanvasDocking,
357
370
  useCanvasDraw: () => useCanvasDraw,
371
+ useCanvasEffects: () => useCanvasEffects,
372
+ useCanvasEffectsProviderContext: () => useCanvasEffectsProviderContext,
373
+ useCanvasEffectsTools: () => useCanvasEffectsTools,
358
374
  useCanvasExplosion: () => useCanvasExplosion,
359
375
  useCanvasGraph: () => useCanvasGraph,
360
376
  useCanvasLayout: () => useCanvasLayout,
@@ -369,14 +385,14 @@ __export(canvas_exports, {
369
385
  usePresenceState: () => usePresenceState,
370
386
  useShapeBrushstroke: () => useShapeBrushstroke,
371
387
  useStreamingCanvas: () => useStreamingCanvas,
372
- validateCanvasBrush: () => import_canvas33.validateCanvasBrush,
373
- withNodeAnimation: () => import_canvas32.withNodeAnimation,
374
- withStyleSize: () => import_canvas26.withStyleSize,
375
- wouldCreateComponentCycle: () => import_canvas33.wouldCreateComponentCycle,
376
- wrapAnimationTime: () => import_canvas32.wrapAnimationTime,
377
- writeNodeStyleProperty: () => import_canvas31.writeNodeStyleProperty,
378
- xToTime: () => import_canvas32.xToTime,
379
- xorPolygons: () => import_canvas27.xorPolygons
388
+ validateCanvasBrush: () => import_canvas34.validateCanvasBrush,
389
+ withNodeAnimation: () => import_canvas33.withNodeAnimation,
390
+ withStyleSize: () => import_canvas27.withStyleSize,
391
+ wouldCreateComponentCycle: () => import_canvas34.wouldCreateComponentCycle,
392
+ wrapAnimationTime: () => import_canvas33.wrapAnimationTime,
393
+ writeNodeStyleProperty: () => import_canvas32.writeNodeStyleProperty,
394
+ xToTime: () => import_canvas33.xToTime,
395
+ xorPolygons: () => import_canvas28.xorPolygons
380
396
  });
381
397
  module.exports = __toCommonJS(canvas_exports);
382
398
 
@@ -1204,9 +1220,13 @@ function useCanvasScenes(options = {}) {
1204
1220
  );
1205
1221
  const actions = (0, import_react9.useMemo)(() => {
1206
1222
  const show = (scene) => {
1207
- if (scene) {
1208
- optionsRef.current.setViewport?.(scene.viewport, { duration: optionsRef.current.duration ?? 300 });
1209
- }
1223
+ if (!scene) return scene;
1224
+ const o = optionsRef.current;
1225
+ const provider = o.transitions?.provider;
1226
+ const element = o.transitions?.element();
1227
+ if (scene.transition && provider && element) {
1228
+ void (0, import_canvas7.transitionCanvasView)({ provider, transition: scene.transition, element, jump: () => o.setViewport?.(scene.viewport, { duration: 0 }) });
1229
+ } else o.setViewport?.(scene.viewport, { duration: o.duration ?? 300 });
1210
1230
  return scene;
1211
1231
  };
1212
1232
  return {
@@ -1624,11 +1644,11 @@ function useCanvasMeasure(options) {
1624
1644
  }
1625
1645
 
1626
1646
  // src/canvas/index.ts
1627
- var import_canvas25 = require("@pixerate/editor/canvas");
1628
1647
  var import_canvas26 = require("@pixerate/editor/canvas");
1648
+ var import_canvas27 = require("@pixerate/editor/canvas");
1629
1649
 
1630
1650
  // src/canvas/ShapeNode.tsx
1631
- var import_canvas13 = require("@pixerate/editor/canvas");
1651
+ var import_canvas14 = require("@pixerate/editor/canvas");
1632
1652
 
1633
1653
  // src/canvas/useShapeBrushstroke.tsx
1634
1654
  var import_react14 = require("react");
@@ -1682,14 +1702,708 @@ function useCanvasBrushes() {
1682
1702
  return (0, import_react14.useMemo)(() => state, [state]);
1683
1703
  }
1684
1704
 
1685
- // src/canvas/ShapeNode.tsx
1705
+ // src/canvas/CanvasEffects.tsx
1706
+ var import_react20 = require("react");
1707
+ var import_canvas13 = require("@pixerate/editor/canvas");
1708
+
1709
+ // src/effects/useEffects.ts
1710
+ var import_react15 = require("react");
1711
+ function useEffectDescription(provider, effect) {
1712
+ const [state, setState] = (0, import_react15.useState)({ key: "", description: null, error: null });
1713
+ const key = provider && effect ? `${provider.id}:${effect}` : "";
1714
+ (0, import_react15.useEffect)(() => {
1715
+ if (!provider || !effect) return;
1716
+ let live = true;
1717
+ Promise.resolve().then(() => provider.describe(effect)).then(
1718
+ (description) => live && setState({ key, description, error: null }),
1719
+ (e) => live && setState({ key, description: null, error: e instanceof Error ? e.message : String(e) })
1720
+ );
1721
+ return () => {
1722
+ live = false;
1723
+ };
1724
+ }, [provider, effect, key]);
1725
+ return state.key === key ? { description: state.description, error: state.error } : { description: null, error: null };
1726
+ }
1727
+
1728
+ // src/effects/EffectThumbnail.tsx
1729
+ var import_react16 = require("react");
1730
+ var import_effects = require("@pixerate/editor/effects");
1686
1731
  var import_jsx_runtime5 = require("react/jsx-runtime");
1732
+ function EffectThumbnail({ provider, effect, width = 96, height = 54, className = "" }) {
1733
+ const ref = (0, import_react16.useRef)(null);
1734
+ const [failed, setFailed] = (0, import_react16.useState)(effect.kind === "motion");
1735
+ (0, import_react16.useEffect)(() => {
1736
+ if (effect.kind === "motion") return;
1737
+ let live = true;
1738
+ (0, import_effects.renderEffectThumbnail)(provider, effect, { width, height }).then(
1739
+ (pixels) => {
1740
+ const ctx = live ? ref.current?.getContext("2d") : null;
1741
+ if (!ctx || typeof ImageData === "undefined") return;
1742
+ ctx.putImageData(new ImageData(new Uint8ClampedArray(pixels.data), pixels.width, pixels.height), 0, 0);
1743
+ },
1744
+ () => live && setFailed(true)
1745
+ );
1746
+ return () => {
1747
+ live = false;
1748
+ };
1749
+ }, [provider, effect, width, height]);
1750
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1751
+ "div",
1752
+ {
1753
+ className: `relative overflow-hidden rounded border border-border bg-[repeating-conic-gradient(#8884_0_25%,transparent_0_50%)] bg-[length:12px_12px] ${className}`,
1754
+ style: { aspectRatio: `${width} / ${height}` },
1755
+ "data-effect-thumbnail": effect.id,
1756
+ children: failed ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "absolute inset-0 flex items-center justify-center text-[10px] text-muted-foreground", children: effect.kind === "motion" ? "Motion" : "No preview" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("canvas", { ref, width, height, className: "h-full w-full", "aria-hidden": "true" })
1757
+ }
1758
+ );
1759
+ }
1760
+
1761
+ // src/effects/EffectsBrowser.tsx
1762
+ var import_react17 = require("react");
1763
+ var import_effects2 = require("@pixerate/editor/effects");
1764
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1765
+ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, title = "Effects", className = "" }) {
1766
+ const [all, setAll] = (0, import_react17.useState)([]);
1767
+ const [query, setQuery] = (0, import_react17.useState)("");
1768
+ const [category, setCategory] = (0, import_react17.useState)("");
1769
+ const [use, setUse] = (0, import_react17.useState)("");
1770
+ const [error, setError] = (0, import_react17.useState)(null);
1771
+ (0, import_react17.useEffect)(() => {
1772
+ if (!provider) return setAll([]);
1773
+ let live = true;
1774
+ Promise.resolve().then(() => provider.list()).then(
1775
+ (list) => live && (setAll(list), setError(null)),
1776
+ (e) => live && setError(e instanceof Error ? e.message : String(e))
1777
+ );
1778
+ return () => {
1779
+ live = false;
1780
+ };
1781
+ }, [provider]);
1782
+ const [found, setFound] = (0, import_react17.useState)([]);
1783
+ (0, import_react17.useEffect)(() => {
1784
+ if (!provider) return setFound([]);
1785
+ let live = true;
1786
+ Promise.resolve().then(() => provider.search(query, { ...category ? { category } : {}, ...use ? { use } : {} })).then((list) => live && setFound(list), () => live && setFound([]));
1787
+ return () => {
1788
+ live = false;
1789
+ };
1790
+ }, [provider, query, category, use]);
1791
+ const allowed = (e) => (!kinds || kinds.includes(e.kind)) && (uses ? e.kind !== "motion" || uses.includes("motion") : e.kind !== "motion") && (!uses || e.uses.some((u) => uses.includes(u)));
1792
+ const categories = (0, import_react17.useMemo)(() => [...new Set(all.filter(allowed).map((e) => e.category))], [all, uses, kinds]);
1793
+ const shown = found.filter(allowed);
1794
+ if (!provider)
1795
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: `rounded-md border border-dashed border-border p-3 text-xs text-muted-foreground ${className}`, "data-effects-browser": "", "data-effects-unavailable": "", children: "No effects provider is registered, so effects cannot be added. Effects already in the document are kept." });
1796
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: `flex flex-col gap-2 ${className}`, "data-effects-browser": "", "aria-label": "Effects browser", children: [
1797
+ title && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { className: "text-xs font-semibold", children: title }),
1798
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
1799
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1800
+ "input",
1801
+ {
1802
+ type: "search",
1803
+ className: "min-w-0 flex-1 rounded border border-border bg-transparent px-1.5 py-0.5 text-xs",
1804
+ placeholder: "Search effects",
1805
+ "aria-label": "Search effects",
1806
+ value: query,
1807
+ onChange: (e) => setQuery(e.currentTarget.value)
1808
+ }
1809
+ ),
1810
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("select", { className: "rounded border border-border bg-transparent px-1 py-0.5 text-xs", "aria-label": "Category", value: category, onChange: (e) => setCategory(e.currentTarget.value), children: [
1811
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: "All categories" }),
1812
+ categories.map((c) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: c, children: c }, c))
1813
+ ] }),
1814
+ uses && uses.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("select", { className: "rounded border border-border bg-transparent px-1 py-0.5 text-xs", "aria-label": "Use", value: use, onChange: (e) => setUse(e.currentTarget.value), children: [
1815
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: "Any use" }),
1816
+ uses.map((u) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: u, children: import_effects2.EFFECT_USE_LABELS[u] }, u))
1817
+ ] })
1818
+ ] }),
1819
+ error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: error }),
1820
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "grid max-h-96 grid-cols-[repeat(auto-fill,minmax(6.5rem,1fr))] gap-1.5 overflow-y-auto", role: "list", children: shown.map((e) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1821
+ "button",
1822
+ {
1823
+ type: "button",
1824
+ className: "flex w-full flex-col gap-1 rounded border border-transparent p-1 text-left hover:border-border focus-visible:border-border",
1825
+ title: e.description ?? e.name,
1826
+ "data-effect-id": e.id,
1827
+ onClick: () => onPick(e),
1828
+ children: [
1829
+ thumbnails && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(EffectThumbnail, { provider, effect: e }),
1830
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate text-[11px] font-medium", children: e.name }),
1831
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate text-[10px] text-muted-foreground", children: e.uses.map((u) => import_effects2.EFFECT_USE_LABELS[u]).join(" \xB7 ") })
1832
+ ]
1833
+ }
1834
+ ) }, e.id)) }),
1835
+ !shown.length && !error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No effects match." })
1836
+ ] });
1837
+ }
1838
+
1839
+ // src/effects/EffectParameters.tsx
1840
+ var import_react19 = __toESM(require("react"), 1);
1841
+ var import_effects3 = require("@pixerate/editor/effects");
1842
+ var import_parameters2 = require("@pixerate/editor/parameters");
1843
+
1844
+ // src/parameters/fields.tsx
1845
+ var import_react18 = require("react");
1846
+ var import_parameters = require("@pixerate/editor/parameters");
1847
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1848
+ var parameterInputClass = "h-7 w-full min-w-0 rounded-md border border-input bg-background px-2 text-xs text-foreground tabular-nums focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:cursor-not-allowed disabled:opacity-50";
1849
+ var parameterButtonClass = "inline-flex h-7 items-center justify-center gap-1 rounded-md border border-input bg-background px-2 text-xs text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:pointer-events-none disabled:opacity-50";
1850
+ var rangeClass = "h-4 w-full min-w-0 flex-1 cursor-pointer accent-primary disabled:cursor-not-allowed disabled:opacity-50";
1851
+ function ParameterCommitInput({ value, onCommit, multiline, className, onKeyDown, ...rest }) {
1852
+ const commit = (el) => {
1853
+ if (el.value !== value) onCommit(el.value, el);
1854
+ };
1855
+ const keyDown = (e) => {
1856
+ onKeyDown?.(e);
1857
+ if (e.defaultPrevented) return;
1858
+ if (e.key === "Enter" && (!multiline || e.metaKey || e.ctrlKey)) {
1859
+ e.preventDefault();
1860
+ commit(e.currentTarget);
1861
+ }
1862
+ if (e.key === "Escape") e.currentTarget.value = value;
1863
+ };
1864
+ const props = {
1865
+ defaultValue: value,
1866
+ className: className ?? parameterInputClass,
1867
+ onBlur: (e) => commit(e.currentTarget),
1868
+ onKeyDown: keyDown,
1869
+ ...rest
1870
+ };
1871
+ return multiline ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("textarea", { ...props, className: `${props.className} h-auto min-h-[3.5rem] py-1` }, value) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "text", ...props }, value);
1872
+ }
1873
+ var plainNumber = (field, value) => (0, import_parameters.formatParameterNumber)({ ...field, unit: void 0 }, value);
1874
+ function ParameterNumberInput({
1875
+ field,
1876
+ value,
1877
+ onChange,
1878
+ disabled,
1879
+ id,
1880
+ "aria-label": ariaLabel
1881
+ }) {
1882
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "relative min-w-0 flex-1", children: [
1883
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1884
+ ParameterCommitInput,
1885
+ {
1886
+ id,
1887
+ inputMode: "decimal",
1888
+ "aria-label": ariaLabel ?? (0, import_parameters.parameterLabel)(field),
1889
+ value: plainNumber(field, value),
1890
+ disabled: disabled || field.readOnly,
1891
+ className: `${parameterInputClass} ${field.unit ? "pr-6" : ""}`,
1892
+ onCommit: (text, input) => {
1893
+ const n = (0, import_parameters.parseParameterNumberInput)(field, text);
1894
+ if (n === null || n === value) input.value = plainNumber(field, value);
1895
+ else onChange(n);
1896
+ },
1897
+ onKeyDown: (e) => {
1898
+ if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
1899
+ e.preventDefault();
1900
+ const step = (0, import_parameters.parameterStep)(field) * (e.shiftKey ? 10 : 1);
1901
+ onChange((0, import_parameters.clampParameterNumber)(field, value + (e.key === "ArrowUp" ? step : -step)));
1902
+ }
1903
+ }
1904
+ ),
1905
+ field.unit && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-[10px] text-muted-foreground", children: field.unit })
1906
+ ] });
1907
+ }
1908
+ function ParameterSlider(props) {
1909
+ const { field, value, onChange, onGestureStart, onGestureEnd, disabled } = props;
1910
+ const dragging = (0, import_react18.useRef)(false);
1911
+ const end = () => {
1912
+ if (!dragging.current) return;
1913
+ dragging.current = false;
1914
+ onGestureEnd?.();
1915
+ };
1916
+ if (!(0, import_parameters.isSliderField)(field)) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterNumberInput, { ...props });
1917
+ const step = (0, import_parameters.parameterStep)(field);
1918
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
1919
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1920
+ "input",
1921
+ {
1922
+ type: "range",
1923
+ "aria-label": (0, import_parameters.parameterLabel)(field),
1924
+ "aria-valuetext": (0, import_parameters.formatParameterNumber)(field, value),
1925
+ min: field.min,
1926
+ max: field.max,
1927
+ step,
1928
+ value,
1929
+ disabled: disabled || field.readOnly,
1930
+ className: rangeClass,
1931
+ onPointerDown: () => {
1932
+ if (dragging.current) return;
1933
+ dragging.current = true;
1934
+ onGestureStart?.();
1935
+ },
1936
+ onPointerUp: end,
1937
+ onPointerCancel: end,
1938
+ onBlur: end,
1939
+ onChange: (e) => onChange((0, import_parameters.clampParameterNumber)(field, Number(e.target.value)))
1940
+ }
1941
+ ),
1942
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-20 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterNumberInput, { ...props, id: props.id, "aria-label": `${(0, import_parameters.parameterLabel)(field)} value` }) })
1943
+ ] });
1944
+ }
1945
+ function ParameterToggle({ field, value, onChange, disabled, id }) {
1946
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1947
+ "button",
1948
+ {
1949
+ type: "button",
1950
+ role: "switch",
1951
+ id,
1952
+ "aria-checked": value,
1953
+ "aria-label": (0, import_parameters.parameterLabel)(field),
1954
+ disabled: disabled || field.readOnly,
1955
+ onClick: () => onChange(!value),
1956
+ className: `relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-transparent transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:opacity-50 ${value ? "bg-primary" : "bg-muted"}`,
1957
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1958
+ "span",
1959
+ {
1960
+ className: `pointer-events-none block h-4 w-4 rounded-full bg-background shadow transition-transform ${value ? "translate-x-4" : "translate-x-0.5"}`
1961
+ }
1962
+ )
1963
+ }
1964
+ );
1965
+ }
1966
+ function ParameterSelect({ field, value, onChange, disabled, id }) {
1967
+ const options = (0, import_parameters.getChoiceOptions)(field);
1968
+ const off = disabled || field.readOnly;
1969
+ if (field.control === "segmented") {
1970
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { role: "radiogroup", "aria-label": (0, import_parameters.parameterLabel)(field), className: "inline-flex flex-wrap rounded-md border border-input bg-muted p-0.5", children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1971
+ "button",
1972
+ {
1973
+ type: "button",
1974
+ role: "radio",
1975
+ "aria-checked": o.value === value,
1976
+ title: o.description,
1977
+ disabled: off,
1978
+ onClick: () => onChange(o.value),
1979
+ className: `rounded px-2 py-0.5 text-xs disabled:opacity-50 ${o.value === value ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
1980
+ children: (0, import_parameters.choiceOptionLabel)(o)
1981
+ },
1982
+ String(o.value)
1983
+ )) });
1984
+ }
1985
+ const index = options.findIndex((o) => o.value === value);
1986
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1987
+ "select",
1988
+ {
1989
+ id,
1990
+ "aria-label": (0, import_parameters.parameterLabel)(field),
1991
+ value: String(index),
1992
+ disabled: off,
1993
+ onChange: (e) => {
1994
+ const option = options[Number(e.target.value)];
1995
+ if (option) onChange(option.value);
1996
+ },
1997
+ className: parameterInputClass,
1998
+ children: options.map((o, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: String(i), title: o.description, children: (0, import_parameters.choiceOptionLabel)(o) }, String(o.value)))
1999
+ }
2000
+ );
2001
+ }
2002
+ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd, disabled, id }) {
2003
+ const picking = (0, import_react18.useRef)(false);
2004
+ const alpha = !!field.alpha;
2005
+ const hex = (0, import_parameters.normalizeHexColor)(value, true) ?? "#000000ff";
2006
+ const rgb = hex.slice(0, 7);
2007
+ const a = hex.slice(7);
2008
+ const off = disabled || field.readOnly;
2009
+ const start = () => {
2010
+ if (picking.current) return;
2011
+ picking.current = true;
2012
+ onGestureStart?.();
2013
+ };
2014
+ const end = () => {
2015
+ if (!picking.current) return;
2016
+ picking.current = false;
2017
+ onGestureEnd?.();
2018
+ };
2019
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1.5", children: [
2020
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
2021
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "relative h-7 w-9 shrink-0 overflow-hidden rounded-md border border-input bg-[repeating-conic-gradient(#d4d4d8_0_25%,#fff_0_50%)] bg-[length:8px_8px]", children: [
2022
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "absolute inset-0", style: { background: alpha ? hex : rgb } }),
2023
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2024
+ "input",
2025
+ {
2026
+ type: "color",
2027
+ "aria-label": (0, import_parameters.parameterLabel)(field),
2028
+ value: rgb,
2029
+ disabled: off,
2030
+ className: "absolute inset-0 h-full w-full cursor-pointer opacity-0 disabled:cursor-not-allowed",
2031
+ onChange: (e) => {
2032
+ start();
2033
+ onChange(alpha ? `${e.target.value}${a}` : e.target.value);
2034
+ },
2035
+ onBlur: end
2036
+ }
2037
+ )
2038
+ ] }),
2039
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2040
+ ParameterCommitInput,
2041
+ {
2042
+ id,
2043
+ "aria-label": `${(0, import_parameters.parameterLabel)(field)} hex`,
2044
+ value: alpha ? hex : rgb,
2045
+ disabled: off,
2046
+ spellCheck: false,
2047
+ className: `${parameterInputClass} font-mono`,
2048
+ onCommit: (text) => {
2049
+ const next = (0, import_parameters.normalizeHexColor)(text, alpha);
2050
+ if (next) onChange(next);
2051
+ }
2052
+ }
2053
+ )
2054
+ ] }),
2055
+ alpha && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2056
+ "input",
2057
+ {
2058
+ type: "range",
2059
+ "aria-label": `${(0, import_parameters.parameterLabel)(field)} opacity`,
2060
+ min: 0,
2061
+ max: 255,
2062
+ step: 1,
2063
+ value: parseInt(a, 16),
2064
+ disabled: off,
2065
+ className: rangeClass,
2066
+ onPointerDown: start,
2067
+ onPointerUp: end,
2068
+ onPointerCancel: end,
2069
+ onBlur: end,
2070
+ onChange: (e) => onChange(`${rgb}${Number(e.target.value).toString(16).padStart(2, "0")}`)
2071
+ }
2072
+ ),
2073
+ field.swatches && field.swatches.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-wrap gap-1", children: field.swatches.map((s) => {
2074
+ const swatch = (0, import_parameters.normalizeHexColor)(s, alpha);
2075
+ if (!swatch) return null;
2076
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2077
+ "button",
2078
+ {
2079
+ type: "button",
2080
+ title: swatch,
2081
+ "aria-label": `${(0, import_parameters.parameterLabel)(field)} ${swatch}`,
2082
+ "aria-pressed": swatch === (alpha ? hex : rgb),
2083
+ disabled: off,
2084
+ onClick: () => onChange(swatch),
2085
+ className: "h-5 w-5 rounded border border-input aria-pressed:ring-1 aria-pressed:ring-primary",
2086
+ style: { background: swatch }
2087
+ },
2088
+ s
2089
+ );
2090
+ }) })
2091
+ ] });
2092
+ }
2093
+ function ParameterVector({ field, value, onChange, disabled, id }) {
2094
+ const size = (0, import_parameters.vectorSize)(field);
2095
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "grid gap-1.5", style: { gridTemplateColumns: `repeat(${size}, minmax(0, 1fr))` }, children: Array.from({ length: size }, (_, i) => {
2096
+ const component = (0, import_parameters.vectorComponentField)(field, i);
2097
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex min-w-0 items-center gap-1", children: [
2098
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-3 shrink-0 text-[10px] uppercase text-muted-foreground", children: component.label }),
2099
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2100
+ ParameterNumberInput,
2101
+ {
2102
+ field: component,
2103
+ value: value[i] ?? 0,
2104
+ id: i === 0 ? id : void 0,
2105
+ "aria-label": `${(0, import_parameters.parameterLabel)(field)} ${component.label}`,
2106
+ disabled: disabled || field.readOnly,
2107
+ onChange: (n) => onChange(Array.from({ length: size }, (_2, j) => j === i ? n : value[j] ?? 0))
2108
+ }
2109
+ )
2110
+ ] }, i);
2111
+ }) });
2112
+ }
2113
+ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
2114
+ const off = disabled || field.readOnly;
2115
+ const name = (0, import_parameters.parameterLabel)(field);
2116
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1.5", children: [
2117
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
2118
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex h-12 w-16 shrink-0 items-center justify-center overflow-hidden rounded-md border border-input bg-muted", children: value ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: value, alt: name, className: "h-full w-full object-cover" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[10px] text-muted-foreground", children: "None" }) }),
2119
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
2120
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2121
+ ParameterCommitInput,
2122
+ {
2123
+ id,
2124
+ "aria-label": `${name} URL`,
2125
+ placeholder: "Image URL",
2126
+ value: value.startsWith("data:") ? "" : value,
2127
+ disabled: off,
2128
+ onCommit: (text) => onChange(text.trim())
2129
+ }
2130
+ ),
2131
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-1", children: [
2132
+ resolveFile && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: `${parameterButtonClass} cursor-pointer ${off ? "pointer-events-none opacity-50" : ""}`, children: [
2133
+ "Choose file\u2026",
2134
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2135
+ "input",
2136
+ {
2137
+ type: "file",
2138
+ className: "sr-only",
2139
+ accept: field.accept ?? "image/*",
2140
+ disabled: off,
2141
+ "aria-label": `${name} file`,
2142
+ onChange: async (e) => {
2143
+ const file = e.target.files?.[0];
2144
+ e.target.value = "";
2145
+ if (file) onChange(await resolveFile(file));
2146
+ }
2147
+ }
2148
+ )
2149
+ ] }),
2150
+ value && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: parameterButtonClass, disabled: off, onClick: () => onChange(""), "aria-label": `Clear ${name}`, children: "Clear" })
2151
+ ] })
2152
+ ] })
2153
+ ] }),
2154
+ field.options && field.options.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-wrap gap-1", children: field.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2155
+ "button",
2156
+ {
2157
+ type: "button",
2158
+ title: o.label ?? o.url,
2159
+ "aria-label": o.label ?? o.url,
2160
+ "aria-pressed": o.url === value,
2161
+ disabled: off,
2162
+ onClick: () => onChange(o.url),
2163
+ className: "h-9 w-12 overflow-hidden rounded border border-input aria-pressed:ring-2 aria-pressed:ring-primary",
2164
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: o.url, alt: "", className: "h-full w-full object-cover" })
2165
+ },
2166
+ o.url
2167
+ )) })
2168
+ ] });
2169
+ }
2170
+ function ParameterText({ field, value, onChange, disabled, id }) {
2171
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2172
+ ParameterCommitInput,
2173
+ {
2174
+ id,
2175
+ "aria-label": (0, import_parameters.parameterLabel)(field),
2176
+ multiline: field.multiline,
2177
+ placeholder: field.placeholder,
2178
+ maxLength: field.maxLength,
2179
+ value,
2180
+ disabled: disabled || field.readOnly,
2181
+ onCommit: onChange
2182
+ }
2183
+ );
2184
+ }
2185
+ function ParameterFieldControl({ field, value, onChange, resolveFile, ...rest }) {
2186
+ const set = onChange;
2187
+ switch (field.type) {
2188
+ case "number":
2189
+ case "int":
2190
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterSlider, { field, value, onChange: set, ...rest });
2191
+ case "boolean":
2192
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterToggle, { field, value, onChange: set, ...rest });
2193
+ case "choice":
2194
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterSelect, { field, value, onChange: set, ...rest });
2195
+ case "color":
2196
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterColor, { field, value, onChange: set, ...rest });
2197
+ case "vector":
2198
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterVector, { field, value, onChange: set, ...rest });
2199
+ case "image":
2200
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterImage, { field, value, onChange: set, resolveFile, ...rest });
2201
+ case "text":
2202
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterText, { field, value, onChange: set, ...rest });
2203
+ }
2204
+ }
2205
+
2206
+ // src/effects/EffectParameters.tsx
2207
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2208
+ function EffectParameters({ description, values, onChange, onReset, keyframed, onPreset, disabled = false, className = "" }) {
2209
+ const fields = (0, import_react19.useMemo)(() => (0, import_effects3.effectParameterFields)(description), [description]);
2210
+ const idBase = (0, import_react19.useId)();
2211
+ const gesture = import_react19.default.useRef(null);
2212
+ const count = import_react19.default.useRef(0);
2213
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: `space-y-2 ${className}`, "data-effect-parameters": description.id, children: [
2214
+ onPreset && description.presets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2215
+ "select",
2216
+ {
2217
+ className: "w-full rounded border border-border bg-transparent px-1 py-0.5 text-xs",
2218
+ "aria-label": `${description.name} presets`,
2219
+ value: "",
2220
+ disabled,
2221
+ onChange: (e) => {
2222
+ const preset = description.presets.find((p) => p.name === e.currentTarget.value);
2223
+ if (preset) onPreset({ ...description.defaults, ...preset.values });
2224
+ },
2225
+ children: [
2226
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "", children: "Presets\u2026" }),
2227
+ description.presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: p.name, children: p.name }, p.name))
2228
+ ]
2229
+ }
2230
+ ),
2231
+ fields.map((field) => {
2232
+ const label = (0, import_parameters2.parameterLabel)(field);
2233
+ const inputId = `${idBase}-${field.id}`;
2234
+ const keyed = keyframed?.has(field.id) ?? false;
2235
+ const value = (0, import_effects3.effectFieldValue)(field, values[field.id]);
2236
+ const changed = !keyed && !(0, import_parameters2.parameterValuesEqual)(value, field.default);
2237
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1", "data-effect-control": field.id, children: [
2238
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2239
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { htmlFor: inputId, className: "min-w-0 flex-1 truncate text-xs font-medium", title: field.description, children: label }),
2240
+ keyed && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] text-muted-foreground", children: "keyframed" }),
2241
+ onReset && changed && !disabled && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: "rounded px-1 text-[11px] text-muted-foreground hover:text-foreground", "aria-label": `Reset ${label}`, onClick: () => onReset(field.id), children: "\u21BA" })
2242
+ ] }),
2243
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2244
+ ParameterFieldControl,
2245
+ {
2246
+ field,
2247
+ value,
2248
+ id: inputId,
2249
+ disabled: disabled || keyed,
2250
+ onChange: (v) => onChange(field.id, v, gesture.current),
2251
+ onGestureStart: () => gesture.current = `${idBase}:${field.id}:${++count.current}`,
2252
+ onGestureEnd: () => gesture.current = null
2253
+ }
2254
+ )
2255
+ ] }, field.id);
2256
+ }),
2257
+ !fields.length && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No controls." })
2258
+ ] });
2259
+ }
2260
+
2261
+ // src/canvas/CanvasEffects.tsx
2262
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2263
+ var ProviderContext = (0, import_react20.createContext)(null);
2264
+ function CanvasEffectsProvider({ provider, children }) {
2265
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ProviderContext.Provider, { value: provider ?? null, children });
2266
+ }
2267
+ var useCanvasEffectsProviderContext = () => (0, import_react20.useContext)(ProviderContext);
2268
+ function CanvasNodeEffectLayer({ effect, width, height, clipPath, clipTransform }) {
2269
+ const provider = useCanvasEffectsProviderContext();
2270
+ const ref = (0, import_react20.useRef)(null);
2271
+ const [failed, setFailed] = (0, import_react20.useState)(false);
2272
+ const dpr = typeof window !== "undefined" ? Math.min(2, window.devicePixelRatio || 1) : 1;
2273
+ const pw = Math.max(1, Math.round(width * dpr));
2274
+ const ph = Math.max(1, Math.round(height * dpr));
2275
+ const key = JSON.stringify(effect);
2276
+ (0, import_react20.useEffect)(() => {
2277
+ const canvas2 = ref.current;
2278
+ if (!provider || !canvas2) return;
2279
+ setFailed(false);
2280
+ const run = (0, import_canvas13.runCanvasNodeEffect)({ provider, effect, target: canvas2, onError: () => setFailed(true) });
2281
+ return () => run.stop();
2282
+ }, [provider, key, pw, ph]);
2283
+ const clipId = (0, import_react20.useMemo)(() => `pixerate-effect-clip-${Math.random().toString(36).slice(2)}`, []);
2284
+ if (!provider || failed || !(width > 0 && height > 0)) return null;
2285
+ const style = { position: "absolute", inset: 0, width: "100%", height: "100%", pointerEvents: "none", opacity: effect.opacity ?? 1 };
2286
+ const canvas = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("canvas", { ref, width: pw, height: ph, style: { width: "100%", height: "100%", display: "block" }, "data-canvas-effect": effect.effect });
2287
+ if (effect.mode === "overlay" || !clipPath) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style, children: canvas });
2288
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { style, viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "none", "aria-hidden": "true", children: [
2289
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("clipPath", { id: clipId, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: clipPath, transform: clipTransform }) }) }),
2290
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("foreignObject", { x: 0, y: 0, width, height, clipPath: `url(#${clipId})`, children: canvas })
2291
+ ] });
2292
+ }
2293
+ function useCanvasEffects(options) {
2294
+ const opts = (0, import_react20.useRef)(options);
2295
+ opts.current = options;
2296
+ const controller = (0, import_react20.useMemo)(
2297
+ () => (0, import_canvas13.createCanvasEffectsController)({
2298
+ getNodes: () => opts.current.getNodes(),
2299
+ setNodes: (n) => opts.current.setNodes(n),
2300
+ history: { execute: (c) => opts.current.history ? opts.current.history.execute(c) : c.execute() },
2301
+ get scenes() {
2302
+ return opts.current.scenes;
2303
+ }
2304
+ }),
2305
+ []
2306
+ );
2307
+ (0, import_react20.useEffect)(() => {
2308
+ if (!options.effects) return;
2309
+ return controller.useEffects(options.effects);
2310
+ }, [controller, options.effects]);
2311
+ return controller;
2312
+ }
2313
+ function useCanvasEffectsTools(registry, controller, options = {}) {
2314
+ const { id, namespace, readOnly, subscribe } = options;
2315
+ (0, import_react20.useEffect)(() => {
2316
+ if (!registry) return;
2317
+ return registry.register((0, import_canvas13.createCanvasEffectsToolProvider)(controller, { id, namespace, readOnly, subscribe }));
2318
+ }, [registry, controller, id, namespace, readOnly, subscribe]);
2319
+ }
2320
+ var btn = "rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40";
2321
+ function Controls({ controller, nodeId, effect }) {
2322
+ const { description, error } = useEffectDescription(controller.effectsProvider, effect.effect);
2323
+ const [message, setMessage] = (0, import_react20.useState)(null);
2324
+ const run = (work) => void work.then(() => setMessage(null), (e) => setMessage(e instanceof Error ? e.message : String(e)));
2325
+ if (error) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-[11px] text-amber-500", children: error });
2326
+ if (!description) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Loading\u2026" });
2327
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2328
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2329
+ EffectParameters,
2330
+ {
2331
+ description,
2332
+ values: effect.values,
2333
+ onChange: (k, v) => run(controller.updateNodeEffect(nodeId, { values: { [k]: v } })),
2334
+ onReset: (k) => run(controller.updateNodeEffect(nodeId, { values: { [k]: null } })),
2335
+ onPreset: (v) => run(controller.updateNodeEffect(nodeId, { values: v }))
2336
+ }
2337
+ ),
2338
+ message && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
2339
+ ] });
2340
+ }
2341
+ function CanvasEffectsPanel({ controller, nodeId, shape, sceneId, className = "" }) {
2342
+ const [, setTick] = (0, import_react20.useState)(0);
2343
+ (0, import_react20.useEffect)(() => controller.effects.subscribe(() => setTick((n) => n + 1)), [controller]);
2344
+ const provider = controller.effectsProvider;
2345
+ const [browse, setBrowse] = (0, import_react20.useState)(null);
2346
+ const [message, setMessage] = (0, import_react20.useState)(null);
2347
+ const run = (work) => {
2348
+ setMessage(null);
2349
+ Promise.resolve().then(work).then(() => setTick((n) => n + 1), (e) => setMessage(e instanceof Error ? e.message : String(e)));
2350
+ };
2351
+ const effect = (0, import_canvas13.isShapeDescription)(shape) ? shape.effect : void 0;
2352
+ const transition = sceneId ? controller.sceneTransition(sceneId) : void 0;
2353
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("section", { className: `flex flex-col gap-2 text-xs ${className}`, "aria-label": "Canvas effects", "data-canvas-effects": "", children: [
2354
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
2355
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "flex-1 font-semibold", children: "Effects" }),
2356
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: btn, disabled: !provider || !nodeId || !shape, "aria-pressed": browse === "fill", onClick: () => setBrowse(browse === "fill" ? null : "fill"), children: "Fill\u2026" }),
2357
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: btn, disabled: !provider || !nodeId || !shape, "aria-pressed": browse === "overlay", onClick: () => setBrowse(browse === "overlay" ? null : "overlay"), children: "Overlay\u2026" }),
2358
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: btn, disabled: !provider || !sceneId, "aria-pressed": browse === "transition", onClick: () => setBrowse(browse === "transition" ? null : "transition"), children: "Scene transition\u2026" })
2359
+ ] }),
2360
+ !provider && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No effects provider is registered. Effects on the canvas are kept." }),
2361
+ browse === "fill" && nodeId && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EffectsBrowser, { provider, uses: ["generator", "interactive"], title: "Fills", onPick: (e) => (setBrowse(null), run(() => controller.applyNodeEffect(nodeId, e.id, { mode: "fill" }))) }),
2362
+ browse === "overlay" && nodeId && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EffectsBrowser, { provider, uses: ["overlay", "title", "interactive", "generator"], title: "Overlays", onPick: (e) => (setBrowse(null), run(() => controller.applyNodeEffect(nodeId, e.id, { mode: "overlay" }))) }),
2363
+ browse === "transition" && sceneId && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(EffectsBrowser, { provider, uses: ["transition"], title: "Transitions", onPick: (e) => (setBrowse(null), run(() => controller.setSceneTransition(sceneId, e.id))) }),
2364
+ effect && nodeId && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "space-y-1 rounded border border-border p-1", "data-canvas-node-effect": nodeId, children: [
2365
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-1", children: [
2366
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "min-w-0 flex-1 truncate font-medium", children: [
2367
+ effect.name ?? effect.effect,
2368
+ " ",
2369
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "text-muted-foreground", children: [
2370
+ "\xB7 ",
2371
+ effect.mode
2372
+ ] })
2373
+ ] }),
2374
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-1", children: [
2375
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { type: "checkbox", checked: effect.playing !== false, "aria-label": "Play", onChange: (e) => {
2376
+ const playing = e.currentTarget.checked;
2377
+ run(() => controller.updateNodeEffect(nodeId, { playing }));
2378
+ } }),
2379
+ " Play"
2380
+ ] }),
2381
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: btn, "aria-label": "Remove effect", onClick: () => run(() => controller.removeNodeEffect(nodeId)), children: "\u2715" })
2382
+ ] }),
2383
+ provider && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Controls, { controller, nodeId, effect })
2384
+ ] }),
2385
+ sceneId && transition && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-1", "data-canvas-scene-transition": sceneId, children: [
2386
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
2387
+ "Into scene: ",
2388
+ transition.name ?? transition.effect,
2389
+ " (",
2390
+ transition.duration ?? 600,
2391
+ " ms)"
2392
+ ] }),
2393
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: btn, "aria-label": "Remove transition", onClick: () => run(() => controller.setSceneTransition(sceneId, null)), children: "\u2715" })
2394
+ ] }),
2395
+ message && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
2396
+ ] });
2397
+ }
2398
+
2399
+ // src/canvas/ShapeNode.tsx
2400
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1687
2401
  function ShapeNode({ id, data, width, height, selected, className = "", children }) {
1688
2402
  const shape = data?.shape;
1689
- const brushImage = useShapeBrushstroke((0, import_canvas13.isShapeDescription)(shape) ? shape : null, width, height);
1690
- if (!(0, import_canvas13.isShapeDescription)(shape)) return null;
1691
- const render = (0, import_canvas13.getShapeRenderData)(shape, { width, height }, { id: id || data?.id });
1692
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2403
+ const brushImage = useShapeBrushstroke((0, import_canvas14.isShapeDescription)(shape) ? shape : null, width, height);
2404
+ if (!(0, import_canvas14.isShapeDescription)(shape)) return null;
2405
+ const render = (0, import_canvas14.getShapeRenderData)(shape, { width, height }, { id: id || data?.id });
2406
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1693
2407
  "div",
1694
2408
  {
1695
2409
  className: `pixerate-shape-node ${className}`.trim(),
@@ -1697,7 +2411,7 @@ function ShapeNode({ id, data, width, height, selected, className = "", children
1697
2411
  "data-selected": selected ? "true" : void 0,
1698
2412
  style: { position: "relative", width: "100%", height: "100%" },
1699
2413
  children: [
1700
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2414
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1701
2415
  "svg",
1702
2416
  {
1703
2417
  viewBox: render.viewBox,
@@ -1707,13 +2421,13 @@ function ShapeNode({ id, data, width, height, selected, className = "", children
1707
2421
  style: { display: "block", overflow: "visible" },
1708
2422
  "aria-hidden": "true",
1709
2423
  children: [
1710
- (render.fillGradient || render.strokeGradient) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("defs", { children: [
1711
- render.fillGradient && render.fillGradient.type === "linear" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("linearGradient", { id: render.fillGradient.id, ...render.fillGradient.attrs, children: render.fillGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) }),
1712
- render.fillGradient && render.fillGradient.type === "radial" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("radialGradient", { id: render.fillGradient.id, ...render.fillGradient.attrs, children: render.fillGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) }),
1713
- render.strokeGradient && render.strokeGradient.type === "linear" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("linearGradient", { id: render.strokeGradient.id, ...render.strokeGradient.attrs, children: render.strokeGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) }),
1714
- render.strokeGradient && render.strokeGradient.type === "radial" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("radialGradient", { id: render.strokeGradient.id, ...render.strokeGradient.attrs, children: render.strokeGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) })
2424
+ (render.fillGradient || render.strokeGradient) && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("defs", { children: [
2425
+ render.fillGradient && render.fillGradient.type === "linear" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("linearGradient", { id: render.fillGradient.id, ...render.fillGradient.attrs, children: render.fillGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) }),
2426
+ render.fillGradient && render.fillGradient.type === "radial" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("radialGradient", { id: render.fillGradient.id, ...render.fillGradient.attrs, children: render.fillGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) }),
2427
+ render.strokeGradient && render.strokeGradient.type === "linear" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("linearGradient", { id: render.strokeGradient.id, ...render.strokeGradient.attrs, children: render.strokeGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) }),
2428
+ render.strokeGradient && render.strokeGradient.type === "radial" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("radialGradient", { id: render.strokeGradient.id, ...render.strokeGradient.attrs, children: render.strokeGradient.stops.map((stop, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("stop", { offset: stop.offset, stopColor: stop.stopColor, stopOpacity: stop.stopOpacity }, i)) })
1715
2429
  ] }),
1716
- brushImage ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("g", { transform: render.transform, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2430
+ brushImage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("g", { transform: render.transform, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1717
2431
  "image",
1718
2432
  {
1719
2433
  className: "pixerate-shape-brushstroke",
@@ -1725,7 +2439,7 @@ function ShapeNode({ id, data, width, height, selected, className = "", children
1725
2439
  preserveAspectRatio: "none",
1726
2440
  opacity: render.opacity
1727
2441
  }
1728
- ) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2442
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1729
2443
  "path",
1730
2444
  {
1731
2445
  d: render.d,
@@ -1743,6 +2457,7 @@ function ShapeNode({ id, data, width, height, selected, className = "", children
1743
2457
  ]
1744
2458
  }
1745
2459
  ),
2460
+ shape.effect && width && height ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CanvasNodeEffectLayer, { effect: shape.effect, width, height, clipPath: render.d, clipTransform: render.transform }) : null,
1746
2461
  children
1747
2462
  ]
1748
2463
  }
@@ -1750,22 +2465,22 @@ function ShapeNode({ id, data, width, height, selected, className = "", children
1750
2465
  }
1751
2466
 
1752
2467
  // src/canvas/index.ts
1753
- var import_canvas27 = require("@pixerate/editor/canvas");
1754
2468
  var import_canvas28 = require("@pixerate/editor/canvas");
1755
2469
  var import_canvas29 = require("@pixerate/editor/canvas");
1756
2470
  var import_canvas30 = require("@pixerate/editor/canvas");
2471
+ var import_canvas31 = require("@pixerate/editor/canvas");
1757
2472
 
1758
2473
  // src/canvas/useCanvasAutoLayout.ts
1759
- var import_react15 = require("react");
1760
- var import_canvas14 = require("@pixerate/editor/canvas");
2474
+ var import_react21 = require("react");
2475
+ var import_canvas15 = require("@pixerate/editor/canvas");
1761
2476
  function useCanvasAutoLayout(options) {
1762
- const [guides, setGuides] = (0, import_react15.useState)([]);
1763
- const nodesRef = (0, import_react15.useRef)(options.nodes);
2477
+ const [guides, setGuides] = (0, import_react21.useState)([]);
2478
+ const nodesRef = (0, import_react21.useRef)(options.nodes);
1764
2479
  nodesRef.current = options.nodes;
1765
- const optionsRef = (0, import_react15.useRef)(options);
2480
+ const optionsRef = (0, import_react21.useRef)(options);
1766
2481
  optionsRef.current = options;
1767
- const controller = (0, import_react15.useMemo)(
1768
- () => (0, import_canvas14.createCanvasAutoLayoutController)({
2482
+ const controller = (0, import_react21.useMemo)(
2483
+ () => (0, import_canvas15.createCanvasAutoLayoutController)({
1769
2484
  getNodes: () => nodesRef.current,
1770
2485
  setNodes: (next) => {
1771
2486
  nodesRef.current = next;
@@ -1790,10 +2505,10 @@ function useCanvasAutoLayout(options) {
1790
2505
  }),
1791
2506
  []
1792
2507
  );
1793
- (0, import_react15.useLayoutEffect)(() => {
2508
+ (0, import_react21.useLayoutEffect)(() => {
1794
2509
  if (controller.hasPending) controller.flush();
1795
2510
  }, [options.nodes, controller]);
1796
- return (0, import_react15.useMemo)(
2511
+ return (0, import_react21.useMemo)(
1797
2512
  () => ({
1798
2513
  ...controller,
1799
2514
  /** Drop marker of the active reorder drag (flow coordinates). */
@@ -1807,47 +2522,47 @@ function useCanvasAutoLayout(options) {
1807
2522
  }
1808
2523
 
1809
2524
  // src/canvas/useCanvasTokens.ts
1810
- var import_react16 = require("react");
1811
- var import_canvas15 = require("@pixerate/editor/canvas");
2525
+ var import_react22 = require("react");
2526
+ var import_canvas16 = require("@pixerate/editor/canvas");
1812
2527
  function useCanvasTokens(options) {
1813
2528
  const { store, nodes, setNodes, modes, properties } = options;
1814
- const state = (0, import_react16.useSyncExternalStore)(store.subscribe, store.getState, store.getState);
1815
- const latest = (0, import_react16.useRef)({ nodes, setNodes, modes, properties });
2529
+ const state = (0, import_react22.useSyncExternalStore)(store.subscribe, store.getState, store.getState);
2530
+ const latest = (0, import_react22.useRef)({ nodes, setNodes, modes, properties });
1816
2531
  latest.current = { nodes, setNodes, modes, properties };
1817
2532
  const opts = () => ({ modes: latest.current.modes, properties: latest.current.properties });
1818
- (0, import_react16.useEffect)(
2533
+ (0, import_react22.useEffect)(
1819
2534
  () => store.subscribe((event) => {
1820
2535
  if (event.deletedVariableIds.length === 0) return;
1821
- latest.current.setNodes((prev) => (0, import_canvas15.detachTokenBindings)(prev, event.previous, event.deletedVariableIds, opts()));
2536
+ latest.current.setNodes((prev) => (0, import_canvas16.detachTokenBindings)(prev, event.previous, event.deletedVariableIds, opts()));
1822
2537
  }),
1823
2538
  // eslint-disable-next-line react-hooks/exhaustive-deps
1824
2539
  [store]
1825
2540
  );
1826
2541
  const modesKey = JSON.stringify(modes ?? {});
1827
- (0, import_react16.useEffect)(() => {
1828
- const next = (0, import_canvas15.resolveCanvasTokens)(nodes, state, opts());
2542
+ (0, import_react22.useEffect)(() => {
2543
+ const next = (0, import_canvas16.resolveCanvasTokens)(nodes, state, opts());
1829
2544
  if (next !== nodes) setNodes(next);
1830
2545
  }, [nodes, state, modesKey, properties]);
1831
- const bind = (0, import_react16.useCallback)(
2546
+ const bind = (0, import_react22.useCallback)(
1832
2547
  (ids, propertyKey, variableId) => {
1833
- const next = (0, import_canvas15.bindCanvasToken)(latest.current.nodes, ids, propertyKey, variableId, store.getState(), opts());
2548
+ const next = (0, import_canvas16.bindCanvasToken)(latest.current.nodes, ids, propertyKey, variableId, store.getState(), opts());
1834
2549
  if (next !== latest.current.nodes) latest.current.setNodes(next);
1835
2550
  },
1836
2551
  // eslint-disable-next-line react-hooks/exhaustive-deps
1837
2552
  [store]
1838
2553
  );
1839
- const setMode = (0, import_react16.useCallback)(
2554
+ const setMode = (0, import_react22.useCallback)(
1840
2555
  (ids, collectionId, modeId) => {
1841
- const next = (0, import_canvas15.setCanvasTokenMode)(latest.current.nodes, ids, collectionId, modeId, store.getState(), opts());
2556
+ const next = (0, import_canvas16.setCanvasTokenMode)(latest.current.nodes, ids, collectionId, modeId, store.getState(), opts());
1842
2557
  if (next !== latest.current.nodes) latest.current.setNodes(next);
1843
2558
  },
1844
2559
  // eslint-disable-next-line react-hooks/exhaustive-deps
1845
2560
  [store]
1846
2561
  );
1847
- const modesOf = (0, import_react16.useCallback)(
2562
+ const modesOf = (0, import_react22.useCallback)(
1848
2563
  (nodeId) => {
1849
2564
  const node = latest.current.nodes.find((n) => n.id === nodeId);
1850
- return node ? (0, import_canvas15.getEffectiveTokenModes)(node, latest.current.nodes, store.getState(), opts()) : {};
2565
+ return node ? (0, import_canvas16.getEffectiveTokenModes)(node, latest.current.nodes, store.getState(), opts()) : {};
1851
2566
  },
1852
2567
  // eslint-disable-next-line react-hooks/exhaustive-deps
1853
2568
  [store]
@@ -1856,9 +2571,9 @@ function useCanvasTokens(options) {
1856
2571
  }
1857
2572
 
1858
2573
  // src/canvas/TokenBindingPicker.tsx
1859
- var import_canvas16 = require("@pixerate/editor/canvas");
2574
+ var import_canvas17 = require("@pixerate/editor/canvas");
1860
2575
  var import_tokens = require("@pixerate/editor/tokens");
1861
- var import_jsx_runtime6 = require("react/jsx-runtime");
2576
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1862
2577
  function TokenBindingPicker({
1863
2578
  state,
1864
2579
  nodes,
@@ -1872,18 +2587,18 @@ function TokenBindingPicker({
1872
2587
  const selected = nodes.filter((n) => selectedIds.includes(n.id));
1873
2588
  const first = selected[0];
1874
2589
  if (!first) return null;
1875
- let rows = (0, import_canvas16.getBindableTokenProperties)(first, options);
2590
+ let rows = (0, import_canvas17.getBindableTokenProperties)(first, options);
1876
2591
  if (properties) rows = properties.map((key) => rows.find((p) => p.key === key)).filter((p) => !!p);
1877
- const modes = (0, import_canvas16.getEffectiveTokenModes)(first, nodes, state, options);
1878
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-token-binding-picker": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
2592
+ const modes = (0, import_canvas17.getEffectiveTokenModes)(first, nodes, state, options);
2593
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { "data-token-binding-picker": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
1879
2594
  rows.map((property) => {
1880
- const ids = new Set(selected.map((n) => (0, import_canvas16.getNodeTokenBindings)(n)[property.key] ?? ""));
2595
+ const ids = new Set(selected.map((n) => (0, import_canvas17.getNodeTokenBindings)(n)[property.key] ?? ""));
1881
2596
  const value = ids.size === 1 ? [...ids][0] : "__mixed";
1882
- const candidates = (0, import_canvas16.getTokensForProperty)(state, property, first);
2597
+ const candidates = (0, import_canvas17.getTokensForProperty)(state, property, first);
1883
2598
  const resolved = value && value !== "__mixed" ? (0, import_tokens.resolveToken)(state, value, modes) : null;
1884
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-2", "data-token-property": property.key, children: [
1885
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-28 shrink-0 text-muted-foreground", children: property.label }),
1886
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2599
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-2", "data-token-property": property.key, children: [
2600
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "w-28 shrink-0 text-muted-foreground", children: property.label }),
2601
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1887
2602
  "select",
1888
2603
  {
1889
2604
  "aria-label": `${property.label} variable`,
@@ -1892,17 +2607,17 @@ function TokenBindingPicker({
1892
2607
  onChange: (e) => {
1893
2608
  const id = e.currentTarget.value || null;
1894
2609
  try {
1895
- onChange((0, import_canvas16.bindCanvasToken)(nodes, selectedIds, property.key, id, state, options));
2610
+ onChange((0, import_canvas17.bindCanvasToken)(nodes, selectedIds, property.key, id, state, options));
1896
2611
  } catch (error) {
1897
2612
  onError?.(error);
1898
2613
  }
1899
2614
  },
1900
2615
  children: [
1901
- value === "__mixed" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "__mixed", children: "Mixed" }) : null,
1902
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: "None" }),
2616
+ value === "__mixed" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "__mixed", children: "Mixed" }) : null,
2617
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "", children: "None" }),
1903
2618
  candidates.map((v) => {
1904
2619
  const collection = state.collections.find((c) => c.id === v.collectionId);
1905
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("option", { value: v.id, children: [
2620
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("option", { value: v.id, children: [
1906
2621
  v.name,
1907
2622
  collection && state.collections.length > 1 ? ` (${collection.name})` : ""
1908
2623
  ] }, v.id);
@@ -1910,17 +2625,17 @@ function TokenBindingPicker({
1910
2625
  ]
1911
2626
  }
1912
2627
  ),
1913
- /* @__PURE__ */ (0, import_jsx_runtime6.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_runtime6.jsx)(
2628
+ /* @__PURE__ */ (0, import_jsx_runtime11.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_runtime11.jsx)(
1914
2629
  "span",
1915
2630
  {
1916
2631
  className: "inline-block h-3 w-3 rounded border border-border align-middle",
1917
2632
  style: { background: String(resolved.value) },
1918
2633
  title: String(resolved.value)
1919
2634
  }
1920
- ) : String(resolved.value) : resolved ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { title: resolved.message, children: "\u26A0" }) : null })
2635
+ ) : String(resolved.value) : resolved ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { title: resolved.message, children: "\u26A0" }) : null })
1921
2636
  ] }, property.key);
1922
2637
  }),
1923
- state.collections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-muted-foreground", children: "No variables yet." }) : null
2638
+ state.collections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-muted-foreground", children: "No variables yet." }) : null
1924
2639
  ] });
1925
2640
  }
1926
2641
  function TokenModeSwitcher({
@@ -1934,29 +2649,29 @@ function TokenModeSwitcher({
1934
2649
  }) {
1935
2650
  const first = nodes.find((n) => nodeIds.includes(n.id));
1936
2651
  if (!first) return null;
1937
- const own = (0, import_canvas16.getNodeTokenModes)(first);
2652
+ const own = (0, import_canvas17.getNodeTokenModes)(first);
1938
2653
  const parent = first.parentId ? nodes.find((n) => n.id === first.parentId) : void 0;
1939
- const inherited = parent ? (0, import_canvas16.getEffectiveTokenModes)(parent, nodes, state, options) : { ...options.modes };
2654
+ const inherited = parent ? (0, import_canvas17.getEffectiveTokenModes)(parent, nodes, state, options) : { ...options.modes };
1940
2655
  const collections = state.collections.filter((c) => showSingleMode || c.modes.length > 1);
1941
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { "data-token-mode-switcher": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: collections.map((collection) => {
2656
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { "data-token-mode-switcher": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: collections.map((collection) => {
1942
2657
  const auto = (0, import_tokens.getCurrentMode)(collection, inherited);
1943
2658
  const explicit = collection.modes.some((m) => m.id === own[collection.id]) ? own[collection.id] : "";
1944
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-2", "data-token-collection": collection.id, children: [
1945
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-28 shrink-0 truncate text-muted-foreground", children: collection.name }),
1946
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2659
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-2", "data-token-collection": collection.id, children: [
2660
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "w-28 shrink-0 truncate text-muted-foreground", children: collection.name }),
2661
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1947
2662
  "select",
1948
2663
  {
1949
2664
  "aria-label": `${collection.name} mode`,
1950
2665
  className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
1951
2666
  value: explicit,
1952
- onChange: (e) => onChange((0, import_canvas16.setCanvasTokenMode)(nodes, nodeIds, collection.id, e.currentTarget.value || null, state, options)),
2667
+ onChange: (e) => onChange((0, import_canvas17.setCanvasTokenMode)(nodes, nodeIds, collection.id, e.currentTarget.value || null, state, options)),
1953
2668
  children: [
1954
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("option", { value: "", children: [
2669
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("option", { value: "", children: [
1955
2670
  "Auto (",
1956
2671
  auto.name,
1957
2672
  ")"
1958
2673
  ] }),
1959
- collection.modes.map((m) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: m.id, children: m.name }, m.id))
2674
+ collection.modes.map((m) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: m.id, children: m.name }, m.id))
1960
2675
  ]
1961
2676
  }
1962
2677
  )
@@ -1965,18 +2680,18 @@ function TokenModeSwitcher({
1965
2680
  }
1966
2681
 
1967
2682
  // src/canvas/index.ts
1968
- var import_canvas31 = require("@pixerate/editor/canvas");
2683
+ var import_canvas32 = require("@pixerate/editor/canvas");
1969
2684
 
1970
2685
  // src/canvas/useCanvasAnimation.ts
1971
- var import_react17 = require("react");
1972
- var import_canvas17 = require("@pixerate/editor/canvas");
2686
+ var import_react23 = require("react");
2687
+ var import_canvas18 = require("@pixerate/editor/canvas");
1973
2688
  function useCanvasAnimation(options) {
1974
- const nodesRef = (0, import_react17.useRef)(options.nodes);
2689
+ const nodesRef = (0, import_react23.useRef)(options.nodes);
1975
2690
  nodesRef.current = options.nodes;
1976
- const optionsRef = (0, import_react17.useRef)(options);
2691
+ const optionsRef = (0, import_react23.useRef)(options);
1977
2692
  optionsRef.current = options;
1978
- const controller = (0, import_react17.useMemo)(
1979
- () => (0, import_canvas17.createCanvasAnimationController)({
2693
+ const controller = (0, import_react23.useMemo)(
2694
+ () => (0, import_canvas18.createCanvasAnimationController)({
1980
2695
  getNodes: () => nodesRef.current,
1981
2696
  setNodes: (next) => {
1982
2697
  nodesRef.current = next;
@@ -2002,26 +2717,26 @@ function useCanvasAnimation(options) {
2002
2717
  }),
2003
2718
  []
2004
2719
  );
2005
- (0, import_react17.useEffect)(() => () => controller.destroy(), [controller]);
2006
- (0, import_react17.useEffect)(() => {
2720
+ (0, import_react23.useEffect)(() => () => controller.destroy(), [controller]);
2721
+ (0, import_react23.useEffect)(() => {
2007
2722
  if (options.loop !== void 0) controller.setLoop(options.loop);
2008
2723
  }, [controller, options.loop]);
2009
- (0, import_react17.useEffect)(() => {
2724
+ (0, import_react23.useEffect)(() => {
2010
2725
  if (options.playbackRate !== void 0) controller.setPlaybackRate(options.playbackRate);
2011
2726
  }, [controller, options.playbackRate]);
2012
- (0, import_react17.useEffect)(() => {
2727
+ (0, import_react23.useEffect)(() => {
2013
2728
  if (options.recording !== void 0) controller.setRecording(options.recording);
2014
2729
  }, [controller, options.recording]);
2015
- const state = (0, import_react17.useSyncExternalStore)(
2730
+ const state = (0, import_react23.useSyncExternalStore)(
2016
2731
  (listener) => controller.subscribe(listener),
2017
2732
  () => controller.getState(),
2018
2733
  () => controller.getState()
2019
2734
  );
2020
- (0, import_react17.useEffect)(() => {
2735
+ (0, import_react23.useEffect)(() => {
2021
2736
  controller.refresh();
2022
2737
  }, [controller, options.nodes]);
2023
- const displayNodes = (0, import_react17.useMemo)(() => controller.display(options.nodes), [controller, options.nodes, state.time]);
2024
- return (0, import_react17.useMemo)(
2738
+ const displayNodes = (0, import_react23.useMemo)(() => controller.display(options.nodes), [controller, options.nodes, state.time]);
2739
+ return (0, import_react23.useMemo)(
2025
2740
  () => ({
2026
2741
  ...controller,
2027
2742
  state,
@@ -2042,24 +2757,24 @@ function useCanvasAnimation(options) {
2042
2757
  }
2043
2758
 
2044
2759
  // src/canvas/AnimationTimeline.tsx
2045
- var import_react18 = require("react");
2046
- var import_canvas18 = require("@pixerate/editor/canvas");
2047
- var import_jsx_runtime7 = require("react/jsx-runtime");
2760
+ var import_react24 = require("react");
2761
+ var import_canvas19 = require("@pixerate/editor/canvas");
2762
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2048
2763
  var LOOP_LABELS = { none: "Once", loop: "Loop", "ping-pong": "Ping-pong" };
2049
2764
  var easingValue = (easing) => typeof easing === "string" ? easing : easing ? "custom" : "linear";
2050
2765
  function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8, labelOf, className = "" }) {
2051
2766
  const { state } = animation;
2052
2767
  const duration = state.duration;
2053
2768
  const rows = animation.timelineRows(nodeIds ?? void 0, labelOf ? { labelOf } : {});
2054
- const ticks = (0, import_canvas18.getTimelineTicks)(duration, width);
2769
+ const ticks = (0, import_canvas19.getTimelineTicks)(duration, width);
2055
2770
  const selectedEasing = (() => {
2056
2771
  const first = state.selection[0];
2057
2772
  if (!first) return "";
2058
2773
  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);
2059
2774
  return "";
2060
2775
  })();
2061
- const dragRef = (0, import_react18.useRef)(null);
2062
- (0, import_react18.useEffect)(() => {
2776
+ const dragRef = (0, import_react24.useRef)(null);
2777
+ (0, import_react24.useEffect)(() => {
2063
2778
  const onKey = (event) => {
2064
2779
  if (event.key === "Escape" && dragRef.current) {
2065
2780
  dragRef.current = null;
@@ -2072,8 +2787,8 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2072
2787
  const onRulerDown = (event) => {
2073
2788
  const lane = event.currentTarget;
2074
2789
  const left = lane.getBoundingClientRect().left;
2075
- animation.scrub((0, import_canvas18.xToTime)(event.clientX - left, duration, width));
2076
- const move = (e) => animation.scrub((0, import_canvas18.xToTime)(e.clientX - left, duration, width));
2790
+ animation.scrub((0, import_canvas19.xToTime)(event.clientX - left, duration, width));
2791
+ const move = (e) => animation.scrub((0, import_canvas19.xToTime)(e.clientX - left, duration, width));
2077
2792
  const up = () => {
2078
2793
  window.removeEventListener("pointermove", move);
2079
2794
  window.removeEventListener("pointerup", up);
@@ -2112,17 +2827,17 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2112
2827
  animation.deleteKeyframes();
2113
2828
  }
2114
2829
  };
2115
- const btn = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-50";
2116
- const playheadX = (0, import_canvas18.timeToX)(state.time, duration, width);
2830
+ const btn2 = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-50";
2831
+ const playheadX = (0, import_canvas19.timeToX)(state.time, duration, width);
2117
2832
  const labelWidth = 120;
2118
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-animation-timeline": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, tabIndex: 0, onKeyDown: onTimelineKey, children: [
2119
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "toolbar", "aria-label": "Animation", children: [
2120
- /* @__PURE__ */ (0, import_jsx_runtime7.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" }),
2121
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2833
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { "data-animation-timeline": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, tabIndex: 0, onKeyDown: onTimelineKey, children: [
2834
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "toolbar", "aria-label": "Animation", children: [
2835
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: btn2, "data-action": "toggle-play", "aria-label": state.playing ? "Pause" : "Play", onClick: () => animation.toggle(), children: state.playing ? "\u275A\u275A" : "\u25B6" }),
2836
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2122
2837
  "button",
2123
2838
  {
2124
2839
  type: "button",
2125
- className: `${btn} ${state.recording ? "text-red-500" : ""}`,
2840
+ className: `${btn2} ${state.recording ? "text-red-500" : ""}`,
2126
2841
  "data-action": "record",
2127
2842
  "aria-pressed": state.recording,
2128
2843
  "aria-label": "Record keyframes",
@@ -2130,13 +2845,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2130
2845
  children: "\u25CF Rec"
2131
2846
  }
2132
2847
  ),
2133
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: btn, "data-action": "add-keyframe", onClick: () => animation.addKeyframe(), children: "\u25C6 Key" }),
2134
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { "data-time": "", className: "tabular-nums text-muted-foreground", children: [
2135
- (0, import_canvas18.formatAnimationTime)(state.time),
2848
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: btn2, "data-action": "add-keyframe", onClick: () => animation.addKeyframe(), children: "\u25C6 Key" }),
2849
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { "data-time": "", className: "tabular-nums text-muted-foreground", children: [
2850
+ (0, import_canvas19.formatAnimationTime)(state.time),
2136
2851
  " / ",
2137
- (0, import_canvas18.formatAnimationTime)(duration)
2852
+ (0, import_canvas19.formatAnimationTime)(duration)
2138
2853
  ] }),
2139
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2854
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2140
2855
  "select",
2141
2856
  {
2142
2857
  "aria-label": "Easing",
@@ -2146,13 +2861,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2146
2861
  disabled: state.selection.length === 0,
2147
2862
  onChange: (e) => e.target.value && e.target.value !== "custom" && animation.setEasing(e.target.value),
2148
2863
  children: [
2149
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "", children: "Easing\u2026" }),
2150
- import_canvas18.ANIMATION_EASING_PRESETS.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: preset, children: import_canvas18.ANIMATION_EASING_LABELS[preset] }, preset)),
2151
- selectedEasing === "custom" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "custom", children: "Custom" }) : null
2864
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: "", children: "Easing\u2026" }),
2865
+ import_canvas19.ANIMATION_EASING_PRESETS.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: preset, children: import_canvas19.ANIMATION_EASING_LABELS[preset] }, preset)),
2866
+ selectedEasing === "custom" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: "custom", children: "Custom" }) : null
2152
2867
  ]
2153
2868
  }
2154
2869
  ),
2155
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2870
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2156
2871
  "select",
2157
2872
  {
2158
2873
  "aria-label": "Loop",
@@ -2160,13 +2875,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2160
2875
  className: "rounded border border-border bg-background px-1 py-0.5",
2161
2876
  value: state.loop,
2162
2877
  onChange: (e) => animation.setLoop(e.target.value),
2163
- children: Object.keys(LOOP_LABELS).map((mode) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: mode, children: LOOP_LABELS[mode] }, mode))
2878
+ children: Object.keys(LOOP_LABELS).map((mode) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: mode, children: LOOP_LABELS[mode] }, mode))
2164
2879
  }
2165
2880
  )
2166
2881
  ] }),
2167
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex", children: [
2168
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { width: labelWidth }, className: "shrink-0" }),
2169
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2882
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex", children: [
2883
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { width: labelWidth }, className: "shrink-0" }),
2884
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2170
2885
  "div",
2171
2886
  {
2172
2887
  "data-timeline-ruler": "",
@@ -2174,15 +2889,15 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2174
2889
  style: { width },
2175
2890
  onPointerDown: onRulerDown,
2176
2891
  children: [
2177
- ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "absolute top-0 -translate-x-1/2 text-[10px] text-muted-foreground", style: { left: tick.x }, children: tick.label }, tick.time)),
2178
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-playhead": "", className: "absolute top-0 h-5 w-px bg-red-500", style: { left: playheadX } })
2892
+ ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "absolute top-0 -translate-x-1/2 text-[10px] text-muted-foreground", style: { left: tick.x }, children: tick.label }, tick.time)),
2893
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { "data-playhead": "", className: "absolute top-0 h-5 w-px bg-red-500", style: { left: playheadX } })
2179
2894
  ]
2180
2895
  }
2181
2896
  )
2182
2897
  ] }),
2183
- rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.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_runtime7.jsxs)("div", { className: "flex items-center", "data-track": row.id, children: [
2184
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex shrink-0 items-center gap-1 truncate pr-2", style: { width: labelWidth }, title: `${row.nodeLabel} \xB7 ${row.label}`, children: [
2185
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2898
+ rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.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_runtime12.jsxs)("div", { className: "flex items-center", "data-track": row.id, children: [
2899
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex shrink-0 items-center gap-1 truncate pr-2", style: { width: labelWidth }, title: `${row.nodeLabel} \xB7 ${row.label}`, children: [
2900
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2186
2901
  "input",
2187
2902
  {
2188
2903
  type: "checkbox",
@@ -2191,24 +2906,24 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2191
2906
  onChange: (e) => animation.setTrackEnabled(row.nodeId, row.property, e.target.checked)
2192
2907
  }
2193
2908
  ),
2194
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "truncate", children: [
2909
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "truncate", children: [
2195
2910
  rows.filter((r) => r.nodeId === row.nodeId).length < rows.length ? `${row.nodeLabel} \xB7 ` : "",
2196
2911
  row.label
2197
2912
  ] })
2198
2913
  ] }),
2199
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { "data-lane": "", className: `relative h-5 rounded bg-muted/40 ${row.enabled ? "" : "opacity-50"}`, style: { width }, children: [
2200
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "pointer-events-none absolute top-0 h-5 w-px bg-red-500/60", style: { left: playheadX } }),
2201
- state.drag?.target != null ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { "data-snap-target": "", className: "pointer-events-none absolute top-0 h-5 w-px bg-sky-400", style: { left: (0, import_canvas18.timeToX)(state.drag.target, duration, width) } }) : null,
2202
- row.keyframes.map((k) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2914
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { "data-lane": "", className: `relative h-5 rounded bg-muted/40 ${row.enabled ? "" : "opacity-50"}`, style: { width }, children: [
2915
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "pointer-events-none absolute top-0 h-5 w-px bg-red-500/60", style: { left: playheadX } }),
2916
+ state.drag?.target != null ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { "data-snap-target": "", className: "pointer-events-none absolute top-0 h-5 w-px bg-sky-400", style: { left: (0, import_canvas19.timeToX)(state.drag.target, duration, width) } }) : null,
2917
+ row.keyframes.map((k) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2203
2918
  "button",
2204
2919
  {
2205
2920
  type: "button",
2206
2921
  "data-keyframe": k.ref.time,
2207
2922
  "aria-pressed": k.selected,
2208
- "aria-label": `${row.label} keyframe at ${(0, import_canvas18.formatAnimationTime)(k.ref.time)}`,
2209
- title: `${(0, import_canvas18.formatAnimationTime)(k.time)} \xB7 ${String(k.value)}`,
2923
+ "aria-label": `${row.label} keyframe at ${(0, import_canvas19.formatAnimationTime)(k.ref.time)}`,
2924
+ title: `${(0, import_canvas19.formatAnimationTime)(k.time)} \xB7 ${String(k.value)}`,
2210
2925
  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]"}`,
2211
- style: { left: (0, import_canvas18.timeToX)(k.time, duration, width) },
2926
+ style: { left: (0, import_canvas19.timeToX)(k.time, duration, width) },
2212
2927
  onPointerDown: onKeyDown(k.ref)
2213
2928
  },
2214
2929
  k.ref.time
@@ -2219,18 +2934,18 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2219
2934
  }
2220
2935
 
2221
2936
  // src/canvas/index.ts
2222
- var import_canvas32 = require("@pixerate/editor/canvas");
2937
+ var import_canvas33 = require("@pixerate/editor/canvas");
2223
2938
 
2224
2939
  // src/canvas/useCanvasComponents.ts
2225
- var import_react19 = require("react");
2226
- var import_canvas19 = require("@pixerate/editor/canvas");
2940
+ var import_react25 = require("react");
2941
+ var import_canvas20 = require("@pixerate/editor/canvas");
2227
2942
  function useCanvasComponents(options) {
2228
- const nodesRef = (0, import_react19.useRef)(options.nodes);
2943
+ const nodesRef = (0, import_react25.useRef)(options.nodes);
2229
2944
  nodesRef.current = options.nodes;
2230
- const optionsRef = (0, import_react19.useRef)(options);
2945
+ const optionsRef = (0, import_react25.useRef)(options);
2231
2946
  optionsRef.current = options;
2232
- const controller = (0, import_react19.useMemo)(
2233
- () => (0, import_canvas19.createCanvasComponentsController)({
2947
+ const controller = (0, import_react25.useMemo)(
2948
+ () => (0, import_canvas20.createCanvasComponentsController)({
2234
2949
  getNodes: () => nodesRef.current,
2235
2950
  setNodes: (next) => {
2236
2951
  nodesRef.current = next;
@@ -2258,18 +2973,18 @@ function useCanvasComponents(options) {
2258
2973
  }),
2259
2974
  []
2260
2975
  );
2261
- (0, import_react19.useLayoutEffect)(() => {
2976
+ (0, import_react25.useLayoutEffect)(() => {
2262
2977
  if (optionsRef.current.autoSync !== false) controller.sync();
2263
2978
  }, [options.nodes, controller]);
2264
2979
  return controller;
2265
2980
  }
2266
2981
 
2267
2982
  // src/canvas/CanvasComponentsPanel.tsx
2268
- var import_react20 = require("react");
2269
- var import_canvas20 = require("@pixerate/editor/canvas");
2270
- var import_jsx_runtime8 = require("react/jsx-runtime");
2983
+ var import_react26 = require("react");
2984
+ var import_canvas21 = require("@pixerate/editor/canvas");
2985
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2271
2986
  function InlineField({ value, label, onCommit }) {
2272
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2987
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2273
2988
  "input",
2274
2989
  {
2275
2990
  type: "text",
@@ -2300,11 +3015,11 @@ function CanvasComponentsPanel({
2300
3015
  search = true,
2301
3016
  className = ""
2302
3017
  }) {
2303
- const [query, setQuery] = (0, import_react20.useState)("");
2304
- const [propsOpen, setPropsOpen] = (0, import_react20.useState)(null);
2305
- const [menuFor, setMenuFor] = (0, import_react20.useState)(null);
2306
- const [editing, setEditing] = (0, import_react20.useState)(null);
2307
- const { components: all, sets } = (0, import_canvas20.listCanvasComponents)(nodes);
3018
+ const [query, setQuery] = (0, import_react26.useState)("");
3019
+ const [propsOpen, setPropsOpen] = (0, import_react26.useState)(null);
3020
+ const [menuFor, setMenuFor] = (0, import_react26.useState)(null);
3021
+ const [editing, setEditing] = (0, import_react26.useState)(null);
3022
+ const { components: all, sets } = (0, import_canvas21.listCanvasComponents)(nodes);
2308
3023
  const q = query.trim().toLowerCase();
2309
3024
  const match = (name) => !q || name.toLowerCase().includes(q);
2310
3025
  const lone = all.filter((c) => !c.setId && match(c.name));
@@ -2315,7 +3030,7 @@ function CanvasComponentsPanel({
2315
3030
  };
2316
3031
  const small = "shrink-0 rounded px-1 text-[10px] text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-40";
2317
3032
  const menuItem = "rounded px-2 py-0.5 text-left hover:bg-muted disabled:opacity-40";
2318
- const item = (id, name, count, extra = {}, onContextMenu) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3033
+ const item = (id, name, count, extra = {}, onContextMenu) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2319
3034
  "button",
2320
3035
  {
2321
3036
  type: "button",
@@ -2327,22 +3042,22 @@ function CanvasComponentsPanel({
2327
3042
  onClick: () => onInsert(id),
2328
3043
  onContextMenu,
2329
3044
  onDragStart: (e) => {
2330
- e.dataTransfer.setData(import_canvas20.CANVAS_COMPONENT_DRAG_TYPE, id);
3045
+ e.dataTransfer.setData(import_canvas21.CANVAS_COMPONENT_DRAG_TYPE, id);
2331
3046
  e.dataTransfer.setData("text/plain", name);
2332
3047
  e.dataTransfer.effectAllowed = "copy";
2333
3048
  },
2334
3049
  children: [
2335
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "truncate", children: [
2336
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "aria-hidden": true, className: "mr-1 text-muted-foreground", children: "\u25C7" }),
3050
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "truncate", children: [
3051
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { "aria-hidden": true, className: "mr-1 text-muted-foreground", children: "\u25C7" }),
2337
3052
  name
2338
3053
  ] }),
2339
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] text-muted-foreground", "data-instance-count": "", children: count })
3054
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-[10px] text-muted-foreground", "data-instance-count": "", children: count })
2340
3055
  ]
2341
3056
  },
2342
3057
  id
2343
3058
  );
2344
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { "data-components-panel": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
2345
- search ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3059
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { "data-components-panel": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
3060
+ search ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2346
3061
  "input",
2347
3062
  {
2348
3063
  type: "search",
@@ -2352,11 +3067,11 @@ function CanvasComponentsPanel({
2352
3067
  onInput: (e) => setQuery(e.target.value)
2353
3068
  }
2354
3069
  ) : null,
2355
- shownSets.map((set) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { "data-component-set": set.id, className: "flex flex-col", children: [
2356
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-1", children: [
3070
+ shownSets.map((set) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { "data-component-set": set.id, className: "flex flex-col", children: [
3071
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-1", children: [
2357
3072
  item(set.id, set.name, set.variants.reduce((sum, v) => sum + v.instanceCount, 0), { "data-kind": "set" }),
2358
- components ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2359
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3073
+ components ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3074
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2360
3075
  "button",
2361
3076
  {
2362
3077
  type: "button",
@@ -2368,7 +3083,7 @@ function CanvasComponentsPanel({
2368
3083
  children: "+\xA0Variant"
2369
3084
  }
2370
3085
  ),
2371
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3086
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2372
3087
  "button",
2373
3088
  {
2374
3089
  type: "button",
@@ -2383,8 +3098,8 @@ function CanvasComponentsPanel({
2383
3098
  )
2384
3099
  ] }) : null
2385
3100
  ] }),
2386
- components && propsOpen === set.id ? /* @__PURE__ */ (0, import_jsx_runtime8.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_runtime8.jsxs)("div", { "data-variant-option": option.name, className: "flex flex-col gap-0.5", children: [
2387
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3101
+ components && propsOpen === set.id ? /* @__PURE__ */ (0, import_jsx_runtime13.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_runtime13.jsxs)("div", { "data-variant-option": option.name, className: "flex flex-col gap-0.5", children: [
3102
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2388
3103
  InlineField,
2389
3104
  {
2390
3105
  value: option.name,
@@ -2392,7 +3107,7 @@ function CanvasComponentsPanel({
2392
3107
  onCommit: (next) => report(components.renameVariantProperty(option.name, next, set.id))
2393
3108
  }
2394
3109
  ),
2395
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "ml-2 flex flex-wrap gap-1", children: option.values.map((value) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3110
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ml-2 flex flex-wrap gap-1", children: option.values.map((value) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2396
3111
  InlineField,
2397
3112
  {
2398
3113
  value,
@@ -2402,8 +3117,8 @@ function CanvasComponentsPanel({
2402
3117
  value
2403
3118
  )) })
2404
3119
  ] }, option.name)) }) : null,
2405
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "ml-3 flex flex-col border-l border-border pl-1", children: set.variants.map((v) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { "data-variant-row": v.id, className: "flex flex-col", children: [
2406
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-1", children: [
3120
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "ml-3 flex flex-col border-l border-border pl-1", children: set.variants.map((v) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { "data-variant-row": v.id, className: "flex flex-col", children: [
3121
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-1", children: [
2407
3122
  item(
2408
3123
  v.id,
2409
3124
  v.name,
@@ -2414,7 +3129,7 @@ function CanvasComponentsPanel({
2414
3129
  setMenuFor(v.id);
2415
3130
  } : void 0
2416
3131
  ),
2417
- components ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3132
+ components ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2418
3133
  "button",
2419
3134
  {
2420
3135
  type: "button",
@@ -2428,8 +3143,8 @@ function CanvasComponentsPanel({
2428
3143
  }
2429
3144
  ) : null
2430
3145
  ] }),
2431
- components && menuFor === v.id ? /* @__PURE__ */ (0, import_jsx_runtime8.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: [
2432
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3146
+ components && menuFor === v.id ? /* @__PURE__ */ (0, import_jsx_runtime13.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: [
3147
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2433
3148
  "button",
2434
3149
  {
2435
3150
  type: "button",
@@ -2443,7 +3158,7 @@ function CanvasComponentsPanel({
2443
3158
  children: "Edit values\u2026"
2444
3159
  }
2445
3160
  ),
2446
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3161
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2447
3162
  "button",
2448
3163
  {
2449
3164
  type: "button",
@@ -2457,7 +3172,7 @@ function CanvasComponentsPanel({
2457
3172
  children: "Duplicate"
2458
3173
  }
2459
3174
  ),
2460
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3175
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2461
3176
  "button",
2462
3177
  {
2463
3178
  type: "button",
@@ -2474,7 +3189,7 @@ function CanvasComponentsPanel({
2474
3189
  }
2475
3190
  )
2476
3191
  ] }) : null,
2477
- components && editing === v.id ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3192
+ components && editing === v.id ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2478
3193
  "form",
2479
3194
  {
2480
3195
  "data-variant-editor": v.id,
@@ -2488,9 +3203,9 @@ function CanvasComponentsPanel({
2488
3203
  if (report(components.setVariantProperties(values, v.id))) setEditing(null);
2489
3204
  },
2490
3205
  children: [
2491
- set.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex items-center gap-2", children: [
2492
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "w-16 shrink-0 truncate text-muted-foreground", children: option.name }),
2493
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3206
+ set.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-2", children: [
3207
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "w-16 shrink-0 truncate text-muted-foreground", children: option.name }),
3208
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2494
3209
  "input",
2495
3210
  {
2496
3211
  type: "text",
@@ -2501,9 +3216,9 @@ function CanvasComponentsPanel({
2501
3216
  }
2502
3217
  )
2503
3218
  ] }, option.name)),
2504
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex gap-1", children: [
2505
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "submit", className: "rounded border border-border px-2 py-0.5 hover:bg-muted", "data-action": "save-variant", children: "Save" }),
2506
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: "rounded px-2 py-0.5 hover:bg-muted", "data-action": "cancel-variant", onClick: () => setEditing(null), children: "Cancel" })
3219
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex gap-1", children: [
3220
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "submit", className: "rounded border border-border px-2 py-0.5 hover:bg-muted", "data-action": "save-variant", children: "Save" }),
3221
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: "rounded px-2 py-0.5 hover:bg-muted", "data-action": "cancel-variant", onClick: () => setEditing(null), children: "Cancel" })
2507
3222
  ] })
2508
3223
  ]
2509
3224
  }
@@ -2511,7 +3226,7 @@ function CanvasComponentsPanel({
2511
3226
  ] }, v.id)) })
2512
3227
  ] }, set.id)),
2513
3228
  lone.map((c) => item(c.id, c.name, c.instanceCount, { "data-kind": "component" })),
2514
- all.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-muted-foreground", children: "No components yet. Select a frame and choose Create Component." }) : null
3229
+ all.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-muted-foreground", children: "No components yet. Select a frame and choose Create Component." }) : null
2515
3230
  ] });
2516
3231
  }
2517
3232
  function CanvasInstanceInspector({
@@ -2521,36 +3236,36 @@ function CanvasInstanceInspector({
2521
3236
  onError,
2522
3237
  className = ""
2523
3238
  }) {
2524
- const info = nodeId ? (0, import_canvas20.inspectCanvasInstance)(nodes, nodeId) : void 0;
3239
+ const info = nodeId ? (0, import_canvas21.inspectCanvasInstance)(nodes, nodeId) : void 0;
2525
3240
  if (!info) return null;
2526
3241
  const report = (result) => {
2527
3242
  if (result && !result.ok && result.reason) onError?.(result.reason);
2528
3243
  };
2529
3244
  const setProp = (name, value) => report(components.setInstanceProperties({ [name]: value }, [info.id]));
2530
- const allComponents = (0, import_canvas20.listCanvasComponents)(nodes).components;
3245
+ const allComponents = (0, import_canvas21.listCanvasComponents)(nodes).components;
2531
3246
  const linked = info.status === "linked";
2532
- const btn = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-40";
2533
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { "data-instance-inspector": "", "data-instance-id": info.id, className: `flex flex-col gap-2 text-xs text-foreground ${className}`, children: [
2534
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
2535
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "truncate font-medium", "data-instance-main": "", children: linked ? info.componentName : "Main component missing" }),
2536
- info.nested ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-muted-foreground", children: "Nested" }) : null
3247
+ const btn2 = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-40";
3248
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { "data-instance-inspector": "", "data-instance-id": info.id, className: `flex flex-col gap-2 text-xs text-foreground ${className}`, children: [
3249
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
3250
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "truncate font-medium", "data-instance-main": "", children: linked ? info.componentName : "Main component missing" }),
3251
+ info.nested ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-muted-foreground", children: "Nested" }) : null
2537
3252
  ] }),
2538
- info.variantOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex items-center gap-2", "data-variant-property": option.name, children: [
2539
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: option.name }),
2540
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3253
+ info.variantOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-2", "data-variant-property": option.name, children: [
3254
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: option.name }),
3255
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2541
3256
  "select",
2542
3257
  {
2543
3258
  "aria-label": `${option.name} variant`,
2544
3259
  className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
2545
3260
  value: info.variant[option.name] ?? "",
2546
3261
  onChange: (e) => setProp(option.name, e.currentTarget.value),
2547
- children: option.values.map((v) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: v, children: v }, v))
3262
+ children: option.values.map((v) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: v, children: v }, v))
2548
3263
  }
2549
3264
  )
2550
3265
  ] }, option.name)),
2551
- info.properties.map((p) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex items-center gap-2", "data-component-property": p.name, children: [
2552
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: p.name }),
2553
- p.type === "boolean" ? /* @__PURE__ */ (0, import_jsx_runtime8.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_runtime8.jsx)(
3266
+ info.properties.map((p) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-2", "data-component-property": p.name, children: [
3267
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: p.name }),
3268
+ p.type === "boolean" ? /* @__PURE__ */ (0, import_jsx_runtime13.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_runtime13.jsx)(
2554
3269
  "input",
2555
3270
  {
2556
3271
  type: "text",
@@ -2565,22 +3280,22 @@ function CanvasInstanceInspector({
2565
3280
  }
2566
3281
  },
2567
3282
  String(p.value)
2568
- ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3283
+ ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2569
3284
  "select",
2570
3285
  {
2571
3286
  "aria-label": p.name,
2572
3287
  className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
2573
3288
  value: String(p.value),
2574
3289
  onChange: (e) => setProp(p.name, e.currentTarget.value),
2575
- children: allComponents.filter((c) => !p.preferred?.length || p.preferred.includes(c.id) || c.id === p.value).map((c) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: c.id, children: c.name }, c.id))
3290
+ children: allComponents.filter((c) => !p.preferred?.length || p.preferred.includes(c.id) || c.id === p.value).map((c) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: c.id, children: c.name }, c.id))
2576
3291
  }
2577
3292
  )
2578
3293
  ] }, p.name)),
2579
- info.overrides.length ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-col gap-1", "data-instance-overrides": "", children: [
2580
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-muted-foreground", children: "Overrides" }),
2581
- info.overrides.map((o) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-wrap items-center gap-1", "data-override-layer": o.id, children: [
2582
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "mr-1 truncate", children: o.name }),
2583
- o.groups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3294
+ info.overrides.length ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-1", "data-instance-overrides": "", children: [
3295
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-muted-foreground", children: "Overrides" }),
3296
+ info.overrides.map((o) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-wrap items-center gap-1", "data-override-layer": o.id, children: [
3297
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "mr-1 truncate", children: o.name }),
3298
+ o.groups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2584
3299
  "button",
2585
3300
  {
2586
3301
  type: "button",
@@ -2597,27 +3312,27 @@ function CanvasInstanceInspector({
2597
3312
  ))
2598
3313
  ] }, o.id))
2599
3314
  ] }) : null,
2600
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
2601
- linked ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2602
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: btn, "data-action": "reset", onClick: () => report(components.resetOverrides(info.id)), children: "Reset all" }),
2603
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: btn, "data-action": "go-to-main", onClick: () => components.goToMainComponent(info.id), children: "Go to main" }),
2604
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3315
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
3316
+ linked ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3317
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: btn2, "data-action": "reset", onClick: () => report(components.resetOverrides(info.id)), children: "Reset all" }),
3318
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: btn2, "data-action": "go-to-main", onClick: () => components.goToMainComponent(info.id), children: "Go to main" }),
3319
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2605
3320
  "button",
2606
3321
  {
2607
3322
  type: "button",
2608
- className: btn,
3323
+ className: btn2,
2609
3324
  "data-action": "push",
2610
3325
  disabled: info.overrides.length === 0,
2611
3326
  onClick: () => report(components.pushOverrides(info.rootId)),
2612
3327
  children: "Push changes"
2613
3328
  }
2614
3329
  )
2615
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: btn, "data-action": "restore", onClick: () => report(components.restoreMainComponent(info.rootId)), children: "Restore main component" }),
2616
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3330
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: btn2, "data-action": "restore", onClick: () => report(components.restoreMainComponent(info.rootId)), children: "Restore main component" }),
3331
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2617
3332
  "button",
2618
3333
  {
2619
3334
  type: "button",
2620
- className: btn,
3335
+ className: btn2,
2621
3336
  "data-action": "detach",
2622
3337
  disabled: info.nested,
2623
3338
  title: info.nested ? "Detach the outer instance first" : void 0,
@@ -2630,12 +3345,12 @@ function CanvasInstanceInspector({
2630
3345
  }
2631
3346
 
2632
3347
  // src/canvas/index.ts
2633
- var import_canvas33 = require("@pixerate/editor/canvas");
3348
+ var import_canvas34 = require("@pixerate/editor/canvas");
2634
3349
 
2635
3350
  // src/canvas/MermaidFamilyScene.tsx
2636
- var import_react21 = require("react");
2637
- var import_canvas21 = require("@pixerate/editor/canvas");
2638
- var import_jsx_runtime9 = require("react/jsx-runtime");
3351
+ var import_react27 = require("react");
3352
+ var import_canvas22 = require("@pixerate/editor/canvas");
3353
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2639
3354
  function MermaidFamilyScene({
2640
3355
  scene,
2641
3356
  padding = 16,
@@ -2648,7 +3363,7 @@ function MermaidFamilyScene({
2648
3363
  style,
2649
3364
  title
2650
3365
  }) {
2651
- const uid = (0, import_react21.useId)().replace(/:/g, "");
3366
+ const uid = (0, import_react27.useId)().replace(/:/g, "");
2652
3367
  const marker = (kind) => kind ? `url(#${uid}-${kind})` : void 0;
2653
3368
  const x = scene.x - padding;
2654
3369
  const y = scene.y - padding;
@@ -2666,7 +3381,7 @@ function MermaidFamilyScene({
2666
3381
  cursor: "pointer"
2667
3382
  } : { pointerEvents: "none" };
2668
3383
  const stroke = (mark) => mark.selected ? { stroke: selectionColor, strokeWidth: Math.max(2, mark.strokeWidth ?? 0) } : { stroke: mark.stroke, strokeWidth: mark.strokeWidth };
2669
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
3384
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2670
3385
  "svg",
2671
3386
  {
2672
3387
  className: `pixerate-diagram-scene ${className}`.trim(),
@@ -2679,15 +3394,15 @@ function MermaidFamilyScene({
2679
3394
  style: { display: "block", maxWidth: "100%", height: "auto", overflow: "visible", ...style },
2680
3395
  onClick: interactive ? (event) => onSelect?.(null, event) : void 0,
2681
3396
  children: [
2682
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("defs", { children: [
2683
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("marker", { id: `${uid}-arrowclosed`, viewBox: "0 0 10 10", refX: "9", refY: "5", markerWidth: "8", markerHeight: "8", orient: "auto-start-reverse", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M0,0 L10,5 L0,10 Z", style: { fill: markerColor } }) }),
2684
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("marker", { id: `${uid}-arrow`, viewBox: "0 0 10 10", refX: "9", refY: "5", markerWidth: "8", markerHeight: "8", orient: "auto-start-reverse", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M0,0 L10,5 L0,10", style: { fill: "none", stroke: markerColor, strokeWidth: 1.5 } }) })
3397
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("defs", { children: [
3398
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("marker", { id: `${uid}-arrowclosed`, viewBox: "0 0 10 10", refX: "9", refY: "5", markerWidth: "8", markerHeight: "8", orient: "auto-start-reverse", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("path", { d: "M0,0 L10,5 L0,10 Z", style: { fill: markerColor } }) }),
3399
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("marker", { id: `${uid}-arrow`, viewBox: "0 0 10 10", refX: "9", refY: "5", markerWidth: "8", markerHeight: "8", orient: "auto-start-reverse", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("path", { d: "M0,0 L10,5 L0,10", style: { fill: "none", stroke: markerColor, strokeWidth: 1.5 } }) })
2685
3400
  ] }),
2686
3401
  scene.marks.map((mark) => {
2687
3402
  const common = { "data-role": mark.role, "data-target": mark.target, "data-selected": mark.selected ? "" : void 0, opacity: mark.opacity, ...handlers(mark) };
2688
3403
  switch (mark.kind) {
2689
3404
  case "rect":
2690
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3405
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2691
3406
  "rect",
2692
3407
  {
2693
3408
  ...common,
@@ -2702,9 +3417,9 @@ function MermaidFamilyScene({
2702
3417
  mark.key
2703
3418
  );
2704
3419
  case "circle":
2705
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("circle", { ...common, cx: mark.cx, cy: mark.cy, r: mark.r, style: { fill: mark.fill, ...stroke(mark) } }, mark.key);
3420
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("circle", { ...common, cx: mark.cx, cy: mark.cy, r: mark.r, style: { fill: mark.fill, ...stroke(mark) } }, mark.key);
2706
3421
  case "line":
2707
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3422
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2708
3423
  "line",
2709
3424
  {
2710
3425
  ...common,
@@ -2720,7 +3435,7 @@ function MermaidFamilyScene({
2720
3435
  mark.key
2721
3436
  );
2722
3437
  case "path":
2723
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3438
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2724
3439
  "path",
2725
3440
  {
2726
3441
  ...common,
@@ -2734,14 +3449,14 @@ function MermaidFamilyScene({
2734
3449
  mark.key
2735
3450
  );
2736
3451
  case "text":
2737
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3452
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2738
3453
  "text",
2739
3454
  {
2740
3455
  ...common,
2741
3456
  x: mark.x,
2742
3457
  y: mark.y,
2743
3458
  textAnchor: mark.anchor,
2744
- dominantBaseline: (0, import_canvas21.diagramTextBaseline)(mark.baseline),
3459
+ dominantBaseline: (0, import_canvas22.diagramTextBaseline)(mark.baseline),
2745
3460
  transform: mark.rotate ? `rotate(${mark.rotate} ${mark.x} ${mark.y})` : void 0,
2746
3461
  style: {
2747
3462
  fill: mark.selected ? selectionColor : mark.fill,
@@ -2762,14 +3477,14 @@ function MermaidFamilyScene({
2762
3477
  }
2763
3478
 
2764
3479
  // src/canvas/useMermaidDiagram.ts
2765
- var import_react22 = require("react");
3480
+ var import_react28 = require("react");
2766
3481
  var import_diagram = require("@pixerate/editor/diagram");
2767
- var import_canvas22 = require("@pixerate/editor/canvas");
3482
+ var import_canvas23 = require("@pixerate/editor/canvas");
2768
3483
  function useDiagramState(controller) {
2769
- return (0, import_react22.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
3484
+ return (0, import_react28.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
2770
3485
  }
2771
3486
  function useMermaidDiagram(controllerOrOptions = {}, view = {}) {
2772
- const own = (0, import_react22.useRef)(null);
3487
+ const own = (0, import_react28.useRef)(null);
2773
3488
  let controller;
2774
3489
  if (controllerOrOptions instanceof import_diagram.DiagramController) controller = controllerOrOptions;
2775
3490
  else {
@@ -2779,24 +3494,24 @@ function useMermaidDiagram(controllerOrOptions = {}, view = {}) {
2779
3494
  const layoutOptions = (controllerOrOptions instanceof import_diagram.DiagramController ? void 0 : controllerOrOptions.layoutOptions) ?? view.layoutOptions;
2780
3495
  const sceneTheme = (controllerOrOptions instanceof import_diagram.DiagramController ? void 0 : controllerOrOptions.sceneTheme) ?? view.sceneTheme;
2781
3496
  const state = useDiagramState(controller);
2782
- const canvas = (0, import_react22.useMemo)(
2783
- () => (0, import_canvas22.mermaidToCanvas)(state.document, { ...layoutOptions, editable: state.editable }),
3497
+ const canvas = (0, import_react28.useMemo)(
3498
+ () => (0, import_canvas23.mermaidToCanvas)(state.document, { ...layoutOptions, editable: state.editable }),
2784
3499
  // eslint-disable-next-line react-hooks/exhaustive-deps
2785
3500
  [state.document, state.editable]
2786
3501
  );
2787
- const scene = (0, import_react22.useMemo)(
2788
- () => state.document.tier === "editable" ? (0, import_canvas22.familySceneFromLayout)(state.document.family, state.document.graph, canvas.layout, { theme: { ...import_canvas22.CSS_VARIABLE_DIAGRAM_SCENE_THEME, ...sceneTheme }, selection: state.selection }) : null,
3502
+ const scene = (0, import_react28.useMemo)(
3503
+ () => state.document.tier === "editable" ? (0, import_canvas23.familySceneFromLayout)(state.document.family, state.document.graph, canvas.layout, { theme: { ...import_canvas23.CSS_VARIABLE_DIAGRAM_SCENE_THEME, ...sceneTheme }, selection: state.selection }) : null,
2789
3504
  // eslint-disable-next-line react-hooks/exhaustive-deps
2790
3505
  [state.document, canvas.layout, state.selection]
2791
3506
  );
2792
- const layoutRef = (0, import_react22.useRef)(canvas.layout);
3507
+ const layoutRef = (0, import_react28.useRef)(canvas.layout);
2793
3508
  layoutRef.current = canvas.layout;
2794
- const actions = (0, import_react22.useMemo)(
3509
+ const actions = (0, import_react28.useMemo)(
2795
3510
  () => ({
2796
3511
  apply: (ops, label) => controller.apply(ops, label),
2797
3512
  load: (source, options) => controller.load(source, options),
2798
3513
  moveNodes: (moved, all = moved) => {
2799
- const op = (0, import_canvas22.mermaidMovesFromCanvas)(layoutRef.current, moved, all, { stored: controller.getDocument().meta.layout ?? {} });
3514
+ const op = (0, import_canvas23.mermaidMovesFromCanvas)(layoutRef.current, moved, all, { stored: controller.getDocument().meta.layout ?? {} });
2800
3515
  return op ? controller.apply(op, "Move") : null;
2801
3516
  },
2802
3517
  connect: (source, target, label) => controller.apply({ type: "addEdge", edge: { source, target, ...label ? { label } : {} } }, "Connect"),
@@ -2815,7 +3530,7 @@ function useMermaidDiagram(controllerOrOptions = {}, view = {}) {
2815
3530
  "Rename"
2816
3531
  ),
2817
3532
  renameTarget: (target, label) => {
2818
- const op = (0, import_canvas22.diagramRenameOp)(controller.getDocument(), target, label);
3533
+ const op = (0, import_canvas23.diagramRenameOp)(controller.getDocument(), target, label);
2819
3534
  return op ? controller.apply(op, "Rename") : null;
2820
3535
  },
2821
3536
  select: (ids) => controller.select(ids),
@@ -2828,13 +3543,13 @@ function useMermaidDiagram(controllerOrOptions = {}, view = {}) {
2828
3543
  }
2829
3544
  function useMermaidStream(source, options = {}) {
2830
3545
  const { complete = false, duration = 300, ...layoutOptions } = options;
2831
- const stream = (0, import_react22.useRef)(null);
2832
- if (!stream.current) stream.current = new import_canvas22.DiagramStream(layoutOptions);
2833
- const result = (0, import_react22.useMemo)(() => stream.current.update(source, complete), [source, complete]);
2834
- const [shown, setShown] = (0, import_react22.useState)({ layout: result.layout, settled: true });
2835
- const shownRef = (0, import_react22.useRef)(shown.layout);
3546
+ const stream = (0, import_react28.useRef)(null);
3547
+ if (!stream.current) stream.current = new import_canvas23.DiagramStream(layoutOptions);
3548
+ const result = (0, import_react28.useMemo)(() => stream.current.update(source, complete), [source, complete]);
3549
+ const [shown, setShown] = (0, import_react28.useState)({ layout: result.layout, settled: true });
3550
+ const shownRef = (0, import_react28.useRef)(shown.layout);
2836
3551
  shownRef.current = shown.layout;
2837
- (0, import_react22.useEffect)(() => {
3552
+ (0, import_react28.useEffect)(() => {
2838
3553
  const target = result.layout;
2839
3554
  if (!target) return setShown({ layout: null, settled: true });
2840
3555
  const from = shownRef.current;
@@ -2844,14 +3559,14 @@ function useMermaidStream(source, options = {}) {
2844
3559
  const start = performance.now();
2845
3560
  const step = () => {
2846
3561
  const t = Math.min(1, (performance.now() - start) / duration);
2847
- setShown({ layout: (0, import_canvas22.blendDiagramLayout)(from, target, (0, import_canvas22.easeDiagramTween)(t)), settled: t >= 1 });
3562
+ setShown({ layout: (0, import_canvas23.blendDiagramLayout)(from, target, (0, import_canvas23.easeDiagramTween)(t)), settled: t >= 1 });
2848
3563
  if (t < 1) frame = requestAnimationFrame(step);
2849
3564
  };
2850
3565
  frame = requestAnimationFrame(step);
2851
3566
  return () => cancelAnimationFrame(frame);
2852
3567
  }, [result.layout, duration]);
2853
3568
  const doc = result.document.tier === "editable" ? result.document : null;
2854
- const canvas = (0, import_react22.useMemo)(() => {
3569
+ const canvas = (0, import_react28.useMemo)(() => {
2855
3570
  if (!doc || !shown.layout) return { nodes: [], edges: [] };
2856
3571
  const placed = new Set(Object.keys(shown.layout.positions));
2857
3572
  const graph = {
@@ -2860,24 +3575,24 @@ function useMermaidStream(source, options = {}) {
2860
3575
  groups: doc.graph.groups.filter((g) => placed.has(g.id)),
2861
3576
  edges: doc.graph.edges.filter((e) => placed.has(e.source) && placed.has(e.target))
2862
3577
  };
2863
- return (0, import_canvas22.mermaidToCanvas)({ ...doc, graph }, { layout: shown.layout });
3578
+ return (0, import_canvas23.mermaidToCanvas)({ ...doc, graph }, { layout: shown.layout });
2864
3579
  }, [doc, shown.layout]);
2865
3580
  return { document: doc, ...canvas, layout: shown.layout, settled: shown.settled };
2866
3581
  }
2867
3582
 
2868
3583
  // src/canvas/MermaidDiagramNode.tsx
2869
- var import_canvas23 = require("@pixerate/editor/canvas");
2870
- var import_jsx_runtime10 = require("react/jsx-runtime");
3584
+ var import_canvas24 = require("@pixerate/editor/canvas");
3585
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2871
3586
  function mermaidNodeStyle(styles = {}, selected = false) {
2872
- const paint = (0, import_canvas23.mermaidNodePaint)(styles, selected);
3587
+ const paint = (0, import_canvas24.mermaidNodePaint)(styles, selected);
2873
3588
  const { color, "stroke-width": strokeWidth, "stroke-dasharray": strokeDasharray, ...vars } = paint;
2874
3589
  return { ...vars, color, strokeWidth, strokeDasharray };
2875
3590
  }
2876
3591
  function MermaidDiagramNode({ data, width = 160, height = 56, selected, className = "", children }) {
2877
3592
  const node = data.node;
2878
3593
  if (!node) return null;
2879
- const members = (0, import_canvas23.mermaidNodeMembers)(node.data);
2880
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3594
+ const members = (0, import_canvas24.mermaidNodeMembers)(node.data);
3595
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2881
3596
  "div",
2882
3597
  {
2883
3598
  className: `pixerate-diagram-node ${className}`.trim(),
@@ -2885,14 +3600,14 @@ function MermaidDiagramNode({ data, width = 160, height = 56, selected, classNam
2885
3600
  "data-selected": selected ? "true" : void 0,
2886
3601
  style: { position: "relative", width: "100%", height: "100%", ...mermaidNodeStyle(data.resolvedStyles, selected) },
2887
3602
  children: [
2888
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "none", width: "100%", height: "100%", style: { position: "absolute", inset: 0, overflow: "visible" }, "aria-hidden": "true", children: (0, import_canvas23.mermaidShapePaths)(node.shape, width, height).map((path, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: path.d, style: { ...import_canvas23.MERMAID_SHAPE_PAINT[path.paint], vectorEffect: "non-scaling-stroke" } }, i)) }),
2889
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3603
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("svg", { viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "none", width: "100%", height: "100%", style: { position: "absolute", inset: 0, overflow: "visible" }, "aria-hidden": "true", children: (0, import_canvas24.mermaidShapePaths)(node.shape, width, height).map((path, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("path", { d: path.d, style: { ...import_canvas24.MERMAID_SHAPE_PAINT[path.paint], vectorEffect: "non-scaling-stroke" } }, i)) }),
3604
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2890
3605
  "div",
2891
3606
  {
2892
3607
  style: { position: "relative", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: members.length ? "flex-start" : "center", height: "100%", padding: "6px 10px", boxSizing: "border-box", fontSize: 13, lineHeight: 1.3, textAlign: "center", pointerEvents: "none" },
2893
3608
  children: [
2894
- (0, import_canvas23.mermaidLabelLines)(node.label).map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { fontWeight: members.length ? 600 : void 0 }, children: line }, i)),
2895
- members.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { alignSelf: "stretch", marginTop: 4, paddingTop: 4, borderTop: "1px solid var(--pixerate-diagram-node-border)", textAlign: "left", fontSize: 12 }, children: members.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { children: m }, i)) })
3609
+ (0, import_canvas24.mermaidLabelLines)(node.label).map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { style: { fontWeight: members.length ? 600 : void 0 }, children: line }, i)),
3610
+ members.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { alignSelf: "stretch", marginTop: 4, paddingTop: 4, borderTop: "1px solid var(--pixerate-diagram-node-border)", textAlign: "left", fontSize: 12 }, children: members.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { children: m }, i)) })
2896
3611
  ]
2897
3612
  }
2898
3613
  ),
@@ -2904,7 +3619,7 @@ function MermaidDiagramNode({ data, width = 160, height = 56, selected, classNam
2904
3619
  function MermaidDiagramGroup({ data, selected, className = "", children }) {
2905
3620
  const group = data.group;
2906
3621
  if (!group) return null;
2907
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3622
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2908
3623
  "div",
2909
3624
  {
2910
3625
  className: `pixerate-diagram-group ${className}`.trim(),
@@ -2919,7 +3634,7 @@ function MermaidDiagramGroup({ data, selected, className = "", children }) {
2919
3634
  color: data.resolvedStyles?.color ?? "var(--muted-foreground, #475569)"
2920
3635
  },
2921
3636
  children: [
2922
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { padding: "6px 10px", fontSize: 12, fontWeight: 600 }, children: (0, import_canvas23.mermaidLabelLines)(group.label).join(" ") }),
3637
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { padding: "6px 10px", fontSize: 12, fontWeight: 600 }, children: (0, import_canvas24.mermaidLabelLines)(group.label).join(" ") }),
2923
3638
  children
2924
3639
  ]
2925
3640
  }
@@ -2927,29 +3642,29 @@ function MermaidDiagramGroup({ data, selected, className = "", children }) {
2927
3642
  }
2928
3643
 
2929
3644
  // src/canvas/MermaidThumbnail.tsx
2930
- var import_react23 = require("react");
3645
+ var import_react29 = require("react");
2931
3646
  var import_diagram2 = require("@pixerate/editor/diagram");
2932
- var import_canvas24 = require("@pixerate/editor/canvas");
2933
- var import_jsx_runtime11 = require("react/jsx-runtime");
3647
+ var import_canvas25 = require("@pixerate/editor/canvas");
3648
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2934
3649
  function MermaidThumbnail({ source, className = "", fallback = null, ...options }) {
2935
- const doc = (0, import_react23.useMemo)(() => typeof source === "string" ? (0, import_diagram2.parseMermaid)(source) : source, [source]);
3650
+ const doc = (0, import_react29.useMemo)(() => typeof source === "string" ? (0, import_diagram2.parseMermaid)(source) : source, [source]);
2936
3651
  const key = JSON.stringify(options);
2937
- const drawn = (0, import_react23.useMemo)(
2938
- () => doc.tier === "editable" && doc.graph.nodes.length ? (0, import_canvas24.mermaidThumbnailSvg)(doc, options) : null,
3652
+ const drawn = (0, import_react29.useMemo)(
3653
+ () => doc.tier === "editable" && doc.graph.nodes.length ? (0, import_canvas25.mermaidThumbnailSvg)(doc, options) : null,
2939
3654
  // eslint-disable-next-line react-hooks/exhaustive-deps
2940
3655
  [doc, key]
2941
3656
  );
2942
- if (!drawn) return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: fallback });
2943
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: `pixerate-diagram-thumbnail ${className}`.trim(), style: { display: "inline-block", lineHeight: 0 }, dangerouslySetInnerHTML: { __html: drawn.svg } });
3657
+ if (!drawn) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: fallback });
3658
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: `pixerate-diagram-thumbnail ${className}`.trim(), style: { display: "inline-block", lineHeight: 0 }, dangerouslySetInnerHTML: { __html: drawn.svg } });
2944
3659
  }
2945
3660
 
2946
3661
  // src/canvas/useDiagramDirector.ts
2947
- var import_react24 = require("react");
3662
+ var import_react30 = require("react");
2948
3663
  var import_diagram3 = require("@pixerate/editor/diagram");
2949
3664
  function useDiagramDirector(controller, options) {
2950
- const placement = (0, import_react24.useRef)(options.placement);
3665
+ const placement = (0, import_react30.useRef)(options.placement);
2951
3666
  placement.current = options.placement;
2952
- const ref = (0, import_react24.useRef)(null);
3667
+ const ref = (0, import_react30.useRef)(null);
2953
3668
  if (!ref.current) {
2954
3669
  const presence = new import_diagram3.PresenceStore();
2955
3670
  ref.current = {
@@ -2960,17 +3675,17 @@ function useDiagramDirector(controller, options) {
2960
3675
  return ref.current;
2961
3676
  }
2962
3677
  function usePresenceState(presence) {
2963
- return (0, import_react24.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
3678
+ return (0, import_react30.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
2964
3679
  }
2965
3680
 
2966
3681
  // src/canvas/DiagramPresenceLayer.tsx
2967
- var import_jsx_runtime12 = require("react/jsx-runtime");
3682
+ var import_jsx_runtime17 = require("react/jsx-runtime");
2968
3683
  function DiagramPresenceLayer({ presence, viewport, className = "" }) {
2969
3684
  const { actors } = usePresenceState(presence);
2970
3685
  if (!actors.length) return null;
2971
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: `pixerate-diagram-presence ${className}`.trim(), "aria-hidden": "true", style: { position: "absolute", inset: 0, pointerEvents: "none", overflow: "hidden", zIndex: 50 }, children: actors.map((a) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { "data-actor": a.id, style: { position: "absolute", left: 0, top: 0, transform: `translate(${a.x * viewport.zoom + viewport.x}px, ${a.y * viewport.zoom + viewport.y}px)` }, children: [
2972
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("svg", { width: "18", height: "20", viewBox: "0 0 12 18", style: { display: "block", transform: a.pressed ? "scale(0.85)" : void 0, transformOrigin: "0 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("path", { d: "M0,0 L0,14 L4,10.5 L7,17 L9.5,16 L6.5,9.5 L11.5,9.5 Z", style: { fill: a.color, stroke: "#ffffff", strokeWidth: 1 } }) }),
2973
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: { position: "absolute", left: 14, top: 16, whiteSpace: "nowrap", borderRadius: 4, padding: "1px 6px", fontSize: 11, fontWeight: 600, color: "#ffffff", background: a.color }, children: a.message ?? a.name })
3686
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: `pixerate-diagram-presence ${className}`.trim(), "aria-hidden": "true", style: { position: "absolute", inset: 0, pointerEvents: "none", overflow: "hidden", zIndex: 50 }, children: actors.map((a) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { "data-actor": a.id, style: { position: "absolute", left: 0, top: 0, transform: `translate(${a.x * viewport.zoom + viewport.x}px, ${a.y * viewport.zoom + viewport.y}px)` }, children: [
3687
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { width: "18", height: "20", viewBox: "0 0 12 18", style: { display: "block", transform: a.pressed ? "scale(0.85)" : void 0, transformOrigin: "0 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M0,0 L0,14 L4,10.5 L7,17 L9.5,16 L6.5,9.5 L11.5,9.5 Z", style: { fill: a.color, stroke: "#ffffff", strokeWidth: 1 } }) }),
3688
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { style: { position: "absolute", left: 14, top: 16, whiteSpace: "nowrap", borderRadius: 4, padding: "1px 6px", fontSize: 11, fontWeight: 600, color: "#ffffff", background: a.color }, children: a.message ?? a.name })
2974
3689
  ] }, a.id)) });
2975
3690
  }
2976
3691
  // Annotate the CommonJS export names for ESM import in node:
@@ -2994,8 +3709,11 @@ function DiagramPresenceLayer({ presence, viewport, className = "" }) {
2994
3709
  CUBIC_BEZIER_PRESETS,
2995
3710
  CanvasComponentsPanel,
2996
3711
  CanvasDrawLayer,
3712
+ CanvasEffectsPanel,
3713
+ CanvasEffectsProvider,
2997
3714
  CanvasGuidesLayer,
2998
3715
  CanvasInstanceInspector,
3716
+ CanvasNodeEffectLayer,
2999
3717
  CanvasScenesStore,
3000
3718
  DEFAULT_ARRANGE_SHORTCUTS,
3001
3719
  DiagramPresenceLayer,
@@ -3310,6 +4028,9 @@ function DiagramPresenceLayer({ presence, viewport, className = "" }) {
3310
4028
  useCanvasComponents,
3311
4029
  useCanvasDocking,
3312
4030
  useCanvasDraw,
4031
+ useCanvasEffects,
4032
+ useCanvasEffectsProviderContext,
4033
+ useCanvasEffectsTools,
3313
4034
  useCanvasExplosion,
3314
4035
  useCanvasGraph,
3315
4036
  useCanvasLayout,