@pixerate/editor-react 0.76.0 → 0.77.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.
@@ -40,6 +40,7 @@ __export(image_editor_exports, {
40
40
  ImageEditor: () => ImageEditor,
41
41
  LayerEffectsPanel: () => LayerEffectsPanel,
42
42
  LayersPanel: () => LayersPanel,
43
+ PaintGradientEditor: () => PaintGradientEditor,
43
44
  RefineEdgePanel: () => RefineEdgePanel,
44
45
  SelectionOptionsBar: () => SelectionOptionsBar,
45
46
  ShapeOptionsBar: () => ShapeOptionsBar,
@@ -208,8 +209,8 @@ function useImageEditor(options = {}) {
208
209
  }
209
210
 
210
211
  // src/image-editor/ImageEditor.tsx
211
- var import_react14 = __toESM(require("react"), 1);
212
- var import_image_editor15 = require("@pixerate/editor/image-editor");
212
+ var import_react15 = __toESM(require("react"), 1);
213
+ var import_image_editor17 = require("@pixerate/editor/image-editor");
213
214
 
214
215
  // src/image-editor/ControlSlider.tsx
215
216
  var import_image_editor2 = require("@pixerate/editor/image-editor");
@@ -1259,16 +1260,148 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
1259
1260
  };
1260
1261
 
1261
1262
  // src/image-editor/BrushOptionsBar.tsx
1262
- var import_react7 = require("react");
1263
+ var import_react8 = require("react");
1264
+ var import_image_editor9 = require("@pixerate/editor/image-editor");
1265
+ var import_image_editor10 = require("@pixerate/editor/image-editor");
1266
+
1267
+ // src/image-editor/PaintGradientEditor.tsx
1263
1268
  var import_image_editor8 = require("@pixerate/editor/image-editor");
1269
+
1270
+ // src/paint-editor/PaintGradientEditorView.tsx
1271
+ var import_react7 = require("react");
1264
1272
  var import_jsx_runtime7 = require("react/jsx-runtime");
1273
+ var button2 = "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-200 hover:bg-slate-700 disabled:opacity-40";
1274
+ var select = "rounded bg-slate-800 px-1 py-0.5 text-[11px]";
1275
+ var number = "w-16 rounded bg-slate-800 px-1 py-0.5 text-[11px]";
1276
+ var pct = (v) => Math.round(v * 1e3) / 10;
1277
+ var PaintGradientEditorView = ({ value, onChange, colors, className, kit }) => {
1278
+ const {
1279
+ PAINT_GRADIENT_MAPPINGS,
1280
+ PAINT_GRADIENT_MAPPING_LABELS,
1281
+ PAINT_GRADIENT_PRESETS,
1282
+ PAINT_GRADIENT_REPEATS,
1283
+ PAINT_GRADIENT_REPEAT_LABELS,
1284
+ PAINT_GRADIENT_SPACES,
1285
+ PAINT_GRADIENT_SPACE_LABELS,
1286
+ addPaintGradientStop,
1287
+ paintGradientMappingFor,
1288
+ paintSourceCss,
1289
+ removePaintGradientStop,
1290
+ reversePaintGradient,
1291
+ updatePaintGradientStop
1292
+ } = kit;
1293
+ const [selected, setSelected] = (0, import_react7.useState)(0);
1294
+ const sel = Math.min(selected, value.stops.length - 1);
1295
+ const stop = value.stops[sel];
1296
+ const map = value.map;
1297
+ const stopHex = (c) => c === "paint" ? colors.paint : c === "secondary" ? colors.secondary : c;
1298
+ const patchStop = (patch) => {
1299
+ const r = updatePaintGradientStop(value, sel, patch);
1300
+ setSelected(r.index);
1301
+ onChange(r.paint);
1302
+ };
1303
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex flex-col gap-1.5 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "paint-gradient-editor", "aria-label": "Gradient paint", children: [
1304
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-1", children: [
1305
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("select", { "aria-label": "Gradient preset", className: select, value: "", onChange: (e) => e.target.value && (setSelected(0), onChange(PAINT_GRADIENT_PRESETS[Number(e.target.value)].paint)), children: [
1306
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "", children: "Presets\u2026" }),
1307
+ PAINT_GRADIENT_PRESETS.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: i, children: p.name }, p.name))
1308
+ ] }),
1309
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: button2, onClick: () => onChange(reversePaintGradient(value)), children: "Reverse" })
1310
+ ] }),
1311
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1312
+ "div",
1313
+ {
1314
+ role: "slider",
1315
+ tabIndex: 0,
1316
+ "aria-label": "Gradient ramp: click to add a stop",
1317
+ "aria-valuemin": 0,
1318
+ "aria-valuemax": 100,
1319
+ "aria-valuenow": pct(stop.offset),
1320
+ "data-testid": "paint-gradient-ramp",
1321
+ className: "relative h-6 cursor-copy rounded ring-1 ring-slate-700",
1322
+ style: { background: paintSourceCss(value, colors) },
1323
+ onClick: (e) => {
1324
+ const rect = e.currentTarget.getBoundingClientRect();
1325
+ const r = addPaintGradientStop(value, rect.width ? (e.clientX - rect.left) / rect.width : 0.5, colors);
1326
+ if (r.index >= 0) {
1327
+ setSelected(r.index);
1328
+ onChange(r.paint);
1329
+ }
1330
+ }
1331
+ }
1332
+ ),
1333
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "relative h-4", "aria-label": "Stops", children: value.stops.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1334
+ "button",
1335
+ {
1336
+ type: "button",
1337
+ "aria-label": `Stop ${i + 1} at ${pct(s.offset)}%`,
1338
+ "aria-pressed": i === sel,
1339
+ className: `absolute top-0 h-4 w-3 -translate-x-1/2 rounded-sm ring-1 ${i === sel ? "ring-white" : "ring-slate-600"}`,
1340
+ style: { left: `${s.offset * 100}%`, background: stopHex(s.color) },
1341
+ onClick: () => setSelected(i)
1342
+ },
1343
+ i
1344
+ )) }),
1345
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap items-center gap-1", "data-testid": "paint-gradient-stop", children: [
1346
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("select", { "aria-label": "Stop colour source", className: select, value: stop.color === "paint" || stop.color === "secondary" ? stop.color : "color", onChange: (e) => patchStop({ color: e.target.value === "color" ? stopHex(stop.color) : e.target.value }), children: [
1347
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "color", children: "Colour" }),
1348
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "paint", children: "Paint colour" }),
1349
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "secondary", children: "Second colour" })
1350
+ ] }),
1351
+ stop.color !== "paint" && stop.color !== "secondary" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "color", "aria-label": "Stop colour", value: stop.color, onChange: (e) => patchStop({ color: e.target.value }), className: "h-6 w-8 rounded bg-transparent" }),
1352
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1", children: [
1353
+ "At",
1354
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "number", "aria-label": "Stop position", min: 0, max: 100, step: 1, value: pct(stop.offset), onChange: (e) => patchStop({ offset: Number(e.target.value) / 100 }), className: number }),
1355
+ "%"
1356
+ ] }),
1357
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1", children: [
1358
+ "Opacity",
1359
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "number", "aria-label": "Stop opacity", min: 0, max: 100, step: 5, value: pct(stop.opacity ?? 1), onChange: (e) => patchStop({ opacity: Number(e.target.value) / 100 }), className: number }),
1360
+ "%"
1361
+ ] }),
1362
+ sel < value.stops.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1", children: [
1363
+ "Midpoint",
1364
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "number", "aria-label": "Stop midpoint", min: 5, max: 95, step: 1, value: pct(stop.midpoint ?? 0.5), onChange: (e) => patchStop({ midpoint: Number(e.target.value) / 100 }), className: number }),
1365
+ "%"
1366
+ ] }),
1367
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: button2, disabled: value.stops.length <= 2, onClick: () => (setSelected(Math.max(0, sel - 1)), onChange(removePaintGradientStop(value, sel))), children: "Remove stop" })
1368
+ ] }),
1369
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap items-center gap-1", "data-testid": "paint-gradient-mapping", children: [
1370
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("select", { "aria-label": "Gradient follows", className: select, value: map.by, onChange: (e) => onChange({ ...value, map: paintGradientMappingFor(e.target.value, map) }), children: PAINT_GRADIENT_MAPPINGS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: m, children: PAINT_GRADIENT_MAPPING_LABELS[m] }, m)) }),
1371
+ map.by === "distance" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1372
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "number", "aria-label": "Gradient length", min: 1, max: 1e5, value: map.length, onChange: (e) => onChange({ ...value, map: { ...map, length: Math.max(1, Number(e.target.value) || 1) } }), className: number }),
1373
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("select", { "aria-label": "Gradient length unit", className: select, value: map.unit ?? "px", onChange: (e) => onChange({ ...value, map: { ...map, unit: e.target.value } }), children: [
1374
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "px", children: "px" }),
1375
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "dabs", children: "dabs" })
1376
+ ] })
1377
+ ] }),
1378
+ map.by === "time" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "number", "aria-label": "Gradient duration", min: 1, max: 6e5, value: map.duration, onChange: (e) => onChange({ ...value, map: { ...map, duration: Math.max(1, Number(e.target.value) || 1) } }), className: number }),
1379
+ map.by === "random" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "number", "aria-label": "Dabs per pick", min: 1, max: 500, value: map.every ?? 1, onChange: (e) => onChange({ ...value, map: { ...map, every: Math.max(1, Math.round(Number(e.target.value) || 1)) } }), className: number }),
1380
+ (map.by === "distance" || map.by === "time") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("select", { "aria-label": "Gradient repeat", className: select, value: map.repeat ?? "clamp", onChange: (e) => onChange({ ...value, map: { ...map, repeat: e.target.value } }), children: PAINT_GRADIENT_REPEATS.map((r) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: r, children: PAINT_GRADIENT_REPEAT_LABELS[r] }, r)) })
1381
+ ] }),
1382
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-1", children: [
1383
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("select", { "aria-label": "Gradient mixing", className: select, value: value.space, onChange: (e) => onChange({ ...value, space: e.target.value }), children: PAINT_GRADIENT_SPACES.map((s) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: s, children: PAINT_GRADIENT_SPACE_LABELS[s] }, s)) }),
1384
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex flex-1 items-center gap-1", children: [
1385
+ "Softness",
1386
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "range", "aria-label": "Gradient softness", min: 0, max: 1, step: 0.05, value: value.softness ?? 1, onChange: (e) => onChange({ ...value, softness: Number(e.target.value) }), className: "flex-1 accent-indigo-500" })
1387
+ ] })
1388
+ ] })
1389
+ ] });
1390
+ };
1391
+
1392
+ // src/image-editor/PaintGradientEditor.tsx
1393
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1394
+ var PaintGradientEditor = (props) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PaintGradientEditorView, { ...props, kit: import_image_editor8.PAINT_GRADIENT_KIT });
1395
+
1396
+ // src/image-editor/BrushOptionsBar.tsx
1397
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1265
1398
  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"}`;
