@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.
@@ -159,7 +159,7 @@ function useImageEditor(options = {}) {
159
159
  }
160
160
 
161
161
  // src/image-editor/ImageEditor.tsx
162
- import React10, { useRef as useRef5, useEffect as useEffect8, useState as useState11, useCallback as useCallback2 } from "react";
162
+ import React12, { useRef as useRef5, useEffect as useEffect10, useState as useState13, useCallback as useCallback2 } from "react";
163
163
  import {
164
164
  canvasToImagePoint,
165
165
  hitTestCrop,
@@ -176,7 +176,11 @@ import {
176
176
  handlePaintShortcut,
177
177
  pointerPressure,
178
178
  FreeTransformTool,
179
- getViewportProjection
179
+ getViewportProjection,
180
+ ShapeDrawGesture,
181
+ TypeToolGesture,
182
+ DEFAULT_SHAPE_TOOL_OPTIONS,
183
+ DEFAULT_TYPE_TOOL_OPTIONS
180
184
  } from "@pixerate/editor/image-editor";
181
185
 
182
186
  // src/image-editor/ControlSlider.tsx
@@ -826,6 +830,8 @@ import {
826
830
  dropZone,
827
831
  openPsdFile,
828
832
  layerBadge,
833
+ layerHasThumbnail,
834
+ layerWarning,
829
835
  layerEffectsBadge,
830
836
  layerMenu,
831
837
  layerPanelRows,
@@ -918,7 +924,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
918
924
  const placement = dropPlacement(state.layers, id, row.layer.id, dropZone(fraction, row.layer.type === "group"));
919
925
  if (placement) attempt(() => controller.moveLayer(id, placement));
920
926
  };
921
- const thumb = (layer) => layer.type === "pixel" ? controller.getLayerThumbnail(layer.id, { maxSide: 64 }) : null;
927
+ const thumb = (layer) => layerHasThumbnail(layer) ? controller.getLayerThumbnail(layer.id, { maxSide: 64 }) : null;
922
928
  const maskThumb = (layer) => layer.mask && !layer.mask.source ? controller.getLayerThumbnail(layer.id, { maxSide: 64, mask: true }) : null;
923
929
  const locked = (layer) => Boolean(layer.locks?.all || layer.locks?.pixels || layer.locks?.position || layer.locks?.transparency);
924
930
  return /* @__PURE__ */ jsxs6("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layers-panel", onClick: () => menu && setMenu(null), children: [
@@ -1111,15 +1117,25 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
1111
1117
  }
1112
1118
  ),
1113
1119
  row.clipped && /* @__PURE__ */ jsx6("span", { className: "text-slate-500", "aria-label": "Clipped", children: "\u21B3" }),
1114
- layer.type === "pixel" ? /* @__PURE__ */ jsx6(
1115
- Thumbnail,
1116
- {
1117
- pixels: thumb(layer),
1118
- size: thumbnailSize,
1119
- label: `${row.label} pixels`,
1120
- selected: row.active && state.activeTarget === "pixels" && Boolean(layer.mask)
1121
- }
1122
- ) : /* @__PURE__ */ jsx6(
1120
+ layerHasThumbnail(layer) ? /* @__PURE__ */ jsxs6("span", { className: "relative shrink-0", children: [
1121
+ /* @__PURE__ */ jsx6(
1122
+ Thumbnail,
1123
+ {
1124
+ pixels: thumb(layer),
1125
+ size: thumbnailSize,
1126
+ label: `${row.label} pixels`,
1127
+ selected: row.active && state.activeTarget === "pixels" && Boolean(layer.mask)
1128
+ }
1129
+ ),
1130
+ layer.type !== "pixel" && /* @__PURE__ */ jsx6(
1131
+ "span",
1132
+ {
1133
+ "data-testid": "layer-kind-badge",
1134
+ 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",
1135
+ children: layerBadge(layer)
1136
+ }
1137
+ )
1138
+ ] }) : /* @__PURE__ */ jsx6(
1123
1139
  "span",
1124
1140
  {
1125
1141
  className: "shrink-0 grid place-items-center rounded bg-slate-800 text-[9px] text-slate-400 ring-1 ring-slate-700",
@@ -1186,6 +1202,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
1186
1202
  children: row.label
1187
1203
  }
1188
1204
  ),
1205
+ layerWarning(layer) && /* @__PURE__ */ jsx6("span", { role: "img", "data-testid": "layer-warning", "aria-label": layerWarning(layer), title: layerWarning(layer), className: "text-[10px] text-amber-400", children: "\u26A0" }),
1189
1206
  layerEffectsBadge(layer) && /* @__PURE__ */ jsx6(
1190
1207
  "button",
1191
1208
  {
@@ -1237,7 +1254,19 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
1237
1254
 
1238
1255
  // src/image-editor/BrushOptionsBar.tsx
1239
1256
  import { useEffect as useEffect6, useState as useState7 } from "react";
1240
- import { BRUSH_OPTION_CONTROLS, MIXER_MIXING_OPTIONS, MIXER_OPTION_CONTROLS, PAINT_TOOLS, rgbUnitToHex } from "@pixerate/editor/image-editor";
1257
+ import {
1258
+ BRUSH_OPTION_CONTROLS,
1259
+ MIXER_MIXING_OPTIONS,
1260
+ MIXER_OPTION_CONTROLS,
1261
+ PAINT_TOOLS,
1262
+ RETOUCH_CHOICES,
1263
+ RETOUCH_OPTION_CONTROLS,
1264
+ RETOUCH_TOGGLES,
1265
+ cloneSourceLabel,
1266
+ isRetouchPaintTool,
1267
+ rgbUnitToHex,
1268
+ setRetouchChoice
1269
+ } from "@pixerate/editor/image-editor";
1241
1270
  import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1242
1271
  var chip = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
1243
1272
  var BrushOptionsBar = ({ controller, className }) => {
@@ -1245,7 +1274,8 @@ var BrushOptionsBar = ({ controller, className }) => {
1245
1274
  useEffect6(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
1246
1275
  const [error, setError] = useState7(null);
1247
1276
  const state = controller.getState();
1248
- const { brush, foreground, background, mixer, mixerLoad } = state.paint;
1277
+ const { brush, foreground, background, mixer, mixerLoad, retouch, cloneSource } = state.paint;
1278
+ const tool = state.activeTool;
1249
1279
  const attempt = (fn) => {
1250
1280
  try {
1251
1281
  setError(null);
@@ -1255,12 +1285,12 @@ var BrushOptionsBar = ({ controller, className }) => {
1255
1285
  }
1256
1286
  };
1257
1287
  return /* @__PURE__ */ jsxs7("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
1258
- /* @__PURE__ */ jsx7("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Paint tools", children: PAINT_TOOLS.map((t) => /* @__PURE__ */ jsx7(
1288
+ /* @__PURE__ */ jsx7("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Paint tools", children: PAINT_TOOLS.map((t) => /* @__PURE__ */ jsx7(
1259
1289
  "button",
1260
1290
  {
1261
1291
  type: "button",
1262
1292
  "aria-pressed": state.activeTool === t.id,
1263
- title: `${t.label} (${t.shortcut})`,
1293
+ title: t.shortcut ? `${t.label} (${t.shortcut})` : t.label,
1264
1294
  className: chip(state.activeTool === t.id),
1265
1295
  onClick: () => controller.setTool(t.id),
1266
1296
  children: t.label
@@ -1362,6 +1392,41 @@ var BrushOptionsBar = ({ controller, className }) => {
1362
1392
  ] })
1363
1393
  ] })
1364
1394
  ] }),
1395
+ isRetouchPaintTool(tool) && /* @__PURE__ */ jsxs7("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: [
1396
+ (tool === "clone" || tool === "heal") && /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
1397
+ /* @__PURE__ */ jsx7("span", { className: "text-slate-400", "data-testid": "clone-source", children: cloneSourceLabel(controller) }),
1398
+ cloneSource && /* @__PURE__ */ jsx7("button", { type: "button", title: "Forget the source point", className: chip(false), onClick: () => controller.setCloneSource(null), children: "Clear source" })
1399
+ ] }),
1400
+ RETOUCH_CHOICES.filter((c) => c.tools.includes(tool)).map((choice) => /* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": choice.label, children: [
1401
+ /* @__PURE__ */ jsx7("span", { className: "text-slate-400", children: choice.label }),
1402
+ choice.options.map((o) => /* @__PURE__ */ jsx7(
1403
+ "button",
1404
+ {
1405
+ type: "button",
1406
+ "aria-pressed": retouch[choice.id] === o.id,
1407
+ title: o.title,
1408
+ className: chip(retouch[choice.id] === o.id),
1409
+ onClick: () => setRetouchChoice(controller, choice.id, o.id),
1410
+ children: o.label
1411
+ },
1412
+ o.id
1413
+ ))
1414
+ ] }, choice.id)),
1415
+ RETOUCH_OPTION_CONTROLS.filter((c) => c.tools.includes(tool)).map((spec) => /* @__PURE__ */ jsx7(ControlSlider, { spec, value: retouch[spec.id], onChange: (v) => controller.setPaintOptions({ retouch: { [spec.id]: v } }) }, spec.id)),
1416
+ /* @__PURE__ */ jsx7("div", { className: "flex flex-wrap gap-3 text-slate-300", children: RETOUCH_TOGGLES.filter((t) => t.tools.includes(tool)).map((t) => /* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1.5", children: [
1417
+ /* @__PURE__ */ jsx7(
1418
+ "input",
1419
+ {
1420
+ type: "checkbox",
1421
+ "aria-label": t.label,
1422
+ checked: retouch[t.id],
1423
+ onChange: (e) => controller.setPaintOptions({ retouch: { [t.id]: e.target.checked } }),
1424
+ className: "accent-indigo-500"
1425
+ }
1426
+ ),
1427
+ t.label
1428
+ ] }, t.id)) })
1429
+ ] }),
1365
1430
  /* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
1366
1431
  /* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1.5", children: [
1367
1432
  /* @__PURE__ */ jsx7(
@@ -1803,8 +1868,215 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
1803
1868
  ] });
