@pixerate/editor-react 0.81.0 → 0.83.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/canvas/index.cjs +2 -0
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +1 -1
- package/dist/canvas/index.d.ts +1 -1
- package/dist/canvas/index.js +2 -0
- package/dist/canvas/index.js.map +1 -1
- package/dist/vector/index.cjs +319 -263
- 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 +220 -165
- package/dist/vector/index.js.map +1 -1
- package/package.json +3 -3
package/dist/vector/index.js
CHANGED
|
@@ -2091,6 +2091,59 @@ function VectorSymmetryPanel({ controller, className }) {
|
|
|
2091
2091
|
] });
|
|
2092
2092
|
}
|
|
2093
2093
|
|
|
2094
|
+
// src/vector/VectorLensPanel.tsx
|
|
2095
|
+
import { VECTOR_LENS_LABELS, VECTOR_LENS_SPECS, VECTOR_LENS_TYPES } from "@pixerate/editor/vector";
|
|
2096
|
+
import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2097
|
+
var selectClass10 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2098
|
+
var numberClass9 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
2099
|
+
function VectorLensPanel({ controller, className }) {
|
|
2100
|
+
const state = useVectorEditorState(controller);
|
|
2101
|
+
const path = state.selection.map((id) => controller.getNode(id)).find((n) => n?.type === "path" && n.subpaths.some((sp) => sp.closed) && !n.connector);
|
|
2102
|
+
if (!path) return null;
|
|
2103
|
+
const lens = path.lens ?? null;
|
|
2104
|
+
const spec = lens ? VECTOR_LENS_SPECS[lens.type] : null;
|
|
2105
|
+
const ids = [path.id];
|
|
2106
|
+
return /* @__PURE__ */ jsxs15("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-lens-panel": "", "aria-label": "Lens", children: [
|
|
2107
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2108
|
+
/* @__PURE__ */ jsx15("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Lens" }),
|
|
2109
|
+
/* @__PURE__ */ jsxs15(
|
|
2110
|
+
"select",
|
|
2111
|
+
{
|
|
2112
|
+
"aria-label": "Lens type",
|
|
2113
|
+
className: selectClass10,
|
|
2114
|
+
value: lens?.type ?? "",
|
|
2115
|
+
onChange: (e) => e.target.value ? controller.setLens({ type: e.target.value }, { ids }) : controller.setLens(null, { ids }),
|
|
2116
|
+
children: [
|
|
2117
|
+
/* @__PURE__ */ jsx15("option", { value: "", children: "None" }),
|
|
2118
|
+
VECTOR_LENS_TYPES.map((t) => /* @__PURE__ */ jsx15("option", { value: t, children: VECTOR_LENS_LABELS[t] }, t))
|
|
2119
|
+
]
|
|
2120
|
+
}
|
|
2121
|
+
)
|
|
2122
|
+
] }),
|
|
2123
|
+
lens && spec && /* @__PURE__ */ jsxs15("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2124
|
+
/* @__PURE__ */ jsx15("span", { className: "w-16" }),
|
|
2125
|
+
/* @__PURE__ */ jsx15(
|
|
2126
|
+
"input",
|
|
2127
|
+
{
|
|
2128
|
+
type: "number",
|
|
2129
|
+
"aria-label": "Lens amount",
|
|
2130
|
+
title: `Amount: ${spec.unit} (${spec.min} to ${spec.max})`,
|
|
2131
|
+
className: numberClass9,
|
|
2132
|
+
min: spec.min,
|
|
2133
|
+
max: spec.max,
|
|
2134
|
+
step: lens.type === "magnify" ? 0.1 : 1,
|
|
2135
|
+
value: lens.amount,
|
|
2136
|
+
onChange: (e) => {
|
|
2137
|
+
const v = parseFloat(e.target.value);
|
|
2138
|
+
if (Number.isFinite(v)) controller.setLens({ amount: Math.min(spec.max, Math.max(spec.min, v)) }, { ids, merge: `lens-amount-${path.id}` });
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
),
|
|
2142
|
+
spec.color !== null && /* @__PURE__ */ jsx15("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}` }) })
|
|
2143
|
+
] })
|
|
2144
|
+
] });
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2094
2147
|
// src/vector/VectorGradientEditor.tsx
|
|
2095
2148
|
import {
|
|
2096
2149
|
VECTOR_GRADIENT_TYPES,
|
|
@@ -2104,9 +2157,9 @@ import {
|
|
|
2104
2157
|
getVectorGradientEditor,
|
|
2105
2158
|
vectorPaintToHex as vectorPaintToHex5
|
|
2106
2159
|
} from "@pixerate/editor/vector";
|
|
2107
|
-
import { Fragment as Fragment5, jsx as
|
|
2108
|
-
var
|
|
2109
|
-
var
|
|
2160
|
+
import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2161
|
+
var selectClass11 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2162
|
+
var numberClass10 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
2110
2163
|
var buttonClass13 = "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";
|
|
2111
2164
|
var percent = (v) => Math.round(v * 1e3) / 10;
|
|
2112
2165
|
function VectorGradientEditor({ controller, className }) {
|
|
@@ -2122,23 +2175,23 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2122
2175
|
controller.setStyle({ [ed.target]: vectorPaintToHex5(first?.color) ?? first?.color ?? "#000000" }, void 0, { label: "Solid Colour" });
|
|
2123
2176
|
} else controller.setGradient({ type: value });
|
|
2124
2177
|
};
|
|
2125
|
-
return /* @__PURE__ */
|
|
2126
|
-
/* @__PURE__ */
|
|
2127
|
-
/* @__PURE__ */
|
|
2128
|
-
["fill", "stroke"].map((t) => /* @__PURE__ */
|
|
2129
|
-
ed.mixed && /* @__PURE__ */
|
|
2178
|
+
return /* @__PURE__ */ jsxs16("div", { className: `space-y-1.5 ${className ?? ""}`, "data-vector-gradient-editor": ed.target, "aria-label": "Gradient", children: [
|
|
2179
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1.5", children: [
|
|
2180
|
+
/* @__PURE__ */ jsx16("span", { className: "w-16 text-xs text-foreground", children: "Gradient" }),
|
|
2181
|
+
["fill", "stroke"].map((t) => /* @__PURE__ */ jsx16("button", { type: "button", className: buttonClass13, "aria-pressed": ed.target === t, onClick: () => controller.setGradientTarget(t), children: t === "fill" ? "Fill" : "Stroke" }, t)),
|
|
2182
|
+
ed.mixed && /* @__PURE__ */ jsx16("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
2130
2183
|
] }),
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
/* @__PURE__ */
|
|
2133
|
-
/* @__PURE__ */
|
|
2134
|
-
/* @__PURE__ */
|
|
2135
|
-
VECTOR_GRADIENT_TYPES.map((t) => /* @__PURE__ */
|
|
2184
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-1.5", children: [
|
|
2185
|
+
/* @__PURE__ */ jsx16("span", { className: "w-16 text-xs text-foreground", children: "Type" }),
|
|
2186
|
+
/* @__PURE__ */ jsxs16("select", { "aria-label": "Gradient type", className: selectClass11, value: ed.type ?? "solid", onChange: (e) => setType(e.target.value), children: [
|
|
2187
|
+
/* @__PURE__ */ jsx16("option", { value: "solid", children: "Solid" }),
|
|
2188
|
+
VECTOR_GRADIENT_TYPES.map((t) => /* @__PURE__ */ jsx16("option", { value: t, children: VECTOR_GRADIENT_TYPE_LABELS[t] }, t))
|
|
2136
2189
|
] }),
|
|
2137
|
-
/* @__PURE__ */
|
|
2190
|
+
/* @__PURE__ */ jsx16("button", { type: "button", className: buttonClass13, "aria-label": "Reverse gradient", title: "Reverse gradient", disabled: !g, onClick: () => controller.reverseGradient(), children: "\u21C4" })
|
|
2138
2191
|
] }),
|
|
2139
|
-
g && /* @__PURE__ */
|
|
2140
|
-
/* @__PURE__ */
|
|
2141
|
-
/* @__PURE__ */
|
|
2192
|
+
g && /* @__PURE__ */ jsxs16(Fragment5, { children: [
|
|
2193
|
+
/* @__PURE__ */ jsxs16("div", { className: "relative h-8", "data-vector-gradient-ramp": "", children: [
|
|
2194
|
+
/* @__PURE__ */ jsx16(
|
|
2142
2195
|
"div",
|
|
2143
2196
|
{
|
|
2144
2197
|
role: "button",
|
|
@@ -2152,7 +2205,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2152
2205
|
}
|
|
2153
2206
|
}
|
|
2154
2207
|
),
|
|
2155
|
-
ed.stops.map((s) => /* @__PURE__ */
|
|
2208
|
+
ed.stops.map((s) => /* @__PURE__ */ jsx16(
|
|
2156
2209
|
"button",
|
|
2157
2210
|
{
|
|
2158
2211
|
type: "button",
|
|
@@ -2166,8 +2219,8 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2166
2219
|
s.index
|
|
2167
2220
|
))
|
|
2168
2221
|
] }),
|
|
2169
|
-
sel && /* @__PURE__ */
|
|
2170
|
-
/* @__PURE__ */
|
|
2222
|
+
sel && /* @__PURE__ */ jsxs16("div", { className: "flex flex-wrap items-center gap-1.5", "data-vector-gradient-selected-stop": sel.index, children: [
|
|
2223
|
+
/* @__PURE__ */ jsx16(
|
|
2171
2224
|
"input",
|
|
2172
2225
|
{
|
|
2173
2226
|
type: "color",
|
|
@@ -2178,9 +2231,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2178
2231
|
onBlur: end
|
|
2179
2232
|
}
|
|
2180
2233
|
),
|
|
2181
|
-
/* @__PURE__ */
|
|
2234
|
+
/* @__PURE__ */ jsxs16("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
2182
2235
|
"Opacity",
|
|
2183
|
-
/* @__PURE__ */
|
|
2236
|
+
/* @__PURE__ */ jsx16(
|
|
2184
2237
|
"input",
|
|
2185
2238
|
{
|
|
2186
2239
|
type: "number",
|
|
@@ -2188,7 +2241,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2188
2241
|
max: 100,
|
|
2189
2242
|
step: 5,
|
|
2190
2243
|
"aria-label": "Stop opacity",
|
|
2191
|
-
className:
|
|
2244
|
+
className: numberClass10,
|
|
2192
2245
|
value: percent(sel.opacity ?? 1),
|
|
2193
2246
|
onChange: (e) => {
|
|
2194
2247
|
const n = parseFloat(e.target.value);
|
|
@@ -2197,9 +2250,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2197
2250
|
}
|
|
2198
2251
|
)
|
|
2199
2252
|
] }),
|
|
2200
|
-
/* @__PURE__ */
|
|
2253
|
+
/* @__PURE__ */ jsxs16("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
2201
2254
|
"At",
|
|
2202
|
-
/* @__PURE__ */
|
|
2255
|
+
/* @__PURE__ */ jsx16(
|
|
2203
2256
|
"input",
|
|
2204
2257
|
{
|
|
2205
2258
|
type: "number",
|
|
@@ -2207,7 +2260,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2207
2260
|
max: 100,
|
|
2208
2261
|
step: 1,
|
|
2209
2262
|
"aria-label": "Stop position",
|
|
2210
|
-
className:
|
|
2263
|
+
className: numberClass10,
|
|
2211
2264
|
value: percent(sel.offset),
|
|
2212
2265
|
onChange: (e) => {
|
|
2213
2266
|
const n = parseFloat(e.target.value);
|
|
@@ -2216,9 +2269,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2216
2269
|
}
|
|
2217
2270
|
)
|
|
2218
2271
|
] }),
|
|
2219
|
-
!sel.last && /* @__PURE__ */
|
|
2272
|
+
!sel.last && /* @__PURE__ */ jsxs16("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
2220
2273
|
"Midpoint",
|
|
2221
|
-
/* @__PURE__ */
|
|
2274
|
+
/* @__PURE__ */ jsx16(
|
|
2222
2275
|
"input",
|
|
2223
2276
|
{
|
|
2224
2277
|
type: "number",
|
|
@@ -2226,7 +2279,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2226
2279
|
max: 95,
|
|
2227
2280
|
step: 1,
|
|
2228
2281
|
"aria-label": "Stop midpoint",
|
|
2229
|
-
className:
|
|
2282
|
+
className: numberClass10,
|
|
2230
2283
|
value: percent(sel.midpoint ?? 0.5),
|
|
2231
2284
|
onChange: (e) => {
|
|
2232
2285
|
const n = parseFloat(e.target.value);
|
|
@@ -2235,15 +2288,15 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2235
2288
|
}
|
|
2236
2289
|
)
|
|
2237
2290
|
] }),
|
|
2238
|
-
/* @__PURE__ */
|
|
2291
|
+
/* @__PURE__ */ jsx16("button", { type: "button", className: buttonClass13, "aria-label": "Delete stop", title: "Delete stop", disabled: ed.stops.length <= 2, onClick: () => controller.removeGradientStop(sel.index), children: "\u2715" })
|
|
2239
2292
|
] }),
|
|
2240
|
-
/* @__PURE__ */
|
|
2241
|
-
/* @__PURE__ */
|
|
2242
|
-
/* @__PURE__ */
|
|
2293
|
+
/* @__PURE__ */ jsxs16("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2294
|
+
/* @__PURE__ */ jsx16("span", { className: "w-16", children: "Colours" }),
|
|
2295
|
+
/* @__PURE__ */ jsx16("select", { "aria-label": "Gradient interpolation", className: selectClass11, value: ed.interpolation, onChange: (e) => controller.setGradient({ interpolation: e.target.value }), children: VECTOR_GRADIENT_INTERPOLATIONS.map((i) => /* @__PURE__ */ jsx16("option", { value: i, children: VECTOR_GRADIENT_INTERPOLATION_LABELS[i] }, i)) })
|
|
2243
2296
|
] }),
|
|
2244
|
-
/* @__PURE__ */
|
|
2245
|
-
/* @__PURE__ */
|
|
2246
|
-
/* @__PURE__ */
|
|
2297
|
+
/* @__PURE__ */ jsxs16("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2298
|
+
/* @__PURE__ */ jsx16("span", { className: "w-16", children: "Smooth" }),
|
|
2299
|
+
/* @__PURE__ */ jsx16(
|
|
2247
2300
|
"input",
|
|
2248
2301
|
{
|
|
2249
2302
|
type: "range",
|
|
@@ -2259,20 +2312,20 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2259
2312
|
}
|
|
2260
2313
|
)
|
|
2261
2314
|
] }),
|
|
2262
|
-
/* @__PURE__ */
|
|
2263
|
-
/* @__PURE__ */
|
|
2264
|
-
/* @__PURE__ */
|
|
2315
|
+
/* @__PURE__ */ jsxs16("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2316
|
+
/* @__PURE__ */ jsx16("span", { className: "w-16", children: "Spread" }),
|
|
2317
|
+
/* @__PURE__ */ jsx16("select", { "aria-label": "Gradient spread", className: selectClass11, value: ed.spread, onChange: (e) => controller.setGradient({ spread: e.target.value }), children: VECTOR_GRADIENT_SPREADS.map((sp) => /* @__PURE__ */ jsx16("option", { value: sp, children: VECTOR_GRADIENT_SPREAD_LABELS[sp] }, sp)) })
|
|
2265
2318
|
] }),
|
|
2266
|
-
ed.target === "stroke" && /* @__PURE__ */
|
|
2267
|
-
/* @__PURE__ */
|
|
2268
|
-
/* @__PURE__ */
|
|
2319
|
+
ed.target === "stroke" && /* @__PURE__ */ jsxs16("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2320
|
+
/* @__PURE__ */ jsx16("span", { className: "w-16", children: "On stroke" }),
|
|
2321
|
+
/* @__PURE__ */ jsx16("select", { "aria-label": "Gradient on stroke", className: selectClass11, value: ed.strokeMode, onChange: (e) => controller.setGradient({ strokeMode: e.target.value }), children: VECTOR_STROKE_GRADIENT_MODES.map((m) => /* @__PURE__ */ jsx16("option", { value: m, children: VECTOR_STROKE_GRADIENT_MODE_LABELS[m] }, m)) })
|
|
2269
2322
|
] })
|
|
2270
2323
|
] })
|
|
2271
2324
|
] });
|
|
2272
2325
|
}
|
|
2273
2326
|
|
|
2274
2327
|
// src/vector/VectorToolbar.tsx
|
|
2275
|
-
import { Fragment as Fragment6, jsx as
|
|
2328
|
+
import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2276
2329
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
2277
2330
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
2278
2331
|
var buttonClass14 = "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";
|
|
@@ -2295,9 +2348,9 @@ function VectorToolbar({
|
|
|
2295
2348
|
const maskSelected = state.selection.some((id) => isVectorMaskGroup(controller.getNode(id)));
|
|
2296
2349
|
const [live, setLive] = React9.useState(false);
|
|
2297
2350
|
const booleanDisabled = live ? count < 1 : count < 2;
|
|
2298
|
-
const act = (label, title, run, disabled = false) => /* @__PURE__ */
|
|
2299
|
-
return /* @__PURE__ */
|
|
2300
|
-
/* @__PURE__ */
|
|
2351
|
+
const act = (label, title, run, disabled = false) => /* @__PURE__ */ jsx17("button", { type: "button", className: buttonClass14, title, "aria-label": title, disabled, onClick: () => void run(), children: label }, label);
|
|
2352
|
+
return /* @__PURE__ */ jsxs17("div", { role: "toolbar", "aria-label": "Vector tools", className: `flex flex-wrap items-center gap-1 ${className ?? ""}`, children: [
|
|
2353
|
+
/* @__PURE__ */ jsx17("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Tools", children: tools.map((tool) => /* @__PURE__ */ jsx17(
|
|
2301
2354
|
"button",
|
|
2302
2355
|
{
|
|
2303
2356
|
type: "button",
|
|
@@ -2311,12 +2364,12 @@ function VectorToolbar({
|
|
|
2311
2364
|
},
|
|
2312
2365
|
tool
|
|
2313
2366
|
)) }),
|
|
2314
|
-
showHistory && /* @__PURE__ */
|
|
2367
|
+
showHistory && /* @__PURE__ */ jsxs17("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "History", children: [
|
|
2315
2368
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
2316
2369
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
2317
2370
|
] }),
|
|
2318
|
-
showSnap && /* @__PURE__ */
|
|
2319
|
-
/* @__PURE__ */
|
|
2371
|
+
showSnap && /* @__PURE__ */ jsxs17("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Snapping", children: [
|
|
2372
|
+
/* @__PURE__ */ jsx17(
|
|
2320
2373
|
"button",
|
|
2321
2374
|
{
|
|
2322
2375
|
type: "button",
|
|
@@ -2329,7 +2382,7 @@ function VectorToolbar({
|
|
|
2329
2382
|
children: "Snap"
|
|
2330
2383
|
}
|
|
2331
2384
|
),
|
|
2332
|
-
/* @__PURE__ */
|
|
2385
|
+
/* @__PURE__ */ jsxs17(
|
|
2333
2386
|
"select",
|
|
2334
2387
|
{
|
|
2335
2388
|
"data-vector-polar": "",
|
|
@@ -2339,8 +2392,8 @@ function VectorToolbar({
|
|
|
2339
2392
|
value: String(vectorPolarIncrementOf(state.snap.angles) ?? ""),
|
|
2340
2393
|
onChange: (e) => controller.setSnap({ angles: vectorPolarAngles(Number(e.target.value)) }),
|
|
2341
2394
|
children: [
|
|
2342
|
-
vectorPolarIncrementOf(state.snap.angles) === null && /* @__PURE__ */
|
|
2343
|
-
[90, 45, 30, 15].map((n) => /* @__PURE__ */
|
|
2395
|
+
vectorPolarIncrementOf(state.snap.angles) === null && /* @__PURE__ */ jsx17("option", { value: "", children: "Custom" }),
|
|
2396
|
+
[90, 45, 30, 15].map((n) => /* @__PURE__ */ jsxs17("option", { value: n, children: [
|
|
2344
2397
|
n,
|
|
2345
2398
|
"\xB0"
|
|
2346
2399
|
] }, n))
|
|
@@ -2348,8 +2401,8 @@ function VectorToolbar({
|
|
|
2348
2401
|
}
|
|
2349
2402
|
)
|
|
2350
2403
|
] }),
|
|
2351
|
-
showPathEdit && /* @__PURE__ */
|
|
2352
|
-
VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */
|
|
2404
|
+
showPathEdit && /* @__PURE__ */ jsxs17("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Path editing", children: [
|
|
2405
|
+
VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */ jsx17(
|
|
2353
2406
|
"button",
|
|
2354
2407
|
{
|
|
2355
2408
|
type: "button",
|
|
@@ -2363,7 +2416,7 @@ function VectorToolbar({
|
|
|
2363
2416
|
},
|
|
2364
2417
|
a.id
|
|
2365
2418
|
)),
|
|
2366
|
-
VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */
|
|
2419
|
+
VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ jsx17(
|
|
2367
2420
|
"button",
|
|
2368
2421
|
{
|
|
2369
2422
|
type: "button",
|
|
@@ -2377,9 +2430,9 @@ function VectorToolbar({
|
|
|
2377
2430
|
},
|
|
2378
2431
|
t.key
|
|
2379
2432
|
)),
|
|
2380
|
-
state.tool === "pencil" && /* @__PURE__ */
|
|
2433
|
+
state.tool === "pencil" && /* @__PURE__ */ jsxs17("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
2381
2434
|
"Smoothing",
|
|
2382
|
-
/* @__PURE__ */
|
|
2435
|
+
/* @__PURE__ */ jsx17(
|
|
2383
2436
|
"input",
|
|
2384
2437
|
{
|
|
2385
2438
|
type: "range",
|
|
@@ -2393,9 +2446,9 @@ function VectorToolbar({
|
|
|
2393
2446
|
}
|
|
2394
2447
|
)
|
|
2395
2448
|
] }),
|
|
2396
|
-
state.tool === "eraser" && /* @__PURE__ */
|
|
2449
|
+
state.tool === "eraser" && /* @__PURE__ */ jsxs17("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
2397
2450
|
"Size",
|
|
2398
|
-
/* @__PURE__ */
|
|
2451
|
+
/* @__PURE__ */ jsx17(
|
|
2399
2452
|
"input",
|
|
2400
2453
|
{
|
|
2401
2454
|
type: "number",
|
|
@@ -2411,7 +2464,7 @@ function VectorToolbar({
|
|
|
2411
2464
|
}
|
|
2412
2465
|
)
|
|
2413
2466
|
] }),
|
|
2414
|
-
state.tool === "paintBucket" && /* @__PURE__ */
|
|
2467
|
+
state.tool === "paintBucket" && /* @__PURE__ */ jsx17(
|
|
2415
2468
|
"button",
|
|
2416
2469
|
{
|
|
2417
2470
|
type: "button",
|
|
@@ -2425,7 +2478,7 @@ function VectorToolbar({
|
|
|
2425
2478
|
}
|
|
2426
2479
|
)
|
|
2427
2480
|
] }),
|
|
2428
|
-
showDistort && /* @__PURE__ */
|
|
2481
|
+
showDistort && /* @__PURE__ */ jsx17("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Distort", children: /* @__PURE__ */ jsx17(
|
|
2429
2482
|
"button",
|
|
2430
2483
|
{
|
|
2431
2484
|
type: "button",
|
|
@@ -2438,10 +2491,10 @@ function VectorToolbar({
|
|
|
2438
2491
|
children: "Distort"
|
|
2439
2492
|
}
|
|
2440
2493
|
) }),
|
|
2441
|
-
showBlend && /* @__PURE__ */
|
|
2442
|
-
showArrange && /* @__PURE__ */
|
|
2443
|
-
/* @__PURE__ */
|
|
2444
|
-
/* @__PURE__ */
|
|
2494
|
+
showBlend && /* @__PURE__ */ jsx17(VectorBlendControls, { controller }),
|
|
2495
|
+
showArrange && /* @__PURE__ */ jsxs17(Fragment6, { children: [
|
|
2496
|
+
/* @__PURE__ */ jsxs17("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Combine", children: [
|
|
2497
|
+
/* @__PURE__ */ jsx17(
|
|
2445
2498
|
"button",
|
|
2446
2499
|
{
|
|
2447
2500
|
type: "button",
|
|
@@ -2463,7 +2516,7 @@ function VectorToolbar({
|
|
|
2463
2516
|
act("\u25D0", `Make Clipping Mask (${modKeyLabel()}+7)`, () => controller.makeMask("clip"), count < 2),
|
|
2464
2517
|
act("\u25D1", `Release Mask (${modKeyLabel()}+Alt+7)`, () => controller.releaseMask(), !maskSelected)
|
|
2465
2518
|
] }),
|
|
2466
|
-
/* @__PURE__ */
|
|
2519
|
+
/* @__PURE__ */ jsx17("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Pathfinder", children: VECTOR_PATHFINDER_ACTIONS.map((a) => /* @__PURE__ */ jsx17(
|
|
2467
2520
|
"button",
|
|
2468
2521
|
{
|
|
2469
2522
|
type: "button",
|
|
@@ -2477,7 +2530,7 @@ function VectorToolbar({
|
|
|
2477
2530
|
},
|
|
2478
2531
|
a.id
|
|
2479
2532
|
)) }),
|
|
2480
|
-
/* @__PURE__ */
|
|
2533
|
+
/* @__PURE__ */ jsxs17("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
2481
2534
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
2482
2535
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
2483
2536
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -2495,19 +2548,19 @@ function VectorBlendControls({ controller }) {
|
|
|
2495
2548
|
const blend = getVectorBlendControls(state);
|
|
2496
2549
|
const o = blend.options;
|
|
2497
2550
|
const selected = blend.ids.length > 0;
|
|
2498
|
-
return /* @__PURE__ */
|
|
2499
|
-
/* @__PURE__ */
|
|
2500
|
-
/* @__PURE__ */
|
|
2551
|
+
return /* @__PURE__ */ jsxs17("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Blend", "data-vector-blend-controls": "", children: [
|
|
2552
|
+
/* @__PURE__ */ jsx17("button", { type: "button", "data-vector-blend-action": "make", className: buttonClass14, title: "Make Blend", "aria-label": "Make Blend", disabled: !blend.canBlend, onClick: () => controller.blend(), children: "\u29D3" }),
|
|
2553
|
+
/* @__PURE__ */ jsx17(
|
|
2501
2554
|
"select",
|
|
2502
2555
|
{
|
|
2503
2556
|
"aria-label": "Blend spacing",
|
|
2504
2557
|
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
2505
2558
|
value: o.spacing,
|
|
2506
2559
|
onChange: (e) => applyVectorBlendOptions(controller, { spacing: e.target.value }),
|
|
2507
|
-
children: VECTOR_BLEND_SPACINGS.map((sp) => /* @__PURE__ */
|
|
2560
|
+
children: VECTOR_BLEND_SPACINGS.map((sp) => /* @__PURE__ */ jsx17("option", { value: sp, children: VECTOR_BLEND_SPACING_LABELS[sp] }, sp))
|
|
2508
2561
|
}
|
|
2509
2562
|
),
|
|
2510
|
-
o.spacing !== "smoothColor" && /* @__PURE__ */
|
|
2563
|
+
o.spacing !== "smoothColor" && /* @__PURE__ */ jsx17(
|
|
2511
2564
|
"input",
|
|
2512
2565
|
{
|
|
2513
2566
|
type: "number",
|
|
@@ -2523,7 +2576,7 @@ function VectorBlendControls({ controller }) {
|
|
|
2523
2576
|
}
|
|
2524
2577
|
}
|
|
2525
2578
|
),
|
|
2526
|
-
/* @__PURE__ */
|
|
2579
|
+
/* @__PURE__ */ jsx17(
|
|
2527
2580
|
"button",
|
|
2528
2581
|
{
|
|
2529
2582
|
type: "button",
|
|
@@ -2536,7 +2589,7 @@ function VectorBlendControls({ controller }) {
|
|
|
2536
2589
|
children: "\u293F"
|
|
2537
2590
|
}
|
|
2538
2591
|
),
|
|
2539
|
-
/* @__PURE__ */
|
|
2592
|
+
/* @__PURE__ */ jsx17(
|
|
2540
2593
|
"button",
|
|
2541
2594
|
{
|
|
2542
2595
|
type: "button",
|
|
@@ -2549,12 +2602,12 @@ function VectorBlendControls({ controller }) {
|
|
|
2549
2602
|
children: "\u2307"
|
|
2550
2603
|
}
|
|
2551
2604
|
),
|
|
2552
|
-
/* @__PURE__ */
|
|
2553
|
-
/* @__PURE__ */
|
|
2605
|
+
/* @__PURE__ */ jsx17("button", { type: "button", "data-vector-blend-action": "expand", className: buttonClass14, title: "Expand Blend", "aria-label": "Expand Blend", disabled: !selected, onClick: () => controller.expandBlend(), children: "\u29C9" }),
|
|
2606
|
+
/* @__PURE__ */ jsx17("button", { type: "button", "data-vector-blend-action": "release", className: buttonClass14, title: "Release Blend", "aria-label": "Release Blend", disabled: !selected, onClick: () => controller.releaseBlend(), children: "\u29C4" })
|
|
2554
2607
|
] });
|
|
2555
2608
|
}
|
|
2556
|
-
var
|
|
2557
|
-
var
|
|
2609
|
+
var selectClass12 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2610
|
+
var numberClass11 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
2558
2611
|
function VectorStylePanel({ controller, className }) {
|
|
2559
2612
|
const state = useVectorEditorState(controller);
|
|
2560
2613
|
const style = getVectorSelectionStyle(state);
|
|
@@ -2586,17 +2639,17 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2586
2639
|
if (style) controller.setWidthProfile(id);
|
|
2587
2640
|
else controller.setDefaults({ strokeWidthProfile: widthProfilePreset(id)?.length ? widthProfilePreset(id) : null });
|
|
2588
2641
|
};
|
|
2589
|
-
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */
|
|
2642
|
+
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ jsx17("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }) : null;
|
|
2590
2643
|
const arrowRow = (end, label) => {
|
|
2591
2644
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
2592
2645
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
2593
|
-
return /* @__PURE__ */
|
|
2594
|
-
/* @__PURE__ */
|
|
2595
|
-
/* @__PURE__ */
|
|
2596
|
-
/* @__PURE__ */
|
|
2597
|
-
VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */
|
|
2646
|
+
return /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
2647
|
+
/* @__PURE__ */ jsx17("span", { className: "w-16 text-xs text-foreground", children: label }),
|
|
2648
|
+
/* @__PURE__ */ jsxs17("select", { "aria-label": `${label} arrowhead`, className: selectClass12, value: source[key] ?? "", onChange: (e) => apply({ [key]: e.target.value || null }), children: [
|
|
2649
|
+
/* @__PURE__ */ jsx17("option", { value: "", children: "None" }),
|
|
2650
|
+
VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */ jsx17("option", { value: h, children: VECTOR_ARROWHEAD_LABELS[h] }, h))
|
|
2598
2651
|
] }),
|
|
2599
|
-
/* @__PURE__ */
|
|
2652
|
+
/* @__PURE__ */ jsx17(
|
|
2600
2653
|
"input",
|
|
2601
2654
|
{
|
|
2602
2655
|
type: "number",
|
|
@@ -2604,7 +2657,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2604
2657
|
step: 0.25,
|
|
2605
2658
|
"aria-label": `${label} arrowhead scale`,
|
|
2606
2659
|
title: "Scale (\xD7 stroke width)",
|
|
2607
|
-
className:
|
|
2660
|
+
className: numberClass11,
|
|
2608
2661
|
value: source[scaleKey],
|
|
2609
2662
|
onChange: (e) => {
|
|
2610
2663
|
const n = parseFloat(e.target.value);
|
|
@@ -2622,12 +2675,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2622
2675
|
const paint = source[key];
|
|
2623
2676
|
const hex = vectorPaintToHex6(paint);
|
|
2624
2677
|
const on = paint !== null && paint !== "none";
|
|
2625
|
-
return /* @__PURE__ */
|
|
2626
|
-
/* @__PURE__ */
|
|
2627
|
-
/* @__PURE__ */
|
|
2678
|
+
return /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
2679
|
+
/* @__PURE__ */ jsxs17("label", { className: "flex w-16 items-center gap-1.5 text-xs text-foreground", children: [
|
|
2680
|
+
/* @__PURE__ */ jsx17("input", { type: "checkbox", checked: on, "aria-label": `${label} on`, onChange: (e) => apply({ [key]: e.target.checked ? hex ?? "#000000" : null }) }),
|
|
2628
2681
|
label
|
|
2629
2682
|
] }),
|
|
2630
|
-
/* @__PURE__ */
|
|
2683
|
+
/* @__PURE__ */ jsx17(
|
|
2631
2684
|
"input",
|
|
2632
2685
|
{
|
|
2633
2686
|
type: "color",
|
|
@@ -2638,18 +2691,18 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2638
2691
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
2639
2692
|
}
|
|
2640
2693
|
),
|
|
2641
|
-
on && !hex && /* @__PURE__ */
|
|
2642
|
-
style?.mixed[key] && /* @__PURE__ */
|
|
2694
|
+
on && !hex && /* @__PURE__ */ jsx17("span", { className: "truncate text-[11px] text-muted-foreground", children: typeof paint === "string" ? paint : "Gradient" }),
|
|
2695
|
+
style?.mixed[key] && /* @__PURE__ */ jsx17("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
2643
2696
|
] });
|
|
2644
2697
|
};
|
|
2645
|
-
return /* @__PURE__ */
|
|
2646
|
-
/* @__PURE__ */
|
|
2698
|
+
return /* @__PURE__ */ jsxs17("div", { className: `space-y-2 ${className ?? ""}`, "aria-label": style ? "Selection style" : "New shape style", children: [
|
|
2699
|
+
/* @__PURE__ */ jsx17("p", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: style ? "Selection" : "New shapes" }),
|
|
2647
2700
|
paintRow("fill", "Fill"),
|
|
2648
2701
|
paintRow("stroke", "Stroke"),
|
|
2649
|
-
style && /* @__PURE__ */
|
|
2650
|
-
/* @__PURE__ */
|
|
2651
|
-
/* @__PURE__ */
|
|
2652
|
-
/* @__PURE__ */
|
|
2702
|
+
style && /* @__PURE__ */ jsx17(VectorGradientEditor, { controller }),
|
|
2703
|
+
/* @__PURE__ */ jsxs17("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
2704
|
+
/* @__PURE__ */ jsx17("span", { className: "w-16", children: "Width" }),
|
|
2705
|
+
/* @__PURE__ */ jsx17(
|
|
2653
2706
|
"input",
|
|
2654
2707
|
{
|
|
2655
2708
|
type: "number",
|
|
@@ -2665,29 +2718,29 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2665
2718
|
}
|
|
2666
2719
|
)
|
|
2667
2720
|
] }),
|
|
2668
|
-
/* @__PURE__ */
|
|
2669
|
-
/* @__PURE__ */
|
|
2670
|
-
/* @__PURE__ */
|
|
2721
|
+
/* @__PURE__ */ jsxs17("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "strokeAlign", children: [
|
|
2722
|
+
/* @__PURE__ */ jsx17("span", { className: "w-16", children: "Align" }),
|
|
2723
|
+
/* @__PURE__ */ jsx17("select", { "aria-label": "Stroke alignment", className: selectClass12, value: source.strokeAlign, onChange: (e) => apply({ strokeAlign: e.target.value }), children: Object.keys(VECTOR_STROKE_ALIGN_LABELS2).map((a) => /* @__PURE__ */ jsx17("option", { value: a, children: VECTOR_STROKE_ALIGN_LABELS2[a] }, a)) }),
|
|
2671
2724
|
mixed("strokeAlign")
|
|
2672
2725
|
] }),
|
|
2673
|
-
/* @__PURE__ */
|
|
2674
|
-
/* @__PURE__ */
|
|
2675
|
-
/* @__PURE__ */
|
|
2726
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "widthProfile", children: [
|
|
2727
|
+
/* @__PURE__ */ jsx17("span", { className: "w-16", children: "Profile" }),
|
|
2728
|
+
/* @__PURE__ */ jsxs17(
|
|
2676
2729
|
"select",
|
|
2677
2730
|
{
|
|
2678
2731
|
"aria-label": "Width profile",
|
|
2679
|
-
className:
|
|
2732
|
+
className: selectClass12,
|
|
2680
2733
|
value: source.widthProfile,
|
|
2681
2734
|
onChange: (e) => {
|
|
2682
2735
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
2683
2736
|
},
|
|
2684
2737
|
children: [
|
|
2685
|
-
VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */
|
|
2686
|
-
source.widthProfile === "custom" && /* @__PURE__ */
|
|
2738
|
+
VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */ jsx17("option", { value: p.id, children: p.label }, p.id)),
|
|
2739
|
+
source.widthProfile === "custom" && /* @__PURE__ */ jsx17("option", { value: "custom", disabled: true, children: "Custom" })
|
|
2687
2740
|
]
|
|
2688
2741
|
}
|
|
2689
2742
|
),
|
|
2690
|
-
/* @__PURE__ */
|
|
2743
|
+
/* @__PURE__ */ jsx17(
|
|
2691
2744
|
"button",
|
|
2692
2745
|
{
|
|
2693
2746
|
type: "button",
|
|
@@ -2701,27 +2754,27 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2701
2754
|
),
|
|
2702
2755
|
mixed("widthProfile")
|
|
2703
2756
|
] }),
|
|
2704
|
-
source.hasOpenPath && /* @__PURE__ */
|
|
2757
|
+
source.hasOpenPath && /* @__PURE__ */ jsxs17(Fragment6, { children: [
|
|
2705
2758
|
arrowRow("start", "Start"),
|
|
2706
2759
|
arrowRow("end", "End"),
|
|
2707
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */
|
|
2708
|
-
/* @__PURE__ */
|
|
2709
|
-
/* @__PURE__ */
|
|
2710
|
-
/* @__PURE__ */
|
|
2711
|
-
/* @__PURE__ */
|
|
2760
|
+
(source.startArrow || source.endArrow) && /* @__PURE__ */ jsxs17("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "arrowAlign", children: [
|
|
2761
|
+
/* @__PURE__ */ jsx17("span", { className: "w-16", children: "Heads" }),
|
|
2762
|
+
/* @__PURE__ */ jsxs17("select", { "aria-label": "Arrowhead alignment", className: selectClass12, value: source.arrowAlign, onChange: (e) => apply({ arrowAlign: e.target.value }), children: [
|
|
2763
|
+
/* @__PURE__ */ jsx17("option", { value: "extend", children: "Tip past end" }),
|
|
2764
|
+
/* @__PURE__ */ jsx17("option", { value: "tip", children: "Tip at end" })
|
|
2712
2765
|
] })
|
|
2713
2766
|
] })
|
|
2714
2767
|
] }),
|
|
2715
|
-
source.corners > 0 && /* @__PURE__ */
|
|
2716
|
-
/* @__PURE__ */
|
|
2717
|
-
/* @__PURE__ */
|
|
2768
|
+
source.corners > 0 && /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", "data-vector-style": "corners", children: [
|
|
2769
|
+
/* @__PURE__ */ jsx17("span", { className: "w-16 text-xs text-foreground", children: "Corners" }),
|
|
2770
|
+
/* @__PURE__ */ jsx17(
|
|
2718
2771
|
"input",
|
|
2719
2772
|
{
|
|
2720
2773
|
type: "number",
|
|
2721
2774
|
min: 0,
|
|
2722
2775
|
step: 1,
|
|
2723
2776
|
"aria-label": "Corner radius",
|
|
2724
|
-
className:
|
|
2777
|
+
className: numberClass11,
|
|
2725
2778
|
value: Math.round(source.cornerRadius * 100) / 100,
|
|
2726
2779
|
onChange: (e) => {
|
|
2727
2780
|
const n = parseFloat(e.target.value);
|
|
@@ -2729,12 +2782,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2729
2782
|
}
|
|
2730
2783
|
}
|
|
2731
2784
|
),
|
|
2732
|
-
/* @__PURE__ */
|
|
2785
|
+
/* @__PURE__ */ jsx17("select", { "aria-label": "Corner kind", className: selectClass12, value: source.cornerKind, onChange: (e) => setCorners({ kind: e.target.value }), children: VECTOR_CORNER_KINDS.map((k) => /* @__PURE__ */ jsx17("option", { value: k, children: VECTOR_CORNER_KIND_LABELS[k] }, k)) }),
|
|
2733
2786
|
mixed("cornerRadius")
|
|
2734
2787
|
] }),
|
|
2735
|
-
style && source.corners > 0 && source.cornerKind === "round" && source.cornerRadius > 0 && /* @__PURE__ */
|
|
2736
|
-
/* @__PURE__ */
|
|
2737
|
-
/* @__PURE__ */
|
|
2788
|
+
style && source.corners > 0 && source.cornerKind === "round" && source.cornerRadius > 0 && /* @__PURE__ */ jsxs17("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: [
|
|
2789
|
+
/* @__PURE__ */ jsx17("span", { className: "w-16", children: "Smoothing" }),
|
|
2790
|
+
/* @__PURE__ */ jsx17(
|
|
2738
2791
|
"input",
|
|
2739
2792
|
{
|
|
2740
2793
|
type: "range",
|
|
@@ -2749,9 +2802,9 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2749
2802
|
}
|
|
2750
2803
|
)
|
|
2751
2804
|
] }),
|
|
2752
|
-
style && /* @__PURE__ */
|
|
2753
|
-
/* @__PURE__ */
|
|
2754
|
-
/* @__PURE__ */
|
|
2805
|
+
style && /* @__PURE__ */ jsxs17("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
2806
|
+
/* @__PURE__ */ jsx17("span", { className: "w-16", children: "Opacity" }),
|
|
2807
|
+
/* @__PURE__ */ jsx17(
|
|
2755
2808
|
"input",
|
|
2756
2809
|
{
|
|
2757
2810
|
type: "range",
|
|
@@ -2765,24 +2818,25 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2765
2818
|
}
|
|
2766
2819
|
)
|
|
2767
2820
|
] }),
|
|
2768
|
-
/* @__PURE__ */
|
|
2769
|
-
style && /* @__PURE__ */
|
|
2770
|
-
style && /* @__PURE__ */
|
|
2771
|
-
style && /* @__PURE__ */
|
|
2772
|
-
style && /* @__PURE__ */
|
|
2773
|
-
/* @__PURE__ */
|
|
2774
|
-
/* @__PURE__ */
|
|
2775
|
-
/* @__PURE__ */
|
|
2776
|
-
/* @__PURE__ */
|
|
2777
|
-
/* @__PURE__ */
|
|
2778
|
-
/* @__PURE__ */
|
|
2779
|
-
/* @__PURE__ */
|
|
2821
|
+
/* @__PURE__ */ jsx17(VectorTextPanel, { controller }),
|
|
2822
|
+
style && /* @__PURE__ */ jsx17(VectorAppearancePanel, { controller }),
|
|
2823
|
+
style && /* @__PURE__ */ jsx17(VectorEffectsPanel, { controller }),
|
|
2824
|
+
style && /* @__PURE__ */ jsx17(VectorEnvelopePanel, { controller }),
|
|
2825
|
+
style && /* @__PURE__ */ jsx17(VectorMaskPanel, { controller }),
|
|
2826
|
+
/* @__PURE__ */ jsx17(VectorFramePanel, { controller }),
|
|
2827
|
+
/* @__PURE__ */ jsx17(VectorConnectorPanel, { controller }),
|
|
2828
|
+
/* @__PURE__ */ jsx17(VectorShadingPanel, { controller }),
|
|
2829
|
+
/* @__PURE__ */ jsx17(VectorSymmetryPanel, { controller }),
|
|
2830
|
+
/* @__PURE__ */ jsx17(VectorLensPanel, { controller }),
|
|
2831
|
+
/* @__PURE__ */ jsx17(VectorTracePanel, { controller }),
|
|
2832
|
+
/* @__PURE__ */ jsx17(VectorConstraintsPanel, { controller }),
|
|
2833
|
+
/* @__PURE__ */ jsx17(VectorSymbolsPanel, { controller })
|
|
2780
2834
|
] });
|
|
2781
2835
|
}
|
|
2782
2836
|
|
|
2783
2837
|
// src/vector/VectorProviderEffectsPanel.tsx
|
|
2784
2838
|
import { useState as useState7, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
2785
|
-
import { Fragment as Fragment7, jsx as
|
|
2839
|
+
import { Fragment as Fragment7, jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2786
2840
|
var btn = "rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40";
|
|
2787
2841
|
function Controls({ controller, group }) {
|
|
2788
2842
|
const provider = controller.effectsProvider;
|
|
@@ -2790,11 +2844,11 @@ function Controls({ controller, group }) {
|
|
|
2790
2844
|
const { description, error } = useEffectDescription(provider, tag.effect);
|
|
2791
2845
|
const [message, setMessage] = useState7(null);
|
|
2792
2846
|
const run = (work) => void work.then(() => setMessage(null), (e) => setMessage(e instanceof Error ? e.message : String(e)));
|
|
2793
|
-
if (!provider) return /* @__PURE__ */
|
|
2794
|
-
if (error) return /* @__PURE__ */
|
|
2795
|
-
if (!description) return /* @__PURE__ */
|
|
2796
|
-
return /* @__PURE__ */
|
|
2797
|
-
/* @__PURE__ */
|
|
2847
|
+
if (!provider) return /* @__PURE__ */ jsx18("p", { className: "text-[11px] text-muted-foreground", children: "No effects provider: the shapes are kept as they are." });
|
|
2848
|
+
if (error) return /* @__PURE__ */ jsx18("p", { className: "text-[11px] text-amber-500", children: error });
|
|
2849
|
+
if (!description) return /* @__PURE__ */ jsx18("p", { className: "text-[11px] text-muted-foreground", children: "Loading\u2026" });
|
|
2850
|
+
return /* @__PURE__ */ jsxs18(Fragment7, { children: [
|
|
2851
|
+
/* @__PURE__ */ jsx18(
|
|
2798
2852
|
EffectParameters,
|
|
2799
2853
|
{
|
|
2800
2854
|
description,
|
|
@@ -2804,7 +2858,7 @@ function Controls({ controller, group }) {
|
|
|
2804
2858
|
onPreset: (v) => run(controller.updateVectorEffect(group.id, v))
|
|
2805
2859
|
}
|
|
2806
2860
|
),
|
|
2807
|
-
message && /* @__PURE__ */
|
|
2861
|
+
message && /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
|
|
2808
2862
|
] });
|
|
2809
2863
|
}
|
|
2810
2864
|
function VectorProviderEffectsPanel({ controller, className = "" }) {
|
|
@@ -2823,41 +2877,41 @@ function VectorProviderEffectsPanel({ controller, className = "" }) {
|
|
|
2823
2877
|
setMessage(null);
|
|
2824
2878
|
Promise.resolve().then(work).catch((e) => setMessage(e instanceof Error ? e.message : String(e)));
|
|
2825
2879
|
};
|
|
2826
|
-
return /* @__PURE__ */
|
|
2827
|
-
/* @__PURE__ */
|
|
2828
|
-
/* @__PURE__ */
|
|
2829
|
-
/* @__PURE__ */
|
|
2880
|
+
return /* @__PURE__ */ jsxs18("section", { className: `flex flex-col gap-2 text-xs ${className}`, "aria-label": "Vector effects", "data-vector-provider-effects": "", children: [
|
|
2881
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-1", children: [
|
|
2882
|
+
/* @__PURE__ */ jsx18("span", { className: "flex-1 font-semibold", children: "Effects" }),
|
|
2883
|
+
/* @__PURE__ */ jsx18("button", { type: "button", className: btn, disabled: !provider, "aria-pressed": browse, onClick: () => setBrowse(!browse), children: "Add effect\u2026" })
|
|
2830
2884
|
] }),
|
|
2831
|
-
!provider && /* @__PURE__ */
|
|
2832
|
-
browse && /* @__PURE__ */
|
|
2833
|
-
selected.map((g) => /* @__PURE__ */
|
|
2834
|
-
/* @__PURE__ */
|
|
2835
|
-
/* @__PURE__ */
|
|
2836
|
-
/* @__PURE__ */
|
|
2885
|
+
!provider && /* @__PURE__ */ jsx18("p", { className: "text-[11px] text-muted-foreground", children: "No effects provider is registered. Effect groups are kept as shapes." }),
|
|
2886
|
+
browse && /* @__PURE__ */ jsx18(EffectsBrowser, { provider, kinds: ["vector"], title: "Vector effects", onPick: (e) => (setBrowse(false), run(() => controller.addVectorEffect(e.id))) }),
|
|
2887
|
+
selected.map((g) => /* @__PURE__ */ jsxs18("div", { className: "space-y-1 rounded border border-border p-1", "data-vector-effect-group": g.id, children: [
|
|
2888
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-1", children: [
|
|
2889
|
+
/* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1 truncate font-medium", children: g.providerEffect.name ?? g.providerEffect.effect }),
|
|
2890
|
+
/* @__PURE__ */ jsx18("button", { type: "button", className: btn, title: "Keep the shapes as a plain group", onClick: () => run(() => controller.detachVectorEffect(g.id)), children: "Detach" })
|
|
2837
2891
|
] }),
|
|
2838
|
-
/* @__PURE__ */
|
|
2892
|
+
/* @__PURE__ */ jsx18(Controls, { controller, group: g })
|
|
2839
2893
|
] }, g.id)),
|
|
2840
|
-
groups.length > 0 && !selected.length && /* @__PURE__ */
|
|
2894
|
+
groups.length > 0 && !selected.length && /* @__PURE__ */ jsxs18("p", { className: "text-[11px] text-muted-foreground", children: [
|
|
2841
2895
|
"Select an effect group (",
|
|
2842
2896
|
groups.length,
|
|
2843
2897
|
" in the drawing) to change it."
|
|
2844
2898
|
] }),
|
|
2845
|
-
message && /* @__PURE__ */
|
|
2899
|
+
message && /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
|
|
2846
2900
|
] });
|
|
2847
2901
|
}
|
|
2848
2902
|
|
|
2849
2903
|
// src/vector/VectorEditor.tsx
|
|
2850
|
-
import { jsx as
|
|
2904
|
+
import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2851
2905
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, effects, className }) {
|
|
2852
2906
|
useEffects(controller, effects);
|
|
2853
2907
|
const effectsShown = !!effects || controller.vectorEffectGroups().length > 0;
|
|
2854
|
-
return /* @__PURE__ */
|
|
2855
|
-
/* @__PURE__ */
|
|
2856
|
-
/* @__PURE__ */
|
|
2857
|
-
/* @__PURE__ */
|
|
2858
|
-
showStylePanel && /* @__PURE__ */
|
|
2859
|
-
/* @__PURE__ */
|
|
2860
|
-
effectsShown && /* @__PURE__ */
|
|
2908
|
+
return /* @__PURE__ */ jsxs19("div", { className: `flex flex-col gap-2 ${className ?? ""}`, "data-vector-editor": "", children: [
|
|
2909
|
+
/* @__PURE__ */ jsx19(VectorToolbar, { controller, tools }),
|
|
2910
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex min-h-0 flex-col gap-2 md:flex-row", children: [
|
|
2911
|
+
/* @__PURE__ */ jsx19("div", { className: "relative min-h-[320px] flex-1 overflow-hidden rounded-md border border-border bg-muted/40", style: { height }, children: /* @__PURE__ */ jsx19(VectorCanvas, { controller, ...canvasProps }) }),
|
|
2912
|
+
showStylePanel && /* @__PURE__ */ jsxs19("div", { className: "flex w-full shrink-0 flex-col gap-2 md:w-56", children: [
|
|
2913
|
+
/* @__PURE__ */ jsx19(VectorStylePanel, { controller, className: "rounded-md border border-border p-3" }),
|
|
2914
|
+
effectsShown && /* @__PURE__ */ jsx19(VectorProviderEffectsPanel, { controller, className: "rounded-md border border-border p-3" })
|
|
2861
2915
|
] })
|
|
2862
2916
|
] })
|
|
2863
2917
|
] });
|
|
@@ -2875,6 +2929,7 @@ export {
|
|
|
2875
2929
|
VectorGradientAnnotator,
|
|
2876
2930
|
VectorGradientDefs,
|
|
2877
2931
|
VectorGradientEditor,
|
|
2932
|
+
VectorLensPanel,
|
|
2878
2933
|
VectorMaskPanel,
|
|
2879
2934
|
VectorMaskedNodes,
|
|
2880
2935
|
VectorProviderEffectsPanel,
|