@pixerate/editor-react 0.83.0 → 0.85.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 +476 -391
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +22 -1
- package/dist/vector/index.d.ts +22 -1
- package/dist/vector/index.js +336 -253
- package/dist/vector/index.js.map +1 -1
- package/package.json +3 -3
package/dist/vector/index.cjs
CHANGED
|
@@ -45,6 +45,8 @@ __export(vector_exports, {
|
|
|
45
45
|
VectorLensPanel: () => VectorLensPanel,
|
|
46
46
|
VectorMaskPanel: () => VectorMaskPanel,
|
|
47
47
|
VectorMaskedNodes: () => VectorMaskedNodes,
|
|
48
|
+
VectorPagesPanel: () => VectorPagesPanel,
|
|
49
|
+
VectorPerspectivePanel: () => VectorPerspectivePanel,
|
|
48
50
|
VectorProviderEffectsPanel: () => VectorProviderEffectsPanel,
|
|
49
51
|
VectorSceneNodes: () => VectorSceneNodes,
|
|
50
52
|
VectorShadingPanel: () => VectorShadingPanel,
|
|
@@ -694,6 +696,11 @@ function VectorCanvas({
|
|
|
694
696
|
sh.lines.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d, stroke: accentColor, strokeWidth: 1, opacity: 0.7 }, i)),
|
|
695
697
|
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
698
|
] }, `shading:${sh.nodeId}`)),
|
|
699
|
+
overlay.perspective && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-perspective-grid": "", fill: "none", pointerEvents: "none", children: [
|
|
700
|
+
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)),
|
|
701
|
+
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)),
|
|
702
|
+
/* @__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 })
|
|
703
|
+
] }),
|
|
697
704
|
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
705
|
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
706
|
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 +837,8 @@ function VectorCanvas({
|
|
|
830
837
|
}
|
|
831
838
|
|
|
832
839
|
// src/vector/VectorToolbar.tsx
|
|
833
|
-
var
|
|
834
|
-
var
|
|
840
|
+
var import_react11 = __toESM(require("react"), 1);
|
|
841
|
+
var import_vector19 = require("@pixerate/editor/vector");
|
|
835
842
|
|
|
836
843
|
// src/vector/VectorEffectsPanel.tsx
|
|
837
844
|
var import_vector4 = require("@pixerate/editor/vector");
|
|
@@ -1878,38 +1885,67 @@ function VectorFramePanel({ controller, className }) {
|
|
|
1878
1885
|
] });
|
|
1879
1886
|
}
|
|
1880
1887
|
|
|
1881
|
-
// src/vector/
|
|
1888
|
+
// src/vector/VectorPagesPanel.tsx
|
|
1882
1889
|
var import_vector12 = require("@pixerate/editor/vector");
|
|
1883
1890
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1884
|
-
var buttonClass9 = "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";
|
|
1891
|
+
var buttonClass9 = "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-[current=true]:bg-primary aria-[current=true]:text-primary-foreground";
|
|
1885
1892
|
var selectClass7 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
1893
|
+
function VectorPagesPanel({ controller, className }) {
|
|
1894
|
+
const state = useVectorEditorState(controller);
|
|
1895
|
+
const pages = (0, import_vector12.vectorPages)(state.document);
|
|
1896
|
+
const masters = (0, import_vector12.vectorMasterPages)(state.document);
|
|
1897
|
+
const selected = state.selection.map((id) => state.document.nodes.find((n) => n.id === id)).find((n) => (0, import_vector12.isVectorFrame)(n));
|
|
1898
|
+
const page = selected && !selected.frame.master ? selected : null;
|
|
1899
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-pages-panel": "", "aria-label": "Pages", children: [
|
|
1900
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
1901
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Pages" }),
|
|
1902
|
+
pages.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: buttonClass9, "aria-current": state.selection.includes(p.id), "data-vector-page": p.id, title: `Go to ${p.name ?? `page ${i + 1}`}`, onClick: () => controller.goToPage(p.id), children: i + 1 }, p.id)),
|
|
1903
|
+
masters.map((m) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: buttonClass9, "aria-current": state.selection.includes(m.id), "data-vector-master-page": m.id, title: `Go to master page ${m.name ?? ""}`, onClick: () => controller.goToPage(m.id), children: m.name ?? "Master" }, m.id)),
|
|
1904
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: buttonClass9, "data-vector-pages-action": "add", title: "Add a page after the last", onClick: () => controller.addPage(), children: "+ Page" }),
|
|
1905
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: buttonClass9, "data-vector-pages-action": "master", title: "Add a master page used by every page (headers, footers, {page} numbers)", onClick: () => controller.addMasterPage({ assignTo: "all" }), children: "+ Master" })
|
|
1906
|
+
] }),
|
|
1907
|
+
page && masters.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
1908
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "w-16" }),
|
|
1909
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("select", { "aria-label": "Master page", className: selectClass7, value: page.frame.masterId ?? "", onChange: (e) => controller.setPageMaster(e.target.value || null, { ids: [page.id] }), children: [
|
|
1910
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "", children: "No master" }),
|
|
1911
|
+
masters.map((m) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: m.id, children: m.name ?? "Master" }, m.id))
|
|
1912
|
+
] })
|
|
1913
|
+
] })
|
|
1914
|
+
] });
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
// src/vector/VectorConnectorPanel.tsx
|
|
1918
|
+
var import_vector13 = require("@pixerate/editor/vector");
|
|
1919
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1920
|
+
var buttonClass10 = "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";
|
|
1921
|
+
var selectClass8 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
1886
1922
|
var numberClass5 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
1887
1923
|
function VectorConnectorPanel({ controller, className }) {
|
|
1888
1924
|
const state = useVectorEditorState(controller);
|
|
1889
|
-
const panel = (0,
|
|
1925
|
+
const panel = (0, import_vector13.getVectorConnectorPanel)(state);
|
|
1890
1926
|
if (!panel) return null;
|
|
1891
1927
|
const ids = [panel.id];
|
|
1892
|
-
const end = (key, label, e) => /* @__PURE__ */ (0,
|
|
1893
|
-
/* @__PURE__ */ (0,
|
|
1894
|
-
e ? /* @__PURE__ */ (0,
|
|
1895
|
-
/* @__PURE__ */ (0,
|
|
1928
|
+
const end = (key, label, e) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-1", "data-vector-connector-end": key, children: [
|
|
1929
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "w-16 text-xs text-foreground", children: label }),
|
|
1930
|
+
e ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1931
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1896
1932
|
"select",
|
|
1897
1933
|
{
|
|
1898
1934
|
"aria-label": `${label} side`,
|
|
1899
|
-
className:
|
|
1935
|
+
className: selectClass8,
|
|
1900
1936
|
value: e.side ?? "auto",
|
|
1901
1937
|
onChange: (ev) => controller.setConnector({ [key]: { nodeId: e.nodeId, side: ev.target.value } }, { ids }),
|
|
1902
|
-
children:
|
|
1938
|
+
children: import_vector13.VECTOR_CONNECTOR_SIDES.map((s) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: s, children: import_vector13.VECTOR_CONNECTOR_SIDE_LABELS[s] }, s))
|
|
1903
1939
|
}
|
|
1904
1940
|
),
|
|
1905
|
-
/* @__PURE__ */ (0,
|
|
1906
|
-
] }) : /* @__PURE__ */ (0,
|
|
1941
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: buttonClass10, title: "Unglue: the end stays where it is", "aria-label": `Unglue ${label.toLowerCase()}`, onClick: () => controller.setConnector({ [key]: null }, { ids }), children: "Unglue" })
|
|
1942
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Free" })
|
|
1907
1943
|
] });
|
|
1908
|
-
return /* @__PURE__ */ (0,
|
|
1909
|
-
/* @__PURE__ */ (0,
|
|
1910
|
-
/* @__PURE__ */ (0,
|
|
1911
|
-
/* @__PURE__ */ (0,
|
|
1912
|
-
panel.route === "elbow" && /* @__PURE__ */ (0,
|
|
1944
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-connector-panel": panel.id, "aria-label": "Connector", children: [
|
|
1945
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
1946
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Connector" }),
|
|
1947
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("select", { "aria-label": "Connector route", className: selectClass8, value: panel.route, onChange: (e) => controller.setConnector({ route: e.target.value }, { ids }), children: import_vector13.VECTOR_CONNECTOR_ROUTES.map((r) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: r, children: import_vector13.VECTOR_CONNECTOR_ROUTE_LABELS[r] }, r)) }),
|
|
1948
|
+
panel.route === "elbow" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1913
1949
|
"input",
|
|
1914
1950
|
{
|
|
1915
1951
|
type: "number",
|
|
@@ -1933,9 +1969,9 @@ function VectorConnectorPanel({ controller, className }) {
|
|
|
1933
1969
|
|
|
1934
1970
|
// src/vector/VectorShadingPanel.tsx
|
|
1935
1971
|
var import_react8 = require("react");
|
|
1936
|
-
var
|
|
1937
|
-
var
|
|
1938
|
-
var
|
|
1972
|
+
var import_vector14 = require("@pixerate/editor/vector");
|
|
1973
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1974
|
+
var buttonClass11 = "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";
|
|
1939
1975
|
var numberClass6 = "h-7 w-12 rounded border border-border bg-background px-1.5 text-xs";
|
|
1940
1976
|
function VectorShadingPanel({ controller, className }) {
|
|
1941
1977
|
const state = useVectorEditorState(controller);
|
|
@@ -1945,8 +1981,8 @@ function VectorShadingPanel({ controller, className }) {
|
|
|
1945
1981
|
if (!path) return null;
|
|
1946
1982
|
const fill = path.fill;
|
|
1947
1983
|
const sel = state.shadingPoint?.nodeId === path.id ? state.shadingPoint : null;
|
|
1948
|
-
const mesh = (0,
|
|
1949
|
-
const free = (0,
|
|
1984
|
+
const mesh = (0, import_vector14.isVectorMeshGradient)(fill) ? fill : null;
|
|
1985
|
+
const free = (0, import_vector14.isVectorFreeformGradient)(fill) ? fill : null;
|
|
1950
1986
|
const color = sel ? mesh ? mesh.colors[sel.index] : free?.points[sel.index]?.color : void 0;
|
|
1951
1987
|
const opacity = sel ? mesh ? mesh.opacities?.[sel.index] ?? 1 : free?.points[sel.index]?.opacity ?? 1 : 1;
|
|
1952
1988
|
const spread = sel && free ? free.points[sel.index]?.spread ?? 0 : 0;
|
|
@@ -1955,29 +1991,29 @@ function VectorShadingPanel({ controller, className }) {
|
|
|
1955
1991
|
if (mesh) controller.setMeshPoint(path.id, sel.index, patch, merge ? { merge } : {});
|
|
1956
1992
|
else controller.setFreeformPoint(path.id, sel.index, patch, merge ? { merge } : {});
|
|
1957
1993
|
};
|
|
1958
|
-
return /* @__PURE__ */ (0,
|
|
1959
|
-
/* @__PURE__ */ (0,
|
|
1960
|
-
/* @__PURE__ */ (0,
|
|
1961
|
-
/* @__PURE__ */ (0,
|
|
1962
|
-
/* @__PURE__ */ (0,
|
|
1963
|
-
/* @__PURE__ */ (0,
|
|
1964
|
-
/* @__PURE__ */ (0,
|
|
1965
|
-
/* @__PURE__ */ (0,
|
|
1994
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-shading-panel": path.id, "aria-label": "Mesh and freeform gradient", children: [
|
|
1995
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
1996
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Shading" }),
|
|
1997
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "number", min: 1, max: 32, "aria-label": "Mesh rows", title: "Mesh rows", className: numberClass6, value: rows, onChange: (e) => setRows(Math.max(1, Math.min(32, parseInt(e.target.value, 10) || 1))) }),
|
|
1998
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-xs text-muted-foreground", children: "\xD7" }),
|
|
1999
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "number", min: 1, max: 32, "aria-label": "Mesh columns", title: "Mesh columns", className: numberClass6, value: columns, onChange: (e) => setColumns(Math.max(1, Math.min(32, parseInt(e.target.value, 10) || 1))) }),
|
|
2000
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: buttonClass11, "data-vector-shading-action": "mesh", title: "Create Gradient Mesh: smooth patches whose points blend colours (edit them with the Gradient tool)", onClick: () => controller.setMeshGradient({ rows, columns }, { ids: [path.id] }), children: "Mesh" }),
|
|
2001
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: buttonClass11, "data-vector-shading-action": "freeform", title: "Freeform Gradient: colour points blended across the shape (click inside with the Gradient tool to add one)", onClick: () => controller.setFreeformGradient({}, { ids: [path.id] }), children: "Freeform" })
|
|
1966
2002
|
] }),
|
|
1967
|
-
(mesh || free) && !sel && /* @__PURE__ */ (0,
|
|
2003
|
+
(mesh || free) && !sel && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { className: "text-[11px] text-muted-foreground", children: [
|
|
1968
2004
|
"Gradient tool (G): drag points; ",
|
|
1969
2005
|
free ? "click inside to add one, Alt-click to remove." : "pick one to colour it."
|
|
1970
2006
|
] }),
|
|
1971
|
-
sel && /* @__PURE__ */ (0,
|
|
1972
|
-
/* @__PURE__ */ (0,
|
|
2007
|
+
sel && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-wrap items-center gap-2", "data-vector-shading-point": sel.index, children: [
|
|
2008
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "w-16 text-xs text-foreground", children: [
|
|
1973
2009
|
"Point ",
|
|
1974
2010
|
sel.index
|
|
1975
2011
|
] }),
|
|
1976
|
-
/* @__PURE__ */ (0,
|
|
1977
|
-
/* @__PURE__ */ (0,
|
|
1978
|
-
free && /* @__PURE__ */ (0,
|
|
1979
|
-
/* @__PURE__ */ (0,
|
|
1980
|
-
/* @__PURE__ */ (0,
|
|
2012
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "color", "aria-label": "Point colour", className: "h-7 w-10 cursor-pointer rounded border border-border bg-background", value: (0, import_vector14.vectorPaintToHex)(color ?? "#000000") ?? "#000000", onChange: (e) => edit({ color: e.target.value }, "shading-color") }),
|
|
2013
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "range", min: 0, max: 1, step: 0.05, "aria-label": "Point opacity", title: "Opacity", className: "h-4 w-20 accent-primary", value: opacity, onChange: (e) => edit({ opacity: parseFloat(e.target.value) }, "shading-opacity") }),
|
|
2014
|
+
free && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
2015
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("input", { type: "range", min: 0, max: 1, step: 0.05, "aria-label": "Point spread", title: "Spread: pure colour round the point", className: "h-4 w-20 accent-primary", value: spread, onChange: (e) => edit({ spread: parseFloat(e.target.value) }, "shading-spread") }),
|
|
2016
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", className: buttonClass11, "aria-label": "Remove point", onClick: () => controller.removeFreeformPoint(path.id, sel.index), children: "Remove" })
|
|
1981
2017
|
] })
|
|
1982
2018
|
] })
|
|
1983
2019
|
] });
|
|
@@ -1985,9 +2021,9 @@ function VectorShadingPanel({ controller, className }) {
|
|
|
1985
2021
|
|
|
1986
2022
|
// src/vector/VectorTracePanel.tsx
|
|
1987
2023
|
var import_react9 = require("react");
|
|
1988
|
-
var
|
|
1989
|
-
var
|
|
1990
|
-
var
|
|
2024
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2025
|
+
var buttonClass12 = "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";
|
|
2026
|
+
var selectClass9 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
1991
2027
|
var numberClass7 = "h-7 w-12 rounded border border-border bg-background px-1.5 text-xs";
|
|
1992
2028
|
async function filePixels(file, max = 1e6) {
|
|
1993
2029
|
const bitmap = await createImageBitmap(file);
|
|
@@ -2017,16 +2053,16 @@ function VectorTracePanel({ controller, className }) {
|
|
|
2017
2053
|
setMessage("That file could not be read as an image.");
|
|
2018
2054
|
}
|
|
2019
2055
|
};
|
|
2020
|
-
return /* @__PURE__ */ (0,
|
|
2021
|
-
/* @__PURE__ */ (0,
|
|
2022
|
-
/* @__PURE__ */ (0,
|
|
2023
|
-
/* @__PURE__ */ (0,
|
|
2024
|
-
/* @__PURE__ */ (0,
|
|
2025
|
-
/* @__PURE__ */ (0,
|
|
2056
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: `space-y-1 ${className ?? ""}`, "data-vector-trace-panel": "", "aria-label": "Image trace", children: [
|
|
2057
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
2058
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Trace" }),
|
|
2059
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("select", { "aria-label": "Trace mode", className: selectClass9, value: mode, onChange: (e) => setMode(e.target.value), children: [
|
|
2060
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("option", { value: "threshold", children: "Black & white" }),
|
|
2061
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("option", { value: "color", children: "Colours" })
|
|
2026
2062
|
] }),
|
|
2027
|
-
mode === "color" && /* @__PURE__ */ (0,
|
|
2028
|
-
/* @__PURE__ */ (0,
|
|
2029
|
-
/* @__PURE__ */ (0,
|
|
2063
|
+
mode === "color" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("input", { type: "number", min: 2, max: 32, "aria-label": "Trace colours", title: "Colours", className: numberClass7, value: colors, onChange: (e) => setColors(Math.max(2, Math.min(32, parseInt(e.target.value, 10) || 2))) }),
|
|
2064
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: buttonClass12, "data-vector-trace-action": "", title: "Image Trace: pick an image to turn into paths", onClick: () => input.current?.click(), children: "Image\u2026" }),
|
|
2065
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2030
2066
|
"input",
|
|
2031
2067
|
{
|
|
2032
2068
|
ref: input,
|
|
@@ -2041,79 +2077,124 @@ function VectorTracePanel({ controller, className }) {
|
|
|
2041
2077
|
}
|
|
2042
2078
|
)
|
|
2043
2079
|
] }),
|
|
2044
|
-
message && /* @__PURE__ */ (0,
|
|
2080
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-[11px] text-red-600", children: message })
|
|
2045
2081
|
] });
|
|
2046
2082
|
}
|
|
2047
2083
|
|
|
2048
2084
|
// src/vector/VectorSymmetryPanel.tsx
|
|
2049
|
-
var
|
|
2050
|
-
var
|
|
2051
|
-
var
|
|
2052
|
-
var
|
|
2085
|
+
var import_vector15 = require("@pixerate/editor/vector");
|
|
2086
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2087
|
+
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
|
+
var selectClass10 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2053
2089
|
var numberClass8 = "h-7 w-12 rounded border border-border bg-background px-1.5 text-xs";
|
|
2054
2090
|
function VectorSymmetryPanel({ controller, className }) {
|
|
2055
2091
|
const state = useVectorEditorState(controller);
|
|
2056
|
-
const group = state.selection.map((id) => controller.getNode(id)).find(
|
|
2092
|
+
const group = state.selection.map((id) => controller.getNode(id)).find(import_vector15.isVectorSymmetryGroup) ?? null;
|
|
2057
2093
|
const s = group?.symmetry;
|
|
2058
2094
|
const ids = group ? [group.id] : void 0;
|
|
2059
2095
|
const drawing = !!group && state.symmetryTarget === group.id;
|
|
2060
|
-
return /* @__PURE__ */ (0,
|
|
2061
|
-
/* @__PURE__ */ (0,
|
|
2062
|
-
/* @__PURE__ */ (0,
|
|
2063
|
-
!group && /* @__PURE__ */ (0,
|
|
2064
|
-
!group && /* @__PURE__ */ (0,
|
|
2065
|
-
group && s && /* @__PURE__ */ (0,
|
|
2066
|
-
/* @__PURE__ */ (0,
|
|
2067
|
-
s.mode === "radial" && /* @__PURE__ */ (0,
|
|
2068
|
-
/* @__PURE__ */ (0,
|
|
2069
|
-
/* @__PURE__ */ (0,
|
|
2070
|
-
/* @__PURE__ */ (0,
|
|
2096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-symmetry-panel": "", "aria-label": "Symmetry", children: [
|
|
2097
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2098
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Symmetry" }),
|
|
2099
|
+
!group && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", className: buttonClass13, "data-vector-symmetry-action": "make", title: "Make Symmetry: the selection (or nothing yet) mirrored live across a vertical axis", onClick: () => controller.makeSymmetry({ mode: "vertical" }), children: "Mirror" }),
|
|
2100
|
+
!group && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", className: buttonClass13, "data-vector-symmetry-action": "radial", title: "Make Symmetry: the selection repeated round its centre", onClick: () => controller.makeSymmetry({ mode: "radial", copies: 6 }), children: "Radial" }),
|
|
2101
|
+
group && s && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
2102
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("select", { "aria-label": "Symmetry mode", className: selectClass10, value: s.mode, onChange: (e) => controller.setSymmetry({ mode: e.target.value }, { ids }), children: import_vector15.VECTOR_SYMMETRY_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: m, children: import_vector15.VECTOR_SYMMETRY_MODE_LABELS[m] }, m)) }),
|
|
2103
|
+
s.mode === "radial" && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
2104
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("input", { type: "number", min: 2, max: 64, "aria-label": "Symmetry copies", title: "Copies round the circle", className: numberClass8, value: s.copies ?? 6, onChange: (e) => controller.setSymmetry({ copies: Math.max(2, Math.min(64, parseInt(e.target.value, 10) || 2)) }, { ids }) }),
|
|
2105
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", title: "Mirror each copy too (kaleidoscope)", children: [
|
|
2106
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("input", { type: "checkbox", "aria-label": "Mirror copies", checked: !!s.mirror, onChange: (e) => controller.setSymmetry({ mirror: e.target.checked }, { ids }) }),
|
|
2071
2107
|
"Mirror"
|
|
2072
2108
|
] })
|
|
2073
2109
|
] })
|
|
2074
2110
|
] })
|
|
2075
2111
|
] }),
|
|
2076
|
-
group && /* @__PURE__ */ (0,
|
|
2077
|
-
/* @__PURE__ */ (0,
|
|
2078
|
-
/* @__PURE__ */ (0,
|
|
2079
|
-
/* @__PURE__ */ (0,
|
|
2080
|
-
/* @__PURE__ */ (0,
|
|
2112
|
+
group && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2113
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "w-16" }),
|
|
2114
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", className: buttonClass13, "aria-pressed": drawing, "data-vector-symmetry-action": "draw", title: "Draw inside: new pen, pencil, shape and text art goes into the group, mirrored as you draw (Escape stops)", onClick: () => drawing ? controller.exitSymmetry() : controller.enterSymmetry(group.id), children: "Draw inside" }),
|
|
2115
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", className: buttonClass13, title: "Expand: keep the copies as real objects", onClick: () => controller.releaseSymmetry({ ids, expand: true }), children: "Expand" }),
|
|
2116
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", className: buttonClass13, title: "Release: stop repeating (the copies go)", onClick: () => controller.releaseSymmetry({ ids }), children: "Release" })
|
|
2117
|
+
] })
|
|
2118
|
+
] });
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
// src/vector/VectorPerspectivePanel.tsx
|
|
2122
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
2123
|
+
var import_vector16 = require("@pixerate/editor/vector");
|
|
2124
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
2125
|
+
var buttonClass14 = "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";
|
|
2126
|
+
var selectClass11 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2127
|
+
var PLANE_LABELS = { floor: "Floor", left: "Left wall", right: "Right wall", side: "Side wall", front: "Front" };
|
|
2128
|
+
function VectorPerspectivePanel({ controller, className }) {
|
|
2129
|
+
const state = useVectorEditorState(controller);
|
|
2130
|
+
const grid = state.document.perspective ?? null;
|
|
2131
|
+
const planes = grid ? (0, import_vector16.vectorPerspectivePlanes)(grid) : [];
|
|
2132
|
+
const [attachTo, setAttachTo] = import_react10.default.useState("");
|
|
2133
|
+
const target = (state.perspectivePlane ?? attachTo) || planes[0];
|
|
2134
|
+
const add = (n) => controller.setPerspective((0, import_vector16.vectorPerspectivePreset)(n, state.document.width, state.document.height));
|
|
2135
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-perspective-panel": "", "aria-label": "Perspective", children: [
|
|
2136
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2137
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Perspective" }),
|
|
2138
|
+
[1, 2, 3].map((n) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("button", { type: "button", className: buttonClass14, "aria-pressed": grid?.vanishingPoints.length === n, "data-vector-perspective-preset": n, title: `A ${n}-point perspective grid for the page`, onClick: () => add(n), children: [
|
|
2139
|
+
n,
|
|
2140
|
+
"-pt"
|
|
2141
|
+
] }, n))
|
|
2142
|
+
] }),
|
|
2143
|
+
grid && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2144
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "w-16" }),
|
|
2145
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("select", { "aria-label": "Draw on plane", title: "New rectangles, ellipses, polygons and stars are drawn on this plane", className: selectClass11, value: state.perspectivePlane ?? "", onChange: (e) => controller.setPerspectivePlane(e.target.value || null), children: [
|
|
2146
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("option", { value: "", children: "Draw flat" }),
|
|
2147
|
+
planes.map((p) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("option", { value: p, children: [
|
|
2148
|
+
"Draw on ",
|
|
2149
|
+
PLANE_LABELS[p].toLowerCase()
|
|
2150
|
+
] }, p))
|
|
2151
|
+
] })
|
|
2152
|
+
] }),
|
|
2153
|
+
grid && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2154
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "w-16" }),
|
|
2155
|
+
!state.perspectivePlane && /* @__PURE__ */ (0, import_jsx_runtime16.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_runtime16.jsx)("option", { value: p, children: PLANE_LABELS[p] }, p)) }),
|
|
2156
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", className: buttonClass14, disabled: !state.selection.length, title: "Lay the selection onto the plane (read flat from the grid's origin)", onClick: () => controller.attachToPerspective(target), children: "Attach" }),
|
|
2157
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", title: "Show the grid on the canvas", children: [
|
|
2158
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("input", { type: "checkbox", "aria-label": "Show perspective grid", checked: grid.visible !== false, onChange: (e) => controller.setPerspective({ ...grid, visible: e.target.checked }) }),
|
|
2159
|
+
"Show"
|
|
2160
|
+
] }),
|
|
2161
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("button", { type: "button", className: buttonClass14, title: "Remove the grid (art on it stays)", onClick: () => controller.setPerspective(null), children: "Remove" })
|
|
2081
2162
|
] })
|
|
2082
2163
|
] });
|
|
2083
2164
|
}
|
|
2084
2165
|
|
|
2085
2166
|
// src/vector/VectorLensPanel.tsx
|
|
2086
|
-
var
|
|
2087
|
-
var
|
|
2088
|
-
var
|
|
2167
|
+
var import_vector17 = require("@pixerate/editor/vector");
|
|
2168
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
2169
|
+
var selectClass12 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2089
2170
|
var numberClass9 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
2090
2171
|
function VectorLensPanel({ controller, className }) {
|
|
2091
2172
|
const state = useVectorEditorState(controller);
|
|
2092
2173
|
const path = state.selection.map((id) => controller.getNode(id)).find((n) => n?.type === "path" && n.subpaths.some((sp) => sp.closed) && !n.connector);
|
|
2093
2174
|
if (!path) return null;
|
|
2094
2175
|
const lens = path.lens ?? null;
|
|
2095
|
-
const spec = lens ?
|
|
2176
|
+
const spec = lens ? import_vector17.VECTOR_LENS_SPECS[lens.type] : null;
|
|
2096
2177
|
const ids = [path.id];
|
|
2097
|
-
return /* @__PURE__ */ (0,
|
|
2098
|
-
/* @__PURE__ */ (0,
|
|
2099
|
-
/* @__PURE__ */ (0,
|
|
2100
|
-
/* @__PURE__ */ (0,
|
|
2178
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-lens-panel": "", "aria-label": "Lens", children: [
|
|
2179
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2180
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Lens" }),
|
|
2181
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2101
2182
|
"select",
|
|
2102
2183
|
{
|
|
2103
2184
|
"aria-label": "Lens type",
|
|
2104
|
-
className:
|
|
2185
|
+
className: selectClass12,
|
|
2105
2186
|
value: lens?.type ?? "",
|
|
2106
2187
|
onChange: (e) => e.target.value ? controller.setLens({ type: e.target.value }, { ids }) : controller.setLens(null, { ids }),
|
|
2107
2188
|
children: [
|
|
2108
|
-
/* @__PURE__ */ (0,
|
|
2109
|
-
|
|
2189
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("option", { value: "", children: "None" }),
|
|
2190
|
+
import_vector17.VECTOR_LENS_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("option", { value: t, children: import_vector17.VECTOR_LENS_LABELS[t] }, t))
|
|
2110
2191
|
]
|
|
2111
2192
|
}
|
|
2112
2193
|
)
|
|
2113
2194
|
] }),
|
|
2114
|
-
lens && spec && /* @__PURE__ */ (0,
|
|
2115
|
-
/* @__PURE__ */ (0,
|
|
2116
|
-
/* @__PURE__ */ (0,
|
|
2195
|
+
lens && spec && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
2196
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "w-16" }),
|
|
2197
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2117
2198
|
"input",
|
|
2118
2199
|
{
|
|
2119
2200
|
type: "number",
|
|
@@ -2130,21 +2211,21 @@ function VectorLensPanel({ controller, className }) {
|
|
|
2130
2211
|
}
|
|
2131
2212
|
}
|
|
2132
2213
|
),
|
|
2133
|
-
spec.color !== null && /* @__PURE__ */ (0,
|
|
2214
|
+
spec.color !== null && /* @__PURE__ */ (0, import_jsx_runtime17.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
2215
|
] })
|
|
2135
2216
|
] });
|
|
2136
2217
|
}
|
|
2137
2218
|
|
|
2138
2219
|
// src/vector/VectorGradientEditor.tsx
|
|
2139
|
-
var
|
|
2140
|
-
var
|
|
2141
|
-
var
|
|
2220
|
+
var import_vector18 = require("@pixerate/editor/vector");
|
|
2221
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
2222
|
+
var selectClass13 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2142
2223
|
var numberClass10 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
2143
|
-
var
|
|
2224
|
+
var buttonClass15 = "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
2225
|
var percent = (v) => Math.round(v * 1e3) / 10;
|
|
2145
2226
|
function VectorGradientEditor({ controller, className }) {
|
|
2146
2227
|
const state = useVectorEditorState(controller);
|
|
2147
|
-
const ed = (0,
|
|
2228
|
+
const ed = (0, import_vector18.getVectorGradientEditor)(state);
|
|
2148
2229
|
if (!ed) return null;
|
|
2149
2230
|
const g = ed.gradient;
|
|
2150
2231
|
const sel = ed.selected;
|
|
@@ -2152,26 +2233,26 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2152
2233
|
const setType = (value) => {
|
|
2153
2234
|
if (value === "solid") {
|
|
2154
2235
|
const first = ed.stops[0];
|
|
2155
|
-
controller.setStyle({ [ed.target]: (0,
|
|
2236
|
+
controller.setStyle({ [ed.target]: (0, import_vector18.vectorPaintToHex)(first?.color) ?? first?.color ?? "#000000" }, void 0, { label: "Solid Colour" });
|
|
2156
2237
|
} else controller.setGradient({ type: value });
|
|
2157
2238
|
};
|
|
2158
|
-
return /* @__PURE__ */ (0,
|
|
2159
|
-
/* @__PURE__ */ (0,
|
|
2160
|
-
/* @__PURE__ */ (0,
|
|
2161
|
-
["fill", "stroke"].map((t) => /* @__PURE__ */ (0,
|
|
2162
|
-
ed.mixed && /* @__PURE__ */ (0,
|
|
2239
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: `space-y-1.5 ${className ?? ""}`, "data-vector-gradient-editor": ed.target, "aria-label": "Gradient", children: [
|
|
2240
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
2241
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Gradient" }),
|
|
2242
|
+
["fill", "stroke"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: buttonClass15, "aria-pressed": ed.target === t, onClick: () => controller.setGradientTarget(t), children: t === "fill" ? "Fill" : "Stroke" }, t)),
|
|
2243
|
+
ed.mixed && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
2163
2244
|
] }),
|
|
2164
|
-
/* @__PURE__ */ (0,
|
|
2165
|
-
/* @__PURE__ */ (0,
|
|
2166
|
-
/* @__PURE__ */ (0,
|
|
2167
|
-
/* @__PURE__ */ (0,
|
|
2168
|
-
|
|
2245
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
2246
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Type" }),
|
|
2247
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("select", { "aria-label": "Gradient type", className: selectClass13, value: ed.type ?? "solid", onChange: (e) => setType(e.target.value), children: [
|
|
2248
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: "solid", children: "Solid" }),
|
|
2249
|
+
import_vector18.VECTOR_GRADIENT_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: t, children: import_vector18.VECTOR_GRADIENT_TYPE_LABELS[t] }, t))
|
|
2169
2250
|
] }),
|
|
2170
|
-
/* @__PURE__ */ (0,
|
|
2251
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: buttonClass15, "aria-label": "Reverse gradient", title: "Reverse gradient", disabled: !g, onClick: () => controller.reverseGradient(), children: "\u21C4" })
|
|
2171
2252
|
] }),
|
|
2172
|
-
g && /* @__PURE__ */ (0,
|
|
2173
|
-
/* @__PURE__ */ (0,
|
|
2174
|
-
/* @__PURE__ */ (0,
|
|
2253
|
+
g && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
2254
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "relative h-8", "data-vector-gradient-ramp": "", children: [
|
|
2255
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2175
2256
|
"div",
|
|
2176
2257
|
{
|
|
2177
2258
|
role: "button",
|
|
@@ -2185,7 +2266,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2185
2266
|
}
|
|
2186
2267
|
}
|
|
2187
2268
|
),
|
|
2188
|
-
ed.stops.map((s) => /* @__PURE__ */ (0,
|
|
2269
|
+
ed.stops.map((s) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2189
2270
|
"button",
|
|
2190
2271
|
{
|
|
2191
2272
|
type: "button",
|
|
@@ -2199,21 +2280,21 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2199
2280
|
s.index
|
|
2200
2281
|
))
|
|
2201
2282
|
] }),
|
|
2202
|
-
sel && /* @__PURE__ */ (0,
|
|
2203
|
-
/* @__PURE__ */ (0,
|
|
2283
|
+
sel && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", "data-vector-gradient-selected-stop": sel.index, children: [
|
|
2284
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2204
2285
|
"input",
|
|
2205
2286
|
{
|
|
2206
2287
|
type: "color",
|
|
2207
2288
|
"aria-label": "Stop colour",
|
|
2208
2289
|
className: "h-7 w-9 cursor-pointer rounded border border-border bg-background",
|
|
2209
|
-
value: (0,
|
|
2290
|
+
value: (0, import_vector18.vectorPaintToHex)(sel.color) ?? "#000000",
|
|
2210
2291
|
onChange: (e) => controller.setGradientStop(sel.index, { color: e.target.value }, { merge: `gradient-stop-color-${sel.index}` }),
|
|
2211
2292
|
onBlur: end
|
|
2212
2293
|
}
|
|
2213
2294
|
),
|
|
2214
|
-
/* @__PURE__ */ (0,
|
|
2295
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
2215
2296
|
"Opacity",
|
|
2216
|
-
/* @__PURE__ */ (0,
|
|
2297
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2217
2298
|
"input",
|
|
2218
2299
|
{
|
|
2219
2300
|
type: "number",
|
|
@@ -2230,9 +2311,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2230
2311
|
}
|
|
2231
2312
|
)
|
|
2232
2313
|
] }),
|
|
2233
|
-
/* @__PURE__ */ (0,
|
|
2314
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
2234
2315
|
"At",
|
|
2235
|
-
/* @__PURE__ */ (0,
|
|
2316
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2236
2317
|
"input",
|
|
2237
2318
|
{
|
|
2238
2319
|
type: "number",
|
|
@@ -2249,9 +2330,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2249
2330
|
}
|
|
2250
2331
|
)
|
|
2251
2332
|
] }),
|
|
2252
|
-
!sel.last && /* @__PURE__ */ (0,
|
|
2333
|
+
!sel.last && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
2253
2334
|
"Midpoint",
|
|
2254
|
-
/* @__PURE__ */ (0,
|
|
2335
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2255
2336
|
"input",
|
|
2256
2337
|
{
|
|
2257
2338
|
type: "number",
|
|
@@ -2268,15 +2349,15 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2268
2349
|
}
|
|
2269
2350
|
)
|
|
2270
2351
|
] }),
|
|
2271
|
-
/* @__PURE__ */ (0,
|
|
2352
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { type: "button", className: buttonClass15, "aria-label": "Delete stop", title: "Delete stop", disabled: ed.stops.length <= 2, onClick: () => controller.removeGradientStop(sel.index), children: "\u2715" })
|
|
2272
2353
|
] }),
|
|
2273
|
-
/* @__PURE__ */ (0,
|
|
2274
|
-
/* @__PURE__ */ (0,
|
|
2275
|
-
/* @__PURE__ */ (0,
|
|
2354
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2355
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16", children: "Colours" }),
|
|
2356
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("select", { "aria-label": "Gradient interpolation", className: selectClass13, value: ed.interpolation, onChange: (e) => controller.setGradient({ interpolation: e.target.value }), children: import_vector18.VECTOR_GRADIENT_INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: i, children: import_vector18.VECTOR_GRADIENT_INTERPOLATION_LABELS[i] }, i)) })
|
|
2276
2357
|
] }),
|
|
2277
|
-
/* @__PURE__ */ (0,
|
|
2278
|
-
/* @__PURE__ */ (0,
|
|
2279
|
-
/* @__PURE__ */ (0,
|
|
2358
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2359
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16", children: "Smooth" }),
|
|
2360
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2280
2361
|
"input",
|
|
2281
2362
|
{
|
|
2282
2363
|
type: "range",
|
|
@@ -2292,26 +2373,26 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2292
2373
|
}
|
|
2293
2374
|
)
|
|
2294
2375
|
] }),
|
|
2295
|
-
/* @__PURE__ */ (0,
|
|
2296
|
-
/* @__PURE__ */ (0,
|
|
2297
|
-
/* @__PURE__ */ (0,
|
|
2376
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2377
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16", children: "Spread" }),
|
|
2378
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("select", { "aria-label": "Gradient spread", className: selectClass13, value: ed.spread, onChange: (e) => controller.setGradient({ spread: e.target.value }), children: import_vector18.VECTOR_GRADIENT_SPREADS.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: sp, children: import_vector18.VECTOR_GRADIENT_SPREAD_LABELS[sp] }, sp)) })
|
|
2298
2379
|
] }),
|
|
2299
|
-
ed.target === "stroke" && /* @__PURE__ */ (0,
|
|
2300
|
-
/* @__PURE__ */ (0,
|
|
2301
|
-
/* @__PURE__ */ (0,
|
|
2380
|
+
ed.target === "stroke" && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
2381
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "w-16", children: "On stroke" }),
|
|
2382
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("select", { "aria-label": "Gradient on stroke", className: selectClass13, value: ed.strokeMode, onChange: (e) => controller.setGradient({ strokeMode: e.target.value }), children: import_vector18.VECTOR_STROKE_GRADIENT_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("option", { value: m, children: import_vector18.VECTOR_STROKE_GRADIENT_MODE_LABELS[m] }, m)) })
|
|
2302
2383
|
] })
|
|
2303
2384
|
] })
|
|
2304
2385
|
] });
|
|
2305
2386
|
}
|
|
2306
2387
|
|
|
2307
2388
|
// src/vector/VectorToolbar.tsx
|
|
2308
|
-
var
|
|
2389
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2309
2390
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
2310
2391
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
2311
|
-
var
|
|
2392
|
+
var buttonClass16 = "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
2393
|
function VectorToolbar({
|
|
2313
2394
|
controller,
|
|
2314
|
-
tools =
|
|
2395
|
+
tools = import_vector19.VECTOR_TOOLS,
|
|
2315
2396
|
showHistory = true,
|
|
2316
2397
|
showArrange = true,
|
|
2317
2398
|
showSnap = true,
|
|
@@ -2325,36 +2406,36 @@ function VectorToolbar({
|
|
|
2325
2406
|
const points = state.tool === "direct" ? state.selectedAnchors.length : 0;
|
|
2326
2407
|
const editing = state.editing;
|
|
2327
2408
|
const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === "group");
|
|
2328
|
-
const maskSelected = state.selection.some((id) => (0,
|
|
2329
|
-
const [live, setLive] =
|
|
2409
|
+
const maskSelected = state.selection.some((id) => (0, import_vector19.isVectorMaskGroup)(controller.getNode(id)));
|
|
2410
|
+
const [live, setLive] = import_react11.default.useState(false);
|
|
2330
2411
|
const booleanDisabled = live ? count < 1 : count < 2;
|
|
2331
|
-
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0,
|
|
2332
|
-
return /* @__PURE__ */ (0,
|
|
2333
|
-
/* @__PURE__ */ (0,
|
|
2412
|
+
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", className: buttonClass16, title, "aria-label": title, disabled, onClick: () => void run(), children: label }, label);
|
|
2413
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { role: "toolbar", "aria-label": "Vector tools", className: `flex flex-wrap items-center gap-1 ${className ?? ""}`, children: [
|
|
2414
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Tools", children: tools.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2334
2415
|
"button",
|
|
2335
2416
|
{
|
|
2336
2417
|
type: "button",
|
|
2337
2418
|
"data-vector-tool": tool,
|
|
2338
|
-
className:
|
|
2419
|
+
className: buttonClass16,
|
|
2339
2420
|
"aria-pressed": state.tool === tool,
|
|
2340
|
-
title: `${(0,
|
|
2341
|
-
"aria-label": (0,
|
|
2421
|
+
title: `${(0, import_vector19.vectorToolLabel)(tool)} (${import_vector19.VECTOR_TOOL_SHORTCUTS[tool]})`,
|
|
2422
|
+
"aria-label": (0, import_vector19.vectorToolLabel)(tool),
|
|
2342
2423
|
onClick: () => controller.setTool(tool),
|
|
2343
|
-
children:
|
|
2424
|
+
children: import_vector19.VECTOR_TOOL_GLYPHS[tool]
|
|
2344
2425
|
},
|
|
2345
2426
|
tool
|
|
2346
2427
|
)) }),
|
|
2347
|
-
showHistory && /* @__PURE__ */ (0,
|
|
2428
|
+
showHistory && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "History", children: [
|
|
2348
2429
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
2349
2430
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
2350
2431
|
] }),
|
|
2351
|
-
showSnap && /* @__PURE__ */ (0,
|
|
2352
|
-
/* @__PURE__ */ (0,
|
|
2432
|
+
showSnap && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Snapping", children: [
|
|
2433
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2353
2434
|
"button",
|
|
2354
2435
|
{
|
|
2355
2436
|
type: "button",
|
|
2356
2437
|
"data-vector-snap": "",
|
|
2357
|
-
className:
|
|
2438
|
+
className: buttonClass16,
|
|
2358
2439
|
"aria-pressed": state.snap.objects,
|
|
2359
2440
|
title: `${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`,
|
|
2360
2441
|
"aria-label": VECTOR_SNAP_TITLE,
|
|
@@ -2362,18 +2443,18 @@ function VectorToolbar({
|
|
|
2362
2443
|
children: "Snap"
|
|
2363
2444
|
}
|
|
2364
2445
|
),
|
|
2365
|
-
/* @__PURE__ */ (0,
|
|
2446
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2366
2447
|
"select",
|
|
2367
2448
|
{
|
|
2368
2449
|
"data-vector-polar": "",
|
|
2369
2450
|
"aria-label": "Polar tracking increment",
|
|
2370
2451
|
title: "Polar tracking: the angles drawn points snap to from where they leave",
|
|
2371
2452
|
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,
|
|
2453
|
+
value: String((0, import_vector19.vectorPolarIncrementOf)(state.snap.angles) ?? ""),
|
|
2454
|
+
onChange: (e) => controller.setSnap({ angles: (0, import_vector19.vectorPolarAngles)(Number(e.target.value)) }),
|
|
2374
2455
|
children: [
|
|
2375
|
-
(0,
|
|
2376
|
-
[90, 45, 30, 15].map((n) => /* @__PURE__ */ (0,
|
|
2456
|
+
(0, import_vector19.vectorPolarIncrementOf)(state.snap.angles) === null && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("option", { value: "", children: "Custom" }),
|
|
2457
|
+
[90, 45, 30, 15].map((n) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("option", { value: n, children: [
|
|
2377
2458
|
n,
|
|
2378
2459
|
"\xB0"
|
|
2379
2460
|
] }, n))
|
|
@@ -2381,13 +2462,13 @@ function VectorToolbar({
|
|
|
2381
2462
|
}
|
|
2382
2463
|
)
|
|
2383
2464
|
] }),
|
|
2384
|
-
showPathEdit && /* @__PURE__ */ (0,
|
|
2385
|
-
|
|
2465
|
+
showPathEdit && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Path editing", children: [
|
|
2466
|
+
import_vector19.VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2386
2467
|
"button",
|
|
2387
2468
|
{
|
|
2388
2469
|
type: "button",
|
|
2389
2470
|
"data-vector-path-action": a.id,
|
|
2390
|
-
className:
|
|
2471
|
+
className: buttonClass16,
|
|
2391
2472
|
title: a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title,
|
|
2392
2473
|
"aria-label": a.title,
|
|
2393
2474
|
disabled: !a.enabled(count, points),
|
|
@@ -2396,12 +2477,12 @@ function VectorToolbar({
|
|
|
2396
2477
|
},
|
|
2397
2478
|
a.id
|
|
2398
2479
|
)),
|
|
2399
|
-
|
|
2480
|
+
import_vector19.VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2400
2481
|
"button",
|
|
2401
2482
|
{
|
|
2402
2483
|
type: "button",
|
|
2403
2484
|
"data-vector-edit": t.key,
|
|
2404
|
-
className:
|
|
2485
|
+
className: buttonClass16,
|
|
2405
2486
|
"aria-pressed": editing[t.key],
|
|
2406
2487
|
title: t.title,
|
|
2407
2488
|
"aria-label": t.title,
|
|
@@ -2410,9 +2491,9 @@ function VectorToolbar({
|
|
|
2410
2491
|
},
|
|
2411
2492
|
t.key
|
|
2412
2493
|
)),
|
|
2413
|
-
state.tool === "pencil" && /* @__PURE__ */ (0,
|
|
2494
|
+
state.tool === "pencil" && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
2414
2495
|
"Smoothing",
|
|
2415
|
-
/* @__PURE__ */ (0,
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2416
2497
|
"input",
|
|
2417
2498
|
{
|
|
2418
2499
|
type: "range",
|
|
@@ -2426,9 +2507,9 @@ function VectorToolbar({
|
|
|
2426
2507
|
}
|
|
2427
2508
|
)
|
|
2428
2509
|
] }),
|
|
2429
|
-
state.tool === "eraser" && /* @__PURE__ */ (0,
|
|
2510
|
+
state.tool === "eraser" && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
2430
2511
|
"Size",
|
|
2431
|
-
/* @__PURE__ */ (0,
|
|
2512
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2432
2513
|
"input",
|
|
2433
2514
|
{
|
|
2434
2515
|
type: "number",
|
|
@@ -2444,26 +2525,26 @@ function VectorToolbar({
|
|
|
2444
2525
|
}
|
|
2445
2526
|
)
|
|
2446
2527
|
] }),
|
|
2447
|
-
state.tool === "paintBucket" && /* @__PURE__ */ (0,
|
|
2528
|
+
state.tool === "paintBucket" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2448
2529
|
"button",
|
|
2449
2530
|
{
|
|
2450
2531
|
type: "button",
|
|
2451
2532
|
"data-vector-fill-gap": "",
|
|
2452
|
-
className:
|
|
2533
|
+
className: buttonClass16,
|
|
2453
2534
|
"aria-pressed": editing.fillGap > 0,
|
|
2454
2535
|
title: "Close small gaps between path ends when filling",
|
|
2455
2536
|
"aria-label": "Close gaps",
|
|
2456
|
-
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 :
|
|
2537
|
+
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : import_vector19.VECTOR_FILL_GAP }),
|
|
2457
2538
|
children: "Gaps"
|
|
2458
2539
|
}
|
|
2459
2540
|
)
|
|
2460
2541
|
] }),
|
|
2461
|
-
showDistort && /* @__PURE__ */ (0,
|
|
2542
|
+
showDistort && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Distort", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2462
2543
|
"button",
|
|
2463
2544
|
{
|
|
2464
2545
|
type: "button",
|
|
2465
2546
|
"data-vector-free-distort": "",
|
|
2466
|
-
className:
|
|
2547
|
+
className: buttonClass16,
|
|
2467
2548
|
"aria-pressed": state.freeDistort,
|
|
2468
2549
|
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
2550
|
"aria-label": "Free Distort",
|
|
@@ -2471,15 +2552,15 @@ function VectorToolbar({
|
|
|
2471
2552
|
children: "Distort"
|
|
2472
2553
|
}
|
|
2473
2554
|
) }),
|
|
2474
|
-
showBlend && /* @__PURE__ */ (0,
|
|
2475
|
-
showArrange && /* @__PURE__ */ (0,
|
|
2476
|
-
/* @__PURE__ */ (0,
|
|
2477
|
-
/* @__PURE__ */ (0,
|
|
2555
|
+
showBlend && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorBlendControls, { controller }),
|
|
2556
|
+
showArrange && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
2557
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Combine", children: [
|
|
2558
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2478
2559
|
"button",
|
|
2479
2560
|
{
|
|
2480
2561
|
type: "button",
|
|
2481
2562
|
"data-vector-live-boolean": "",
|
|
2482
|
-
className:
|
|
2563
|
+
className: buttonClass16,
|
|
2483
2564
|
"aria-pressed": live,
|
|
2484
2565
|
title: "Live booleans: keep the shapes editable",
|
|
2485
2566
|
"aria-label": "Live booleans",
|
|
@@ -2496,12 +2577,12 @@ function VectorToolbar({
|
|
|
2496
2577
|
act("\u25D0", `Make Clipping Mask (${modKeyLabel()}+7)`, () => controller.makeMask("clip"), count < 2),
|
|
2497
2578
|
act("\u25D1", `Release Mask (${modKeyLabel()}+Alt+7)`, () => controller.releaseMask(), !maskSelected)
|
|
2498
2579
|
] }),
|
|
2499
|
-
/* @__PURE__ */ (0,
|
|
2580
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Pathfinder", children: import_vector19.VECTOR_PATHFINDER_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2500
2581
|
"button",
|
|
2501
2582
|
{
|
|
2502
2583
|
type: "button",
|
|
2503
2584
|
"data-vector-pathfinder": a.id,
|
|
2504
|
-
className:
|
|
2585
|
+
className: buttonClass16,
|
|
2505
2586
|
title: a.title,
|
|
2506
2587
|
"aria-label": a.title,
|
|
2507
2588
|
disabled: count < a.min,
|
|
@@ -2510,7 +2591,7 @@ function VectorToolbar({
|
|
|
2510
2591
|
},
|
|
2511
2592
|
a.id
|
|
2512
2593
|
)) }),
|
|
2513
|
-
/* @__PURE__ */ (0,
|
|
2594
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
2514
2595
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
2515
2596
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
2516
2597
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -2525,22 +2606,22 @@ function VectorToolbar({
|
|
|
2525
2606
|
}
|
|
2526
2607
|
function VectorBlendControls({ controller }) {
|
|
2527
2608
|
const state = useVectorEditorState(controller);
|
|
2528
|
-
const blend = (0,
|
|
2609
|
+
const blend = (0, import_vector19.getVectorBlendControls)(state);
|
|
2529
2610
|
const o = blend.options;
|
|
2530
2611
|
const selected = blend.ids.length > 0;
|
|
2531
|
-
return /* @__PURE__ */ (0,
|
|
2532
|
-
/* @__PURE__ */ (0,
|
|
2533
|
-
/* @__PURE__ */ (0,
|
|
2612
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Blend", "data-vector-blend-controls": "", children: [
|
|
2613
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", "data-vector-blend-action": "make", className: buttonClass16, title: "Make Blend", "aria-label": "Make Blend", disabled: !blend.canBlend, onClick: () => controller.blend(), children: "\u29D3" }),
|
|
2614
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2534
2615
|
"select",
|
|
2535
2616
|
{
|
|
2536
2617
|
"aria-label": "Blend spacing",
|
|
2537
2618
|
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
2538
2619
|
value: o.spacing,
|
|
2539
|
-
onChange: (e) => (0,
|
|
2540
|
-
children:
|
|
2620
|
+
onChange: (e) => (0, import_vector19.applyVectorBlendOptions)(controller, { spacing: e.target.value }),
|
|
2621
|
+
children: import_vector19.VECTOR_BLEND_SPACINGS.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("option", { value: sp, children: import_vector19.VECTOR_BLEND_SPACING_LABELS[sp] }, sp))
|
|
2541
2622
|
}
|
|
2542
2623
|
),
|
|
2543
|
-
o.spacing !== "smoothColor" && /* @__PURE__ */ (0,
|
|
2624
|
+
o.spacing !== "smoothColor" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2544
2625
|
"input",
|
|
2545
2626
|
{
|
|
2546
2627
|
type: "number",
|
|
@@ -2552,29 +2633,29 @@ function VectorBlendControls({ controller }) {
|
|
|
2552
2633
|
onChange: (e) => {
|
|
2553
2634
|
const n = parseFloat(e.target.value);
|
|
2554
2635
|
if (!Number.isFinite(n) || n <= 0) return;
|
|
2555
|
-
(0,
|
|
2636
|
+
(0, import_vector19.applyVectorBlendOptions)(controller, o.spacing === "steps" ? { steps: n } : { distance: n });
|
|
2556
2637
|
}
|
|
2557
2638
|
}
|
|
2558
2639
|
),
|
|
2559
|
-
/* @__PURE__ */ (0,
|
|
2640
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2560
2641
|
"button",
|
|
2561
2642
|
{
|
|
2562
2643
|
type: "button",
|
|
2563
2644
|
"data-vector-blend-action": "orient",
|
|
2564
|
-
className:
|
|
2645
|
+
className: buttonClass16,
|
|
2565
2646
|
"aria-pressed": o.orientToSpine,
|
|
2566
2647
|
title: "Orient steps to the spine",
|
|
2567
2648
|
"aria-label": "Orient to spine",
|
|
2568
|
-
onClick: () => (0,
|
|
2649
|
+
onClick: () => (0, import_vector19.applyVectorBlendOptions)(controller, { orientToSpine: !o.orientToSpine }),
|
|
2569
2650
|
children: "\u293F"
|
|
2570
2651
|
}
|
|
2571
2652
|
),
|
|
2572
|
-
/* @__PURE__ */ (0,
|
|
2653
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2573
2654
|
"button",
|
|
2574
2655
|
{
|
|
2575
2656
|
type: "button",
|
|
2576
2657
|
"data-vector-blend-action": "spine",
|
|
2577
|
-
className:
|
|
2658
|
+
className: buttonClass16,
|
|
2578
2659
|
title: "Replace Spine (select a blend and a path)",
|
|
2579
2660
|
"aria-label": "Replace Spine",
|
|
2580
2661
|
disabled: !blend.canReplaceSpine,
|
|
@@ -2582,15 +2663,15 @@ function VectorBlendControls({ controller }) {
|
|
|
2582
2663
|
children: "\u2307"
|
|
2583
2664
|
}
|
|
2584
2665
|
),
|
|
2585
|
-
/* @__PURE__ */ (0,
|
|
2586
|
-
/* @__PURE__ */ (0,
|
|
2666
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", "data-vector-blend-action": "expand", className: buttonClass16, title: "Expand Blend", "aria-label": "Expand Blend", disabled: !selected, onClick: () => controller.expandBlend(), children: "\u29C9" }),
|
|
2667
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("button", { type: "button", "data-vector-blend-action": "release", className: buttonClass16, title: "Release Blend", "aria-label": "Release Blend", disabled: !selected, onClick: () => controller.releaseBlend(), children: "\u29C4" })
|
|
2587
2668
|
] });
|
|
2588
2669
|
}
|
|
2589
|
-
var
|
|
2670
|
+
var selectClass14 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2590
2671
|
var numberClass11 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
2591
2672
|
function VectorStylePanel({ controller, className }) {
|
|
2592
2673
|
const state = useVectorEditorState(controller);
|
|
2593
|
-
const style = (0,
|
|
2674
|
+
const style = (0, import_vector19.getVectorSelectionStyle)(state);
|
|
2594
2675
|
const d = state.defaults;
|
|
2595
2676
|
const source = style ?? {
|
|
2596
2677
|
fill: d.fill ?? null,
|
|
@@ -2603,7 +2684,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2603
2684
|
arrowAlign: d.arrowAlign ?? "extend",
|
|
2604
2685
|
startArrowScale: d.startArrowScale ?? 1,
|
|
2605
2686
|
endArrowScale: d.endArrowScale ?? 1,
|
|
2606
|
-
widthProfile: (0,
|
|
2687
|
+
widthProfile: (0, import_vector19.widthProfilePresetId)(d.strokeWidthProfile),
|
|
2607
2688
|
cornerRadius: d.cornerRadius,
|
|
2608
2689
|
cornerKind: d.cornerKind ?? "round",
|
|
2609
2690
|
cornerSmoothing: 0,
|
|
@@ -2617,19 +2698,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2617
2698
|
};
|
|
2618
2699
|
const setProfile = (id) => {
|
|
2619
2700
|
if (style) controller.setWidthProfile(id);
|
|
2620
|
-
else controller.setDefaults({ strokeWidthProfile: (0,
|
|
2701
|
+
else controller.setDefaults({ strokeWidthProfile: (0, import_vector19.widthProfilePreset)(id)?.length ? (0, import_vector19.widthProfilePreset)(id) : null });
|
|
2621
2702
|
};
|
|
2622
|
-
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0,
|
|
2703
|
+
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }) : null;
|
|
2623
2704
|
const arrowRow = (end, label) => {
|
|
2624
2705
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
2625
2706
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
2626
|
-
return /* @__PURE__ */ (0,
|
|
2627
|
-
/* @__PURE__ */ (0,
|
|
2628
|
-
/* @__PURE__ */ (0,
|
|
2629
|
-
/* @__PURE__ */ (0,
|
|
2630
|
-
|
|
2707
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
2708
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "w-16 text-xs text-foreground", children: label }),
|
|
2709
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("select", { "aria-label": `${label} arrowhead`, className: selectClass14, value: source[key] ?? "", onChange: (e) => apply({ [key]: e.target.value || null }), children: [
|
|
2710
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("option", { value: "", children: "None" }),
|
|
2711
|
+
import_vector19.VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("option", { value: h, children: import_vector19.VECTOR_ARROWHEAD_LABELS[h] }, h))
|
|
2631
2712
|
] }),
|
|
2632
|
-
/* @__PURE__ */ (0,
|
|
2713
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2633
2714
|
"input",
|
|
2634
2715
|
{
|
|
2635
2716
|
type: "number",
|
|
@@ -2653,14 +2734,14 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2653
2734
|
};
|
|
2654
2735
|
const paintRow = (key, label) => {
|
|
2655
2736
|
const paint = source[key];
|
|
2656
|
-
const hex = (0,
|
|
2737
|
+
const hex = (0, import_vector19.vectorPaintToHex)(paint);
|
|
2657
2738
|
const on = paint !== null && paint !== "none";
|
|
2658
|
-
return /* @__PURE__ */ (0,
|
|
2659
|
-
/* @__PURE__ */ (0,
|
|
2660
|
-
/* @__PURE__ */ (0,
|
|
2739
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
2740
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { className: "flex w-16 items-center gap-1.5 text-xs text-foreground", children: [
|
|
2741
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("input", { type: "checkbox", checked: on, "aria-label": `${label} on`, onChange: (e) => apply({ [key]: e.target.checked ? hex ?? "#000000" : null }) }),
|
|
2661
2742
|
label
|
|
2662
2743
|
] }),
|
|
2663
|
-
/* @__PURE__ */ (0,
|
|
2744
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2664
2745
|
"input",
|
|
2665
2746
|
{
|
|
2666
2747
|
type: "color",
|
|
@@ -2671,18 +2752,18 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2671
2752
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
2672
2753
|
}
|
|
2673
2754
|
),
|
|
2674
|
-
on && !hex && /* @__PURE__ */ (0,
|
|
2675
|
-
style?.mixed[key] && /* @__PURE__ */ (0,
|
|
2755
|
+
on && !hex && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "truncate text-[11px] text-muted-foreground", children: typeof paint === "string" ? paint : "Gradient" }),
|
|
2756
|
+
style?.mixed[key] && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
2676
2757
|
] });
|
|
2677
2758
|
};
|
|
2678
|
-
return /* @__PURE__ */ (0,
|
|
2679
|
-
/* @__PURE__ */ (0,
|
|
2759
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "aria-label": style ? "Selection style" : "New shape style", children: [
|
|
2760
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: style ? "Selection" : "New shapes" }),
|
|
2680
2761
|
paintRow("fill", "Fill"),
|
|
2681
2762
|
paintRow("stroke", "Stroke"),
|
|
2682
|
-
style && /* @__PURE__ */ (0,
|
|
2683
|
-
/* @__PURE__ */ (0,
|
|
2684
|
-
/* @__PURE__ */ (0,
|
|
2685
|
-
/* @__PURE__ */ (0,
|
|
2763
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorGradientEditor, { controller }),
|
|
2764
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
2765
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "w-16", children: "Width" }),
|
|
2766
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2686
2767
|
"input",
|
|
2687
2768
|
{
|
|
2688
2769
|
type: "number",
|
|
@@ -2698,33 +2779,33 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2698
2779
|
}
|
|
2699
2780
|
)
|
|
2700
2781
|
] }),
|
|
2701
|
-
/* @__PURE__ */ (0,
|
|
2702
|
-
/* @__PURE__ */ (0,
|
|
2703
|
-
/* @__PURE__ */ (0,
|
|
2782
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "strokeAlign", children: [
|
|
2783
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "w-16", children: "Align" }),
|
|
2784
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("select", { "aria-label": "Stroke alignment", className: selectClass14, value: source.strokeAlign, onChange: (e) => apply({ strokeAlign: e.target.value }), children: Object.keys(import_vector19.VECTOR_STROKE_ALIGN_LABELS).map((a) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("option", { value: a, children: import_vector19.VECTOR_STROKE_ALIGN_LABELS[a] }, a)) }),
|
|
2704
2785
|
mixed("strokeAlign")
|
|
2705
2786
|
] }),
|
|
2706
|
-
/* @__PURE__ */ (0,
|
|
2707
|
-
/* @__PURE__ */ (0,
|
|
2708
|
-
/* @__PURE__ */ (0,
|
|
2787
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "widthProfile", children: [
|
|
2788
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "w-16", children: "Profile" }),
|
|
2789
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2709
2790
|
"select",
|
|
2710
2791
|
{
|
|
2711
2792
|
"aria-label": "Width profile",
|
|
2712
|
-
className:
|
|
2793
|
+
className: selectClass14,
|
|
2713
2794
|
value: source.widthProfile,
|
|
2714
2795
|
onChange: (e) => {
|
|
2715
2796
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
2716
2797
|
},
|
|
2717
2798
|
children: [
|
|
2718
|
-
|
|
2719
|
-
source.widthProfile === "custom" && /* @__PURE__ */ (0,
|
|
2799
|
+
import_vector19.VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("option", { value: p.id, children: p.label }, p.id)),
|
|
2800
|
+
source.widthProfile === "custom" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("option", { value: "custom", disabled: true, children: "Custom" })
|
|
2720
2801
|
]
|
|
2721
2802
|
}
|
|
2722
2803
|
),
|
|
2723
|
-
/* @__PURE__ */ (0,
|
|
2804
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2724
2805
|
"button",
|
|
2725
2806
|
{
|
|
2726
2807
|
type: "button",
|
|
2727
|
-
className:
|
|
2808
|
+
className: buttonClass16,
|
|
2728
2809
|
title: "Reset to uniform width",
|
|
2729
2810
|
"aria-label": "Reset to uniform width",
|
|
2730
2811
|
disabled: source.widthProfile === "uniform" && !style?.mixed.widthProfile,
|
|
@@ -2734,20 +2815,20 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2734
2815
|
),
|
|
2735
2816
|
mixed("widthProfile")
|
|
2736
2817
|
] }),
|
|
2737
|
-
source.hasOpenPath && /* @__PURE__ */ (0,
|
|
2818
|
+
source.hasOpenPath && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
2738
2819
|
arrowRow("start", "Start"),
|
|
2739
2820
|
arrowRow("end", "End"),
|
|
2740
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0,
|
|
2741
|
-
/* @__PURE__ */ (0,
|
|
2742
|
-
/* @__PURE__ */ (0,
|
|
2743
|
-
/* @__PURE__ */ (0,
|
|
2744
|
-
/* @__PURE__ */ (0,
|
|
2821
|
+
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "arrowAlign", children: [
|
|
2822
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "w-16", children: "Heads" }),
|
|
2823
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("select", { "aria-label": "Arrowhead alignment", className: selectClass14, value: source.arrowAlign, onChange: (e) => apply({ arrowAlign: e.target.value }), children: [
|
|
2824
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("option", { value: "extend", children: "Tip past end" }),
|
|
2825
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("option", { value: "tip", children: "Tip at end" })
|
|
2745
2826
|
] })
|
|
2746
2827
|
] })
|
|
2747
2828
|
] }),
|
|
2748
|
-
source.corners > 0 && /* @__PURE__ */ (0,
|
|
2749
|
-
/* @__PURE__ */ (0,
|
|
2750
|
-
/* @__PURE__ */ (0,
|
|
2829
|
+
source.corners > 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": "corners", children: [
|
|
2830
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Corners" }),
|
|
2831
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2751
2832
|
"input",
|
|
2752
2833
|
{
|
|
2753
2834
|
type: "number",
|
|
@@ -2762,12 +2843,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2762
2843
|
}
|
|
2763
2844
|
}
|
|
2764
2845
|
),
|
|
2765
|
-
/* @__PURE__ */ (0,
|
|
2846
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("select", { "aria-label": "Corner kind", className: selectClass14, value: source.cornerKind, onChange: (e) => setCorners({ kind: e.target.value }), children: import_vector19.VECTOR_CORNER_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("option", { value: k, children: import_vector19.VECTOR_CORNER_KIND_LABELS[k] }, k)) }),
|
|
2766
2847
|
mixed("cornerRadius")
|
|
2767
2848
|
] }),
|
|
2768
|
-
style && source.corners > 0 && source.cornerKind === "round" && source.cornerRadius > 0 && /* @__PURE__ */ (0,
|
|
2769
|
-
/* @__PURE__ */ (0,
|
|
2770
|
-
/* @__PURE__ */ (0,
|
|
2849
|
+
style && source.corners > 0 && source.cornerKind === "round" && source.cornerRadius > 0 && /* @__PURE__ */ (0, import_jsx_runtime19.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: [
|
|
2850
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "w-16", children: "Smoothing" }),
|
|
2851
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2771
2852
|
"input",
|
|
2772
2853
|
{
|
|
2773
2854
|
type: "range",
|
|
@@ -2782,9 +2863,9 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2782
2863
|
}
|
|
2783
2864
|
)
|
|
2784
2865
|
] }),
|
|
2785
|
-
style && /* @__PURE__ */ (0,
|
|
2786
|
-
/* @__PURE__ */ (0,
|
|
2787
|
-
/* @__PURE__ */ (0,
|
|
2866
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
2867
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "w-16", children: "Opacity" }),
|
|
2868
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2788
2869
|
"input",
|
|
2789
2870
|
{
|
|
2790
2871
|
type: "range",
|
|
@@ -2798,34 +2879,36 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2798
2879
|
}
|
|
2799
2880
|
)
|
|
2800
2881
|
] }),
|
|
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,
|
|
2882
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorTextPanel, { controller }),
|
|
2883
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorAppearancePanel, { controller }),
|
|
2884
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorEffectsPanel, { controller }),
|
|
2885
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorEnvelopePanel, { controller }),
|
|
2886
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorMaskPanel, { controller }),
|
|
2887
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorFramePanel, { controller }),
|
|
2888
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorPagesPanel, { controller }),
|
|
2889
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorConnectorPanel, { controller }),
|
|
2890
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorShadingPanel, { controller }),
|
|
2891
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorSymmetryPanel, { controller }),
|
|
2892
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorPerspectivePanel, { controller }),
|
|
2893
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorLensPanel, { controller }),
|
|
2894
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorTracePanel, { controller }),
|
|
2895
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorConstraintsPanel, { controller }),
|
|
2896
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(VectorSymbolsPanel, { controller })
|
|
2814
2897
|
] });
|
|
2815
2898
|
}
|
|
2816
2899
|
|
|
2817
2900
|
// src/effects/useEffects.ts
|
|
2818
|
-
var
|
|
2901
|
+
var import_react12 = require("react");
|
|
2819
2902
|
function useEffects(host, provider) {
|
|
2820
|
-
(0,
|
|
2903
|
+
(0, import_react12.useEffect)(() => {
|
|
2821
2904
|
if (!host || !provider) return;
|
|
2822
2905
|
return host.useEffects(provider);
|
|
2823
2906
|
}, [host, provider]);
|
|
2824
2907
|
}
|
|
2825
2908
|
function useEffectDescription(provider, effect) {
|
|
2826
|
-
const [state, setState] = (0,
|
|
2909
|
+
const [state, setState] = (0, import_react12.useState)({ key: "", description: null, error: null });
|
|
2827
2910
|
const key = provider && effect ? `${provider.id}:${effect}` : "";
|
|
2828
|
-
(0,
|
|
2911
|
+
(0, import_react12.useEffect)(() => {
|
|
2829
2912
|
if (!provider || !effect) return;
|
|
2830
2913
|
let live = true;
|
|
2831
2914
|
Promise.resolve().then(() => provider.describe(effect)).then(
|
|
@@ -2840,13 +2923,13 @@ function useEffectDescription(provider, effect) {
|
|
|
2840
2923
|
}
|
|
2841
2924
|
|
|
2842
2925
|
// src/effects/EffectThumbnail.tsx
|
|
2843
|
-
var
|
|
2926
|
+
var import_react13 = require("react");
|
|
2844
2927
|
var import_effects = require("@pixerate/editor/effects");
|
|
2845
|
-
var
|
|
2928
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2846
2929
|
function EffectThumbnail({ provider, effect, width = 96, height = 54, className = "" }) {
|
|
2847
|
-
const ref = (0,
|
|
2848
|
-
const [failed, setFailed] = (0,
|
|
2849
|
-
(0,
|
|
2930
|
+
const ref = (0, import_react13.useRef)(null);
|
|
2931
|
+
const [failed, setFailed] = (0, import_react13.useState)(effect.kind === "motion");
|
|
2932
|
+
(0, import_react13.useEffect)(() => {
|
|
2850
2933
|
if (effect.kind === "motion") return;
|
|
2851
2934
|
let live = true;
|
|
2852
2935
|
(0, import_effects.renderEffectThumbnail)(provider, effect, { width, height }).then(
|
|
@@ -2861,28 +2944,28 @@ function EffectThumbnail({ provider, effect, width = 96, height = 54, className
|
|
|
2861
2944
|
live = false;
|
|
2862
2945
|
};
|
|
2863
2946
|
}, [provider, effect, width, height]);
|
|
2864
|
-
return /* @__PURE__ */ (0,
|
|
2947
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2865
2948
|
"div",
|
|
2866
2949
|
{
|
|
2867
2950
|
className: `relative overflow-hidden rounded border border-border bg-[repeating-conic-gradient(#8884_0_25%,transparent_0_50%)] bg-[length:12px_12px] ${className}`,
|
|
2868
2951
|
style: { aspectRatio: `${width} / ${height}` },
|
|
2869
2952
|
"data-effect-thumbnail": effect.id,
|
|
2870
|
-
children: failed ? /* @__PURE__ */ (0,
|
|
2953
|
+
children: failed ? /* @__PURE__ */ (0, import_jsx_runtime20.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_runtime20.jsx)("canvas", { ref, width, height, className: "h-full w-full", "aria-hidden": "true" })
|
|
2871
2954
|
}
|
|
2872
2955
|
);
|
|
2873
2956
|
}
|
|
2874
2957
|
|
|
2875
2958
|
// src/effects/EffectsBrowser.tsx
|
|
2876
|
-
var
|
|
2959
|
+
var import_react14 = require("react");
|
|
2877
2960
|
var import_effects2 = require("@pixerate/editor/effects");
|
|
2878
|
-
var
|
|
2961
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2879
2962
|
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,
|
|
2963
|
+
const [all, setAll] = (0, import_react14.useState)([]);
|
|
2964
|
+
const [query, setQuery] = (0, import_react14.useState)("");
|
|
2965
|
+
const [category, setCategory] = (0, import_react14.useState)("");
|
|
2966
|
+
const [use, setUse] = (0, import_react14.useState)("");
|
|
2967
|
+
const [error, setError] = (0, import_react14.useState)(null);
|
|
2968
|
+
(0, import_react14.useEffect)(() => {
|
|
2886
2969
|
if (!provider) return setAll([]);
|
|
2887
2970
|
let live = true;
|
|
2888
2971
|
Promise.resolve().then(() => provider.list()).then(
|
|
@@ -2893,8 +2976,8 @@ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, titl
|
|
|
2893
2976
|
live = false;
|
|
2894
2977
|
};
|
|
2895
2978
|
}, [provider]);
|
|
2896
|
-
const [found, setFound] = (0,
|
|
2897
|
-
(0,
|
|
2979
|
+
const [found, setFound] = (0, import_react14.useState)([]);
|
|
2980
|
+
(0, import_react14.useEffect)(() => {
|
|
2898
2981
|
if (!provider) return setFound([]);
|
|
2899
2982
|
let live = true;
|
|
2900
2983
|
Promise.resolve().then(() => provider.search(query, { ...category ? { category } : {}, ...use ? { use } : {} })).then((list) => live && setFound(list), () => live && setFound([]));
|
|
@@ -2903,14 +2986,14 @@ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, titl
|
|
|
2903
2986
|
};
|
|
2904
2987
|
}, [provider, query, category, use]);
|
|
2905
2988
|
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,
|
|
2989
|
+
const categories = (0, import_react14.useMemo)(() => [...new Set(all.filter(allowed).map((e) => e.category))], [all, uses, kinds]);
|
|
2907
2990
|
const shown = found.filter(allowed);
|
|
2908
2991
|
if (!provider)
|
|
2909
|
-
return /* @__PURE__ */ (0,
|
|
2910
|
-
return /* @__PURE__ */ (0,
|
|
2911
|
-
title && /* @__PURE__ */ (0,
|
|
2912
|
-
/* @__PURE__ */ (0,
|
|
2913
|
-
/* @__PURE__ */ (0,
|
|
2992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.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." });
|
|
2993
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("section", { className: `flex flex-col gap-2 ${className}`, "data-effects-browser": "", "aria-label": "Effects browser", children: [
|
|
2994
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h3", { className: "text-xs font-semibold", children: title }),
|
|
2995
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
2996
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2914
2997
|
"input",
|
|
2915
2998
|
{
|
|
2916
2999
|
type: "search",
|
|
@@ -2921,17 +3004,17 @@ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, titl
|
|
|
2921
3004
|
onChange: (e) => setQuery(e.currentTarget.value)
|
|
2922
3005
|
}
|
|
2923
3006
|
),
|
|
2924
|
-
/* @__PURE__ */ (0,
|
|
2925
|
-
/* @__PURE__ */ (0,
|
|
2926
|
-
categories.map((c) => /* @__PURE__ */ (0,
|
|
3007
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.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: [
|
|
3008
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: "", children: "All categories" }),
|
|
3009
|
+
categories.map((c) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: c, children: c }, c))
|
|
2927
3010
|
] }),
|
|
2928
|
-
uses && uses.length > 1 && /* @__PURE__ */ (0,
|
|
2929
|
-
/* @__PURE__ */ (0,
|
|
2930
|
-
uses.map((u) => /* @__PURE__ */ (0,
|
|
3011
|
+
uses && uses.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime21.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: [
|
|
3012
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: "", children: "Any use" }),
|
|
3013
|
+
uses.map((u) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: u, children: import_effects2.EFFECT_USE_LABELS[u] }, u))
|
|
2931
3014
|
] })
|
|
2932
3015
|
] }),
|
|
2933
|
-
error && /* @__PURE__ */ (0,
|
|
2934
|
-
/* @__PURE__ */ (0,
|
|
3016
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: error }),
|
|
3017
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.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_runtime21.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
2935
3018
|
"button",
|
|
2936
3019
|
{
|
|
2937
3020
|
type: "button",
|
|
@@ -2940,25 +3023,25 @@ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, titl
|
|
|
2940
3023
|
"data-effect-id": e.id,
|
|
2941
3024
|
onClick: () => onPick(e),
|
|
2942
3025
|
children: [
|
|
2943
|
-
thumbnails && /* @__PURE__ */ (0,
|
|
2944
|
-
/* @__PURE__ */ (0,
|
|
2945
|
-
/* @__PURE__ */ (0,
|
|
3026
|
+
thumbnails && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(EffectThumbnail, { provider, effect: e }),
|
|
3027
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "truncate text-[11px] font-medium", children: e.name }),
|
|
3028
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "truncate text-[10px] text-muted-foreground", children: e.uses.map((u) => import_effects2.EFFECT_USE_LABELS[u]).join(" \xB7 ") })
|
|
2946
3029
|
]
|
|
2947
3030
|
}
|
|
2948
3031
|
) }, e.id)) }),
|
|
2949
|
-
!shown.length && !error && /* @__PURE__ */ (0,
|
|
3032
|
+
!shown.length && !error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No effects match." })
|
|
2950
3033
|
] });
|
|
2951
3034
|
}
|
|
2952
3035
|
|
|
2953
3036
|
// src/effects/EffectParameters.tsx
|
|
2954
|
-
var
|
|
3037
|
+
var import_react16 = __toESM(require("react"), 1);
|
|
2955
3038
|
var import_effects3 = require("@pixerate/editor/effects");
|
|
2956
3039
|
var import_parameters2 = require("@pixerate/editor/parameters");
|
|
2957
3040
|
|
|
2958
3041
|
// src/parameters/fields.tsx
|
|
2959
|
-
var
|
|
3042
|
+
var import_react15 = require("react");
|
|
2960
3043
|
var import_parameters = require("@pixerate/editor/parameters");
|
|
2961
|
-
var
|
|
3044
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2962
3045
|
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
3046
|
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
3047
|
var rangeClass = "h-4 w-full min-w-0 flex-1 cursor-pointer accent-primary disabled:cursor-not-allowed disabled:opacity-50";
|
|
@@ -2982,7 +3065,7 @@ function ParameterCommitInput({ value, onCommit, multiline, className, onKeyDown
|
|
|
2982
3065
|
onKeyDown: keyDown,
|
|
2983
3066
|
...rest
|
|
2984
3067
|
};
|
|
2985
|
-
return multiline ? /* @__PURE__ */ (0,
|
|
3068
|
+
return multiline ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("textarea", { ...props, className: `${props.className} h-auto min-h-[3.5rem] py-1` }, value) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("input", { type: "text", ...props }, value);
|
|
2986
3069
|
}
|
|
2987
3070
|
var plainNumber = (field, value) => (0, import_parameters.formatParameterNumber)({ ...field, unit: void 0 }, value);
|
|
2988
3071
|
function ParameterNumberInput({
|
|
@@ -2993,8 +3076,8 @@ function ParameterNumberInput({
|
|
|
2993
3076
|
id,
|
|
2994
3077
|
"aria-label": ariaLabel
|
|
2995
3078
|
}) {
|
|
2996
|
-
return /* @__PURE__ */ (0,
|
|
2997
|
-
/* @__PURE__ */ (0,
|
|
3079
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "relative min-w-0 flex-1", children: [
|
|
3080
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2998
3081
|
ParameterCommitInput,
|
|
2999
3082
|
{
|
|
3000
3083
|
id,
|
|
@@ -3016,21 +3099,21 @@ function ParameterNumberInput({
|
|
|
3016
3099
|
}
|
|
3017
3100
|
}
|
|
3018
3101
|
),
|
|
3019
|
-
field.unit && /* @__PURE__ */ (0,
|
|
3102
|
+
field.unit && /* @__PURE__ */ (0, import_jsx_runtime22.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
3103
|
] });
|
|
3021
3104
|
}
|
|
3022
3105
|
function ParameterSlider(props) {
|
|
3023
3106
|
const { field, value, onChange, onGestureStart, onGestureEnd, disabled } = props;
|
|
3024
|
-
const dragging = (0,
|
|
3107
|
+
const dragging = (0, import_react15.useRef)(false);
|
|
3025
3108
|
const end = () => {
|
|
3026
3109
|
if (!dragging.current) return;
|
|
3027
3110
|
dragging.current = false;
|
|
3028
3111
|
onGestureEnd?.();
|
|
3029
3112
|
};
|
|
3030
|
-
if (!(0, import_parameters.isSliderField)(field)) return /* @__PURE__ */ (0,
|
|
3113
|
+
if (!(0, import_parameters.isSliderField)(field)) return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterNumberInput, { ...props });
|
|
3031
3114
|
const step = (0, import_parameters.parameterStep)(field);
|
|
3032
|
-
return /* @__PURE__ */ (0,
|
|
3033
|
-
/* @__PURE__ */ (0,
|
|
3115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3116
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3034
3117
|
"input",
|
|
3035
3118
|
{
|
|
3036
3119
|
type: "range",
|
|
@@ -3053,11 +3136,11 @@ function ParameterSlider(props) {
|
|
|
3053
3136
|
onChange: (e) => onChange((0, import_parameters.clampParameterNumber)(field, Number(e.target.value)))
|
|
3054
3137
|
}
|
|
3055
3138
|
),
|
|
3056
|
-
/* @__PURE__ */ (0,
|
|
3139
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "w-20 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterNumberInput, { ...props, id: props.id, "aria-label": `${(0, import_parameters.parameterLabel)(field)} value` }) })
|
|
3057
3140
|
] });
|
|
3058
3141
|
}
|
|
3059
3142
|
function ParameterToggle({ field, value, onChange, disabled, id }) {
|
|
3060
|
-
return /* @__PURE__ */ (0,
|
|
3143
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3061
3144
|
"button",
|
|
3062
3145
|
{
|
|
3063
3146
|
type: "button",
|
|
@@ -3068,7 +3151,7 @@ function ParameterToggle({ field, value, onChange, disabled, id }) {
|
|
|
3068
3151
|
disabled: disabled || field.readOnly,
|
|
3069
3152
|
onClick: () => onChange(!value),
|
|
3070
3153
|
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,
|
|
3154
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3072
3155
|
"span",
|
|
3073
3156
|
{
|
|
3074
3157
|
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 +3164,7 @@ function ParameterSelect({ field, value, onChange, disabled, id }) {
|
|
|
3081
3164
|
const options = (0, import_parameters.getChoiceOptions)(field);
|
|
3082
3165
|
const off = disabled || field.readOnly;
|
|
3083
3166
|
if (field.control === "segmented") {
|
|
3084
|
-
return /* @__PURE__ */ (0,
|
|
3167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.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_runtime22.jsx)(
|
|
3085
3168
|
"button",
|
|
3086
3169
|
{
|
|
3087
3170
|
type: "button",
|
|
@@ -3097,7 +3180,7 @@ function ParameterSelect({ field, value, onChange, disabled, id }) {
|
|
|
3097
3180
|
)) });
|
|
3098
3181
|
}
|
|
3099
3182
|
const index = options.findIndex((o) => o.value === value);
|
|
3100
|
-
return /* @__PURE__ */ (0,
|
|
3183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3101
3184
|
"select",
|
|
3102
3185
|
{
|
|
3103
3186
|
id,
|
|
@@ -3109,12 +3192,12 @@ function ParameterSelect({ field, value, onChange, disabled, id }) {
|
|
|
3109
3192
|
if (option) onChange(option.value);
|
|
3110
3193
|
},
|
|
3111
3194
|
className: parameterInputClass,
|
|
3112
|
-
children: options.map((o, i) => /* @__PURE__ */ (0,
|
|
3195
|
+
children: options.map((o, i) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("option", { value: String(i), title: o.description, children: (0, import_parameters.choiceOptionLabel)(o) }, String(o.value)))
|
|
3113
3196
|
}
|
|
3114
3197
|
);
|
|
3115
3198
|
}
|
|
3116
3199
|
function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd, disabled, id }) {
|
|
3117
|
-
const picking = (0,
|
|
3200
|
+
const picking = (0, import_react15.useRef)(false);
|
|
3118
3201
|
const alpha = !!field.alpha;
|
|
3119
3202
|
const hex = (0, import_parameters.normalizeHexColor)(value, true) ?? "#000000ff";
|
|
3120
3203
|
const rgb = hex.slice(0, 7);
|
|
@@ -3130,11 +3213,11 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3130
3213
|
picking.current = false;
|
|
3131
3214
|
onGestureEnd?.();
|
|
3132
3215
|
};
|
|
3133
|
-
return /* @__PURE__ */ (0,
|
|
3134
|
-
/* @__PURE__ */ (0,
|
|
3135
|
-
/* @__PURE__ */ (0,
|
|
3136
|
-
/* @__PURE__ */ (0,
|
|
3137
|
-
/* @__PURE__ */ (0,
|
|
3216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-1.5", children: [
|
|
3217
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3218
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.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: [
|
|
3219
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "absolute inset-0", style: { background: alpha ? hex : rgb } }),
|
|
3220
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3138
3221
|
"input",
|
|
3139
3222
|
{
|
|
3140
3223
|
type: "color",
|
|
@@ -3150,7 +3233,7 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3150
3233
|
}
|
|
3151
3234
|
)
|
|
3152
3235
|
] }),
|
|
3153
|
-
/* @__PURE__ */ (0,
|
|
3236
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3154
3237
|
ParameterCommitInput,
|
|
3155
3238
|
{
|
|
3156
3239
|
id,
|
|
@@ -3166,7 +3249,7 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3166
3249
|
}
|
|
3167
3250
|
)
|
|
3168
3251
|
] }),
|
|
3169
|
-
alpha && /* @__PURE__ */ (0,
|
|
3252
|
+
alpha && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3170
3253
|
"input",
|
|
3171
3254
|
{
|
|
3172
3255
|
type: "range",
|
|
@@ -3184,10 +3267,10 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3184
3267
|
onChange: (e) => onChange(`${rgb}${Number(e.target.value).toString(16).padStart(2, "0")}`)
|
|
3185
3268
|
}
|
|
3186
3269
|
),
|
|
3187
|
-
field.swatches && field.swatches.length > 0 && /* @__PURE__ */ (0,
|
|
3270
|
+
field.swatches && field.swatches.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex flex-wrap gap-1", children: field.swatches.map((s) => {
|
|
3188
3271
|
const swatch = (0, import_parameters.normalizeHexColor)(s, alpha);
|
|
3189
3272
|
if (!swatch) return null;
|
|
3190
|
-
return /* @__PURE__ */ (0,
|
|
3273
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3191
3274
|
"button",
|
|
3192
3275
|
{
|
|
3193
3276
|
type: "button",
|
|
@@ -3206,11 +3289,11 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3206
3289
|
}
|
|
3207
3290
|
function ParameterVector({ field, value, onChange, disabled, id }) {
|
|
3208
3291
|
const size = (0, import_parameters.vectorSize)(field);
|
|
3209
|
-
return /* @__PURE__ */ (0,
|
|
3292
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "grid gap-1.5", style: { gridTemplateColumns: `repeat(${size}, minmax(0, 1fr))` }, children: Array.from({ length: size }, (_, i) => {
|
|
3210
3293
|
const component = (0, import_parameters.vectorComponentField)(field, i);
|
|
3211
|
-
return /* @__PURE__ */ (0,
|
|
3212
|
-
/* @__PURE__ */ (0,
|
|
3213
|
-
/* @__PURE__ */ (0,
|
|
3294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex min-w-0 items-center gap-1", children: [
|
|
3295
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "w-3 shrink-0 text-[10px] uppercase text-muted-foreground", children: component.label }),
|
|
3296
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3214
3297
|
ParameterNumberInput,
|
|
3215
3298
|
{
|
|
3216
3299
|
field: component,
|
|
@@ -3227,11 +3310,11 @@ function ParameterVector({ field, value, onChange, disabled, id }) {
|
|
|
3227
3310
|
function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
3228
3311
|
const off = disabled || field.readOnly;
|
|
3229
3312
|
const name = (0, import_parameters.parameterLabel)(field);
|
|
3230
|
-
return /* @__PURE__ */ (0,
|
|
3231
|
-
/* @__PURE__ */ (0,
|
|
3232
|
-
/* @__PURE__ */ (0,
|
|
3233
|
-
/* @__PURE__ */ (0,
|
|
3234
|
-
/* @__PURE__ */ (0,
|
|
3313
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-1.5", children: [
|
|
3314
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3315
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.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_runtime22.jsx)("img", { src: value, alt: name, className: "h-full w-full object-cover" }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-[10px] text-muted-foreground", children: "None" }) }),
|
|
3316
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
|
|
3317
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3235
3318
|
ParameterCommitInput,
|
|
3236
3319
|
{
|
|
3237
3320
|
id,
|
|
@@ -3242,10 +3325,10 @@ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
|
3242
3325
|
onCommit: (text) => onChange(text.trim())
|
|
3243
3326
|
}
|
|
3244
3327
|
),
|
|
3245
|
-
/* @__PURE__ */ (0,
|
|
3246
|
-
resolveFile && /* @__PURE__ */ (0,
|
|
3328
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex gap-1", children: [
|
|
3329
|
+
resolveFile && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: `${parameterButtonClass} cursor-pointer ${off ? "pointer-events-none opacity-50" : ""}`, children: [
|
|
3247
3330
|
"Choose file\u2026",
|
|
3248
|
-
/* @__PURE__ */ (0,
|
|
3331
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3249
3332
|
"input",
|
|
3250
3333
|
{
|
|
3251
3334
|
type: "file",
|
|
@@ -3261,11 +3344,11 @@ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
|
3261
3344
|
}
|
|
3262
3345
|
)
|
|
3263
3346
|
] }),
|
|
3264
|
-
value && /* @__PURE__ */ (0,
|
|
3347
|
+
value && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: parameterButtonClass, disabled: off, onClick: () => onChange(""), "aria-label": `Clear ${name}`, children: "Clear" })
|
|
3265
3348
|
] })
|
|
3266
3349
|
] })
|
|
3267
3350
|
] }),
|
|
3268
|
-
field.options && field.options.length > 0 && /* @__PURE__ */ (0,
|
|
3351
|
+
field.options && field.options.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex flex-wrap gap-1", children: field.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3269
3352
|
"button",
|
|
3270
3353
|
{
|
|
3271
3354
|
type: "button",
|
|
@@ -3275,14 +3358,14 @@ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
|
3275
3358
|
disabled: off,
|
|
3276
3359
|
onClick: () => onChange(o.url),
|
|
3277
3360
|
className: "h-9 w-12 overflow-hidden rounded border border-input aria-pressed:ring-2 aria-pressed:ring-primary",
|
|
3278
|
-
children: /* @__PURE__ */ (0,
|
|
3361
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("img", { src: o.url, alt: "", className: "h-full w-full object-cover" })
|
|
3279
3362
|
},
|
|
3280
3363
|
o.url
|
|
3281
3364
|
)) })
|
|
3282
3365
|
] });
|
|
3283
3366
|
}
|
|
3284
3367
|
function ParameterText({ field, value, onChange, disabled, id }) {
|
|
3285
|
-
return /* @__PURE__ */ (0,
|
|
3368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3286
3369
|
ParameterCommitInput,
|
|
3287
3370
|
{
|
|
3288
3371
|
id,
|
|
@@ -3301,31 +3384,31 @@ function ParameterFieldControl({ field, value, onChange, resolveFile, ...rest })
|
|
|
3301
3384
|
switch (field.type) {
|
|
3302
3385
|
case "number":
|
|
3303
3386
|
case "int":
|
|
3304
|
-
return /* @__PURE__ */ (0,
|
|
3387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterSlider, { field, value, onChange: set, ...rest });
|
|
3305
3388
|
case "boolean":
|
|
3306
|
-
return /* @__PURE__ */ (0,
|
|
3389
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterToggle, { field, value, onChange: set, ...rest });
|
|
3307
3390
|
case "choice":
|
|
3308
|
-
return /* @__PURE__ */ (0,
|
|
3391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterSelect, { field, value, onChange: set, ...rest });
|
|
3309
3392
|
case "color":
|
|
3310
|
-
return /* @__PURE__ */ (0,
|
|
3393
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterColor, { field, value, onChange: set, ...rest });
|
|
3311
3394
|
case "vector":
|
|
3312
|
-
return /* @__PURE__ */ (0,
|
|
3395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterVector, { field, value, onChange: set, ...rest });
|
|
3313
3396
|
case "image":
|
|
3314
|
-
return /* @__PURE__ */ (0,
|
|
3397
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterImage, { field, value, onChange: set, resolveFile, ...rest });
|
|
3315
3398
|
case "text":
|
|
3316
|
-
return /* @__PURE__ */ (0,
|
|
3399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterText, { field, value, onChange: set, ...rest });
|
|
3317
3400
|
}
|
|
3318
3401
|
}
|
|
3319
3402
|
|
|
3320
3403
|
// src/effects/EffectParameters.tsx
|
|
3321
|
-
var
|
|
3404
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
3322
3405
|
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,
|
|
3406
|
+
const fields = (0, import_react16.useMemo)(() => (0, import_effects3.effectParameterFields)(description), [description]);
|
|
3407
|
+
const idBase = (0, import_react16.useId)();
|
|
3408
|
+
const gesture = import_react16.default.useRef(null);
|
|
3409
|
+
const count = import_react16.default.useRef(0);
|
|
3410
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `space-y-2 ${className}`, "data-effect-parameters": description.id, children: [
|
|
3411
|
+
onPreset && description.presets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
3329
3412
|
"select",
|
|
3330
3413
|
{
|
|
3331
3414
|
className: "w-full rounded border border-border bg-transparent px-1 py-0.5 text-xs",
|
|
@@ -3337,8 +3420,8 @@ function EffectParameters({ description, values, onChange, onReset, keyframed, o
|
|
|
3337
3420
|
if (preset) onPreset({ ...description.defaults, ...preset.values });
|
|
3338
3421
|
},
|
|
3339
3422
|
children: [
|
|
3340
|
-
/* @__PURE__ */ (0,
|
|
3341
|
-
description.presets.map((p) => /* @__PURE__ */ (0,
|
|
3423
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "", children: "Presets\u2026" }),
|
|
3424
|
+
description.presets.map((p) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: p.name, children: p.name }, p.name))
|
|
3342
3425
|
]
|
|
3343
3426
|
}
|
|
3344
3427
|
),
|
|
@@ -3348,13 +3431,13 @@ function EffectParameters({ description, values, onChange, onReset, keyframed, o
|
|
|
3348
3431
|
const keyed = keyframed?.has(field.id) ?? false;
|
|
3349
3432
|
const value = (0, import_effects3.effectFieldValue)(field, values[field.id]);
|
|
3350
3433
|
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,
|
|
3434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "space-y-1", "data-effect-control": field.id, children: [
|
|
3435
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
3436
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("label", { htmlFor: inputId, className: "min-w-0 flex-1 truncate text-xs font-medium", title: field.description, children: label }),
|
|
3437
|
+
keyed && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[10px] text-muted-foreground", children: "keyframed" }),
|
|
3438
|
+
onReset && changed && !disabled && /* @__PURE__ */ (0, import_jsx_runtime23.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
3439
|
] }),
|
|
3357
|
-
/* @__PURE__ */ (0,
|
|
3440
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3358
3441
|
ParameterFieldControl,
|
|
3359
3442
|
{
|
|
3360
3443
|
field,
|
|
@@ -3368,25 +3451,25 @@ function EffectParameters({ description, values, onChange, onReset, keyframed, o
|
|
|
3368
3451
|
)
|
|
3369
3452
|
] }, field.id);
|
|
3370
3453
|
}),
|
|
3371
|
-
!fields.length && /* @__PURE__ */ (0,
|
|
3454
|
+
!fields.length && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No controls." })
|
|
3372
3455
|
] });
|
|
3373
3456
|
}
|
|
3374
3457
|
|
|
3375
3458
|
// src/vector/VectorProviderEffectsPanel.tsx
|
|
3376
|
-
var
|
|
3377
|
-
var
|
|
3459
|
+
var import_react17 = require("react");
|
|
3460
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
3378
3461
|
var btn = "rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40";
|
|
3379
3462
|
function Controls({ controller, group }) {
|
|
3380
3463
|
const provider = controller.effectsProvider;
|
|
3381
3464
|
const tag = group.providerEffect;
|
|
3382
3465
|
const { description, error } = useEffectDescription(provider, tag.effect);
|
|
3383
|
-
const [message, setMessage] = (0,
|
|
3466
|
+
const [message, setMessage] = (0, import_react17.useState)(null);
|
|
3384
3467
|
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,
|
|
3468
|
+
if (!provider) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No effects provider: the shapes are kept as they are." });
|
|
3469
|
+
if (error) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-[11px] text-amber-500", children: error });
|
|
3470
|
+
if (!description) return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Loading\u2026" });
|
|
3471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
3472
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
3390
3473
|
EffectParameters,
|
|
3391
3474
|
{
|
|
3392
3475
|
description,
|
|
@@ -3396,18 +3479,18 @@ function Controls({ controller, group }) {
|
|
|
3396
3479
|
onPreset: (v) => run(controller.updateVectorEffect(group.id, v))
|
|
3397
3480
|
}
|
|
3398
3481
|
),
|
|
3399
|
-
message && /* @__PURE__ */ (0,
|
|
3482
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
|
|
3400
3483
|
] });
|
|
3401
3484
|
}
|
|
3402
3485
|
function VectorProviderEffectsPanel({ controller, className = "" }) {
|
|
3403
3486
|
const state = useVectorEditorState(controller);
|
|
3404
|
-
const provider = (0,
|
|
3487
|
+
const provider = (0, import_react17.useSyncExternalStore)(
|
|
3405
3488
|
(cb) => controller.effects.subscribe(cb),
|
|
3406
3489
|
() => controller.effects.provider,
|
|
3407
3490
|
() => controller.effects.provider
|
|
3408
3491
|
);
|
|
3409
|
-
const [browse, setBrowse] = (0,
|
|
3410
|
-
const [message, setMessage] = (0,
|
|
3492
|
+
const [browse, setBrowse] = (0, import_react17.useState)(false);
|
|
3493
|
+
const [message, setMessage] = (0, import_react17.useState)(null);
|
|
3411
3494
|
void state;
|
|
3412
3495
|
const groups = controller.vectorEffectGroups();
|
|
3413
3496
|
const selected = groups.filter((g) => state.selection.includes(g.id));
|
|
@@ -3415,41 +3498,41 @@ function VectorProviderEffectsPanel({ controller, className = "" }) {
|
|
|
3415
3498
|
setMessage(null);
|
|
3416
3499
|
Promise.resolve().then(work).catch((e) => setMessage(e instanceof Error ? e.message : String(e)));
|
|
3417
3500
|
};
|
|
3418
|
-
return /* @__PURE__ */ (0,
|
|
3419
|
-
/* @__PURE__ */ (0,
|
|
3420
|
-
/* @__PURE__ */ (0,
|
|
3421
|
-
/* @__PURE__ */ (0,
|
|
3501
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("section", { className: `flex flex-col gap-2 text-xs ${className}`, "aria-label": "Vector effects", "data-vector-provider-effects": "", children: [
|
|
3502
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
3503
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "flex-1 font-semibold", children: "Effects" }),
|
|
3504
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn, disabled: !provider, "aria-pressed": browse, onClick: () => setBrowse(!browse), children: "Add effect\u2026" })
|
|
3422
3505
|
] }),
|
|
3423
|
-
!provider && /* @__PURE__ */ (0,
|
|
3424
|
-
browse && /* @__PURE__ */ (0,
|
|
3425
|
-
selected.map((g) => /* @__PURE__ */ (0,
|
|
3426
|
-
/* @__PURE__ */ (0,
|
|
3427
|
-
/* @__PURE__ */ (0,
|
|
3428
|
-
/* @__PURE__ */ (0,
|
|
3506
|
+
!provider && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No effects provider is registered. Effect groups are kept as shapes." }),
|
|
3507
|
+
browse && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(EffectsBrowser, { provider, kinds: ["vector"], title: "Vector effects", onPick: (e) => (setBrowse(false), run(() => controller.addVectorEffect(e.id))) }),
|
|
3508
|
+
selected.map((g) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "space-y-1 rounded border border-border p-1", "data-vector-effect-group": g.id, children: [
|
|
3509
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
3510
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "min-w-0 flex-1 truncate font-medium", children: g.providerEffect.name ?? g.providerEffect.effect }),
|
|
3511
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn, title: "Keep the shapes as a plain group", onClick: () => run(() => controller.detachVectorEffect(g.id)), children: "Detach" })
|
|
3429
3512
|
] }),
|
|
3430
|
-
/* @__PURE__ */ (0,
|
|
3513
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Controls, { controller, group: g })
|
|
3431
3514
|
] }, g.id)),
|
|
3432
|
-
groups.length > 0 && !selected.length && /* @__PURE__ */ (0,
|
|
3515
|
+
groups.length > 0 && !selected.length && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("p", { className: "text-[11px] text-muted-foreground", children: [
|
|
3433
3516
|
"Select an effect group (",
|
|
3434
3517
|
groups.length,
|
|
3435
3518
|
" in the drawing) to change it."
|
|
3436
3519
|
] }),
|
|
3437
|
-
message && /* @__PURE__ */ (0,
|
|
3520
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
|
|
3438
3521
|
] });
|
|
3439
3522
|
}
|
|
3440
3523
|
|
|
3441
3524
|
// src/vector/VectorEditor.tsx
|
|
3442
|
-
var
|
|
3525
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
3443
3526
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, effects, className }) {
|
|
3444
3527
|
useEffects(controller, effects);
|
|
3445
3528
|
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,
|
|
3529
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: `flex flex-col gap-2 ${className ?? ""}`, "data-vector-editor": "", children: [
|
|
3530
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VectorToolbar, { controller, tools }),
|
|
3531
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex min-h-0 flex-col gap-2 md:flex-row", children: [
|
|
3532
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.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_runtime25.jsx)(VectorCanvas, { controller, ...canvasProps }) }),
|
|
3533
|
+
showStylePanel && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex w-full shrink-0 flex-col gap-2 md:w-56", children: [
|
|
3534
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VectorStylePanel, { controller, className: "rounded-md border border-border p-3" }),
|
|
3535
|
+
effectsShown && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VectorProviderEffectsPanel, { controller, className: "rounded-md border border-border p-3" })
|
|
3453
3536
|
] })
|
|
3454
3537
|
] })
|
|
3455
3538
|
] });
|
|
@@ -3471,6 +3554,8 @@ function VectorEditor({ controller, tools, showStylePanel = true, height = 520,
|
|
|
3471
3554
|
VectorLensPanel,
|
|
3472
3555
|
VectorMaskPanel,
|
|
3473
3556
|
VectorMaskedNodes,
|
|
3557
|
+
VectorPagesPanel,
|
|
3558
|
+
VectorPerspectivePanel,
|
|
3474
3559
|
VectorProviderEffectsPanel,
|
|
3475
3560
|
VectorSceneNodes,
|
|
3476
3561
|
VectorShadingPanel,
|