1266
1399
  var BrushOptionsBar = ({ controller, className }) => {
1267
- const [, setTick] = (0, import_react7.useState)(0);
1268
- (0, import_react7.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
1269
- const [error, setError] = (0, import_react7.useState)(null);
1400
+ const [, setTick] = (0, import_react8.useState)(0);
1401
+ (0, import_react8.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
1402
+ const [error, setError] = (0, import_react8.useState)(null);
1270
1403
  const state = controller.getState();
1271
- const { brush, foreground, background, mixer, mixerLoad, retouch, cloneSource } = state.paint;
1404
+ const { brush, foreground, background, mixer, mixerLoad, retouch, cloneSource, paint } = state.paint;
1272
1405
  const tool = state.activeTool;
1273
1406
  const attempt = (fn) => {
1274
1407
  try {
@@ -1278,8 +1411,8 @@ var BrushOptionsBar = ({ controller, className }) => {
1278
1411
  setError(err instanceof Error ? err.message : String(err));
1279
1412
  }
1280
1413
  };
1281
- 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: [
1282
- /* @__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)(
1414
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
1415
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor9.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1283
1416
  "button",
1284
1417
  {
1285
1418
  type: "button",
@@ -1291,9 +1424,9 @@ var BrushOptionsBar = ({ controller, className }) => {
1291
1424
  },
1292
1425
  t.id
1293
1426
  )) }),
1294
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
1295
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1", children: [
1296
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1427
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
1428
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-1", children: [
1429
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1297
1430
  "input",
1298
1431
  {
1299
1432
  type: "color",
@@ -1303,10 +1436,10 @@ var BrushOptionsBar = ({ controller, className }) => {
1303
1436
  className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
1304
1437
  }
1305
1438
  ),
1306
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-slate-400", children: "FG" })
1439
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-slate-400", children: "FG" })
1307
1440
  ] }),
1308
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1", children: [
1309
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1441
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-1", children: [
1442
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1310
1443
  "input",
1311
1444
  {
1312
1445
  type: "color",
@@ -1316,12 +1449,24 @@ var BrushOptionsBar = ({ controller, className }) => {
1316
1449
  className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
1317
1450
  }
1318
1451
  ),
1319
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-slate-400", children: "BG" })
1452
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-slate-400", children: "BG" })
1320
1453
  ] }),
1321
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
1322
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" })
1454
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
1455
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" }),
1456
+ state.activeTool === "brush" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1457
+ "button",
1458
+ {
1459
+ type: "button",
1460
+ "aria-pressed": paint.type === "gradient",
1461
+ title: "Gradient paint: the brush changes colour as the stroke goes",
1462
+ className: chip(paint.type === "gradient"),
1463
+ onClick: () => attempt(() => controller.setPaintOptions(paint.type === "gradient" ? { foreground } : { paint: import_image_editor10.DEFAULT_PAINT_GRADIENT })),
1464
+ children: "Gradient"
1465
+ }
1466
+ )
1323
1467
  ] }),
1324
- import_image_editor8.BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1468
+ state.activeTool === "brush" && paint.type === "gradient" && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(PaintGradientEditor, { value: paint, colors: { paint: foreground, secondary: background }, onChange: (g) => attempt(() => controller.setPaintOptions({ paint: g })) }),
1469
+ import_image_editor9.BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1325
1470
  ControlSlider,
1326
1471
  {
1327
1472
  spec,
@@ -1330,21 +1475,21 @@ var BrushOptionsBar = ({ controller, className }) => {
1330
1475
  },
1331
1476
  spec.id
1332
1477
  )),
1333
- state.activeTool === "mixer" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Mixer Brush", "data-testid": "mixer-options", children: [
1334
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
1335
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1478
+ state.activeTool === "mixer" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Mixer Brush", "data-testid": "mixer-options", children: [
1479
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-2", children: [
1480
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1336
1481
  "span",
1337
1482
  {
1338
1483
  "aria-label": "Brush load",
1339
- title: mixerLoad.reservoir ? `Loaded ${(0, import_image_editor8.rgbUnitToHex)(mixerLoad.reservoir)}, ${Math.round(mixerLoad.amount * 100)}% left` : "Unloaded",
1484
+ title: mixerLoad.reservoir ? `Loaded ${(0, import_image_editor9.rgbUnitToHex)(mixerLoad.reservoir)}, ${Math.round(mixerLoad.amount * 100)}% left` : "Unloaded",
1340
1485
  className: "h-6 w-6 rounded border border-slate-700",
1341
- style: { background: mixerLoad.reservoir ? (0, import_image_editor8.rgbUnitToHex)(mixerLoad.reservoir) : "transparent" }
1486
+ style: { background: mixerLoad.reservoir ? (0, import_image_editor9.rgbUnitToHex)(mixerLoad.reservoir) : "transparent" }
1342
1487
  }
1343
1488
  ),
1344
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", title: "Fill the reservoir with the foreground colour", className: chip(false), onClick: () => controller.loadMixerBrush(), children: "Load brush" }),
1345
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", title: "Empty the picked-up colour", className: chip(false), onClick: () => controller.cleanMixerBrush(), children: "Clean brush" })
1489
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", title: "Fill the reservoir with the foreground colour", className: chip(false), onClick: () => controller.loadMixerBrush(), children: "Load brush" }),
1490
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", title: "Empty the picked-up colour", className: chip(false), onClick: () => controller.cleanMixerBrush(), children: "Clean brush" })
1346
1491
  ] }),
1347
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Mixing", children: import_image_editor8.MIXER_MIXING_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1492
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Mixing", children: import_image_editor9.MIXER_MIXING_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1348
1493
  "button",
1349
1494
  {
1350
1495
  type: "button",
@@ -1356,10 +1501,10 @@ var BrushOptionsBar = ({ controller, className }) => {
1356
1501
  },
1357
1502
  m.id
1358
1503
  )) }),
1359
- import_image_editor8.MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ControlSlider, { spec, value: mixer[spec.id], onChange: (v) => controller.setPaintOptions({ mixer: { [spec.id]: v } }) }, spec.id)),
1360
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: [
1361
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1.5", children: [
1362
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1504
+ import_image_editor9.MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ControlSlider, { spec, value: mixer[spec.id], onChange: (v) => controller.setPaintOptions({ mixer: { [spec.id]: v } }) }, spec.id)),
1505
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: [
1506
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-1.5", children: [
1507
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1363
1508
  "input",
1364
1509
  {
1365
1510
  type: "checkbox",
@@ -1371,8 +1516,8 @@ var BrushOptionsBar = ({ controller, className }) => {
1371
1516
  ),
1372
1517
  "Load each stroke"
1373
1518
  ] }),
1374
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1.5", children: [
1375
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1519
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-1.5", children: [
1520
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1376
1521
  "input",
1377
1522
  {
1378
1523
  type: "checkbox",
@@ -1386,29 +1531,29 @@ var BrushOptionsBar = ({ controller, className }) => {
1386
1531
  ] })
1387
1532
  ] })
1388
1533
  ] }),
1389
- (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: [
1390
- (tool === "clone" || tool === "heal") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
1391
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-slate-400", "data-testid": "clone-source", children: (0, import_image_editor8.cloneSourceLabel)(controller) }),
1392
- 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" })
1534
+ (0, import_image_editor9.isRetouchPaintTool)(tool) && /* @__PURE__ */ (0, import_jsx_runtime9.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: [
1535
+ (tool === "clone" || tool === "heal") && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-2", children: [
1536
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-slate-400", "data-testid": "clone-source", children: (0, import_image_editor9.cloneSourceLabel)(controller) }),
1537
+ cloneSource && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", title: "Forget the source point", className: chip(false), onClick: () => controller.setCloneSource(null), children: "Clear source" })
1393
1538
  ] }),
1394
- 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: [
1395
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-slate-400", children: choice.label }),
1396
- choice.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1539
+ import_image_editor9.RETOUCH_CHOICES.filter((c) => c.tools.includes(tool)).map((choice) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": choice.label, children: [
1540
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-slate-400", children: choice.label }),
1541
+ choice.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1397
1542
  "button",
1398
1543
  {
1399
1544
  type: "button",
1400
1545
  "aria-pressed": retouch[choice.id] === o.id,
1401
1546
  title: o.title,
1402
1547
  className: chip(retouch[choice.id] === o.id),
1403
- onClick: () => (0, import_image_editor8.setRetouchChoice)(controller, choice.id, o.id),
1548
+ onClick: () => (0, import_image_editor9.setRetouchChoice)(controller, choice.id, o.id),
1404
1549
  children: o.label
1405
1550
  },
1406
1551
  o.id
1407
1552
  ))
1408
1553
  ] }, choice.id)),
