@pixerate/editor-react 0.75.0 → 0.75.1

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.
@@ -44,7 +44,7 @@ function useVectorCommands(registry, controller, options = {}) {
44
44
  }
45
45
 
46
46
  // src/vector/VectorCanvas.tsx
47
- import React2, { useEffect as useEffect2, useId, useRef as useRef3 } from "react";
47
+ import React2, { useEffect as useEffect2, useId, useRef as useRef3, useState as useState2 } from "react";
48
48
  import {
49
49
  VECTOR_OVERLAY_THEME as THEME2,
50
50
  getVectorOverlayRenderData,
@@ -227,48 +227,19 @@ function VectorTextElement({ node }) {
227
227
  )) });
228
228
  }
229
229
  function VectorSceneNodes({ nodes }) {
230
- return /* @__PURE__ */ jsx2(Fragment, { children: nodes.map(
231
- (node) => node.kind === "text" ? /* @__PURE__ */ jsx2(VectorTextElement, { node }, node.id) : node.kind === "group" ? /* @__PURE__ */ jsx2(
232
- "g",
233
- {
234
- "data-vector-id": node.id,
235
- "data-vector-mask": node.mask?.type,
236
- transform: node.transform,
237
- opacity: node.opacity < 1 ? node.opacity : void 0,
238
- filter: node.filter,
239
- style: blendStyle(node.blendMode),
240
- children: node.mask ? /* @__PURE__ */ jsx2(VectorMaskedNodes, { mask: node.mask, nodes: node.children }) : /* @__PURE__ */ jsx2(VectorSceneNodes, { nodes: node.children })
241
- },
242
- node.id
243
- ) : node.layers ? (
244
- // Fill and stroke stacks: each layer in order, bottom to top.
245
- /* @__PURE__ */ jsx2(
246
- "g",
247
- {
248
- "data-vector-id": node.id,
249
- transform: node.transform,
250
- opacity: node.opacity < 1 ? node.opacity : void 0,
251
- filter: node.filter,
252
- style: blendStyle(node.blendMode),
253
- children: node.layers.map((layer) => /* @__PURE__ */ jsx2(VectorPaintPath, { paint: layer, d: node.d, fillRule: node.fillRule, layer: `${layer.kind}-${layer.index}` }, `${layer.kind}-${layer.index}`))
254
- },
255
- node.id
256
- )
257
- ) : /* @__PURE__ */ jsx2(
258
- VectorPaintPath,
259
- {
260
- paint: node,
261
- d: node.d,
262
- fillRule: node.fillRule,
263
- id: node.id,
264
- transform: node.transform,
265
- filter: node.filter,
266
- blendMode: node.blendMode
267
- },
268
- node.id
269
- )
270
- ) });
230
+ return /* @__PURE__ */ jsx2(Fragment, { children: nodes.map((node) => /* @__PURE__ */ jsx2(VectorSceneNode, { node }, node.id)) });
271
231
  }
