@pixerate/editor-react 0.80.0 → 0.82.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,15 @@ __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
+ validateCanvasBrushPaint: () => import_canvas34.validateCanvasBrushPaint,
390
+ withNodeAnimation: () => import_canvas33.withNodeAnimation,
391
+ withStyleSize: () => import_canvas27.withStyleSize,
392
+ wouldCreateComponentCycle: () => import_canvas34.wouldCreateComponentCycle,
393
+ wrapAnimationTime: () => import_canvas33.wrapAnimationTime,
394
+ writeNodeStyleProperty: () => import_canvas32.writeNodeStyleProperty,
395
+ xToTime: () => import_canvas33.xToTime,
396
+ xorPolygons: () => import_canvas28.xorPolygons
380
397
  });
381
398
  module.exports = __toCommonJS(canvas_exports);
382
399
 
@@ -1204,9 +1221,13 @@ function useCanvasScenes(options = {}) {
1204
1221
  );
1205
1222
  const actions = (0, import_react9.useMemo)(() => {
1206
1223
  const show = (scene) => {
1207
- if (scene) {
1208
- optionsRef.current.setViewport?.(scene.viewport, { duration: optionsRef.current.duration ?? 300 });
1209
- }
1224
+ if (!scene) return scene;
1225
+ const o = optionsRef.current;
1226
+ const provider = o.transitions?.provider;
1227
+ const element = o.transitions?.element();
1228
+ if (scene.transition && provider && element) {
1229
+ void (0, import_canvas7.transitionCanvasView)({ provider, transition: scene.transition, element, jump: () => o.setViewport?.(scene.viewport, { duration: 0 }) });
1230
+ } else o.setViewport?.(scene.viewport, { duration: o.duration ?? 300 });
1210
1231
  return scene;
1211
1232
  };
1212
1233
  return {
@@ -1624,11 +1645,11 @@ function useCanvasMeasure(options) {
1624
1645
  }
1625
1646
 
1626
1647
  // src/canvas/index.ts
1627
- var import_canvas25 = require("@pixerate/editor/canvas");
1628
1648
  var import_canvas26 = require("@pixerate/editor/canvas");
1649
+ var import_canvas27 = require("@pixerate/editor/canvas");
1629
1650
 
1630
1651
  // src/canvas/ShapeNode.tsx
1631
- var import_canvas13 = require("@pixerate/editor/canvas");
1652
+ var import_canvas14 = require("@pixerate/editor/canvas");
1632
1653
 
1633
1654
  // src/canvas/useShapeBrushstroke.tsx
1634
1655
  var import_react14 = require("react");
@@ -1682,14 +1703,708 @@ function useCanvasBrushes() {
1682
1703
  return (0, import_react14.useMemo)(() => state, [state]);
1683
1704
  }
1684
1705
 
1685
- // src/canvas/ShapeNode.tsx
1706
+ // src/canvas/CanvasEffects.tsx
1707
+ var import_react20 = require("react");
1708
+ var import_canvas13 = require("@pixerate/editor/canvas");
1709
+
1710
+ // src/effects/useEffects.ts
1711
+ var import_react15 = require("react");
1712
+ function useEffectDescription(provider, effect) {
1713
+ const [state, setState] = (0, import_react15.useState)({ key: "", description: null, error: null });
1714
+ const key = provider && effect ? `${provider.id}:${effect}` : "";
1715
+ (0, import_react15.useEffect)(() => {
1716
+ if (!provider || !effect) return;
1717
+ let live = true;
1718
+ Promise.resolve().then(() => provider.describe(effect)).then(
1719
+ (description) => live && setState({ key, description, error: null }),
1720
+ (e) => live && setState({ key, description: null, error: e instanceof Error ? e.message : String(e) })
1721
+ );
1722
+ return () => {
1723
+ live = false;
1724
+ };
1725
+ }, [provider, effect, key]);
1726
+ return state.key === key ? { description: state.description, error: state.error } : { description: null, error: null };
1727
+ }
1728
+
1729
+ // src/effects/EffectThumbnail.tsx
1730
+ var import_react16 = require("react");
1731
+ var import_effects = require("@pixerate/editor/effects");
1686
1732
  var import_jsx_runtime5 = require("react/jsx-runtime");
1733
+ function EffectThumbnail({ provider, effect, width = 96, height = 54, className = "" }) {
1734
+ const ref = (0, import_react16.useRef)(null);
1735
+ const [failed, setFailed] = (0, import_react16.useState)(effect.kind === "motion");
1736
+ (0, import_react16.useEffect)(() => {
1737
+ if (effect.kind === "motion") return;
1738
+ let live = true;
1739
+ (0, import_effects.renderEffectThumbnail)(provider, effect, { width, height }).then(
1740
+ (pixels) => {
1741
+ const ctx = live ? ref.current?.getContext("2d") : null;
1742
+ if (!ctx || typeof ImageData === "undefined") return;
1743
+ ctx.putImageData(new ImageData(new Uint8ClampedArray(pixels.data), pixels.width, pixels.height), 0, 0);
1744
+ },
1745
+ () => live && setFailed(true)
1746
+ );
1747
+ return () => {
1748
+ live = false;
1749
+ };
1750
+ }, [provider, effect, width, height]);
1751
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1752
+ "div",
1753
+ {
1754
+ className: `relative overflow-hidden rounded border border-border bg-[repeating-conic-gradient(#8884_0_25%,transparent_0_50%)] bg-[length:12px_12px] ${className}`,
1755
+ style: { aspectRatio: `${width} / ${height}` },
1756
+ "data-effect-thumbnail": effect.id,
1757
+ 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" })
1758
+ }
1759
+ );
1760
+ }
1761
+
1762
+ // src/effects/EffectsBrowser.tsx
1763
+ var import_react17 = require("react");
1764
+ var import_effects2 = require("@pixerate/editor/effects");
1765
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1766
+ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, title = "Effects", className = "" }) {
1767
+ const [all, setAll] = (0, import_react17.useState)([]);
1768
+ const [query, setQuery] = (0, import_react17.useState)("");
1769
+ const [category, setCategory] = (0, import_react17.useState)("");
1770
+ const [use, setUse] = (0, import_react17.useState)("");
1771
+ const [error, setError] = (0, import_react17.useState)(null);
1772
+ (0, import_react17.useEffect)(() => {
1773
+ if (!provider) return setAll([]);
1774
+ let live = true;
1775
+ Promise.resolve().then(() => provider.list()).then(
1776
+ (list) => live && (setAll(list), setError(null)),
1777
+ (e) => live && setError(e instanceof Error ? e.message : String(e))
1778
+ );
1779
+ return () => {
1780
+ live = false;
1781
+ };
1782
+ }, [provider]);
1783
+ const [found, setFound] = (0, import_react17.useState)([]);
1784
+ (0, import_react17.useEffect)(() => {
1785
+ if (!provider) return setFound([]);
1786
+ let live = true;
1787
+ Promise.resolve().then(() => provider.search(query, { ...category ? { category } : {}, ...use ? { use } : {} })).then((list) => live && setFound(list), () => live && setFound([]));
1788
+ return () => {
1789
+ live = false;
1790
+ };
1791
+ }, [provider, query, category, use]);
1792
+ 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)));
1793
+ const categories = (0, import_react17.useMemo)(() => [...new Set(all.filter(allowed).map((e) => e.category))], [all, uses, kinds]);
1794
+ const shown = found.filter(allowed);
1795
+ if (!provider)
1796
+ 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." });
1797
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: `flex flex-col gap-2 ${className}`, "data-effects-browser": "", "aria-label": "Effects browser", children: [
1798
+ title && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { className: "text-xs font-semibold", children: title }),
1799
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
1800
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1801
+ "input",
1802
+ {
1803
+ type: "search",
1804
+ className: "min-w-0 flex-1 rounded border border-border bg-transparent px-1.5 py-0.5 text-xs",
1805
+ placeholder: "Search effects",
1806
+ "aria-label": "Search effects",
1807
+ value: query,
1808
+ onChange: (e) => setQuery(e.currentTarget.value)
1809
+ }
1810
+ ),
1811
+ /* @__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: [
1812
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: "All categories" }),
1813
+ categories.map((c) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: c, children: c }, c))
1814
+ ] }),
1815
+ 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: [
1816
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: "Any use" }),
1817
+ uses.map((u) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: u, children: import_effects2.EFFECT_USE_LABELS[u] }, u))
1818
+ ] })
1819
+ ] }),
1820
+ error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: error }),
1821
+ /* @__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)(
1822
+ "button",
1823
+ {
1824
+ type: "button",
1825
+ className: "flex w-full flex-col gap-1 rounded border border-transparent p-1 text-left hover:border-border focus-visible:border-border",
1826
+ title: e.description ?? e.name,
1827
+ "data-effect-id": e.id,
1828
+ onClick: () => onPick(e),
1829
+ children: [
1830
+ thumbnails && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(EffectThumbnail, { provider, effect: e }),
1831
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate text-[11px] font-medium", children: e.name }),
1832
+ /* @__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 ") })
1833
+ ]
1834
+ }
1835
+ ) }, e.id)) }),
1836
+ !shown.length && !error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No effects match." })
1837
+ ] });
1838
+ }
1839
+
1840
+ // src/effects/EffectParameters.tsx
1841
+ var import_react19 = __toESM(require("react"), 1);
1842
+ var import_effects3 = require("@pixerate/editor/effects");
1843
+ var import_parameters2 = require("@pixerate/editor/parameters");
1844
+
1845
+ // src/parameters/fields.tsx
1846
+ var import_react18 = require("react");
1847
+ var import_parameters = require("@pixerate/editor/parameters");
1848
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1849
+ 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";
1850
+ 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";
1851
+ var rangeClass = "h-4 w-full min-w-0 flex-1 cursor-pointer accent-primary disabled:cursor-not-allowed disabled:opacity-50";
1852
+ function ParameterCommitInput({ value, onCommit, multiline, className, onKeyDown, ...rest }) {
1853
+ const commit = (el) => {
1854
+ if (el.value !== value) onCommit(el.value, el);
1855
+ };
1856
+ const keyDown = (e) => {
1857
+ onKeyDown?.(e);
1858
+ if (e.defaultPrevented) return;
1859
+ if (e.key === "Enter" && (!multiline || e.metaKey || e.ctrlKey)) {
1860
+ e.preventDefault();
1861
+ commit(e.currentTarget);
1862
+ }
1863
+ if (e.key === "Escape") e.currentTarget.value = value;
1864
+ };
1865
+ const props = {
1866
+ defaultValue: value,
1867
+ className: className ?? parameterInputClass,
1868
+ onBlur: (e) => commit(e.currentTarget),
1869
+ onKeyDown: keyDown,
1870
+ ...rest
1871
+ };
1872
+ 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);
1873
+ }
1874
+ var plainNumber = (field, value) => (0, import_parameters.formatParameterNumber)({ ...field, unit: void 0 }, value);
1875
+ function ParameterNumberInput({
1876
+ field,
1877
+ value,
1878
+ onChange,
1879
+ disabled,
1880
+ id,
1881
+ "aria-label": ariaLabel
1882
+ }) {
1883
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "relative min-w-0 flex-1", children: [
1884
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1885
+ ParameterCommitInput,
1886
+ {
1887
+ id,
1888
+ inputMode: "decimal",
1889
+ "aria-label": ariaLabel ?? (0, import_parameters.parameterLabel)(field),
1890
+ value: plainNumber(field, value),
1891
+ disabled: disabled || field.readOnly,
1892
+ className: `${parameterInputClass} ${field.unit ? "pr-6" : ""}`,
1893
+ onCommit: (text, input) => {
1894
+ const n = (0, import_parameters.parseParameterNumberInput)(field, text);
1895
+ if (n === null || n === value) input.value = plainNumber(field, value);
1896
+ else onChange(n);
1897
+ },
1898
+ onKeyDown: (e) => {
1899
+ if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
1900
+ e.preventDefault();
1901
+ const step = (0, import_parameters.parameterStep)(field) * (e.shiftKey ? 10 : 1);
1902
+ onChange((0, import_parameters.clampParameterNumber)(field, value + (e.key === "ArrowUp" ? step : -step)));
1903
+ }
1904
+ }
1905
+ ),
1906
+ 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 })
1907
+ ] });
1908
+ }
1909
+ function ParameterSlider(props) {
1910
+ const { field, value, onChange, onGestureStart, onGestureEnd, disabled } = props;
1911
+ const dragging = (0, import_react18.useRef)(false);
1912
+ const end = () => {
1913
+ if (!dragging.current) return;
1914
+ dragging.current = false;
1915
+ onGestureEnd?.();
1916
+ };
1917
+ if (!(0, import_parameters.isSliderField)(field)) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterNumberInput, { ...props });
1918
+ const step = (0, import_parameters.parameterStep)(field);
1919
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
1920
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1921
+ "input",
1922
+ {
1923
+ type: "range",
1924
+ "aria-label": (0, import_parameters.parameterLabel)(field),
1925
+ "aria-valuetext": (0, import_parameters.formatParameterNumber)(field, value),
1926
+ min: field.min,
1927
+ max: field.max,
1928
+ step,
1929
+ value,
1930
+ disabled: disabled || field.readOnly,
1931
+ className: rangeClass,
1932
+ onPointerDown: () => {
1933
+ if (dragging.current) return;
1934
+ dragging.current = true;
1935
+ onGestureStart?.();
1936
+ },
1937
+ onPointerUp: end,
1938
+ onPointerCancel: end,
1939
+ onBlur: end,
1940
+ onChange: (e) => onChange((0, import_parameters.clampParameterNumber)(field, Number(e.target.value)))
1941
+ }
1942
+ ),
1943
+ /* @__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` }) })
1944
+ ] });
1945
+ }
1946
+ function ParameterToggle({ field, value, onChange, disabled, id }) {
1947
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1948
+ "button",
1949
+ {
1950
+ type: "button",
1951
+ role: "switch",
1952
+ id,
1953
+ "aria-checked": value,
1954
+ "aria-label": (0, import_parameters.parameterLabel)(field),
1955
+ disabled: disabled || field.readOnly,
1956
+ onClick: () => onChange(!value),
1957
+ 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"}`,
1958
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1959
+ "span",
1960
+ {
1961
+ className: `pointer-events-none block h-4 w-4 rounded-full bg-background shadow transition-transform ${value ? "translate-x-4" : "translate-x-0.5"}`
1962
+ }
1963
+ )
1964
+ }
1965
+ );
1966
+ }
1967
+ function ParameterSelect({ field, value, onChange, disabled, id }) {
1968
+ const options = (0, import_parameters.getChoiceOptions)(field);
1969
+ const off = disabled || field.readOnly;
1970
+ if (field.control === "segmented") {
1971
+ 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)(
1972
+ "button",
1973
+ {
1974
+ type: "button",
1975
+ role: "radio",
1976
+ "aria-checked": o.value === value,
1977
+ title: o.description,
1978
+ disabled: off,
1979
+ onClick: () => onChange(o.value),
1980
+ 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"}`,
1981
+ children: (0, import_parameters.choiceOptionLabel)(o)
1982
+ },
1983
+ String(o.value)
1984
+ )) });
1985
+ }
1986
+ const index = options.findIndex((o) => o.value === value);
1987
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1988
+ "select",
1989
+ {
1990
+ id,
1991
+ "aria-label": (0, import_parameters.parameterLabel)(field),
1992
+ value: String(index),
1993
+ disabled: off,
1994
+ onChange: (e) => {
1995
+ const option = options[Number(e.target.value)];
1996
+ if (option) onChange(option.value);
1997
+ },
1998
+ className: parameterInputClass,
1999
+ 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)))
2000
+ }
2001
+ );
2002
+ }
2003
+ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd, disabled, id }) {
2004
+ const picking = (0, import_react18.useRef)(false);
2005
+ const alpha = !!field.alpha;
2006
+ const hex = (0, import_parameters.normalizeHexColor)(value, true) ?? "#000000ff";
2007
+ const rgb = hex.slice(0, 7);
2008
+ const a = hex.slice(7);
2009
+ const off = disabled || field.readOnly;
2010
+ const start = () => {
2011
+ if (picking.current) return;
2012
+ picking.current = true;
2013
+ onGestureStart?.();
2014
+ };
2015
+ const end = () => {
2016
+ if (!picking.current) return;
2017
+ picking.current = false;
2018
+ onGestureEnd?.();
2019
+ };
2020
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1.5", children: [
2021
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
2022
+ /* @__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: [
2023
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "absolute inset-0", style: { background: alpha ? hex : rgb } }),
2024
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2025
+ "input",
2026
+ {
2027
+ type: "color",
2028
+ "aria-label": (0, import_parameters.parameterLabel)(field),
2029
+ value: rgb,
2030
+ disabled: off,
2031
+ className: "absolute inset-0 h-full w-full cursor-pointer opacity-0 disabled:cursor-not-allowed",
2032
+ onChange: (e) => {
2033
+ start();
2034
+ onChange(alpha ? `${e.target.value}${a}` : e.target.value);
2035
+ },
2036
+ onBlur: end
2037
+ }
2038
+ )
2039
+ ] }),
2040
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2041
+ ParameterCommitInput,
2042
+ {
2043
+ id,
2044
+ "aria-label": `${(0, import_parameters.parameterLabel)(field)} hex`,
2045
+ value: alpha ? hex : rgb,
2046
+ disabled: off,
2047
+ spellCheck: false,
2048
+ className: `${parameterInputClass} font-mono`,
2049
+ onCommit: (text) => {
2050
+ const next = (0, import_parameters.normalizeHexColor)(text, alpha);
2051
+ if (next) onChange(next);
2052
+ }
2053
+ }
2054
+ )
2055
+ ] }),
2056
+ alpha && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2057
+ "input",
2058
+ {
2059
+ type: "range",
2060
+ "aria-label": `${(0, import_parameters.parameterLabel)(field)} opacity`,
2061
+ min: 0,
2062
+ max: 255,
2063
+ step: 1,
2064
+ value: parseInt(a, 16),
2065
+ disabled: off,
2066
+ className: rangeClass,
2067
+ onPointerDown: start,
2068
+ onPointerUp: end,
2069
+ onPointerCancel: end,
2070
+ onBlur: end,
2071
+ onChange: (e) => onChange(`${rgb}${Number(e.target.value).toString(16).padStart(2, "0")}`)
2072
+ }
2073
+ ),
2074
+ field.swatches && field.swatches.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-wrap gap-1", children: field.swatches.map((s) => {
2075
+ const swatch = (0, import_parameters.normalizeHexColor)(s, alpha);
2076
+ if (!swatch) return null;
2077
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2078
+ "button",
2079
+ {
2080
+ type: "button",
2081
+ title: swatch,
2082
+ "aria-label": `${(0, import_parameters.parameterLabel)(field)} ${swatch}`,
2083
+ "aria-pressed": swatch === (alpha ? hex : rgb),
2084
+ disabled: off,
2085
+ onClick: () => onChange(swatch),
2086
+ className: "h-5 w-5 rounded border border-input aria-pressed:ring-1 aria-pressed:ring-primary",
2087
+ style: { background: swatch }
2088
+ },
2089
+ s
2090
+ );
2091
+ }) })
2092
+ ] });
2093
+ }
2094
+ function ParameterVector({ field, value, onChange, disabled, id }) {
2095
+ const size = (0, import_parameters.vectorSize)(field);
2096
+ 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) => {
2097
+ const component = (0, import_parameters.vectorComponentField)(field, i);
2098
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex min-w-0 items-center gap-1", children: [
2099
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-3 shrink-0 text-[10px] uppercase text-muted-foreground", children: component.label }),
2100
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2101
+ ParameterNumberInput,
2102
+ {
2103
+ field: component,
2104
+ value: value[i] ?? 0,
2105
+ id: i === 0 ? id : void 0,
2106
+ "aria-label": `${(0, import_parameters.parameterLabel)(field)} ${component.label}`,
2107
+ disabled: disabled || field.readOnly,
2108
+ onChange: (n) => onChange(Array.from({ length: size }, (_2, j) => j === i ? n : value[j] ?? 0))
2109
+ }
2110
+ )
2111
+ ] }, i);
2112
+ }) });
2113
+ }
2114
+ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
2115
+ const off = disabled || field.readOnly;
2116
+ const name = (0, import_parameters.parameterLabel)(field);
2117
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1.5", children: [
2118
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
2119
+ /* @__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" }) }),
2120
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
2121
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2122
+ ParameterCommitInput,
2123
+ {
2124
+ id,
2125
+ "aria-label": `${name} URL`,
2126
+ placeholder: "Image URL",
2127
+ value: value.startsWith("data:") ? "" : value,
2128
+ disabled: off,
2129
+ onCommit: (text) => onChange(text.trim())
2130
+ }
2131
+ ),
2132
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-1", children: [
2133
+ resolveFile && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: `${parameterButtonClass} cursor-pointer ${off ? "pointer-events-none opacity-50" : ""}`, children: [
2134
+ "Choose file\u2026",
2135
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2136
+ "input",
2137
+ {
2138
+ type: "file",
2139
+ className: "sr-only",
2140
+ accept: field.accept ?? "image/*",
2141
+ disabled: off,
2142
+ "aria-label": `${name} file`,
2143
+ onChange: async (e) => {
2144
+ const file = e.target.files?.[0];
2145
+ e.target.value = "";
2146
+ if (file) onChange(await resolveFile(file));
2147
+ }
2148
+ }
2149
+ )
2150
+ ] }),
2151
+ value && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: parameterButtonClass, disabled: off, onClick: () => onChange(""), "aria-label": `Clear ${name}`, children: "Clear" })
2152
+ ] })
2153
+ ] })
2154
+ ] }),
2155
+ 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)(
2156
+ "button",
2157
+ {
2158
+ type: "button",
2159
+ title: o.label ?? o.url,
2160
+ "aria-label": o.label ?? o.url,
2161
+ "aria-pressed": o.url === value,
2162
+ disabled: off,
2163
+ onClick: () => onChange(o.url),
2164
+ className: "h-9 w-12 overflow-hidden rounded border border-input aria-pressed:ring-2 aria-pressed:ring-primary",
2165
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: o.url, alt: "", className: "h-full w-full object-cover" })
2166
+ },
2167
+ o.url
2168
+ )) })
2169
+ ] });
2170
+ }
2171
+ function ParameterText({ field, value, onChange, disabled, id }) {
2172
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2173
+ ParameterCommitInput,
2174
+ {
2175
+ id,
2176
+ "aria-label": (0, import_parameters.parameterLabel)(field),
2177
+ multiline: field.multiline,
2178
+ placeholder: field.placeholder,
2179
+ maxLength: field.maxLength,
2180
+ value,
2181
+ disabled: disabled || field.readOnly,
2182
+ onCommit: onChange
2183
+ }
2184
+ );
2185
+ }
2186
+ function ParameterFieldControl({ field, value, onChange, resolveFile, ...rest }) {
2187
+ const set = onChange;
2188
+ switch (field.type) {
2189
+ case "number":
2190
+ case "int":
2191
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterSlider, { field, value, onChange: set, ...rest });
2192
+ case "boolean":
2193
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterToggle, { field, value, onChange: set, ...rest });
2194
+ case "choice":
2195
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterSelect, { field, value, onChange: set, ...rest });
2196
+ case "color":
2197
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterColor, { field, value, onChange: set, ...rest });
2198
+ case "vector":
2199
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterVector, { field, value, onChange: set, ...rest });
2200
+ case "image":
2201
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterImage, { field, value, onChange: set, resolveFile, ...rest });
2202
+ case "text":
2203
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ParameterText, { field, value, onChange: set, ...rest });
2204
+ }
2205
+ }
2206
+
2207
+ // src/effects/EffectParameters.tsx
2208
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2209
+ function EffectParameters({ description, values, onChange, onReset, keyframed, onPreset, disabled = false, className = "" }) {
2210
+ const fields = (0, import_react19.useMemo)(() => (0, import_effects3.effectParameterFields)(description), [description]);
2211
+ const idBase = (0, import_react19.useId)();
2212
+ const gesture = import_react19.default.useRef(null);
2213
+ const count = import_react19.default.useRef(0);
2214
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: `space-y-2 ${className}`, "data-effect-parameters": description.id, children: [
2215
+ onPreset && description.presets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2216
+ "select",
2217
+ {
2218
+ className: "w-full rounded border border-border bg-transparent px-1 py-0.5 text-xs",
2219
+ "aria-label": `${description.name} presets`,
2220
+ value: "",
2221
+ disabled,
2222
+ onChange: (e) => {
2223
+ const preset = description.presets.find((p) => p.name === e.currentTarget.value);
2224
+ if (preset) onPreset({ ...description.defaults, ...preset.values });
2225
+ },
2226
+ children: [
2227
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "", children: "Presets\u2026" }),
2228
+ description.presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: p.name, children: p.name }, p.name))
2229
+ ]
2230
+ }
2231
+ ),
2232
+ fields.map((field) => {
2233
+ const label = (0, import_parameters2.parameterLabel)(field);
2234
+ const inputId = `${idBase}-${field.id}`;
2235
+ const keyed = keyframed?.has(field.id) ?? false;
2236
+ const value = (0, import_effects3.effectFieldValue)(field, values[field.id]);
2237
+ const changed = !keyed && !(0, import_parameters2.parameterValuesEqual)(value, field.default);
2238
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-1", "data-effect-control": field.id, children: [
2239
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2240
+ /* @__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 }),
2241
+ keyed && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] text-muted-foreground", children: "keyframed" }),
2242
+ 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" })
2243
+ ] }),
2244
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2245
+ ParameterFieldControl,
2246
+ {
2247
+ field,
2248
+ value,
2249
+ id: inputId,
2250
+ disabled: disabled || keyed,
2251
+ onChange: (v) => onChange(field.id, v, gesture.current),
2252
+ onGestureStart: () => gesture.current = `${idBase}:${field.id}:${++count.current}`,
2253
+ onGestureEnd: () => gesture.current = null
2254
+ }
2255
+ )
2256
+ ] }, field.id);
2257
+ }),
2258
+ !fields.length && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No controls." })
2259
+ ] });
2260
+ }
2261
+
2262
+ // src/canvas/CanvasEffects.tsx
2263
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2264
+ var ProviderContext = (0, import_react20.createContext)(null);
2265
+ function CanvasEffectsProvider({ provider, children }) {
2266
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ProviderContext.Provider, { value: provider ?? null, children });
2267
+ }
2268
+ var useCanvasEffectsProviderContext = () => (0, import_react20.useContext)(ProviderContext);
2269
+ function CanvasNodeEffectLayer({ effect, width, height, clipPath, clipTransform }) {
2270
+ const provider = useCanvasEffectsProviderContext();
2271
+ const ref = (0, import_react20.useRef)(null);
2272
+ const [failed, setFailed] = (0, import_react20.useState)(false);
2273
+ const dpr = typeof window !== "undefined" ? Math.min(2, window.devicePixelRatio || 1) : 1;
2274
+ const pw = Math.max(1, Math.round(width * dpr));
2275
+ const ph = Math.max(1, Math.round(height * dpr));
2276
+ const key = JSON.stringify(effect);
2277
+ (0, import_react20.useEffect)(() => {
2278
+ const canvas2 = ref.current;
2279
+ if (!provider || !canvas2) return;
2280
+ setFailed(false);
2281
+ const run = (0, import_canvas13.runCanvasNodeEffect)({ provider, effect, target: canvas2, onError: () => setFailed(true) });
2282
+ return () => run.stop();
2283
+ }, [provider, key, pw, ph]);
2284
+ const clipId = (0, import_react20.useMemo)(() => `pixerate-effect-clip-${Math.random().toString(36).slice(2)}`, []);
2285
+ if (!provider || failed || !(width > 0 && height > 0)) return null;
2286
+ const style = { position: "absolute", inset: 0, width: "100%", height: "100%", pointerEvents: "none", opacity: effect.opacity ?? 1 };
2287
+ 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 });
2288
+ if (effect.mode === "overlay" || !clipPath) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { style, children: canvas });
2289
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("svg", { style, viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "none", "aria-hidden": "true", children: [
2290
+ /* @__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 }) }) }),
2291
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("foreignObject", { x: 0, y: 0, width, height, clipPath: `url(#${clipId})`, children: canvas })
2292
+ ] });
2293
+ }
2294
+ function useCanvasEffects(options) {
2295
+ const opts = (0, import_react20.useRef)(options);
2296
+ opts.current = options;
2297
+ const controller = (0, import_react20.useMemo)(
2298
+ () => (0, import_canvas13.createCanvasEffectsController)({
2299
+ getNodes: () => opts.current.getNodes(),
2300
+ setNodes: (n) => opts.current.setNodes(n),
2301
+ history: { execute: (c) => opts.current.history ? opts.current.history.execute(c) : c.execute() },
2302
+ get scenes() {
2303
+ return opts.current.scenes;
2304
+ }
2305
+ }),
2306
+ []
2307
+ );
2308
+ (0, import_react20.useEffect)(() => {
2309
+ if (!options.effects) return;
2310
+ return controller.useEffects(options.effects);
2311
+ }, [controller, options.effects]);
2312
+ return controller;
2313
+ }
2314
+ function useCanvasEffectsTools(registry, controller, options = {}) {
2315
+ const { id, namespace, readOnly, subscribe } = options;
2316
+ (0, import_react20.useEffect)(() => {
2317
+ if (!registry) return;
2318
+ return registry.register((0, import_canvas13.createCanvasEffectsToolProvider)(controller, { id, namespace, readOnly, subscribe }));
2319
+ }, [registry, controller, id, namespace, readOnly, subscribe]);
2320
+ }
2321
+ var btn = "rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40";
2322
+ function Controls({ controller, nodeId, effect }) {
2323
+ const { description, error } = useEffectDescription(controller.effectsProvider, effect.effect);
2324
+ const [message, setMessage] = (0, import_react20.useState)(null);
2325
+ const run = (work) => void work.then(() => setMessage(null), (e) => setMessage(e instanceof Error ? e.message : String(e)));
2326
+ if (error) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-[11px] text-amber-500", children: error });
2327
+ if (!description) return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Loading\u2026" });
2328
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
2329
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2330
+ EffectParameters,
2331
+ {
2332
+ description,
2333
+ values: effect.values,
2334
+ onChange: (k, v) => run(controller.updateNodeEffect(nodeId, { values: { [k]: v } })),
2335
+ onReset: (k) => run(controller.updateNodeEffect(nodeId, { values: { [k]: null } })),
2336
+ onPreset: (v) => run(controller.updateNodeEffect(nodeId, { values: v }))
2337
+ }
2338
+ ),
2339
+ message && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
2340
+ ] });
2341
+ }
2342
+ function CanvasEffectsPanel({ controller, nodeId, shape, sceneId, className = "" }) {
2343
+ const [, setTick] = (0, import_react20.useState)(0);
2344
+ (0, import_react20.useEffect)(() => controller.effects.subscribe(() => setTick((n) => n + 1)), [controller]);
2345
+ const provider = controller.effectsProvider;
2346
+ const [browse, setBrowse] = (0, import_react20.useState)(null);
2347
+ const [message, setMessage] = (0, import_react20.useState)(null);
2348
+ const run = (work) => {
2349
+ setMessage(null);
2350
+ Promise.resolve().then(work).then(() => setTick((n) => n + 1), (e) => setMessage(e instanceof Error ? e.message : String(e)));
2351
+ };
2352
+ const effect = (0, import_canvas13.isShapeDescription)(shape) ? shape.effect : void 0;
2353
+ const transition = sceneId ? controller.sceneTransition(sceneId) : void 0;
2354
+ 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: [
2355
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
2356
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "flex-1 font-semibold", children: "Effects" }),
2357
+ /* @__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" }),
2358
+ /* @__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" }),
2359
+ /* @__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" })
2360
+ ] }),
2361
+ !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." }),
2362
+ 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" }))) }),
2363
+ 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" }))) }),
2364
+ 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))) }),
2365
+ 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: [
2366
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-1", children: [
2367
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "min-w-0 flex-1 truncate font-medium", children: [
2368
+ effect.name ?? effect.effect,
2369
+ " ",
2370
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "text-muted-foreground", children: [
2371
+ "\xB7 ",
2372
+ effect.mode
2373
+ ] })
2374
+ ] }),
2375
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-1", children: [
2376
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { type: "checkbox", checked: effect.playing !== false, "aria-label": "Play", onChange: (e) => {
2377
+ const playing = e.currentTarget.checked;
2378
+ run(() => controller.updateNodeEffect(nodeId, { playing }));
2379
+ } }),
2380
+ " Play"
2381
+ ] }),
2382
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: btn, "aria-label": "Remove effect", onClick: () => run(() => controller.removeNodeEffect(nodeId)), children: "\u2715" })
2383
+ ] }),
2384
+ provider && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Controls, { controller, nodeId, effect })
2385
+ ] }),
2386
+ sceneId && transition && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-1", "data-canvas-scene-transition": sceneId, children: [
2387
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
2388
+ "Into scene: ",
2389
+ transition.name ?? transition.effect,
2390
+ " (",
2391
+ transition.duration ?? 600,
2392
+ " ms)"
2393
+ ] }),
2394
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: btn, "aria-label": "Remove transition", onClick: () => run(() => controller.setSceneTransition(sceneId, null)), children: "\u2715" })
2395
+ ] }),
2396
+ message && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
2397
+ ] });
2398
+ }
2399
+
2400
+ // src/canvas/ShapeNode.tsx
2401
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1687
2402
  function ShapeNode({ id, data, width, height, selected, className = "", children }) {
1688
2403
  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)(
2404
+ const brushImage = useShapeBrushstroke((0, import_canvas14.isShapeDescription)(shape) ? shape : null, width, height);
2405
+ if (!(0, import_canvas14.isShapeDescription)(shape)) return null;
2406
+ const render = (0, import_canvas14.getShapeRenderData)(shape, { width, height }, { id: id || data?.id });
2407
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1693
2408
  "div",
1694
2409
  {
1695
2410
  className: `pixerate-shape-node ${className}`.trim(),
@@ -1697,7 +2412,7 @@ function ShapeNode({ id, data, width, height, selected, className = "", children
1697
2412
  "data-selected": selected ? "true" : void 0,
1698
2413
  style: { position: "relative", width: "100%", height: "100%" },
1699
2414
  children: [
1700
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2415
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1701
2416
  "svg",
1702
2417
  {
1703
2418
  viewBox: render.viewBox,
@@ -1707,13 +2422,13 @@ function ShapeNode({ id, data, width, height, selected, className = "", children
1707
2422
  style: { display: "block", overflow: "visible" },
1708
2423
  "aria-hidden": "true",
1709
2424
  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)) })
2425
+ (render.fillGradient || render.strokeGradient) && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("defs", { children: [
2426
+ 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)) }),
2427
+ 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)) }),
2428
+ 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)) }),
2429
+ 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
2430
  ] }),
1716
- brushImage ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("g", { transform: render.transform, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2431
+ brushImage ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("g", { transform: render.transform, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1717
2432
  "image",
1718
2433
  {
1719
2434
  className: "pixerate-shape-brushstroke",
@@ -1725,7 +2440,7 @@ function ShapeNode({ id, data, width, height, selected, className = "", children
1725
2440
  preserveAspectRatio: "none",
1726
2441
  opacity: render.opacity
1727
2442
  }
1728
- ) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2443
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1729
2444
  "path",
1730
2445
  {
1731
2446
  d: render.d,
@@ -1743,6 +2458,7 @@ function ShapeNode({ id, data, width, height, selected, className = "", children
1743
2458
  ]
1744
2459
  }
1745
2460
  ),
2461
+ shape.effect && width && height ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CanvasNodeEffectLayer, { effect: shape.effect, width, height, clipPath: render.d, clipTransform: render.transform }) : null,
1746
2462
  children
1747
2463
  ]
1748
2464
  }
@@ -1750,22 +2466,22 @@ function ShapeNode({ id, data, width, height, selected, className = "", children
1750
2466
  }
1751
2467
 
1752
2468
  // src/canvas/index.ts
1753
- var import_canvas27 = require("@pixerate/editor/canvas");
1754
2469
  var import_canvas28 = require("@pixerate/editor/canvas");
1755
2470
  var import_canvas29 = require("@pixerate/editor/canvas");
1756
2471
  var import_canvas30 = require("@pixerate/editor/canvas");
2472
+ var import_canvas31 = require("@pixerate/editor/canvas");
1757
2473
 
1758
2474
  // src/canvas/useCanvasAutoLayout.ts
1759
- var import_react15 = require("react");
1760
- var import_canvas14 = require("@pixerate/editor/canvas");
2475
+ var import_react21 = require("react");
2476
+ var import_canvas15 = require("@pixerate/editor/canvas");
1761
2477
  function useCanvasAutoLayout(options) {
1762
- const [guides, setGuides] = (0, import_react15.useState)([]);
1763
- const nodesRef = (0, import_react15.useRef)(options.nodes);
2478
+ const [guides, setGuides] = (0, import_react21.useState)([]);
2479
+ const nodesRef = (0, import_react21.useRef)(options.nodes);
1764
2480
  nodesRef.current = options.nodes;
1765
- const optionsRef = (0, import_react15.useRef)(options);
2481
+ const optionsRef = (0, import_react21.useRef)(options);
1766
2482
  optionsRef.current = options;
1767
- const controller = (0, import_react15.useMemo)(
1768
- () => (0, import_canvas14.createCanvasAutoLayoutController)({
2483
+ const controller = (0, import_react21.useMemo)(
2484
+ () => (0, import_canvas15.createCanvasAutoLayoutController)({
1769
2485
  getNodes: () => nodesRef.current,
1770
2486
  setNodes: (next) => {
1771
2487
  nodesRef.current = next;
@@ -1790,10 +2506,10 @@ function useCanvasAutoLayout(options) {
1790
2506
  }),
1791
2507
  []
1792
2508
  );
1793
- (0, import_react15.useLayoutEffect)(() => {
2509
+ (0, import_react21.useLayoutEffect)(() => {
1794
2510
  if (controller.hasPending) controller.flush();
1795
2511
  }, [options.nodes, controller]);
1796
- return (0, import_react15.useMemo)(
2512
+ return (0, import_react21.useMemo)(
1797
2513
  () => ({
1798
2514
  ...controller,
1799
2515
  /** Drop marker of the active reorder drag (flow coordinates). */
