@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
|
@@ -36,6 +36,7 @@ __export(image_editor_exports, {
|
|
|
36
36
|
CurvesEditor: () => CurvesEditor,
|
|
37
37
|
Histogram: () => Histogram,
|
|
38
38
|
ImageEditor: () => ImageEditor,
|
|
39
|
+
LayerEffectsPanel: () => LayerEffectsPanel,
|
|
39
40
|
LayersPanel: () => LayersPanel,
|
|
40
41
|
RefineEdgePanel: () => RefineEdgePanel,
|
|
41
42
|
SelectionOptionsBar: () => SelectionOptionsBar,
|
|
@@ -203,8 +204,8 @@ function useImageEditor(options = {}) {
|
|
|
203
204
|
}
|
|
204
205
|
|
|
205
206
|
// src/image-editor/ImageEditor.tsx
|
|
206
|
-
var
|
|
207
|
-
var
|
|
207
|
+
var import_react10 = __toESM(require("react"), 1);
|
|
208
|
+
var import_image_editor11 = require("@pixerate/editor/image-editor");
|
|
208
209
|
|
|
209
210
|
// src/image-editor/ControlSlider.tsx
|
|
210
211
|
var import_image_editor2 = require("@pixerate/editor/image-editor");
|
|
@@ -636,9 +637,198 @@ var AdjustmentLayersPanel = ({ controller, layers: layersProp, histogram }) => {
|
|
|
636
637
|
};
|
|
637
638
|
|
|
638
639
|
// src/image-editor/LayersPanel.tsx
|
|
640
|
+
var import_react6 = require("react");
|
|
641
|
+
|
|
642
|
+
// src/image-editor/LayerEffectsPanel.tsx
|
|
639
643
|
var import_react5 = require("react");
|
|
640
644
|
var import_image_editor6 = require("@pixerate/editor/image-editor");
|
|
641
645
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
646
|
+
var button = "px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40";
|
|
647
|
+
var LayerEffectsPanel = ({ controller, layerId, className }) => {
|
|
648
|
+
const [, setTick] = (0, import_react5.useState)(0);
|
|
649
|
+
(0, import_react5.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
650
|
+
const [open, setOpen] = (0, import_react5.useState)(null);
|
|
651
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
652
|
+
const commitNext = (0, import_react5.useRef)(true);
|
|
653
|
+
const layer = layerId ? controller.getLayer(layerId) : controller.getActiveLayer();
|
|
654
|
+
const model = (0, import_image_editor6.layerEffectsPanel)(layer);
|
|
655
|
+
const id = layer?.id;
|
|
656
|
+
const attempt = (fn) => {
|
|
657
|
+
try {
|
|
658
|
+
setError(null);
|
|
659
|
+
fn();
|
|
660
|
+
} catch (err) {
|
|
661
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
const sliderEvents = {
|
|
665
|
+
onPointerDown: () => commitNext.current = true,
|
|
666
|
+
onPointerUp: () => commitNext.current = true,
|
|
667
|
+
onKeyDown: () => commitNext.current = true
|
|
668
|
+
};
|
|
669
|
+
if (!model.available || !id) {
|
|
670
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: `text-xs text-slate-500 ${className ?? ""}`, "data-testid": "layer-effects", children: model.reason });
|
|
671
|
+
}
|
|
672
|
+
const effects = controller.getLayerEffects(id);
|
|
673
|
+
const patterns = controller.getDocumentPatterns();
|
|
674
|
+
const change = (effectId, control, value, drag = false) => attempt(() => {
|
|
675
|
+
const effect = controller.getLayerEffects(id).items.find((e) => e.id === effectId);
|
|
676
|
+
controller.updateLayerEffect(id, effectId, (0, import_image_editor6.effectControlChange)(effect, control.key, value, patterns), drag ? commitNext.current : true);
|
|
677
|
+
if (drag) commitNext.current = false;
|
|
678
|
+
});
|
|
679
|
+
const renderControl = (effectId, c) => {
|
|
680
|
+
const label = `${c.label}`;
|
|
681
|
+
switch (c.type) {
|
|
682
|
+
case "range": {
|
|
683
|
+
const k = c.percent ? 100 : 1;
|
|
684
|
+
const shown = Math.round(c.value * k * 100) / 100;
|
|
685
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
686
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "text-slate-400", children: [
|
|
687
|
+
label,
|
|
688
|
+
" ",
|
|
689
|
+
shown,
|
|
690
|
+
c.unit
|
|
691
|
+
] }),
|
|
692
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
693
|
+
"input",
|
|
694
|
+
{
|
|
695
|
+
type: "range",
|
|
696
|
+
"aria-label": label,
|
|
697
|
+
min: c.min * k,
|
|
698
|
+
max: c.max * k,
|
|
699
|
+
step: c.step * k,
|
|
700
|
+
value: shown,
|
|
701
|
+
disabled: model.readOnly,
|
|
702
|
+
...sliderEvents,
|
|
703
|
+
onChange: (e) => change(effectId, c, Number(e.target.value) / k, true),
|
|
704
|
+
className: "accent-indigo-500"
|
|
705
|
+
}
|
|
706
|
+
)
|
|
707
|
+
] }, c.key);
|
|
708
|
+
}
|
|
709
|
+
case "color":
|
|
710
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
711
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "color", "aria-label": label, value: c.value, disabled: model.readOnly, onChange: (e) => change(effectId, c, e.target.value) }),
|
|
712
|
+
label
|
|
713
|
+
] }, c.key);
|
|
714
|
+
case "checkbox":
|
|
715
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
716
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "checkbox", "aria-label": label, checked: c.value, disabled: model.readOnly, onChange: (e) => change(effectId, c, e.target.checked), className: "accent-indigo-500" }),
|
|
717
|
+
label
|
|
718
|
+
] }, c.key);
|
|
719
|
+
case "select":
|
|
720
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
721
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-slate-400", children: label }),
|
|
722
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
723
|
+
"select",
|
|
724
|
+
{
|
|
725
|
+
"aria-label": label,
|
|
726
|
+
value: c.value,
|
|
727
|
+
disabled: model.readOnly,
|
|
728
|
+
onChange: (e) => change(effectId, c, e.target.value),
|
|
729
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
730
|
+
children: c.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: o.value, children: o.label }, o.value))
|
|
731
|
+
}
|
|
732
|
+
)
|
|
733
|
+
] }, c.key);
|
|
734
|
+
}
|
|
735
|
+
};
|
|
736
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("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: [
|
|
737
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
738
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "font-semibold text-slate-300", children: "fx Effects" }),
|
|
739
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1 text-slate-300", children: [
|
|
740
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
741
|
+
"input",
|
|
742
|
+
{
|
|
743
|
+
type: "checkbox",
|
|
744
|
+
"aria-label": "Effects on",
|
|
745
|
+
checked: model.enabled,
|
|
746
|
+
disabled: model.readOnly,
|
|
747
|
+
onChange: (e) => attempt(() => controller.setLayerEffectsEnabled(id, e.target.checked)),
|
|
748
|
+
className: "accent-indigo-500"
|
|
749
|
+
}
|
|
750
|
+
),
|
|
751
|
+
"On"
|
|
752
|
+
] }),
|
|
753
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
|
|
754
|
+
"Scale",
|
|
755
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
756
|
+
"input",
|
|
757
|
+
{
|
|
758
|
+
type: "number",
|
|
759
|
+
"aria-label": "Scale effects",
|
|
760
|
+
min: 1,
|
|
761
|
+
max: 1e3,
|
|
762
|
+
step: 1,
|
|
763
|
+
value: Math.round(model.scale * 100),
|
|
764
|
+
disabled: model.readOnly,
|
|
765
|
+
onChange: (e) => {
|
|
766
|
+
const v = Number(e.target.value);
|
|
767
|
+
if (v >= 1 && v <= 1e3) attempt(() => controller.setLayerEffectsEnabled(id, model.enabled, v / 100));
|
|
768
|
+
},
|
|
769
|
+
className: "w-14 bg-slate-800 border border-slate-700 rounded px-1"
|
|
770
|
+
}
|
|
771
|
+
),
|
|
772
|
+
"%"
|
|
773
|
+
] }),
|
|
774
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
775
|
+
"select",
|
|
776
|
+
{
|
|
777
|
+
"aria-label": "Add effect",
|
|
778
|
+
value: "",
|
|
779
|
+
disabled: model.readOnly,
|
|
780
|
+
onChange: (e) => {
|
|
781
|
+
const kind = e.target.value;
|
|
782
|
+
if (!kind) return;
|
|
783
|
+
attempt(() => setOpen(controller.addLayerEffect(id, kind).effect.id));
|
|
784
|
+
},
|
|
785
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
786
|
+
children: [
|
|
787
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "", children: "Add effect\u2026" }),
|
|
788
|
+
import_image_editor6.LAYER_EFFECT_MENU.map((m) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: m.kind, children: m.label }, m.kind))
|
|
789
|
+
]
|
|
790
|
+
}
|
|
791
|
+
)
|
|
792
|
+
] }),
|
|
793
|
+
model.readOnly && model.reason && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-slate-500", children: model.reason }),
|
|
794
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "flex flex-col gap-1", "aria-label": "Effects", children: model.rows.map((row) => {
|
|
795
|
+
const effect = effects.items.find((e) => e.id === row.id);
|
|
796
|
+
const expanded = open === row.id;
|
|
797
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("li", { "data-effect-id": row.id, className: "rounded bg-slate-900/60 ring-1 ring-slate-800", children: [
|
|
798
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1.5 px-1.5 py-1", children: [
|
|
799
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
800
|
+
"input",
|
|
801
|
+
{
|
|
802
|
+
type: "checkbox",
|
|
803
|
+
"aria-label": `${row.label} on`,
|
|
804
|
+
checked: row.enabled,
|
|
805
|
+
disabled: model.readOnly,
|
|
806
|
+
onChange: (e) => attempt(() => controller.updateLayerEffect(id, row.id, { enabled: e.target.checked })),
|
|
807
|
+
className: "accent-indigo-500"
|
|
808
|
+
}
|
|
809
|
+
),
|
|
810
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
811
|
+
"button",
|
|
812
|
+
{
|
|
813
|
+
type: "button",
|
|
814
|
+
"aria-expanded": expanded,
|
|
815
|
+
className: `flex-1 text-left ${row.enabled && model.enabled ? "" : "text-slate-500"}`,
|
|
816
|
+
onClick: () => setOpen(expanded ? null : row.id),
|
|
817
|
+
children: row.label
|
|
818
|
+
}
|
|
819
|
+
),
|
|
820
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: button, "aria-label": `Remove ${row.label}`, disabled: model.readOnly, onClick: () => attempt(() => controller.removeLayerEffect(id, row.id)), children: "\u2715" })
|
|
821
|
+
] }),
|
|
822
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 px-1.5 pb-1.5", "data-testid": "effect-settings", children: (0, import_image_editor6.layerEffectControls)(effect, patterns).map((c) => renderControl(row.id, c)) })
|
|
823
|
+
] }, row.id);
|
|
824
|
+
}) }),
|
|
825
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
|
|
826
|
+
] });
|
|
827
|
+
};
|
|
828
|
+
|
|
829
|
+
// src/image-editor/LayersPanel.tsx
|
|
830
|
+
var import_image_editor7 = require("@pixerate/editor/image-editor");
|
|
831
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
642
832
|
var iconButton = "px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40";
|
|
643
833
|
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"}`;
|
|
644
834
|
var Thumbnail = ({
|
|
@@ -649,8 +839,8 @@ var Thumbnail = ({
|
|
|
649
839
|
selected,
|
|
650
840
|
testId
|
|
651
841
|
}) => {
|
|
652
|
-
const ref = (0,
|
|
653
|
-
(0,
|
|
842
|
+
const ref = (0, import_react6.useRef)(null);
|
|
843
|
+
(0, import_react6.useEffect)(() => {
|
|
654
844
|
const canvas = ref.current;
|
|
655
845
|
const ctx = canvas?.getContext("2d");
|
|
656
846
|
if (!canvas || !ctx || !pixels || typeof ctx.createImageData !== "function") return;
|
|
@@ -660,7 +850,7 @@ var Thumbnail = ({
|
|
|
660
850
|
img.data.set(pixels.data);
|
|
661
851
|
ctx.putImageData(img, 0, 0);
|
|
662
852
|
}, [pixels]);
|
|
663
|
-
return /* @__PURE__ */ (0,
|
|
853
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
664
854
|
"canvas",
|
|
665
855
|
{
|
|
666
856
|
ref,
|
|
@@ -673,15 +863,15 @@ var Thumbnail = ({
|
|
|
673
863
|
}
|
|
674
864
|
);
|
|
675
865
|
};
|
|
676
|
-
var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", className }) => {
|
|
677
|
-
const [, setTick] = (0,
|
|
678
|
-
(0,
|
|
679
|
-
const [error, setError] = (0,
|
|
680
|
-
const [renaming, setRenaming] = (0,
|
|
681
|
-
const [menu, setMenu] = (0,
|
|
682
|
-
const [drag, setDrag] = (0,
|
|
683
|
-
const [psdNotes, setPsdNotes] = (0,
|
|
684
|
-
const fileInput = (0,
|
|
866
|
+
var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", effects = true, className }) => {
|
|
867
|
+
const [, setTick] = (0, import_react6.useState)(0);
|
|
868
|
+
(0, import_react6.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
869
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
870
|
+
const [renaming, setRenaming] = (0, import_react6.useState)(null);
|
|
871
|
+
const [menu, setMenu] = (0, import_react6.useState)(null);
|
|
872
|
+
const [drag, setDrag] = (0, import_react6.useState)(null);
|
|
873
|
+
const [psdNotes, setPsdNotes] = (0, import_react6.useState)([]);
|
|
874
|
+
const fileInput = (0, import_react6.useRef)(null);
|
|
685
875
|
const psdTask = async (fn) => {
|
|
686
876
|
try {
|
|
687
877
|
setError(null);
|
|
@@ -690,9 +880,9 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
690
880
|
setError(err instanceof Error ? err.message : String(err));
|
|
691
881
|
}
|
|
692
882
|
};
|
|
693
|
-
const commitNext = (0,
|
|
883
|
+
const commitNext = (0, import_react6.useRef)(true);
|
|
694
884
|
const state = controller.getState();
|
|
695
|
-
const rows = (0,
|
|
885
|
+
const rows = (0, import_image_editor7.layerPanelRows)(state.layers, state.activeLayerId);
|
|
696
886
|
const active = controller.getActiveLayer();
|
|
697
887
|
const attempt = (fn) => {
|
|
698
888
|
try {
|
|
@@ -704,7 +894,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
704
894
|
};
|
|
705
895
|
const run = async (action) => {
|
|
706
896
|
setMenu(null);
|
|
707
|
-
setError(await (0,
|
|
897
|
+
setError(await (0, import_image_editor7.runLayerMenuAction)(controller, action));
|
|
708
898
|
};
|
|
709
899
|
const prop = (key, value) => attempt(() => {
|
|
710
900
|
controller.setLayerProperties(active.id, { [key]: value }, commitNext.current);
|
|
@@ -722,20 +912,20 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
722
912
|
if (!id) return;
|
|
723
913
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
724
914
|
const fraction = rect.height ? (e.clientY - rect.top) / rect.height : 0.5;
|
|
725
|
-
const placement = (0,
|
|
915
|
+
const placement = (0, import_image_editor7.dropPlacement)(state.layers, id, row.layer.id, (0, import_image_editor7.dropZone)(fraction, row.layer.type === "group"));
|
|
726
916
|
if (placement) attempt(() => controller.moveLayer(id, placement));
|
|
727
917
|
};
|
|
728
918
|
const thumb = (layer) => layer.type === "pixel" ? controller.getLayerThumbnail(layer.id, { maxSide: 64 }) : null;
|
|
729
919
|
const maskThumb = (layer) => layer.mask && !layer.mask.source ? controller.getLayerThumbnail(layer.id, { maxSide: 64, mask: true }) : null;
|
|
730
920
|
const locked = (layer) => Boolean(layer.locks?.all || layer.locks?.pixels || layer.locks?.position || layer.locks?.transparency);
|
|
731
|
-
return /* @__PURE__ */ (0,
|
|
732
|
-
/* @__PURE__ */ (0,
|
|
733
|
-
/* @__PURE__ */ (0,
|
|
734
|
-
/* @__PURE__ */ (0,
|
|
735
|
-
/* @__PURE__ */ (0,
|
|
736
|
-
/* @__PURE__ */ (0,
|
|
737
|
-
/* @__PURE__ */ (0,
|
|
738
|
-
/* @__PURE__ */ (0,
|
|
921
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layers-panel", onClick: () => menu && setMenu(null), children: [
|
|
922
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "toolbar", "aria-label": "Layer actions", children: [
|
|
923
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-layer"), children: "New Layer" }),
|
|
924
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-group"), children: "New Group" }),
|
|
925
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("duplicate"), children: "Duplicate" }),
|
|
926
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("add-mask"), children: "Add Mask" }),
|
|
927
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("delete"), children: "Delete" }),
|
|
928
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
739
929
|
"button",
|
|
740
930
|
{
|
|
741
931
|
type: "button",
|
|
@@ -750,39 +940,39 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
750
940
|
children: "\u22EF"
|
|
751
941
|
}
|
|
752
942
|
),
|
|
753
|
-
psd && /* @__PURE__ */ (0,
|
|
754
|
-
/* @__PURE__ */ (0,
|
|
755
|
-
/* @__PURE__ */ (0,
|
|
756
|
-
/* @__PURE__ */ (0,
|
|
943
|
+
psd && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
944
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: iconButton, onClick: () => fileInput.current?.click(), children: "Open PSD\u2026" }),
|
|
945
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: iconButton, onClick: () => psdTask(async () => (await (0, import_image_editor7.downloadPsd)(controller, psdFileName)).warnings), children: "Export PSD" }),
|
|
946
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
757
947
|
"input",
|
|
758
948
|
{
|
|
759
949
|
ref: fileInput,
|
|
760
950
|
type: "file",
|
|
761
|
-
accept:
|
|
951
|
+
accept: import_image_editor7.PSD_FILE_ACCEPT,
|
|
762
952
|
className: "hidden",
|
|
763
953
|
"data-testid": "psd-file-input",
|
|
764
954
|
"aria-label": "Open a PSD file",
|
|
765
955
|
onChange: (e) => {
|
|
766
956
|
const file = e.currentTarget.files?.[0];
|
|
767
957
|
e.currentTarget.value = "";
|
|
768
|
-
if (file) psdTask(() => (0,
|
|
958
|
+
if (file) psdTask(() => (0, import_image_editor7.openPsdFile)(controller, file));
|
|
769
959
|
}
|
|
770
960
|
}
|
|
771
961
|
)
|
|
772
962
|
] })
|
|
773
963
|
] }),
|
|
774
|
-
psdNotes.length > 0 && /* @__PURE__ */ (0,
|
|
775
|
-
psdNotes.map((n) => /* @__PURE__ */ (0,
|
|
776
|
-
/* @__PURE__ */ (0,
|
|
964
|
+
psdNotes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("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: [
|
|
965
|
+
psdNotes.map((n) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { children: n }, n)),
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "underline", onClick: () => setPsdNotes([]), children: "Dismiss" }) })
|
|
777
967
|
] }),
|
|
778
|
-
active && /* @__PURE__ */ (0,
|
|
779
|
-
/* @__PURE__ */ (0,
|
|
780
|
-
/* @__PURE__ */ (0,
|
|
968
|
+
active && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 items-center", "data-testid": "layer-properties", children: [
|
|
969
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
970
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-slate-400", children: [
|
|
781
971
|
"Opacity ",
|
|
782
972
|
Math.round(active.opacity * 100),
|
|
783
973
|
"%"
|
|
784
974
|
] }),
|
|
785
|
-
/* @__PURE__ */ (0,
|
|
975
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
786
976
|
"input",
|
|
787
977
|
{
|
|
788
978
|
type: "range",
|
|
@@ -796,13 +986,13 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
796
986
|
}
|
|
797
987
|
)
|
|
798
988
|
] }),
|
|
799
|
-
/* @__PURE__ */ (0,
|
|
800
|
-
/* @__PURE__ */ (0,
|
|
989
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
|
|
990
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-slate-400", children: [
|
|
801
991
|
"Fill ",
|
|
802
992
|
Math.round(((active.type === "pixel" ? active.fillOpacity : void 0) ?? 1) * 100),
|
|
803
993
|
"%"
|
|
804
994
|
] }),
|
|
805
|
-
/* @__PURE__ */ (0,
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
806
996
|
"input",
|
|
807
997
|
{
|
|
808
998
|
type: "range",
|
|
@@ -817,7 +1007,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
817
1007
|
}
|
|
818
1008
|
)
|
|
819
1009
|
] }),
|
|
820
|
-
/* @__PURE__ */ (0,
|
|
1010
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
821
1011
|
"select",
|
|
822
1012
|
{
|
|
823
1013
|
"aria-label": "Layer blend mode",
|
|
@@ -825,13 +1015,13 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
825
1015
|
value: active.blend,
|
|
826
1016
|
onChange: (e) => attempt(() => controller.setLayerProperties(active.id, { blend: e.target.value })),
|
|
827
1017
|
children: [
|
|
828
|
-
active.type === "group" && /* @__PURE__ */ (0,
|
|
829
|
-
|
|
1018
|
+
active.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "pass-through", children: "Pass Through" }),
|
|
1019
|
+
import_image_editor7.BLEND_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: m.id, children: m.label }, m.id))
|
|
830
1020
|
]
|
|
831
1021
|
}
|
|
832
1022
|
),
|
|
833
|
-
/* @__PURE__ */ (0,
|
|
834
|
-
/* @__PURE__ */ (0,
|
|
1023
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
1024
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
835
1025
|
"input",
|
|
836
1026
|
{
|
|
837
1027
|
type: "checkbox",
|
|
@@ -843,8 +1033,8 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
843
1033
|
),
|
|
844
1034
|
"Clip to below"
|
|
845
1035
|
] }),
|
|
846
|
-
/* @__PURE__ */ (0,
|
|
847
|
-
/* @__PURE__ */ (0,
|
|
1036
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
1037
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
848
1038
|
"input",
|
|
849
1039
|
{
|
|
850
1040
|
type: "checkbox",
|
|
@@ -857,9 +1047,10 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
857
1047
|
k
|
|
858
1048
|
] }, k)) })
|
|
859
1049
|
] }),
|
|
860
|
-
/* @__PURE__ */ (0,
|
|
1050
|
+
effects && active && active.type !== "adjustment" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(LayerEffectsPanel, { controller, className: "border-t border-slate-800 pt-1.5" }),
|
|
1051
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "flex flex-col gap-0.5", role: "tree", "aria-label": "Layers", children: rows.map((row) => {
|
|
861
1052
|
const { layer } = row;
|
|
862
|
-
return /* @__PURE__ */ (0,
|
|
1053
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
863
1054
|
"li",
|
|
864
1055
|
{
|
|
865
1056
|
role: "treeitem",
|
|
@@ -889,7 +1080,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
889
1080
|
className: rowClass(row.active),
|
|
890
1081
|
style: { paddingLeft: 6 + row.depth * 14 },
|
|
891
1082
|
children: [
|
|
892
|
-
/* @__PURE__ */ (0,
|
|
1083
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
893
1084
|
"button",
|
|
894
1085
|
{
|
|
895
1086
|
type: "button",
|
|
@@ -903,7 +1094,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
903
1094
|
children: layer.visible ? "\u25CF" : "\u25CB"
|
|
904
1095
|
}
|
|
905
1096
|
),
|
|
906
|
-
layer.type === "group" && /* @__PURE__ */ (0,
|
|
1097
|
+
layer.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
907
1098
|
"button",
|
|
908
1099
|
{
|
|
909
1100
|
type: "button",
|
|
@@ -916,8 +1107,8 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
916
1107
|
children: layer.collapsed ? "\u25B8" : "\u25BE"
|
|
917
1108
|
}
|
|
918
1109
|
),
|
|
919
|
-
row.clipped && /* @__PURE__ */ (0,
|
|
920
|
-
layer.type === "pixel" ? /* @__PURE__ */ (0,
|
|
1110
|
+
row.clipped && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-slate-500", "aria-label": "Clipped", children: "\u21B3" }),
|
|
1111
|
+
layer.type === "pixel" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
921
1112
|
Thumbnail,
|
|
922
1113
|
{
|
|
923
1114
|
pixels: thumb(layer),
|
|
@@ -925,15 +1116,15 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
925
1116
|
label: `${row.label} pixels`,
|
|
926
1117
|
selected: row.active && state.activeTarget === "pixels" && Boolean(layer.mask)
|
|
927
1118
|
}
|
|
928
|
-
) : /* @__PURE__ */ (0,
|
|
1119
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
929
1120
|
"span",
|
|
930
1121
|
{
|
|
931
1122
|
className: "shrink-0 grid place-items-center rounded bg-slate-800 text-[9px] text-slate-400 ring-1 ring-slate-700",
|
|
932
1123
|
style: { width: thumbnailSize, height: thumbnailSize },
|
|
933
|
-
children: (0,
|
|
1124
|
+
children: (0, import_image_editor7.layerBadge)(layer)
|
|
934
1125
|
}
|
|
935
1126
|
),
|
|
936
|
-
layer.mask && /* @__PURE__ */ (0,
|
|
1127
|
+
layer.mask && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
937
1128
|
Thumbnail,
|
|
938
1129
|
{
|
|
939
1130
|
pixels: maskThumb(layer),
|
|
@@ -948,7 +1139,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
948
1139
|
}
|
|
949
1140
|
}
|
|
950
1141
|
),
|
|
951
|
-
renaming === layer.id ? /* @__PURE__ */ (0,
|
|
1142
|
+
renaming === layer.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
952
1143
|
"input",
|
|
953
1144
|
{
|
|
954
1145
|
autoFocus: true,
|
|
@@ -965,7 +1156,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
965
1156
|
if (e.key === "Escape") setRenaming(null);
|
|
966
1157
|
}
|
|
967
1158
|
}
|
|
968
|
-
) : /* @__PURE__ */ (0,
|
|
1159
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
969
1160
|
"span",
|
|
970
1161
|
{
|
|
971
1162
|
className: `flex-1 min-w-0 truncate ${layer.visible ? "" : "text-slate-500"}`,
|
|
@@ -976,15 +1167,30 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
976
1167
|
children: row.label
|
|
977
1168
|
}
|
|
978
1169
|
),
|
|
979
|
-
|
|
980
|
-
|
|
1170
|
+
(0, import_image_editor7.layerEffectsBadge)(layer) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1171
|
+
"button",
|
|
1172
|
+
{
|
|
1173
|
+
type: "button",
|
|
1174
|
+
"data-testid": "layer-fx-badge",
|
|
1175
|
+
"aria-label": (0, import_image_editor7.layerEffectsBadge)(layer) === "on" ? `Turn effects off for ${row.label}` : `Turn effects on for ${row.label}`,
|
|
1176
|
+
"aria-pressed": (0, import_image_editor7.layerEffectsBadge)(layer) === "on",
|
|
1177
|
+
className: `text-[9px] italic font-semibold ${(0, import_image_editor7.layerEffectsBadge)(layer) === "on" ? "text-indigo-300" : "text-slate-600 line-through"}`,
|
|
1178
|
+
onClick: (e) => {
|
|
1179
|
+
e.stopPropagation();
|
|
1180
|
+
attempt(() => controller.setLayerEffectsEnabled(layer.id, (0, import_image_editor7.layerEffectsBadge)(layer) !== "on"));
|
|
1181
|
+
},
|
|
1182
|
+
children: "fx"
|
|
1183
|
+
}
|
|
1184
|
+
),
|
|
1185
|
+
locked(layer) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "aria-label": "Locked", className: "text-slate-400", children: "\u{1F512}" }),
|
|
1186
|
+
layer.blend !== "normal" && layer.blend !== "pass-through" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[9px] text-slate-500", children: layer.blend })
|
|
981
1187
|
]
|
|
982
1188
|
},
|
|
983
1189
|
layer.id
|
|
984
1190
|
);
|
|
985
1191
|
}) }),
|
|
986
|
-
error && /* @__PURE__ */ (0,
|
|
987
|
-
menu && /* @__PURE__ */ (0,
|
|
1192
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
1193
|
+
menu && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
988
1194
|
"div",
|
|
989
1195
|
{
|
|
990
1196
|
role: "menu",
|
|
@@ -993,7 +1199,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
993
1199
|
style: { left: menu.x, top: menu.y },
|
|
994
1200
|
onClick: (e) => e.stopPropagation(),
|
|
995
1201
|
onKeyDown: (e) => e.key === "Escape" && setMenu(null),
|
|
996
|
-
children: (0,
|
|
1202
|
+
children: (0, import_image_editor7.layerMenu)(controller).map((item) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
997
1203
|
"button",
|
|
998
1204
|
{
|
|
999
1205
|
type: "button",
|
|
@@ -1011,14 +1217,14 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
1011
1217
|
};
|
|
1012
1218
|
|
|
1013
1219
|
// src/image-editor/BrushOptionsBar.tsx
|
|
1014
|
-
var
|
|
1015
|
-
var
|
|
1016
|
-
var
|
|
1220
|
+
var import_react7 = require("react");
|
|
1221
|
+
var import_image_editor8 = require("@pixerate/editor/image-editor");
|
|
1222
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1017
1223
|
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"}`;
|
|
1018
1224
|
var BrushOptionsBar = ({ controller, className }) => {
|
|
1019
|
-
const [, setTick] = (0,
|
|
1020
|
-
(0,
|
|
1021
|
-
const [error, setError] = (0,
|
|
1225
|
+
const [, setTick] = (0, import_react7.useState)(0);
|
|
1226
|
+
(0, import_react7.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
1227
|
+
const [error, setError] = (0, import_react7.useState)(null);
|
|
1022
1228
|
const state = controller.getState();
|
|
1023
1229
|
const { brush, foreground, background, mixer, mixerLoad } = state.paint;
|
|
1024
1230
|
const attempt = (fn) => {
|
|
@@ -1029,8 +1235,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1029
1235
|
setError(err instanceof Error ? err.message : String(err));
|
|
1030
1236
|
}
|
|
1031
1237
|
};
|
|
1032
|
-
return /* @__PURE__ */ (0,
|
|
1033
|
-
/* @__PURE__ */ (0,
|
|
1238
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
|
|
1239
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor8.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1034
1240
|
"button",
|
|
1035
1241
|
{
|
|
1036
1242
|
type: "button",
|
|
@@ -1042,9 +1248,9 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1042
1248
|
},
|
|
1043
1249
|
t.id
|
|
1044
1250
|
)) }),
|
|
1045
|
-
/* @__PURE__ */ (0,
|
|
1046
|
-
/* @__PURE__ */ (0,
|
|
1047
|
-
/* @__PURE__ */ (0,
|
|
1251
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
|
|
1252
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
1253
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1048
1254
|
"input",
|
|
1049
1255
|
{
|
|
1050
1256
|
type: "color",
|
|
@@ -1054,10 +1260,10 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1054
1260
|
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
1055
1261
|
}
|
|
1056
1262
|
),
|
|
1057
|
-
/* @__PURE__ */ (0,
|
|
1263
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-slate-400", children: "FG" })
|
|
1058
1264
|
] }),
|
|
1059
|
-
/* @__PURE__ */ (0,
|
|
1060
|
-
/* @__PURE__ */ (0,
|
|
1265
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1", children: [
|
|
1266
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1061
1267
|
"input",
|
|
1062
1268
|
{
|
|
1063
1269
|
type: "color",
|
|
@@ -1067,12 +1273,12 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1067
1273
|
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
1068
1274
|
}
|
|
1069
1275
|
),
|
|
1070
|
-
/* @__PURE__ */ (0,
|
|
1276
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-slate-400", children: "BG" })
|
|
1071
1277
|
] }),
|
|
1072
|
-
/* @__PURE__ */ (0,
|
|
1073
|
-
/* @__PURE__ */ (0,
|
|
1278
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
|
|
1279
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" })
|
|
1074
1280
|
] }),
|
|
1075
|
-
|
|
1281
|
+
import_image_editor8.BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1076
1282
|
ControlSlider,
|
|
1077
1283
|
{
|
|
1078
1284
|
spec,
|
|
@@ -1081,21 +1287,21 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1081
1287
|
},
|
|
1082
1288
|
spec.id
|
|
1083
1289
|
)),
|
|
1084
|
-
state.activeTool === "mixer" && /* @__PURE__ */ (0,
|
|
1085
|
-
/* @__PURE__ */ (0,
|
|
1086
|
-
/* @__PURE__ */ (0,
|
|
1290
|
+
state.activeTool === "mixer" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Mixer Brush", "data-testid": "mixer-options", children: [
|
|
1291
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1292
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1087
1293
|
"span",
|
|
1088
1294
|
{
|
|
1089
1295
|
"aria-label": "Brush load",
|
|
1090
|
-
title: mixerLoad.reservoir ? `Loaded ${(0,
|
|
1296
|
+
title: mixerLoad.reservoir ? `Loaded ${(0, import_image_editor8.rgbUnitToHex)(mixerLoad.reservoir)}, ${Math.round(mixerLoad.amount * 100)}% left` : "Unloaded",
|
|
1091
1297
|
className: "h-6 w-6 rounded border border-slate-700",
|
|
1092
|
-
style: { background: mixerLoad.reservoir ? (0,
|
|
1298
|
+
style: { background: mixerLoad.reservoir ? (0, import_image_editor8.rgbUnitToHex)(mixerLoad.reservoir) : "transparent" }
|
|
1093
1299
|
}
|
|
1094
1300
|
),
|
|
1095
|
-
/* @__PURE__ */ (0,
|
|
1096
|
-
/* @__PURE__ */ (0,
|
|
1301
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", title: "Fill the reservoir with the foreground colour", className: chip(false), onClick: () => controller.loadMixerBrush(), children: "Load brush" }),
|
|
1302
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", title: "Empty the picked-up colour", className: chip(false), onClick: () => controller.cleanMixerBrush(), children: "Clean brush" })
|
|
1097
1303
|
] }),
|
|
1098
|
-
/* @__PURE__ */ (0,
|
|
1304
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Mixing", children: import_image_editor8.MIXER_MIXING_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1099
1305
|
"button",
|
|
1100
1306
|
{
|
|
1101
1307
|
type: "button",
|
|
@@ -1107,10 +1313,10 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1107
1313
|
},
|
|
1108
1314
|
m.id
|
|
1109
1315
|
)) }),
|
|
1110
|
-
|
|
1111
|
-
/* @__PURE__ */ (0,
|
|
1112
|
-
/* @__PURE__ */ (0,
|
|
1113
|
-
/* @__PURE__ */ (0,
|
|
1316
|
+
import_image_editor8.MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ControlSlider, { spec, value: mixer[spec.id], onChange: (v) => controller.setPaintOptions({ mixer: { [spec.id]: v } }) }, spec.id)),
|
|
1317
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: [
|
|
1318
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
1319
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1114
1320
|
"input",
|
|
1115
1321
|
{
|
|
1116
1322
|
type: "checkbox",
|
|
@@ -1122,8 +1328,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1122
1328
|
),
|
|
1123
1329
|
"Load each stroke"
|
|
1124
1330
|
] }),
|
|
1125
|
-
/* @__PURE__ */ (0,
|
|
1126
|
-
/* @__PURE__ */ (0,
|
|
1331
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
1332
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1127
1333
|
"input",
|
|
1128
1334
|
{
|
|
1129
1335
|
type: "checkbox",
|
|
@@ -1137,9 +1343,9 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1137
1343
|
] })
|
|
1138
1344
|
] })
|
|
1139
1345
|
] }),
|
|
1140
|
-
/* @__PURE__ */ (0,
|
|
1141
|
-
/* @__PURE__ */ (0,
|
|
1142
|
-
/* @__PURE__ */ (0,
|
|
1346
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
|
|
1347
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
1348
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1143
1349
|
"input",
|
|
1144
1350
|
{
|
|
1145
1351
|
type: "checkbox",
|
|
@@ -1151,8 +1357,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1151
1357
|
),
|
|
1152
1358
|
"Pressure size"
|
|
1153
1359
|
] }),
|
|
1154
|
-
/* @__PURE__ */ (0,
|
|
1155
|
-
/* @__PURE__ */ (0,
|
|
1360
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1.5", children: [
|
|
1361
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1156
1362
|
"input",
|
|
1157
1363
|
{
|
|
1158
1364
|
type: "checkbox",
|
|
@@ -1165,18 +1371,18 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1165
1371
|
"Pressure opacity"
|
|
1166
1372
|
] })
|
|
1167
1373
|
] }),
|
|
1168
|
-
/* @__PURE__ */ (0,
|
|
1169
|
-
/* @__PURE__ */ (0,
|
|
1170
|
-
/* @__PURE__ */ (0,
|
|
1374
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex gap-1", children: [
|
|
1375
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
|
|
1376
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
|
|
1171
1377
|
] }),
|
|
1172
|
-
error && /* @__PURE__ */ (0,
|
|
1378
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
|
|
1173
1379
|
] });
|
|
1174
1380
|
};
|
|
1175
1381
|
|
|
1176
1382
|
// src/image-editor/SelectionOptionsBar.tsx
|
|
1177
|
-
var
|
|
1178
|
-
var
|
|
1179
|
-
var
|
|
1383
|
+
var import_react8 = require("react");
|
|
1384
|
+
var import_image_editor9 = require("@pixerate/editor/image-editor");
|
|
1385
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1180
1386
|
var MODIFY_OPS = [
|
|
1181
1387
|
{ op: "grow", label: "Grow" },
|
|
1182
1388
|
{ op: "shrink", label: "Shrink" },
|
|
@@ -1193,20 +1399,20 @@ var SelectionOptionsBar = ({
|
|
|
1193
1399
|
quickMask,
|
|
1194
1400
|
className = ""
|
|
1195
1401
|
}) => {
|
|
1196
|
-
const [radius, setRadius] = (0,
|
|
1402
|
+
const [radius, setRadius] = (0, import_react8.useState)(2);
|
|
1197
1403
|
const set = (patch) => onOptionsChange({ ...options, ...patch });
|
|
1198
1404
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
1199
1405
|
const qm = quickMask ?? Boolean(controller.getState().quickMask);
|
|
1200
|
-
return /* @__PURE__ */ (0,
|
|
1201
|
-
/* @__PURE__ */ (0,
|
|
1202
|
-
/* @__PURE__ */ (0,
|
|
1203
|
-
options.tool === "wand" && /* @__PURE__ */ (0,
|
|
1204
|
-
/* @__PURE__ */ (0,
|
|
1205
|
-
/* @__PURE__ */ (0,
|
|
1206
|
-
/* @__PURE__ */ (0,
|
|
1207
|
-
/* @__PURE__ */ (0,
|
|
1406
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
1407
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: import_image_editor9.SELECTION_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", "aria-pressed": options.tool === t.id, className: btn(options.tool === t.id), onClick: () => set({ tool: t.id }), children: t.label }, t.id)) }),
|
|
1408
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: import_image_editor9.SELECTION_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: import_image_editor9.SELECTION_MODE_LABELS[m] }, m)) }),
|
|
1409
|
+
options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
1410
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
1411
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
1412
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Tolerance" }),
|
|
1413
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "font-mono", children: options.tolerance })
|
|
1208
1414
|
] }),
|
|
1209
|
-
/* @__PURE__ */ (0,
|
|
1415
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1210
1416
|
"input",
|
|
1211
1417
|
{
|
|
1212
1418
|
type: "range",
|
|
@@ -1220,17 +1426,17 @@ var SelectionOptionsBar = ({
|
|
|
1220
1426
|
}
|
|
1221
1427
|
)
|
|
1222
1428
|
] }),
|
|
1223
|
-
/* @__PURE__ */ (0,
|
|
1224
|
-
/* @__PURE__ */ (0,
|
|
1429
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1430
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
|
|
1225
1431
|
"Contiguous"
|
|
1226
1432
|
] }),
|
|
1227
|
-
/* @__PURE__ */ (0,
|
|
1228
|
-
/* @__PURE__ */ (0,
|
|
1433
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1434
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
|
|
1229
1435
|
"Sample adjusted image"
|
|
1230
1436
|
] }),
|
|
1231
|
-
/* @__PURE__ */ (0,
|
|
1437
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1232
1438
|
"Sample",
|
|
1233
|
-
/* @__PURE__ */ (0,
|
|
1439
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1234
1440
|
"select",
|
|
1235
1441
|
{
|
|
1236
1442
|
"aria-label": "Sample from",
|
|
@@ -1238,27 +1444,27 @@ var SelectionOptionsBar = ({
|
|
|
1238
1444
|
onChange: (e) => set({ sample: e.target.value }),
|
|
1239
1445
|
className: "bg-slate-800 border border-slate-700 rounded px-1 py-0.5",
|
|
1240
1446
|
children: [
|
|
1241
|
-
/* @__PURE__ */ (0,
|
|
1242
|
-
/* @__PURE__ */ (0,
|
|
1447
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "composite", children: "All layers" }),
|
|
1448
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "active-layer", children: "Active layer" })
|
|
1243
1449
|
]
|
|
1244
1450
|
}
|
|
1245
1451
|
)
|
|
1246
1452
|
] })
|
|
1247
1453
|
] }),
|
|
1248
|
-
/* @__PURE__ */ (0,
|
|
1249
|
-
/* @__PURE__ */ (0,
|
|
1454
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1455
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
|
|
1250
1456
|
"Anti-alias"
|
|
1251
1457
|
] }),
|
|
1252
|
-
/* @__PURE__ */ (0,
|
|
1253
|
-
/* @__PURE__ */ (0,
|
|
1254
|
-
/* @__PURE__ */ (0,
|
|
1255
|
-
/* @__PURE__ */ (0,
|
|
1256
|
-
/* @__PURE__ */ (0,
|
|
1458
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
1459
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
|
|
1460
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
|
|
1461
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
|
|
1462
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
|
|
1257
1463
|
] }),
|
|
1258
|
-
/* @__PURE__ */ (0,
|
|
1259
|
-
/* @__PURE__ */ (0,
|
|
1464
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
1465
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
|
|
1260
1466
|
"Radius",
|
|
1261
|
-
/* @__PURE__ */ (0,
|
|
1467
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1262
1468
|
"input",
|
|
1263
1469
|
{
|
|
1264
1470
|
type: "number",
|
|
@@ -1272,24 +1478,24 @@ var SelectionOptionsBar = ({
|
|
|
1272
1478
|
}
|
|
1273
1479
|
)
|
|
1274
1480
|
] }),
|
|
1275
|
-
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0,
|
|
1481
|
+
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
|
|
1276
1482
|
] }),
|
|
1277
|
-
/* @__PURE__ */ (0,
|
|
1483
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor9.describeSelection)(sel) })
|
|
1278
1484
|
] });
|
|
1279
1485
|
};
|
|
1280
1486
|
|
|
1281
1487
|
// src/image-editor/RefineEdgePanel.tsx
|
|
1282
|
-
var
|
|
1283
|
-
var
|
|
1284
|
-
var
|
|
1488
|
+
var import_react9 = require("react");
|
|
1489
|
+
var import_image_editor10 = require("@pixerate/editor/image-editor");
|
|
1490
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1285
1491
|
var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
|
|
1286
|
-
var
|
|
1492
|
+
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";
|
|
1287
1493
|
var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
1288
|
-
const [params, setParams] = (0,
|
|
1289
|
-
const [busy, setBusy] = (0,
|
|
1290
|
-
const [error, setError] = (0,
|
|
1291
|
-
const [layerId, setLayerId] = (0,
|
|
1292
|
-
const [newKind, setNewKind] = (0,
|
|
1494
|
+
const [params, setParams] = (0, import_react9.useState)(DEFAULT_PARAMS);
|
|
1495
|
+
const [busy, setBusy] = (0, import_react9.useState)(false);
|
|
1496
|
+
const [error, setError] = (0, import_react9.useState)(null);
|
|
1497
|
+
const [layerId, setLayerId] = (0, import_react9.useState)("");
|
|
1498
|
+
const [newKind, setNewKind] = (0, import_react9.useState)("hueSaturation");
|
|
1293
1499
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
1294
1500
|
const list = layers ?? controller.getAdjustmentLayers();
|
|
1295
1501
|
const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
|
|
@@ -1304,17 +1510,17 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1304
1510
|
setBusy(false);
|
|
1305
1511
|
}
|
|
1306
1512
|
};
|
|
1307
|
-
return /* @__PURE__ */ (0,
|
|
1308
|
-
/* @__PURE__ */ (0,
|
|
1309
|
-
|
|
1310
|
-
/* @__PURE__ */ (0,
|
|
1311
|
-
/* @__PURE__ */ (0,
|
|
1312
|
-
/* @__PURE__ */ (0,
|
|
1513
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
1514
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
|
|
1515
|
+
import_image_editor10.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
1516
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
1517
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: c.label }),
|
|
1518
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "font-mono", children: [
|
|
1313
1519
|
params[c.id],
|
|
1314
1520
|
c.unit
|
|
1315
1521
|
] })
|
|
1316
1522
|
] }),
|
|
1317
|
-
/* @__PURE__ */ (0,
|
|
1523
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1318
1524
|
"input",
|
|
1319
1525
|
{
|
|
1320
1526
|
type: "range",
|
|
@@ -1328,67 +1534,67 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1328
1534
|
}
|
|
1329
1535
|
)
|
|
1330
1536
|
] }, c.id)),
|
|
1331
|
-
/* @__PURE__ */ (0,
|
|
1332
|
-
/* @__PURE__ */ (0,
|
|
1537
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1538
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
|
|
1333
1539
|
"Smart Radius"
|
|
1334
1540
|
] }),
|
|
1335
|
-
/* @__PURE__ */ (0,
|
|
1336
|
-
/* @__PURE__ */ (0,
|
|
1337
|
-
/* @__PURE__ */ (0,
|
|
1541
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex gap-1", children: [
|
|
1542
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: button2, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
|
|
1543
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: button2, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
|
|
1338
1544
|
] }),
|
|
1339
|
-
error && /* @__PURE__ */ (0,
|
|
1340
|
-
/* @__PURE__ */ (0,
|
|
1341
|
-
/* @__PURE__ */ (0,
|
|
1342
|
-
/* @__PURE__ */ (0,
|
|
1545
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
1546
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
|
|
1547
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex gap-1 items-center", children: [
|
|
1548
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1343
1549
|
"select",
|
|
1344
1550
|
{
|
|
1345
1551
|
"aria-label": "New masked layer kind",
|
|
1346
1552
|
value: newKind,
|
|
1347
1553
|
onChange: (e) => setNewKind(e.target.value),
|
|
1348
1554
|
className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
1349
|
-
children:
|
|
1555
|
+
children: import_image_editor10.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("option", { value: k.kind, children: k.label }, k.kind))
|
|
1350
1556
|
}
|
|
1351
1557
|
),
|
|
1352
|
-
/* @__PURE__ */ (0,
|
|
1558
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1353
1559
|
"button",
|
|
1354
1560
|
{
|
|
1355
1561
|
type: "button",
|
|
1356
|
-
className:
|
|
1562
|
+
className: button2,
|
|
1357
1563
|
disabled: !sel,
|
|
1358
|
-
onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0,
|
|
1564
|
+
onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor10.layerMaskFromSelection)(sel) })),
|
|
1359
1565
|
children: "New Masked Layer"
|
|
1360
1566
|
}
|
|
1361
1567
|
)
|
|
1362
1568
|
] }),
|
|
1363
|
-
list.length > 0 && target && /* @__PURE__ */ (0,
|
|
1364
|
-
/* @__PURE__ */ (0,
|
|
1569
|
+
list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
1570
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1365
1571
|
"select",
|
|
1366
1572
|
{
|
|
1367
1573
|
"aria-label": "Mask layer",
|
|
1368
1574
|
value: target.id,
|
|
1369
1575
|
onChange: (e) => setLayerId(e.target.value),
|
|
1370
1576
|
className: "bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
1371
|
-
children: list.map((l) => /* @__PURE__ */ (0,
|
|
1372
|
-
l.name || (0,
|
|
1577
|
+
children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("option", { value: l.id, children: [
|
|
1578
|
+
l.name || (0, import_image_editor10.adjustmentKindLabel)(l.kind),
|
|
1373
1579
|
l.mask ? " (masked)" : ""
|
|
1374
1580
|
] }, l.id))
|
|
1375
1581
|
}
|
|
1376
1582
|
),
|
|
1377
|
-
/* @__PURE__ */ (0,
|
|
1378
|
-
/* @__PURE__ */ (0,
|
|
1379
|
-
/* @__PURE__ */ (0,
|
|
1380
|
-
/* @__PURE__ */ (0,
|
|
1583
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
|
|
1584
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: button2, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
|
|
1585
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
|
|
1586
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
|
|
1381
1587
|
] }),
|
|
1382
|
-
target.mask && /* @__PURE__ */ (0,
|
|
1383
|
-
/* @__PURE__ */ (0,
|
|
1384
|
-
/* @__PURE__ */ (0,
|
|
1385
|
-
/* @__PURE__ */ (0,
|
|
1386
|
-
/* @__PURE__ */ (0,
|
|
1588
|
+
target.mask && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1589
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
1590
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
1591
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "Density" }),
|
|
1592
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "font-mono", children: [
|
|
1387
1593
|
Math.round((target.mask.density ?? 1) * 100),
|
|
1388
1594
|
"%"
|
|
1389
1595
|
] })
|
|
1390
1596
|
] }),
|
|
1391
|
-
/* @__PURE__ */ (0,
|
|
1597
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1392
1598
|
"input",
|
|
1393
1599
|
{
|
|
1394
1600
|
type: "range",
|
|
@@ -1402,15 +1608,15 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1402
1608
|
}
|
|
1403
1609
|
)
|
|
1404
1610
|
] }),
|
|
1405
|
-
/* @__PURE__ */ (0,
|
|
1406
|
-
/* @__PURE__ */ (0,
|
|
1407
|
-
/* @__PURE__ */ (0,
|
|
1408
|
-
/* @__PURE__ */ (0,
|
|
1611
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("label", { className: "flex flex-col gap-1", children: [
|
|
1612
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
|
|
1613
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { children: "Mask Feather" }),
|
|
1614
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: "font-mono", children: [
|
|
1409
1615
|
target.mask.feather ?? 0,
|
|
1410
1616
|
"px"
|
|
1411
1617
|
] })
|
|
1412
1618
|
] }),
|
|
1413
|
-
/* @__PURE__ */ (0,
|
|
1619
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1414
1620
|
"input",
|
|
1415
1621
|
{
|
|
1416
1622
|
type: "range",
|
|
@@ -1430,7 +1636,7 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1430
1636
|
};
|
|
1431
1637
|
|
|
1432
1638
|
// src/image-editor/ImageEditor.tsx
|
|
1433
|
-
var
|
|
1639
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1434
1640
|
var ImageEditor = ({
|
|
1435
1641
|
editor: externalEditor,
|
|
1436
1642
|
src,
|
|
@@ -1445,35 +1651,35 @@ var ImageEditor = ({
|
|
|
1445
1651
|
const internalEditor = useImageEditor({ image: src });
|
|
1446
1652
|
const editor = externalEditor || internalEditor;
|
|
1447
1653
|
const { state, controller } = editor;
|
|
1448
|
-
const legacyProcess = (0,
|
|
1449
|
-
const canvasRef = (0,
|
|
1450
|
-
const containerRef = (0,
|
|
1451
|
-
const [activeTab, setActiveTab] = (0,
|
|
1452
|
-
const [activeCropRatio, setActiveCropRatio] = (0,
|
|
1453
|
-
const [selectionOptions, setSelectionOptions] = (0,
|
|
1454
|
-
const selectionOptionsRef = (0,
|
|
1654
|
+
const legacyProcess = (0, import_image_editor11.normalizeProcessVersion)(state.adjustments.process) < import_image_editor11.LATEST_PROCESS_VERSION;
|
|
1655
|
+
const canvasRef = (0, import_react10.useRef)(null);
|
|
1656
|
+
const containerRef = (0, import_react10.useRef)(null);
|
|
1657
|
+
const [activeTab, setActiveTab] = (0, import_react10.useState)("crop");
|
|
1658
|
+
const [activeCropRatio, setActiveCropRatio] = (0, import_react10.useState)(null);
|
|
1659
|
+
const [selectionOptions, setSelectionOptions] = (0, import_react10.useState)(import_image_editor11.DEFAULT_SELECTION_TOOL_OPTIONS);
|
|
1660
|
+
const selectionOptionsRef = (0, import_react10.useRef)(selectionOptions);
|
|
1455
1661
|
selectionOptionsRef.current = selectionOptions;
|
|
1456
|
-
const selectionGestureRef = (0,
|
|
1662
|
+
const selectionGestureRef = (0, import_react10.useRef)(null);
|
|
1457
1663
|
if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
|
|
1458
|
-
selectionGestureRef.current = new
|
|
1664
|
+
selectionGestureRef.current = new import_image_editor11.SelectionGesture(controller, () => selectionOptionsRef.current);
|
|
1459
1665
|
}
|
|
1460
|
-
const selectionDraftRef = (0,
|
|
1461
|
-
const [selectionError, setSelectionError] = (0,
|
|
1462
|
-
const paintGestureRef = (0,
|
|
1463
|
-
const paintControllerRef = (0,
|
|
1666
|
+
const selectionDraftRef = (0, import_react10.useRef)(null);
|
|
1667
|
+
const [selectionError, setSelectionError] = (0, import_react10.useState)(null);
|
|
1668
|
+
const paintGestureRef = (0, import_react10.useRef)(null);
|
|
1669
|
+
const paintControllerRef = (0, import_react10.useRef)(controller);
|
|
1464
1670
|
if (!paintGestureRef.current || paintControllerRef.current !== controller) {
|
|
1465
|
-
paintGestureRef.current = new
|
|
1671
|
+
paintGestureRef.current = new import_image_editor11.PaintGesture(controller);
|
|
1466
1672
|
paintControllerRef.current = controller;
|
|
1467
1673
|
}
|
|
1468
|
-
const brushCursorRef = (0,
|
|
1469
|
-
const [paintError, setPaintError] = (0,
|
|
1470
|
-
const [inpaintPrompt, setInpaintPrompt] = (0,
|
|
1471
|
-
const [inpaintMaskMode, setInpaintMaskMode] = (0,
|
|
1472
|
-
const [isRemovingBg, setIsRemovingBg] = (0,
|
|
1473
|
-
const [isInpainting, setIsInpainting] = (0,
|
|
1474
|
-
const [aiError, setAiError] = (0,
|
|
1475
|
-
const [aiSuccess, setAiSuccess] = (0,
|
|
1476
|
-
const [aiTarget, setAiTarget] = (0,
|
|
1674
|
+
const brushCursorRef = (0, import_react10.useRef)(null);
|
|
1675
|
+
const [paintError, setPaintError] = (0, import_react10.useState)(null);
|
|
1676
|
+
const [inpaintPrompt, setInpaintPrompt] = (0, import_react10.useState)("");
|
|
1677
|
+
const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react10.useState)("annotations");
|
|
1678
|
+
const [isRemovingBg, setIsRemovingBg] = (0, import_react10.useState)(false);
|
|
1679
|
+
const [isInpainting, setIsInpainting] = (0, import_react10.useState)(false);
|
|
1680
|
+
const [aiError, setAiError] = (0, import_react10.useState)(null);
|
|
1681
|
+
const [aiSuccess, setAiSuccess] = (0, import_react10.useState)(null);
|
|
1682
|
+
const [aiTarget, setAiTarget] = (0, import_react10.useState)("auto");
|
|
1477
1683
|
const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
|
|
1478
1684
|
const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
|
|
1479
1685
|
const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
|
|
@@ -1536,18 +1742,18 @@ var ImageEditor = ({
|
|
|
1536
1742
|
setIsInpainting(false);
|
|
1537
1743
|
}
|
|
1538
1744
|
};
|
|
1539
|
-
const [activeColor, setActiveColor] = (0,
|
|
1540
|
-
const [strokeWidth, setStrokeWidth] = (0,
|
|
1541
|
-
const [fontSize, setFontSize] = (0,
|
|
1542
|
-
const [textInput, setTextInput] = (0,
|
|
1543
|
-
const draftAnnotationRef = (0,
|
|
1544
|
-
const draftCropRef = (0,
|
|
1545
|
-
const cropDragInfoRef = (0,
|
|
1546
|
-
const annotationDragInfoRef = (0,
|
|
1547
|
-
const isDrawingRef = (0,
|
|
1548
|
-
const currentPathRef = (0,
|
|
1549
|
-
const dragStartPointRef = (0,
|
|
1550
|
-
const renderCanvas = (0,
|
|
1745
|
+
const [activeColor, setActiveColor] = (0, import_react10.useState)("#ef4444");
|
|
1746
|
+
const [strokeWidth, setStrokeWidth] = (0, import_react10.useState)(3);
|
|
1747
|
+
const [fontSize, setFontSize] = (0, import_react10.useState)(24);
|
|
1748
|
+
const [textInput, setTextInput] = (0, import_react10.useState)("");
|
|
1749
|
+
const draftAnnotationRef = (0, import_react10.useRef)(null);
|
|
1750
|
+
const draftCropRef = (0, import_react10.useRef)(null);
|
|
1751
|
+
const cropDragInfoRef = (0, import_react10.useRef)(null);
|
|
1752
|
+
const annotationDragInfoRef = (0, import_react10.useRef)(null);
|
|
1753
|
+
const isDrawingRef = (0, import_react10.useRef)(false);
|
|
1754
|
+
const currentPathRef = (0, import_react10.useRef)([]);
|
|
1755
|
+
const dragStartPointRef = (0, import_react10.useRef)(null);
|
|
1756
|
+
const renderCanvas = (0, import_react10.useCallback)(
|
|
1551
1757
|
async (draftAnnotation, draftCrop) => {
|
|
1552
1758
|
const canvas = canvasRef.current;
|
|
1553
1759
|
const container = containerRef.current;
|
|
@@ -1568,7 +1774,7 @@ var ImageEditor = ({
|
|
|
1568
1774
|
},
|
|
1569
1775
|
[controller, activeTab]
|
|
1570
1776
|
);
|
|
1571
|
-
(0,
|
|
1777
|
+
(0, import_react10.useEffect)(() => {
|
|
1572
1778
|
const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
|
|
1573
1779
|
const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
|
|
1574
1780
|
const animId = raf(() => {
|
|
@@ -1576,12 +1782,12 @@ var ImageEditor = ({
|
|
|
1576
1782
|
});
|
|
1577
1783
|
return () => caf(animId);
|
|
1578
1784
|
}, [renderCanvas, state]);
|
|
1579
|
-
(0,
|
|
1785
|
+
(0, import_react10.useEffect)(() => {
|
|
1580
1786
|
if (activeTab === "crop" && editor.state.activeTool !== "crop") {
|
|
1581
1787
|
editor.setTool("crop");
|
|
1582
1788
|
}
|
|
1583
1789
|
}, [activeTab, editor]);
|
|
1584
|
-
(0,
|
|
1790
|
+
(0, import_react10.useEffect)(() => {
|
|
1585
1791
|
const container = containerRef.current;
|
|
1586
1792
|
if (!container) return;
|
|
1587
1793
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -1617,8 +1823,8 @@ var ImageEditor = ({
|
|
|
1617
1823
|
const sy = rect.height > 0 ? canvas.height / rect.height : 1;
|
|
1618
1824
|
const s = controller.getState();
|
|
1619
1825
|
return list.map((ev) => ({
|
|
1620
|
-
...(0,
|
|
1621
|
-
pressure: (0,
|
|
1826
|
+
...(0, import_image_editor11.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
|
|
1827
|
+
pressure: (0, import_image_editor11.pointerPressure)(ev)
|
|
1622
1828
|
}));
|
|
1623
1829
|
};
|
|
1624
1830
|
const handlePaintPointerDown = (e) => {
|
|
@@ -1646,10 +1852,10 @@ var ImageEditor = ({
|
|
|
1646
1852
|
if (g.error) setPaintError(g.error);
|
|
1647
1853
|
}
|
|
1648
1854
|
};
|
|
1649
|
-
(0,
|
|
1855
|
+
(0, import_react10.useEffect)(() => {
|
|
1650
1856
|
if (activeTab !== "paint" || typeof window === "undefined") return;
|
|
1651
1857
|
const onKey = (e) => {
|
|
1652
|
-
if ((0,
|
|
1858
|
+
if ((0, import_image_editor11.handlePaintShortcut)(controller, e)) e.preventDefault();
|
|
1653
1859
|
};
|
|
1654
1860
|
window.addEventListener("keydown", onKey);
|
|
1655
1861
|
return () => window.removeEventListener("keydown", onKey);
|
|
@@ -1660,7 +1866,7 @@ var ImageEditor = ({
|
|
|
1660
1866
|
const canvasPt = getCanvasEventPoint(e);
|
|
1661
1867
|
if (activeTab === "select") {
|
|
1662
1868
|
const gesture = selectionGestureRef.current;
|
|
1663
|
-
const imgPt = (0,
|
|
1869
|
+
const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
1664
1870
|
void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
|
|
1665
1871
|
return;
|
|
1666
1872
|
}
|
|
@@ -1671,8 +1877,8 @@ var ImageEditor = ({
|
|
|
1671
1877
|
width: state.imageDimensions.width,
|
|
1672
1878
|
height: state.imageDimensions.height
|
|
1673
1879
|
};
|
|
1674
|
-
const handle = (0,
|
|
1675
|
-
const startImgPt = (0,
|
|
1880
|
+
const handle = (0, import_image_editor11.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
1881
|
+
const startImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
1676
1882
|
if (handle) {
|
|
1677
1883
|
cropDragInfoRef.current = {
|
|
1678
1884
|
handle,
|
|
@@ -1691,12 +1897,12 @@ var ImageEditor = ({
|
|
|
1691
1897
|
return;
|
|
1692
1898
|
}
|
|
1693
1899
|
if (activeTab === "annotate") {
|
|
1694
|
-
const imgPt = (0,
|
|
1900
|
+
const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
1695
1901
|
dragStartPointRef.current = imgPt;
|
|
1696
1902
|
if (state.activeTool === "select") {
|
|
1697
1903
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
1698
1904
|
const ann = state.annotations[i];
|
|
1699
|
-
if ((0,
|
|
1905
|
+
if ((0, import_image_editor11.hitTestAnnotation)(imgPt, ann)) {
|
|
1700
1906
|
editor.selectAnnotation(ann.id);
|
|
1701
1907
|
annotationDragInfoRef.current = {
|
|
1702
1908
|
annId: ann.id,
|
|
@@ -1732,7 +1938,7 @@ var ImageEditor = ({
|
|
|
1732
1938
|
const canvasPt = getCanvasEventPoint(e);
|
|
1733
1939
|
if (activeTab === "select") {
|
|
1734
1940
|
const gesture = selectionGestureRef.current;
|
|
1735
|
-
if (gesture.active && gesture.move((0,
|
|
1941
|
+
if (gesture.active && gesture.move((0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
|
|
1736
1942
|
selectionDraftRef.current = gesture.draftPath;
|
|
1737
1943
|
renderCanvas();
|
|
1738
1944
|
}
|
|
@@ -1741,7 +1947,7 @@ var ImageEditor = ({
|
|
|
1741
1947
|
if (activeTab === "crop") {
|
|
1742
1948
|
const drag = cropDragInfoRef.current;
|
|
1743
1949
|
if (drag) {
|
|
1744
|
-
const currentImgPt = (0,
|
|
1950
|
+
const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
|
|
1745
1951
|
let newCrop;
|
|
1746
1952
|
if (drag.handle === "new") {
|
|
1747
1953
|
const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
|
|
@@ -1755,7 +1961,7 @@ var ImageEditor = ({
|
|
|
1755
1961
|
height: Math.round(Math.max(20, maxY - minY))
|
|
1756
1962
|
};
|
|
1757
1963
|
} else {
|
|
1758
|
-
newCrop = (0,
|
|
1964
|
+
newCrop = (0, import_image_editor11.calculateCropDrag)(
|
|
1759
1965
|
drag.startCrop,
|
|
1760
1966
|
drag.handle,
|
|
1761
1967
|
drag.startImgPt,
|
|
@@ -1775,15 +1981,15 @@ var ImageEditor = ({
|
|
|
1775
1981
|
width: state.imageDimensions.width,
|
|
1776
1982
|
height: state.imageDimensions.height
|
|
1777
1983
|
};
|
|
1778
|
-
const handle = (0,
|
|
1779
|
-
canvas.style.cursor = (0,
|
|
1984
|
+
const handle = (0, import_image_editor11.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
|
|
1985
|
+
canvas.style.cursor = (0, import_image_editor11.getCropCursor)(handle, state.transform);
|
|
1780
1986
|
}
|
|
1781
1987
|
return;
|
|
1782
1988
|
}
|
|
1783
1989
|
if (activeTab === "annotate") {
|
|
1784
1990
|
if (annotationDragInfoRef.current) {
|
|
1785
1991
|
const drag = annotationDragInfoRef.current;
|
|
1786
|
-
const currentImgPt2 = (0,
|
|
1992
|
+
const currentImgPt2 = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
1787
1993
|
const dx = currentImgPt2.x - drag.startImgPt.x;
|
|
1788
1994
|
const dy = currentImgPt2.y - drag.startImgPt.y;
|
|
1789
1995
|
editor.updateAnnotation(drag.annId, {
|
|
@@ -1795,10 +2001,10 @@ var ImageEditor = ({
|
|
|
1795
2001
|
const startPt = dragStartPointRef.current;
|
|
1796
2002
|
if (!startPt) {
|
|
1797
2003
|
if (state.activeTool === "select") {
|
|
1798
|
-
const imgPt = (0,
|
|
2004
|
+
const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
1799
2005
|
let hovered = false;
|
|
1800
2006
|
for (let i = state.annotations.length - 1; i >= 0; i--) {
|
|
1801
|
-
if ((0,
|
|
2007
|
+
if ((0, import_image_editor11.hitTestAnnotation)(imgPt, state.annotations[i])) {
|
|
1802
2008
|
hovered = true;
|
|
1803
2009
|
break;
|
|
1804
2010
|
}
|
|
@@ -1809,7 +2015,7 @@ var ImageEditor = ({
|
|
|
1809
2015
|
}
|
|
1810
2016
|
return;
|
|
1811
2017
|
}
|
|
1812
|
-
const currentImgPt = (0,
|
|
2018
|
+
const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
1813
2019
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
1814
2020
|
currentPathRef.current.push(currentImgPt);
|
|
1815
2021
|
const draft = {
|
|
@@ -1889,7 +2095,7 @@ var ImageEditor = ({
|
|
|
1889
2095
|
if (activeTab === "select") {
|
|
1890
2096
|
const gesture = selectionGestureRef.current;
|
|
1891
2097
|
if (gesture.active) {
|
|
1892
|
-
gesture.end((0,
|
|
2098
|
+
gesture.end((0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
|
|
1893
2099
|
selectionDraftRef.current = null;
|
|
1894
2100
|
renderCanvas();
|
|
1895
2101
|
}
|
|
@@ -1913,7 +2119,7 @@ var ImageEditor = ({
|
|
|
1913
2119
|
}
|
|
1914
2120
|
const startPt = dragStartPointRef.current;
|
|
1915
2121
|
if (startPt) {
|
|
1916
|
-
const currentImgPt = (0,
|
|
2122
|
+
const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
|
|
1917
2123
|
if (state.activeTool === "pen" && isDrawingRef.current) {
|
|
1918
2124
|
if (currentPathRef.current.length > 1) {
|
|
1919
2125
|
editor.addAnnotation({
|
|
@@ -2009,15 +2215,15 @@ var ImageEditor = ({
|
|
|
2009
2215
|
link.click();
|
|
2010
2216
|
}
|
|
2011
2217
|
};
|
|
2012
|
-
return /* @__PURE__ */ (0,
|
|
2218
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2013
2219
|
"div",
|
|
2014
2220
|
{
|
|
2015
2221
|
className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
|
|
2016
2222
|
style,
|
|
2017
2223
|
children: [
|
|
2018
|
-
/* @__PURE__ */ (0,
|
|
2019
|
-
/* @__PURE__ */ (0,
|
|
2020
|
-
/* @__PURE__ */ (0,
|
|
2224
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-wrap items-center justify-between px-4 py-3 bg-slate-950/80 border-b border-slate-800 gap-3", children: [
|
|
2225
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
|
|
2226
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2021
2227
|
"button",
|
|
2022
2228
|
{
|
|
2023
2229
|
type: "button",
|
|
@@ -2029,7 +2235,7 @@ var ImageEditor = ({
|
|
|
2029
2235
|
children: "Transform & Crop"
|
|
2030
2236
|
}
|
|
2031
2237
|
),
|
|
2032
|
-
/* @__PURE__ */ (0,
|
|
2238
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2033
2239
|
"button",
|
|
2034
2240
|
{
|
|
2035
2241
|
type: "button",
|
|
@@ -2041,7 +2247,7 @@ var ImageEditor = ({
|
|
|
2041
2247
|
children: "Adjustments"
|
|
2042
2248
|
}
|
|
2043
2249
|
),
|
|
2044
|
-
/* @__PURE__ */ (0,
|
|
2250
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2045
2251
|
"button",
|
|
2046
2252
|
{
|
|
2047
2253
|
type: "button",
|
|
@@ -2053,7 +2259,7 @@ var ImageEditor = ({
|
|
|
2053
2259
|
children: "Layers"
|
|
2054
2260
|
}
|
|
2055
2261
|
),
|
|
2056
|
-
/* @__PURE__ */ (0,
|
|
2262
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2057
2263
|
"button",
|
|
2058
2264
|
{
|
|
2059
2265
|
type: "button",
|
|
@@ -2065,7 +2271,7 @@ var ImageEditor = ({
|
|
|
2065
2271
|
children: "Paint"
|
|
2066
2272
|
}
|
|
2067
2273
|
),
|
|
2068
|
-
/* @__PURE__ */ (0,
|
|
2274
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2069
2275
|
"button",
|
|
2070
2276
|
{
|
|
2071
2277
|
type: "button",
|
|
@@ -2077,7 +2283,7 @@ var ImageEditor = ({
|
|
|
2077
2283
|
children: "Select & Mask"
|
|
2078
2284
|
}
|
|
2079
2285
|
),
|
|
2080
|
-
/* @__PURE__ */ (0,
|
|
2286
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2081
2287
|
"button",
|
|
2082
2288
|
{
|
|
2083
2289
|
type: "button",
|
|
@@ -2089,7 +2295,7 @@ var ImageEditor = ({
|
|
|
2089
2295
|
children: "Annotations"
|
|
2090
2296
|
}
|
|
2091
2297
|
),
|
|
2092
|
-
/* @__PURE__ */ (0,
|
|
2298
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2093
2299
|
"button",
|
|
2094
2300
|
{
|
|
2095
2301
|
type: "button",
|
|
@@ -2101,7 +2307,7 @@ var ImageEditor = ({
|
|
|
2101
2307
|
children: "Depth Mask"
|
|
2102
2308
|
}
|
|
2103
2309
|
),
|
|
2104
|
-
/* @__PURE__ */ (0,
|
|
2310
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2105
2311
|
"button",
|
|
2106
2312
|
{
|
|
2107
2313
|
type: "button",
|
|
@@ -2111,14 +2317,14 @@ var ImageEditor = ({
|
|
|
2111
2317
|
},
|
|
2112
2318
|
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"}`,
|
|
2113
2319
|
children: [
|
|
2114
|
-
/* @__PURE__ */ (0,
|
|
2320
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
|
|
2115
2321
|
"AI Tools"
|
|
2116
2322
|
]
|
|
2117
2323
|
}
|
|
2118
2324
|
)
|
|
2119
2325
|
] }),
|
|
2120
|
-
/* @__PURE__ */ (0,
|
|
2121
|
-
/* @__PURE__ */ (0,
|
|
2326
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2327
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2122
2328
|
"button",
|
|
2123
2329
|
{
|
|
2124
2330
|
type: "button",
|
|
@@ -2129,7 +2335,7 @@ var ImageEditor = ({
|
|
|
2129
2335
|
children: "\u21A9"
|
|
2130
2336
|
}
|
|
2131
2337
|
),
|
|
2132
|
-
/* @__PURE__ */ (0,
|
|
2338
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2133
2339
|
"button",
|
|
2134
2340
|
{
|
|
2135
2341
|
type: "button",
|
|
@@ -2140,7 +2346,7 @@ var ImageEditor = ({
|
|
|
2140
2346
|
children: "\u21AA"
|
|
2141
2347
|
}
|
|
2142
2348
|
),
|
|
2143
|
-
/* @__PURE__ */ (0,
|
|
2349
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2144
2350
|
"button",
|
|
2145
2351
|
{
|
|
2146
2352
|
type: "button",
|
|
@@ -2149,8 +2355,8 @@ var ImageEditor = ({
|
|
|
2149
2355
|
children: "Reset"
|
|
2150
2356
|
}
|
|
2151
2357
|
),
|
|
2152
|
-
/* @__PURE__ */ (0,
|
|
2153
|
-
/* @__PURE__ */ (0,
|
|
2358
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
2359
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2154
2360
|
"button",
|
|
2155
2361
|
{
|
|
2156
2362
|
type: "button",
|
|
@@ -2160,11 +2366,11 @@ var ImageEditor = ({
|
|
|
2160
2366
|
children: "-"
|
|
2161
2367
|
}
|
|
2162
2368
|
),
|
|
2163
|
-
/* @__PURE__ */ (0,
|
|
2369
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
|
|
2164
2370
|
Math.round(state.zoom * 100),
|
|
2165
2371
|
"%"
|
|
2166
2372
|
] }),
|
|
2167
|
-
/* @__PURE__ */ (0,
|
|
2373
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2168
2374
|
"button",
|
|
2169
2375
|
{
|
|
2170
2376
|
type: "button",
|
|
@@ -2174,8 +2380,8 @@ var ImageEditor = ({
|
|
|
2174
2380
|
children: "+"
|
|
2175
2381
|
}
|
|
2176
2382
|
),
|
|
2177
|
-
/* @__PURE__ */ (0,
|
|
2178
|
-
/* @__PURE__ */ (0,
|
|
2383
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
2384
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2179
2385
|
"button",
|
|
2180
2386
|
{
|
|
2181
2387
|
type: "button",
|
|
@@ -2186,7 +2392,7 @@ var ImageEditor = ({
|
|
|
2186
2392
|
children: "Hold Compare"
|
|
2187
2393
|
}
|
|
2188
2394
|
),
|
|
2189
|
-
/* @__PURE__ */ (0,
|
|
2395
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2190
2396
|
"button",
|
|
2191
2397
|
{
|
|
2192
2398
|
type: "button",
|
|
@@ -2197,13 +2403,13 @@ var ImageEditor = ({
|
|
|
2197
2403
|
)
|
|
2198
2404
|
] })
|
|
2199
2405
|
] }),
|
|
2200
|
-
/* @__PURE__ */ (0,
|
|
2201
|
-
/* @__PURE__ */ (0,
|
|
2406
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
|
|
2407
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2202
2408
|
"div",
|
|
2203
2409
|
{
|
|
2204
2410
|
ref: containerRef,
|
|
2205
2411
|
className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
|
|
2206
|
-
children: /* @__PURE__ */ (0,
|
|
2412
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2207
2413
|
"canvas",
|
|
2208
2414
|
{
|
|
2209
2415
|
ref: canvasRef,
|
|
@@ -2221,11 +2427,11 @@ var ImageEditor = ({
|
|
|
2221
2427
|
)
|
|
2222
2428
|
}
|
|
2223
2429
|
),
|
|
2224
|
-
/* @__PURE__ */ (0,
|
|
2225
|
-
activeTab === "crop" && /* @__PURE__ */ (0,
|
|
2226
|
-
/* @__PURE__ */ (0,
|
|
2227
|
-
/* @__PURE__ */ (0,
|
|
2228
|
-
/* @__PURE__ */ (0,
|
|
2430
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "w-full md:w-80 bg-slate-900/90 border-t md:border-t-0 md:border-l border-slate-800 p-4 overflow-y-auto h-auto md:h-full md:max-h-[560px]", children: [
|
|
2431
|
+
activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
2432
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
|
|
2433
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
2434
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2229
2435
|
"button",
|
|
2230
2436
|
{
|
|
2231
2437
|
type: "button",
|
|
@@ -2237,7 +2443,7 @@ var ImageEditor = ({
|
|
|
2237
2443
|
children: "Freeform"
|
|
2238
2444
|
}
|
|
2239
2445
|
),
|
|
2240
|
-
/* @__PURE__ */ (0,
|
|
2446
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2241
2447
|
"button",
|
|
2242
2448
|
{
|
|
2243
2449
|
type: "button",
|
|
@@ -2249,7 +2455,7 @@ var ImageEditor = ({
|
|
|
2249
2455
|
children: "1:1 Square"
|
|
2250
2456
|
}
|
|
2251
2457
|
),
|
|
2252
|
-
/* @__PURE__ */ (0,
|
|
2458
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2253
2459
|
"button",
|
|
2254
2460
|
{
|
|
2255
2461
|
type: "button",
|
|
@@ -2261,7 +2467,7 @@ var ImageEditor = ({
|
|
|
2261
2467
|
children: "4:3 Standard"
|
|
2262
2468
|
}
|
|
2263
2469
|
),
|
|
2264
|
-
/* @__PURE__ */ (0,
|
|
2470
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2265
2471
|
"button",
|
|
2266
2472
|
{
|
|
2267
2473
|
type: "button",
|
|
@@ -2273,7 +2479,7 @@ var ImageEditor = ({
|
|
|
2273
2479
|
children: "16:9 Wide"
|
|
2274
2480
|
}
|
|
2275
2481
|
),
|
|
2276
|
-
/* @__PURE__ */ (0,
|
|
2482
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2277
2483
|
"button",
|
|
2278
2484
|
{
|
|
2279
2485
|
type: "button",
|
|
@@ -2285,7 +2491,7 @@ var ImageEditor = ({
|
|
|
2285
2491
|
children: "3:2 Photo"
|
|
2286
2492
|
}
|
|
2287
2493
|
),
|
|
2288
|
-
/* @__PURE__ */ (0,
|
|
2494
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2289
2495
|
"button",
|
|
2290
2496
|
{
|
|
2291
2497
|
type: "button",
|
|
@@ -2298,10 +2504,10 @@ var ImageEditor = ({
|
|
|
2298
2504
|
}
|
|
2299
2505
|
)
|
|
2300
2506
|
] }),
|
|
2301
|
-
/* @__PURE__ */ (0,
|
|
2302
|
-
/* @__PURE__ */ (0,
|
|
2303
|
-
/* @__PURE__ */ (0,
|
|
2304
|
-
/* @__PURE__ */ (0,
|
|
2507
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
2508
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
|
|
2509
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
2510
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2305
2511
|
"button",
|
|
2306
2512
|
{
|
|
2307
2513
|
type: "button",
|
|
@@ -2310,7 +2516,7 @@ var ImageEditor = ({
|
|
|
2310
2516
|
children: "Rotate -90\xB0"
|
|
2311
2517
|
}
|
|
2312
2518
|
),
|
|
2313
|
-
/* @__PURE__ */ (0,
|
|
2519
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2314
2520
|
"button",
|
|
2315
2521
|
{
|
|
2316
2522
|
type: "button",
|
|
@@ -2319,7 +2525,7 @@ var ImageEditor = ({
|
|
|
2319
2525
|
children: "Rotate +90\xB0"
|
|
2320
2526
|
}
|
|
2321
2527
|
),
|
|
2322
|
-
/* @__PURE__ */ (0,
|
|
2528
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2323
2529
|
"button",
|
|
2324
2530
|
{
|
|
2325
2531
|
type: "button",
|
|
@@ -2328,7 +2534,7 @@ var ImageEditor = ({
|
|
|
2328
2534
|
children: "Flip Horizontal"
|
|
2329
2535
|
}
|
|
2330
2536
|
),
|
|
2331
|
-
/* @__PURE__ */ (0,
|
|
2537
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2332
2538
|
"button",
|
|
2333
2539
|
{
|
|
2334
2540
|
type: "button",
|
|
@@ -2339,10 +2545,10 @@ var ImageEditor = ({
|
|
|
2339
2545
|
)
|
|
2340
2546
|
] })
|
|
2341
2547
|
] }),
|
|
2342
|
-
activeTab === "adjust" && /* @__PURE__ */ (0,
|
|
2343
|
-
/* @__PURE__ */ (0,
|
|
2344
|
-
/* @__PURE__ */ (0,
|
|
2345
|
-
/* @__PURE__ */ (0,
|
|
2548
|
+
activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2549
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2550
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
|
|
2551
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2346
2552
|
"button",
|
|
2347
2553
|
{
|
|
2348
2554
|
type: "button",
|
|
@@ -2352,25 +2558,25 @@ var ImageEditor = ({
|
|
|
2352
2558
|
}
|
|
2353
2559
|
)
|
|
2354
2560
|
] }),
|
|
2355
|
-
/* @__PURE__ */ (0,
|
|
2356
|
-
|
|
2357
|
-
/* @__PURE__ */ (0,
|
|
2561
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Histogram, { histogram: editor.histogram }),
|
|
2562
|
+
import_image_editor11.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_react10.default.Fragment, { children: [
|
|
2563
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2358
2564
|
ControlSlider,
|
|
2359
2565
|
{
|
|
2360
2566
|
spec,
|
|
2361
|
-
value: (0,
|
|
2567
|
+
value: (0, import_image_editor11.readAdjustmentControls)(state.adjustments)[spec.id],
|
|
2362
2568
|
disabled: spec.requiresProcess !== void 0 && legacyProcess,
|
|
2363
2569
|
onChange: (v) => editor.setAdjustments({ [spec.id]: v })
|
|
2364
2570
|
}
|
|
2365
2571
|
),
|
|
2366
|
-
spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0,
|
|
2572
|
+
spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2367
2573
|
"div",
|
|
2368
2574
|
{
|
|
2369
2575
|
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",
|
|
2370
2576
|
"data-testid": "image-editor-process-notice",
|
|
2371
2577
|
children: [
|
|
2372
|
-
/* @__PURE__ */ (0,
|
|
2373
|
-
/* @__PURE__ */ (0,
|
|
2578
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
|
|
2579
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2374
2580
|
"button",
|
|
2375
2581
|
{
|
|
2376
2582
|
type: "button",
|
|
@@ -2383,7 +2589,7 @@ var ImageEditor = ({
|
|
|
2383
2589
|
}
|
|
2384
2590
|
)
|
|
2385
2591
|
] }, spec.id)),
|
|
2386
|
-
/* @__PURE__ */ (0,
|
|
2592
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2387
2593
|
AdjustmentLayersPanel,
|
|
2388
2594
|
{
|
|
2389
2595
|
controller,
|
|
@@ -2392,19 +2598,19 @@ var ImageEditor = ({
|
|
|
2392
2598
|
}
|
|
2393
2599
|
) })
|
|
2394
2600
|
] }),
|
|
2395
|
-
activeTab === "layers" && /* @__PURE__ */ (0,
|
|
2396
|
-
/* @__PURE__ */ (0,
|
|
2397
|
-
/* @__PURE__ */ (0,
|
|
2601
|
+
activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2602
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
|
|
2603
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(LayersPanel, { controller })
|
|
2398
2604
|
] }),
|
|
2399
|
-
activeTab === "paint" && /* @__PURE__ */ (0,
|
|
2400
|
-
/* @__PURE__ */ (0,
|
|
2401
|
-
/* @__PURE__ */ (0,
|
|
2402
|
-
paintError && /* @__PURE__ */ (0,
|
|
2403
|
-
/* @__PURE__ */ (0,
|
|
2605
|
+
activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2606
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
|
|
2607
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(BrushOptionsBar, { controller }),
|
|
2608
|
+
paintError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
|
|
2609
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(LayersPanel, { controller }) })
|
|
2404
2610
|
] }),
|
|
2405
|
-
activeTab === "annotate" && /* @__PURE__ */ (0,
|
|
2406
|
-
/* @__PURE__ */ (0,
|
|
2407
|
-
/* @__PURE__ */ (0,
|
|
2611
|
+
activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2612
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
|
|
2613
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2408
2614
|
"button",
|
|
2409
2615
|
{
|
|
2410
2616
|
type: "button",
|
|
@@ -2414,9 +2620,9 @@ var ImageEditor = ({
|
|
|
2414
2620
|
},
|
|
2415
2621
|
t
|
|
2416
2622
|
)) }),
|
|
2417
|
-
/* @__PURE__ */ (0,
|
|
2418
|
-
/* @__PURE__ */ (0,
|
|
2419
|
-
/* @__PURE__ */ (0,
|
|
2623
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
2624
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "text-slate-400", children: "Color:" }),
|
|
2625
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2420
2626
|
"input",
|
|
2421
2627
|
{
|
|
2422
2628
|
type: "color",
|
|
@@ -2425,15 +2631,15 @@ var ImageEditor = ({
|
|
|
2425
2631
|
className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
|
|
2426
2632
|
}
|
|
2427
2633
|
),
|
|
2428
|
-
/* @__PURE__ */ (0,
|
|
2429
|
-
/* @__PURE__ */ (0,
|
|
2430
|
-
/* @__PURE__ */ (0,
|
|
2431
|
-
/* @__PURE__ */ (0,
|
|
2634
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex-1 ml-2", children: [
|
|
2635
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
|
|
2636
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Width:" }),
|
|
2637
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-mono", children: [
|
|
2432
2638
|
strokeWidth,
|
|
2433
2639
|
"px"
|
|
2434
2640
|
] })
|
|
2435
2641
|
] }),
|
|
2436
|
-
/* @__PURE__ */ (0,
|
|
2642
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2437
2643
|
"input",
|
|
2438
2644
|
{
|
|
2439
2645
|
type: "range",
|
|
@@ -2446,10 +2652,10 @@ var ImageEditor = ({
|
|
|
2446
2652
|
)
|
|
2447
2653
|
] })
|
|
2448
2654
|
] }),
|
|
2449
|
-
/* @__PURE__ */ (0,
|
|
2450
|
-
/* @__PURE__ */ (0,
|
|
2451
|
-
/* @__PURE__ */ (0,
|
|
2452
|
-
/* @__PURE__ */ (0,
|
|
2655
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
2656
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
|
|
2657
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex gap-2", children: [
|
|
2658
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2453
2659
|
"input",
|
|
2454
2660
|
{
|
|
2455
2661
|
type: "text",
|
|
@@ -2460,7 +2666,7 @@ var ImageEditor = ({
|
|
|
2460
2666
|
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"
|
|
2461
2667
|
}
|
|
2462
2668
|
),
|
|
2463
|
-
/* @__PURE__ */ (0,
|
|
2669
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2464
2670
|
"button",
|
|
2465
2671
|
{
|
|
2466
2672
|
type: "button",
|
|
@@ -2470,14 +2676,14 @@ var ImageEditor = ({
|
|
|
2470
2676
|
}
|
|
2471
2677
|
)
|
|
2472
2678
|
] }),
|
|
2473
|
-
/* @__PURE__ */ (0,
|
|
2474
|
-
/* @__PURE__ */ (0,
|
|
2475
|
-
/* @__PURE__ */ (0,
|
|
2679
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
|
|
2680
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Font Size:" }),
|
|
2681
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-mono", children: [
|
|
2476
2682
|
fontSize,
|
|
2477
2683
|
"px"
|
|
2478
2684
|
] })
|
|
2479
2685
|
] }),
|
|
2480
|
-
/* @__PURE__ */ (0,
|
|
2686
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2481
2687
|
"input",
|
|
2482
2688
|
{
|
|
2483
2689
|
type: "range",
|
|
@@ -2488,14 +2694,14 @@ var ImageEditor = ({
|
|
|
2488
2694
|
className: "w-full accent-indigo-500"
|
|
2489
2695
|
}
|
|
2490
2696
|
),
|
|
2491
|
-
/* @__PURE__ */ (0,
|
|
2492
|
-
/* @__PURE__ */ (0,
|
|
2493
|
-
/* @__PURE__ */ (0,
|
|
2697
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
|
|
2698
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2699
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "text-slate-400", children: [
|
|
2494
2700
|
"Layers (",
|
|
2495
2701
|
state.annotations.length,
|
|
2496
2702
|
")"
|
|
2497
2703
|
] }),
|
|
2498
|
-
state.selectedAnnotationId && /* @__PURE__ */ (0,
|
|
2704
|
+
state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2499
2705
|
"button",
|
|
2500
2706
|
{
|
|
2501
2707
|
type: "button",
|
|
@@ -2504,7 +2710,7 @@ var ImageEditor = ({
|
|
|
2504
2710
|
children: "Delete Selected"
|
|
2505
2711
|
}
|
|
2506
2712
|
),
|
|
2507
|
-
state.annotations.length > 0 && /* @__PURE__ */ (0,
|
|
2713
|
+
state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2508
2714
|
"button",
|
|
2509
2715
|
{
|
|
2510
2716
|
type: "button",
|
|
@@ -2515,10 +2721,10 @@ var ImageEditor = ({
|
|
|
2515
2721
|
)
|
|
2516
2722
|
] })
|
|
2517
2723
|
] }),
|
|
2518
|
-
activeTab === "depth" && /* @__PURE__ */ (0,
|
|
2519
|
-
/* @__PURE__ */ (0,
|
|
2520
|
-
/* @__PURE__ */ (0,
|
|
2521
|
-
/* @__PURE__ */ (0,
|
|
2724
|
+
activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2725
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2726
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
|
|
2727
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2522
2728
|
"button",
|
|
2523
2729
|
{
|
|
2524
2730
|
type: "button",
|
|
@@ -2528,8 +2734,8 @@ var ImageEditor = ({
|
|
|
2528
2734
|
}
|
|
2529
2735
|
)
|
|
2530
2736
|
] }),
|
|
2531
|
-
/* @__PURE__ */ (0,
|
|
2532
|
-
/* @__PURE__ */ (0,
|
|
2737
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
|
|
2738
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2533
2739
|
"input",
|
|
2534
2740
|
{
|
|
2535
2741
|
type: "checkbox",
|
|
@@ -2538,12 +2744,12 @@ var ImageEditor = ({
|
|
|
2538
2744
|
className: "rounded accent-indigo-500"
|
|
2539
2745
|
}
|
|
2540
2746
|
),
|
|
2541
|
-
/* @__PURE__ */ (0,
|
|
2747
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Enable Depth / Alpha Mask" })
|
|
2542
2748
|
] }),
|
|
2543
|
-
state.depthMask.enabled && /* @__PURE__ */ (0,
|
|
2544
|
-
/* @__PURE__ */ (0,
|
|
2545
|
-
/* @__PURE__ */ (0,
|
|
2546
|
-
/* @__PURE__ */ (0,
|
|
2749
|
+
state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
2750
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
|
|
2751
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
|
|
2752
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2547
2753
|
"input",
|
|
2548
2754
|
{
|
|
2549
2755
|
type: "text",
|
|
@@ -2554,8 +2760,8 @@ var ImageEditor = ({
|
|
|
2554
2760
|
}
|
|
2555
2761
|
)
|
|
2556
2762
|
] }),
|
|
2557
|
-
/* @__PURE__ */ (0,
|
|
2558
|
-
/* @__PURE__ */ (0,
|
|
2763
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex gap-2", children: [
|
|
2764
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2559
2765
|
"button",
|
|
2560
2766
|
{
|
|
2561
2767
|
type: "button",
|
|
@@ -2564,7 +2770,7 @@ var ImageEditor = ({
|
|
|
2564
2770
|
children: "Threshold Mode"
|
|
2565
2771
|
}
|
|
2566
2772
|
),
|
|
2567
|
-
/* @__PURE__ */ (0,
|
|
2773
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2568
2774
|
"button",
|
|
2569
2775
|
{
|
|
2570
2776
|
type: "button",
|
|
@@ -2574,12 +2780,12 @@ var ImageEditor = ({
|
|
|
2574
2780
|
}
|
|
2575
2781
|
)
|
|
2576
2782
|
] }),
|
|
2577
|
-
/* @__PURE__ */ (0,
|
|
2578
|
-
/* @__PURE__ */ (0,
|
|
2579
|
-
/* @__PURE__ */ (0,
|
|
2580
|
-
/* @__PURE__ */ (0,
|
|
2783
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
|
|
2784
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
2785
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Depth Start (Lower):" }),
|
|
2786
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
|
|
2581
2787
|
] }),
|
|
2582
|
-
/* @__PURE__ */ (0,
|
|
2788
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2583
2789
|
"input",
|
|
2584
2790
|
{
|
|
2585
2791
|
type: "range",
|
|
@@ -2593,12 +2799,12 @@ var ImageEditor = ({
|
|
|
2593
2799
|
}
|
|
2594
2800
|
)
|
|
2595
2801
|
] }),
|
|
2596
|
-
/* @__PURE__ */ (0,
|
|
2597
|
-
/* @__PURE__ */ (0,
|
|
2598
|
-
/* @__PURE__ */ (0,
|
|
2599
|
-
/* @__PURE__ */ (0,
|
|
2802
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
|
|
2803
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
2804
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Depth Stop (Upper):" }),
|
|
2805
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
|
|
2600
2806
|
] }),
|
|
2601
|
-
/* @__PURE__ */ (0,
|
|
2807
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2602
2808
|
"input",
|
|
2603
2809
|
{
|
|
2604
2810
|
type: "range",
|
|
@@ -2612,12 +2818,12 @@ var ImageEditor = ({
|
|
|
2612
2818
|
}
|
|
2613
2819
|
)
|
|
2614
2820
|
] }),
|
|
2615
|
-
/* @__PURE__ */ (0,
|
|
2616
|
-
/* @__PURE__ */ (0,
|
|
2617
|
-
/* @__PURE__ */ (0,
|
|
2618
|
-
/* @__PURE__ */ (0,
|
|
2821
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
|
|
2822
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
2823
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Softness:" }),
|
|
2824
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
|
|
2619
2825
|
] }),
|
|
2620
|
-
/* @__PURE__ */ (0,
|
|
2826
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2621
2827
|
"input",
|
|
2622
2828
|
{
|
|
2623
2829
|
type: "range",
|
|
@@ -2629,8 +2835,8 @@ var ImageEditor = ({
|
|
|
2629
2835
|
}
|
|
2630
2836
|
)
|
|
2631
2837
|
] }),
|
|
2632
|
-
/* @__PURE__ */ (0,
|
|
2633
|
-
/* @__PURE__ */ (0,
|
|
2838
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
|
|
2839
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2634
2840
|
"input",
|
|
2635
2841
|
{
|
|
2636
2842
|
type: "checkbox",
|
|
@@ -2639,12 +2845,12 @@ var ImageEditor = ({
|
|
|
2639
2845
|
className: "rounded accent-indigo-500"
|
|
2640
2846
|
}
|
|
2641
2847
|
),
|
|
2642
|
-
/* @__PURE__ */ (0,
|
|
2848
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Invert Mask" })
|
|
2643
2849
|
] })
|
|
2644
2850
|
] })
|
|
2645
2851
|
] }),
|
|
2646
|
-
activeTab === "select" && /* @__PURE__ */ (0,
|
|
2647
|
-
/* @__PURE__ */ (0,
|
|
2852
|
+
activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
2853
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2648
2854
|
SelectionOptionsBar,
|
|
2649
2855
|
{
|
|
2650
2856
|
controller,
|
|
@@ -2654,13 +2860,13 @@ var ImageEditor = ({
|
|
|
2654
2860
|
quickMask: Boolean(state.quickMask)
|
|
2655
2861
|
}
|
|
2656
2862
|
),
|
|
2657
|
-
selectionError && /* @__PURE__ */ (0,
|
|
2658
|
-
/* @__PURE__ */ (0,
|
|
2863
|
+
selectionError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
|
|
2864
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
|
|
2659
2865
|
] }),
|
|
2660
|
-
activeTab === "ai" && /* @__PURE__ */ (0,
|
|
2661
|
-
/* @__PURE__ */ (0,
|
|
2662
|
-
/* @__PURE__ */ (0,
|
|
2663
|
-
/* @__PURE__ */ (0,
|
|
2866
|
+
activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
2867
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
|
|
2868
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: "Results go to" }),
|
|
2869
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2664
2870
|
"select",
|
|
2665
2871
|
{
|
|
2666
2872
|
"aria-label": "AI result target",
|
|
@@ -2668,54 +2874,54 @@ var ImageEditor = ({
|
|
|
2668
2874
|
onChange: (e) => setAiTarget(e.target.value),
|
|
2669
2875
|
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
2670
2876
|
children: [
|
|
2671
|
-
/* @__PURE__ */ (0,
|
|
2672
|
-
/* @__PURE__ */ (0,
|
|
2673
|
-
/* @__PURE__ */ (0,
|
|
2877
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
|
|
2878
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
|
|
2879
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("option", { value: "replace", children: "Replace image" })
|
|
2674
2880
|
]
|
|
2675
2881
|
}
|
|
2676
2882
|
)
|
|
2677
2883
|
] }),
|
|
2678
|
-
/* @__PURE__ */ (0,
|
|
2679
|
-
/* @__PURE__ */ (0,
|
|
2680
|
-
/* @__PURE__ */ (0,
|
|
2681
|
-
/* @__PURE__ */ (0,
|
|
2884
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
2885
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2886
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
2887
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" }) }),
|
|
2682
2888
|
"Background Removal"
|
|
2683
2889
|
] }),
|
|
2684
|
-
isRemovingBg && /* @__PURE__ */ (0,
|
|
2890
|
+
isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse", children: "Removing..." })
|
|
2685
2891
|
] }),
|
|
2686
|
-
/* @__PURE__ */ (0,
|
|
2687
|
-
/* @__PURE__ */ (0,
|
|
2892
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
|
|
2893
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2688
2894
|
"button",
|
|
2689
2895
|
{
|
|
2690
2896
|
type: "button",
|
|
2691
2897
|
onClick: handleRemoveBackground,
|
|
2692
2898
|
disabled: isRemovingBg || isInpainting,
|
|
2693
2899
|
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",
|
|
2694
|
-
children: isRemovingBg ? /* @__PURE__ */ (0,
|
|
2695
|
-
/* @__PURE__ */ (0,
|
|
2900
|
+
children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
2901
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
2696
2902
|
"Removing Background..."
|
|
2697
|
-
] }) : /* @__PURE__ */ (0,
|
|
2698
|
-
/* @__PURE__ */ (0,
|
|
2903
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
2904
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
|
|
2699
2905
|
"Remove Background"
|
|
2700
2906
|
] })
|
|
2701
2907
|
}
|
|
2702
2908
|
)
|
|
2703
2909
|
] }),
|
|
2704
|
-
/* @__PURE__ */ (0,
|
|
2705
|
-
/* @__PURE__ */ (0,
|
|
2706
|
-
/* @__PURE__ */ (0,
|
|
2707
|
-
/* @__PURE__ */ (0,
|
|
2708
|
-
/* @__PURE__ */ (0,
|
|
2709
|
-
/* @__PURE__ */ (0,
|
|
2910
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
2911
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2912
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
2913
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "m21.64 3.64-1.28-1.28a1.2 1.2 0 0 0-1.7 0l-9.72 9.72-1.94 4.86 4.86-1.94 9.72-9.72a1.2 1.2 0 0 0 .06-1.64z" }),
|
|
2915
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "m14 7 3 3" })
|
|
2710
2916
|
] }),
|
|
2711
2917
|
"Generative Inpainting"
|
|
2712
2918
|
] }),
|
|
2713
|
-
isInpainting && /* @__PURE__ */ (0,
|
|
2919
|
+
isInpainting && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse", children: "Inpainting..." })
|
|
2714
2920
|
] }),
|
|
2715
|
-
/* @__PURE__ */ (0,
|
|
2716
|
-
/* @__PURE__ */ (0,
|
|
2717
|
-
/* @__PURE__ */ (0,
|
|
2718
|
-
/* @__PURE__ */ (0,
|
|
2921
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
|
|
2922
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
2923
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
|
|
2924
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2719
2925
|
"textarea",
|
|
2720
2926
|
{
|
|
2721
2927
|
id: "ai-inpaint-prompt-react",
|
|
@@ -2727,10 +2933,10 @@ var ImageEditor = ({
|
|
|
2727
2933
|
}
|
|
2728
2934
|
)
|
|
2729
2935
|
] }),
|
|
2730
|
-
/* @__PURE__ */ (0,
|
|
2731
|
-
/* @__PURE__ */ (0,
|
|
2732
|
-
/* @__PURE__ */ (0,
|
|
2733
|
-
/* @__PURE__ */ (0,
|
|
2936
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
2937
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
|
|
2938
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
|
|
2939
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2734
2940
|
"button",
|
|
2735
2941
|
{
|
|
2736
2942
|
type: "button",
|
|
@@ -2743,7 +2949,7 @@ var ImageEditor = ({
|
|
|
2743
2949
|
]
|
|
2744
2950
|
}
|
|
2745
2951
|
),
|
|
2746
|
-
/* @__PURE__ */ (0,
|
|
2952
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
2747
2953
|
"button",
|
|
2748
2954
|
{
|
|
2749
2955
|
type: "button",
|
|
@@ -2758,25 +2964,25 @@ var ImageEditor = ({
|
|
|
2758
2964
|
)
|
|
2759
2965
|
] })
|
|
2760
2966
|
] }),
|
|
2761
|
-
/* @__PURE__ */ (0,
|
|
2967
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2762
2968
|
"button",
|
|
2763
2969
|
{
|
|
2764
2970
|
type: "button",
|
|
2765
2971
|
onClick: handleInpaint,
|
|
2766
2972
|
disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
|
|
2767
2973
|
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",
|
|
2768
|
-
children: isInpainting ? /* @__PURE__ */ (0,
|
|
2769
|
-
/* @__PURE__ */ (0,
|
|
2974
|
+
children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
2975
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
2770
2976
|
"Generating Inpaint..."
|
|
2771
|
-
] }) : /* @__PURE__ */ (0,
|
|
2772
|
-
/* @__PURE__ */ (0,
|
|
2977
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
2978
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
|
|
2773
2979
|
"Apply Inpainting"
|
|
2774
2980
|
] })
|
|
2775
2981
|
}
|
|
2776
2982
|
)
|
|
2777
2983
|
] }),
|
|
2778
|
-
aiError && /* @__PURE__ */ (0,
|
|
2779
|
-
aiSuccess && /* @__PURE__ */ (0,
|
|
2984
|
+
aiError && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
|
|
2985
|
+
aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
|
|
2780
2986
|
] })
|
|
2781
2987
|
] })
|
|
2782
2988
|
] })
|
|
@@ -2792,6 +2998,7 @@ var ImageEditor = ({
|
|
|
2792
2998
|
CurvesEditor,
|
|
2793
2999
|
Histogram,
|
|
2794
3000
|
ImageEditor,
|
|
3001
|
+
LayerEffectsPanel,
|
|
2795
3002
|
LayersPanel,
|
|
2796
3003
|
RefineEdgePanel,
|
|
2797
3004
|
SelectionOptionsBar,
|