@pixerate/editor-react 0.70.0 → 0.72.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.
@@ -41,6 +41,8 @@ __export(image_editor_exports, {
41
41
  LayersPanel: () => LayersPanel,
42
42
  RefineEdgePanel: () => RefineEdgePanel,
43
43
  SelectionOptionsBar: () => SelectionOptionsBar,
44
+ ShapeOptionsBar: () => ShapeOptionsBar,
45
+ TypeOptionsBar: () => TypeOptionsBar,
44
46
  useImageEditor: () => useImageEditor,
45
47
  useImageHistogram: () => useImageHistogram
46
48
  });
@@ -205,8 +207,8 @@ function useImageEditor(options = {}) {
205
207
  }
206
208
 
207
209
  // src/image-editor/ImageEditor.tsx
208
- var import_react11 = __toESM(require("react"), 1);
209
- var import_image_editor12 = require("@pixerate/editor/image-editor");
210
+ var import_react13 = __toESM(require("react"), 1);
211
+ var import_image_editor14 = require("@pixerate/editor/image-editor");
210
212
 
211
213
  // src/image-editor/ControlSlider.tsx
212
214
  var import_image_editor2 = require("@pixerate/editor/image-editor");
@@ -916,7 +918,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
916
918
  const placement = (0, import_image_editor7.dropPlacement)(state.layers, id, row.layer.id, (0, import_image_editor7.dropZone)(fraction, row.layer.type === "group"));
917
919
  if (placement) attempt(() => controller.moveLayer(id, placement));
918
920
  };
919
- const thumb = (layer) => layer.type === "pixel" ? controller.getLayerThumbnail(layer.id, { maxSide: 64 }) : null;
921
+ const thumb = (layer) => (0, import_image_editor7.layerHasThumbnail)(layer) ? controller.getLayerThumbnail(layer.id, { maxSide: 64 }) : null;
920
922
  const maskThumb = (layer) => layer.mask && !layer.mask.source ? controller.getLayerThumbnail(layer.id, { maxSide: 64, mask: true }) : null;
921
923
  const locked = (layer) => Boolean(layer.locks?.all || layer.locks?.pixels || layer.locks?.position || layer.locks?.transparency);
922
924
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layers-panel", onClick: () => menu && setMenu(null), children: [
@@ -1109,15 +1111,25 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
1109
1111
  }
1110
1112
  ),
1111
1113
  row.clipped && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-slate-500", "aria-label": "Clipped", children: "\u21B3" }),
1112
- layer.type === "pixel" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1113
- Thumbnail,
1114
- {
1115
- pixels: thumb(layer),
1116
- size: thumbnailSize,
1117
- label: `${row.label} pixels`,
1118
- selected: row.active && state.activeTarget === "pixels" && Boolean(layer.mask)
1119
- }
1120
- ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1114
+ (0, import_image_editor7.layerHasThumbnail)(layer) ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "relative shrink-0", children: [
1115
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1116
+ Thumbnail,
1117
+ {
1118
+ pixels: thumb(layer),
1119
+ size: thumbnailSize,
1120
+ label: `${row.label} pixels`,
1121
+ selected: row.active && state.activeTarget === "pixels" && Boolean(layer.mask)
1122
+ }
1123
+ ),
1124
+ layer.type !== "pixel" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1125
+ "span",
1126
+ {
1127
+ "data-testid": "layer-kind-badge",
1128
+ className: "absolute -bottom-1 -right-1 rounded bg-slate-700 px-0.5 text-[8px] font-bold leading-tight text-slate-100 ring-1 ring-slate-900",
1129
+ children: (0, import_image_editor7.layerBadge)(layer)
1130
+ }
1131
+ )
1132
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1121
1133
  "span",
1122
1134
  {
1123
1135
  className: "shrink-0 grid place-items-center rounded bg-slate-800 text-[9px] text-slate-400 ring-1 ring-slate-700",
@@ -1184,6 +1196,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
1184
1196
  children: row.label
1185
1197
  }
1186
1198
  ),
1199
+ (0, import_image_editor7.layerWarning)(layer) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { role: "img", "data-testid": "layer-warning", "aria-label": (0, import_image_editor7.layerWarning)(layer), title: (0, import_image_editor7.layerWarning)(layer), className: "text-[10px] text-amber-400", children: "\u26A0" }),
1187
1200
  (0, import_image_editor7.layerEffectsBadge)(layer) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1188
1201
  "button",
1189
1202
  {
@@ -1243,7 +1256,8 @@ var BrushOptionsBar = ({ controller, className }) => {
1243
1256
  (0, import_react7.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
1244
1257
  const [error, setError] = (0, import_react7.useState)(null);
1245
1258
  const state = controller.getState();
1246
- const { brush, foreground, background, mixer, mixerLoad } = state.paint;
1259
+ const { brush, foreground, background, mixer, mixerLoad, retouch, cloneSource } = state.paint;
1260
+ const tool = state.activeTool;
1247
1261
  const attempt = (fn) => {
1248
1262
  try {
1249
1263
  setError(null);
@@ -1253,12 +1267,12 @@ var BrushOptionsBar = ({ controller, className }) => {
1253
1267
  }
1254
1268
  };
1255
1269
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
1256
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor8.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1270
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor8.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1257
1271
  "button",
1258
1272
  {
1259
1273
  type: "button",
1260
1274
  "aria-pressed": state.activeTool === t.id,
1261
- title: `${t.label} (${t.shortcut})`,
1275
+ title: t.shortcut ? `${t.label} (${t.shortcut})` : t.label,
1262
1276
  className: chip(state.activeTool === t.id),
1263
1277
  onClick: () => controller.setTool(t.id),
1264
1278
  children: t.label
@@ -1360,6 +1374,41 @@ var BrushOptionsBar = ({ controller, className }) => {
1360
1374
  ] })
1361
1375
  ] })
1362
1376
  ] }),
1377
+ (0, import_image_editor8.isRetouchPaintTool)(tool) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Retouch options", "data-testid": "retouch-options", children: [
1378
+ (tool === "clone" || tool === "heal") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
1379
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-slate-400", "data-testid": "clone-source", children: (0, import_image_editor8.cloneSourceLabel)(controller) }),
1380
+ cloneSource && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", title: "Forget the source point", className: chip(false), onClick: () => controller.setCloneSource(null), children: "Clear source" })
1381
+ ] }),
1382
+ import_image_editor8.RETOUCH_CHOICES.filter((c) => c.tools.includes(tool)).map((choice) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": choice.label, children: [
1383
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-slate-400", children: choice.label }),
1384
+ choice.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1385
+ "button",
1386
+ {
1387
+ type: "button",
1388
+ "aria-pressed": retouch[choice.id] === o.id,
1389
+ title: o.title,
1390
+ className: chip(retouch[choice.id] === o.id),
1391
+ onClick: () => (0, import_image_editor8.setRetouchChoice)(controller, choice.id, o.id),
1392
+ children: o.label
1393
+ },
1394
+ o.id
1395
+ ))
1396
+ ] }, choice.id)),
1397
+ import_image_editor8.RETOUCH_OPTION_CONTROLS.filter((c) => c.tools.includes(tool)).map((spec) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ControlSlider, { spec, value: retouch[spec.id], onChange: (v) => controller.setPaintOptions({ retouch: { [spec.id]: v } }) }, spec.id)),
1398
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: import_image_editor8.RETOUCH_TOGGLES.filter((t) => t.tools.includes(tool)).map((t) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1.5", children: [
1399
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1400
+ "input",
1401
+ {
1402
+ type: "checkbox",
1403
+ "aria-label": t.label,
1404
+ checked: retouch[t.id],
1405
+ onChange: (e) => controller.setPaintOptions({ retouch: { [t.id]: e.target.checked } }),
1406
+ className: "accent-indigo-500"
1407
+ }
1408
+ ),
1409
+ t.label
1410
+ ] }, t.id)) })
1411
+ ] }),
1363
1412
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
1364
1413
  /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1.5", children: [
1365
1414
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
@@ -1791,8 +1840,215 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
1791
1840
  ] });
