@pixerate/editor-react 0.64.0 → 0.66.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.
@@ -34,6 +34,7 @@ __export(image_editor_exports, {
34
34
  BrushOptionsBar: () => BrushOptionsBar,
35
35
  ControlSlider: () => ControlSlider,
36
36
  CurvesEditor: () => CurvesEditor,
37
+ FreeTransformOptionsBar: () => FreeTransformOptionsBar,
37
38
  Histogram: () => Histogram,
38
39
  ImageEditor: () => ImageEditor,
39
40
  LayerEffectsPanel: () => LayerEffectsPanel,
@@ -204,8 +205,8 @@ function useImageEditor(options = {}) {
204
205
  }
205
206
 
206
207
  // src/image-editor/ImageEditor.tsx
207
- var import_react10 = __toESM(require("react"), 1);
208
- var import_image_editor11 = require("@pixerate/editor/image-editor");
208
+ var import_react11 = __toESM(require("react"), 1);
209
+ var import_image_editor12 = require("@pixerate/editor/image-editor");
209
210
 
210
211
  // src/image-editor/ControlSlider.tsx
211
212
  var import_image_editor2 = require("@pixerate/editor/image-editor");
@@ -1124,6 +1125,22 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
1124
1125
  children: (0, import_image_editor7.layerBadge)(layer)
1125
1126
  }
1126
1127
  ),
1128
+ layer.mask && !layer.mask.source && layer.type === "pixel" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1129
+ "button",
1130
+ {
1131
+ type: "button",
1132
+ "aria-label": `${layer.mask.linked === false ? "Link" : "Unlink"} ${row.label} mask`,
1133
+ "aria-pressed": layer.mask.linked !== false,
1134
+ title: layer.mask.linked === false ? "Mask unlinked: it stays put when the layer moves or transforms. Click to link." : "Mask linked: it moves with the layer. Click to unlink.",
1135
+ "data-testid": "layer-mask-link",
1136
+ className: `shrink-0 text-[10px] leading-none ${layer.mask.linked === false ? "text-slate-600" : "text-slate-300"}`,
1137
+ onClick: (e) => {
1138
+ e.stopPropagation();
1139
+ attempt(() => controller.setLayerMaskProps(layer.id, { linked: layer.mask.linked === false }));
1140
+ },
1141
+ children: layer.mask.linked === false ? "\u26D3\uFE0E\u0338" : "\u26D3\uFE0E"
1142
+ }
1143
+ ),
1127
1144
  layer.mask && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1128
1145
  Thumbnail,
1129
1146
  {
@@ -1635,8 +1652,147 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
1635
1652
  ] });
1636
1653
  };
1637
1654
 
1638
- // src/image-editor/ImageEditor.tsx
1655
+ // src/image-editor/FreeTransformOptionsBar.tsx
1656
+ var import_react10 = require("react");
1657
+ var import_image_editor11 = require("@pixerate/editor/image-editor");
1639
1658
  var import_jsx_runtime10 = require("react/jsx-runtime");
