@pixerate/editor-react 0.19.1 → 0.21.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.
- package/README.md +1 -0
- package/dist/canvas/index.cjs +706 -492
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +56 -3
- package/dist/canvas/index.d.ts +56 -3
- package/dist/canvas/index.js +364 -148
- package/dist/canvas/index.js.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/parameters/index.cjs +692 -0
- package/dist/parameters/index.cjs.map +1 -0
- package/dist/parameters/index.d.cts +121 -0
- package/dist/parameters/index.d.ts +121 -0
- package/dist/parameters/index.js +667 -0
- package/dist/parameters/index.js.map +1 -0
- package/package.json +13 -4
package/dist/canvas/index.js
CHANGED
|
@@ -976,8 +976,210 @@ function CanvasGuidesLayer({
|
|
|
976
976
|
);
|
|
977
977
|
}
|
|
978
978
|
|
|
979
|
+
// src/canvas/useCanvasDraw.ts
|
|
980
|
+
import { useEffect as useEffect4, useMemo as useMemo3, useRef as useRef7, useState as useState3 } from "react";
|
|
981
|
+
import {
|
|
982
|
+
createCanvasDrawController
|
|
983
|
+
} from "@pixerate/editor/canvas";
|
|
984
|
+
function useCanvasDraw(options) {
|
|
985
|
+
const nodesRef = useRef7(options.nodes);
|
|
986
|
+
nodesRef.current = options.nodes;
|
|
987
|
+
const optionsRef = useRef7(options);
|
|
988
|
+
optionsRef.current = options;
|
|
989
|
+
const [tool, setToolState] = useState3(options.initialTool ?? "select");
|
|
990
|
+
const [activeStroke, setActiveStroke] = useState3(null);
|
|
991
|
+
const controller = useMemo3(
|
|
992
|
+
() => createCanvasDrawController({
|
|
993
|
+
getNodes: () => nodesRef.current,
|
|
994
|
+
setNodes: (next) => {
|
|
995
|
+
nodesRef.current = next;
|
|
996
|
+
optionsRef.current.setNodes(next);
|
|
997
|
+
},
|
|
998
|
+
get history() {
|
|
999
|
+
return optionsRef.current.history;
|
|
1000
|
+
},
|
|
1001
|
+
tool: options.initialTool ?? "select",
|
|
1002
|
+
style: options.initialStyle,
|
|
1003
|
+
drawOptions: options.drawOptions,
|
|
1004
|
+
generateNodeId: options.generateNodeId,
|
|
1005
|
+
onToolChange: setToolState,
|
|
1006
|
+
onStyleChange: (s) => setStyleState(s),
|
|
1007
|
+
onActiveStrokeChange: setActiveStroke,
|
|
1008
|
+
onStrokeComplete: (n) => optionsRef.current.onStrokeComplete?.(n),
|
|
1009
|
+
onNodesErase: (erased) => optionsRef.current.onNodesErase?.(erased)
|
|
1010
|
+
}),
|
|
1011
|
+
[]
|
|
1012
|
+
);
|
|
1013
|
+
const [style, setStyleState] = useState3(controller.style);
|
|
1014
|
+
useEffect4(() => {
|
|
1015
|
+
if (options.initialTool && options.initialTool !== controller.tool) {
|
|
1016
|
+
controller.setTool(options.initialTool);
|
|
1017
|
+
}
|
|
1018
|
+
}, [options.initialTool, controller]);
|
|
1019
|
+
return useMemo3(
|
|
1020
|
+
() => ({
|
|
1021
|
+
tool,
|
|
1022
|
+
style,
|
|
1023
|
+
activeStroke,
|
|
1024
|
+
isDrawing: activeStroke !== null,
|
|
1025
|
+
setTool: controller.setTool,
|
|
1026
|
+
setStyle: controller.setStyle,
|
|
1027
|
+
startStroke: controller.startStroke,
|
|
1028
|
+
continueStroke: controller.continueStroke,
|
|
1029
|
+
endStroke: controller.endStroke,
|
|
1030
|
+
cancelStroke: controller.cancelStroke,
|
|
1031
|
+
eraseAt: controller.eraseAt
|
|
1032
|
+
}),
|
|
1033
|
+
[tool, style, activeStroke, controller]
|
|
1034
|
+
);
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// src/canvas/CanvasDrawLayer.tsx
|
|
1038
|
+
import { useCallback as useCallback7, useEffect as useEffect5, useRef as useRef8, useState as useState4 } from "react";
|
|
1039
|
+
import {
|
|
1040
|
+
strokePointsToPathData
|
|
1041
|
+
} from "@pixerate/editor/canvas";
|
|
1042
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1043
|
+
var DEFAULT_VIEWPORT2 = { x: 0, y: 0, zoom: 1 };
|
|
1044
|
+
function CanvasDrawLayer({
|
|
1045
|
+
draw,
|
|
1046
|
+
viewport = DEFAULT_VIEWPORT2,
|
|
1047
|
+
className = "",
|
|
1048
|
+
style,
|
|
1049
|
+
cursor,
|
|
1050
|
+
eraserRadius = 12
|
|
1051
|
+
}) {
|
|
1052
|
+
const svgRef = useRef8(null);
|
|
1053
|
+
const [spaceHeld, setSpaceHeld] = useState4(false);
|
|
1054
|
+
const [eraserPos, setEraserPos] = useState4(null);
|
|
1055
|
+
useEffect5(() => {
|
|
1056
|
+
function onKeyDown(e) {
|
|
1057
|
+
if (e.code === "Space" && !e.repeat) {
|
|
1058
|
+
const tag = e.target?.tagName;
|
|
1059
|
+
if (tag === "INPUT" || tag === "TEXTAREA" || e.target?.isContentEditable) {
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
setSpaceHeld(true);
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
function onKeyUp(e) {
|
|
1066
|
+
if (e.code === "Space") {
|
|
1067
|
+
setSpaceHeld(false);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
window.addEventListener("keydown", onKeyDown);
|
|
1071
|
+
window.addEventListener("keyup", onKeyUp);
|
|
1072
|
+
return () => {
|
|
1073
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
1074
|
+
window.removeEventListener("keyup", onKeyUp);
|
|
1075
|
+
};
|
|
1076
|
+
}, []);
|
|
1077
|
+
const clientToFlow = useCallback7(
|
|
1078
|
+
(clientX, clientY) => {
|
|
1079
|
+
if (!svgRef.current) return [0, 0];
|
|
1080
|
+
const rect = svgRef.current.getBoundingClientRect();
|
|
1081
|
+
const screenX = clientX - rect.left;
|
|
1082
|
+
const screenY = clientY - rect.top;
|
|
1083
|
+
const flowX = (screenX - viewport.x) / viewport.zoom;
|
|
1084
|
+
const flowY = (screenY - viewport.y) / viewport.zoom;
|
|
1085
|
+
return [flowX, flowY];
|
|
1086
|
+
},
|
|
1087
|
+
[viewport.x, viewport.y, viewport.zoom]
|
|
1088
|
+
);
|
|
1089
|
+
const isDrawingMode = draw.tool !== "select";
|
|
1090
|
+
const interactive = isDrawingMode && !spaceHeld;
|
|
1091
|
+
const handlePointerDown = (e) => {
|
|
1092
|
+
if (!interactive || e.button !== 0) return;
|
|
1093
|
+
e.preventDefault();
|
|
1094
|
+
e.stopPropagation();
|
|
1095
|
+
e.target.setPointerCapture?.(e.pointerId);
|
|
1096
|
+
const flowPt = clientToFlow(e.clientX, e.clientY);
|
|
1097
|
+
draw.startStroke(flowPt);
|
|
1098
|
+
if (draw.tool === "eraser") {
|
|
1099
|
+
setEraserPos([e.clientX, e.clientY]);
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
const handlePointerMove = (e) => {
|
|
1103
|
+
if (draw.tool === "eraser" && !spaceHeld) {
|
|
1104
|
+
setEraserPos([e.clientX, e.clientY]);
|
|
1105
|
+
}
|
|
1106
|
+
if (!interactive) return;
|
|
1107
|
+
if (e.buttons === 1) {
|
|
1108
|
+
e.preventDefault();
|
|
1109
|
+
e.stopPropagation();
|
|
1110
|
+
const flowPt = clientToFlow(e.clientX, e.clientY);
|
|
1111
|
+
draw.continueStroke(flowPt);
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
1114
|
+
const handlePointerUp = (e) => {
|
|
1115
|
+
if (!interactive || e.button !== 0) return;
|
|
1116
|
+
e.preventDefault();
|
|
1117
|
+
e.stopPropagation();
|
|
1118
|
+
try {
|
|
1119
|
+
e.target.releasePointerCapture?.(e.pointerId);
|
|
1120
|
+
} catch {
|
|
1121
|
+
}
|
|
1122
|
+
draw.endStroke();
|
|
1123
|
+
};
|
|
1124
|
+
const handlePointerLeave = () => {
|
|
1125
|
+
setEraserPos(null);
|
|
1126
|
+
};
|
|
1127
|
+
const resolvedCursor = cursor ? cursor : spaceHeld ? "grab" : draw.tool === "eraser" ? "crosshair" : draw.tool === "pen" || draw.tool === "highlighter" ? "crosshair" : "default";
|
|
1128
|
+
const strokePath = draw.activeStroke ? strokePointsToPathData(draw.activeStroke.points) : null;
|
|
1129
|
+
return /* @__PURE__ */ jsxs3(
|
|
1130
|
+
"svg",
|
|
1131
|
+
{
|
|
1132
|
+
ref: svgRef,
|
|
1133
|
+
className: `pixerate-canvas-draw-layer ${className}`,
|
|
1134
|
+
style: {
|
|
1135
|
+
position: "absolute",
|
|
1136
|
+
inset: 0,
|
|
1137
|
+
width: "100%",
|
|
1138
|
+
height: "100%",
|
|
1139
|
+
pointerEvents: interactive ? "all" : "none",
|
|
1140
|
+
cursor: interactive ? resolvedCursor : void 0,
|
|
1141
|
+
overflow: "visible",
|
|
1142
|
+
zIndex: 20,
|
|
1143
|
+
touchAction: "none",
|
|
1144
|
+
...style
|
|
1145
|
+
},
|
|
1146
|
+
onPointerDown: handlePointerDown,
|
|
1147
|
+
onPointerMove: handlePointerMove,
|
|
1148
|
+
onPointerUp: handlePointerUp,
|
|
1149
|
+
onPointerLeave: handlePointerLeave,
|
|
1150
|
+
children: [
|
|
1151
|
+
/* @__PURE__ */ jsx3("g", { transform: `translate(${viewport.x}, ${viewport.y}) scale(${viewport.zoom})`, children: draw.activeStroke && strokePath && /* @__PURE__ */ jsx3(
|
|
1152
|
+
"path",
|
|
1153
|
+
{
|
|
1154
|
+
d: strokePath,
|
|
1155
|
+
fill: "none",
|
|
1156
|
+
stroke: draw.activeStroke.style.color,
|
|
1157
|
+
strokeWidth: draw.activeStroke.style.width,
|
|
1158
|
+
opacity: draw.activeStroke.style.opacity,
|
|
1159
|
+
strokeLinecap: draw.activeStroke.style.cap ?? "round",
|
|
1160
|
+
strokeLinejoin: draw.activeStroke.style.join ?? "round"
|
|
1161
|
+
}
|
|
1162
|
+
) }),
|
|
1163
|
+
draw.tool === "eraser" && eraserPos && svgRef.current && /* @__PURE__ */ jsx3(
|
|
1164
|
+
"circle",
|
|
1165
|
+
{
|
|
1166
|
+
cx: eraserPos[0] - svgRef.current.getBoundingClientRect().left,
|
|
1167
|
+
cy: eraserPos[1] - svgRef.current.getBoundingClientRect().top,
|
|
1168
|
+
r: eraserRadius,
|
|
1169
|
+
fill: "rgba(239, 68, 68, 0.15)",
|
|
1170
|
+
stroke: "rgba(239, 68, 68, 0.8)",
|
|
1171
|
+
strokeWidth: 1.5,
|
|
1172
|
+
strokeDasharray: "3 3",
|
|
1173
|
+
pointerEvents: "none"
|
|
1174
|
+
}
|
|
1175
|
+
)
|
|
1176
|
+
]
|
|
1177
|
+
}
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
979
1181
|
// src/canvas/useCanvasMeasure.ts
|
|
980
|
-
import { useCallback as
|
|
1182
|
+
import { useCallback as useCallback8, useEffect as useEffect6, useMemo as useMemo4, useRef as useRef9, useState as useState5 } from "react";
|
|
981
1183
|
import {
|
|
982
1184
|
isMeasureModifierHeld,
|
|
983
1185
|
measureSelection
|
|
@@ -985,11 +1187,11 @@ import {
|
|
|
985
1187
|
var EMPTY = { guides: [], target: null, selection: null };
|
|
986
1188
|
function useCanvasMeasure(options) {
|
|
987
1189
|
const { nodes, enabled = true, requireModifier = true, targetElement, rectOptions } = options;
|
|
988
|
-
const [hoveredId, setHoveredId] =
|
|
989
|
-
const [modifier, setModifier] =
|
|
990
|
-
const optionsRef =
|
|
1190
|
+
const [hoveredId, setHoveredId] = useState5(null);
|
|
1191
|
+
const [modifier, setModifier] = useState5(false);
|
|
1192
|
+
const optionsRef = useRef9(options);
|
|
991
1193
|
optionsRef.current = options;
|
|
992
|
-
|
|
1194
|
+
useEffect6(() => {
|
|
993
1195
|
if (!enabled) return;
|
|
994
1196
|
const target = targetElement ?? (typeof window !== "undefined" ? window : null);
|
|
995
1197
|
if (!target) return;
|
|
@@ -1006,16 +1208,16 @@ function useCanvasMeasure(options) {
|
|
|
1006
1208
|
};
|
|
1007
1209
|
}, [enabled, targetElement]);
|
|
1008
1210
|
const active = enabled && (!requireModifier || modifier);
|
|
1009
|
-
const result =
|
|
1211
|
+
const result = useMemo4(() => {
|
|
1010
1212
|
if (!active) return EMPTY;
|
|
1011
1213
|
const ids = optionsRef.current.getSelectedIds?.() ?? nodes.filter((n) => n.selected).map((n) => n.id);
|
|
1012
1214
|
return measureSelection(nodes, ids, hoveredId, rectOptions);
|
|
1013
1215
|
}, [active, nodes, hoveredId, rectOptions]);
|
|
1014
|
-
const onNodeMouseEnter =
|
|
1216
|
+
const onNodeMouseEnter = useCallback8((event, node) => {
|
|
1015
1217
|
setHoveredId(node.id);
|
|
1016
1218
|
if (event && typeof event.altKey === "boolean") setModifier(event.altKey);
|
|
1017
1219
|
}, []);
|
|
1018
|
-
const onNodeMouseLeave =
|
|
1220
|
+
const onNodeMouseLeave = useCallback8((_event, node) => {
|
|
1019
1221
|
setHoveredId((current) => current === node.id ? null : current);
|
|
1020
1222
|
}, []);
|
|
1021
1223
|
return {
|
|
@@ -1094,12 +1296,12 @@ import {
|
|
|
1094
1296
|
|
|
1095
1297
|
// src/canvas/ShapeNode.tsx
|
|
1096
1298
|
import { getShapeRenderData, isShapeDescription } from "@pixerate/editor/canvas";
|
|
1097
|
-
import { jsx as
|
|
1299
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1098
1300
|
function ShapeNode({ data, width, height, selected, className = "", children }) {
|
|
1099
1301
|
const shape = data?.shape;
|
|
1100
1302
|
if (!isShapeDescription(shape)) return null;
|
|
1101
1303
|
const render = getShapeRenderData(shape, { width, height });
|
|
1102
|
-
return /* @__PURE__ */
|
|
1304
|
+
return /* @__PURE__ */ jsxs4(
|
|
1103
1305
|
"div",
|
|
1104
1306
|
{
|
|
1105
1307
|
className: `pixerate-shape-node ${className}`.trim(),
|
|
@@ -1107,7 +1309,7 @@ function ShapeNode({ data, width, height, selected, className = "", children })
|
|
|
1107
1309
|
"data-selected": selected ? "true" : void 0,
|
|
1108
1310
|
style: { position: "relative", width: "100%", height: "100%" },
|
|
1109
1311
|
children: [
|
|
1110
|
-
/* @__PURE__ */
|
|
1312
|
+
/* @__PURE__ */ jsx4(
|
|
1111
1313
|
"svg",
|
|
1112
1314
|
{
|
|
1113
1315
|
viewBox: render.viewBox,
|
|
@@ -1116,7 +1318,7 @@ function ShapeNode({ data, width, height, selected, className = "", children })
|
|
|
1116
1318
|
height: "100%",
|
|
1117
1319
|
style: { display: "block", overflow: "visible" },
|
|
1118
1320
|
"aria-hidden": "true",
|
|
1119
|
-
children: /* @__PURE__ */
|
|
1321
|
+
children: /* @__PURE__ */ jsx4(
|
|
1120
1322
|
"path",
|
|
1121
1323
|
{
|
|
1122
1324
|
d: render.d,
|
|
@@ -1264,17 +1466,17 @@ import {
|
|
|
1264
1466
|
} from "@pixerate/editor/canvas";
|
|
1265
1467
|
|
|
1266
1468
|
// src/canvas/useCanvasAutoLayout.ts
|
|
1267
|
-
import { useLayoutEffect, useMemo as
|
|
1469
|
+
import { useLayoutEffect, useMemo as useMemo5, useRef as useRef10, useState as useState6 } from "react";
|
|
1268
1470
|
import {
|
|
1269
1471
|
createCanvasAutoLayoutController
|
|
1270
1472
|
} from "@pixerate/editor/canvas";
|
|
1271
1473
|
function useCanvasAutoLayout(options) {
|
|
1272
|
-
const [guides, setGuides] =
|
|
1273
|
-
const nodesRef =
|
|
1474
|
+
const [guides, setGuides] = useState6([]);
|
|
1475
|
+
const nodesRef = useRef10(options.nodes);
|
|
1274
1476
|
nodesRef.current = options.nodes;
|
|
1275
|
-
const optionsRef =
|
|
1477
|
+
const optionsRef = useRef10(options);
|
|
1276
1478
|
optionsRef.current = options;
|
|
1277
|
-
const controller =
|
|
1479
|
+
const controller = useMemo5(
|
|
1278
1480
|
() => createCanvasAutoLayoutController({
|
|
1279
1481
|
getNodes: () => nodesRef.current,
|
|
1280
1482
|
setNodes: (next) => {
|
|
@@ -1303,7 +1505,7 @@ function useCanvasAutoLayout(options) {
|
|
|
1303
1505
|
useLayoutEffect(() => {
|
|
1304
1506
|
if (controller.hasPending) controller.flush();
|
|
1305
1507
|
}, [options.nodes, controller]);
|
|
1306
|
-
return
|
|
1508
|
+
return useMemo5(
|
|
1307
1509
|
() => ({
|
|
1308
1510
|
...controller,
|
|
1309
1511
|
/** Drop marker of the active reorder drag (flow coordinates). */
|
|
@@ -1317,7 +1519,7 @@ function useCanvasAutoLayout(options) {
|
|
|
1317
1519
|
}
|
|
1318
1520
|
|
|
1319
1521
|
// src/canvas/useCanvasTokens.ts
|
|
1320
|
-
import { useCallback as
|
|
1522
|
+
import { useCallback as useCallback9, useEffect as useEffect7, useRef as useRef11, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
1321
1523
|
import {
|
|
1322
1524
|
bindCanvasToken,
|
|
1323
1525
|
detachTokenBindings,
|
|
@@ -1328,10 +1530,10 @@ import {
|
|
|
1328
1530
|
function useCanvasTokens(options) {
|
|
1329
1531
|
const { store, nodes, setNodes, modes, properties } = options;
|
|
1330
1532
|
const state = useSyncExternalStore2(store.subscribe, store.getState, store.getState);
|
|
1331
|
-
const latest =
|
|
1533
|
+
const latest = useRef11({ nodes, setNodes, modes, properties });
|
|
1332
1534
|
latest.current = { nodes, setNodes, modes, properties };
|
|
1333
1535
|
const opts = () => ({ modes: latest.current.modes, properties: latest.current.properties });
|
|
1334
|
-
|
|
1536
|
+
useEffect7(
|
|
1335
1537
|
() => store.subscribe((event) => {
|
|
1336
1538
|
if (event.deletedVariableIds.length === 0) return;
|
|
1337
1539
|
latest.current.setNodes((prev) => detachTokenBindings(prev, event.previous, event.deletedVariableIds, opts()));
|
|
@@ -1340,11 +1542,11 @@ function useCanvasTokens(options) {
|
|
|
1340
1542
|
[store]
|
|
1341
1543
|
);
|
|
1342
1544
|
const modesKey = JSON.stringify(modes ?? {});
|
|
1343
|
-
|
|
1545
|
+
useEffect7(() => {
|
|
1344
1546
|
const next = resolveCanvasTokens(nodes, state, opts());
|
|
1345
1547
|
if (next !== nodes) setNodes(next);
|
|
1346
1548
|
}, [nodes, state, modesKey, properties]);
|
|
1347
|
-
const bind =
|
|
1549
|
+
const bind = useCallback9(
|
|
1348
1550
|
(ids, propertyKey, variableId) => {
|
|
1349
1551
|
const next = bindCanvasToken(latest.current.nodes, ids, propertyKey, variableId, store.getState(), opts());
|
|
1350
1552
|
if (next !== latest.current.nodes) latest.current.setNodes(next);
|
|
@@ -1352,7 +1554,7 @@ function useCanvasTokens(options) {
|
|
|
1352
1554
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1353
1555
|
[store]
|
|
1354
1556
|
);
|
|
1355
|
-
const setMode =
|
|
1557
|
+
const setMode = useCallback9(
|
|
1356
1558
|
(ids, collectionId, modeId) => {
|
|
1357
1559
|
const next = setCanvasTokenMode(latest.current.nodes, ids, collectionId, modeId, store.getState(), opts());
|
|
1358
1560
|
if (next !== latest.current.nodes) latest.current.setNodes(next);
|
|
@@ -1360,7 +1562,7 @@ function useCanvasTokens(options) {
|
|
|
1360
1562
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1361
1563
|
[store]
|
|
1362
1564
|
);
|
|
1363
|
-
const modesOf =
|
|
1565
|
+
const modesOf = useCallback9(
|
|
1364
1566
|
(nodeId) => {
|
|
1365
1567
|
const node = latest.current.nodes.find((n) => n.id === nodeId);
|
|
1366
1568
|
return node ? getEffectiveTokenModes(node, latest.current.nodes, store.getState(), opts()) : {};
|
|
@@ -1382,7 +1584,7 @@ import {
|
|
|
1382
1584
|
getTokensForProperty
|
|
1383
1585
|
} from "@pixerate/editor/canvas";
|
|
1384
1586
|
import { getCurrentMode, resolveToken } from "@pixerate/editor/tokens";
|
|
1385
|
-
import { jsx as
|
|
1587
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1386
1588
|
function TokenBindingPicker({
|
|
1387
1589
|
state,
|
|
1388
1590
|
nodes,
|
|
@@ -1399,15 +1601,15 @@ function TokenBindingPicker({
|
|
|
1399
1601
|
let rows = getBindableTokenProperties(first, options);
|
|
1400
1602
|
if (properties) rows = properties.map((key) => rows.find((p) => p.key === key)).filter((p) => !!p);
|
|
1401
1603
|
const modes = getEffectiveTokenModes2(first, nodes, state, options);
|
|
1402
|
-
return /* @__PURE__ */
|
|
1604
|
+
return /* @__PURE__ */ jsxs5("div", { "data-token-binding-picker": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
|
|
1403
1605
|
rows.map((property) => {
|
|
1404
1606
|
const ids = new Set(selected.map((n) => getNodeTokenBindings(n)[property.key] ?? ""));
|
|
1405
1607
|
const value = ids.size === 1 ? [...ids][0] : "__mixed";
|
|
1406
1608
|
const candidates = getTokensForProperty(state, property, first);
|
|
1407
1609
|
const resolved = value && value !== "__mixed" ? resolveToken(state, value, modes) : null;
|
|
1408
|
-
return /* @__PURE__ */
|
|
1409
|
-
/* @__PURE__ */
|
|
1410
|
-
/* @__PURE__ */
|
|
1610
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-2", "data-token-property": property.key, children: [
|
|
1611
|
+
/* @__PURE__ */ jsx5("span", { className: "w-28 shrink-0 text-muted-foreground", children: property.label }),
|
|
1612
|
+
/* @__PURE__ */ jsxs5(
|
|
1411
1613
|
"select",
|
|
1412
1614
|
{
|
|
1413
1615
|
"aria-label": `${property.label} variable`,
|
|
@@ -1422,11 +1624,11 @@ function TokenBindingPicker({
|
|
|
1422
1624
|
}
|
|
1423
1625
|
},
|
|
1424
1626
|
children: [
|
|
1425
|
-
value === "__mixed" ? /* @__PURE__ */
|
|
1426
|
-
/* @__PURE__ */
|
|
1627
|
+
value === "__mixed" ? /* @__PURE__ */ jsx5("option", { value: "__mixed", children: "Mixed" }) : null,
|
|
1628
|
+
/* @__PURE__ */ jsx5("option", { value: "", children: "None" }),
|
|
1427
1629
|
candidates.map((v) => {
|
|
1428
1630
|
const collection = state.collections.find((c) => c.id === v.collectionId);
|
|
1429
|
-
return /* @__PURE__ */
|
|
1631
|
+
return /* @__PURE__ */ jsxs5("option", { value: v.id, children: [
|
|
1430
1632
|
v.name,
|
|
1431
1633
|
collection && state.collections.length > 1 ? ` (${collection.name})` : ""
|
|
1432
1634
|
] }, v.id);
|
|
@@ -1434,17 +1636,17 @@ function TokenBindingPicker({
|
|
|
1434
1636
|
]
|
|
1435
1637
|
}
|
|
1436
1638
|
),
|
|
1437
|
-
/* @__PURE__ */
|
|
1639
|
+
/* @__PURE__ */ jsx5("span", { className: "w-16 shrink-0 truncate text-right text-muted-foreground", "data-token-resolved": "", children: resolved?.ok ? property.type === "color" ? /* @__PURE__ */ jsx5(
|
|
1438
1640
|
"span",
|
|
1439
1641
|
{
|
|
1440
1642
|
className: "inline-block h-3 w-3 rounded border border-border align-middle",
|
|
1441
1643
|
style: { background: String(resolved.value) },
|
|
1442
1644
|
title: String(resolved.value)
|
|
1443
1645
|
}
|
|
1444
|
-
) : String(resolved.value) : resolved ? /* @__PURE__ */
|
|
1646
|
+
) : String(resolved.value) : resolved ? /* @__PURE__ */ jsx5("span", { title: resolved.message, children: "\u26A0" }) : null })
|
|
1445
1647
|
] }, property.key);
|
|
1446
1648
|
}),
|
|
1447
|
-
state.collections.length === 0 ? /* @__PURE__ */
|
|
1649
|
+
state.collections.length === 0 ? /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground", children: "No variables yet." }) : null
|
|
1448
1650
|
] });
|
|
1449
1651
|
}
|
|
1450
1652
|
function TokenModeSwitcher({
|
|
@@ -1462,12 +1664,12 @@ function TokenModeSwitcher({
|
|
|
1462
1664
|
const parent = first.parentId ? nodes.find((n) => n.id === first.parentId) : void 0;
|
|
1463
1665
|
const inherited = parent ? getEffectiveTokenModes2(parent, nodes, state, options) : { ...options.modes };
|
|
1464
1666
|
const collections = state.collections.filter((c) => showSingleMode || c.modes.length > 1);
|
|
1465
|
-
return /* @__PURE__ */
|
|
1667
|
+
return /* @__PURE__ */ jsx5("div", { "data-token-mode-switcher": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: collections.map((collection) => {
|
|
1466
1668
|
const auto = getCurrentMode(collection, inherited);
|
|
1467
1669
|
const explicit = collection.modes.some((m) => m.id === own[collection.id]) ? own[collection.id] : "";
|
|
1468
|
-
return /* @__PURE__ */
|
|
1469
|
-
/* @__PURE__ */
|
|
1470
|
-
/* @__PURE__ */
|
|
1670
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-2", "data-token-collection": collection.id, children: [
|
|
1671
|
+
/* @__PURE__ */ jsx5("span", { className: "w-28 shrink-0 truncate text-muted-foreground", children: collection.name }),
|
|
1672
|
+
/* @__PURE__ */ jsxs5(
|
|
1471
1673
|
"select",
|
|
1472
1674
|
{
|
|
1473
1675
|
"aria-label": `${collection.name} mode`,
|
|
@@ -1475,12 +1677,12 @@ function TokenModeSwitcher({
|
|
|
1475
1677
|
value: explicit,
|
|
1476
1678
|
onChange: (e) => onChange(setCanvasTokenMode2(nodes, nodeIds, collection.id, e.currentTarget.value || null, state, options)),
|
|
1477
1679
|
children: [
|
|
1478
|
-
/* @__PURE__ */
|
|
1680
|
+
/* @__PURE__ */ jsxs5("option", { value: "", children: [
|
|
1479
1681
|
"Auto (",
|
|
1480
1682
|
auto.name,
|
|
1481
1683
|
")"
|
|
1482
1684
|
] }),
|
|
1483
|
-
collection.modes.map((m) => /* @__PURE__ */
|
|
1685
|
+
collection.modes.map((m) => /* @__PURE__ */ jsx5("option", { value: m.id, children: m.name }, m.id))
|
|
1484
1686
|
]
|
|
1485
1687
|
}
|
|
1486
1688
|
)
|
|
@@ -1511,16 +1713,16 @@ import {
|
|
|
1511
1713
|
} from "@pixerate/editor/canvas";
|
|
1512
1714
|
|
|
1513
1715
|
// src/canvas/useCanvasAnimation.ts
|
|
1514
|
-
import { useEffect as
|
|
1716
|
+
import { useEffect as useEffect8, useMemo as useMemo6, useRef as useRef12, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
1515
1717
|
import {
|
|
1516
1718
|
createCanvasAnimationController
|
|
1517
1719
|
} from "@pixerate/editor/canvas";
|
|
1518
1720
|
function useCanvasAnimation(options) {
|
|
1519
|
-
const nodesRef =
|
|
1721
|
+
const nodesRef = useRef12(options.nodes);
|
|
1520
1722
|
nodesRef.current = options.nodes;
|
|
1521
|
-
const optionsRef =
|
|
1723
|
+
const optionsRef = useRef12(options);
|
|
1522
1724
|
optionsRef.current = options;
|
|
1523
|
-
const controller =
|
|
1725
|
+
const controller = useMemo6(
|
|
1524
1726
|
() => createCanvasAnimationController({
|
|
1525
1727
|
getNodes: () => nodesRef.current,
|
|
1526
1728
|
setNodes: (next) => {
|
|
@@ -1547,14 +1749,14 @@ function useCanvasAnimation(options) {
|
|
|
1547
1749
|
}),
|
|
1548
1750
|
[]
|
|
1549
1751
|
);
|
|
1550
|
-
|
|
1551
|
-
|
|
1752
|
+
useEffect8(() => () => controller.destroy(), [controller]);
|
|
1753
|
+
useEffect8(() => {
|
|
1552
1754
|
if (options.loop !== void 0) controller.setLoop(options.loop);
|
|
1553
1755
|
}, [controller, options.loop]);
|
|
1554
|
-
|
|
1756
|
+
useEffect8(() => {
|
|
1555
1757
|
if (options.playbackRate !== void 0) controller.setPlaybackRate(options.playbackRate);
|
|
1556
1758
|
}, [controller, options.playbackRate]);
|
|
1557
|
-
|
|
1759
|
+
useEffect8(() => {
|
|
1558
1760
|
if (options.recording !== void 0) controller.setRecording(options.recording);
|
|
1559
1761
|
}, [controller, options.recording]);
|
|
1560
1762
|
const state = useSyncExternalStore3(
|
|
@@ -1562,11 +1764,11 @@ function useCanvasAnimation(options) {
|
|
|
1562
1764
|
() => controller.getState(),
|
|
1563
1765
|
() => controller.getState()
|
|
1564
1766
|
);
|
|
1565
|
-
|
|
1767
|
+
useEffect8(() => {
|
|
1566
1768
|
controller.refresh();
|
|
1567
1769
|
}, [controller, options.nodes]);
|
|
1568
|
-
const displayNodes =
|
|
1569
|
-
return
|
|
1770
|
+
const displayNodes = useMemo6(() => controller.display(options.nodes), [controller, options.nodes, state.time]);
|
|
1771
|
+
return useMemo6(
|
|
1570
1772
|
() => ({
|
|
1571
1773
|
...controller,
|
|
1572
1774
|
state,
|
|
@@ -1587,7 +1789,7 @@ function useCanvasAnimation(options) {
|
|
|
1587
1789
|
}
|
|
1588
1790
|
|
|
1589
1791
|
// src/canvas/AnimationTimeline.tsx
|
|
1590
|
-
import { useEffect as
|
|
1792
|
+
import { useEffect as useEffect9, useRef as useRef13 } from "react";
|
|
1591
1793
|
import {
|
|
1592
1794
|
ANIMATION_EASING_LABELS,
|
|
1593
1795
|
ANIMATION_EASING_PRESETS,
|
|
@@ -1596,7 +1798,7 @@ import {
|
|
|
1596
1798
|
timeToX,
|
|
1597
1799
|
xToTime
|
|
1598
1800
|
} from "@pixerate/editor/canvas";
|
|
1599
|
-
import { jsx as
|
|
1801
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1600
1802
|
var LOOP_LABELS = { none: "Once", loop: "Loop", "ping-pong": "Ping-pong" };
|
|
1601
1803
|
var easingValue = (easing) => typeof easing === "string" ? easing : easing ? "custom" : "linear";
|
|
1602
1804
|
function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8, labelOf, className = "" }) {
|
|
@@ -1610,8 +1812,8 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
|
|
|
1610
1812
|
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);
|
|
1611
1813
|
return "";
|
|
1612
1814
|
})();
|
|
1613
|
-
const dragRef =
|
|
1614
|
-
|
|
1815
|
+
const dragRef = useRef13(null);
|
|
1816
|
+
useEffect9(() => {
|
|
1615
1817
|
const onKey = (event) => {
|
|
1616
1818
|
if (event.key === "Escape" && dragRef.current) {
|
|
1617
1819
|
dragRef.current = null;
|
|
@@ -1667,10 +1869,10 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
|
|
|
1667
1869
|
const btn = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-50";
|
|
1668
1870
|
const playheadX = timeToX(state.time, duration, width);
|
|
1669
1871
|
const labelWidth = 120;
|
|
1670
|
-
return /* @__PURE__ */
|
|
1671
|
-
/* @__PURE__ */
|
|
1672
|
-
/* @__PURE__ */
|
|
1673
|
-
/* @__PURE__ */
|
|
1872
|
+
return /* @__PURE__ */ jsxs6("div", { "data-animation-timeline": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, tabIndex: 0, onKeyDown: onTimelineKey, children: [
|
|
1873
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap items-center gap-2", role: "toolbar", "aria-label": "Animation", children: [
|
|
1874
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: btn, "data-action": "toggle-play", "aria-label": state.playing ? "Pause" : "Play", onClick: () => animation.toggle(), children: state.playing ? "\u275A\u275A" : "\u25B6" }),
|
|
1875
|
+
/* @__PURE__ */ jsx6(
|
|
1674
1876
|
"button",
|
|
1675
1877
|
{
|
|
1676
1878
|
type: "button",
|
|
@@ -1682,13 +1884,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
|
|
|
1682
1884
|
children: "\u25CF Rec"
|
|
1683
1885
|
}
|
|
1684
1886
|
),
|
|
1685
|
-
/* @__PURE__ */
|
|
1686
|
-
/* @__PURE__ */
|
|
1887
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: btn, "data-action": "add-keyframe", onClick: () => animation.addKeyframe(), children: "\u25C6 Key" }),
|
|
1888
|
+
/* @__PURE__ */ jsxs6("span", { "data-time": "", className: "tabular-nums text-muted-foreground", children: [
|
|
1687
1889
|
formatAnimationTime(state.time),
|
|
1688
1890
|
" / ",
|
|
1689
1891
|
formatAnimationTime(duration)
|
|
1690
1892
|
] }),
|
|
1691
|
-
/* @__PURE__ */
|
|
1893
|
+
/* @__PURE__ */ jsxs6(
|
|
1692
1894
|
"select",
|
|
1693
1895
|
{
|
|
1694
1896
|
"aria-label": "Easing",
|
|
@@ -1698,13 +1900,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
|
|
|
1698
1900
|
disabled: state.selection.length === 0,
|
|
1699
1901
|
onChange: (e) => e.target.value && e.target.value !== "custom" && animation.setEasing(e.target.value),
|
|
1700
1902
|
children: [
|
|
1701
|
-
/* @__PURE__ */
|
|
1702
|
-
ANIMATION_EASING_PRESETS.map((preset) => /* @__PURE__ */
|
|
1703
|
-
selectedEasing === "custom" ? /* @__PURE__ */
|
|
1903
|
+
/* @__PURE__ */ jsx6("option", { value: "", children: "Easing\u2026" }),
|
|
1904
|
+
ANIMATION_EASING_PRESETS.map((preset) => /* @__PURE__ */ jsx6("option", { value: preset, children: ANIMATION_EASING_LABELS[preset] }, preset)),
|
|
1905
|
+
selectedEasing === "custom" ? /* @__PURE__ */ jsx6("option", { value: "custom", children: "Custom" }) : null
|
|
1704
1906
|
]
|
|
1705
1907
|
}
|
|
1706
1908
|
),
|
|
1707
|
-
/* @__PURE__ */
|
|
1909
|
+
/* @__PURE__ */ jsx6(
|
|
1708
1910
|
"select",
|
|
1709
1911
|
{
|
|
1710
1912
|
"aria-label": "Loop",
|
|
@@ -1712,13 +1914,13 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
|
|
|
1712
1914
|
className: "rounded border border-border bg-background px-1 py-0.5",
|
|
1713
1915
|
value: state.loop,
|
|
1714
1916
|
onChange: (e) => animation.setLoop(e.target.value),
|
|
1715
|
-
children: Object.keys(LOOP_LABELS).map((mode) => /* @__PURE__ */
|
|
1917
|
+
children: Object.keys(LOOP_LABELS).map((mode) => /* @__PURE__ */ jsx6("option", { value: mode, children: LOOP_LABELS[mode] }, mode))
|
|
1716
1918
|
}
|
|
1717
1919
|
)
|
|
1718
1920
|
] }),
|
|
1719
|
-
/* @__PURE__ */
|
|
1720
|
-
/* @__PURE__ */
|
|
1721
|
-
/* @__PURE__ */
|
|
1921
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex", children: [
|
|
1922
|
+
/* @__PURE__ */ jsx6("div", { style: { width: labelWidth }, className: "shrink-0" }),
|
|
1923
|
+
/* @__PURE__ */ jsxs6(
|
|
1722
1924
|
"div",
|
|
1723
1925
|
{
|
|
1724
1926
|
"data-timeline-ruler": "",
|
|
@@ -1726,15 +1928,15 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
|
|
|
1726
1928
|
style: { width },
|
|
1727
1929
|
onPointerDown: onRulerDown,
|
|
1728
1930
|
children: [
|
|
1729
|
-
ticks.map((tick) => /* @__PURE__ */
|
|
1730
|
-
/* @__PURE__ */
|
|
1931
|
+
ticks.map((tick) => /* @__PURE__ */ jsx6("span", { className: "absolute top-0 -translate-x-1/2 text-[10px] text-muted-foreground", style: { left: tick.x }, children: tick.label }, tick.time)),
|
|
1932
|
+
/* @__PURE__ */ jsx6("div", { "data-playhead": "", className: "absolute top-0 h-5 w-px bg-red-500", style: { left: playheadX } })
|
|
1731
1933
|
]
|
|
1732
1934
|
}
|
|
1733
1935
|
)
|
|
1734
1936
|
] }),
|
|
1735
|
-
rows.length === 0 ? /* @__PURE__ */
|
|
1736
|
-
/* @__PURE__ */
|
|
1737
|
-
/* @__PURE__ */
|
|
1937
|
+
rows.length === 0 ? /* @__PURE__ */ jsx6("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__ */ jsxs6("div", { className: "flex items-center", "data-track": row.id, children: [
|
|
1938
|
+
/* @__PURE__ */ jsxs6("label", { className: "flex shrink-0 items-center gap-1 truncate pr-2", style: { width: labelWidth }, title: `${row.nodeLabel} \xB7 ${row.label}`, children: [
|
|
1939
|
+
/* @__PURE__ */ jsx6(
|
|
1738
1940
|
"input",
|
|
1739
1941
|
{
|
|
1740
1942
|
type: "checkbox",
|
|
@@ -1743,15 +1945,15 @@ function AnimationTimeline({ animation, nodeIds, width = 360, snapThreshold = 8,
|
|
|
1743
1945
|
onChange: (e) => animation.setTrackEnabled(row.nodeId, row.property, e.target.checked)
|
|
1744
1946
|
}
|
|
1745
1947
|
),
|
|
1746
|
-
/* @__PURE__ */
|
|
1948
|
+
/* @__PURE__ */ jsxs6("span", { className: "truncate", children: [
|
|
1747
1949
|
rows.filter((r) => r.nodeId === row.nodeId).length < rows.length ? `${row.nodeLabel} \xB7 ` : "",
|
|
1748
1950
|
row.label
|
|
1749
1951
|
] })
|
|
1750
1952
|
] }),
|
|
1751
|
-
/* @__PURE__ */
|
|
1752
|
-
/* @__PURE__ */
|
|
1753
|
-
state.drag?.target != null ? /* @__PURE__ */
|
|
1754
|
-
row.keyframes.map((k) => /* @__PURE__ */
|
|
1953
|
+
/* @__PURE__ */ jsxs6("div", { "data-lane": "", className: `relative h-5 rounded bg-muted/40 ${row.enabled ? "" : "opacity-50"}`, style: { width }, children: [
|
|
1954
|
+
/* @__PURE__ */ jsx6("div", { className: "pointer-events-none absolute top-0 h-5 w-px bg-red-500/60", style: { left: playheadX } }),
|
|
1955
|
+
state.drag?.target != null ? /* @__PURE__ */ jsx6("div", { "data-snap-target": "", className: "pointer-events-none absolute top-0 h-5 w-px bg-sky-400", style: { left: timeToX(state.drag.target, duration, width) } }) : null,
|
|
1956
|
+
row.keyframes.map((k) => /* @__PURE__ */ jsx6(
|
|
1755
1957
|
"button",
|
|
1756
1958
|
{
|
|
1757
1959
|
type: "button",
|
|
@@ -1849,16 +2051,16 @@ import {
|
|
|
1849
2051
|
} from "@pixerate/editor/canvas";
|
|
1850
2052
|
|
|
1851
2053
|
// src/canvas/useCanvasComponents.ts
|
|
1852
|
-
import { useLayoutEffect as useLayoutEffect2, useMemo as
|
|
2054
|
+
import { useLayoutEffect as useLayoutEffect2, useMemo as useMemo7, useRef as useRef14 } from "react";
|
|
1853
2055
|
import {
|
|
1854
2056
|
createCanvasComponentsController
|
|
1855
2057
|
} from "@pixerate/editor/canvas";
|
|
1856
2058
|
function useCanvasComponents(options) {
|
|
1857
|
-
const nodesRef =
|
|
2059
|
+
const nodesRef = useRef14(options.nodes);
|
|
1858
2060
|
nodesRef.current = options.nodes;
|
|
1859
|
-
const optionsRef =
|
|
2061
|
+
const optionsRef = useRef14(options);
|
|
1860
2062
|
optionsRef.current = options;
|
|
1861
|
-
const controller =
|
|
2063
|
+
const controller = useMemo7(
|
|
1862
2064
|
() => createCanvasComponentsController({
|
|
1863
2065
|
getNodes: () => nodesRef.current,
|
|
1864
2066
|
setNodes: (next) => {
|
|
@@ -1894,15 +2096,15 @@ function useCanvasComponents(options) {
|
|
|
1894
2096
|
}
|
|
1895
2097
|
|
|
1896
2098
|
// src/canvas/CanvasComponentsPanel.tsx
|
|
1897
|
-
import { useState as
|
|
2099
|
+
import { useState as useState7 } from "react";
|
|
1898
2100
|
import {
|
|
1899
2101
|
CANVAS_COMPONENT_DRAG_TYPE,
|
|
1900
2102
|
inspectCanvasInstance,
|
|
1901
2103
|
listCanvasComponents
|
|
1902
2104
|
} from "@pixerate/editor/canvas";
|
|
1903
|
-
import { Fragment, jsx as
|
|
2105
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1904
2106
|
function InlineField({ value, label, onCommit }) {
|
|
1905
|
-
return /* @__PURE__ */
|
|
2107
|
+
return /* @__PURE__ */ jsx7(
|
|
1906
2108
|
"input",
|
|
1907
2109
|
{
|
|
1908
2110
|
type: "text",
|
|
@@ -1933,10 +2135,10 @@ function CanvasComponentsPanel({
|
|
|
1933
2135
|
search = true,
|
|
1934
2136
|
className = ""
|
|
1935
2137
|
}) {
|
|
1936
|
-
const [query, setQuery] =
|
|
1937
|
-
const [propsOpen, setPropsOpen] =
|
|
1938
|
-
const [menuFor, setMenuFor] =
|
|
1939
|
-
const [editing, setEditing] =
|
|
2138
|
+
const [query, setQuery] = useState7("");
|
|
2139
|
+
const [propsOpen, setPropsOpen] = useState7(null);
|
|
2140
|
+
const [menuFor, setMenuFor] = useState7(null);
|
|
2141
|
+
const [editing, setEditing] = useState7(null);
|
|
1940
2142
|
const { components: all, sets } = listCanvasComponents(nodes);
|
|
1941
2143
|
const q = query.trim().toLowerCase();
|
|
1942
2144
|
const match = (name) => !q || name.toLowerCase().includes(q);
|
|
@@ -1948,7 +2150,7 @@ function CanvasComponentsPanel({
|
|
|
1948
2150
|
};
|
|
1949
2151
|
const small = "shrink-0 rounded px-1 text-[10px] text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-40";
|
|
1950
2152
|
const menuItem = "rounded px-2 py-0.5 text-left hover:bg-muted disabled:opacity-40";
|
|
1951
|
-
const item = (id, name, count, extra = {}, onContextMenu) => /* @__PURE__ */
|
|
2153
|
+
const item = (id, name, count, extra = {}, onContextMenu) => /* @__PURE__ */ jsxs7(
|
|
1952
2154
|
"button",
|
|
1953
2155
|
{
|
|
1954
2156
|
type: "button",
|
|
@@ -1965,17 +2167,17 @@ function CanvasComponentsPanel({
|
|
|
1965
2167
|
e.dataTransfer.effectAllowed = "copy";
|
|
1966
2168
|
},
|
|
1967
2169
|
children: [
|
|
1968
|
-
/* @__PURE__ */
|
|
1969
|
-
/* @__PURE__ */
|
|
2170
|
+
/* @__PURE__ */ jsxs7("span", { className: "truncate", children: [
|
|
2171
|
+
/* @__PURE__ */ jsx7("span", { "aria-hidden": true, className: "mr-1 text-muted-foreground", children: "\u25C7" }),
|
|
1970
2172
|
name
|
|
1971
2173
|
] }),
|
|
1972
|
-
/* @__PURE__ */
|
|
2174
|
+
/* @__PURE__ */ jsx7("span", { className: "text-[10px] text-muted-foreground", "data-instance-count": "", children: count })
|
|
1973
2175
|
]
|
|
1974
2176
|
},
|
|
1975
2177
|
id
|
|
1976
2178
|
);
|
|
1977
|
-
return /* @__PURE__ */
|
|
1978
|
-
search ? /* @__PURE__ */
|
|
2179
|
+
return /* @__PURE__ */ jsxs7("div", { "data-components-panel": "", className: `flex flex-col gap-1 text-xs text-foreground ${className}`, children: [
|
|
2180
|
+
search ? /* @__PURE__ */ jsx7(
|
|
1979
2181
|
"input",
|
|
1980
2182
|
{
|
|
1981
2183
|
type: "search",
|
|
@@ -1985,11 +2187,11 @@ function CanvasComponentsPanel({
|
|
|
1985
2187
|
onInput: (e) => setQuery(e.target.value)
|
|
1986
2188
|
}
|
|
1987
2189
|
) : null,
|
|
1988
|
-
shownSets.map((set) => /* @__PURE__ */
|
|
1989
|
-
/* @__PURE__ */
|
|
2190
|
+
shownSets.map((set) => /* @__PURE__ */ jsxs7("div", { "data-component-set": set.id, className: "flex flex-col", children: [
|
|
2191
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1", children: [
|
|
1990
2192
|
item(set.id, set.name, set.variants.reduce((sum, v) => sum + v.instanceCount, 0), { "data-kind": "set" }),
|
|
1991
|
-
components ? /* @__PURE__ */
|
|
1992
|
-
/* @__PURE__ */
|
|
2193
|
+
components ? /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
2194
|
+
/* @__PURE__ */ jsx7(
|
|
1993
2195
|
"button",
|
|
1994
2196
|
{
|
|
1995
2197
|
type: "button",
|
|
@@ -2001,7 +2203,7 @@ function CanvasComponentsPanel({
|
|
|
2001
2203
|
children: "+\xA0Variant"
|
|
2002
2204
|
}
|
|
2003
2205
|
),
|
|
2004
|
-
/* @__PURE__ */
|
|
2206
|
+
/* @__PURE__ */ jsx7(
|
|
2005
2207
|
"button",
|
|
2006
2208
|
{
|
|
2007
2209
|
type: "button",
|
|
@@ -2016,8 +2218,8 @@ function CanvasComponentsPanel({
|
|
|
2016
2218
|
)
|
|
2017
2219
|
] }) : null
|
|
2018
2220
|
] }),
|
|
2019
|
-
components && propsOpen === set.id ? /* @__PURE__ */
|
|
2020
|
-
/* @__PURE__ */
|
|
2221
|
+
components && propsOpen === set.id ? /* @__PURE__ */ jsx7("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__ */ jsxs7("div", { "data-variant-option": option.name, className: "flex flex-col gap-0.5", children: [
|
|
2222
|
+
/* @__PURE__ */ jsx7(
|
|
2021
2223
|
InlineField,
|
|
2022
2224
|
{
|
|
2023
2225
|
value: option.name,
|
|
@@ -2025,7 +2227,7 @@ function CanvasComponentsPanel({
|
|
|
2025
2227
|
onCommit: (next) => report(components.renameVariantProperty(option.name, next, set.id))
|
|
2026
2228
|
}
|
|
2027
2229
|
),
|
|
2028
|
-
/* @__PURE__ */
|
|
2230
|
+
/* @__PURE__ */ jsx7("div", { className: "ml-2 flex flex-wrap gap-1", children: option.values.map((value) => /* @__PURE__ */ jsx7(
|
|
2029
2231
|
InlineField,
|
|
2030
2232
|
{
|
|
2031
2233
|
value,
|
|
@@ -2035,8 +2237,8 @@ function CanvasComponentsPanel({
|
|
|
2035
2237
|
value
|
|
2036
2238
|
)) })
|
|
2037
2239
|
] }, option.name)) }) : null,
|
|
2038
|
-
/* @__PURE__ */
|
|
2039
|
-
/* @__PURE__ */
|
|
2240
|
+
/* @__PURE__ */ jsx7("div", { className: "ml-3 flex flex-col border-l border-border pl-1", children: set.variants.map((v) => /* @__PURE__ */ jsxs7("div", { "data-variant-row": v.id, className: "flex flex-col", children: [
|
|
2241
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1", children: [
|
|
2040
2242
|
item(
|
|
2041
2243
|
v.id,
|
|
2042
2244
|
v.name,
|
|
@@ -2047,7 +2249,7 @@ function CanvasComponentsPanel({
|
|
|
2047
2249
|
setMenuFor(v.id);
|
|
2048
2250
|
} : void 0
|
|
2049
2251
|
),
|
|
2050
|
-
components ? /* @__PURE__ */
|
|
2252
|
+
components ? /* @__PURE__ */ jsx7(
|
|
2051
2253
|
"button",
|
|
2052
2254
|
{
|
|
2053
2255
|
type: "button",
|
|
@@ -2061,8 +2263,8 @@ function CanvasComponentsPanel({
|
|
|
2061
2263
|
}
|
|
2062
2264
|
) : null
|
|
2063
2265
|
] }),
|
|
2064
|
-
components && menuFor === v.id ? /* @__PURE__ */
|
|
2065
|
-
/* @__PURE__ */
|
|
2266
|
+
components && menuFor === v.id ? /* @__PURE__ */ jsxs7("div", { role: "menu", "data-variant-menu": v.id, className: "ml-2 flex flex-col rounded border border-border bg-background p-1 shadow", children: [
|
|
2267
|
+
/* @__PURE__ */ jsx7(
|
|
2066
2268
|
"button",
|
|
2067
2269
|
{
|
|
2068
2270
|
type: "button",
|
|
@@ -2076,7 +2278,7 @@ function CanvasComponentsPanel({
|
|
|
2076
2278
|
children: "Edit values\u2026"
|
|
2077
2279
|
}
|
|
2078
2280
|
),
|
|
2079
|
-
/* @__PURE__ */
|
|
2281
|
+
/* @__PURE__ */ jsx7(
|
|
2080
2282
|
"button",
|
|
2081
2283
|
{
|
|
2082
2284
|
type: "button",
|
|
@@ -2090,7 +2292,7 @@ function CanvasComponentsPanel({
|
|
|
2090
2292
|
children: "Duplicate"
|
|
2091
2293
|
}
|
|
2092
2294
|
),
|
|
2093
|
-
/* @__PURE__ */
|
|
2295
|
+
/* @__PURE__ */ jsx7(
|
|
2094
2296
|
"button",
|
|
2095
2297
|
{
|
|
2096
2298
|
type: "button",
|
|
@@ -2107,7 +2309,7 @@ function CanvasComponentsPanel({
|
|
|
2107
2309
|
}
|
|
2108
2310
|
)
|
|
2109
2311
|
] }) : null,
|
|
2110
|
-
components && editing === v.id ? /* @__PURE__ */
|
|
2312
|
+
components && editing === v.id ? /* @__PURE__ */ jsxs7(
|
|
2111
2313
|
"form",
|
|
2112
2314
|
{
|
|
2113
2315
|
"data-variant-editor": v.id,
|
|
@@ -2121,9 +2323,9 @@ function CanvasComponentsPanel({
|
|
|
2121
2323
|
if (report(components.setVariantProperties(values, v.id))) setEditing(null);
|
|
2122
2324
|
},
|
|
2123
2325
|
children: [
|
|
2124
|
-
set.options.map((option) => /* @__PURE__ */
|
|
2125
|
-
/* @__PURE__ */
|
|
2126
|
-
/* @__PURE__ */
|
|
2326
|
+
set.options.map((option) => /* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-2", children: [
|
|
2327
|
+
/* @__PURE__ */ jsx7("span", { className: "w-16 shrink-0 truncate text-muted-foreground", children: option.name }),
|
|
2328
|
+
/* @__PURE__ */ jsx7(
|
|
2127
2329
|
"input",
|
|
2128
2330
|
{
|
|
2129
2331
|
type: "text",
|
|
@@ -2134,9 +2336,9 @@ function CanvasComponentsPanel({
|
|
|
2134
2336
|
}
|
|
2135
2337
|
)
|
|
2136
2338
|
] }, option.name)),
|
|
2137
|
-
/* @__PURE__ */
|
|
2138
|
-
/* @__PURE__ */
|
|
2139
|
-
/* @__PURE__ */
|
|
2339
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex gap-1", children: [
|
|
2340
|
+
/* @__PURE__ */ jsx7("button", { type: "submit", className: "rounded border border-border px-2 py-0.5 hover:bg-muted", "data-action": "save-variant", children: "Save" }),
|
|
2341
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: "rounded px-2 py-0.5 hover:bg-muted", "data-action": "cancel-variant", onClick: () => setEditing(null), children: "Cancel" })
|
|
2140
2342
|
] })
|
|
2141
2343
|
]
|
|
2142
2344
|
}
|
|
@@ -2144,7 +2346,7 @@ function CanvasComponentsPanel({
|
|
|
2144
2346
|
] }, v.id)) })
|
|
2145
2347
|
] }, set.id)),
|
|
2146
2348
|
lone.map((c) => item(c.id, c.name, c.instanceCount, { "data-kind": "component" })),
|
|
2147
|
-
all.length === 0 ? /* @__PURE__ */
|
|
2349
|
+
all.length === 0 ? /* @__PURE__ */ jsx7("p", { className: "text-muted-foreground", children: "No components yet. Select a frame and choose Create Component." }) : null
|
|
2148
2350
|
] });
|
|
2149
2351
|
}
|
|
2150
2352
|
function CanvasInstanceInspector({
|
|
@@ -2163,27 +2365,27 @@ function CanvasInstanceInspector({
|
|
|
2163
2365
|
const allComponents = listCanvasComponents(nodes).components;
|
|
2164
2366
|
const linked = info.status === "linked";
|
|
2165
2367
|
const btn = "rounded border border-border px-2 py-0.5 text-xs hover:bg-muted disabled:opacity-40";
|
|
2166
|
-
return /* @__PURE__ */
|
|
2167
|
-
/* @__PURE__ */
|
|
2168
|
-
/* @__PURE__ */
|
|
2169
|
-
info.nested ? /* @__PURE__ */
|
|
2368
|
+
return /* @__PURE__ */ jsxs7("div", { "data-instance-inspector": "", "data-instance-id": info.id, className: `flex flex-col gap-2 text-xs text-foreground ${className}`, children: [
|
|
2369
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2370
|
+
/* @__PURE__ */ jsx7("span", { className: "truncate font-medium", "data-instance-main": "", children: linked ? info.componentName : "Main component missing" }),
|
|
2371
|
+
info.nested ? /* @__PURE__ */ jsx7("span", { className: "text-muted-foreground", children: "Nested" }) : null
|
|
2170
2372
|
] }),
|
|
2171
|
-
info.variantOptions.map((option) => /* @__PURE__ */
|
|
2172
|
-
/* @__PURE__ */
|
|
2173
|
-
/* @__PURE__ */
|
|
2373
|
+
info.variantOptions.map((option) => /* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-2", "data-variant-property": option.name, children: [
|
|
2374
|
+
/* @__PURE__ */ jsx7("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: option.name }),
|
|
2375
|
+
/* @__PURE__ */ jsx7(
|
|
2174
2376
|
"select",
|
|
2175
2377
|
{
|
|
2176
2378
|
"aria-label": `${option.name} variant`,
|
|
2177
2379
|
className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
|
|
2178
2380
|
value: info.variant[option.name] ?? "",
|
|
2179
2381
|
onChange: (e) => setProp(option.name, e.currentTarget.value),
|
|
2180
|
-
children: option.values.map((v) => /* @__PURE__ */
|
|
2382
|
+
children: option.values.map((v) => /* @__PURE__ */ jsx7("option", { value: v, children: v }, v))
|
|
2181
2383
|
}
|
|
2182
2384
|
)
|
|
2183
2385
|
] }, option.name)),
|
|
2184
|
-
info.properties.map((p) => /* @__PURE__ */
|
|
2185
|
-
/* @__PURE__ */
|
|
2186
|
-
p.type === "boolean" ? /* @__PURE__ */
|
|
2386
|
+
info.properties.map((p) => /* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-2", "data-component-property": p.name, children: [
|
|
2387
|
+
/* @__PURE__ */ jsx7("span", { className: "w-24 shrink-0 truncate text-muted-foreground", children: p.name }),
|
|
2388
|
+
p.type === "boolean" ? /* @__PURE__ */ jsx7("input", { type: "checkbox", "aria-label": p.name, checked: p.value === true, onChange: (e) => setProp(p.name, e.currentTarget.checked) }) : p.type === "text" ? /* @__PURE__ */ jsx7(
|
|
2187
2389
|
"input",
|
|
2188
2390
|
{
|
|
2189
2391
|
type: "text",
|
|
@@ -2198,22 +2400,22 @@ function CanvasInstanceInspector({
|
|
|
2198
2400
|
}
|
|
2199
2401
|
},
|
|
2200
2402
|
String(p.value)
|
|
2201
|
-
) : /* @__PURE__ */
|
|
2403
|
+
) : /* @__PURE__ */ jsx7(
|
|
2202
2404
|
"select",
|
|
2203
2405
|
{
|
|
2204
2406
|
"aria-label": p.name,
|
|
2205
2407
|
className: "min-w-0 flex-1 rounded border border-border bg-background px-1 py-0.5 text-xs",
|
|
2206
2408
|
value: String(p.value),
|
|
2207
2409
|
onChange: (e) => setProp(p.name, e.currentTarget.value),
|
|
2208
|
-
children: allComponents.filter((c) => !p.preferred?.length || p.preferred.includes(c.id) || c.id === p.value).map((c) => /* @__PURE__ */
|
|
2410
|
+
children: allComponents.filter((c) => !p.preferred?.length || p.preferred.includes(c.id) || c.id === p.value).map((c) => /* @__PURE__ */ jsx7("option", { value: c.id, children: c.name }, c.id))
|
|
2209
2411
|
}
|
|
2210
2412
|
)
|
|
2211
2413
|
] }, p.name)),
|
|
2212
|
-
info.overrides.length ? /* @__PURE__ */
|
|
2213
|
-
/* @__PURE__ */
|
|
2214
|
-
info.overrides.map((o) => /* @__PURE__ */
|
|
2215
|
-
/* @__PURE__ */
|
|
2216
|
-
o.groups.map((g) => /* @__PURE__ */
|
|
2414
|
+
info.overrides.length ? /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1", "data-instance-overrides": "", children: [
|
|
2415
|
+
/* @__PURE__ */ jsx7("span", { className: "text-muted-foreground", children: "Overrides" }),
|
|
2416
|
+
info.overrides.map((o) => /* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap items-center gap-1", "data-override-layer": o.id, children: [
|
|
2417
|
+
/* @__PURE__ */ jsx7("span", { className: "mr-1 truncate", children: o.name }),
|
|
2418
|
+
o.groups.map((g) => /* @__PURE__ */ jsxs7(
|
|
2217
2419
|
"button",
|
|
2218
2420
|
{
|
|
2219
2421
|
type: "button",
|
|
@@ -2230,11 +2432,11 @@ function CanvasInstanceInspector({
|
|
|
2230
2432
|
))
|
|
2231
2433
|
] }, o.id))
|
|
2232
2434
|
] }) : null,
|
|
2233
|
-
/* @__PURE__ */
|
|
2234
|
-
linked ? /* @__PURE__ */
|
|
2235
|
-
/* @__PURE__ */
|
|
2236
|
-
/* @__PURE__ */
|
|
2237
|
-
/* @__PURE__ */
|
|
2435
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap gap-1", children: [
|
|
2436
|
+
linked ? /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
2437
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: btn, "data-action": "reset", onClick: () => report(components.resetOverrides(info.id)), children: "Reset all" }),
|
|
2438
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: btn, "data-action": "go-to-main", onClick: () => components.goToMainComponent(info.id), children: "Go to main" }),
|
|
2439
|
+
/* @__PURE__ */ jsx7(
|
|
2238
2440
|
"button",
|
|
2239
2441
|
{
|
|
2240
2442
|
type: "button",
|
|
@@ -2245,8 +2447,8 @@ function CanvasInstanceInspector({
|
|
|
2245
2447
|
children: "Push changes"
|
|
2246
2448
|
}
|
|
2247
2449
|
)
|
|
2248
|
-
] }) : /* @__PURE__ */
|
|
2249
|
-
/* @__PURE__ */
|
|
2450
|
+
] }) : /* @__PURE__ */ jsx7("button", { type: "button", className: btn, "data-action": "restore", onClick: () => report(components.restoreMainComponent(info.rootId)), children: "Restore main component" }),
|
|
2451
|
+
/* @__PURE__ */ jsx7(
|
|
2250
2452
|
"button",
|
|
2251
2453
|
{
|
|
2252
2454
|
type: "button",
|
|
@@ -2296,7 +2498,13 @@ import {
|
|
|
2296
2498
|
isCanvasComponentSet,
|
|
2297
2499
|
isCanvasInstance,
|
|
2298
2500
|
wouldCreateComponentCycle,
|
|
2299
|
-
CANVAS_COMPONENT_DRAG_TYPE as CANVAS_COMPONENT_DRAG_TYPE2
|
|
2501
|
+
CANVAS_COMPONENT_DRAG_TYPE as CANVAS_COMPONENT_DRAG_TYPE2,
|
|
2502
|
+
createCanvasDrawController as createCanvasDrawController2,
|
|
2503
|
+
createDefaultStrokeStyle,
|
|
2504
|
+
findStrokesAtPoint,
|
|
2505
|
+
streamlinePoints,
|
|
2506
|
+
strokePointsToPathData as strokePointsToPathData2,
|
|
2507
|
+
strokeToShapeNode
|
|
2300
2508
|
} from "@pixerate/editor/canvas";
|
|
2301
2509
|
export {
|
|
2302
2510
|
ANIMATABLE_PROPERTIES,
|
|
@@ -2316,6 +2524,7 @@ export {
|
|
|
2316
2524
|
CSS_ANIMATION_PROPERTIES,
|
|
2317
2525
|
CUBIC_BEZIER_PRESETS,
|
|
2318
2526
|
CanvasComponentsPanel,
|
|
2527
|
+
CanvasDrawLayer,
|
|
2319
2528
|
CanvasGuidesLayer,
|
|
2320
2529
|
CanvasInstanceInspector,
|
|
2321
2530
|
CanvasScenesStore2 as CanvasScenesStore,
|
|
@@ -2375,8 +2584,10 @@ export {
|
|
|
2375
2584
|
createCanvasAutoLayoutController2 as createCanvasAutoLayoutController,
|
|
2376
2585
|
createCanvasComponent,
|
|
2377
2586
|
createCanvasComponentsController2 as createCanvasComponentsController,
|
|
2587
|
+
createCanvasDrawController2 as createCanvasDrawController,
|
|
2378
2588
|
createCanvasInstance,
|
|
2379
2589
|
createCanvasScenesStore,
|
|
2590
|
+
createDefaultStrokeStyle,
|
|
2380
2591
|
createFanOutTrajectory2 as createFanOutTrajectory,
|
|
2381
2592
|
createGuideIndex,
|
|
2382
2593
|
createNodeGuideIndex,
|
|
@@ -2404,6 +2615,7 @@ export {
|
|
|
2404
2615
|
excludePaths,
|
|
2405
2616
|
exportCssAnimation,
|
|
2406
2617
|
findConnectorSnap,
|
|
2618
|
+
findStrokesAtPoint,
|
|
2407
2619
|
fitCubicRun,
|
|
2408
2620
|
fitCubics,
|
|
2409
2621
|
fitFreehandPath,
|
|
@@ -2577,7 +2789,10 @@ export {
|
|
|
2577
2789
|
snapTimeToFrame,
|
|
2578
2790
|
snapToGrid,
|
|
2579
2791
|
springAt,
|
|
2792
|
+
streamlinePoints,
|
|
2580
2793
|
strokeOutlineRings,
|
|
2794
|
+
strokePointsToPathData2 as strokePointsToPathData,
|
|
2795
|
+
strokeToShapeNode,
|
|
2581
2796
|
subtractPaths,
|
|
2582
2797
|
subtractPolygons,
|
|
2583
2798
|
swapCanvasInstance,
|
|
@@ -2600,6 +2815,7 @@ export {
|
|
|
2600
2815
|
useCanvasClipboard,
|
|
2601
2816
|
useCanvasComponents,
|
|
2602
2817
|
useCanvasDocking,
|
|
2818
|
+
useCanvasDraw,
|
|
2603
2819
|
useCanvasExplosion,
|
|
2604
2820
|
useCanvasGraph,
|
|
2605
2821
|
useCanvasLayout,
|