@pixerate/editor-react 0.63.0 → 0.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-QJSMW4CM.js → chunk-M4WLX3IR.js} +582 -375
- package/dist/chunk-M4WLX3IR.js.map +1 -0
- package/dist/image-editor/index.cjs +618 -411
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +18 -2
- package/dist/image-editor/index.d.ts +18 -2
- package/dist/image-editor/index.js +3 -1
- package/dist/index.cjs +1036 -829
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-QJSMW4CM.js.map +0 -1
|
@@ -159,7 +159,7 @@ function useImageEditor(options = {}) {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
// src/image-editor/ImageEditor.tsx
|
|
162
|
-
import
|
|
162
|
+
import React9, { useRef as useRef5, useEffect as useEffect7, useState as useState10, useCallback as useCallback2 } from "react";
|
|
163
163
|
import {
|
|
164
164
|
canvasToImagePoint,
|
|
165
165
|
hitTestCrop,
|
|
@@ -626,7 +626,196 @@ var AdjustmentLayersPanel = ({ controller, layers: layersProp, histogram }) => {
|
|
|
626
626
|
};
|
|
627
627
|
|
|
628
628
|
// src/image-editor/LayersPanel.tsx
|
|
629
|
+
import { useEffect as useEffect5, useRef as useRef4, useState as useState6 } from "react";
|
|
630
|
+
|
|
631
|
+
// src/image-editor/LayerEffectsPanel.tsx
|
|
629
632
|
import { useEffect as useEffect4, useRef as useRef3, useState as useState5 } from "react";
|
|
633
|
+
import { LAYER_EFFECT_MENU, effectControlChange, layerEffectControls, layerEffectsPanel } from "@pixerate/editor/image-editor";
|
|
634
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
635
|
+
var button = "px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40";
|
|
636
|
+
var LayerEffectsPanel = ({ controller, layerId, className }) => {
|
|
637
|
+
const [, setTick] = useState5(0);
|
|
638
|
+
useEffect4(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
639
|
+
const [open, setOpen] = useState5(null);
|
|
640
|
+
const [error, setError] = useState5(null);
|
|
641
|
+
const commitNext = useRef3(true);
|
|
642
|
+
const layer = layerId ? controller.getLayer(layerId) : controller.getActiveLayer();
|
|
643
|
+
const model = layerEffectsPanel(layer);
|
|
644
|
+
const id = layer?.id;
|
|
645
|
+
const attempt = (fn) => {
|
|
646
|
+
try {
|
|
647
|
+
setError(null);
|
|
648
|
+
fn();
|
|
649
|
+
} catch (err) {
|
|
650
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
const sliderEvents = {
|
|
654
|
+
onPointerDown: () => commitNext.current = true,
|
|
655
|
+
onPointerUp: () => commitNext.current = true,
|
|
656
|
+
onKeyDown: () => commitNext.current = true
|
|
657
|
+
};
|
|
658
|
+
if (!model.available || !id) {
|
|
659
|
+
return /* @__PURE__ */ jsx5("div", { className: `text-xs text-slate-500 ${className ?? ""}`, "data-testid": "layer-effects", children: model.reason });
|
|
660
|
+
}
|
|
661
|
+
const effects = controller.getLayerEffects(id);
|
|
662
|
+
const patterns = controller.getDocumentPatterns();
|
|
663
|
+
const change = (effectId, control, value, drag = false) => attempt(() => {
|
|
664
|
+
const effect = controller.getLayerEffects(id).items.find((e) => e.id === effectId);
|
|
665
|
+
controller.updateLayerEffect(id, effectId, effectControlChange(effect, control.key, value, patterns), drag ? commitNext.current : true);
|
|
666
|
+
if (drag) commitNext.current = false;
|
|
667
|
+
});
|
|
668
|
+
const renderControl = (effectId, c) => {
|
|
669
|
+
const label = `${c.label}`;
|
|
670
|
+
switch (c.type) {
|
|
671
|
+
case "range": {
|
|
672
|
+
const k = c.percent ? 100 : 1;
|
|
673
|
+
const shown = Math.round(c.value * k * 100) / 100;
|
|
674
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex flex-col gap-0.5", children: [
|
|
675
|
+
/* @__PURE__ */ jsxs5("span", { className: "text-slate-400", children: [
|
|
676
|
+
label,
|
|
677
|
+
" ",
|
|
678
|
+
shown,
|
|
679
|
+
c.unit
|
|
680
|
+
] }),
|
|
681
|
+
/* @__PURE__ */ jsx5(
|
|
682
|
+
"input",
|
|
683
|
+
{
|
|
684
|
+
type: "range",
|
|
685
|
+
"aria-label": label,
|
|
686
|
+
min: c.min * k,
|
|
687
|
+
max: c.max * k,
|
|
688
|
+
step: c.step * k,
|
|
689
|
+
value: shown,
|
|
690
|
+
disabled: model.readOnly,
|
|
691
|
+
...sliderEvents,
|
|
692
|
+
onChange: (e) => change(effectId, c, Number(e.target.value) / k, true),
|
|
693
|
+
className: "accent-indigo-500"
|
|
694
|
+
}
|
|
695
|
+
)
|
|
696
|
+
] }, c.key);
|
|
697
|
+
}
|
|
698
|
+
case "color":
|
|
699
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
700
|
+
/* @__PURE__ */ jsx5("input", { type: "color", "aria-label": label, value: c.value, disabled: model.readOnly, onChange: (e) => change(effectId, c, e.target.value) }),
|
|
701
|
+
label
|
|
702
|
+
] }, c.key);
|
|
703
|
+
case "checkbox":
|
|
704
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
705
|
+
/* @__PURE__ */ jsx5("input", { type: "checkbox", "aria-label": label, checked: c.value, disabled: model.readOnly, onChange: (e) => change(effectId, c, e.target.checked), className: "accent-indigo-500" }),
|
|
706
|
+
label
|
|
707
|
+
] }, c.key);
|
|
708
|
+
case "select":
|
|
709
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex flex-col gap-0.5", children: [
|
|
710
|
+
/* @__PURE__ */ jsx5("span", { className: "text-slate-400", children: label }),
|
|
711
|
+
/* @__PURE__ */ jsx5(
|
|
712
|
+
"select",
|
|
713
|
+
{
|
|
714
|
+
"aria-label": label,
|
|
715
|
+
value: c.value,
|
|
716
|
+
disabled: model.readOnly,
|
|
717
|
+
onChange: (e) => change(effectId, c, e.target.value),
|
|
718
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
719
|
+
children: c.options.map((o) => /* @__PURE__ */ jsx5("option", { value: o.value, children: o.label }, o.value))
|
|
720
|
+
}
|
|
721
|
+
)
|
|
722
|
+
] }, c.key);
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
return /* @__PURE__ */ jsxs5("div", { className: `flex flex-col gap-1.5 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layer-effects", "aria-label": "Layer effects", role: "group", children: [
|
|
726
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
727
|
+
/* @__PURE__ */ jsx5("span", { className: "font-semibold text-slate-300", children: "fx Effects" }),
|
|
728
|
+
/* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-1 text-slate-300", children: [
|
|
729
|
+
/* @__PURE__ */ jsx5(
|
|
730
|
+
"input",
|
|
731
|
+
{
|
|
732
|
+
type: "checkbox",
|
|
733
|
+
"aria-label": "Effects on",
|
|
734
|
+
checked: model.enabled,
|
|
735
|
+
disabled: model.readOnly,
|
|
736
|
+
onChange: (e) => attempt(() => controller.setLayerEffectsEnabled(id, e.target.checked)),
|
|
737
|
+
className: "accent-indigo-500"
|
|
738
|
+
}
|
|
739
|
+
),
|
|
740
|
+
"On"
|
|
741
|
+
] }),
|
|
742
|
+
/* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-1 text-slate-400", children: [
|
|
743
|
+
"Scale",
|
|
744
|
+
/* @__PURE__ */ jsx5(
|
|
745
|
+
"input",
|
|
746
|
+
{
|
|
747
|
+
type: "number",
|
|
748
|
+
"aria-label": "Scale effects",
|
|
749
|
+
min: 1,
|
|
750
|
+
max: 1e3,
|
|
751
|
+
step: 1,
|
|
752
|
+
value: Math.round(model.scale * 100),
|
|
753
|
+
disabled: model.readOnly,
|
|
754
|
+
onChange: (e) => {
|
|
755
|
+
const v = Number(e.target.value);
|
|
756
|
+
if (v >= 1 && v <= 1e3) attempt(() => controller.setLayerEffectsEnabled(id, model.enabled, v / 100));
|
|
757
|
+
},
|
|
758
|
+
className: "w-14 bg-slate-800 border border-slate-700 rounded px-1"
|
|
759
|
+
}
|
|
760
|
+
),
|
|
761
|
+
"%"
|
|
762
|
+
] }),
|
|
763
|
+
/* @__PURE__ */ jsxs5(
|
|
764
|
+
"select",
|
|
765
|
+
{
|
|
766
|
+
"aria-label": "Add effect",
|
|
767
|
+
value: "",
|
|
768
|
+
disabled: model.readOnly,
|
|
769
|
+
onChange: (e) => {
|
|
770
|
+
const kind = e.target.value;
|
|
771
|
+
if (!kind) return;
|
|
772
|
+
attempt(() => setOpen(controller.addLayerEffect(id, kind).effect.id));
|
|
773
|
+
},
|
|
774
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
775
|
+
children: [
|
|
776
|
+
/* @__PURE__ */ jsx5("option", { value: "", children: "Add effect\u2026" }),
|
|
777
|
+
LAYER_EFFECT_MENU.map((m) => /* @__PURE__ */ jsx5("option", { value: m.kind, children: m.label }, m.kind))
|
|
778
|
+
]
|
|
779
|
+
}
|
|
780
|
+
)
|
|
781
|
+
] }),
|
|
782
|
+
model.readOnly && model.reason && /* @__PURE__ */ jsx5("p", { className: "text-slate-500", children: model.reason }),
|
|
783
|
+
/* @__PURE__ */ jsx5("ul", { className: "flex flex-col gap-1", "aria-label": "Effects", children: model.rows.map((row) => {
|
|
784
|
+
const effect = effects.items.find((e) => e.id === row.id);
|
|
785
|
+
const expanded = open === row.id;
|
|
786
|
+
return /* @__PURE__ */ jsxs5("li", { "data-effect-id": row.id, className: "rounded bg-slate-900/60 ring-1 ring-slate-800", children: [
|
|
787
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5 px-1.5 py-1", children: [
|
|
788
|
+
/* @__PURE__ */ jsx5(
|
|
789
|
+
"input",
|
|
790
|
+
{
|
|
791
|
+
type: "checkbox",
|
|
792
|
+
"aria-label": `${row.label} on`,
|
|
793
|
+
checked: row.enabled,
|
|
794
|
+
disabled: model.readOnly,
|
|
795
|
+
onChange: (e) => attempt(() => controller.updateLayerEffect(id, row.id, { enabled: e.target.checked })),
|
|
796
|
+
className: "accent-indigo-500"
|
|
797
|
+
}
|
|
798
|
+
),
|
|
799
|
+
/* @__PURE__ */ jsx5(
|
|
800
|
+
"button",
|
|
801
|
+
{
|
|
802
|
+
type: "button",
|
|
803
|
+
"aria-expanded": expanded,
|
|
804
|
+
className: `flex-1 text-left ${row.enabled && model.enabled ? "" : "text-slate-500"}`,
|
|
805
|
+
onClick: () => setOpen(expanded ? null : row.id),
|
|
806
|
+
children: row.label
|
|
807
|
+
}
|
|
808
|
+
),
|
|
809
|
+
/* @__PURE__ */ jsx5("button", { type: "button", className: button, "aria-label": `Remove ${row.label}`, disabled: model.readOnly, onClick: () => attempt(() => controller.removeLayerEffect(id, row.id)), children: "\u2715" })
|
|
810
|
+
] }),
|
|
811
|
+
expanded && /* @__PURE__ */ jsx5("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 px-1.5 pb-1.5", "data-testid": "effect-settings", children: layerEffectControls(effect, patterns).map((c) => renderControl(row.id, c)) })
|
|
812
|
+
] }, row.id);
|
|
813
|
+
}) }),
|
|
814
|
+
error && /* @__PURE__ */ jsx5("p", { role: "alert", className: "text-rose-400", children: error })
|
|
815
|
+
] });
|
|
816
|
+
};
|
|
817
|
+
|
|
818
|
+
// src/image-editor/LayersPanel.tsx
|
|
630
819
|
import {
|
|
631
820
|
BLEND_MODES as BLEND_MODES2,
|
|
632
821
|
PSD_FILE_ACCEPT,
|
|
@@ -635,11 +824,12 @@ import {
|
|
|
635
824
|
dropZone,
|
|
636
825
|
openPsdFile,
|
|
637
826
|
layerBadge,
|
|
827
|
+
layerEffectsBadge,
|
|
638
828
|
layerMenu,
|
|
639
829
|
layerPanelRows,
|
|
640
830
|
runLayerMenuAction
|
|
641
831
|
} from "@pixerate/editor/image-editor";
|
|
642
|
-
import { Fragment, jsx as
|
|
832
|
+
import { Fragment, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
643
833
|
var iconButton = "px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40";
|
|
644
834
|
var rowClass = (active) => `flex items-center gap-1.5 px-1.5 py-1 rounded cursor-pointer select-none ${active ? "bg-indigo-600/30 ring-1 ring-indigo-500" : "hover:bg-slate-800"}`;
|
|
645
835
|
var Thumbnail = ({
|
|
@@ -650,8 +840,8 @@ var Thumbnail = ({
|
|
|
650
840
|
selected,
|
|
651
841
|
testId
|
|
652
842
|
}) => {
|
|
653
|
-
const ref =
|
|
654
|
-
|
|
843
|
+
const ref = useRef4(null);
|
|
844
|
+
useEffect5(() => {
|
|
655
845
|
const canvas = ref.current;
|
|
656
846
|
const ctx = canvas?.getContext("2d");
|
|
657
847
|
if (!canvas || !ctx || !pixels || typeof ctx.createImageData !== "function") return;
|
|
@@ -661,7 +851,7 @@ var Thumbnail = ({
|
|
|
661
851
|
img.data.set(pixels.data);
|
|
662
852
|
ctx.putImageData(img, 0, 0);
|
|
663
853
|
}, [pixels]);
|
|
664
|
-
return /* @__PURE__ */
|
|
854
|
+
return /* @__PURE__ */ jsx6(
|
|
665
855
|
"canvas",
|
|
666
856
|
{
|
|
667
857
|
ref,
|
|
@@ -674,15 +864,15 @@ var Thumbnail = ({
|
|
|
674
864
|
}
|
|
675
865
|
);
|
|
676
866
|
};
|
|
677
|
-
var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", className }) => {
|
|
678
|
-
const [, setTick] =
|
|
679
|
-
|
|
680
|
-
const [error, setError] =
|
|
681
|
-
const [renaming, setRenaming] =
|
|
682
|
-
const [menu, setMenu] =
|
|
683
|
-
const [drag, setDrag] =
|
|
684
|
-
const [psdNotes, setPsdNotes] =
|
|
685
|
-
const fileInput =
|
|
867
|
+
var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", effects = true, className }) => {
|
|
868
|
+
const [, setTick] = useState6(0);
|
|
869
|
+
useEffect5(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
870
|
+
const [error, setError] = useState6(null);
|
|
871
|
+
const [renaming, setRenaming] = useState6(null);
|
|
872
|
+
const [menu, setMenu] = useState6(null);
|
|
873
|
+
const [drag, setDrag] = useState6(null);
|
|
874
|
+
const [psdNotes, setPsdNotes] = useState6([]);
|
|
875
|
+
const fileInput = useRef4(null);
|
|
686
876
|
const psdTask = async (fn) => {
|
|
687
877
|
try {
|
|
688
878
|
setError(null);
|
|
@@ -691,7 +881,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
691
881
|
setError(err instanceof Error ? err.message : String(err));
|
|
692
882
|
}
|
|
693
883
|
};
|
|
694
|
-
const commitNext =
|
|
884
|
+
const commitNext = useRef4(true);
|
|
695
885
|
const state = controller.getState();
|
|
696
886
|
const rows = layerPanelRows(state.layers, state.activeLayerId);
|
|
697
887
|
const active = controller.getActiveLayer();
|
|
@@ -729,14 +919,14 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
729
919
|
const thumb = (layer) => layer.type === "pixel" ? controller.getLayerThumbnail(layer.id, { maxSide: 64 }) : null;
|
|
730
920
|
const maskThumb = (layer) => layer.mask && !layer.mask.source ? controller.getLayerThumbnail(layer.id, { maxSide: 64, mask: true }) : null;
|
|
731
921
|
const locked = (layer) => Boolean(layer.locks?.all || layer.locks?.pixels || layer.locks?.position || layer.locks?.transparency);
|
|
732
|
-
return /* @__PURE__ */
|
|
733
|
-
/* @__PURE__ */
|
|
734
|
-
/* @__PURE__ */
|
|
735
|
-
/* @__PURE__ */
|
|
736
|
-
/* @__PURE__ */
|
|
737
|
-
/* @__PURE__ */
|
|
738
|
-
/* @__PURE__ */
|
|
739
|
-
/* @__PURE__ */
|
|
922
|
+
return /* @__PURE__ */ jsxs6("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layers-panel", onClick: () => menu && setMenu(null), children: [
|
|
923
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap items-center gap-1", role: "toolbar", "aria-label": "Layer actions", children: [
|
|
924
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, onClick: () => run("new-layer"), children: "New Layer" }),
|
|
925
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, onClick: () => run("new-group"), children: "New Group" }),
|
|
926
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("duplicate"), children: "Duplicate" }),
|
|
927
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("add-mask"), children: "Add Mask" }),
|
|
928
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("delete"), children: "Delete" }),
|
|
929
|
+
/* @__PURE__ */ jsx6(
|
|
740
930
|
"button",
|
|
741
931
|
{
|
|
742
932
|
type: "button",
|
|
@@ -751,10 +941,10 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
751
941
|
children: "\u22EF"
|
|
752
942
|
}
|
|
753
943
|
),
|
|
754
|
-
psd && /* @__PURE__ */
|
|
755
|
-
/* @__PURE__ */
|
|
756
|
-
/* @__PURE__ */
|
|
757
|
-
/* @__PURE__ */
|
|
944
|
+
psd && /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
945
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, onClick: () => fileInput.current?.click(), children: "Open PSD\u2026" }),
|
|
946
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, onClick: () => psdTask(async () => (await downloadPsd(controller, psdFileName)).warnings), children: "Export PSD" }),
|
|
947
|
+
/* @__PURE__ */ jsx6(
|
|
758
948
|
"input",
|
|
759
949
|
{
|
|
760
950
|
ref: fileInput,
|
|
@@ -772,18 +962,18 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
772
962
|
)
|
|
773
963
|
] })
|
|
774
964
|
] }),
|
|
775
|
-
psdNotes.length > 0 && /* @__PURE__ */
|
|
776
|
-
psdNotes.map((n) => /* @__PURE__ */
|
|
777
|
-
/* @__PURE__ */
|
|
965
|
+
psdNotes.length > 0 && /* @__PURE__ */ jsxs6("ul", { className: "rounded bg-amber-900/30 text-amber-200 px-2 py-1 space-y-0.5", "data-testid": "psd-warnings", "aria-label": "PSD warnings", children: [
|
|
966
|
+
psdNotes.map((n) => /* @__PURE__ */ jsx6("li", { children: n }, n)),
|
|
967
|
+
/* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsx6("button", { type: "button", className: "underline", onClick: () => setPsdNotes([]), children: "Dismiss" }) })
|
|
778
968
|
] }),
|
|
779
|
-
active && /* @__PURE__ */
|
|
780
|
-
/* @__PURE__ */
|
|
781
|
-
/* @__PURE__ */
|
|
969
|
+
active && /* @__PURE__ */ jsxs6("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 items-center", "data-testid": "layer-properties", children: [
|
|
970
|
+
/* @__PURE__ */ jsxs6("label", { className: "flex flex-col gap-0.5", children: [
|
|
971
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-slate-400", children: [
|
|
782
972
|
"Opacity ",
|
|
783
973
|
Math.round(active.opacity * 100),
|
|
784
974
|
"%"
|
|
785
975
|
] }),
|
|
786
|
-
/* @__PURE__ */
|
|
976
|
+
/* @__PURE__ */ jsx6(
|
|
787
977
|
"input",
|
|
788
978
|
{
|
|
789
979
|
type: "range",
|
|
@@ -797,13 +987,13 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
797
987
|
}
|
|
798
988
|
)
|
|
799
989
|
] }),
|
|
800
|
-
/* @__PURE__ */
|
|
801
|
-
/* @__PURE__ */
|
|
990
|
+
/* @__PURE__ */ jsxs6("label", { className: "flex flex-col gap-0.5", children: [
|
|
991
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-slate-400", children: [
|
|
802
992
|
"Fill ",
|
|
803
993
|
Math.round(((active.type === "pixel" ? active.fillOpacity : void 0) ?? 1) * 100),
|
|
804
994
|
"%"
|
|
805
995
|
] }),
|
|
806
|
-
/* @__PURE__ */
|
|
996
|
+
/* @__PURE__ */ jsx6(
|
|
807
997
|
"input",
|
|
808
998
|
{
|
|
809
999
|
type: "range",
|
|
@@ -818,7 +1008,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
818
1008
|
}
|
|
819
1009
|
)
|
|
820
1010
|
] }),
|
|
821
|
-
/* @__PURE__ */
|
|
1011
|
+
/* @__PURE__ */ jsxs6(
|
|
822
1012
|
"select",
|
|
823
1013
|
{
|
|
824
1014
|
"aria-label": "Layer blend mode",
|
|
@@ -826,13 +1016,13 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
826
1016
|
value: active.blend,
|
|
827
1017
|
onChange: (e) => attempt(() => controller.setLayerProperties(active.id, { blend: e.target.value })),
|
|
828
1018
|
children: [
|
|
829
|
-
active.type === "group" && /* @__PURE__ */
|
|
830
|
-
BLEND_MODES2.map((m) => /* @__PURE__ */
|
|
1019
|
+
active.type === "group" && /* @__PURE__ */ jsx6("option", { value: "pass-through", children: "Pass Through" }),
|
|
1020
|
+
BLEND_MODES2.map((m) => /* @__PURE__ */ jsx6("option", { value: m.id, children: m.label }, m.id))
|
|
831
1021
|
]
|
|
832
1022
|
}
|
|
833
1023
|
),
|
|
834
|
-
/* @__PURE__ */
|
|
835
|
-
/* @__PURE__ */
|
|
1024
|
+
/* @__PURE__ */ jsxs6("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
1025
|
+
/* @__PURE__ */ jsx6(
|
|
836
1026
|
"input",
|
|
837
1027
|
{
|
|
838
1028
|
type: "checkbox",
|
|
@@ -844,8 +1034,8 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
844
1034
|
),
|
|
845
1035
|
"Clip to below"
|
|
846
1036
|
] }),
|
|
847
|
-
/* @__PURE__ */
|
|
848
|
-
/* @__PURE__ */
|
|
1037
|
+
/* @__PURE__ */ jsx6("div", { className: "col-span-2 flex flex-wrap gap-2 text-slate-400", role: "group", "aria-label": "Layer locks", children: ["pixels", "transparency", "position", "all"].map((k) => /* @__PURE__ */ jsxs6("label", { className: "flex items-center gap-1", children: [
|
|
1038
|
+
/* @__PURE__ */ jsx6(
|
|
849
1039
|
"input",
|
|
850
1040
|
{
|
|
851
1041
|
type: "checkbox",
|
|
@@ -858,9 +1048,10 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
858
1048
|
k
|
|
859
1049
|
] }, k)) })
|
|
860
1050
|
] }),
|
|
861
|
-
/* @__PURE__ */
|
|
1051
|
+
effects && active && active.type !== "adjustment" && /* @__PURE__ */ jsx6(LayerEffectsPanel, { controller, className: "border-t border-slate-800 pt-1.5" }),
|
|
1052
|
+
/* @__PURE__ */ jsx6("ul", { className: "flex flex-col gap-0.5", role: "tree", "aria-label": "Layers", children: rows.map((row) => {
|
|
862
1053
|
const { layer } = row;
|
|
863
|
-
return /* @__PURE__ */
|
|
1054
|
+
return /* @__PURE__ */ jsxs6(
|
|
864
1055
|
"li",
|
|
865
1056
|
{
|
|
866
1057
|
role: "treeitem",
|
|
@@ -890,7 +1081,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
890
1081
|
className: rowClass(row.active),
|
|
891
1082
|
style: { paddingLeft: 6 + row.depth * 14 },
|
|
892
1083
|
children: [
|
|
893
|
-
/* @__PURE__ */
|
|
1084
|
+
/* @__PURE__ */ jsx6(
|
|
894
1085
|
"button",
|
|
895
1086
|
{
|
|
896
1087
|
type: "button",
|
|
@@ -904,7 +1095,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
904
1095
|
children: layer.visible ? "\u25CF" : "\u25CB"
|
|
905
1096
|
}
|
|
906
1097
|
),
|
|
907
|
-
layer.type === "group" && /* @__PURE__ */
|
|
1098
|
+
layer.type === "group" && /* @__PURE__ */ jsx6(
|
|
908
1099
|
"button",
|
|
909
1100
|
{
|
|
910
1101
|
type: "button",
|
|
@@ -917,8 +1108,8 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
917
1108
|
children: layer.collapsed ? "\u25B8" : "\u25BE"
|
|
918
1109
|
}
|
|
919
1110
|
),
|
|
920
|
-
row.clipped && /* @__PURE__ */
|
|
921
|
-
layer.type === "pixel" ? /* @__PURE__ */
|
|
1111
|
+
row.clipped && /* @__PURE__ */ jsx6("span", { className: "text-slate-500", "aria-label": "Clipped", children: "\u21B3" }),
|
|
1112
|
+
layer.type === "pixel" ? /* @__PURE__ */ jsx6(
|
|
922
1113
|
Thumbnail,
|
|
923
1114
|
{
|
|
924
1115
|
pixels: thumb(layer),
|
|
@@ -926,7 +1117,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
926
1117
|
label: `${row.label} pixels`,
|
|
927
1118
|
selected: row.active && state.activeTarget === "pixels" && Boolean(layer.mask)
|
|
928
1119
|
}
|
|
929
|
-
) : /* @__PURE__ */
|
|
1120
|
+
) : /* @__PURE__ */ jsx6(
|
|
930
1121
|
"span",
|
|
931
1122
|
{
|
|
932
1123
|
className: "shrink-0 grid place-items-center rounded bg-slate-800 text-[9px] text-slate-400 ring-1 ring-slate-700",
|
|
@@ -934,7 +1125,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
934
1125
|
children: layerBadge(layer)
|
|
935
1126
|
}
|
|
936
1127
|
),
|
|
937
|
-
layer.mask && /* @__PURE__ */
|
|
1128
|
+
layer.mask && /* @__PURE__ */ jsx6(
|
|
938
1129
|
Thumbnail,
|
|
939
1130
|
{
|
|
940
1131
|
pixels: maskThumb(layer),
|
|
@@ -949,7 +1140,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
949
1140
|
}
|
|
950
1141
|
}
|
|
951
1142
|
),
|
|
952
|
-
renaming === layer.id ? /* @__PURE__ */
|
|
1143
|
+
renaming === layer.id ? /* @__PURE__ */ jsx6(
|
|
953
1144
|
"input",
|
|
954
1145
|
{
|
|
955
1146
|
autoFocus: true,
|
|
@@ -966,7 +1157,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
966
1157
|
if (e.key === "Escape") setRenaming(null);
|
|
967
1158
|
}
|
|
968
1159
|
}
|
|
969
|
-
) : /* @__PURE__ */
|
|
1160
|
+
) : /* @__PURE__ */ jsx6(
|
|
970
1161
|
"span",
|
|
971
1162
|
{
|
|
972
1163
|
className: `flex-1 min-w-0 truncate ${layer.visible ? "" : "text-slate-500"}`,
|
|
@@ -977,15 +1168,30 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
977
1168
|
children: row.label
|
|
978
1169
|
}
|
|
979
1170
|
),
|
|
980
|
-
|
|
981
|
-
|
|
1171
|
+
layerEffectsBadge(layer) && /* @__PURE__ */ jsx6(
|
|
1172
|
+
"button",
|
|
1173
|
+
{
|
|
1174
|
+
type: "button",
|
|
1175
|
+
"data-testid": "layer-fx-badge",
|
|
1176
|
+
"aria-label": layerEffectsBadge(layer) === "on" ? `Turn effects off for ${row.label}` : `Turn effects on for ${row.label}`,
|
|
1177
|
+
"aria-pressed": layerEffectsBadge(layer) === "on",
|
|
1178
|
+
className: `text-[9px] italic font-semibold ${layerEffectsBadge(layer) === "on" ? "text-indigo-300" : "text-slate-600 line-through"}`,
|
|
1179
|
+
onClick: (e) => {
|
|
1180
|
+
e.stopPropagation();
|
|
1181
|
+
attempt(() => controller.setLayerEffectsEnabled(layer.id, layerEffectsBadge(layer) !== "on"));
|
|
1182
|
+
},
|
|
1183
|
+
children: "fx"
|
|
1184
|
+
}
|
|
1185
|
+
),
|
|
1186
|
+
locked(layer) && /* @__PURE__ */ jsx6("span", { "aria-label": "Locked", className: "text-slate-400", children: "\u{1F512}" }),
|
|
1187
|
+
layer.blend !== "normal" && layer.blend !== "pass-through" && /* @__PURE__ */ jsx6("span", { className: "text-[9px] text-slate-500", children: layer.blend })
|
|
982
1188
|
]
|
|
983
1189
|
},
|
|
984
1190
|
layer.id
|
|
985
1191
|
);
|
|
986
1192
|
}) }),
|
|
987
|
-
error && /* @__PURE__ */
|
|
988
|
-
menu && /* @__PURE__ */
|
|
1193
|
+
error && /* @__PURE__ */ jsx6("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
1194
|
+
menu && /* @__PURE__ */ jsx6(
|
|
989
1195
|
"div",
|
|
990
1196
|
{
|
|
991
1197
|
role: "menu",
|
|
@@ -994,7 +1200,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
994
1200
|
style: { left: menu.x, top: menu.y },
|
|
995
1201
|
onClick: (e) => e.stopPropagation(),
|
|
996
1202
|
onKeyDown: (e) => e.key === "Escape" && setMenu(null),
|
|
997
|
-
children: layerMenu(controller).map((item) => /* @__PURE__ */
|
|
1203
|
+
children: layerMenu(controller).map((item) => /* @__PURE__ */ jsx6(
|
|
998
1204
|
"button",
|
|
999
1205
|
{
|
|
1000
1206
|
type: "button",
|
|
@@ -1012,14 +1218,14 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
1012
1218
|
};
|
|
1013
1219
|
|
|
1014
1220
|
// src/image-editor/BrushOptionsBar.tsx
|
|
1015
|
-
import { useEffect as
|
|
1221
|
+
import { useEffect as useEffect6, useState as useState7 } from "react";
|
|
1016
1222
|
import { BRUSH_OPTION_CONTROLS, MIXER_MIXING_OPTIONS, MIXER_OPTION_CONTROLS, PAINT_TOOLS, rgbUnitToHex } from "@pixerate/editor/image-editor";
|
|
1017
|
-
import { jsx as
|
|
1223
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1018
1224
|
var chip = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
|
|
1019
1225
|
var BrushOptionsBar = ({ controller, className }) => {
|
|
1020
|
-
const [, setTick] =
|
|
1021
|
-
|
|
1022
|
-
const [error, setError] =
|
|
1226
|
+
const [, setTick] = useState7(0);
|
|
1227
|
+
useEffect6(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
1228
|
+
const [error, setError] = useState7(null);
|
|
1023
1229
|
const state = controller.getState();
|
|
1024
1230
|
const { brush, foreground, background, mixer, mixerLoad } = state.paint;
|
|
1025
1231
|
const attempt = (fn) => {
|
|
@@ -1030,8 +1236,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1030
1236
|
setError(err instanceof Error ? err.message : String(err));
|
|
1031
1237
|
}
|
|
1032
1238
|
};
|
|
1033
|
-
return /* @__PURE__ */
|
|
1034
|
-
/* @__PURE__ */
|
|
1239
|
+
return /* @__PURE__ */ jsxs7("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
|
|
1240
|
+
/* @__PURE__ */ jsx7("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Paint tools", children: PAINT_TOOLS.map((t) => /* @__PURE__ */ jsx7(
|
|
1035
1241
|
"button",
|
|
1036
1242
|
{
|
|
1037
1243
|
type: "button",
|
|
@@ -1043,9 +1249,9 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1043
1249
|
},
|
|
1044
1250
|
t.id
|
|
1045
1251
|
)) }),
|
|
1046
|
-
/* @__PURE__ */
|
|
1047
|
-
/* @__PURE__ */
|
|
1048
|
-
/* @__PURE__ */
|
|
1252
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
|
|
1253
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1", children: [
|
|
1254
|
+
/* @__PURE__ */ jsx7(
|
|
1049
1255
|
"input",
|
|
1050
1256
|
{
|
|
1051
1257
|
type: "color",
|
|
@@ -1055,10 +1261,10 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1055
1261
|
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
1056
1262
|
}
|
|
1057
1263
|
),
|
|
1058
|
-
/* @__PURE__ */
|
|
1264
|
+
/* @__PURE__ */ jsx7("span", { className: "text-slate-400", children: "FG" })
|
|
1059
1265
|
] }),
|
|
1060
|
-
/* @__PURE__ */
|
|
1061
|
-
/* @__PURE__ */
|
|
1266
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1", children: [
|
|
1267
|
+
/* @__PURE__ */ jsx7(
|
|
1062
1268
|
"input",
|
|
1063
1269
|
{
|
|
1064
1270
|
type: "color",
|
|
@@ -1068,12 +1274,12 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1068
1274
|
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
1069
1275
|
}
|
|
1070
1276
|
),
|
|
1071
|
-
/* @__PURE__ */
|
|
1277
|
+
/* @__PURE__ */ jsx7("span", { className: "text-slate-400", children: "BG" })
|
|
1072
1278
|
] }),
|
|
1073
|
-
/* @__PURE__ */
|
|
1074
|
-
/* @__PURE__ */
|
|
1279
|
+
/* @__PURE__ */ jsx7("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
|
|
1280
|
+
/* @__PURE__ */ jsx7("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" })
|
|
1075
1281
|
] }),
|
|
1076
|
-
BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */
|
|
1282
|
+
BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ jsx7(
|
|
1077
1283
|
ControlSlider,
|
|
1078
1284
|
{
|
|
1079
1285
|
spec,
|
|
@@ -1082,9 +1288,9 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1082
1288
|
},
|
|
1083
1289
|
spec.id
|
|
1084
1290
|
)),
|
|
1085
|
-
state.activeTool === "mixer" && /* @__PURE__ */
|
|
1086
|
-
/* @__PURE__ */
|
|
1087
|
-
/* @__PURE__ */
|
|
1291
|
+
state.activeTool === "mixer" && /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Mixer Brush", "data-testid": "mixer-options", children: [
|
|
1292
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
|
|
1293
|
+
/* @__PURE__ */ jsx7(
|
|
1088
1294
|
"span",
|
|
1089
1295
|
{
|
|
1090
1296
|
"aria-label": "Brush load",
|
|
@@ -1093,10 +1299,10 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1093
1299
|
style: { background: mixerLoad.reservoir ? rgbUnitToHex(mixerLoad.reservoir) : "transparent" }
|
|
1094
1300
|
}
|
|
1095
1301
|
),
|
|
1096
|
-
/* @__PURE__ */
|
|
1097
|
-
/* @__PURE__ */
|
|
1302
|
+
/* @__PURE__ */ jsx7("button", { type: "button", title: "Fill the reservoir with the foreground colour", className: chip(false), onClick: () => controller.loadMixerBrush(), children: "Load brush" }),
|
|
1303
|
+
/* @__PURE__ */ jsx7("button", { type: "button", title: "Empty the picked-up colour", className: chip(false), onClick: () => controller.cleanMixerBrush(), children: "Clean brush" })
|
|
1098
1304
|
] }),
|
|
1099
|
-
/* @__PURE__ */
|
|
1305
|
+
/* @__PURE__ */ jsx7("div", { className: "flex gap-1", role: "group", "aria-label": "Mixing", children: MIXER_MIXING_OPTIONS.map((m) => /* @__PURE__ */ jsx7(
|
|
1100
1306
|
"button",
|
|
1101
1307
|
{
|
|
1102
1308
|
type: "button",
|
|
@@ -1108,10 +1314,10 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1108
1314
|
},
|
|
1109
1315
|
m.id
|
|
1110
1316
|
)) }),
|
|
1111
|
-
MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */
|
|
1112
|
-
/* @__PURE__ */
|
|
1113
|
-
/* @__PURE__ */
|
|
1114
|
-
/* @__PURE__ */
|
|
1317
|
+
MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ jsx7(ControlSlider, { spec, value: mixer[spec.id], onChange: (v) => controller.setPaintOptions({ mixer: { [spec.id]: v } }) }, spec.id)),
|
|
1318
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap gap-3 text-slate-300", children: [
|
|
1319
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1.5", children: [
|
|
1320
|
+
/* @__PURE__ */ jsx7(
|
|
1115
1321
|
"input",
|
|
1116
1322
|
{
|
|
1117
1323
|
type: "checkbox",
|
|
@@ -1123,8 +1329,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1123
1329
|
),
|
|
1124
1330
|
"Load each stroke"
|
|
1125
1331
|
] }),
|
|
1126
|
-
/* @__PURE__ */
|
|
1127
|
-
/* @__PURE__ */
|
|
1332
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1.5", children: [
|
|
1333
|
+
/* @__PURE__ */ jsx7(
|
|
1128
1334
|
"input",
|
|
1129
1335
|
{
|
|
1130
1336
|
type: "checkbox",
|
|
@@ -1138,9 +1344,9 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1138
1344
|
] })
|
|
1139
1345
|
] })
|
|
1140
1346
|
] }),
|
|
1141
|
-
/* @__PURE__ */
|
|
1142
|
-
/* @__PURE__ */
|
|
1143
|
-
/* @__PURE__ */
|
|
1347
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
|
|
1348
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1.5", children: [
|
|
1349
|
+
/* @__PURE__ */ jsx7(
|
|
1144
1350
|
"input",
|
|
1145
1351
|
{
|
|
1146
1352
|
type: "checkbox",
|
|
@@ -1152,8 +1358,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1152
1358
|
),
|
|
1153
1359
|
"Pressure size"
|
|
1154
1360
|
] }),
|
|
1155
|
-
/* @__PURE__ */
|
|
1156
|
-
/* @__PURE__ */
|
|
1361
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1.5", children: [
|
|
1362
|
+
/* @__PURE__ */ jsx7(
|
|
1157
1363
|
"input",
|
|
1158
1364
|
{
|
|
1159
1365
|
type: "checkbox",
|
|
@@ -1166,23 +1372,23 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1166
1372
|
"Pressure opacity"
|
|
1167
1373
|
] })
|
|
1168
1374
|
] }),
|
|
1169
|
-
/* @__PURE__ */
|
|
1170
|
-
/* @__PURE__ */
|
|
1171
|
-
/* @__PURE__ */
|
|
1375
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex gap-1", children: [
|
|
1376
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
|
|
1377
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
|
|
1172
1378
|
] }),
|
|
1173
|
-
error && /* @__PURE__ */
|
|
1379
|
+
error && /* @__PURE__ */ jsx7("p", { role: "alert", className: "text-rose-400", children: error })
|
|
1174
1380
|
] });
|
|
1175
1381
|
};
|
|
1176
1382
|
|
|
1177
1383
|
// src/image-editor/SelectionOptionsBar.tsx
|
|
1178
|
-
import { useState as
|
|
1384
|
+
import { useState as useState8 } from "react";
|
|
1179
1385
|
import {
|
|
1180
1386
|
SELECTION_MODES,
|
|
1181
1387
|
SELECTION_MODE_LABELS,
|
|
1182
1388
|
SELECTION_TOOLS,
|
|
1183
1389
|
describeSelection
|
|
1184
1390
|
} from "@pixerate/editor/image-editor";
|
|
1185
|
-
import { jsx as
|
|
1391
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1186
1392
|
var MODIFY_OPS = [
|
|
1187
1393
|
{ op: "grow", label: "Grow" },
|
|
1188
1394
|
{ op: "shrink", label: "Shrink" },
|
|
@@ -1199,20 +1405,20 @@ var SelectionOptionsBar = ({
|
|
|
1199
1405
|
quickMask,
|
|
1200
1406
|
className = ""
|
|
1201
1407
|
}) => {
|
|
1202
|
-
const [radius, setRadius] =
|
|
1408
|
+
const [radius, setRadius] = useState8(2);
|
|
1203
1409
|
const set = (patch) => onOptionsChange({ ...options, ...patch });
|
|
1204
1410
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
1205
1411
|
const qm = quickMask ?? Boolean(controller.getState().quickMask);
|
|
1206
|
-
return /* @__PURE__ */
|
|
1207
|
-
/* @__PURE__ */
|
|
1208
|
-
/* @__PURE__ */
|
|
1209
|
-
options.tool === "wand" && /* @__PURE__ */
|
|
1210
|
-
/* @__PURE__ */
|
|
1211
|
-
/* @__PURE__ */
|
|
1212
|
-
/* @__PURE__ */
|
|
1213
|
-
/* @__PURE__ */
|
|
1412
|
+
return /* @__PURE__ */ jsxs8("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
1413
|
+
/* @__PURE__ */ jsx8("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: SELECTION_TOOLS.map((t) => /* @__PURE__ */ jsx8("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)) }),
|
|
1414
|
+
/* @__PURE__ */ jsx8("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: SELECTION_MODES.map((m) => /* @__PURE__ */ jsx8("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: SELECTION_MODE_LABELS[m] }, m)) }),
|
|
1415
|
+
options.tool === "wand" && /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-2", children: [
|
|
1416
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex flex-col gap-1", children: [
|
|
1417
|
+
/* @__PURE__ */ jsxs8("span", { className: "flex justify-between text-slate-400", children: [
|
|
1418
|
+
/* @__PURE__ */ jsx8("span", { children: "Tolerance" }),
|
|
1419
|
+
/* @__PURE__ */ jsx8("span", { className: "font-mono", children: options.tolerance })
|
|
1214
1420
|
] }),
|
|
1215
|
-
/* @__PURE__ */
|
|
1421
|
+
/* @__PURE__ */ jsx8(
|
|
1216
1422
|
"input",
|
|
1217
1423
|
{
|
|
1218
1424
|
type: "range",
|
|
@@ -1226,17 +1432,17 @@ var SelectionOptionsBar = ({
|
|
|
1226
1432
|
}
|
|
1227
1433
|
)
|
|
1228
1434
|
] }),
|
|
1229
|
-
/* @__PURE__ */
|
|
1230
|
-
/* @__PURE__ */
|
|
1435
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1436
|
+
/* @__PURE__ */ jsx8("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
|
|
1231
1437
|
"Contiguous"
|
|
1232
1438
|
] }),
|
|
1233
|
-
/* @__PURE__ */
|
|
1234
|
-
/* @__PURE__ */
|
|
1439
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1440
|
+
/* @__PURE__ */ jsx8("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
|
|
1235
1441
|
"Sample adjusted image"
|
|
1236
1442
|
] }),
|
|
1237
|
-
/* @__PURE__ */
|
|
1443
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1238
1444
|
"Sample",
|
|
1239
|
-
/* @__PURE__ */
|
|
1445
|
+
/* @__PURE__ */ jsxs8(
|
|
1240
1446
|
"select",
|
|
1241
1447
|
{
|
|
1242
1448
|
"aria-label": "Sample from",
|
|
@@ -1244,27 +1450,27 @@ var SelectionOptionsBar = ({
|
|
|
1244
1450
|
onChange: (e) => set({ sample: e.target.value }),
|
|
1245
1451
|
className: "bg-slate-800 border border-slate-700 rounded px-1 py-0.5",
|
|
1246
1452
|
children: [
|
|
1247
|
-
/* @__PURE__ */
|
|
1248
|
-
/* @__PURE__ */
|
|
1453
|
+
/* @__PURE__ */ jsx8("option", { value: "composite", children: "All layers" }),
|
|
1454
|
+
/* @__PURE__ */ jsx8("option", { value: "active-layer", children: "Active layer" })
|
|
1249
1455
|
]
|
|
1250
1456
|
}
|
|
1251
1457
|
)
|
|
1252
1458
|
] })
|
|
1253
1459
|
] }),
|
|
1254
|
-
/* @__PURE__ */
|
|
1255
|
-
/* @__PURE__ */
|
|
1460
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1461
|
+
/* @__PURE__ */ jsx8("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
|
|
1256
1462
|
"Anti-alias"
|
|
1257
1463
|
] }),
|
|
1258
|
-
/* @__PURE__ */
|
|
1259
|
-
/* @__PURE__ */
|
|
1260
|
-
/* @__PURE__ */
|
|
1261
|
-
/* @__PURE__ */
|
|
1262
|
-
/* @__PURE__ */
|
|
1464
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex flex-wrap gap-1", children: [
|
|
1465
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
|
|
1466
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
|
|
1467
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
|
|
1468
|
+
/* @__PURE__ */ jsx8("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
|
|
1263
1469
|
] }),
|
|
1264
|
-
/* @__PURE__ */
|
|
1265
|
-
/* @__PURE__ */
|
|
1470
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
1471
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex items-center gap-1 text-slate-400", children: [
|
|
1266
1472
|
"Radius",
|
|
1267
|
-
/* @__PURE__ */
|
|
1473
|
+
/* @__PURE__ */ jsx8(
|
|
1268
1474
|
"input",
|
|
1269
1475
|
{
|
|
1270
1476
|
type: "number",
|
|
@@ -1278,29 +1484,29 @@ var SelectionOptionsBar = ({
|
|
|
1278
1484
|
}
|
|
1279
1485
|
)
|
|
1280
1486
|
] }),
|
|
1281
|
-
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */
|
|
1487
|
+
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ jsx8("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
|
|
1282
1488
|
] }),
|
|
1283
|
-
/* @__PURE__ */
|
|
1489
|
+
/* @__PURE__ */ jsx8("p", { "data-testid": "selection-status", className: "text-slate-400", children: describeSelection(sel) })
|
|
1284
1490
|
] });
|
|
1285
1491
|
};
|
|
1286
1492
|
|
|
1287
1493
|
// src/image-editor/RefineEdgePanel.tsx
|
|
1288
|
-
import { useState as
|
|
1494
|
+
import { useState as useState9 } from "react";
|
|
1289
1495
|
import {
|
|
1290
1496
|
ADJUSTMENT_KINDS as ADJUSTMENT_KINDS2,
|
|
1291
1497
|
REFINE_EDGE_CONTROLS,
|
|
1292
1498
|
adjustmentKindLabel as adjustmentKindLabel2,
|
|
1293
1499
|
layerMaskFromSelection
|
|
1294
1500
|
} from "@pixerate/editor/image-editor";
|
|
1295
|
-
import { Fragment as Fragment2, jsx as
|
|
1501
|
+
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1296
1502
|
var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
|
|
1297
|
-
var
|
|
1503
|
+
var button2 = "px-2 py-1 rounded-md border border-slate-800 bg-slate-950 text-[11px] text-slate-200 hover:text-white disabled:opacity-40";
|
|
1298
1504
|
var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
1299
|
-
const [params, setParams] =
|
|
1300
|
-
const [busy, setBusy] =
|
|
1301
|
-
const [error, setError] =
|
|
1302
|
-
const [layerId, setLayerId] =
|
|
1303
|
-
const [newKind, setNewKind] =
|
|
1505
|
+
const [params, setParams] = useState9(DEFAULT_PARAMS);
|
|
1506
|
+
const [busy, setBusy] = useState9(false);
|
|
1507
|
+
const [error, setError] = useState9(null);
|
|
1508
|
+
const [layerId, setLayerId] = useState9("");
|
|
1509
|
+
const [newKind, setNewKind] = useState9("hueSaturation");
|
|
1304
1510
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
1305
1511
|
const list = layers ?? controller.getAdjustmentLayers();
|
|
1306
1512
|
const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
|
|
@@ -1315,17 +1521,17 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1315
1521
|
setBusy(false);
|
|
1316
1522
|
}
|
|
1317
1523
|
};
|
|
1318
|
-
return /* @__PURE__ */
|
|
1319
|
-
/* @__PURE__ */
|
|
1320
|
-
REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */
|
|
1321
|
-
/* @__PURE__ */
|
|
1322
|
-
/* @__PURE__ */
|
|
1323
|
-
/* @__PURE__ */
|
|
1524
|
+
return /* @__PURE__ */ jsxs9("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
1525
|
+
/* @__PURE__ */ jsx9("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
|
|
1526
|
+
REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ jsxs9("label", { className: "flex flex-col gap-1", children: [
|
|
1527
|
+
/* @__PURE__ */ jsxs9("span", { className: "flex justify-between text-slate-400", children: [
|
|
1528
|
+
/* @__PURE__ */ jsx9("span", { children: c.label }),
|
|
1529
|
+
/* @__PURE__ */ jsxs9("span", { className: "font-mono", children: [
|
|
1324
1530
|
params[c.id],
|
|
1325
1531
|
c.unit
|
|
1326
1532
|
] })
|
|
1327
1533
|
] }),
|
|
1328
|
-
/* @__PURE__ */
|
|
1534
|
+
/* @__PURE__ */ jsx9(
|
|
1329
1535
|
"input",
|
|
1330
1536
|
{
|
|
1331
1537
|
type: "range",
|
|
@@ -1339,67 +1545,67 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1339
1545
|
}
|
|
1340
1546
|
)
|
|
1341
1547
|
] }, c.id)),
|
|
1342
|
-
/* @__PURE__ */
|
|
1343
|
-
/* @__PURE__ */
|
|
1548
|
+
/* @__PURE__ */ jsxs9("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1549
|
+
/* @__PURE__ */ jsx9("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
|
|
1344
1550
|
"Smart Radius"
|
|
1345
1551
|
] }),
|
|
1346
|
-
/* @__PURE__ */
|
|
1347
|
-
/* @__PURE__ */
|
|
1348
|
-
/* @__PURE__ */
|
|
1552
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex gap-1", children: [
|
|
1553
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: button2, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
|
|
1554
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: button2, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
|
|
1349
1555
|
] }),
|
|
1350
|
-
error && /* @__PURE__ */
|
|
1351
|
-
/* @__PURE__ */
|
|
1352
|
-
/* @__PURE__ */
|
|
1353
|
-
/* @__PURE__ */
|
|
1556
|
+
error && /* @__PURE__ */ jsx9("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
1557
|
+
/* @__PURE__ */ jsx9("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
|
|
1558
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex gap-1 items-center", children: [
|
|
1559
|
+
/* @__PURE__ */ jsx9(
|
|
1354
1560
|
"select",
|
|
1355
1561
|
{
|
|
1356
1562
|
"aria-label": "New masked layer kind",
|
|
1357
1563
|
value: newKind,
|
|
1358
1564
|
onChange: (e) => setNewKind(e.target.value),
|
|
1359
1565
|
className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
1360
|
-
children: ADJUSTMENT_KINDS2.map((k) => /* @__PURE__ */
|
|
1566
|
+
children: ADJUSTMENT_KINDS2.map((k) => /* @__PURE__ */ jsx9("option", { value: k.kind, children: k.label }, k.kind))
|
|
1361
1567
|
}
|
|
1362
1568
|
),
|
|
1363
|
-
/* @__PURE__ */
|
|
1569
|
+
/* @__PURE__ */ jsx9(
|
|
1364
1570
|
"button",
|
|
1365
1571
|
{
|
|
1366
1572
|
type: "button",
|
|
1367
|
-
className:
|
|
1573
|
+
className: button2,
|
|
1368
1574
|
disabled: !sel,
|
|
1369
1575
|
onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: layerMaskFromSelection(sel) })),
|
|
1370
1576
|
children: "New Masked Layer"
|
|
1371
1577
|
}
|
|
1372
1578
|
)
|
|
1373
1579
|
] }),
|
|
1374
|
-
list.length > 0 && target && /* @__PURE__ */
|
|
1375
|
-
/* @__PURE__ */
|
|
1580
|
+
list.length > 0 && target && /* @__PURE__ */ jsxs9("div", { className: "flex flex-col gap-2", children: [
|
|
1581
|
+
/* @__PURE__ */ jsx9(
|
|
1376
1582
|
"select",
|
|
1377
1583
|
{
|
|
1378
1584
|
"aria-label": "Mask layer",
|
|
1379
1585
|
value: target.id,
|
|
1380
1586
|
onChange: (e) => setLayerId(e.target.value),
|
|
1381
1587
|
className: "bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
1382
|
-
children: list.map((l) => /* @__PURE__ */
|
|
1588
|
+
children: list.map((l) => /* @__PURE__ */ jsxs9("option", { value: l.id, children: [
|
|
1383
1589
|
l.name || adjustmentKindLabel2(l.kind),
|
|
1384
1590
|
l.mask ? " (masked)" : ""
|
|
1385
1591
|
] }, l.id))
|
|
1386
1592
|
}
|
|
1387
1593
|
),
|
|
1388
|
-
/* @__PURE__ */
|
|
1389
|
-
/* @__PURE__ */
|
|
1390
|
-
/* @__PURE__ */
|
|
1391
|
-
/* @__PURE__ */
|
|
1594
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex flex-wrap gap-1", children: [
|
|
1595
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: button2, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
|
|
1596
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
|
|
1597
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
|
|
1392
1598
|
] }),
|
|
1393
|
-
target.mask && /* @__PURE__ */
|
|
1394
|
-
/* @__PURE__ */
|
|
1395
|
-
/* @__PURE__ */
|
|
1396
|
-
/* @__PURE__ */
|
|
1397
|
-
/* @__PURE__ */
|
|
1599
|
+
target.mask && /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
1600
|
+
/* @__PURE__ */ jsxs9("label", { className: "flex flex-col gap-1", children: [
|
|
1601
|
+
/* @__PURE__ */ jsxs9("span", { className: "flex justify-between text-slate-400", children: [
|
|
1602
|
+
/* @__PURE__ */ jsx9("span", { children: "Density" }),
|
|
1603
|
+
/* @__PURE__ */ jsxs9("span", { className: "font-mono", children: [
|
|
1398
1604
|
Math.round((target.mask.density ?? 1) * 100),
|
|
1399
1605
|
"%"
|
|
1400
1606
|
] })
|
|
1401
1607
|
] }),
|
|
1402
|
-
/* @__PURE__ */
|
|
1608
|
+
/* @__PURE__ */ jsx9(
|
|
1403
1609
|
"input",
|
|
1404
1610
|
{
|
|
1405
1611
|
type: "range",
|
|
@@ -1413,15 +1619,15 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1413
1619
|
}
|
|
1414
1620
|
)
|
|
1415
1621
|
] }),
|
|
1416
|
-
/* @__PURE__ */
|
|
1417
|
-
/* @__PURE__ */
|
|
1418
|
-
/* @__PURE__ */
|
|
1419
|
-
/* @__PURE__ */
|
|
1622
|
+
/* @__PURE__ */ jsxs9("label", { className: "flex flex-col gap-1", children: [
|
|
1623
|
+
/* @__PURE__ */ jsxs9("span", { className: "flex justify-between text-slate-400", children: [
|
|
1624
|
+
/* @__PURE__ */ jsx9("span", { children: "Mask Feather" }),
|
|
1625
|
+
/* @__PURE__ */ jsxs9("span", { className: "font-mono", children: [
|
|
1420
1626
|
target.mask.feather ?? 0,
|
|
1421
1627
|
"px"
|
|
1422
1628
|
] })
|
|
1423
1629
|
] }),
|
|
1424
|
-
/* @__PURE__ */
|
|
1630
|
+
/* @__PURE__ */ jsx9(
|
|
1425
1631
|
"input",
|
|
1426
1632
|
{
|
|
1427
1633
|
type: "range",
|
|
@@ -1441,7 +1647,7 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1441
1647
|
};
|
|
1442
1648
|
|
|
1443
1649
|
// src/image-editor/ImageEditor.tsx
|
|
1444
|
-
import { Fragment as Fragment3, jsx as
|
|
1650
|
+
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1445
1651
|
var ImageEditor = ({
|
|
1446
1652
|
editor: externalEditor,
|
|
1447
1653
|
src,
|
|
@@ -1457,34 +1663,34 @@ var ImageEditor = ({
|
|
|
1457
1663
|
const editor = externalEditor || internalEditor;
|
|
1458
1664
|
const { state, controller } = editor;
|
|
1459
1665
|
const legacyProcess = normalizeProcessVersion(state.adjustments.process) < LATEST_PROCESS_VERSION;
|
|
1460
|
-
const canvasRef =
|
|
1461
|
-
const containerRef =
|
|
1462
|
-
const [activeTab, setActiveTab] =
|
|
1463
|
-
const [activeCropRatio, setActiveCropRatio] =
|
|
1464
|
-
const [selectionOptions, setSelectionOptions] =
|
|
1465
|
-
const selectionOptionsRef =
|
|
1666
|
+
const canvasRef = useRef5(null);
|
|
1667
|
+
const containerRef = useRef5(null);
|
|
1668
|
+
const [activeTab, setActiveTab] = useState10("crop");
|
|
1669
|
+
const [activeCropRatio, setActiveCropRatio] = useState10(null);
|
|
1670
|
+
const [selectionOptions, setSelectionOptions] = useState10(DEFAULT_SELECTION_TOOL_OPTIONS);
|
|
1671
|
+
const selectionOptionsRef = useRef5(selectionOptions);
|
|
1466
1672
|
selectionOptionsRef.current = selectionOptions;
|
|
1467
|
-
const selectionGestureRef =
|
|
1673
|
+
const selectionGestureRef = useRef5(null);
|
|
1468
1674
|
if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
|
|
1469
1675
|
selectionGestureRef.current = new SelectionGesture(controller, () => selectionOptionsRef.current);
|
|
1470
1676
|
}
|
|
1471
|
-
const selectionDraftRef =
|
|
1472
|
-
const [selectionError, setSelectionError] =
|
|
1473
|
-
const paintGestureRef =
|
|
1474
|
-
const paintControllerRef =
|
|
1677
|
+
const selectionDraftRef = useRef5(null);
|
|
1678
|
+
const [selectionError, setSelectionError] = useState10(null);
|
|
1679
|
+
const paintGestureRef = useRef5(null);
|
|
1680
|
+
const paintControllerRef = useRef5(controller);
|
|
1475
1681
|
if (!paintGestureRef.current || paintControllerRef.current !== controller) {
|
|
1476
1682
|
paintGestureRef.current = new PaintGesture(controller);
|
|
1477
1683
|
paintControllerRef.current = controller;
|
|
1478
1684
|
}
|
|
1479
|
-
const brushCursorRef =
|
|
1480
|
-
const [paintError, setPaintError] =
|
|
1481
|
-
const [inpaintPrompt, setInpaintPrompt] =
|
|
1482
|
-
const [inpaintMaskMode, setInpaintMaskMode] =
|
|
1483
|
-
const [isRemovingBg, setIsRemovingBg] =
|
|
1484
|
-
const [isInpainting, setIsInpainting] =
|
|
1485
|
-
const [aiError, setAiError] =
|
|
1486
|
-
const [aiSuccess, setAiSuccess] =
|
|
1487
|
-
const [aiTarget, setAiTarget] =
|
|
1685
|
+
const brushCursorRef = useRef5(null);
|
|
1686
|
+
const [paintError, setPaintError] = useState10(null);
|
|
1687
|
+
const [inpaintPrompt, setInpaintPrompt] = useState10("");
|
|
1688
|
+
const [inpaintMaskMode, setInpaintMaskMode] = useState10("annotations");
|
|
1689
|
+
const [isRemovingBg, setIsRemovingBg] = useState10(false);
|
|
1690
|
+
const [isInpainting, setIsInpainting] = useState10(false);
|
|
1691
|
+
const [aiError, setAiError] = useState10(null);
|
|
1692
|
+
const [aiSuccess, setAiSuccess] = useState10(null);
|
|
1693
|
+
const [aiTarget, setAiTarget] = useState10("auto");
|
|
1488
1694
|
const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
|
|
1489
1695
|
const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
|
|
1490
1696
|
const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
|
|
@@ -1547,17 +1753,17 @@ var ImageEditor = ({
|
|
|
1547
1753
|
setIsInpainting(false);
|
|
1548
1754
|
}
|
|
1549
1755
|
};
|
|
1550
|
-
const [activeColor, setActiveColor] =
|
|
1551
|
-
const [strokeWidth, setStrokeWidth] =
|
|
1552
|
-
const [fontSize, setFontSize] =
|
|
1553
|
-
const [textInput, setTextInput] =
|
|
1554
|
-
const draftAnnotationRef =
|
|
1555
|
-
const draftCropRef =
|
|
1556
|
-
const cropDragInfoRef =
|
|
1557
|
-
const annotationDragInfoRef =
|
|
1558
|
-
const isDrawingRef =
|
|
1559
|
-
const currentPathRef =
|
|
1560
|
-
const dragStartPointRef =
|
|
1756
|
+
const [activeColor, setActiveColor] = useState10("#ef4444");
|
|
1757
|
+
const [strokeWidth, setStrokeWidth] = useState10(3);
|
|
1758
|
+
const [fontSize, setFontSize] = useState10(24);
|
|
1759
|
+
const [textInput, setTextInput] = useState10("");
|
|
1760
|
+
const draftAnnotationRef = useRef5(null);
|
|
1761
|
+
const draftCropRef = useRef5(null);
|
|
1762
|
+
const cropDragInfoRef = useRef5(null);
|
|
1763
|
+
const annotationDragInfoRef = useRef5(null);
|
|
1764
|
+
const isDrawingRef = useRef5(false);
|
|
1765
|
+
const currentPathRef = useRef5([]);
|
|
1766
|
+
const dragStartPointRef = useRef5(null);
|
|
1561
1767
|
const renderCanvas = useCallback2(
|
|
1562
1768
|
async (draftAnnotation, draftCrop) => {
|
|
1563
1769
|
const canvas = canvasRef.current;
|
|
@@ -1579,7 +1785,7 @@ var ImageEditor = ({
|
|
|
1579
1785
|
},
|
|
1580
1786
|
[controller, activeTab]
|
|
1581
1787
|
);
|
|
1582
|
-
|
|
1788
|
+
useEffect7(() => {
|
|
1583
1789
|
const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
|
|
1584
1790
|
const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
|
|
1585
1791
|
const animId = raf(() => {
|
|
@@ -1587,12 +1793,12 @@ var ImageEditor = ({
|
|
|
1587
1793
|
});
|
|
1588
1794
|
return () => caf(animId);
|
|
1589
1795
|
}, [renderCanvas, state]);
|
|
1590
|
-
|
|
1796
|
+
useEffect7(() => {
|
|
1591
1797
|
if (activeTab === "crop" && editor.state.activeTool !== "crop") {
|
|
1592
1798
|
editor.setTool("crop");
|
|
1593
1799
|
}
|
|
1594
1800
|
}, [activeTab, editor]);
|
|
1595
|
-
|
|
1801
|
+
useEffect7(() => {
|
|
1596
1802
|
const container = containerRef.current;
|
|
1597
1803
|
if (!container) return;
|
|
1598
1804
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -1657,7 +1863,7 @@ var ImageEditor = ({
|
|
|
1657
1863
|
if (g.error) setPaintError(g.error);
|
|
1658
1864
|
}
|
|
1659
1865
|
};
|
|
1660
|
-
|
|
1866
|
+
useEffect7(() => {
|
|
1661
1867
|
if (activeTab !== "paint" || typeof window === "undefined") return;
|
|
1662
1868
|
const onKey = (e) => {
|
|
1663
1869
|
if (handlePaintShortcut(controller, e)) e.preventDefault();
|
|
@@ -2020,15 +2226,15 @@ var ImageEditor = ({
|
|
|
2020
2226
|
link.click();
|
|
2021
2227
|
}
|
|
2022
2228
|
};
|
|
2023
|
-
return /* @__PURE__ */
|
|
2229
|
+
return /* @__PURE__ */ jsxs10(
|
|
2024
2230
|
"div",
|
|
2025
2231
|
{
|
|
2026
2232
|
className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
|
|
2027
2233
|
style,
|
|
2028
2234
|
children: [
|
|
2029
|
-
/* @__PURE__ */
|
|
2030
|
-
/* @__PURE__ */
|
|
2031
|
-
/* @__PURE__ */
|
|
2235
|
+
/* @__PURE__ */ jsxs10("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: [
|
|
2236
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
|
|
2237
|
+
/* @__PURE__ */ jsx10(
|
|
2032
2238
|
"button",
|
|
2033
2239
|
{
|
|
2034
2240
|
type: "button",
|
|
@@ -2040,7 +2246,7 @@ var ImageEditor = ({
|
|
|
2040
2246
|
children: "Transform & Crop"
|
|
2041
2247
|
}
|
|
2042
2248
|
),
|
|
2043
|
-
/* @__PURE__ */
|
|
2249
|
+
/* @__PURE__ */ jsx10(
|
|
2044
2250
|
"button",
|
|
2045
2251
|
{
|
|
2046
2252
|
type: "button",
|
|
@@ -2052,7 +2258,7 @@ var ImageEditor = ({
|
|
|
2052
2258
|
children: "Adjustments"
|
|
2053
2259
|
}
|
|
2054
2260
|
),
|
|
2055
|
-
/* @__PURE__ */
|
|
2261
|
+
/* @__PURE__ */ jsx10(
|
|
2056
2262
|
"button",
|
|
2057
2263
|
{
|
|
2058
2264
|
type: "button",
|
|
@@ -2064,7 +2270,7 @@ var ImageEditor = ({
|
|
|
2064
2270
|
children: "Layers"
|
|
2065
2271
|
}
|
|
2066
2272
|
),
|
|
2067
|
-
/* @__PURE__ */
|
|
2273
|
+
/* @__PURE__ */ jsx10(
|
|
2068
2274
|
"button",
|
|
2069
2275
|
{
|
|
2070
2276
|
type: "button",
|
|
@@ -2076,7 +2282,7 @@ var ImageEditor = ({
|
|
|
2076
2282
|
children: "Paint"
|
|
2077
2283
|
}
|
|
2078
2284
|
),
|
|
2079
|
-
/* @__PURE__ */
|
|
2285
|
+
/* @__PURE__ */ jsx10(
|
|
2080
2286
|
"button",
|
|
2081
2287
|
{
|
|
2082
2288
|
type: "button",
|
|
@@ -2088,7 +2294,7 @@ var ImageEditor = ({
|
|
|
2088
2294
|
children: "Select & Mask"
|
|
2089
2295
|
}
|
|
2090
2296
|
),
|
|
2091
|
-
/* @__PURE__ */
|
|
2297
|
+
/* @__PURE__ */ jsx10(
|
|
2092
2298
|
"button",
|
|
2093
2299
|
{
|
|
2094
2300
|
type: "button",
|
|
@@ -2100,7 +2306,7 @@ var ImageEditor = ({
|
|
|
2100
2306
|
children: "Annotations"
|
|
2101
2307
|
}
|
|
2102
2308
|
),
|
|
2103
|
-
/* @__PURE__ */
|
|
2309
|
+
/* @__PURE__ */ jsx10(
|
|
2104
2310
|
"button",
|
|
2105
2311
|
{
|
|
2106
2312
|
type: "button",
|
|
@@ -2112,7 +2318,7 @@ var ImageEditor = ({
|
|
|
2112
2318
|
children: "Depth Mask"
|
|
2113
2319
|
}
|
|
2114
2320
|
),
|
|
2115
|
-
/* @__PURE__ */
|
|
2321
|
+
/* @__PURE__ */ jsxs10(
|
|
2116
2322
|
"button",
|
|
2117
2323
|
{
|
|
2118
2324
|
type: "button",
|
|
@@ -2122,14 +2328,14 @@ var ImageEditor = ({
|
|
|
2122
2328
|
},
|
|
2123
2329
|
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"}`,
|
|
2124
2330
|
children: [
|
|
2125
|
-
/* @__PURE__ */
|
|
2331
|
+
/* @__PURE__ */ jsx10("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx10("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" }) }),
|
|
2126
2332
|
"AI Tools"
|
|
2127
2333
|
]
|
|
2128
2334
|
}
|
|
2129
2335
|
)
|
|
2130
2336
|
] }),
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
/* @__PURE__ */
|
|
2337
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2338
|
+
/* @__PURE__ */ jsx10(
|
|
2133
2339
|
"button",
|
|
2134
2340
|
{
|
|
2135
2341
|
type: "button",
|
|
@@ -2140,7 +2346,7 @@ var ImageEditor = ({
|
|
|
2140
2346
|
children: "\u21A9"
|
|
2141
2347
|
}
|
|
2142
2348
|
),
|
|
2143
|
-
/* @__PURE__ */
|
|
2349
|
+
/* @__PURE__ */ jsx10(
|
|
2144
2350
|
"button",
|
|
2145
2351
|
{
|
|
2146
2352
|
type: "button",
|
|
@@ -2151,7 +2357,7 @@ var ImageEditor = ({
|
|
|
2151
2357
|
children: "\u21AA"
|
|
2152
2358
|
}
|
|
2153
2359
|
),
|
|
2154
|
-
/* @__PURE__ */
|
|
2360
|
+
/* @__PURE__ */ jsx10(
|
|
2155
2361
|
"button",
|
|
2156
2362
|
{
|
|
2157
2363
|
type: "button",
|
|
@@ -2160,8 +2366,8 @@ var ImageEditor = ({
|
|
|
2160
2366
|
children: "Reset"
|
|
2161
2367
|
}
|
|
2162
2368
|
),
|
|
2163
|
-
/* @__PURE__ */
|
|
2164
|
-
/* @__PURE__ */
|
|
2369
|
+
/* @__PURE__ */ jsx10("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
2370
|
+
/* @__PURE__ */ jsx10(
|
|
2165
2371
|
"button",
|
|
2166
2372
|
{
|
|
2167
2373
|
type: "button",
|
|
@@ -2171,11 +2377,11 @@ var ImageEditor = ({
|
|
|
2171
2377
|
children: "-"
|
|
2172
2378
|
}
|
|
2173
2379
|
),
|
|
2174
|
-
/* @__PURE__ */
|
|
2380
|
+
/* @__PURE__ */ jsxs10("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
|
|
2175
2381
|
Math.round(state.zoom * 100),
|
|
2176
2382
|
"%"
|
|
2177
2383
|
] }),
|
|
2178
|
-
/* @__PURE__ */
|
|
2384
|
+
/* @__PURE__ */ jsx10(
|
|
2179
2385
|
"button",
|
|
2180
2386
|
{
|
|
2181
2387
|
type: "button",
|
|
@@ -2185,8 +2391,8 @@ var ImageEditor = ({
|
|
|
2185
2391
|
children: "+"
|
|
2186
2392
|
}
|
|
2187
2393
|
),
|
|
2188
|
-
/* @__PURE__ */
|
|
2189
|
-
/* @__PURE__ */
|
|
2394
|
+
/* @__PURE__ */ jsx10("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
2395
|
+
/* @__PURE__ */ jsx10(
|
|
2190
2396
|
"button",
|
|
2191
2397
|
{
|
|
2192
2398
|
type: "button",
|
|
@@ -2197,7 +2403,7 @@ var ImageEditor = ({
|
|
|
2197
2403
|
children: "Hold Compare"
|
|
2198
2404
|
}
|
|
2199
2405
|
),
|
|
2200
|
-
/* @__PURE__ */
|
|
2406
|
+
/* @__PURE__ */ jsx10(
|
|
2201
2407
|
"button",
|
|
2202
2408
|
{
|
|
2203
2409
|
type: "button",
|
|
@@ -2208,13 +2414,13 @@ var ImageEditor = ({
|
|
|
2208
2414
|
)
|
|
2209
2415
|
] })
|
|
2210
2416
|
] }),
|
|
2211
|
-
/* @__PURE__ */
|
|
2212
|
-
/* @__PURE__ */
|
|
2417
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
|
|
2418
|
+
/* @__PURE__ */ jsx10(
|
|
2213
2419
|
"div",
|
|
2214
2420
|
{
|
|
2215
2421
|
ref: containerRef,
|
|
2216
2422
|
className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
|
|
2217
|
-
children: /* @__PURE__ */
|
|
2423
|
+
children: /* @__PURE__ */ jsx10(
|
|
2218
2424
|
"canvas",
|
|
2219
2425
|
{
|
|
2220
2426
|
ref: canvasRef,
|
|
@@ -2232,11 +2438,11 @@ var ImageEditor = ({
|
|
|
2232
2438
|
)
|
|
2233
2439
|
}
|
|
2234
2440
|
),
|
|
2235
|
-
/* @__PURE__ */
|
|
2236
|
-
activeTab === "crop" && /* @__PURE__ */
|
|
2237
|
-
/* @__PURE__ */
|
|
2238
|
-
/* @__PURE__ */
|
|
2239
|
-
/* @__PURE__ */
|
|
2441
|
+
/* @__PURE__ */ jsxs10("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: [
|
|
2442
|
+
activeTab === "crop" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
2443
|
+
/* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
|
|
2444
|
+
/* @__PURE__ */ jsxs10("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
2445
|
+
/* @__PURE__ */ jsx10(
|
|
2240
2446
|
"button",
|
|
2241
2447
|
{
|
|
2242
2448
|
type: "button",
|
|
@@ -2248,7 +2454,7 @@ var ImageEditor = ({
|
|
|
2248
2454
|
children: "Freeform"
|
|
2249
2455
|
}
|
|
2250
2456
|
),
|
|
2251
|
-
/* @__PURE__ */
|
|
2457
|
+
/* @__PURE__ */ jsx10(
|
|
2252
2458
|
"button",
|
|
2253
2459
|
{
|
|
2254
2460
|
type: "button",
|
|
@@ -2260,7 +2466,7 @@ var ImageEditor = ({
|
|
|
2260
2466
|
children: "1:1 Square"
|
|
2261
2467
|
}
|
|
2262
2468
|
),
|
|
2263
|
-
/* @__PURE__ */
|
|
2469
|
+
/* @__PURE__ */ jsx10(
|
|
2264
2470
|
"button",
|
|
2265
2471
|
{
|
|
2266
2472
|
type: "button",
|
|
@@ -2272,7 +2478,7 @@ var ImageEditor = ({
|
|
|
2272
2478
|
children: "4:3 Standard"
|
|
2273
2479
|
}
|
|
2274
2480
|
),
|
|
2275
|
-
/* @__PURE__ */
|
|
2481
|
+
/* @__PURE__ */ jsx10(
|
|
2276
2482
|
"button",
|
|
2277
2483
|
{
|
|
2278
2484
|
type: "button",
|
|
@@ -2284,7 +2490,7 @@ var ImageEditor = ({
|
|
|
2284
2490
|
children: "16:9 Wide"
|
|
2285
2491
|
}
|
|
2286
2492
|
),
|
|
2287
|
-
/* @__PURE__ */
|
|
2493
|
+
/* @__PURE__ */ jsx10(
|
|
2288
2494
|
"button",
|
|
2289
2495
|
{
|
|
2290
2496
|
type: "button",
|
|
@@ -2296,7 +2502,7 @@ var ImageEditor = ({
|
|
|
2296
2502
|
children: "3:2 Photo"
|
|
2297
2503
|
}
|
|
2298
2504
|
),
|
|
2299
|
-
/* @__PURE__ */
|
|
2505
|
+
/* @__PURE__ */ jsx10(
|
|
2300
2506
|
"button",
|
|
2301
2507
|
{
|
|
2302
2508
|
type: "button",
|
|
@@ -2309,10 +2515,10 @@ var ImageEditor = ({
|
|
|
2309
2515
|
}
|
|
2310
2516
|
)
|
|
2311
2517
|
] }),
|
|
2312
|
-
/* @__PURE__ */
|
|
2313
|
-
/* @__PURE__ */
|
|
2314
|
-
/* @__PURE__ */
|
|
2315
|
-
/* @__PURE__ */
|
|
2518
|
+
/* @__PURE__ */ jsx10("div", { className: "h-px bg-slate-800 my-1" }),
|
|
2519
|
+
/* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
|
|
2520
|
+
/* @__PURE__ */ jsxs10("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
2521
|
+
/* @__PURE__ */ jsx10(
|
|
2316
2522
|
"button",
|
|
2317
2523
|
{
|
|
2318
2524
|
type: "button",
|
|
@@ -2321,7 +2527,7 @@ var ImageEditor = ({
|
|
|
2321
2527
|
children: "Rotate -90\xB0"
|
|
2322
2528
|
}
|
|
2323
2529
|
),
|
|
2324
|
-
/* @__PURE__ */
|
|
2530
|
+
/* @__PURE__ */ jsx10(
|
|
2325
2531
|
"button",
|
|
2326
2532
|
{
|
|
2327
2533
|
type: "button",
|
|
@@ -2330,7 +2536,7 @@ var ImageEditor = ({
|
|
|
2330
2536
|
children: "Rotate +90\xB0"
|
|
2331
2537
|
}
|
|
2332
2538
|
),
|
|
2333
|
-
/* @__PURE__ */
|
|
2539
|
+
/* @__PURE__ */ jsx10(
|
|
2334
2540
|
"button",
|
|
2335
2541
|
{
|
|
2336
2542
|
type: "button",
|
|
@@ -2339,7 +2545,7 @@ var ImageEditor = ({
|
|
|
2339
2545
|
children: "Flip Horizontal"
|
|
2340
2546
|
}
|
|
2341
2547
|
),
|
|
2342
|
-
/* @__PURE__ */
|
|
2548
|
+
/* @__PURE__ */ jsx10(
|
|
2343
2549
|
"button",
|
|
2344
2550
|
{
|
|
2345
2551
|
type: "button",
|
|
@@ -2350,10 +2556,10 @@ var ImageEditor = ({
|
|
|
2350
2556
|
)
|
|
2351
2557
|
] })
|
|
2352
2558
|
] }),
|
|
2353
|
-
activeTab === "adjust" && /* @__PURE__ */
|
|
2354
|
-
/* @__PURE__ */
|
|
2355
|
-
/* @__PURE__ */
|
|
2356
|
-
/* @__PURE__ */
|
|
2559
|
+
activeTab === "adjust" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2560
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
|
|
2561
|
+
/* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
|
|
2562
|
+
/* @__PURE__ */ jsx10(
|
|
2357
2563
|
"button",
|
|
2358
2564
|
{
|
|
2359
2565
|
type: "button",
|
|
@@ -2363,9 +2569,9 @@ var ImageEditor = ({
|
|
|
2363
2569
|
}
|
|
2364
2570
|
)
|
|
2365
2571
|
] }),
|
|
2366
|
-
/* @__PURE__ */
|
|
2367
|
-
IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */
|
|
2368
|
-
/* @__PURE__ */
|
|
2572
|
+
/* @__PURE__ */ jsx10(Histogram, { histogram: editor.histogram }),
|
|
2573
|
+
IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ jsxs10(React9.Fragment, { children: [
|
|
2574
|
+
/* @__PURE__ */ jsx10(
|
|
2369
2575
|
ControlSlider,
|
|
2370
2576
|
{
|
|
2371
2577
|
spec,
|
|
@@ -2374,14 +2580,14 @@ var ImageEditor = ({
|
|
|
2374
2580
|
onChange: (v) => editor.setAdjustments({ [spec.id]: v })
|
|
2375
2581
|
}
|
|
2376
2582
|
),
|
|
2377
|
-
spec.id === "tint" && legacyProcess && /* @__PURE__ */
|
|
2583
|
+
spec.id === "tint" && legacyProcess && /* @__PURE__ */ jsxs10(
|
|
2378
2584
|
"div",
|
|
2379
2585
|
{
|
|
2380
2586
|
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",
|
|
2381
2587
|
"data-testid": "image-editor-process-notice",
|
|
2382
2588
|
children: [
|
|
2383
|
-
/* @__PURE__ */
|
|
2384
|
-
/* @__PURE__ */
|
|
2589
|
+
/* @__PURE__ */ jsx10("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
|
|
2590
|
+
/* @__PURE__ */ jsx10(
|
|
2385
2591
|
"button",
|
|
2386
2592
|
{
|
|
2387
2593
|
type: "button",
|
|
@@ -2394,7 +2600,7 @@ var ImageEditor = ({
|
|
|
2394
2600
|
}
|
|
2395
2601
|
)
|
|
2396
2602
|
] }, spec.id)),
|
|
2397
|
-
/* @__PURE__ */
|
|
2603
|
+
/* @__PURE__ */ jsx10("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx10(
|
|
2398
2604
|
AdjustmentLayersPanel,
|
|
2399
2605
|
{
|
|
2400
2606
|
controller,
|
|
@@ -2403,19 +2609,19 @@ var ImageEditor = ({
|
|
|
2403
2609
|
}
|
|
2404
2610
|
) })
|
|
2405
2611
|
] }),
|
|
2406
|
-
activeTab === "layers" && /* @__PURE__ */
|
|
2407
|
-
/* @__PURE__ */
|
|
2408
|
-
/* @__PURE__ */
|
|
2612
|
+
activeTab === "layers" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2613
|
+
/* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
|
|
2614
|
+
/* @__PURE__ */ jsx10(LayersPanel, { controller })
|
|
2409
2615
|
] }),
|
|
2410
|
-
activeTab === "paint" && /* @__PURE__ */
|
|
2411
|
-
/* @__PURE__ */
|
|
2412
|
-
/* @__PURE__ */
|
|
2413
|
-
paintError && /* @__PURE__ */
|
|
2414
|
-
/* @__PURE__ */
|
|
2616
|
+
activeTab === "paint" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2617
|
+
/* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
|
|
2618
|
+
/* @__PURE__ */ jsx10(BrushOptionsBar, { controller }),
|
|
2619
|
+
paintError && /* @__PURE__ */ jsx10("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
|
|
2620
|
+
/* @__PURE__ */ jsx10("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx10(LayersPanel, { controller }) })
|
|
2415
2621
|
] }),
|
|
2416
|
-
activeTab === "annotate" && /* @__PURE__ */
|
|
2417
|
-
/* @__PURE__ */
|
|
2418
|
-
/* @__PURE__ */
|
|
2622
|
+
activeTab === "annotate" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2623
|
+
/* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
|
|
2624
|
+
/* @__PURE__ */ jsx10("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ jsx10(
|
|
2419
2625
|
"button",
|
|
2420
2626
|
{
|
|
2421
2627
|
type: "button",
|
|
@@ -2425,9 +2631,9 @@ var ImageEditor = ({
|
|
|
2425
2631
|
},
|
|
2426
2632
|
t
|
|
2427
2633
|
)) }),
|
|
2428
|
-
/* @__PURE__ */
|
|
2429
|
-
/* @__PURE__ */
|
|
2430
|
-
/* @__PURE__ */
|
|
2634
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
2635
|
+
/* @__PURE__ */ jsx10("label", { className: "text-slate-400", children: "Color:" }),
|
|
2636
|
+
/* @__PURE__ */ jsx10(
|
|
2431
2637
|
"input",
|
|
2432
2638
|
{
|
|
2433
2639
|
type: "color",
|
|
@@ -2436,15 +2642,15 @@ var ImageEditor = ({
|
|
|
2436
2642
|
className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
|
|
2437
2643
|
}
|
|
2438
2644
|
),
|
|
2439
|
-
/* @__PURE__ */
|
|
2440
|
-
/* @__PURE__ */
|
|
2441
|
-
/* @__PURE__ */
|
|
2442
|
-
/* @__PURE__ */
|
|
2645
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex-1 ml-2", children: [
|
|
2646
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
|
|
2647
|
+
/* @__PURE__ */ jsx10("span", { children: "Width:" }),
|
|
2648
|
+
/* @__PURE__ */ jsxs10("span", { className: "font-mono", children: [
|
|
2443
2649
|
strokeWidth,
|
|
2444
2650
|
"px"
|
|
2445
2651
|
] })
|
|
2446
2652
|
] }),
|
|
2447
|
-
/* @__PURE__ */
|
|
2653
|
+
/* @__PURE__ */ jsx10(
|
|
2448
2654
|
"input",
|
|
2449
2655
|
{
|
|
2450
2656
|
type: "range",
|
|
@@ -2457,10 +2663,10 @@ var ImageEditor = ({
|
|
|
2457
2663
|
)
|
|
2458
2664
|
] })
|
|
2459
2665
|
] }),
|
|
2460
|
-
/* @__PURE__ */
|
|
2461
|
-
/* @__PURE__ */
|
|
2462
|
-
/* @__PURE__ */
|
|
2463
|
-
/* @__PURE__ */
|
|
2666
|
+
/* @__PURE__ */ jsx10("div", { className: "h-px bg-slate-800 my-1" }),
|
|
2667
|
+
/* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
|
|
2668
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex gap-2", children: [
|
|
2669
|
+
/* @__PURE__ */ jsx10(
|
|
2464
2670
|
"input",
|
|
2465
2671
|
{
|
|
2466
2672
|
type: "text",
|
|
@@ -2471,7 +2677,7 @@ var ImageEditor = ({
|
|
|
2471
2677
|
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"
|
|
2472
2678
|
}
|
|
2473
2679
|
),
|
|
2474
|
-
/* @__PURE__ */
|
|
2680
|
+
/* @__PURE__ */ jsx10(
|
|
2475
2681
|
"button",
|
|
2476
2682
|
{
|
|
2477
2683
|
type: "button",
|
|
@@ -2481,14 +2687,14 @@ var ImageEditor = ({
|
|
|
2481
2687
|
}
|
|
2482
2688
|
)
|
|
2483
2689
|
] }),
|
|
2484
|
-
/* @__PURE__ */
|
|
2485
|
-
/* @__PURE__ */
|
|
2486
|
-
/* @__PURE__ */
|
|
2690
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between text-slate-400", children: [
|
|
2691
|
+
/* @__PURE__ */ jsx10("span", { children: "Font Size:" }),
|
|
2692
|
+
/* @__PURE__ */ jsxs10("span", { className: "font-mono", children: [
|
|
2487
2693
|
fontSize,
|
|
2488
2694
|
"px"
|
|
2489
2695
|
] })
|
|
2490
2696
|
] }),
|
|
2491
|
-
/* @__PURE__ */
|
|
2697
|
+
/* @__PURE__ */ jsx10(
|
|
2492
2698
|
"input",
|
|
2493
2699
|
{
|
|
2494
2700
|
type: "range",
|
|
@@ -2499,14 +2705,14 @@ var ImageEditor = ({
|
|
|
2499
2705
|
className: "w-full accent-indigo-500"
|
|
2500
2706
|
}
|
|
2501
2707
|
),
|
|
2502
|
-
/* @__PURE__ */
|
|
2503
|
-
/* @__PURE__ */
|
|
2504
|
-
/* @__PURE__ */
|
|
2708
|
+
/* @__PURE__ */ jsx10("div", { className: "h-px bg-slate-800 my-1" }),
|
|
2709
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
|
|
2710
|
+
/* @__PURE__ */ jsxs10("span", { className: "text-slate-400", children: [
|
|
2505
2711
|
"Layers (",
|
|
2506
2712
|
state.annotations.length,
|
|
2507
2713
|
")"
|
|
2508
2714
|
] }),
|
|
2509
|
-
state.selectedAnnotationId && /* @__PURE__ */
|
|
2715
|
+
state.selectedAnnotationId && /* @__PURE__ */ jsx10(
|
|
2510
2716
|
"button",
|
|
2511
2717
|
{
|
|
2512
2718
|
type: "button",
|
|
@@ -2515,7 +2721,7 @@ var ImageEditor = ({
|
|
|
2515
2721
|
children: "Delete Selected"
|
|
2516
2722
|
}
|
|
2517
2723
|
),
|
|
2518
|
-
state.annotations.length > 0 && /* @__PURE__ */
|
|
2724
|
+
state.annotations.length > 0 && /* @__PURE__ */ jsx10(
|
|
2519
2725
|
"button",
|
|
2520
2726
|
{
|
|
2521
2727
|
type: "button",
|
|
@@ -2526,10 +2732,10 @@ var ImageEditor = ({
|
|
|
2526
2732
|
)
|
|
2527
2733
|
] })
|
|
2528
2734
|
] }),
|
|
2529
|
-
activeTab === "depth" && /* @__PURE__ */
|
|
2530
|
-
/* @__PURE__ */
|
|
2531
|
-
/* @__PURE__ */
|
|
2532
|
-
/* @__PURE__ */
|
|
2735
|
+
activeTab === "depth" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2736
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
|
|
2737
|
+
/* @__PURE__ */ jsx10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
|
|
2738
|
+
/* @__PURE__ */ jsx10(
|
|
2533
2739
|
"button",
|
|
2534
2740
|
{
|
|
2535
2741
|
type: "button",
|
|
@@ -2539,8 +2745,8 @@ var ImageEditor = ({
|
|
|
2539
2745
|
}
|
|
2540
2746
|
)
|
|
2541
2747
|
] }),
|
|
2542
|
-
/* @__PURE__ */
|
|
2543
|
-
/* @__PURE__ */
|
|
2748
|
+
/* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
|
|
2749
|
+
/* @__PURE__ */ jsx10(
|
|
2544
2750
|
"input",
|
|
2545
2751
|
{
|
|
2546
2752
|
type: "checkbox",
|
|
@@ -2549,12 +2755,12 @@ var ImageEditor = ({
|
|
|
2549
2755
|
className: "rounded accent-indigo-500"
|
|
2550
2756
|
}
|
|
2551
2757
|
),
|
|
2552
|
-
/* @__PURE__ */
|
|
2758
|
+
/* @__PURE__ */ jsx10("span", { children: "Enable Depth / Alpha Mask" })
|
|
2553
2759
|
] }),
|
|
2554
|
-
state.depthMask.enabled && /* @__PURE__ */
|
|
2555
|
-
/* @__PURE__ */
|
|
2556
|
-
/* @__PURE__ */
|
|
2557
|
-
/* @__PURE__ */
|
|
2760
|
+
state.depthMask.enabled && /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
2761
|
+
/* @__PURE__ */ jsxs10("div", { children: [
|
|
2762
|
+
/* @__PURE__ */ jsx10("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
|
|
2763
|
+
/* @__PURE__ */ jsx10(
|
|
2558
2764
|
"input",
|
|
2559
2765
|
{
|
|
2560
2766
|
type: "text",
|
|
@@ -2565,8 +2771,8 @@ var ImageEditor = ({
|
|
|
2565
2771
|
}
|
|
2566
2772
|
)
|
|
2567
2773
|
] }),
|
|
2568
|
-
/* @__PURE__ */
|
|
2569
|
-
/* @__PURE__ */
|
|
2774
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex gap-2", children: [
|
|
2775
|
+
/* @__PURE__ */ jsx10(
|
|
2570
2776
|
"button",
|
|
2571
2777
|
{
|
|
2572
2778
|
type: "button",
|
|
@@ -2575,7 +2781,7 @@ var ImageEditor = ({
|
|
|
2575
2781
|
children: "Threshold Mode"
|
|
2576
2782
|
}
|
|
2577
2783
|
),
|
|
2578
|
-
/* @__PURE__ */
|
|
2784
|
+
/* @__PURE__ */ jsx10(
|
|
2579
2785
|
"button",
|
|
2580
2786
|
{
|
|
2581
2787
|
type: "button",
|
|
@@ -2585,12 +2791,12 @@ var ImageEditor = ({
|
|
|
2585
2791
|
}
|
|
2586
2792
|
)
|
|
2587
2793
|
] }),
|
|
2588
|
-
/* @__PURE__ */
|
|
2589
|
-
/* @__PURE__ */
|
|
2590
|
-
/* @__PURE__ */
|
|
2591
|
-
/* @__PURE__ */
|
|
2794
|
+
/* @__PURE__ */ jsxs10("div", { children: [
|
|
2795
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
2796
|
+
/* @__PURE__ */ jsx10("span", { children: "Depth Start (Lower):" }),
|
|
2797
|
+
/* @__PURE__ */ jsx10("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
|
|
2592
2798
|
] }),
|
|
2593
|
-
/* @__PURE__ */
|
|
2799
|
+
/* @__PURE__ */ jsx10(
|
|
2594
2800
|
"input",
|
|
2595
2801
|
{
|
|
2596
2802
|
type: "range",
|
|
@@ -2604,12 +2810,12 @@ var ImageEditor = ({
|
|
|
2604
2810
|
}
|
|
2605
2811
|
)
|
|
2606
2812
|
] }),
|
|
2607
|
-
/* @__PURE__ */
|
|
2608
|
-
/* @__PURE__ */
|
|
2609
|
-
/* @__PURE__ */
|
|
2610
|
-
/* @__PURE__ */
|
|
2813
|
+
/* @__PURE__ */ jsxs10("div", { children: [
|
|
2814
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
2815
|
+
/* @__PURE__ */ jsx10("span", { children: "Depth Stop (Upper):" }),
|
|
2816
|
+
/* @__PURE__ */ jsx10("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
|
|
2611
2817
|
] }),
|
|
2612
|
-
/* @__PURE__ */
|
|
2818
|
+
/* @__PURE__ */ jsx10(
|
|
2613
2819
|
"input",
|
|
2614
2820
|
{
|
|
2615
2821
|
type: "range",
|
|
@@ -2623,12 +2829,12 @@ var ImageEditor = ({
|
|
|
2623
2829
|
}
|
|
2624
2830
|
)
|
|
2625
2831
|
] }),
|
|
2626
|
-
/* @__PURE__ */
|
|
2627
|
-
/* @__PURE__ */
|
|
2628
|
-
/* @__PURE__ */
|
|
2629
|
-
/* @__PURE__ */
|
|
2832
|
+
/* @__PURE__ */ jsxs10("div", { children: [
|
|
2833
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
2834
|
+
/* @__PURE__ */ jsx10("span", { children: "Softness:" }),
|
|
2835
|
+
/* @__PURE__ */ jsx10("span", { className: "font-mono", children: state.depthMask.softness })
|
|
2630
2836
|
] }),
|
|
2631
|
-
/* @__PURE__ */
|
|
2837
|
+
/* @__PURE__ */ jsx10(
|
|
2632
2838
|
"input",
|
|
2633
2839
|
{
|
|
2634
2840
|
type: "range",
|
|
@@ -2640,8 +2846,8 @@ var ImageEditor = ({
|
|
|
2640
2846
|
}
|
|
2641
2847
|
)
|
|
2642
2848
|
] }),
|
|
2643
|
-
/* @__PURE__ */
|
|
2644
|
-
/* @__PURE__ */
|
|
2849
|
+
/* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
|
|
2850
|
+
/* @__PURE__ */ jsx10(
|
|
2645
2851
|
"input",
|
|
2646
2852
|
{
|
|
2647
2853
|
type: "checkbox",
|
|
@@ -2650,12 +2856,12 @@ var ImageEditor = ({
|
|
|
2650
2856
|
className: "rounded accent-indigo-500"
|
|
2651
2857
|
}
|
|
2652
2858
|
),
|
|
2653
|
-
/* @__PURE__ */
|
|
2859
|
+
/* @__PURE__ */ jsx10("span", { children: "Invert Mask" })
|
|
2654
2860
|
] })
|
|
2655
2861
|
] })
|
|
2656
2862
|
] }),
|
|
2657
|
-
activeTab === "select" && /* @__PURE__ */
|
|
2658
|
-
/* @__PURE__ */
|
|
2863
|
+
activeTab === "select" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
2864
|
+
/* @__PURE__ */ jsx10(
|
|
2659
2865
|
SelectionOptionsBar,
|
|
2660
2866
|
{
|
|
2661
2867
|
controller,
|
|
@@ -2665,13 +2871,13 @@ var ImageEditor = ({
|
|
|
2665
2871
|
quickMask: Boolean(state.quickMask)
|
|
2666
2872
|
}
|
|
2667
2873
|
),
|
|
2668
|
-
selectionError && /* @__PURE__ */
|
|
2669
|
-
/* @__PURE__ */
|
|
2874
|
+
selectionError && /* @__PURE__ */ jsx10("p", { role: "alert", className: "text-rose-400", children: selectionError }),
|
|
2875
|
+
/* @__PURE__ */ jsx10(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
|
|
2670
2876
|
] }),
|
|
2671
|
-
activeTab === "ai" && /* @__PURE__ */
|
|
2672
|
-
/* @__PURE__ */
|
|
2673
|
-
/* @__PURE__ */
|
|
2674
|
-
/* @__PURE__ */
|
|
2877
|
+
activeTab === "ai" && /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
2878
|
+
/* @__PURE__ */ jsxs10("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
|
|
2879
|
+
/* @__PURE__ */ jsx10("span", { children: "Results go to" }),
|
|
2880
|
+
/* @__PURE__ */ jsxs10(
|
|
2675
2881
|
"select",
|
|
2676
2882
|
{
|
|
2677
2883
|
"aria-label": "AI result target",
|
|
@@ -2679,54 +2885,54 @@ var ImageEditor = ({
|
|
|
2679
2885
|
onChange: (e) => setAiTarget(e.target.value),
|
|
2680
2886
|
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
2681
2887
|
children: [
|
|
2682
|
-
/* @__PURE__ */
|
|
2683
|
-
/* @__PURE__ */
|
|
2684
|
-
/* @__PURE__ */
|
|
2888
|
+
/* @__PURE__ */ jsx10("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
|
|
2889
|
+
/* @__PURE__ */ jsx10("option", { value: "new-layer", children: "New layer / mask" }),
|
|
2890
|
+
/* @__PURE__ */ jsx10("option", { value: "replace", children: "Replace image" })
|
|
2685
2891
|
]
|
|
2686
2892
|
}
|
|
2687
2893
|
)
|
|
2688
2894
|
] }),
|
|
2689
|
-
/* @__PURE__ */
|
|
2690
|
-
/* @__PURE__ */
|
|
2691
|
-
/* @__PURE__ */
|
|
2692
|
-
/* @__PURE__ */
|
|
2895
|
+
/* @__PURE__ */ jsxs10("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
2896
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
|
|
2897
|
+
/* @__PURE__ */ jsxs10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
2898
|
+
/* @__PURE__ */ jsx10("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx10("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" }) }),
|
|
2693
2899
|
"Background Removal"
|
|
2694
2900
|
] }),
|
|
2695
|
-
isRemovingBg && /* @__PURE__ */
|
|
2901
|
+
isRemovingBg && /* @__PURE__ */ jsx10("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..." })
|
|
2696
2902
|
] }),
|
|
2697
|
-
/* @__PURE__ */
|
|
2698
|
-
/* @__PURE__ */
|
|
2903
|
+
/* @__PURE__ */ jsx10("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
|
|
2904
|
+
/* @__PURE__ */ jsx10(
|
|
2699
2905
|
"button",
|
|
2700
2906
|
{
|
|
2701
2907
|
type: "button",
|
|
2702
2908
|
onClick: handleRemoveBackground,
|
|
2703
2909
|
disabled: isRemovingBg || isInpainting,
|
|
2704
2910
|
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",
|
|
2705
|
-
children: isRemovingBg ? /* @__PURE__ */
|
|
2706
|
-
/* @__PURE__ */
|
|
2911
|
+
children: isRemovingBg ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
2912
|
+
/* @__PURE__ */ jsx10("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
2707
2913
|
"Removing Background..."
|
|
2708
|
-
] }) : /* @__PURE__ */
|
|
2709
|
-
/* @__PURE__ */
|
|
2914
|
+
] }) : /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
2915
|
+
/* @__PURE__ */ jsx10("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx10("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" }) }),
|
|
2710
2916
|
"Remove Background"
|
|
2711
2917
|
] })
|
|
2712
2918
|
}
|
|
2713
2919
|
)
|
|
2714
2920
|
] }),
|
|
2715
|
-
/* @__PURE__ */
|
|
2716
|
-
/* @__PURE__ */
|
|
2717
|
-
/* @__PURE__ */
|
|
2718
|
-
/* @__PURE__ */
|
|
2719
|
-
/* @__PURE__ */
|
|
2720
|
-
/* @__PURE__ */
|
|
2921
|
+
/* @__PURE__ */ jsxs10("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
2922
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between", children: [
|
|
2923
|
+
/* @__PURE__ */ jsxs10("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
2924
|
+
/* @__PURE__ */ jsxs10("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
2925
|
+
/* @__PURE__ */ jsx10("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" }),
|
|
2926
|
+
/* @__PURE__ */ jsx10("path", { d: "m14 7 3 3" })
|
|
2721
2927
|
] }),
|
|
2722
2928
|
"Generative Inpainting"
|
|
2723
2929
|
] }),
|
|
2724
|
-
isInpainting && /* @__PURE__ */
|
|
2930
|
+
isInpainting && /* @__PURE__ */ jsx10("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..." })
|
|
2725
2931
|
] }),
|
|
2726
|
-
/* @__PURE__ */
|
|
2727
|
-
/* @__PURE__ */
|
|
2728
|
-
/* @__PURE__ */
|
|
2729
|
-
/* @__PURE__ */
|
|
2932
|
+
/* @__PURE__ */ jsx10("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
|
|
2933
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-1", children: [
|
|
2934
|
+
/* @__PURE__ */ jsx10("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
|
|
2935
|
+
/* @__PURE__ */ jsx10(
|
|
2730
2936
|
"textarea",
|
|
2731
2937
|
{
|
|
2732
2938
|
id: "ai-inpaint-prompt-react",
|
|
@@ -2738,10 +2944,10 @@ var ImageEditor = ({
|
|
|
2738
2944
|
}
|
|
2739
2945
|
)
|
|
2740
2946
|
] }),
|
|
2741
|
-
/* @__PURE__ */
|
|
2742
|
-
/* @__PURE__ */
|
|
2743
|
-
/* @__PURE__ */
|
|
2744
|
-
/* @__PURE__ */
|
|
2947
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-1", children: [
|
|
2948
|
+
/* @__PURE__ */ jsx10("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
|
|
2949
|
+
/* @__PURE__ */ jsxs10("div", { className: "grid grid-cols-2 gap-1.5", children: [
|
|
2950
|
+
/* @__PURE__ */ jsxs10(
|
|
2745
2951
|
"button",
|
|
2746
2952
|
{
|
|
2747
2953
|
type: "button",
|
|
@@ -2754,7 +2960,7 @@ var ImageEditor = ({
|
|
|
2754
2960
|
]
|
|
2755
2961
|
}
|
|
2756
2962
|
),
|
|
2757
|
-
/* @__PURE__ */
|
|
2963
|
+
/* @__PURE__ */ jsxs10(
|
|
2758
2964
|
"button",
|
|
2759
2965
|
{
|
|
2760
2966
|
type: "button",
|
|
@@ -2769,25 +2975,25 @@ var ImageEditor = ({
|
|
|
2769
2975
|
)
|
|
2770
2976
|
] })
|
|
2771
2977
|
] }),
|
|
2772
|
-
/* @__PURE__ */
|
|
2978
|
+
/* @__PURE__ */ jsx10(
|
|
2773
2979
|
"button",
|
|
2774
2980
|
{
|
|
2775
2981
|
type: "button",
|
|
2776
2982
|
onClick: handleInpaint,
|
|
2777
2983
|
disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
|
|
2778
2984
|
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",
|
|
2779
|
-
children: isInpainting ? /* @__PURE__ */
|
|
2780
|
-
/* @__PURE__ */
|
|
2985
|
+
children: isInpainting ? /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
2986
|
+
/* @__PURE__ */ jsx10("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
2781
2987
|
"Generating Inpaint..."
|
|
2782
|
-
] }) : /* @__PURE__ */
|
|
2783
|
-
/* @__PURE__ */
|
|
2988
|
+
] }) : /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
2989
|
+
/* @__PURE__ */ jsx10("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx10("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" }) }),
|
|
2784
2990
|
"Apply Inpainting"
|
|
2785
2991
|
] })
|
|
2786
2992
|
}
|
|
2787
2993
|
)
|
|
2788
2994
|
] }),
|
|
2789
|
-
aiError && /* @__PURE__ */
|
|
2790
|
-
aiSuccess && /* @__PURE__ */
|
|
2995
|
+
aiError && /* @__PURE__ */ jsx10("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
|
|
2996
|
+
aiSuccess && /* @__PURE__ */ jsx10("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
|
|
2791
2997
|
] })
|
|
2792
2998
|
] })
|
|
2793
2999
|
] })
|
|
@@ -2803,10 +3009,11 @@ export {
|
|
|
2803
3009
|
useImageHistogram,
|
|
2804
3010
|
CurvesEditor,
|
|
2805
3011
|
AdjustmentLayersPanel,
|
|
3012
|
+
LayerEffectsPanel,
|
|
2806
3013
|
LayersPanel,
|
|
2807
3014
|
BrushOptionsBar,
|
|
2808
3015
|
SelectionOptionsBar,
|
|
2809
3016
|
RefineEdgePanel,
|
|
2810
3017
|
ImageEditor
|
|
2811
3018
|
};
|
|
2812
|
-
//# sourceMappingURL=chunk-
|
|
3019
|
+
//# sourceMappingURL=chunk-M4WLX3IR.js.map
|