1409
- 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)),
1410
- /* @__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: [
1411
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1554
+ import_image_editor9.RETOUCH_OPTION_CONTROLS.filter((c) => c.tools.includes(tool)).map((spec) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ControlSlider, { spec, value: retouch[spec.id], onChange: (v) => controller.setPaintOptions({ retouch: { [spec.id]: v } }) }, spec.id)),
1555
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: import_image_editor9.RETOUCH_TOGGLES.filter((t) => t.tools.includes(tool)).map((t) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-1.5", children: [
1556
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1412
1557
  "input",
1413
1558
  {
1414
1559
  type: "checkbox",
@@ -1421,9 +1566,9 @@ var BrushOptionsBar = ({ controller, className }) => {
1421
1566
  t.label
1422
1567
  ] }, t.id)) })
1423
1568
  ] }),
1424
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
1425
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1.5", children: [
1426
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1569
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
1570
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-1.5", children: [
1571
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1427
1572
  "input",
1428
1573
  {
1429
1574
  type: "checkbox",
@@ -1435,8 +1580,8 @@ var BrushOptionsBar = ({ controller, className }) => {
1435
1580
  ),
1436
1581
  "Pressure size"
1437
1582
  ] }),
1438
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1.5", children: [
1439
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1583
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-1.5", children: [
1584
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1440
1585
  "input",
1441
1586
  {
1442
1587
  type: "checkbox",
@@ -1449,28 +1594,28 @@ var BrushOptionsBar = ({ controller, className }) => {
1449
1594
  "Pressure opacity"
1450
1595
  ] })
1451
1596
  ] }),
1452
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-1", children: [
1453
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
1454
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
1597
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex gap-1", children: [
1598
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
1599
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
1455
1600
  ] }),
1456
- error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
1601
+ error && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
1457
1602
  ] });
1458
1603
  };
1459
1604
 
1460
1605
  // src/image-editor/ColorProfilePanel.tsx
1461
- var import_react8 = require("react");
1462
- var import_image_editor9 = require("@pixerate/editor/image-editor");
1463
- var import_jsx_runtime8 = require("react/jsx-runtime");
1606
+ var import_react9 = require("react");
1607
+ var import_image_editor11 = require("@pixerate/editor/image-editor");
1608
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1464
1609
  var chip2 = "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white";
1465
- var select = "rounded bg-slate-800 px-1 py-0.5 text-[11px] text-slate-200";
1610
+ var select2 = "rounded bg-slate-800 px-1 py-0.5 text-[11px] text-slate-200";
1466
1611
  var ColorProfilePanel = ({ controller, className }) => {
1467
- const [, setTick] = (0, import_react8.useState)(0);
1468
- (0, import_react8.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
1469
- const [target, setTarget] = (0, import_react8.useState)("display-p3");
1470
- const [intent, setIntent] = (0, import_react8.useState)("relative");
1471
- const [bpc, setBpc] = (0, import_react8.useState)(true);
1472
- const [error, setError] = (0, import_react8.useState)(null);
1473
- const view = (0, import_image_editor9.colorPanelView)(controller);
1612
+ const [, setTick] = (0, import_react9.useState)(0);
1613
+ (0, import_react9.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
1614
+ const [target, setTarget] = (0, import_react9.useState)("display-p3");
1615
+ const [intent, setIntent] = (0, import_react9.useState)("relative");
1616
+ const [bpc, setBpc] = (0, import_react9.useState)(true);
1617
+ const [error, setError] = (0, import_react9.useState)(null);
1618
+ const view = (0, import_image_editor11.colorPanelView)(controller);
1474
1619
  const attempt = (fn) => {
1475
1620
  try {
1476
1621
  setError(null);
@@ -1491,61 +1636,61 @@ var ColorProfilePanel = ({ controller, className }) => {
1491
1636
  })
1492
1637
  );
1493
1638
  };
1494
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "color-profile-panel", children: [
1495
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-2", children: [
1496
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-slate-400", children: "Profile" }),
1497
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "data-testid": "color-profile-name", children: view.profileName })
1639
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "color-profile-panel", children: [
1640
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2", children: [
1641
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-400", children: "Profile" }),
1642
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { "data-testid": "color-profile-name", children: view.profileName })
1498
1643
  ] }),
1499
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Colour mode", children: [
1500
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-slate-400", children: "Mode" }),
1501
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("select", { "aria-label": "Colour mode", className: select, value: view.mode, onChange: (e) => attempt(() => controller.setColorMode(e.target.value)), children: import_image_editor9.COLOR_MODE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: o.id, title: o.title, children: o.label }, o.id)) }),
1502
- view.cmykProfileName && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-slate-400", children: view.cmykProfileName })
1644
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Colour mode", children: [
1645
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-400", children: "Mode" }),
1646
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("select", { "aria-label": "Colour mode", className: select2, value: view.mode, onChange: (e) => attempt(() => controller.setColorMode(e.target.value)), children: import_image_editor11.COLOR_MODE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: o.id, title: o.title, children: o.label }, o.id)) }),
1647
+ view.cmykProfileName && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-400", children: view.cmykProfileName })
1503
1648
  ] }),
1504
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Assign or convert", children: [
1505
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("select", { "aria-label": "Target profile", className: select, value: target, onChange: (e) => setTarget(e.target.value), children: import_image_editor9.WORKING_SPACE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: o.id, children: o.label }, o.id)) }),
1506
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("select", { "aria-label": "Rendering intent", className: select, value: intent, onChange: (e) => setIntent(e.target.value), children: import_image_editor9.INTENT_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: o.id, title: o.title, children: o.label }, o.id)) }),
1507
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex items-center gap-1", children: [
1508
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "checkbox", "aria-label": "Black point compensation", checked: bpc, onChange: (e) => setBpc(e.target.checked), className: "accent-indigo-500" }),
1649
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Assign or convert", children: [
1650
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("select", { "aria-label": "Target profile", className: select2, value: target, onChange: (e) => setTarget(e.target.value), children: import_image_editor11.WORKING_SPACE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: o.id, children: o.label }, o.id)) }),
1651
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("select", { "aria-label": "Rendering intent", className: select2, value: intent, onChange: (e) => setIntent(e.target.value), children: import_image_editor11.INTENT_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: o.id, title: o.title, children: o.label }, o.id)) }),
1652
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-1", children: [
1653
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("input", { type: "checkbox", "aria-label": "Black point compensation", checked: bpc, onChange: (e) => setBpc(e.target.checked), className: "accent-indigo-500" }),
1509
1654
  "BPC"
1510
1655
  ] }),
1511
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: chip2, title: "Edit \u203A Assign Profile: keep the numbers", onClick: () => attempt(() => controller.assignProfile(target)), children: "Assign" }),
1512
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: chip2, title: "Edit \u203A Convert to Profile: keep the look", onClick: () => attempt(() => controller.convertToProfile(target, { intent, bpc })), children: "Convert" })
1656
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: chip2, title: "Edit \u203A Assign Profile: keep the numbers", onClick: () => attempt(() => controller.assignProfile(target)), children: "Assign" }),
1657
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: chip2, title: "Edit \u203A Convert to Profile: keep the look", onClick: () => attempt(() => controller.convertToProfile(target, { intent, bpc })), children: "Convert" })
1513
1658
  ] }),
1514
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Proof setup", children: [
1515
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-slate-400", children: "Proof" }),
1516
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1659
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Proof setup", children: [
1660
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-400", children: "Proof" }),
1661
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1517
1662
  "select",
1518
1663
  {
1519
1664
  "aria-label": "Proof profile",
1520
- className: select,
1665
+ className: select2,
1521
1666
  value: view.proof?.id ?? "",
1522
1667
  onChange: (e) => e.target.value ? proofWith({ id: e.target.value }) : attempt(() => controller.setProofSetup(null)),
1523
1668
  children: [
1524
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "", children: "Off" }),
1525
- import_image_editor9.PROOF_PROFILE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: o.id, children: o.label }, o.id))
1669
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "", children: "Off" }),
1670
+ import_image_editor11.PROOF_PROFILE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: o.id, children: o.label }, o.id))
1526
1671
  ]
1527
1672
  }
1528
1673
  ),
1529
- view.proof && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1530
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("select", { "aria-label": "Proof intent", className: select, value: view.proof.intent, onChange: (e) => proofWith({ intent: e.target.value }), children: import_image_editor9.INTENT_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: o.id, children: o.label }, o.id)) }),
1531
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex items-center gap-1", children: [
1532
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "checkbox", "aria-label": "Simulate paper colour", checked: view.proof.simulatePaper, onChange: (e) => proofWith({ simulatePaper: e.target.checked }), className: "accent-indigo-500" }),
1674
+ view.proof && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1675
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("select", { "aria-label": "Proof intent", className: select2, value: view.proof.intent, onChange: (e) => proofWith({ intent: e.target.value }), children: import_image_editor11.INTENT_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: o.id, children: o.label }, o.id)) }),
1676
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-1", children: [
1677
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("input", { type: "checkbox", "aria-label": "Simulate paper colour", checked: view.proof.simulatePaper, onChange: (e) => proofWith({ simulatePaper: e.target.checked }), className: "accent-indigo-500" }),
1533
1678
  "Paper"
1534
1679
  ] }),
1535
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex items-center gap-1", children: [
1536
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "checkbox", "aria-label": "Gamut warning", checked: view.proof.gamutWarning, onChange: (e) => proofWith({ gamutWarning: e.target.checked }), className: "accent-indigo-500" }),
1680
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-1", children: [
1681
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("input", { type: "checkbox", "aria-label": "Gamut warning", checked: view.proof.gamutWarning, onChange: (e) => proofWith({ gamutWarning: e.target.checked }), className: "accent-indigo-500" }),
1537
1682
  "Gamut warning"
1538
1683
  ] })
1539
1684
  ] })
1540
1685
  ] }),
1541
- error && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
1686
+ error && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
1542
1687
  ] });
1543
1688
  };
1544
1689
 
1545
1690
  // src/image-editor/SelectionOptionsBar.tsx
1546
- var import_react9 = require("react");
1547
- var import_image_editor10 = require("@pixerate/editor/image-editor");
1548
- var import_jsx_runtime9 = require("react/jsx-runtime");
1691
+ var import_react10 = require("react");
1692
+ var import_image_editor12 = require("@pixerate/editor/image-editor");
1693
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1549
1694
  var MODIFY_OPS = [
1550
1695
  { op: "grow", label: "Grow" },
1551
1696
  { op: "shrink", label: "Shrink" },
@@ -1562,20 +1707,20 @@ var SelectionOptionsBar = ({
1562
1707
  quickMask,
1563
1708
  className = ""
1564
1709
  }) => {
1565
- const [radius, setRadius] = (0, import_react9.useState)(2);
1710
+ const [radius, setRadius] = (0, import_react10.useState)(2);
1566
1711
  const set = (patch) => onOptionsChange({ ...options, ...patch });
1567
1712
  const sel = selection === void 0 ? controller.getSelection() : selection;
1568
1713
  const qm = quickMask ?? Boolean(controller.getState().quickMask);
1569
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
1570
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: import_image_editor10.SELECTION_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", "aria-pressed": options.tool === t.id, className: btn(options.tool === t.id), onClick: () => set({ tool: t.id }), children: t.label }, t.id)) }),
1571
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: import_image_editor10.SELECTION_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: import_image_editor10.SELECTION_MODE_LABELS[m] }, m)) }),
1572
- options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col gap-2", children: [
1573
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex flex-col gap-1", children: [
1574
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
1575
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "Tolerance" }),
1576
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "font-mono", children: options.tolerance })
1714
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
1715
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: import_image_editor12.SELECTION_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", "aria-pressed": options.tool === t.id, className: btn(options.tool === t.id), onClick: () => set({ tool: t.id }), children: t.label }, t.id)) }),
1716
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: import_image_editor12.SELECTION_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: import_image_editor12.SELECTION_MODE_LABELS[m] }, m)) }),
1717
+ options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col gap-2", children: [
1718
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex flex-col gap-1", children: [
1719
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
1720
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { children: "Tolerance" }),
1721
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "font-mono", children: options.tolerance })
1577
1722
  ] }),
1578
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1723
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1579
1724
  "input",
1580
1725
  {
1581
1726
  type: "range",
@@ -1589,17 +1734,17 @@ var SelectionOptionsBar = ({
1589
1734
  }
1590
1735
  )
1591
1736
  ] }),
1592
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
1593
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
1737
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
1738
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
1594
1739
  "Contiguous"
1595
1740
  ] }),
1596
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
1597
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
1741
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
1742
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
1598
1743
  "Sample adjusted image"
1599
1744
  ] }),
1600
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
1745
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
1601
1746
  "Sample",
1602
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1747
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
1603
1748
  "select",
1604
1749
  {
1605
1750
  "aria-label": "Sample from",
@@ -1607,27 +1752,27 @@ var SelectionOptionsBar = ({
1607
1752
  onChange: (e) => set({ sample: e.target.value }),
1608
1753
  className: "bg-slate-800 border border-slate-700 rounded px-1 py-0.5",
1609
1754
  children: [
1610
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: "composite", children: "All layers" }),
1611
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: "active-layer", children: "Active layer" })
1755
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "composite", children: "All layers" }),
1756
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "active-layer", children: "Active layer" })
1612
1757
  ]
1613
1758
  }
1614
1759
  )
1615
1760
  ] })
1616
1761
  ] }),
1617
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
1618
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
1762
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
1763
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
1619
1764
  "Anti-alias"
1620
1765
  ] }),
1621
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
1622
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
1623
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
1624
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
1625
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
1766
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
1767
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
1768
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
1769
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
1770
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
1626
1771
  ] }),
1627
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
1628
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
1772
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
1773
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
1629
1774
  "Radius",
1630
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1775
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1631
1776
  "input",
1632
1777
  {
1633
1778
  type: "number",
@@ -1641,24 +1786,24 @@ var SelectionOptionsBar = ({
1641
1786
  }
1642
1787
  )
1643
1788
  ] }),
1644
- MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
1789
+ MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
1645
1790
  ] }),
1646
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor10.describeSelection)(sel) })
1791
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor12.describeSelection)(sel) })
1647
1792
  ] });
1648
1793
  };
1649
1794
 
1650
1795
  // src/image-editor/RefineEdgePanel.tsx
1651
- var import_react10 = require("react");
1652
- var import_image_editor11 = require("@pixerate/editor/image-editor");
1653
- var import_jsx_runtime10 = require("react/jsx-runtime");
1796
+ var import_react11 = require("react");
1797
+ var import_image_editor13 = require("@pixerate/editor/image-editor");
1798
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1654
1799
  var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
1655
- var button2 = "px-2 py-1 rounded-md border border-slate-800 bg-slate-950 text-[11px] text-slate-200 hover:text-white disabled:opacity-40";
1800
+ var button3 = "px-2 py-1 rounded-md border border-slate-800 bg-slate-950 text-[11px] text-slate-200 hover:text-white disabled:opacity-40";
1656
1801
  var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
1657
- const [params, setParams] = (0, import_react10.useState)(DEFAULT_PARAMS);
1658
- const [busy, setBusy] = (0, import_react10.useState)(false);
1659
- const [error, setError] = (0, import_react10.useState)(null);
1660
- const [layerId, setLayerId] = (0, import_react10.useState)("");
1661
- const [newKind, setNewKind] = (0, import_react10.useState)("hueSaturation");
1802
+ const [params, setParams] = (0, import_react11.useState)(DEFAULT_PARAMS);
1803
+ const [busy, setBusy] = (0, import_react11.useState)(false);
1804
+ const [error, setError] = (0, import_react11.useState)(null);
1805
+ const [layerId, setLayerId] = (0, import_react11.useState)("");
1806
+ const [newKind, setNewKind] = (0, import_react11.useState)("hueSaturation");
1662
1807
  const sel = selection === void 0 ? controller.getSelection() : selection;
1663
1808
  const list = layers ?? controller.getAdjustmentLayers();
1664
1809
  const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
@@ -1673,17 +1818,17 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
1673
1818
  setBusy(false);
1674
1819
  }
1675
1820
  };
1676
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
1677
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
1678
- import_image_editor11.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex flex-col gap-1", children: [
1679
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
1680
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: c.label }),
1681
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-mono", children: [
1821
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
1822
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
1823
+ import_image_editor13.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex flex-col gap-1", children: [
1824
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
1825
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: c.label }),
1826
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "font-mono", children: [
1682
1827
  params[c.id],
1683
1828
  c.unit
1684
1829
  ] })
1685
1830
  ] }),
1686
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1831
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1687
1832
  "input",
1688
1833
  {
1689
1834
  type: "range",
@@ -1697,67 +1842,67 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
1697
1842
  }
1698
1843
  )
1699
1844
  ] }, c.id)),
1700
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
1701
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
1845
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
1846
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
1702
1847
  "Smart Radius"
1703
1848
  ] }),
1704
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex gap-1", children: [
1705
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: button2, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
1706
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: button2, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
1849
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex gap-1", children: [
1850
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: button3, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
1851
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: button3, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
1707
1852
  ] }),
1708
- error && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
1709
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
1710
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex gap-1 items-center", children: [
1711
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1853
+ error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
1854
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
1855
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex gap-1 items-center", children: [
1856
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1712
1857
  "select",
1713
1858
  {
1714
1859
  "aria-label": "New masked layer kind",
1715
1860
  value: newKind,
1716
1861
  onChange: (e) => setNewKind(e.target.value),
1717
1862
  className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
1718
- children: import_image_editor11.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: k.kind, children: k.label }, k.kind))
1863
+ children: import_image_editor13.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("option", { value: k.kind, children: k.label }, k.kind))
1719
1864
  }
1720
1865
  ),
1721
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1866
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1722
1867
  "button",
1723
1868
  {
1724
1869
  type: "button",
1725
- className: button2,
1870
+ className: button3,
1726
1871
  disabled: !sel,
1727
- onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor11.layerMaskFromSelection)(sel) })),
1872
+ onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor13.layerMaskFromSelection)(sel) })),
1728
1873
  children: "New Masked Layer"
1729
1874
  }
1730
1875
  )
1731
1876
  ] }),
1732
- list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-2", children: [
1733
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1877
+ list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-2", children: [
1878
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1734
1879
  "select",
1735
1880
  {
1736
1881
  "aria-label": "Mask layer",
1737
1882
  value: target.id,
1738
1883
  onChange: (e) => setLayerId(e.target.value),
1739
1884
  className: "bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
1740
- children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("option", { value: l.id, children: [
1741
- l.name || (0, import_image_editor11.adjustmentKindLabel)(l.kind),
1885
+ children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("option", { value: l.id, children: [
1886
+ l.name || (0, import_image_editor13.adjustmentKindLabel)(l.kind),
1742
1887
  l.mask ? " (masked)" : ""
1743
1888
  ] }, l.id))
1744
1889
  }
1745
1890
  ),
1746
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
1747
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: button2, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
1748
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
1749
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
1891
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
1892
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: button3, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
1893
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: button3, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
1894
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", className: button3, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
1750
1895
  ] }),
1751
- target.mask && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1752
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex flex-col gap-1", children: [
1753
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
1754
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Density" }),
1755
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-mono", children: [
1896
+ target.mask && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
1897
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex flex-col gap-1", children: [
1898
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
1899
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "Density" }),
1900
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "font-mono", children: [
1756
1901
  Math.round((target.mask.density ?? 1) * 100),
1757
1902
  "%"
1758
1903
  ] })
1759
1904
  ] }),
1760
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1905
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1761
1906
  "input",
1762
1907
  {
1763
1908
  type: "range",
@@ -1771,15 +1916,15 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
1771
1916
  }
1772
1917
  )
1773
1918
  ] }),
1774
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex flex-col gap-1", children: [
1775
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
1776
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Mask Feather" }),
1777
- /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-mono", children: [
1919
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex flex-col gap-1", children: [
1920
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
1921
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "Mask Feather" }),
1922
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "font-mono", children: [
1778
1923
  target.mask.feather ?? 0,
1779
1924
  "px"
1780
1925
  ] })
1781
1926
  ] }),
1782
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1927
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1783
1928
  "input",
1784
1929
  {
1785
1930
  type: "range",
@@ -1799,14 +1944,14 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
1799
1944
  };
1800
1945
 
1801
1946
  // src/image-editor/FreeTransformOptionsBar.tsx
1802
- var import_react11 = require("react");
1803
- var import_image_editor12 = require("@pixerate/editor/image-editor");
1804
- var import_jsx_runtime11 = require("react/jsx-runtime");
1947
+ var import_react12 = require("react");
1948
+ var import_image_editor14 = require("@pixerate/editor/image-editor");
1949
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1805
1950
  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"}`;
1806
1951
  var round = (v, unit) => unit === "px" ? Math.round(v * 10) / 10 : Math.round(v * 100) / 100;
1807
1952
  var FreeTransformOptionsBar = ({ tool, className }) => {
1808
- const [, setTick] = (0, import_react11.useState)(0);
1809
- (0, import_react11.useEffect)(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
1953
+ const [, setTick] = (0, import_react12.useState)(0);
1954
+ (0, import_react12.useEffect)(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
1810
1955
  const bar = tool.bar();
1811
1956
  if (!tool.active || !bar) return null;
1812
1957
  const warp = tool.warpBar();
@@ -1818,17 +1963,17 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
1818
1963
  const v = Number(raw);
1819
1964
  if (raw.trim() !== "" && Number.isFinite(v) && Math.abs(v - bar[field]) > 1e-9) tool.setField(field, v);
1820
1965
  };
1821
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `flex flex-wrap items-center gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "free-transform-options", role: "toolbar", "aria-label": "Free Transform options", children: [
1822
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Transform mode", children: import_image_editor12.FREE_TRANSFORM_MODE_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", title: m.title, "aria-pressed": tool.mode === m.id, className: chip3(tool.mode === m.id), onClick: () => tool.setMode(m.id), children: m.label }, m.id)) }),
1823
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "grid grid-cols-3 gap-px", role: "group", "aria-label": "Reference point", children: import_image_editor12.TRANSFORM_ANCHORS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", "aria-label": `Reference point ${a}`, title: `Reference point: ${a}`, className: "h-2.5 w-2.5 rounded-sm bg-slate-700 hover:bg-indigo-500", onClick: () => tool.setReference(a) }, a)) }),
1824
- tool.mode === "warp" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": "Warp options", children: [
1825
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1826
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-slate-400", children: "Warp" }),
1827
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("select", { "aria-label": "Warp style", value: warp.style, onChange: (e) => tool.setWarp({ style: e.target.value }), className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5", children: import_image_editor12.WARP_STYLE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: o.id, children: o.label }, o.id)) })
1966
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: `flex flex-wrap items-center gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "free-transform-options", role: "toolbar", "aria-label": "Free Transform options", children: [
1967
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Transform mode", children: import_image_editor14.FREE_TRANSFORM_MODE_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", title: m.title, "aria-pressed": tool.mode === m.id, className: chip3(tool.mode === m.id), onClick: () => tool.setMode(m.id), children: m.label }, m.id)) }),
1968
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "grid grid-cols-3 gap-px", role: "group", "aria-label": "Reference point", children: import_image_editor14.TRANSFORM_ANCHORS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", "aria-label": `Reference point ${a}`, title: `Reference point: ${a}`, className: "h-2.5 w-2.5 rounded-sm bg-slate-700 hover:bg-indigo-500", onClick: () => tool.setReference(a) }, a)) }),
1969
+ tool.mode === "warp" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": "Warp options", children: [
1970
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-1", children: [
1971
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-slate-400", children: "Warp" }),
1972
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("select", { "aria-label": "Warp style", value: warp.style, onChange: (e) => tool.setWarp({ style: e.target.value }), className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5", children: import_image_editor14.WARP_STYLE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: o.id, children: o.label }, o.id)) })
1828
1973
  ] }),
1829
- ["bend", "horizontal", "vertical"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1830
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-slate-400", children: k === "bend" ? "Bend" : k === "horizontal" ? "H" : "V" }),
1831
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1974
+ ["bend", "horizontal", "vertical"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-1", children: [
1975
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-slate-400", children: k === "bend" ? "Bend" : k === "horizontal" ? "H" : "V" }),
1976
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1832
1977
  "input",
1833
1978
  {
1834
1979
  type: "number",
@@ -1849,9 +1994,9 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
1849
1994
  },
1850
1995
  `${k}:${warp[k]}`
1851
1996
  ),
1852
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-slate-500", children: "%" })
1997
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-slate-500", children: "%" })
1853
1998
  ] }, k)),
1854
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1999
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1855
2000
  "button",
1856
2001
  {
1857
2002
  type: "button",
@@ -1863,26 +2008,26 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
1863
2008
  children: "Vertical"
1864
2009
  }
1865
2010
  ),
1866
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1867
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-slate-400", children: "Grid" }),
1868
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2011
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-1", children: [
2012
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-slate-400", children: "Grid" }),
2013
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1869
2014
  "select",
1870
2015
  {
1871
2016
  "aria-label": "Warp grid",
1872
- value: import_image_editor12.WARP_GRID_OPTIONS.find((g) => g.columns === warp.columns && g.rows === warp.rows)?.id ?? "1x1",
2017
+ value: import_image_editor14.WARP_GRID_OPTIONS.find((g) => g.columns === warp.columns && g.rows === warp.rows)?.id ?? "1x1",
1873
2018
  onChange: (e) => {
1874
- const g = import_image_editor12.WARP_GRID_OPTIONS.find((o) => o.id === e.target.value);
2019
+ const g = import_image_editor14.WARP_GRID_OPTIONS.find((o) => o.id === e.target.value);
1875
2020
  tool.setWarp({ columns: g.columns, rows: g.rows });
1876
2021
  },
1877
2022
  className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
1878
- children: import_image_editor12.WARP_GRID_OPTIONS.map((g) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: g.id, children: g.label }, g.id))
2023
+ children: import_image_editor14.WARP_GRID_OPTIONS.map((g) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: g.id, children: g.label }, g.id))
1879
2024
  }
1880
2025
  )
1881
2026
  ] })
1882
2027
  ] }),
1883
- tool.mode !== "warp" && import_image_editor12.FREE_TRANSFORM_FIELDS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", title: f.title, children: [
1884
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-slate-400", children: f.label }),
1885
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2028
+ tool.mode !== "warp" && import_image_editor14.FREE_TRANSFORM_FIELDS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-1", title: f.title, children: [
2029
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-slate-400", children: f.label }),
2030
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1886
2031
  "input",
1887
2032
  {
1888
2033
  type: "number",
@@ -1902,8 +2047,8 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
1902
2047
  },
1903
2048
  `${f.id}:${round(bar[f.id], f.unit)}`
1904
2049
  ),
1905
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-slate-500", children: f.unit }),
1906
- f.id === "scaleX" && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2050
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-slate-500", children: f.unit }),
2051
+ f.id === "scaleX" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1907
2052
  "button",
1908
2053
  {
1909
2054
  type: "button",
@@ -1918,34 +2063,34 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
1918
2063
  }
1919
2064
  )
1920
2065
  ] }, f.id)),
1921
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("label", { className: "flex items-center gap-1", children: [
1922
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "text-slate-400", children: "Interpolation" }),
1923
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2066
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-1", children: [
2067
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-slate-400", children: "Interpolation" }),
2068
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1924
2069
  "select",
1925
2070
  {
1926
2071
  "aria-label": "Interpolation",
1927
2072
  value: tool.interpolation,
1928
2073
  onChange: (e) => tool.setInterpolation(e.target.value),
1929
2074
  className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
1930
- children: import_image_editor12.INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
2075
+ children: import_image_editor14.INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
1931
2076
  }
1932
2077
  )
1933
2078
  ] }),
1934
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", title: "Commit (Enter)", className: "px-2 py-1 rounded bg-emerald-600 text-white hover:bg-emerald-500", onClick: () => tool.commit(), children: "Commit" }),
1935
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("button", { type: "button", title: "Cancel (Esc)", className: chip3(false), onClick: () => tool.cancel(), children: "Cancel" }),
1936
- tool.error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { role: "alert", className: "text-rose-400", children: tool.error })
2079
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", title: "Commit (Enter)", className: "px-2 py-1 rounded bg-emerald-600 text-white hover:bg-emerald-500", onClick: () => tool.commit(), children: "Commit" }),
2080
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", title: "Cancel (Esc)", className: chip3(false), onClick: () => tool.cancel(), children: "Cancel" }),
2081
+ tool.error && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { role: "alert", className: "text-rose-400", children: tool.error })
1937
2082
  ] });
1938
2083
  };
1939
2084
 
1940
2085
  // src/image-editor/ShapeOptionsBar.tsx
1941
- var import_react12 = require("react");
1942
- var import_image_editor13 = require("@pixerate/editor/image-editor");
1943
- var import_jsx_runtime12 = require("react/jsx-runtime");
2086
+ var import_react13 = require("react");
2087
+ var import_image_editor15 = require("@pixerate/editor/image-editor");
2088
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1944
2089
  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"}`;
1945
2090
  var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
1946
- const [, setTick] = (0, import_react12.useState)(0);
1947
- (0, import_react12.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
1948
- const [error, setError] = (0, import_react12.useState)(null);
2091
+ const [, setTick] = (0, import_react13.useState)(0);
2092
+ (0, import_react13.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
2093
+ const [error, setError] = (0, import_react13.useState)(null);
1949
2094
  const active = controller.getActiveLayer();
1950
2095
  const shapeId = active?.type === "shape" ? active.id : null;
1951
2096
  const set = (change) => {
@@ -1953,19 +2098,19 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
1953
2098
  if (!shapeId) return;
1954
2099
  try {
1955
2100
  setError(null);
1956
- (0, import_image_editor13.applyShapeOptions)(controller, shapeId, change);
2101
+ (0, import_image_editor15.applyShapeOptions)(controller, shapeId, change);
1957
2102
  } catch (e) {
1958
2103
  setError(e instanceof Error ? e.message : String(e));
1959
2104
  }
1960
2105
  };
1961
2106
  const num = (v, min, max) => Math.max(min, Math.min(max, Number(v) || min));
1962
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "shape-options", children: [
1963
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Shape kind", children: import_image_editor13.LIVE_SHAPE_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("button", { type: "button", "aria-pressed": options.kind === k, className: chip4(options.kind === k), onClick: () => onChange({ ...options, kind: k }), children: import_image_editor13.SHAPE_KIND_LABELS[k] }, k)) }),
1964
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
1965
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-1", children: [
1966
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("input", { type: "checkbox", "aria-label": "Fill", checked: options.fill !== null, onChange: (e) => set({ fill: e.target.checked ? "#4f46e5" : null }) }),
2107
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "shape-options", children: [
2108
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Shape kind", children: import_image_editor15.LIVE_SHAPE_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", "aria-pressed": options.kind === k, className: chip4(options.kind === k), onClick: () => onChange({ ...options, kind: k }), children: import_image_editor15.SHAPE_KIND_LABELS[k] }, k)) }),
2109
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
2110
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-1", children: [
2111
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("input", { type: "checkbox", "aria-label": "Fill", checked: options.fill !== null, onChange: (e) => set({ fill: e.target.checked ? "#4f46e5" : null }) }),
1967
2112
  "Fill",
1968
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2113
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1969
2114
  "input",
1970
2115
  {
1971
2116
  type: "color",
@@ -1977,10 +2122,10 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
1977
2122
  }
1978
2123
  )
1979
2124
  ] }),
1980
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-1", children: [
1981
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("input", { type: "checkbox", "aria-label": "Stroke", checked: options.stroke !== null, onChange: (e) => set({ stroke: e.target.checked ? "#000000" : null }) }),
2125
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-1", children: [
2126
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("input", { type: "checkbox", "aria-label": "Stroke", checked: options.stroke !== null, onChange: (e) => set({ stroke: e.target.checked ? "#000000" : null }) }),
1982
2127
  "Stroke",
1983
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2128
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1984
2129
  "input",
1985
2130
  {
1986
2131
  type: "color",
@@ -1992,9 +2137,9 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
1992
2137
  }
1993
2138
  )
1994
2139
  ] }),
1995
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-1", children: [
2140
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-1", children: [
1996
2141
  "Width",
1997
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2142
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1998
2143
  "input",
1999
2144
  {
2000
2145
  type: "number",
@@ -2008,23 +2153,23 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
2008
2153
  )
2009
2154
  ] })
2010
2155
  ] }),
2011
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
2012
- options.kind === "rect" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-1", children: [
2156
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
2157
+ options.kind === "rect" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-1", children: [
2013
2158
  "Radius",
2014
- /* @__PURE__ */ (0, import_jsx_runtime12.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" })
2159
+ /* @__PURE__ */ (0, import_jsx_runtime14.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" })
2015
2160
  ] }),
