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