@pixerate/editor-react 0.15.0 → 0.16.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/README.md +4 -0
- package/dist/canvas/index.cjs +219 -118
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +59 -3
- package/dist/canvas/index.d.ts +59 -3
- package/dist/canvas/index.js +103 -0
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-7SPRQZ6H.js +216 -0
- package/dist/chunk-7SPRQZ6H.js.map +1 -0
- package/dist/{chunk-QVQYYHJ5.js → chunk-FYIPXHAE.js} +21 -13
- package/dist/chunk-FYIPXHAE.js.map +1 -0
- package/dist/{chunk-LPFZMZ3L.js → chunk-XTFR3IMK.js} +676 -322
- package/dist/chunk-XTFR3IMK.js.map +1 -0
- package/dist/chunk-XWFU2CSG.js +167 -0
- package/dist/chunk-XWFU2CSG.js.map +1 -0
- package/dist/generation/index.cjs +235 -0
- package/dist/generation/index.cjs.map +1 -0
- package/dist/generation/index.d.cts +60 -0
- package/dist/generation/index.d.ts +60 -0
- package/dist/generation/index.js +13 -0
- package/dist/generation/index.js.map +1 -0
- package/dist/image-editor/index.cjs +684 -336
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +60 -2
- package/dist/image-editor/index.d.ts +60 -2
- package/dist/image-editor/index.js +13 -3
- package/dist/index.cjs +1881 -648
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +143 -4
- package/dist/index.d.ts +143 -4
- package/dist/index.js +626 -73
- package/dist/index.js.map +1 -1
- package/dist/persistence/index.cjs +191 -0
- package/dist/persistence/index.cjs.map +1 -0
- package/dist/persistence/index.d.cts +77 -0
- package/dist/persistence/index.d.ts +77 -0
- package/dist/persistence/index.js +9 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/spreadsheet/index.cjs +17 -10
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +2 -0
- package/dist/spreadsheet/index.d.ts +2 -0
- package/dist/spreadsheet/index.js +1 -1
- package/package.json +18 -2
- package/dist/chunk-LPFZMZ3L.js.map +0 -1
- package/dist/chunk-QVQYYHJ5.js.map +0 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,13 +17,26 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/image-editor/index.ts
|
|
21
31
|
var image_editor_exports = {};
|
|
22
32
|
__export(image_editor_exports, {
|
|
33
|
+
AdjustmentLayersPanel: () => AdjustmentLayersPanel,
|
|
34
|
+
ControlSlider: () => ControlSlider,
|
|
35
|
+
CurvesEditor: () => CurvesEditor,
|
|
36
|
+
Histogram: () => Histogram,
|
|
23
37
|
ImageEditor: () => ImageEditor,
|
|
24
|
-
useImageEditor: () => useImageEditor
|
|
38
|
+
useImageEditor: () => useImageEditor,
|
|
39
|
+
useImageHistogram: () => useImageHistogram
|
|
25
40
|
});
|
|
26
41
|
module.exports = __toCommonJS(image_editor_exports);
|
|
27
42
|
|
|
@@ -36,6 +51,8 @@ function useImageEditor(options = {}) {
|
|
|
36
51
|
const controller = controllerRef.current;
|
|
37
52
|
const [state, setState] = (0, import_react.useState)(() => controller.getState());
|
|
38
53
|
const [historyTicks, setHistoryTicks] = (0, import_react.useState)(0);
|
|
54
|
+
const [histogram, setHistogram] = (0, import_react.useState)(() => controller.getHistogram());
|
|
55
|
+
(0, import_react.useEffect)(() => controller.subscribeHistogram(setHistogram), [controller]);
|
|
39
56
|
(0, import_react.useEffect)(() => {
|
|
40
57
|
const unsub = controller.subscribe((next) => {
|
|
41
58
|
setState(next);
|
|
@@ -68,6 +85,20 @@ function useImageEditor(options = {}) {
|
|
|
68
85
|
);
|
|
69
86
|
const resetAdjustments = (0, import_react.useCallback)(() => controller.resetAdjustments(), [controller]);
|
|
70
87
|
const upgradeProcess = (0, import_react.useCallback)(() => controller.upgradeProcess(), [controller]);
|
|
88
|
+
const addAdjustmentLayer = (0, import_react.useCallback)(
|
|
89
|
+
(init, index) => controller.addAdjustmentLayer(init, index),
|
|
90
|
+
[controller]
|
|
91
|
+
);
|
|
92
|
+
const updateAdjustmentLayer = (0, import_react.useCallback)(
|
|
93
|
+
(id, update, commitToHistory = true) => controller.updateAdjustmentLayer(id, update, commitToHistory),
|
|
94
|
+
[controller]
|
|
95
|
+
);
|
|
96
|
+
const removeAdjustmentLayer = (0, import_react.useCallback)((id) => controller.removeAdjustmentLayer(id), [controller]);
|
|
97
|
+
const moveAdjustmentLayer = (0, import_react.useCallback)((id, to) => controller.moveAdjustmentLayer(id, to), [controller]);
|
|
98
|
+
const toggleAdjustmentLayer = (0, import_react.useCallback)(
|
|
99
|
+
(id, enabled) => controller.toggleAdjustmentLayer(id, enabled),
|
|
100
|
+
[controller]
|
|
101
|
+
);
|
|
71
102
|
const setDepthMask = (0, import_react.useCallback)((partial) => controller.setDepthMask(partial), [controller]);
|
|
72
103
|
const resetDepthMask = (0, import_react.useCallback)(() => controller.resetDepthMask(), [controller]);
|
|
73
104
|
const addAnnotation = (0, import_react.useCallback)((ann) => controller.addAnnotation(ann), [controller]);
|
|
@@ -129,6 +160,12 @@ function useImageEditor(options = {}) {
|
|
|
129
160
|
setAdjustments,
|
|
130
161
|
resetAdjustments,
|
|
131
162
|
upgradeProcess,
|
|
163
|
+
addAdjustmentLayer,
|
|
164
|
+
updateAdjustmentLayer,
|
|
165
|
+
removeAdjustmentLayer,
|
|
166
|
+
moveAdjustmentLayer,
|
|
167
|
+
toggleAdjustmentLayer,
|
|
168
|
+
histogram,
|
|
132
169
|
setDepthMask,
|
|
133
170
|
resetDepthMask,
|
|
134
171
|
addAnnotation,
|
|
@@ -157,14 +194,445 @@ function useImageEditor(options = {}) {
|
|
|
157
194
|
applyBackgroundRemovedImage
|
|
158
195
|
}),
|
|
159
196
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
160
|
-
[controller, state, historyTicks]
|
|
197
|
+
[controller, state, historyTicks, histogram]
|
|
161
198
|
);
|
|
162
199
|
}
|
|
163
200
|
|
|
164
201
|
// src/image-editor/ImageEditor.tsx
|
|
165
|
-
var
|
|
202
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
203
|
+
var import_image_editor6 = require("@pixerate/editor/image-editor");
|
|
204
|
+
|
|
205
|
+
// src/image-editor/ControlSlider.tsx
|
|
166
206
|
var import_image_editor2 = require("@pixerate/editor/image-editor");
|
|
167
207
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
208
|
+
var ControlSlider = ({ spec, value, onChange, disabled, label }) => {
|
|
209
|
+
const name = label ?? spec.label;
|
|
210
|
+
const track = (0, import_image_editor2.controlTrackBackground)(spec);
|
|
211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "data-control-id": spec.id, children: [
|
|
212
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
213
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: name }),
|
|
214
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-mono", children: (0, import_image_editor2.formatControlValue)(spec, value) })
|
|
215
|
+
] }),
|
|
216
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
217
|
+
"input",
|
|
218
|
+
{
|
|
219
|
+
type: "range",
|
|
220
|
+
min: spec.min,
|
|
221
|
+
max: spec.max,
|
|
222
|
+
step: spec.step,
|
|
223
|
+
"aria-label": name,
|
|
224
|
+
disabled,
|
|
225
|
+
value,
|
|
226
|
+
onChange: (e) => onChange(Number(e.target.value)),
|
|
227
|
+
className: "w-full accent-indigo-500 disabled:opacity-40"
|
|
228
|
+
}
|
|
229
|
+
),
|
|
230
|
+
track && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-0.5 rounded-full opacity-70", style: { background: track } })
|
|
231
|
+
] });
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// src/image-editor/Histogram.tsx
|
|
235
|
+
var import_react2 = require("react");
|
|
236
|
+
var import_image_editor3 = require("@pixerate/editor/image-editor");
|
|
237
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
238
|
+
var FILL = {
|
|
239
|
+
luminance: "rgba(148, 163, 184, 0.45)",
|
|
240
|
+
red: "rgba(239, 68, 68, 0.45)",
|
|
241
|
+
green: "rgba(34, 197, 94, 0.45)",
|
|
242
|
+
blue: "rgba(59, 130, 246, 0.45)"
|
|
243
|
+
};
|
|
244
|
+
var W = 256;
|
|
245
|
+
var Histogram = ({ histogram, channel = "rgb", height = 64, className = "", style }) => {
|
|
246
|
+
const channels = channel === "rgb" ? ["luminance", "red", "green", "blue"] : [channel];
|
|
247
|
+
const paths = (0, import_react2.useMemo)(
|
|
248
|
+
() => histogram && histogram.samples > 0 ? channels.map((c) => ({ c, d: (0, import_image_editor3.histogramPath)(histogram, c, W, height) })) : [],
|
|
249
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
250
|
+
[histogram, channel, height]
|
|
251
|
+
);
|
|
252
|
+
const clipLow = histogram && histogram.samples ? Math.max(...histogram.shadows) / histogram.samples : 0;
|
|
253
|
+
const clipHigh = histogram && histogram.samples ? Math.max(...histogram.highlights) / histogram.samples : 0;
|
|
254
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
255
|
+
"svg",
|
|
256
|
+
{
|
|
257
|
+
viewBox: `0 0 ${W} ${height}`,
|
|
258
|
+
preserveAspectRatio: "none",
|
|
259
|
+
role: "img",
|
|
260
|
+
"aria-label": histogram ? `Histogram of ${histogram.samples} pixels` : "Histogram (no data)",
|
|
261
|
+
"data-testid": "image-editor-histogram",
|
|
262
|
+
className: `w-full rounded bg-slate-950/60 ${className}`,
|
|
263
|
+
style: { height, ...style },
|
|
264
|
+
children: [
|
|
265
|
+
paths.map(({ c, d }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d, fill: FILL[c], stroke: "none" }, c)),
|
|
266
|
+
clipLow > 5e-3 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: 0, y: 0, width: 3, height, fill: "#3b82f6", "data-testid": "histogram-clip-shadows" }),
|
|
267
|
+
clipHigh > 5e-3 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: W - 3, y: 0, width: 3, height, fill: "#ef4444", "data-testid": "histogram-clip-highlights" })
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
);
|
|
271
|
+
};
|
|
272
|
+
function useImageHistogram(controller) {
|
|
273
|
+
const [histogram, setHistogram] = (0, import_react2.useState)(() => controller.getHistogram());
|
|
274
|
+
(0, import_react2.useEffect)(() => controller.subscribeHistogram(setHistogram), [controller]);
|
|
275
|
+
return histogram;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// src/image-editor/AdjustmentLayersPanel.tsx
|
|
279
|
+
var import_react4 = require("react");
|
|
280
|
+
var import_image_editor5 = require("@pixerate/editor/image-editor");
|
|
281
|
+
|
|
282
|
+
// src/image-editor/CurvesEditor.tsx
|
|
283
|
+
var import_react3 = require("react");
|
|
284
|
+
var import_image_editor4 = require("@pixerate/editor/image-editor");
|
|
285
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
286
|
+
var BOX = 256;
|
|
287
|
+
var STROKE = { master: "#e2e8f0", red: "#ef4444", green: "#22c55e", blue: "#3b82f6" };
|
|
288
|
+
var CurvesEditor = ({ points, onChange, histogram, channel = "master", size = 200 }) => {
|
|
289
|
+
const svgRef = (0, import_react3.useRef)(null);
|
|
290
|
+
const [drag, setDrag] = (0, import_react3.useState)(null);
|
|
291
|
+
const toBox = (e) => {
|
|
292
|
+
const rect = svgRef.current?.getBoundingClientRect();
|
|
293
|
+
if (!rect || !rect.width || !rect.height) return { x: 0, y: 0 };
|
|
294
|
+
return { x: (e.clientX - rect.left) / rect.width * BOX, y: (e.clientY - rect.top) / rect.height * BOX };
|
|
295
|
+
};
|
|
296
|
+
const onPointerDown = (e) => {
|
|
297
|
+
const { x, y } = toBox(e);
|
|
298
|
+
let index = (0, import_image_editor4.hitTestCurvePoint)(points, x, y, BOX, BOX, 10);
|
|
299
|
+
if (index === -1) {
|
|
300
|
+
const inserted = (0, import_image_editor4.insertCurvePoint)(points, (0, import_image_editor4.boxToCurvePoint)(x, y, BOX, BOX));
|
|
301
|
+
onChange(inserted.points, true);
|
|
302
|
+
index = inserted.index;
|
|
303
|
+
} else {
|
|
304
|
+
onChange(points, true);
|
|
305
|
+
}
|
|
306
|
+
setDrag(index);
|
|
307
|
+
e.target.setPointerCapture?.(e.pointerId);
|
|
308
|
+
};
|
|
309
|
+
const onPointerMove = (e) => {
|
|
310
|
+
if (drag === null) return;
|
|
311
|
+
onChange((0, import_image_editor4.moveCurvePoint)(points, drag, (0, import_image_editor4.boxToCurvePoint)(toBox(e).x, toBox(e).y, BOX, BOX)), false);
|
|
312
|
+
};
|
|
313
|
+
const onDoubleClick = (e) => {
|
|
314
|
+
const { x, y } = toBox(e);
|
|
315
|
+
const index = (0, import_image_editor4.hitTestCurvePoint)(points, x, y, BOX, BOX, 10);
|
|
316
|
+
if (index !== -1 && points.length > 2) onChange((0, import_image_editor4.removeCurvePoint)(points, index), true);
|
|
317
|
+
};
|
|
318
|
+
const histChannel = channel === "master" ? "luminance" : channel;
|
|
319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
320
|
+
"svg",
|
|
321
|
+
{
|
|
322
|
+
ref: svgRef,
|
|
323
|
+
viewBox: `0 0 ${BOX} ${BOX}`,
|
|
324
|
+
width: size,
|
|
325
|
+
height: size,
|
|
326
|
+
role: "application",
|
|
327
|
+
"aria-label": `${channel} curve`,
|
|
328
|
+
"data-testid": "curves-editor",
|
|
329
|
+
className: "rounded bg-slate-950/70 touch-none select-none cursor-crosshair",
|
|
330
|
+
onPointerDown,
|
|
331
|
+
onPointerMove,
|
|
332
|
+
onPointerUp: () => setDrag(null),
|
|
333
|
+
onPointerCancel: () => setDrag(null),
|
|
334
|
+
onDoubleClick,
|
|
335
|
+
children: [
|
|
336
|
+
histogram && histogram.samples > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: (0, import_image_editor4.histogramPath)(histogram, histChannel, BOX, BOX), fill: "rgba(148, 163, 184, 0.25)" }),
|
|
337
|
+
[64, 128, 192].map((v) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { stroke: "rgba(148, 163, 184, 0.2)", strokeWidth: 1, children: [
|
|
338
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: v, y1: 0, x2: v, y2: BOX }),
|
|
339
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: 0, y1: v, x2: BOX, y2: v })
|
|
340
|
+
] }, v)),
|
|
341
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: 0, y1: BOX, x2: BOX, y2: 0, stroke: "rgba(148, 163, 184, 0.35)", strokeDasharray: "4 4" }),
|
|
342
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: (0, import_image_editor4.curveSvgPath)(points, BOX, BOX), fill: "none", stroke: STROKE[channel], strokeWidth: 2 }),
|
|
343
|
+
points.map((p, i) => {
|
|
344
|
+
const b = (0, import_image_editor4.curvePointToBox)(p, BOX, BOX);
|
|
345
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
346
|
+
"circle",
|
|
347
|
+
{
|
|
348
|
+
cx: b.x,
|
|
349
|
+
cy: b.y,
|
|
350
|
+
r: 5,
|
|
351
|
+
fill: drag === i ? STROKE[channel] : "#0f172a",
|
|
352
|
+
stroke: STROKE[channel],
|
|
353
|
+
strokeWidth: 2,
|
|
354
|
+
"aria-label": `Point ${p.input} to ${p.output}`
|
|
355
|
+
},
|
|
356
|
+
i
|
|
357
|
+
);
|
|
358
|
+
})
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
);
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
// src/image-editor/AdjustmentLayersPanel.tsx
|
|
365
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
366
|
+
var CHANNELS = [
|
|
367
|
+
{ id: "master", label: "RGB" },
|
|
368
|
+
{ id: "red", label: "Red" },
|
|
369
|
+
{ id: "green", label: "Green" },
|
|
370
|
+
{ id: "blue", label: "Blue" }
|
|
371
|
+
];
|
|
372
|
+
var TONES = [
|
|
373
|
+
{ id: "shadows", label: "Shadows" },
|
|
374
|
+
{ id: "midtones", label: "Midtones" },
|
|
375
|
+
{ id: "highlights", label: "Highlights" }
|
|
376
|
+
];
|
|
377
|
+
var selectClass = "bg-slate-800 border border-slate-700 rounded px-1.5 py-1 text-slate-200";
|
|
378
|
+
var chipClass = (on) => `px-2 py-0.5 rounded text-[10px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-400 hover:text-slate-200"}`;
|
|
379
|
+
var HueRangeStrip = ({ bounds }) => {
|
|
380
|
+
const pts = Array.from({ length: 73 }, (_, i) => `${i / 72 * 360},${20 - (0, import_image_editor5.hueRangeWeight)({ bounds }, i * 5) * 18}`).join(" ");
|
|
381
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { viewBox: "0 0 360 20", preserveAspectRatio: "none", className: "w-full h-4 rounded", "data-testid": "hue-range-strip", children: [
|
|
382
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("linearGradient", { id: "pixerate-hue-strip", children: [0, 60, 120, 180, 240, 300, 360].map((h) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("stop", { offset: `${h / 360 * 100}%`, stopColor: `hsl(${h}, 90%, 50%)` }, h)) }) }),
|
|
383
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { width: 360, height: 20, fill: "url(#pixerate-hue-strip)", opacity: 0.6 }),
|
|
384
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polyline", { points: pts, fill: "none", stroke: "#fff", strokeWidth: 1.5 })
|
|
385
|
+
] });
|
|
386
|
+
};
|
|
387
|
+
var AdjustmentLayersPanel = ({ controller, layers: layersProp, histogram }) => {
|
|
388
|
+
const follow = layersProp === void 0;
|
|
389
|
+
const [, setTick] = (0, import_react4.useState)(0);
|
|
390
|
+
(0, import_react4.useEffect)(() => follow ? controller.subscribe(() => setTick((n) => n + 1)) : void 0, [controller, follow]);
|
|
391
|
+
const layers = layersProp ?? controller.getAdjustmentLayers();
|
|
392
|
+
const [newKind, setNewKind] = (0, import_react4.useState)("curves");
|
|
393
|
+
const [selectedId, setSelectedId] = (0, import_react4.useState)(null);
|
|
394
|
+
const [channel, setChannel] = (0, import_react4.useState)("master");
|
|
395
|
+
const [range, setRange] = (0, import_react4.useState)(-1);
|
|
396
|
+
const [tone, setTone] = (0, import_react4.useState)("midtones");
|
|
397
|
+
const selected = layers.find((l) => l.id === selectedId) ?? null;
|
|
398
|
+
const topFirst = [...layers].reverse();
|
|
399
|
+
const setParam = (layer, path, value, commit = true) => controller.updateAdjustmentLayer(layer.id, { params: (0, import_image_editor5.setControlPath)(layer.params, path, value) }, commit);
|
|
400
|
+
const slider = (layer, spec, label) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
401
|
+
ControlSlider,
|
|
402
|
+
{
|
|
403
|
+
spec,
|
|
404
|
+
label,
|
|
405
|
+
value: Number((0, import_image_editor5.getControlPath)(layer.params, spec.id) ?? spec.default),
|
|
406
|
+
onChange: (v) => setParam(layer, spec.id, v)
|
|
407
|
+
},
|
|
408
|
+
spec.id
|
|
409
|
+
);
|
|
410
|
+
const controlsOf = (layer, filter = () => true) => import_image_editor5.ADJUSTMENT_LAYER_CONTROLS[layer.kind].filter(filter);
|
|
411
|
+
const checkbox = (layer, path, label) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
412
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
413
|
+
"input",
|
|
414
|
+
{
|
|
415
|
+
type: "checkbox",
|
|
416
|
+
checked: Boolean((0, import_image_editor5.getControlPath)(layer.params, path)),
|
|
417
|
+
onChange: (e) => setParam(layer, path, e.target.checked),
|
|
418
|
+
className: "accent-indigo-500"
|
|
419
|
+
}
|
|
420
|
+
),
|
|
421
|
+
label
|
|
422
|
+
] });
|
|
423
|
+
const editor = (layer) => {
|
|
424
|
+
switch (layer.kind) {
|
|
425
|
+
case "curves":
|
|
426
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
427
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Curve channel", children: CHANNELS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: chipClass(channel === c.id), onClick: () => setChannel(c.id), children: c.label }, c.id)) }),
|
|
428
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
429
|
+
CurvesEditor,
|
|
430
|
+
{
|
|
431
|
+
points: layer.params[channel],
|
|
432
|
+
channel,
|
|
433
|
+
histogram,
|
|
434
|
+
onChange: (points, commit) => setParam(layer, channel, points, commit)
|
|
435
|
+
}
|
|
436
|
+
)
|
|
437
|
+
] });
|
|
438
|
+
case "levels":
|
|
439
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
440
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Levels channel", children: CHANNELS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: chipClass(channel === c.id), onClick: () => setChannel(c.id), children: c.label }, c.id)) }),
|
|
441
|
+
controlsOf(layer, (s) => s.id.startsWith(`${channel}.`)).map((s) => slider(layer, s))
|
|
442
|
+
] });
|
|
443
|
+
case "hueSaturation":
|
|
444
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
445
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-wrap gap-1", role: "group", "aria-label": "Hue range", children: [
|
|
446
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: chipClass(range === -1), onClick: () => setRange(-1), children: "Master" }),
|
|
447
|
+
import_image_editor5.HUE_RANGE_LABELS.map((name, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: chipClass(range === i), onClick: () => setRange(i), disabled: layer.params.colorize, children: name }, name))
|
|
448
|
+
] }),
|
|
449
|
+
range >= 0 && !layer.params.colorize && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HueRangeStrip, { bounds: layer.params.ranges[range].bounds }),
|
|
450
|
+
controlsOf(layer, (s) => range === -1 || layer.params.colorize ? !s.id.startsWith("ranges.") : s.id.startsWith(`ranges.${range}.`)).map(
|
|
451
|
+
(s) => slider(layer, s)
|
|
452
|
+
),
|
|
453
|
+
range === -1 && checkbox(layer, "colorize", "Colorize")
|
|
454
|
+
] });
|
|
455
|
+
case "colorBalance":
|
|
456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
457
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Tone", children: TONES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: chipClass(tone === t.id), onClick: () => setTone(t.id), children: t.label }, t.id)) }),
|
|
458
|
+
controlsOf(layer, (s) => s.id.startsWith(`${tone}.`)).map((s) => slider(layer, s)),
|
|
459
|
+
checkbox(layer, "preserveLuminosity", "Preserve luminosity")
|
|
460
|
+
] });
|
|
461
|
+
case "blackWhite":
|
|
462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
463
|
+
controlsOf(layer).map((s) => slider(layer, s)),
|
|
464
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
465
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
466
|
+
"input",
|
|
467
|
+
{
|
|
468
|
+
type: "checkbox",
|
|
469
|
+
checked: layer.params.tint !== null,
|
|
470
|
+
onChange: (e) => setParam(layer, "tint", e.target.checked ? "#e1d3b3" : null),
|
|
471
|
+
className: "accent-indigo-500"
|
|
472
|
+
}
|
|
473
|
+
),
|
|
474
|
+
"Tint",
|
|
475
|
+
layer.params.tint && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
476
|
+
"input",
|
|
477
|
+
{
|
|
478
|
+
type: "color",
|
|
479
|
+
"aria-label": "Tint colour",
|
|
480
|
+
value: layer.params.tint,
|
|
481
|
+
onChange: (e) => setParam(layer, "tint", e.target.value),
|
|
482
|
+
className: "h-5 w-8 bg-transparent"
|
|
483
|
+
}
|
|
484
|
+
)
|
|
485
|
+
] })
|
|
486
|
+
] });
|
|
487
|
+
case "photoFilter":
|
|
488
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
489
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
490
|
+
"Filter colour",
|
|
491
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
492
|
+
"input",
|
|
493
|
+
{
|
|
494
|
+
type: "color",
|
|
495
|
+
"aria-label": "Filter colour",
|
|
496
|
+
value: layer.params.color,
|
|
497
|
+
onChange: (e) => setParam(layer, "color", e.target.value),
|
|
498
|
+
className: "h-5 w-8 bg-transparent"
|
|
499
|
+
}
|
|
500
|
+
)
|
|
501
|
+
] }),
|
|
502
|
+
controlsOf(layer).map((s) => slider(layer, s)),
|
|
503
|
+
checkbox(layer, "preserveLuminosity", "Preserve luminosity")
|
|
504
|
+
] });
|
|
505
|
+
case "invert":
|
|
506
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-slate-500 text-[11px]", children: "Invert has no settings." });
|
|
507
|
+
default:
|
|
508
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex flex-col gap-2", children: controlsOf(layer).map((s) => slider(layer, s)) });
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-col gap-2 text-xs", "data-testid": "adjustment-layers-panel", children: [
|
|
512
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Adjustment Layers" }) }),
|
|
513
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex gap-1.5", children: [
|
|
514
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
515
|
+
"select",
|
|
516
|
+
{
|
|
517
|
+
"aria-label": "New adjustment layer kind",
|
|
518
|
+
className: `${selectClass} flex-1`,
|
|
519
|
+
value: newKind,
|
|
520
|
+
onChange: (e) => setNewKind(e.target.value),
|
|
521
|
+
children: import_image_editor5.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: k.kind, children: k.label }, k.kind))
|
|
522
|
+
}
|
|
523
|
+
),
|
|
524
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
525
|
+
"button",
|
|
526
|
+
{
|
|
527
|
+
type: "button",
|
|
528
|
+
className: "px-2 py-1 rounded bg-indigo-600 text-white hover:bg-indigo-500",
|
|
529
|
+
onClick: () => {
|
|
530
|
+
setSelectedId(controller.addAdjustmentLayer(newKind));
|
|
531
|
+
setChannel("master");
|
|
532
|
+
setRange(-1);
|
|
533
|
+
},
|
|
534
|
+
children: "Add Layer"
|
|
535
|
+
}
|
|
536
|
+
)
|
|
537
|
+
] }),
|
|
538
|
+
topFirst.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "flex flex-col gap-1", "aria-label": "Adjustment layers", children: topFirst.map((layer) => {
|
|
539
|
+
const index = layers.indexOf(layer);
|
|
540
|
+
const label = layer.name || (0, import_image_editor5.adjustmentKindLabel)(layer.kind);
|
|
541
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
542
|
+
"li",
|
|
543
|
+
{
|
|
544
|
+
className: `flex items-center gap-1.5 rounded px-1.5 py-1 ${layer.id === selectedId ? "bg-indigo-600/20 ring-1 ring-indigo-500/50" : "bg-slate-800/60"}`,
|
|
545
|
+
children: [
|
|
546
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
547
|
+
"input",
|
|
548
|
+
{
|
|
549
|
+
type: "checkbox",
|
|
550
|
+
"aria-label": `Show ${label}`,
|
|
551
|
+
checked: layer.enabled,
|
|
552
|
+
onChange: () => controller.toggleAdjustmentLayer(layer.id),
|
|
553
|
+
className: "accent-indigo-500"
|
|
554
|
+
}
|
|
555
|
+
),
|
|
556
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
557
|
+
"button",
|
|
558
|
+
{
|
|
559
|
+
type: "button",
|
|
560
|
+
className: `flex-1 text-left truncate ${layer.enabled ? "text-slate-200" : "text-slate-500 line-through"}`,
|
|
561
|
+
onClick: () => setSelectedId(layer.id === selectedId ? null : layer.id),
|
|
562
|
+
"aria-pressed": layer.id === selectedId,
|
|
563
|
+
children: label
|
|
564
|
+
}
|
|
565
|
+
),
|
|
566
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
567
|
+
"button",
|
|
568
|
+
{
|
|
569
|
+
type: "button",
|
|
570
|
+
"aria-label": `Move ${label} up`,
|
|
571
|
+
disabled: index === layers.length - 1,
|
|
572
|
+
onClick: () => controller.moveAdjustmentLayer(layer.id, index + 1),
|
|
573
|
+
className: "px-1 text-slate-400 hover:text-slate-200 disabled:opacity-30",
|
|
574
|
+
children: "\u2191"
|
|
575
|
+
}
|
|
576
|
+
),
|
|
577
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
578
|
+
"button",
|
|
579
|
+
{
|
|
580
|
+
type: "button",
|
|
581
|
+
"aria-label": `Move ${label} down`,
|
|
582
|
+
disabled: index === 0,
|
|
583
|
+
onClick: () => controller.moveAdjustmentLayer(layer.id, index - 1),
|
|
584
|
+
className: "px-1 text-slate-400 hover:text-slate-200 disabled:opacity-30",
|
|
585
|
+
children: "\u2193"
|
|
586
|
+
}
|
|
587
|
+
),
|
|
588
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
589
|
+
"button",
|
|
590
|
+
{
|
|
591
|
+
type: "button",
|
|
592
|
+
"aria-label": `Remove ${label}`,
|
|
593
|
+
onClick: () => {
|
|
594
|
+
controller.removeAdjustmentLayer(layer.id);
|
|
595
|
+
if (selectedId === layer.id) setSelectedId(null);
|
|
596
|
+
},
|
|
597
|
+
className: "px-1 text-rose-400 hover:text-rose-300",
|
|
598
|
+
children: "\u2715"
|
|
599
|
+
}
|
|
600
|
+
)
|
|
601
|
+
]
|
|
602
|
+
},
|
|
603
|
+
layer.id
|
|
604
|
+
);
|
|
605
|
+
}) }),
|
|
606
|
+
selected && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-col gap-2 rounded border border-slate-700/60 p-2", "data-testid": "adjustment-layer-editor", children: [
|
|
607
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
608
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-slate-400", children: "Blend" }),
|
|
609
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
610
|
+
"select",
|
|
611
|
+
{
|
|
612
|
+
"aria-label": "Blend mode",
|
|
613
|
+
className: `${selectClass} flex-1`,
|
|
614
|
+
value: selected.blend,
|
|
615
|
+
onChange: (e) => controller.updateAdjustmentLayer(selected.id, { blend: e.target.value }),
|
|
616
|
+
children: import_image_editor5.BLEND_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: m.id, children: m.label }, m.id))
|
|
617
|
+
}
|
|
618
|
+
)
|
|
619
|
+
] }),
|
|
620
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
621
|
+
ControlSlider,
|
|
622
|
+
{
|
|
623
|
+
spec: import_image_editor5.ADJUSTMENT_LAYER_OPACITY_CONTROL,
|
|
624
|
+
label: "Layer opacity",
|
|
625
|
+
value: selected.opacity,
|
|
626
|
+
onChange: (v) => controller.updateAdjustmentLayer(selected.id, { opacity: v })
|
|
627
|
+
}
|
|
628
|
+
),
|
|
629
|
+
editor(selected)
|
|
630
|
+
] })
|
|
631
|
+
] });
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
// src/image-editor/ImageEditor.tsx
|
|
635
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
168
636
|
var ImageEditor = ({
|
|
169
637
|
editor: externalEditor,
|
|
170
638
|
src,
|
|
@@ -179,17 +647,17 @@ var ImageEditor = ({
|
|
|
179
647
|
const internalEditor = useImageEditor({ image: src });
|
|
180
648
|
const editor = externalEditor || internalEditor;
|
|
181
649
|
const { state, controller } = editor;
|
|
182
|
-
const legacyProcess = (0,
|
|
183
|
-
const canvasRef = (0,
|
|
184
|
-
const containerRef = (0,
|
|
185
|
-
const [activeTab, setActiveTab] = (0,
|
|
186
|
-
const [activeCropRatio, setActiveCropRatio] = (0,
|
|
187
|
-
const [inpaintPrompt, setInpaintPrompt] = (0,
|
|
188
|
-
const [inpaintMaskMode, setInpaintMaskMode] = (0,
|
|
189
|
-
const [isRemovingBg, setIsRemovingBg] = (0,
|
|
190
|
-
const [isInpainting, setIsInpainting] = (0,
|
|
191
|
-
const [aiError, setAiError] = (0,
|
|
192
|
-
const [aiSuccess, setAiSuccess] = (0,
|
|
650
|
+
const legacyProcess = (0, import_image_editor6.normalizeProcessVersion)(state.adjustments.process) < import_image_editor6.LATEST_PROCESS_VERSION;
|
|
651
|
+
const canvasRef = (0, import_react5.useRef)(null);
|
|
652
|
+
const containerRef = (0, import_react5.useRef)(null);
|
|
653
|
+
const [activeTab, setActiveTab] = (0, import_react5.useState)("crop");
|
|
654
|
+
const [activeCropRatio, setActiveCropRatio] = (0, import_react5.useState)(null);
|
|
655
|
+
const [inpaintPrompt, setInpaintPrompt] = (0, import_react5.useState)("");
|
|
656
|
+
const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react5.useState)("annotations");
|
|
657
|
+
const [isRemovingBg, setIsRemovingBg] = (0, import_react5.useState)(false);
|
|
658
|
+
const [isInpainting, setIsInpainting] = (0, import_react5.useState)(false);
|
|
659
|
+
const [aiError, setAiError] = (0, import_react5.useState)(null);
|
|
660
|
+
const [aiSuccess, setAiSuccess] = (0, import_react5.useState)(null);
|
|
193
661
|
const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
|
|
194
662
|
const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
|
|
195
663
|
const handleRemoveBackground = async () => {
|
|
@@ -251,18 +719,18 @@ var ImageEditor = ({
|
|
|
251
719
|
setIsInpainting(false);
|
|
252
720
|
}
|
|
253
721
|
};
|
|
254
|
-
const [activeColor, setActiveColor] = (0,
|
|
255
|
-
const [strokeWidth, setStrokeWidth] = (0,
|
|
256
|
-
const [fontSize, setFontSize] = (0,
|
|
257
|
-
const [textInput, setTextInput] = (0,
|
|
258
|
-
const draftAnnotationRef = (0,
|
|
259
|
-
const draftCropRef = (0,
|
|
260
|
-
const cropDragInfoRef = (0,
|
|
261
|
-
const annotationDragInfoRef = (0,
|
|
262
|
-
const isDrawingRef = (0,
|
|
263
|
-
const currentPathRef = (0,
|
|
264
|
-
const dragStartPointRef = (0,
|
|
265
|
-
const renderCanvas = (0,
|
|
722
|
+
const [activeColor, setActiveColor] = (0, import_react5.useState)("#ef4444");
|
|
723
|
+
const [strokeWidth, setStrokeWidth] = (0, import_react5.useState)(3);
|
|
724
|
+
const [fontSize, setFontSize] = (0, import_react5.useState)(24);
|
|
725
|
+
const [textInput, setTextInput] = (0, import_react5.useState)("");
|
|
726
|
+
const draftAnnotationRef = (0, import_react5.useRef)(null);
|
|
727
|
+
const draftCropRef = (0, import_react5.useRef)(null);
|
|
728
|
+
const cropDragInfoRef = (0, import_react5.useRef)(null);
|
|
729
|
+
const annotationDragInfoRef = (0, import_react5.useRef)(null);
|
|
730
|
+
const isDrawingRef = (0, import_react5.useRef)(false);
|
|
731
|
+
const currentPathRef = (0, import_react5.useRef)([]);
|
|
732
|
+
const dragStartPointRef = (0, import_react5.useRef)(null);
|
|
733
|
+
const renderCanvas = (0, import_react5.useCallback)(
|
|
266
734
|
async (draftAnnotation, draftCrop) => {
|
|
267
735
|
const canvas = canvasRef.current;
|
|
268
736
|
const container = containerRef.current;
|
|
@@ -281,7 +749,7 @@ var ImageEditor = ({
|
|
|
281
749
|
},
|
|
282
750
|
[controller, activeTab]
|
|
283
751
|
);
|
|
284
|
-
(0,
|
|
752
|
+
(0, import_react5.useEffect)(() => {
|
|
285
753
|
const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
|
|
286
754
|
const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
|
|
287
755
|
const animId = raf(() => {
|
|
@@ -289,12 +757,12 @@ var ImageEditor = ({
|
|
|
289
757
|
});
|
|
290
758
|
return () => caf(animId);
|
|
291
759
|
}, [renderCanvas, state]);
|
|
292
|
-
(0,
|
|
760
|
+
(0, import_react5.useEffect)(() => {
|
|
293
761
|
if (activeTab === "crop" && editor.state.activeTool !== "crop") {
|
|
294
762
|
editor.setTool("crop");
|
|
295
763
|
}
|
|
296
764
|
}, [activeTab, editor]);
|
|
297
|
-
(0,
|
|
765
|
+
(0, import_react5.useEffect)(() => {
|
|
298
766
|
const container = containerRef.current;
|
|
299
767
|
if (!container) return;
|
|
300
768
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -331,8 +799,8 @@ var ImageEditor = ({
|
|
|
331
799
|
width: state.imageDimensions.width,
|
|
332
800
|
height: state.imageDimensions.height
|
|
333
801
|
};
|
|
334
|
-
const handle = (0,
|
|
335
|
-
const startImgPt = (0,
|
|
802
|
+
const handle = (0, import_image_editor6.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
803
|
+
const startImgPt = (0, import_image_editor6.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
336
804
|
if (handle) {
|
|
337
805
|
cropDragInfoRef.current = {
|
|
338
806
|
handle,
|
|
@@ -351,12 +819,12 @@ var ImageEditor = ({
|
|
|
351
819
|
return;
|
|
352
820
|
}
|
|
353
821
|
if (activeTab === "annotate") {
|
|
354
|
-
const imgPt = (0,
|
|
822
|
+
const imgPt = (0, import_image_editor6.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
355
823
|
dragStartPointRef.current = imgPt;
|
|
356
824
|
if (state.activeTool === "select") {
|
|
357
825
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
358
826
|
const ann = state.annotations[i];
|
|
359
|
-
if ((0,
|
|
827
|
+
if ((0, import_image_editor6.hitTestAnnotation)(imgPt, ann)) {
|
|
360
828
|
editor.selectAnnotation(ann.id);
|
|
361
829
|
annotationDragInfoRef.current = {
|
|
362
830
|
annId: ann.id,
|
|
@@ -393,7 +861,7 @@ var ImageEditor = ({
|
|
|
393
861
|
if (activeTab === "crop") {
|
|
394
862
|
const drag = cropDragInfoRef.current;
|
|
395
863
|
if (drag) {
|
|
396
|
-
const currentImgPt = (0,
|
|
864
|
+
const currentImgPt = (0, import_image_editor6.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
397
865
|
let newCrop;
|
|
398
866
|
if (drag.handle === "new") {
|
|
399
867
|
const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
|
|
@@ -407,7 +875,7 @@ var ImageEditor = ({
|
|
|
407
875
|
height: Math.round(Math.max(20, maxY - minY))
|
|
408
876
|
};
|
|
409
877
|
} else {
|
|
410
|
-
newCrop = (0,
|
|
878
|
+
newCrop = (0, import_image_editor6.calculateCropDrag)(
|
|
411
879
|
drag.startCrop,
|
|
412
880
|
drag.handle,
|
|
413
881
|
drag.startImgPt,
|
|
@@ -427,15 +895,15 @@ var ImageEditor = ({
|
|
|
427
895
|
width: state.imageDimensions.width,
|
|
428
896
|
height: state.imageDimensions.height
|
|
429
897
|
};
|
|
430
|
-
const handle = (0,
|
|
431
|
-
canvas.style.cursor = (0,
|
|
898
|
+
const handle = (0, import_image_editor6.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
899
|
+
canvas.style.cursor = (0, import_image_editor6.getCropCursor)(handle, state.transform);
|
|
432
900
|
}
|
|
433
901
|
return;
|
|
434
902
|
}
|
|
435
903
|
if (activeTab === "annotate") {
|
|
436
904
|
if (annotationDragInfoRef.current) {
|
|
437
905
|
const drag = annotationDragInfoRef.current;
|
|
438
|
-
const currentImgPt2 = (0,
|
|
906
|
+
const currentImgPt2 = (0, import_image_editor6.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
439
907
|
const dx = currentImgPt2.x - drag.startImgPt.x;
|
|
440
908
|
const dy = currentImgPt2.y - drag.startImgPt.y;
|
|
441
909
|
editor.updateAnnotation(drag.annId, {
|
|
@@ -447,10 +915,10 @@ var ImageEditor = ({
|
|
|
447
915
|
const startPt = dragStartPointRef.current;
|
|
448
916
|
if (!startPt) {
|
|
449
917
|
if (state.activeTool === "select") {
|
|
450
|
-
const imgPt = (0,
|
|
918
|
+
const imgPt = (0, import_image_editor6.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
451
919
|
let hovered = false;
|
|
452
920
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
453
|
-
if ((0,
|
|
921
|
+
if ((0, import_image_editor6.hitTestAnnotation)(imgPt, state.annotations[i])) {
|
|
454
922
|
hovered = true;
|
|
455
923
|
break;
|
|
456
924
|
}
|
|
@@ -461,7 +929,7 @@ var ImageEditor = ({
|
|
|
461
929
|
}
|
|
462
930
|
return;
|
|
463
931
|
}
|
|
464
|
-
const currentImgPt = (0,
|
|
932
|
+
const currentImgPt = (0, import_image_editor6.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
465
933
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
466
934
|
currentPathRef.current.push(currentImgPt);
|
|
467
935
|
const draft = {
|
|
@@ -556,7 +1024,7 @@ var ImageEditor = ({
|
|
|
556
1024
|
}
|
|
557
1025
|
const startPt = dragStartPointRef.current;
|
|
558
1026
|
if (startPt) {
|
|
559
|
-
const currentImgPt = (0,
|
|
1027
|
+
const currentImgPt = (0, import_image_editor6.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
560
1028
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
561
1029
|
if (currentPathRef.current.length > 1) {
|
|
562
1030
|
editor.addAnnotation({
|
|
@@ -652,15 +1120,15 @@ var ImageEditor = ({
|
|
|
652
1120
|
link.click();
|
|
653
1121
|
}
|
|
654
1122
|
};
|
|
655
|
-
return /* @__PURE__ */ (0,
|
|
1123
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
656
1124
|
"div",
|
|
657
1125
|
{
|
|
658
1126
|
className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
|
|
659
1127
|
style,
|
|
660
1128
|
children: [
|
|
661
|
-
/* @__PURE__ */ (0,
|
|
662
|
-
/* @__PURE__ */ (0,
|
|
663
|
-
/* @__PURE__ */ (0,
|
|
1129
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.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: [
|
|
1130
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
|
|
1131
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
664
1132
|
"button",
|
|
665
1133
|
{
|
|
666
1134
|
type: "button",
|
|
@@ -672,7 +1140,7 @@ var ImageEditor = ({
|
|
|
672
1140
|
children: "Transform & Crop"
|
|
673
1141
|
}
|
|
674
1142
|
),
|
|
675
|
-
/* @__PURE__ */ (0,
|
|
1143
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
676
1144
|
"button",
|
|
677
1145
|
{
|
|
678
1146
|
type: "button",
|
|
@@ -684,7 +1152,7 @@ var ImageEditor = ({
|
|
|
684
1152
|
children: "Adjustments"
|
|
685
1153
|
}
|
|
686
1154
|
),
|
|
687
|
-
/* @__PURE__ */ (0,
|
|
1155
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
688
1156
|
"button",
|
|
689
1157
|
{
|
|
690
1158
|
type: "button",
|
|
@@ -696,7 +1164,7 @@ var ImageEditor = ({
|
|
|
696
1164
|
children: "Annotations"
|
|
697
1165
|
}
|
|
698
1166
|
),
|
|
699
|
-
/* @__PURE__ */ (0,
|
|
1167
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
700
1168
|
"button",
|
|
701
1169
|
{
|
|
702
1170
|
type: "button",
|
|
@@ -708,7 +1176,7 @@ var ImageEditor = ({
|
|
|
708
1176
|
children: "Depth Mask"
|
|
709
1177
|
}
|
|
710
1178
|
),
|
|
711
|
-
/* @__PURE__ */ (0,
|
|
1179
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
712
1180
|
"button",
|
|
713
1181
|
{
|
|
714
1182
|
type: "button",
|
|
@@ -718,14 +1186,14 @@ var ImageEditor = ({
|
|
|
718
1186
|
},
|
|
719
1187
|
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"}`,
|
|
720
1188
|
children: [
|
|
721
|
-
/* @__PURE__ */ (0,
|
|
1189
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.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_runtime5.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" }) }),
|
|
722
1190
|
"AI Tools"
|
|
723
1191
|
]
|
|
724
1192
|
}
|
|
725
1193
|
)
|
|
726
1194
|
] }),
|
|
727
|
-
/* @__PURE__ */ (0,
|
|
728
|
-
/* @__PURE__ */ (0,
|
|
1195
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
1196
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
729
1197
|
"button",
|
|
730
1198
|
{
|
|
731
1199
|
type: "button",
|
|
@@ -736,7 +1204,7 @@ var ImageEditor = ({
|
|
|
736
1204
|
children: "\u21A9"
|
|
737
1205
|
}
|
|
738
1206
|
),
|
|
739
|
-
/* @__PURE__ */ (0,
|
|
1207
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
740
1208
|
"button",
|
|
741
1209
|
{
|
|
742
1210
|
type: "button",
|
|
@@ -747,7 +1215,7 @@ var ImageEditor = ({
|
|
|
747
1215
|
children: "\u21AA"
|
|
748
1216
|
}
|
|
749
1217
|
),
|
|
750
|
-
/* @__PURE__ */ (0,
|
|
1218
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
751
1219
|
"button",
|
|
752
1220
|
{
|
|
753
1221
|
type: "button",
|
|
@@ -756,8 +1224,8 @@ var ImageEditor = ({
|
|
|
756
1224
|
children: "Reset"
|
|
757
1225
|
}
|
|
758
1226
|
),
|
|
759
|
-
/* @__PURE__ */ (0,
|
|
760
|
-
/* @__PURE__ */ (0,
|
|
1227
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
1228
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
761
1229
|
"button",
|
|
762
1230
|
{
|
|
763
1231
|
type: "button",
|
|
@@ -767,11 +1235,11 @@ var ImageEditor = ({
|
|
|
767
1235
|
children: "-"
|
|
768
1236
|
}
|
|
769
1237
|
),
|
|
770
|
-
/* @__PURE__ */ (0,
|
|
1238
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
|
|
771
1239
|
Math.round(state.zoom * 100),
|
|
772
1240
|
"%"
|
|
773
1241
|
] }),
|
|
774
|
-
/* @__PURE__ */ (0,
|
|
1242
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
775
1243
|
"button",
|
|
776
1244
|
{
|
|
777
1245
|
type: "button",
|
|
@@ -781,8 +1249,8 @@ var ImageEditor = ({
|
|
|
781
1249
|
children: "+"
|
|
782
1250
|
}
|
|
783
1251
|
),
|
|
784
|
-
/* @__PURE__ */ (0,
|
|
785
|
-
/* @__PURE__ */ (0,
|
|
1252
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
1253
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
786
1254
|
"button",
|
|
787
1255
|
{
|
|
788
1256
|
type: "button",
|
|
@@ -793,7 +1261,7 @@ var ImageEditor = ({
|
|
|
793
1261
|
children: "Hold Compare"
|
|
794
1262
|
}
|
|
795
1263
|
),
|
|
796
|
-
/* @__PURE__ */ (0,
|
|
1264
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
797
1265
|
"button",
|
|
798
1266
|
{
|
|
799
1267
|
type: "button",
|
|
@@ -804,13 +1272,13 @@ var ImageEditor = ({
|
|
|
804
1272
|
)
|
|
805
1273
|
] })
|
|
806
1274
|
] }),
|
|
807
|
-
/* @__PURE__ */ (0,
|
|
808
|
-
/* @__PURE__ */ (0,
|
|
1275
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
|
|
1276
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
809
1277
|
"div",
|
|
810
1278
|
{
|
|
811
1279
|
ref: containerRef,
|
|
812
1280
|
className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
|
|
813
|
-
children: /* @__PURE__ */ (0,
|
|
1281
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
814
1282
|
"canvas",
|
|
815
1283
|
{
|
|
816
1284
|
ref: canvasRef,
|
|
@@ -823,11 +1291,11 @@ var ImageEditor = ({
|
|
|
823
1291
|
)
|
|
824
1292
|
}
|
|
825
1293
|
),
|
|
826
|
-
/* @__PURE__ */ (0,
|
|
827
|
-
activeTab === "crop" && /* @__PURE__ */ (0,
|
|
828
|
-
/* @__PURE__ */ (0,
|
|
829
|
-
/* @__PURE__ */ (0,
|
|
830
|
-
/* @__PURE__ */ (0,
|
|
1294
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.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: [
|
|
1295
|
+
activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
1296
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
|
|
1297
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
1298
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
831
1299
|
"button",
|
|
832
1300
|
{
|
|
833
1301
|
type: "button",
|
|
@@ -839,7 +1307,7 @@ var ImageEditor = ({
|
|
|
839
1307
|
children: "Freeform"
|
|
840
1308
|
}
|
|
841
1309
|
),
|
|
842
|
-
/* @__PURE__ */ (0,
|
|
1310
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
843
1311
|
"button",
|
|
844
1312
|
{
|
|
845
1313
|
type: "button",
|
|
@@ -851,7 +1319,7 @@ var ImageEditor = ({
|
|
|
851
1319
|
children: "1:1 Square"
|
|
852
1320
|
}
|
|
853
1321
|
),
|
|
854
|
-
/* @__PURE__ */ (0,
|
|
1322
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
855
1323
|
"button",
|
|
856
1324
|
{
|
|
857
1325
|
type: "button",
|
|
@@ -863,7 +1331,7 @@ var ImageEditor = ({
|
|
|
863
1331
|
children: "4:3 Standard"
|
|
864
1332
|
}
|
|
865
1333
|
),
|
|
866
|
-
/* @__PURE__ */ (0,
|
|
1334
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
867
1335
|
"button",
|
|
868
1336
|
{
|
|
869
1337
|
type: "button",
|
|
@@ -875,7 +1343,7 @@ var ImageEditor = ({
|
|
|
875
1343
|
children: "16:9 Wide"
|
|
876
1344
|
}
|
|
877
1345
|
),
|
|
878
|
-
/* @__PURE__ */ (0,
|
|
1346
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
879
1347
|
"button",
|
|
880
1348
|
{
|
|
881
1349
|
type: "button",
|
|
@@ -887,7 +1355,7 @@ var ImageEditor = ({
|
|
|
887
1355
|
children: "3:2 Photo"
|
|
888
1356
|
}
|
|
889
1357
|
),
|
|
890
|
-
/* @__PURE__ */ (0,
|
|
1358
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
891
1359
|
"button",
|
|
892
1360
|
{
|
|
893
1361
|
type: "button",
|
|
@@ -900,10 +1368,10 @@ var ImageEditor = ({
|
|
|
900
1368
|
}
|
|
901
1369
|
)
|
|
902
1370
|
] }),
|
|
903
|
-
/* @__PURE__ */ (0,
|
|
904
|
-
/* @__PURE__ */ (0,
|
|
905
|
-
/* @__PURE__ */ (0,
|
|
906
|
-
/* @__PURE__ */ (0,
|
|
1371
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
1372
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
|
|
1373
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
1374
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
907
1375
|
"button",
|
|
908
1376
|
{
|
|
909
1377
|
type: "button",
|
|
@@ -912,7 +1380,7 @@ var ImageEditor = ({
|
|
|
912
1380
|
children: "Rotate -90\xB0"
|
|
913
1381
|
}
|
|
914
1382
|
),
|
|
915
|
-
/* @__PURE__ */ (0,
|
|
1383
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
916
1384
|
"button",
|
|
917
1385
|
{
|
|
918
1386
|
type: "button",
|
|
@@ -921,7 +1389,7 @@ var ImageEditor = ({
|
|
|
921
1389
|
children: "Rotate +90\xB0"
|
|
922
1390
|
}
|
|
923
1391
|
),
|
|
924
|
-
/* @__PURE__ */ (0,
|
|
1392
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
925
1393
|
"button",
|
|
926
1394
|
{
|
|
927
1395
|
type: "button",
|
|
@@ -930,7 +1398,7 @@ var ImageEditor = ({
|
|
|
930
1398
|
children: "Flip Horizontal"
|
|
931
1399
|
}
|
|
932
1400
|
),
|
|
933
|
-
/* @__PURE__ */ (0,
|
|
1401
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
934
1402
|
"button",
|
|
935
1403
|
{
|
|
936
1404
|
type: "button",
|
|
@@ -941,10 +1409,10 @@ var ImageEditor = ({
|
|
|
941
1409
|
)
|
|
942
1410
|
] })
|
|
943
1411
|
] }),
|
|
944
|
-
activeTab === "adjust" && /* @__PURE__ */ (0,
|
|
945
|
-
/* @__PURE__ */ (0,
|
|
946
|
-
/* @__PURE__ */ (0,
|
|
947
|
-
/* @__PURE__ */ (0,
|
|
1412
|
+
activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
1413
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1414
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
|
|
1415
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
948
1416
|
"button",
|
|
949
1417
|
{
|
|
950
1418
|
type: "button",
|
|
@@ -954,174 +1422,49 @@ var ImageEditor = ({
|
|
|
954
1422
|
}
|
|
955
1423
|
)
|
|
956
1424
|
] }),
|
|
957
|
-
/* @__PURE__ */ (0,
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
] }),
|
|
962
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
963
|
-
"input",
|
|
964
|
-
{
|
|
965
|
-
type: "range",
|
|
966
|
-
min: "-100",
|
|
967
|
-
max: "100",
|
|
968
|
-
value: state.adjustments.brightness,
|
|
969
|
-
onChange: (e) => editor.setAdjustments({ brightness: Number(e.target.value) }),
|
|
970
|
-
className: "w-full accent-indigo-500"
|
|
971
|
-
}
|
|
972
|
-
)
|
|
973
|
-
] }),
|
|
974
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
975
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
976
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Contrast" }),
|
|
977
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-mono", children: state.adjustments.contrast })
|
|
978
|
-
] }),
|
|
979
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
980
|
-
"input",
|
|
981
|
-
{
|
|
982
|
-
type: "range",
|
|
983
|
-
min: "-100",
|
|
984
|
-
max: "100",
|
|
985
|
-
value: state.adjustments.contrast,
|
|
986
|
-
onChange: (e) => editor.setAdjustments({ contrast: Number(e.target.value) }),
|
|
987
|
-
className: "w-full accent-indigo-500"
|
|
988
|
-
}
|
|
989
|
-
)
|
|
990
|
-
] }),
|
|
991
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
992
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
993
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Saturation" }),
|
|
994
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-mono", children: state.adjustments.saturation })
|
|
995
|
-
] }),
|
|
996
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
997
|
-
"input",
|
|
998
|
-
{
|
|
999
|
-
type: "range",
|
|
1000
|
-
min: "-100",
|
|
1001
|
-
max: "100",
|
|
1002
|
-
value: state.adjustments.saturation,
|
|
1003
|
-
onChange: (e) => editor.setAdjustments({ saturation: Number(e.target.value) }),
|
|
1004
|
-
className: "w-full accent-indigo-500"
|
|
1005
|
-
}
|
|
1006
|
-
)
|
|
1007
|
-
] }),
|
|
1008
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1009
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
1010
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Exposure" }),
|
|
1011
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-mono", children: state.adjustments.exposure })
|
|
1012
|
-
] }),
|
|
1013
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1014
|
-
"input",
|
|
1015
|
-
{
|
|
1016
|
-
type: "range",
|
|
1017
|
-
min: "-100",
|
|
1018
|
-
max: "100",
|
|
1019
|
-
value: state.adjustments.exposure,
|
|
1020
|
-
onChange: (e) => editor.setAdjustments({ exposure: Number(e.target.value) }),
|
|
1021
|
-
className: "w-full accent-indigo-500"
|
|
1022
|
-
}
|
|
1023
|
-
)
|
|
1024
|
-
] }),
|
|
1025
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1026
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
1027
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Warmth / Temperature" }),
|
|
1028
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-mono", children: state.adjustments.temperature })
|
|
1029
|
-
] }),
|
|
1030
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1031
|
-
"input",
|
|
1425
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Histogram, { histogram: editor.histogram }),
|
|
1426
|
+
import_image_editor6.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react5.default.Fragment, { children: [
|
|
1427
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1428
|
+
ControlSlider,
|
|
1032
1429
|
{
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
onChange: (e) => editor.setAdjustments({ temperature: Number(e.target.value) }),
|
|
1038
|
-
className: "w-full accent-indigo-500"
|
|
1430
|
+
spec,
|
|
1431
|
+
value: (0, import_image_editor6.readAdjustmentControls)(state.adjustments)[spec.id],
|
|
1432
|
+
disabled: spec.requiresProcess !== void 0 && legacyProcess,
|
|
1433
|
+
onChange: (v) => editor.setAdjustments({ [spec.id]: v })
|
|
1039
1434
|
}
|
|
1040
|
-
)
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
1044
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Tint" }),
|
|
1045
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-mono", children: state.adjustments.tint ?? 0 })
|
|
1046
|
-
] }),
|
|
1047
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1048
|
-
"input",
|
|
1435
|
+
),
|
|
1436
|
+
spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1437
|
+
"div",
|
|
1049
1438
|
{
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1439
|
+
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",
|
|
1440
|
+
"data-testid": "image-editor-process-notice",
|
|
1441
|
+
children: [
|
|
1442
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
|
|
1443
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1444
|
+
"button",
|
|
1445
|
+
{
|
|
1446
|
+
type: "button",
|
|
1447
|
+
onClick: () => editor.upgradeProcess(),
|
|
1448
|
+
className: "shrink-0 rounded bg-amber-500/20 px-2 py-0.5 hover:bg-amber-500/30",
|
|
1449
|
+
children: "Update"
|
|
1450
|
+
}
|
|
1451
|
+
)
|
|
1452
|
+
]
|
|
1058
1453
|
}
|
|
1059
1454
|
)
|
|
1060
|
-
] }),
|
|
1061
|
-
|
|
1062
|
-
|
|
1455
|
+
] }, spec.id)),
|
|
1456
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1457
|
+
AdjustmentLayersPanel,
|
|
1063
1458
|
{
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
|
|
1068
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1069
|
-
"button",
|
|
1070
|
-
{
|
|
1071
|
-
type: "button",
|
|
1072
|
-
onClick: () => editor.upgradeProcess(),
|
|
1073
|
-
className: "shrink-0 rounded bg-amber-500/20 px-2 py-0.5 hover:bg-amber-500/30",
|
|
1074
|
-
children: "Update"
|
|
1075
|
-
}
|
|
1076
|
-
)
|
|
1077
|
-
]
|
|
1459
|
+
controller,
|
|
1460
|
+
layers: state.adjustments.layers,
|
|
1461
|
+
histogram: editor.histogram
|
|
1078
1462
|
}
|
|
1079
|
-
)
|
|
1080
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1081
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
1082
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Blur" }),
|
|
1083
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "font-mono", children: [
|
|
1084
|
-
state.adjustments.blur,
|
|
1085
|
-
"px"
|
|
1086
|
-
] })
|
|
1087
|
-
] }),
|
|
1088
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1089
|
-
"input",
|
|
1090
|
-
{
|
|
1091
|
-
type: "range",
|
|
1092
|
-
min: "0",
|
|
1093
|
-
max: "30",
|
|
1094
|
-
value: state.adjustments.blur,
|
|
1095
|
-
onChange: (e) => editor.setAdjustments({ blur: Number(e.target.value) }),
|
|
1096
|
-
className: "w-full accent-indigo-500"
|
|
1097
|
-
}
|
|
1098
|
-
)
|
|
1099
|
-
] }),
|
|
1100
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1101
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
1102
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Opacity" }),
|
|
1103
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "font-mono", children: [
|
|
1104
|
-
Math.round(state.adjustments.opacity * 100),
|
|
1105
|
-
"%"
|
|
1106
|
-
] })
|
|
1107
|
-
] }),
|
|
1108
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1109
|
-
"input",
|
|
1110
|
-
{
|
|
1111
|
-
type: "range",
|
|
1112
|
-
min: "0",
|
|
1113
|
-
max: "1",
|
|
1114
|
-
step: "0.05",
|
|
1115
|
-
value: state.adjustments.opacity,
|
|
1116
|
-
onChange: (e) => editor.setAdjustments({ opacity: Number(e.target.value) }),
|
|
1117
|
-
className: "w-full accent-indigo-500"
|
|
1118
|
-
}
|
|
1119
|
-
)
|
|
1120
|
-
] })
|
|
1463
|
+
) })
|
|
1121
1464
|
] }),
|
|
1122
|
-
activeTab === "annotate" && /* @__PURE__ */ (0,
|
|
1123
|
-
/* @__PURE__ */ (0,
|
|
1124
|
-
/* @__PURE__ */ (0,
|
|
1465
|
+
activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
1466
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
|
|
1467
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1125
1468
|
"button",
|
|
1126
1469
|
{
|
|
1127
1470
|
type: "button",
|
|
@@ -1131,9 +1474,9 @@ var ImageEditor = ({
|
|
|
1131
1474
|
},
|
|
1132
1475
|
t
|
|
1133
1476
|
)) }),
|
|
1134
|
-
/* @__PURE__ */ (0,
|
|
1135
|
-
/* @__PURE__ */ (0,
|
|
1136
|
-
/* @__PURE__ */ (0,
|
|
1477
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
1478
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("label", { className: "text-slate-400", children: "Color:" }),
|
|
1479
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1137
1480
|
"input",
|
|
1138
1481
|
{
|
|
1139
1482
|
type: "color",
|
|
@@ -1142,15 +1485,15 @@ var ImageEditor = ({
|
|
|
1142
1485
|
className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
|
|
1143
1486
|
}
|
|
1144
1487
|
),
|
|
1145
|
-
/* @__PURE__ */ (0,
|
|
1146
|
-
/* @__PURE__ */ (0,
|
|
1147
|
-
/* @__PURE__ */ (0,
|
|
1148
|
-
/* @__PURE__ */ (0,
|
|
1488
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex-1 ml-2", children: [
|
|
1489
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
|
|
1490
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Width:" }),
|
|
1491
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "font-mono", children: [
|
|
1149
1492
|
strokeWidth,
|
|
1150
1493
|
"px"
|
|
1151
1494
|
] })
|
|
1152
1495
|
] }),
|
|
1153
|
-
/* @__PURE__ */ (0,
|
|
1496
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1154
1497
|
"input",
|
|
1155
1498
|
{
|
|
1156
1499
|
type: "range",
|
|
@@ -1163,10 +1506,10 @@ var ImageEditor = ({
|
|
|
1163
1506
|
)
|
|
1164
1507
|
] })
|
|
1165
1508
|
] }),
|
|
1166
|
-
/* @__PURE__ */ (0,
|
|
1167
|
-
/* @__PURE__ */ (0,
|
|
1168
|
-
/* @__PURE__ */ (0,
|
|
1169
|
-
/* @__PURE__ */ (0,
|
|
1509
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
1510
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
|
|
1511
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex gap-2", children: [
|
|
1512
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1170
1513
|
"input",
|
|
1171
1514
|
{
|
|
1172
1515
|
type: "text",
|
|
@@ -1177,7 +1520,7 @@ var ImageEditor = ({
|
|
|
1177
1520
|
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"
|
|
1178
1521
|
}
|
|
1179
1522
|
),
|
|
1180
|
-
/* @__PURE__ */ (0,
|
|
1523
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1181
1524
|
"button",
|
|
1182
1525
|
{
|
|
1183
1526
|
type: "button",
|
|
@@ -1187,14 +1530,14 @@ var ImageEditor = ({
|
|
|
1187
1530
|
}
|
|
1188
1531
|
)
|
|
1189
1532
|
] }),
|
|
1190
|
-
/* @__PURE__ */ (0,
|
|
1191
|
-
/* @__PURE__ */ (0,
|
|
1192
|
-
/* @__PURE__ */ (0,
|
|
1533
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
|
|
1534
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Font Size:" }),
|
|
1535
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "font-mono", children: [
|
|
1193
1536
|
fontSize,
|
|
1194
1537
|
"px"
|
|
1195
1538
|
] })
|
|
1196
1539
|
] }),
|
|
1197
|
-
/* @__PURE__ */ (0,
|
|
1540
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1198
1541
|
"input",
|
|
1199
1542
|
{
|
|
1200
1543
|
type: "range",
|
|
@@ -1205,14 +1548,14 @@ var ImageEditor = ({
|
|
|
1205
1548
|
className: "w-full accent-indigo-500"
|
|
1206
1549
|
}
|
|
1207
1550
|
),
|
|
1208
|
-
/* @__PURE__ */ (0,
|
|
1209
|
-
/* @__PURE__ */ (0,
|
|
1210
|
-
/* @__PURE__ */ (0,
|
|
1551
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
1552
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1553
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "text-slate-400", children: [
|
|
1211
1554
|
"Layers (",
|
|
1212
1555
|
state.annotations.length,
|
|
1213
1556
|
")"
|
|
1214
1557
|
] }),
|
|
1215
|
-
state.selectedAnnotationId && /* @__PURE__ */ (0,
|
|
1558
|
+
state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1216
1559
|
"button",
|
|
1217
1560
|
{
|
|
1218
1561
|
type: "button",
|
|
@@ -1221,7 +1564,7 @@ var ImageEditor = ({
|
|
|
1221
1564
|
children: "Delete Selected"
|
|
1222
1565
|
}
|
|
1223
1566
|
),
|
|
1224
|
-
state.annotations.length > 0 && /* @__PURE__ */ (0,
|
|
1567
|
+
state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1225
1568
|
"button",
|
|
1226
1569
|
{
|
|
1227
1570
|
type: "button",
|
|
@@ -1232,10 +1575,10 @@ var ImageEditor = ({
|
|
|
1232
1575
|
)
|
|
1233
1576
|
] })
|
|
1234
1577
|
] }),
|
|
1235
|
-
activeTab === "depth" && /* @__PURE__ */ (0,
|
|
1236
|
-
/* @__PURE__ */ (0,
|
|
1237
|
-
/* @__PURE__ */ (0,
|
|
1238
|
-
/* @__PURE__ */ (0,
|
|
1578
|
+
activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
1579
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1580
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
|
|
1581
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1239
1582
|
"button",
|
|
1240
1583
|
{
|
|
1241
1584
|
type: "button",
|
|
@@ -1245,8 +1588,8 @@ var ImageEditor = ({
|
|
|
1245
1588
|
}
|
|
1246
1589
|
)
|
|
1247
1590
|
] }),
|
|
1248
|
-
/* @__PURE__ */ (0,
|
|
1249
|
-
/* @__PURE__ */ (0,
|
|
1591
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
|
|
1592
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1250
1593
|
"input",
|
|
1251
1594
|
{
|
|
1252
1595
|
type: "checkbox",
|
|
@@ -1255,12 +1598,12 @@ var ImageEditor = ({
|
|
|
1255
1598
|
className: "rounded accent-indigo-500"
|
|
1256
1599
|
}
|
|
1257
1600
|
),
|
|
1258
|
-
/* @__PURE__ */ (0,
|
|
1601
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Enable Depth / Alpha Mask" })
|
|
1259
1602
|
] }),
|
|
1260
|
-
state.depthMask.enabled && /* @__PURE__ */ (0,
|
|
1261
|
-
/* @__PURE__ */ (0,
|
|
1262
|
-
/* @__PURE__ */ (0,
|
|
1263
|
-
/* @__PURE__ */ (0,
|
|
1603
|
+
state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1604
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
1605
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
|
|
1606
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1264
1607
|
"input",
|
|
1265
1608
|
{
|
|
1266
1609
|
type: "text",
|
|
@@ -1271,8 +1614,8 @@ var ImageEditor = ({
|
|
|
1271
1614
|
}
|
|
1272
1615
|
)
|
|
1273
1616
|
] }),
|
|
1274
|
-
/* @__PURE__ */ (0,
|
|
1275
|
-
/* @__PURE__ */ (0,
|
|
1617
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex gap-2", children: [
|
|
1618
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1276
1619
|
"button",
|
|
1277
1620
|
{
|
|
1278
1621
|
type: "button",
|
|
@@ -1281,7 +1624,7 @@ var ImageEditor = ({
|
|
|
1281
1624
|
children: "Threshold Mode"
|
|
1282
1625
|
}
|
|
1283
1626
|
),
|
|
1284
|
-
/* @__PURE__ */ (0,
|
|
1627
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1285
1628
|
"button",
|
|
1286
1629
|
{
|
|
1287
1630
|
type: "button",
|
|
@@ -1291,12 +1634,12 @@ var ImageEditor = ({
|
|
|
1291
1634
|
}
|
|
1292
1635
|
)
|
|
1293
1636
|
] }),
|
|
1294
|
-
/* @__PURE__ */ (0,
|
|
1295
|
-
/* @__PURE__ */ (0,
|
|
1296
|
-
/* @__PURE__ */ (0,
|
|
1297
|
-
/* @__PURE__ */ (0,
|
|
1637
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
1638
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
1639
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Depth Start (Lower):" }),
|
|
1640
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
|
|
1298
1641
|
] }),
|
|
1299
|
-
/* @__PURE__ */ (0,
|
|
1642
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1300
1643
|
"input",
|
|
1301
1644
|
{
|
|
1302
1645
|
type: "range",
|
|
@@ -1310,12 +1653,12 @@ var ImageEditor = ({
|
|
|
1310
1653
|
}
|
|
1311
1654
|
)
|
|
1312
1655
|
] }),
|
|
1313
|
-
/* @__PURE__ */ (0,
|
|
1314
|
-
/* @__PURE__ */ (0,
|
|
1315
|
-
/* @__PURE__ */ (0,
|
|
1316
|
-
/* @__PURE__ */ (0,
|
|
1656
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
1657
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
1658
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Depth Stop (Upper):" }),
|
|
1659
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
|
|
1317
1660
|
] }),
|
|
1318
|
-
/* @__PURE__ */ (0,
|
|
1661
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1319
1662
|
"input",
|
|
1320
1663
|
{
|
|
1321
1664
|
type: "range",
|
|
@@ -1329,12 +1672,12 @@ var ImageEditor = ({
|
|
|
1329
1672
|
}
|
|
1330
1673
|
)
|
|
1331
1674
|
] }),
|
|
1332
|
-
/* @__PURE__ */ (0,
|
|
1333
|
-
/* @__PURE__ */ (0,
|
|
1334
|
-
/* @__PURE__ */ (0,
|
|
1335
|
-
/* @__PURE__ */ (0,
|
|
1675
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
1676
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
1677
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Softness:" }),
|
|
1678
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
|
|
1336
1679
|
] }),
|
|
1337
|
-
/* @__PURE__ */ (0,
|
|
1680
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1338
1681
|
"input",
|
|
1339
1682
|
{
|
|
1340
1683
|
type: "range",
|
|
@@ -1346,8 +1689,8 @@ var ImageEditor = ({
|
|
|
1346
1689
|
}
|
|
1347
1690
|
)
|
|
1348
1691
|
] }),
|
|
1349
|
-
/* @__PURE__ */ (0,
|
|
1350
|
-
/* @__PURE__ */ (0,
|
|
1692
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
|
|
1693
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1351
1694
|
"input",
|
|
1352
1695
|
{
|
|
1353
1696
|
type: "checkbox",
|
|
@@ -1356,52 +1699,52 @@ var ImageEditor = ({
|
|
|
1356
1699
|
className: "rounded accent-indigo-500"
|
|
1357
1700
|
}
|
|
1358
1701
|
),
|
|
1359
|
-
/* @__PURE__ */ (0,
|
|
1702
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Invert Mask" })
|
|
1360
1703
|
] })
|
|
1361
1704
|
] })
|
|
1362
1705
|
] }),
|
|
1363
|
-
activeTab === "ai" && /* @__PURE__ */ (0,
|
|
1364
|
-
/* @__PURE__ */ (0,
|
|
1365
|
-
/* @__PURE__ */ (0,
|
|
1366
|
-
/* @__PURE__ */ (0,
|
|
1367
|
-
/* @__PURE__ */ (0,
|
|
1706
|
+
activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
1707
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
1708
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1709
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
1710
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.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_runtime5.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" }) }),
|
|
1368
1711
|
"Background Removal"
|
|
1369
1712
|
] }),
|
|
1370
|
-
isRemovingBg && /* @__PURE__ */ (0,
|
|
1713
|
+
isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime5.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..." })
|
|
1371
1714
|
] }),
|
|
1372
|
-
/* @__PURE__ */ (0,
|
|
1373
|
-
/* @__PURE__ */ (0,
|
|
1715
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
|
|
1716
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1374
1717
|
"button",
|
|
1375
1718
|
{
|
|
1376
1719
|
type: "button",
|
|
1377
1720
|
onClick: handleRemoveBackground,
|
|
1378
1721
|
disabled: isRemovingBg || isInpainting,
|
|
1379
1722
|
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",
|
|
1380
|
-
children: isRemovingBg ? /* @__PURE__ */ (0,
|
|
1381
|
-
/* @__PURE__ */ (0,
|
|
1723
|
+
children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1724
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
1382
1725
|
"Removing Background..."
|
|
1383
|
-
] }) : /* @__PURE__ */ (0,
|
|
1384
|
-
/* @__PURE__ */ (0,
|
|
1726
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1727
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.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_runtime5.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" }) }),
|
|
1385
1728
|
"Remove Background"
|
|
1386
1729
|
] })
|
|
1387
1730
|
}
|
|
1388
1731
|
)
|
|
1389
1732
|
] }),
|
|
1390
|
-
/* @__PURE__ */ (0,
|
|
1391
|
-
/* @__PURE__ */ (0,
|
|
1392
|
-
/* @__PURE__ */ (0,
|
|
1393
|
-
/* @__PURE__ */ (0,
|
|
1394
|
-
/* @__PURE__ */ (0,
|
|
1395
|
-
/* @__PURE__ */ (0,
|
|
1733
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
1734
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1735
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
1736
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
1737
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.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" }),
|
|
1738
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "m14 7 3 3" })
|
|
1396
1739
|
] }),
|
|
1397
1740
|
"Generative Inpainting"
|
|
1398
1741
|
] }),
|
|
1399
|
-
isInpainting && /* @__PURE__ */ (0,
|
|
1742
|
+
isInpainting && /* @__PURE__ */ (0, import_jsx_runtime5.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..." })
|
|
1400
1743
|
] }),
|
|
1401
|
-
/* @__PURE__ */ (0,
|
|
1402
|
-
/* @__PURE__ */ (0,
|
|
1403
|
-
/* @__PURE__ */ (0,
|
|
1404
|
-
/* @__PURE__ */ (0,
|
|
1744
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
|
|
1745
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
1746
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
|
|
1747
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1405
1748
|
"textarea",
|
|
1406
1749
|
{
|
|
1407
1750
|
id: "ai-inpaint-prompt-react",
|
|
@@ -1413,10 +1756,10 @@ var ImageEditor = ({
|
|
|
1413
1756
|
}
|
|
1414
1757
|
)
|
|
1415
1758
|
] }),
|
|
1416
|
-
/* @__PURE__ */ (0,
|
|
1417
|
-
/* @__PURE__ */ (0,
|
|
1418
|
-
/* @__PURE__ */ (0,
|
|
1419
|
-
/* @__PURE__ */ (0,
|
|
1759
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
1760
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
|
|
1761
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
|
|
1762
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1420
1763
|
"button",
|
|
1421
1764
|
{
|
|
1422
1765
|
type: "button",
|
|
@@ -1429,7 +1772,7 @@ var ImageEditor = ({
|
|
|
1429
1772
|
]
|
|
1430
1773
|
}
|
|
1431
1774
|
),
|
|
1432
|
-
/* @__PURE__ */ (0,
|
|
1775
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
1433
1776
|
"button",
|
|
1434
1777
|
{
|
|
1435
1778
|
type: "button",
|
|
@@ -1444,25 +1787,25 @@ var ImageEditor = ({
|
|
|
1444
1787
|
)
|
|
1445
1788
|
] })
|
|
1446
1789
|
] }),
|
|
1447
|
-
/* @__PURE__ */ (0,
|
|
1790
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1448
1791
|
"button",
|
|
1449
1792
|
{
|
|
1450
1793
|
type: "button",
|
|
1451
1794
|
onClick: handleInpaint,
|
|
1452
1795
|
disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
|
|
1453
1796
|
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",
|
|
1454
|
-
children: isInpainting ? /* @__PURE__ */ (0,
|
|
1455
|
-
/* @__PURE__ */ (0,
|
|
1797
|
+
children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1798
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
1456
1799
|
"Generating Inpaint..."
|
|
1457
|
-
] }) : /* @__PURE__ */ (0,
|
|
1458
|
-
/* @__PURE__ */ (0,
|
|
1800
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1801
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.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_runtime5.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" }) }),
|
|
1459
1802
|
"Apply Inpainting"
|
|
1460
1803
|
] })
|
|
1461
1804
|
}
|
|
1462
1805
|
)
|
|
1463
1806
|
] }),
|
|
1464
|
-
aiError && /* @__PURE__ */ (0,
|
|
1465
|
-
aiSuccess && /* @__PURE__ */ (0,
|
|
1807
|
+
aiError && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
|
|
1808
|
+
aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
|
|
1466
1809
|
] })
|
|
1467
1810
|
] })
|
|
1468
1811
|
] })
|
|
@@ -1472,7 +1815,12 @@ var ImageEditor = ({
|
|
|
1472
1815
|
};
|
|
1473
1816
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1474
1817
|
0 && (module.exports = {
|
|
1818
|
+
AdjustmentLayersPanel,
|
|
1819
|
+
ControlSlider,
|
|
1820
|
+
CurvesEditor,
|
|
1821
|
+
Histogram,
|
|
1475
1822
|
ImageEditor,
|
|
1476
|
-
useImageEditor
|
|
1823
|
+
useImageEditor,
|
|
1824
|
+
useImageHistogram
|
|
1477
1825
|
});
|
|
1478
1826
|
//# sourceMappingURL=index.cjs.map
|