@pixerate/editor-react 0.16.0 → 0.17.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 +2 -2
- package/dist/canvas/index.cjs +406 -142
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +66 -3
- package/dist/canvas/index.d.ts +66 -3
- package/dist/canvas/index.js +277 -0
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-I3E4KSA2.js +515 -0
- package/dist/chunk-I3E4KSA2.js.map +1 -0
- package/dist/chunk-JR5ZBDR7.js +2012 -0
- package/dist/chunk-JR5ZBDR7.js.map +1 -0
- package/dist/{chunk-XTFR3IMK.js → chunk-ZU54BMDC.js} +473 -160
- package/dist/chunk-ZU54BMDC.js.map +1 -0
- package/dist/generation/index.cjs +290 -0
- package/dist/generation/index.cjs.map +1 -1
- package/dist/generation/index.d.cts +66 -2
- package/dist/generation/index.d.ts +66 -2
- package/dist/generation/index.js +7 -1
- package/dist/image-editor/index.cjs +490 -187
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +34 -2
- package/dist/image-editor/index.d.ts +34 -2
- package/dist/image-editor/index.js +5 -1
- package/dist/index.cjs +2372 -731
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +88 -6
- package/dist/index.d.ts +88 -6
- package/dist/index.js +334 -96
- package/dist/index.js.map +1 -1
- package/dist/spreadsheet/index.cjs +943 -112
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +119 -7
- package/dist/spreadsheet/index.d.ts +119 -7
- package/dist/spreadsheet/index.js +11 -1
- package/dist/tokens/index.cjs +395 -0
- package/dist/tokens/index.cjs.map +1 -0
- package/dist/tokens/index.d.cts +54 -0
- package/dist/tokens/index.d.ts +54 -0
- package/dist/tokens/index.js +375 -0
- package/dist/tokens/index.js.map +1 -0
- package/package.json +10 -2
- package/dist/chunk-7SPRQZ6H.js +0 -216
- package/dist/chunk-7SPRQZ6H.js.map +0 -1
- package/dist/chunk-FYIPXHAE.js +0 -1169
- package/dist/chunk-FYIPXHAE.js.map +0 -1
- package/dist/chunk-XTFR3IMK.js.map +0 -1
|
@@ -35,6 +35,8 @@ __export(image_editor_exports, {
|
|
|
35
35
|
CurvesEditor: () => CurvesEditor,
|
|
36
36
|
Histogram: () => Histogram,
|
|
37
37
|
ImageEditor: () => ImageEditor,
|
|
38
|
+
RefineEdgePanel: () => RefineEdgePanel,
|
|
39
|
+
SelectionOptionsBar: () => SelectionOptionsBar,
|
|
38
40
|
useImageEditor: () => useImageEditor,
|
|
39
41
|
useImageHistogram: () => useImageHistogram
|
|
40
42
|
});
|
|
@@ -199,8 +201,8 @@ function useImageEditor(options = {}) {
|
|
|
199
201
|
}
|
|
200
202
|
|
|
201
203
|
// src/image-editor/ImageEditor.tsx
|
|
202
|
-
var
|
|
203
|
-
var
|
|
204
|
+
var import_react7 = __toESM(require("react"), 1);
|
|
205
|
+
var import_image_editor8 = require("@pixerate/editor/image-editor");
|
|
204
206
|
|
|
205
207
|
// src/image-editor/ControlSlider.tsx
|
|
206
208
|
var import_image_editor2 = require("@pixerate/editor/image-editor");
|
|
@@ -631,8 +633,248 @@ var AdjustmentLayersPanel = ({ controller, layers: layersProp, histogram }) => {
|
|
|
631
633
|
] });
|
|
632
634
|
};
|
|
633
635
|
|
|
634
|
-
// src/image-editor/
|
|
636
|
+
// src/image-editor/SelectionOptionsBar.tsx
|
|
637
|
+
var import_react5 = require("react");
|
|
638
|
+
var import_image_editor6 = require("@pixerate/editor/image-editor");
|
|
635
639
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
640
|
+
var MODIFY_OPS = [
|
|
641
|
+
{ op: "grow", label: "Grow" },
|
|
642
|
+
{ op: "shrink", label: "Shrink" },
|
|
643
|
+
{ op: "feather", label: "Feather" },
|
|
644
|
+
{ op: "border", label: "Border" },
|
|
645
|
+
{ op: "smooth", label: "Smooth" }
|
|
646
|
+
];
|
|
647
|
+
var btn = (on) => `px-2 py-1 rounded-md border text-[11px] transition-colors ${on ? "bg-indigo-600 border-indigo-500 text-white" : "bg-slate-950 border-slate-800 text-slate-300 hover:text-white"}`;
|
|
648
|
+
var SelectionOptionsBar = ({
|
|
649
|
+
controller,
|
|
650
|
+
options,
|
|
651
|
+
onOptionsChange,
|
|
652
|
+
selection,
|
|
653
|
+
quickMask,
|
|
654
|
+
className = ""
|
|
655
|
+
}) => {
|
|
656
|
+
const [radius, setRadius] = (0, import_react5.useState)(2);
|
|
657
|
+
const set = (patch) => onOptionsChange({ ...options, ...patch });
|
|
658
|
+
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
659
|
+
const qm = quickMask ?? Boolean(controller.getState().quickMask);
|
|
660
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
661
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: import_image_editor6.SELECTION_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", "aria-pressed": options.tool === t.id, className: btn(options.tool === t.id), onClick: () => set({ tool: t.id }), children: t.label }, t.id)) }),
|
|
662
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: import_image_editor6.SELECTION_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: import_image_editor6.SELECTION_MODE_LABELS[m] }, m)) }),
|
|
663
|
+
options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
664
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
665
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
666
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Tolerance" }),
|
|
667
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-mono", children: options.tolerance })
|
|
668
|
+
] }),
|
|
669
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
670
|
+
"input",
|
|
671
|
+
{
|
|
672
|
+
type: "range",
|
|
673
|
+
min: 0,
|
|
674
|
+
max: 255,
|
|
675
|
+
step: 1,
|
|
676
|
+
"aria-label": "Tolerance",
|
|
677
|
+
value: options.tolerance,
|
|
678
|
+
onChange: (e) => set({ tolerance: Number(e.target.value) }),
|
|
679
|
+
className: "w-full accent-indigo-500"
|
|
680
|
+
}
|
|
681
|
+
)
|
|
682
|
+
] }),
|
|
683
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
684
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
|
|
685
|
+
"Contiguous"
|
|
686
|
+
] }),
|
|
687
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
688
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
|
|
689
|
+
"Sample adjusted image"
|
|
690
|
+
] })
|
|
691
|
+
] }),
|
|
692
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
693
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
|
|
694
|
+
"Anti-alias"
|
|
695
|
+
] }),
|
|
696
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
697
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
|
|
698
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
|
|
699
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
|
|
700
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
|
|
701
|
+
] }),
|
|
702
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
703
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
|
|
704
|
+
"Radius",
|
|
705
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
706
|
+
"input",
|
|
707
|
+
{
|
|
708
|
+
type: "number",
|
|
709
|
+
min: 0,
|
|
710
|
+
max: 500,
|
|
711
|
+
step: 1,
|
|
712
|
+
"aria-label": "Modify radius",
|
|
713
|
+
value: radius,
|
|
714
|
+
onChange: (e) => setRadius(Math.max(0, Number(e.target.value) || 0)),
|
|
715
|
+
className: "w-14 bg-slate-950 border border-slate-800 rounded px-1 py-0.5 text-slate-200"
|
|
716
|
+
}
|
|
717
|
+
)
|
|
718
|
+
] }),
|
|
719
|
+
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
|
|
720
|
+
] }),
|
|
721
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor6.describeSelection)(sel) })
|
|
722
|
+
] });
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
// src/image-editor/RefineEdgePanel.tsx
|
|
726
|
+
var import_react6 = require("react");
|
|
727
|
+
var import_image_editor7 = require("@pixerate/editor/image-editor");
|
|
728
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
729
|
+
var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
|
|
730
|
+
var button = "px-2 py-1 rounded-md border border-slate-800 bg-slate-950 text-[11px] text-slate-200 hover:text-white disabled:opacity-40";
|
|
731
|
+
var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
732
|
+
const [params, setParams] = (0, import_react6.useState)(DEFAULT_PARAMS);
|
|
733
|
+
const [busy, setBusy] = (0, import_react6.useState)(false);
|
|
734
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
735
|
+
const [layerId, setLayerId] = (0, import_react6.useState)("");
|
|
736
|
+
const [newKind, setNewKind] = (0, import_react6.useState)("hueSaturation");
|
|
737
|
+
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
738
|
+
const list = layers ?? controller.getAdjustmentLayers();
|
|
739
|
+
const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
|
|
740
|
+
const refine = async () => {
|
|
741
|
+
setBusy(true);
|
|
742
|
+
setError(null);
|
|
743
|
+
try {
|
|
744
|
+
await controller.refineSelection(params);
|
|
745
|
+
} catch (err) {
|
|
746
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
747
|
+
} finally {
|
|
748
|
+
setBusy(false);
|
|
749
|
+
}
|
|
750
|
+
};
|
|
751
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
752
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
|
|
753
|
+
import_image_editor7.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
754
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
755
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: c.label }),
|
|
756
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-mono", children: [
|
|
757
|
+
params[c.id],
|
|
758
|
+
c.unit
|
|
759
|
+
] })
|
|
760
|
+
] }),
|
|
761
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
762
|
+
"input",
|
|
763
|
+
{
|
|
764
|
+
type: "range",
|
|
765
|
+
min: c.min,
|
|
766
|
+
max: c.max,
|
|
767
|
+
step: c.step,
|
|
768
|
+
"aria-label": c.label,
|
|
769
|
+
value: params[c.id],
|
|
770
|
+
onChange: (e) => setParams({ ...params, [c.id]: Number(e.target.value) }),
|
|
771
|
+
className: "w-full accent-indigo-500"
|
|
772
|
+
}
|
|
773
|
+
)
|
|
774
|
+
] }, c.id)),
|
|
775
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
776
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
|
|
777
|
+
"Smart Radius"
|
|
778
|
+
] }),
|
|
779
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-1", children: [
|
|
780
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: button, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
|
|
781
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: button, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
|
|
782
|
+
] }),
|
|
783
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
784
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
|
|
785
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-1 items-center", children: [
|
|
786
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
787
|
+
"select",
|
|
788
|
+
{
|
|
789
|
+
"aria-label": "New masked layer kind",
|
|
790
|
+
value: newKind,
|
|
791
|
+
onChange: (e) => setNewKind(e.target.value),
|
|
792
|
+
className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
793
|
+
children: import_image_editor7.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: k.kind, children: k.label }, k.kind))
|
|
794
|
+
}
|
|
795
|
+
),
|
|
796
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
797
|
+
"button",
|
|
798
|
+
{
|
|
799
|
+
type: "button",
|
|
800
|
+
className: button,
|
|
801
|
+
disabled: !sel,
|
|
802
|
+
onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor7.layerMaskFromSelection)(sel) })),
|
|
803
|
+
children: "New Masked Layer"
|
|
804
|
+
}
|
|
805
|
+
)
|
|
806
|
+
] }),
|
|
807
|
+
list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
808
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
809
|
+
"select",
|
|
810
|
+
{
|
|
811
|
+
"aria-label": "Mask layer",
|
|
812
|
+
value: target.id,
|
|
813
|
+
onChange: (e) => setLayerId(e.target.value),
|
|
814
|
+
className: "bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
815
|
+
children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("option", { value: l.id, children: [
|
|
816
|
+
l.name || (0, import_image_editor7.adjustmentKindLabel)(l.kind),
|
|
817
|
+
l.mask ? " (masked)" : ""
|
|
818
|
+
] }, l.id))
|
|
819
|
+
}
|
|
820
|
+
),
|
|
821
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: button, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
|
|
823
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: button, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
|
|
824
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: button, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
|
|
825
|
+
] }),
|
|
826
|
+
target.mask && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
827
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
828
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
829
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Density" }),
|
|
830
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-mono", children: [
|
|
831
|
+
Math.round((target.mask.density ?? 1) * 100),
|
|
832
|
+
"%"
|
|
833
|
+
] })
|
|
834
|
+
] }),
|
|
835
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
836
|
+
"input",
|
|
837
|
+
{
|
|
838
|
+
type: "range",
|
|
839
|
+
min: 0,
|
|
840
|
+
max: 100,
|
|
841
|
+
step: 1,
|
|
842
|
+
"aria-label": "Mask density",
|
|
843
|
+
value: Math.round((target.mask.density ?? 1) * 100),
|
|
844
|
+
onChange: (e) => controller.setAdjustmentLayerMaskProps(target.id, { density: Number(e.target.value) / 100 }),
|
|
845
|
+
className: "w-full accent-indigo-500"
|
|
846
|
+
}
|
|
847
|
+
)
|
|
848
|
+
] }),
|
|
849
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
850
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
851
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Mask Feather" }),
|
|
852
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "font-mono", children: [
|
|
853
|
+
target.mask.feather ?? 0,
|
|
854
|
+
"px"
|
|
855
|
+
] })
|
|
856
|
+
] }),
|
|
857
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
858
|
+
"input",
|
|
859
|
+
{
|
|
860
|
+
type: "range",
|
|
861
|
+
min: 0,
|
|
862
|
+
max: 50,
|
|
863
|
+
step: 0.5,
|
|
864
|
+
"aria-label": "Mask feather",
|
|
865
|
+
value: target.mask.feather ?? 0,
|
|
866
|
+
onChange: (e) => controller.setAdjustmentLayerMaskProps(target.id, { feather: Number(e.target.value) }),
|
|
867
|
+
className: "w-full accent-indigo-500"
|
|
868
|
+
}
|
|
869
|
+
)
|
|
870
|
+
] })
|
|
871
|
+
] })
|
|
872
|
+
] })
|
|
873
|
+
] });
|
|
874
|
+
};
|
|
875
|
+
|
|
876
|
+
// src/image-editor/ImageEditor.tsx
|
|
877
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
636
878
|
var ImageEditor = ({
|
|
637
879
|
editor: externalEditor,
|
|
638
880
|
src,
|
|
@@ -647,17 +889,26 @@ var ImageEditor = ({
|
|
|
647
889
|
const internalEditor = useImageEditor({ image: src });
|
|
648
890
|
const editor = externalEditor || internalEditor;
|
|
649
891
|
const { state, controller } = editor;
|
|
650
|
-
const legacyProcess = (0,
|
|
651
|
-
const canvasRef = (0,
|
|
652
|
-
const containerRef = (0,
|
|
653
|
-
const [activeTab, setActiveTab] = (0,
|
|
654
|
-
const [activeCropRatio, setActiveCropRatio] = (0,
|
|
655
|
-
const [
|
|
656
|
-
const
|
|
657
|
-
|
|
658
|
-
const
|
|
659
|
-
|
|
660
|
-
|
|
892
|
+
const legacyProcess = (0, import_image_editor8.normalizeProcessVersion)(state.adjustments.process) < import_image_editor8.LATEST_PROCESS_VERSION;
|
|
893
|
+
const canvasRef = (0, import_react7.useRef)(null);
|
|
894
|
+
const containerRef = (0, import_react7.useRef)(null);
|
|
895
|
+
const [activeTab, setActiveTab] = (0, import_react7.useState)("crop");
|
|
896
|
+
const [activeCropRatio, setActiveCropRatio] = (0, import_react7.useState)(null);
|
|
897
|
+
const [selectionOptions, setSelectionOptions] = (0, import_react7.useState)(import_image_editor8.DEFAULT_SELECTION_TOOL_OPTIONS);
|
|
898
|
+
const selectionOptionsRef = (0, import_react7.useRef)(selectionOptions);
|
|
899
|
+
selectionOptionsRef.current = selectionOptions;
|
|
900
|
+
const selectionGestureRef = (0, import_react7.useRef)(null);
|
|
901
|
+
if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
|
|
902
|
+
selectionGestureRef.current = new import_image_editor8.SelectionGesture(controller, () => selectionOptionsRef.current);
|
|
903
|
+
}
|
|
904
|
+
const selectionDraftRef = (0, import_react7.useRef)(null);
|
|
905
|
+
const [selectionError, setSelectionError] = (0, import_react7.useState)(null);
|
|
906
|
+
const [inpaintPrompt, setInpaintPrompt] = (0, import_react7.useState)("");
|
|
907
|
+
const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react7.useState)("annotations");
|
|
908
|
+
const [isRemovingBg, setIsRemovingBg] = (0, import_react7.useState)(false);
|
|
909
|
+
const [isInpainting, setIsInpainting] = (0, import_react7.useState)(false);
|
|
910
|
+
const [aiError, setAiError] = (0, import_react7.useState)(null);
|
|
911
|
+
const [aiSuccess, setAiSuccess] = (0, import_react7.useState)(null);
|
|
661
912
|
const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
|
|
662
913
|
const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
|
|
663
914
|
const handleRemoveBackground = async () => {
|
|
@@ -719,18 +970,18 @@ var ImageEditor = ({
|
|
|
719
970
|
setIsInpainting(false);
|
|
720
971
|
}
|
|
721
972
|
};
|
|
722
|
-
const [activeColor, setActiveColor] = (0,
|
|
723
|
-
const [strokeWidth, setStrokeWidth] = (0,
|
|
724
|
-
const [fontSize, setFontSize] = (0,
|
|
725
|
-
const [textInput, setTextInput] = (0,
|
|
726
|
-
const draftAnnotationRef = (0,
|
|
727
|
-
const draftCropRef = (0,
|
|
728
|
-
const cropDragInfoRef = (0,
|
|
729
|
-
const annotationDragInfoRef = (0,
|
|
730
|
-
const isDrawingRef = (0,
|
|
731
|
-
const currentPathRef = (0,
|
|
732
|
-
const dragStartPointRef = (0,
|
|
733
|
-
const renderCanvas = (0,
|
|
973
|
+
const [activeColor, setActiveColor] = (0, import_react7.useState)("#ef4444");
|
|
974
|
+
const [strokeWidth, setStrokeWidth] = (0, import_react7.useState)(3);
|
|
975
|
+
const [fontSize, setFontSize] = (0, import_react7.useState)(24);
|
|
976
|
+
const [textInput, setTextInput] = (0, import_react7.useState)("");
|
|
977
|
+
const draftAnnotationRef = (0, import_react7.useRef)(null);
|
|
978
|
+
const draftCropRef = (0, import_react7.useRef)(null);
|
|
979
|
+
const cropDragInfoRef = (0, import_react7.useRef)(null);
|
|
980
|
+
const annotationDragInfoRef = (0, import_react7.useRef)(null);
|
|
981
|
+
const isDrawingRef = (0, import_react7.useRef)(false);
|
|
982
|
+
const currentPathRef = (0, import_react7.useRef)([]);
|
|
983
|
+
const dragStartPointRef = (0, import_react7.useRef)(null);
|
|
984
|
+
const renderCanvas = (0, import_react7.useCallback)(
|
|
734
985
|
async (draftAnnotation, draftCrop) => {
|
|
735
986
|
const canvas = canvasRef.current;
|
|
736
987
|
const container = containerRef.current;
|
|
@@ -744,12 +995,13 @@ var ImageEditor = ({
|
|
|
744
995
|
showSelectionOverlay: true,
|
|
745
996
|
interactive: true,
|
|
746
997
|
draftAnnotation: draftAnnotation !== void 0 ? draftAnnotation : draftAnnotationRef.current,
|
|
747
|
-
draftCrop: draftCrop !== void 0 ? draftCrop : draftCropRef.current
|
|
998
|
+
draftCrop: draftCrop !== void 0 ? draftCrop : draftCropRef.current,
|
|
999
|
+
draftSelectionPath: selectionDraftRef.current
|
|
748
1000
|
});
|
|
749
1001
|
},
|
|
750
1002
|
[controller, activeTab]
|
|
751
1003
|
);
|
|
752
|
-
(0,
|
|
1004
|
+
(0, import_react7.useEffect)(() => {
|
|
753
1005
|
const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
|
|
754
1006
|
const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
|
|
755
1007
|
const animId = raf(() => {
|
|
@@ -757,12 +1009,12 @@ var ImageEditor = ({
|
|
|
757
1009
|
});
|
|
758
1010
|
return () => caf(animId);
|
|
759
1011
|
}, [renderCanvas, state]);
|
|
760
|
-
(0,
|
|
1012
|
+
(0, import_react7.useEffect)(() => {
|
|
761
1013
|
if (activeTab === "crop" && editor.state.activeTool !== "crop") {
|
|
762
1014
|
editor.setTool("crop");
|
|
763
1015
|
}
|
|
764
1016
|
}, [activeTab, editor]);
|
|
765
|
-
(0,
|
|
1017
|
+
(0, import_react7.useEffect)(() => {
|
|
766
1018
|
const container = containerRef.current;
|
|
767
1019
|
if (!container) return;
|
|
768
1020
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -792,6 +1044,12 @@ var ImageEditor = ({
|
|
|
792
1044
|
const canvas = canvasRef.current;
|
|
793
1045
|
if (!canvas) return;
|
|
794
1046
|
const canvasPt = getCanvasEventPoint(e);
|
|
1047
|
+
if (activeTab === "select") {
|
|
1048
|
+
const gesture = selectionGestureRef.current;
|
|
1049
|
+
const imgPt = (0, import_image_editor8.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
1050
|
+
void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
795
1053
|
if (activeTab === "crop") {
|
|
796
1054
|
const activeCrop = draftCropRef.current || state.crop || {
|
|
797
1055
|
x: 0,
|
|
@@ -799,8 +1057,8 @@ var ImageEditor = ({
|
|
|
799
1057
|
width: state.imageDimensions.width,
|
|
800
1058
|
height: state.imageDimensions.height
|
|
801
1059
|
};
|
|
802
|
-
const handle = (0,
|
|
803
|
-
const startImgPt = (0,
|
|
1060
|
+
const handle = (0, import_image_editor8.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
1061
|
+
const startImgPt = (0, import_image_editor8.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
804
1062
|
if (handle) {
|
|
805
1063
|
cropDragInfoRef.current = {
|
|
806
1064
|
handle,
|
|
@@ -819,12 +1077,12 @@ var ImageEditor = ({
|
|
|
819
1077
|
return;
|
|
820
1078
|
}
|
|
821
1079
|
if (activeTab === "annotate") {
|
|
822
|
-
const imgPt = (0,
|
|
1080
|
+
const imgPt = (0, import_image_editor8.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
823
1081
|
dragStartPointRef.current = imgPt;
|
|
824
1082
|
if (state.activeTool === "select") {
|
|
825
1083
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
826
1084
|
const ann = state.annotations[i];
|
|
827
|
-
if ((0,
|
|
1085
|
+
if ((0, import_image_editor8.hitTestAnnotation)(imgPt, ann)) {
|
|
828
1086
|
editor.selectAnnotation(ann.id);
|
|
829
1087
|
annotationDragInfoRef.current = {
|
|
830
1088
|
annId: ann.id,
|
|
@@ -858,10 +1116,18 @@ var ImageEditor = ({
|
|
|
858
1116
|
const canvas = canvasRef.current;
|
|
859
1117
|
if (!canvas) return;
|
|
860
1118
|
const canvasPt = getCanvasEventPoint(e);
|
|
1119
|
+
if (activeTab === "select") {
|
|
1120
|
+
const gesture = selectionGestureRef.current;
|
|
1121
|
+
if (gesture.active && gesture.move((0, import_image_editor8.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
|
|
1122
|
+
selectionDraftRef.current = gesture.draftPath;
|
|
1123
|
+
renderCanvas();
|
|
1124
|
+
}
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
861
1127
|
if (activeTab === "crop") {
|
|
862
1128
|
const drag = cropDragInfoRef.current;
|
|
863
1129
|
if (drag) {
|
|
864
|
-
const currentImgPt = (0,
|
|
1130
|
+
const currentImgPt = (0, import_image_editor8.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
865
1131
|
let newCrop;
|
|
866
1132
|
if (drag.handle === "new") {
|
|
867
1133
|
const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
|
|
@@ -875,7 +1141,7 @@ var ImageEditor = ({
|
|
|
875
1141
|
height: Math.round(Math.max(20, maxY - minY))
|
|
876
1142
|
};
|
|
877
1143
|
} else {
|
|
878
|
-
newCrop = (0,
|
|
1144
|
+
newCrop = (0, import_image_editor8.calculateCropDrag)(
|
|
879
1145
|
drag.startCrop,
|
|
880
1146
|
drag.handle,
|
|
881
1147
|
drag.startImgPt,
|
|
@@ -895,15 +1161,15 @@ var ImageEditor = ({
|
|
|
895
1161
|
width: state.imageDimensions.width,
|
|
896
1162
|
height: state.imageDimensions.height
|
|
897
1163
|
};
|
|
898
|
-
const handle = (0,
|
|
899
|
-
canvas.style.cursor = (0,
|
|
1164
|
+
const handle = (0, import_image_editor8.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
1165
|
+
canvas.style.cursor = (0, import_image_editor8.getCropCursor)(handle, state.transform);
|
|
900
1166
|
}
|
|
901
1167
|
return;
|
|
902
1168
|
}
|
|
903
1169
|
if (activeTab === "annotate") {
|
|
904
1170
|
if (annotationDragInfoRef.current) {
|
|
905
1171
|
const drag = annotationDragInfoRef.current;
|
|
906
|
-
const currentImgPt2 = (0,
|
|
1172
|
+
const currentImgPt2 = (0, import_image_editor8.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
907
1173
|
const dx = currentImgPt2.x - drag.startImgPt.x;
|
|
908
1174
|
const dy = currentImgPt2.y - drag.startImgPt.y;
|
|
909
1175
|
editor.updateAnnotation(drag.annId, {
|
|
@@ -915,10 +1181,10 @@ var ImageEditor = ({
|
|
|
915
1181
|
const startPt = dragStartPointRef.current;
|
|
916
1182
|
if (!startPt) {
|
|
917
1183
|
if (state.activeTool === "select") {
|
|
918
|
-
const imgPt = (0,
|
|
1184
|
+
const imgPt = (0, import_image_editor8.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
919
1185
|
let hovered = false;
|
|
920
1186
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
921
|
-
if ((0,
|
|
1187
|
+
if ((0, import_image_editor8.hitTestAnnotation)(imgPt, state.annotations[i])) {
|
|
922
1188
|
hovered = true;
|
|
923
1189
|
break;
|
|
924
1190
|
}
|
|
@@ -929,7 +1195,7 @@ var ImageEditor = ({
|
|
|
929
1195
|
}
|
|
930
1196
|
return;
|
|
931
1197
|
}
|
|
932
|
-
const currentImgPt = (0,
|
|
1198
|
+
const currentImgPt = (0, import_image_editor8.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
933
1199
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
934
1200
|
currentPathRef.current.push(currentImgPt);
|
|
935
1201
|
const draft = {
|
|
@@ -1006,6 +1272,15 @@ var ImageEditor = ({
|
|
|
1006
1272
|
const canvas = canvasRef.current;
|
|
1007
1273
|
if (!canvas) return;
|
|
1008
1274
|
const canvasPt = getCanvasEventPoint(e);
|
|
1275
|
+
if (activeTab === "select") {
|
|
1276
|
+
const gesture = selectionGestureRef.current;
|
|
1277
|
+
if (gesture.active) {
|
|
1278
|
+
gesture.end((0, import_image_editor8.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
|
|
1279
|
+
selectionDraftRef.current = null;
|
|
1280
|
+
renderCanvas();
|
|
1281
|
+
}
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1009
1284
|
if (activeTab === "crop") {
|
|
1010
1285
|
if (cropDragInfoRef.current) {
|
|
1011
1286
|
if (draftCropRef.current && draftCropRef.current.width >= 20 && draftCropRef.current.height >= 20) {
|
|
@@ -1024,7 +1299,7 @@ var ImageEditor = ({
|
|
|
1024
1299
|
}
|
|
1025
1300
|
const startPt = dragStartPointRef.current;
|
|
1026
1301
|
if (startPt) {
|
|
1027
|
-
const currentImgPt = (0,
|
|
1302
|
+
const currentImgPt = (0, import_image_editor8.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
1028
1303
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
1029
1304
|
if (currentPathRef.current.length > 1) {
|
|
1030
1305
|
editor.addAnnotation({
|
|
@@ -1120,15 +1395,15 @@ var ImageEditor = ({
|
|
|
1120
1395
|
link.click();
|
|
1121
1396
|
}
|
|
1122
1397
|
};
|
|
1123
|
-
return /* @__PURE__ */ (0,
|
|
1398
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1124
1399
|
"div",
|
|
1125
1400
|
{
|
|
1126
1401
|
className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
|
|
1127
1402
|
style,
|
|
1128
1403
|
children: [
|
|
1129
|
-
/* @__PURE__ */ (0,
|
|
1130
|
-
/* @__PURE__ */ (0,
|
|
1131
|
-
/* @__PURE__ */ (0,
|
|
1404
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.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: [
|
|
1405
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
|
|
1406
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1132
1407
|
"button",
|
|
1133
1408
|
{
|
|
1134
1409
|
type: "button",
|
|
@@ -1140,7 +1415,7 @@ var ImageEditor = ({
|
|
|
1140
1415
|
children: "Transform & Crop"
|
|
1141
1416
|
}
|
|
1142
1417
|
),
|
|
1143
|
-
/* @__PURE__ */ (0,
|
|
1418
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1144
1419
|
"button",
|
|
1145
1420
|
{
|
|
1146
1421
|
type: "button",
|
|
@@ -1152,7 +1427,19 @@ var ImageEditor = ({
|
|
|
1152
1427
|
children: "Adjustments"
|
|
1153
1428
|
}
|
|
1154
1429
|
),
|
|
1155
|
-
/* @__PURE__ */ (0,
|
|
1430
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1431
|
+
"button",
|
|
1432
|
+
{
|
|
1433
|
+
type: "button",
|
|
1434
|
+
onClick: () => {
|
|
1435
|
+
setActiveTab("select");
|
|
1436
|
+
editor.setTool("select");
|
|
1437
|
+
},
|
|
1438
|
+
className: `px-3 py-1.5 rounded-md font-medium transition-colors ${activeTab === "select" ? "bg-indigo-600 text-white shadow" : "text-slate-400 hover:text-slate-200"}`,
|
|
1439
|
+
children: "Select & Mask"
|
|
1440
|
+
}
|
|
1441
|
+
),
|
|
1442
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1156
1443
|
"button",
|
|
1157
1444
|
{
|
|
1158
1445
|
type: "button",
|
|
@@ -1164,7 +1451,7 @@ var ImageEditor = ({
|
|
|
1164
1451
|
children: "Annotations"
|
|
1165
1452
|
}
|
|
1166
1453
|
),
|
|
1167
|
-
/* @__PURE__ */ (0,
|
|
1454
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1168
1455
|
"button",
|
|
1169
1456
|
{
|
|
1170
1457
|
type: "button",
|
|
@@ -1176,7 +1463,7 @@ var ImageEditor = ({
|
|
|
1176
1463
|
children: "Depth Mask"
|
|
1177
1464
|
}
|
|
1178
1465
|
),
|
|
1179
|
-
/* @__PURE__ */ (0,
|
|
1466
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1180
1467
|
"button",
|
|
1181
1468
|
{
|
|
1182
1469
|
type: "button",
|
|
@@ -1186,14 +1473,14 @@ var ImageEditor = ({
|
|
|
1186
1473
|
},
|
|
1187
1474
|
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"}`,
|
|
1188
1475
|
children: [
|
|
1189
|
-
/* @__PURE__ */ (0,
|
|
1476
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.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_runtime7.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" }) }),
|
|
1190
1477
|
"AI Tools"
|
|
1191
1478
|
]
|
|
1192
1479
|
}
|
|
1193
1480
|
)
|
|
1194
1481
|
] }),
|
|
1195
|
-
/* @__PURE__ */ (0,
|
|
1196
|
-
/* @__PURE__ */ (0,
|
|
1482
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
1483
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1197
1484
|
"button",
|
|
1198
1485
|
{
|
|
1199
1486
|
type: "button",
|
|
@@ -1204,7 +1491,7 @@ var ImageEditor = ({
|
|
|
1204
1491
|
children: "\u21A9"
|
|
1205
1492
|
}
|
|
1206
1493
|
),
|
|
1207
|
-
/* @__PURE__ */ (0,
|
|
1494
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1208
1495
|
"button",
|
|
1209
1496
|
{
|
|
1210
1497
|
type: "button",
|
|
@@ -1215,7 +1502,7 @@ var ImageEditor = ({
|
|
|
1215
1502
|
children: "\u21AA"
|
|
1216
1503
|
}
|
|
1217
1504
|
),
|
|
1218
|
-
/* @__PURE__ */ (0,
|
|
1505
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1219
1506
|
"button",
|
|
1220
1507
|
{
|
|
1221
1508
|
type: "button",
|
|
@@ -1224,8 +1511,8 @@ var ImageEditor = ({
|
|
|
1224
1511
|
children: "Reset"
|
|
1225
1512
|
}
|
|
1226
1513
|
),
|
|
1227
|
-
/* @__PURE__ */ (0,
|
|
1228
|
-
/* @__PURE__ */ (0,
|
|
1514
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
1515
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1229
1516
|
"button",
|
|
1230
1517
|
{
|
|
1231
1518
|
type: "button",
|
|
@@ -1235,11 +1522,11 @@ var ImageEditor = ({
|
|
|
1235
1522
|
children: "-"
|
|
1236
1523
|
}
|
|
1237
1524
|
),
|
|
1238
|
-
/* @__PURE__ */ (0,
|
|
1525
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
|
|
1239
1526
|
Math.round(state.zoom * 100),
|
|
1240
1527
|
"%"
|
|
1241
1528
|
] }),
|
|
1242
|
-
/* @__PURE__ */ (0,
|
|
1529
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1243
1530
|
"button",
|
|
1244
1531
|
{
|
|
1245
1532
|
type: "button",
|
|
@@ -1249,8 +1536,8 @@ var ImageEditor = ({
|
|
|
1249
1536
|
children: "+"
|
|
1250
1537
|
}
|
|
1251
1538
|
),
|
|
1252
|
-
/* @__PURE__ */ (0,
|
|
1253
|
-
/* @__PURE__ */ (0,
|
|
1539
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
1540
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1254
1541
|
"button",
|
|
1255
1542
|
{
|
|
1256
1543
|
type: "button",
|
|
@@ -1261,7 +1548,7 @@ var ImageEditor = ({
|
|
|
1261
1548
|
children: "Hold Compare"
|
|
1262
1549
|
}
|
|
1263
1550
|
),
|
|
1264
|
-
/* @__PURE__ */ (0,
|
|
1551
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1265
1552
|
"button",
|
|
1266
1553
|
{
|
|
1267
1554
|
type: "button",
|
|
@@ -1272,13 +1559,13 @@ var ImageEditor = ({
|
|
|
1272
1559
|
)
|
|
1273
1560
|
] })
|
|
1274
1561
|
] }),
|
|
1275
|
-
/* @__PURE__ */ (0,
|
|
1276
|
-
/* @__PURE__ */ (0,
|
|
1562
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
|
|
1563
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1277
1564
|
"div",
|
|
1278
1565
|
{
|
|
1279
1566
|
ref: containerRef,
|
|
1280
1567
|
className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
|
|
1281
|
-
children: /* @__PURE__ */ (0,
|
|
1568
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1282
1569
|
"canvas",
|
|
1283
1570
|
{
|
|
1284
1571
|
ref: canvasRef,
|
|
@@ -1291,11 +1578,11 @@ var ImageEditor = ({
|
|
|
1291
1578
|
)
|
|
1292
1579
|
}
|
|
1293
1580
|
),
|
|
1294
|
-
/* @__PURE__ */ (0,
|
|
1295
|
-
activeTab === "crop" && /* @__PURE__ */ (0,
|
|
1296
|
-
/* @__PURE__ */ (0,
|
|
1297
|
-
/* @__PURE__ */ (0,
|
|
1298
|
-
/* @__PURE__ */ (0,
|
|
1581
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.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: [
|
|
1582
|
+
activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
1583
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
|
|
1584
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
1585
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1299
1586
|
"button",
|
|
1300
1587
|
{
|
|
1301
1588
|
type: "button",
|
|
@@ -1307,7 +1594,7 @@ var ImageEditor = ({
|
|
|
1307
1594
|
children: "Freeform"
|
|
1308
1595
|
}
|
|
1309
1596
|
),
|
|
1310
|
-
/* @__PURE__ */ (0,
|
|
1597
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1311
1598
|
"button",
|
|
1312
1599
|
{
|
|
1313
1600
|
type: "button",
|
|
@@ -1319,7 +1606,7 @@ var ImageEditor = ({
|
|
|
1319
1606
|
children: "1:1 Square"
|
|
1320
1607
|
}
|
|
1321
1608
|
),
|
|
1322
|
-
/* @__PURE__ */ (0,
|
|
1609
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1323
1610
|
"button",
|
|
1324
1611
|
{
|
|
1325
1612
|
type: "button",
|
|
@@ -1331,7 +1618,7 @@ var ImageEditor = ({
|
|
|
1331
1618
|
children: "4:3 Standard"
|
|
1332
1619
|
}
|
|
1333
1620
|
),
|
|
1334
|
-
/* @__PURE__ */ (0,
|
|
1621
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1335
1622
|
"button",
|
|
1336
1623
|
{
|
|
1337
1624
|
type: "button",
|
|
@@ -1343,7 +1630,7 @@ var ImageEditor = ({
|
|
|
1343
1630
|
children: "16:9 Wide"
|
|
1344
1631
|
}
|
|
1345
1632
|
),
|
|
1346
|
-
/* @__PURE__ */ (0,
|
|
1633
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1347
1634
|
"button",
|
|
1348
1635
|
{
|
|
1349
1636
|
type: "button",
|
|
@@ -1355,7 +1642,7 @@ var ImageEditor = ({
|
|
|
1355
1642
|
children: "3:2 Photo"
|
|
1356
1643
|
}
|
|
1357
1644
|
),
|
|
1358
|
-
/* @__PURE__ */ (0,
|
|
1645
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1359
1646
|
"button",
|
|
1360
1647
|
{
|
|
1361
1648
|
type: "button",
|
|
@@ -1368,10 +1655,10 @@ var ImageEditor = ({
|
|
|
1368
1655
|
}
|
|
1369
1656
|
)
|
|
1370
1657
|
] }),
|
|
1371
|
-
/* @__PURE__ */ (0,
|
|
1372
|
-
/* @__PURE__ */ (0,
|
|
1373
|
-
/* @__PURE__ */ (0,
|
|
1374
|
-
/* @__PURE__ */ (0,
|
|
1658
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
1659
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
|
|
1660
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
1661
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1375
1662
|
"button",
|
|
1376
1663
|
{
|
|
1377
1664
|
type: "button",
|
|
@@ -1380,7 +1667,7 @@ var ImageEditor = ({
|
|
|
1380
1667
|
children: "Rotate -90\xB0"
|
|
1381
1668
|
}
|
|
1382
1669
|
),
|
|
1383
|
-
/* @__PURE__ */ (0,
|
|
1670
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1384
1671
|
"button",
|
|
1385
1672
|
{
|
|
1386
1673
|
type: "button",
|
|
@@ -1389,7 +1676,7 @@ var ImageEditor = ({
|
|
|
1389
1676
|
children: "Rotate +90\xB0"
|
|
1390
1677
|
}
|
|
1391
1678
|
),
|
|
1392
|
-
/* @__PURE__ */ (0,
|
|
1679
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1393
1680
|
"button",
|
|
1394
1681
|
{
|
|
1395
1682
|
type: "button",
|
|
@@ -1398,7 +1685,7 @@ var ImageEditor = ({
|
|
|
1398
1685
|
children: "Flip Horizontal"
|
|
1399
1686
|
}
|
|
1400
1687
|
),
|
|
1401
|
-
/* @__PURE__ */ (0,
|
|
1688
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1402
1689
|
"button",
|
|
1403
1690
|
{
|
|
1404
1691
|
type: "button",
|
|
@@ -1409,10 +1696,10 @@ var ImageEditor = ({
|
|
|
1409
1696
|
)
|
|
1410
1697
|
] })
|
|
1411
1698
|
] }),
|
|
1412
|
-
activeTab === "adjust" && /* @__PURE__ */ (0,
|
|
1413
|
-
/* @__PURE__ */ (0,
|
|
1414
|
-
/* @__PURE__ */ (0,
|
|
1415
|
-
/* @__PURE__ */ (0,
|
|
1699
|
+
activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
1700
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1701
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
|
|
1702
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1416
1703
|
"button",
|
|
1417
1704
|
{
|
|
1418
1705
|
type: "button",
|
|
@@ -1422,25 +1709,25 @@ var ImageEditor = ({
|
|
|
1422
1709
|
}
|
|
1423
1710
|
)
|
|
1424
1711
|
] }),
|
|
1425
|
-
/* @__PURE__ */ (0,
|
|
1426
|
-
|
|
1427
|
-
/* @__PURE__ */ (0,
|
|
1712
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Histogram, { histogram: editor.histogram }),
|
|
1713
|
+
import_image_editor8.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_react7.default.Fragment, { children: [
|
|
1714
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1428
1715
|
ControlSlider,
|
|
1429
1716
|
{
|
|
1430
1717
|
spec,
|
|
1431
|
-
value: (0,
|
|
1718
|
+
value: (0, import_image_editor8.readAdjustmentControls)(state.adjustments)[spec.id],
|
|
1432
1719
|
disabled: spec.requiresProcess !== void 0 && legacyProcess,
|
|
1433
1720
|
onChange: (v) => editor.setAdjustments({ [spec.id]: v })
|
|
1434
1721
|
}
|
|
1435
1722
|
),
|
|
1436
|
-
spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0,
|
|
1723
|
+
spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1437
1724
|
"div",
|
|
1438
1725
|
{
|
|
1439
1726
|
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
1727
|
"data-testid": "image-editor-process-notice",
|
|
1441
1728
|
children: [
|
|
1442
|
-
/* @__PURE__ */ (0,
|
|
1443
|
-
/* @__PURE__ */ (0,
|
|
1729
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
|
|
1730
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1444
1731
|
"button",
|
|
1445
1732
|
{
|
|
1446
1733
|
type: "button",
|
|
@@ -1453,7 +1740,7 @@ var ImageEditor = ({
|
|
|
1453
1740
|
}
|
|
1454
1741
|
)
|
|
1455
1742
|
] }, spec.id)),
|
|
1456
|
-
/* @__PURE__ */ (0,
|
|
1743
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1457
1744
|
AdjustmentLayersPanel,
|
|
1458
1745
|
{
|
|
1459
1746
|
controller,
|
|
@@ -1462,9 +1749,9 @@ var ImageEditor = ({
|
|
|
1462
1749
|
}
|
|
1463
1750
|
) })
|
|
1464
1751
|
] }),
|
|
1465
|
-
activeTab === "annotate" && /* @__PURE__ */ (0,
|
|
1466
|
-
/* @__PURE__ */ (0,
|
|
1467
|
-
/* @__PURE__ */ (0,
|
|
1752
|
+
activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
1753
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
|
|
1754
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1468
1755
|
"button",
|
|
1469
1756
|
{
|
|
1470
1757
|
type: "button",
|
|
@@ -1474,9 +1761,9 @@ var ImageEditor = ({
|
|
|
1474
1761
|
},
|
|
1475
1762
|
t
|
|
1476
1763
|
)) }),
|
|
1477
|
-
/* @__PURE__ */ (0,
|
|
1478
|
-
/* @__PURE__ */ (0,
|
|
1479
|
-
/* @__PURE__ */ (0,
|
|
1764
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
1765
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "text-slate-400", children: "Color:" }),
|
|
1766
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1480
1767
|
"input",
|
|
1481
1768
|
{
|
|
1482
1769
|
type: "color",
|
|
@@ -1485,15 +1772,15 @@ var ImageEditor = ({
|
|
|
1485
1772
|
className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
|
|
1486
1773
|
}
|
|
1487
1774
|
),
|
|
1488
|
-
/* @__PURE__ */ (0,
|
|
1489
|
-
/* @__PURE__ */ (0,
|
|
1490
|
-
/* @__PURE__ */ (0,
|
|
1491
|
-
/* @__PURE__ */ (0,
|
|
1775
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex-1 ml-2", children: [
|
|
1776
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
|
|
1777
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Width:" }),
|
|
1778
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "font-mono", children: [
|
|
1492
1779
|
strokeWidth,
|
|
1493
1780
|
"px"
|
|
1494
1781
|
] })
|
|
1495
1782
|
] }),
|
|
1496
|
-
/* @__PURE__ */ (0,
|
|
1783
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1497
1784
|
"input",
|
|
1498
1785
|
{
|
|
1499
1786
|
type: "range",
|
|
@@ -1506,10 +1793,10 @@ var ImageEditor = ({
|
|
|
1506
1793
|
)
|
|
1507
1794
|
] })
|
|
1508
1795
|
] }),
|
|
1509
|
-
/* @__PURE__ */ (0,
|
|
1510
|
-
/* @__PURE__ */ (0,
|
|
1511
|
-
/* @__PURE__ */ (0,
|
|
1512
|
-
/* @__PURE__ */ (0,
|
|
1796
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
1797
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
|
|
1798
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-2", children: [
|
|
1799
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1513
1800
|
"input",
|
|
1514
1801
|
{
|
|
1515
1802
|
type: "text",
|
|
@@ -1520,7 +1807,7 @@ var ImageEditor = ({
|
|
|
1520
1807
|
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"
|
|
1521
1808
|
}
|
|
1522
1809
|
),
|
|
1523
|
-
/* @__PURE__ */ (0,
|
|
1810
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1524
1811
|
"button",
|
|
1525
1812
|
{
|
|
1526
1813
|
type: "button",
|
|
@@ -1530,14 +1817,14 @@ var ImageEditor = ({
|
|
|
1530
1817
|
}
|
|
1531
1818
|
)
|
|
1532
1819
|
] }),
|
|
1533
|
-
/* @__PURE__ */ (0,
|
|
1534
|
-
/* @__PURE__ */ (0,
|
|
1535
|
-
/* @__PURE__ */ (0,
|
|
1820
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
|
|
1821
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Font Size:" }),
|
|
1822
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "font-mono", children: [
|
|
1536
1823
|
fontSize,
|
|
1537
1824
|
"px"
|
|
1538
1825
|
] })
|
|
1539
1826
|
] }),
|
|
1540
|
-
/* @__PURE__ */ (0,
|
|
1827
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1541
1828
|
"input",
|
|
1542
1829
|
{
|
|
1543
1830
|
type: "range",
|
|
@@ -1548,14 +1835,14 @@ var ImageEditor = ({
|
|
|
1548
1835
|
className: "w-full accent-indigo-500"
|
|
1549
1836
|
}
|
|
1550
1837
|
),
|
|
1551
|
-
/* @__PURE__ */ (0,
|
|
1552
|
-
/* @__PURE__ */ (0,
|
|
1553
|
-
/* @__PURE__ */ (0,
|
|
1838
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
1839
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1840
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "text-slate-400", children: [
|
|
1554
1841
|
"Layers (",
|
|
1555
1842
|
state.annotations.length,
|
|
1556
1843
|
")"
|
|
1557
1844
|
] }),
|
|
1558
|
-
state.selectedAnnotationId && /* @__PURE__ */ (0,
|
|
1845
|
+
state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1559
1846
|
"button",
|
|
1560
1847
|
{
|
|
1561
1848
|
type: "button",
|
|
@@ -1564,7 +1851,7 @@ var ImageEditor = ({
|
|
|
1564
1851
|
children: "Delete Selected"
|
|
1565
1852
|
}
|
|
1566
1853
|
),
|
|
1567
|
-
state.annotations.length > 0 && /* @__PURE__ */ (0,
|
|
1854
|
+
state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1568
1855
|
"button",
|
|
1569
1856
|
{
|
|
1570
1857
|
type: "button",
|
|
@@ -1575,10 +1862,10 @@ var ImageEditor = ({
|
|
|
1575
1862
|
)
|
|
1576
1863
|
] })
|
|
1577
1864
|
] }),
|
|
1578
|
-
activeTab === "depth" && /* @__PURE__ */ (0,
|
|
1579
|
-
/* @__PURE__ */ (0,
|
|
1580
|
-
/* @__PURE__ */ (0,
|
|
1581
|
-
/* @__PURE__ */ (0,
|
|
1865
|
+
activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
1866
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1867
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
|
|
1868
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1582
1869
|
"button",
|
|
1583
1870
|
{
|
|
1584
1871
|
type: "button",
|
|
@@ -1588,8 +1875,8 @@ var ImageEditor = ({
|
|
|
1588
1875
|
}
|
|
1589
1876
|
)
|
|
1590
1877
|
] }),
|
|
1591
|
-
/* @__PURE__ */ (0,
|
|
1592
|
-
/* @__PURE__ */ (0,
|
|
1878
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
|
|
1879
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1593
1880
|
"input",
|
|
1594
1881
|
{
|
|
1595
1882
|
type: "checkbox",
|
|
@@ -1598,12 +1885,12 @@ var ImageEditor = ({
|
|
|
1598
1885
|
className: "rounded accent-indigo-500"
|
|
1599
1886
|
}
|
|
1600
1887
|
),
|
|
1601
|
-
/* @__PURE__ */ (0,
|
|
1888
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Enable Depth / Alpha Mask" })
|
|
1602
1889
|
] }),
|
|
1603
|
-
state.depthMask.enabled && /* @__PURE__ */ (0,
|
|
1604
|
-
/* @__PURE__ */ (0,
|
|
1605
|
-
/* @__PURE__ */ (0,
|
|
1606
|
-
/* @__PURE__ */ (0,
|
|
1890
|
+
state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1891
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
|
|
1892
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
|
|
1893
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1607
1894
|
"input",
|
|
1608
1895
|
{
|
|
1609
1896
|
type: "text",
|
|
@@ -1614,8 +1901,8 @@ var ImageEditor = ({
|
|
|
1614
1901
|
}
|
|
1615
1902
|
)
|
|
1616
1903
|
] }),
|
|
1617
|
-
/* @__PURE__ */ (0,
|
|
1618
|
-
/* @__PURE__ */ (0,
|
|
1904
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-2", children: [
|
|
1905
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1619
1906
|
"button",
|
|
1620
1907
|
{
|
|
1621
1908
|
type: "button",
|
|
@@ -1624,7 +1911,7 @@ var ImageEditor = ({
|
|
|
1624
1911
|
children: "Threshold Mode"
|
|
1625
1912
|
}
|
|
1626
1913
|
),
|
|
1627
|
-
/* @__PURE__ */ (0,
|
|
1914
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1628
1915
|
"button",
|
|
1629
1916
|
{
|
|
1630
1917
|
type: "button",
|
|
@@ -1634,12 +1921,12 @@ var ImageEditor = ({
|
|
|
1634
1921
|
}
|
|
1635
1922
|
)
|
|
1636
1923
|
] }),
|
|
1637
|
-
/* @__PURE__ */ (0,
|
|
1638
|
-
/* @__PURE__ */ (0,
|
|
1639
|
-
/* @__PURE__ */ (0,
|
|
1640
|
-
/* @__PURE__ */ (0,
|
|
1924
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
|
|
1925
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
1926
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Depth Start (Lower):" }),
|
|
1927
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
|
|
1641
1928
|
] }),
|
|
1642
|
-
/* @__PURE__ */ (0,
|
|
1929
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1643
1930
|
"input",
|
|
1644
1931
|
{
|
|
1645
1932
|
type: "range",
|
|
@@ -1653,12 +1940,12 @@ var ImageEditor = ({
|
|
|
1653
1940
|
}
|
|
1654
1941
|
)
|
|
1655
1942
|
] }),
|
|
1656
|
-
/* @__PURE__ */ (0,
|
|
1657
|
-
/* @__PURE__ */ (0,
|
|
1658
|
-
/* @__PURE__ */ (0,
|
|
1659
|
-
/* @__PURE__ */ (0,
|
|
1943
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
|
|
1944
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
1945
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Depth Stop (Upper):" }),
|
|
1946
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
|
|
1660
1947
|
] }),
|
|
1661
|
-
/* @__PURE__ */ (0,
|
|
1948
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1662
1949
|
"input",
|
|
1663
1950
|
{
|
|
1664
1951
|
type: "range",
|
|
@@ -1672,12 +1959,12 @@ var ImageEditor = ({
|
|
|
1672
1959
|
}
|
|
1673
1960
|
)
|
|
1674
1961
|
] }),
|
|
1675
|
-
/* @__PURE__ */ (0,
|
|
1676
|
-
/* @__PURE__ */ (0,
|
|
1677
|
-
/* @__PURE__ */ (0,
|
|
1678
|
-
/* @__PURE__ */ (0,
|
|
1962
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { children: [
|
|
1963
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
1964
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Softness:" }),
|
|
1965
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
|
|
1679
1966
|
] }),
|
|
1680
|
-
/* @__PURE__ */ (0,
|
|
1967
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1681
1968
|
"input",
|
|
1682
1969
|
{
|
|
1683
1970
|
type: "range",
|
|
@@ -1689,8 +1976,8 @@ var ImageEditor = ({
|
|
|
1689
1976
|
}
|
|
1690
1977
|
)
|
|
1691
1978
|
] }),
|
|
1692
|
-
/* @__PURE__ */ (0,
|
|
1693
|
-
/* @__PURE__ */ (0,
|
|
1979
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
|
|
1980
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1694
1981
|
"input",
|
|
1695
1982
|
{
|
|
1696
1983
|
type: "checkbox",
|
|
@@ -1699,52 +1986,66 @@ var ImageEditor = ({
|
|
|
1699
1986
|
className: "rounded accent-indigo-500"
|
|
1700
1987
|
}
|
|
1701
1988
|
),
|
|
1702
|
-
/* @__PURE__ */ (0,
|
|
1989
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Invert Mask" })
|
|
1703
1990
|
] })
|
|
1704
1991
|
] })
|
|
1705
1992
|
] }),
|
|
1706
|
-
activeTab === "
|
|
1707
|
-
/* @__PURE__ */ (0,
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1993
|
+
activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
1994
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1995
|
+
SelectionOptionsBar,
|
|
1996
|
+
{
|
|
1997
|
+
controller,
|
|
1998
|
+
options: selectionOptions,
|
|
1999
|
+
onOptionsChange: setSelectionOptions,
|
|
2000
|
+
selection: state.selection ?? null,
|
|
2001
|
+
quickMask: Boolean(state.quickMask)
|
|
2002
|
+
}
|
|
2003
|
+
),
|
|
2004
|
+
selectionError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
|
|
2005
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
|
|
2006
|
+
] }),
|
|
2007
|
+
activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
2008
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
2009
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2010
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
2011
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.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_runtime7.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" }) }),
|
|
1711
2012
|
"Background Removal"
|
|
1712
2013
|
] }),
|
|
1713
|
-
isRemovingBg && /* @__PURE__ */ (0,
|
|
2014
|
+
isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime7.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..." })
|
|
1714
2015
|
] }),
|
|
1715
|
-
/* @__PURE__ */ (0,
|
|
1716
|
-
/* @__PURE__ */ (0,
|
|
2016
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
|
|
2017
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1717
2018
|
"button",
|
|
1718
2019
|
{
|
|
1719
2020
|
type: "button",
|
|
1720
2021
|
onClick: handleRemoveBackground,
|
|
1721
2022
|
disabled: isRemovingBg || isInpainting,
|
|
1722
2023
|
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",
|
|
1723
|
-
children: isRemovingBg ? /* @__PURE__ */ (0,
|
|
1724
|
-
/* @__PURE__ */ (0,
|
|
2024
|
+
children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2025
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
1725
2026
|
"Removing Background..."
|
|
1726
|
-
] }) : /* @__PURE__ */ (0,
|
|
1727
|
-
/* @__PURE__ */ (0,
|
|
2027
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2028
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.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_runtime7.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" }) }),
|
|
1728
2029
|
"Remove Background"
|
|
1729
2030
|
] })
|
|
1730
2031
|
}
|
|
1731
2032
|
)
|
|
1732
2033
|
] }),
|
|
1733
|
-
/* @__PURE__ */ (0,
|
|
1734
|
-
/* @__PURE__ */ (0,
|
|
1735
|
-
/* @__PURE__ */ (0,
|
|
1736
|
-
/* @__PURE__ */ (0,
|
|
1737
|
-
/* @__PURE__ */ (0,
|
|
1738
|
-
/* @__PURE__ */ (0,
|
|
2034
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
2035
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2036
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
2037
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
2038
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.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" }),
|
|
2039
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "m14 7 3 3" })
|
|
1739
2040
|
] }),
|
|
1740
2041
|
"Generative Inpainting"
|
|
1741
2042
|
] }),
|
|
1742
|
-
isInpainting && /* @__PURE__ */ (0,
|
|
2043
|
+
isInpainting && /* @__PURE__ */ (0, import_jsx_runtime7.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..." })
|
|
1743
2044
|
] }),
|
|
1744
|
-
/* @__PURE__ */ (0,
|
|
1745
|
-
/* @__PURE__ */ (0,
|
|
1746
|
-
/* @__PURE__ */ (0,
|
|
1747
|
-
/* @__PURE__ */ (0,
|
|
2045
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
|
|
2046
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
2047
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
|
|
2048
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1748
2049
|
"textarea",
|
|
1749
2050
|
{
|
|
1750
2051
|
id: "ai-inpaint-prompt-react",
|
|
@@ -1756,10 +2057,10 @@ var ImageEditor = ({
|
|
|
1756
2057
|
}
|
|
1757
2058
|
)
|
|
1758
2059
|
] }),
|
|
1759
|
-
/* @__PURE__ */ (0,
|
|
1760
|
-
/* @__PURE__ */ (0,
|
|
1761
|
-
/* @__PURE__ */ (0,
|
|
1762
|
-
/* @__PURE__ */ (0,
|
|
2060
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
2061
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
|
|
2062
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
|
|
2063
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1763
2064
|
"button",
|
|
1764
2065
|
{
|
|
1765
2066
|
type: "button",
|
|
@@ -1772,7 +2073,7 @@ var ImageEditor = ({
|
|
|
1772
2073
|
]
|
|
1773
2074
|
}
|
|
1774
2075
|
),
|
|
1775
|
-
/* @__PURE__ */ (0,
|
|
2076
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1776
2077
|
"button",
|
|
1777
2078
|
{
|
|
1778
2079
|
type: "button",
|
|
@@ -1787,25 +2088,25 @@ var ImageEditor = ({
|
|
|
1787
2088
|
)
|
|
1788
2089
|
] })
|
|
1789
2090
|
] }),
|
|
1790
|
-
/* @__PURE__ */ (0,
|
|
2091
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1791
2092
|
"button",
|
|
1792
2093
|
{
|
|
1793
2094
|
type: "button",
|
|
1794
2095
|
onClick: handleInpaint,
|
|
1795
2096
|
disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
|
|
1796
2097
|
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",
|
|
1797
|
-
children: isInpainting ? /* @__PURE__ */ (0,
|
|
1798
|
-
/* @__PURE__ */ (0,
|
|
2098
|
+
children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2099
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
1799
2100
|
"Generating Inpaint..."
|
|
1800
|
-
] }) : /* @__PURE__ */ (0,
|
|
1801
|
-
/* @__PURE__ */ (0,
|
|
2101
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2102
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.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_runtime7.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" }) }),
|
|
1802
2103
|
"Apply Inpainting"
|
|
1803
2104
|
] })
|
|
1804
2105
|
}
|
|
1805
2106
|
)
|
|
1806
2107
|
] }),
|
|
1807
|
-
aiError && /* @__PURE__ */ (0,
|
|
1808
|
-
aiSuccess && /* @__PURE__ */ (0,
|
|
2108
|
+
aiError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
|
|
2109
|
+
aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
|
|
1809
2110
|
] })
|
|
1810
2111
|
] })
|
|
1811
2112
|
] })
|
|
@@ -1820,6 +2121,8 @@ var ImageEditor = ({
|
|
|
1820
2121
|
CurvesEditor,
|
|
1821
2122
|
Histogram,
|
|
1822
2123
|
ImageEditor,
|
|
2124
|
+
RefineEdgePanel,
|
|
2125
|
+
SelectionOptionsBar,
|
|
1823
2126
|
useImageEditor,
|
|
1824
2127
|
useImageHistogram
|
|
1825
2128
|
});
|