@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.
@@ -159,7 +159,7 @@ function useImageEditor(options = {}) {
159
159
  }
160
160
 
161
161
  // src/image-editor/ImageEditor.tsx
162
- import React9, { useRef as useRef5, useEffect as useEffect7, useState as useState10, useCallback as useCallback2 } from "react";
162
+ import React10, { useRef as useRef5, useEffect as useEffect8, useState as useState11, useCallback as useCallback2 } from "react";
163
163
  import {
164
164
  canvasToImagePoint,
165
165
  hitTestCrop,
@@ -174,7 +174,9 @@ import {
174
174
  SelectionGesture,
175
175
  PaintGesture,
176
176
  handlePaintShortcut,
177
- pointerPressure
177
+ pointerPressure,
178
+ FreeTransformTool,
179
+ getViewportProjection
178
180
  } from "@pixerate/editor/image-editor";
179
181
 
180
182
  // src/image-editor/ControlSlider.tsx
@@ -1125,6 +1127,22 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
1125
1127
  children: layerBadge(layer)
1126
1128
  }
1127
1129
  ),
1130
+ layer.mask && !layer.mask.source && layer.type === "pixel" && /* @__PURE__ */ jsx6(
1131
+ "button",
1132
+ {
1133
+ type: "button",
1134
+ "aria-label": `${layer.mask.linked === false ? "Link" : "Unlink"} ${row.label} mask`,
1135
+ "aria-pressed": layer.mask.linked !== false,
1136
+ 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.",
1137
+ "data-testid": "layer-mask-link",
1138
+ className: `shrink-0 text-[10px] leading-none ${layer.mask.linked === false ? "text-slate-600" : "text-slate-300"}`,
1139
+ onClick: (e) => {
1140
+ e.stopPropagation();
1141
+ attempt(() => controller.setLayerMaskProps(layer.id, { linked: layer.mask.linked === false }));
1142
+ },
1143
+ children: layer.mask.linked === false ? "\u26D3\uFE0E\u0338" : "\u26D3\uFE0E"
1144
+ }
1145
+ ),
1128
1146
  layer.mask && /* @__PURE__ */ jsx6(
1129
1147
  Thumbnail,
1130
1148
  {
@@ -1646,8 +1664,147 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
1646
1664
  ] });
1647
1665
  };
1648
1666
 
1667
+ // src/image-editor/FreeTransformOptionsBar.tsx
1668
+ import { useEffect as useEffect7, useState as useState10 } from "react";
1669
+ import { FREE_TRANSFORM_FIELDS, FREE_TRANSFORM_MODE_OPTIONS, INTERPOLATIONS, TRANSFORM_ANCHORS, WARP_GRID_OPTIONS, WARP_STYLE_OPTIONS } from "@pixerate/editor/image-editor";
1670
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1671
+ 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"}`;
1672
+ var round = (v, unit) => unit === "px" ? Math.round(v * 10) / 10 : Math.round(v * 100) / 100;
1673
+ var FreeTransformOptionsBar = ({ tool, className }) => {
1674
+ const [, setTick] = useState10(0);
1675
+ useEffect7(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
1676
+ const bar = tool.bar();
1677
+ if (!tool.active || !bar) return null;
1678
+ const warp = tool.warpBar();
1679
+ const warpNumber = (key, raw) => {
1680
+ const v = Number(raw);
1681
+ if (raw.trim() !== "" && Number.isFinite(v) && v !== warp[key]) tool.setWarp({ [key]: Math.max(-100, Math.min(100, v)) });
1682
+ };
1683
+ const apply = (field, raw) => {
1684
+ const v = Number(raw);
1685
+ if (raw.trim() !== "" && Number.isFinite(v) && Math.abs(v - bar[field]) > 1e-9) tool.setField(field, v);
1686
+ };
1687
+ return /* @__PURE__ */ jsxs10("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: [
1688
+ /* @__PURE__ */ jsx10("div", { className: "flex gap-1", role: "group", "aria-label": "Transform mode", children: FREE_TRANSFORM_MODE_OPTIONS.map((m) => /* @__PURE__ */ jsx10("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)) }),
1689
+ /* @__PURE__ */ jsx10("div", { className: "grid grid-cols-3 gap-px", role: "group", "aria-label": "Reference point", children: TRANSFORM_ANCHORS.map((a) => /* @__PURE__ */ jsx10("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)) }),
1690
+ tool.mode === "warp" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": "Warp options", children: [
1691
+ /* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-1", children: [
1692
+ /* @__PURE__ */ jsx10("span", { className: "text-slate-400", children: "Warp" }),
1693
+ /* @__PURE__ */ jsx10("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: WARP_STYLE_OPTIONS.map((o) => /* @__PURE__ */ jsx10("option", { value: o.id, children: o.label }, o.id)) })
1694
+ ] }),
1695
+ ["bend", "horizontal", "vertical"].map((k) => /* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-1", children: [
1696
+ /* @__PURE__ */ jsx10("span", { className: "text-slate-400", children: k === "bend" ? "Bend" : k === "horizontal" ? "H" : "V" }),
1697
+ /* @__PURE__ */ jsx10(
1698
+ "input",
1699
+ {
1700
+ type: "number",
1701
+ "aria-label": k === "bend" ? "Warp bend in percent" : `Warp ${k} distortion in percent`,
1702
+ defaultValue: warp[k],
1703
+ min: -100,
1704
+ max: 100,
1705
+ disabled: warp.style === "custom",
1706
+ className: "w-14 rounded border border-slate-700 bg-slate-900 px-1 py-0.5 text-right disabled:opacity-40",
1707
+ onBlur: (e) => warpNumber(k, e.currentTarget.value),
1708
+ onKeyDown: (e) => {
1709
+ if (e.key === "Enter") {
1710
+ e.preventDefault();
1711
+ e.stopPropagation();
1712
+ warpNumber(k, e.currentTarget.value);
1713
+ }
1714
+ }
1715
+ },
1716
+ `${k}:${warp[k]}`
1717
+ ),
1718
+ /* @__PURE__ */ jsx10("span", { className: "text-slate-500", children: "%" })
1719
+ ] }, k)),
1720
+ /* @__PURE__ */ jsx10(
1721
+ "button",
1722
+ {
1723
+ type: "button",
1724
+ title: "Bend along the vertical axis",
1725
+ "aria-pressed": warp.orientation === "vertical",
1726
+ disabled: warp.style === "custom",
1727
+ className: chip2(warp.orientation === "vertical"),
1728
+ onClick: () => tool.setWarp({ orientation: warp.orientation === "vertical" ? "horizontal" : "vertical" }),
1729
+ children: "Vertical"
1730
+ }
1731
+ ),
1732
+ /* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-1", children: [
1733
+ /* @__PURE__ */ jsx10("span", { className: "text-slate-400", children: "Grid" }),
1734
+ /* @__PURE__ */ jsx10(
1735
+ "select",
1736
+ {
1737
+ "aria-label": "Warp grid",
1738
+ value: WARP_GRID_OPTIONS.find((g) => g.columns === warp.columns && g.rows === warp.rows)?.id ?? "1x1",
1739
+ onChange: (e) => {
1740
+ const g = WARP_GRID_OPTIONS.find((o) => o.id === e.target.value);
1741
+ tool.setWarp({ columns: g.columns, rows: g.rows });
1742
+ },
1743
+ className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
1744
+ children: WARP_GRID_OPTIONS.map((g) => /* @__PURE__ */ jsx10("option", { value: g.id, children: g.label }, g.id))
1745
+ }
1746
+ )
1747
+ ] })
1748
+ ] }),
1749
+ tool.mode !== "warp" && FREE_TRANSFORM_FIELDS.map((f) => /* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-1", title: f.title, children: [
1750
+ /* @__PURE__ */ jsx10("span", { className: "text-slate-400", children: f.label }),
1751
+ /* @__PURE__ */ jsx10(
1752
+ "input",
1753
+ {
1754
+ type: "number",
1755
+ "aria-label": f.title,
1756
+ defaultValue: round(bar[f.id], f.unit),
1757
+ disabled: !bar.affine,
1758
+ step: f.unit === "px" ? 1 : 0.1,
1759
+ className: "w-16 rounded border border-slate-700 bg-slate-900 px-1 py-0.5 text-right disabled:opacity-40",
1760
+ onBlur: (e) => apply(f.id, e.currentTarget.value),
1761
+ onKeyDown: (e) => {
1762
+ if (e.key === "Enter") {
1763
+ e.preventDefault();
1764
+ e.stopPropagation();
1765
+ apply(f.id, e.currentTarget.value);
1766
+ }
1767
+ }
1768
+ },
1769
+ `${f.id}:${round(bar[f.id], f.unit)}`
1770
+ ),
1771
+ /* @__PURE__ */ jsx10("span", { className: "text-slate-500", children: f.unit }),
1772
+ f.id === "scaleX" && /* @__PURE__ */ jsx10(
1773
+ "button",
1774
+ {
1775
+ type: "button",
1776
+ "aria-label": "Keep width and height proportional",
1777
+ "aria-pressed": tool.proportional,
1778
+ className: chip2(tool.proportional),
1779
+ onClick: () => {
1780
+ tool.proportional = !tool.proportional;
1781
+ setTick((n) => n + 1);
1782
+ },
1783
+ children: "\u26D3\uFE0E"
1784
+ }
1785
+ )
1786
+ ] }, f.id)),
1787
+ /* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-1", children: [
1788
+ /* @__PURE__ */ jsx10("span", { className: "text-slate-400", children: "Interpolation" }),
1789
+ /* @__PURE__ */ jsx10(
1790
+ "select",
1791
+ {
1792
+ "aria-label": "Interpolation",
1793
+ value: tool.interpolation,
1794
+ onChange: (e) => tool.setInterpolation(e.target.value),
1795
+ className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
1796
+ children: INTERPOLATIONS.map((i) => /* @__PURE__ */ jsx10("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
1797
+ }
1798
+ )
1799
+ ] }),
1800
+ /* @__PURE__ */ jsx10("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" }),
1801
+ /* @__PURE__ */ jsx10("button", { type: "button", title: "Cancel (Esc)", className: chip2(false), onClick: () => tool.cancel(), children: "Cancel" }),
1802
+ tool.error && /* @__PURE__ */ jsx10("span", { role: "alert", className: "text-rose-400", children: tool.error })
1803
+ ] });
1804
+ };
1805
+
1649
1806
  // src/image-editor/ImageEditor.tsx