2016
- options.kind === "polygon" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-1", children: [
2161
+ options.kind === "polygon" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-1", children: [
2017
2162
  "Sides",
2018
- /* @__PURE__ */ (0, import_jsx_runtime12.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" })
2163
+ /* @__PURE__ */ (0, import_jsx_runtime14.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" })
2019
2164
  ] }),
2020
- options.kind === "star" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
2021
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-1", children: [
2165
+ options.kind === "star" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
2166
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-1", children: [
2022
2167
  "Points",
2023
- /* @__PURE__ */ (0, import_jsx_runtime12.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" })
2168
+ /* @__PURE__ */ (0, import_jsx_runtime14.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" })
2024
2169
  ] }),
2025
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-1", children: [
2170
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-1", children: [
2026
2171
  "Inner",
2027
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2172
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2028
2173
  "input",
2029
2174
  {
2030
2175
  type: "range",
@@ -2039,33 +2184,33 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
2039
2184
  )
2040
2185
  ] })
2041
2186
  ] }),
2042
- options.kind === "line" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
2043
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-1", children: [
2187
+ options.kind === "line" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
2188
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-1", children: [
2044
2189
  "Weight",
2045
- /* @__PURE__ */ (0, import_jsx_runtime12.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" })
2190
+ /* @__PURE__ */ (0, import_jsx_runtime14.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" })
2046
2191
  ] }),
2047
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("label", { className: "flex items-center gap-1", children: [
2048
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("input", { type: "checkbox", "aria-label": "Arrowhead", checked: options.arrow, onChange: (e) => set({ arrow: e.target.checked }) }),
2192
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-1", children: [
2193
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("input", { type: "checkbox", "aria-label": "Arrowhead", checked: options.arrow, onChange: (e) => set({ arrow: e.target.checked }) }),
2049
2194
  "Arrowhead"
2050
2195
  ] })
2051
2196
  ] })
2052
2197
  ] }),
2053
- /* @__PURE__ */ (0, import_jsx_runtime12.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." }),
2054
- error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
2198
+ /* @__PURE__ */ (0, import_jsx_runtime14.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." }),
2199
+ error && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
2055
2200
  ] });