1659
+ var chip2 = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
1660
+ var round = (v, unit) => unit === "px" ? Math.round(v * 10) / 10 : Math.round(v * 100) / 100;
1661
+ var FreeTransformOptionsBar = ({ tool, className }) => {
1662
+ const [, setTick] = (0, import_react10.useState)(0);
1663
+ (0, import_react10.useEffect)(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
1664
+ const bar = tool.bar();
1665
+ if (!tool.active || !bar) return null;
1666
+ const warp = tool.warpBar();
1667
+ const warpNumber = (key, raw) => {
1668
+ const v = Number(raw);
1669
+ if (raw.trim() !== "" && Number.isFinite(v) && v !== warp[key]) tool.setWarp({ [key]: Math.max(-100, Math.min(100, v)) });
1670
+ };
1671
+ const apply = (field, raw) => {
1672
+ const v = Number(raw);
1673
+ if (raw.trim() !== "" && Number.isFinite(v) && Math.abs(v - bar[field]) > 1e-9) tool.setField(field, v);
1674
+ };
1675
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: `flex flex-wrap items-center gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "free-transform-options", role: "toolbar", "aria-label": "Free Transform options", children: [
1676
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Transform mode", children: import_image_editor11.FREE_TRANSFORM_MODE_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", title: m.title, "aria-pressed": tool.mode === m.id, className: chip2(tool.mode === m.id), onClick: () => tool.setMode(m.id), children: m.label }, m.id)) }),
1677
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "grid grid-cols-3 gap-px", role: "group", "aria-label": "Reference point", children: import_image_editor11.TRANSFORM_ANCHORS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", "aria-label": `Reference point ${a}`, title: `Reference point: ${a}`, className: "h-2.5 w-2.5 rounded-sm bg-slate-700 hover:bg-indigo-500", onClick: () => tool.setReference(a) }, a)) }),
1678
+ tool.mode === "warp" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": "Warp options", children: [
1679
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-1", children: [
1680
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-400", children: "Warp" }),
1681
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("select", { "aria-label": "Warp style", value: warp.style, onChange: (e) => tool.setWarp({ style: e.target.value }), className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5", children: import_image_editor11.WARP_STYLE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: o.id, children: o.label }, o.id)) })
1682
+ ] }),
1683
+ ["bend", "horizontal", "vertical"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-1", children: [
1684
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-400", children: k === "bend" ? "Bend" : k === "horizontal" ? "H" : "V" }),
1685
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1686
+ "input",
1687
+ {
1688
+ type: "number",
1689
+ "aria-label": k === "bend" ? "Warp bend in percent" : `Warp ${k} distortion in percent`,
1690
+ defaultValue: warp[k],
1691
+ min: -100,
1692
+ max: 100,
1693
+ disabled: warp.style === "custom",
1694
+ className: "w-14 rounded border border-slate-700 bg-slate-900 px-1 py-0.5 text-right disabled:opacity-40",
1695
+ onBlur: (e) => warpNumber(k, e.currentTarget.value),
1696
+ onKeyDown: (e) => {
1697
+ if (e.key === "Enter") {
1698
+ e.preventDefault();
1699
+ e.stopPropagation();
1700
+ warpNumber(k, e.currentTarget.value);
1701
+ }
1702
+ }
1703
+ },
1704
+ `${k}:${warp[k]}`
1705
+ ),
1706
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-500", children: "%" })
1707
+ ] }, k)),
1708
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1709
+ "button",
1710
+ {
1711
+ type: "button",
1712
+ title: "Bend along the vertical axis",
1713
+ "aria-pressed": warp.orientation === "vertical",
1714
+ disabled: warp.style === "custom",
1715
+ className: chip2(warp.orientation === "vertical"),
1716
+ onClick: () => tool.setWarp({ orientation: warp.orientation === "vertical" ? "horizontal" : "vertical" }),
1717
+ children: "Vertical"
1718
+ }
1719
+ ),
1720
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-1", children: [
1721
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-400", children: "Grid" }),
1722
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1723
+ "select",
1724
+ {
1725
+ "aria-label": "Warp grid",
1726
+ value: import_image_editor11.WARP_GRID_OPTIONS.find((g) => g.columns === warp.columns && g.rows === warp.rows)?.id ?? "1x1",
1727
+ onChange: (e) => {
1728
+ const g = import_image_editor11.WARP_GRID_OPTIONS.find((o) => o.id === e.target.value);
1729
+ tool.setWarp({ columns: g.columns, rows: g.rows });
1730
+ },
1731
+ className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
1732
+ children: import_image_editor11.WARP_GRID_OPTIONS.map((g) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: g.id, children: g.label }, g.id))
1733
+ }
1734
+ )
1735
+ ] })
1736
+ ] }),
1737
+ tool.mode !== "warp" && import_image_editor11.FREE_TRANSFORM_FIELDS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-1", title: f.title, children: [
1738
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-400", children: f.label }),
1739
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1740
+ "input",
1741
+ {
1742
+ type: "number",
1743
+ "aria-label": f.title,
1744
+ defaultValue: round(bar[f.id], f.unit),
1745
+ disabled: !bar.affine,
1746
+ step: f.unit === "px" ? 1 : 0.1,
1747
+ className: "w-16 rounded border border-slate-700 bg-slate-900 px-1 py-0.5 text-right disabled:opacity-40",
1748
+ onBlur: (e) => apply(f.id, e.currentTarget.value),
1749
+ onKeyDown: (e) => {
1750
+ if (e.key === "Enter") {
1751
+ e.preventDefault();
1752
+ e.stopPropagation();
1753
+ apply(f.id, e.currentTarget.value);
1754
+ }
1755
+ }
1756
+ },
1757
+ `${f.id}:${round(bar[f.id], f.unit)}`
1758
+ ),
1759
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-500", children: f.unit }),
1760
+ f.id === "scaleX" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1761
+ "button",
1762
+ {
1763
+ type: "button",
1764
+ "aria-label": "Keep width and height proportional",
1765
+ "aria-pressed": tool.proportional,
1766
+ className: chip2(tool.proportional),
1767
+ onClick: () => {
1768
+ tool.proportional = !tool.proportional;
1769
+ setTick((n) => n + 1);
1770
+ },
1771
+ children: "\u26D3\uFE0E"
1772
+ }
1773
+ )
1774
+ ] }, f.id)),
1775
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-1", children: [
1776
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-400", children: "Interpolation" }),
1777
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1778
+ "select",
1779
+ {
1780
+ "aria-label": "Interpolation",
1781
+ value: tool.interpolation,
1782
+ onChange: (e) => tool.setInterpolation(e.target.value),
1783
+ className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
1784
+ children: import_image_editor11.INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
1785
+ }
1786
+ )
1787
+ ] }),
1788
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", title: "Commit (Enter)", className: "px-2 py-1 rounded bg-emerald-600 text-white hover:bg-emerald-500", onClick: () => tool.commit(), children: "Commit" }),
1789
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", title: "Cancel (Esc)", className: chip2(false), onClick: () => tool.cancel(), children: "Cancel" }),
1790
+ tool.error && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { role: "alert", className: "text-rose-400", children: tool.error })
1791
+ ] });
1792
+ };
1793
+
1794
+ // src/image-editor/ImageEditor.tsx
1795
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1640
1796
  var ImageEditor = ({
1641
1797
  editor: externalEditor,
1642
1798
  src,
@@ -1651,35 +1807,47 @@ var ImageEditor = ({
1651
1807
  const internalEditor = useImageEditor({ image: src });
1652
1808
  const editor = externalEditor || internalEditor;
1653
1809
  const { state, controller } = editor;
1654
- const legacyProcess = (0, import_image_editor11.normalizeProcessVersion)(state.adjustments.process) < import_image_editor11.LATEST_PROCESS_VERSION;
1655
- const canvasRef = (0, import_react10.useRef)(null);
1656
- const containerRef = (0, import_react10.useRef)(null);
1657
- const [activeTab, setActiveTab] = (0, import_react10.useState)("crop");
1658
- const [activeCropRatio, setActiveCropRatio] = (0, import_react10.useState)(null);
1659
- const [selectionOptions, setSelectionOptions] = (0, import_react10.useState)(import_image_editor11.DEFAULT_SELECTION_TOOL_OPTIONS);
1660
- const selectionOptionsRef = (0, import_react10.useRef)(selectionOptions);
1810
+ const legacyProcess = (0, import_image_editor12.normalizeProcessVersion)(state.adjustments.process) < import_image_editor12.LATEST_PROCESS_VERSION;
1811
+ const canvasRef = (0, import_react11.useRef)(null);
1812
+ const containerRef = (0, import_react11.useRef)(null);
1813
+ const [activeTab, setActiveTab] = (0, import_react11.useState)("crop");
1814
+ const [activeCropRatio, setActiveCropRatio] = (0, import_react11.useState)(null);
1815
+ const [selectionOptions, setSelectionOptions] = (0, import_react11.useState)(import_image_editor12.DEFAULT_SELECTION_TOOL_OPTIONS);
1816
+ const selectionOptionsRef = (0, import_react11.useRef)(selectionOptions);
1661
1817
  selectionOptionsRef.current = selectionOptions;
1662
- const selectionGestureRef = (0, import_react10.useRef)(null);
1818
+ const selectionGestureRef = (0, import_react11.useRef)(null);
1663
1819
  if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
1664
- selectionGestureRef.current = new import_image_editor11.SelectionGesture(controller, () => selectionOptionsRef.current);
1820
+ selectionGestureRef.current = new import_image_editor12.SelectionGesture(controller, () => selectionOptionsRef.current);
1665
1821
  }
1666
- const selectionDraftRef = (0, import_react10.useRef)(null);
1667
- const [selectionError, setSelectionError] = (0, import_react10.useState)(null);
1668
- const paintGestureRef = (0, import_react10.useRef)(null);
1669
- const paintControllerRef = (0, import_react10.useRef)(controller);
1822
+ const selectionDraftRef = (0, import_react11.useRef)(null);
1823
+ const [selectionError, setSelectionError] = (0, import_react11.useState)(null);
1824
+ const paintGestureRef = (0, import_react11.useRef)(null);
1825
+ const paintControllerRef = (0, import_react11.useRef)(controller);
1670
1826
  if (!paintGestureRef.current || paintControllerRef.current !== controller) {
1671
- paintGestureRef.current = new import_image_editor11.PaintGesture(controller);
1827
+ paintGestureRef.current = new import_image_editor12.PaintGesture(controller);
1672
1828
  paintControllerRef.current = controller;
1673
1829
  }
1674
- const brushCursorRef = (0, import_react10.useRef)(null);
1675
- const [paintError, setPaintError] = (0, import_react10.useState)(null);
1676
- const [inpaintPrompt, setInpaintPrompt] = (0, import_react10.useState)("");
1677
- const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react10.useState)("annotations");
1678
- const [isRemovingBg, setIsRemovingBg] = (0, import_react10.useState)(false);
1679
- const [isInpainting, setIsInpainting] = (0, import_react10.useState)(false);
1680
- const [aiError, setAiError] = (0, import_react10.useState)(null);
1681
- const [aiSuccess, setAiSuccess] = (0, import_react10.useState)(null);
1682
- const [aiTarget, setAiTarget] = (0, import_react10.useState)("auto");
1830
+ const brushCursorRef = (0, import_react11.useRef)(null);
1831
+ const [paintError, setPaintError] = (0, import_react11.useState)(null);
1832
+ const transformToolRef = (0, import_react11.useRef)(null);
1833
+ const transformControllerRef = (0, import_react11.useRef)(controller);
1834
+ if (!transformToolRef.current || transformControllerRef.current !== controller) {
1835
+ transformToolRef.current?.cancel();
1836
+ transformToolRef.current = new import_image_editor12.FreeTransformTool(controller, {
1837
+ schedule: (run) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(run) : run()
1838
+ });
1839
+ transformControllerRef.current = controller;
1840
+ }
1841
+ const transformTool = transformToolRef.current;
1842
+ const [, setTransformTick] = (0, import_react11.useState)(0);
1843
+ const [transformCursor, setTransformCursor] = (0, import_react11.useState)("default");
1844
+ const [inpaintPrompt, setInpaintPrompt] = (0, import_react11.useState)("");
1845
+ const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react11.useState)("annotations");
1846
+ const [isRemovingBg, setIsRemovingBg] = (0, import_react11.useState)(false);
1847
+ const [isInpainting, setIsInpainting] = (0, import_react11.useState)(false);
1848
+ const [aiError, setAiError] = (0, import_react11.useState)(null);
1849
+ const [aiSuccess, setAiSuccess] = (0, import_react11.useState)(null);
1850
+ const [aiTarget, setAiTarget] = (0, import_react11.useState)("auto");
1683
1851
  const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
1684
1852
  const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
1685
1853
  const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
@@ -1742,18 +1910,18 @@ var ImageEditor = ({
1742
1910
  setIsInpainting(false);
1743
1911
  }
1744
1912
  };
1745
- const [activeColor, setActiveColor] = (0, import_react10.useState)("#ef4444");
1746
- const [strokeWidth, setStrokeWidth] = (0, import_react10.useState)(3);
1747
- const [fontSize, setFontSize] = (0, import_react10.useState)(24);
1748
- const [textInput, setTextInput] = (0, import_react10.useState)("");
1749
- const draftAnnotationRef = (0, import_react10.useRef)(null);
1750
- const draftCropRef = (0, import_react10.useRef)(null);
1751
- const cropDragInfoRef = (0, import_react10.useRef)(null);
1752
- const annotationDragInfoRef = (0, import_react10.useRef)(null);
1753
- const isDrawingRef = (0, import_react10.useRef)(false);
1754
- const currentPathRef = (0, import_react10.useRef)([]);
1755
- const dragStartPointRef = (0, import_react10.useRef)(null);
1756
- const renderCanvas = (0, import_react10.useCallback)(
1913
+ const [activeColor, setActiveColor] = (0, import_react11.useState)("#ef4444");
1914
+ const [strokeWidth, setStrokeWidth] = (0, import_react11.useState)(3);
1915
+ const [fontSize, setFontSize] = (0, import_react11.useState)(24);
1916
+ const [textInput, setTextInput] = (0, import_react11.useState)("");
1917
+ const draftAnnotationRef = (0, import_react11.useRef)(null);
1918
+ const draftCropRef = (0, import_react11.useRef)(null);
1919
+ const cropDragInfoRef = (0, import_react11.useRef)(null);
1920
+ const annotationDragInfoRef = (0, import_react11.useRef)(null);
1921
+ const isDrawingRef = (0, import_react11.useRef)(false);
1922
+ const currentPathRef = (0, import_react11.useRef)([]);
1923
+ const dragStartPointRef = (0, import_react11.useRef)(null);
1924
+ const renderCanvas = (0, import_react11.useCallback)(
1757
1925
  async (draftAnnotation, draftCrop) => {
1758
1926
  const canvas = canvasRef.current;
1759
1927
  const container = containerRef.current;
@@ -1769,12 +1937,64 @@ var ImageEditor = ({
1769
1937
  draftAnnotation: draftAnnotation !== void 0 ? draftAnnotation : draftAnnotationRef.current,
1770
1938
  draftCrop: draftCrop !== void 0 ? draftCrop : draftCropRef.current,
1771
1939
  draftSelectionPath: selectionDraftRef.current,
1772
- brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null
1940
+ brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" && !transformTool.active ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null,
1941
+ freeTransform: transformTool.overlay()
1773
1942
  });
1774
1943
  },
1775
- [controller, activeTab]
1944
+ [controller, activeTab, transformTool]
1776
1945
  );
1777
- (0, import_react10.useEffect)(() => {
1946
+ (0, import_react11.useEffect)(() => transformTool.subscribe(() => {
1947
+ setTransformTick((n) => n + 1);
1948
+ void renderCanvas();
1949
+ }), [transformTool, renderCanvas]);
1950
+ const transformPoint = (e) => {
1951
+ const canvas = canvasRef.current;
1952
+ const rect = canvas.getBoundingClientRect();
1953
+ const sx = rect.width > 0 ? canvas.width / rect.width : 1;
1954
+ const sy = rect.height > 0 ? canvas.height / rect.height : 1;
1955
+ const s = controller.getState();
1956
+ const cropping = activeTab === "crop";
1957
+ const projection = (0, import_image_editor12.getViewportProjection)(s, canvas.width, canvas.height, cropping);
1958
+ const pt = (0, import_image_editor12.canvasToImagePoint)({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
1959
+ transformTool.setView(projection.scale);
1960
+ return { pt, tolerance: 6 / (projection.scale || 1) };
1961
+ };
1962
+ const handleTransformPointerDown = (e) => {
1963
+ if (!transformTool.active) return false;
1964
+ if (e.button !== 0) return true;
1965
+ e.preventDefault();
1966
+ try {
1967
+ e.currentTarget.setPointerCapture?.(e.pointerId);
1968
+ } catch {
1969
+ }
1970
+ const { pt, tolerance } = transformPoint(e);
1971
+ transformTool.down(pt, tolerance);
1972
+ return true;
1973
+ };
1974
+ const handleTransformPointerMove = (e) => {
1975
+ if (!transformTool.active) return false;
1976
+ const { pt, tolerance } = transformPoint(e);
1977
+ if (e.buttons & 1) transformTool.move(pt, e);
1978
+ else {
1979
+ const over = transformTool.hit(pt, tolerance);
1980
+ setTransformCursor(transformTool.cursor(over));
1981
+ }
1982
+ return true;
1983
+ };
1984
+ const handleTransformPointerUp = () => {
1985
+ if (!transformTool.active) return false;
1986
+ transformTool.up();
1987
+ return true;
1988
+ };
1989
+ (0, import_react11.useEffect)(() => {
1990
+ if (typeof window === "undefined") return;
1991
+ const onKey = (e) => {
1992
+ if (transformTool.key(e)) e.preventDefault();
1993
+ };
1994
+ window.addEventListener("keydown", onKey);
1995
+ return () => window.removeEventListener("keydown", onKey);
1996
+ }, [transformTool]);
1997
+ (0, import_react11.useEffect)(() => {
1778
1998
  const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
1779
1999
  const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
1780
2000
  const animId = raf(() => {
@@ -1782,12 +2002,12 @@ var ImageEditor = ({
1782
2002
  });
1783
2003
  return () => caf(animId);
1784
2004
  }, [renderCanvas, state]);
1785
- (0, import_react10.useEffect)(() => {
2005
+ (0, import_react11.useEffect)(() => {
1786
2006
  if (activeTab === "crop" && editor.state.activeTool !== "crop") {
1787
2007
  editor.setTool("crop");
1788
2008
  }
1789
2009
  }, [activeTab, editor]);
1790
- (0, import_react10.useEffect)(() => {
2010
+ (0, import_react11.useEffect)(() => {
1791
2011
  const container = containerRef.current;
1792
2012
  if (!container) return;
1793
2013
  if (typeof ResizeObserver !== "undefined") {
@@ -1823,11 +2043,12 @@ var ImageEditor = ({
1823
2043
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
1824
2044
  const s = controller.getState();
1825
2045
  return list.map((ev) => ({
1826
- ...(0, import_image_editor11.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
1827
- pressure: (0, import_image_editor11.pointerPressure)(ev)
2046
+ ...(0, import_image_editor12.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
2047
+ pressure: (0, import_image_editor12.pointerPressure)(ev)
1828
2048
  }));
1829
2049
  };
1830
2050
  const handlePaintPointerDown = (e) => {
2051
+ if (handleTransformPointerDown(e)) return;
1831
2052
  if (activeTab !== "paint" || e.button !== 0) return;
1832
2053
  e.preventDefault();
1833
2054
  try {
@@ -1838,6 +2059,7 @@ var ImageEditor = ({
1838
2059
  setPaintError(paintGestureRef.current.down(first));
1839
2060
  };
1840
2061
  const handlePaintPointerMove = (e) => {
2062
+ if (handleTransformPointerMove(e)) return;
1841
2063
  if (activeTab !== "paint") return;
1842
2064
  const samples = paintSamples(e);
1843
2065
  brushCursorRef.current = samples[samples.length - 1] ?? null;
@@ -1845,6 +2067,7 @@ var ImageEditor = ({
1845
2067
  else void renderCanvas();
1846
2068
  };
1847
2069
  const handlePaintPointerUp = () => {
2070
+ if (handleTransformPointerUp()) return;
1848
2071
  if (activeTab !== "paint") return;
1849
2072
  const g = paintGestureRef.current;
1850
2073
  if (g.active) {
@@ -1852,21 +2075,21 @@ var ImageEditor = ({
1852
2075
  if (g.error) setPaintError(g.error);
1853
2076
  }
1854
2077
  };
1855
- (0, import_react10.useEffect)(() => {
2078
+ (0, import_react11.useEffect)(() => {
1856
2079
  if (activeTab !== "paint" || typeof window === "undefined") return;
1857
2080
  const onKey = (e) => {
1858
- if ((0, import_image_editor11.handlePaintShortcut)(controller, e)) e.preventDefault();
2081
+ if ((0, import_image_editor12.handlePaintShortcut)(controller, e)) e.preventDefault();
1859
2082
  };
1860
2083
  window.addEventListener("keydown", onKey);
1861
2084
  return () => window.removeEventListener("keydown", onKey);
1862
2085
  }, [activeTab, controller]);
1863
2086
  const handleMouseDown = (e) => {
1864
2087
  const canvas = canvasRef.current;
1865
- if (!canvas) return;
2088
+ if (!canvas || transformTool.active) return;
1866
2089
  const canvasPt = getCanvasEventPoint(e);
1867
2090
  if (activeTab === "select") {
1868
2091
  const gesture = selectionGestureRef.current;
1869
- const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2092
+ const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
1870
2093
  void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
1871
2094
  return;
1872
2095
  }
@@ -1877,8 +2100,8 @@ var ImageEditor = ({
1877
2100
  width: state.imageDimensions.width,
1878
2101
  height: state.imageDimensions.height
1879
2102
  };
1880
- const handle = (0, import_image_editor11.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
1881
- const startImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
2103
+ const handle = (0, import_image_editor12.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
2104
+ const startImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
1882
2105
  if (handle) {
1883
2106
  cropDragInfoRef.current = {
1884
2107
  handle,
@@ -1897,12 +2120,12 @@ var ImageEditor = ({
1897
2120
  return;
1898
2121
  }
1899
2122
  if (activeTab === "annotate") {
1900
- const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2123
+ const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
1901
2124
  dragStartPointRef.current = imgPt;
1902
2125
  if (state.activeTool === "select") {
1903
2126
  for (let i = state.annotations.length - 1; i >= 0; i--) {
1904
2127
  const ann = state.annotations[i];
1905
- if ((0, import_image_editor11.hitTestAnnotation)(imgPt, ann)) {
2128
+ if ((0, import_image_editor12.hitTestAnnotation)(imgPt, ann)) {
1906
2129
  editor.selectAnnotation(ann.id);
1907
2130
  annotationDragInfoRef.current = {
1908
2131
  annId: ann.id,
@@ -1934,11 +2157,11 @@ var ImageEditor = ({
1934
2157
  };
1935
2158
  const handleMouseMove = (e) => {
1936
2159
  const canvas = canvasRef.current;
1937
- if (!canvas) return;
2160
+ if (!canvas || transformTool.active) return;
1938
2161
  const canvasPt = getCanvasEventPoint(e);
1939
2162
  if (activeTab === "select") {
1940
2163
  const gesture = selectionGestureRef.current;
1941
- if (gesture.active && gesture.move((0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
2164
+ if (gesture.active && gesture.move((0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
1942
2165
  selectionDraftRef.current = gesture.draftPath;
1943
2166
  renderCanvas();
1944
2167
  }
@@ -1947,7 +2170,7 @@ var ImageEditor = ({
1947
2170
  if (activeTab === "crop") {
1948
2171
  const drag = cropDragInfoRef.current;
1949
2172
  if (drag) {
1950
- const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
2173
+ const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
1951
2174
  let newCrop;
1952
2175
  if (drag.handle === "new") {
1953
2176
  const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
@@ -1961,7 +2184,7 @@ var ImageEditor = ({
1961
2184
  height: Math.round(Math.max(20, maxY - minY))
1962
2185
  };
1963
2186
  } else {
1964
- newCrop = (0, import_image_editor11.calculateCropDrag)(
2187
+ newCrop = (0, import_image_editor12.calculateCropDrag)(
1965
2188
  drag.startCrop,
1966
2189
  drag.handle,
1967
2190
  drag.startImgPt,
@@ -1981,15 +2204,15 @@ var ImageEditor = ({
1981
2204
  width: state.imageDimensions.width,
1982
2205
  height: state.imageDimensions.height
1983
2206
  };
1984
- const handle = (0, import_image_editor11.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
1985
- canvas.style.cursor = (0, import_image_editor11.getCropCursor)(handle, state.transform);
2207
+ const handle = (0, import_image_editor12.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
2208
+ canvas.style.cursor = (0, import_image_editor12.getCropCursor)(handle, state.transform);
1986
2209
  }
1987
2210
  return;
1988
2211
  }
1989
2212
  if (activeTab === "annotate") {
1990
2213
  if (annotationDragInfoRef.current) {
1991
2214
  const drag = annotationDragInfoRef.current;
1992
- const currentImgPt2 = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2215
+ const currentImgPt2 = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
1993
2216
  const dx = currentImgPt2.x - drag.startImgPt.x;
1994
2217
  const dy = currentImgPt2.y - drag.startImgPt.y;
1995
2218
  editor.updateAnnotation(drag.annId, {
@@ -2001,10 +2224,10 @@ var ImageEditor = ({
2001
2224
  const startPt = dragStartPointRef.current;
2002
2225
  if (!startPt) {
2003
2226
  if (state.activeTool === "select") {
2004
- const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2227
+ const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2005
2228
  let hovered = false;
2006
2229
  for (let i = state.annotations.length - 1; i >= 0; i--) {
2007
- if ((0, import_image_editor11.hitTestAnnotation)(imgPt, state.annotations[i])) {
2230
+ if ((0, import_image_editor12.hitTestAnnotation)(imgPt, state.annotations[i])) {
2008
2231
  hovered = true;
2009
2232
  break;
2010
2233
  }
@@ -2015,7 +2238,7 @@ var ImageEditor = ({
2015
2238
  }
2016
2239
  return;
2017
2240
  }
2018
- const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2241
+ const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2019
2242
  if (state.activeTool === "pen" && isDrawingRef.current) {
2020
2243
  currentPathRef.current.push(currentImgPt);
2021
2244
  const draft = {
@@ -2090,12 +2313,12 @@ var ImageEditor = ({
2090
2313
  };
2091
2314
  const handleMouseUp = (e) => {
2092
2315
  const canvas = canvasRef.current;
2093
- if (!canvas) return;
2316
+ if (!canvas || transformTool.active) return;
2094
2317
  const canvasPt = getCanvasEventPoint(e);
2095
2318
  if (activeTab === "select") {
2096
2319
  const gesture = selectionGestureRef.current;
2097
2320
  if (gesture.active) {
2098
- gesture.end((0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
2321
+ gesture.end((0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
2099
2322
  selectionDraftRef.current = null;
2100
2323
  renderCanvas();
2101
2324
  }
@@ -2119,7 +2342,7 @@ var ImageEditor = ({
2119
2342
  }
2120
2343
  const startPt = dragStartPointRef.current;
2121
2344
  if (startPt) {
2122
- const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2345
+ const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2123
2346
  if (state.activeTool === "pen" && isDrawingRef.current) {
2124
2347
  if (currentPathRef.current.length > 1) {
2125
2348
  editor.addAnnotation({
@@ -2215,15 +2438,15 @@ var ImageEditor = ({
2215
2438
  link.click();
2216
2439
  }
2217
2440
  };
2218
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2441
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2219
2442
  "div",
2220
2443
  {
2221
2444
  className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
2222
2445
  style,
2223
2446
  children: [
2224
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-wrap items-center justify-between px-4 py-3 bg-slate-950/80 border-b border-slate-800 gap-3", children: [
2225
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
2226
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2447
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-wrap items-center justify-between px-4 py-3 bg-slate-950/80 border-b border-slate-800 gap-3", children: [
2448
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
2449
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2227
2450
  "button",
2228
2451
  {
2229
2452
  type: "button",
@@ -2235,7 +2458,7 @@ var ImageEditor = ({
2235
2458
  children: "Transform & Crop"
2236
2459
  }
2237
2460
  ),
2238
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2461
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2239
2462
  "button",
2240
2463
  {
2241
2464
  type: "button",
@@ -2247,7 +2470,7 @@ var ImageEditor = ({
2247
2470
  children: "Adjustments"
2248
2471
  }
2249
2472
  ),
2250
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2473
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2251
2474
  "button",
2252
2475
  {
2253
2476
  type: "button",
@@ -2259,7 +2482,7 @@ var ImageEditor = ({
2259
2482
  children: "Layers"
2260
2483
  }
2261
2484
  ),
2262
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2485
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2263
2486
  "button",
2264
2487
  {
2265
2488
  type: "button",
@@ -2271,7 +2494,7 @@ var ImageEditor = ({
2271
2494
  children: "Paint"
2272
2495
  }
2273
2496
  ),
2274
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2497
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2275
2498
  "button",
2276
2499
  {
2277
2500
  type: "button",
@@ -2283,7 +2506,7 @@ var ImageEditor = ({
2283
2506
  children: "Select & Mask"
2284
2507
  }
2285
2508
  ),
2286
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2509
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2287
2510
  "button",
2288
2511
  {
2289
2512
  type: "button",
@@ -2295,7 +2518,7 @@ var ImageEditor = ({
2295
2518
  children: "Annotations"
2296
2519
  }
2297
2520
  ),
2298
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2521
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2299
2522
  "button",
2300
2523
  {
2301
2524
  type: "button",
@@ -2307,7 +2530,7 @@ var ImageEditor = ({
2307
2530
  children: "Depth Mask"
2308
2531
  }
2309
2532
  ),
2310
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2533
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2311
2534
  "button",
2312
2535
  {
2313
2536
  type: "button",
@@ -2317,14 +2540,14 @@ var ImageEditor = ({
2317
2540
  },
2318
2541
  className: `px-3 py-1.5 rounded-md font-medium transition-colors flex items-center gap-1.5 ${activeTab === "ai" ? "bg-indigo-600 text-white shadow" : "text-slate-400 hover:text-slate-200"}`,
2319
2542
  children: [
2320
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
2543
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
2321
2544
  "AI Tools"
2322
2545
  ]
2323
2546
  }
2324
2547
  )
2325
2548
  ] }),
2326
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
2327
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2549
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
2550
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2328
2551
  "button",
2329
2552
  {
2330
2553
  type: "button",
@@ -2335,7 +2558,7 @@ var ImageEditor = ({
2335
2558
  children: "\u21A9"
2336
2559
  }
2337
2560
  ),
2338
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2561
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2339
2562
  "button",
2340
2563
  {
2341
2564
  type: "button",
@@ -2346,7 +2569,7 @@ var ImageEditor = ({
2346
2569
  children: "\u21AA"
2347
2570
  }
2348
2571
  ),
2349
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2572
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2350
2573
  "button",
2351
2574
  {
2352
2575
  type: "button",
@@ -2355,8 +2578,8 @@ var ImageEditor = ({
2355
2578
  children: "Reset"
2356
2579
  }
2357
2580
  ),
2358
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2359
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2581
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2582
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2360
2583
  "button",
2361
2584
  {
2362
2585
  type: "button",
@@ -2366,11 +2589,11 @@ var ImageEditor = ({
2366
2589
  children: "-"
2367
2590
  }
2368
2591
  ),
2369
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
2592
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
2370
2593
  Math.round(state.zoom * 100),
2371
2594
  "%"
2372
2595
  ] }),
2373
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2596
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2374
2597
  "button",
2375
2598
  {
2376
2599
  type: "button",
@@ -2380,8 +2603,8 @@ var ImageEditor = ({
2380
2603
  children: "+"
2381
2604
  }
2382
2605
  ),
2383
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2384
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2606
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2607
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2385
2608
  "button",
2386
2609
  {
2387
2610
  type: "button",
@@ -2392,7 +2615,7 @@ var ImageEditor = ({
2392
2615
  children: "Hold Compare"
2393
2616
  }
2394
2617
  ),
2395
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2618
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2396
2619
  "button",
2397
2620
  {
2398
2621
  type: "button",
@@ -2403,13 +2626,15 @@ var ImageEditor = ({
2403
2626
  )
2404
2627
  ] })
2405
2628
  ] }),
2406
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
2407
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2629
+ transformTool.active && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
2630
+ !transformTool.active && transformTool.error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "alert", className: "border-b border-rose-900 bg-rose-950/80 px-4 py-1.5 text-xs text-rose-200", children: transformTool.error }),
2631
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
2632
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2408
2633
  "div",
2409
2634
  {
2410
2635
  ref: containerRef,
2411
2636
  className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
2412
- children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2637
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2413
2638
  "canvas",
2414
2639
  {
2415
2640
  ref: canvasRef,
@@ -2422,16 +2647,17 @@ var ImageEditor = ({
2422
2647
  onPointerUp: handlePaintPointerUp,
2423
2648
  onPointerCancel: () => paintGestureRef.current?.cancel(),
2424
2649
  "data-testid": "image-editor-canvas",
2425
- className: `absolute inset-0 w-full h-full block ${activeTab === "paint" ? "touch-none cursor-crosshair" : ""}`
2650
+ style: transformTool.active ? { cursor: transformCursor } : void 0,
2651
+ className: `absolute inset-0 w-full h-full block ${transformTool.active ? "touch-none" : activeTab === "paint" ? "touch-none cursor-crosshair" : ""}`
2426
2652
  }
2427
2653
  )
2428
2654
  }
2429
2655
  ),
2430
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "w-full md:w-80 bg-slate-900/90 border-t md:border-t-0 md:border-l border-slate-800 p-4 overflow-y-auto h-auto md:h-full md:max-h-[560px]", children: [
2431
- activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
2432
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
2433
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
2434
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2656
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "w-full md:w-80 bg-slate-900/90 border-t md:border-t-0 md:border-l border-slate-800 p-4 overflow-y-auto h-auto md:h-full md:max-h-[560px]", children: [
2657
+ activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
2658
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
2659
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
2660
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2435
2661
  "button",
2436
2662
  {
2437
2663
  type: "button",
@@ -2443,7 +2669,7 @@ var ImageEditor = ({
2443
2669
  children: "Freeform"
2444
2670
  }
2445
2671
  ),
2446
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2672
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2447
2673
  "button",
2448
2674
  {
2449
2675
  type: "button",
@@ -2455,7 +2681,7 @@ var ImageEditor = ({
2455
2681
  children: "1:1 Square"
2456
2682
  }
2457
2683
  ),
2458
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2684
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2459
2685
  "button",
2460
2686
  {
2461
2687
  type: "button",
@@ -2467,7 +2693,7 @@ var ImageEditor = ({
2467
2693
  children: "4:3 Standard"
2468
2694
  }
2469
2695
  ),
2470
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2696
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2471
2697
  "button",
2472
2698
  {
2473
2699
  type: "button",
@@ -2479,7 +2705,7 @@ var ImageEditor = ({
2479
2705
  children: "16:9 Wide"
2480
2706
  }
2481
2707
  ),
2482
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2708
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2483
2709
  "button",
2484
2710
  {
2485
2711
  type: "button",
@@ -2491,7 +2717,7 @@ var ImageEditor = ({
2491
2717
  children: "3:2 Photo"
2492
2718
  }
2493
2719
  ),
2494
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2720
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2495
2721
  "button",
2496
2722
  {
2497
2723
  type: "button",
@@ -2504,10 +2730,10 @@ var ImageEditor = ({
2504
2730
  }
2505
2731
  )
2506
2732
  ] }),
2507
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
2508
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
2509
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
2510
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2733
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
2734
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
2735
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
2736
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2511
2737
  "button",
2512
2738
  {
2513
2739
  type: "button",
@@ -2516,7 +2742,7 @@ var ImageEditor = ({
2516
2742
  children: "Rotate -90\xB0"
2517
2743
  }
2518
2744
  ),
2519
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2745
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2520
2746
  "button",
2521
2747
  {
2522
2748
  type: "button",
@@ -2525,7 +2751,7 @@ var ImageEditor = ({
2525
2751
  children: "Rotate +90\xB0"
2526
2752
  }
2527
2753
  ),
2528
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2754
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2529
2755
  "button",
2530
2756
  {
2531
2757
  type: "button",
@@ -2534,7 +2760,7 @@ var ImageEditor = ({
2534
2760
  children: "Flip Horizontal"
2535
2761
  }
2536
2762
  ),
2537
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2763
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2538
2764
  "button",
2539
2765
  {
2540
2766
  type: "button",
@@ -2545,10 +2771,10 @@ var ImageEditor = ({
2545
2771
  )
2546
2772
  ] })
2547
2773
  ] }),
2548
- activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
2549
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
2550
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
2551
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2774
+ activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
2775
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between", children: [
2776
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
2777
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2552
2778
  "button",
2553
2779
  {
2554
2780
  type: "button",
@@ -2558,25 +2784,25 @@ var ImageEditor = ({
2558
2784
  }
2559
2785
  )
2560
2786
  ] }),
2561
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Histogram, { histogram: editor.histogram }),
2562
- import_image_editor11.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react10.default.Fragment, { children: [
2563
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2787
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Histogram, { histogram: editor.histogram }),
2788
+ import_image_editor12.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_react11.default.Fragment, { children: [
2789
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2564
2790
  ControlSlider,
2565
2791
  {
2566
2792
  spec,
2567
- value: (0, import_image_editor11.readAdjustmentControls)(state.adjustments)[spec.id],
2793
+ value: (0, import_image_editor12.readAdjustmentControls)(state.adjustments)[spec.id],
2568
2794
  disabled: spec.requiresProcess !== void 0 && legacyProcess,
2569
2795
  onChange: (v) => editor.setAdjustments({ [spec.id]: v })
2570
2796
  }
2571
2797
  ),
2572
- spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2798
+ spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2573
2799
  "div",
2574
2800
  {
2575
2801
  className: "flex items-center justify-between gap-2 rounded border border-amber-500/30 bg-amber-500/10 px-2 py-1.5 text-[10px] text-amber-200",
2576
2802
  "data-testid": "image-editor-process-notice",
2577
2803
  children: [
2578
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
2579
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2804
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
2805
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2580
2806
  "button",
2581
2807
  {
2582
2808
  type: "button",
@@ -2589,7 +2815,7 @@ var ImageEditor = ({
2589
2815
  }
2590
2816
  )
2591
2817
  ] }, spec.id)),
2592
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2818
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2593
2819
  AdjustmentLayersPanel,
2594
2820
  {
2595
2821
  controller,
@@ -2598,19 +2824,41 @@ var ImageEditor = ({
2598
2824
  }
2599
2825
  ) })
2600
2826
  ] }),
2601
- activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
2602
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
2603
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(LayersPanel, { controller })
2827
+ activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
2828
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
2829
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2830
+ "button",
2831
+ {
2832
+ type: "button",
2833
+ title: "Edit \u203A Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer",
2834
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
2835
+ disabled: transformTool.active,
2836
+ onClick: () => transformTool.begin(),
2837
+ children: "Free Transform"
2838
+ }
2839
+ ),
2840
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(LayersPanel, { controller })
2604
2841
  ] }),
2605
- activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
2606
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
2607
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(BrushOptionsBar, { controller }),
2608
- paintError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
2609
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(LayersPanel, { controller }) })
2842
+ activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
2843
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
2844
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(BrushOptionsBar, { controller }),
2845
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2846
+ "button",
2847
+ {
2848
+ type: "button",
2849
+ title: "Edit \u203A Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer",
2850
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start",
2851
+ disabled: transformTool.active,
2852
+ onClick: () => transformTool.begin(),
2853
+ children: "Free Transform"
2854
+ }
2855
+ ),
2856
+ paintError && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
2857
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(LayersPanel, { controller }) })
2610
2858
  ] }),
2611
- activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
2612
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
2613
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2859
+ activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
2860
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
2861
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2614
2862
  "button",
2615
2863
  {
2616
2864
  type: "button",
@@ -2620,9 +2868,9 @@ var ImageEditor = ({
2620
2868
  },
2621
2869
  t
2622
2870
  )) }),
2623
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
2624
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "text-slate-400", children: "Color:" }),
2625
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2871
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
2872
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("label", { className: "text-slate-400", children: "Color:" }),
2873
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2626
2874
  "input",
2627
2875
  {
2628
2876
  type: "color",
@@ -2631,15 +2879,15 @@ var ImageEditor = ({
2631
2879
  className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
2632
2880
  }
2633
2881
  ),
2634
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex-1 ml-2", children: [
2635
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
2636
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Width:" }),
2637
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-mono", children: [
2882
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex-1 ml-2", children: [
2883
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
2884
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Width:" }),
2885
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "font-mono", children: [
2638
2886
  strokeWidth,
2639
2887
  "px"
2640
2888
  ] })
2641
2889
  ] }),
2642
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2890
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2643
2891
  "input",
2644
2892
  {
2645
2893
  type: "range",
@@ -2652,10 +2900,10 @@ var ImageEditor = ({
2652
2900
  )
2653
2901
  ] })
2654
2902
  ] }),
2655
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
2656
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
2657
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex gap-2", children: [
2658
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2903
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
2904
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
2905
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex gap-2", children: [
2906
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2659
2907
  "input",
2660
2908
  {
2661
2909
  type: "text",
@@ -2666,7 +2914,7 @@ var ImageEditor = ({
2666
2914
  className: "flex-1 bg-slate-950 border border-slate-700 rounded-lg px-2.5 py-1.5 text-xs text-slate-100 placeholder-slate-500 focus:outline-none focus:border-indigo-500"
2667
2915
  }
2668
2916
  ),
2669
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2917
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2670
2918
  "button",
2671
2919
  {
2672
2920
  type: "button",
@@ -2676,14 +2924,14 @@ var ImageEditor = ({
2676
2924
  }
2677
2925
  )
2678
2926
  ] }),
2679
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
2680
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Font Size:" }),
2681
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-mono", children: [
2927
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
2928
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Font Size:" }),
2929
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "font-mono", children: [
2682
2930
  fontSize,
2683
2931
  "px"
2684
2932
  ] })
2685
2933
  ] }),
2686
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2934
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2687
2935
  "input",
2688
2936
  {
2689
2937
  type: "range",
@@ -2694,14 +2942,14 @@ var ImageEditor = ({
2694
2942
  className: "w-full accent-indigo-500"
2695
2943
  }
2696
2944
  ),
2697
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
2698
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
2699
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-slate-400", children: [
2945
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
2946
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between", children: [
2947
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "text-slate-400", children: [
2700
2948
  "Layers (",
2701
2949
  state.annotations.length,
2702
2950
  ")"
2703
2951
  ] }),
2704
- state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2952
+ state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2705
2953
  "button",
2706
2954
  {
2707
2955
  type: "button",
@@ -2710,7 +2958,7 @@ var ImageEditor = ({
2710
2958
  children: "Delete Selected"
2711
2959
  }
2712
2960
  ),
2713
- state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2961
+ state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2714
2962
  "button",
2715
2963
  {
2716
2964
  type: "button",
@@ -2721,10 +2969,10 @@ var ImageEditor = ({
2721
2969
  )
2722
2970
  ] })
2723
2971
  ] }),
2724
- activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
2725
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
2726
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
2727
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2972
+ activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
2973
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between", children: [
2974
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
2975
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2728
2976
  "button",
2729
2977
  {
2730
2978
  type: "button",
@@ -2734,8 +2982,8 @@ var ImageEditor = ({
2734
2982
  }
2735
2983
  )
2736
2984
  ] }),
2737
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
2738
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2985
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
2986
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2739
2987
  "input",
2740
2988
  {
2741
2989
  type: "checkbox",
@@ -2744,12 +2992,12 @@ var ImageEditor = ({
2744
2992
  className: "rounded accent-indigo-500"
2745
2993
  }
2746
2994
  ),
2747
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Enable Depth / Alpha Mask" })
2995
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Enable Depth / Alpha Mask" })
2748
2996
  ] }),
2749
- state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2750
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
2751
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
2752
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2997
+ state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
2998
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2999
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
3000
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2753
3001
  "input",
2754
3002
  {
2755
3003
  type: "text",
@@ -2760,8 +3008,8 @@ var ImageEditor = ({
2760
3008
  }
2761
3009
  )
2762
3010
  ] }),
2763
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex gap-2", children: [
2764
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3011
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex gap-2", children: [
3012
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2765
3013
  "button",
2766
3014
  {
2767
3015
  type: "button",
@@ -2770,7 +3018,7 @@ var ImageEditor = ({
2770
3018
  children: "Threshold Mode"
2771
3019
  }
2772
3020
  ),
2773
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3021
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2774
3022
  "button",
2775
3023
  {
2776
3024
  type: "button",
@@ -2780,12 +3028,12 @@ var ImageEditor = ({
2780
3028
  }
2781
3029
  )
2782
3030
  ] }),
2783
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
2784
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
2785
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Depth Start (Lower):" }),
2786
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
3031
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
3032
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3033
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Depth Start (Lower):" }),
3034
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
2787
3035
  ] }),
2788
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3036
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2789
3037
  "input",
2790
3038
  {
2791
3039
  type: "range",
@@ -2799,12 +3047,12 @@ var ImageEditor = ({
2799
3047
  }
2800
3048
  )
2801
3049
  ] }),
2802
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
2803
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
2804
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Depth Stop (Upper):" }),
2805
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
3050
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
3051
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3052
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Depth Stop (Upper):" }),
3053
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
2806
3054
  ] }),
2807
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3055
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2808
3056
  "input",
2809
3057
  {
2810
3058
  type: "range",
@@ -2818,12 +3066,12 @@ var ImageEditor = ({
2818
3066
  }
2819
3067
  )
2820
3068
  ] }),
2821
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
2822
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
2823
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Softness:" }),
2824
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
3069
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
3070
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3071
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Softness:" }),
3072
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
2825
3073
  ] }),
2826
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3074
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2827
3075
  "input",
2828
3076
  {
2829
3077
  type: "range",
@@ -2835,8 +3083,8 @@ var ImageEditor = ({
2835
3083
  }
2836
3084
  )
2837
3085
  ] }),
2838
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
2839
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3086
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
3087
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2840
3088
  "input",
2841
3089
  {
2842
3090
  type: "checkbox",
@@ -2845,12 +3093,12 @@ var ImageEditor = ({
2845
3093
  className: "rounded accent-indigo-500"
2846
3094
  }
2847
3095
  ),
2848
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Invert Mask" })
3096
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Invert Mask" })
2849
3097
  ] })
2850
3098
  ] })
2851
3099
  ] }),
2852
- activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
2853
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3100
+ activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
3101
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2854
3102
  SelectionOptionsBar,
2855
3103
  {
2856
3104
  controller,
@@ -2860,13 +3108,37 @@ var ImageEditor = ({
2860
3108
  quickMask: Boolean(state.quickMask)
2861
3109
  }
2862
3110
  ),
2863
- selectionError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
2864
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
3111
+ selectionError && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
3112
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex gap-1", children: [
3113
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3114
+ "button",
3115
+ {
3116
+ type: "button",
3117
+ title: "Select \u203A Transform Selection: the outline only",
3118
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
3119
+ disabled: transformTool.active,
3120
+ onClick: () => transformTool.begin({ content: "selection-outline" }),
3121
+ children: "Transform Selection"
3122
+ }
3123
+ ),
3124
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3125
+ "button",
3126
+ {
3127
+ type: "button",
3128
+ title: "Edit \u203A Free Transform: the selected pixels of the active layer",
3129
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
3130
+ disabled: transformTool.active,
3131
+ onClick: () => transformTool.begin({ content: "selection" }),
3132
+ children: "Free Transform Pixels"
3133
+ }
3134
+ )
3135
+ ] }),
3136
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
2865
3137
  ] }),
2866
- activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
2867
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
2868
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Results go to" }),
2869
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3138
+ activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
3139
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
3140
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Results go to" }),
3141
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2870
3142
  "select",
2871
3143
  {
2872
3144
  "aria-label": "AI result target",
@@ -2874,54 +3146,54 @@ var ImageEditor = ({
2874
3146
  onChange: (e) => setAiTarget(e.target.value),
2875
3147
  className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
2876
3148
  children: [
2877
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
2878
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
2879
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "replace", children: "Replace image" })
3149
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
3150
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
3151
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "replace", children: "Replace image" })
2880
3152
  ]
2881
3153
  }
2882
3154
  )
2883
3155
  ] }),
2884
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
2885
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
2886
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
2887
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" }) }),
3156
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3157
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between", children: [
3158
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3159
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" }) }),
2888
3160
  "Background Removal"
2889
3161
  ] }),
2890
- isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse", children: "Removing..." })
3162
+ isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse", children: "Removing..." })
2891
3163
  ] }),
2892
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
2893
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3164
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
3165
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2894
3166
  "button",
2895
3167
  {
2896
3168
  type: "button",
2897
3169
  onClick: handleRemoveBackground,
2898
3170
  disabled: isRemovingBg || isInpainting,
2899
3171
  className: "mt-1 px-3 py-2 rounded-lg bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2",
2900
- children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2901
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3172
+ children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
3173
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
2902
3174
  "Removing Background..."
2903
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2904
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
3175
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
3176
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
2905
3177
  "Remove Background"
2906
3178
  ] })
2907
3179
  }
2908
3180
  )
2909
3181
  ] }),
2910
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
2911
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
2912
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
2913
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
2914
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "m21.64 3.64-1.28-1.28a1.2 1.2 0 0 0-1.7 0l-9.72 9.72-1.94 4.86 4.86-1.94 9.72-9.72a1.2 1.2 0 0 0 .06-1.64z" }),
2915
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "m14 7 3 3" })
3182
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3183
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center justify-between", children: [
3184
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3185
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
3186
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "m21.64 3.64-1.28-1.28a1.2 1.2 0 0 0-1.7 0l-9.72 9.72-1.94 4.86 4.86-1.94 9.72-9.72a1.2 1.2 0 0 0 .06-1.64z" }),
3187
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "m14 7 3 3" })
2916
3188
  ] }),
2917
3189
  "Generative Inpainting"
2918
3190
  ] }),
2919
- isInpainting && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse", children: "Inpainting..." })
3191
+ isInpainting && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse", children: "Inpainting..." })
2920
3192
  ] }),
2921
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
2922
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-1", children: [
2923
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
2924
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3193
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
3194
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-1", children: [
3195
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
3196
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2925
3197
  "textarea",
2926
3198
  {
2927
3199
  id: "ai-inpaint-prompt-react",
@@ -2933,10 +3205,10 @@ var ImageEditor = ({
2933
3205
  }
2934
3206
  )
2935
3207
  ] }),
2936
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-1", children: [
2937
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
2938
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
2939
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3208
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-1", children: [
3209
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
3210
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
3211
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2940
3212
  "button",
2941
3213
  {
2942
3214
  type: "button",
@@ -2949,7 +3221,7 @@ var ImageEditor = ({
2949
3221
  ]
2950
3222
  }
2951
3223
  ),
2952
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
3224
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2953
3225
  "button",
2954
3226
  {
2955
3227
  type: "button",
@@ -2964,25 +3236,25 @@ var ImageEditor = ({
2964
3236
  )
2965
3237
  ] })
2966
3238
  ] }),
2967
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3239
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2968
3240
  "button",
2969
3241
  {
2970
3242
  type: "button",
2971
3243
  onClick: handleInpaint,
2972
3244
  disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
2973
3245
  className: "mt-1 px-3 py-2 rounded-lg bg-purple-600 hover:bg-purple-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2",
2974
- children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2975
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3246
+ children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
3247
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
2976
3248
  "Generating Inpaint..."
2977
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
2978
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
3249
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
3250
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
2979
3251
  "Apply Inpainting"
2980
3252
  ] })
2981
3253
  }
2982
3254
  )
2983
3255
  ] }),
2984
- aiError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
2985
- aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
3256
+ aiError && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
3257
+ aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
2986
3258
  ] })
2987
3259
  ] })
2988
3260
  ] })
@@ -2996,6 +3268,7 @@ var ImageEditor = ({
2996
3268
  BrushOptionsBar,
2997
3269
  ControlSlider,
2998
3270
  CurvesEditor,
3271
+ FreeTransformOptionsBar,
2999
3272
  Histogram,
3000
3273
  ImageEditor,
3001
3274
  LayerEffectsPanel,