1804
1869
  };
1805
1870
 
1806
- // src/image-editor/ImageEditor.tsx
1871
+ // src/image-editor/ShapeOptionsBar.tsx
1872
+ import { useEffect as useEffect8, useState as useState11 } from "react";
1873
+ import { LIVE_SHAPE_KINDS, SHAPE_KIND_LABELS, applyShapeOptions } from "@pixerate/editor/image-editor";
1807
1874
  import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1875
+ 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"}`;
1876
+ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
1877
+ const [, setTick] = useState11(0);
1878
+ useEffect8(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
1879
+ const [error, setError] = useState11(null);
1880
+ const active = controller.getActiveLayer();
1881
+ const shapeId = active?.type === "shape" ? active.id : null;
1882
+ const set = (change) => {
1883
+ onChange({ ...options, ...change });
1884
+ if (!shapeId) return;
1885
+ try {
1886
+ setError(null);
1887
+ applyShapeOptions(controller, shapeId, change);
1888
+ } catch (e) {
1889
+ setError(e instanceof Error ? e.message : String(e));
1890
+ }
1891
+ };
1892
+ const num = (v, min, max) => Math.max(min, Math.min(max, Number(v) || min));
1893
+ return /* @__PURE__ */ jsxs11("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "shape-options", children: [
1894
+ /* @__PURE__ */ jsx11("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Shape kind", children: LIVE_SHAPE_KINDS.map((k) => /* @__PURE__ */ jsx11("button", { type: "button", "aria-pressed": options.kind === k, className: chip3(options.kind === k), onClick: () => onChange({ ...options, kind: k }), children: SHAPE_KIND_LABELS[k] }, k)) }),
1895
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-3", children: [
1896
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-1", children: [
1897
+ /* @__PURE__ */ jsx11("input", { type: "checkbox", "aria-label": "Fill", checked: options.fill !== null, onChange: (e) => set({ fill: e.target.checked ? "#4f46e5" : null }) }),
1898
+ "Fill",
1899
+ /* @__PURE__ */ jsx11(
1900
+ "input",
1901
+ {
1902
+ type: "color",
1903
+ "aria-label": "Fill colour",
1904
+ disabled: options.fill === null,
1905
+ value: options.fill ?? "#4f46e5",
1906
+ onChange: (e) => set({ fill: e.target.value }),
1907
+ className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
1908
+ }
1909
+ )
1910
+ ] }),
1911
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-1", children: [
1912
+ /* @__PURE__ */ jsx11("input", { type: "checkbox", "aria-label": "Stroke", checked: options.stroke !== null, onChange: (e) => set({ stroke: e.target.checked ? "#000000" : null }) }),
1913
+ "Stroke",
1914
+ /* @__PURE__ */ jsx11(
1915
+ "input",
1916
+ {
1917
+ type: "color",
1918
+ "aria-label": "Stroke colour",
1919
+ disabled: options.stroke === null,
1920
+ value: options.stroke ?? "#000000",
1921
+ onChange: (e) => set({ stroke: e.target.value }),
1922
+ className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
1923
+ }
1924
+ )
1925
+ ] }),
1926
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-1", children: [
1927
+ "Width",
1928
+ /* @__PURE__ */ jsx11(
1929
+ "input",
1930
+ {
1931
+ type: "number",
1932
+ "aria-label": "Stroke width",
1933
+ min: 0,
1934
+ max: 200,
1935
+ value: options.strokeWidth,
1936
+ onChange: (e) => set({ strokeWidth: num(e.target.value, 0, 200) }),
1937
+ className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5"
1938
+ }
1939
+ )
1940
+ ] })
1941
+ ] }),
1942
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center gap-3", children: [
1943
+ options.kind === "rect" && /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-1", children: [
1944
+ "Radius",
1945
+ /* @__PURE__ */ jsx11("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" })
1946
+ ] }),
1947
+ options.kind === "polygon" && /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-1", children: [
1948
+ "Sides",
1949
+ /* @__PURE__ */ jsx11("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" })
1950
+ ] }),
1951
+ options.kind === "star" && /* @__PURE__ */ jsxs11(Fragment3, { children: [
1952
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-1", children: [
1953
+ "Points",
1954
+ /* @__PURE__ */ jsx11("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" })
1955
+ ] }),
1956
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-1", children: [
1957
+ "Inner",
1958
+ /* @__PURE__ */ jsx11(
1959
+ "input",
1960
+ {
1961
+ type: "range",
1962
+ "aria-label": "Inner radius",
1963
+ min: 0.05,
1964
+ max: 1,
1965
+ step: 0.05,
1966
+ value: options.innerRatio,
1967
+ onChange: (e) => set({ innerRatio: Number(e.target.value) }),
1968
+ className: "accent-indigo-500"
1969
+ }
1970
+ )
1971
+ ] })
1972
+ ] }),
1973
+ options.kind === "line" && /* @__PURE__ */ jsxs11(Fragment3, { children: [
1974
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-1", children: [
1975
+ "Weight",
1976
+ /* @__PURE__ */ jsx11("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" })
1977
+ ] }),
1978
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-1", children: [
1979
+ /* @__PURE__ */ jsx11("input", { type: "checkbox", "aria-label": "Arrowhead", checked: options.arrow, onChange: (e) => set({ arrow: e.target.checked }) }),
1980
+ "Arrowhead"
1981
+ ] })
1982
+ ] })
1983
+ ] }),
1984
+ /* @__PURE__ */ jsx11("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." }),
1985
+ error && /* @__PURE__ */ jsx11("p", { role: "alert", className: "text-rose-400", children: error })
1986
+ ] });
1987
+ };
1988
+
1989
+ // src/image-editor/TypeOptionsBar.tsx
1990
+ import { useEffect as useEffect9, useState as useState12 } from "react";
1991
+ import { TEXT_ALIGNS } from "@pixerate/editor/image-editor";
1992
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
1993
+ 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"}`;
1994
+ var ALIGN_LABELS = { left: "Left", center: "Centre", right: "Right", justify: "Justify" };
1995
+ var TypeOptionsBar = ({ controller, options, onChange, session, className }) => {
1996
+ const [, setTick] = useState12(0);
1997
+ useEffect9(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
1998
+ useEffect9(() => session?.subscribe(() => setTick((n) => n + 1)), [session]);
1999
+ const [error, setError] = useState12(null);
2000
+ const active = controller.getActiveLayer();
2001
+ const typeId = !session && active?.type === "type" ? active.id : null;
2002
+ const here = session?.alive ? session.styleHere() : {};
2003
+ const shown = {
2004
+ ...options,
2005
+ ...here.fontFamily ? { fontFamily: here.fontFamily } : {},
2006
+ ...here.fontSize ? { fontSize: here.fontSize } : {},
2007
+ ...here.fontWeight ? { fontWeight: here.fontWeight } : {},
2008
+ ...session?.alive ? { italic: Boolean(here.italic), color: here.color ?? options.color } : {}
2009
+ };
2010
+ const fonts = controller.listFonts();
2011
+ const missing = active?.type === "type" ? active.missingFonts ?? [] : [];
2012
+ const style = (change) => {
2013
+ onChange({ ...options, ...change });
2014
+ const s = {};
2015
+ for (const k of ["fontFamily", "fontSize", "fontWeight", "italic", "color"]) if (k in change) s[k] = change[k];
2016
+ const p = change.align ? { align: change.align } : null;
2017
+ try {
2018
+ setError(null);
2019
+ if (session?.alive) {
2020
+ if (Object.keys(s).length) session.setStyle(s);
2021
+ if (p) session.setParagraph(p);
2022
+ if (session.error) setError(session.error);
2023
+ } else if (typeId) {
2024
+ if (Object.keys(s).length) controller.setTextStyle(typeId, s);
2025
+ if (p) controller.setParagraphStyle(typeId, p);
2026
+ }
2027
+ } catch (e) {
2028
+ setError(e instanceof Error ? e.message : String(e));
2029
+ }
2030
+ };
2031
+ return /* @__PURE__ */ jsxs12("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "type-options", children: [
2032
+ /* @__PURE__ */ jsxs12("div", { className: "flex flex-wrap items-center gap-2", children: [
2033
+ /* @__PURE__ */ jsxs12("label", { className: "flex items-center gap-1", children: [
2034
+ "Font",
2035
+ /* @__PURE__ */ jsx12(
2036
+ "input",
2037
+ {
2038
+ list: "pixerate-type-fonts",
2039
+ "aria-label": "Font family",
2040
+ value: shown.fontFamily,
2041
+ onChange: (e) => e.target.value.trim() && style({ fontFamily: e.target.value }),
2042
+ className: "w-32 rounded border border-slate-700 bg-slate-950 px-1 py-0.5"
2043
+ }
2044
+ ),
2045
+ /* @__PURE__ */ jsx12("datalist", { id: "pixerate-type-fonts", children: fonts.map((f) => /* @__PURE__ */ jsx12("option", { value: f }, f)) })
2046
+ ] }),
2047
+ /* @__PURE__ */ jsxs12("label", { className: "flex items-center gap-1", children: [
2048
+ "Size",
2049
+ /* @__PURE__ */ jsx12(
2050
+ "input",
2051
+ {
2052
+ type: "number",
2053
+ "aria-label": "Font size",
2054
+ min: 1,
2055
+ max: 2e3,
2056
+ value: Math.round(shown.fontSize * 10) / 10,
2057
+ onChange: (e) => Number(e.target.value) > 0 && style({ fontSize: Number(e.target.value) }),
2058
+ className: "w-16 rounded border border-slate-700 bg-slate-950 px-1 py-0.5"
2059
+ }
2060
+ )
2061
+ ] }),
2062
+ /* @__PURE__ */ jsx12("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" }),
2063
+ /* @__PURE__ */ jsx12("button", { type: "button", "aria-pressed": shown.italic, className: `${chip4(shown.italic)} italic`, onClick: () => style({ italic: !shown.italic }), children: "I" }),
2064
+ /* @__PURE__ */ jsx12("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" })
2065
+ ] }),
2066
+ /* @__PURE__ */ jsx12("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Alignment", children: TEXT_ALIGNS.map((a) => /* @__PURE__ */ jsx12("button", { type: "button", "aria-pressed": options.align === a, className: chip4(options.align === a), onClick: () => style({ align: a }), children: ALIGN_LABELS[a] }, a)) }),
2067
+ /* @__PURE__ */ jsx12("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." }),
2068
+ missing.length > 0 && /* @__PURE__ */ jsxs12("p", { role: "status", className: "text-amber-400", "data-testid": "type-missing-fonts", children: [
2069
+ "Missing ",
2070
+ missing.length === 1 ? "font" : "fonts",
2071
+ ": ",
2072
+ missing.join(", ")
2073
+ ] }),
2074
+ error && /* @__PURE__ */ jsx12("p", { role: "alert", className: "text-rose-400", children: error })
2075
+ ] });
2076
+ };
2077
+
2078
+ // src/image-editor/ImageEditor.tsx
2079
+ import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
1808
2080
  var ImageEditor = ({
1809
2081
  editor: externalEditor,
1810
2082
  src,
@@ -1822,9 +2094,9 @@ var ImageEditor = ({
1822
2094
  const legacyProcess = normalizeProcessVersion(state.adjustments.process) < LATEST_PROCESS_VERSION;
1823
2095
  const canvasRef = useRef5(null);
1824
2096
  const containerRef = useRef5(null);
1825
- const [activeTab, setActiveTab] = useState11("crop");
1826
- const [activeCropRatio, setActiveCropRatio] = useState11(null);
1827
- const [selectionOptions, setSelectionOptions] = useState11(DEFAULT_SELECTION_TOOL_OPTIONS);
2097
+ const [activeTab, setActiveTab] = useState13("crop");
2098
+ const [activeCropRatio, setActiveCropRatio] = useState13(null);
2099
+ const [selectionOptions, setSelectionOptions] = useState13(DEFAULT_SELECTION_TOOL_OPTIONS);
1828
2100
  const selectionOptionsRef = useRef5(selectionOptions);
1829
2101
  selectionOptionsRef.current = selectionOptions;
1830
2102
  const selectionGestureRef = useRef5(null);
@@ -1832,7 +2104,7 @@ var ImageEditor = ({
1832
2104
  selectionGestureRef.current = new SelectionGesture(controller, () => selectionOptionsRef.current);
1833
2105
  }
1834
2106
  const selectionDraftRef = useRef5(null);
1835
- const [selectionError, setSelectionError] = useState11(null);
2107
+ const [selectionError, setSelectionError] = useState13(null);
1836
2108
  const paintGestureRef = useRef5(null);
1837
2109
  const paintControllerRef = useRef5(controller);
1838
2110
  if (!paintGestureRef.current || paintControllerRef.current !== controller) {
@@ -1840,7 +2112,7 @@ var ImageEditor = ({
1840
2112
  paintControllerRef.current = controller;
1841
2113
  }
1842
2114
  const brushCursorRef = useRef5(null);
1843
- const [paintError, setPaintError] = useState11(null);
2115
+ const [paintError, setPaintError] = useState13(null);
1844
2116
  const transformToolRef = useRef5(null);
1845
2117
  const transformControllerRef = useRef5(controller);
1846
2118
  if (!transformToolRef.current || transformControllerRef.current !== controller) {
@@ -1851,15 +2123,33 @@ var ImageEditor = ({
1851
2123
  transformControllerRef.current = controller;
1852
2124
  }
1853
2125
  const transformTool = transformToolRef.current;
1854
- const [, setTransformTick] = useState11(0);
1855
- const [transformCursor, setTransformCursor] = useState11("default");
1856
- const [inpaintPrompt, setInpaintPrompt] = useState11("");
1857
- const [inpaintMaskMode, setInpaintMaskMode] = useState11("annotations");
1858
- const [isRemovingBg, setIsRemovingBg] = useState11(false);
1859
- const [isInpainting, setIsInpainting] = useState11(false);
1860
- const [aiError, setAiError] = useState11(null);
1861
- const [aiSuccess, setAiSuccess] = useState11(null);
1862
- const [aiTarget, setAiTarget] = useState11("auto");
2126
+ const [, setTransformTick] = useState13(0);
2127
+ const [transformCursor, setTransformCursor] = useState13("default");
2128
+ const [shapeOptions, setShapeOptions] = useState13(DEFAULT_SHAPE_TOOL_OPTIONS);
2129
+ const shapeOptionsRef = useRef5(shapeOptions);
2130
+ shapeOptionsRef.current = shapeOptions;
2131
+ const [typeOptions, setTypeOptions] = useState13(DEFAULT_TYPE_TOOL_OPTIONS);
2132
+ const typeOptionsRef = useRef5(typeOptions);
2133
+ typeOptionsRef.current = typeOptions;
2134
+ const shapeGestureRef = useRef5(null);
2135
+ const typeToolRef = useRef5(null);
2136
+ const shapeTypeControllerRef = useRef5(controller);
2137
+ if (!shapeGestureRef.current || !typeToolRef.current || shapeTypeControllerRef.current !== controller) {
2138
+ typeToolRef.current?.finish();
2139
+ shapeGestureRef.current = new ShapeDrawGesture(controller, () => shapeOptionsRef.current);
2140
+ typeToolRef.current = new TypeToolGesture(controller, () => typeOptionsRef.current);
2141
+ shapeTypeControllerRef.current = controller;
2142
+ }
2143
+ const typeInputRef = useRef5(null);
2144
+ const [typeSession, setTypeSession] = useState13(typeToolRef.current.session);
2145
+ const [shapeTypeError, setShapeTypeError] = useState13(null);
2146
+ const [inpaintPrompt, setInpaintPrompt] = useState13("");
2147
+ const [inpaintMaskMode, setInpaintMaskMode] = useState13("annotations");
2148
+ const [isRemovingBg, setIsRemovingBg] = useState13(false);
2149
+ const [isInpainting, setIsInpainting] = useState13(false);
2150
+ const [aiError, setAiError] = useState13(null);
2151
+ const [aiSuccess, setAiSuccess] = useState13(null);
2152
+ const [aiTarget, setAiTarget] = useState13("auto");
1863
2153
  const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
1864
2154
  const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
1865
2155
  const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
@@ -1922,10 +2212,10 @@ var ImageEditor = ({
1922
2212
  setIsInpainting(false);
1923
2213
  }
1924
2214
  };
1925
- const [activeColor, setActiveColor] = useState11("#ef4444");
1926
- const [strokeWidth, setStrokeWidth] = useState11(3);
1927
- const [fontSize, setFontSize] = useState11(24);
1928
- const [textInput, setTextInput] = useState11("");
2215
+ const [activeColor, setActiveColor] = useState13("#ef4444");
2216
+ const [strokeWidth, setStrokeWidth] = useState13(3);
2217
+ const [fontSize, setFontSize] = useState13(24);
2218
+ const [textInput, setTextInput] = useState13("");
1929
2219
  const draftAnnotationRef = useRef5(null);
1930
2220
  const draftCropRef = useRef5(null);
1931
2221
  const cropDragInfoRef = useRef5(null);
@@ -1950,12 +2240,49 @@ var ImageEditor = ({
1950
2240
  draftCrop: draftCrop !== void 0 ? draftCrop : draftCropRef.current,
1951
2241
  draftSelectionPath: selectionDraftRef.current,
1952
2242
  brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" && !transformTool.active ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null,
1953
- freeTransform: transformTool.overlay()
2243
+ freeTransform: transformTool.overlay(),
2244
+ textEdit: typeToolRef.current?.session?.alive ? typeToolRef.current.session.overlay() : null
1954
2245
  });
1955
2246
  },
1956
2247
  [controller, activeTab, transformTool]
1957
2248
  );
1958
- useEffect8(() => transformTool.subscribe(() => {
2249
+ useEffect10(() => typeSession?.subscribe(() => void renderCanvas()), [typeSession, renderCanvas]);
2250
+ useEffect10(() => {
2251
+ if (activeTab === "annotate" && state.activeTool === "type") return;
2252
+ if (typeToolRef.current?.session) {
2253
+ typeToolRef.current.finish();
2254
+ setTypeSession(null);
2255
+ void renderCanvas();
2256
+ }
2257
+ }, [activeTab, state.activeTool, renderCanvas]);
2258
+ const finishTyping = () => {
2259
+ typeToolRef.current?.finish();
2260
+ setTypeSession(null);
2261
+ void renderCanvas();
2262
+ };
2263
+ const handleTypeKeyDown = (e) => {
2264
+ const session = typeToolRef.current?.session;
2265
+ if (!session || e.nativeEvent.isComposing) return;
2266
+ if (e.key === "Escape") {
2267
+ e.preventDefault();
2268
+ finishTyping();
2269
+ return;
2270
+ }
2271
+ if ((e.metaKey || e.ctrlKey) && ["z", "y", "c", "x", "v"].includes(e.key.toLowerCase())) return;
2272
+ if (session.handleKey(e)) {
2273
+ e.preventDefault();
2274
+ setShapeTypeError(session.error);
2275
+ }
2276
+ };
2277
+ const handleTypeInput = (e) => {
2278
+ const el = e.currentTarget;
2279
+ const session = typeToolRef.current?.session;
2280
+ if (session && el.value && !e.nativeEvent.isComposing) {
2281
+ session.insert(el.value);
2282
+ el.value = "";
2283
+ }
2284
+ };
2285
+ useEffect10(() => transformTool.subscribe(() => {
1959
2286
  setTransformTick((n) => n + 1);
1960
2287
  void renderCanvas();
1961
2288
  }), [transformTool, renderCanvas]);
@@ -1998,7 +2325,7 @@ var ImageEditor = ({
1998
2325
  transformTool.up();
1999
2326
  return true;
2000
2327
  };
2001
- useEffect8(() => {
2328
+ useEffect10(() => {
2002
2329
  if (typeof window === "undefined") return;
2003
2330
  const onKey = (e) => {
2004
2331
  if (transformTool.key(e)) e.preventDefault();
@@ -2006,7 +2333,7 @@ var ImageEditor = ({
2006
2333
  window.addEventListener("keydown", onKey);
2007
2334
  return () => window.removeEventListener("keydown", onKey);
2008
2335
  }, [transformTool]);
2009
- useEffect8(() => {
2336
+ useEffect10(() => {
2010
2337
  const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
2011
2338
  const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
2012
2339
  const animId = raf(() => {
@@ -2014,12 +2341,12 @@ var ImageEditor = ({
2014
2341
  });
2015
2342
  return () => caf(animId);
2016
2343
  }, [renderCanvas, state]);
2017
- useEffect8(() => {
2344
+ useEffect10(() => {
2018
2345
  if (activeTab === "crop" && editor.state.activeTool !== "crop") {
2019
2346
  editor.setTool("crop");
2020
2347
  }
2021
2348
  }, [activeTab, editor]);
2022
- useEffect8(() => {
2349
+ useEffect10(() => {
2023
2350
  const container = containerRef.current;
2024
2351
  if (!container) return;
2025
2352
  if (typeof ResizeObserver !== "undefined") {
@@ -2068,7 +2395,7 @@ var ImageEditor = ({
2068
2395
  } catch {
2069
2396
  }
2070
2397
  const [first] = paintSamples(e);
2071
- setPaintError(paintGestureRef.current.down(first));
2398
+ setPaintError(paintGestureRef.current.down({ ...first, altKey: e.altKey }));
2072
2399
  };
2073
2400
  const handlePaintPointerMove = (e) => {
2074
2401
  if (handleTransformPointerMove(e)) return;
@@ -2087,7 +2414,7 @@ var ImageEditor = ({
2087
2414
  if (g.error) setPaintError(g.error);
2088
2415
  }
2089
2416
  };
2090
- useEffect8(() => {
2417
+ useEffect10(() => {
2091
2418
  if (activeTab !== "paint" || typeof window === "undefined") return;
2092
2419
  const onKey = (e) => {
2093
2420
  if (handlePaintShortcut(controller, e)) e.preventDefault();
@@ -2131,6 +2458,17 @@ var ImageEditor = ({
2131
2458
  }
2132
2459
  return;
2133
2460
  }
2461
+ if (activeTab === "annotate" && (state.activeTool === "shape" || state.activeTool === "type")) {
2462
+ const imgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);
2463
+ setShapeTypeError(null);
2464
+ if (state.activeTool === "shape") shapeGestureRef.current.down(imgPt);
2465
+ else {
2466
+ typeToolRef.current.down(imgPt, { shift: e.shiftKey });
2467
+ setTypeSession(typeToolRef.current.session);
2468
+ void renderCanvas();
2469
+ }
2470
+ return;
2471
+ }
2134
2472
  if (activeTab === "annotate") {
2135
2473
  const imgPt = canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false);
2136
2474
  dragStartPointRef.current = imgPt;
@@ -2221,6 +2559,14 @@ var ImageEditor = ({
2221
2559
  }
2222
2560
  return;
2223
2561
  }
2562
+ if (activeTab === "annotate" && state.activeTool === "shape") {
2563
+ const g = shapeGestureRef.current;
2564
+ if (g.active) {
2565
+ g.move(canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false), { shift: e.shiftKey, alt: e.altKey });
2566
+ if (g.error) setShapeTypeError(g.error);
2567
+ }
2568
+ return;
2569
+ }
2224
2570
  if (activeTab === "annotate") {
2225
2571
  if (annotationDragInfoRef.current) {
2226
2572
  const drag = annotationDragInfoRef.current;
@@ -2347,6 +2693,19 @@ var ImageEditor = ({
2347
2693
  }
2348
2694
  return;
2349
2695
  }
2696
+ if (activeTab === "annotate" && state.activeTool === "shape") {
2697
+ shapeGestureRef.current.up();
2698
+ return;
2699
+ }
2700
+ if (activeTab === "annotate" && state.activeTool === "type") {
2701
+ const tool = typeToolRef.current;
2702
+ tool.up(canvasToImagePoint(canvasPt, state, canvas.width, canvas.height, false));
2703
+ setTypeSession(tool.session);
2704
+ if (tool.error) setShapeTypeError(tool.error);
2705
+ void renderCanvas();
2706
+ if (tool.session) setTimeout(() => typeInputRef.current?.focus(), 0);
2707
+ return;
2708
+ }
2350
2709
  if (activeTab === "annotate") {
2351
2710
  if (annotationDragInfoRef.current) {
2352
2711
  annotationDragInfoRef.current = null;
@@ -2450,15 +2809,15 @@ var ImageEditor = ({
2450
2809
  link.click();
2451
2810
  }
2452
2811
  };
2453
- return /* @__PURE__ */ jsxs11(
2812
+ return /* @__PURE__ */ jsxs13(
2454
2813
  "div",
2455
2814
  {
2456
2815
  className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
2457
2816
  style,
2458
2817
  children: [
2459
- /* @__PURE__ */ jsxs11("div", { className: "flex flex-wrap items-center justify-between px-4 py-3 bg-slate-950/80 border-b border-slate-800 gap-3", children: [
2460
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
2461
- /* @__PURE__ */ jsx11(
2818
+ /* @__PURE__ */ jsxs13("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: [
2819
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
2820
+ /* @__PURE__ */ jsx13(
2462
2821
  "button",
2463
2822
  {
2464
2823
  type: "button",
@@ -2470,7 +2829,7 @@ var ImageEditor = ({
2470
2829
  children: "Transform & Crop"
2471
2830
  }
2472
2831
  ),
2473
- /* @__PURE__ */ jsx11(
2832
+ /* @__PURE__ */ jsx13(
2474
2833
  "button",
2475
2834
  {
2476
2835
  type: "button",
@@ -2482,7 +2841,7 @@ var ImageEditor = ({
2482
2841
  children: "Adjustments"
2483
2842
  }
2484
2843
  ),
2485
- /* @__PURE__ */ jsx11(
2844
+ /* @__PURE__ */ jsx13(
2486
2845
  "button",
2487
2846
  {
2488
2847
  type: "button",
@@ -2494,7 +2853,7 @@ var ImageEditor = ({
2494
2853
  children: "Layers"
2495
2854
  }
2496
2855
  ),
2497
- /* @__PURE__ */ jsx11(
2856
+ /* @__PURE__ */ jsx13(
2498
2857
  "button",
2499
2858
  {
2500
2859
  type: "button",
@@ -2506,7 +2865,7 @@ var ImageEditor = ({
2506
2865
  children: "Paint"
2507
2866
  }
2508
2867
  ),
2509
- /* @__PURE__ */ jsx11(
2868
+ /* @__PURE__ */ jsx13(
2510
2869
  "button",
2511
2870
  {
2512
2871
  type: "button",
@@ -2518,7 +2877,7 @@ var ImageEditor = ({
2518
2877
  children: "Select & Mask"
2519
2878
  }
2520
2879
  ),
2521
- /* @__PURE__ */ jsx11(
2880
+ /* @__PURE__ */ jsx13(
2522
2881
  "button",
2523
2882
  {
2524
2883
  type: "button",
@@ -2530,7 +2889,7 @@ var ImageEditor = ({
2530
2889
  children: "Annotations"
2531
2890
  }
2532
2891
  ),
2533
- /* @__PURE__ */ jsx11(
2892
+ /* @__PURE__ */ jsx13(
2534
2893
  "button",
2535
2894
  {
2536
2895
  type: "button",
@@ -2542,7 +2901,7 @@ var ImageEditor = ({
2542
2901
  children: "Depth Mask"
2543
2902
  }
2544
2903
  ),
2545
- /* @__PURE__ */ jsxs11(
2904
+ /* @__PURE__ */ jsxs13(
2546
2905
  "button",
2547
2906
  {
2548
2907
  type: "button",
@@ -2552,14 +2911,14 @@ var ImageEditor = ({
2552
2911
  },
2553
2912
  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"}`,
2554
2913
  children: [
2555
- /* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
2914
+ /* @__PURE__ */ jsx13("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx13("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" }) }),
2556
2915
  "AI Tools"
2557
2916
  ]
2558
2917
  }
2559
2918
  )
2560
2919
  ] }),
2561
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 text-xs", children: [
2562
- /* @__PURE__ */ jsx11(
2920
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 text-xs", children: [
2921
+ /* @__PURE__ */ jsx13(
2563
2922
  "button",
2564
2923
  {
2565
2924
  type: "button",
@@ -2570,7 +2929,7 @@ var ImageEditor = ({
2570
2929
  children: "\u21A9"
2571
2930
  }
2572
2931
  ),
2573
- /* @__PURE__ */ jsx11(
2932
+ /* @__PURE__ */ jsx13(
2574
2933
  "button",
2575
2934
  {
2576
2935
  type: "button",
@@ -2581,7 +2940,7 @@ var ImageEditor = ({
2581
2940
  children: "\u21AA"
2582
2941
  }
2583
2942
  ),
2584
- /* @__PURE__ */ jsx11(
2943
+ /* @__PURE__ */ jsx13(
2585
2944
  "button",
2586
2945
  {
2587
2946
  type: "button",
@@ -2590,8 +2949,8 @@ var ImageEditor = ({
2590
2949
  children: "Reset"
2591
2950
  }
2592
2951
  ),
2593
- /* @__PURE__ */ jsx11("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2594
- /* @__PURE__ */ jsx11(
2952
+ /* @__PURE__ */ jsx13("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2953
+ /* @__PURE__ */ jsx13(
2595
2954
  "button",
2596
2955
  {
2597
2956
  type: "button",
@@ -2601,11 +2960,11 @@ var ImageEditor = ({
2601
2960
  children: "-"
2602
2961
  }
2603
2962
  ),
2604
- /* @__PURE__ */ jsxs11("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
2963
+ /* @__PURE__ */ jsxs13("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
2605
2964
  Math.round(state.zoom * 100),
2606
2965
  "%"
2607
2966
  ] }),
2608
- /* @__PURE__ */ jsx11(
2967
+ /* @__PURE__ */ jsx13(
2609
2968
  "button",
2610
2969
  {
2611
2970
  type: "button",
@@ -2615,8 +2974,8 @@ var ImageEditor = ({
2615
2974
  children: "+"
2616
2975
  }
2617
2976
  ),
2618
- /* @__PURE__ */ jsx11("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2619
- /* @__PURE__ */ jsx11(
2977
+ /* @__PURE__ */ jsx13("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
2978
+ /* @__PURE__ */ jsx13(
2620
2979
  "button",
2621
2980
  {
2622
2981
  type: "button",
@@ -2627,7 +2986,7 @@ var ImageEditor = ({
2627
2986
  children: "Hold Compare"
2628
2987
  }
2629
2988
  ),
2630
- /* @__PURE__ */ jsx11(
2989
+ /* @__PURE__ */ jsx13(
2631
2990
  "button",
2632
2991
  {
2633
2992
  type: "button",
@@ -2638,38 +2997,59 @@ var ImageEditor = ({
2638
2997
  )
2639
2998
  ] })
2640
2999
  ] }),
2641
- transformTool.active && /* @__PURE__ */ jsx11(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
2642
- !transformTool.active && transformTool.error && /* @__PURE__ */ jsx11("div", { role: "alert", className: "border-b border-rose-900 bg-rose-950/80 px-4 py-1.5 text-xs text-rose-200", children: transformTool.error }),
2643
- /* @__PURE__ */ jsxs11("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
2644
- /* @__PURE__ */ jsx11(
3000
+ transformTool.active && /* @__PURE__ */ jsx13(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
3001
+ !transformTool.active && transformTool.error && /* @__PURE__ */ jsx13("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 }),
3002
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
3003
+ /* @__PURE__ */ jsxs13(
2645
3004
  "div",
2646
3005
  {
2647
3006
  ref: containerRef,
2648
3007
  className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
2649
- children: /* @__PURE__ */ jsx11(
2650
- "canvas",
2651
- {
2652
- ref: canvasRef,
2653
- onMouseDown: handleMouseDown,
2654
- onMouseMove: handleMouseMove,
2655
- onMouseUp: handleMouseUp,
2656
- onMouseLeave: handleMouseUp,
2657
- onPointerDown: handlePaintPointerDown,
2658
- onPointerMove: handlePaintPointerMove,
2659
- onPointerUp: handlePaintPointerUp,
2660
- onPointerCancel: () => paintGestureRef.current?.cancel(),
2661
- "data-testid": "image-editor-canvas",
2662
- style: transformTool.active ? { cursor: transformCursor } : void 0,
2663
- className: `absolute inset-0 w-full h-full block ${transformTool.active ? "touch-none" : activeTab === "paint" ? "touch-none cursor-crosshair" : ""}`
2664
- }
2665
- )
3008
+ children: [
3009
+ /* @__PURE__ */ jsx13(
3010
+ "canvas",
3011
+ {
3012
+ ref: canvasRef,
3013
+ onMouseDown: handleMouseDown,
3014
+ onMouseMove: handleMouseMove,
3015
+ onMouseUp: handleMouseUp,
3016
+ onMouseLeave: handleMouseUp,
3017
+ onPointerDown: handlePaintPointerDown,
3018
+ onPointerMove: handlePaintPointerMove,
3019
+ onPointerUp: handlePaintPointerUp,
3020
+ onPointerCancel: () => paintGestureRef.current?.cancel(),
3021
+ "data-testid": "image-editor-canvas",
3022
+ style: transformTool.active ? { cursor: transformCursor } : void 0,
3023
+ 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" : ""}`
3024
+ }
3025
+ ),
3026
+ typeSession && /* @__PURE__ */ jsx13(
3027
+ "textarea",
3028
+ {
3029
+ ref: typeInputRef,
3030
+ "aria-label": "Edit text",
3031
+ "data-testid": "type-input",
3032
+ autoCapitalize: "off",
3033
+ autoCorrect: "off",
3034
+ spellCheck: false,
3035
+ onKeyDown: handleTypeKeyDown,
3036
+ onInput: handleTypeInput,
3037
+ onCompositionEnd: (e) => {
3038
+ const session = typeToolRef.current?.session;
3039
+ if (session && e.data) session.insert(e.data);
3040
+ e.currentTarget.value = "";
3041
+ },
3042
+ className: "absolute left-0 top-0 h-px w-px opacity-0"
3043
+ }
3044
+ )
3045
+ ]
2666
3046
  }
2667
3047
  ),
2668
- /* @__PURE__ */ jsxs11("div", { className: "w-full md:w-80 bg-slate-900/90 border-t md:border-t-0 md:border-l border-slate-800 p-4 overflow-y-auto h-auto md:h-full md:max-h-[560px]", children: [
2669
- activeTab === "crop" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-4 text-xs", children: [
2670
- /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
2671
- /* @__PURE__ */ jsxs11("div", { className: "grid grid-cols-3 gap-2", children: [
2672
- /* @__PURE__ */ jsx11(
3048
+ /* @__PURE__ */ jsxs13("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: [
3049
+ activeTab === "crop" && /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-4 text-xs", children: [
3050
+ /* @__PURE__ */ jsx13("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
3051
+ /* @__PURE__ */ jsxs13("div", { className: "grid grid-cols-3 gap-2", children: [
3052
+ /* @__PURE__ */ jsx13(
2673
3053
  "button",
2674
3054
  {
2675
3055
  type: "button",
@@ -2681,7 +3061,7 @@ var ImageEditor = ({
2681
3061
  children: "Freeform"
2682
3062
  }
2683
3063
  ),
2684
- /* @__PURE__ */ jsx11(
3064
+ /* @__PURE__ */ jsx13(
2685
3065
  "button",
2686
3066
  {
2687
3067
  type: "button",
@@ -2693,7 +3073,7 @@ var ImageEditor = ({
2693
3073
  children: "1:1 Square"
2694
3074
  }
2695
3075
  ),
2696
- /* @__PURE__ */ jsx11(
3076
+ /* @__PURE__ */ jsx13(
2697
3077
  "button",
2698
3078
  {
2699
3079
  type: "button",
@@ -2705,7 +3085,7 @@ var ImageEditor = ({
2705
3085
  children: "4:3 Standard"
2706
3086
  }
2707
3087
  ),
2708
- /* @__PURE__ */ jsx11(
3088
+ /* @__PURE__ */ jsx13(
2709
3089
  "button",
2710
3090
  {
2711
3091
  type: "button",
@@ -2717,7 +3097,7 @@ var ImageEditor = ({
2717
3097
  children: "16:9 Wide"
2718
3098
  }
2719
3099
  ),
2720
- /* @__PURE__ */ jsx11(
3100
+ /* @__PURE__ */ jsx13(
2721
3101
  "button",
2722
3102
  {
2723
3103
  type: "button",
@@ -2729,7 +3109,7 @@ var ImageEditor = ({
2729
3109
  children: "3:2 Photo"
2730
3110
  }
2731
3111
  ),
2732
- /* @__PURE__ */ jsx11(
3112
+ /* @__PURE__ */ jsx13(
2733
3113
  "button",
2734
3114
  {
2735
3115
  type: "button",
@@ -2742,10 +3122,10 @@ var ImageEditor = ({
2742
3122
  }
2743
3123
  )
2744
3124
  ] }),
2745
- /* @__PURE__ */ jsx11("div", { className: "h-px bg-slate-800 my-1" }),
2746
- /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
2747
- /* @__PURE__ */ jsxs11("div", { className: "grid grid-cols-2 gap-2", children: [
2748
- /* @__PURE__ */ jsx11(
3125
+ /* @__PURE__ */ jsx13("div", { className: "h-px bg-slate-800 my-1" }),
3126
+ /* @__PURE__ */ jsx13("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
3127
+ /* @__PURE__ */ jsxs13("div", { className: "grid grid-cols-2 gap-2", children: [
3128
+ /* @__PURE__ */ jsx13(
2749
3129
  "button",
2750
3130
  {
2751
3131
  type: "button",
@@ -2754,7 +3134,7 @@ var ImageEditor = ({
2754
3134
  children: "Rotate -90\xB0"
2755
3135
  }
2756
3136
  ),
2757
- /* @__PURE__ */ jsx11(
3137
+ /* @__PURE__ */ jsx13(
2758
3138
  "button",
2759
3139
  {
2760
3140
  type: "button",
@@ -2763,7 +3143,7 @@ var ImageEditor = ({
2763
3143
  children: "Rotate +90\xB0"
2764
3144
  }
2765
3145
  ),
2766
- /* @__PURE__ */ jsx11(
3146
+ /* @__PURE__ */ jsx13(
2767
3147
  "button",
2768
3148
  {
2769
3149
  type: "button",
@@ -2772,7 +3152,7 @@ var ImageEditor = ({
2772
3152
  children: "Flip Horizontal"
2773
3153
  }
2774
3154
  ),
2775
- /* @__PURE__ */ jsx11(
3155
+ /* @__PURE__ */ jsx13(
2776
3156
  "button",
2777
3157
  {
2778
3158
  type: "button",
@@ -2783,10 +3163,10 @@ var ImageEditor = ({
2783
3163
  )
2784
3164
  ] })
2785
3165
  ] }),
2786
- activeTab === "adjust" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
2787
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
2788
- /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
2789
- /* @__PURE__ */ jsx11(
3166
+ activeTab === "adjust" && /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-3 text-xs", children: [
3167
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between", children: [
3168
+ /* @__PURE__ */ jsx13("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
3169
+ /* @__PURE__ */ jsx13(
2790
3170
  "button",
2791
3171
  {
2792
3172
  type: "button",
@@ -2796,9 +3176,9 @@ var ImageEditor = ({
2796
3176
  }
2797
3177
  )
2798
3178
  ] }),
2799
- /* @__PURE__ */ jsx11(Histogram, { histogram: editor.histogram }),
2800
- IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ jsxs11(React10.Fragment, { children: [
2801
- /* @__PURE__ */ jsx11(
3179
+ /* @__PURE__ */ jsx13(Histogram, { histogram: editor.histogram }),
3180
+ IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ jsxs13(React12.Fragment, { children: [
3181
+ /* @__PURE__ */ jsx13(
2802
3182
  ControlSlider,
2803
3183
  {
2804
3184
  spec,
@@ -2807,14 +3187,14 @@ var ImageEditor = ({
2807
3187
  onChange: (v) => editor.setAdjustments({ [spec.id]: v })
2808
3188
  }
2809
3189
  ),
2810
- spec.id === "tint" && legacyProcess && /* @__PURE__ */ jsxs11(
3190
+ spec.id === "tint" && legacyProcess && /* @__PURE__ */ jsxs13(
2811
3191
  "div",
2812
3192
  {
2813
3193
  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",
2814
3194
  "data-testid": "image-editor-process-notice",
2815
3195
  children: [
2816
- /* @__PURE__ */ jsx11("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
2817
- /* @__PURE__ */ jsx11(
3196
+ /* @__PURE__ */ jsx13("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
3197
+ /* @__PURE__ */ jsx13(
2818
3198
  "button",
2819
3199
  {
2820
3200
  type: "button",
@@ -2827,7 +3207,7 @@ var ImageEditor = ({
2827
3207
  }
2828
3208
  )
2829
3209
  ] }, spec.id)),
2830
- /* @__PURE__ */ jsx11("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx11(
3210
+ /* @__PURE__ */ jsx13("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx13(
2831
3211
  AdjustmentLayersPanel,
2832
3212
  {
2833
3213
  controller,
@@ -2836,9 +3216,9 @@ var ImageEditor = ({
2836
3216
  }
2837
3217
  ) })
2838
3218
  ] }),
2839
- activeTab === "layers" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
2840
- /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
2841
- /* @__PURE__ */ jsx11(
3219
+ activeTab === "layers" && /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-3 text-xs", children: [
3220
+ /* @__PURE__ */ jsx13("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
3221
+ /* @__PURE__ */ jsx13(
2842
3222
  "button",
2843
3223
  {
2844
3224
  type: "button",
@@ -2849,12 +3229,12 @@ var ImageEditor = ({
2849
3229
  children: "Free Transform"
2850
3230
  }
2851
3231
  ),
2852
- /* @__PURE__ */ jsx11(LayersPanel, { controller })
3232
+ /* @__PURE__ */ jsx13(LayersPanel, { controller })
2853
3233
  ] }),
2854
- activeTab === "paint" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
2855
- /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
2856
- /* @__PURE__ */ jsx11(BrushOptionsBar, { controller }),
2857
- /* @__PURE__ */ jsx11(
3234
+ activeTab === "paint" && /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-3 text-xs", children: [
3235
+ /* @__PURE__ */ jsx13("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
3236
+ /* @__PURE__ */ jsx13(BrushOptionsBar, { controller }),
3237
+ /* @__PURE__ */ jsx13(
2858
3238
  "button",
2859
3239
  {
2860
3240
  type: "button",
@@ -2865,12 +3245,29 @@ var ImageEditor = ({
2865
3245
  children: "Free Transform"
2866
3246
  }
2867
3247
  ),
2868
- paintError && /* @__PURE__ */ jsx11("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
2869
- /* @__PURE__ */ jsx11("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx11(LayersPanel, { controller }) })
3248
+ paintError && /* @__PURE__ */ jsx13("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
3249
+ /* @__PURE__ */ jsx13("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx13(LayersPanel, { controller }) })
2870
3250
  ] }),
2871
- activeTab === "annotate" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
2872
- /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
2873
- /* @__PURE__ */ jsx11("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ jsx11(
3251
+ activeTab === "annotate" && /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-3 text-xs", children: [
3252
+ /* @__PURE__ */ jsx13("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Shape & Type Layers" }),
3253
+ /* @__PURE__ */ jsx13("div", { className: "grid grid-cols-2 gap-1.5", children: ["shape", "type"].map((t) => /* @__PURE__ */ jsx13(
3254
+ "button",
3255
+ {
3256
+ type: "button",
3257
+ "aria-pressed": state.activeTool === t,
3258
+ onClick: () => editor.setTool(t),
3259
+ 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"}`,
3260
+ children: t === "shape" ? "Shape" : "Type"
3261
+ },
3262
+ t
3263
+ )) }),
3264
+ state.activeTool === "shape" && /* @__PURE__ */ jsx13(ShapeOptionsBar, { controller, options: shapeOptions, onChange: setShapeOptions }),
3265
+ state.activeTool === "type" && /* @__PURE__ */ jsx13(TypeOptionsBar, { controller, options: typeOptions, onChange: setTypeOptions, session: typeSession }),
3266
+ state.activeTool === "type" && typeSession && /* @__PURE__ */ jsx13("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" }),
3267
+ shapeTypeError && /* @__PURE__ */ jsx13("p", { role: "alert", className: "text-rose-400", "data-testid": "shape-type-error", children: shapeTypeError }),
3268
+ /* @__PURE__ */ jsx13("div", { className: "h-px bg-slate-800 my-1" }),
3269
+ /* @__PURE__ */ jsx13("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
3270
+ /* @__PURE__ */ jsx13("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ jsx13(
2874
3271
  "button",
2875
3272
  {
2876
3273
  type: "button",
@@ -2880,9 +3277,9 @@ var ImageEditor = ({
2880
3277
  },
2881
3278
  t
2882
3279
  )) }),
2883
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 mt-2", children: [
2884
- /* @__PURE__ */ jsx11("label", { className: "text-slate-400", children: "Color:" }),
2885
- /* @__PURE__ */ jsx11(
3280
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 mt-2", children: [
3281
+ /* @__PURE__ */ jsx13("label", { className: "text-slate-400", children: "Color:" }),
3282
+ /* @__PURE__ */ jsx13(
2886
3283
  "input",
2887
3284
  {
2888
3285
  type: "color",
@@ -2891,15 +3288,15 @@ var ImageEditor = ({
2891
3288
  className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
2892
3289
  }
2893
3290
  ),
2894
- /* @__PURE__ */ jsxs11("div", { className: "flex-1 ml-2", children: [
2895
- /* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
2896
- /* @__PURE__ */ jsx11("span", { children: "Width:" }),
2897
- /* @__PURE__ */ jsxs11("span", { className: "font-mono", children: [
3291
+ /* @__PURE__ */ jsxs13("div", { className: "flex-1 ml-2", children: [
3292
+ /* @__PURE__ */ jsxs13("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
3293
+ /* @__PURE__ */ jsx13("span", { children: "Width:" }),
3294
+ /* @__PURE__ */ jsxs13("span", { className: "font-mono", children: [
2898
3295
  strokeWidth,
2899
3296
  "px"
2900
3297
  ] })
2901
3298
  ] }),
2902
- /* @__PURE__ */ jsx11(
3299
+ /* @__PURE__ */ jsx13(
2903
3300
  "input",
2904
3301
  {
2905
3302
  type: "range",
@@ -2912,10 +3309,10 @@ var ImageEditor = ({
2912
3309
  )
2913
3310
  ] })
2914
3311
  ] }),
2915
- /* @__PURE__ */ jsx11("div", { className: "h-px bg-slate-800 my-1" }),
2916
- /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
2917
- /* @__PURE__ */ jsxs11("div", { className: "flex gap-2", children: [
2918
- /* @__PURE__ */ jsx11(
3312
+ /* @__PURE__ */ jsx13("div", { className: "h-px bg-slate-800 my-1" }),
3313
+ /* @__PURE__ */ jsx13("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
3314
+ /* @__PURE__ */ jsxs13("div", { className: "flex gap-2", children: [
3315
+ /* @__PURE__ */ jsx13(
2919
3316
  "input",
2920
3317
  {
2921
3318
  type: "text",
@@ -2926,7 +3323,7 @@ var ImageEditor = ({
2926
3323
  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"
2927
3324
  }
2928
3325
  ),
2929
- /* @__PURE__ */ jsx11(
3326
+ /* @__PURE__ */ jsx13(
2930
3327
  "button",
2931
3328
  {
2932
3329
  type: "button",
@@ -2936,14 +3333,14 @@ var ImageEditor = ({
2936
3333
  }
2937
3334
  )
2938
3335
  ] }),
2939
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between text-slate-400", children: [
2940
- /* @__PURE__ */ jsx11("span", { children: "Font Size:" }),
2941
- /* @__PURE__ */ jsxs11("span", { className: "font-mono", children: [
3336
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between text-slate-400", children: [
3337
+ /* @__PURE__ */ jsx13("span", { children: "Font Size:" }),
3338
+ /* @__PURE__ */ jsxs13("span", { className: "font-mono", children: [
2942
3339
  fontSize,
2943
3340
  "px"
2944
3341
  ] })
2945
3342
  ] }),
2946
- /* @__PURE__ */ jsx11(
3343
+ /* @__PURE__ */ jsx13(
2947
3344
  "input",
2948
3345
  {
2949
3346
  type: "range",
@@ -2954,14 +3351,14 @@ var ImageEditor = ({
2954
3351
  className: "w-full accent-indigo-500"
2955
3352
  }
2956
3353
  ),
2957
- /* @__PURE__ */ jsx11("div", { className: "h-px bg-slate-800 my-1" }),
2958
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
2959
- /* @__PURE__ */ jsxs11("span", { className: "text-slate-400", children: [
3354
+ /* @__PURE__ */ jsx13("div", { className: "h-px bg-slate-800 my-1" }),
3355
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between", children: [
3356
+ /* @__PURE__ */ jsxs13("span", { className: "text-slate-400", children: [
2960
3357
  "Layers (",
2961
3358
  state.annotations.length,
2962
3359
  ")"
2963
3360
  ] }),
2964
- state.selectedAnnotationId && /* @__PURE__ */ jsx11(
3361
+ state.selectedAnnotationId && /* @__PURE__ */ jsx13(
2965
3362
  "button",
2966
3363
  {
2967
3364
  type: "button",
@@ -2970,7 +3367,7 @@ var ImageEditor = ({
2970
3367
  children: "Delete Selected"
2971
3368
  }
2972
3369
  ),
2973
- state.annotations.length > 0 && /* @__PURE__ */ jsx11(
3370
+ state.annotations.length > 0 && /* @__PURE__ */ jsx13(
2974
3371
  "button",
2975
3372
  {
2976
3373
  type: "button",
@@ -2981,10 +3378,10 @@ var ImageEditor = ({
2981
3378
  )
2982
3379
  ] })
2983
3380
  ] }),
2984
- activeTab === "depth" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
2985
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
2986
- /* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
2987
- /* @__PURE__ */ jsx11(
3381
+ activeTab === "depth" && /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-3 text-xs", children: [
3382
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between", children: [
3383
+ /* @__PURE__ */ jsx13("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
3384
+ /* @__PURE__ */ jsx13(
2988
3385
  "button",
2989
3386
  {
2990
3387
  type: "button",
@@ -2994,8 +3391,8 @@ var ImageEditor = ({
2994
3391
  }
2995
3392
  )
2996
3393
  ] }),
2997
- /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
2998
- /* @__PURE__ */ jsx11(
3394
+ /* @__PURE__ */ jsxs13("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
3395
+ /* @__PURE__ */ jsx13(
2999
3396
  "input",
3000
3397
  {
3001
3398
  type: "checkbox",
@@ -3004,12 +3401,12 @@ var ImageEditor = ({
3004
3401
  className: "rounded accent-indigo-500"
3005
3402
  }
3006
3403
  ),
3007
- /* @__PURE__ */ jsx11("span", { children: "Enable Depth / Alpha Mask" })
3404
+ /* @__PURE__ */ jsx13("span", { children: "Enable Depth / Alpha Mask" })
3008
3405
  ] }),
3009
- state.depthMask.enabled && /* @__PURE__ */ jsxs11(Fragment3, { children: [
3010
- /* @__PURE__ */ jsxs11("div", { children: [
3011
- /* @__PURE__ */ jsx11("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
3012
- /* @__PURE__ */ jsx11(
3406
+ state.depthMask.enabled && /* @__PURE__ */ jsxs13(Fragment4, { children: [
3407
+ /* @__PURE__ */ jsxs13("div", { children: [
3408
+ /* @__PURE__ */ jsx13("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
3409
+ /* @__PURE__ */ jsx13(
3013
3410
  "input",
3014
3411
  {
3015
3412
  type: "text",
@@ -3020,8 +3417,8 @@ var ImageEditor = ({
3020
3417
  }
3021
3418
  )
3022
3419
  ] }),
3023
- /* @__PURE__ */ jsxs11("div", { className: "flex gap-2", children: [
3024
- /* @__PURE__ */ jsx11(
3420
+ /* @__PURE__ */ jsxs13("div", { className: "flex gap-2", children: [
3421
+ /* @__PURE__ */ jsx13(
3025
3422
  "button",
3026
3423
  {
3027
3424
  type: "button",
@@ -3030,7 +3427,7 @@ var ImageEditor = ({
3030
3427
  children: "Threshold Mode"
3031
3428
  }
3032
3429
  ),
3033
- /* @__PURE__ */ jsx11(
3430
+ /* @__PURE__ */ jsx13(
3034
3431
  "button",
3035
3432
  {
3036
3433
  type: "button",
@@ -3040,12 +3437,12 @@ var ImageEditor = ({
3040
3437
  }
3041
3438
  )
3042
3439
  ] }),
3043
- /* @__PURE__ */ jsxs11("div", { children: [
3044
- /* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3045
- /* @__PURE__ */ jsx11("span", { children: "Depth Start (Lower):" }),
3046
- /* @__PURE__ */ jsx11("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
3440
+ /* @__PURE__ */ jsxs13("div", { children: [
3441
+ /* @__PURE__ */ jsxs13("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3442
+ /* @__PURE__ */ jsx13("span", { children: "Depth Start (Lower):" }),
3443
+ /* @__PURE__ */ jsx13("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
3047
3444
  ] }),
3048
- /* @__PURE__ */ jsx11(
3445
+ /* @__PURE__ */ jsx13(
3049
3446
  "input",
3050
3447
  {
3051
3448
  type: "range",
@@ -3059,12 +3456,12 @@ var ImageEditor = ({
3059
3456
  }
3060
3457
  )
3061
3458
  ] }),
3062
- /* @__PURE__ */ jsxs11("div", { children: [
3063
- /* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3064
- /* @__PURE__ */ jsx11("span", { children: "Depth Stop (Upper):" }),
3065
- /* @__PURE__ */ jsx11("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
3459
+ /* @__PURE__ */ jsxs13("div", { children: [
3460
+ /* @__PURE__ */ jsxs13("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3461
+ /* @__PURE__ */ jsx13("span", { children: "Depth Stop (Upper):" }),
3462
+ /* @__PURE__ */ jsx13("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
3066
3463
  ] }),
3067
- /* @__PURE__ */ jsx11(
3464
+ /* @__PURE__ */ jsx13(
3068
3465
  "input",
3069
3466
  {
3070
3467
  type: "range",
@@ -3078,12 +3475,12 @@ var ImageEditor = ({
3078
3475
  }
3079
3476
  )
3080
3477
  ] }),
3081
- /* @__PURE__ */ jsxs11("div", { children: [
3082
- /* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3083
- /* @__PURE__ */ jsx11("span", { children: "Softness:" }),
3084
- /* @__PURE__ */ jsx11("span", { className: "font-mono", children: state.depthMask.softness })
3478
+ /* @__PURE__ */ jsxs13("div", { children: [
3479
+ /* @__PURE__ */ jsxs13("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3480
+ /* @__PURE__ */ jsx13("span", { children: "Softness:" }),
3481
+ /* @__PURE__ */ jsx13("span", { className: "font-mono", children: state.depthMask.softness })
3085
3482
  ] }),
3086
- /* @__PURE__ */ jsx11(
3483
+ /* @__PURE__ */ jsx13(
3087
3484
  "input",
3088
3485
  {
3089
3486
  type: "range",
@@ -3095,8 +3492,8 @@ var ImageEditor = ({
3095
3492
  }
3096
3493
  )
3097
3494
  ] }),
3098
- /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
3099
- /* @__PURE__ */ jsx11(
3495
+ /* @__PURE__ */ jsxs13("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
3496
+ /* @__PURE__ */ jsx13(
3100
3497
  "input",
3101
3498
  {
3102
3499
  type: "checkbox",
@@ -3105,12 +3502,12 @@ var ImageEditor = ({
3105
3502
  className: "rounded accent-indigo-500"
3106
3503
  }
3107
3504
  ),
3108
- /* @__PURE__ */ jsx11("span", { children: "Invert Mask" })
3505
+ /* @__PURE__ */ jsx13("span", { children: "Invert Mask" })
3109
3506
  ] })
3110
3507
  ] })
3111
3508
  ] }),
3112
- activeTab === "select" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-4 text-xs", children: [
3113
- /* @__PURE__ */ jsx11(
3509
+ activeTab === "select" && /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-4 text-xs", children: [
3510
+ /* @__PURE__ */ jsx13(
3114
3511
  SelectionOptionsBar,
3115
3512
  {
3116
3513
  controller,
@@ -3120,9 +3517,9 @@ var ImageEditor = ({
3120
3517
  quickMask: Boolean(state.quickMask)
3121
3518
  }
3122
3519
  ),
3123
- selectionError && /* @__PURE__ */ jsx11("p", { role: "alert", className: "text-rose-400", children: selectionError }),
3124
- /* @__PURE__ */ jsxs11("div", { className: "flex gap-1", children: [
3125
- /* @__PURE__ */ jsx11(
3520
+ selectionError && /* @__PURE__ */ jsx13("p", { role: "alert", className: "text-rose-400", children: selectionError }),
3521
+ /* @__PURE__ */ jsxs13("div", { className: "flex gap-1", children: [
3522
+ /* @__PURE__ */ jsx13(
3126
3523
  "button",
3127
3524
  {
3128
3525
  type: "button",
@@ -3133,7 +3530,7 @@ var ImageEditor = ({
3133
3530
  children: "Transform Selection"
3134
3531
  }
3135
3532
  ),
3136
- /* @__PURE__ */ jsx11(
3533
+ /* @__PURE__ */ jsx13(
3137
3534
  "button",
3138
3535
  {
3139
3536
  type: "button",
@@ -3145,12 +3542,12 @@ var ImageEditor = ({
3145
3542
  }
3146
3543
  )
3147
3544
  ] }),
3148
- /* @__PURE__ */ jsx11(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
3545
+ /* @__PURE__ */ jsx13(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
3149
3546
  ] }),
3150
- activeTab === "ai" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-4 text-xs", children: [
3151
- /* @__PURE__ */ jsxs11("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
3152
- /* @__PURE__ */ jsx11("span", { children: "Results go to" }),
3153
- /* @__PURE__ */ jsxs11(
3547
+ activeTab === "ai" && /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-4 text-xs", children: [
3548
+ /* @__PURE__ */ jsxs13("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
3549
+ /* @__PURE__ */ jsx13("span", { children: "Results go to" }),
3550
+ /* @__PURE__ */ jsxs13(
3154
3551
  "select",
3155
3552
  {
3156
3553
  "aria-label": "AI result target",
@@ -3158,54 +3555,54 @@ var ImageEditor = ({
3158
3555
  onChange: (e) => setAiTarget(e.target.value),
3159
3556
  className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
3160
3557
  children: [
3161
- /* @__PURE__ */ jsx11("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
3162
- /* @__PURE__ */ jsx11("option", { value: "new-layer", children: "New layer / mask" }),
3163
- /* @__PURE__ */ jsx11("option", { value: "replace", children: "Replace image" })
3558
+ /* @__PURE__ */ jsx13("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
3559
+ /* @__PURE__ */ jsx13("option", { value: "new-layer", children: "New layer / mask" }),
3560
+ /* @__PURE__ */ jsx13("option", { value: "replace", children: "Replace image" })
3164
3561
  ]
3165
3562
  }
3166
3563
  )
3167
3564
  ] }),
3168
- /* @__PURE__ */ jsxs11("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3169
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
3170
- /* @__PURE__ */ jsxs11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3171
- /* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("path", { d: "M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" }) }),
3565
+ /* @__PURE__ */ jsxs13("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3566
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between", children: [
3567
+ /* @__PURE__ */ jsxs13("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3568
+ /* @__PURE__ */ jsx13("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx13("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" }) }),
3172
3569
  "Background Removal"
3173
3570
  ] }),
3174
- isRemovingBg && /* @__PURE__ */ jsx11("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse", children: "Removing..." })
3571
+ isRemovingBg && /* @__PURE__ */ jsx13("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..." })
3175
3572
  ] }),
3176
- /* @__PURE__ */ jsx11("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
3177
- /* @__PURE__ */ jsx11(
3573
+ /* @__PURE__ */ jsx13("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
3574
+ /* @__PURE__ */ jsx13(
3178
3575
  "button",
3179
3576
  {
3180
3577
  type: "button",
3181
3578
  onClick: handleRemoveBackground,
3182
3579
  disabled: isRemovingBg || isInpainting,
3183
3580
  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",
3184
- children: isRemovingBg ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
3185
- /* @__PURE__ */ jsx11("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3581
+ children: isRemovingBg ? /* @__PURE__ */ jsxs13(Fragment4, { children: [
3582
+ /* @__PURE__ */ jsx13("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3186
3583
  "Removing Background..."
3187
- ] }) : /* @__PURE__ */ jsxs11(Fragment3, { children: [
3188
- /* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
3584
+ ] }) : /* @__PURE__ */ jsxs13(Fragment4, { children: [
3585
+ /* @__PURE__ */ jsx13("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx13("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" }) }),
3189
3586
  "Remove Background"
3190
3587
  ] })
3191
3588
  }
3192
3589
  )
3193
3590
  ] }),
3194
- /* @__PURE__ */ jsxs11("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3195
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
3196
- /* @__PURE__ */ jsxs11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3197
- /* @__PURE__ */ jsxs11("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
3198
- /* @__PURE__ */ jsx11("path", { d: "m21.64 3.64-1.28-1.28a1.2 1.2 0 0 0-1.7 0l-9.72 9.72-1.94 4.86 4.86-1.94 9.72-9.72a1.2 1.2 0 0 0 .06-1.64z" }),
3199
- /* @__PURE__ */ jsx11("path", { d: "m14 7 3 3" })
3591
+ /* @__PURE__ */ jsxs13("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3592
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between", children: [
3593
+ /* @__PURE__ */ jsxs13("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3594
+ /* @__PURE__ */ jsxs13("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
3595
+ /* @__PURE__ */ jsx13("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" }),
3596
+ /* @__PURE__ */ jsx13("path", { d: "m14 7 3 3" })
3200
3597
  ] }),
3201
3598
  "Generative Inpainting"
3202
3599
  ] }),
3203
- isInpainting && /* @__PURE__ */ jsx11("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse", children: "Inpainting..." })
3600
+ isInpainting && /* @__PURE__ */ jsx13("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..." })
3204
3601
  ] }),
3205
- /* @__PURE__ */ jsx11("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
3206
- /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1", children: [
3207
- /* @__PURE__ */ jsx11("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
3208
- /* @__PURE__ */ jsx11(
3602
+ /* @__PURE__ */ jsx13("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
3603
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-1", children: [
3604
+ /* @__PURE__ */ jsx13("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
3605
+ /* @__PURE__ */ jsx13(
3209
3606
  "textarea",
3210
3607
  {
3211
3608
  id: "ai-inpaint-prompt-react",
@@ -3217,10 +3614,10 @@ var ImageEditor = ({
3217
3614
  }
3218
3615
  )
3219
3616
  ] }),
3220
- /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1", children: [
3221
- /* @__PURE__ */ jsx11("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
3222
- /* @__PURE__ */ jsxs11("div", { className: "grid grid-cols-2 gap-1.5", children: [
3223
- /* @__PURE__ */ jsxs11(
3617
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-1", children: [
3618
+ /* @__PURE__ */ jsx13("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
3619
+ /* @__PURE__ */ jsxs13("div", { className: "grid grid-cols-2 gap-1.5", children: [
3620
+ /* @__PURE__ */ jsxs13(
3224
3621
  "button",
3225
3622
  {
3226
3623
  type: "button",
@@ -3233,7 +3630,7 @@ var ImageEditor = ({
3233
3630
  ]
3234
3631
  }
3235
3632
  ),
3236
- /* @__PURE__ */ jsxs11(
3633
+ /* @__PURE__ */ jsxs13(
3237
3634
  "button",
3238
3635
  {
3239
3636
  type: "button",
@@ -3248,25 +3645,25 @@ var ImageEditor = ({
3248
3645
  )
3249
3646
  ] })
3250
3647
  ] }),
3251
- /* @__PURE__ */ jsx11(
3648
+ /* @__PURE__ */ jsx13(
3252
3649
  "button",
3253
3650
  {
3254
3651
  type: "button",
3255
3652
  onClick: handleInpaint,
3256
3653
  disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
3257
3654
  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",
3258
- children: isInpainting ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
3259
- /* @__PURE__ */ jsx11("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3655
+ children: isInpainting ? /* @__PURE__ */ jsxs13(Fragment4, { children: [
3656
+ /* @__PURE__ */ jsx13("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3260
3657
  "Generating Inpaint..."
3261
- ] }) : /* @__PURE__ */ jsxs11(Fragment3, { children: [
3262
- /* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
3658
+ ] }) : /* @__PURE__ */ jsxs13(Fragment4, { children: [
3659
+ /* @__PURE__ */ jsx13("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx13("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" }) }),
3263
3660
  "Apply Inpainting"
3264
3661
  ] })
3265
3662
  }
3266
3663
  )
3267
3664
  ] }),
3268
- aiError && /* @__PURE__ */ jsx11("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
3269
- aiSuccess && /* @__PURE__ */ jsx11("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
3665
+ aiError && /* @__PURE__ */ jsx13("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
3666
+ aiSuccess && /* @__PURE__ */ jsx13("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
3270
3667
  ] })
3271
3668
  ] })
3272
3669
  ] })
@@ -3288,6 +3685,8 @@ export {
3288
3685
  SelectionOptionsBar,
3289
3686
  RefineEdgePanel,
3290
3687
  FreeTransformOptionsBar,
3688
+ ShapeOptionsBar,
3689
+ TypeOptionsBar,
3291
3690
  ImageEditor
3292
3691
  };
3293
- //# sourceMappingURL=chunk-LCTQWNTL.js.map
3692
+ //# sourceMappingURL=chunk-YAFNCBDA.js.map