@pixerate/editor-react 0.83.0 → 0.84.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/dist/vector/index.cjs +371 -318
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +12 -1
- package/dist/vector/index.d.ts +12 -1
- package/dist/vector/index.js +239 -187
- package/dist/vector/index.js.map +1 -1
- package/package.json +3 -3
package/dist/vector/index.cjs
CHANGED
|
@@ -45,6 +45,7 @@ __export(vector_exports, {
|
|
|
45
45
|
VectorLensPanel: () => VectorLensPanel,
|
|
46
46
|
VectorMaskPanel: () => VectorMaskPanel,
|
|
47
47
|
VectorMaskedNodes: () => VectorMaskedNodes,
|
|
48
|
+
VectorPerspectivePanel: () => VectorPerspectivePanel,
|
|
48
49
|
VectorProviderEffectsPanel: () => VectorProviderEffectsPanel,
|
|
49
50
|
VectorSceneNodes: () => VectorSceneNodes,
|
|
50
51
|
VectorShadingPanel: () => VectorShadingPanel,
|
|
@@ -694,6 +695,11 @@ function VectorCanvas({
|
|
|
694
695
|
sh.lines.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d, stroke: accentColor, strokeWidth: 1, opacity: 0.7 }, i)),
|
|
695
696
|
sh.points.map((p) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { "data-vector-shading-point": p.index, "data-selected": p.selected || void 0, cx: p.x, cy: p.y, r: p.selected ? 6 : 4.5, fill: p.color, stroke: p.selected ? accentColor : "#ffffff", strokeWidth: p.selected ? 2 : 1.5 }, p.index))
|
|
696
697
|
] }, `shading:${sh.nodeId}`)),
|
|
698
|
+
overlay.perspective && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-perspective-grid": "", fill: "none", pointerEvents: "none", children: [
|
|
699
|
+
overlay.perspective.planes.map((pl) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { "data-vector-perspective-plane": pl.plane, "data-active": pl.active || void 0, d: pl.d, stroke: pl.active ? accentColor : guideColor, strokeWidth: pl.active ? 1 : 0.75, opacity: pl.active ? 0.55 : 0.25 }, pl.plane)),
|
|
700
|
+
overlay.perspective.vanishingPoints.map((v, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { "data-vector-vanishing-point": i, cx: v.x, cy: v.y, r: 4, stroke: accentColor, strokeWidth: 1.5 }, i)),
|
|
701
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { "data-vector-perspective-origin": "", cx: overlay.perspective.origin.x, cy: overlay.perspective.origin.y, r: 3, fill: accentColor })
|
|
702
|
+
] }),
|
|
697
703
|
overlay.symmetry.map((sy) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { "data-vector-symmetry-axes": sy.nodeId, stroke: accentColor, strokeDasharray: sy.drawing ? void 0 : "6 4", opacity: sy.drawing ? 0.9 : 0.6, children: sy.lines.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: l.x1, y1: l.y1, x2: l.x2, y2: l.y2 }, i)) }, `sym:${sy.nodeId}`)),
|
|
698
704
|
overlay.trackingPoints.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { "data-vector-tracking-point": "", d: `M${t.x - 5} ${t.y}H${t.x + 5}M${t.x} ${t.y - 5}V${t.y + 5}`, stroke: guideColor, strokeWidth: 1.5 }, `track:${i}`)),
|
|
699
705
|
overlay.typedEntry && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-typed-entry": "", transform: `translate(${overlay.typedEntry.x + 14} ${overlay.typedEntry.y + 18})`, children: [
|
|
@@ -830,8 +836,8 @@ function VectorCanvas({
|
|
|
830
836
|
}
|
|
831
837
|
|
|
832
838
|
// src/vector/VectorToolbar.tsx
|
|
833
|
-
var
|
|
834
|
-
var
|
|
839
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
840
|
+
var import_vector18 = require("@pixerate/editor/vector");
|
|
835
841
|
|
|
836
842
|
// src/vector/VectorEffectsPanel.tsx
|
|
837
843
|
var import_vector4 = require("@pixerate/editor/vector");
|
|
@@ -2082,38 +2088,83 @@ function VectorSymmetryPanel({ controller, className }) {
|
|
|
2082
2088
|
] });
|
|
2083
2089
|
}
|
|
2084
2090
|
|
|
2085
|
-
// src/vector/
|
|
2091
|
+
// src/vector/VectorPerspectivePanel.tsx
|
|
2092
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
2086
2093
|
var import_vector15 = require("@pixerate/editor/vector");
|
|
2087
2094
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2095
|
+
var buttonClass13 = "inline-flex h-7 min-w-7 items-center justify-center rounded-md border border-border bg-background px-1.5 text-xs font-medium text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40 aria-pressed:bg-primary aria-pressed:text-primary-foreground";
|
|
2088
2096
|
var selectClass10 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2097
|
+
var PLANE_LABELS = { floor: "Floor", left: "Left wall", right: "Right wall", side: "Side wall", front: "Front" };
|
|
2098
|
+
function VectorPerspectivePanel({ controller, className }) {
|
|
2099
|
+
const state = useVectorEditorState(controller);
|
|
2100
|
+
const grid = state.document.perspective ?? null;
|
|
2101
|
+
const planes = grid ? (0, import_vector15.vectorPerspectivePlanes)(grid) : [];
|
|
2102
|
+
const [attachTo, setAttachTo] = import_react10.default.useState("");
|
|
2103
|
+
const target = (state.perspectivePlane ?? attachTo) || planes[0];
|
|
2104
|
+
const add = (n) => controller.setPerspective((0, import_vector15.vectorPerspectivePreset)(n, state.document.width, state.document.height));
|
|
2105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-perspective-panel": "", "aria-label": "Perspective", children: [
|
|
2106
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2107
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Perspective" }),
|
|
2108
|
+
[1, 2, 3].map((n) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("button", { type: "button", className: buttonClass13, "aria-pressed": grid?.vanishingPoints.length === n, "data-vector-perspective-preset": n, title: `A ${n}-point perspective grid for the page`, onClick: () => add(n), children: [
|
|
2109
|
+
n,
|
|
2110
|
+
"-pt"
|
|
2111
|
+
] }, n))
|
|
2112
|
+
] }),
|
|
2113
|
+
grid && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2114
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "w-16" }),
|
|
2115
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("select", { "aria-label": "Draw on plane", title: "New rectangles, ellipses, polygons and stars are drawn on this plane", className: selectClass10, value: state.perspectivePlane ?? "", onChange: (e) => controller.setPerspectivePlane(e.target.value || null), children: [
|
|
2116
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: "", children: "Draw flat" }),
|
|
2117
|
+
planes.map((p) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("option", { value: p, children: [
|
|
2118
|
+
"Draw on ",
|
|
2119
|
+
PLANE_LABELS[p].toLowerCase()
|
|
2120
|
+
] }, p))
|
|
2121
|
+
] })
|
|
2122
|
+
] }),
|
|
2123
|
+
grid && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2124
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "w-16" }),
|
|
2125
|
+
!state.perspectivePlane && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("select", { "aria-label": "Attach to plane", className: "h-7 w-24 rounded border border-border bg-background px-1 text-xs", value: attachTo || planes[0], onChange: (e) => setAttachTo(e.target.value), children: planes.map((p) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: p, children: PLANE_LABELS[p] }, p)) }),
|
|
2126
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", className: buttonClass13, disabled: !state.selection.length, title: "Lay the selection onto the plane (read flat from the grid's origin)", onClick: () => controller.attachToPerspective(target), children: "Attach" }),
|
|
2127
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", title: "Show the grid on the canvas", children: [
|
|
2128
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("input", { type: "checkbox", "aria-label": "Show perspective grid", checked: grid.visible !== false, onChange: (e) => controller.setPerspective({ ...grid, visible: e.target.checked }) }),
|
|
2129
|
+
"Show"
|
|
2130
|
+
] }),
|
|
2131
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", className: buttonClass13, title: "Remove the grid (art on it stays)", onClick: () => controller.setPerspective(null), children: "Remove" })
|
|
2132
|
+
] })
|
|
2133
|
+
] });
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
// src/vector/VectorLensPanel.tsx
|
|
2137
|
+
var import_vector16 = require("@pixerate/editor/vector");
|
|
2138
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
2139
|
+
var selectClass11 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2089
2140
|
var numberClass9 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
2090
2141
|
function VectorLensPanel({ controller, className }) {
|
|
2091
2142
|
const state = useVectorEditorState(controller);
|
|
2092
2143
|
const path = state.selection.map((id) => controller.getNode(id)).find((n) => n?.type === "path" && n.subpaths.some((sp) => sp.closed) && !n.connector);
|
|
2093
2144
|
if (!path) return null;
|
|
2094
2145
|
const lens = path.lens ?? null;
|
|
2095
|
-
const spec = lens ?
|
|
2146
|
+
const spec = lens ? import_vector16.VECTOR_LENS_SPECS[lens.type] : null;
|
|
2096
2147
|
const ids = [path.id];
|
|
2097
|
-
return /* @__PURE__ */ (0,
|
|
2098
|
-
/* @__PURE__ */ (0,
|
|
2099
|
-
/* @__PURE__ */ (0,
|
|
2100
|
-
/* @__PURE__ */ (0,
|
|
2148
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-lens-panel": "", "aria-label": "Lens", children: [
|
|
2149
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2150
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Lens" }),
|
|
2151
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
2101
2152
|
"select",
|
|
2102
2153
|
{
|
|
2103
2154
|
"aria-label": "Lens type",
|
|
2104
|
-
className:
|
|
2155
|
+
className: selectClass11,
|
|
2105
2156
|
value: lens?.type ?? "",
|
|
2106
2157
|
onChange: (e) => e.target.value ? controller.setLens({ type: e.target.value }, { ids }) : controller.setLens(null, { ids }),
|
|
2107
2158
|
children: [
|
|
2108
|
-
/* @__PURE__ */ (0,
|
|
2109
|
-
|
|
2159
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("option", { value: "", children: "None" }),
|
|
2160
|
+
import_vector16.VECTOR_LENS_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("option", { value: t, children: import_vector16.VECTOR_LENS_LABELS[t] }, t))
|
|
2110
2161
|
]
|
|
2111
2162
|
}
|
|
2112
2163
|
)
|
|
2113
2164
|
] }),
|
|
2114
|
-
lens && spec && /* @__PURE__ */ (0,
|
|
2115
|
-
/* @__PURE__ */ (0,
|
|
2116
|
-
/* @__PURE__ */ (0,
|
|
2165
|
+
lens && spec && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2166
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "w-16" }),
|
|
2167
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2117
2168
|
"input",
|
|
2118
2169
|
{
|
|
2119
2170
|
type: "number",
|
|
@@ -2130,21 +2181,21 @@ function VectorLensPanel({ controller, className }) {
|
|
|
2130
2181
|
}
|
|
2131
2182
|
}
|
|
2132
2183
|
),
|
|
2133
|
-
spec.color !== null && /* @__PURE__ */ (0,
|
|
2184
|
+
spec.color !== null && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("input", { type: "color", "aria-label": "Lens colour", title: "Lens colour", className: "h-7 w-9 rounded border border-border bg-background", value: lens.color ?? spec.color, onChange: (e) => controller.setLens({ color: e.target.value }, { ids, merge: `lens-color-${path.id}` }) })
|
|
2134
2185
|
] })
|
|
2135
2186
|
] });
|
|
2136
2187
|
}
|
|
2137
2188
|
|
|
2138
2189
|
// src/vector/VectorGradientEditor.tsx
|
|
2139
|
-
var
|
|
2140
|
-
var
|
|
2141
|
-
var
|
|
2190
|
+
var import_vector17 = require("@pixerate/editor/vector");
|
|
2191
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
2192
|
+
var selectClass12 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2142
2193
|
var numberClass10 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
2143
|
-
var
|
|
2194
|
+
var buttonClass14 = "inline-flex h-7 min-w-7 items-center justify-center rounded border border-border bg-background px-1.5 text-xs text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40 aria-pressed:bg-primary aria-pressed:text-primary-foreground";
|
|
2144
2195
|
var percent = (v) => Math.round(v * 1e3) / 10;
|
|
2145
2196
|
function VectorGradientEditor({ controller, className }) {
|
|
2146
2197
|
const state = useVectorEditorState(controller);
|
|
2147
|
-
const ed = (0,
|
|
2198
|
+
const ed = (0, import_vector17.getVectorGradientEditor)(state);
|
|
2148
2199
|
if (!ed) return null;
|
|
2149
2200
|
const g = ed.gradient;
|
|
2150
2201
|
const sel = ed.selected;
|
|
@@ -2152,26 +2203,26 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2152
2203
|
const setType = (value) => {
|
|
2153
2204
|
if (value === "solid") {
|
|
2154
2205
|
const first = ed.stops[0];
|
|
2155
|
-
controller.setStyle({ [ed.target]: (0,
|
|
2206
|
+
controller.setStyle({ [ed.target]: (0, import_vector17.vectorPaintToHex)(first?.color) ?? first?.color ?? "#000000" }, void 0, { label: "Solid Colour" });
|
|
2156
2207
|
} else controller.setGradient({ type: value });
|
|
2157
2208
|
};
|
|
2158
|
-
return /* @__PURE__ */ (0,
|
|
2159
|
-
/* @__PURE__ */ (0,
|
|
2160
|
-
/* @__PURE__ */ (0,
|
|
2161
|
-
["fill", "stroke"].map((t) => /* @__PURE__ */ (0,
|
|
2162
|
-
ed.mixed && /* @__PURE__ */ (0,
|
|
2209
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: `space-y-1.5 ${className ?? ""}`, "data-vector-gradient-editor": ed.target, "aria-label": "Gradient", children: [
|
|
2210
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
2211
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Gradient" }),
|
|
2212
|
+
["fill", "stroke"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: buttonClass14, "aria-pressed": ed.target === t, onClick: () => controller.setGradientTarget(t), children: t === "fill" ? "Fill" : "Stroke" }, t)),
|
|
2213
|
+
ed.mixed && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
2163
2214
|
] }),
|
|
2164
|
-
/* @__PURE__ */ (0,
|
|
2165
|
-
/* @__PURE__ */ (0,
|
|
2166
|
-
/* @__PURE__ */ (0,
|
|
2167
|
-
/* @__PURE__ */ (0,
|
|
2168
|
-
|
|
2215
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
2216
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Type" }),
|
|
2217
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("select", { "aria-label": "Gradient type", className: selectClass12, value: ed.type ?? "solid", onChange: (e) => setType(e.target.value), children: [
|
|
2218
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("option", { value: "solid", children: "Solid" }),
|
|
2219
|
+
import_vector17.VECTOR_GRADIENT_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("option", { value: t, children: import_vector17.VECTOR_GRADIENT_TYPE_LABELS[t] }, t))
|
|
2169
2220
|
] }),
|
|
2170
|
-
/* @__PURE__ */ (0,
|
|
2221
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: buttonClass14, "aria-label": "Reverse gradient", title: "Reverse gradient", disabled: !g, onClick: () => controller.reverseGradient(), children: "\u21C4" })
|
|
2171
2222
|
] }),
|
|
2172
|
-
g && /* @__PURE__ */ (0,
|
|
2173
|
-
/* @__PURE__ */ (0,
|
|
2174
|
-
/* @__PURE__ */ (0,
|
|
2223
|
+
g && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
2224
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "relative h-8", "data-vector-gradient-ramp": "", children: [
|
|
2225
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2175
2226
|
"div",
|
|
2176
2227
|
{
|
|
2177
2228
|
role: "button",
|
|
@@ -2185,7 +2236,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2185
2236
|
}
|
|
2186
2237
|
}
|
|
2187
2238
|
),
|
|
2188
|
-
ed.stops.map((s) => /* @__PURE__ */ (0,
|
|
2239
|
+
ed.stops.map((s) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2189
2240
|
"button",
|
|
2190
2241
|
{
|
|
2191
2242
|
type: "button",
|
|
@@ -2199,21 +2250,21 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2199
2250
|
s.index
|
|
2200
2251
|
))
|
|
2201
2252
|
] }),
|
|
2202
|
-
sel && /* @__PURE__ */ (0,
|
|
2203
|
-
/* @__PURE__ */ (0,
|
|
2253
|
+
sel && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", "data-vector-gradient-selected-stop": sel.index, children: [
|
|
2254
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2204
2255
|
"input",
|
|
2205
2256
|
{
|
|
2206
2257
|
type: "color",
|
|
2207
2258
|
"aria-label": "Stop colour",
|
|
2208
2259
|
className: "h-7 w-9 cursor-pointer rounded border border-border bg-background",
|
|
2209
|
-
value: (0,
|
|
2260
|
+
value: (0, import_vector17.vectorPaintToHex)(sel.color) ?? "#000000",
|
|
2210
2261
|
onChange: (e) => controller.setGradientStop(sel.index, { color: e.target.value }, { merge: `gradient-stop-color-${sel.index}` }),
|
|
2211
2262
|
onBlur: end
|
|
2212
2263
|
}
|
|
2213
2264
|
),
|
|
2214
|
-
/* @__PURE__ */ (0,
|
|
2265
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
2215
2266
|
"Opacity",
|
|
2216
|
-
/* @__PURE__ */ (0,
|
|
2267
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2217
2268
|
"input",
|
|
2218
2269
|
{
|
|
2219
2270
|
type: "number",
|
|
@@ -2230,9 +2281,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2230
2281
|
}
|
|
2231
2282
|
)
|
|
2232
2283
|
] }),
|
|
2233
|
-
/* @__PURE__ */ (0,
|
|
2284
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
2234
2285
|
"At",
|
|
2235
|
-
/* @__PURE__ */ (0,
|
|
2286
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2236
2287
|
"input",
|
|
2237
2288
|
{
|
|
2238
2289
|
type: "number",
|
|
@@ -2249,9 +2300,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2249
2300
|
}
|
|
2250
2301
|
)
|
|
2251
2302
|
] }),
|
|
2252
|
-
!sel.last && /* @__PURE__ */ (0,
|
|
2303
|
+
!sel.last && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
2253
2304
|
"Midpoint",
|
|
2254
|
-
/* @__PURE__ */ (0,
|
|
2305
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2255
2306
|
"input",
|
|
2256
2307
|
{
|
|
2257
2308
|
type: "number",
|
|
@@ -2268,15 +2319,15 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2268
2319
|
}
|
|
2269
2320
|
)
|
|
2270
2321
|
] }),
|
|
2271
|
-
/* @__PURE__ */ (0,
|
|
2322
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", className: buttonClass14, "aria-label": "Delete stop", title: "Delete stop", disabled: ed.stops.length <= 2, onClick: () => controller.removeGradientStop(sel.index), children: "\u2715" })
|
|
2272
2323
|
] }),
|
|
2273
|
-
/* @__PURE__ */ (0,
|
|
2274
|
-
/* @__PURE__ */ (0,
|
|
2275
|
-
/* @__PURE__ */ (0,
|
|
2324
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2325
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "w-16", children: "Colours" }),
|
|
2326
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("select", { "aria-label": "Gradient interpolation", className: selectClass12, value: ed.interpolation, onChange: (e) => controller.setGradient({ interpolation: e.target.value }), children: import_vector17.VECTOR_GRADIENT_INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("option", { value: i, children: import_vector17.VECTOR_GRADIENT_INTERPOLATION_LABELS[i] }, i)) })
|
|
2276
2327
|
] }),
|
|
2277
|
-
/* @__PURE__ */ (0,
|
|
2278
|
-
/* @__PURE__ */ (0,
|
|
2279
|
-
/* @__PURE__ */ (0,
|
|
2328
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2329
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "w-16", children: "Smooth" }),
|
|
2330
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2280
2331
|
"input",
|
|
2281
2332
|
{
|
|
2282
2333
|
type: "range",
|
|
@@ -2292,26 +2343,26 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2292
2343
|
}
|
|
2293
2344
|
)
|
|
2294
2345
|
] }),
|
|
2295
|
-
/* @__PURE__ */ (0,
|
|
2296
|
-
/* @__PURE__ */ (0,
|
|
2297
|
-
/* @__PURE__ */ (0,
|
|
2346
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2347
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "w-16", children: "Spread" }),
|
|
2348
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("select", { "aria-label": "Gradient spread", className: selectClass12, value: ed.spread, onChange: (e) => controller.setGradient({ spread: e.target.value }), children: import_vector17.VECTOR_GRADIENT_SPREADS.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("option", { value: sp, children: import_vector17.VECTOR_GRADIENT_SPREAD_LABELS[sp] }, sp)) })
|
|
2298
2349
|
] }),
|
|
2299
|
-
ed.target === "stroke" && /* @__PURE__ */ (0,
|
|
2300
|
-
/* @__PURE__ */ (0,
|
|
2301
|
-
/* @__PURE__ */ (0,
|
|
2350
|
+
ed.target === "stroke" && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2351
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "w-16", children: "On stroke" }),
|
|
2352
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("select", { "aria-label": "Gradient on stroke", className: selectClass12, value: ed.strokeMode, onChange: (e) => controller.setGradient({ strokeMode: e.target.value }), children: import_vector17.VECTOR_STROKE_GRADIENT_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("option", { value: m, children: import_vector17.VECTOR_STROKE_GRADIENT_MODE_LABELS[m] }, m)) })
|
|
2302
2353
|
] })
|
|
2303
2354
|
] })
|
|
2304
2355
|
] });
|
|
2305
2356
|
}
|
|
2306
2357
|
|
|
2307
2358
|
// src/vector/VectorToolbar.tsx
|
|
2308
|
-
var
|
|
2359
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
2309
2360
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
2310
2361
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
2311
|
-
var
|
|
2362
|
+
var buttonClass15 = "inline-flex h-8 min-w-8 items-center justify-center rounded-md border border-border bg-background px-2 text-xs font-medium text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40 aria-pressed:bg-primary aria-pressed:text-primary-foreground";
|
|
2312
2363
|
function VectorToolbar({
|
|
2313
2364
|
controller,
|
|
2314
|
-
tools =
|
|
2365
|
+
tools = import_vector18.VECTOR_TOOLS,
|
|
2315
2366
|
showHistory = true,
|
|
2316
2367
|
showArrange = true,
|
|
2317
2368
|
showSnap = true,
|
|
@@ -2325,36 +2376,36 @@ function VectorToolbar({
|
|
|
2325
2376
|
const points = state.tool === "direct" ? state.selectedAnchors.length : 0;
|
|
2326
2377
|
const editing = state.editing;
|
|
2327
2378
|
const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === "group");
|
|
2328
|
-
const maskSelected = state.selection.some((id) => (0,
|
|
2329
|
-
const [live, setLive] =
|
|
2379
|
+
const maskSelected = state.selection.some((id) => (0, import_vector18.isVectorMaskGroup)(controller.getNode(id)));
|
|
2380
|
+
const [live, setLive] = import_react11.default.useState(false);
|
|
2330
2381
|
const booleanDisabled = live ? count < 1 : count < 2;
|
|
2331
|
-
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0,
|
|
2332
|
-
return /* @__PURE__ */ (0,
|
|
2333
|
-
/* @__PURE__ */ (0,
|
|
2382
|
+
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: buttonClass15, title, "aria-label": title, disabled, onClick: () => void run(), children: label }, label);
|
|
2383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { role: "toolbar", "aria-label": "Vector tools", className: `flex flex-wrap items-center gap-1 ${className ?? ""}`, children: [
|
|
2384
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Tools", children: tools.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2334
2385
|
"button",
|
|
2335
2386
|
{
|
|
2336
2387
|
type: "button",
|
|
2337
2388
|
"data-vector-tool": tool,
|
|
2338
|
-
className:
|
|
2389
|
+
className: buttonClass15,
|
|
2339
2390
|
"aria-pressed": state.tool === tool,
|
|
2340
|
-
title: `${(0,
|
|
2341
|
-
"aria-label": (0,
|
|
2391
|
+
title: `${(0, import_vector18.vectorToolLabel)(tool)} (${import_vector18.VECTOR_TOOL_SHORTCUTS[tool]})`,
|
|
2392
|
+
"aria-label": (0, import_vector18.vectorToolLabel)(tool),
|
|
2342
2393
|
onClick: () => controller.setTool(tool),
|
|
2343
|
-
children:
|
|
2394
|
+
children: import_vector18.VECTOR_TOOL_GLYPHS[tool]
|
|
2344
2395
|
},
|
|
2345
2396
|
tool
|
|
2346
2397
|
)) }),
|
|
2347
|
-
showHistory && /* @__PURE__ */ (0,
|
|
2398
|
+
showHistory && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "History", children: [
|
|
2348
2399
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
2349
2400
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
2350
2401
|
] }),
|
|
2351
|
-
showSnap && /* @__PURE__ */ (0,
|
|
2352
|
-
/* @__PURE__ */ (0,
|
|
2402
|
+
showSnap && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Snapping", children: [
|
|
2403
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2353
2404
|
"button",
|
|
2354
2405
|
{
|
|
2355
2406
|
type: "button",
|
|
2356
2407
|
"data-vector-snap": "",
|
|
2357
|
-
className:
|
|
2408
|
+
className: buttonClass15,
|
|
2358
2409
|
"aria-pressed": state.snap.objects,
|
|
2359
2410
|
title: `${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`,
|
|
2360
2411
|
"aria-label": VECTOR_SNAP_TITLE,
|
|
@@ -2362,18 +2413,18 @@ function VectorToolbar({
|
|
|
2362
2413
|
children: "Snap"
|
|
2363
2414
|
}
|
|
2364
2415
|
),
|
|
2365
|
-
/* @__PURE__ */ (0,
|
|
2416
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2366
2417
|
"select",
|
|
2367
2418
|
{
|
|
2368
2419
|
"data-vector-polar": "",
|
|
2369
2420
|
"aria-label": "Polar tracking increment",
|
|
2370
2421
|
title: "Polar tracking: the angles drawn points snap to from where they leave",
|
|
2371
2422
|
className: "h-8 rounded-md border border-border bg-background px-1 text-xs",
|
|
2372
|
-
value: String((0,
|
|
2373
|
-
onChange: (e) => controller.setSnap({ angles: (0,
|
|
2423
|
+
value: String((0, import_vector18.vectorPolarIncrementOf)(state.snap.angles) ?? ""),
|
|
2424
|
+
onChange: (e) => controller.setSnap({ angles: (0, import_vector18.vectorPolarAngles)(Number(e.target.value)) }),
|
|
2374
2425
|
children: [
|
|
2375
|
-
(0,
|
|
2376
|
-
[90, 45, 30, 15].map((n) => /* @__PURE__ */ (0,
|
|
2426
|
+
(0, import_vector18.vectorPolarIncrementOf)(state.snap.angles) === null && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: "", children: "Custom" }),
|
|
2427
|
+
[90, 45, 30, 15].map((n) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("option", { value: n, children: [
|
|
2377
2428
|
n,
|
|
2378
2429
|
"\xB0"
|
|
2379
2430
|
] }, n))
|
|
@@ -2381,13 +2432,13 @@ function VectorToolbar({
|
|
|
2381
2432
|
}
|
|
2382
2433
|
)
|
|
2383
2434
|
] }),
|
|
2384
|
-
showPathEdit && /* @__PURE__ */ (0,
|
|
2385
|
-
|
|
2435
|
+
showPathEdit && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Path editing", children: [
|
|
2436
|
+
import_vector18.VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2386
2437
|
"button",
|
|
2387
2438
|
{
|
|
2388
2439
|
type: "button",
|
|
2389
2440
|
"data-vector-path-action": a.id,
|
|
2390
|
-
className:
|
|
2441
|
+
className: buttonClass15,
|
|
2391
2442
|
title: a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title,
|
|
2392
2443
|
"aria-label": a.title,
|
|
2393
2444
|
disabled: !a.enabled(count, points),
|
|
@@ -2396,12 +2447,12 @@ function VectorToolbar({
|
|
|
2396
2447
|
},
|
|
2397
2448
|
a.id
|
|
2398
2449
|
)),
|
|
2399
|
-
|
|
2450
|
+
import_vector18.VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2400
2451
|
"button",
|
|
2401
2452
|
{
|
|
2402
2453
|
type: "button",
|
|
2403
2454
|
"data-vector-edit": t.key,
|
|
2404
|
-
className:
|
|
2455
|
+
className: buttonClass15,
|
|
2405
2456
|
"aria-pressed": editing[t.key],
|
|
2406
2457
|
title: t.title,
|
|
2407
2458
|
"aria-label": t.title,
|
|
@@ -2410,9 +2461,9 @@ function VectorToolbar({
|
|
|
2410
2461
|
},
|
|
2411
2462
|
t.key
|
|
2412
2463
|
)),
|
|
2413
|
-
state.tool === "pencil" && /* @__PURE__ */ (0,
|
|
2464
|
+
state.tool === "pencil" && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
2414
2465
|
"Smoothing",
|
|
2415
|
-
/* @__PURE__ */ (0,
|
|
2466
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2416
2467
|
"input",
|
|
2417
2468
|
{
|
|
2418
2469
|
type: "range",
|
|
@@ -2426,9 +2477,9 @@ function VectorToolbar({
|
|
|
2426
2477
|
}
|
|
2427
2478
|
)
|
|
2428
2479
|
] }),
|
|
2429
|
-
state.tool === "eraser" && /* @__PURE__ */ (0,
|
|
2480
|
+
state.tool === "eraser" && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
2430
2481
|
"Size",
|
|
2431
|
-
/* @__PURE__ */ (0,
|
|
2482
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2432
2483
|
"input",
|
|
2433
2484
|
{
|
|
2434
2485
|
type: "number",
|
|
@@ -2444,26 +2495,26 @@ function VectorToolbar({
|
|
|
2444
2495
|
}
|
|
2445
2496
|
)
|
|
2446
2497
|
] }),
|
|
2447
|
-
state.tool === "paintBucket" && /* @__PURE__ */ (0,
|
|
2498
|
+
state.tool === "paintBucket" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2448
2499
|
"button",
|
|
2449
2500
|
{
|
|
2450
2501
|
type: "button",
|
|
2451
2502
|
"data-vector-fill-gap": "",
|
|
2452
|
-
className:
|
|
2503
|
+
className: buttonClass15,
|
|
2453
2504
|
"aria-pressed": editing.fillGap > 0,
|
|
2454
2505
|
title: "Close small gaps between path ends when filling",
|
|
2455
2506
|
"aria-label": "Close gaps",
|
|
2456
|
-
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 :
|
|
2507
|
+
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : import_vector18.VECTOR_FILL_GAP }),
|
|
2457
2508
|
children: "Gaps"
|
|
2458
2509
|
}
|
|
2459
2510
|
)
|
|
2460
2511
|
] }),
|
|
2461
|
-
showDistort && /* @__PURE__ */ (0,
|
|
2512
|
+
showDistort && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Distort", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2462
2513
|
"button",
|
|
2463
2514
|
{
|
|
2464
2515
|
type: "button",
|
|
2465
2516
|
"data-vector-free-distort": "",
|
|
2466
|
-
className:
|
|
2517
|
+
className: buttonClass15,
|
|
2467
2518
|
"aria-pressed": state.freeDistort,
|
|
2468
2519
|
title: `Free Distort: drag a corner of the selection box to distort in perspective (Shift+Alt+${modKeyLabel()}: symmetric perspective; ${modKeyLabel()}-drag a side to skew)`,
|
|
2469
2520
|
"aria-label": "Free Distort",
|
|
@@ -2471,15 +2522,15 @@ function VectorToolbar({
|
|
|
2471
2522
|
children: "Distort"
|
|
2472
2523
|
}
|
|
2473
2524
|
) }),
|
|
2474
|
-
showBlend && /* @__PURE__ */ (0,
|
|
2475
|
-
showArrange && /* @__PURE__ */ (0,
|
|
2476
|
-
/* @__PURE__ */ (0,
|
|
2477
|
-
/* @__PURE__ */ (0,
|
|
2525
|
+
showBlend && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorBlendControls, { controller }),
|
|
2526
|
+
showArrange && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
2527
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Combine", children: [
|
|
2528
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2478
2529
|
"button",
|
|
2479
2530
|
{
|
|
2480
2531
|
type: "button",
|
|
2481
2532
|
"data-vector-live-boolean": "",
|
|
2482
|
-
className:
|
|
2533
|
+
className: buttonClass15,
|
|
2483
2534
|
"aria-pressed": live,
|
|
2484
2535
|
title: "Live booleans: keep the shapes editable",
|
|
2485
2536
|
"aria-label": "Live booleans",
|
|
@@ -2496,12 +2547,12 @@ function VectorToolbar({
|
|
|
2496
2547
|
act("\u25D0", `Make Clipping Mask (${modKeyLabel()}+7)`, () => controller.makeMask("clip"), count < 2),
|
|
2497
2548
|
act("\u25D1", `Release Mask (${modKeyLabel()}+Alt+7)`, () => controller.releaseMask(), !maskSelected)
|
|
2498
2549
|
] }),
|
|
2499
|
-
/* @__PURE__ */ (0,
|
|
2550
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Pathfinder", children: import_vector18.VECTOR_PATHFINDER_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2500
2551
|
"button",
|
|
2501
2552
|
{
|
|
2502
2553
|
type: "button",
|
|
2503
2554
|
"data-vector-pathfinder": a.id,
|
|
2504
|
-
className:
|
|
2555
|
+
className: buttonClass15,
|
|
2505
2556
|
title: a.title,
|
|
2506
2557
|
"aria-label": a.title,
|
|
2507
2558
|
disabled: count < a.min,
|
|
@@ -2510,7 +2561,7 @@ function VectorToolbar({
|
|
|
2510
2561
|
},
|
|
2511
2562
|
a.id
|
|
2512
2563
|
)) }),
|
|
2513
|
-
/* @__PURE__ */ (0,
|
|
2564
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
2514
2565
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
2515
2566
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
2516
2567
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -2525,22 +2576,22 @@ function VectorToolbar({
|
|
|
2525
2576
|
}
|
|
2526
2577
|
function VectorBlendControls({ controller }) {
|
|
2527
2578
|
const state = useVectorEditorState(controller);
|
|
2528
|
-
const blend = (0,
|
|
2579
|
+
const blend = (0, import_vector18.getVectorBlendControls)(state);
|
|
2529
2580
|
const o = blend.options;
|
|
2530
2581
|
const selected = blend.ids.length > 0;
|
|
2531
|
-
return /* @__PURE__ */ (0,
|
|
2532
|
-
/* @__PURE__ */ (0,
|
|
2533
|
-
/* @__PURE__ */ (0,
|
|
2582
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Blend", "data-vector-blend-controls": "", children: [
|
|
2583
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", "data-vector-blend-action": "make", className: buttonClass15, title: "Make Blend", "aria-label": "Make Blend", disabled: !blend.canBlend, onClick: () => controller.blend(), children: "\u29D3" }),
|
|
2584
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2534
2585
|
"select",
|
|
2535
2586
|
{
|
|
2536
2587
|
"aria-label": "Blend spacing",
|
|
2537
2588
|
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
2538
2589
|
value: o.spacing,
|
|
2539
|
-
onChange: (e) => (0,
|
|
2540
|
-
children:
|
|
2590
|
+
onChange: (e) => (0, import_vector18.applyVectorBlendOptions)(controller, { spacing: e.target.value }),
|
|
2591
|
+
children: import_vector18.VECTOR_BLEND_SPACINGS.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: sp, children: import_vector18.VECTOR_BLEND_SPACING_LABELS[sp] }, sp))
|
|
2541
2592
|
}
|
|
2542
2593
|
),
|
|
2543
|
-
o.spacing !== "smoothColor" && /* @__PURE__ */ (0,
|
|
2594
|
+
o.spacing !== "smoothColor" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2544
2595
|
"input",
|
|
2545
2596
|
{
|
|
2546
2597
|
type: "number",
|
|
@@ -2552,29 +2603,29 @@ function VectorBlendControls({ controller }) {
|
|
|
2552
2603
|
onChange: (e) => {
|
|
2553
2604
|
const n = parseFloat(e.target.value);
|
|
2554
2605
|
if (!Number.isFinite(n) || n <= 0) return;
|
|
2555
|
-
(0,
|
|
2606
|
+
(0, import_vector18.applyVectorBlendOptions)(controller, o.spacing === "steps" ? { steps: n } : { distance: n });
|
|
2556
2607
|
}
|
|
2557
2608
|
}
|
|
2558
2609
|
),
|
|
2559
|
-
/* @__PURE__ */ (0,
|
|
2610
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2560
2611
|
"button",
|
|
2561
2612
|
{
|
|
2562
2613
|
type: "button",
|
|
2563
2614
|
"data-vector-blend-action": "orient",
|
|
2564
|
-
className:
|
|
2615
|
+
className: buttonClass15,
|
|
2565
2616
|
"aria-pressed": o.orientToSpine,
|
|
2566
2617
|
title: "Orient steps to the spine",
|
|
2567
2618
|
"aria-label": "Orient to spine",
|
|
2568
|
-
onClick: () => (0,
|
|
2619
|
+
onClick: () => (0, import_vector18.applyVectorBlendOptions)(controller, { orientToSpine: !o.orientToSpine }),
|
|
2569
2620
|
children: "\u293F"
|
|
2570
2621
|
}
|
|
2571
2622
|
),
|
|
2572
|
-
/* @__PURE__ */ (0,
|
|
2623
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2573
2624
|
"button",
|
|
2574
2625
|
{
|
|
2575
2626
|
type: "button",
|
|
2576
2627
|
"data-vector-blend-action": "spine",
|
|
2577
|
-
className:
|
|
2628
|
+
className: buttonClass15,
|
|
2578
2629
|
title: "Replace Spine (select a blend and a path)",
|
|
2579
2630
|
"aria-label": "Replace Spine",
|
|
2580
2631
|
disabled: !blend.canReplaceSpine,
|
|
@@ -2582,15 +2633,15 @@ function VectorBlendControls({ controller }) {
|
|
|
2582
2633
|
children: "\u2307"
|
|
2583
2634
|
}
|
|
2584
2635
|
),
|
|
2585
|
-
/* @__PURE__ */ (0,
|
|
2586
|
-
/* @__PURE__ */ (0,
|
|
2636
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", "data-vector-blend-action": "expand", className: buttonClass15, title: "Expand Blend", "aria-label": "Expand Blend", disabled: !selected, onClick: () => controller.expandBlend(), children: "\u29C9" }),
|
|
2637
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", "data-vector-blend-action": "release", className: buttonClass15, title: "Release Blend", "aria-label": "Release Blend", disabled: !selected, onClick: () => controller.releaseBlend(), children: "\u29C4" })
|
|
2587
2638
|
] });
|
|
2588
2639
|
}
|
|
2589
|
-
var
|
|
2640
|
+
var selectClass13 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2590
2641
|
var numberClass11 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
2591
2642
|
function VectorStylePanel({ controller, className }) {
|
|
2592
2643
|
const state = useVectorEditorState(controller);
|
|
2593
|
-
const style = (0,
|
|
2644
|
+
const style = (0, import_vector18.getVectorSelectionStyle)(state);
|
|
2594
2645
|
const d = state.defaults;
|
|
2595
2646
|
const source = style ?? {
|
|
2596
2647
|
fill: d.fill ?? null,
|
|
@@ -2603,7 +2654,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2603
2654
|
arrowAlign: d.arrowAlign ?? "extend",
|
|
2604
2655
|
startArrowScale: d.startArrowScale ?? 1,
|
|
2605
2656
|
endArrowScale: d.endArrowScale ?? 1,
|
|
2606
|
-
widthProfile: (0,
|
|
2657
|
+
widthProfile: (0, import_vector18.widthProfilePresetId)(d.strokeWidthProfile),
|
|
2607
2658
|
cornerRadius: d.cornerRadius,
|
|
2608
2659
|
cornerKind: d.cornerKind ?? "round",
|
|
2609
2660
|
cornerSmoothing: 0,
|
|
@@ -2617,19 +2668,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2617
2668
|
};
|
|
2618
2669
|
const setProfile = (id) => {
|
|
2619
2670
|
if (style) controller.setWidthProfile(id);
|
|
2620
|
-
else controller.setDefaults({ strokeWidthProfile: (0,
|
|
2671
|
+
else controller.setDefaults({ strokeWidthProfile: (0, import_vector18.widthProfilePreset)(id)?.length ? (0, import_vector18.widthProfilePreset)(id) : null });
|
|
2621
2672
|
};
|
|
2622
|
-
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0,
|
|
2673
|
+
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }) : null;
|
|
2623
2674
|
const arrowRow = (end, label) => {
|
|
2624
2675
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
2625
2676
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
2626
|
-
return /* @__PURE__ */ (0,
|
|
2627
|
-
/* @__PURE__ */ (0,
|
|
2628
|
-
/* @__PURE__ */ (0,
|
|
2629
|
-
/* @__PURE__ */ (0,
|
|
2630
|
-
|
|
2677
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
2678
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16 text-xs text-foreground", children: label }),
|
|
2679
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("select", { "aria-label": `${label} arrowhead`, className: selectClass13, value: source[key] ?? "", onChange: (e) => apply({ [key]: e.target.value || null }), children: [
|
|
2680
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: "", children: "None" }),
|
|
2681
|
+
import_vector18.VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: h, children: import_vector18.VECTOR_ARROWHEAD_LABELS[h] }, h))
|
|
2631
2682
|
] }),
|
|
2632
|
-
/* @__PURE__ */ (0,
|
|
2683
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2633
2684
|
"input",
|
|
2634
2685
|
{
|
|
2635
2686
|
type: "number",
|
|
@@ -2653,14 +2704,14 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2653
2704
|
};
|
|
2654
2705
|
const paintRow = (key, label) => {
|
|
2655
2706
|
const paint = source[key];
|
|
2656
|
-
const hex = (0,
|
|
2707
|
+
const hex = (0, import_vector18.vectorPaintToHex)(paint);
|
|
2657
2708
|
const on = paint !== null && paint !== "none";
|
|
2658
|
-
return /* @__PURE__ */ (0,
|
|
2659
|
-
/* @__PURE__ */ (0,
|
|
2660
|
-
/* @__PURE__ */ (0,
|
|
2709
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
2710
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex w-16 items-center gap-1.5 text-xs text-foreground", children: [
|
|
2711
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("input", { type: "checkbox", checked: on, "aria-label": `${label} on`, onChange: (e) => apply({ [key]: e.target.checked ? hex ?? "#000000" : null }) }),
|
|
2661
2712
|
label
|
|
2662
2713
|
] }),
|
|
2663
|
-
/* @__PURE__ */ (0,
|
|
2714
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2664
2715
|
"input",
|
|
2665
2716
|
{
|
|
2666
2717
|
type: "color",
|
|
@@ -2671,18 +2722,18 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2671
2722
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
2672
2723
|
}
|
|
2673
2724
|
),
|
|
2674
|
-
on && !hex && /* @__PURE__ */ (0,
|
|
2675
|
-
style?.mixed[key] && /* @__PURE__ */ (0,
|
|
2725
|
+
on && !hex && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate text-[11px] text-muted-foreground", children: typeof paint === "string" ? paint : "Gradient" }),
|
|
2726
|
+
style?.mixed[key] && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
2676
2727
|
] });
|
|
2677
2728
|
};
|
|
2678
|
-
return /* @__PURE__ */ (0,
|
|
2679
|
-
/* @__PURE__ */ (0,
|
|
2729
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "aria-label": style ? "Selection style" : "New shape style", children: [
|
|
2730
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: style ? "Selection" : "New shapes" }),
|
|
2680
2731
|
paintRow("fill", "Fill"),
|
|
2681
2732
|
paintRow("stroke", "Stroke"),
|
|
2682
|
-
style && /* @__PURE__ */ (0,
|
|
2683
|
-
/* @__PURE__ */ (0,
|
|
2684
|
-
/* @__PURE__ */ (0,
|
|
2685
|
-
/* @__PURE__ */ (0,
|
|
2733
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorGradientEditor, { controller }),
|
|
2734
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
2735
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16", children: "Width" }),
|
|
2736
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2686
2737
|
"input",
|
|
2687
2738
|
{
|
|
2688
2739
|
type: "number",
|
|
@@ -2698,33 +2749,33 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2698
2749
|
}
|
|
2699
2750
|
)
|
|
2700
2751
|
] }),
|
|
2701
|
-
/* @__PURE__ */ (0,
|
|
2702
|
-
/* @__PURE__ */ (0,
|
|
2703
|
-
/* @__PURE__ */ (0,
|
|
2752
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "strokeAlign", children: [
|
|
2753
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16", children: "Align" }),
|
|
2754
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("select", { "aria-label": "Stroke alignment", className: selectClass13, value: source.strokeAlign, onChange: (e) => apply({ strokeAlign: e.target.value }), children: Object.keys(import_vector18.VECTOR_STROKE_ALIGN_LABELS).map((a) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: a, children: import_vector18.VECTOR_STROKE_ALIGN_LABELS[a] }, a)) }),
|
|
2704
2755
|
mixed("strokeAlign")
|
|
2705
2756
|
] }),
|
|
2706
|
-
/* @__PURE__ */ (0,
|
|
2707
|
-
/* @__PURE__ */ (0,
|
|
2708
|
-
/* @__PURE__ */ (0,
|
|
2757
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "widthProfile", children: [
|
|
2758
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16", children: "Profile" }),
|
|
2759
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
2709
2760
|
"select",
|
|
2710
2761
|
{
|
|
2711
2762
|
"aria-label": "Width profile",
|
|
2712
|
-
className:
|
|
2763
|
+
className: selectClass13,
|
|
2713
2764
|
value: source.widthProfile,
|
|
2714
2765
|
onChange: (e) => {
|
|
2715
2766
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
2716
2767
|
},
|
|
2717
2768
|
children: [
|
|
2718
|
-
|
|
2719
|
-
source.widthProfile === "custom" && /* @__PURE__ */ (0,
|
|
2769
|
+
import_vector18.VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: p.id, children: p.label }, p.id)),
|
|
2770
|
+
source.widthProfile === "custom" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: "custom", disabled: true, children: "Custom" })
|
|
2720
2771
|
]
|
|
2721
2772
|
}
|
|
2722
2773
|
),
|
|
2723
|
-
/* @__PURE__ */ (0,
|
|
2774
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2724
2775
|
"button",
|
|
2725
2776
|
{
|
|
2726
2777
|
type: "button",
|
|
2727
|
-
className:
|
|
2778
|
+
className: buttonClass15,
|
|
2728
2779
|
title: "Reset to uniform width",
|
|
2729
2780
|
"aria-label": "Reset to uniform width",
|
|
2730
2781
|
disabled: source.widthProfile === "uniform" && !style?.mixed.widthProfile,
|
|
@@ -2734,20 +2785,20 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2734
2785
|
),
|
|
2735
2786
|
mixed("widthProfile")
|
|
2736
2787
|
] }),
|
|
2737
|
-
source.hasOpenPath && /* @__PURE__ */ (0,
|
|
2788
|
+
source.hasOpenPath && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
2738
2789
|
arrowRow("start", "Start"),
|
|
2739
2790
|
arrowRow("end", "End"),
|
|
2740
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0,
|
|
2741
|
-
/* @__PURE__ */ (0,
|
|
2742
|
-
/* @__PURE__ */ (0,
|
|
2743
|
-
/* @__PURE__ */ (0,
|
|
2744
|
-
/* @__PURE__ */ (0,
|
|
2791
|
+
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "arrowAlign", children: [
|
|
2792
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16", children: "Heads" }),
|
|
2793
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("select", { "aria-label": "Arrowhead alignment", className: selectClass13, value: source.arrowAlign, onChange: (e) => apply({ arrowAlign: e.target.value }), children: [
|
|
2794
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: "extend", children: "Tip past end" }),
|
|
2795
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: "tip", children: "Tip at end" })
|
|
2745
2796
|
] })
|
|
2746
2797
|
] })
|
|
2747
2798
|
] }),
|
|
2748
|
-
source.corners > 0 && /* @__PURE__ */ (0,
|
|
2749
|
-
/* @__PURE__ */ (0,
|
|
2750
|
-
/* @__PURE__ */ (0,
|
|
2799
|
+
source.corners > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": "corners", children: [
|
|
2800
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Corners" }),
|
|
2801
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2751
2802
|
"input",
|
|
2752
2803
|
{
|
|
2753
2804
|
type: "number",
|
|
@@ -2762,12 +2813,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2762
2813
|
}
|
|
2763
2814
|
}
|
|
2764
2815
|
),
|
|
2765
|
-
/* @__PURE__ */ (0,
|
|
2816
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("select", { "aria-label": "Corner kind", className: selectClass13, value: source.cornerKind, onChange: (e) => setCorners({ kind: e.target.value }), children: import_vector18.VECTOR_CORNER_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: k, children: import_vector18.VECTOR_CORNER_KIND_LABELS[k] }, k)) }),
|
|
2766
2817
|
mixed("cornerRadius")
|
|
2767
2818
|
] }),
|
|
2768
|
-
style && source.corners > 0 && source.cornerKind === "round" && source.cornerRadius > 0 && /* @__PURE__ */ (0,
|
|
2769
|
-
/* @__PURE__ */ (0,
|
|
2770
|
-
/* @__PURE__ */ (0,
|
|
2819
|
+
style && source.corners > 0 && source.cornerKind === "round" && source.cornerRadius > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "corner-smoothing", title: "Corner smoothing: squircle corners that ease into the curve (0.6 is iOS-like)", children: [
|
|
2820
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16", children: "Smoothing" }),
|
|
2821
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2771
2822
|
"input",
|
|
2772
2823
|
{
|
|
2773
2824
|
type: "range",
|
|
@@ -2782,9 +2833,9 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2782
2833
|
}
|
|
2783
2834
|
)
|
|
2784
2835
|
] }),
|
|
2785
|
-
style && /* @__PURE__ */ (0,
|
|
2786
|
-
/* @__PURE__ */ (0,
|
|
2787
|
-
/* @__PURE__ */ (0,
|
|
2836
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
2837
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16", children: "Opacity" }),
|
|
2838
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2788
2839
|
"input",
|
|
2789
2840
|
{
|
|
2790
2841
|
type: "range",
|
|
@@ -2798,34 +2849,35 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2798
2849
|
}
|
|
2799
2850
|
)
|
|
2800
2851
|
] }),
|
|
2801
|
-
/* @__PURE__ */ (0,
|
|
2802
|
-
style && /* @__PURE__ */ (0,
|
|
2803
|
-
style && /* @__PURE__ */ (0,
|
|
2804
|
-
style && /* @__PURE__ */ (0,
|
|
2805
|
-
style && /* @__PURE__ */ (0,
|
|
2806
|
-
/* @__PURE__ */ (0,
|
|
2807
|
-
/* @__PURE__ */ (0,
|
|
2808
|
-
/* @__PURE__ */ (0,
|
|
2809
|
-
/* @__PURE__ */ (0,
|
|
2810
|
-
/* @__PURE__ */ (0,
|
|
2811
|
-
/* @__PURE__ */ (0,
|
|
2812
|
-
/* @__PURE__ */ (0,
|
|
2813
|
-
/* @__PURE__ */ (0,
|
|
2852
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorTextPanel, { controller }),
|
|
2853
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorAppearancePanel, { controller }),
|
|
2854
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorEffectsPanel, { controller }),
|
|
2855
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorEnvelopePanel, { controller }),
|
|
2856
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorMaskPanel, { controller }),
|
|
2857
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorFramePanel, { controller }),
|
|
2858
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorConnectorPanel, { controller }),
|
|
2859
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorShadingPanel, { controller }),
|
|
2860
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorSymmetryPanel, { controller }),
|
|
2861
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorPerspectivePanel, { controller }),
|
|
2862
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorLensPanel, { controller }),
|
|
2863
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorTracePanel, { controller }),
|
|
2864
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorConstraintsPanel, { controller }),
|
|
2865
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(VectorSymbolsPanel, { controller })
|
|
2814
2866
|
] });
|
|
2815
2867
|
}
|
|
2816
2868
|
|
|
2817
2869
|
// src/effects/useEffects.ts
|
|
2818
|
-
var
|
|
2870
|
+
var import_react12 = require("react");
|
|
2819
2871
|
function useEffects(host, provider) {
|
|
2820
|
-
(0,
|
|
2872
|
+
(0, import_react12.useEffect)(() => {
|
|
2821
2873
|
if (!host || !provider) return;
|
|
2822
2874
|
return host.useEffects(provider);
|
|
2823
2875
|
}, [host, provider]);
|
|
2824
2876
|
}
|
|
2825
2877
|
function useEffectDescription(provider, effect) {
|
|
2826
|
-
const [state, setState] = (0,
|
|
2878
|
+
const [state, setState] = (0, import_react12.useState)({ key: "", description: null, error: null });
|
|
2827
2879
|
const key = provider && effect ? `${provider.id}:${effect}` : "";
|
|
2828
|
-
(0,
|
|
2880
|
+
(0, import_react12.useEffect)(() => {
|
|
2829
2881
|
if (!provider || !effect) return;
|
|
2830
2882
|
let live = true;
|
|
2831
2883
|
Promise.resolve().then(() => provider.describe(effect)).then(
|
|
@@ -2840,13 +2892,13 @@ function useEffectDescription(provider, effect) {
|
|
|
2840
2892
|
}
|
|
2841
2893
|
|
|
2842
2894
|
// src/effects/EffectThumbnail.tsx
|
|
2843
|
-
var
|
|
2895
|
+
var import_react13 = require("react");
|
|
2844
2896
|
var import_effects = require("@pixerate/editor/effects");
|
|
2845
|
-
var
|
|
2897
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2846
2898
|
function EffectThumbnail({ provider, effect, width = 96, height = 54, className = "" }) {
|
|
2847
|
-
const ref = (0,
|
|
2848
|
-
const [failed, setFailed] = (0,
|
|
2849
|
-
(0,
|
|
2899
|
+
const ref = (0, import_react13.useRef)(null);
|
|
2900
|
+
const [failed, setFailed] = (0, import_react13.useState)(effect.kind === "motion");
|
|
2901
|
+
(0, import_react13.useEffect)(() => {
|
|
2850
2902
|
if (effect.kind === "motion") return;
|
|
2851
2903
|
let live = true;
|
|
2852
2904
|
(0, import_effects.renderEffectThumbnail)(provider, effect, { width, height }).then(
|
|
@@ -2861,28 +2913,28 @@ function EffectThumbnail({ provider, effect, width = 96, height = 54, className
|
|
|
2861
2913
|
live = false;
|
|
2862
2914
|
};
|
|
2863
2915
|
}, [provider, effect, width, height]);
|
|
2864
|
-
return /* @__PURE__ */ (0,
|
|
2916
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2865
2917
|
"div",
|
|
2866
2918
|
{
|
|
2867
2919
|
className: `relative overflow-hidden rounded border border-border bg-[repeating-conic-gradient(#8884_0_25%,transparent_0_50%)] bg-[length:12px_12px] ${className}`,
|
|
2868
2920
|
style: { aspectRatio: `${width} / ${height}` },
|
|
2869
2921
|
"data-effect-thumbnail": effect.id,
|
|
2870
|
-
children: failed ? /* @__PURE__ */ (0,
|
|
2922
|
+
children: failed ? /* @__PURE__ */ (0, import_jsx_runtime19.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_runtime19.jsx)("canvas", { ref, width, height, className: "h-full w-full", "aria-hidden": "true" })
|
|
2871
2923
|
}
|
|
2872
2924
|
);
|
|
2873
2925
|
}
|
|
2874
2926
|
|
|
2875
2927
|
// src/effects/EffectsBrowser.tsx
|
|
2876
|
-
var
|
|
2928
|
+
var import_react14 = require("react");
|
|
2877
2929
|
var import_effects2 = require("@pixerate/editor/effects");
|
|
2878
|
-
var
|
|
2930
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2879
2931
|
function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, title = "Effects", className = "" }) {
|
|
2880
|
-
const [all, setAll] = (0,
|
|
2881
|
-
const [query, setQuery] = (0,
|
|
2882
|
-
const [category, setCategory] = (0,
|
|
2883
|
-
const [use, setUse] = (0,
|
|
2884
|
-
const [error, setError] = (0,
|
|
2885
|
-
(0,
|
|
2932
|
+
const [all, setAll] = (0, import_react14.useState)([]);
|
|
2933
|
+
const [query, setQuery] = (0, import_react14.useState)("");
|
|
2934
|
+
const [category, setCategory] = (0, import_react14.useState)("");
|
|
2935
|
+
const [use, setUse] = (0, import_react14.useState)("");
|
|
2936
|
+
const [error, setError] = (0, import_react14.useState)(null);
|
|
2937
|
+
(0, import_react14.useEffect)(() => {
|
|
2886
2938
|
if (!provider) return setAll([]);
|
|
2887
2939
|
let live = true;
|
|
2888
2940
|
Promise.resolve().then(() => provider.list()).then(
|
|
@@ -2893,8 +2945,8 @@ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, titl
|
|
|
2893
2945
|
live = false;
|
|
2894
2946
|
};
|
|
2895
2947
|
}, [provider]);
|
|
2896
|
-
const [found, setFound] = (0,
|
|
2897
|
-
(0,
|
|
2948
|
+
const [found, setFound] = (0, import_react14.useState)([]);
|
|
2949
|
+
(0, import_react14.useEffect)(() => {
|
|
2898
2950
|
if (!provider) return setFound([]);
|
|
2899
2951
|
let live = true;
|
|
2900
2952
|
Promise.resolve().then(() => provider.search(query, { ...category ? { category } : {}, ...use ? { use } : {} })).then((list) => live && setFound(list), () => live && setFound([]));
|
|
@@ -2903,14 +2955,14 @@ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, titl
|
|
|
2903
2955
|
};
|
|
2904
2956
|
}, [provider, query, category, use]);
|
|
2905
2957
|
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)));
|
|
2906
|
-
const categories = (0,
|
|
2958
|
+
const categories = (0, import_react14.useMemo)(() => [...new Set(all.filter(allowed).map((e) => e.category))], [all, uses, kinds]);
|
|
2907
2959
|
const shown = found.filter(allowed);
|
|
2908
2960
|
if (!provider)
|
|
2909
|
-
return /* @__PURE__ */ (0,
|
|
2910
|
-
return /* @__PURE__ */ (0,
|
|
2911
|
-
title && /* @__PURE__ */ (0,
|
|
2912
|
-
/* @__PURE__ */ (0,
|
|
2913
|
-
/* @__PURE__ */ (0,
|
|
2961
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.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." });
|
|
2962
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("section", { className: `flex flex-col gap-2 ${className}`, "data-effects-browser": "", "aria-label": "Effects browser", children: [
|
|
2963
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { className: "text-xs font-semibold", children: title }),
|
|
2964
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
2965
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2914
2966
|
"input",
|
|
2915
2967
|
{
|
|
2916
2968
|
type: "search",
|
|
@@ -2921,17 +2973,17 @@ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, titl
|
|
|
2921
2973
|
onChange: (e) => setQuery(e.currentTarget.value)
|
|
2922
2974
|
}
|
|
2923
2975
|
),
|
|
2924
|
-
/* @__PURE__ */ (0,
|
|
2925
|
-
/* @__PURE__ */ (0,
|
|
2926
|
-
categories.map((c) => /* @__PURE__ */ (0,
|
|
2976
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.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: [
|
|
2977
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("option", { value: "", children: "All categories" }),
|
|
2978
|
+
categories.map((c) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("option", { value: c, children: c }, c))
|
|
2927
2979
|
] }),
|
|
2928
|
-
uses && uses.length > 1 && /* @__PURE__ */ (0,
|
|
2929
|
-
/* @__PURE__ */ (0,
|
|
2930
|
-
uses.map((u) => /* @__PURE__ */ (0,
|
|
2980
|
+
uses && uses.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime20.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: [
|
|
2981
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("option", { value: "", children: "Any use" }),
|
|
2982
|
+
uses.map((u) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("option", { value: u, children: import_effects2.EFFECT_USE_LABELS[u] }, u))
|
|
2931
2983
|
] })
|
|
2932
2984
|
] }),
|
|
2933
|
-
error && /* @__PURE__ */ (0,
|
|
2934
|
-
/* @__PURE__ */ (0,
|
|
2985
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: error }),
|
|
2986
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.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_runtime20.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
2935
2987
|
"button",
|
|
2936
2988
|
{
|
|
2937
2989
|
type: "button",
|
|
@@ -2940,25 +2992,25 @@ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, titl
|
|
|
2940
2992
|
"data-effect-id": e.id,
|
|
2941
2993
|
onClick: () => onPick(e),
|
|
2942
2994
|
children: [
|
|
2943
|
-
thumbnails && /* @__PURE__ */ (0,
|
|
2944
|
-
/* @__PURE__ */ (0,
|
|
2945
|
-
/* @__PURE__ */ (0,
|
|
2995
|
+
thumbnails && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(EffectThumbnail, { provider, effect: e }),
|
|
2996
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "truncate text-[11px] font-medium", children: e.name }),
|
|
2997
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "truncate text-[10px] text-muted-foreground", children: e.uses.map((u) => import_effects2.EFFECT_USE_LABELS[u]).join(" \xB7 ") })
|
|
2946
2998
|
]
|
|
2947
2999
|
}
|
|
2948
3000
|
) }, e.id)) }),
|
|
2949
|
-
!shown.length && !error && /* @__PURE__ */ (0,
|
|
3001
|
+
!shown.length && !error && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No effects match." })
|
|
2950
3002
|
] });
|
|
2951
3003
|
}
|
|
2952
3004
|
|
|
2953
3005
|
// src/effects/EffectParameters.tsx
|
|
2954
|
-
var
|
|
3006
|
+
var import_react16 = __toESM(require("react"), 1);
|
|
2955
3007
|
var import_effects3 = require("@pixerate/editor/effects");
|
|
2956
3008
|
var import_parameters2 = require("@pixerate/editor/parameters");
|
|
2957
3009
|
|
|
2958
3010
|
// src/parameters/fields.tsx
|
|
2959
|
-
var
|
|
3011
|
+
var import_react15 = require("react");
|
|
2960
3012
|
var import_parameters = require("@pixerate/editor/parameters");
|
|
2961
|
-
var
|
|
3013
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2962
3014
|
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";
|
|
2963
3015
|
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";
|
|
2964
3016
|
var rangeClass = "h-4 w-full min-w-0 flex-1 cursor-pointer accent-primary disabled:cursor-not-allowed disabled:opacity-50";
|
|
@@ -2982,7 +3034,7 @@ function ParameterCommitInput({ value, onCommit, multiline, className, onKeyDown
|
|
|
2982
3034
|
onKeyDown: keyDown,
|
|
2983
3035
|
...rest
|
|
2984
3036
|
};
|
|
2985
|
-
return multiline ? /* @__PURE__ */ (0,
|
|
3037
|
+
return multiline ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("textarea", { ...props, className: `${props.className} h-auto min-h-[3.5rem] py-1` }, value) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { type: "text", ...props }, value);
|
|
2986
3038
|
}
|
|
2987
3039
|
var plainNumber = (field, value) => (0, import_parameters.formatParameterNumber)({ ...field, unit: void 0 }, value);
|
|
2988
3040
|
function ParameterNumberInput({
|
|
@@ -2993,8 +3045,8 @@ function ParameterNumberInput({
|
|
|
2993
3045
|
id,
|
|
2994
3046
|
"aria-label": ariaLabel
|
|
2995
3047
|
}) {
|
|
2996
|
-
return /* @__PURE__ */ (0,
|
|
2997
|
-
/* @__PURE__ */ (0,
|
|
3048
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative min-w-0 flex-1", children: [
|
|
3049
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2998
3050
|
ParameterCommitInput,
|
|
2999
3051
|
{
|
|
3000
3052
|
id,
|
|
@@ -3016,21 +3068,21 @@ function ParameterNumberInput({
|
|
|
3016
3068
|
}
|
|
3017
3069
|
}
|
|
3018
3070
|
),
|
|
3019
|
-
field.unit && /* @__PURE__ */ (0,
|
|
3071
|
+
field.unit && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-[10px] text-muted-foreground", children: field.unit })
|
|
3020
3072
|
] });
|
|
3021
3073
|
}
|
|
3022
3074
|
function ParameterSlider(props) {
|
|
3023
3075
|
const { field, value, onChange, onGestureStart, onGestureEnd, disabled } = props;
|
|
3024
|
-
const dragging = (0,
|
|
3076
|
+
const dragging = (0, import_react15.useRef)(false);
|
|
3025
3077
|
const end = () => {
|
|
3026
3078
|
if (!dragging.current) return;
|
|
3027
3079
|
dragging.current = false;
|
|
3028
3080
|
onGestureEnd?.();
|
|
3029
3081
|
};
|
|
3030
|
-
if (!(0, import_parameters.isSliderField)(field)) return /* @__PURE__ */ (0,
|
|
3082
|
+
if (!(0, import_parameters.isSliderField)(field)) return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ParameterNumberInput, { ...props });
|
|
3031
3083
|
const step = (0, import_parameters.parameterStep)(field);
|
|
3032
|
-
return /* @__PURE__ */ (0,
|
|
3033
|
-
/* @__PURE__ */ (0,
|
|
3084
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3085
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3034
3086
|
"input",
|
|
3035
3087
|
{
|
|
3036
3088
|
type: "range",
|
|
@@ -3053,11 +3105,11 @@ function ParameterSlider(props) {
|
|
|
3053
3105
|
onChange: (e) => onChange((0, import_parameters.clampParameterNumber)(field, Number(e.target.value)))
|
|
3054
3106
|
}
|
|
3055
3107
|
),
|
|
3056
|
-
/* @__PURE__ */ (0,
|
|
3108
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "w-20 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ParameterNumberInput, { ...props, id: props.id, "aria-label": `${(0, import_parameters.parameterLabel)(field)} value` }) })
|
|
3057
3109
|
] });
|
|
3058
3110
|
}
|
|
3059
3111
|
function ParameterToggle({ field, value, onChange, disabled, id }) {
|
|
3060
|
-
return /* @__PURE__ */ (0,
|
|
3112
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3061
3113
|
"button",
|
|
3062
3114
|
{
|
|
3063
3115
|
type: "button",
|
|
@@ -3068,7 +3120,7 @@ function ParameterToggle({ field, value, onChange, disabled, id }) {
|
|
|
3068
3120
|
disabled: disabled || field.readOnly,
|
|
3069
3121
|
onClick: () => onChange(!value),
|
|
3070
3122
|
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"}`,
|
|
3071
|
-
children: /* @__PURE__ */ (0,
|
|
3123
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3072
3124
|
"span",
|
|
3073
3125
|
{
|
|
3074
3126
|
className: `pointer-events-none block h-4 w-4 rounded-full bg-background shadow transition-transform ${value ? "translate-x-4" : "translate-x-0.5"}`
|
|
@@ -3081,7 +3133,7 @@ function ParameterSelect({ field, value, onChange, disabled, id }) {
|
|
|
3081
3133
|
const options = (0, import_parameters.getChoiceOptions)(field);
|
|
3082
3134
|
const off = disabled || field.readOnly;
|
|
3083
3135
|
if (field.control === "segmented") {
|
|
3084
|
-
return /* @__PURE__ */ (0,
|
|
3136
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.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_runtime21.jsx)(
|
|
3085
3137
|
"button",
|
|
3086
3138
|
{
|
|
3087
3139
|
type: "button",
|
|
@@ -3097,7 +3149,7 @@ function ParameterSelect({ field, value, onChange, disabled, id }) {
|
|
|
3097
3149
|
)) });
|
|
3098
3150
|
}
|
|
3099
3151
|
const index = options.findIndex((o) => o.value === value);
|
|
3100
|
-
return /* @__PURE__ */ (0,
|
|
3152
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3101
3153
|
"select",
|
|
3102
3154
|
{
|
|
3103
3155
|
id,
|
|
@@ -3109,12 +3161,12 @@ function ParameterSelect({ field, value, onChange, disabled, id }) {
|
|
|
3109
3161
|
if (option) onChange(option.value);
|
|
3110
3162
|
},
|
|
3111
3163
|
className: parameterInputClass,
|
|
3112
|
-
children: options.map((o, i) => /* @__PURE__ */ (0,
|
|
3164
|
+
children: options.map((o, i) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: String(i), title: o.description, children: (0, import_parameters.choiceOptionLabel)(o) }, String(o.value)))
|
|
3113
3165
|
}
|
|
3114
3166
|
);
|
|
3115
3167
|
}
|
|
3116
3168
|
function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd, disabled, id }) {
|
|
3117
|
-
const picking = (0,
|
|
3169
|
+
const picking = (0, import_react15.useRef)(false);
|
|
3118
3170
|
const alpha = !!field.alpha;
|
|
3119
3171
|
const hex = (0, import_parameters.normalizeHexColor)(value, true) ?? "#000000ff";
|
|
3120
3172
|
const rgb = hex.slice(0, 7);
|
|
@@ -3130,11 +3182,11 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3130
3182
|
picking.current = false;
|
|
3131
3183
|
onGestureEnd?.();
|
|
3132
3184
|
};
|
|
3133
|
-
return /* @__PURE__ */ (0,
|
|
3134
|
-
/* @__PURE__ */ (0,
|
|
3135
|
-
/* @__PURE__ */ (0,
|
|
3136
|
-
/* @__PURE__ */ (0,
|
|
3137
|
-
/* @__PURE__ */ (0,
|
|
3185
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-1.5", children: [
|
|
3186
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3187
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.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: [
|
|
3188
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "absolute inset-0", style: { background: alpha ? hex : rgb } }),
|
|
3189
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3138
3190
|
"input",
|
|
3139
3191
|
{
|
|
3140
3192
|
type: "color",
|
|
@@ -3150,7 +3202,7 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3150
3202
|
}
|
|
3151
3203
|
)
|
|
3152
3204
|
] }),
|
|
3153
|
-
/* @__PURE__ */ (0,
|
|
3205
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3154
3206
|
ParameterCommitInput,
|
|
3155
3207
|
{
|
|
3156
3208
|
id,
|
|
@@ -3166,7 +3218,7 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3166
3218
|
}
|
|
3167
3219
|
)
|
|
3168
3220
|
] }),
|
|
3169
|
-
alpha && /* @__PURE__ */ (0,
|
|
3221
|
+
alpha && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3170
3222
|
"input",
|
|
3171
3223
|
{
|
|
3172
3224
|
type: "range",
|
|
@@ -3184,10 +3236,10 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3184
3236
|
onChange: (e) => onChange(`${rgb}${Number(e.target.value).toString(16).padStart(2, "0")}`)
|
|
3185
3237
|
}
|
|
3186
3238
|
),
|
|
3187
|
-
field.swatches && field.swatches.length > 0 && /* @__PURE__ */ (0,
|
|
3239
|
+
field.swatches && field.swatches.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex flex-wrap gap-1", children: field.swatches.map((s) => {
|
|
3188
3240
|
const swatch = (0, import_parameters.normalizeHexColor)(s, alpha);
|
|
3189
3241
|
if (!swatch) return null;
|
|
3190
|
-
return /* @__PURE__ */ (0,
|
|
3242
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3191
3243
|
"button",
|
|
3192
3244
|
{
|
|
3193
3245
|
type: "button",
|
|
@@ -3206,11 +3258,11 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3206
3258
|
}
|
|
3207
3259
|
function ParameterVector({ field, value, onChange, disabled, id }) {
|
|
3208
3260
|
const size = (0, import_parameters.vectorSize)(field);
|
|
3209
|
-
return /* @__PURE__ */ (0,
|
|
3261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "grid gap-1.5", style: { gridTemplateColumns: `repeat(${size}, minmax(0, 1fr))` }, children: Array.from({ length: size }, (_, i) => {
|
|
3210
3262
|
const component = (0, import_parameters.vectorComponentField)(field, i);
|
|
3211
|
-
return /* @__PURE__ */ (0,
|
|
3212
|
-
/* @__PURE__ */ (0,
|
|
3213
|
-
/* @__PURE__ */ (0,
|
|
3263
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex min-w-0 items-center gap-1", children: [
|
|
3264
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "w-3 shrink-0 text-[10px] uppercase text-muted-foreground", children: component.label }),
|
|
3265
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3214
3266
|
ParameterNumberInput,
|
|
3215
3267
|
{
|
|
3216
3268
|
field: component,
|
|
@@ -3227,11 +3279,11 @@ function ParameterVector({ field, value, onChange, disabled, id }) {
|
|
|
3227
3279
|
function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
3228
3280
|
const off = disabled || field.readOnly;
|
|
3229
3281
|
const name = (0, import_parameters.parameterLabel)(field);
|
|
3230
|
-
return /* @__PURE__ */ (0,
|
|
3231
|
-
/* @__PURE__ */ (0,
|
|
3232
|
-
/* @__PURE__ */ (0,
|
|
3233
|
-
/* @__PURE__ */ (0,
|
|
3234
|
-
/* @__PURE__ */ (0,
|
|
3282
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-1.5", children: [
|
|
3283
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3284
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.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_runtime21.jsx)("img", { src: value, alt: name, className: "h-full w-full object-cover" }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[10px] text-muted-foreground", children: "None" }) }),
|
|
3285
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
|
|
3286
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3235
3287
|
ParameterCommitInput,
|
|
3236
3288
|
{
|
|
3237
3289
|
id,
|
|
@@ -3242,10 +3294,10 @@ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
|
3242
3294
|
onCommit: (text) => onChange(text.trim())
|
|
3243
3295
|
}
|
|
3244
3296
|
),
|
|
3245
|
-
/* @__PURE__ */ (0,
|
|
3246
|
-
resolveFile && /* @__PURE__ */ (0,
|
|
3297
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex gap-1", children: [
|
|
3298
|
+
resolveFile && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: `${parameterButtonClass} cursor-pointer ${off ? "pointer-events-none opacity-50" : ""}`, children: [
|
|
3247
3299
|
"Choose file\u2026",
|
|
3248
|
-
/* @__PURE__ */ (0,
|
|
3300
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3249
3301
|
"input",
|
|
3250
3302
|
{
|
|
3251
3303
|
type: "file",
|
|
@@ -3261,11 +3313,11 @@ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
|
3261
3313
|
}
|
|
3262
3314
|
)
|
|
3263
3315
|
] }),
|
|
3264
|
-
value && /* @__PURE__ */ (0,
|
|
3316
|
+
value && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: parameterButtonClass, disabled: off, onClick: () => onChange(""), "aria-label": `Clear ${name}`, children: "Clear" })
|
|
3265
3317
|
] })
|
|
3266
3318
|
] })
|
|
3267
3319
|
] }),
|
|
3268
|
-
field.options && field.options.length > 0 && /* @__PURE__ */ (0,
|
|
3320
|
+
field.options && field.options.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex flex-wrap gap-1", children: field.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3269
3321
|
"button",
|
|
3270
3322
|
{
|
|
3271
3323
|
type: "button",
|
|
@@ -3275,14 +3327,14 @@ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
|
3275
3327
|
disabled: off,
|
|
3276
3328
|
onClick: () => onChange(o.url),
|
|
3277
3329
|
className: "h-9 w-12 overflow-hidden rounded border border-input aria-pressed:ring-2 aria-pressed:ring-primary",
|
|
3278
|
-
children: /* @__PURE__ */ (0,
|
|
3330
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("img", { src: o.url, alt: "", className: "h-full w-full object-cover" })
|
|
3279
3331
|
},
|
|
3280
3332
|
o.url
|
|
3281
3333
|
)) })
|
|
3282
3334
|
] });
|
|
3283
3335
|
}
|
|
3284
3336
|
function ParameterText({ field, value, onChange, disabled, id }) {
|
|
3285
|
-
return /* @__PURE__ */ (0,
|
|
3337
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3286
3338
|
ParameterCommitInput,
|
|
3287
3339
|
{
|
|
3288
3340
|
id,
|
|
@@ -3301,31 +3353,31 @@ function ParameterFieldControl({ field, value, onChange, resolveFile, ...rest })
|
|
|
3301
3353
|
switch (field.type) {
|
|
3302
3354
|
case "number":
|
|
3303
3355
|
case "int":
|
|
3304
|
-
return /* @__PURE__ */ (0,
|
|
3356
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ParameterSlider, { field, value, onChange: set, ...rest });
|
|
3305
3357
|
case "boolean":
|
|
3306
|
-
return /* @__PURE__ */ (0,
|
|
3358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ParameterToggle, { field, value, onChange: set, ...rest });
|
|
3307
3359
|
case "choice":
|
|
3308
|
-
return /* @__PURE__ */ (0,
|
|
3360
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ParameterSelect, { field, value, onChange: set, ...rest });
|
|
3309
3361
|
case "color":
|
|
3310
|
-
return /* @__PURE__ */ (0,
|
|
3362
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ParameterColor, { field, value, onChange: set, ...rest });
|
|
3311
3363
|
case "vector":
|
|
3312
|
-
return /* @__PURE__ */ (0,
|
|
3364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ParameterVector, { field, value, onChange: set, ...rest });
|
|
3313
3365
|
case "image":
|
|
3314
|
-
return /* @__PURE__ */ (0,
|
|
3366
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ParameterImage, { field, value, onChange: set, resolveFile, ...rest });
|
|
3315
3367
|
case "text":
|
|
3316
|
-
return /* @__PURE__ */ (0,
|
|
3368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ParameterText, { field, value, onChange: set, ...rest });
|
|
3317
3369
|
}
|
|
3318
3370
|
}
|
|
3319
3371
|
|
|
3320
3372
|
// src/effects/EffectParameters.tsx
|
|
3321
|
-
var
|
|
3373
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
3322
3374
|
function EffectParameters({ description, values, onChange, onReset, keyframed, onPreset, disabled = false, className = "" }) {
|
|
3323
|
-
const fields = (0,
|
|
3324
|
-
const idBase = (0,
|
|
3325
|
-
const gesture =
|
|
3326
|
-
const count =
|
|
3327
|
-
return /* @__PURE__ */ (0,
|
|
3328
|
-
onPreset && description.presets.length > 0 && /* @__PURE__ */ (0,
|
|
3375
|
+
const fields = (0, import_react16.useMemo)(() => (0, import_effects3.effectParameterFields)(description), [description]);
|
|
3376
|
+
const idBase = (0, import_react16.useId)();
|
|
3377
|
+
const gesture = import_react16.default.useRef(null);
|
|
3378
|
+
const count = import_react16.default.useRef(0);
|
|
3379
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: `space-y-2 ${className}`, "data-effect-parameters": description.id, children: [
|
|
3380
|
+
onPreset && description.presets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
3329
3381
|
"select",
|
|
3330
3382
|
{
|
|
3331
3383
|
className: "w-full rounded border border-border bg-transparent px-1 py-0.5 text-xs",
|
|
@@ -3337,8 +3389,8 @@ function EffectParameters({ description, values, onChange, onReset, keyframed, o
|
|
|
3337
3389
|
if (preset) onPreset({ ...description.defaults, ...preset.values });
|
|
3338
3390
|
},
|
|
3339
3391
|
children: [
|
|
3340
|
-
/* @__PURE__ */ (0,
|
|
3341
|
-
description.presets.map((p) => /* @__PURE__ */ (0,
|
|
3392
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("option", { value: "", children: "Presets\u2026" }),
|
|
3393
|
+
description.presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("option", { value: p.name, children: p.name }, p.name))
|
|
3342
3394
|
]
|
|
3343
3395
|
}
|
|
3344
3396
|
),
|
|
@@ -3348,13 +3400,13 @@ function EffectParameters({ description, values, onChange, onReset, keyframed, o
|
|
|
3348
3400
|
const keyed = keyframed?.has(field.id) ?? false;
|
|
3349
3401
|
const value = (0, import_effects3.effectFieldValue)(field, values[field.id]);
|
|
3350
3402
|
const changed = !keyed && !(0, import_parameters2.parameterValuesEqual)(value, field.default);
|
|
3351
|
-
return /* @__PURE__ */ (0,
|
|
3352
|
-
/* @__PURE__ */ (0,
|
|
3353
|
-
/* @__PURE__ */ (0,
|
|
3354
|
-
keyed && /* @__PURE__ */ (0,
|
|
3355
|
-
onReset && changed && !disabled && /* @__PURE__ */ (0,
|
|
3403
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-1", "data-effect-control": field.id, children: [
|
|
3404
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
3405
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { htmlFor: inputId, className: "min-w-0 flex-1 truncate text-xs font-medium", title: field.description, children: label }),
|
|
3406
|
+
keyed && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-[10px] text-muted-foreground", children: "keyframed" }),
|
|
3407
|
+
onReset && changed && !disabled && /* @__PURE__ */ (0, import_jsx_runtime22.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" })
|
|
3356
3408
|
] }),
|
|
3357
|
-
/* @__PURE__ */ (0,
|
|
3409
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3358
3410
|
ParameterFieldControl,
|
|
3359
3411
|
{
|
|
3360
3412
|
field,
|
|
@@ -3368,25 +3420,25 @@ function EffectParameters({ description, values, onChange, onReset, keyframed, o
|
|
|
3368
3420
|
)
|
|
3369
3421
|
] }, field.id);
|
|
3370
3422
|
}),
|
|
3371
|
-
!fields.length && /* @__PURE__ */ (0,
|
|
3423
|
+
!fields.length && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No controls." })
|
|
3372
3424
|
] });
|
|
3373
3425
|
}
|
|
3374
3426
|
|
|
3375
3427
|
// src/vector/VectorProviderEffectsPanel.tsx
|
|
3376
|
-
var
|
|
3377
|
-
var
|
|
3428
|
+
var import_react17 = require("react");
|
|
3429
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
3378
3430
|
var btn = "rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40";
|
|
3379
3431
|
function Controls({ controller, group }) {
|
|
3380
3432
|
const provider = controller.effectsProvider;
|
|
3381
3433
|
const tag = group.providerEffect;
|
|
3382
3434
|
const { description, error } = useEffectDescription(provider, tag.effect);
|
|
3383
|
-
const [message, setMessage] = (0,
|
|
3435
|
+
const [message, setMessage] = (0, import_react17.useState)(null);
|
|
3384
3436
|
const run = (work) => void work.then(() => setMessage(null), (e) => setMessage(e instanceof Error ? e.message : String(e)));
|
|
3385
|
-
if (!provider) return /* @__PURE__ */ (0,
|
|
3386
|
-
if (error) return /* @__PURE__ */ (0,
|
|
3387
|
-
if (!description) return /* @__PURE__ */ (0,
|
|
3388
|
-
return /* @__PURE__ */ (0,
|
|
3389
|
-
/* @__PURE__ */ (0,
|
|
3437
|
+
if (!provider) return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No effects provider: the shapes are kept as they are." });
|
|
3438
|
+
if (error) return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[11px] text-amber-500", children: error });
|
|
3439
|
+
if (!description) return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Loading\u2026" });
|
|
3440
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
3441
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3390
3442
|
EffectParameters,
|
|
3391
3443
|
{
|
|
3392
3444
|
description,
|
|
@@ -3396,18 +3448,18 @@ function Controls({ controller, group }) {
|
|
|
3396
3448
|
onPreset: (v) => run(controller.updateVectorEffect(group.id, v))
|
|
3397
3449
|
}
|
|
3398
3450
|
),
|
|
3399
|
-
message && /* @__PURE__ */ (0,
|
|
3451
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
|
|
3400
3452
|
] });
|
|
3401
3453
|
}
|
|
3402
3454
|
function VectorProviderEffectsPanel({ controller, className = "" }) {
|
|
3403
3455
|
const state = useVectorEditorState(controller);
|
|
3404
|
-
const provider = (0,
|
|
3456
|
+
const provider = (0, import_react17.useSyncExternalStore)(
|
|
3405
3457
|
(cb) => controller.effects.subscribe(cb),
|
|
3406
3458
|
() => controller.effects.provider,
|
|
3407
3459
|
() => controller.effects.provider
|
|
3408
3460
|
);
|
|
3409
|
-
const [browse, setBrowse] = (0,
|
|
3410
|
-
const [message, setMessage] = (0,
|
|
3461
|
+
const [browse, setBrowse] = (0, import_react17.useState)(false);
|
|
3462
|
+
const [message, setMessage] = (0, import_react17.useState)(null);
|
|
3411
3463
|
void state;
|
|
3412
3464
|
const groups = controller.vectorEffectGroups();
|
|
3413
3465
|
const selected = groups.filter((g) => state.selection.includes(g.id));
|
|
@@ -3415,41 +3467,41 @@ function VectorProviderEffectsPanel({ controller, className = "" }) {
|
|
|
3415
3467
|
setMessage(null);
|
|
3416
3468
|
Promise.resolve().then(work).catch((e) => setMessage(e instanceof Error ? e.message : String(e)));
|
|
3417
3469
|
};
|
|
3418
|
-
return /* @__PURE__ */ (0,
|
|
3419
|
-
/* @__PURE__ */ (0,
|
|
3420
|
-
/* @__PURE__ */ (0,
|
|
3421
|
-
/* @__PURE__ */ (0,
|
|
3470
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("section", { className: `flex flex-col gap-2 text-xs ${className}`, "aria-label": "Vector effects", "data-vector-provider-effects": "", children: [
|
|
3471
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
3472
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "flex-1 font-semibold", children: "Effects" }),
|
|
3473
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn, disabled: !provider, "aria-pressed": browse, onClick: () => setBrowse(!browse), children: "Add effect\u2026" })
|
|
3422
3474
|
] }),
|
|
3423
|
-
!provider && /* @__PURE__ */ (0,
|
|
3424
|
-
browse && /* @__PURE__ */ (0,
|
|
3425
|
-
selected.map((g) => /* @__PURE__ */ (0,
|
|
3426
|
-
/* @__PURE__ */ (0,
|
|
3427
|
-
/* @__PURE__ */ (0,
|
|
3428
|
-
/* @__PURE__ */ (0,
|
|
3475
|
+
!provider && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No effects provider is registered. Effect groups are kept as shapes." }),
|
|
3476
|
+
browse && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EffectsBrowser, { provider, kinds: ["vector"], title: "Vector effects", onPick: (e) => (setBrowse(false), run(() => controller.addVectorEffect(e.id))) }),
|
|
3477
|
+
selected.map((g) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "space-y-1 rounded border border-border p-1", "data-vector-effect-group": g.id, children: [
|
|
3478
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
3479
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "min-w-0 flex-1 truncate font-medium", children: g.providerEffect.name ?? g.providerEffect.effect }),
|
|
3480
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn, title: "Keep the shapes as a plain group", onClick: () => run(() => controller.detachVectorEffect(g.id)), children: "Detach" })
|
|
3429
3481
|
] }),
|
|
3430
|
-
/* @__PURE__ */ (0,
|
|
3482
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Controls, { controller, group: g })
|
|
3431
3483
|
] }, g.id)),
|
|
3432
|
-
groups.length > 0 && !selected.length && /* @__PURE__ */ (0,
|
|
3484
|
+
groups.length > 0 && !selected.length && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("p", { className: "text-[11px] text-muted-foreground", children: [
|
|
3433
3485
|
"Select an effect group (",
|
|
3434
3486
|
groups.length,
|
|
3435
3487
|
" in the drawing) to change it."
|
|
3436
3488
|
] }),
|
|
3437
|
-
message && /* @__PURE__ */ (0,
|
|
3489
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
|
|
3438
3490
|
] });
|
|
3439
3491
|
}
|
|
3440
3492
|
|
|
3441
3493
|
// src/vector/VectorEditor.tsx
|
|
3442
|
-
var
|
|
3494
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
3443
3495
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, effects, className }) {
|
|
3444
3496
|
useEffects(controller, effects);
|
|
3445
3497
|
const effectsShown = !!effects || controller.vectorEffectGroups().length > 0;
|
|
3446
|
-
return /* @__PURE__ */ (0,
|
|
3447
|
-
/* @__PURE__ */ (0,
|
|
3448
|
-
/* @__PURE__ */ (0,
|
|
3449
|
-
/* @__PURE__ */ (0,
|
|
3450
|
-
showStylePanel && /* @__PURE__ */ (0,
|
|
3451
|
-
/* @__PURE__ */ (0,
|
|
3452
|
-
effectsShown && /* @__PURE__ */ (0,
|
|
3498
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: `flex flex-col gap-2 ${className ?? ""}`, "data-vector-editor": "", children: [
|
|
3499
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VectorToolbar, { controller, tools }),
|
|
3500
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex min-h-0 flex-col gap-2 md:flex-row", children: [
|
|
3501
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "relative min-h-[320px] flex-1 overflow-hidden rounded-md border border-border bg-muted/40", style: { height }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VectorCanvas, { controller, ...canvasProps }) }),
|
|
3502
|
+
showStylePanel && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex w-full shrink-0 flex-col gap-2 md:w-56", children: [
|
|
3503
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VectorStylePanel, { controller, className: "rounded-md border border-border p-3" }),
|
|
3504
|
+
effectsShown && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(VectorProviderEffectsPanel, { controller, className: "rounded-md border border-border p-3" })
|
|
3453
3505
|
] })
|
|
3454
3506
|
] })
|
|
3455
3507
|
] });
|
|
@@ -3471,6 +3523,7 @@ function VectorEditor({ controller, tools, showStylePanel = true, height = 520,
|
|
|
3471
3523
|
VectorLensPanel,
|
|
3472
3524
|
VectorMaskPanel,
|
|
3473
3525
|
VectorMaskedNodes,
|
|
3526
|
+
VectorPerspectivePanel,
|
|
3474
3527
|
VectorProviderEffectsPanel,
|
|
3475
3528
|
VectorSceneNodes,
|
|
3476
3529
|
VectorShadingPanel,
|