@@ -1807,47 +2523,47 @@ function useCanvasAutoLayout(options) {
1807
2523
  }
1808
2524
 
1809
2525
  // src/canvas/useCanvasTokens.ts
1810
- var import_react16 = require("react");
1811
- var import_canvas15 = require("@pixerate/editor/canvas");
2526
+ var import_react22 = require("react");
2527
+ var import_canvas16 = require("@pixerate/editor/canvas");
1812
2528
  function useCanvasTokens(options) {
1813
2529
  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 });
2530
+ const state = (0, import_react22.useSyncExternalStore)(store.subscribe, store.getState, store.getState);
2531
+ const latest = (0, import_react22.useRef)({ nodes, setNodes, modes, properties });
1816
2532
  latest.current = { nodes, setNodes, modes, properties };
1817
2533
  const opts = () => ({ modes: latest.current.modes, properties: latest.current.properties });
1818
- (0, import_react16.useEffect)(
2534
+ (0, import_react22.useEffect)(
1819
2535
  () => store.subscribe((event) => {
1820
2536
  if (event.deletedVariableIds.length === 0) return;
1821
- latest.current.setNodes((prev) => (0, import_canvas15.detachTokenBindings)(prev, event.previous, event.deletedVariableIds, opts()));
2537
+ latest.current.setNodes((prev) => (0, import_canvas16.detachTokenBindings)(prev, event.previous, event.deletedVariableIds, opts()));
1822
2538
  }),
1823
2539
  // eslint-disable-next-line react-hooks/exhaustive-deps
1824
2540
  [store]
1825
2541
  );
1826
2542
  const modesKey = JSON.stringify(modes ?? {});
1827
- (0, import_react16.useEffect)(() => {
1828
- const next = (0, import_canvas15.resolveCanvasTokens)(nodes, state, opts());
2543
+ (0, import_react22.useEffect)(() => {
2544
+ const next = (0, import_canvas16.resolveCanvasTokens)(nodes, state, opts());
1829
2545
  if (next !== nodes) setNodes(next);
1830
2546
  }, [nodes, state, modesKey, properties]);
1831
- const bind = (0, import_react16.useCallback)(
2547
+ const bind = (0, import_react22.useCallback)(
1832
2548
  (ids, propertyKey, variableId) => {
1833
- const next = (0, import_canvas15.bindCanvasToken)(latest.current.nodes, ids, propertyKey, variableId, store.getState(), opts());
2549
+ const next = (0, import_canvas16.bindCanvasToken)(latest.current.nodes, ids, propertyKey, variableId, store.getState(), opts());
1834
2550
  if (next !== latest.current.nodes) latest.current.setNodes(next);
1835
2551
  },
1836
2552
  // eslint-disable-next-line react-hooks/exhaustive-deps
1837
2553
  [store]
1838
2554
  );
1839
- const setMode = (0, import_react16.useCallback)(
2555
+ const setMode = (0, import_react22.useCallback)(
1840
2556
  (ids, collectionId, modeId) => {
1841
- const next = (0, import_canvas15.setCanvasTokenMode)(latest.current.nodes, ids, collectionId, modeId, store.getState(), opts());
2557
+ const next = (0, import_canvas16.setCanvasTokenMode)(latest.current.nodes, ids, collectionId, modeId, store.getState(), opts());
1842
2558
  if (next !== latest.current.nodes) latest.current.setNodes(next);
1843
2559
  },
1844
2560
  // eslint-disable-next-line react-hooks/exhaustive-deps
1845
2561
  [store]
1846
2562
  );
1847
- const modesOf = (0, import_react16.useCallback)(
2563
+ const modesOf = (0, import_react22.useCallback)(
1848
2564
  (nodeId) => {
1849
2565
  const node = latest.current.nodes.find((n) => n.id === nodeId);
1850
- return node ? (0, import_canvas15.getEffectiveTokenModes)(node, latest.current.nodes, store.getState(), opts()) : {};
2566
+ return node ? (0, import_canvas16.getEffectiveTokenModes)(node, latest.current.nodes, store.getState(), opts()) : {};
1851
2567
  },
1852
2568
  // eslint-disable-next-line react-hooks/exhaustive-deps
1853
2569
  [store]
@@ -1856,9 +2572,9 @@ function useCanvasTokens(options) {
1856
2572
  }
1857
2573
 
1858
2574
  // src/canvas/TokenBindingPicker.tsx
1859
- var import_canvas16 = require("@pixerate/editor/canvas");
2575
+ var import_canvas17 = require("@pixerate/editor/canvas");
1860
2576
  var import_tokens = require("@pixerate/editor/tokens");
1861
- var import_jsx_runtime6 = require("react/jsx-runtime");
2577
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1862
2578
  function TokenBindingPicker({
1863
2579
  state,
1864
2580
  nodes,
@@ -1872,18 +2588,18 @@ function TokenBindingPicker({
1872
2588
  const selected = nodes.filter((n) => selectedIds.includes(n.id));
1873
2589
  const first = selected[0];
1874
2590
  if (!first) return null;
1875
- let rows = (0, import_canvas16.getBindableTokenProperties)(first, options);
2591
+ let rows = (0, import_canvas17.getBindableTokenProperties)(first, options);
1876
2592
  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: [
2593
+ const modes = (0, import_canvas17.getEffectiveTokenModes)(first, nodes, state, options);
2594
+ 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
2595
  rows.map((property) => {
1880
- const ids = new Set(selected.map((n) => (0, import_canvas16.getNodeTokenBindings)(n)[property.key] ?? ""));
2596
+ const ids = new Set(selected.map((n) => (0, import_canvas17.getNodeTokenBindings)(n)[property.key] ?? ""));
1881
2597
  const value = ids.size === 1 ? [...ids][0] : "__mixed";
1882
- const candidates = (0, import_canvas16.getTokensForProperty)(state, property, first);
2598
+ const candidates = (0, import_canvas17.getTokensForProperty)(state, property, first);
1883
2599
  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)(
2600
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-2", "data-token-property": property.key, children: [
2601
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "w-28 shrink-0 text-muted-foreground", children: property.label }),
2602
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1887
2603
  "select",
1888
2604
  {
1889
2605
  "aria-label": `${property.label} variable`,
@@ -1892,17 +2608,17 @@ function TokenBindingPicker({
1892
2608
  onChange: (e) => {
1893
2609
  const id = e.currentTarget.value || null;
1894
2610
  try {
1895
- onChange((0, import_canvas16.bindCanvasToken)(nodes, selectedIds, property.key, id, state, options));
2611
+ onChange((0, import_canvas17.bindCanvasToken)(nodes, selectedIds, property.key, id, state, options));
1896
2612
  } catch (error) {
1897
2613
  onError?.(error);
1898
2614
  }
1899
2615
  },
1900
2616
  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" }),
2617
+ value === "__mixed" ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "__mixed", children: "Mixed" }) : null,
2618
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "", children: "None" }),
1903
2619
  candidates.map((v) => {
1904
2620
  const collection = state.collections.find((c) => c.id === v.collectionId);
1905
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("option", { value: v.id, children: [
2621
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("option", { value: v.id, children: [
1906
2622
  v.name,
1907
2623
  collection && state.collections.length > 1 ? ` (${collection.name})` : ""
1908
2624
  ] }, v.id);
@@ -1910,17 +2626,17 @@ function TokenBindingPicker({
1910
2626
  ]
1911
2627
  }
1912
2628
  ),
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)(
2629
+ /* @__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
2630
  "span",
1915
2631
  {
1916
2632
  className: "inline-block h-3 w-3 rounded border border-border align-middle",
1917
2633
  style: { background: String(resolved.value) },
1918
2634
  title: String(resolved.value)
1919
2635
  }
1920
- ) : String(resolved.value) : resolved ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { title: resolved.message, children: "\u26A0" }) : null })
2636
+ ) : String(resolved.value) : resolved ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { title: resolved.message, children: "\u26A0" }) : null })
1921
2637
  ] }, property.key);
1922
2638
  }),
1923
- state.collections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-muted-foreground", children: "No variables yet." }) : null
2639
+ state.collections.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-muted-foreground", children: "No variables yet." }) : null
1924
2640
  ] });
1925
2641
  }
1926
2642
  function TokenModeSwitcher({
@@ -1934,29 +2650,29 @@ function TokenModeSwitcher({
1934
2650
  }) {
1935
2651
  const first = nodes.find((n) => nodeIds.includes(n.id));
1936
2652
  if (!first) return null;
1937
- const own = (0, import_canvas16.getNodeTokenModes)(first);
2653
+ const own = (0, import_canvas17.getNodeTokenModes)(first);
1938
2654
  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 };
2655
+ const inherited = parent ? (0, import_canvas17.getEffectiveTokenModes)(parent, nodes, state, options) : { ...options.modes };
1940
2656
  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) => {
2657
+ 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
2658
  const auto = (0, import_tokens.getCurrentMode)(collection, inherited);
1943
2659
  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)(
2660
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-2", "data-token-collection": collection.id, children: [
2661
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "w-28 shrink-0 truncate text-muted-foreground", children: collection.name }),
2662
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1947
2663
  "select",
1948
2664
  {
1949
2665
  "aria-label": `${collection.name} mode`,
1950
2666
  className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
1951
2667
  value: explicit,
1952
- onChange: (e) => onChange((0, import_canvas16.setCanvasTokenMode)(nodes, nodeIds, collection.id, e.currentTarget.value || null, state, options)),
2668
+ onChange: (e) => onChange((0, import_canvas17.setCanvasTokenMode)(nodes, nodeIds, collection.id, e.currentTarget.value || null, state, options)),
1953
2669
  children: [
1954
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("option", { value: "", children: [
2670
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("option", { value: "", children: [
1955
2671
  "Auto (",
1956
2672
  auto.name,
1957
2673
  ")"
1958
2674
  ] }),
1959
- collection.modes.map((m) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: m.id, children: m.name }, m.id))
2675
+ collection.modes.map((m) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: m.id, children: m.name }, m.id))
1960
2676
  ]
1961
2677
  }
1962
2678
  )
@@ -1965,18 +2681,18 @@ function TokenModeSwitcher({
1965
2681
  }
1966
2682
 
1967
2683
  // src/canvas/index.ts
1968
- var import_canvas31 = require("@pixerate/editor/canvas");
2684
+ var import_canvas32 = require("@pixerate/editor/canvas");
1969
2685
 
1970
2686
  // src/canvas/useCanvasAnimation.ts
1971
- var import_react17 = require("react");
1972
- var import_canvas17 = require("@pixerate/editor/canvas");
2687
+ var import_react23 = require("react");
2688
+ var import_canvas18 = require("@pixerate/editor/canvas");
1973
2689
  function useCanvasAnimation(options) {
1974
- const nodesRef = (0, import_react17.useRef)(options.nodes);
2690
+ const nodesRef = (0, import_react23.useRef)(options.nodes);
1975
2691
  nodesRef.current = options.nodes;
1976
- const optionsRef = (0, import_react17.useRef)(options);
2692
+ const optionsRef = (0, import_react23.useRef)(options);
1977
2693
  optionsRef.current = options;
1978
- const controller = (0, import_react17.useMemo)(
1979
- () => (0, import_canvas17.createCanvasAnimationController)({
2694
+ const controller = (0, import_react23.useMemo)(
2695
+ () => (0, import_canvas18.createCanvasAnimationController)({
1980
2696
  getNodes: () => nodesRef.current,
1981
2697
  setNodes: (next) => {
1982
2698
  nodesRef.current = next;
@@ -2002,26 +2718,26 @@ function useCanvasAnimation(options) {
2002
2718
  }),
2003
2719
  []
2004
2720
  );
2005
- (0, import_react17.useEffect)(() => () => controller.destroy(), [controller]);
2006
- (0, import_react17.useEffect)(() => {
2721
+ (0, import_react23.useEffect)(() => () => controller.destroy(), [controller]);
2722
+ (0, import_react23.useEffect)(() => {
2007
2723
  if (options.loop !== void 0) controller.setLoop(options.loop);
2008
2724
  }, [controller, options.loop]);
2009
- (0, import_react17.useEffect)(() => {
2725
+ (0, import_react23.useEffect)(() => {
2010
2726
  if (options.playbackRate !== void 0) controller.setPlaybackRate(options.playbackRate);
2011
2727
  }, [controller, options.playbackRate]);
2012
- (0, import_react17.useEffect)(() => {
2728
+ (0, import_react23.useEffect)(() => {
2013
2729
  if (options.recording !== void 0) controller.setRecording(options.recording);
2014
2730
  }, [controller, options.recording]);
2015
- const state = (0, import_react17.useSyncExternalStore)(
2731
+ const state = (0, import_react23.useSyncExternalStore)(
2016
2732
  (listener) => controller.subscribe(listener),
2017
2733
  () => controller.getState(),
2018
2734
  () => controller.getState()
2019
2735
  );
2020
- (0, import_react17.useEffect)(() => {
2736
+ (0, import_react23.useEffect)(() => {
2021
2737
  controller.refresh();
2022
2738
  }, [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)(
2739
+ const displayNodes = (0, import_react23.useMemo)(() => controller.display(options.nodes), [controller, options.nodes, state.time]);
2740
+ return (0, import_react23.useMemo)(
2025
2741
  () => ({
2026
2742
  ...controller,
2027
2743
  state,
@@ -2042,24 +2758,24 @@ function useCanvasAnimation(options) {
2042
2758
  }
2043
2759
 
2044
2760
  // 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");
2761
+ var import_react24 = require("react");
2762
+ var import_canvas19 = require("@pixerate/editor/canvas");
2763
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2048
2764
  var LOOP_LABELS = { none: "Once", loop: "Loop", "ping-pong": "Ping-pong" };
2049
2765
  var easingValue = (easing) => typeof easing === "string" ? easing : easing ? "custom" : "linear";
2050
2766
  function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8, labelOf, className = "" }) {
2051
2767
  const { state } = animation;
2052
2768
  const duration = state.duration;
2053
2769
  const rows = animation.timelineRows(nodeIds ?? void 0, labelOf ? { labelOf } : {});
2054
- const ticks = (0, import_canvas18.getTimelineTicks)(duration, width);
2770
+ const ticks = (0, import_canvas19.getTimelineTicks)(duration, width);
2055
2771
  const selectedEasing = (() => {
2056
2772
  const first = state.selection[0];
2057
2773
  if (!first) return "";
2058
2774
  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
2775
  return "";
2060
2776
  })();
2061
- const dragRef = (0, import_react18.useRef)(null);
2062
- (0, import_react18.useEffect)(() => {
2777
+ const dragRef = (0, import_react24.useRef)(null);
2778
+ (0, import_react24.useEffect)(() => {
2063
2779
  const onKey = (event) => {
2064
2780
  if (event.key === "Escape" && dragRef.current) {
2065
2781
  dragRef.current = null;
@@ -2072,8 +2788,8 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2072
2788
  const onRulerDown = (event) => {
2073
2789
  const lane = event.currentTarget;
2074
2790
  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));
2791
+ animation.scrub((0, import_canvas19.xToTime)(event.clientX - left, duration, width));
2792
+ const move = (e) => animation.scrub((0, import_canvas19.xToTime)(e.clientX - left, duration, width));
2077
2793
  const up = () => {
2078
2794
  window.removeEventListener("pointermove", move);
2079
2795
  window.removeEventListener("pointerup", up);
@@ -2112,17 +2828,17 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2112
2828
  animation.deleteKeyframes();
2113
2829
  }
2114
2830
  };
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);
2831
+ const btn2 = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-50";
2832
+ const playheadX = (0, import_canvas19.timeToX)(state.time, duration, width);
2117
2833
  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)(
2834
+ 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: [
2835
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "toolbar", "aria-label": "Animation", children: [
2836
+ /* @__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" }),
2837
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2122
2838
  "button",
2123
2839
  {
2124
2840
  type: "button",
2125
- className: `${btn} ${state.recording ? "text-red-500" : ""}`,
2841
+ className: `${btn2} ${state.recording ? "text-red-500" : ""}`,
2126
2842
  "data-action": "record",
2127
2843
  "aria-pressed": state.recording,
2128
2844
  "aria-label": "Record keyframes",
@@ -2130,13 +2846,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2130
2846
  children: "\u25CF Rec"
2131
2847
  }
2132
2848
  ),
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),
2849
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: btn2, "data-action": "add-keyframe", onClick: () => animation.addKeyframe(), children: "\u25C6 Key" }),
2850
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { "data-time": "", className: "tabular-nums text-muted-foreground", children: [
2851
+ (0, import_canvas19.formatAnimationTime)(state.time),
2136
2852
  " / ",
2137
- (0, import_canvas18.formatAnimationTime)(duration)
2853
+ (0, import_canvas19.formatAnimationTime)(duration)
2138
2854
  ] }),
2139
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2855
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2140
2856
  "select",
2141
2857
  {
2142
2858
  "aria-label": "Easing",
@@ -2146,13 +2862,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2146
2862
  disabled: state.selection.length === 0,
2147
2863
  onChange: (e) => e.target.value && e.target.value !== "custom" && animation.setEasing(e.target.value),
2148
2864
  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
2865
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: "", children: "Easing\u2026" }),
2866
+ import_canvas19.ANIMATION_EASING_PRESETS.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: preset, children: import_canvas19.ANIMATION_EASING_LABELS[preset] }, preset)),
2867
+ selectedEasing === "custom" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: "custom", children: "Custom" }) : null
2152
2868
  ]
2153
2869
  }
2154
2870
  ),
2155
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2871
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2156
2872
  "select",
2157
2873
  {
2158
2874
  "aria-label": "Loop",
@@ -2160,13 +2876,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2160
2876
  className: "rounded border border-border bg-background px-1 py-0.5",
2161
2877
  value: state.loop,
2162
2878
  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))
2879
+ children: Object.keys(LOOP_LABELS).map((mode) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: mode, children: LOOP_LABELS[mode] }, mode))
2164
2880
  }
2165
2881
  )
2166
2882
  ] }),
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)(
2883
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex", children: [
2884
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { width: labelWidth }, className: "shrink-0" }),
2885
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2170
2886
  "div",
2171
2887
  {
2172
2888
  "data-timeline-ruler": "",
@@ -2174,15 +2890,15 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2174
2890
  style: { width },
2175
2891
  onPointerDown: onRulerDown,
2176
2892
  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 } })
2893
+ 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)),
2894
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { "data-playhead": "", className: "absolute top-0 h-5 w-px bg-red-500", style: { left: playheadX } })
2179
2895
  ]
2180
2896
  }
2181
2897
  )
2182
2898
  ] }),
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)(
2899
+ 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: [
2900
+ /* @__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: [
2901
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2186
2902
  "input",
2187
2903
  {
2188
2904
  type: "checkbox",
@@ -2191,24 +2907,24 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2191
2907
  onChange: (e) => animation.setTrackEnabled(row.nodeId, row.property, e.target.checked)
2192
2908
  }
2193
2909
  ),
2194
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "truncate", children: [
2910
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "truncate", children: [
2195
2911
  rows.filter((r) => r.nodeId === row.nodeId).length < rows.length ? `${row.nodeLabel} \xB7 ` : "",
2196
2912
  row.label
2197
2913
  ] })
2198
2914
  ] }),
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)(
2915
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { "data-lane": "", className: `relative h-5 rounded bg-muted/40 ${row.enabled ? "" : "opacity-50"}`, style: { width }, children: [
2916
+ /* @__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 } }),
2917
+ 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,
2918
+ row.keyframes.map((k) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2203
2919
  "button",
2204
2920
  {
2205
2921
  type: "button",
2206
2922
  "data-keyframe": k.ref.time,
2207
2923
  "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)}`,
2924
+ "aria-label": `${row.label} keyframe at ${(0, import_canvas19.formatAnimationTime)(k.ref.time)}`,
2925
+ title: `${(0, import_canvas19.formatAnimationTime)(k.time)} \xB7 ${String(k.value)}`,
2210
2926
  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) },
2927
+ style: { left: (0, import_canvas19.timeToX)(k.time, duration, width) },
2212
2928
  onPointerDown: onKeyDown(k.ref)
2213
2929
  },
2214
2930
  k.ref.time
@@ -2219,18 +2935,18 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
2219
2935
  }
2220
2936
 
2221
2937
  // src/canvas/index.ts
2222
- var import_canvas32 = require("@pixerate/editor/canvas");
2938
+ var import_canvas33 = require("@pixerate/editor/canvas");
2223
2939
 
2224
2940
  // src/canvas/useCanvasComponents.ts
2225
- var import_react19 = require("react");
2226
- var import_canvas19 = require("@pixerate/editor/canvas");
2941
+ var import_react25 = require("react");
2942
+ var import_canvas20 = require("@pixerate/editor/canvas");
2227
2943
  function useCanvasComponents(options) {
2228
- const nodesRef = (0, import_react19.useRef)(options.nodes);
2944
+ const nodesRef = (0, import_react25.useRef)(options.nodes);
2229
2945
  nodesRef.current = options.nodes;
2230
- const optionsRef = (0, import_react19.useRef)(options);
2946
+ const optionsRef = (0, import_react25.useRef)(options);
2231
2947
  optionsRef.current = options;
2232
- const controller = (0, import_react19.useMemo)(
2233
- () => (0, import_canvas19.createCanvasComponentsController)({
2948
+ const controller = (0, import_react25.useMemo)(
2949
+ () => (0, import_canvas20.createCanvasComponentsController)({
2234
2950
  getNodes: () => nodesRef.current,
2235
2951
  setNodes: (next) => {
2236
2952
  nodesRef.current = next;
@@ -2258,18 +2974,18 @@ function useCanvasComponents(options) {
2258
2974
  }),
2259
2975
  []
2260
2976
  );
2261
- (0, import_react19.useLayoutEffect)(() => {
2977
+ (0, import_react25.useLayoutEffect)(() => {
2262
2978
  if (optionsRef.current.autoSync !== false) controller.sync();
2263
2979
  }, [options.nodes, controller]);
2264
2980
  return controller;
2265
2981
  }
2266
2982
 
2267
2983
  // 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");
2984
+ var import_react26 = require("react");
2985
+ var import_canvas21 = require("@pixerate/editor/canvas");
2986
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2271
2987
  function InlineField({ value, label, onCommit }) {
2272
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2988
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2273
2989
  "input",
2274
2990
  {
2275
2991
  type: "text",
@@ -2300,11 +3016,11 @@ function CanvasComponentsPanel({
2300
3016
  search = true,
2301
3017
  className = ""
2302
3018
  }) {
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);
3019
+ const [query, setQuery] = (0, import_react26.useState)("");
3020
+ const [propsOpen, setPropsOpen] = (0, import_react26.useState)(null);
3021
+ const [menuFor, setMenuFor] = (0, import_react26.useState)(null);
3022
+ const [editing, setEditing] = (0, import_react26.useState)(null);
3023
+ const { components: all, sets } = (0, import_canvas21.listCanvasComponents)(nodes);
2308
3024
  const q = query.trim().toLowerCase();
2309
3025
  const match = (name) => !q || name.toLowerCase().includes(q);
2310
3026
  const lone = all.filter((c) => !c.setId && match(c.name));
@@ -2315,7 +3031,7 @@ function CanvasComponentsPanel({
2315
3031
  };
2316
3032
  const small = "shrink-0 rounded px-1 text-[10px] text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-40";
2317
3033
  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)(
3034
+ const item = (id, name, count, extra = {}, onContextMenu) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2319
3035
  "button",
2320
3036
  {
2321
3037
  type: "button",
@@ -2327,22 +3043,22 @@ function CanvasComponentsPanel({
2327
3043
  onClick: () => onInsert(id),
2328
3044
  onContextMenu,
2329
3045
  onDragStart: (e) => {
2330
- e.dataTransfer.setData(import_canvas20.CANVAS_COMPONENT_DRAG_TYPE, id);
3046
+ e.dataTransfer.setData(import_canvas21.CANVAS_COMPONENT_DRAG_TYPE, id);
2331
3047
  e.dataTransfer.setData("text/plain", name);
2332
3048
  e.dataTransfer.effectAllowed = "copy";
2333
3049
  },
2334
3050
  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" }),
3051
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "truncate", children: [
3052
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { "aria-hidden": true, className: "mr-1 text-muted-foreground", children: "\u25C7" }),
2337
3053
  name
2338
3054
  ] }),
2339
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] text-muted-foreground", "data-instance-count": "", children: count })
3055
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-[10px] text-muted-foreground", "data-instance-count": "", children: count })
2340
3056
  ]
2341
3057
  },
2342
3058
  id
2343
3059
  );
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)(
3060
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { "data-components-panel": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
3061
+ search ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2346
3062
  "input",
2347
3063
  {
2348
3064
  type: "search",
@@ -2352,11 +3068,11 @@ function CanvasComponentsPanel({
2352
3068
  onInput: (e) => setQuery(e.target.value)
2353
3069
  }
2354
3070
  ) : 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: [
3071
+ shownSets.map((set) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { "data-component-set": set.id, className: "flex flex-col", children: [
3072
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-1", children: [
2357
3073
  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)(
3074
+ components ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3075
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2360
3076
  "button",
2361
3077
  {
2362
3078
  type: "button",
@@ -2368,7 +3084,7 @@ function CanvasComponentsPanel({
2368
3084
  children: "+\xA0Variant"
2369
3085
  }
2370
3086
  ),
2371
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3087
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2372
3088
  "button",
2373
3089
  {
2374
3090
  type: "button",
@@ -2383,8 +3099,8 @@ function CanvasComponentsPanel({
2383
3099
  )
2384
3100
  ] }) : null
2385
3101
  ] }),
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)(
3102
+ 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: [
3103
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2388
3104
  InlineField,
2389
3105
  {
2390
3106
  value: option.name,
@@ -2392,7 +3108,7 @@ function CanvasComponentsPanel({
2392
3108
  onCommit: (next) => report(components.renameVariantProperty(option.name, next, set.id))
2393
3109
  }
2394
3110
  ),
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)(
3111
+ /* @__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
3112
  InlineField,
2397
3113
  {
2398
3114
  value,
@@ -2402,8 +3118,8 @@ function CanvasComponentsPanel({
2402
3118
  value
2403
3119
  )) })
2404
3120
  ] }, 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: [
3121
+ /* @__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: [
3122
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-1", children: [
2407
3123
  item(
2408
3124
  v.id,
2409
3125
  v.name,
@@ -2414,7 +3130,7 @@ function CanvasComponentsPanel({
2414
3130
  setMenuFor(v.id);
2415
3131
  } : void 0
2416
3132
  ),
2417
- components ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3133
+ components ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2418
3134
  "button",
2419
3135
  {
2420
3136
  type: "button",
@@ -2428,8 +3144,8 @@ function CanvasComponentsPanel({
2428
3144
  }
2429
3145
  ) : null
2430
3146
  ] }),
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)(
3147
+ 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: [
3148
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2433
3149
  "button",
2434
3150
  {
2435
3151
  type: "button",
@@ -2443,7 +3159,7 @@ function CanvasComponentsPanel({
2443
3159
  children: "Edit values\u2026"
2444
3160
  }
2445
3161
  ),
2446
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3162
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2447
3163
  "button",
2448
3164
  {
2449
3165
  type: "button",
@@ -2457,7 +3173,7 @@ function CanvasComponentsPanel({
2457
3173
  children: "Duplicate"
2458
3174
  }
2459
3175
  ),
2460
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3176
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2461
3177
  "button",
2462
3178
  {
2463
3179
  type: "button",
@@ -2474,7 +3190,7 @@ function CanvasComponentsPanel({
2474
3190
  }
2475
3191
  )
2476
3192
  ] }) : null,
2477
- components && editing === v.id ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
3193
+ components && editing === v.id ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2478
3194
  "form",
2479
3195
  {
2480
3196
  "data-variant-editor": v.id,
@@ -2488,9 +3204,9 @@ function CanvasComponentsPanel({
2488
3204
  if (report(components.setVariantProperties(values, v.id))) setEditing(null);
2489
3205
  },
2490
3206
  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)(
3207
+ set.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-2", children: [
3208
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "w-16 shrink-0 truncate text-muted-foreground", children: option.name }),
3209
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2494
3210
  "input",
2495
3211
  {
2496
3212
  type: "text",
@@ -2501,9 +3217,9 @@ function CanvasComponentsPanel({
2501
3217
  }
2502
3218
  )
2503
3219
  ] }, 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" })
3220
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex gap-1", children: [
3221
+ /* @__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" }),
3222
+ /* @__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
3223
  ] })
2508
3224
  ]
2509
3225
  }
@@ -2511,7 +3227,7 @@ function CanvasComponentsPanel({
2511
3227
  ] }, v.id)) })
2512
3228
  ] }, set.id)),
2513
3229
  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
3230
+ 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
3231
  ] });
2516
3232
  }
2517
3233
  function CanvasInstanceInspector({
@@ -2521,36 +3237,36 @@ function CanvasInstanceInspector({
2521
3237
  onError,
2522
3238
  className = ""
2523
3239
  }) {
2524
- const info = nodeId ? (0, import_canvas20.inspectCanvasInstance)(nodes, nodeId) : void 0;
3240
+ const info = nodeId ? (0, import_canvas21.inspectCanvasInstance)(nodes, nodeId) : void 0;
2525
3241
  if (!info) return null;
2526
3242
  const report = (result) => {
2527
3243
  if (result && !result.ok && result.reason) onError?.(result.reason);
2528
3244
  };
2529
3245
  const setProp = (name, value) => report(components.setInstanceProperties({ [name]: value }, [info.id]));
2530
- const allComponents = (0, import_canvas20.listCanvasComponents)(nodes).components;
3246
+ const allComponents = (0, import_canvas21.listCanvasComponents)(nodes).components;
2531
3247
  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
3248
+ const btn2 = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-40";
3249
+ 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: [
3250
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
3251
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "truncate font-medium", "data-instance-main": "", children: linked ? info.componentName : "Main component missing" }),
3252
+ info.nested ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-muted-foreground", children: "Nested" }) : null
2537
3253
  ] }),
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)(
3254
+ info.variantOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-2", "data-variant-property": option.name, children: [
3255
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: option.name }),
3256
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2541
3257
  "select",
2542
3258
  {
2543
3259
  "aria-label": `${option.name} variant`,
2544
3260
  className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
2545
3261
  value: info.variant[option.name] ?? "",
2546
3262
  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))
3263
+ children: option.values.map((v) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: v, children: v }, v))
2548
3264
  }
2549
3265
  )
2550
3266
  ] }, 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)(
3267
+ info.properties.map((p) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-2", "data-component-property": p.name, children: [
3268
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: p.name }),
3269
+ 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
3270
  "input",
2555
3271
  {
2556
3272
  type: "text",
@@ -2565,22 +3281,22 @@ function CanvasInstanceInspector({
2565
3281
  }
2566
3282
  },
2567
3283
  String(p.value)
2568
- ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3284
+ ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2569
3285
  "select",
2570
3286
  {
2571
3287
  "aria-label": p.name,
2572
3288
  className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
2573
3289
  value: String(p.value),
2574
3290
  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))
3291
+ 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
3292
  }
2577
3293
  )
2578
3294
  ] }, 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)(
3295
+ info.overrides.length ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-1", "data-instance-overrides": "", children: [
3296
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-muted-foreground", children: "Overrides" }),
3297
+ 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: [
3298
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "mr-1 truncate", children: o.name }),
3299
+ o.groups.map((g) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2584
3300
  "button",
2585
3301
  {
2586
3302
  type: "button",
@@ -2597,27 +3313,27 @@ function CanvasInstanceInspector({
2597
3313
  ))
2598
3314
  ] }, o.id))
2599
3315
  ] }) : 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)(
3316
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
3317
+ linked ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3318
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: btn2, "data-action": "reset", onClick: () => report(components.resetOverrides(info.id)), children: "Reset all" }),
3319
+ /* @__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" }),
3320
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2605
3321
  "button",
2606
3322
  {
2607
3323
  type: "button",
2608
- className: btn,
3324
+ className: btn2,
2609
3325
  "data-action": "push",
2610
3326
  disabled: info.overrides.length === 0,
2611
3327
  onClick: () => report(components.pushOverrides(info.rootId)),
2612
3328
  children: "Push changes"
2613
3329
  }
2614
3330
  )
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)(
3331
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: btn2, "data-action": "restore", onClick: () => report(components.restoreMainComponent(info.rootId)), children: "Restore main component" }),
3332
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2617
3333
  "button",
2618
3334
  {
2619
3335
  type: "button",
2620
- className: btn,
3336
+ className: btn2,
2621
3337
  "data-action": "detach",
2622
3338
  disabled: info.nested,
2623
3339
  title: info.nested ? "Detach the outer instance first" : void 0,
@@ -2630,12 +3346,12 @@ function CanvasInstanceInspector({
2630
3346
  }
2631
3347
 
2632
3348
  // src/canvas/index.ts
2633
- var import_canvas33 = require("@pixerate/editor/canvas");
3349
+ var import_canvas34 = require("@pixerate/editor/canvas");
2634
3350
 
2635
3351
  // 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");
3352
+ var import_react27 = require("react");
3353
+ var import_canvas22 = require("@pixerate/editor/canvas");
3354
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2639
3355
  function MermaidFamilyScene({
2640
3356
  scene,
2641
3357
  padding = 16,
@@ -2648,7 +3364,7 @@ function MermaidFamilyScene({
2648
3364
  style,
2649
3365
  title
2650
3366
  }) {
2651
- const uid = (0, import_react21.useId)().replace(/:/g, "");
3367
+ const uid = (0, import_react27.useId)().replace(/:/g, "");
2652
3368
  const marker = (kind) => kind ? `url(#${uid}-${kind})` : void 0;
2653
3369
  const x = scene.x - padding;
2654
3370
  const y = scene.y - padding;
@@ -2666,7 +3382,7 @@ function MermaidFamilyScene({
2666
3382
  cursor: "pointer"
2667
3383
  } : { pointerEvents: "none" };
2668
3384
  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)(
3385
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2670
3386
  "svg",
2671
3387
  {
2672
3388
  className: `pixerate-diagram-scene ${className}`.trim(),
@@ -2679,15 +3395,15 @@ function MermaidFamilyScene({
2679
3395
  style: { display: "block", maxWidth: "100%", height: "auto", overflow: "visible", ...style },
2680
3396
  onClick: interactive ? (event) => onSelect?.(null, event) : void 0,
2681
3397
  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 } }) })
3398
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("defs", { children: [
3399
+ /* @__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 } }) }),
3400
+ /* @__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
3401
  ] }),
2686
3402
  scene.marks.map((mark) => {
2687
3403
  const common = { "data-role": mark.role, "data-target": mark.target, "data-selected": mark.selected ? "" : void 0, opacity: mark.opacity, ...handlers(mark) };
2688
3404
  switch (mark.kind) {
2689
3405
  case "rect":
2690
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3406
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2691
3407
  "rect",
2692
3408
  {
2693
3409
  ...common,
@@ -2702,9 +3418,9 @@ function MermaidFamilyScene({
2702
3418
  mark.key
2703
3419
  );
2704
3420
  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);
3421
+ 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
3422
  case "line":
2707
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3423
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2708
3424
  "line",
2709
3425
  {
2710
3426
  ...common,
@@ -2720,7 +3436,7 @@ function MermaidFamilyScene({
2720
3436
  mark.key
2721
3437
  );
2722
3438
  case "path":
2723
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3439
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2724
3440
  "path",
2725
3441
  {
2726
3442
  ...common,
@@ -2734,14 +3450,14 @@ function MermaidFamilyScene({
2734
3450
  mark.key
2735
3451
  );
2736
3452
  case "text":
2737
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3453
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2738
3454
  "text",
2739
3455
  {
2740
3456
  ...common,
2741
3457
  x: mark.x,
2742
3458
  y: mark.y,
2743
3459
  textAnchor: mark.anchor,
2744
- dominantBaseline: (0, import_canvas21.diagramTextBaseline)(mark.baseline),
3460
+ dominantBaseline: (0, import_canvas22.diagramTextBaseline)(mark.baseline),
2745
3461
  transform: mark.rotate ? `rotate(${mark.rotate} ${mark.x} ${mark.y})` : void 0,
2746
3462
  style: {
2747
3463
  fill: mark.selected ? selectionColor : mark.fill,
@@ -2762,14 +3478,14 @@ function MermaidFamilyScene({
2762
3478
  }
2763
3479
 
2764
3480
  // src/canvas/useMermaidDiagram.ts
2765
- var import_react22 = require("react");
3481
+ var import_react28 = require("react");
2766
3482
  var import_diagram = require("@pixerate/editor/diagram");
2767
- var import_canvas22 = require("@pixerate/editor/canvas");
3483
+ var import_canvas23 = require("@pixerate/editor/canvas");
2768
3484
  function useDiagramState(controller) {
2769
- return (0, import_react22.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
3485
+ return (0, import_react28.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
2770
3486
  }
2771
3487
  function useMermaidDiagram(controllerOrOptions = {}, view = {}) {
2772
- const own = (0, import_react22.useRef)(null);
3488
+ const own = (0, import_react28.useRef)(null);
2773
3489
  let controller;
2774
3490
  if (controllerOrOptions instanceof import_diagram.DiagramController) controller = controllerOrOptions;
2775
3491
  else {
@@ -2779,24 +3495,24 @@ function useMermaidDiagram(controllerOrOptions = {}, view = {}) {
2779
3495
  const layoutOptions = (controllerOrOptions instanceof import_diagram.DiagramController ? void 0 : controllerOrOptions.layoutOptions) ?? view.layoutOptions;
2780
3496
  const sceneTheme = (controllerOrOptions instanceof import_diagram.DiagramController ? void 0 : controllerOrOptions.sceneTheme) ?? view.sceneTheme;
2781
3497
  const state = useDiagramState(controller);
2782
- const canvas = (0, import_react22.useMemo)(
2783
- () => (0, import_canvas22.mermaidToCanvas)(state.document, { ...layoutOptions, editable: state.editable }),
3498
+ const canvas = (0, import_react28.useMemo)(
3499
+ () => (0, import_canvas23.mermaidToCanvas)(state.document, { ...layoutOptions, editable: state.editable }),
2784
3500
  // eslint-disable-next-line react-hooks/exhaustive-deps
2785
3501
  [state.document, state.editable]
2786
3502
  );
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,
3503
+ const scene = (0, import_react28.useMemo)(
3504
+ () => 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
3505
  // eslint-disable-next-line react-hooks/exhaustive-deps
2790
3506
  [state.document, canvas.layout, state.selection]
2791
3507
  );
2792
- const layoutRef = (0, import_react22.useRef)(canvas.layout);
3508
+ const layoutRef = (0, import_react28.useRef)(canvas.layout);
2793
3509
  layoutRef.current = canvas.layout;
2794
- const actions = (0, import_react22.useMemo)(
3510
+ const actions = (0, import_react28.useMemo)(
2795
3511
  () => ({
2796
3512
  apply: (ops, label) => controller.apply(ops, label),
2797
3513
  load: (source, options) => controller.load(source, options),
2798
3514
  moveNodes: (moved, all = moved) => {
2799
- const op = (0, import_canvas22.mermaidMovesFromCanvas)(layoutRef.current, moved, all, { stored: controller.getDocument().meta.layout ?? {} });
3515
+ const op = (0, import_canvas23.mermaidMovesFromCanvas)(layoutRef.current, moved, all, { stored: controller.getDocument().meta.layout ?? {} });
2800
3516
  return op ? controller.apply(op, "Move") : null;
2801
3517
  },
2802
3518
  connect: (source, target, label) => controller.apply({ type: "addEdge", edge: { source, target, ...label ? { label } : {} } }, "Connect"),
@@ -2815,7 +3531,7 @@ function useMermaidDiagram(controllerOrOptions = {}, view = {}) {
2815
3531
  "Rename"
2816
3532
  ),
2817
3533
  renameTarget: (target, label) => {
2818
- const op = (0, import_canvas22.diagramRenameOp)(controller.getDocument(), target, label);
3534
+ const op = (0, import_canvas23.diagramRenameOp)(controller.getDocument(), target, label);
2819
3535
  return op ? controller.apply(op, "Rename") : null;
2820
3536
  },
2821
3537
  select: (ids) => controller.select(ids),
@@ -2828,13 +3544,13 @@ function useMermaidDiagram(controllerOrOptions = {}, view = {}) {
2828
3544
  }
2829
3545
  function useMermaidStream(source, options = {}) {
2830
3546
  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);
3547
+ const stream = (0, import_react28.useRef)(null);
3548
+ if (!stream.current) stream.current = new import_canvas23.DiagramStream(layoutOptions);
3549
+ const result = (0, import_react28.useMemo)(() => stream.current.update(source, complete), [source, complete]);
3550
+ const [shown, setShown] = (0, import_react28.useState)({ layout: result.layout, settled: true });
3551
+ const shownRef = (0, import_react28.useRef)(shown.layout);
2836
3552
  shownRef.current = shown.layout;
2837
- (0, import_react22.useEffect)(() => {
3553
+ (0, import_react28.useEffect)(() => {
2838
3554
  const target = result.layout;
2839
3555
  if (!target) return setShown({ layout: null, settled: true });
2840
3556
  const from = shownRef.current;
@@ -2844,14 +3560,14 @@ function useMermaidStream(source, options = {}) {
2844
3560
  const start = performance.now();
2845
3561
  const step = () => {
2846
3562
  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 });
3563
+ setShown({ layout: (0, import_canvas23.blendDiagramLayout)(from, target, (0, import_canvas23.easeDiagramTween)(t)), settled: t >= 1 });
2848
3564
  if (t < 1) frame = requestAnimationFrame(step);
2849
3565
  };
2850
3566
  frame = requestAnimationFrame(step);
2851
3567
  return () => cancelAnimationFrame(frame);
2852
3568
  }, [result.layout, duration]);
2853
3569
  const doc = result.document.tier === "editable" ? result.document : null;
2854
- const canvas = (0, import_react22.useMemo)(() => {
3570
+ const canvas = (0, import_react28.useMemo)(() => {
2855
3571
  if (!doc || !shown.layout) return { nodes: [], edges: [] };
2856
3572
  const placed = new Set(Object.keys(shown.layout.positions));
2857
3573
  const graph = {
@@ -2860,24 +3576,24 @@ function useMermaidStream(source, options = {}) {
2860
3576
  groups: doc.graph.groups.filter((g) => placed.has(g.id)),
2861
3577
  edges: doc.graph.edges.filter((e) => placed.has(e.source) && placed.has(e.target))
2862
3578
  };
2863
- return (0, import_canvas22.mermaidToCanvas)({ ...doc, graph }, { layout: shown.layout });
3579
+ return (0, import_canvas23.mermaidToCanvas)({ ...doc, graph }, { layout: shown.layout });
2864
3580
  }, [doc, shown.layout]);
2865
3581
  return { document: doc, ...canvas, layout: shown.layout, settled: shown.settled };
2866
3582
  }
2867
3583
 
2868
3584
  // src/canvas/MermaidDiagramNode.tsx
2869
- var import_canvas23 = require("@pixerate/editor/canvas");
2870
- var import_jsx_runtime10 = require("react/jsx-runtime");
3585
+ var import_canvas24 = require("@pixerate/editor/canvas");
3586
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2871
3587
  function mermaidNodeStyle(styles = {}, selected = false) {
2872
- const paint = (0, import_canvas23.mermaidNodePaint)(styles, selected);
3588
+ const paint = (0, import_canvas24.mermaidNodePaint)(styles, selected);
2873
3589
  const { color, "stroke-width": strokeWidth, "stroke-dasharray": strokeDasharray, ...vars } = paint;
2874
3590
  return { ...vars, color, strokeWidth, strokeDasharray };
2875
3591
  }
2876
3592
  function MermaidDiagramNode({ data, width = 160, height = 56, selected, className = "", children }) {
2877
3593
  const node = data.node;
2878
3594
  if (!node) return null;
2879
- const members = (0, import_canvas23.mermaidNodeMembers)(node.data);
2880
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3595
+ const members = (0, import_canvas24.mermaidNodeMembers)(node.data);
3596
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2881
3597
  "div",
2882
3598
  {
2883
3599
  className: `pixerate-diagram-node ${className}`.trim(),
@@ -2885,14 +3601,14 @@ function MermaidDiagramNode({ data, width = 160, height = 56, selected, classNam
2885
3601
  "data-selected": selected ? "true" : void 0,
2886
3602
  style: { position: "relative", width: "100%", height: "100%", ...mermaidNodeStyle(data.resolvedStyles, selected) },
2887
3603
  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)(
3604
+ /* @__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)) }),
3605
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2890
3606
  "div",
2891
3607
  {
2892
3608
  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
3609
  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)) })
3610
+ (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)),
3611
+ 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
3612
  ]
2897
3613
  }
2898
3614
  ),
@@ -2904,7 +3620,7 @@ function MermaidDiagramNode({ data, width = 160, height = 56, selected, classNam
2904
3620
  function MermaidDiagramGroup({ data, selected, className = "", children }) {
2905
3621
  const group = data.group;
2906
3622
  if (!group) return null;
2907
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3623
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2908
3624
  "div",
2909
3625
  {
2910
3626
  className: `pixerate-diagram-group ${className}`.trim(),
@@ -2919,7 +3635,7 @@ function MermaidDiagramGroup({ data, selected, className = "", children }) {
2919
3635
  color: data.resolvedStyles?.color ?? "var(--muted-foreground, #475569)"
2920
3636
  },
2921
3637
  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(" ") }),
3638
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { style: { padding: "6px 10px", fontSize: 12, fontWeight: 600 }, children: (0, import_canvas24.mermaidLabelLines)(group.label).join(" ") }),
2923
3639
  children
2924
3640
  ]
2925
3641
  }
@@ -2927,29 +3643,29 @@ function MermaidDiagramGroup({ data, selected, className = "", children }) {
2927
3643
  }
2928
3644
 
2929
3645
  // src/canvas/MermaidThumbnail.tsx
2930
- var import_react23 = require("react");
3646
+ var import_react29 = require("react");
2931
3647
  var import_diagram2 = require("@pixerate/editor/diagram");
2932
- var import_canvas24 = require("@pixerate/editor/canvas");
2933
- var import_jsx_runtime11 = require("react/jsx-runtime");
3648
+ var import_canvas25 = require("@pixerate/editor/canvas");
3649
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2934
3650
  function MermaidThumbnail({ source, className = "", fallback = null, ...options }) {
2935
- const doc = (0, import_react23.useMemo)(() => typeof source === "string" ? (0, import_diagram2.parseMermaid)(source) : source, [source]);
3651
+ const doc = (0, import_react29.useMemo)(() => typeof source === "string" ? (0, import_diagram2.parseMermaid)(source) : source, [source]);
2936
3652
  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,
3653
+ const drawn = (0, import_react29.useMemo)(
3654
+ () => doc.tier === "editable" && doc.graph.nodes.length ? (0, import_canvas25.mermaidThumbnailSvg)(doc, options) : null,
2939
3655
  // eslint-disable-next-line react-hooks/exhaustive-deps
2940
3656
  [doc, key]
2941
3657
  );
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 } });
3658
+ if (!drawn) return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, { children: fallback });
3659
+ 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
3660
  }
2945
3661
 
2946
3662
  // src/canvas/useDiagramDirector.ts
2947
- var import_react24 = require("react");
3663
+ var import_react30 = require("react");
2948
3664
  var import_diagram3 = require("@pixerate/editor/diagram");
2949
3665
  function useDiagramDirector(controller, options) {
2950
- const placement = (0, import_react24.useRef)(options.placement);
3666
+ const placement = (0, import_react30.useRef)(options.placement);
2951
3667
  placement.current = options.placement;
2952
- const ref = (0, import_react24.useRef)(null);
3668
+ const ref = (0, import_react30.useRef)(null);
2953
3669
  if (!ref.current) {
2954
3670
  const presence = new import_diagram3.PresenceStore();
2955
3671
  ref.current = {
@@ -2960,17 +3676,17 @@ function useDiagramDirector(controller, options) {
2960
3676
  return ref.current;
2961
3677
  }
2962
3678
  function usePresenceState(presence) {
2963
- return (0, import_react24.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
3679
+ return (0, import_react30.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
2964
3680
  }
2965
3681
 
2966
3682
  // src/canvas/DiagramPresenceLayer.tsx
2967
- var import_jsx_runtime12 = require("react/jsx-runtime");
3683
+ var import_jsx_runtime17 = require("react/jsx-runtime");
2968
3684
  function DiagramPresenceLayer({ presence, viewport, className = "" }) {
2969
3685
  const { actors } = usePresenceState(presence);
2970
3686
  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 })
3687
+ 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: [
3688
+ /* @__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 } }) }),
3689
+ /* @__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
3690
  ] }, a.id)) });
2975
3691
  }
2976
3692
  // Annotate the CommonJS export names for ESM import in node:
@@ -2994,8 +3710,11 @@ function DiagramPresenceLayer({ presence, viewport, className = "" }) {
2994
3710
  CUBIC_BEZIER_PRESETS,
2995
3711
  CanvasComponentsPanel,
2996
3712
  CanvasDrawLayer,
3713
+ CanvasEffectsPanel,
3714
+ CanvasEffectsProvider,
2997
3715
  CanvasGuidesLayer,
2998
3716
  CanvasInstanceInspector,
3717
+ CanvasNodeEffectLayer,
2999
3718
  CanvasScenesStore,
3000
3719
  DEFAULT_ARRANGE_SHORTCUTS,
3001
3720
  DiagramPresenceLayer,
@@ -3310,6 +4029,9 @@ function DiagramPresenceLayer({ presence, viewport, className = "" }) {
3310
4029
  useCanvasComponents,
3311
4030
  useCanvasDocking,
3312
4031
  useCanvasDraw,
4032
+ useCanvasEffects,
4033
+ useCanvasEffectsProviderContext,
4034
+ useCanvasEffectsTools,
3313
4035
  useCanvasExplosion,
3314
4036
  useCanvasGraph,
3315
4037
  useCanvasLayout,
@@ -3325,6 +4047,7 @@ function DiagramPresenceLayer({ presence, viewport, className = "" }) {
3325
4047
  useShapeBrushstroke,
3326
4048
  useStreamingCanvas,
3327
4049
  validateCanvasBrush,
4050
+ validateCanvasBrushPaint,
3328
4051
  withNodeAnimation,
3329
4052
  withStyleSize,
3330
4053
  wouldCreateComponentCycle,