2056
2201
  };
2057
2202
 
2058
2203
  // src/image-editor/TypeOptionsBar.tsx
2059
- var import_react13 = require("react");
2060
- var import_image_editor14 = require("@pixerate/editor/image-editor");
2061
- var import_jsx_runtime13 = require("react/jsx-runtime");
2204
+ var import_react14 = require("react");
2205
+ var import_image_editor16 = require("@pixerate/editor/image-editor");
2206
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2062
2207
  var chip5 = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
2063
2208
  var ALIGN_LABELS = { left: "Left", center: "Centre", right: "Right", justify: "Justify" };
2064
2209
  var TypeOptionsBar = ({ controller, options, onChange, session, className }) => {
2065
- const [, setTick] = (0, import_react13.useState)(0);
2066
- (0, import_react13.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
2067
- (0, import_react13.useEffect)(() => session?.subscribe(() => setTick((n) => n + 1)), [session]);
2068
- const [error, setError] = (0, import_react13.useState)(null);
2210
+ const [, setTick] = (0, import_react14.useState)(0);
2211
+ (0, import_react14.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
2212
+ (0, import_react14.useEffect)(() => session?.subscribe(() => setTick((n) => n + 1)), [session]);
2213
+ const [error, setError] = (0, import_react14.useState)(null);
2069
2214
  const active = controller.getActiveLayer();
2070
2215
  const typeId = !session && active?.type === "type" ? active.id : null;
2071
2216
  const here = session?.alive ? session.styleHere() : {};
@@ -2097,11 +2242,11 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
2097
2242
  setError(e instanceof Error ? e.message : String(e));
2098
2243
  }
2099
2244
  };
2100
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "type-options", children: [
2101
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
2102
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-1", children: [
2245
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "type-options", children: [
2246
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
2247
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "flex items-center gap-1", children: [
2103
2248
  "Font",
2104
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2249
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2105
2250
  "input",
2106
2251
  {
2107
2252
  list: "pixerate-type-fonts",
@@ -2111,11 +2256,11 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
2111
2256
  className: "w-32 rounded border border-slate-700 bg-slate-950 px-1 py-0.5"
2112
2257
  }
2113
2258
  ),
2114
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("datalist", { id: "pixerate-type-fonts", children: fonts.map((f) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("option", { value: f }, f)) })
2259
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("datalist", { id: "pixerate-type-fonts", children: fonts.map((f) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("option", { value: f }, f)) })
2115
2260
  ] }),
2116
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "flex items-center gap-1", children: [
2261
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("label", { className: "flex items-center gap-1", children: [
2117
2262
  "Size",
2118
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2263
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
2119
2264
  "input",
2120
2265
  {
2121
2266
  type: "number",
@@ -2128,24 +2273,24 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
2128
2273
  }
2129
2274
  )
2130
2275
  ] }),
2131
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", "aria-pressed": shown.fontWeight >= 600, className: `${chip5(shown.fontWeight >= 600)} font-bold`, onClick: () => style({ fontWeight: shown.fontWeight >= 600 ? 400 : 700 }), children: "B" }),
2132
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", "aria-pressed": shown.italic, className: `${chip5(shown.italic)} italic`, onClick: () => style({ italic: !shown.italic }), children: "I" }),
2133
- /* @__PURE__ */ (0, import_jsx_runtime13.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" })
2276
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", "aria-pressed": shown.fontWeight >= 600, className: `${chip5(shown.fontWeight >= 600)} font-bold`, onClick: () => style({ fontWeight: shown.fontWeight >= 600 ? 400 : 700 }), children: "B" }),
2277
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", "aria-pressed": shown.italic, className: `${chip5(shown.italic)} italic`, onClick: () => style({ italic: !shown.italic }), children: "I" }),
2278
+ /* @__PURE__ */ (0, import_jsx_runtime15.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" })
2134
2279
  ] }),
2135
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Alignment", children: import_image_editor14.TEXT_ALIGNS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { type: "button", "aria-pressed": options.align === a, className: chip5(options.align === a), onClick: () => style({ align: a }), children: ALIGN_LABELS[a] }, a)) }),
2136
- /* @__PURE__ */ (0, import_jsx_runtime13.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." }),
2137
- missing.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { role: "status", className: "text-amber-400", "data-testid": "type-missing-fonts", children: [
2280
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Alignment", children: import_image_editor16.TEXT_ALIGNS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("button", { type: "button", "aria-pressed": options.align === a, className: chip5(options.align === a), onClick: () => style({ align: a }), children: ALIGN_LABELS[a] }, a)) }),
2281
+ /* @__PURE__ */ (0, import_jsx_runtime15.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." }),
2282
+ missing.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { role: "status", className: "text-amber-400", "data-testid": "type-missing-fonts", children: [
2138
2283
  "Missing ",
2139
2284
  missing.length === 1 ? "font" : "fonts",
2140
2285
  ": ",
2141
2286
  missing.join(", ")
2142
2287
  ] }),
2143
- error && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
2288
+ error && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
2144
2289
  ] });
2145
2290
  };
2146
2291
 
2147
2292
  // src/image-editor/ImageEditor.tsx