232
+ var VectorSceneNode = React2.memo(function VectorSceneNode2({ node }) {
233
+ if (node.kind === "text") return /* @__PURE__ */ jsx2(VectorTextElement, { node });
234
+ if (node.kind === "group")
235
+ return /* @__PURE__ */ jsx2("g", { "data-vector-id": node.id, "data-vector-mask": node.mask?.type, transform: node.transform, opacity: node.opacity < 1 ? node.opacity : void 0, filter: node.filter, style: blendStyle(node.blendMode), children: node.mask ? /* @__PURE__ */ jsx2(VectorMaskedNodes, { mask: node.mask, nodes: node.children }) : /* @__PURE__ */ jsx2(VectorSceneNodes, { nodes: node.children }) });
236
+ if (node.layers)
237
+ return (
238
+ // Fill and stroke stacks: each layer in order, bottom to top.
239
+ /* @__PURE__ */ jsx2("g", { "data-vector-id": node.id, transform: node.transform, opacity: node.opacity < 1 ? node.opacity : void 0, filter: node.filter, style: blendStyle(node.blendMode), children: node.layers.map((layer) => /* @__PURE__ */ jsx2(VectorPaintPath, { paint: layer, d: node.d, fillRule: node.fillRule, layer: `${layer.kind}-${layer.index}` }, `${layer.kind}-${layer.index}`)) })
240
+ );
241
+ return /* @__PURE__ */ jsx2(VectorPaintPath, { paint: node, d: node.d, fillRule: node.fillRule, id: node.id, transform: node.transform, filter: node.filter, blendMode: node.blendMode });
242
+ });
272
243
  function VectorMaskedNodes({ mask, nodes }) {
273
244
  const b = mask.bounds;
274
245
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
@@ -363,7 +334,8 @@ function VectorCanvas({
363
334
  const editingText = state.textEdit?.nodeId ?? null;
364
335
  const fitted = useRef3(!fitOnMount);
365
336
  const uid = useId().replace(/:/g, "");
366
- const scene = getVectorSceneRenderData(state, { idPrefix: `ve${uid}-` });
337
+ const [size, setSize] = useState2(null);
338
+ const scene = getVectorSceneRenderData(state, { idPrefix: `ve${uid}-`, ...size ? { viewportSize: size } : {} });
367
339
  const overlay = getVectorOverlayRenderData(state);
368
340
  const host = getVectorSymbolEditBackground(state, { idPrefix: `ve${uid}-host-` });
369
341
  useEffect2(() => {
@@ -381,6 +353,18 @@ function VectorCanvas({
381
353
  observer.observe(el);
382
354
  return () => observer.disconnect();
383
355
  }, [controller]);
356
+ useEffect2(() => {
357
+ const el = svgRef.current;
358
+ if (!el || typeof ResizeObserver === "undefined") return;
359
+ const measure = () => {
360
+ const r = el.getBoundingClientRect();
361
+ if (r.width > 0 && r.height > 0) setSize((s) => s && s.width === r.width && s.height === r.height ? s : { width: r.width, height: r.height });
362
+ };
363
+ measure();
364
+ const observer = new ResizeObserver(measure);
365
+ observer.observe(el);
366
+ return () => observer.disconnect();
367
+ }, []);
384
368
  useEffect2(() => {
385
369
  if (!editingText) return;
386
370
  const t = setTimeout(() => textRef.current?.focus({ preventScroll: true }), 0);
@@ -516,8 +500,8 @@ function VectorCanvas({
516
500
  /* @__PURE__ */ jsx2("circle", { cx: h.x, cy: h.y, r: THEME2.handleRadius + (h.hovered || h.active ? 1 : 0), fill: h.active ? accentColor : THEME2.handleFill, stroke: accentColor })
517
501
  ] }, h.index)),
518
502
  overlay.envelope.anchors.map((a) => {
519
- const size = as + (a.hovered || a.active ? 2 : 0);
520
- return /* @__PURE__ */ jsx2("rect", { "data-vector-envelope-anchor": a.index, x: a.x - size / 2, y: a.y - size / 2, width: size, height: size, fill: a.active ? accentColor : THEME2.handleFill, stroke: accentColor }, a.index);
503
+ const size2 = as + (a.hovered || a.active ? 2 : 0);
504
+ return /* @__PURE__ */ jsx2("rect", { "data-vector-envelope-anchor": a.index, x: a.x - size2 / 2, y: a.y - size2 / 2, width: size2, height: size2, fill: a.active ? accentColor : THEME2.handleFill, stroke: accentColor }, a.index);
521
505
  })
522
506
  ] }),
523
507
  overlay.handles.map((h) => /* @__PURE__ */ jsxs2("g", { "data-vector-handle": h.ref.handle, children: [
@@ -525,10 +509,10 @@ function VectorCanvas({
525
509
  /* @__PURE__ */ jsx2("circle", { cx: h.x, cy: h.y, r: THEME2.handleRadius + (h.hovered ? 1 : 0), fill: THEME2.handleFill, stroke: accentColor })
526
510
  ] }, `${h.ref.nodeId}:${h.ref.subpath}:${h.ref.index}:${h.ref.handle}`)),
527
511
  overlay.anchors.map((a) => {
528
- const size = as + (a.hovered ? 2 : 0);
512
+ const size2 = as + (a.hovered ? 2 : 0);
529
513
  const fill = a.selected ? accentColor : THEME2.handleFill;
530
514
  const key = `${a.ref.nodeId}:${a.ref.subpath}:${a.ref.index}`;
531
- return a.type === "corner" ? /* @__PURE__ */ jsx2("rect", { "data-vector-anchor": a.ref.index, x: a.x - size / 2, y: a.y - size / 2, width: size, height: size, fill, stroke: accentColor }, key) : /* @__PURE__ */ jsx2("circle", { "data-vector-anchor": a.ref.index, cx: a.x, cy: a.y, r: size / 2, fill, stroke: accentColor }, key);
515
+ return a.type === "corner" ? /* @__PURE__ */ jsx2("rect", { "data-vector-anchor": a.ref.index, x: a.x - size2 / 2, y: a.y - size2 / 2, width: size2, height: size2, fill, stroke: accentColor }, key) : /* @__PURE__ */ jsx2("circle", { "data-vector-anchor": a.ref.index, cx: a.x, cy: a.y, r: size2 / 2, fill, stroke: accentColor }, key);
532
516
  }),
533
517
  overlay.cornerWidgets.map((w) => /* @__PURE__ */ jsxs2("g", { "data-vector-corner-widget": w.ref.index, "data-corner-kind": w.kind, children: [
534
518
  /* @__PURE__ */ jsx2("circle", { cx: w.x, cy: w.y, r: THEME2.cornerWidgetRadius + (w.hovered ? 1 : 0), fill: THEME2.handleFill, stroke: accentColor }),
@@ -1584,7 +1568,7 @@ function VectorTextPanel({ controller, className }) {
1584
1568
  }
1585
1569
 
1586
1570
  // src/vector/VectorSymbolsPanel.tsx
1587
- import { useId as useId3, useState as useState2 } from "react";
1571
+ import { useId as useId3, useState as useState3 } from "react";
1588
1572
  import { getVectorSymbolsPanel, vectorPaintToHex } from "@pixerate/editor/vector";
1589
1573
  import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1590
1574
  var buttonClass6 = "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";
@@ -1594,7 +1578,7 @@ function VectorSymbolsPanel({ controller, className }) {
1594
1578
  const state = useVectorEditorState(controller);
1595
1579
  const uid = useId3().replace(/:/g, "");
1596
1580
  const panel = getVectorSymbolsPanel(state, { idPrefix: `vsym${uid}-` });
1597
- const [error, setError] = useState2(null);
1581
+ const [error, setError] = useState3(null);
1598
1582
  const report = (r) => setError(r.ok ? null : r.message ?? null);
1599
1583
  const inst = panel.instance;
1600
1584
  return /* @__PURE__ */ jsxs8("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-symbols-panel": "", "aria-label": "Symbols", children: [
@@ -1652,7 +1636,7 @@ function VectorSymbolsPanel({ controller, className }) {
1652
1636
  }
1653
1637
 
1654
1638
  // src/vector/VectorConstraintsPanel.tsx
1655
- import { useState as useState3 } from "react";
1639
+ import { useState as useState4 } from "react";
1656
1640
  import { getVectorConstraintPanel } from "@pixerate/editor/vector";
1657
1641
  import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1658
1642
  var buttonClass7 = "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";
@@ -1661,8 +1645,8 @@ var labelClass6 = "w-16 text-[11px] font-medium uppercase tracking-wide text-mut
1661
1645
  function VectorConstraintsPanel({ controller, className }) {
1662
1646
  const state = useVectorEditorState(controller);
1663
1647
  const panel = getVectorConstraintPanel(state);
1664
- const [error, setError] = useState3(null);
1665
- const [param, setParam] = useState3({ name: "", value: "" });
1648
+ const [error, setError] = useState4(null);
1649
+ const [param, setParam] = useState4({ name: "", value: "" });
1666
1650
  const report = (r) => setError(r.ok ? null : r.message ?? null);
1667
1651
  const add = (a) => report(controller.addConstraint({ kind: a.kind, refs: a.refs }));
1668
1652
  if (!panel.actions.length && !panel.constraints.length && !state.document.constraints?.length && state.tool !== "direct") return null;
@@ -1930,15 +1914,15 @@ function VectorConnectorPanel({ controller, className }) {
1930
1914
  }
1931
1915
 
1932
1916
  // src/vector/VectorShadingPanel.tsx
1933
- import { useState as useState4 } from "react";
1917
+ import { useState as useState5 } from "react";
1934
1918
  import { isVectorFreeformGradient, isVectorMeshGradient, vectorPaintToHex as vectorPaintToHex3 } from "@pixerate/editor/vector";
1935
1919
  import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1936
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";
1937
1921
  var numberClass6 = "h-7 w-12 rounded border border-border bg-background px-1.5 text-xs";
1938
1922
  function VectorShadingPanel({ controller, className }) {
1939
1923
  const state = useVectorEditorState(controller);
1940
- const [rows, setRows] = useState4(2);
1941
- const [columns, setColumns] = useState4(2);
1924
+ const [rows, setRows] = useState5(2);
1925
+ const [columns, setColumns] = useState5(2);
1942
1926
  const path = state.selection.map((id) => controller.getNode(id)).find((n) => n?.type === "path");
1943
1927
  if (!path) return null;
1944
1928
  const fill = path.fill;
@@ -1982,7 +1966,7 @@ function VectorShadingPanel({ controller, className }) {
1982
1966
  }
1983
1967
 
1984
1968
  // src/vector/VectorTracePanel.tsx
1985
- import { useRef as useRef4, useState as useState5 } from "react";
1969
+ import { useRef as useRef4, useState as useState6 } from "react";
1986
1970
  import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1987
1971
  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";
1988
1972
  var selectClass8 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
@@ -2001,9 +1985,9 @@ async function filePixels(file, max = 1e6) {
2001
1985
  }
2002
1986
  function VectorTracePanel({ controller, className }) {
2003
1987
  const input = useRef4(null);
2004
- const [mode, setMode] = useState5("threshold");
2005
- const [colors, setColors] = useState5(6);
2006
- const [message, setMessage] = useState5(null);
1988
+ const [mode, setMode] = useState6("threshold");
1989
+ const [colors, setColors] = useState6(6);
1990
+ const [message, setMessage] = useState6(null);
2007
1991
  const trace = async (file) => {
2008
1992
  try {
2009
1993
  const pixels = await filePixels(file);