@pixerate/editor-react 0.84.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 +413 -381
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +11 -1
- package/dist/vector/index.d.ts +11 -1
- package/dist/vector/index.js +302 -271
- package/dist/vector/index.js.map +1 -1
- package/package.json +3 -3
package/dist/vector/index.cjs
CHANGED
|
@@ -45,6 +45,7 @@ __export(vector_exports, {
|
|
|
45
45
|
VectorLensPanel: () => VectorLensPanel,
|
|
46
46
|
VectorMaskPanel: () => VectorMaskPanel,
|
|
47
47
|
VectorMaskedNodes: () => VectorMaskedNodes,
|
|
48
|
+
VectorPagesPanel: () => VectorPagesPanel,
|
|
48
49
|
VectorPerspectivePanel: () => VectorPerspectivePanel,
|
|
49
50
|
VectorProviderEffectsPanel: () => VectorProviderEffectsPanel,
|
|
50
51
|
VectorSceneNodes: () => VectorSceneNodes,
|
|
@@ -837,7 +838,7 @@ function VectorCanvas({
|
|
|
837
838
|
|
|
838
839
|
// src/vector/VectorToolbar.tsx
|
|
839
840
|
var import_react11 = __toESM(require("react"), 1);
|
|
840
|
-
var
|
|
841
|
+
var import_vector19 = require("@pixerate/editor/vector");
|
|
841
842
|
|
|
842
843
|
// src/vector/VectorEffectsPanel.tsx
|
|
843
844
|
var import_vector4 = require("@pixerate/editor/vector");
|
|
@@ -1884,38 +1885,67 @@ function VectorFramePanel({ controller, className }) {
|
|
|
1884
1885
|
] });
|
|
1885
1886
|
}
|
|
1886
1887
|
|
|
1887
|
-
// src/vector/
|
|
1888
|
+
// src/vector/VectorPagesPanel.tsx
|
|
1888
1889
|
var import_vector12 = require("@pixerate/editor/vector");
|
|
1889
1890
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1890
|
-
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";
|
|
1891
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";
|
|
1892
1922
|
var numberClass5 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
1893
1923
|
function VectorConnectorPanel({ controller, className }) {
|
|
1894
1924
|
const state = useVectorEditorState(controller);
|
|
1895
|
-
const panel = (0,
|
|
1925
|
+
const panel = (0, import_vector13.getVectorConnectorPanel)(state);
|
|
1896
1926
|
if (!panel) return null;
|
|
1897
1927
|
const ids = [panel.id];
|
|
1898
|
-
const end = (key, label, e) => /* @__PURE__ */ (0,
|
|
1899
|
-
/* @__PURE__ */ (0,
|
|
1900
|
-
e ? /* @__PURE__ */ (0,
|
|
1901
|
-
/* @__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)(
|
|
1902
1932
|
"select",
|
|
1903
1933
|
{
|
|
1904
1934
|
"aria-label": `${label} side`,
|
|
1905
|
-
className:
|
|
1935
|
+
className: selectClass8,
|
|
1906
1936
|
value: e.side ?? "auto",
|
|
1907
1937
|
onChange: (ev) => controller.setConnector({ [key]: { nodeId: e.nodeId, side: ev.target.value } }, { ids }),
|
|
1908
|
-
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))
|
|
1909
1939
|
}
|
|
1910
1940
|
),
|
|
1911
|
-
/* @__PURE__ */ (0,
|
|
1912
|
-
] }) : /* @__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" })
|
|
1913
1943
|
] });
|
|
1914
|
-
return /* @__PURE__ */ (0,
|
|
1915
|
-
/* @__PURE__ */ (0,
|
|
1916
|
-
/* @__PURE__ */ (0,
|
|
1917
|
-
/* @__PURE__ */ (0,
|
|
1918
|
-
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)(
|
|
1919
1949
|
"input",
|
|
1920
1950
|
{
|
|
1921
1951
|
type: "number",
|
|
@@ -1939,9 +1969,9 @@ function VectorConnectorPanel({ controller, className }) {
|
|
|
1939
1969
|
|
|
1940
1970
|
// src/vector/VectorShadingPanel.tsx
|
|
1941
1971
|
var import_react8 = require("react");
|
|
1942
|
-
var
|
|
1943
|
-
var
|
|
1944
|
-
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";
|
|
1945
1975
|
var numberClass6 = "h-7 w-12 rounded border border-border bg-background px-1.5 text-xs";
|
|
1946
1976
|
function VectorShadingPanel({ controller, className }) {
|
|
1947
1977
|
const state = useVectorEditorState(controller);
|
|
@@ -1951,8 +1981,8 @@ function VectorShadingPanel({ controller, className }) {
|
|
|
1951
1981
|
if (!path) return null;
|
|
1952
1982
|
const fill = path.fill;
|
|
1953
1983
|
const sel = state.shadingPoint?.nodeId === path.id ? state.shadingPoint : null;
|
|
1954
|
-
const mesh = (0,
|
|
1955
|
-
const free = (0,
|
|
1984
|
+
const mesh = (0, import_vector14.isVectorMeshGradient)(fill) ? fill : null;
|
|
1985
|
+
const free = (0, import_vector14.isVectorFreeformGradient)(fill) ? fill : null;
|
|
1956
1986
|
const color = sel ? mesh ? mesh.colors[sel.index] : free?.points[sel.index]?.color : void 0;
|
|
1957
1987
|
const opacity = sel ? mesh ? mesh.opacities?.[sel.index] ?? 1 : free?.points[sel.index]?.opacity ?? 1 : 1;
|
|
1958
1988
|
const spread = sel && free ? free.points[sel.index]?.spread ?? 0 : 0;
|
|
@@ -1961,29 +1991,29 @@ function VectorShadingPanel({ controller, className }) {
|
|
|
1961
1991
|
if (mesh) controller.setMeshPoint(path.id, sel.index, patch, merge ? { merge } : {});
|
|
1962
1992
|
else controller.setFreeformPoint(path.id, sel.index, patch, merge ? { merge } : {});
|
|
1963
1993
|
};
|
|
1964
|
-
return /* @__PURE__ */ (0,
|
|
1965
|
-
/* @__PURE__ */ (0,
|
|
1966
|
-
/* @__PURE__ */ (0,
|
|
1967
|
-
/* @__PURE__ */ (0,
|
|
1968
|
-
/* @__PURE__ */ (0,
|
|
1969
|
-
/* @__PURE__ */ (0,
|
|
1970
|
-
/* @__PURE__ */ (0,
|
|
1971
|
-
/* @__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" })
|
|
1972
2002
|
] }),
|
|
1973
|
-
(mesh || free) && !sel && /* @__PURE__ */ (0,
|
|
2003
|
+
(mesh || free) && !sel && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { className: "text-[11px] text-muted-foreground", children: [
|
|
1974
2004
|
"Gradient tool (G): drag points; ",
|
|
1975
2005
|
free ? "click inside to add one, Alt-click to remove." : "pick one to colour it."
|
|
1976
2006
|
] }),
|
|
1977
|
-
sel && /* @__PURE__ */ (0,
|
|
1978
|
-
/* @__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: [
|
|
1979
2009
|
"Point ",
|
|
1980
2010
|
sel.index
|
|
1981
2011
|
] }),
|
|
1982
|
-
/* @__PURE__ */ (0,
|
|
1983
|
-
/* @__PURE__ */ (0,
|
|
1984
|
-
free && /* @__PURE__ */ (0,
|
|
1985
|
-
/* @__PURE__ */ (0,
|
|
1986
|
-
/* @__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" })
|
|
1987
2017
|
] })
|
|
1988
2018
|
] })
|
|
1989
2019
|
] });
|
|
@@ -1991,9 +2021,9 @@ function VectorShadingPanel({ controller, className }) {
|
|
|
1991
2021
|
|
|
1992
2022
|
// src/vector/VectorTracePanel.tsx
|
|
1993
2023
|
var import_react9 = require("react");
|
|
1994
|
-
var
|
|
1995
|
-
var
|
|
1996
|
-
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";
|
|
1997
2027
|
var numberClass7 = "h-7 w-12 rounded border border-border bg-background px-1.5 text-xs";
|
|
1998
2028
|
async function filePixels(file, max = 1e6) {
|
|
1999
2029
|
const bitmap = await createImageBitmap(file);
|
|
@@ -2023,16 +2053,16 @@ function VectorTracePanel({ controller, className }) {
|
|
|
2023
2053
|
setMessage("That file could not be read as an image.");
|
|
2024
2054
|
}
|
|
2025
2055
|
};
|
|
2026
|
-
return /* @__PURE__ */ (0,
|
|
2027
|
-
/* @__PURE__ */ (0,
|
|
2028
|
-
/* @__PURE__ */ (0,
|
|
2029
|
-
/* @__PURE__ */ (0,
|
|
2030
|
-
/* @__PURE__ */ (0,
|
|
2031
|
-
/* @__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" })
|
|
2032
2062
|
] }),
|
|
2033
|
-
mode === "color" && /* @__PURE__ */ (0,
|
|
2034
|
-
/* @__PURE__ */ (0,
|
|
2035
|
-
/* @__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)(
|
|
2036
2066
|
"input",
|
|
2037
2067
|
{
|
|
2038
2068
|
ref: input,
|
|
@@ -2047,124 +2077,124 @@ function VectorTracePanel({ controller, className }) {
|
|
|
2047
2077
|
}
|
|
2048
2078
|
)
|
|
2049
2079
|
] }),
|
|
2050
|
-
message && /* @__PURE__ */ (0,
|
|
2080
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-[11px] text-red-600", children: message })
|
|
2051
2081
|
] });
|
|
2052
2082
|
}
|
|
2053
2083
|
|
|
2054
2084
|
// src/vector/VectorSymmetryPanel.tsx
|
|
2055
|
-
var
|
|
2056
|
-
var
|
|
2057
|
-
var
|
|
2058
|
-
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";
|
|
2059
2089
|
var numberClass8 = "h-7 w-12 rounded border border-border bg-background px-1.5 text-xs";
|
|
2060
2090
|
function VectorSymmetryPanel({ controller, className }) {
|
|
2061
2091
|
const state = useVectorEditorState(controller);
|
|
2062
|
-
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;
|
|
2063
2093
|
const s = group?.symmetry;
|
|
2064
2094
|
const ids = group ? [group.id] : void 0;
|
|
2065
2095
|
const drawing = !!group && state.symmetryTarget === group.id;
|
|
2066
|
-
return /* @__PURE__ */ (0,
|
|
2067
|
-
/* @__PURE__ */ (0,
|
|
2068
|
-
/* @__PURE__ */ (0,
|
|
2069
|
-
!group && /* @__PURE__ */ (0,
|
|
2070
|
-
!group && /* @__PURE__ */ (0,
|
|
2071
|
-
group && s && /* @__PURE__ */ (0,
|
|
2072
|
-
/* @__PURE__ */ (0,
|
|
2073
|
-
s.mode === "radial" && /* @__PURE__ */ (0,
|
|
2074
|
-
/* @__PURE__ */ (0,
|
|
2075
|
-
/* @__PURE__ */ (0,
|
|
2076
|
-
/* @__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 }) }),
|
|
2077
2107
|
"Mirror"
|
|
2078
2108
|
] })
|
|
2079
2109
|
] })
|
|
2080
2110
|
] })
|
|
2081
2111
|
] }),
|
|
2082
|
-
group && /* @__PURE__ */ (0,
|
|
2083
|
-
/* @__PURE__ */ (0,
|
|
2084
|
-
/* @__PURE__ */ (0,
|
|
2085
|
-
/* @__PURE__ */ (0,
|
|
2086
|
-
/* @__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" })
|
|
2087
2117
|
] })
|
|
2088
2118
|
] });
|
|
2089
2119
|
}
|
|
2090
2120
|
|
|
2091
2121
|
// src/vector/VectorPerspectivePanel.tsx
|
|
2092
2122
|
var import_react10 = __toESM(require("react"), 1);
|
|
2093
|
-
var
|
|
2094
|
-
var
|
|
2095
|
-
var
|
|
2096
|
-
var
|
|
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";
|
|
2097
2127
|
var PLANE_LABELS = { floor: "Floor", left: "Left wall", right: "Right wall", side: "Side wall", front: "Front" };
|
|
2098
2128
|
function VectorPerspectivePanel({ controller, className }) {
|
|
2099
2129
|
const state = useVectorEditorState(controller);
|
|
2100
2130
|
const grid = state.document.perspective ?? null;
|
|
2101
|
-
const planes = grid ? (0,
|
|
2131
|
+
const planes = grid ? (0, import_vector16.vectorPerspectivePlanes)(grid) : [];
|
|
2102
2132
|
const [attachTo, setAttachTo] = import_react10.default.useState("");
|
|
2103
2133
|
const target = (state.perspectivePlane ?? attachTo) || planes[0];
|
|
2104
|
-
const add = (n) => controller.setPerspective((0,
|
|
2105
|
-
return /* @__PURE__ */ (0,
|
|
2106
|
-
/* @__PURE__ */ (0,
|
|
2107
|
-
/* @__PURE__ */ (0,
|
|
2108
|
-
[1, 2, 3].map((n) => /* @__PURE__ */ (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: [
|
|
2109
2139
|
n,
|
|
2110
2140
|
"-pt"
|
|
2111
2141
|
] }, n))
|
|
2112
2142
|
] }),
|
|
2113
|
-
grid && /* @__PURE__ */ (0,
|
|
2114
|
-
/* @__PURE__ */ (0,
|
|
2115
|
-
/* @__PURE__ */ (0,
|
|
2116
|
-
/* @__PURE__ */ (0,
|
|
2117
|
-
planes.map((p) => /* @__PURE__ */ (0,
|
|
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: [
|
|
2118
2148
|
"Draw on ",
|
|
2119
2149
|
PLANE_LABELS[p].toLowerCase()
|
|
2120
2150
|
] }, p))
|
|
2121
2151
|
] })
|
|
2122
2152
|
] }),
|
|
2123
|
-
grid && /* @__PURE__ */ (0,
|
|
2124
|
-
/* @__PURE__ */ (0,
|
|
2125
|
-
!state.perspectivePlane && /* @__PURE__ */ (0,
|
|
2126
|
-
/* @__PURE__ */ (0,
|
|
2127
|
-
/* @__PURE__ */ (0,
|
|
2128
|
-
/* @__PURE__ */ (0,
|
|
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 }) }),
|
|
2129
2159
|
"Show"
|
|
2130
2160
|
] }),
|
|
2131
|
-
/* @__PURE__ */ (0,
|
|
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" })
|
|
2132
2162
|
] })
|
|
2133
2163
|
] });
|
|
2134
2164
|
}
|
|
2135
2165
|
|
|
2136
2166
|
// src/vector/VectorLensPanel.tsx
|
|
2137
|
-
var
|
|
2138
|
-
var
|
|
2139
|
-
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";
|
|
2140
2170
|
var numberClass9 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
2141
2171
|
function VectorLensPanel({ controller, className }) {
|
|
2142
2172
|
const state = useVectorEditorState(controller);
|
|
2143
2173
|
const path = state.selection.map((id) => controller.getNode(id)).find((n) => n?.type === "path" && n.subpaths.some((sp) => sp.closed) && !n.connector);
|
|
2144
2174
|
if (!path) return null;
|
|
2145
2175
|
const lens = path.lens ?? null;
|
|
2146
|
-
const spec = lens ?
|
|
2176
|
+
const spec = lens ? import_vector17.VECTOR_LENS_SPECS[lens.type] : null;
|
|
2147
2177
|
const ids = [path.id];
|
|
2148
|
-
return /* @__PURE__ */ (0,
|
|
2149
|
-
/* @__PURE__ */ (0,
|
|
2150
|
-
/* @__PURE__ */ (0,
|
|
2151
|
-
/* @__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)(
|
|
2152
2182
|
"select",
|
|
2153
2183
|
{
|
|
2154
2184
|
"aria-label": "Lens type",
|
|
2155
|
-
className:
|
|
2185
|
+
className: selectClass12,
|
|
2156
2186
|
value: lens?.type ?? "",
|
|
2157
2187
|
onChange: (e) => e.target.value ? controller.setLens({ type: e.target.value }, { ids }) : controller.setLens(null, { ids }),
|
|
2158
2188
|
children: [
|
|
2159
|
-
/* @__PURE__ */ (0,
|
|
2160
|
-
|
|
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))
|
|
2161
2191
|
]
|
|
2162
2192
|
}
|
|
2163
2193
|
)
|
|
2164
2194
|
] }),
|
|
2165
|
-
lens && spec && /* @__PURE__ */ (0,
|
|
2166
|
-
/* @__PURE__ */ (0,
|
|
2167
|
-
/* @__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)(
|
|
2168
2198
|
"input",
|
|
2169
2199
|
{
|
|
2170
2200
|
type: "number",
|
|
@@ -2181,21 +2211,21 @@ function VectorLensPanel({ controller, className }) {
|
|
|
2181
2211
|
}
|
|
2182
2212
|
}
|
|
2183
2213
|
),
|
|
2184
|
-
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}` }) })
|
|
2185
2215
|
] })
|
|
2186
2216
|
] });
|
|
2187
2217
|
}
|
|
2188
2218
|
|
|
2189
2219
|
// src/vector/VectorGradientEditor.tsx
|
|
2190
|
-
var
|
|
2191
|
-
var
|
|
2192
|
-
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";
|
|
2193
2223
|
var numberClass10 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
2194
|
-
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";
|
|
2195
2225
|
var percent = (v) => Math.round(v * 1e3) / 10;
|
|
2196
2226
|
function VectorGradientEditor({ controller, className }) {
|
|
2197
2227
|
const state = useVectorEditorState(controller);
|
|
2198
|
-
const ed = (0,
|
|
2228
|
+
const ed = (0, import_vector18.getVectorGradientEditor)(state);
|
|
2199
2229
|
if (!ed) return null;
|
|
2200
2230
|
const g = ed.gradient;
|
|
2201
2231
|
const sel = ed.selected;
|
|
@@ -2203,26 +2233,26 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2203
2233
|
const setType = (value) => {
|
|
2204
2234
|
if (value === "solid") {
|
|
2205
2235
|
const first = ed.stops[0];
|
|
2206
|
-
controller.setStyle({ [ed.target]: (0,
|
|
2236
|
+
controller.setStyle({ [ed.target]: (0, import_vector18.vectorPaintToHex)(first?.color) ?? first?.color ?? "#000000" }, void 0, { label: "Solid Colour" });
|
|
2207
2237
|
} else controller.setGradient({ type: value });
|
|
2208
2238
|
};
|
|
2209
|
-
return /* @__PURE__ */ (0,
|
|
2210
|
-
/* @__PURE__ */ (0,
|
|
2211
|
-
/* @__PURE__ */ (0,
|
|
2212
|
-
["fill", "stroke"].map((t) => /* @__PURE__ */ (0,
|
|
2213
|
-
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" })
|
|
2214
2244
|
] }),
|
|
2215
|
-
/* @__PURE__ */ (0,
|
|
2216
|
-
/* @__PURE__ */ (0,
|
|
2217
|
-
/* @__PURE__ */ (0,
|
|
2218
|
-
/* @__PURE__ */ (0,
|
|
2219
|
-
|
|
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))
|
|
2220
2250
|
] }),
|
|
2221
|
-
/* @__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" })
|
|
2222
2252
|
] }),
|
|
2223
|
-
g && /* @__PURE__ */ (0,
|
|
2224
|
-
/* @__PURE__ */ (0,
|
|
2225
|
-
/* @__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)(
|
|
2226
2256
|
"div",
|
|
2227
2257
|
{
|
|
2228
2258
|
role: "button",
|
|
@@ -2236,7 +2266,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2236
2266
|
}
|
|
2237
2267
|
}
|
|
2238
2268
|
),
|
|
2239
|
-
ed.stops.map((s) => /* @__PURE__ */ (0,
|
|
2269
|
+
ed.stops.map((s) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2240
2270
|
"button",
|
|
2241
2271
|
{
|
|
2242
2272
|
type: "button",
|
|
@@ -2250,21 +2280,21 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2250
2280
|
s.index
|
|
2251
2281
|
))
|
|
2252
2282
|
] }),
|
|
2253
|
-
sel && /* @__PURE__ */ (0,
|
|
2254
|
-
/* @__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)(
|
|
2255
2285
|
"input",
|
|
2256
2286
|
{
|
|
2257
2287
|
type: "color",
|
|
2258
2288
|
"aria-label": "Stop colour",
|
|
2259
2289
|
className: "h-7 w-9 cursor-pointer rounded border border-border bg-background",
|
|
2260
|
-
value: (0,
|
|
2290
|
+
value: (0, import_vector18.vectorPaintToHex)(sel.color) ?? "#000000",
|
|
2261
2291
|
onChange: (e) => controller.setGradientStop(sel.index, { color: e.target.value }, { merge: `gradient-stop-color-${sel.index}` }),
|
|
2262
2292
|
onBlur: end
|
|
2263
2293
|
}
|
|
2264
2294
|
),
|
|
2265
|
-
/* @__PURE__ */ (0,
|
|
2295
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
2266
2296
|
"Opacity",
|
|
2267
|
-
/* @__PURE__ */ (0,
|
|
2297
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2268
2298
|
"input",
|
|
2269
2299
|
{
|
|
2270
2300
|
type: "number",
|
|
@@ -2281,9 +2311,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2281
2311
|
}
|
|
2282
2312
|
)
|
|
2283
2313
|
] }),
|
|
2284
|
-
/* @__PURE__ */ (0,
|
|
2314
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
2285
2315
|
"At",
|
|
2286
|
-
/* @__PURE__ */ (0,
|
|
2316
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2287
2317
|
"input",
|
|
2288
2318
|
{
|
|
2289
2319
|
type: "number",
|
|
@@ -2300,9 +2330,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2300
2330
|
}
|
|
2301
2331
|
)
|
|
2302
2332
|
] }),
|
|
2303
|
-
!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: [
|
|
2304
2334
|
"Midpoint",
|
|
2305
|
-
/* @__PURE__ */ (0,
|
|
2335
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
2306
2336
|
"input",
|
|
2307
2337
|
{
|
|
2308
2338
|
type: "number",
|
|
@@ -2319,15 +2349,15 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2319
2349
|
}
|
|
2320
2350
|
)
|
|
2321
2351
|
] }),
|
|
2322
|
-
/* @__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" })
|
|
2323
2353
|
] }),
|
|
2324
|
-
/* @__PURE__ */ (0,
|
|
2325
|
-
/* @__PURE__ */ (0,
|
|
2326
|
-
/* @__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)) })
|
|
2327
2357
|
] }),
|
|
2328
|
-
/* @__PURE__ */ (0,
|
|
2329
|
-
/* @__PURE__ */ (0,
|
|
2330
|
-
/* @__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)(
|
|
2331
2361
|
"input",
|
|
2332
2362
|
{
|
|
2333
2363
|
type: "range",
|
|
@@ -2343,26 +2373,26 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
2343
2373
|
}
|
|
2344
2374
|
)
|
|
2345
2375
|
] }),
|
|
2346
|
-
/* @__PURE__ */ (0,
|
|
2347
|
-
/* @__PURE__ */ (0,
|
|
2348
|
-
/* @__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)) })
|
|
2349
2379
|
] }),
|
|
2350
|
-
ed.target === "stroke" && /* @__PURE__ */ (0,
|
|
2351
|
-
/* @__PURE__ */ (0,
|
|
2352
|
-
/* @__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)) })
|
|
2353
2383
|
] })
|
|
2354
2384
|
] })
|
|
2355
2385
|
] });
|
|
2356
2386
|
}
|
|
2357
2387
|
|
|
2358
2388
|
// src/vector/VectorToolbar.tsx
|
|
2359
|
-
var
|
|
2389
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2360
2390
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
2361
2391
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
2362
|
-
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";
|
|
2363
2393
|
function VectorToolbar({
|
|
2364
2394
|
controller,
|
|
2365
|
-
tools =
|
|
2395
|
+
tools = import_vector19.VECTOR_TOOLS,
|
|
2366
2396
|
showHistory = true,
|
|
2367
2397
|
showArrange = true,
|
|
2368
2398
|
showSnap = true,
|
|
@@ -2376,36 +2406,36 @@ function VectorToolbar({
|
|
|
2376
2406
|
const points = state.tool === "direct" ? state.selectedAnchors.length : 0;
|
|
2377
2407
|
const editing = state.editing;
|
|
2378
2408
|
const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === "group");
|
|
2379
|
-
const maskSelected = state.selection.some((id) => (0,
|
|
2409
|
+
const maskSelected = state.selection.some((id) => (0, import_vector19.isVectorMaskGroup)(controller.getNode(id)));
|
|
2380
2410
|
const [live, setLive] = import_react11.default.useState(false);
|
|
2381
2411
|
const booleanDisabled = live ? count < 1 : count < 2;
|
|
2382
|
-
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0,
|
|
2383
|
-
return /* @__PURE__ */ (0,
|
|
2384
|
-
/* @__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)(
|
|
2385
2415
|
"button",
|
|
2386
2416
|
{
|
|
2387
2417
|
type: "button",
|
|
2388
2418
|
"data-vector-tool": tool,
|
|
2389
|
-
className:
|
|
2419
|
+
className: buttonClass16,
|
|
2390
2420
|
"aria-pressed": state.tool === tool,
|
|
2391
|
-
title: `${(0,
|
|
2392
|
-
"aria-label": (0,
|
|
2421
|
+
title: `${(0, import_vector19.vectorToolLabel)(tool)} (${import_vector19.VECTOR_TOOL_SHORTCUTS[tool]})`,
|
|
2422
|
+
"aria-label": (0, import_vector19.vectorToolLabel)(tool),
|
|
2393
2423
|
onClick: () => controller.setTool(tool),
|
|
2394
|
-
children:
|
|
2424
|
+
children: import_vector19.VECTOR_TOOL_GLYPHS[tool]
|
|
2395
2425
|
},
|
|
2396
2426
|
tool
|
|
2397
2427
|
)) }),
|
|
2398
|
-
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: [
|
|
2399
2429
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
2400
2430
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
2401
2431
|
] }),
|
|
2402
|
-
showSnap && /* @__PURE__ */ (0,
|
|
2403
|
-
/* @__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)(
|
|
2404
2434
|
"button",
|
|
2405
2435
|
{
|
|
2406
2436
|
type: "button",
|
|
2407
2437
|
"data-vector-snap": "",
|
|
2408
|
-
className:
|
|
2438
|
+
className: buttonClass16,
|
|
2409
2439
|
"aria-pressed": state.snap.objects,
|
|
2410
2440
|
title: `${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`,
|
|
2411
2441
|
"aria-label": VECTOR_SNAP_TITLE,
|
|
@@ -2413,18 +2443,18 @@ function VectorToolbar({
|
|
|
2413
2443
|
children: "Snap"
|
|
2414
2444
|
}
|
|
2415
2445
|
),
|
|
2416
|
-
/* @__PURE__ */ (0,
|
|
2446
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
2417
2447
|
"select",
|
|
2418
2448
|
{
|
|
2419
2449
|
"data-vector-polar": "",
|
|
2420
2450
|
"aria-label": "Polar tracking increment",
|
|
2421
2451
|
title: "Polar tracking: the angles drawn points snap to from where they leave",
|
|
2422
2452
|
className: "h-8 rounded-md border border-border bg-background px-1 text-xs",
|
|
2423
|
-
value: String((0,
|
|
2424
|
-
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)) }),
|
|
2425
2455
|
children: [
|
|
2426
|
-
(0,
|
|
2427
|
-
[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: [
|
|
2428
2458
|
n,
|
|
2429
2459
|
"\xB0"
|
|
2430
2460
|
] }, n))
|
|
@@ -2432,13 +2462,13 @@ function VectorToolbar({
|
|
|
2432
2462
|
}
|
|
2433
2463
|
)
|
|
2434
2464
|
] }),
|
|
2435
|
-
showPathEdit && /* @__PURE__ */ (0,
|
|
2436
|
-
|
|
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)(
|
|
2437
2467
|
"button",
|
|
2438
2468
|
{
|
|
2439
2469
|
type: "button",
|
|
2440
2470
|
"data-vector-path-action": a.id,
|
|
2441
|
-
className:
|
|
2471
|
+
className: buttonClass16,
|
|
2442
2472
|
title: a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title,
|
|
2443
2473
|
"aria-label": a.title,
|
|
2444
2474
|
disabled: !a.enabled(count, points),
|
|
@@ -2447,12 +2477,12 @@ function VectorToolbar({
|
|
|
2447
2477
|
},
|
|
2448
2478
|
a.id
|
|
2449
2479
|
)),
|
|
2450
|
-
|
|
2480
|
+
import_vector19.VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2451
2481
|
"button",
|
|
2452
2482
|
{
|
|
2453
2483
|
type: "button",
|
|
2454
2484
|
"data-vector-edit": t.key,
|
|
2455
|
-
className:
|
|
2485
|
+
className: buttonClass16,
|
|
2456
2486
|
"aria-pressed": editing[t.key],
|
|
2457
2487
|
title: t.title,
|
|
2458
2488
|
"aria-label": t.title,
|
|
@@ -2461,9 +2491,9 @@ function VectorToolbar({
|
|
|
2461
2491
|
},
|
|
2462
2492
|
t.key
|
|
2463
2493
|
)),
|
|
2464
|
-
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: [
|
|
2465
2495
|
"Smoothing",
|
|
2466
|
-
/* @__PURE__ */ (0,
|
|
2496
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2467
2497
|
"input",
|
|
2468
2498
|
{
|
|
2469
2499
|
type: "range",
|
|
@@ -2477,9 +2507,9 @@ function VectorToolbar({
|
|
|
2477
2507
|
}
|
|
2478
2508
|
)
|
|
2479
2509
|
] }),
|
|
2480
|
-
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: [
|
|
2481
2511
|
"Size",
|
|
2482
|
-
/* @__PURE__ */ (0,
|
|
2512
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2483
2513
|
"input",
|
|
2484
2514
|
{
|
|
2485
2515
|
type: "number",
|
|
@@ -2495,26 +2525,26 @@ function VectorToolbar({
|
|
|
2495
2525
|
}
|
|
2496
2526
|
)
|
|
2497
2527
|
] }),
|
|
2498
|
-
state.tool === "paintBucket" && /* @__PURE__ */ (0,
|
|
2528
|
+
state.tool === "paintBucket" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2499
2529
|
"button",
|
|
2500
2530
|
{
|
|
2501
2531
|
type: "button",
|
|
2502
2532
|
"data-vector-fill-gap": "",
|
|
2503
|
-
className:
|
|
2533
|
+
className: buttonClass16,
|
|
2504
2534
|
"aria-pressed": editing.fillGap > 0,
|
|
2505
2535
|
title: "Close small gaps between path ends when filling",
|
|
2506
2536
|
"aria-label": "Close gaps",
|
|
2507
|
-
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 :
|
|
2537
|
+
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : import_vector19.VECTOR_FILL_GAP }),
|
|
2508
2538
|
children: "Gaps"
|
|
2509
2539
|
}
|
|
2510
2540
|
)
|
|
2511
2541
|
] }),
|
|
2512
|
-
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)(
|
|
2513
2543
|
"button",
|
|
2514
2544
|
{
|
|
2515
2545
|
type: "button",
|
|
2516
2546
|
"data-vector-free-distort": "",
|
|
2517
|
-
className:
|
|
2547
|
+
className: buttonClass16,
|
|
2518
2548
|
"aria-pressed": state.freeDistort,
|
|
2519
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)`,
|
|
2520
2550
|
"aria-label": "Free Distort",
|
|
@@ -2522,15 +2552,15 @@ function VectorToolbar({
|
|
|
2522
2552
|
children: "Distort"
|
|
2523
2553
|
}
|
|
2524
2554
|
) }),
|
|
2525
|
-
showBlend && /* @__PURE__ */ (0,
|
|
2526
|
-
showArrange && /* @__PURE__ */ (0,
|
|
2527
|
-
/* @__PURE__ */ (0,
|
|
2528
|
-
/* @__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)(
|
|
2529
2559
|
"button",
|
|
2530
2560
|
{
|
|
2531
2561
|
type: "button",
|
|
2532
2562
|
"data-vector-live-boolean": "",
|
|
2533
|
-
className:
|
|
2563
|
+
className: buttonClass16,
|
|
2534
2564
|
"aria-pressed": live,
|
|
2535
2565
|
title: "Live booleans: keep the shapes editable",
|
|
2536
2566
|
"aria-label": "Live booleans",
|
|
@@ -2547,12 +2577,12 @@ function VectorToolbar({
|
|
|
2547
2577
|
act("\u25D0", `Make Clipping Mask (${modKeyLabel()}+7)`, () => controller.makeMask("clip"), count < 2),
|
|
2548
2578
|
act("\u25D1", `Release Mask (${modKeyLabel()}+Alt+7)`, () => controller.releaseMask(), !maskSelected)
|
|
2549
2579
|
] }),
|
|
2550
|
-
/* @__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)(
|
|
2551
2581
|
"button",
|
|
2552
2582
|
{
|
|
2553
2583
|
type: "button",
|
|
2554
2584
|
"data-vector-pathfinder": a.id,
|
|
2555
|
-
className:
|
|
2585
|
+
className: buttonClass16,
|
|
2556
2586
|
title: a.title,
|
|
2557
2587
|
"aria-label": a.title,
|
|
2558
2588
|
disabled: count < a.min,
|
|
@@ -2561,7 +2591,7 @@ function VectorToolbar({
|
|
|
2561
2591
|
},
|
|
2562
2592
|
a.id
|
|
2563
2593
|
)) }),
|
|
2564
|
-
/* @__PURE__ */ (0,
|
|
2594
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
2565
2595
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
2566
2596
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
2567
2597
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -2576,22 +2606,22 @@ function VectorToolbar({
|
|
|
2576
2606
|
}
|
|
2577
2607
|
function VectorBlendControls({ controller }) {
|
|
2578
2608
|
const state = useVectorEditorState(controller);
|
|
2579
|
-
const blend = (0,
|
|
2609
|
+
const blend = (0, import_vector19.getVectorBlendControls)(state);
|
|
2580
2610
|
const o = blend.options;
|
|
2581
2611
|
const selected = blend.ids.length > 0;
|
|
2582
|
-
return /* @__PURE__ */ (0,
|
|
2583
|
-
/* @__PURE__ */ (0,
|
|
2584
|
-
/* @__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)(
|
|
2585
2615
|
"select",
|
|
2586
2616
|
{
|
|
2587
2617
|
"aria-label": "Blend spacing",
|
|
2588
2618
|
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
2589
2619
|
value: o.spacing,
|
|
2590
|
-
onChange: (e) => (0,
|
|
2591
|
-
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))
|
|
2592
2622
|
}
|
|
2593
2623
|
),
|
|
2594
|
-
o.spacing !== "smoothColor" && /* @__PURE__ */ (0,
|
|
2624
|
+
o.spacing !== "smoothColor" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2595
2625
|
"input",
|
|
2596
2626
|
{
|
|
2597
2627
|
type: "number",
|
|
@@ -2603,29 +2633,29 @@ function VectorBlendControls({ controller }) {
|
|
|
2603
2633
|
onChange: (e) => {
|
|
2604
2634
|
const n = parseFloat(e.target.value);
|
|
2605
2635
|
if (!Number.isFinite(n) || n <= 0) return;
|
|
2606
|
-
(0,
|
|
2636
|
+
(0, import_vector19.applyVectorBlendOptions)(controller, o.spacing === "steps" ? { steps: n } : { distance: n });
|
|
2607
2637
|
}
|
|
2608
2638
|
}
|
|
2609
2639
|
),
|
|
2610
|
-
/* @__PURE__ */ (0,
|
|
2640
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2611
2641
|
"button",
|
|
2612
2642
|
{
|
|
2613
2643
|
type: "button",
|
|
2614
2644
|
"data-vector-blend-action": "orient",
|
|
2615
|
-
className:
|
|
2645
|
+
className: buttonClass16,
|
|
2616
2646
|
"aria-pressed": o.orientToSpine,
|
|
2617
2647
|
title: "Orient steps to the spine",
|
|
2618
2648
|
"aria-label": "Orient to spine",
|
|
2619
|
-
onClick: () => (0,
|
|
2649
|
+
onClick: () => (0, import_vector19.applyVectorBlendOptions)(controller, { orientToSpine: !o.orientToSpine }),
|
|
2620
2650
|
children: "\u293F"
|
|
2621
2651
|
}
|
|
2622
2652
|
),
|
|
2623
|
-
/* @__PURE__ */ (0,
|
|
2653
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2624
2654
|
"button",
|
|
2625
2655
|
{
|
|
2626
2656
|
type: "button",
|
|
2627
2657
|
"data-vector-blend-action": "spine",
|
|
2628
|
-
className:
|
|
2658
|
+
className: buttonClass16,
|
|
2629
2659
|
title: "Replace Spine (select a blend and a path)",
|
|
2630
2660
|
"aria-label": "Replace Spine",
|
|
2631
2661
|
disabled: !blend.canReplaceSpine,
|
|
@@ -2633,15 +2663,15 @@ function VectorBlendControls({ controller }) {
|
|
|
2633
2663
|
children: "\u2307"
|
|
2634
2664
|
}
|
|
2635
2665
|
),
|
|
2636
|
-
/* @__PURE__ */ (0,
|
|
2637
|
-
/* @__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" })
|
|
2638
2668
|
] });
|
|
2639
2669
|
}
|
|
2640
|
-
var
|
|
2670
|
+
var selectClass14 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
2641
2671
|
var numberClass11 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
2642
2672
|
function VectorStylePanel({ controller, className }) {
|
|
2643
2673
|
const state = useVectorEditorState(controller);
|
|
2644
|
-
const style = (0,
|
|
2674
|
+
const style = (0, import_vector19.getVectorSelectionStyle)(state);
|
|
2645
2675
|
const d = state.defaults;
|
|
2646
2676
|
const source = style ?? {
|
|
2647
2677
|
fill: d.fill ?? null,
|
|
@@ -2654,7 +2684,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2654
2684
|
arrowAlign: d.arrowAlign ?? "extend",
|
|
2655
2685
|
startArrowScale: d.startArrowScale ?? 1,
|
|
2656
2686
|
endArrowScale: d.endArrowScale ?? 1,
|
|
2657
|
-
widthProfile: (0,
|
|
2687
|
+
widthProfile: (0, import_vector19.widthProfilePresetId)(d.strokeWidthProfile),
|
|
2658
2688
|
cornerRadius: d.cornerRadius,
|
|
2659
2689
|
cornerKind: d.cornerKind ?? "round",
|
|
2660
2690
|
cornerSmoothing: 0,
|
|
@@ -2668,19 +2698,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2668
2698
|
};
|
|
2669
2699
|
const setProfile = (id) => {
|
|
2670
2700
|
if (style) controller.setWidthProfile(id);
|
|
2671
|
-
else controller.setDefaults({ strokeWidthProfile: (0,
|
|
2701
|
+
else controller.setDefaults({ strokeWidthProfile: (0, import_vector19.widthProfilePreset)(id)?.length ? (0, import_vector19.widthProfilePreset)(id) : null });
|
|
2672
2702
|
};
|
|
2673
|
-
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;
|
|
2674
2704
|
const arrowRow = (end, label) => {
|
|
2675
2705
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
2676
2706
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
2677
|
-
return /* @__PURE__ */ (0,
|
|
2678
|
-
/* @__PURE__ */ (0,
|
|
2679
|
-
/* @__PURE__ */ (0,
|
|
2680
|
-
/* @__PURE__ */ (0,
|
|
2681
|
-
|
|
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))
|
|
2682
2712
|
] }),
|
|
2683
|
-
/* @__PURE__ */ (0,
|
|
2713
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2684
2714
|
"input",
|
|
2685
2715
|
{
|
|
2686
2716
|
type: "number",
|
|
@@ -2704,14 +2734,14 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2704
2734
|
};
|
|
2705
2735
|
const paintRow = (key, label) => {
|
|
2706
2736
|
const paint = source[key];
|
|
2707
|
-
const hex = (0,
|
|
2737
|
+
const hex = (0, import_vector19.vectorPaintToHex)(paint);
|
|
2708
2738
|
const on = paint !== null && paint !== "none";
|
|
2709
|
-
return /* @__PURE__ */ (0,
|
|
2710
|
-
/* @__PURE__ */ (0,
|
|
2711
|
-
/* @__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 }) }),
|
|
2712
2742
|
label
|
|
2713
2743
|
] }),
|
|
2714
|
-
/* @__PURE__ */ (0,
|
|
2744
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2715
2745
|
"input",
|
|
2716
2746
|
{
|
|
2717
2747
|
type: "color",
|
|
@@ -2722,18 +2752,18 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2722
2752
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
2723
2753
|
}
|
|
2724
2754
|
),
|
|
2725
|
-
on && !hex && /* @__PURE__ */ (0,
|
|
2726
|
-
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" })
|
|
2727
2757
|
] });
|
|
2728
2758
|
};
|
|
2729
|
-
return /* @__PURE__ */ (0,
|
|
2730
|
-
/* @__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" }),
|
|
2731
2761
|
paintRow("fill", "Fill"),
|
|
2732
2762
|
paintRow("stroke", "Stroke"),
|
|
2733
|
-
style && /* @__PURE__ */ (0,
|
|
2734
|
-
/* @__PURE__ */ (0,
|
|
2735
|
-
/* @__PURE__ */ (0,
|
|
2736
|
-
/* @__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)(
|
|
2737
2767
|
"input",
|
|
2738
2768
|
{
|
|
2739
2769
|
type: "number",
|
|
@@ -2749,33 +2779,33 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2749
2779
|
}
|
|
2750
2780
|
)
|
|
2751
2781
|
] }),
|
|
2752
|
-
/* @__PURE__ */ (0,
|
|
2753
|
-
/* @__PURE__ */ (0,
|
|
2754
|
-
/* @__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)) }),
|
|
2755
2785
|
mixed("strokeAlign")
|
|
2756
2786
|
] }),
|
|
2757
|
-
/* @__PURE__ */ (0,
|
|
2758
|
-
/* @__PURE__ */ (0,
|
|
2759
|
-
/* @__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)(
|
|
2760
2790
|
"select",
|
|
2761
2791
|
{
|
|
2762
2792
|
"aria-label": "Width profile",
|
|
2763
|
-
className:
|
|
2793
|
+
className: selectClass14,
|
|
2764
2794
|
value: source.widthProfile,
|
|
2765
2795
|
onChange: (e) => {
|
|
2766
2796
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
2767
2797
|
},
|
|
2768
2798
|
children: [
|
|
2769
|
-
|
|
2770
|
-
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" })
|
|
2771
2801
|
]
|
|
2772
2802
|
}
|
|
2773
2803
|
),
|
|
2774
|
-
/* @__PURE__ */ (0,
|
|
2804
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
2775
2805
|
"button",
|
|
2776
2806
|
{
|
|
2777
2807
|
type: "button",
|
|
2778
|
-
className:
|
|
2808
|
+
className: buttonClass16,
|
|
2779
2809
|
title: "Reset to uniform width",
|
|
2780
2810
|
"aria-label": "Reset to uniform width",
|
|
2781
2811
|
disabled: source.widthProfile === "uniform" && !style?.mixed.widthProfile,
|
|
@@ -2785,20 +2815,20 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2785
2815
|
),
|
|
2786
2816
|
mixed("widthProfile")
|
|
2787
2817
|
] }),
|
|
2788
|
-
source.hasOpenPath && /* @__PURE__ */ (0,
|
|
2818
|
+
source.hasOpenPath && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
2789
2819
|
arrowRow("start", "Start"),
|
|
2790
2820
|
arrowRow("end", "End"),
|
|
2791
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0,
|
|
2792
|
-
/* @__PURE__ */ (0,
|
|
2793
|
-
/* @__PURE__ */ (0,
|
|
2794
|
-
/* @__PURE__ */ (0,
|
|
2795
|
-
/* @__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" })
|
|
2796
2826
|
] })
|
|
2797
2827
|
] })
|
|
2798
2828
|
] }),
|
|
2799
|
-
source.corners > 0 && /* @__PURE__ */ (0,
|
|
2800
|
-
/* @__PURE__ */ (0,
|
|
2801
|
-
/* @__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)(
|
|
2802
2832
|
"input",
|
|
2803
2833
|
{
|
|
2804
2834
|
type: "number",
|
|
@@ -2813,12 +2843,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2813
2843
|
}
|
|
2814
2844
|
}
|
|
2815
2845
|
),
|
|
2816
|
-
/* @__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)) }),
|
|
2817
2847
|
mixed("cornerRadius")
|
|
2818
2848
|
] }),
|
|
2819
|
-
style && source.corners > 0 && source.cornerKind === "round" && source.cornerRadius > 0 && /* @__PURE__ */ (0,
|
|
2820
|
-
/* @__PURE__ */ (0,
|
|
2821
|
-
/* @__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)(
|
|
2822
2852
|
"input",
|
|
2823
2853
|
{
|
|
2824
2854
|
type: "range",
|
|
@@ -2833,9 +2863,9 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2833
2863
|
}
|
|
2834
2864
|
)
|
|
2835
2865
|
] }),
|
|
2836
|
-
style && /* @__PURE__ */ (0,
|
|
2837
|
-
/* @__PURE__ */ (0,
|
|
2838
|
-
/* @__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)(
|
|
2839
2869
|
"input",
|
|
2840
2870
|
{
|
|
2841
2871
|
type: "range",
|
|
@@ -2849,20 +2879,21 @@ function VectorStylePanel({ controller, className }) {
|
|
|
2849
2879
|
}
|
|
2850
2880
|
)
|
|
2851
2881
|
] }),
|
|
2852
|
-
/* @__PURE__ */ (0,
|
|
2853
|
-
style && /* @__PURE__ */ (0,
|
|
2854
|
-
style && /* @__PURE__ */ (0,
|
|
2855
|
-
style && /* @__PURE__ */ (0,
|
|
2856
|
-
style && /* @__PURE__ */ (0,
|
|
2857
|
-
/* @__PURE__ */ (0,
|
|
2858
|
-
/* @__PURE__ */ (0,
|
|
2859
|
-
/* @__PURE__ */ (0,
|
|
2860
|
-
/* @__PURE__ */ (0,
|
|
2861
|
-
/* @__PURE__ */ (0,
|
|
2862
|
-
/* @__PURE__ */ (0,
|
|
2863
|
-
/* @__PURE__ */ (0,
|
|
2864
|
-
/* @__PURE__ */ (0,
|
|
2865
|
-
/* @__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 })
|
|
2866
2897
|
] });
|
|
2867
2898
|
}
|
|
2868
2899
|
|
|
@@ -2894,7 +2925,7 @@ function useEffectDescription(provider, effect) {
|
|
|
2894
2925
|
// src/effects/EffectThumbnail.tsx
|
|
2895
2926
|
var import_react13 = require("react");
|
|
2896
2927
|
var import_effects = require("@pixerate/editor/effects");
|
|
2897
|
-
var
|
|
2928
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2898
2929
|
function EffectThumbnail({ provider, effect, width = 96, height = 54, className = "" }) {
|
|
2899
2930
|
const ref = (0, import_react13.useRef)(null);
|
|
2900
2931
|
const [failed, setFailed] = (0, import_react13.useState)(effect.kind === "motion");
|
|
@@ -2913,13 +2944,13 @@ function EffectThumbnail({ provider, effect, width = 96, height = 54, className
|
|
|
2913
2944
|
live = false;
|
|
2914
2945
|
};
|
|
2915
2946
|
}, [provider, effect, width, height]);
|
|
2916
|
-
return /* @__PURE__ */ (0,
|
|
2947
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
2917
2948
|
"div",
|
|
2918
2949
|
{
|
|
2919
2950
|
className: `relative overflow-hidden rounded border border-border bg-[repeating-conic-gradient(#8884_0_25%,transparent_0_50%)] bg-[length:12px_12px] ${className}`,
|
|
2920
2951
|
style: { aspectRatio: `${width} / ${height}` },
|
|
2921
2952
|
"data-effect-thumbnail": effect.id,
|
|
2922
|
-
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" })
|
|
2923
2954
|
}
|
|
2924
2955
|
);
|
|
2925
2956
|
}
|
|
@@ -2927,7 +2958,7 @@ function EffectThumbnail({ provider, effect, width = 96, height = 54, className
|
|
|
2927
2958
|
// src/effects/EffectsBrowser.tsx
|
|
2928
2959
|
var import_react14 = require("react");
|
|
2929
2960
|
var import_effects2 = require("@pixerate/editor/effects");
|
|
2930
|
-
var
|
|
2961
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2931
2962
|
function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, title = "Effects", className = "" }) {
|
|
2932
2963
|
const [all, setAll] = (0, import_react14.useState)([]);
|
|
2933
2964
|
const [query, setQuery] = (0, import_react14.useState)("");
|
|
@@ -2958,11 +2989,11 @@ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, titl
|
|
|
2958
2989
|
const categories = (0, import_react14.useMemo)(() => [...new Set(all.filter(allowed).map((e) => e.category))], [all, uses, kinds]);
|
|
2959
2990
|
const shown = found.filter(allowed);
|
|
2960
2991
|
if (!provider)
|
|
2961
|
-
return /* @__PURE__ */ (0,
|
|
2962
|
-
return /* @__PURE__ */ (0,
|
|
2963
|
-
title && /* @__PURE__ */ (0,
|
|
2964
|
-
/* @__PURE__ */ (0,
|
|
2965
|
-
/* @__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)(
|
|
2966
2997
|
"input",
|
|
2967
2998
|
{
|
|
2968
2999
|
type: "search",
|
|
@@ -2973,17 +3004,17 @@ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, titl
|
|
|
2973
3004
|
onChange: (e) => setQuery(e.currentTarget.value)
|
|
2974
3005
|
}
|
|
2975
3006
|
),
|
|
2976
|
-
/* @__PURE__ */ (0,
|
|
2977
|
-
/* @__PURE__ */ (0,
|
|
2978
|
-
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))
|
|
2979
3010
|
] }),
|
|
2980
|
-
uses && uses.length > 1 && /* @__PURE__ */ (0,
|
|
2981
|
-
/* @__PURE__ */ (0,
|
|
2982
|
-
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))
|
|
2983
3014
|
] })
|
|
2984
3015
|
] }),
|
|
2985
|
-
error && /* @__PURE__ */ (0,
|
|
2986
|
-
/* @__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)(
|
|
2987
3018
|
"button",
|
|
2988
3019
|
{
|
|
2989
3020
|
type: "button",
|
|
@@ -2992,13 +3023,13 @@ function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, titl
|
|
|
2992
3023
|
"data-effect-id": e.id,
|
|
2993
3024
|
onClick: () => onPick(e),
|
|
2994
3025
|
children: [
|
|
2995
|
-
thumbnails && /* @__PURE__ */ (0,
|
|
2996
|
-
/* @__PURE__ */ (0,
|
|
2997
|
-
/* @__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 ") })
|
|
2998
3029
|
]
|
|
2999
3030
|
}
|
|
3000
3031
|
) }, e.id)) }),
|
|
3001
|
-
!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." })
|
|
3002
3033
|
] });
|
|
3003
3034
|
}
|
|
3004
3035
|
|
|
@@ -3010,7 +3041,7 @@ var import_parameters2 = require("@pixerate/editor/parameters");
|
|
|
3010
3041
|
// src/parameters/fields.tsx
|
|
3011
3042
|
var import_react15 = require("react");
|
|
3012
3043
|
var import_parameters = require("@pixerate/editor/parameters");
|
|
3013
|
-
var
|
|
3044
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
3014
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";
|
|
3015
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";
|
|
3016
3047
|
var rangeClass = "h-4 w-full min-w-0 flex-1 cursor-pointer accent-primary disabled:cursor-not-allowed disabled:opacity-50";
|
|
@@ -3034,7 +3065,7 @@ function ParameterCommitInput({ value, onCommit, multiline, className, onKeyDown
|
|
|
3034
3065
|
onKeyDown: keyDown,
|
|
3035
3066
|
...rest
|
|
3036
3067
|
};
|
|
3037
|
-
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);
|
|
3038
3069
|
}
|
|
3039
3070
|
var plainNumber = (field, value) => (0, import_parameters.formatParameterNumber)({ ...field, unit: void 0 }, value);
|
|
3040
3071
|
function ParameterNumberInput({
|
|
@@ -3045,8 +3076,8 @@ function ParameterNumberInput({
|
|
|
3045
3076
|
id,
|
|
3046
3077
|
"aria-label": ariaLabel
|
|
3047
3078
|
}) {
|
|
3048
|
-
return /* @__PURE__ */ (0,
|
|
3049
|
-
/* @__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)(
|
|
3050
3081
|
ParameterCommitInput,
|
|
3051
3082
|
{
|
|
3052
3083
|
id,
|
|
@@ -3068,7 +3099,7 @@ function ParameterNumberInput({
|
|
|
3068
3099
|
}
|
|
3069
3100
|
}
|
|
3070
3101
|
),
|
|
3071
|
-
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 })
|
|
3072
3103
|
] });
|
|
3073
3104
|
}
|
|
3074
3105
|
function ParameterSlider(props) {
|
|
@@ -3079,10 +3110,10 @@ function ParameterSlider(props) {
|
|
|
3079
3110
|
dragging.current = false;
|
|
3080
3111
|
onGestureEnd?.();
|
|
3081
3112
|
};
|
|
3082
|
-
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 });
|
|
3083
3114
|
const step = (0, import_parameters.parameterStep)(field);
|
|
3084
|
-
return /* @__PURE__ */ (0,
|
|
3085
|
-
/* @__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)(
|
|
3086
3117
|
"input",
|
|
3087
3118
|
{
|
|
3088
3119
|
type: "range",
|
|
@@ -3105,11 +3136,11 @@ function ParameterSlider(props) {
|
|
|
3105
3136
|
onChange: (e) => onChange((0, import_parameters.clampParameterNumber)(field, Number(e.target.value)))
|
|
3106
3137
|
}
|
|
3107
3138
|
),
|
|
3108
|
-
/* @__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` }) })
|
|
3109
3140
|
] });
|
|
3110
3141
|
}
|
|
3111
3142
|
function ParameterToggle({ field, value, onChange, disabled, id }) {
|
|
3112
|
-
return /* @__PURE__ */ (0,
|
|
3143
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3113
3144
|
"button",
|
|
3114
3145
|
{
|
|
3115
3146
|
type: "button",
|
|
@@ -3120,7 +3151,7 @@ function ParameterToggle({ field, value, onChange, disabled, id }) {
|
|
|
3120
3151
|
disabled: disabled || field.readOnly,
|
|
3121
3152
|
onClick: () => onChange(!value),
|
|
3122
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"}`,
|
|
3123
|
-
children: /* @__PURE__ */ (0,
|
|
3154
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3124
3155
|
"span",
|
|
3125
3156
|
{
|
|
3126
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"}`
|
|
@@ -3133,7 +3164,7 @@ function ParameterSelect({ field, value, onChange, disabled, id }) {
|
|
|
3133
3164
|
const options = (0, import_parameters.getChoiceOptions)(field);
|
|
3134
3165
|
const off = disabled || field.readOnly;
|
|
3135
3166
|
if (field.control === "segmented") {
|
|
3136
|
-
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)(
|
|
3137
3168
|
"button",
|
|
3138
3169
|
{
|
|
3139
3170
|
type: "button",
|
|
@@ -3149,7 +3180,7 @@ function ParameterSelect({ field, value, onChange, disabled, id }) {
|
|
|
3149
3180
|
)) });
|
|
3150
3181
|
}
|
|
3151
3182
|
const index = options.findIndex((o) => o.value === value);
|
|
3152
|
-
return /* @__PURE__ */ (0,
|
|
3183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3153
3184
|
"select",
|
|
3154
3185
|
{
|
|
3155
3186
|
id,
|
|
@@ -3161,7 +3192,7 @@ function ParameterSelect({ field, value, onChange, disabled, id }) {
|
|
|
3161
3192
|
if (option) onChange(option.value);
|
|
3162
3193
|
},
|
|
3163
3194
|
className: parameterInputClass,
|
|
3164
|
-
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)))
|
|
3165
3196
|
}
|
|
3166
3197
|
);
|
|
3167
3198
|
}
|
|
@@ -3182,11 +3213,11 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3182
3213
|
picking.current = false;
|
|
3183
3214
|
onGestureEnd?.();
|
|
3184
3215
|
};
|
|
3185
|
-
return /* @__PURE__ */ (0,
|
|
3186
|
-
/* @__PURE__ */ (0,
|
|
3187
|
-
/* @__PURE__ */ (0,
|
|
3188
|
-
/* @__PURE__ */ (0,
|
|
3189
|
-
/* @__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)(
|
|
3190
3221
|
"input",
|
|
3191
3222
|
{
|
|
3192
3223
|
type: "color",
|
|
@@ -3202,7 +3233,7 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3202
3233
|
}
|
|
3203
3234
|
)
|
|
3204
3235
|
] }),
|
|
3205
|
-
/* @__PURE__ */ (0,
|
|
3236
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3206
3237
|
ParameterCommitInput,
|
|
3207
3238
|
{
|
|
3208
3239
|
id,
|
|
@@ -3218,7 +3249,7 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3218
3249
|
}
|
|
3219
3250
|
)
|
|
3220
3251
|
] }),
|
|
3221
|
-
alpha && /* @__PURE__ */ (0,
|
|
3252
|
+
alpha && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3222
3253
|
"input",
|
|
3223
3254
|
{
|
|
3224
3255
|
type: "range",
|
|
@@ -3236,10 +3267,10 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3236
3267
|
onChange: (e) => onChange(`${rgb}${Number(e.target.value).toString(16).padStart(2, "0")}`)
|
|
3237
3268
|
}
|
|
3238
3269
|
),
|
|
3239
|
-
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) => {
|
|
3240
3271
|
const swatch = (0, import_parameters.normalizeHexColor)(s, alpha);
|
|
3241
3272
|
if (!swatch) return null;
|
|
3242
|
-
return /* @__PURE__ */ (0,
|
|
3273
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3243
3274
|
"button",
|
|
3244
3275
|
{
|
|
3245
3276
|
type: "button",
|
|
@@ -3258,11 +3289,11 @@ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd,
|
|
|
3258
3289
|
}
|
|
3259
3290
|
function ParameterVector({ field, value, onChange, disabled, id }) {
|
|
3260
3291
|
const size = (0, import_parameters.vectorSize)(field);
|
|
3261
|
-
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) => {
|
|
3262
3293
|
const component = (0, import_parameters.vectorComponentField)(field, i);
|
|
3263
|
-
return /* @__PURE__ */ (0,
|
|
3264
|
-
/* @__PURE__ */ (0,
|
|
3265
|
-
/* @__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)(
|
|
3266
3297
|
ParameterNumberInput,
|
|
3267
3298
|
{
|
|
3268
3299
|
field: component,
|
|
@@ -3279,11 +3310,11 @@ function ParameterVector({ field, value, onChange, disabled, id }) {
|
|
|
3279
3310
|
function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
3280
3311
|
const off = disabled || field.readOnly;
|
|
3281
3312
|
const name = (0, import_parameters.parameterLabel)(field);
|
|
3282
|
-
return /* @__PURE__ */ (0,
|
|
3283
|
-
/* @__PURE__ */ (0,
|
|
3284
|
-
/* @__PURE__ */ (0,
|
|
3285
|
-
/* @__PURE__ */ (0,
|
|
3286
|
-
/* @__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)(
|
|
3287
3318
|
ParameterCommitInput,
|
|
3288
3319
|
{
|
|
3289
3320
|
id,
|
|
@@ -3294,10 +3325,10 @@ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
|
3294
3325
|
onCommit: (text) => onChange(text.trim())
|
|
3295
3326
|
}
|
|
3296
3327
|
),
|
|
3297
|
-
/* @__PURE__ */ (0,
|
|
3298
|
-
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: [
|
|
3299
3330
|
"Choose file\u2026",
|
|
3300
|
-
/* @__PURE__ */ (0,
|
|
3331
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3301
3332
|
"input",
|
|
3302
3333
|
{
|
|
3303
3334
|
type: "file",
|
|
@@ -3313,11 +3344,11 @@ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
|
3313
3344
|
}
|
|
3314
3345
|
)
|
|
3315
3346
|
] }),
|
|
3316
|
-
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" })
|
|
3317
3348
|
] })
|
|
3318
3349
|
] })
|
|
3319
3350
|
] }),
|
|
3320
|
-
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)(
|
|
3321
3352
|
"button",
|
|
3322
3353
|
{
|
|
3323
3354
|
type: "button",
|
|
@@ -3327,14 +3358,14 @@ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
|
|
|
3327
3358
|
disabled: off,
|
|
3328
3359
|
onClick: () => onChange(o.url),
|
|
3329
3360
|
className: "h-9 w-12 overflow-hidden rounded border border-input aria-pressed:ring-2 aria-pressed:ring-primary",
|
|
3330
|
-
children: /* @__PURE__ */ (0,
|
|
3361
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("img", { src: o.url, alt: "", className: "h-full w-full object-cover" })
|
|
3331
3362
|
},
|
|
3332
3363
|
o.url
|
|
3333
3364
|
)) })
|
|
3334
3365
|
] });
|
|
3335
3366
|
}
|
|
3336
3367
|
function ParameterText({ field, value, onChange, disabled, id }) {
|
|
3337
|
-
return /* @__PURE__ */ (0,
|
|
3368
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3338
3369
|
ParameterCommitInput,
|
|
3339
3370
|
{
|
|
3340
3371
|
id,
|
|
@@ -3353,31 +3384,31 @@ function ParameterFieldControl({ field, value, onChange, resolveFile, ...rest })
|
|
|
3353
3384
|
switch (field.type) {
|
|
3354
3385
|
case "number":
|
|
3355
3386
|
case "int":
|
|
3356
|
-
return /* @__PURE__ */ (0,
|
|
3387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterSlider, { field, value, onChange: set, ...rest });
|
|
3357
3388
|
case "boolean":
|
|
3358
|
-
return /* @__PURE__ */ (0,
|
|
3389
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterToggle, { field, value, onChange: set, ...rest });
|
|
3359
3390
|
case "choice":
|
|
3360
|
-
return /* @__PURE__ */ (0,
|
|
3391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterSelect, { field, value, onChange: set, ...rest });
|
|
3361
3392
|
case "color":
|
|
3362
|
-
return /* @__PURE__ */ (0,
|
|
3393
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterColor, { field, value, onChange: set, ...rest });
|
|
3363
3394
|
case "vector":
|
|
3364
|
-
return /* @__PURE__ */ (0,
|
|
3395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterVector, { field, value, onChange: set, ...rest });
|
|
3365
3396
|
case "image":
|
|
3366
|
-
return /* @__PURE__ */ (0,
|
|
3397
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterImage, { field, value, onChange: set, resolveFile, ...rest });
|
|
3367
3398
|
case "text":
|
|
3368
|
-
return /* @__PURE__ */ (0,
|
|
3399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParameterText, { field, value, onChange: set, ...rest });
|
|
3369
3400
|
}
|
|
3370
3401
|
}
|
|
3371
3402
|
|
|
3372
3403
|
// src/effects/EffectParameters.tsx
|
|
3373
|
-
var
|
|
3404
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
3374
3405
|
function EffectParameters({ description, values, onChange, onReset, keyframed, onPreset, disabled = false, className = "" }) {
|
|
3375
3406
|
const fields = (0, import_react16.useMemo)(() => (0, import_effects3.effectParameterFields)(description), [description]);
|
|
3376
3407
|
const idBase = (0, import_react16.useId)();
|
|
3377
3408
|
const gesture = import_react16.default.useRef(null);
|
|
3378
3409
|
const count = import_react16.default.useRef(0);
|
|
3379
|
-
return /* @__PURE__ */ (0,
|
|
3380
|
-
onPreset && description.presets.length > 0 && /* @__PURE__ */ (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)(
|
|
3381
3412
|
"select",
|
|
3382
3413
|
{
|
|
3383
3414
|
className: "w-full rounded border border-border bg-transparent px-1 py-0.5 text-xs",
|
|
@@ -3389,8 +3420,8 @@ function EffectParameters({ description, values, onChange, onReset, keyframed, o
|
|
|
3389
3420
|
if (preset) onPreset({ ...description.defaults, ...preset.values });
|
|
3390
3421
|
},
|
|
3391
3422
|
children: [
|
|
3392
|
-
/* @__PURE__ */ (0,
|
|
3393
|
-
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))
|
|
3394
3425
|
]
|
|
3395
3426
|
}
|
|
3396
3427
|
),
|
|
@@ -3400,13 +3431,13 @@ function EffectParameters({ description, values, onChange, onReset, keyframed, o
|
|
|
3400
3431
|
const keyed = keyframed?.has(field.id) ?? false;
|
|
3401
3432
|
const value = (0, import_effects3.effectFieldValue)(field, values[field.id]);
|
|
3402
3433
|
const changed = !keyed && !(0, import_parameters2.parameterValuesEqual)(value, field.default);
|
|
3403
|
-
return /* @__PURE__ */ (0,
|
|
3404
|
-
/* @__PURE__ */ (0,
|
|
3405
|
-
/* @__PURE__ */ (0,
|
|
3406
|
-
keyed && /* @__PURE__ */ (0,
|
|
3407
|
-
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" })
|
|
3408
3439
|
] }),
|
|
3409
|
-
/* @__PURE__ */ (0,
|
|
3440
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3410
3441
|
ParameterFieldControl,
|
|
3411
3442
|
{
|
|
3412
3443
|
field,
|
|
@@ -3420,13 +3451,13 @@ function EffectParameters({ description, values, onChange, onReset, keyframed, o
|
|
|
3420
3451
|
)
|
|
3421
3452
|
] }, field.id);
|
|
3422
3453
|
}),
|
|
3423
|
-
!fields.length && /* @__PURE__ */ (0,
|
|
3454
|
+
!fields.length && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "No controls." })
|
|
3424
3455
|
] });
|
|
3425
3456
|
}
|
|
3426
3457
|
|
|
3427
3458
|
// src/vector/VectorProviderEffectsPanel.tsx
|
|
3428
3459
|
var import_react17 = require("react");
|
|
3429
|
-
var
|
|
3460
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
3430
3461
|
var btn = "rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40";
|
|
3431
3462
|
function Controls({ controller, group }) {
|
|
3432
3463
|
const provider = controller.effectsProvider;
|
|
@@ -3434,11 +3465,11 @@ function Controls({ controller, group }) {
|
|
|
3434
3465
|
const { description, error } = useEffectDescription(provider, tag.effect);
|
|
3435
3466
|
const [message, setMessage] = (0, import_react17.useState)(null);
|
|
3436
3467
|
const run = (work) => void work.then(() => setMessage(null), (e) => setMessage(e instanceof Error ? e.message : String(e)));
|
|
3437
|
-
if (!provider) return /* @__PURE__ */ (0,
|
|
3438
|
-
if (error) return /* @__PURE__ */ (0,
|
|
3439
|
-
if (!description) return /* @__PURE__ */ (0,
|
|
3440
|
-
return /* @__PURE__ */ (0,
|
|
3441
|
-
/* @__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)(
|
|
3442
3473
|
EffectParameters,
|
|
3443
3474
|
{
|
|
3444
3475
|
description,
|
|
@@ -3448,7 +3479,7 @@ function Controls({ controller, group }) {
|
|
|
3448
3479
|
onPreset: (v) => run(controller.updateVectorEffect(group.id, v))
|
|
3449
3480
|
}
|
|
3450
3481
|
),
|
|
3451
|
-
message && /* @__PURE__ */ (0,
|
|
3482
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
|
|
3452
3483
|
] });
|
|
3453
3484
|
}
|
|
3454
3485
|
function VectorProviderEffectsPanel({ controller, className = "" }) {
|
|
@@ -3467,41 +3498,41 @@ function VectorProviderEffectsPanel({ controller, className = "" }) {
|
|
|
3467
3498
|
setMessage(null);
|
|
3468
3499
|
Promise.resolve().then(work).catch((e) => setMessage(e instanceof Error ? e.message : String(e)));
|
|
3469
3500
|
};
|
|
3470
|
-
return /* @__PURE__ */ (0,
|
|
3471
|
-
/* @__PURE__ */ (0,
|
|
3472
|
-
/* @__PURE__ */ (0,
|
|
3473
|
-
/* @__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" })
|
|
3474
3505
|
] }),
|
|
3475
|
-
!provider && /* @__PURE__ */ (0,
|
|
3476
|
-
browse && /* @__PURE__ */ (0,
|
|
3477
|
-
selected.map((g) => /* @__PURE__ */ (0,
|
|
3478
|
-
/* @__PURE__ */ (0,
|
|
3479
|
-
/* @__PURE__ */ (0,
|
|
3480
|
-
/* @__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" })
|
|
3481
3512
|
] }),
|
|
3482
|
-
/* @__PURE__ */ (0,
|
|
3513
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Controls, { controller, group: g })
|
|
3483
3514
|
] }, g.id)),
|
|
3484
|
-
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: [
|
|
3485
3516
|
"Select an effect group (",
|
|
3486
3517
|
groups.length,
|
|
3487
3518
|
" in the drawing) to change it."
|
|
3488
3519
|
] }),
|
|
3489
|
-
message && /* @__PURE__ */ (0,
|
|
3520
|
+
message && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-[11px] text-destructive", children: message })
|
|
3490
3521
|
] });
|
|
3491
3522
|
}
|
|
3492
3523
|
|
|
3493
3524
|
// src/vector/VectorEditor.tsx
|
|
3494
|
-
var
|
|
3525
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
3495
3526
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, effects, className }) {
|
|
3496
3527
|
useEffects(controller, effects);
|
|
3497
3528
|
const effectsShown = !!effects || controller.vectorEffectGroups().length > 0;
|
|
3498
|
-
return /* @__PURE__ */ (0,
|
|
3499
|
-
/* @__PURE__ */ (0,
|
|
3500
|
-
/* @__PURE__ */ (0,
|
|
3501
|
-
/* @__PURE__ */ (0,
|
|
3502
|
-
showStylePanel && /* @__PURE__ */ (0,
|
|
3503
|
-
/* @__PURE__ */ (0,
|
|
3504
|
-
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" })
|
|
3505
3536
|
] })
|
|
3506
3537
|
] })
|
|
3507
3538
|
] });
|
|
@@ -3523,6 +3554,7 @@ function VectorEditor({ controller, tools, showStylePanel = true, height = 520,
|
|
|
3523
3554
|
VectorLensPanel,
|
|
3524
3555
|
VectorMaskPanel,
|
|
3525
3556
|
VectorMaskedNodes,
|
|
3557
|
+
VectorPagesPanel,
|
|
3526
3558
|
VectorPerspectivePanel,
|
|
3527
3559
|
VectorProviderEffectsPanel,
|
|
3528
3560
|
VectorSceneNodes,
|