2148
- var import_jsx_runtime14 = require("react/jsx-runtime");
2293
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2149
2294
  var ImageEditor = ({
2150
2295
  editor: externalEditor,
2151
2296
  src,
@@ -2160,65 +2305,65 @@ var ImageEditor = ({
2160
2305
  const internalEditor = useImageEditor({ image: src });
2161
2306
  const editor = externalEditor || internalEditor;
2162
2307
  const { state, controller } = editor;
2163
- const legacyProcess = (0, import_image_editor15.normalizeProcessVersion)(state.adjustments.process) < import_image_editor15.LATEST_PROCESS_VERSION;
2164
- const canvasRef = (0, import_react14.useRef)(null);
2165
- const containerRef = (0, import_react14.useRef)(null);
2166
- const [activeTab, setActiveTab] = (0, import_react14.useState)("crop");
2167
- const [activeCropRatio, setActiveCropRatio] = (0, import_react14.useState)(null);
2168
- const [selectionOptions, setSelectionOptions] = (0, import_react14.useState)(import_image_editor15.DEFAULT_SELECTION_TOOL_OPTIONS);
2169
- const selectionOptionsRef = (0, import_react14.useRef)(selectionOptions);
2308
+ const legacyProcess = (0, import_image_editor17.normalizeProcessVersion)(state.adjustments.process) < import_image_editor17.LATEST_PROCESS_VERSION;
2309
+ const canvasRef = (0, import_react15.useRef)(null);
2310
+ const containerRef = (0, import_react15.useRef)(null);
2311
+ const [activeTab, setActiveTab] = (0, import_react15.useState)("crop");
2312
+ const [activeCropRatio, setActiveCropRatio] = (0, import_react15.useState)(null);
2313
+ const [selectionOptions, setSelectionOptions] = (0, import_react15.useState)(import_image_editor17.DEFAULT_SELECTION_TOOL_OPTIONS);
2314
+ const selectionOptionsRef = (0, import_react15.useRef)(selectionOptions);
2170
2315
  selectionOptionsRef.current = selectionOptions;
2171
- const selectionGestureRef = (0, import_react14.useRef)(null);
2316
+ const selectionGestureRef = (0, import_react15.useRef)(null);
2172
2317
  if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
2173
- selectionGestureRef.current = new import_image_editor15.SelectionGesture(controller, () => selectionOptionsRef.current);
2318
+ selectionGestureRef.current = new import_image_editor17.SelectionGesture(controller, () => selectionOptionsRef.current);
2174
2319
  }
2175
- const selectionDraftRef = (0, import_react14.useRef)(null);
2176
- const [selectionError, setSelectionError] = (0, import_react14.useState)(null);
2177
- const paintGestureRef = (0, import_react14.useRef)(null);
2178
- const paintControllerRef = (0, import_react14.useRef)(controller);
2320
+ const selectionDraftRef = (0, import_react15.useRef)(null);
2321
+ const [selectionError, setSelectionError] = (0, import_react15.useState)(null);
2322
+ const paintGestureRef = (0, import_react15.useRef)(null);
2323
+ const paintControllerRef = (0, import_react15.useRef)(controller);
2179
2324
  if (!paintGestureRef.current || paintControllerRef.current !== controller) {
2180
- paintGestureRef.current = new import_image_editor15.PaintGesture(controller);
2325
+ paintGestureRef.current = new import_image_editor17.PaintGesture(controller);
2181
2326
  paintControllerRef.current = controller;
2182
2327
  }
2183
- const brushCursorRef = (0, import_react14.useRef)(null);
2184
- const [paintError, setPaintError] = (0, import_react14.useState)(null);
2185
- const transformToolRef = (0, import_react14.useRef)(null);
2186
- const transformControllerRef = (0, import_react14.useRef)(controller);
2328
+ const brushCursorRef = (0, import_react15.useRef)(null);
2329
+ const [paintError, setPaintError] = (0, import_react15.useState)(null);
2330
+ const transformToolRef = (0, import_react15.useRef)(null);
2331
+ const transformControllerRef = (0, import_react15.useRef)(controller);
2187
2332
  if (!transformToolRef.current || transformControllerRef.current !== controller) {
2188
2333
  transformToolRef.current?.cancel();
2189
- transformToolRef.current = new import_image_editor15.FreeTransformTool(controller, {
2334
+ transformToolRef.current = new import_image_editor17.FreeTransformTool(controller, {
2190
2335
  schedule: (run) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(run) : run()
2191
2336
  });
2192
2337
  transformControllerRef.current = controller;
2193
2338
  }
2194
2339
  const transformTool = transformToolRef.current;
2195
- const [, setTransformTick] = (0, import_react14.useState)(0);
2196
- const [transformCursor, setTransformCursor] = (0, import_react14.useState)("default");
2197
- const [shapeOptions, setShapeOptions] = (0, import_react14.useState)(import_image_editor15.DEFAULT_SHAPE_TOOL_OPTIONS);
2198
- const shapeOptionsRef = (0, import_react14.useRef)(shapeOptions);
2340
+ const [, setTransformTick] = (0, import_react15.useState)(0);
2341
+ const [transformCursor, setTransformCursor] = (0, import_react15.useState)("default");
2342
+ const [shapeOptions, setShapeOptions] = (0, import_react15.useState)(import_image_editor17.DEFAULT_SHAPE_TOOL_OPTIONS);
2343
+ const shapeOptionsRef = (0, import_react15.useRef)(shapeOptions);
2199
2344
  shapeOptionsRef.current = shapeOptions;
2200
- const [typeOptions, setTypeOptions] = (0, import_react14.useState)(import_image_editor15.DEFAULT_TYPE_TOOL_OPTIONS);
2201
- const typeOptionsRef = (0, import_react14.useRef)(typeOptions);
2345
+ const [typeOptions, setTypeOptions] = (0, import_react15.useState)(import_image_editor17.DEFAULT_TYPE_TOOL_OPTIONS);
2346
+ const typeOptionsRef = (0, import_react15.useRef)(typeOptions);
2202
2347
  typeOptionsRef.current = typeOptions;
2203
- const shapeGestureRef = (0, import_react14.useRef)(null);
2204
- const typeToolRef = (0, import_react14.useRef)(null);
2205
- const shapeTypeControllerRef = (0, import_react14.useRef)(controller);
2348
+ const shapeGestureRef = (0, import_react15.useRef)(null);
2349
+ const typeToolRef = (0, import_react15.useRef)(null);
2350
+ const shapeTypeControllerRef = (0, import_react15.useRef)(controller);
2206
2351
  if (!shapeGestureRef.current || !typeToolRef.current || shapeTypeControllerRef.current !== controller) {
2207
2352
  typeToolRef.current?.finish();
2208
- shapeGestureRef.current = new import_image_editor15.ShapeDrawGesture(controller, () => shapeOptionsRef.current);
2209
- typeToolRef.current = new import_image_editor15.TypeToolGesture(controller, () => typeOptionsRef.current);
2353
+ shapeGestureRef.current = new import_image_editor17.ShapeDrawGesture(controller, () => shapeOptionsRef.current);
2354
+ typeToolRef.current = new import_image_editor17.TypeToolGesture(controller, () => typeOptionsRef.current);
2210
2355
  shapeTypeControllerRef.current = controller;
2211
2356
  }
2212
- const typeInputRef = (0, import_react14.useRef)(null);
2213
- const [typeSession, setTypeSession] = (0, import_react14.useState)(typeToolRef.current.session);
2214
- const [shapeTypeError, setShapeTypeError] = (0, import_react14.useState)(null);
2215
- const [inpaintPrompt, setInpaintPrompt] = (0, import_react14.useState)("");
2216
- const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react14.useState)("annotations");
2217
- const [isRemovingBg, setIsRemovingBg] = (0, import_react14.useState)(false);
2218
- const [isInpainting, setIsInpainting] = (0, import_react14.useState)(false);
2219
- const [aiError, setAiError] = (0, import_react14.useState)(null);
2220
- const [aiSuccess, setAiSuccess] = (0, import_react14.useState)(null);
2221
- const [aiTarget, setAiTarget] = (0, import_react14.useState)("auto");
2357
+ const typeInputRef = (0, import_react15.useRef)(null);
2358
+ const [typeSession, setTypeSession] = (0, import_react15.useState)(typeToolRef.current.session);
2359
+ const [shapeTypeError, setShapeTypeError] = (0, import_react15.useState)(null);
2360
+ const [inpaintPrompt, setInpaintPrompt] = (0, import_react15.useState)("");
2361
+ const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react15.useState)("annotations");
2362
+ const [isRemovingBg, setIsRemovingBg] = (0, import_react15.useState)(false);
2363
+ const [isInpainting, setIsInpainting] = (0, import_react15.useState)(false);
2364
+ const [aiError, setAiError] = (0, import_react15.useState)(null);
2365
+ const [aiSuccess, setAiSuccess] = (0, import_react15.useState)(null);
2366
+ const [aiTarget, setAiTarget] = (0, import_react15.useState)("auto");
2222
2367
  const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
2223
2368
  const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
2224
2369
  const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
@@ -2281,18 +2426,18 @@ var ImageEditor = ({
2281
2426
  setIsInpainting(false);
2282
2427
  }
2283
2428
  };
2284
- const [activeColor, setActiveColor] = (0, import_react14.useState)("#ef4444");
2285
- const [strokeWidth, setStrokeWidth] = (0, import_react14.useState)(3);
2286
- const [fontSize, setFontSize] = (0, import_react14.useState)(24);
2287
- const [textInput, setTextInput] = (0, import_react14.useState)("");
2288
- const draftAnnotationRef = (0, import_react14.useRef)(null);
2289
- const draftCropRef = (0, import_react14.useRef)(null);
2290
- const cropDragInfoRef = (0, import_react14.useRef)(null);
2291
- const annotationDragInfoRef = (0, import_react14.useRef)(null);
2292
- const isDrawingRef = (0, import_react14.useRef)(false);
2293
- const currentPathRef = (0, import_react14.useRef)([]);
2294
- const dragStartPointRef = (0, import_react14.useRef)(null);
2295
- const renderCanvas = (0, import_react14.useCallback)(
2429
+ const [activeColor, setActiveColor] = (0, import_react15.useState)("#ef4444");
2430
+ const [strokeWidth, setStrokeWidth] = (0, import_react15.useState)(3);
2431
+ const [fontSize, setFontSize] = (0, import_react15.useState)(24);
2432
+ const [textInput, setTextInput] = (0, import_react15.useState)("");
2433
+ const draftAnnotationRef = (0, import_react15.useRef)(null);
2434
+ const draftCropRef = (0, import_react15.useRef)(null);
2435
+ const cropDragInfoRef = (0, import_react15.useRef)(null);
2436
+ const annotationDragInfoRef = (0, import_react15.useRef)(null);
2437
+ const isDrawingRef = (0, import_react15.useRef)(false);
2438
+ const currentPathRef = (0, import_react15.useRef)([]);
2439
+ const dragStartPointRef = (0, import_react15.useRef)(null);
2440
+ const renderCanvas = (0, import_react15.useCallback)(
2296
2441
  async (draftAnnotation, draftCrop) => {
2297
2442
  const canvas = canvasRef.current;
2298
2443
  const container = containerRef.current;
@@ -2315,8 +2460,8 @@ var ImageEditor = ({
2315
2460
  },
2316
2461
  [controller, activeTab, transformTool]
2317
2462
  );
2318
- (0, import_react14.useEffect)(() => typeSession?.subscribe(() => void renderCanvas()), [typeSession, renderCanvas]);
2319
- (0, import_react14.useEffect)(() => {
2463
+ (0, import_react15.useEffect)(() => typeSession?.subscribe(() => void renderCanvas()), [typeSession, renderCanvas]);
2464
+ (0, import_react15.useEffect)(() => {
2320
2465
  if (activeTab === "annotate" && state.activeTool === "type") return;
2321
2466
  if (typeToolRef.current?.session) {
2322
2467
  typeToolRef.current.finish();
@@ -2351,7 +2496,7 @@ var ImageEditor = ({
2351
2496
  el.value = "";
2352
2497
  }
2353
2498
  };
2354
- (0, import_react14.useEffect)(() => transformTool.subscribe(() => {
2499
+ (0, import_react15.useEffect)(() => transformTool.subscribe(() => {
2355
2500
  setTransformTick((n) => n + 1);
2356
2501
  void renderCanvas();
2357
2502
  }), [transformTool, renderCanvas]);
@@ -2362,8 +2507,8 @@ var ImageEditor = ({
2362
2507
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
2363
2508
  const s = controller.getState();
2364
2509
  const cropping = activeTab === "crop";
2365
- const projection = (0, import_image_editor15.getViewportProjection)(s, canvas.width, canvas.height, cropping);
2366
- const pt = (0, import_image_editor15.canvasToImagePoint)({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
2510
+ const projection = (0, import_image_editor17.getViewportProjection)(s, canvas.width, canvas.height, cropping);
2511
+ const pt = (0, import_image_editor17.canvasToImagePoint)({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
2367
2512
  transformTool.setView(projection.scale);
2368
2513
  return { pt, tolerance: 6 / (projection.scale || 1) };
2369
2514
  };
@@ -2394,7 +2539,7 @@ var ImageEditor = ({
2394
2539
  transformTool.up();
2395
2540
  return true;
2396
2541
  };
2397
- (0, import_react14.useEffect)(() => {
2542
+ (0, import_react15.useEffect)(() => {
2398
2543
  if (typeof window === "undefined") return;
2399
2544
  const onKey = (e) => {
2400
2545
  if (transformTool.key(e)) e.preventDefault();
@@ -2402,7 +2547,7 @@ var ImageEditor = ({
2402
2547
  window.addEventListener("keydown", onKey);
2403
2548
  return () => window.removeEventListener("keydown", onKey);
2404
2549
  }, [transformTool]);
2405
- (0, import_react14.useEffect)(() => {
2550
+ (0, import_react15.useEffect)(() => {
2406
2551
  const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
2407
2552
  const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
2408
2553
  const animId = raf(() => {
@@ -2410,12 +2555,12 @@ var ImageEditor = ({
2410
2555
  });
2411
2556
  return () => caf(animId);
2412
2557
  }, [renderCanvas, state]);
2413
- (0, import_react14.useEffect)(() => {
2558
+ (0, import_react15.useEffect)(() => {
2414
2559
  if (activeTab === "crop" && editor.state.activeTool !== "crop") {
2415
2560
  editor.setTool("crop");
2416
2561
  }
2417
2562
  }, [activeTab, editor]);
2418
- (0, import_react14.useEffect)(() => {
2563
+ (0, import_react15.useEffect)(() => {
2419
2564
  const container = containerRef.current;
2420
2565
  if (!container) return;
2421
2566
  if (typeof ResizeObserver !== "undefined") {
@@ -2451,8 +2596,8 @@ var ImageEditor = ({
2451
2596
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
2452
2597
  const s = controller.getState();
2453
2598
  return list.map((ev) => ({
2454
- ...(0, import_image_editor15.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
2455
- pressure: (0, import_image_editor15.pointerPressure)(ev)
2599
+ ...(0, import_image_editor17.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
2600
+ pressure: (0, import_image_editor17.pointerPressure)(ev)
2456
2601
  }));
2457
2602
  };
2458
2603
  const handlePaintPointerDown = (e) => {
@@ -2483,10 +2628,10 @@ var ImageEditor = ({
2483
2628
  if (g.error) setPaintError(g.error);
2484
2629
  }
2485
2630
  };
2486
- (0, import_react14.useEffect)(() => {
2631
+ (0, import_react15.useEffect)(() => {
2487
2632
  if (activeTab !== "paint" || typeof window === "undefined") return;
2488
2633
  const onKey = (e) => {
2489
- if ((0, import_image_editor15.handlePaintShortcut)(controller, e)) e.preventDefault();
2634
+ if ((0, import_image_editor17.handlePaintShortcut)(controller, e)) e.preventDefault();
2490
2635
  };
2491
2636
  window.addEventListener("keydown", onKey);
2492
2637
  return () => window.removeEventListener("keydown", onKey);
@@ -2497,7 +2642,7 @@ var ImageEditor = ({
2497
2642
  const canvasPt = getCanvasEventPoint(e);
2498
2643
  if (activeTab === "select") {
2499
2644
  const gesture = selectionGestureRef.current;
2500
- const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2645
+ const imgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2501
2646
  void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
2502
2647
  return;
2503
2648
  }
@@ -2508,8 +2653,8 @@ var ImageEditor = ({
2508
2653
  width: state.imageDimensions.width,
2509
2654
  height: state.imageDimensions.height
2510
2655
  };
2511
- const handle = (0, import_image_editor15.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
2512
- const startImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
2656
+ const handle = (0, import_image_editor17.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
2657
+ const startImgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
2513
2658
  if (handle) {
2514
2659
  cropDragInfoRef.current = {
2515
2660
  handle,
@@ -2528,7 +2673,7 @@ var ImageEditor = ({
2528
2673
  return;
2529
2674
  }
2530
2675
  if (activeTab === "annotate" && (state.activeTool === "shape" || state.activeTool === "type")) {
2531
- const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2676
+ const imgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2532
2677
  setShapeTypeError(null);
2533
2678
  if (state.activeTool === "shape") shapeGestureRef.current.down(imgPt);
2534
2679
  else {
@@ -2539,12 +2684,12 @@ var ImageEditor = ({
2539
2684
  return;
2540
2685
  }
2541
2686
  if (activeTab === "annotate") {
2542
- const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2687
+ const imgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2543
2688
  dragStartPointRef.current = imgPt;
2544
2689
  if (state.activeTool === "select") {
2545
2690
  for (let i = state.annotations.length - 1; i >= 0; i--) {
2546
2691
  const ann = state.annotations[i];
2547
- if ((0, import_image_editor15.hitTestAnnotation)(imgPt, ann)) {
2692
+ if ((0, import_image_editor17.hitTestAnnotation)(imgPt, ann)) {
2548
2693
  editor.selectAnnotation(ann.id);
2549
2694
  annotationDragInfoRef.current = {
2550
2695
  annId: ann.id,
@@ -2580,7 +2725,7 @@ var ImageEditor = ({
2580
2725
  const canvasPt = getCanvasEventPoint(e);
2581
2726
  if (activeTab === "select") {
2582
2727
  const gesture = selectionGestureRef.current;
2583
- if (gesture.active && gesture.move((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
2728
+ if (gesture.active && gesture.move((0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
2584
2729
  selectionDraftRef.current = gesture.draftPath;
2585
2730
  renderCanvas();
2586
2731
  }
@@ -2589,7 +2734,7 @@ var ImageEditor = ({
2589
2734
  if (activeTab === "crop") {
2590
2735
  const drag = cropDragInfoRef.current;
2591
2736
  if (drag) {
2592
- const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
2737
+ const currentImgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
2593
2738
  let newCrop;
2594
2739
  if (drag.handle === "new") {
2595
2740
  const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
@@ -2603,7 +2748,7 @@ var ImageEditor = ({
2603
2748
  height: Math.round(Math.max(20, maxY - minY))
2604
2749
  };
2605
2750
  } else {
2606
- newCrop = (0, import_image_editor15.calculateCropDrag)(
2751
+ newCrop = (0, import_image_editor17.calculateCropDrag)(
2607
2752
  drag.startCrop,
2608
2753
  drag.handle,
2609
2754
  drag.startImgPt,
@@ -2623,15 +2768,15 @@ var ImageEditor = ({
2623
2768
  width: state.imageDimensions.width,
2624
2769
  height: state.imageDimensions.height
2625
2770
  };
2626
- const handle = (0, import_image_editor15.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
2627
- canvas.style.cursor = (0, import_image_editor15.getCropCursor)(handle, state.transform);
2771
+ const handle = (0, import_image_editor17.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
2772
+ canvas.style.cursor = (0, import_image_editor17.getCropCursor)(handle, state.transform);
2628
2773
  }
2629
2774
  return;
2630
2775
  }
2631
2776
  if (activeTab === "annotate" && state.activeTool === "shape") {
2632
2777
  const g = shapeGestureRef.current;
2633
2778
  if (g.active) {
2634
- g.move((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), { shift: e.shiftKey, alt: e.altKey });
2779
+ g.move((0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), { shift: e.shiftKey, alt: e.altKey });
2635
2780
  if (g.error) setShapeTypeError(g.error);
2636
2781
  }
2637
2782
  return;
@@ -2639,7 +2784,7 @@ var ImageEditor = ({
2639
2784
  if (activeTab === "annotate") {
2640
2785
  if (annotationDragInfoRef.current) {
2641
2786
  const drag = annotationDragInfoRef.current;
2642
- const currentImgPt2 = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2787
+ const currentImgPt2 = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2643
2788
  const dx = currentImgPt2.x - drag.startImgPt.x;
2644
2789
  const dy = currentImgPt2.y - drag.startImgPt.y;
2645
2790
  editor.updateAnnotation(drag.annId, {
@@ -2651,10 +2796,10 @@ var ImageEditor = ({
2651
2796
  const startPt = dragStartPointRef.current;
2652
2797
  if (!startPt) {
2653
2798
  if (state.activeTool === "select") {
2654
- const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2799
+ const imgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2655
2800
  let hovered = false;
2656
2801
  for (let i = state.annotations.length - 1; i >= 0; i--) {
2657
- if ((0, import_image_editor15.hitTestAnnotation)(imgPt, state.annotations[i])) {
2802
+ if ((0, import_image_editor17.hitTestAnnotation)(imgPt, state.annotations[i])) {
2658
2803
  hovered = true;
2659
2804
  break;
2660
2805
  }
@@ -2665,7 +2810,7 @@ var ImageEditor = ({
2665
2810
  }
2666
2811
  return;
2667
2812
  }
2668
- const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2813
+ const currentImgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2669
2814
  if (state.activeTool === "pen" && isDrawingRef.current) {
2670
2815
  currentPathRef.current.push(currentImgPt);
2671
2816
  const draft = {
@@ -2745,7 +2890,7 @@ var ImageEditor = ({
2745
2890
  if (activeTab === "select") {
2746
2891
  const gesture = selectionGestureRef.current;
2747
2892
  if (gesture.active) {
2748
- gesture.end((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
2893
+ gesture.end((0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
2749
2894
  selectionDraftRef.current = null;
2750
2895
  renderCanvas();
2751
2896
  }
@@ -2768,7 +2913,7 @@ var ImageEditor = ({
2768
2913
  }
2769
2914
  if (activeTab === "annotate" && state.activeTool === "type") {
2770
2915
  const tool = typeToolRef.current;
2771
- tool.up((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false));
2916
+ tool.up((0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false));
2772
2917
  setTypeSession(tool.session);
2773
2918
  if (tool.error) setShapeTypeError(tool.error);
2774
2919
  void renderCanvas();
@@ -2782,7 +2927,7 @@ var ImageEditor = ({
2782
2927
  }
2783
2928
  const startPt = dragStartPointRef.current;
2784
2929
  if (startPt) {
2785
- const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2930
+ const currentImgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
2786
2931
  if (state.activeTool === "pen" && isDrawingRef.current) {
2787
2932
  if (currentPathRef.current.length > 1) {
2788
2933
  editor.addAnnotation({
@@ -2878,15 +3023,15 @@ var ImageEditor = ({
2878
3023
  link.click();
2879
3024
  }
2880
3025
  };
2881
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3026
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
2882
3027
  "div",
2883
3028
  {
2884
3029
  className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
2885
3030
  style,
2886
3031
  children: [
2887
- /* @__PURE__ */ (0, import_jsx_runtime14.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: [
2888
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
2889
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3032
+ /* @__PURE__ */ (0, import_jsx_runtime16.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: [
3033
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
3034
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2890
3035
  "button",
2891
3036
  {
2892
3037
  type: "button",
@@ -2898,7 +3043,7 @@ var ImageEditor = ({
2898
3043
  children: "Transform & Crop"
2899
3044
  }
2900
3045
  ),
2901
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3046
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2902
3047
  "button",
2903
3048
  {
2904
3049
  type: "button",
@@ -2910,7 +3055,7 @@ var ImageEditor = ({
2910
3055
  children: "Adjustments"
2911
3056
  }
2912
3057
  ),
2913
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3058
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2914
3059
  "button",
2915
3060
  {
2916
3061
  type: "button",
@@ -2922,7 +3067,7 @@ var ImageEditor = ({
2922
3067
  children: "Layers"
2923
3068
  }
2924
3069
  ),
2925
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3070
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2926
3071
  "button",
2927
3072
  {
2928
3073
  type: "button",
@@ -2934,7 +3079,7 @@ var ImageEditor = ({
2934
3079
  children: "Paint"
2935
3080
  }
2936
3081
  ),
2937
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3082
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2938
3083
  "button",
2939
3084
  {
2940
3085
  type: "button",
@@ -2946,7 +3091,7 @@ var ImageEditor = ({
2946
3091
  children: "Select & Mask"
2947
3092
  }
2948
3093
  ),
2949
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3094
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2950
3095
  "button",
2951
3096
  {
2952
3097
  type: "button",
@@ -2958,7 +3103,7 @@ var ImageEditor = ({
2958
3103
  children: "Annotations"
2959
3104
  }
2960
3105
  ),
2961
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3106
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2962
3107
  "button",
2963
3108
  {
2964
3109
  type: "button",
@@ -2970,7 +3115,7 @@ var ImageEditor = ({
2970
3115
  children: "Depth Mask"
2971
3116
  }
2972
3117
  ),
2973
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3118
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
2974
3119
  "button",
2975
3120
  {
2976
3121
  type: "button",
@@ -2980,14 +3125,14 @@ var ImageEditor = ({
2980
3125
  },
2981
3126
  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"}`,
2982
3127
  children: [
2983
- /* @__PURE__ */ (0, import_jsx_runtime14.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_runtime14.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" }) }),
3128
+ /* @__PURE__ */ (0, import_jsx_runtime16.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_runtime16.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" }) }),
2984
3129
  "AI Tools"
2985
3130
  ]
2986
3131
  }
2987
3132
  )
2988
3133
  ] }),
2989
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
2990
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3134
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
3135
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
2991
3136
  "button",
2992
3137
  {
2993
3138
  type: "button",
@@ -2998,7 +3143,7 @@ var ImageEditor = ({
2998
3143
  children: "\u21A9"
2999
3144
  }
3000
3145
  ),
3001
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3146
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3002
3147
  "button",
3003
3148
  {
3004
3149
  type: "button",
@@ -3009,7 +3154,7 @@ var ImageEditor = ({
3009
3154
  children: "\u21AA"
3010
3155
  }
3011
3156
  ),
3012
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3157
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3013
3158
  "button",
3014
3159
  {
3015
3160
  type: "button",
@@ -3018,8 +3163,8 @@ var ImageEditor = ({
3018
3163
  children: "Reset"
3019
3164
  }
3020
3165
  ),
3021
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
3022
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3166
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
3167
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3023
3168
  "button",
3024
3169
  {
3025
3170
  type: "button",
@@ -3029,11 +3174,11 @@ var ImageEditor = ({
3029
3174
  children: "-"
3030
3175
  }
3031
3176
  ),
3032
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
3177
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
3033
3178
  Math.round(state.zoom * 100),
3034
3179
  "%"
3035
3180
  ] }),
3036
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3181
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3037
3182
  "button",
3038
3183
  {
3039
3184
  type: "button",
@@ -3043,8 +3188,8 @@ var ImageEditor = ({
3043
3188
  children: "+"
3044
3189
  }
3045
3190
  ),
3046
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
3047
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3191
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
3192
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3048
3193
  "button",
3049
3194
  {
3050
3195
  type: "button",
@@ -3055,7 +3200,7 @@ var ImageEditor = ({
3055
3200
  children: "Hold Compare"
3056
3201
  }
3057
3202
  ),
3058
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3203
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3059
3204
  "button",
3060
3205
  {
3061
3206
  type: "button",
@@ -3066,16 +3211,16 @@ var ImageEditor = ({
3066
3211
  )
3067
3212
  ] })
3068
3213
  ] }),
3069
- transformTool.active && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
3070
- !transformTool.active && transformTool.error && /* @__PURE__ */ (0, import_jsx_runtime14.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 }),
3071
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
3072
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3214
+ transformTool.active && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
3215
+ !transformTool.active && transformTool.error && /* @__PURE__ */ (0, import_jsx_runtime16.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 }),
3216
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
3217
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3073
3218
  "div",
3074
3219
  {
3075
3220
  ref: containerRef,
3076
3221
  className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
3077
3222
  children: [
3078
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3223
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3079
3224
  "canvas",
3080
3225
  {
3081
3226
  ref: canvasRef,
@@ -3092,7 +3237,7 @@ var ImageEditor = ({
3092
3237
  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" : ""}`
3093
3238
  }
3094
3239
  ),
3095
- typeSession && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3240
+ typeSession && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3096
3241
  "textarea",
3097
3242
  {
3098
3243
  ref: typeInputRef,
@@ -3114,11 +3259,11 @@ var ImageEditor = ({
3114
3259
  ]
3115
3260
  }
3116
3261
  ),
3117
- /* @__PURE__ */ (0, import_jsx_runtime14.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: [
3118
- activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
3119
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
3120
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
3121
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3262
+ /* @__PURE__ */ (0, import_jsx_runtime16.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: [
3263
+ activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
3264
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
3265
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
3266
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3122
3267
  "button",
3123
3268
  {
3124
3269
  type: "button",
@@ -3130,7 +3275,7 @@ var ImageEditor = ({
3130
3275
  children: "Freeform"
3131
3276
  }
3132
3277
  ),
3133
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3278
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3134
3279
  "button",
3135
3280
  {
3136
3281
  type: "button",
@@ -3142,7 +3287,7 @@ var ImageEditor = ({
3142
3287
  children: "1:1 Square"
3143
3288
  }
3144
3289
  ),
3145
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3290
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3146
3291
  "button",
3147
3292
  {
3148
3293
  type: "button",
@@ -3154,7 +3299,7 @@ var ImageEditor = ({
3154
3299
  children: "4:3 Standard"
3155
3300
  }
3156
3301
  ),
3157
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3302
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3158
3303
  "button",
3159
3304
  {
3160
3305
  type: "button",
@@ -3166,7 +3311,7 @@ var ImageEditor = ({
3166
3311
  children: "16:9 Wide"
3167
3312
  }
3168
3313
  ),
3169
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3314
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3170
3315
  "button",
3171
3316
  {
3172
3317
  type: "button",
@@ -3178,7 +3323,7 @@ var ImageEditor = ({
3178
3323
  children: "3:2 Photo"
3179
3324
  }
3180
3325
  ),
3181
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3326
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3182
3327
  "button",
3183
3328
  {
3184
3329
  type: "button",
@@ -3191,10 +3336,10 @@ var ImageEditor = ({
3191
3336
  }
3192
3337
  )
3193
3338
  ] }),
3194
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3195
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
3196
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
3197
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3339
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3340
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
3341
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
3342
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3198
3343
  "button",
3199
3344
  {
3200
3345
  type: "button",
@@ -3203,7 +3348,7 @@ var ImageEditor = ({
3203
3348
  children: "Rotate -90\xB0"
3204
3349
  }
3205
3350
  ),
3206
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3351
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3207
3352
  "button",
3208
3353
  {
3209
3354
  type: "button",
@@ -3212,7 +3357,7 @@ var ImageEditor = ({
3212
3357
  children: "Rotate +90\xB0"
3213
3358
  }
3214
3359
  ),
3215
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3360
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3216
3361
  "button",
3217
3362
  {
3218
3363
  type: "button",
@@ -3221,7 +3366,7 @@ var ImageEditor = ({
3221
3366
  children: "Flip Horizontal"
3222
3367
  }
3223
3368
  ),
3224
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3369
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3225
3370
  "button",
3226
3371
  {
3227
3372
  type: "button",
@@ -3232,10 +3377,10 @@ var ImageEditor = ({
3232
3377
  )
3233
3378
  ] })
3234
3379
  ] }),
3235
- activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3236
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center justify-between", children: [
3237
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
3238
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3380
+ activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3381
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center justify-between", children: [
3382
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
3383
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3239
3384
  "button",
3240
3385
  {
3241
3386
  type: "button",
@@ -3245,25 +3390,25 @@ var ImageEditor = ({
3245
3390
  }
3246
3391
  )
3247
3392
  ] }),
3248
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Histogram, { histogram: editor.histogram }),
3249
- import_image_editor15.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_react14.default.Fragment, { children: [
3250
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3393
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Histogram, { histogram: editor.histogram }),
3394
+ import_image_editor17.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_react15.default.Fragment, { children: [
3395
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3251
3396
  ControlSlider,
3252
3397
  {
3253
3398
  spec,
3254
- value: (0, import_image_editor15.readAdjustmentControls)(state.adjustments)[spec.id],
3399
+ value: (0, import_image_editor17.readAdjustmentControls)(state.adjustments)[spec.id],
3255
3400
  disabled: spec.requiresProcess !== void 0 && legacyProcess,
3256
3401
  onChange: (v) => editor.setAdjustments({ [spec.id]: v })
3257
3402
  }
3258
3403
  ),
3259
- spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3404
+ spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3260
3405
  "div",
3261
3406
  {
3262
3407
  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",
3263
3408
  "data-testid": "image-editor-process-notice",
3264
3409
  children: [
3265
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
3266
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3410
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
3411
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3267
3412
  "button",
3268
3413
  {
3269
3414
  type: "button",
@@ -3276,7 +3421,7 @@ var ImageEditor = ({
3276
3421
  }
3277
3422
  )
3278
3423
  ] }, spec.id)),
3279
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3424
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3280
3425
  AdjustmentLayersPanel,
3281
3426
  {
3282
3427
  controller,
@@ -3285,9 +3430,9 @@ var ImageEditor = ({
3285
3430
  }
3286
3431
  ) })
3287
3432
  ] }),
3288
- activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3289
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
3290
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3433
+ activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3434
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
3435
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3291
3436
  "button",
3292
3437
  {
3293
3438
  type: "button",
@@ -3298,14 +3443,14 @@ var ImageEditor = ({
3298
3443
  children: "Free Transform"
3299
3444
  }
3300
3445
  ),
3301
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LayersPanel, { controller }),
3302
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Colour" }),
3303
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ColorProfilePanel, { controller })
3446
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(LayersPanel, { controller }),
3447
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Colour" }),
3448
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ColorProfilePanel, { controller })
3304
3449
  ] }),
3305
- activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3306
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
3307
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(BrushOptionsBar, { controller }),
3308
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3450
+ activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3451
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
3452
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(BrushOptionsBar, { controller }),
3453
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3309
3454
  "button",
3310
3455
  {
3311
3456
  type: "button",
@@ -3316,12 +3461,12 @@ var ImageEditor = ({
3316
3461
  children: "Free Transform"
3317
3462
  }
3318
3463
  ),
3319
- paintError && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
3320
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(LayersPanel, { controller }) })
3464
+ paintError && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
3465
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(LayersPanel, { controller }) })
3321
3466
  ] }),
3322
- activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3323
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Shape & Type Layers" }),
3324
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "grid grid-cols-2 gap-1.5", children: ["shape", "type"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3467
+ activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3468
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Shape & Type Layers" }),
3469
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "grid grid-cols-2 gap-1.5", children: ["shape", "type"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3325
3470
  "button",
3326
3471
  {
3327
3472
  type: "button",
@@ -3332,13 +3477,13 @@ var ImageEditor = ({
3332
3477
  },
3333
3478
  t
3334
3479
  )) }),
3335
- state.activeTool === "shape" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ShapeOptionsBar, { controller, options: shapeOptions, onChange: setShapeOptions }),
3336
- state.activeTool === "type" && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TypeOptionsBar, { controller, options: typeOptions, onChange: setTypeOptions, session: typeSession }),
3337
- state.activeTool === "type" && typeSession && /* @__PURE__ */ (0, import_jsx_runtime14.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" }),
3338
- shapeTypeError && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "shape-type-error", children: shapeTypeError }),
3339
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3340
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
3341
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3480
+ state.activeTool === "shape" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ShapeOptionsBar, { controller, options: shapeOptions, onChange: setShapeOptions }),
3481
+ state.activeTool === "type" && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TypeOptionsBar, { controller, options: typeOptions, onChange: setTypeOptions, session: typeSession }),
3482
+ state.activeTool === "type" && typeSession && /* @__PURE__ */ (0, import_jsx_runtime16.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" }),
3483
+ shapeTypeError && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "shape-type-error", children: shapeTypeError }),
3484
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3485
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
3486
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3342
3487
  "button",
3343
3488
  {
3344
3489
  type: "button",
@@ -3348,9 +3493,9 @@ var ImageEditor = ({
3348
3493
  },
3349
3494
  t
3350
3495
  )) }),
3351
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
3352
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("label", { className: "text-slate-400", children: "Color:" }),
3353
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3496
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
3497
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("label", { className: "text-slate-400", children: "Color:" }),
3498
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3354
3499
  "input",
3355
3500
  {
3356
3501
  type: "color",
@@ -3359,15 +3504,15 @@ var ImageEditor = ({
3359
3504
  className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
3360
3505
  }
3361
3506
  ),
3362
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex-1 ml-2", children: [
3363
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
3364
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Width:" }),
3365
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "font-mono", children: [
3507
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 ml-2", children: [
3508
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
3509
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Width:" }),
3510
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "font-mono", children: [
3366
3511
  strokeWidth,
3367
3512
  "px"
3368
3513
  ] })
3369
3514
  ] }),
3370
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3515
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3371
3516
  "input",
3372
3517
  {
3373
3518
  type: "range",
@@ -3380,10 +3525,10 @@ var ImageEditor = ({
3380
3525
  )
3381
3526
  ] })
3382
3527
  ] }),
3383
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3384
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
3385
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex gap-2", children: [
3386
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3528
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3529
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
3530
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex gap-2", children: [
3531
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3387
3532
  "input",
3388
3533
  {
3389
3534
  type: "text",
@@ -3394,7 +3539,7 @@ var ImageEditor = ({
3394
3539
  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"
3395
3540
  }
3396
3541
  ),
3397
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3542
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3398
3543
  "button",
3399
3544
  {
3400
3545
  type: "button",
@@ -3404,14 +3549,14 @@ var ImageEditor = ({
3404
3549
  }
3405
3550
  )
3406
3551
  ] }),
3407
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
3408
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Font Size:" }),
3409
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "font-mono", children: [
3552
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
3553
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Font Size:" }),
3554
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "font-mono", children: [
3410
3555
  fontSize,
3411
3556
  "px"
3412
3557
  ] })
3413
3558
  ] }),
3414
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3559
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3415
3560
  "input",
3416
3561
  {
3417
3562
  type: "range",
@@ -3422,14 +3567,14 @@ var ImageEditor = ({
3422
3567
  className: "w-full accent-indigo-500"
3423
3568
  }
3424
3569
  ),
3425
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3426
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center justify-between", children: [
3427
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "text-slate-400", children: [
3570
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
3571
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center justify-between", children: [
3572
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "text-slate-400", children: [
3428
3573
  "Layers (",
3429
3574
  state.annotations.length,
3430
3575
  ")"
3431
3576
  ] }),
3432
- state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3577
+ state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3433
3578
  "button",
3434
3579
  {
3435
3580
  type: "button",
@@ -3438,7 +3583,7 @@ var ImageEditor = ({
3438
3583
  children: "Delete Selected"
3439
3584
  }
3440
3585
  ),
3441
- state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3586
+ state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3442
3587
  "button",
3443
3588
  {
3444
3589
  type: "button",
@@ -3449,10 +3594,10 @@ var ImageEditor = ({
3449
3594
  )
3450
3595
  ] })
3451
3596
  ] }),
3452
- activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3453
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center justify-between", children: [
3454
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
3455
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3597
+ activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
3598
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center justify-between", children: [
3599
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
3600
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3456
3601
  "button",
3457
3602
  {
3458
3603
  type: "button",
@@ -3462,8 +3607,8 @@ var ImageEditor = ({
3462
3607
  }
3463
3608
  )
3464
3609
  ] }),
3465
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
3466
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3610
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
3611
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3467
3612
  "input",
3468
3613
  {
3469
3614
  type: "checkbox",
@@ -3472,12 +3617,12 @@ var ImageEditor = ({
3472
3617
  className: "rounded accent-indigo-500"
3473
3618
  }
3474
3619
  ),
3475
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Enable Depth / Alpha Mask" })
3620
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Enable Depth / Alpha Mask" })
3476
3621
  ] }),
3477
- state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3478
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
3479
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
3480
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3622
+ state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3623
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
3624
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
3625
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3481
3626
  "input",
3482
3627
  {
3483
3628
  type: "text",
@@ -3488,8 +3633,8 @@ var ImageEditor = ({
3488
3633
  }
3489
3634
  )
3490
3635
  ] }),
3491
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex gap-2", children: [
3492
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3636
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex gap-2", children: [
3637
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3493
3638
  "button",
3494
3639
  {
3495
3640
  type: "button",
@@ -3498,7 +3643,7 @@ var ImageEditor = ({
3498
3643
  children: "Threshold Mode"
3499
3644
  }
3500
3645
  ),
3501
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3646
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3502
3647
  "button",
3503
3648
  {
3504
3649
  type: "button",
@@ -3508,12 +3653,12 @@ var ImageEditor = ({
3508
3653
  }
3509
3654
  )
3510
3655
  ] }),
3511
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
3512
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3513
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Depth Start (Lower):" }),
3514
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
3656
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
3657
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3658
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Depth Start (Lower):" }),
3659
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
3515
3660
  ] }),
3516
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3661
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3517
3662
  "input",
3518
3663
  {
3519
3664
  type: "range",
@@ -3527,12 +3672,12 @@ var ImageEditor = ({
3527
3672
  }
3528
3673
  )
3529
3674
  ] }),
3530
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
3531
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3532
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Depth Stop (Upper):" }),
3533
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
3675
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
3676
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3677
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Depth Stop (Upper):" }),
3678
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
3534
3679
  ] }),
3535
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3680
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3536
3681
  "input",
3537
3682
  {
3538
3683
  type: "range",
@@ -3546,12 +3691,12 @@ var ImageEditor = ({
3546
3691
  }
3547
3692
  )
3548
3693
  ] }),
3549
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
3550
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3551
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Softness:" }),
3552
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
3694
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
3695
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
3696
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Softness:" }),
3697
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
3553
3698
  ] }),
3554
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3699
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3555
3700
  "input",
3556
3701
  {
3557
3702
  type: "range",
@@ -3563,8 +3708,8 @@ var ImageEditor = ({
3563
3708
  }
3564
3709
  )
3565
3710
  ] }),
3566
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
3567
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3711
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
3712
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3568
3713
  "input",
3569
3714
  {
3570
3715
  type: "checkbox",
@@ -3573,12 +3718,12 @@ var ImageEditor = ({
3573
3718
  className: "rounded accent-indigo-500"
3574
3719
  }
3575
3720
  ),
3576
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Invert Mask" })
3721
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Invert Mask" })
3577
3722
  ] })
3578
3723
  ] })
3579
3724
  ] }),
3580
- activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
3581
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3725
+ activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
3726
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3582
3727
  SelectionOptionsBar,
3583
3728
  {
3584
3729
  controller,
@@ -3588,9 +3733,9 @@ var ImageEditor = ({
3588
3733
  quickMask: Boolean(state.quickMask)
3589
3734
  }
3590
3735
  ),
3591
- selectionError && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
3592
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex gap-1", children: [
3593
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3736
+ selectionError && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
3737
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex gap-1", children: [
3738
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3594
3739
  "button",
3595
3740
  {
3596
3741
  type: "button",
@@ -3601,7 +3746,7 @@ var ImageEditor = ({
3601
3746
  children: "Transform Selection"
3602
3747
  }
3603
3748
  ),
3604
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3749
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3605
3750
  "button",
3606
3751
  {
3607
3752
  type: "button",
@@ -3613,12 +3758,12 @@ var ImageEditor = ({
3613
3758
  }
3614
3759
  )
3615
3760
  ] }),
3616
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
3761
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
3617
3762
  ] }),
3618
- activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
3619
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
3620
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: "Results go to" }),
3621
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3763
+ activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
3764
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
3765
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { children: "Results go to" }),
3766
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3622
3767
  "select",
3623
3768
  {
3624
3769
  "aria-label": "AI result target",
@@ -3626,54 +3771,54 @@ var ImageEditor = ({
3626
3771
  onChange: (e) => setAiTarget(e.target.value),
3627
3772
  className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
3628
3773
  children: [
3629
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
3630
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
3631
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("option", { value: "replace", children: "Replace image" })
3774
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
3775
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
3776
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("option", { value: "replace", children: "Replace image" })
3632
3777
  ]
3633
3778
  }
3634
3779
  )
3635
3780
  ] }),
3636
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3637
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center justify-between", children: [
3638
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3639
- /* @__PURE__ */ (0, import_jsx_runtime14.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_runtime14.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" }) }),
3781
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3782
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center justify-between", children: [
3783
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3784
+ /* @__PURE__ */ (0, import_jsx_runtime16.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_runtime16.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" }) }),
3640
3785
  "Background Removal"
3641
3786
  ] }),
3642
- isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime14.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..." })
3787
+ isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime16.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..." })
3643
3788
  ] }),
3644
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
3645
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3789
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
3790
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3646
3791
  "button",
3647
3792
  {
3648
3793
  type: "button",
3649
3794
  onClick: handleRemoveBackground,
3650
3795
  disabled: isRemovingBg || isInpainting,
3651
3796
  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",
3652
- children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3653
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3797
+ children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3798
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3654
3799
  "Removing Background..."
3655
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3656
- /* @__PURE__ */ (0, import_jsx_runtime14.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_runtime14.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" }) }),
3800
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3801
+ /* @__PURE__ */ (0, import_jsx_runtime16.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_runtime16.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" }) }),
3657
3802
  "Remove Background"
3658
3803
  ] })
3659
3804
  }
3660
3805
  )
3661
3806
  ] }),
3662
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3663
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center justify-between", children: [
3664
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3665
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
3666
- /* @__PURE__ */ (0, import_jsx_runtime14.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" }),
3667
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("path", { d: "m14 7 3 3" })
3807
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
3808
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center justify-between", children: [
3809
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
3810
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
3811
+ /* @__PURE__ */ (0, import_jsx_runtime16.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" }),
3812
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("path", { d: "m14 7 3 3" })
3668
3813
  ] }),
3669
3814
  "Generative Inpainting"
3670
3815
  ] }),
3671
- isInpainting && /* @__PURE__ */ (0, import_jsx_runtime14.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..." })
3816
+ isInpainting && /* @__PURE__ */ (0, import_jsx_runtime16.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..." })
3672
3817
  ] }),
3673
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
3674
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-1", children: [
3675
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
3676
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3818
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
3819
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-1", children: [
3820
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
3821
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3677
3822
  "textarea",
3678
3823
  {
3679
3824
  id: "ai-inpaint-prompt-react",
@@ -3685,10 +3830,10 @@ var ImageEditor = ({
3685
3830
  }
3686
3831
  )
3687
3832
  ] }),
3688
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-col gap-1", children: [
3689
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
3690
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
3691
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3833
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex flex-col gap-1", children: [
3834
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
3835
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
3836
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3692
3837
  "button",
3693
3838
  {
3694
3839
  type: "button",
@@ -3701,7 +3846,7 @@ var ImageEditor = ({
3701
3846
  ]
3702
3847
  }
3703
3848
  ),
3704
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
3849
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
3705
3850
  "button",
3706
3851
  {
3707
3852
  type: "button",
@@ -3716,25 +3861,25 @@ var ImageEditor = ({
3716
3861
  )
3717
3862
  ] })
3718
3863
  ] }),
3719
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
3864
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
3720
3865
  "button",
3721
3866
  {
3722
3867
  type: "button",
3723
3868
  onClick: handleInpaint,
3724
3869
  disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
3725
3870
  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",
3726
- children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3727
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3871
+ children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3872
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
3728
3873
  "Generating Inpaint..."
3729
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
3730
- /* @__PURE__ */ (0, import_jsx_runtime14.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_runtime14.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" }) }),
3874
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
3875
+ /* @__PURE__ */ (0, import_jsx_runtime16.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_runtime16.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" }) }),
3731
3876
  "Apply Inpainting"
3732
3877
  ] })
3733
3878
  }
3734
3879
  )
3735
3880
  ] }),
3736
- aiError && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
3737
- aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
3881
+ aiError && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
3882
+ aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
3738
3883
  ] })
3739
3884
  ] })
3740
3885
  ] })
@@ -3754,6 +3899,7 @@ var ImageEditor = ({
3754
3899
  ImageEditor,
3755
3900
  LayerEffectsPanel,
3756
3901
  LayersPanel,
3902
+ PaintGradientEditor,
3757
3903
  RefineEdgePanel,
3758
3904
  SelectionOptionsBar,
3759
3905
  ShapeOptionsBar,