1792
1841
  };
1793
1842
 
1794
- // src/image-editor/ImageEditor.tsx
1843
+ // src/image-editor/ShapeOptionsBar.tsx
1844
+ var import_react11 = require("react");
1845
+ var import_image_editor12 = require("@pixerate/editor/image-editor");
1795
1846
  var import_jsx_runtime11 = require("react/jsx-runtime");
1847
+ var chip3 = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
1848
+ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
1849
+ const [, setTick] = (0, import_react11.useState)(0);
1850
+ (0, import_react11.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
1851
+ const [error, setError] = (0, import_react11.useState)(null);
1852
+ const active = controller.getActiveLayer();
1853
+ const shapeId = active?.type === "shape" ? active.id : null;
1854
+ const set = (change) => {
1855
+ onChange({ ...options, ...change });
1856
+ if (!shapeId) return;
1857
+ try {
1858
+ setError(null);
1859
+ (0, import_image_editor12.applyShapeOptions)(controller, shapeId, change);
1860
+ } catch (e) {
1861
+ setError(e instanceof Error ? e.message : String(e));
1862
+ }
1863
+ };
1864
+ const num = (v, min, max) => Math.max(min, Math.min(max, Number(v) || min));
1865
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "shape-options", children: [
1866
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Shape kind", children: import_image_editor12.LIVE_SHAPE_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", "aria-pressed": options.kind === k, className: chip3(options.kind === k), onClick: () => onChange({ ...options, kind: k }), children: import_image_editor12.SHAPE_KIND_LABELS[k] }, k)) }),
1867
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
1868
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1869
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { type: "checkbox", "aria-label": "Fill", checked: options.fill !== null, onChange: (e) => set({ fill: e.target.checked ? "#4f46e5" : null }) }),
1870
+ "Fill",
1871
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1872
+ "input",
1873
+ {
1874
+ type: "color",
1875
+ "aria-label": "Fill colour",
1876
+ disabled: options.fill === null,
1877
+ value: options.fill ?? "#4f46e5",
1878
+ onChange: (e) => set({ fill: e.target.value }),
1879
+ className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
1880
+ }
1881
+ )
1882
+ ] }),
1883
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1884
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { type: "checkbox", "aria-label": "Stroke", checked: options.stroke !== null, onChange: (e) => set({ stroke: e.target.checked ? "#000000" : null }) }),
1885
+ "Stroke",
1886
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1887
+ "input",
1888
+ {
1889
+ type: "color",
1890
+ "aria-label": "Stroke colour",
1891
+ disabled: options.stroke === null,
1892
+ value: options.stroke ?? "#000000",
1893
+ onChange: (e) => set({ stroke: e.target.value }),
1894
+ className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
1895
+ }
1896
+ )
1897
+ ] }),
1898
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1899
+ "Width",
1900
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1901
+ "input",
1902
+ {
1903
+ type: "number",
1904
+ "aria-label": "Stroke width",
1905
+ min: 0,
1906
+ max: 200,
1907
+ value: options.strokeWidth,
1908
+ onChange: (e) => set({ strokeWidth: num(e.target.value, 0, 200) }),
1909
+ className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5"
1910
+ }
1911
+ )
1912
+ ] })
1913
+ ] }),
1914
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
1915
+ options.kind === "rect" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1916
+ "Radius",
1917
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { type: "number", "aria-label": "Corner radius", min: 0, max: 1e3, value: options.radius, onChange: (e) => set({ radius: num(e.target.value, 0, 1e3) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
1918
+ ] }),
1919
+ options.kind === "polygon" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1920
+ "Sides",
1921
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { type: "number", "aria-label": "Sides", min: 3, max: 100, value: options.sides, onChange: (e) => set({ sides: num(e.target.value, 3, 100) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
1922
+ ] }),
1923
+ options.kind === "star" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
1924
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1925
+ "Points",
1926
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { type: "number", "aria-label": "Points", min: 3, max: 100, value: options.points, onChange: (e) => set({ points: num(e.target.value, 3, 100) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
1927
+ ] }),
1928
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1929
+ "Inner",
1930
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1931
+ "input",
1932
+ {
1933
+ type: "range",
1934
+ "aria-label": "Inner radius",
1935
+ min: 0.05,
1936
+ max: 1,
1937
+ step: 0.05,
1938
+ value: options.innerRatio,
1939
+ onChange: (e) => set({ innerRatio: Number(e.target.value) }),
1940
+ className: "accent-indigo-500"
1941
+ }
1942
+ )
1943
+ ] })
1944
+ ] }),
1945
+ options.kind === "line" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
1946
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1947
+ "Weight",
1948
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { type: "number", "aria-label": "Line weight", min: 1, max: 200, value: options.weight, onChange: (e) => set({ weight: num(e.target.value, 1, 200) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
1949
+ ] }),
1950
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1951
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { type: "checkbox", "aria-label": "Arrowhead", checked: options.arrow, onChange: (e) => set({ arrow: e.target.checked }) }),
1952
+ "Arrowhead"
1953
+ ] })
1954
+ ] })
1955
+ ] }),
1956
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-[10px] text-slate-500", children: "Drag on the image to draw. Shift: square, circle or 45\xB0 line. Alt: from the centre." }),
1957
+ error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
1958
+ ] });
1959
+ };
1960
+
1961
+ // src/image-editor/TypeOptionsBar.tsx
1962
+ var import_react12 = require("react");
1963
+ var import_image_editor13 = require("@pixerate/editor/image-editor");
1964
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1965
+ var chip4 = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
1966
+ var ALIGN_LABELS = { left: "Left", center: "Centre", right: "Right", justify: "Justify" };
1967
+ var TypeOptionsBar = ({ controller, options, onChange, session, className }) => {
1968
+ const [, setTick] = (0, import_react12.useState)(0);
1969
+ (0, import_react12.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
1970
+ (0, import_react12.useEffect)(() => session?.subscribe(() => setTick((n) => n + 1)), [session]);
1971
+ const [error, setError] = (0, import_react12.useState)(null);
1972
+ const active = controller.getActiveLayer();
1973
+ const typeId = !session && active?.type === "type" ? active.id : null;
1974
+ const here = session?.alive ? session.styleHere() : {};
1975
+ const shown = {
1976
+ ...options,
1977
+ ...here.fontFamily ? { fontFamily: here.fontFamily } : {},
1978
+ ...here.fontSize ? { fontSize: here.fontSize } : {},
1979
+ ...here.fontWeight ? { fontWeight: here.fontWeight } : {},
1980
+ ...session?.alive ? { italic: Boolean(here.italic), color: here.color ?? options.color } : {}
1981
+ };
1982
+ const fonts = controller.listFonts();
1983
+ const missing = active?.type === "type" ? active.missingFonts ?? [] : [];
1984
+ const style = (change) => {
1985
+ onChange({ ...options, ...change });
1986
+ const s = {};
1987
+ for (const k of ["fontFamily", "fontSize", "fontWeight", "italic", "color"]) if (k in change) s[k] = change[k];
1988
+ const p = change.align ? { align: change.align } : null;
1989
+ try {
1990
+ setError(null);
1991
+ if (session?.alive) {
1992
+ if (Object.keys(s).length) session.setStyle(s);
1993
+ if (p) session.setParagraph(p);
1994
+ if (session.error) setError(session.error);
1995
+ } else if (typeId) {
1996
+ if (Object.keys(s).length) controller.setTextStyle(typeId, s);
1997
+ if (p) controller.setParagraphStyle(typeId, p);
1998
+ }
1999
+ } catch (e) {
2000
+ setError(e instanceof Error ? e.message : String(e));
2001
+ }
2002
+ };
2003
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "type-options", children: [
2004
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
2005
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-1", children: [
2006
+ "Font",
2007
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2008
+ "input",
2009
+ {
2010
+ list: "pixerate-type-fonts",
2011
+ "aria-label": "Font family",
2012
+ value: shown.fontFamily,
2013
+ onChange: (e) => e.target.value.trim() && style({ fontFamily: e.target.value }),
2014
+ className: "w-32 rounded border border-slate-700 bg-slate-950 px-1 py-0.5"
2015
+ }
2016
+ ),
2017
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("datalist", { id: "pixerate-type-fonts", children: fonts.map((f) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: f }, f)) })
2018
+ ] }),
2019
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-1", children: [
2020
+ "Size",
2021
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2022
+ "input",
2023
+ {
2024
+ type: "number",
2025
+ "aria-label": "Font size",
2026
+ min: 1,
2027
+ max: 2e3,
2028
+ value: Math.round(shown.fontSize * 10) / 10,
2029
+ onChange: (e) => Number(e.target.value) > 0 && style({ fontSize: Number(e.target.value) }),
2030
+ className: "w-16 rounded border border-slate-700 bg-slate-950 px-1 py-0.5"
2031
+ }
2032
+ )
2033
+ ] }),
2034
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", "aria-pressed": shown.fontWeight >= 600, className: `${chip4(shown.fontWeight >= 600)} font-bold`, onClick: () => style({ fontWeight: shown.fontWeight >= 600 ? 400 : 700 }), children: "B" }),
2035
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", "aria-pressed": shown.italic, className: `${chip4(shown.italic)} italic`, onClick: () => style({ italic: !shown.italic }), children: "I" }),
2036
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("input", { type: "color", "aria-label": "Text colour", value: shown.color, onChange: (e) => style({ color: e.target.value }), className: "h-6 w-8 rounded border border-slate-700 bg-transparent" })
2037
+ ] }),
2038
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Alignment", children: import_image_editor13.TEXT_ALIGNS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", "aria-pressed": options.align === a, className: chip4(options.align === a), onClick: () => style({ align: a }), children: ALIGN_LABELS[a] }, a)) }),
2039
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-[10px] text-slate-500", children: "Click to type point text, drag for a paragraph box, click text to edit it. Esc finishes." }),
2040
+ missing.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { role: "status", className: "text-amber-400", "data-testid": "type-missing-fonts", children: [
2041
+ "Missing ",
2042
+ missing.length === 1 ? "font" : "fonts",
2043
+ ": ",
2044
+ missing.join(", ")
2045
+ ] }),
2046
+ error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
2047
+ ] });
2048
+ };
2049
+
2050
+ // src/image-editor/ImageEditor.tsx
2051
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1796
2052
  var ImageEditor = ({
1797
2053
  editor: externalEditor,
1798
2054
  src,
@@ -1807,47 +2063,65 @@ var ImageEditor = ({
1807
2063
  const internalEditor = useImageEditor({ image: src });
1808
2064
  const editor = externalEditor || internalEditor;
1809
2065
  const { state, controller } = editor;
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);
2066
+ const legacyProcess = (0, import_image_editor14.normalizeProcessVersion)(state.adjustments.process) < import_image_editor14.LATEST_PROCESS_VERSION;
2067
+ const canvasRef = (0, import_react13.useRef)(null);
2068
+ const containerRef = (0, import_react13.useRef)(null);
2069
+ const [activeTab, setActiveTab] = (0, import_react13.useState)("crop");
2070
+ const [activeCropRatio, setActiveCropRatio] = (0, import_react13.useState)(null);
2071
+ const [selectionOptions, setSelectionOptions] = (0, import_react13.useState)(import_image_editor14.DEFAULT_SELECTION_TOOL_OPTIONS);
2072
+ const selectionOptionsRef = (0, import_react13.useRef)(selectionOptions);
1817
2073
  selectionOptionsRef.current = selectionOptions;
1818
- const selectionGestureRef = (0, import_react11.useRef)(null);
2074
+ const selectionGestureRef = (0, import_react13.useRef)(null);
1819
2075
  if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
1820
- selectionGestureRef.current = new import_image_editor12.SelectionGesture(controller, () => selectionOptionsRef.current);
2076
+ selectionGestureRef.current = new import_image_editor14.SelectionGesture(controller, () => selectionOptionsRef.current);
1821
2077
  }
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);
2078
+ const selectionDraftRef = (0, import_react13.useRef)(null);
2079
+ const [selectionError, setSelectionError] = (0, import_react13.useState)(null);
2080
+ const paintGestureRef = (0, import_react13.useRef)(null);
2081
+ const paintControllerRef = (0, import_react13.useRef)(controller);
1826
2082
  if (!paintGestureRef.current || paintControllerRef.current !== controller) {
1827
- paintGestureRef.current = new import_image_editor12.PaintGesture(controller);
2083
+ paintGestureRef.current = new import_image_editor14.PaintGesture(controller);
1828
2084
  paintControllerRef.current = controller;
1829
2085
  }
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);
2086
+ const brushCursorRef = (0, import_react13.useRef)(null);
2087
+ const [paintError, setPaintError] = (0, import_react13.useState)(null);
2088
+ const transformToolRef = (0, import_react13.useRef)(null);
2089
+ const transformControllerRef = (0, import_react13.useRef)(controller);
1834
2090
  if (!transformToolRef.current || transformControllerRef.current !== controller) {
1835
2091
  transformToolRef.current?.cancel();
1836
- transformToolRef.current = new import_image_editor12.FreeTransformTool(controller, {
2092
+ transformToolRef.current = new import_image_editor14.FreeTransformTool(controller, {
1837
2093
  schedule: (run) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(run) : run()
1838
2094
  });
1839
2095
  transformControllerRef.current = controller;
1840
2096
  }
1841
2097
  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");
2098
+ const [, setTransformTick] = (0, import_react13.useState)(0);
2099
+ const [transformCursor, setTransformCursor] = (0, import_react13.useState)("default");
2100
+ const [shapeOptions, setShapeOptions] = (0, import_react13.useState)(import_image_editor14.DEFAULT_SHAPE_TOOL_OPTIONS);
2101
+ const shapeOptionsRef = (0, import_react13.useRef)(shapeOptions);
2102
+ shapeOptionsRef.current = shapeOptions;
2103
+ const [typeOptions, setTypeOptions] = (0, import_react13.useState)(import_image_editor14.DEFAULT_TYPE_TOOL_OPTIONS);
2104
+ const typeOptionsRef = (0, import_react13.useRef)(typeOptions);
2105
+ typeOptionsRef.current = typeOptions;
2106
+ const shapeGestureRef = (0, import_react13.useRef)(null);
2107
+ const typeToolRef = (0, import_react13.useRef)(null);
2108
+ const shapeTypeControllerRef = (0, import_react13.useRef)(controller);
2109
+ if (!shapeGestureRef.current || !typeToolRef.current || shapeTypeControllerRef.current !== controller) {
2110
+ typeToolRef.current?.finish();
2111
+ shapeGestureRef.current = new import_image_editor14.ShapeDrawGesture(controller, () => shapeOptionsRef.current);
2112
+ typeToolRef.current = new import_image_editor14.TypeToolGesture(controller, () => typeOptionsRef.current);
2113
+ shapeTypeControllerRef.current = controller;
2114
+ }
2115
+ const typeInputRef = (0, import_react13.useRef)(null);
2116
+ const [typeSession, setTypeSession] = (0, import_react13.useState)(typeToolRef.current.session);
2117
+ const [shapeTypeError, setShapeTypeError] = (0, import_react13.useState)(null);
2118
+ const [inpaintPrompt, setInpaintPrompt] = (0, import_react13.useState)("");
2119
+ const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react13.useState)("annotations");
2120
+ const [isRemovingBg, setIsRemovingBg] = (0, import_react13.useState)(false);
2121
+ const [isInpainting, setIsInpainting] = (0, import_react13.useState)(false);
2122
+ const [aiError, setAiError] = (0, import_react13.useState)(null);
2123
+ const [aiSuccess, setAiSuccess] = (0, import_react13.useState)(null);
2124
+ const [aiTarget, setAiTarget] = (0, import_react13.useState)("auto");
1851
2125
  const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
1852
2126
  const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
1853
2127
  const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
@@ -1910,18 +2184,18 @@ var ImageEditor = ({
1910
2184
  setIsInpainting(false);
1911
2185
  }
1912
2186
  };
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)(
2187
+ const [activeColor, setActiveColor] = (0, import_react13.useState)("#ef4444");
2188
+ const [strokeWidth, setStrokeWidth] = (0, import_react13.useState)(3);
2189
+ const [fontSize, setFontSize] = (0, import_react13.useState)(24);
2190
+ const [textInput, setTextInput] = (0, import_react13.useState)("");
2191
+ const draftAnnotationRef = (0, import_react13.useRef)(null);
2192
+ const draftCropRef = (0, import_react13.useRef)(null);
2193
+ const cropDragInfoRef = (0, import_react13.useRef)(null);
2194
+ const annotationDragInfoRef = (0, import_react13.useRef)(null);
2195
+ const isDrawingRef = (0, import_react13.useRef)(false);
2196
+ const currentPathRef = (0, import_react13.useRef)([]);
2197
+ const dragStartPointRef = (0, import_react13.useRef)(null);
2198
+ const renderCanvas = (0, import_react13.useCallback)(
1925
2199
  async (draftAnnotation, draftCrop) => {
1926
2200
  const canvas = canvasRef.current;
1927
2201
  const container = containerRef.current;
@@ -1938,12 +2212,49 @@ var ImageEditor = ({
1938
2212
  draftCrop: draftCrop !== void 0 ? draftCrop : draftCropRef.current,
1939
2213
  draftSelectionPath: selectionDraftRef.current,
1940
2214
  brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" && !transformTool.active ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null,
1941
- freeTransform: transformTool.overlay()
2215
+ freeTransform: transformTool.overlay(),
2216
+ textEdit: typeToolRef.current?.session?.alive ? typeToolRef.current.session.overlay() : null
1942
2217
  });
1943
2218
  },
1944
2219
  [controller, activeTab, transformTool]
1945
2220
  );
1946
- (0, import_react11.useEffect)(() => transformTool.subscribe(() => {
2221
+ (0, import_react13.useEffect)(() => typeSession?.subscribe(() => void renderCanvas()), [typeSession, renderCanvas]);
2222
+ (0, import_react13.useEffect)(() => {
2223
+ if (activeTab === "annotate" && state.activeTool === "type") return;
2224
+ if (typeToolRef.current?.session) {
2225
+ typeToolRef.current.finish();
2226
+ setTypeSession(null);
2227
+ void renderCanvas();
2228
+ }
2229
+ }, [activeTab, state.activeTool, renderCanvas]);
2230
+ const finishTyping = () => {
2231
+ typeToolRef.current?.finish();
2232
+ setTypeSession(null);
2233
+ void renderCanvas();
2234
+ };
2235
+ const handleTypeKeyDown = (e) => {
2236
+ const session = typeToolRef.current?.session;
2237
+ if (!session || e.nativeEvent.isComposing) return;
2238
+ if (e.key === "Escape") {
2239
+ e.preventDefault();
2240
+ finishTyping();
2241
+ return;
2242
+ }
2243
+ if ((e.metaKey || e.ctrlKey) && ["z", "y", "c", "x", "v"].includes(e.key.toLowerCase())) return;
2244
+ if (session.handleKey(e)) {
2245
+ e.preventDefault();
2246
+ setShapeTypeError(session.error);
2247
+ }
2248
+ };
2249
+ const handleTypeInput = (e) => {
2250
+ const el = e.currentTarget;
2251
+ const session = typeToolRef.current?.session;
2252
+ if (session && el.value && !e.nativeEvent.isComposing) {
2253
+ session.insert(el.value);
2254
+ el.value = "";
2255
+ }
2256
+ };
2257
+ (0, import_react13.useEffect)(() => transformTool.subscribe(() => {
1947
2258
  setTransformTick((n) => n + 1);
1948
2259
  void renderCanvas();
1949
2260
  }), [transformTool, renderCanvas]);
@@ -1954,8 +2265,8 @@ var ImageEditor = ({
1954
2265
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
1955
2266
  const s = controller.getState();
1956
2267
  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);
2268
+ const projection = (0, import_image_editor14.getViewportProjection)(s, canvas.width, canvas.height, cropping);
2269
+ const pt = (0, import_image_editor14.canvasToImagePoint)({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
1959
2270
  transformTool.setView(projection.scale);
1960
2271
  return { pt, tolerance: 6 / (projection.scale || 1) };
1961
2272
  };
@@ -1986,7 +2297,7 @@ var ImageEditor = ({
1986
2297
  transformTool.up();
1987
2298
  return true;
1988
2299
  };
1989
- (0, import_react11.useEffect)(() => {
2300
+ (0, import_react13.useEffect)(() => {
1990
2301
  if (typeof window === "undefined") return;
1991
2302
  const onKey = (e) => {
1992
2303
  if (transformTool.key(e)) e.preventDefault();
@@ -1994,7 +2305,7 @@ var ImageEditor = ({
1994
2305
  window.addEventListener("keydown", onKey);
1995
2306
  return () => window.removeEventListener("keydown", onKey);
1996
2307
  }, [transformTool]);
1997
- (0, import_react11.useEffect)(() => {
2308
+ (0, import_react13.useEffect)(() => {
1998
2309
  const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
1999
2310
  const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
2000
2311
  const animId = raf(() => {
@@ -2002,12 +2313,12 @@ var ImageEditor = ({
2002
2313
  });
2003
2314
  return () => caf(animId);
2004
2315
  }, [renderCanvas, state]);
2005
- (0, import_react11.useEffect)(() => {
2316
+ (0, import_react13.useEffect)(() => {
2006
2317
  if (activeTab === "crop" && editor.state.activeTool !== "crop") {
2007
2318
  editor.setTool("crop");
2008
2319
  }
2009
2320
  }, [activeTab, editor]);
2010
- (0, import_react11.useEffect)(() => {
2321
+ (0, import_react13.useEffect)(() => {
2011
2322
  const container = containerRef.current;
2012
2323
  if (!container) return;
2013
2324
  if (typeof ResizeObserver !== "undefined") {
@@ -2043,8 +2354,8 @@ var ImageEditor = ({
2043
2354
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
2044
2355
  const s = controller.getState();
2045
2356
  return list.map((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)
2357
+ ...(0, import_image_editor14.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
2358
+ pressure: (0, import_image_editor14.pointerPressure)(ev)
2048
2359
  }));
2049
2360
  };
2050
2361
  const handlePaintPointerDown = (e) => {
@@ -2056,7 +2367,7 @@ var ImageEditor = ({
2056
2367
  } catch {
2057
2368
  }
2058
2369
  const [first] = paintSamples(e);
2059
- setPaintError(paintGestureRef.current.down(first));
2370
+ setPaintError(paintGestureRef.current.down({ ...first, altKey: e.altKey }));
2060
2371
  };
2061
2372
  const handlePaintPointerMove = (e) => {
2062
2373
  if (handleTransformPointerMove(e)) return;
@@ -2075,10 +2386,10 @@ var ImageEditor = ({
2075
2386
  if (g.error) setPaintError(g.error);
2076
2387
  }
2077
2388
  };
2078
- (0, import_react11.useEffect)(() => {
2389
+ (0, import_react13.useEffect)(() => {
2079
2390
  if (activeTab !== "paint" || typeof window === "undefined") return;
2080
2391
  const onKey = (e) => {
2081
- if ((0, import_image_editor12.handlePaintShortcut)(controller, e)) e.preventDefault();
2392
+ if ((0, import_image_editor14.handlePaintShortcut)(controller, e)) e.preventDefault();
2082
2393
  };
2083
2394
  window.addEventListener("keydown", onKey);
2084
2395
  return () => window.removeEventListener("keydown", onKey);
@@ -2089,7 +2400,7 @@ var ImageEditor = ({
2089
2400
  const canvasPt = getCanvasEventPoint(e);
2090
2401
  if (activeTab === "select") {
2091
2402
  const gesture = selectionGestureRef.current;
2092
- const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2403
+ const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2093
2404
  void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
2094
2405
  return;
2095
2406
  }
@@ -2100,8 +2411,8 @@ var ImageEditor = ({
2100
2411
  width: state.imageDimensions.width,
2101
2412
  height: state.imageDimensions.height
2102
2413
  };
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);
2414
+ const handle = (0, import_image_editor14.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
2415
+ const startImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
2105
2416
  if (handle) {
2106
2417
  cropDragInfoRef.current = {
2107
2418
  handle,
@@ -2119,13 +2430,24 @@ var ImageEditor = ({
2119
2430
  }
2120
2431
  return;
2121
2432
  }
2433
+ if (activeTab === "annotate" && (state.activeTool === "shape" || state.activeTool === "type")) {
2434
+ const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2435
+ setShapeTypeError(null);
2436
+ if (state.activeTool === "shape") shapeGestureRef.current.down(imgPt);
2437
+ else {
2438
+ typeToolRef.current.down(imgPt, { shift: e.shiftKey });
2439
+ setTypeSession(typeToolRef.current.session);
2440
+ void renderCanvas();
2441
+ }
2442
+ return;
2443
+ }
2122
2444
  if (activeTab === "annotate") {
2123
- const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2445
+ const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2124
2446
  dragStartPointRef.current = imgPt;
2125
2447
  if (state.activeTool === "select") {
2126
2448
  for (let i = state.annotations.length - 1; i >= 0; i--) {
2127
2449
  const ann = state.annotations[i];
2128
- if ((0, import_image_editor12.hitTestAnnotation)(imgPt, ann)) {
2450
+ if ((0, import_image_editor14.hitTestAnnotation)(imgPt, ann)) {
2129
2451
  editor.selectAnnotation(ann.id);
2130
2452
  annotationDragInfoRef.current = {
2131
2453
  annId: ann.id,
@@ -2161,7 +2483,7 @@ var ImageEditor = ({
2161
2483
  const canvasPt = getCanvasEventPoint(e);
2162
2484
  if (activeTab === "select") {
2163
2485
  const gesture = selectionGestureRef.current;
2164
- if (gesture.active && gesture.move((0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
2486
+ if (gesture.active && gesture.move((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
2165
2487
  selectionDraftRef.current = gesture.draftPath;
2166
2488
  renderCanvas();
2167
2489
  }
@@ -2170,7 +2492,7 @@ var ImageEditor = ({
2170
2492
  if (activeTab === "crop") {
2171
2493
  const drag = cropDragInfoRef.current;
2172
2494
  if (drag) {
2173
- const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
2495
+ const currentImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
2174
2496
  let newCrop;
2175
2497
  if (drag.handle === "new") {
2176
2498
  const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
@@ -2184,7 +2506,7 @@ var ImageEditor = ({
2184
2506
  height: Math.round(Math.max(20, maxY - minY))
2185
2507
  };
2186
2508
  } else {
2187
- newCrop = (0, import_image_editor12.calculateCropDrag)(
2509
+ newCrop = (0, import_image_editor14.calculateCropDrag)(
2188
2510
  drag.startCrop,
2189
2511
  drag.handle,
2190
2512
  drag.startImgPt,
@@ -2204,15 +2526,23 @@ var ImageEditor = ({
2204
2526
  width: state.imageDimensions.width,
2205
2527
  height: state.imageDimensions.height
2206
2528
  };
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);
2529
+ const handle = (0, import_image_editor14.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
2530
+ canvas.style.cursor = (0, import_image_editor14.getCropCursor)(handle, state.transform);
2531
+ }
2532
+ return;
2533
+ }
2534
+ if (activeTab === "annotate" && state.activeTool === "shape") {
2535
+ const g = shapeGestureRef.current;
2536
+ if (g.active) {
2537
+ g.move((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), { shift: e.shiftKey, alt: e.altKey });
2538
+ if (g.error) setShapeTypeError(g.error);
2209
2539
  }
2210
2540
  return;
2211
2541
  }
2212
2542
  if (activeTab === "annotate") {
2213
2543
  if (annotationDragInfoRef.current) {
2214
2544
  const drag = annotationDragInfoRef.current;
2215
- const currentImgPt2 = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2545
+ const currentImgPt2 = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2216
2546
  const dx = currentImgPt2.x - drag.startImgPt.x;
2217
2547
  const dy = currentImgPt2.y - drag.startImgPt.y;
2218
2548
  editor.updateAnnotation(drag.annId, {
@@ -2224,10 +2554,10 @@ var ImageEditor = ({
2224
2554
  const startPt = dragStartPointRef.current;
2225
2555
  if (!startPt) {
2226
2556
  if (state.activeTool === "select") {
2227
- const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2557
+ const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2228
2558
  let hovered = false;
2229
2559
  for (let i = state.annotations.length - 1; i >= 0; i--) {
2230
- if ((0, import_image_editor12.hitTestAnnotation)(imgPt, state.annotations[i])) {
2560
+ if ((0, import_image_editor14.hitTestAnnotation)(imgPt, state.annotations[i])) {
2231
2561
  hovered = true;
2232
2562
  break;
2233
2563
  }
@@ -2238,7 +2568,7 @@ var ImageEditor = ({
2238
2568
  }
2239
2569
  return;
2240
2570
  }
2241
- const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2571
+ const currentImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2242
2572
  if (state.activeTool === "pen" && isDrawingRef.current) {
2243
2573
  currentPathRef.current.push(currentImgPt);
2244
2574
  const draft = {
@@ -2318,7 +2648,7 @@ var ImageEditor = ({
2318
2648
  if (activeTab === "select") {
2319
2649
  const gesture = selectionGestureRef.current;
2320
2650
  if (gesture.active) {
2321
- gesture.end((0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
2651
+ gesture.end((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
2322
2652
  selectionDraftRef.current = null;
2323
2653
  renderCanvas();
2324
2654
  }
@@ -2335,6 +2665,19 @@ var ImageEditor = ({
2335
2665
  }
2336
2666
  return;
2337
2667
  }
2668
+ if (activeTab === "annotate" && state.activeTool === "shape") {
2669
+ shapeGestureRef.current.up();
2670
+ return;
2671
+ }
2672
+ if (activeTab === "annotate" && state.activeTool === "type") {
2673
+ const tool = typeToolRef.current;
2674
+ tool.up((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false));
2675
+ setTypeSession(tool.session);
2676
+ if (tool.error) setShapeTypeError(tool.error);
2677
+ void renderCanvas();
2678
+ if (tool.session) setTimeout(() => typeInputRef.current?.focus(), 0);
2679
+ return;
2680
+ }
2338
2681
  if (activeTab === "annotate") {
2339
2682
  if (annotationDragInfoRef.current) {
2340
2683
  annotationDragInfoRef.current = null;
@@ -2342,7 +2685,7 @@ var ImageEditor = ({
2342
2685
  }
2343
2686
  const startPt = dragStartPointRef.current;
2344
2687
  if (startPt) {
2345
- const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2688
+ const currentImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2346
2689
  if (state.activeTool === "pen" && isDrawingRef.current) {
2347
2690
  if (currentPathRef.current.length > 1) {
2348
2691
  editor.addAnnotation({
@@ -2438,15 +2781,15 @@ var ImageEditor = ({
2438
2781
  link.click();
2439
2782
  }
2440
2783
  };
2441
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2784
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2442
2785
  "div",
2443
2786
  {
2444
2787
  className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
2445
2788
  style,
2446
2789
  children: [
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)(
2790
+ /* @__PURE__ */ (0, import_jsx_runtime13.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: [
2791
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
2792
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2450
2793
  "button",
2451
2794
  {
2452
2795
  type: "button",
@@ -2458,7 +2801,7 @@ var ImageEditor = ({
2458
2801
  children: "Transform & Crop"
2459
2802
  }
2460
2803
  ),
2461
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2804
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2462
2805
  "button",
2463
2806
  {
2464
2807
  type: "button",
@@ -2470,7 +2813,7 @@ var ImageEditor = ({
2470
2813
  children: "Adjustments"
2471
2814
  }
2472
2815
  ),
2473
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2816
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2474
2817
  "button",
2475
2818
  {
2476
2819
  type: "button",
@@ -2482,7 +2825,7 @@ var ImageEditor = ({
2482
2825
  children: "Layers"
2483
2826
  }
2484
2827
  ),
2485
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2828
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2486
2829
  "button",
2487
2830
  {
2488
2831
  type: "button",
@@ -2494,7 +2837,7 @@ var ImageEditor = ({
2494
2837
  children: "Paint"
2495
2838
  }
2496
2839
  ),
2497
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2840
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2498
2841
  "button",
2499
2842
  {
2500
2843
  type: "button",
@@ -2506,7 +2849,7 @@ var ImageEditor = ({
2506
2849
  children: "Select & Mask"
2507
2850
  }
2508
2851
  ),
2509
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2852
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2510
2853
  "button",
2511
2854
  {
2512
2855
  type: "button",
@@ -2518,7 +2861,7 @@ var ImageEditor = ({
2518
2861
  children: "Annotations"
2519
2862
  }
2520
2863
  ),
2521
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2864
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2522
2865
  "button",
2523
2866
  {
2524
2867
  type: "button",
@@ -2530,7 +2873,7 @@ var ImageEditor = ({
2530
2873
  children: "Depth Mask"
2531
2874
  }
2532
2875
  ),
2533
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2876
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2534
2877
  "button",
2535
2878
  {
2536
2879
  type: "button",
@@ -2540,14 +2883,14 @@ var ImageEditor = ({
2540
2883
  },
2541
2884
  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"}`,
2542
2885
  children: [
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" }) }),
2886
+ /* @__PURE__ */ (0, import_jsx_runtime13.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_runtime13.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" }) }),
2544
2887
  "AI Tools"
2545
2888
  ]
2546
2889
  }
2547
2890
  )
2548
2891
  ] }),
2549
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
2550
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2892
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
2893
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2551
2894
  "button",
2552
2895
  {
2553
2896
  type: "button",
@@ -2558,7 +2901,7 @@ var ImageEditor = ({
2558
2901
  children: "\u21A9"
2559
2902
  }
2560
2903
  ),
2561
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2904
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2562
2905
  "button",
2563
2906
  {
2564
2907
  type: "button",
@@ -2569,7 +2912,7 @@ var ImageEditor = ({
2569
2912
  children: "\u21AA"
2570
2913
  }
2571
2914
  ),
2572
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2915
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2573
2916
  "button",
2574
2917
  {
2575
2918
  type: "button",
@@ -2578,8 +2921,8 @@ var ImageEditor = ({
2578
2921
  children: "Reset"
2579
2922
  }
2580
2923
  ),
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)(
2924
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2925
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2583
2926
  "button",
2584
2927
  {
2585
2928
  type: "button",
@@ -2589,11 +2932,11 @@ var ImageEditor = ({
2589
2932
  children: "-"
2590
2933
  }
2591
2934
  ),
2592
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
2935
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
2593
2936
  Math.round(state.zoom * 100),
2594
2937
  "%"
2595
2938
  ] }),
2596
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2939
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2597
2940
  "button",
2598
2941
  {
2599
2942
  type: "button",
@@ -2603,8 +2946,8 @@ var ImageEditor = ({
2603
2946
  children: "+"
2604
2947
  }
2605
2948
  ),
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)(
2949
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2950
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2608
2951
  "button",
2609
2952
  {
2610
2953
  type: "button",
@@ -2615,7 +2958,7 @@ var ImageEditor = ({
2615
2958
  children: "Hold Compare"
2616
2959
  }
2617
2960
  ),
2618
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2961
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2619
2962
  "button",
2620
2963
  {
2621
2964
  type: "button",
@@ -2626,38 +2969,59 @@ var ImageEditor = ({
2626
2969
  )
2627
2970
  ] })
2628
2971
  ] }),
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)(
2972
+ transformTool.active && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
2973
+ !transformTool.active && transformTool.error && /* @__PURE__ */ (0, import_jsx_runtime13.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 }),
2974
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
2975
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2633
2976
  "div",
2634
2977
  {
2635
2978
  ref: containerRef,
2636
2979
  className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
2637
- children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2638
- "canvas",
2639
- {
2640
- ref: canvasRef,
2641
- onMouseDown: handleMouseDown,
2642
- onMouseMove: handleMouseMove,
2643
- onMouseUp: handleMouseUp,
2644
- onMouseLeave: handleMouseUp,
2645
- onPointerDown: handlePaintPointerDown,
2646
- onPointerMove: handlePaintPointerMove,
2647
- onPointerUp: handlePaintPointerUp,
2648
- onPointerCancel: () => paintGestureRef.current?.cancel(),
2649
- "data-testid": "image-editor-canvas",
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" : ""}`
2652
- }
2653
- )
2980
+ children: [
2981
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2982
+ "canvas",
2983
+ {
2984
+ ref: canvasRef,
2985
+ onMouseDown: handleMouseDown,
2986
+ onMouseMove: handleMouseMove,
2987
+ onMouseUp: handleMouseUp,
2988
+ onMouseLeave: handleMouseUp,
2989
+ onPointerDown: handlePaintPointerDown,
2990
+ onPointerMove: handlePaintPointerMove,
2991
+ onPointerUp: handlePaintPointerUp,
2992
+ onPointerCancel: () => paintGestureRef.current?.cancel(),
2993
+ "data-testid": "image-editor-canvas",
2994
+ style: transformTool.active ? { cursor: transformCursor } : void 0,
2995
+ className: `absolute inset-0 w-full h-full block ${transformTool.active ? "touch-none" : activeTab === "paint" ? "touch-none cursor-crosshair" : activeTab === "annotate" && state.activeTool === "type" ? "cursor-text" : activeTab === "annotate" && state.activeTool === "shape" ? "cursor-crosshair" : ""}`
2996
+ }
2997
+ ),
2998
+ typeSession && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2999
+ "textarea",
3000
+ {
3001
+ ref: typeInputRef,
3002
+ "aria-label": "Edit text",
3003
+ "data-testid": "type-input",
3004
+ autoCapitalize: "off",
3005
+ autoCorrect: "off",
3006
+ spellCheck: false,
3007
+ onKeyDown: handleTypeKeyDown,
3008
+ onInput: handleTypeInput,
3009
+ onCompositionEnd: (e) => {
3010
+ const session = typeToolRef.current?.session;
3011
+ if (session && e.data) session.insert(e.data);
3012
+ e.currentTarget.value = "";
3013
+ },
3014
+ className: "absolute left-0 top-0 h-px w-px opacity-0"
3015
+ }
3016
+ )
3017
+ ]
2654
3018
  }
2655
3019
  ),
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)(
3020
+ /* @__PURE__ */ (0, import_jsx_runtime13.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: [
3021
+ activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
3022
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
3023
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
3024
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2661
3025
  "button",
2662
3026
  {
2663
3027
  type: "button",
@@ -2669,7 +3033,7 @@ var ImageEditor = ({
2669
3033
  children: "Freeform"
2670
3034
  }
2671
3035
  ),
2672
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3036
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2673
3037
  "button",
2674
3038
  {
2675
3039
  type: "button",
@@ -2681,7 +3045,7 @@ var ImageEditor = ({
2681
3045
  children: "1:1 Square"
2682
3046
  }
2683
3047
  ),
2684
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3048
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2685
3049
  "button",
2686
3050
  {
2687
3051
  type: "button",
@@ -2693,7 +3057,7 @@ var ImageEditor = ({
2693
3057
  children: "4:3 Standard"
2694
3058
  }
2695
3059
  ),
2696
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3060
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2697
3061
  "button",
2698
3062
  {
2699
3063
  type: "button",
@@ -2705,7 +3069,7 @@ var ImageEditor = ({
2705
3069
  children: "16:9 Wide"
2706
3070
  }
2707
3071
  ),
2708
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3072
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2709
3073
  "button",
2710
3074
  {
2711
3075
  type: "button",
@@ -2717,7 +3081,7 @@ var ImageEditor = ({
2717
3081
  children: "3:2 Photo"
2718
3082
  }
2719
3083
  ),
2720
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3084
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2721
3085
  "button",
2722
3086
  {
2723
3087
  type: "button",
@@ -2730,10 +3094,10 @@ var ImageEditor = ({
2730
3094
  }
2731
3095
  )
2732
3096
  ] }),
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)(
3097
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3098
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
3099
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
3100
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2737
3101
  "button",
2738
3102
  {
2739
3103
  type: "button",
@@ -2742,7 +3106,7 @@ var ImageEditor = ({
2742
3106
  children: "Rotate -90\xB0"
2743
3107
  }
2744
3108
  ),
2745
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3109
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2746
3110
  "button",
2747
3111
  {
2748
3112
  type: "button",
@@ -2751,7 +3115,7 @@ var ImageEditor = ({
2751
3115
  children: "Rotate +90\xB0"
2752
3116
  }
2753
3117
  ),
2754
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3118
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2755
3119
  "button",
2756
3120
  {
2757
3121
  type: "button",
@@ -2760,7 +3124,7 @@ var ImageEditor = ({
2760
3124
  children: "Flip Horizontal"
2761
3125
  }
2762
3126
  ),
2763
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3127
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2764
3128
  "button",
2765
3129
  {
2766
3130
  type: "button",
@@ -2771,10 +3135,10 @@ var ImageEditor = ({
2771
3135
  )
2772
3136
  ] })
2773
3137
  ] }),
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)(
3138
+ activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3139
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between", children: [
3140
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
3141
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2778
3142
  "button",
2779
3143
  {
2780
3144
  type: "button",
@@ -2784,25 +3148,25 @@ var ImageEditor = ({
2784
3148
  }
2785
3149
  )
2786
3150
  ] }),
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)(
3151
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Histogram, { histogram: editor.histogram }),
3152
+ import_image_editor14.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_react13.default.Fragment, { children: [
3153
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2790
3154
  ControlSlider,
2791
3155
  {
2792
3156
  spec,
2793
- value: (0, import_image_editor12.readAdjustmentControls)(state.adjustments)[spec.id],
3157
+ value: (0, import_image_editor14.readAdjustmentControls)(state.adjustments)[spec.id],
2794
3158
  disabled: spec.requiresProcess !== void 0 && legacyProcess,
2795
3159
  onChange: (v) => editor.setAdjustments({ [spec.id]: v })
2796
3160
  }
2797
3161
  ),
2798
- spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3162
+ spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2799
3163
  "div",
2800
3164
  {
2801
3165
  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",
2802
3166
  "data-testid": "image-editor-process-notice",
2803
3167
  children: [
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)(
3168
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
3169
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2806
3170
  "button",
2807
3171
  {
2808
3172
  type: "button",
@@ -2815,7 +3179,7 @@ var ImageEditor = ({
2815
3179
  }
2816
3180
  )
2817
3181
  ] }, spec.id)),
2818
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3182
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2819
3183
  AdjustmentLayersPanel,
2820
3184
  {
2821
3185
  controller,
@@ -2824,9 +3188,9 @@ var ImageEditor = ({
2824
3188
  }
2825
3189
  ) })
2826
3190
  ] }),
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)(
3191
+ activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3192
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
3193
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2830
3194
  "button",
2831
3195
  {
2832
3196
  type: "button",
@@ -2837,12 +3201,12 @@ var ImageEditor = ({
2837
3201
  children: "Free Transform"
2838
3202
  }
2839
3203
  ),
2840
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(LayersPanel, { controller })
3204
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LayersPanel, { controller })
2841
3205
  ] }),
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)(
3206
+ activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3207
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
3208
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(BrushOptionsBar, { controller }),
3209
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2846
3210
  "button",
2847
3211
  {
2848
3212
  type: "button",
@@ -2853,12 +3217,29 @@ var ImageEditor = ({
2853
3217
  children: "Free Transform"
2854
3218
  }
2855
3219
  ),
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 }) })
3220
+ paintError && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
3221
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(LayersPanel, { controller }) })
2858
3222
  ] }),
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)(
3223
+ activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3224
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Shape & Type Layers" }),
3225
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "grid grid-cols-2 gap-1.5", children: ["shape", "type"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3226
+ "button",
3227
+ {
3228
+ type: "button",
3229
+ "aria-pressed": state.activeTool === t,
3230
+ onClick: () => editor.setTool(t),
3231
+ className: `py-1.5 px-2 rounded-lg font-medium border transition-colors ${state.activeTool === t ? "bg-indigo-600 border-indigo-500 text-white" : "bg-slate-800 border-slate-700 text-slate-300 hover:bg-slate-700"}`,
3232
+ children: t === "shape" ? "Shape" : "Type"
3233
+ },
3234
+ t
3235
+ )) }),
3236
+ state.activeTool === "shape" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ShapeOptionsBar, { controller, options: shapeOptions, onChange: setShapeOptions }),
3237
+ state.activeTool === "type" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TypeOptionsBar, { controller, options: typeOptions, onChange: setTypeOptions, session: typeSession }),
3238
+ state.activeTool === "type" && typeSession && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", onClick: finishTyping, className: "self-start rounded bg-slate-800 px-2 py-1 text-[11px] text-slate-200 hover:bg-slate-700", children: "Done editing text" }),
3239
+ shapeTypeError && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "shape-type-error", children: shapeTypeError }),
3240
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3241
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
3242
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2862
3243
  "button",
2863
3244
  {
2864
3245
  type: "button",
@@ -2868,9 +3249,9 @@ var ImageEditor = ({
2868
3249
  },
2869
3250
  t
2870
3251
  )) }),
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)(
3252
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
3253
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { className: "text-slate-400", children: "Color:" }),
3254
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2874
3255
  "input",
2875
3256
  {
2876
3257
  type: "color",
@@ -2879,15 +3260,15 @@ var ImageEditor = ({
2879
3260
  className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
2880
3261
  }
2881
3262
  ),
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: [
3263
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex-1 ml-2", children: [
3264
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
3265
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Width:" }),
3266
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "font-mono", children: [
2886
3267
  strokeWidth,
2887
3268
  "px"
2888
3269
  ] })
2889
3270
  ] }),
2890
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3271
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2891
3272
  "input",
2892
3273
  {
2893
3274
  type: "range",
@@ -2900,10 +3281,10 @@ var ImageEditor = ({
2900
3281
  )
2901
3282
  ] })
2902
3283
  ] }),
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)(
3284
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3285
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
3286
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex gap-2", children: [
3287
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2907
3288
  "input",
2908
3289
  {
2909
3290
  type: "text",
@@ -2914,7 +3295,7 @@ var ImageEditor = ({
2914
3295
  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"
2915
3296
  }
2916
3297
  ),
2917
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3298
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2918
3299
  "button",
2919
3300
  {
2920
3301
  type: "button",
@@ -2924,14 +3305,14 @@ var ImageEditor = ({
2924
3305
  }
2925
3306
  )
2926
3307
  ] }),
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: [
3308
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
3309
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Font Size:" }),
3310
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "font-mono", children: [
2930
3311
  fontSize,
2931
3312
  "px"
2932
3313
  ] })
2933
3314
  ] }),
2934
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3315
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2935
3316
  "input",
2936
3317
  {
2937
3318
  type: "range",
@@ -2942,14 +3323,14 @@ var ImageEditor = ({
2942
3323
  className: "w-full accent-indigo-500"
2943
3324
  }
2944
3325
  ),
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: [
3326
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3327
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between", children: [
3328
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "text-slate-400", children: [
2948
3329
  "Layers (",
2949
3330
  state.annotations.length,
2950
3331
  ")"
2951
3332
  ] }),
2952
- state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3333
+ state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2953
3334
  "button",
2954
3335
  {
2955
3336
  type: "button",
@@ -2958,7 +3339,7 @@ var ImageEditor = ({
2958
3339
  children: "Delete Selected"
2959
3340
  }
2960
3341
  ),
2961
- state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3342
+ state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2962
3343
  "button",
2963
3344
  {
2964
3345
  type: "button",
@@ -2969,10 +3350,10 @@ var ImageEditor = ({
2969
3350
  )
2970
3351
  ] })
2971
3352
  ] }),
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)(
3353
+ activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3354
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between", children: [
3355
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
3356
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2976
3357
  "button",
2977
3358
  {
2978
3359
  type: "button",
@@ -2982,8 +3363,8 @@ var ImageEditor = ({
2982
3363
  }
2983
3364
  )
2984
3365
  ] }),
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)(
3366
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
3367
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2987
3368
  "input",
2988
3369
  {
2989
3370
  type: "checkbox",
@@ -2992,12 +3373,12 @@ var ImageEditor = ({
2992
3373
  className: "rounded accent-indigo-500"
2993
3374
  }
2994
3375
  ),
2995
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Enable Depth / Alpha Mask" })
3376
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Enable Depth / Alpha Mask" })
2996
3377
  ] }),
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)(
3378
+ state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3379
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
3380
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
3381
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3001
3382
  "input",
3002
3383
  {
3003
3384
  type: "text",
@@ -3008,8 +3389,8 @@ var ImageEditor = ({
3008
3389
  }
3009
3390
  )
3010
3391
  ] }),
3011
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex gap-2", children: [
3012
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3392
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex gap-2", children: [
3393
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3013
3394
  "button",
3014
3395
  {
3015
3396
  type: "button",
@@ -3018,7 +3399,7 @@ var ImageEditor = ({
3018
3399
  children: "Threshold Mode"
3019
3400
  }
3020
3401
  ),
3021
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3402
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3022
3403
  "button",
3023
3404
  {
3024
3405
  type: "button",
@@ -3028,12 +3409,12 @@ var ImageEditor = ({
3028
3409
  }
3029
3410
  )
3030
3411
  ] }),
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] })
3412
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
3413
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3414
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Depth Start (Lower):" }),
3415
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
3035
3416
  ] }),
3036
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3417
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3037
3418
  "input",
3038
3419
  {
3039
3420
  type: "range",
@@ -3047,12 +3428,12 @@ var ImageEditor = ({
3047
3428
  }
3048
3429
  )
3049
3430
  ] }),
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] })
3431
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
3432
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3433
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Depth Stop (Upper):" }),
3434
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
3054
3435
  ] }),
3055
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3436
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3056
3437
  "input",
3057
3438
  {
3058
3439
  type: "range",
@@ -3066,12 +3447,12 @@ var ImageEditor = ({
3066
3447
  }
3067
3448
  )
3068
3449
  ] }),
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 })
3450
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
3451
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3452
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Softness:" }),
3453
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
3073
3454
  ] }),
3074
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3455
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3075
3456
  "input",
3076
3457
  {
3077
3458
  type: "range",
@@ -3083,8 +3464,8 @@ var ImageEditor = ({
3083
3464
  }
3084
3465
  )
3085
3466
  ] }),
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)(
3467
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
3468
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3088
3469
  "input",
3089
3470
  {
3090
3471
  type: "checkbox",
@@ -3093,12 +3474,12 @@ var ImageEditor = ({
3093
3474
  className: "rounded accent-indigo-500"
3094
3475
  }
3095
3476
  ),
3096
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Invert Mask" })
3477
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Invert Mask" })
3097
3478
  ] })
3098
3479
  ] })
3099
3480
  ] }),
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)(
3481
+ activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
3482
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3102
3483
  SelectionOptionsBar,
3103
3484
  {
3104
3485
  controller,
@@ -3108,9 +3489,9 @@ var ImageEditor = ({
3108
3489
  quickMask: Boolean(state.quickMask)
3109
3490
  }
3110
3491
  ),
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)(
3492
+ selectionError && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
3493
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex gap-1", children: [
3494
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3114
3495
  "button",
3115
3496
  {
3116
3497
  type: "button",
@@ -3121,7 +3502,7 @@ var ImageEditor = ({
3121
3502
  children: "Transform Selection"
3122
3503
  }
3123
3504
  ),
3124
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3505
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3125
3506
  "button",
3126
3507
  {
3127
3508
  type: "button",
@@ -3133,12 +3514,12 @@ var ImageEditor = ({
3133
3514
  }
3134
3515
  )
3135
3516
  ] }),
3136
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
3517
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
3137
3518
  ] }),
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)(
3519
+ activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
3520
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
3521
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Results go to" }),
3522
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3142
3523
  "select",
3143
3524
  {
3144
3525
  "aria-label": "AI result target",
@@ -3146,54 +3527,54 @@ var ImageEditor = ({
3146
3527
  onChange: (e) => setAiTarget(e.target.value),
3147
3528
  className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
3148
3529
  children: [
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" })
3530
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
3531
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
3532
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: "replace", children: "Replace image" })
3152
3533
  ]
3153
3534
  }
3154
3535
  )
3155
3536
  ] }),
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" }) }),
3537
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3538
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between", children: [
3539
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3540
+ /* @__PURE__ */ (0, import_jsx_runtime13.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_runtime13.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" }) }),
3160
3541
  "Background Removal"
3161
3542
  ] }),
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..." })
3543
+ isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime13.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..." })
3163
3544
  ] }),
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)(
3545
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
3546
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3166
3547
  "button",
3167
3548
  {
3168
3549
  type: "button",
3169
3550
  onClick: handleRemoveBackground,
3170
3551
  disabled: isRemovingBg || isInpainting,
3171
3552
  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",
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" }),
3553
+ children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3554
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3174
3555
  "Removing Background..."
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" }) }),
3556
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3557
+ /* @__PURE__ */ (0, import_jsx_runtime13.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_runtime13.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" }) }),
3177
3558
  "Remove Background"
3178
3559
  ] })