1650
- import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1807
+ import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1651
1808
  var ImageEditor = ({
1652
1809
  editor: externalEditor,
1653
1810
  src,
@@ -1665,9 +1822,9 @@ var ImageEditor = ({
1665
1822
  const legacyProcess = normalizeProcessVersion(state.adjustments.process) < LATEST_PROCESS_VERSION;
1666
1823
  const canvasRef = useRef5(null);
1667
1824
  const containerRef = useRef5(null);
1668
- const [activeTab, setActiveTab] = useState10("crop");
1669
- const [activeCropRatio, setActiveCropRatio] = useState10(null);
1670
- const [selectionOptions, setSelectionOptions] = useState10(DEFAULT_SELECTION_TOOL_OPTIONS);
1825
+ const [activeTab, setActiveTab] = useState11("crop");
1826
+ const [activeCropRatio, setActiveCropRatio] = useState11(null);
1827
+ const [selectionOptions, setSelectionOptions] = useState11(DEFAULT_SELECTION_TOOL_OPTIONS);
1671
1828
  const selectionOptionsRef = useRef5(selectionOptions);
1672
1829
  selectionOptionsRef.current = selectionOptions;
1673
1830
  const selectionGestureRef = useRef5(null);
@@ -1675,7 +1832,7 @@ var ImageEditor = ({
1675
1832
  selectionGestureRef.current = new SelectionGesture(controller, () => selectionOptionsRef.current);
1676
1833
  }
1677
1834
  const selectionDraftRef = useRef5(null);
1678
- const [selectionError, setSelectionError] = useState10(null);
1835
+ const [selectionError, setSelectionError] = useState11(null);
1679
1836
  const paintGestureRef = useRef5(null);
1680
1837
  const paintControllerRef = useRef5(controller);
1681
1838
  if (!paintGestureRef.current || paintControllerRef.current !== controller) {
@@ -1683,14 +1840,26 @@ var ImageEditor = ({
1683
1840
  paintControllerRef.current = controller;
1684
1841
  }
1685
1842
  const brushCursorRef = useRef5(null);
1686
- const [paintError, setPaintError] = useState10(null);
1687
- const [inpaintPrompt, setInpaintPrompt] = useState10("");
1688
- const [inpaintMaskMode, setInpaintMaskMode] = useState10("annotations");
1689
- const [isRemovingBg, setIsRemovingBg] = useState10(false);
1690
- const [isInpainting, setIsInpainting] = useState10(false);
1691
- const [aiError, setAiError] = useState10(null);
1692
- const [aiSuccess, setAiSuccess] = useState10(null);
1693
- const [aiTarget, setAiTarget] = useState10("auto");
1843
+ const [paintError, setPaintError] = useState11(null);
1844
+ const transformToolRef = useRef5(null);
1845
+ const transformControllerRef = useRef5(controller);
1846
+ if (!transformToolRef.current || transformControllerRef.current !== controller) {
1847
+ transformToolRef.current?.cancel();
1848
+ transformToolRef.current = new FreeTransformTool(controller, {
1849
+ schedule: (run) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(run) : run()
1850
+ });
1851
+ transformControllerRef.current = controller;
1852
+ }
1853
+ const transformTool = transformToolRef.current;
1854
+ const [, setTransformTick] = useState11(0);
1855
+ const [transformCursor, setTransformCursor] = useState11("default");
1856
+ const [inpaintPrompt, setInpaintPrompt] = useState11("");
1857
+ const [inpaintMaskMode, setInpaintMaskMode] = useState11("annotations");
1858
+ const [isRemovingBg, setIsRemovingBg] = useState11(false);
1859
+ const [isInpainting, setIsInpainting] = useState11(false);
1860
+ const [aiError, setAiError] = useState11(null);
1861
+ const [aiSuccess, setAiSuccess] = useState11(null);
1862
+ const [aiTarget, setAiTarget] = useState11("auto");
1694
1863
  const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
1695
1864
  const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
1696
1865
  const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
@@ -1753,10 +1922,10 @@ var ImageEditor = ({
1753
1922
  setIsInpainting(false);
1754
1923
  }
1755
1924
  };
1756
- const [activeColor, setActiveColor] = useState10("#ef4444");
1757
- const [strokeWidth, setStrokeWidth] = useState10(3);
1758
- const [fontSize, setFontSize] = useState10(24);
1759
- const [textInput, setTextInput] = useState10("");
1925
+ const [activeColor, setActiveColor] = useState11("#ef4444");
1926
+ const [strokeWidth, setStrokeWidth] = useState11(3);
1927
+ const [fontSize, setFontSize] = useState11(24);
1928
+ const [textInput, setTextInput] = useState11("");
1760
1929
  const draftAnnotationRef = useRef5(null);
1761
1930
  const draftCropRef = useRef5(null);
1762
1931
  const cropDragInfoRef = useRef5(null);
@@ -1780,12 +1949,64 @@ var ImageEditor = ({
1780
1949
  draftAnnotation: draftAnnotation !== void 0 ? draftAnnotation : draftAnnotationRef.current,
1781
1950
  draftCrop: draftCrop !== void 0 ? draftCrop : draftCropRef.current,
1782
1951
  draftSelectionPath: selectionDraftRef.current,
1783
- brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null
1952
+ brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" && !transformTool.active ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null,
1953
+ freeTransform: transformTool.overlay()
1784
1954
  });
1785
1955
  },
1786
- [controller, activeTab]
1956
+ [controller, activeTab, transformTool]
1787
1957
  );
1788
- useEffect7(() => {
1958
+ useEffect8(() => transformTool.subscribe(() => {
1959
+ setTransformTick((n) => n + 1);
1960
+ void renderCanvas();
1961
+ }), [transformTool, renderCanvas]);
1962
+ const transformPoint = (e) => {
1963
+ const canvas = canvasRef.current;
1964
+ const rect = canvas.getBoundingClientRect();
1965
+ const sx = rect.width > 0 ? canvas.width / rect.width : 1;
1966
+ const sy = rect.height > 0 ? canvas.height / rect.height : 1;
1967
+ const s = controller.getState();
1968
+ const cropping = activeTab === "crop";
1969
+ const projection = getViewportProjection(s, canvas.width, canvas.height, cropping);
1970
+ const pt = canvasToImagePoint({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
1971
+ transformTool.setView(projection.scale);
1972
+ return { pt, tolerance: 6 / (projection.scale || 1) };
1973
+ };
1974
+ const handleTransformPointerDown = (e) => {
1975
+ if (!transformTool.active) return false;
1976
+ if (e.button !== 0) return true;
1977
+ e.preventDefault();
1978
+ try {
1979
+ e.currentTarget.setPointerCapture?.(e.pointerId);
1980
+ } catch {
1981
+ }
1982
+ const { pt, tolerance } = transformPoint(e);
1983
+ transformTool.down(pt, tolerance);
1984
+ return true;
1985
+ };
1986
+ const handleTransformPointerMove = (e) => {
1987
+ if (!transformTool.active) return false;
1988
+ const { pt, tolerance } = transformPoint(e);
1989
+ if (e.buttons & 1) transformTool.move(pt, e);
1990
+ else {
1991
+ const over = transformTool.hit(pt, tolerance);
1992
+ setTransformCursor(transformTool.cursor(over));
1993
+ }
1994
+ return true;
1995
+ };
1996
+ const handleTransformPointerUp = () => {
1997
+ if (!transformTool.active) return false;
1998
+ transformTool.up();
1999
+ return true;
2000
+ };
2001
+ useEffect8(() => {
2002
+ if (typeof window === "undefined") return;
2003
+ const onKey = (e) => {
2004
+ if (transformTool.key(e)) e.preventDefault();
2005
+ };
2006
+ window.addEventListener("keydown", onKey);
2007
+ return () => window.removeEventListener("keydown", onKey);
2008
+ }, [transformTool]);
2009
+ useEffect8(() => {
1789
2010
  const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
1790
2011
  const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
1791
2012
  const animId = raf(() => {
@@ -1793,12 +2014,12 @@ var ImageEditor = ({
1793
2014
  });
1794
2015
  return () => caf(animId);
1795
2016
  }, [renderCanvas, state]);
1796
- useEffect7(() => {
2017
+ useEffect8(() => {
1797
2018
  if (activeTab === "crop" && editor.state.activeTool !== "crop") {
1798
2019
  editor.setTool("crop");
1799
2020
  }
1800
2021
  }, [activeTab, editor]);
1801
- useEffect7(() => {
2022
+ useEffect8(() => {
1802
2023
  const container = containerRef.current;
1803
2024
  if (!container) return;
1804
2025
  if (typeof ResizeObserver !== "undefined") {
@@ -1839,6 +2060,7 @@ var ImageEditor = ({
1839
2060
  }));
1840
2061
  };
1841
2062
  const handlePaintPointerDown = (e) => {
2063
+ if (handleTransformPointerDown(e)) return;
1842
2064
  if (activeTab !== "paint" || e.button !== 0) return;
1843
2065
  e.preventDefault();
1844
2066
  try {
@@ -1849,6 +2071,7 @@ var ImageEditor = ({
1849
2071
  setPaintError(paintGestureRef.current.down(first));
1850
2072
  };
1851
2073
  const handlePaintPointerMove = (e) => {
2074
+ if (handleTransformPointerMove(e)) return;
1852
2075
  if (activeTab !== "paint") return;
1853
2076
  const samples = paintSamples(e);
1854
2077
  brushCursorRef.current = samples[samples.length - 1] ?? null;
@@ -1856,6 +2079,7 @@ var ImageEditor = ({
1856
2079
  else void renderCanvas();
1857
2080
  };
1858
2081
  const handlePaintPointerUp = () => {
2082
+ if (handleTransformPointerUp()) return;
1859
2083
  if (activeTab !== "paint") return;
1860
2084
  const g = paintGestureRef.current;
1861
2085
  if (g.active) {
@@ -1863,7 +2087,7 @@ var ImageEditor = ({
1863
2087
  if (g.error) setPaintError(g.error);
1864
2088
  }
1865
2089
  };
1866
- useEffect7(() => {
2090
+ useEffect8(() => {
1867
2091
  if (activeTab !== "paint" || typeof window === "undefined") return;
1868
2092
  const onKey = (e) => {
1869
2093
  if (handlePaintShortcut(controller, e)) e.preventDefault();
@@ -1873,7 +2097,7 @@ var ImageEditor = ({
1873
2097
  }, [activeTab, controller]);
1874
2098
  const handleMouseDown = (e) => {
1875
2099
  const canvas = canvasRef.current;
1876
- if (!canvas) return;
2100
+ if (!canvas || transformTool.active) return;
1877
2101
  const canvasPt = getCanvasEventPoint(e);
1878
2102
  if (activeTab === "select") {
1879
2103
  const gesture = selectionGestureRef.current;
@@ -1945,7 +2169,7 @@ var ImageEditor = ({
1945
2169
  };
1946
2170
  const handleMouseMove = (e) => {
1947
2171
  const canvas = canvasRef.current;
1948
- if (!canvas) return;
2172
+ if (!canvas || transformTool.active) return;
1949
2173
  const canvasPt = getCanvasEventPoint(e);
1950
2174
  if (activeTab === "select") {
1951
2175
  const gesture = selectionGestureRef.current;
@@ -2101,7 +2325,7 @@ var ImageEditor = ({
2101
2325
  };
2102
2326
  const handleMouseUp = (e) => {
2103
2327
  const canvas = canvasRef.current;
2104
- if (!canvas) return;
2328
+ if (!canvas || transformTool.active) return;
2105
2329
  const canvasPt = getCanvasEventPoint(e);
2106
2330
  if (activeTab === "select") {
2107
2331
  const gesture = selectionGestureRef.current;
@@ -2226,15 +2450,15 @@ var ImageEditor = ({
2226
2450
  link.click();
2227
2451
  }
2228
2452
  };
2229
- return /* @__PURE__ */ jsxs10(
2453
+ return /* @__PURE__ */ jsxs11(
2230
2454
  "div",
2231
2455
  {
2232
2456
  className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
2233
2457
  style,
2234
2458
  children: [
2235
- /* @__PURE__ */ jsxs10("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: [
2236
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
2237
- /* @__PURE__ */ jsx10(
2459
+ /* @__PURE__ */ jsxs11("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: [
2460
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
2461
+ /* @__PURE__ */ jsx11(
2238
2462
  "button",
2239
2463
  {
2240
2464
  type: "button",
@@ -2246,7 +2470,7 @@ var ImageEditor = ({
2246
2470
  children: "Transform & Crop"
2247
2471
  }
2248
2472
  ),
2249
- /* @__PURE__ */ jsx10(
2473
+ /* @__PURE__ */ jsx11(
2250
2474
  "button",
2251
2475
  {
2252
2476
  type: "button",
@@ -2258,7 +2482,7 @@ var ImageEditor = ({
2258
2482
  children: "Adjustments"
2259
2483
  }
2260
2484
  ),
2261
- /* @__PURE__ */ jsx10(
2485
+ /* @__PURE__ */ jsx11(
2262
2486
  "button",
2263
2487
  {
2264
2488
  type: "button",
@@ -2270,7 +2494,7 @@ var ImageEditor = ({
2270
2494
  children: "Layers"
2271
2495
  }
2272
2496
  ),
2273
- /* @__PURE__ */ jsx10(
2497
+ /* @__PURE__ */ jsx11(
2274
2498
  "button",
2275
2499
  {
2276
2500
  type: "button",
@@ -2282,7 +2506,7 @@ var ImageEditor = ({
2282
2506
  children: "Paint"
2283
2507
  }
2284
2508
  ),
2285
- /* @__PURE__ */ jsx10(
2509
+ /* @__PURE__ */ jsx11(
2286
2510
  "button",
2287
2511
  {
2288
2512
  type: "button",
@@ -2294,7 +2518,7 @@ var ImageEditor = ({
2294
2518
  children: "Select & Mask"
2295
2519
  }
2296
2520
  ),
2297
- /* @__PURE__ */ jsx10(
2521
+ /* @__PURE__ */ jsx11(
2298
2522
  "button",
2299
2523
  {
2300
2524
  type: "button",
@@ -2306,7 +2530,7 @@ var ImageEditor = ({
2306
2530
  children: "Annotations"
2307
2531
  }
2308
2532
  ),
2309
- /* @__PURE__ */ jsx10(
2533
+ /* @__PURE__ */ jsx11(
2310
2534
  "button",
2311
2535
  {
2312
2536
  type: "button",
@@ -2318,7 +2542,7 @@ var ImageEditor = ({
2318
2542
  children: "Depth Mask"
2319
2543
  }
2320
2544
  ),
2321
- /* @__PURE__ */ jsxs10(
2545
+ /* @__PURE__ */ jsxs11(
2322
2546
  "button",
2323
2547
  {
2324
2548
  type: "button",
@@ -2328,14 +2552,14 @@ var ImageEditor = ({
2328
2552
  },
2329
2553
  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"}`,
2330
2554
  children: [
2331
- /* @__PURE__ */ jsx10("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx10("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" }) }),
2555
+ /* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("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" }) }),
2332
2556
  "AI Tools"
2333
2557
  ]
2334
2558
  }
2335
2559
  )
2336
2560
  ] }),
2337
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2 text-xs", children: [
2338
- /* @__PURE__ */ jsx10(
2561
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 text-xs", children: [
2562
+ /* @__PURE__ */ jsx11(
2339
2563
  "button",
2340
2564
  {
2341
2565
  type: "button",
@@ -2346,7 +2570,7 @@ var ImageEditor = ({
2346
2570
  children: "\u21A9"
2347
2571
  }
2348
2572
  ),
2349
- /* @__PURE__ */ jsx10(
2573
+ /* @__PURE__ */ jsx11(
2350
2574
  "button",
2351
2575
  {
2352
2576
  type: "button",
@@ -2357,7 +2581,7 @@ var ImageEditor = ({
2357
2581
  children: "\u21AA"
2358
2582
  }
2359
2583
  ),
2360
- /* @__PURE__ */ jsx10(
2584
+ /* @__PURE__ */ jsx11(
2361
2585
  "button",
2362
2586
  {
2363
2587
  type: "button",
@@ -2366,8 +2590,8 @@ var ImageEditor = ({
2366
2590
  children: "Reset"
2367
2591
  }
2368
2592
  ),
2369
- /* @__PURE__ */ jsx10("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2370
- /* @__PURE__ */ jsx10(
2593
+ /* @__PURE__ */ jsx11("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2594
+ /* @__PURE__ */ jsx11(
2371
2595
  "button",
2372
2596
  {
2373
2597
  type: "button",
@@ -2377,11 +2601,11 @@ var ImageEditor = ({
2377
2601
  children: "-"
2378
2602
  }
2379
2603
  ),
2380
- /* @__PURE__ */ jsxs10("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
2604
+ /* @__PURE__ */ jsxs11("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
2381
2605
  Math.round(state.zoom * 100),
2382
2606
  "%"
2383
2607
  ] }),
2384
- /* @__PURE__ */ jsx10(
2608
+ /* @__PURE__ */ jsx11(
2385
2609
  "button",
2386
2610
  {
2387
2611
  type: "button",
@@ -2391,8 +2615,8 @@ var ImageEditor = ({
2391
2615
  children: "+"
2392
2616
  }
2393
2617
  ),
2394
- /* @__PURE__ */ jsx10("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2395
- /* @__PURE__ */ jsx10(
2618
+ /* @__PURE__ */ jsx11("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2619
+ /* @__PURE__ */ jsx11(
2396
2620
  "button",
2397
2621
  {
2398
2622
  type: "button",
@@ -2403,7 +2627,7 @@ var ImageEditor = ({
2403
2627
  children: "Hold Compare"
2404
2628
  }
2405
2629
  ),
2406
- /* @__PURE__ */ jsx10(
2630
+ /* @__PURE__ */ jsx11(
2407
2631
  "button",
2408
2632
  {
2409
2633
  type: "button",
@@ -2414,13 +2638,15 @@ var ImageEditor = ({
2414
2638
  )
2415
2639
  ] })
2416
2640
  ] }),
2417
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
2418
- /* @__PURE__ */ jsx10(
2641
+ transformTool.active && /* @__PURE__ */ jsx11(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
2642
+ !transformTool.active && transformTool.error && /* @__PURE__ */ jsx11("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 }),
2643
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
2644
+ /* @__PURE__ */ jsx11(
2419
2645
  "div",
2420
2646
  {
2421
2647
  ref: containerRef,
2422
2648
  className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
2423
- children: /* @__PURE__ */ jsx10(
2649
+ children: /* @__PURE__ */ jsx11(
2424
2650
  "canvas",
2425
2651
  {
2426
2652
  ref: canvasRef,
@@ -2433,16 +2659,17 @@ var ImageEditor = ({
2433
2659
  onPointerUp: handlePaintPointerUp,
2434
2660
  onPointerCancel: () => paintGestureRef.current?.cancel(),
2435
2661
  "data-testid": "image-editor-canvas",
2436
- className: `absolute inset-0 w-full h-full block ${activeTab === "paint" ? "touch-none cursor-crosshair" : ""}`
2662
+ style: transformTool.active ? { cursor: transformCursor } : void 0,
2663
+ className: `absolute inset-0 w-full h-full block ${transformTool.active ? "touch-none" : activeTab === "paint" ? "touch-none cursor-crosshair" : ""}`
2437
2664
  }
2438
2665
  )
2439
2666
  }
2440
2667
  ),
2441
- /* @__PURE__ */ jsxs10("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: [
2442
- activeTab === "crop" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-4 text-xs", children: [
2443
- /* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
2444
- /* @__PURE__ */ jsxs10("div", { className: "grid grid-cols-3 gap-2", children: [
2445
- /* @__PURE__ */ jsx10(
2668
+ /* @__PURE__ */ jsxs11("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: [
2669
+ activeTab === "crop" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-4 text-xs", children: [
2670
+ /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
2671
+ /* @__PURE__ */ jsxs11("div", { className: "grid grid-cols-3 gap-2", children: [
2672
+ /* @__PURE__ */ jsx11(
2446
2673
  "button",
2447
2674
  {
2448
2675
  type: "button",
@@ -2454,7 +2681,7 @@ var ImageEditor = ({
2454
2681
  children: "Freeform"
2455
2682
  }
2456
2683
  ),
2457
- /* @__PURE__ */ jsx10(
2684
+ /* @__PURE__ */ jsx11(
2458
2685
  "button",
2459
2686
  {
2460
2687
  type: "button",
@@ -2466,7 +2693,7 @@ var ImageEditor = ({
2466
2693
  children: "1:1 Square"
2467
2694
  }
2468
2695
  ),
2469
- /* @__PURE__ */ jsx10(
2696
+ /* @__PURE__ */ jsx11(
2470
2697
  "button",
2471
2698
  {
2472
2699
  type: "button",
@@ -2478,7 +2705,7 @@ var ImageEditor = ({
2478
2705
  children: "4:3 Standard"
2479
2706
  }
2480
2707
  ),
2481
- /* @__PURE__ */ jsx10(
2708
+ /* @__PURE__ */ jsx11(
2482
2709
  "button",
2483
2710
  {
2484
2711
  type: "button",
@@ -2490,7 +2717,7 @@ var ImageEditor = ({
2490
2717
  children: "16:9 Wide"
2491
2718
  }
2492
2719
  ),
2493
- /* @__PURE__ */ jsx10(
2720
+ /* @__PURE__ */ jsx11(
2494
2721
  "button",
2495
2722
  {
2496
2723
  type: "button",
@@ -2502,7 +2729,7 @@ var ImageEditor = ({
2502
2729
  children: "3:2 Photo"
2503
2730
  }
2504
2731
  ),
2505
- /* @__PURE__ */ jsx10(
2732
+ /* @__PURE__ */ jsx11(
2506
2733
  "button",
2507
2734
  {
2508
2735
  type: "button",
@@ -2515,10 +2742,10 @@ var ImageEditor = ({
2515
2742
  }
2516
2743
  )
2517
2744
  ] }),
2518
- /* @__PURE__ */ jsx10("div", { className: "h-px bg-slate-800 my-1" }),
2519
- /* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
2520
- /* @__PURE__ */ jsxs10("div", { className: "grid grid-cols-2 gap-2", children: [
2521
- /* @__PURE__ */ jsx10(
2745
+ /* @__PURE__ */ jsx11("div", { className: "h-px bg-slate-800 my-1" }),
2746
+ /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
2747
+ /* @__PURE__ */ jsxs11("div", { className: "grid grid-cols-2 gap-2", children: [
2748
+ /* @__PURE__ */ jsx11(
2522
2749
  "button",
2523
2750
  {
2524
2751
  type: "button",
@@ -2527,7 +2754,7 @@ var ImageEditor = ({
2527
2754
  children: "Rotate -90\xB0"
2528
2755
  }
2529
2756
  ),
2530
- /* @__PURE__ */ jsx10(
2757
+ /* @__PURE__ */ jsx11(
2531
2758
  "button",
2532
2759
  {
2533
2760
  type: "button",
@@ -2536,7 +2763,7 @@ var ImageEditor = ({
2536
2763
  children: "Rotate +90\xB0"
2537
2764
  }
2538
2765
  ),
2539
- /* @__PURE__ */ jsx10(
2766
+ /* @__PURE__ */ jsx11(
2540
2767
  "button",
2541
2768
  {
2542
2769
  type: "button",
@@ -2545,7 +2772,7 @@ var ImageEditor = ({
2545
2772
  children: "Flip Horizontal"
2546
2773
  }
2547
2774
  ),
2548
- /* @__PURE__ */ jsx10(
2775
+ /* @__PURE__ */ jsx11(
2549
2776
  "button",
2550
2777
  {
2551
2778
  type: "button",
@@ -2556,10 +2783,10 @@ var ImageEditor = ({
2556
2783
  )
2557
2784
  ] })
2558
2785
  ] }),
2559
- activeTab === "adjust" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3 text-xs", children: [
2560
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
2561
- /* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
2562
- /* @__PURE__ */ jsx10(
2786
+ activeTab === "adjust" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
2787
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
2788
+ /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
2789
+ /* @__PURE__ */ jsx11(
2563
2790
  "button",
2564
2791
  {
2565
2792
  type: "button",
@@ -2569,9 +2796,9 @@ var ImageEditor = ({
2569
2796
  }
2570
2797
  )
2571
2798
  ] }),
2572
- /* @__PURE__ */ jsx10(Histogram, { histogram: editor.histogram }),
2573
- IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ jsxs10(React9.Fragment, { children: [
2574
- /* @__PURE__ */ jsx10(
2799
+ /* @__PURE__ */ jsx11(Histogram, { histogram: editor.histogram }),
2800
+ IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ jsxs11(React10.Fragment, { children: [
2801
+ /* @__PURE__ */ jsx11(
2575
2802
  ControlSlider,
2576
2803
  {
2577
2804
  spec,
@@ -2580,14 +2807,14 @@ var ImageEditor = ({
2580
2807
  onChange: (v) => editor.setAdjustments({ [spec.id]: v })
2581
2808
  }
2582
2809
  ),
2583
- spec.id === "tint" && legacyProcess && /* @__PURE__ */ jsxs10(
2810
+ spec.id === "tint" && legacyProcess && /* @__PURE__ */ jsxs11(
2584
2811
  "div",
2585
2812
  {
2586
2813
  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",
2587
2814
  "data-testid": "image-editor-process-notice",
2588
2815
  children: [
2589
- /* @__PURE__ */ jsx10("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
2590
- /* @__PURE__ */ jsx10(
2816
+ /* @__PURE__ */ jsx11("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
2817
+ /* @__PURE__ */ jsx11(
2591
2818
  "button",
2592
2819
  {
2593
2820
  type: "button",
@@ -2600,7 +2827,7 @@ var ImageEditor = ({
2600
2827
  }
2601
2828
  )
2602
2829
  ] }, spec.id)),
2603
- /* @__PURE__ */ jsx10("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx10(
2830
+ /* @__PURE__ */ jsx11("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx11(
2604
2831
  AdjustmentLayersPanel,
2605
2832
  {
2606
2833
  controller,
@@ -2609,19 +2836,41 @@ var ImageEditor = ({
2609
2836
  }
2610
2837
  ) })
2611
2838
  ] }),
2612
- activeTab === "layers" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3 text-xs", children: [
2613
- /* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
2614
- /* @__PURE__ */ jsx10(LayersPanel, { controller })
2839
+ activeTab === "layers" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
2840
+ /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
2841
+ /* @__PURE__ */ jsx11(
2842
+ "button",
2843
+ {
2844
+ type: "button",
2845
+ title: "Edit \u203A Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer",
2846
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
2847
+ disabled: transformTool.active,
2848
+ onClick: () => transformTool.begin(),
2849
+ children: "Free Transform"
2850
+ }
2851
+ ),
2852
+ /* @__PURE__ */ jsx11(LayersPanel, { controller })
2615
2853
  ] }),
2616
- activeTab === "paint" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3 text-xs", children: [
2617
- /* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
2618
- /* @__PURE__ */ jsx10(BrushOptionsBar, { controller }),
2619
- paintError && /* @__PURE__ */ jsx10("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
2620
- /* @__PURE__ */ jsx10("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx10(LayersPanel, { controller }) })
2854
+ activeTab === "paint" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
2855
+ /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
2856
+ /* @__PURE__ */ jsx11(BrushOptionsBar, { controller }),
2857
+ /* @__PURE__ */ jsx11(
2858
+ "button",
2859
+ {
2860
+ type: "button",
2861
+ title: "Edit \u203A Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer",
2862
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start",
2863
+ disabled: transformTool.active,
2864
+ onClick: () => transformTool.begin(),
2865
+ children: "Free Transform"
2866
+ }
2867
+ ),
2868
+ paintError && /* @__PURE__ */ jsx11("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
2869
+ /* @__PURE__ */ jsx11("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx11(LayersPanel, { controller }) })
2621
2870
  ] }),
2622
- activeTab === "annotate" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3 text-xs", children: [
2623
- /* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
2624
- /* @__PURE__ */ jsx10("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ jsx10(
2871
+ activeTab === "annotate" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
2872
+ /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
2873
+ /* @__PURE__ */ jsx11("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ jsx11(
2625
2874
  "button",
2626
2875
  {
2627
2876
  type: "button",
@@ -2631,9 +2880,9 @@ var ImageEditor = ({
2631
2880
  },
2632
2881
  t
2633
2882
  )) }),
2634
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2 mt-2", children: [
2635
- /* @__PURE__ */ jsx10("label", { className: "text-slate-400", children: "Color:" }),
2636
- /* @__PURE__ */ jsx10(
2883
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 mt-2", children: [
2884
+ /* @__PURE__ */ jsx11("label", { className: "text-slate-400", children: "Color:" }),
2885
+ /* @__PURE__ */ jsx11(
2637
2886
  "input",
2638
2887
  {
2639
2888
  type: "color",
@@ -2642,15 +2891,15 @@ var ImageEditor = ({
2642
2891
  className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
2643
2892
  }
2644
2893
  ),
2645
- /* @__PURE__ */ jsxs10("div", { className: "flex-1 ml-2", children: [
2646
- /* @__PURE__ */ jsxs10("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
2647
- /* @__PURE__ */ jsx10("span", { children: "Width:" }),
2648
- /* @__PURE__ */ jsxs10("span", { className: "font-mono", children: [
2894
+ /* @__PURE__ */ jsxs11("div", { className: "flex-1 ml-2", children: [
2895
+ /* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
2896
+ /* @__PURE__ */ jsx11("span", { children: "Width:" }),
2897
+ /* @__PURE__ */ jsxs11("span", { className: "font-mono", children: [
2649
2898
  strokeWidth,
2650
2899
  "px"
2651
2900
  ] })
2652
2901
  ] }),
2653
- /* @__PURE__ */ jsx10(
2902
+ /* @__PURE__ */ jsx11(
2654
2903
  "input",
2655
2904
  {
2656
2905
  type: "range",
@@ -2663,10 +2912,10 @@ var ImageEditor = ({
2663
2912
  )
2664
2913
  ] })
2665
2914
  ] }),
2666
- /* @__PURE__ */ jsx10("div", { className: "h-px bg-slate-800 my-1" }),
2667
- /* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
2668
- /* @__PURE__ */ jsxs10("div", { className: "flex gap-2", children: [
2669
- /* @__PURE__ */ jsx10(
2915
+ /* @__PURE__ */ jsx11("div", { className: "h-px bg-slate-800 my-1" }),
2916
+ /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
2917
+ /* @__PURE__ */ jsxs11("div", { className: "flex gap-2", children: [
2918
+ /* @__PURE__ */ jsx11(
2670
2919
  "input",
2671
2920
  {
2672
2921
  type: "text",
@@ -2677,7 +2926,7 @@ var ImageEditor = ({
2677
2926
  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"
2678
2927
  }
2679
2928
  ),
2680
- /* @__PURE__ */ jsx10(
2929
+ /* @__PURE__ */ jsx11(
2681
2930
  "button",
2682
2931
  {
2683
2932
  type: "button",
@@ -2687,14 +2936,14 @@ var ImageEditor = ({
2687
2936
  }
2688
2937
  )
2689
2938
  ] }),
2690
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between text-slate-400", children: [
2691
- /* @__PURE__ */ jsx10("span", { children: "Font Size:" }),
2692
- /* @__PURE__ */ jsxs10("span", { className: "font-mono", children: [
2939
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between text-slate-400", children: [
2940
+ /* @__PURE__ */ jsx11("span", { children: "Font Size:" }),
2941
+ /* @__PURE__ */ jsxs11("span", { className: "font-mono", children: [
2693
2942
  fontSize,
2694
2943
  "px"
2695
2944
  ] })
2696
2945
  ] }),
2697
- /* @__PURE__ */ jsx10(
2946
+ /* @__PURE__ */ jsx11(
2698
2947
  "input",
2699
2948
  {
2700
2949
  type: "range",
@@ -2705,14 +2954,14 @@ var ImageEditor = ({
2705
2954
  className: "w-full accent-indigo-500"
2706
2955
  }
2707
2956
  ),
2708
- /* @__PURE__ */ jsx10("div", { className: "h-px bg-slate-800 my-1" }),
2709
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
2710
- /* @__PURE__ */ jsxs10("span", { className: "text-slate-400", children: [
2957
+ /* @__PURE__ */ jsx11("div", { className: "h-px bg-slate-800 my-1" }),
2958
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
2959
+ /* @__PURE__ */ jsxs11("span", { className: "text-slate-400", children: [
2711
2960
  "Layers (",
2712
2961
  state.annotations.length,
2713
2962
  ")"
2714
2963
  ] }),
2715
- state.selectedAnnotationId && /* @__PURE__ */ jsx10(
2964
+ state.selectedAnnotationId && /* @__PURE__ */ jsx11(
2716
2965
  "button",
2717
2966
  {
2718
2967
  type: "button",
@@ -2721,7 +2970,7 @@ var ImageEditor = ({
2721
2970
  children: "Delete Selected"
2722
2971
  }
2723
2972
  ),
2724
- state.annotations.length > 0 && /* @__PURE__ */ jsx10(
2973
+ state.annotations.length > 0 && /* @__PURE__ */ jsx11(
2725
2974
  "button",
2726
2975
  {
2727
2976
  type: "button",
@@ -2732,10 +2981,10 @@ var ImageEditor = ({
2732
2981
  )
2733
2982
  ] })
2734
2983
  ] }),
2735
- activeTab === "depth" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3 text-xs", children: [
2736
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
2737
- /* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
2738
- /* @__PURE__ */ jsx10(
2984
+ activeTab === "depth" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
2985
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
2986
+ /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
2987
+ /* @__PURE__ */ jsx11(
2739
2988
  "button",
2740
2989
  {
2741
2990
  type: "button",
@@ -2745,8 +2994,8 @@ var ImageEditor = ({
2745
2994
  }
2746
2995
  )
2747
2996
  ] }),
2748
- /* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
2749
- /* @__PURE__ */ jsx10(
2997
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
2998
+ /* @__PURE__ */ jsx11(
2750
2999
  "input",
2751
3000
  {
2752
3001
  type: "checkbox",
@@ -2755,12 +3004,12 @@ var ImageEditor = ({
2755
3004
  className: "rounded accent-indigo-500"
2756
3005
  }
2757
3006
  ),
2758
- /* @__PURE__ */ jsx10("span", { children: "Enable Depth / Alpha Mask" })
3007
+ /* @__PURE__ */ jsx11("span", { children: "Enable Depth / Alpha Mask" })
2759
3008
  ] }),
2760
- state.depthMask.enabled && /* @__PURE__ */ jsxs10(Fragment3, { children: [
2761
- /* @__PURE__ */ jsxs10("div", { children: [
2762
- /* @__PURE__ */ jsx10("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
2763
- /* @__PURE__ */ jsx10(
3009
+ state.depthMask.enabled && /* @__PURE__ */ jsxs11(Fragment3, { children: [
3010
+ /* @__PURE__ */ jsxs11("div", { children: [
3011
+ /* @__PURE__ */ jsx11("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
3012
+ /* @__PURE__ */ jsx11(
2764
3013
  "input",
2765
3014
  {
2766
3015
  type: "text",
@@ -2771,8 +3020,8 @@ var ImageEditor = ({
2771
3020
  }
2772
3021
  )
2773
3022
  ] }),
2774
- /* @__PURE__ */ jsxs10("div", { className: "flex gap-2", children: [
2775
- /* @__PURE__ */ jsx10(
3023
+ /* @__PURE__ */ jsxs11("div", { className: "flex gap-2", children: [
3024
+ /* @__PURE__ */ jsx11(
2776
3025
  "button",
2777
3026
  {
2778
3027
  type: "button",
@@ -2781,7 +3030,7 @@ var ImageEditor = ({
2781
3030
  children: "Threshold Mode"
2782
3031
  }
2783
3032
  ),
2784
- /* @__PURE__ */ jsx10(
3033
+ /* @__PURE__ */ jsx11(
2785
3034
  "button",
2786
3035
  {
2787
3036
  type: "button",
@@ -2791,12 +3040,12 @@ var ImageEditor = ({
2791
3040
  }
2792
3041
  )
2793
3042
  ] }),
2794
- /* @__PURE__ */ jsxs10("div", { children: [
2795
- /* @__PURE__ */ jsxs10("div", { className: "flex justify-between text-slate-400 mb-1", children: [
2796
- /* @__PURE__ */ jsx10("span", { children: "Depth Start (Lower):" }),
2797
- /* @__PURE__ */ jsx10("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
3043
+ /* @__PURE__ */ jsxs11("div", { children: [
3044
+ /* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3045
+ /* @__PURE__ */ jsx11("span", { children: "Depth Start (Lower):" }),
3046
+ /* @__PURE__ */ jsx11("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
2798
3047
  ] }),
2799
- /* @__PURE__ */ jsx10(
3048
+ /* @__PURE__ */ jsx11(
2800
3049
  "input",
2801
3050
  {
2802
3051
  type: "range",
@@ -2810,12 +3059,12 @@ var ImageEditor = ({
2810
3059
  }
2811
3060
  )
2812
3061
  ] }),
2813
- /* @__PURE__ */ jsxs10("div", { children: [
2814
- /* @__PURE__ */ jsxs10("div", { className: "flex justify-between text-slate-400 mb-1", children: [
2815
- /* @__PURE__ */ jsx10("span", { children: "Depth Stop (Upper):" }),
2816
- /* @__PURE__ */ jsx10("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
3062
+ /* @__PURE__ */ jsxs11("div", { children: [
3063
+ /* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3064
+ /* @__PURE__ */ jsx11("span", { children: "Depth Stop (Upper):" }),
3065
+ /* @__PURE__ */ jsx11("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
2817
3066
  ] }),
2818
- /* @__PURE__ */ jsx10(
3067
+ /* @__PURE__ */ jsx11(
2819
3068
  "input",
2820
3069
  {
2821
3070
  type: "range",
@@ -2829,12 +3078,12 @@ var ImageEditor = ({
2829
3078
  }
2830
3079
  )
2831
3080
  ] }),
2832
- /* @__PURE__ */ jsxs10("div", { children: [
2833
- /* @__PURE__ */ jsxs10("div", { className: "flex justify-between text-slate-400 mb-1", children: [
2834
- /* @__PURE__ */ jsx10("span", { children: "Softness:" }),
2835
- /* @__PURE__ */ jsx10("span", { className: "font-mono", children: state.depthMask.softness })
3081
+ /* @__PURE__ */ jsxs11("div", { children: [
3082
+ /* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3083
+ /* @__PURE__ */ jsx11("span", { children: "Softness:" }),
3084
+ /* @__PURE__ */ jsx11("span", { className: "font-mono", children: state.depthMask.softness })
2836
3085
  ] }),
2837
- /* @__PURE__ */ jsx10(
3086
+ /* @__PURE__ */ jsx11(
2838
3087
  "input",
2839
3088
  {
2840
3089
  type: "range",
@@ -2846,8 +3095,8 @@ var ImageEditor = ({
2846
3095
  }
2847
3096
  )
2848
3097
  ] }),
2849
- /* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
2850
- /* @__PURE__ */ jsx10(
3098
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
3099
+ /* @__PURE__ */ jsx11(
2851
3100
  "input",
2852
3101
  {
2853
3102
  type: "checkbox",
@@ -2856,12 +3105,12 @@ var ImageEditor = ({
2856
3105
  className: "rounded accent-indigo-500"
2857
3106
  }
2858
3107
  ),
2859
- /* @__PURE__ */ jsx10("span", { children: "Invert Mask" })
3108
+ /* @__PURE__ */ jsx11("span", { children: "Invert Mask" })
2860
3109
  ] })
2861
3110
  ] })
2862
3111
  ] }),
2863
- activeTab === "select" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-4 text-xs", children: [
2864
- /* @__PURE__ */ jsx10(
3112
+ activeTab === "select" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-4 text-xs", children: [
3113
+ /* @__PURE__ */ jsx11(
2865
3114
  SelectionOptionsBar,
2866
3115
  {
2867
3116
  controller,
@@ -2871,13 +3120,37 @@ var ImageEditor = ({
2871
3120
  quickMask: Boolean(state.quickMask)
2872
3121
  }
2873
3122
  ),
2874
- selectionError && /* @__PURE__ */ jsx10("p", { role: "alert", className: "text-rose-400", children: selectionError }),
2875
- /* @__PURE__ */ jsx10(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
3123
+ selectionError && /* @__PURE__ */ jsx11("p", { role: "alert", className: "text-rose-400", children: selectionError }),
3124
+ /* @__PURE__ */ jsxs11("div", { className: "flex gap-1", children: [
3125
+ /* @__PURE__ */ jsx11(
3126
+ "button",
3127
+ {
3128
+ type: "button",
3129
+ title: "Select \u203A Transform Selection: the outline only",
3130
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
3131
+ disabled: transformTool.active,
3132
+ onClick: () => transformTool.begin({ content: "selection-outline" }),
3133
+ children: "Transform Selection"
3134
+ }
3135
+ ),
3136
+ /* @__PURE__ */ jsx11(
3137
+ "button",
3138
+ {
3139
+ type: "button",
3140
+ title: "Edit \u203A Free Transform: the selected pixels of the active layer",
3141
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
3142
+ disabled: transformTool.active,
3143
+ onClick: () => transformTool.begin({ content: "selection" }),
3144
+ children: "Free Transform Pixels"
3145
+ }
3146
+ )
3147
+ ] }),
3148
+ /* @__PURE__ */ jsx11(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
2876
3149
  ] }),
2877
- activeTab === "ai" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-4 text-xs", children: [
2878
- /* @__PURE__ */ jsxs10("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
2879
- /* @__PURE__ */ jsx10("span", { children: "Results go to" }),
2880
- /* @__PURE__ */ jsxs10(
3150
+ activeTab === "ai" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-4 text-xs", children: [
3151
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
3152
+ /* @__PURE__ */ jsx11("span", { children: "Results go to" }),
3153
+ /* @__PURE__ */ jsxs11(
2881
3154
  "select",
2882
3155
  {
2883
3156
  "aria-label": "AI result target",
@@ -2885,54 +3158,54 @@ var ImageEditor = ({
2885
3158
  onChange: (e) => setAiTarget(e.target.value),
2886
3159
  className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
2887
3160
  children: [
2888
- /* @__PURE__ */ jsx10("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
2889
- /* @__PURE__ */ jsx10("option", { value: "new-layer", children: "New layer / mask" }),
2890
- /* @__PURE__ */ jsx10("option", { value: "replace", children: "Replace image" })
3161
+ /* @__PURE__ */ jsx11("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
3162
+ /* @__PURE__ */ jsx11("option", { value: "new-layer", children: "New layer / mask" }),
3163
+ /* @__PURE__ */ jsx11("option", { value: "replace", children: "Replace image" })
2891
3164
  ]
2892
3165
  }
2893
3166
  )
2894
3167
  ] }),
2895
- /* @__PURE__ */ jsxs10("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
2896
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
2897
- /* @__PURE__ */ jsxs10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
2898
- /* @__PURE__ */ jsx10("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx10("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" }) }),
3168
+ /* @__PURE__ */ jsxs11("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3169
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
3170
+ /* @__PURE__ */ jsxs11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3171
+ /* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("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" }) }),
2899
3172
  "Background Removal"
2900
3173
  ] }),
2901
- isRemovingBg && /* @__PURE__ */ jsx10("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..." })
3174
+ isRemovingBg && /* @__PURE__ */ jsx11("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..." })
2902
3175
  ] }),
2903
- /* @__PURE__ */ jsx10("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
2904
- /* @__PURE__ */ jsx10(
3176
+ /* @__PURE__ */ jsx11("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
3177
+ /* @__PURE__ */ jsx11(
2905
3178
  "button",
2906
3179
  {
2907
3180
  type: "button",
2908
3181
  onClick: handleRemoveBackground,
2909
3182
  disabled: isRemovingBg || isInpainting,
2910
3183
  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",
2911
- children: isRemovingBg ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
2912
- /* @__PURE__ */ jsx10("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3184
+ children: isRemovingBg ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
3185
+ /* @__PURE__ */ jsx11("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
2913
3186
  "Removing Background..."
2914
- ] }) : /* @__PURE__ */ jsxs10(Fragment3, { children: [
2915
- /* @__PURE__ */ jsx10("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx10("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" }) }),
3187
+ ] }) : /* @__PURE__ */ jsxs11(Fragment3, { children: [
3188
+ /* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("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" }) }),
2916
3189
  "Remove Background"
2917
3190
  ] })
2918
3191
  }
2919
3192
  )
2920
3193
  ] }),
2921
- /* @__PURE__ */ jsxs10("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
2922
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
2923
- /* @__PURE__ */ jsxs10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
2924
- /* @__PURE__ */ jsxs10("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
2925
- /* @__PURE__ */ jsx10("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" }),
2926
- /* @__PURE__ */ jsx10("path", { d: "m14 7 3 3" })
3194
+ /* @__PURE__ */ jsxs11("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3195
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
3196
+ /* @__PURE__ */ jsxs11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3197
+ /* @__PURE__ */ jsxs11("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
3198
+ /* @__PURE__ */ jsx11("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" }),
3199
+ /* @__PURE__ */ jsx11("path", { d: "m14 7 3 3" })
2927
3200
  ] }),
2928
3201
  "Generative Inpainting"
2929
3202
  ] }),
2930
- isInpainting && /* @__PURE__ */ jsx10("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..." })
3203
+ isInpainting && /* @__PURE__ */ jsx11("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..." })
2931
3204
  ] }),
2932
- /* @__PURE__ */ jsx10("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
2933
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-1", children: [
2934
- /* @__PURE__ */ jsx10("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
2935
- /* @__PURE__ */ jsx10(
3205
+ /* @__PURE__ */ jsx11("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
3206
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1", children: [
3207
+ /* @__PURE__ */ jsx11("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
3208
+ /* @__PURE__ */ jsx11(
2936
3209
  "textarea",
2937
3210
  {
2938
3211
  id: "ai-inpaint-prompt-react",
@@ -2944,10 +3217,10 @@ var ImageEditor = ({
2944
3217
  }
2945
3218
  )
2946
3219
  ] }),
2947
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-1", children: [
2948
- /* @__PURE__ */ jsx10("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
2949
- /* @__PURE__ */ jsxs10("div", { className: "grid grid-cols-2 gap-1.5", children: [
2950
- /* @__PURE__ */ jsxs10(
3220
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1", children: [
3221
+ /* @__PURE__ */ jsx11("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
3222
+ /* @__PURE__ */ jsxs11("div", { className: "grid grid-cols-2 gap-1.5", children: [
3223
+ /* @__PURE__ */ jsxs11(
2951
3224
  "button",
2952
3225
  {
2953
3226
  type: "button",
@@ -2960,7 +3233,7 @@ var ImageEditor = ({
2960
3233
  ]
2961
3234
  }
2962
3235
  ),
2963
- /* @__PURE__ */ jsxs10(
3236
+ /* @__PURE__ */ jsxs11(
2964
3237
  "button",
2965
3238
  {
2966
3239
  type: "button",
@@ -2975,25 +3248,25 @@ var ImageEditor = ({
2975
3248
  )
2976
3249
  ] })
2977
3250
  ] }),
2978
- /* @__PURE__ */ jsx10(
3251
+ /* @__PURE__ */ jsx11(
2979
3252
  "button",
2980
3253
  {
2981
3254
  type: "button",
2982
3255
  onClick: handleInpaint,
2983
3256
  disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
2984
3257
  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",
2985
- children: isInpainting ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
2986
- /* @__PURE__ */ jsx10("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3258
+ children: isInpainting ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
3259
+ /* @__PURE__ */ jsx11("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
2987
3260
  "Generating Inpaint..."
2988
- ] }) : /* @__PURE__ */ jsxs10(Fragment3, { children: [
2989
- /* @__PURE__ */ jsx10("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx10("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" }) }),
3261
+ ] }) : /* @__PURE__ */ jsxs11(Fragment3, { children: [
3262
+ /* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("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" }) }),
2990
3263
  "Apply Inpainting"
2991
3264
  ] })
2992
3265
  }
2993
3266
  )
2994
3267
  ] }),
2995
- aiError && /* @__PURE__ */ jsx10("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
2996
- aiSuccess && /* @__PURE__ */ jsx10("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
3268
+ aiError && /* @__PURE__ */ jsx11("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
3269
+ aiSuccess && /* @__PURE__ */ jsx11("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
2997
3270
  ] })
2998
3271
  ] })
2999
3272
  ] })
@@ -3014,6 +3287,7 @@ export {
3014
3287
  BrushOptionsBar,
3015
3288
  SelectionOptionsBar,
3016
3289
  RefineEdgePanel,
3290
+ FreeTransformOptionsBar,
3017
3291
  ImageEditor
3018
3292
  };
3019
- //# sourceMappingURL=chunk-M4WLX3IR.js.map
3293
+ //# sourceMappingURL=chunk-LCTQWNTL.js.map