3179
3560
  }
3180
3561
  )
3181
3562
  ] }),
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" })
3563
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3564
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between", children: [
3565
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3566
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
3567
+ /* @__PURE__ */ (0, import_jsx_runtime13.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" }),
3568
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "m14 7 3 3" })
3188
3569
  ] }),
3189
3570
  "Generative Inpainting"
3190
3571
  ] }),
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..." })
3572
+ isInpainting && /* @__PURE__ */ (0, import_jsx_runtime13.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..." })
3192
3573
  ] }),
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)(
3574
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
3575
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-1", children: [
3576
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
3577
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3197
3578
  "textarea",
3198
3579
  {
3199
3580
  id: "ai-inpaint-prompt-react",
@@ -3205,10 +3586,10 @@ var ImageEditor = ({
3205
3586
  }
3206
3587
  )
3207
3588
  ] }),
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)(
3589
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-1", children: [
3590
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
3591
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
3592
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3212
3593
  "button",
3213
3594
  {
3214
3595
  type: "button",
@@ -3221,7 +3602,7 @@ var ImageEditor = ({
3221
3602
  ]
3222
3603
  }
3223
3604
  ),
3224
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3605
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
3225
3606
  "button",
3226
3607
  {
3227
3608
  type: "button",
@@ -3236,25 +3617,25 @@ var ImageEditor = ({
3236
3617
  )
3237
3618
  ] })
3238
3619
  ] }),
3239
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3620
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
3240
3621
  "button",
3241
3622
  {
3242
3623
  type: "button",
3243
3624
  onClick: handleInpaint,
3244
3625
  disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
3245
3626
  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",
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" }),
3627
+ children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3628
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3248
3629
  "Generating Inpaint..."
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" }) }),
3630
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
3631
+ /* @__PURE__ */ (0, import_jsx_runtime13.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_runtime13.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" }) }),
3251
3632
  "Apply Inpainting"
3252
3633
  ] })
3253
3634
  }
3254
3635
  )
3255
3636
  ] }),
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 })
3637
+ aiError && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
3638
+ aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
3258
3639
  ] })
3259
3640
  ] })
3260
3641
  ] })
@@ -3275,6 +3656,8 @@ var ImageEditor = ({
3275
3656
  LayersPanel,
3276
3657
  RefineEdgePanel,
3277
3658
  SelectionOptionsBar,
3659
+ ShapeOptionsBar,
3660
+ TypeOptionsBar,
3278
3661
  useImageEditor,
3279
3662
  useImageHistogram
3280
3663
  });