@pixerate/editor-react 0.63.0 → 0.65.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-OSBDCFF4.js} +799 -382
- package/dist/chunk-OSBDCFF4.js.map +1 -0
- package/dist/image-editor/index.cjs +833 -417
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +31 -3
- package/dist/image-editor/index.d.ts +31 -3
- package/dist/image-editor/index.js +5 -1
- package/dist/index.cjs +1267 -851
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/chunk-QJSMW4CM.js.map +0 -1
|
@@ -159,7 +159,7 @@ function useImageEditor(options = {}) {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
// src/image-editor/ImageEditor.tsx
|
|
162
|
-
import
|
|
162
|
+
import React10, { useRef as useRef5, useEffect as useEffect8, useState as useState11, useCallback as useCallback2 } from "react";
|
|
163
163
|
import {
|
|
164
164
|
canvasToImagePoint,
|
|
165
165
|
hitTestCrop,
|
|
@@ -174,7 +174,9 @@ import {
|
|
|
174
174
|
SelectionGesture,
|
|
175
175
|
PaintGesture,
|
|
176
176
|
handlePaintShortcut,
|
|
177
|
-
pointerPressure
|
|
177
|
+
pointerPressure,
|
|
178
|
+
FreeTransformTool,
|
|
179
|
+
getViewportProjection
|
|
178
180
|
} from "@pixerate/editor/image-editor";
|
|
179
181
|
|
|
180
182
|
// src/image-editor/ControlSlider.tsx
|
|
@@ -626,7 +628,196 @@ var AdjustmentLayersPanel = ({ controller, layers: layersProp, histogram }) => {
|
|
|
626
628
|
};
|
|
627
629
|
|
|
628
630
|
// src/image-editor/LayersPanel.tsx
|
|
631
|
+
import { useEffect as useEffect5, useRef as useRef4, useState as useState6 } from "react";
|
|
632
|
+
|
|
633
|
+
// src/image-editor/LayerEffectsPanel.tsx
|
|
629
634
|
import { useEffect as useEffect4, useRef as useRef3, useState as useState5 } from "react";
|
|
635
|
+
import { LAYER_EFFECT_MENU, effectControlChange, layerEffectControls, layerEffectsPanel } from "@pixerate/editor/image-editor";
|
|
636
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
637
|
+
var button = "px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40";
|
|
638
|
+
var LayerEffectsPanel = ({ controller, layerId, className }) => {
|
|
639
|
+
const [, setTick] = useState5(0);
|
|
640
|
+
useEffect4(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
641
|
+
const [open, setOpen] = useState5(null);
|
|
642
|
+
const [error, setError] = useState5(null);
|
|
643
|
+
const commitNext = useRef3(true);
|
|
644
|
+
const layer = layerId ? controller.getLayer(layerId) : controller.getActiveLayer();
|
|
645
|
+
const model = layerEffectsPanel(layer);
|
|
646
|
+
const id = layer?.id;
|
|
647
|
+
const attempt = (fn) => {
|
|
648
|
+
try {
|
|
649
|
+
setError(null);
|
|
650
|
+
fn();
|
|
651
|
+
} catch (err) {
|
|
652
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
const sliderEvents = {
|
|
656
|
+
onPointerDown: () => commitNext.current = true,
|
|
657
|
+
onPointerUp: () => commitNext.current = true,
|
|
658
|
+
onKeyDown: () => commitNext.current = true
|
|
659
|
+
};
|
|
660
|
+
if (!model.available || !id) {
|
|
661
|
+
return /* @__PURE__ */ jsx5("div", { className: `text-xs text-slate-500 ${className ?? ""}`, "data-testid": "layer-effects", children: model.reason });
|
|
662
|
+
}
|
|
663
|
+
const effects = controller.getLayerEffects(id);
|
|
664
|
+
const patterns = controller.getDocumentPatterns();
|
|
665
|
+
const change = (effectId, control, value, drag = false) => attempt(() => {
|
|
666
|
+
const effect = controller.getLayerEffects(id).items.find((e) => e.id === effectId);
|
|
667
|
+
controller.updateLayerEffect(id, effectId, effectControlChange(effect, control.key, value, patterns), drag ? commitNext.current : true);
|
|
668
|
+
if (drag) commitNext.current = false;
|
|
669
|
+
});
|
|
670
|
+
const renderControl = (effectId, c) => {
|
|
671
|
+
const label = `${c.label}`;
|
|
672
|
+
switch (c.type) {
|
|
673
|
+
case "range": {
|
|
674
|
+
const k = c.percent ? 100 : 1;
|
|
675
|
+
const shown = Math.round(c.value * k * 100) / 100;
|
|
676
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex flex-col gap-0.5", children: [
|
|
677
|
+
/* @__PURE__ */ jsxs5("span", { className: "text-slate-400", children: [
|
|
678
|
+
label,
|
|
679
|
+
" ",
|
|
680
|
+
shown,
|
|
681
|
+
c.unit
|
|
682
|
+
] }),
|
|
683
|
+
/* @__PURE__ */ jsx5(
|
|
684
|
+
"input",
|
|
685
|
+
{
|
|
686
|
+
type: "range",
|
|
687
|
+
"aria-label": label,
|
|
688
|
+
min: c.min * k,
|
|
689
|
+
max: c.max * k,
|
|
690
|
+
step: c.step * k,
|
|
691
|
+
value: shown,
|
|
692
|
+
disabled: model.readOnly,
|
|
693
|
+
...sliderEvents,
|
|
694
|
+
onChange: (e) => change(effectId, c, Number(e.target.value) / k, true),
|
|
695
|
+
className: "accent-indigo-500"
|
|
696
|
+
}
|
|
697
|
+
)
|
|
698
|
+
] }, c.key);
|
|
699
|
+
}
|
|
700
|
+
case "color":
|
|
701
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
702
|
+
/* @__PURE__ */ jsx5("input", { type: "color", "aria-label": label, value: c.value, disabled: model.readOnly, onChange: (e) => change(effectId, c, e.target.value) }),
|
|
703
|
+
label
|
|
704
|
+
] }, c.key);
|
|
705
|
+
case "checkbox":
|
|
706
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
707
|
+
/* @__PURE__ */ jsx5("input", { type: "checkbox", "aria-label": label, checked: c.value, disabled: model.readOnly, onChange: (e) => change(effectId, c, e.target.checked), className: "accent-indigo-500" }),
|
|
708
|
+
label
|
|
709
|
+
] }, c.key);
|
|
710
|
+
case "select":
|
|
711
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex flex-col gap-0.5", children: [
|
|
712
|
+
/* @__PURE__ */ jsx5("span", { className: "text-slate-400", children: label }),
|
|
713
|
+
/* @__PURE__ */ jsx5(
|
|
714
|
+
"select",
|
|
715
|
+
{
|
|
716
|
+
"aria-label": label,
|
|
717
|
+
value: c.value,
|
|
718
|
+
disabled: model.readOnly,
|
|
719
|
+
onChange: (e) => change(effectId, c, e.target.value),
|
|
720
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
721
|
+
children: c.options.map((o) => /* @__PURE__ */ jsx5("option", { value: o.value, children: o.label }, o.value))
|
|
722
|
+
}
|
|
723
|
+
)
|
|
724
|
+
] }, c.key);
|
|
725
|
+
}
|
|
726
|
+
};
|
|
727
|
+
return /* @__PURE__ */ jsxs5("div", { className: `flex flex-col gap-1.5 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layer-effects", "aria-label": "Layer effects", role: "group", children: [
|
|
728
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
729
|
+
/* @__PURE__ */ jsx5("span", { className: "font-semibold text-slate-300", children: "fx Effects" }),
|
|
730
|
+
/* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-1 text-slate-300", children: [
|
|
731
|
+
/* @__PURE__ */ jsx5(
|
|
732
|
+
"input",
|
|
733
|
+
{
|
|
734
|
+
type: "checkbox",
|
|
735
|
+
"aria-label": "Effects on",
|
|
736
|
+
checked: model.enabled,
|
|
737
|
+
disabled: model.readOnly,
|
|
738
|
+
onChange: (e) => attempt(() => controller.setLayerEffectsEnabled(id, e.target.checked)),
|
|
739
|
+
className: "accent-indigo-500"
|
|
740
|
+
}
|
|
741
|
+
),
|
|
742
|
+
"On"
|
|
743
|
+
] }),
|
|
744
|
+
/* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-1 text-slate-400", children: [
|
|
745
|
+
"Scale",
|
|
746
|
+
/* @__PURE__ */ jsx5(
|
|
747
|
+
"input",
|
|
748
|
+
{
|
|
749
|
+
type: "number",
|
|
750
|
+
"aria-label": "Scale effects",
|
|
751
|
+
min: 1,
|
|
752
|
+
max: 1e3,
|
|
753
|
+
step: 1,
|
|
754
|
+
value: Math.round(model.scale * 100),
|
|
755
|
+
disabled: model.readOnly,
|
|
756
|
+
onChange: (e) => {
|
|
757
|
+
const v = Number(e.target.value);
|
|
758
|
+
if (v >= 1 && v <= 1e3) attempt(() => controller.setLayerEffectsEnabled(id, model.enabled, v / 100));
|
|
759
|
+
},
|
|
760
|
+
className: "w-14 bg-slate-800 border border-slate-700 rounded px-1"
|
|
761
|
+
}
|
|
762
|
+
),
|
|
763
|
+
"%"
|
|
764
|
+
] }),
|
|
765
|
+
/* @__PURE__ */ jsxs5(
|
|
766
|
+
"select",
|
|
767
|
+
{
|
|
768
|
+
"aria-label": "Add effect",
|
|
769
|
+
value: "",
|
|
770
|
+
disabled: model.readOnly,
|
|
771
|
+
onChange: (e) => {
|
|
772
|
+
const kind = e.target.value;
|
|
773
|
+
if (!kind) return;
|
|
774
|
+
attempt(() => setOpen(controller.addLayerEffect(id, kind).effect.id));
|
|
775
|
+
},
|
|
776
|
+
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
777
|
+
children: [
|
|
778
|
+
/* @__PURE__ */ jsx5("option", { value: "", children: "Add effect\u2026" }),
|
|
779
|
+
LAYER_EFFECT_MENU.map((m) => /* @__PURE__ */ jsx5("option", { value: m.kind, children: m.label }, m.kind))
|
|
780
|
+
]
|
|
781
|
+
}
|
|
782
|
+
)
|
|
783
|
+
] }),
|
|
784
|
+
model.readOnly && model.reason && /* @__PURE__ */ jsx5("p", { className: "text-slate-500", children: model.reason }),
|
|
785
|
+
/* @__PURE__ */ jsx5("ul", { className: "flex flex-col gap-1", "aria-label": "Effects", children: model.rows.map((row) => {
|
|
786
|
+
const effect = effects.items.find((e) => e.id === row.id);
|
|
787
|
+
const expanded = open === row.id;
|
|
788
|
+
return /* @__PURE__ */ jsxs5("li", { "data-effect-id": row.id, className: "rounded bg-slate-900/60 ring-1 ring-slate-800", children: [
|
|
789
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5 px-1.5 py-1", children: [
|
|
790
|
+
/* @__PURE__ */ jsx5(
|
|
791
|
+
"input",
|
|
792
|
+
{
|
|
793
|
+
type: "checkbox",
|
|
794
|
+
"aria-label": `${row.label} on`,
|
|
795
|
+
checked: row.enabled,
|
|
796
|
+
disabled: model.readOnly,
|
|
797
|
+
onChange: (e) => attempt(() => controller.updateLayerEffect(id, row.id, { enabled: e.target.checked })),
|
|
798
|
+
className: "accent-indigo-500"
|
|
799
|
+
}
|
|
800
|
+
),
|
|
801
|
+
/* @__PURE__ */ jsx5(
|
|
802
|
+
"button",
|
|
803
|
+
{
|
|
804
|
+
type: "button",
|
|
805
|
+
"aria-expanded": expanded,
|
|
806
|
+
className: `flex-1 text-left ${row.enabled && model.enabled ? "" : "text-slate-500"}`,
|
|
807
|
+
onClick: () => setOpen(expanded ? null : row.id),
|
|
808
|
+
children: row.label
|
|
809
|
+
}
|
|
810
|
+
),
|
|
811
|
+
/* @__PURE__ */ jsx5("button", { type: "button", className: button, "aria-label": `Remove ${row.label}`, disabled: model.readOnly, onClick: () => attempt(() => controller.removeLayerEffect(id, row.id)), children: "\u2715" })
|
|
812
|
+
] }),
|
|
813
|
+
expanded && /* @__PURE__ */ jsx5("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 px-1.5 pb-1.5", "data-testid": "effect-settings", children: layerEffectControls(effect, patterns).map((c) => renderControl(row.id, c)) })
|
|
814
|
+
] }, row.id);
|
|
815
|
+
}) }),
|
|
816
|
+
error && /* @__PURE__ */ jsx5("p", { role: "alert", className: "text-rose-400", children: error })
|
|
817
|
+
] });
|
|
818
|
+
};
|
|
819
|
+
|
|
820
|
+
// src/image-editor/LayersPanel.tsx
|
|
630
821
|
import {
|
|
631
822
|
BLEND_MODES as BLEND_MODES2,
|
|
632
823
|
PSD_FILE_ACCEPT,
|
|
@@ -635,11 +826,12 @@ import {
|
|
|
635
826
|
dropZone,
|
|
636
827
|
openPsdFile,
|
|
637
828
|
layerBadge,
|
|
829
|
+
layerEffectsBadge,
|
|
638
830
|
layerMenu,
|
|
639
831
|
layerPanelRows,
|
|
640
832
|
runLayerMenuAction
|
|
641
833
|
} from "@pixerate/editor/image-editor";
|
|
642
|
-
import { Fragment, jsx as
|
|
834
|
+
import { Fragment, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
643
835
|
var iconButton = "px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40";
|
|
644
836
|
var rowClass = (active) => `flex items-center gap-1.5 px-1.5 py-1 rounded cursor-pointer select-none ${active ? "bg-indigo-600/30 ring-1 ring-indigo-500" : "hover:bg-slate-800"}`;
|
|
645
837
|
var Thumbnail = ({
|
|
@@ -650,8 +842,8 @@ var Thumbnail = ({
|
|
|
650
842
|
selected,
|
|
651
843
|
testId
|
|
652
844
|
}) => {
|
|
653
|
-
const ref =
|
|
654
|
-
|
|
845
|
+
const ref = useRef4(null);
|
|
846
|
+
useEffect5(() => {
|
|
655
847
|
const canvas = ref.current;
|
|
656
848
|
const ctx = canvas?.getContext("2d");
|
|
657
849
|
if (!canvas || !ctx || !pixels || typeof ctx.createImageData !== "function") return;
|
|
@@ -661,7 +853,7 @@ var Thumbnail = ({
|
|
|
661
853
|
img.data.set(pixels.data);
|
|
662
854
|
ctx.putImageData(img, 0, 0);
|
|
663
855
|
}, [pixels]);
|
|
664
|
-
return /* @__PURE__ */
|
|
856
|
+
return /* @__PURE__ */ jsx6(
|
|
665
857
|
"canvas",
|
|
666
858
|
{
|
|
667
859
|
ref,
|
|
@@ -674,15 +866,15 @@ var Thumbnail = ({
|
|
|
674
866
|
}
|
|
675
867
|
);
|
|
676
868
|
};
|
|
677
|
-
var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", className }) => {
|
|
678
|
-
const [, setTick] =
|
|
679
|
-
|
|
680
|
-
const [error, setError] =
|
|
681
|
-
const [renaming, setRenaming] =
|
|
682
|
-
const [menu, setMenu] =
|
|
683
|
-
const [drag, setDrag] =
|
|
684
|
-
const [psdNotes, setPsdNotes] =
|
|
685
|
-
const fileInput =
|
|
869
|
+
var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", effects = true, className }) => {
|
|
870
|
+
const [, setTick] = useState6(0);
|
|
871
|
+
useEffect5(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
872
|
+
const [error, setError] = useState6(null);
|
|
873
|
+
const [renaming, setRenaming] = useState6(null);
|
|
874
|
+
const [menu, setMenu] = useState6(null);
|
|
875
|
+
const [drag, setDrag] = useState6(null);
|
|
876
|
+
const [psdNotes, setPsdNotes] = useState6([]);
|
|
877
|
+
const fileInput = useRef4(null);
|
|
686
878
|
const psdTask = async (fn) => {
|
|
687
879
|
try {
|
|
688
880
|
setError(null);
|
|
@@ -691,7 +883,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
691
883
|
setError(err instanceof Error ? err.message : String(err));
|
|
692
884
|
}
|
|
693
885
|
};
|
|
694
|
-
const commitNext =
|
|
886
|
+
const commitNext = useRef4(true);
|
|
695
887
|
const state = controller.getState();
|
|
696
888
|
const rows = layerPanelRows(state.layers, state.activeLayerId);
|
|
697
889
|
const active = controller.getActiveLayer();
|
|
@@ -729,14 +921,14 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
729
921
|
const thumb = (layer) => layer.type === "pixel" ? controller.getLayerThumbnail(layer.id, { maxSide: 64 }) : null;
|
|
730
922
|
const maskThumb = (layer) => layer.mask && !layer.mask.source ? controller.getLayerThumbnail(layer.id, { maxSide: 64, mask: true }) : null;
|
|
731
923
|
const locked = (layer) => Boolean(layer.locks?.all || layer.locks?.pixels || layer.locks?.position || layer.locks?.transparency);
|
|
732
|
-
return /* @__PURE__ */
|
|
733
|
-
/* @__PURE__ */
|
|
734
|
-
/* @__PURE__ */
|
|
735
|
-
/* @__PURE__ */
|
|
736
|
-
/* @__PURE__ */
|
|
737
|
-
/* @__PURE__ */
|
|
738
|
-
/* @__PURE__ */
|
|
739
|
-
/* @__PURE__ */
|
|
924
|
+
return /* @__PURE__ */ jsxs6("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layers-panel", onClick: () => menu && setMenu(null), children: [
|
|
925
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex flex-wrap items-center gap-1", role: "toolbar", "aria-label": "Layer actions", children: [
|
|
926
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, onClick: () => run("new-layer"), children: "New Layer" }),
|
|
927
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, onClick: () => run("new-group"), children: "New Group" }),
|
|
928
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("duplicate"), children: "Duplicate" }),
|
|
929
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("add-mask"), children: "Add Mask" }),
|
|
930
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("delete"), children: "Delete" }),
|
|
931
|
+
/* @__PURE__ */ jsx6(
|
|
740
932
|
"button",
|
|
741
933
|
{
|
|
742
934
|
type: "button",
|
|
@@ -751,10 +943,10 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
751
943
|
children: "\u22EF"
|
|
752
944
|
}
|
|
753
945
|
),
|
|
754
|
-
psd && /* @__PURE__ */
|
|
755
|
-
/* @__PURE__ */
|
|
756
|
-
/* @__PURE__ */
|
|
757
|
-
/* @__PURE__ */
|
|
946
|
+
psd && /* @__PURE__ */ jsxs6(Fragment, { children: [
|
|
947
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, onClick: () => fileInput.current?.click(), children: "Open PSD\u2026" }),
|
|
948
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: iconButton, onClick: () => psdTask(async () => (await downloadPsd(controller, psdFileName)).warnings), children: "Export PSD" }),
|
|
949
|
+
/* @__PURE__ */ jsx6(
|
|
758
950
|
"input",
|
|
759
951
|
{
|
|
760
952
|
ref: fileInput,
|
|
@@ -772,18 +964,18 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
772
964
|
)
|
|
773
965
|
] })
|
|
774
966
|
] }),
|
|
775
|
-
psdNotes.length > 0 && /* @__PURE__ */
|
|
776
|
-
psdNotes.map((n) => /* @__PURE__ */
|
|
777
|
-
/* @__PURE__ */
|
|
967
|
+
psdNotes.length > 0 && /* @__PURE__ */ jsxs6("ul", { className: "rounded bg-amber-900/30 text-amber-200 px-2 py-1 space-y-0.5", "data-testid": "psd-warnings", "aria-label": "PSD warnings", children: [
|
|
968
|
+
psdNotes.map((n) => /* @__PURE__ */ jsx6("li", { children: n }, n)),
|
|
969
|
+
/* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsx6("button", { type: "button", className: "underline", onClick: () => setPsdNotes([]), children: "Dismiss" }) })
|
|
778
970
|
] }),
|
|
779
|
-
active && /* @__PURE__ */
|
|
780
|
-
/* @__PURE__ */
|
|
781
|
-
/* @__PURE__ */
|
|
971
|
+
active && /* @__PURE__ */ jsxs6("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 items-center", "data-testid": "layer-properties", children: [
|
|
972
|
+
/* @__PURE__ */ jsxs6("label", { className: "flex flex-col gap-0.5", children: [
|
|
973
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-slate-400", children: [
|
|
782
974
|
"Opacity ",
|
|
783
975
|
Math.round(active.opacity * 100),
|
|
784
976
|
"%"
|
|
785
977
|
] }),
|
|
786
|
-
/* @__PURE__ */
|
|
978
|
+
/* @__PURE__ */ jsx6(
|
|
787
979
|
"input",
|
|
788
980
|
{
|
|
789
981
|
type: "range",
|
|
@@ -797,13 +989,13 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
797
989
|
}
|
|
798
990
|
)
|
|
799
991
|
] }),
|
|
800
|
-
/* @__PURE__ */
|
|
801
|
-
/* @__PURE__ */
|
|
992
|
+
/* @__PURE__ */ jsxs6("label", { className: "flex flex-col gap-0.5", children: [
|
|
993
|
+
/* @__PURE__ */ jsxs6("span", { className: "text-slate-400", children: [
|
|
802
994
|
"Fill ",
|
|
803
995
|
Math.round(((active.type === "pixel" ? active.fillOpacity : void 0) ?? 1) * 100),
|
|
804
996
|
"%"
|
|
805
997
|
] }),
|
|
806
|
-
/* @__PURE__ */
|
|
998
|
+
/* @__PURE__ */ jsx6(
|
|
807
999
|
"input",
|
|
808
1000
|
{
|
|
809
1001
|
type: "range",
|
|
@@ -818,7 +1010,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
818
1010
|
}
|
|
819
1011
|
)
|
|
820
1012
|
] }),
|
|
821
|
-
/* @__PURE__ */
|
|
1013
|
+
/* @__PURE__ */ jsxs6(
|
|
822
1014
|
"select",
|
|
823
1015
|
{
|
|
824
1016
|
"aria-label": "Layer blend mode",
|
|
@@ -826,13 +1018,13 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
826
1018
|
value: active.blend,
|
|
827
1019
|
onChange: (e) => attempt(() => controller.setLayerProperties(active.id, { blend: e.target.value })),
|
|
828
1020
|
children: [
|
|
829
|
-
active.type === "group" && /* @__PURE__ */
|
|
830
|
-
BLEND_MODES2.map((m) => /* @__PURE__ */
|
|
1021
|
+
active.type === "group" && /* @__PURE__ */ jsx6("option", { value: "pass-through", children: "Pass Through" }),
|
|
1022
|
+
BLEND_MODES2.map((m) => /* @__PURE__ */ jsx6("option", { value: m.id, children: m.label }, m.id))
|
|
831
1023
|
]
|
|
832
1024
|
}
|
|
833
1025
|
),
|
|
834
|
-
/* @__PURE__ */
|
|
835
|
-
/* @__PURE__ */
|
|
1026
|
+
/* @__PURE__ */ jsxs6("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
|
|
1027
|
+
/* @__PURE__ */ jsx6(
|
|
836
1028
|
"input",
|
|
837
1029
|
{
|
|
838
1030
|
type: "checkbox",
|
|
@@ -844,8 +1036,8 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
844
1036
|
),
|
|
845
1037
|
"Clip to below"
|
|
846
1038
|
] }),
|
|
847
|
-
/* @__PURE__ */
|
|
848
|
-
/* @__PURE__ */
|
|
1039
|
+
/* @__PURE__ */ jsx6("div", { className: "col-span-2 flex flex-wrap gap-2 text-slate-400", role: "group", "aria-label": "Layer locks", children: ["pixels", "transparency", "position", "all"].map((k) => /* @__PURE__ */ jsxs6("label", { className: "flex items-center gap-1", children: [
|
|
1040
|
+
/* @__PURE__ */ jsx6(
|
|
849
1041
|
"input",
|
|
850
1042
|
{
|
|
851
1043
|
type: "checkbox",
|
|
@@ -858,9 +1050,10 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
858
1050
|
k
|
|
859
1051
|
] }, k)) })
|
|
860
1052
|
] }),
|
|
861
|
-
/* @__PURE__ */
|
|
1053
|
+
effects && active && active.type !== "adjustment" && /* @__PURE__ */ jsx6(LayerEffectsPanel, { controller, className: "border-t border-slate-800 pt-1.5" }),
|
|
1054
|
+
/* @__PURE__ */ jsx6("ul", { className: "flex flex-col gap-0.5", role: "tree", "aria-label": "Layers", children: rows.map((row) => {
|
|
862
1055
|
const { layer } = row;
|
|
863
|
-
return /* @__PURE__ */
|
|
1056
|
+
return /* @__PURE__ */ jsxs6(
|
|
864
1057
|
"li",
|
|
865
1058
|
{
|
|
866
1059
|
role: "treeitem",
|
|
@@ -890,7 +1083,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
890
1083
|
className: rowClass(row.active),
|
|
891
1084
|
style: { paddingLeft: 6 + row.depth * 14 },
|
|
892
1085
|
children: [
|
|
893
|
-
/* @__PURE__ */
|
|
1086
|
+
/* @__PURE__ */ jsx6(
|
|
894
1087
|
"button",
|
|
895
1088
|
{
|
|
896
1089
|
type: "button",
|
|
@@ -904,7 +1097,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
904
1097
|
children: layer.visible ? "\u25CF" : "\u25CB"
|
|
905
1098
|
}
|
|
906
1099
|
),
|
|
907
|
-
layer.type === "group" && /* @__PURE__ */
|
|
1100
|
+
layer.type === "group" && /* @__PURE__ */ jsx6(
|
|
908
1101
|
"button",
|
|
909
1102
|
{
|
|
910
1103
|
type: "button",
|
|
@@ -917,8 +1110,8 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
917
1110
|
children: layer.collapsed ? "\u25B8" : "\u25BE"
|
|
918
1111
|
}
|
|
919
1112
|
),
|
|
920
|
-
row.clipped && /* @__PURE__ */
|
|
921
|
-
layer.type === "pixel" ? /* @__PURE__ */
|
|
1113
|
+
row.clipped && /* @__PURE__ */ jsx6("span", { className: "text-slate-500", "aria-label": "Clipped", children: "\u21B3" }),
|
|
1114
|
+
layer.type === "pixel" ? /* @__PURE__ */ jsx6(
|
|
922
1115
|
Thumbnail,
|
|
923
1116
|
{
|
|
924
1117
|
pixels: thumb(layer),
|
|
@@ -926,7 +1119,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
926
1119
|
label: `${row.label} pixels`,
|
|
927
1120
|
selected: row.active && state.activeTarget === "pixels" && Boolean(layer.mask)
|
|
928
1121
|
}
|
|
929
|
-
) : /* @__PURE__ */
|
|
1122
|
+
) : /* @__PURE__ */ jsx6(
|
|
930
1123
|
"span",
|
|
931
1124
|
{
|
|
932
1125
|
className: "shrink-0 grid place-items-center rounded bg-slate-800 text-[9px] text-slate-400 ring-1 ring-slate-700",
|
|
@@ -934,7 +1127,23 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
934
1127
|
children: layerBadge(layer)
|
|
935
1128
|
}
|
|
936
1129
|
),
|
|
937
|
-
layer.mask && /* @__PURE__ */
|
|
1130
|
+
layer.mask && !layer.mask.source && layer.type === "pixel" && /* @__PURE__ */ jsx6(
|
|
1131
|
+
"button",
|
|
1132
|
+
{
|
|
1133
|
+
type: "button",
|
|
1134
|
+
"aria-label": `${layer.mask.linked === false ? "Link" : "Unlink"} ${row.label} mask`,
|
|
1135
|
+
"aria-pressed": layer.mask.linked !== false,
|
|
1136
|
+
title: layer.mask.linked === false ? "Mask unlinked: it stays put when the layer moves or transforms. Click to link." : "Mask linked: it moves with the layer. Click to unlink.",
|
|
1137
|
+
"data-testid": "layer-mask-link",
|
|
1138
|
+
className: `shrink-0 text-[10px] leading-none ${layer.mask.linked === false ? "text-slate-600" : "text-slate-300"}`,
|
|
1139
|
+
onClick: (e) => {
|
|
1140
|
+
e.stopPropagation();
|
|
1141
|
+
attempt(() => controller.setLayerMaskProps(layer.id, { linked: layer.mask.linked === false }));
|
|
1142
|
+
},
|
|
1143
|
+
children: layer.mask.linked === false ? "\u26D3\uFE0E\u0338" : "\u26D3\uFE0E"
|
|
1144
|
+
}
|
|
1145
|
+
),
|
|
1146
|
+
layer.mask && /* @__PURE__ */ jsx6(
|
|
938
1147
|
Thumbnail,
|
|
939
1148
|
{
|
|
940
1149
|
pixels: maskThumb(layer),
|
|
@@ -949,7 +1158,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
949
1158
|
}
|
|
950
1159
|
}
|
|
951
1160
|
),
|
|
952
|
-
renaming === layer.id ? /* @__PURE__ */
|
|
1161
|
+
renaming === layer.id ? /* @__PURE__ */ jsx6(
|
|
953
1162
|
"input",
|
|
954
1163
|
{
|
|
955
1164
|
autoFocus: true,
|
|
@@ -966,7 +1175,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
966
1175
|
if (e.key === "Escape") setRenaming(null);
|
|
967
1176
|
}
|
|
968
1177
|
}
|
|
969
|
-
) : /* @__PURE__ */
|
|
1178
|
+
) : /* @__PURE__ */ jsx6(
|
|
970
1179
|
"span",
|
|
971
1180
|
{
|
|
972
1181
|
className: `flex-1 min-w-0 truncate ${layer.visible ? "" : "text-slate-500"}`,
|
|
@@ -977,15 +1186,30 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
977
1186
|
children: row.label
|
|
978
1187
|
}
|
|
979
1188
|
),
|
|
980
|
-
|
|
981
|
-
|
|
1189
|
+
layerEffectsBadge(layer) && /* @__PURE__ */ jsx6(
|
|
1190
|
+
"button",
|
|
1191
|
+
{
|
|
1192
|
+
type: "button",
|
|
1193
|
+
"data-testid": "layer-fx-badge",
|
|
1194
|
+
"aria-label": layerEffectsBadge(layer) === "on" ? `Turn effects off for ${row.label}` : `Turn effects on for ${row.label}`,
|
|
1195
|
+
"aria-pressed": layerEffectsBadge(layer) === "on",
|
|
1196
|
+
className: `text-[9px] italic font-semibold ${layerEffectsBadge(layer) === "on" ? "text-indigo-300" : "text-slate-600 line-through"}`,
|
|
1197
|
+
onClick: (e) => {
|
|
1198
|
+
e.stopPropagation();
|
|
1199
|
+
attempt(() => controller.setLayerEffectsEnabled(layer.id, layerEffectsBadge(layer) !== "on"));
|
|
1200
|
+
},
|
|
1201
|
+
children: "fx"
|
|
1202
|
+
}
|
|
1203
|
+
),
|
|
1204
|
+
locked(layer) && /* @__PURE__ */ jsx6("span", { "aria-label": "Locked", className: "text-slate-400", children: "\u{1F512}" }),
|
|
1205
|
+
layer.blend !== "normal" && layer.blend !== "pass-through" && /* @__PURE__ */ jsx6("span", { className: "text-[9px] text-slate-500", children: layer.blend })
|
|
982
1206
|
]
|
|
983
1207
|
},
|
|
984
1208
|
layer.id
|
|
985
1209
|
);
|
|
986
1210
|
}) }),
|
|
987
|
-
error && /* @__PURE__ */
|
|
988
|
-
menu && /* @__PURE__ */
|
|
1211
|
+
error && /* @__PURE__ */ jsx6("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
1212
|
+
menu && /* @__PURE__ */ jsx6(
|
|
989
1213
|
"div",
|
|
990
1214
|
{
|
|
991
1215
|
role: "menu",
|
|
@@ -994,7 +1218,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
994
1218
|
style: { left: menu.x, top: menu.y },
|
|
995
1219
|
onClick: (e) => e.stopPropagation(),
|
|
996
1220
|
onKeyDown: (e) => e.key === "Escape" && setMenu(null),
|
|
997
|
-
children: layerMenu(controller).map((item) => /* @__PURE__ */
|
|
1221
|
+
children: layerMenu(controller).map((item) => /* @__PURE__ */ jsx6(
|
|
998
1222
|
"button",
|
|
999
1223
|
{
|
|
1000
1224
|
type: "button",
|
|
@@ -1012,14 +1236,14 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
|
|
|
1012
1236
|
};
|
|
1013
1237
|
|
|
1014
1238
|
// src/image-editor/BrushOptionsBar.tsx
|
|
1015
|
-
import { useEffect as
|
|
1239
|
+
import { useEffect as useEffect6, useState as useState7 } from "react";
|
|
1016
1240
|
import { BRUSH_OPTION_CONTROLS, MIXER_MIXING_OPTIONS, MIXER_OPTION_CONTROLS, PAINT_TOOLS, rgbUnitToHex } from "@pixerate/editor/image-editor";
|
|
1017
|
-
import { jsx as
|
|
1241
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1018
1242
|
var chip = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
|
|
1019
1243
|
var BrushOptionsBar = ({ controller, className }) => {
|
|
1020
|
-
const [, setTick] =
|
|
1021
|
-
|
|
1022
|
-
const [error, setError] =
|
|
1244
|
+
const [, setTick] = useState7(0);
|
|
1245
|
+
useEffect6(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
|
|
1246
|
+
const [error, setError] = useState7(null);
|
|
1023
1247
|
const state = controller.getState();
|
|
1024
1248
|
const { brush, foreground, background, mixer, mixerLoad } = state.paint;
|
|
1025
1249
|
const attempt = (fn) => {
|
|
@@ -1030,8 +1254,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1030
1254
|
setError(err instanceof Error ? err.message : String(err));
|
|
1031
1255
|
}
|
|
1032
1256
|
};
|
|
1033
|
-
return /* @__PURE__ */
|
|
1034
|
-
/* @__PURE__ */
|
|
1257
|
+
return /* @__PURE__ */ jsxs7("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
|
|
1258
|
+
/* @__PURE__ */ jsx7("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Paint tools", children: PAINT_TOOLS.map((t) => /* @__PURE__ */ jsx7(
|
|
1035
1259
|
"button",
|
|
1036
1260
|
{
|
|
1037
1261
|
type: "button",
|
|
@@ -1043,9 +1267,9 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1043
1267
|
},
|
|
1044
1268
|
t.id
|
|
1045
1269
|
)) }),
|
|
1046
|
-
/* @__PURE__ */
|
|
1047
|
-
/* @__PURE__ */
|
|
1048
|
-
/* @__PURE__ */
|
|
1270
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
|
|
1271
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1", children: [
|
|
1272
|
+
/* @__PURE__ */ jsx7(
|
|
1049
1273
|
"input",
|
|
1050
1274
|
{
|
|
1051
1275
|
type: "color",
|
|
@@ -1055,10 +1279,10 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1055
1279
|
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
1056
1280
|
}
|
|
1057
1281
|
),
|
|
1058
|
-
/* @__PURE__ */
|
|
1282
|
+
/* @__PURE__ */ jsx7("span", { className: "text-slate-400", children: "FG" })
|
|
1059
1283
|
] }),
|
|
1060
|
-
/* @__PURE__ */
|
|
1061
|
-
/* @__PURE__ */
|
|
1284
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1", children: [
|
|
1285
|
+
/* @__PURE__ */ jsx7(
|
|
1062
1286
|
"input",
|
|
1063
1287
|
{
|
|
1064
1288
|
type: "color",
|
|
@@ -1068,12 +1292,12 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1068
1292
|
className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
|
|
1069
1293
|
}
|
|
1070
1294
|
),
|
|
1071
|
-
/* @__PURE__ */
|
|
1295
|
+
/* @__PURE__ */ jsx7("span", { className: "text-slate-400", children: "BG" })
|
|
1072
1296
|
] }),
|
|
1073
|
-
/* @__PURE__ */
|
|
1074
|
-
/* @__PURE__ */
|
|
1297
|
+
/* @__PURE__ */ jsx7("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
|
|
1298
|
+
/* @__PURE__ */ jsx7("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" })
|
|
1075
1299
|
] }),
|
|
1076
|
-
BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */
|
|
1300
|
+
BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ jsx7(
|
|
1077
1301
|
ControlSlider,
|
|
1078
1302
|
{
|
|
1079
1303
|
spec,
|
|
@@ -1082,9 +1306,9 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1082
1306
|
},
|
|
1083
1307
|
spec.id
|
|
1084
1308
|
)),
|
|
1085
|
-
state.activeTool === "mixer" && /* @__PURE__ */
|
|
1086
|
-
/* @__PURE__ */
|
|
1087
|
-
/* @__PURE__ */
|
|
1309
|
+
state.activeTool === "mixer" && /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Mixer Brush", "data-testid": "mixer-options", children: [
|
|
1310
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
|
|
1311
|
+
/* @__PURE__ */ jsx7(
|
|
1088
1312
|
"span",
|
|
1089
1313
|
{
|
|
1090
1314
|
"aria-label": "Brush load",
|
|
@@ -1093,10 +1317,10 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1093
1317
|
style: { background: mixerLoad.reservoir ? rgbUnitToHex(mixerLoad.reservoir) : "transparent" }
|
|
1094
1318
|
}
|
|
1095
1319
|
),
|
|
1096
|
-
/* @__PURE__ */
|
|
1097
|
-
/* @__PURE__ */
|
|
1320
|
+
/* @__PURE__ */ jsx7("button", { type: "button", title: "Fill the reservoir with the foreground colour", className: chip(false), onClick: () => controller.loadMixerBrush(), children: "Load brush" }),
|
|
1321
|
+
/* @__PURE__ */ jsx7("button", { type: "button", title: "Empty the picked-up colour", className: chip(false), onClick: () => controller.cleanMixerBrush(), children: "Clean brush" })
|
|
1098
1322
|
] }),
|
|
1099
|
-
/* @__PURE__ */
|
|
1323
|
+
/* @__PURE__ */ jsx7("div", { className: "flex gap-1", role: "group", "aria-label": "Mixing", children: MIXER_MIXING_OPTIONS.map((m) => /* @__PURE__ */ jsx7(
|
|
1100
1324
|
"button",
|
|
1101
1325
|
{
|
|
1102
1326
|
type: "button",
|
|
@@ -1108,10 +1332,10 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1108
1332
|
},
|
|
1109
1333
|
m.id
|
|
1110
1334
|
)) }),
|
|
1111
|
-
MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */
|
|
1112
|
-
/* @__PURE__ */
|
|
1113
|
-
/* @__PURE__ */
|
|
1114
|
-
/* @__PURE__ */
|
|
1335
|
+
MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ jsx7(ControlSlider, { spec, value: mixer[spec.id], onChange: (v) => controller.setPaintOptions({ mixer: { [spec.id]: v } }) }, spec.id)),
|
|
1336
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap gap-3 text-slate-300", children: [
|
|
1337
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1.5", children: [
|
|
1338
|
+
/* @__PURE__ */ jsx7(
|
|
1115
1339
|
"input",
|
|
1116
1340
|
{
|
|
1117
1341
|
type: "checkbox",
|
|
@@ -1123,8 +1347,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1123
1347
|
),
|
|
1124
1348
|
"Load each stroke"
|
|
1125
1349
|
] }),
|
|
1126
|
-
/* @__PURE__ */
|
|
1127
|
-
/* @__PURE__ */
|
|
1350
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1.5", children: [
|
|
1351
|
+
/* @__PURE__ */ jsx7(
|
|
1128
1352
|
"input",
|
|
1129
1353
|
{
|
|
1130
1354
|
type: "checkbox",
|
|
@@ -1138,9 +1362,9 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1138
1362
|
] })
|
|
1139
1363
|
] })
|
|
1140
1364
|
] }),
|
|
1141
|
-
/* @__PURE__ */
|
|
1142
|
-
/* @__PURE__ */
|
|
1143
|
-
/* @__PURE__ */
|
|
1365
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
|
|
1366
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1.5", children: [
|
|
1367
|
+
/* @__PURE__ */ jsx7(
|
|
1144
1368
|
"input",
|
|
1145
1369
|
{
|
|
1146
1370
|
type: "checkbox",
|
|
@@ -1152,8 +1376,8 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1152
1376
|
),
|
|
1153
1377
|
"Pressure size"
|
|
1154
1378
|
] }),
|
|
1155
|
-
/* @__PURE__ */
|
|
1156
|
-
/* @__PURE__ */
|
|
1379
|
+
/* @__PURE__ */ jsxs7("label", { className: "flex items-center gap-1.5", children: [
|
|
1380
|
+
/* @__PURE__ */ jsx7(
|
|
1157
1381
|
"input",
|
|
1158
1382
|
{
|
|
1159
1383
|
type: "checkbox",
|
|
@@ -1166,23 +1390,23 @@ var BrushOptionsBar = ({ controller, className }) => {
|
|
|
1166
1390
|
"Pressure opacity"
|
|
1167
1391
|
] })
|
|
1168
1392
|
] }),
|
|
1169
|
-
/* @__PURE__ */
|
|
1170
|
-
/* @__PURE__ */
|
|
1171
|
-
/* @__PURE__ */
|
|
1393
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex gap-1", children: [
|
|
1394
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
|
|
1395
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
|
|
1172
1396
|
] }),
|
|
1173
|
-
error && /* @__PURE__ */
|
|
1397
|
+
error && /* @__PURE__ */ jsx7("p", { role: "alert", className: "text-rose-400", children: error })
|
|
1174
1398
|
] });
|
|
1175
1399
|
};
|
|
1176
1400
|
|
|
1177
1401
|
// src/image-editor/SelectionOptionsBar.tsx
|
|
1178
|
-
import { useState as
|
|
1402
|
+
import { useState as useState8 } from "react";
|
|
1179
1403
|
import {
|
|
1180
1404
|
SELECTION_MODES,
|
|
1181
1405
|
SELECTION_MODE_LABELS,
|
|
1182
1406
|
SELECTION_TOOLS,
|
|
1183
1407
|
describeSelection
|
|
1184
1408
|
} from "@pixerate/editor/image-editor";
|
|
1185
|
-
import { jsx as
|
|
1409
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1186
1410
|
var MODIFY_OPS = [
|
|
1187
1411
|
{ op: "grow", label: "Grow" },
|
|
1188
1412
|
{ op: "shrink", label: "Shrink" },
|
|
@@ -1199,20 +1423,20 @@ var SelectionOptionsBar = ({
|
|
|
1199
1423
|
quickMask,
|
|
1200
1424
|
className = ""
|
|
1201
1425
|
}) => {
|
|
1202
|
-
const [radius, setRadius] =
|
|
1426
|
+
const [radius, setRadius] = useState8(2);
|
|
1203
1427
|
const set = (patch) => onOptionsChange({ ...options, ...patch });
|
|
1204
1428
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
1205
1429
|
const qm = quickMask ?? Boolean(controller.getState().quickMask);
|
|
1206
|
-
return /* @__PURE__ */
|
|
1207
|
-
/* @__PURE__ */
|
|
1208
|
-
/* @__PURE__ */
|
|
1209
|
-
options.tool === "wand" && /* @__PURE__ */
|
|
1210
|
-
/* @__PURE__ */
|
|
1211
|
-
/* @__PURE__ */
|
|
1212
|
-
/* @__PURE__ */
|
|
1213
|
-
/* @__PURE__ */
|
|
1430
|
+
return /* @__PURE__ */ jsxs8("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
1431
|
+
/* @__PURE__ */ jsx8("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: SELECTION_TOOLS.map((t) => /* @__PURE__ */ jsx8("button", { type: "button", "aria-pressed": options.tool === t.id, className: btn(options.tool === t.id), onClick: () => set({ tool: t.id }), children: t.label }, t.id)) }),
|
|
1432
|
+
/* @__PURE__ */ jsx8("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: SELECTION_MODES.map((m) => /* @__PURE__ */ jsx8("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: SELECTION_MODE_LABELS[m] }, m)) }),
|
|
1433
|
+
options.tool === "wand" && /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-2", children: [
|
|
1434
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex flex-col gap-1", children: [
|
|
1435
|
+
/* @__PURE__ */ jsxs8("span", { className: "flex justify-between text-slate-400", children: [
|
|
1436
|
+
/* @__PURE__ */ jsx8("span", { children: "Tolerance" }),
|
|
1437
|
+
/* @__PURE__ */ jsx8("span", { className: "font-mono", children: options.tolerance })
|
|
1214
1438
|
] }),
|
|
1215
|
-
/* @__PURE__ */
|
|
1439
|
+
/* @__PURE__ */ jsx8(
|
|
1216
1440
|
"input",
|
|
1217
1441
|
{
|
|
1218
1442
|
type: "range",
|
|
@@ -1226,17 +1450,17 @@ var SelectionOptionsBar = ({
|
|
|
1226
1450
|
}
|
|
1227
1451
|
)
|
|
1228
1452
|
] }),
|
|
1229
|
-
/* @__PURE__ */
|
|
1230
|
-
/* @__PURE__ */
|
|
1453
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1454
|
+
/* @__PURE__ */ jsx8("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
|
|
1231
1455
|
"Contiguous"
|
|
1232
1456
|
] }),
|
|
1233
|
-
/* @__PURE__ */
|
|
1234
|
-
/* @__PURE__ */
|
|
1457
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1458
|
+
/* @__PURE__ */ jsx8("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
|
|
1235
1459
|
"Sample adjusted image"
|
|
1236
1460
|
] }),
|
|
1237
|
-
/* @__PURE__ */
|
|
1461
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1238
1462
|
"Sample",
|
|
1239
|
-
/* @__PURE__ */
|
|
1463
|
+
/* @__PURE__ */ jsxs8(
|
|
1240
1464
|
"select",
|
|
1241
1465
|
{
|
|
1242
1466
|
"aria-label": "Sample from",
|
|
@@ -1244,27 +1468,27 @@ var SelectionOptionsBar = ({
|
|
|
1244
1468
|
onChange: (e) => set({ sample: e.target.value }),
|
|
1245
1469
|
className: "bg-slate-800 border border-slate-700 rounded px-1 py-0.5",
|
|
1246
1470
|
children: [
|
|
1247
|
-
/* @__PURE__ */
|
|
1248
|
-
/* @__PURE__ */
|
|
1471
|
+
/* @__PURE__ */ jsx8("option", { value: "composite", children: "All layers" }),
|
|
1472
|
+
/* @__PURE__ */ jsx8("option", { value: "active-layer", children: "Active layer" })
|
|
1249
1473
|
]
|
|
1250
1474
|
}
|
|
1251
1475
|
)
|
|
1252
1476
|
] })
|
|
1253
1477
|
] }),
|
|
1254
|
-
/* @__PURE__ */
|
|
1255
|
-
/* @__PURE__ */
|
|
1478
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1479
|
+
/* @__PURE__ */ jsx8("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
|
|
1256
1480
|
"Anti-alias"
|
|
1257
1481
|
] }),
|
|
1258
|
-
/* @__PURE__ */
|
|
1259
|
-
/* @__PURE__ */
|
|
1260
|
-
/* @__PURE__ */
|
|
1261
|
-
/* @__PURE__ */
|
|
1262
|
-
/* @__PURE__ */
|
|
1482
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex flex-wrap gap-1", children: [
|
|
1483
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
|
|
1484
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
|
|
1485
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
|
|
1486
|
+
/* @__PURE__ */ jsx8("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
|
|
1263
1487
|
] }),
|
|
1264
|
-
/* @__PURE__ */
|
|
1265
|
-
/* @__PURE__ */
|
|
1488
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
1489
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex items-center gap-1 text-slate-400", children: [
|
|
1266
1490
|
"Radius",
|
|
1267
|
-
/* @__PURE__ */
|
|
1491
|
+
/* @__PURE__ */ jsx8(
|
|
1268
1492
|
"input",
|
|
1269
1493
|
{
|
|
1270
1494
|
type: "number",
|
|
@@ -1278,29 +1502,29 @@ var SelectionOptionsBar = ({
|
|
|
1278
1502
|
}
|
|
1279
1503
|
)
|
|
1280
1504
|
] }),
|
|
1281
|
-
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */
|
|
1505
|
+
MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ jsx8("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
|
|
1282
1506
|
] }),
|
|
1283
|
-
/* @__PURE__ */
|
|
1507
|
+
/* @__PURE__ */ jsx8("p", { "data-testid": "selection-status", className: "text-slate-400", children: describeSelection(sel) })
|
|
1284
1508
|
] });
|
|
1285
1509
|
};
|
|
1286
1510
|
|
|
1287
1511
|
// src/image-editor/RefineEdgePanel.tsx
|
|
1288
|
-
import { useState as
|
|
1512
|
+
import { useState as useState9 } from "react";
|
|
1289
1513
|
import {
|
|
1290
1514
|
ADJUSTMENT_KINDS as ADJUSTMENT_KINDS2,
|
|
1291
1515
|
REFINE_EDGE_CONTROLS,
|
|
1292
1516
|
adjustmentKindLabel as adjustmentKindLabel2,
|
|
1293
1517
|
layerMaskFromSelection
|
|
1294
1518
|
} from "@pixerate/editor/image-editor";
|
|
1295
|
-
import { Fragment as Fragment2, jsx as
|
|
1519
|
+
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1296
1520
|
var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
|
|
1297
|
-
var
|
|
1521
|
+
var button2 = "px-2 py-1 rounded-md border border-slate-800 bg-slate-950 text-[11px] text-slate-200 hover:text-white disabled:opacity-40";
|
|
1298
1522
|
var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
1299
|
-
const [params, setParams] =
|
|
1300
|
-
const [busy, setBusy] =
|
|
1301
|
-
const [error, setError] =
|
|
1302
|
-
const [layerId, setLayerId] =
|
|
1303
|
-
const [newKind, setNewKind] =
|
|
1523
|
+
const [params, setParams] = useState9(DEFAULT_PARAMS);
|
|
1524
|
+
const [busy, setBusy] = useState9(false);
|
|
1525
|
+
const [error, setError] = useState9(null);
|
|
1526
|
+
const [layerId, setLayerId] = useState9("");
|
|
1527
|
+
const [newKind, setNewKind] = useState9("hueSaturation");
|
|
1304
1528
|
const sel = selection === void 0 ? controller.getSelection() : selection;
|
|
1305
1529
|
const list = layers ?? controller.getAdjustmentLayers();
|
|
1306
1530
|
const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
|
|
@@ -1315,17 +1539,17 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1315
1539
|
setBusy(false);
|
|
1316
1540
|
}
|
|
1317
1541
|
};
|
|
1318
|
-
return /* @__PURE__ */
|
|
1319
|
-
/* @__PURE__ */
|
|
1320
|
-
REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */
|
|
1321
|
-
/* @__PURE__ */
|
|
1322
|
-
/* @__PURE__ */
|
|
1323
|
-
/* @__PURE__ */
|
|
1542
|
+
return /* @__PURE__ */ jsxs9("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
|
|
1543
|
+
/* @__PURE__ */ jsx9("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
|
|
1544
|
+
REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ jsxs9("label", { className: "flex flex-col gap-1", children: [
|
|
1545
|
+
/* @__PURE__ */ jsxs9("span", { className: "flex justify-between text-slate-400", children: [
|
|
1546
|
+
/* @__PURE__ */ jsx9("span", { children: c.label }),
|
|
1547
|
+
/* @__PURE__ */ jsxs9("span", { className: "font-mono", children: [
|
|
1324
1548
|
params[c.id],
|
|
1325
1549
|
c.unit
|
|
1326
1550
|
] })
|
|
1327
1551
|
] }),
|
|
1328
|
-
/* @__PURE__ */
|
|
1552
|
+
/* @__PURE__ */ jsx9(
|
|
1329
1553
|
"input",
|
|
1330
1554
|
{
|
|
1331
1555
|
type: "range",
|
|
@@ -1339,67 +1563,67 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1339
1563
|
}
|
|
1340
1564
|
)
|
|
1341
1565
|
] }, c.id)),
|
|
1342
|
-
/* @__PURE__ */
|
|
1343
|
-
/* @__PURE__ */
|
|
1566
|
+
/* @__PURE__ */ jsxs9("label", { className: "flex items-center gap-2 text-slate-300", children: [
|
|
1567
|
+
/* @__PURE__ */ jsx9("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
|
|
1344
1568
|
"Smart Radius"
|
|
1345
1569
|
] }),
|
|
1346
|
-
/* @__PURE__ */
|
|
1347
|
-
/* @__PURE__ */
|
|
1348
|
-
/* @__PURE__ */
|
|
1570
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex gap-1", children: [
|
|
1571
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: button2, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
|
|
1572
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: button2, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
|
|
1349
1573
|
] }),
|
|
1350
|
-
error && /* @__PURE__ */
|
|
1351
|
-
/* @__PURE__ */
|
|
1352
|
-
/* @__PURE__ */
|
|
1353
|
-
/* @__PURE__ */
|
|
1574
|
+
error && /* @__PURE__ */ jsx9("p", { role: "alert", className: "text-rose-400", children: error }),
|
|
1575
|
+
/* @__PURE__ */ jsx9("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
|
|
1576
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex gap-1 items-center", children: [
|
|
1577
|
+
/* @__PURE__ */ jsx9(
|
|
1354
1578
|
"select",
|
|
1355
1579
|
{
|
|
1356
1580
|
"aria-label": "New masked layer kind",
|
|
1357
1581
|
value: newKind,
|
|
1358
1582
|
onChange: (e) => setNewKind(e.target.value),
|
|
1359
1583
|
className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
1360
|
-
children: ADJUSTMENT_KINDS2.map((k) => /* @__PURE__ */
|
|
1584
|
+
children: ADJUSTMENT_KINDS2.map((k) => /* @__PURE__ */ jsx9("option", { value: k.kind, children: k.label }, k.kind))
|
|
1361
1585
|
}
|
|
1362
1586
|
),
|
|
1363
|
-
/* @__PURE__ */
|
|
1587
|
+
/* @__PURE__ */ jsx9(
|
|
1364
1588
|
"button",
|
|
1365
1589
|
{
|
|
1366
1590
|
type: "button",
|
|
1367
|
-
className:
|
|
1591
|
+
className: button2,
|
|
1368
1592
|
disabled: !sel,
|
|
1369
1593
|
onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: layerMaskFromSelection(sel) })),
|
|
1370
1594
|
children: "New Masked Layer"
|
|
1371
1595
|
}
|
|
1372
1596
|
)
|
|
1373
1597
|
] }),
|
|
1374
|
-
list.length > 0 && target && /* @__PURE__ */
|
|
1375
|
-
/* @__PURE__ */
|
|
1598
|
+
list.length > 0 && target && /* @__PURE__ */ jsxs9("div", { className: "flex flex-col gap-2", children: [
|
|
1599
|
+
/* @__PURE__ */ jsx9(
|
|
1376
1600
|
"select",
|
|
1377
1601
|
{
|
|
1378
1602
|
"aria-label": "Mask layer",
|
|
1379
1603
|
value: target.id,
|
|
1380
1604
|
onChange: (e) => setLayerId(e.target.value),
|
|
1381
1605
|
className: "bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
|
|
1382
|
-
children: list.map((l) => /* @__PURE__ */
|
|
1606
|
+
children: list.map((l) => /* @__PURE__ */ jsxs9("option", { value: l.id, children: [
|
|
1383
1607
|
l.name || adjustmentKindLabel2(l.kind),
|
|
1384
1608
|
l.mask ? " (masked)" : ""
|
|
1385
1609
|
] }, l.id))
|
|
1386
1610
|
}
|
|
1387
1611
|
),
|
|
1388
|
-
/* @__PURE__ */
|
|
1389
|
-
/* @__PURE__ */
|
|
1390
|
-
/* @__PURE__ */
|
|
1391
|
-
/* @__PURE__ */
|
|
1612
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex flex-wrap gap-1", children: [
|
|
1613
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: button2, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
|
|
1614
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
|
|
1615
|
+
/* @__PURE__ */ jsx9("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
|
|
1392
1616
|
] }),
|
|
1393
|
-
target.mask && /* @__PURE__ */
|
|
1394
|
-
/* @__PURE__ */
|
|
1395
|
-
/* @__PURE__ */
|
|
1396
|
-
/* @__PURE__ */
|
|
1397
|
-
/* @__PURE__ */
|
|
1617
|
+
target.mask && /* @__PURE__ */ jsxs9(Fragment2, { children: [
|
|
1618
|
+
/* @__PURE__ */ jsxs9("label", { className: "flex flex-col gap-1", children: [
|
|
1619
|
+
/* @__PURE__ */ jsxs9("span", { className: "flex justify-between text-slate-400", children: [
|
|
1620
|
+
/* @__PURE__ */ jsx9("span", { children: "Density" }),
|
|
1621
|
+
/* @__PURE__ */ jsxs9("span", { className: "font-mono", children: [
|
|
1398
1622
|
Math.round((target.mask.density ?? 1) * 100),
|
|
1399
1623
|
"%"
|
|
1400
1624
|
] })
|
|
1401
1625
|
] }),
|
|
1402
|
-
/* @__PURE__ */
|
|
1626
|
+
/* @__PURE__ */ jsx9(
|
|
1403
1627
|
"input",
|
|
1404
1628
|
{
|
|
1405
1629
|
type: "range",
|
|
@@ -1413,15 +1637,15 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1413
1637
|
}
|
|
1414
1638
|
)
|
|
1415
1639
|
] }),
|
|
1416
|
-
/* @__PURE__ */
|
|
1417
|
-
/* @__PURE__ */
|
|
1418
|
-
/* @__PURE__ */
|
|
1419
|
-
/* @__PURE__ */
|
|
1640
|
+
/* @__PURE__ */ jsxs9("label", { className: "flex flex-col gap-1", children: [
|
|
1641
|
+
/* @__PURE__ */ jsxs9("span", { className: "flex justify-between text-slate-400", children: [
|
|
1642
|
+
/* @__PURE__ */ jsx9("span", { children: "Mask Feather" }),
|
|
1643
|
+
/* @__PURE__ */ jsxs9("span", { className: "font-mono", children: [
|
|
1420
1644
|
target.mask.feather ?? 0,
|
|
1421
1645
|
"px"
|
|
1422
1646
|
] })
|
|
1423
1647
|
] }),
|
|
1424
|
-
/* @__PURE__ */
|
|
1648
|
+
/* @__PURE__ */ jsx9(
|
|
1425
1649
|
"input",
|
|
1426
1650
|
{
|
|
1427
1651
|
type: "range",
|
|
@@ -1440,8 +1664,83 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
|
|
|
1440
1664
|
] });
|
|
1441
1665
|
};
|
|
1442
1666
|
|
|
1667
|
+
// src/image-editor/FreeTransformOptionsBar.tsx
|
|
1668
|
+
import { useEffect as useEffect7, useState as useState10 } from "react";
|
|
1669
|
+
import { FREE_TRANSFORM_FIELDS, FREE_TRANSFORM_MODE_OPTIONS, INTERPOLATIONS, TRANSFORM_ANCHORS } from "@pixerate/editor/image-editor";
|
|
1670
|
+
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1671
|
+
var chip2 = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
|
|
1672
|
+
var round = (v, unit) => unit === "px" ? Math.round(v * 10) / 10 : Math.round(v * 100) / 100;
|
|
1673
|
+
var FreeTransformOptionsBar = ({ tool, className }) => {
|
|
1674
|
+
const [, setTick] = useState10(0);
|
|
1675
|
+
useEffect7(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
|
|
1676
|
+
const bar = tool.bar();
|
|
1677
|
+
if (!tool.active || !bar) return null;
|
|
1678
|
+
const apply = (field, raw) => {
|
|
1679
|
+
const v = Number(raw);
|
|
1680
|
+
if (raw.trim() !== "" && Number.isFinite(v) && Math.abs(v - bar[field]) > 1e-9) tool.setField(field, v);
|
|
1681
|
+
};
|
|
1682
|
+
return /* @__PURE__ */ jsxs10("div", { className: `flex flex-wrap items-center gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "free-transform-options", role: "toolbar", "aria-label": "Free Transform options", children: [
|
|
1683
|
+
/* @__PURE__ */ jsx10("div", { className: "flex gap-1", role: "group", "aria-label": "Transform mode", children: FREE_TRANSFORM_MODE_OPTIONS.map((m) => /* @__PURE__ */ jsx10("button", { type: "button", title: m.title, "aria-pressed": tool.mode === m.id, className: chip2(tool.mode === m.id), onClick: () => tool.setMode(m.id), children: m.label }, m.id)) }),
|
|
1684
|
+
/* @__PURE__ */ jsx10("div", { className: "grid grid-cols-3 gap-px", role: "group", "aria-label": "Reference point", children: TRANSFORM_ANCHORS.map((a) => /* @__PURE__ */ jsx10("button", { type: "button", "aria-label": `Reference point ${a}`, title: `Reference point: ${a}`, className: "h-2.5 w-2.5 rounded-sm bg-slate-700 hover:bg-indigo-500", onClick: () => tool.setReference(a) }, a)) }),
|
|
1685
|
+
FREE_TRANSFORM_FIELDS.map((f) => /* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-1", title: f.title, children: [
|
|
1686
|
+
/* @__PURE__ */ jsx10("span", { className: "text-slate-400", children: f.label }),
|
|
1687
|
+
/* @__PURE__ */ jsx10(
|
|
1688
|
+
"input",
|
|
1689
|
+
{
|
|
1690
|
+
type: "number",
|
|
1691
|
+
"aria-label": f.title,
|
|
1692
|
+
defaultValue: round(bar[f.id], f.unit),
|
|
1693
|
+
disabled: !bar.affine,
|
|
1694
|
+
step: f.unit === "px" ? 1 : 0.1,
|
|
1695
|
+
className: "w-16 rounded border border-slate-700 bg-slate-900 px-1 py-0.5 text-right disabled:opacity-40",
|
|
1696
|
+
onBlur: (e) => apply(f.id, e.currentTarget.value),
|
|
1697
|
+
onKeyDown: (e) => {
|
|
1698
|
+
if (e.key === "Enter") {
|
|
1699
|
+
e.preventDefault();
|
|
1700
|
+
e.stopPropagation();
|
|
1701
|
+
apply(f.id, e.currentTarget.value);
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
},
|
|
1705
|
+
`${f.id}:${round(bar[f.id], f.unit)}`
|
|
1706
|
+
),
|
|
1707
|
+
/* @__PURE__ */ jsx10("span", { className: "text-slate-500", children: f.unit }),
|
|
1708
|
+
f.id === "scaleX" && /* @__PURE__ */ jsx10(
|
|
1709
|
+
"button",
|
|
1710
|
+
{
|
|
1711
|
+
type: "button",
|
|
1712
|
+
"aria-label": "Keep width and height proportional",
|
|
1713
|
+
"aria-pressed": tool.proportional,
|
|
1714
|
+
className: chip2(tool.proportional),
|
|
1715
|
+
onClick: () => {
|
|
1716
|
+
tool.proportional = !tool.proportional;
|
|
1717
|
+
setTick((n) => n + 1);
|
|
1718
|
+
},
|
|
1719
|
+
children: "\u26D3\uFE0E"
|
|
1720
|
+
}
|
|
1721
|
+
)
|
|
1722
|
+
] }, f.id)),
|
|
1723
|
+
/* @__PURE__ */ jsxs10("label", { className: "flex items-center gap-1", children: [
|
|
1724
|
+
/* @__PURE__ */ jsx10("span", { className: "text-slate-400", children: "Interpolation" }),
|
|
1725
|
+
/* @__PURE__ */ jsx10(
|
|
1726
|
+
"select",
|
|
1727
|
+
{
|
|
1728
|
+
"aria-label": "Interpolation",
|
|
1729
|
+
value: tool.interpolation,
|
|
1730
|
+
onChange: (e) => tool.setInterpolation(e.target.value),
|
|
1731
|
+
className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
|
|
1732
|
+
children: INTERPOLATIONS.map((i) => /* @__PURE__ */ jsx10("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
|
|
1733
|
+
}
|
|
1734
|
+
)
|
|
1735
|
+
] }),
|
|
1736
|
+
/* @__PURE__ */ jsx10("button", { type: "button", title: "Commit (Enter)", className: "px-2 py-1 rounded bg-emerald-600 text-white hover:bg-emerald-500", onClick: () => tool.commit(), children: "Commit" }),
|
|
1737
|
+
/* @__PURE__ */ jsx10("button", { type: "button", title: "Cancel (Esc)", className: chip2(false), onClick: () => tool.cancel(), children: "Cancel" }),
|
|
1738
|
+
tool.error && /* @__PURE__ */ jsx10("span", { role: "alert", className: "text-rose-400", children: tool.error })
|
|
1739
|
+
] });
|
|
1740
|
+
};
|
|
1741
|
+
|
|
1443
1742
|
// src/image-editor/ImageEditor.tsx
|
|
1444
|
-
import { Fragment as Fragment3, jsx as
|
|
1743
|
+
import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1445
1744
|
var ImageEditor = ({
|
|
1446
1745
|
editor: externalEditor,
|
|
1447
1746
|
src,
|
|
@@ -1457,34 +1756,46 @@ var ImageEditor = ({
|
|
|
1457
1756
|
const editor = externalEditor || internalEditor;
|
|
1458
1757
|
const { state, controller } = editor;
|
|
1459
1758
|
const legacyProcess = normalizeProcessVersion(state.adjustments.process) < LATEST_PROCESS_VERSION;
|
|
1460
|
-
const canvasRef =
|
|
1461
|
-
const containerRef =
|
|
1462
|
-
const [activeTab, setActiveTab] =
|
|
1463
|
-
const [activeCropRatio, setActiveCropRatio] =
|
|
1464
|
-
const [selectionOptions, setSelectionOptions] =
|
|
1465
|
-
const selectionOptionsRef =
|
|
1759
|
+
const canvasRef = useRef5(null);
|
|
1760
|
+
const containerRef = useRef5(null);
|
|
1761
|
+
const [activeTab, setActiveTab] = useState11("crop");
|
|
1762
|
+
const [activeCropRatio, setActiveCropRatio] = useState11(null);
|
|
1763
|
+
const [selectionOptions, setSelectionOptions] = useState11(DEFAULT_SELECTION_TOOL_OPTIONS);
|
|
1764
|
+
const selectionOptionsRef = useRef5(selectionOptions);
|
|
1466
1765
|
selectionOptionsRef.current = selectionOptions;
|
|
1467
|
-
const selectionGestureRef =
|
|
1766
|
+
const selectionGestureRef = useRef5(null);
|
|
1468
1767
|
if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
|
|
1469
1768
|
selectionGestureRef.current = new SelectionGesture(controller, () => selectionOptionsRef.current);
|
|
1470
1769
|
}
|
|
1471
|
-
const selectionDraftRef =
|
|
1472
|
-
const [selectionError, setSelectionError] =
|
|
1473
|
-
const paintGestureRef =
|
|
1474
|
-
const paintControllerRef =
|
|
1770
|
+
const selectionDraftRef = useRef5(null);
|
|
1771
|
+
const [selectionError, setSelectionError] = useState11(null);
|
|
1772
|
+
const paintGestureRef = useRef5(null);
|
|
1773
|
+
const paintControllerRef = useRef5(controller);
|
|
1475
1774
|
if (!paintGestureRef.current || paintControllerRef.current !== controller) {
|
|
1476
1775
|
paintGestureRef.current = new PaintGesture(controller);
|
|
1477
1776
|
paintControllerRef.current = controller;
|
|
1478
1777
|
}
|
|
1479
|
-
const brushCursorRef =
|
|
1480
|
-
const [paintError, setPaintError] =
|
|
1481
|
-
const
|
|
1482
|
-
const
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1778
|
+
const brushCursorRef = useRef5(null);
|
|
1779
|
+
const [paintError, setPaintError] = useState11(null);
|
|
1780
|
+
const transformToolRef = useRef5(null);
|
|
1781
|
+
const transformControllerRef = useRef5(controller);
|
|
1782
|
+
if (!transformToolRef.current || transformControllerRef.current !== controller) {
|
|
1783
|
+
transformToolRef.current?.cancel();
|
|
1784
|
+
transformToolRef.current = new FreeTransformTool(controller, {
|
|
1785
|
+
schedule: (run) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(run) : run()
|
|
1786
|
+
});
|
|
1787
|
+
transformControllerRef.current = controller;
|
|
1788
|
+
}
|
|
1789
|
+
const transformTool = transformToolRef.current;
|
|
1790
|
+
const [, setTransformTick] = useState11(0);
|
|
1791
|
+
const [transformCursor, setTransformCursor] = useState11("default");
|
|
1792
|
+
const [inpaintPrompt, setInpaintPrompt] = useState11("");
|
|
1793
|
+
const [inpaintMaskMode, setInpaintMaskMode] = useState11("annotations");
|
|
1794
|
+
const [isRemovingBg, setIsRemovingBg] = useState11(false);
|
|
1795
|
+
const [isInpainting, setIsInpainting] = useState11(false);
|
|
1796
|
+
const [aiError, setAiError] = useState11(null);
|
|
1797
|
+
const [aiSuccess, setAiSuccess] = useState11(null);
|
|
1798
|
+
const [aiTarget, setAiTarget] = useState11("auto");
|
|
1488
1799
|
const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
|
|
1489
1800
|
const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
|
|
1490
1801
|
const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
|
|
@@ -1547,17 +1858,17 @@ var ImageEditor = ({
|
|
|
1547
1858
|
setIsInpainting(false);
|
|
1548
1859
|
}
|
|
1549
1860
|
};
|
|
1550
|
-
const [activeColor, setActiveColor] =
|
|
1551
|
-
const [strokeWidth, setStrokeWidth] =
|
|
1552
|
-
const [fontSize, setFontSize] =
|
|
1553
|
-
const [textInput, setTextInput] =
|
|
1554
|
-
const draftAnnotationRef =
|
|
1555
|
-
const draftCropRef =
|
|
1556
|
-
const cropDragInfoRef =
|
|
1557
|
-
const annotationDragInfoRef =
|
|
1558
|
-
const isDrawingRef =
|
|
1559
|
-
const currentPathRef =
|
|
1560
|
-
const dragStartPointRef =
|
|
1861
|
+
const [activeColor, setActiveColor] = useState11("#ef4444");
|
|
1862
|
+
const [strokeWidth, setStrokeWidth] = useState11(3);
|
|
1863
|
+
const [fontSize, setFontSize] = useState11(24);
|
|
1864
|
+
const [textInput, setTextInput] = useState11("");
|
|
1865
|
+
const draftAnnotationRef = useRef5(null);
|
|
1866
|
+
const draftCropRef = useRef5(null);
|
|
1867
|
+
const cropDragInfoRef = useRef5(null);
|
|
1868
|
+
const annotationDragInfoRef = useRef5(null);
|
|
1869
|
+
const isDrawingRef = useRef5(false);
|
|
1870
|
+
const currentPathRef = useRef5([]);
|
|
1871
|
+
const dragStartPointRef = useRef5(null);
|
|
1561
1872
|
const renderCanvas = useCallback2(
|
|
1562
1873
|
async (draftAnnotation, draftCrop) => {
|
|
1563
1874
|
const canvas = canvasRef.current;
|
|
@@ -1574,12 +1885,64 @@ var ImageEditor = ({
|
|
|
1574
1885
|
draftAnnotation: draftAnnotation !== void 0 ? draftAnnotation : draftAnnotationRef.current,
|
|
1575
1886
|
draftCrop: draftCrop !== void 0 ? draftCrop : draftCropRef.current,
|
|
1576
1887
|
draftSelectionPath: selectionDraftRef.current,
|
|
1577
|
-
brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null
|
|
1888
|
+
brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" && !transformTool.active ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null,
|
|
1889
|
+
freeTransform: transformTool.overlay()
|
|
1578
1890
|
});
|
|
1579
1891
|
},
|
|
1580
|
-
[controller, activeTab]
|
|
1892
|
+
[controller, activeTab, transformTool]
|
|
1581
1893
|
);
|
|
1582
|
-
|
|
1894
|
+
useEffect8(() => transformTool.subscribe(() => {
|
|
1895
|
+
setTransformTick((n) => n + 1);
|
|
1896
|
+
void renderCanvas();
|
|
1897
|
+
}), [transformTool, renderCanvas]);
|
|
1898
|
+
const transformPoint = (e) => {
|
|
1899
|
+
const canvas = canvasRef.current;
|
|
1900
|
+
const rect = canvas.getBoundingClientRect();
|
|
1901
|
+
const sx = rect.width > 0 ? canvas.width / rect.width : 1;
|
|
1902
|
+
const sy = rect.height > 0 ? canvas.height / rect.height : 1;
|
|
1903
|
+
const s = controller.getState();
|
|
1904
|
+
const cropping = activeTab === "crop";
|
|
1905
|
+
const projection = getViewportProjection(s, canvas.width, canvas.height, cropping);
|
|
1906
|
+
const pt = canvasToImagePoint({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
|
|
1907
|
+
transformTool.setView(projection.scale);
|
|
1908
|
+
return { pt, tolerance: 6 / (projection.scale || 1) };
|
|
1909
|
+
};
|
|
1910
|
+
const handleTransformPointerDown = (e) => {
|
|
1911
|
+
if (!transformTool.active) return false;
|
|
1912
|
+
if (e.button !== 0) return true;
|
|
1913
|
+
e.preventDefault();
|
|
1914
|
+
try {
|
|
1915
|
+
e.currentTarget.setPointerCapture?.(e.pointerId);
|
|
1916
|
+
} catch {
|
|
1917
|
+
}
|
|
1918
|
+
const { pt, tolerance } = transformPoint(e);
|
|
1919
|
+
transformTool.down(pt, tolerance);
|
|
1920
|
+
return true;
|
|
1921
|
+
};
|
|
1922
|
+
const handleTransformPointerMove = (e) => {
|
|
1923
|
+
if (!transformTool.active) return false;
|
|
1924
|
+
const { pt, tolerance } = transformPoint(e);
|
|
1925
|
+
if (e.buttons & 1) transformTool.move(pt, e);
|
|
1926
|
+
else {
|
|
1927
|
+
const over = transformTool.hit(pt, tolerance);
|
|
1928
|
+
setTransformCursor(transformTool.cursor(over));
|
|
1929
|
+
}
|
|
1930
|
+
return true;
|
|
1931
|
+
};
|
|
1932
|
+
const handleTransformPointerUp = () => {
|
|
1933
|
+
if (!transformTool.active) return false;
|
|
1934
|
+
transformTool.up();
|
|
1935
|
+
return true;
|
|
1936
|
+
};
|
|
1937
|
+
useEffect8(() => {
|
|
1938
|
+
if (typeof window === "undefined") return;
|
|
1939
|
+
const onKey = (e) => {
|
|
1940
|
+
if (transformTool.key(e)) e.preventDefault();
|
|
1941
|
+
};
|
|
1942
|
+
window.addEventListener("keydown", onKey);
|
|
1943
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
1944
|
+
}, [transformTool]);
|
|
1945
|
+
useEffect8(() => {
|
|
1583
1946
|
const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
|
|
1584
1947
|
const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
|
|
1585
1948
|
const animId = raf(() => {
|
|
@@ -1587,12 +1950,12 @@ var ImageEditor = ({
|
|
|
1587
1950
|
});
|
|
1588
1951
|
return () => caf(animId);
|
|
1589
1952
|
}, [renderCanvas, state]);
|
|
1590
|
-
|
|
1953
|
+
useEffect8(() => {
|
|
1591
1954
|
if (activeTab === "crop" && editor.state.activeTool !== "crop") {
|
|
1592
1955
|
editor.setTool("crop");
|
|
1593
1956
|
}
|
|
1594
1957
|
}, [activeTab, editor]);
|
|
1595
|
-
|
|
1958
|
+
useEffect8(() => {
|
|
1596
1959
|
const container = containerRef.current;
|
|
1597
1960
|
if (!container) return;
|
|
1598
1961
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -1633,6 +1996,7 @@ var ImageEditor = ({
|
|
|
1633
1996
|
}));
|
|
1634
1997
|
};
|
|
1635
1998
|
const handlePaintPointerDown = (e) => {
|
|
1999
|
+
if (handleTransformPointerDown(e)) return;
|
|
1636
2000
|
if (activeTab !== "paint" || e.button !== 0) return;
|
|
1637
2001
|
e.preventDefault();
|
|
1638
2002
|
try {
|
|
@@ -1643,6 +2007,7 @@ var ImageEditor = ({
|
|
|
1643
2007
|
setPaintError(paintGestureRef.current.down(first));
|
|
1644
2008
|
};
|
|
1645
2009
|
const handlePaintPointerMove = (e) => {
|
|
2010
|
+
if (handleTransformPointerMove(e)) return;
|
|
1646
2011
|
if (activeTab !== "paint") return;
|
|
1647
2012
|
const samples = paintSamples(e);
|
|
1648
2013
|
brushCursorRef.current = samples[samples.length - 1] ?? null;
|
|
@@ -1650,6 +2015,7 @@ var ImageEditor = ({
|
|
|
1650
2015
|
else void renderCanvas();
|
|
1651
2016
|
};
|
|
1652
2017
|
const handlePaintPointerUp = () => {
|
|
2018
|
+
if (handleTransformPointerUp()) return;
|
|
1653
2019
|
if (activeTab !== "paint") return;
|
|
1654
2020
|
const g = paintGestureRef.current;
|
|
1655
2021
|
if (g.active) {
|
|
@@ -1657,7 +2023,7 @@ var ImageEditor = ({
|
|
|
1657
2023
|
if (g.error) setPaintError(g.error);
|
|
1658
2024
|
}
|
|
1659
2025
|
};
|
|
1660
|
-
|
|
2026
|
+
useEffect8(() => {
|
|
1661
2027
|
if (activeTab !== "paint" || typeof window === "undefined") return;
|
|
1662
2028
|
const onKey = (e) => {
|
|
1663
2029
|
if (handlePaintShortcut(controller, e)) e.preventDefault();
|
|
@@ -1667,7 +2033,7 @@ var ImageEditor = ({
|
|
|
1667
2033
|
}, [activeTab, controller]);
|
|
1668
2034
|
const handleMouseDown = (e) => {
|
|
1669
2035
|
const canvas = canvasRef.current;
|
|
1670
|
-
if (!canvas) return;
|
|
2036
|
+
if (!canvas || transformTool.active) return;
|
|
1671
2037
|
const canvasPt = getCanvasEventPoint(e);
|
|
1672
2038
|
if (activeTab === "select") {
|
|
1673
2039
|
const gesture = selectionGestureRef.current;
|
|
@@ -1739,7 +2105,7 @@ var ImageEditor = ({
|
|
|
1739
2105
|
};
|
|
1740
2106
|
const handleMouseMove = (e) => {
|
|
1741
2107
|
const canvas = canvasRef.current;
|
|
1742
|
-
if (!canvas) return;
|
|
2108
|
+
if (!canvas || transformTool.active) return;
|
|
1743
2109
|
const canvasPt = getCanvasEventPoint(e);
|
|
1744
2110
|
if (activeTab === "select") {
|
|
1745
2111
|
const gesture = selectionGestureRef.current;
|
|
@@ -1895,7 +2261,7 @@ var ImageEditor = ({
|
|
|
1895
2261
|
};
|
|
1896
2262
|
const handleMouseUp = (e) => {
|
|
1897
2263
|
const canvas = canvasRef.current;
|
|
1898
|
-
if (!canvas) return;
|
|
2264
|
+
if (!canvas || transformTool.active) return;
|
|
1899
2265
|
const canvasPt = getCanvasEventPoint(e);
|
|
1900
2266
|
if (activeTab === "select") {
|
|
1901
2267
|
const gesture = selectionGestureRef.current;
|
|
@@ -2020,15 +2386,15 @@ var ImageEditor = ({
|
|
|
2020
2386
|
link.click();
|
|
2021
2387
|
}
|
|
2022
2388
|
};
|
|
2023
|
-
return /* @__PURE__ */
|
|
2389
|
+
return /* @__PURE__ */ jsxs11(
|
|
2024
2390
|
"div",
|
|
2025
2391
|
{
|
|
2026
2392
|
className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
|
|
2027
2393
|
style,
|
|
2028
2394
|
children: [
|
|
2029
|
-
/* @__PURE__ */
|
|
2030
|
-
/* @__PURE__ */
|
|
2031
|
-
/* @__PURE__ */
|
|
2395
|
+
/* @__PURE__ */ jsxs11("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: [
|
|
2396
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
|
|
2397
|
+
/* @__PURE__ */ jsx11(
|
|
2032
2398
|
"button",
|
|
2033
2399
|
{
|
|
2034
2400
|
type: "button",
|
|
@@ -2040,7 +2406,7 @@ var ImageEditor = ({
|
|
|
2040
2406
|
children: "Transform & Crop"
|
|
2041
2407
|
}
|
|
2042
2408
|
),
|
|
2043
|
-
/* @__PURE__ */
|
|
2409
|
+
/* @__PURE__ */ jsx11(
|
|
2044
2410
|
"button",
|
|
2045
2411
|
{
|
|
2046
2412
|
type: "button",
|
|
@@ -2052,7 +2418,7 @@ var ImageEditor = ({
|
|
|
2052
2418
|
children: "Adjustments"
|
|
2053
2419
|
}
|
|
2054
2420
|
),
|
|
2055
|
-
/* @__PURE__ */
|
|
2421
|
+
/* @__PURE__ */ jsx11(
|
|
2056
2422
|
"button",
|
|
2057
2423
|
{
|
|
2058
2424
|
type: "button",
|
|
@@ -2064,7 +2430,7 @@ var ImageEditor = ({
|
|
|
2064
2430
|
children: "Layers"
|
|
2065
2431
|
}
|
|
2066
2432
|
),
|
|
2067
|
-
/* @__PURE__ */
|
|
2433
|
+
/* @__PURE__ */ jsx11(
|
|
2068
2434
|
"button",
|
|
2069
2435
|
{
|
|
2070
2436
|
type: "button",
|
|
@@ -2076,7 +2442,7 @@ var ImageEditor = ({
|
|
|
2076
2442
|
children: "Paint"
|
|
2077
2443
|
}
|
|
2078
2444
|
),
|
|
2079
|
-
/* @__PURE__ */
|
|
2445
|
+
/* @__PURE__ */ jsx11(
|
|
2080
2446
|
"button",
|
|
2081
2447
|
{
|
|
2082
2448
|
type: "button",
|
|
@@ -2088,7 +2454,7 @@ var ImageEditor = ({
|
|
|
2088
2454
|
children: "Select & Mask"
|
|
2089
2455
|
}
|
|
2090
2456
|
),
|
|
2091
|
-
/* @__PURE__ */
|
|
2457
|
+
/* @__PURE__ */ jsx11(
|
|
2092
2458
|
"button",
|
|
2093
2459
|
{
|
|
2094
2460
|
type: "button",
|
|
@@ -2100,7 +2466,7 @@ var ImageEditor = ({
|
|
|
2100
2466
|
children: "Annotations"
|
|
2101
2467
|
}
|
|
2102
2468
|
),
|
|
2103
|
-
/* @__PURE__ */
|
|
2469
|
+
/* @__PURE__ */ jsx11(
|
|
2104
2470
|
"button",
|
|
2105
2471
|
{
|
|
2106
2472
|
type: "button",
|
|
@@ -2112,7 +2478,7 @@ var ImageEditor = ({
|
|
|
2112
2478
|
children: "Depth Mask"
|
|
2113
2479
|
}
|
|
2114
2480
|
),
|
|
2115
|
-
/* @__PURE__ */
|
|
2481
|
+
/* @__PURE__ */ jsxs11(
|
|
2116
2482
|
"button",
|
|
2117
2483
|
{
|
|
2118
2484
|
type: "button",
|
|
@@ -2122,14 +2488,14 @@ var ImageEditor = ({
|
|
|
2122
2488
|
},
|
|
2123
2489
|
className: `px-3 py-1.5 rounded-md font-medium transition-colors flex items-center gap-1.5 ${activeTab === "ai" ? "bg-indigo-600 text-white shadow" : "text-slate-400 hover:text-slate-200"}`,
|
|
2124
2490
|
children: [
|
|
2125
|
-
/* @__PURE__ */
|
|
2491
|
+
/* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
|
|
2126
2492
|
"AI Tools"
|
|
2127
2493
|
]
|
|
2128
2494
|
}
|
|
2129
2495
|
)
|
|
2130
2496
|
] }),
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
/* @__PURE__ */
|
|
2497
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2498
|
+
/* @__PURE__ */ jsx11(
|
|
2133
2499
|
"button",
|
|
2134
2500
|
{
|
|
2135
2501
|
type: "button",
|
|
@@ -2140,7 +2506,7 @@ var ImageEditor = ({
|
|
|
2140
2506
|
children: "\u21A9"
|
|
2141
2507
|
}
|
|
2142
2508
|
),
|
|
2143
|
-
/* @__PURE__ */
|
|
2509
|
+
/* @__PURE__ */ jsx11(
|
|
2144
2510
|
"button",
|
|
2145
2511
|
{
|
|
2146
2512
|
type: "button",
|
|
@@ -2151,7 +2517,7 @@ var ImageEditor = ({
|
|
|
2151
2517
|
children: "\u21AA"
|
|
2152
2518
|
}
|
|
2153
2519
|
),
|
|
2154
|
-
/* @__PURE__ */
|
|
2520
|
+
/* @__PURE__ */ jsx11(
|
|
2155
2521
|
"button",
|
|
2156
2522
|
{
|
|
2157
2523
|
type: "button",
|
|
@@ -2160,8 +2526,8 @@ var ImageEditor = ({
|
|
|
2160
2526
|
children: "Reset"
|
|
2161
2527
|
}
|
|
2162
2528
|
),
|
|
2163
|
-
/* @__PURE__ */
|
|
2164
|
-
/* @__PURE__ */
|
|
2529
|
+
/* @__PURE__ */ jsx11("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
2530
|
+
/* @__PURE__ */ jsx11(
|
|
2165
2531
|
"button",
|
|
2166
2532
|
{
|
|
2167
2533
|
type: "button",
|
|
@@ -2171,11 +2537,11 @@ var ImageEditor = ({
|
|
|
2171
2537
|
children: "-"
|
|
2172
2538
|
}
|
|
2173
2539
|
),
|
|
2174
|
-
/* @__PURE__ */
|
|
2540
|
+
/* @__PURE__ */ jsxs11("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
|
|
2175
2541
|
Math.round(state.zoom * 100),
|
|
2176
2542
|
"%"
|
|
2177
2543
|
] }),
|
|
2178
|
-
/* @__PURE__ */
|
|
2544
|
+
/* @__PURE__ */ jsx11(
|
|
2179
2545
|
"button",
|
|
2180
2546
|
{
|
|
2181
2547
|
type: "button",
|
|
@@ -2185,8 +2551,8 @@ var ImageEditor = ({
|
|
|
2185
2551
|
children: "+"
|
|
2186
2552
|
}
|
|
2187
2553
|
),
|
|
2188
|
-
/* @__PURE__ */
|
|
2189
|
-
/* @__PURE__ */
|
|
2554
|
+
/* @__PURE__ */ jsx11("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
|
|
2555
|
+
/* @__PURE__ */ jsx11(
|
|
2190
2556
|
"button",
|
|
2191
2557
|
{
|
|
2192
2558
|
type: "button",
|
|
@@ -2197,7 +2563,7 @@ var ImageEditor = ({
|
|
|
2197
2563
|
children: "Hold Compare"
|
|
2198
2564
|
}
|
|
2199
2565
|
),
|
|
2200
|
-
/* @__PURE__ */
|
|
2566
|
+
/* @__PURE__ */ jsx11(
|
|
2201
2567
|
"button",
|
|
2202
2568
|
{
|
|
2203
2569
|
type: "button",
|
|
@@ -2208,13 +2574,15 @@ var ImageEditor = ({
|
|
|
2208
2574
|
)
|
|
2209
2575
|
] })
|
|
2210
2576
|
] }),
|
|
2211
|
-
/* @__PURE__ */
|
|
2212
|
-
|
|
2577
|
+
transformTool.active && /* @__PURE__ */ jsx11(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
|
|
2578
|
+
!transformTool.active && transformTool.error && /* @__PURE__ */ jsx11("div", { role: "alert", className: "border-b border-rose-900 bg-rose-950/80 px-4 py-1.5 text-xs text-rose-200", children: transformTool.error }),
|
|
2579
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
|
|
2580
|
+
/* @__PURE__ */ jsx11(
|
|
2213
2581
|
"div",
|
|
2214
2582
|
{
|
|
2215
2583
|
ref: containerRef,
|
|
2216
2584
|
className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
|
|
2217
|
-
children: /* @__PURE__ */
|
|
2585
|
+
children: /* @__PURE__ */ jsx11(
|
|
2218
2586
|
"canvas",
|
|
2219
2587
|
{
|
|
2220
2588
|
ref: canvasRef,
|
|
@@ -2227,16 +2595,17 @@ var ImageEditor = ({
|
|
|
2227
2595
|
onPointerUp: handlePaintPointerUp,
|
|
2228
2596
|
onPointerCancel: () => paintGestureRef.current?.cancel(),
|
|
2229
2597
|
"data-testid": "image-editor-canvas",
|
|
2230
|
-
|
|
2598
|
+
style: transformTool.active ? { cursor: transformCursor } : void 0,
|
|
2599
|
+
className: `absolute inset-0 w-full h-full block ${transformTool.active ? "touch-none" : activeTab === "paint" ? "touch-none cursor-crosshair" : ""}`
|
|
2231
2600
|
}
|
|
2232
2601
|
)
|
|
2233
2602
|
}
|
|
2234
2603
|
),
|
|
2235
|
-
/* @__PURE__ */
|
|
2236
|
-
activeTab === "crop" && /* @__PURE__ */
|
|
2237
|
-
/* @__PURE__ */
|
|
2238
|
-
/* @__PURE__ */
|
|
2239
|
-
/* @__PURE__ */
|
|
2604
|
+
/* @__PURE__ */ jsxs11("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: [
|
|
2605
|
+
activeTab === "crop" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
2606
|
+
/* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
|
|
2607
|
+
/* @__PURE__ */ jsxs11("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
2608
|
+
/* @__PURE__ */ jsx11(
|
|
2240
2609
|
"button",
|
|
2241
2610
|
{
|
|
2242
2611
|
type: "button",
|
|
@@ -2248,7 +2617,7 @@ var ImageEditor = ({
|
|
|
2248
2617
|
children: "Freeform"
|
|
2249
2618
|
}
|
|
2250
2619
|
),
|
|
2251
|
-
/* @__PURE__ */
|
|
2620
|
+
/* @__PURE__ */ jsx11(
|
|
2252
2621
|
"button",
|
|
2253
2622
|
{
|
|
2254
2623
|
type: "button",
|
|
@@ -2260,7 +2629,7 @@ var ImageEditor = ({
|
|
|
2260
2629
|
children: "1:1 Square"
|
|
2261
2630
|
}
|
|
2262
2631
|
),
|
|
2263
|
-
/* @__PURE__ */
|
|
2632
|
+
/* @__PURE__ */ jsx11(
|
|
2264
2633
|
"button",
|
|
2265
2634
|
{
|
|
2266
2635
|
type: "button",
|
|
@@ -2272,7 +2641,7 @@ var ImageEditor = ({
|
|
|
2272
2641
|
children: "4:3 Standard"
|
|
2273
2642
|
}
|
|
2274
2643
|
),
|
|
2275
|
-
/* @__PURE__ */
|
|
2644
|
+
/* @__PURE__ */ jsx11(
|
|
2276
2645
|
"button",
|
|
2277
2646
|
{
|
|
2278
2647
|
type: "button",
|
|
@@ -2284,7 +2653,7 @@ var ImageEditor = ({
|
|
|
2284
2653
|
children: "16:9 Wide"
|
|
2285
2654
|
}
|
|
2286
2655
|
),
|
|
2287
|
-
/* @__PURE__ */
|
|
2656
|
+
/* @__PURE__ */ jsx11(
|
|
2288
2657
|
"button",
|
|
2289
2658
|
{
|
|
2290
2659
|
type: "button",
|
|
@@ -2296,7 +2665,7 @@ var ImageEditor = ({
|
|
|
2296
2665
|
children: "3:2 Photo"
|
|
2297
2666
|
}
|
|
2298
2667
|
),
|
|
2299
|
-
/* @__PURE__ */
|
|
2668
|
+
/* @__PURE__ */ jsx11(
|
|
2300
2669
|
"button",
|
|
2301
2670
|
{
|
|
2302
2671
|
type: "button",
|
|
@@ -2309,10 +2678,10 @@ var ImageEditor = ({
|
|
|
2309
2678
|
}
|
|
2310
2679
|
)
|
|
2311
2680
|
] }),
|
|
2312
|
-
/* @__PURE__ */
|
|
2313
|
-
/* @__PURE__ */
|
|
2314
|
-
/* @__PURE__ */
|
|
2315
|
-
/* @__PURE__ */
|
|
2681
|
+
/* @__PURE__ */ jsx11("div", { className: "h-px bg-slate-800 my-1" }),
|
|
2682
|
+
/* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
|
|
2683
|
+
/* @__PURE__ */ jsxs11("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
2684
|
+
/* @__PURE__ */ jsx11(
|
|
2316
2685
|
"button",
|
|
2317
2686
|
{
|
|
2318
2687
|
type: "button",
|
|
@@ -2321,7 +2690,7 @@ var ImageEditor = ({
|
|
|
2321
2690
|
children: "Rotate -90\xB0"
|
|
2322
2691
|
}
|
|
2323
2692
|
),
|
|
2324
|
-
/* @__PURE__ */
|
|
2693
|
+
/* @__PURE__ */ jsx11(
|
|
2325
2694
|
"button",
|
|
2326
2695
|
{
|
|
2327
2696
|
type: "button",
|
|
@@ -2330,7 +2699,7 @@ var ImageEditor = ({
|
|
|
2330
2699
|
children: "Rotate +90\xB0"
|
|
2331
2700
|
}
|
|
2332
2701
|
),
|
|
2333
|
-
/* @__PURE__ */
|
|
2702
|
+
/* @__PURE__ */ jsx11(
|
|
2334
2703
|
"button",
|
|
2335
2704
|
{
|
|
2336
2705
|
type: "button",
|
|
@@ -2339,7 +2708,7 @@ var ImageEditor = ({
|
|
|
2339
2708
|
children: "Flip Horizontal"
|
|
2340
2709
|
}
|
|
2341
2710
|
),
|
|
2342
|
-
/* @__PURE__ */
|
|
2711
|
+
/* @__PURE__ */ jsx11(
|
|
2343
2712
|
"button",
|
|
2344
2713
|
{
|
|
2345
2714
|
type: "button",
|
|
@@ -2350,10 +2719,10 @@ var ImageEditor = ({
|
|
|
2350
2719
|
)
|
|
2351
2720
|
] })
|
|
2352
2721
|
] }),
|
|
2353
|
-
activeTab === "adjust" && /* @__PURE__ */
|
|
2354
|
-
/* @__PURE__ */
|
|
2355
|
-
/* @__PURE__ */
|
|
2356
|
-
/* @__PURE__ */
|
|
2722
|
+
activeTab === "adjust" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2723
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
|
|
2724
|
+
/* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
|
|
2725
|
+
/* @__PURE__ */ jsx11(
|
|
2357
2726
|
"button",
|
|
2358
2727
|
{
|
|
2359
2728
|
type: "button",
|
|
@@ -2363,9 +2732,9 @@ var ImageEditor = ({
|
|
|
2363
2732
|
}
|
|
2364
2733
|
)
|
|
2365
2734
|
] }),
|
|
2366
|
-
/* @__PURE__ */
|
|
2367
|
-
IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */
|
|
2368
|
-
/* @__PURE__ */
|
|
2735
|
+
/* @__PURE__ */ jsx11(Histogram, { histogram: editor.histogram }),
|
|
2736
|
+
IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ jsxs11(React10.Fragment, { children: [
|
|
2737
|
+
/* @__PURE__ */ jsx11(
|
|
2369
2738
|
ControlSlider,
|
|
2370
2739
|
{
|
|
2371
2740
|
spec,
|
|
@@ -2374,14 +2743,14 @@ var ImageEditor = ({
|
|
|
2374
2743
|
onChange: (v) => editor.setAdjustments({ [spec.id]: v })
|
|
2375
2744
|
}
|
|
2376
2745
|
),
|
|
2377
|
-
spec.id === "tint" && legacyProcess && /* @__PURE__ */
|
|
2746
|
+
spec.id === "tint" && legacyProcess && /* @__PURE__ */ jsxs11(
|
|
2378
2747
|
"div",
|
|
2379
2748
|
{
|
|
2380
2749
|
className: "flex items-center justify-between gap-2 rounded border border-amber-500/30 bg-amber-500/10 px-2 py-1.5 text-[10px] text-amber-200",
|
|
2381
2750
|
"data-testid": "image-editor-process-notice",
|
|
2382
2751
|
children: [
|
|
2383
|
-
/* @__PURE__ */
|
|
2384
|
-
/* @__PURE__ */
|
|
2752
|
+
/* @__PURE__ */ jsx11("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
|
|
2753
|
+
/* @__PURE__ */ jsx11(
|
|
2385
2754
|
"button",
|
|
2386
2755
|
{
|
|
2387
2756
|
type: "button",
|
|
@@ -2394,7 +2763,7 @@ var ImageEditor = ({
|
|
|
2394
2763
|
}
|
|
2395
2764
|
)
|
|
2396
2765
|
] }, spec.id)),
|
|
2397
|
-
/* @__PURE__ */
|
|
2766
|
+
/* @__PURE__ */ jsx11("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx11(
|
|
2398
2767
|
AdjustmentLayersPanel,
|
|
2399
2768
|
{
|
|
2400
2769
|
controller,
|
|
@@ -2403,19 +2772,41 @@ var ImageEditor = ({
|
|
|
2403
2772
|
}
|
|
2404
2773
|
) })
|
|
2405
2774
|
] }),
|
|
2406
|
-
activeTab === "layers" && /* @__PURE__ */
|
|
2407
|
-
/* @__PURE__ */
|
|
2408
|
-
/* @__PURE__ */
|
|
2775
|
+
activeTab === "layers" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2776
|
+
/* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
|
|
2777
|
+
/* @__PURE__ */ jsx11(
|
|
2778
|
+
"button",
|
|
2779
|
+
{
|
|
2780
|
+
type: "button",
|
|
2781
|
+
title: "Edit \u203A Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer",
|
|
2782
|
+
className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
|
|
2783
|
+
disabled: transformTool.active,
|
|
2784
|
+
onClick: () => transformTool.begin(),
|
|
2785
|
+
children: "Free Transform"
|
|
2786
|
+
}
|
|
2787
|
+
),
|
|
2788
|
+
/* @__PURE__ */ jsx11(LayersPanel, { controller })
|
|
2409
2789
|
] }),
|
|
2410
|
-
activeTab === "paint" && /* @__PURE__ */
|
|
2411
|
-
/* @__PURE__ */
|
|
2412
|
-
/* @__PURE__ */
|
|
2413
|
-
|
|
2414
|
-
|
|
2790
|
+
activeTab === "paint" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2791
|
+
/* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
|
|
2792
|
+
/* @__PURE__ */ jsx11(BrushOptionsBar, { controller }),
|
|
2793
|
+
/* @__PURE__ */ jsx11(
|
|
2794
|
+
"button",
|
|
2795
|
+
{
|
|
2796
|
+
type: "button",
|
|
2797
|
+
title: "Edit \u203A Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer",
|
|
2798
|
+
className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start",
|
|
2799
|
+
disabled: transformTool.active,
|
|
2800
|
+
onClick: () => transformTool.begin(),
|
|
2801
|
+
children: "Free Transform"
|
|
2802
|
+
}
|
|
2803
|
+
),
|
|
2804
|
+
paintError && /* @__PURE__ */ jsx11("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
|
|
2805
|
+
/* @__PURE__ */ jsx11("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ jsx11(LayersPanel, { controller }) })
|
|
2415
2806
|
] }),
|
|
2416
|
-
activeTab === "annotate" && /* @__PURE__ */
|
|
2417
|
-
/* @__PURE__ */
|
|
2418
|
-
/* @__PURE__ */
|
|
2807
|
+
activeTab === "annotate" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2808
|
+
/* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
|
|
2809
|
+
/* @__PURE__ */ jsx11("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ jsx11(
|
|
2419
2810
|
"button",
|
|
2420
2811
|
{
|
|
2421
2812
|
type: "button",
|
|
@@ -2425,9 +2816,9 @@ var ImageEditor = ({
|
|
|
2425
2816
|
},
|
|
2426
2817
|
t
|
|
2427
2818
|
)) }),
|
|
2428
|
-
/* @__PURE__ */
|
|
2429
|
-
/* @__PURE__ */
|
|
2430
|
-
/* @__PURE__ */
|
|
2819
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
2820
|
+
/* @__PURE__ */ jsx11("label", { className: "text-slate-400", children: "Color:" }),
|
|
2821
|
+
/* @__PURE__ */ jsx11(
|
|
2431
2822
|
"input",
|
|
2432
2823
|
{
|
|
2433
2824
|
type: "color",
|
|
@@ -2436,15 +2827,15 @@ var ImageEditor = ({
|
|
|
2436
2827
|
className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
|
|
2437
2828
|
}
|
|
2438
2829
|
),
|
|
2439
|
-
/* @__PURE__ */
|
|
2440
|
-
/* @__PURE__ */
|
|
2441
|
-
/* @__PURE__ */
|
|
2442
|
-
/* @__PURE__ */
|
|
2830
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex-1 ml-2", children: [
|
|
2831
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
|
|
2832
|
+
/* @__PURE__ */ jsx11("span", { children: "Width:" }),
|
|
2833
|
+
/* @__PURE__ */ jsxs11("span", { className: "font-mono", children: [
|
|
2443
2834
|
strokeWidth,
|
|
2444
2835
|
"px"
|
|
2445
2836
|
] })
|
|
2446
2837
|
] }),
|
|
2447
|
-
/* @__PURE__ */
|
|
2838
|
+
/* @__PURE__ */ jsx11(
|
|
2448
2839
|
"input",
|
|
2449
2840
|
{
|
|
2450
2841
|
type: "range",
|
|
@@ -2457,10 +2848,10 @@ var ImageEditor = ({
|
|
|
2457
2848
|
)
|
|
2458
2849
|
] })
|
|
2459
2850
|
] }),
|
|
2460
|
-
/* @__PURE__ */
|
|
2461
|
-
/* @__PURE__ */
|
|
2462
|
-
/* @__PURE__ */
|
|
2463
|
-
/* @__PURE__ */
|
|
2851
|
+
/* @__PURE__ */ jsx11("div", { className: "h-px bg-slate-800 my-1" }),
|
|
2852
|
+
/* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
|
|
2853
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex gap-2", children: [
|
|
2854
|
+
/* @__PURE__ */ jsx11(
|
|
2464
2855
|
"input",
|
|
2465
2856
|
{
|
|
2466
2857
|
type: "text",
|
|
@@ -2471,7 +2862,7 @@ var ImageEditor = ({
|
|
|
2471
2862
|
className: "flex-1 bg-slate-950 border border-slate-700 rounded-lg px-2.5 py-1.5 text-xs text-slate-100 placeholder-slate-500 focus:outline-none focus:border-indigo-500"
|
|
2472
2863
|
}
|
|
2473
2864
|
),
|
|
2474
|
-
/* @__PURE__ */
|
|
2865
|
+
/* @__PURE__ */ jsx11(
|
|
2475
2866
|
"button",
|
|
2476
2867
|
{
|
|
2477
2868
|
type: "button",
|
|
@@ -2481,14 +2872,14 @@ var ImageEditor = ({
|
|
|
2481
2872
|
}
|
|
2482
2873
|
)
|
|
2483
2874
|
] }),
|
|
2484
|
-
/* @__PURE__ */
|
|
2485
|
-
/* @__PURE__ */
|
|
2486
|
-
/* @__PURE__ */
|
|
2875
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between text-slate-400", children: [
|
|
2876
|
+
/* @__PURE__ */ jsx11("span", { children: "Font Size:" }),
|
|
2877
|
+
/* @__PURE__ */ jsxs11("span", { className: "font-mono", children: [
|
|
2487
2878
|
fontSize,
|
|
2488
2879
|
"px"
|
|
2489
2880
|
] })
|
|
2490
2881
|
] }),
|
|
2491
|
-
/* @__PURE__ */
|
|
2882
|
+
/* @__PURE__ */ jsx11(
|
|
2492
2883
|
"input",
|
|
2493
2884
|
{
|
|
2494
2885
|
type: "range",
|
|
@@ -2499,14 +2890,14 @@ var ImageEditor = ({
|
|
|
2499
2890
|
className: "w-full accent-indigo-500"
|
|
2500
2891
|
}
|
|
2501
2892
|
),
|
|
2502
|
-
/* @__PURE__ */
|
|
2503
|
-
/* @__PURE__ */
|
|
2504
|
-
/* @__PURE__ */
|
|
2893
|
+
/* @__PURE__ */ jsx11("div", { className: "h-px bg-slate-800 my-1" }),
|
|
2894
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
|
|
2895
|
+
/* @__PURE__ */ jsxs11("span", { className: "text-slate-400", children: [
|
|
2505
2896
|
"Layers (",
|
|
2506
2897
|
state.annotations.length,
|
|
2507
2898
|
")"
|
|
2508
2899
|
] }),
|
|
2509
|
-
state.selectedAnnotationId && /* @__PURE__ */
|
|
2900
|
+
state.selectedAnnotationId && /* @__PURE__ */ jsx11(
|
|
2510
2901
|
"button",
|
|
2511
2902
|
{
|
|
2512
2903
|
type: "button",
|
|
@@ -2515,7 +2906,7 @@ var ImageEditor = ({
|
|
|
2515
2906
|
children: "Delete Selected"
|
|
2516
2907
|
}
|
|
2517
2908
|
),
|
|
2518
|
-
state.annotations.length > 0 && /* @__PURE__ */
|
|
2909
|
+
state.annotations.length > 0 && /* @__PURE__ */ jsx11(
|
|
2519
2910
|
"button",
|
|
2520
2911
|
{
|
|
2521
2912
|
type: "button",
|
|
@@ -2526,10 +2917,10 @@ var ImageEditor = ({
|
|
|
2526
2917
|
)
|
|
2527
2918
|
] })
|
|
2528
2919
|
] }),
|
|
2529
|
-
activeTab === "depth" && /* @__PURE__ */
|
|
2530
|
-
/* @__PURE__ */
|
|
2531
|
-
/* @__PURE__ */
|
|
2532
|
-
/* @__PURE__ */
|
|
2920
|
+
activeTab === "depth" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-3 text-xs", children: [
|
|
2921
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
|
|
2922
|
+
/* @__PURE__ */ jsx11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
|
|
2923
|
+
/* @__PURE__ */ jsx11(
|
|
2533
2924
|
"button",
|
|
2534
2925
|
{
|
|
2535
2926
|
type: "button",
|
|
@@ -2539,8 +2930,8 @@ var ImageEditor = ({
|
|
|
2539
2930
|
}
|
|
2540
2931
|
)
|
|
2541
2932
|
] }),
|
|
2542
|
-
/* @__PURE__ */
|
|
2543
|
-
/* @__PURE__ */
|
|
2933
|
+
/* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
|
|
2934
|
+
/* @__PURE__ */ jsx11(
|
|
2544
2935
|
"input",
|
|
2545
2936
|
{
|
|
2546
2937
|
type: "checkbox",
|
|
@@ -2549,12 +2940,12 @@ var ImageEditor = ({
|
|
|
2549
2940
|
className: "rounded accent-indigo-500"
|
|
2550
2941
|
}
|
|
2551
2942
|
),
|
|
2552
|
-
/* @__PURE__ */
|
|
2943
|
+
/* @__PURE__ */ jsx11("span", { children: "Enable Depth / Alpha Mask" })
|
|
2553
2944
|
] }),
|
|
2554
|
-
state.depthMask.enabled && /* @__PURE__ */
|
|
2555
|
-
/* @__PURE__ */
|
|
2556
|
-
/* @__PURE__ */
|
|
2557
|
-
/* @__PURE__ */
|
|
2945
|
+
state.depthMask.enabled && /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
2946
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
2947
|
+
/* @__PURE__ */ jsx11("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
|
|
2948
|
+
/* @__PURE__ */ jsx11(
|
|
2558
2949
|
"input",
|
|
2559
2950
|
{
|
|
2560
2951
|
type: "text",
|
|
@@ -2565,8 +2956,8 @@ var ImageEditor = ({
|
|
|
2565
2956
|
}
|
|
2566
2957
|
)
|
|
2567
2958
|
] }),
|
|
2568
|
-
/* @__PURE__ */
|
|
2569
|
-
/* @__PURE__ */
|
|
2959
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex gap-2", children: [
|
|
2960
|
+
/* @__PURE__ */ jsx11(
|
|
2570
2961
|
"button",
|
|
2571
2962
|
{
|
|
2572
2963
|
type: "button",
|
|
@@ -2575,7 +2966,7 @@ var ImageEditor = ({
|
|
|
2575
2966
|
children: "Threshold Mode"
|
|
2576
2967
|
}
|
|
2577
2968
|
),
|
|
2578
|
-
/* @__PURE__ */
|
|
2969
|
+
/* @__PURE__ */ jsx11(
|
|
2579
2970
|
"button",
|
|
2580
2971
|
{
|
|
2581
2972
|
type: "button",
|
|
@@ -2585,12 +2976,12 @@ var ImageEditor = ({
|
|
|
2585
2976
|
}
|
|
2586
2977
|
)
|
|
2587
2978
|
] }),
|
|
2588
|
-
/* @__PURE__ */
|
|
2589
|
-
/* @__PURE__ */
|
|
2590
|
-
/* @__PURE__ */
|
|
2591
|
-
/* @__PURE__ */
|
|
2979
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
2980
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
2981
|
+
/* @__PURE__ */ jsx11("span", { children: "Depth Start (Lower):" }),
|
|
2982
|
+
/* @__PURE__ */ jsx11("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
|
|
2592
2983
|
] }),
|
|
2593
|
-
/* @__PURE__ */
|
|
2984
|
+
/* @__PURE__ */ jsx11(
|
|
2594
2985
|
"input",
|
|
2595
2986
|
{
|
|
2596
2987
|
type: "range",
|
|
@@ -2604,12 +2995,12 @@ var ImageEditor = ({
|
|
|
2604
2995
|
}
|
|
2605
2996
|
)
|
|
2606
2997
|
] }),
|
|
2607
|
-
/* @__PURE__ */
|
|
2608
|
-
/* @__PURE__ */
|
|
2609
|
-
/* @__PURE__ */
|
|
2610
|
-
/* @__PURE__ */
|
|
2998
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
2999
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
3000
|
+
/* @__PURE__ */ jsx11("span", { children: "Depth Stop (Upper):" }),
|
|
3001
|
+
/* @__PURE__ */ jsx11("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
|
|
2611
3002
|
] }),
|
|
2612
|
-
/* @__PURE__ */
|
|
3003
|
+
/* @__PURE__ */ jsx11(
|
|
2613
3004
|
"input",
|
|
2614
3005
|
{
|
|
2615
3006
|
type: "range",
|
|
@@ -2623,12 +3014,12 @@ var ImageEditor = ({
|
|
|
2623
3014
|
}
|
|
2624
3015
|
)
|
|
2625
3016
|
] }),
|
|
2626
|
-
/* @__PURE__ */
|
|
2627
|
-
/* @__PURE__ */
|
|
2628
|
-
/* @__PURE__ */
|
|
2629
|
-
/* @__PURE__ */
|
|
3017
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
3018
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex justify-between text-slate-400 mb-1", children: [
|
|
3019
|
+
/* @__PURE__ */ jsx11("span", { children: "Softness:" }),
|
|
3020
|
+
/* @__PURE__ */ jsx11("span", { className: "font-mono", children: state.depthMask.softness })
|
|
2630
3021
|
] }),
|
|
2631
|
-
/* @__PURE__ */
|
|
3022
|
+
/* @__PURE__ */ jsx11(
|
|
2632
3023
|
"input",
|
|
2633
3024
|
{
|
|
2634
3025
|
type: "range",
|
|
@@ -2640,8 +3031,8 @@ var ImageEditor = ({
|
|
|
2640
3031
|
}
|
|
2641
3032
|
)
|
|
2642
3033
|
] }),
|
|
2643
|
-
/* @__PURE__ */
|
|
2644
|
-
/* @__PURE__ */
|
|
3034
|
+
/* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
|
|
3035
|
+
/* @__PURE__ */ jsx11(
|
|
2645
3036
|
"input",
|
|
2646
3037
|
{
|
|
2647
3038
|
type: "checkbox",
|
|
@@ -2650,12 +3041,12 @@ var ImageEditor = ({
|
|
|
2650
3041
|
className: "rounded accent-indigo-500"
|
|
2651
3042
|
}
|
|
2652
3043
|
),
|
|
2653
|
-
/* @__PURE__ */
|
|
3044
|
+
/* @__PURE__ */ jsx11("span", { children: "Invert Mask" })
|
|
2654
3045
|
] })
|
|
2655
3046
|
] })
|
|
2656
3047
|
] }),
|
|
2657
|
-
activeTab === "select" && /* @__PURE__ */
|
|
2658
|
-
/* @__PURE__ */
|
|
3048
|
+
activeTab === "select" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
3049
|
+
/* @__PURE__ */ jsx11(
|
|
2659
3050
|
SelectionOptionsBar,
|
|
2660
3051
|
{
|
|
2661
3052
|
controller,
|
|
@@ -2665,13 +3056,37 @@ var ImageEditor = ({
|
|
|
2665
3056
|
quickMask: Boolean(state.quickMask)
|
|
2666
3057
|
}
|
|
2667
3058
|
),
|
|
2668
|
-
selectionError && /* @__PURE__ */
|
|
2669
|
-
/* @__PURE__ */
|
|
3059
|
+
selectionError && /* @__PURE__ */ jsx11("p", { role: "alert", className: "text-rose-400", children: selectionError }),
|
|
3060
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex gap-1", children: [
|
|
3061
|
+
/* @__PURE__ */ jsx11(
|
|
3062
|
+
"button",
|
|
3063
|
+
{
|
|
3064
|
+
type: "button",
|
|
3065
|
+
title: "Select \u203A Transform Selection: the outline only",
|
|
3066
|
+
className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
|
|
3067
|
+
disabled: transformTool.active,
|
|
3068
|
+
onClick: () => transformTool.begin({ content: "selection-outline" }),
|
|
3069
|
+
children: "Transform Selection"
|
|
3070
|
+
}
|
|
3071
|
+
),
|
|
3072
|
+
/* @__PURE__ */ jsx11(
|
|
3073
|
+
"button",
|
|
3074
|
+
{
|
|
3075
|
+
type: "button",
|
|
3076
|
+
title: "Edit \u203A Free Transform: the selected pixels of the active layer",
|
|
3077
|
+
className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
|
|
3078
|
+
disabled: transformTool.active,
|
|
3079
|
+
onClick: () => transformTool.begin({ content: "selection" }),
|
|
3080
|
+
children: "Free Transform Pixels"
|
|
3081
|
+
}
|
|
3082
|
+
)
|
|
3083
|
+
] }),
|
|
3084
|
+
/* @__PURE__ */ jsx11(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
|
|
2670
3085
|
] }),
|
|
2671
|
-
activeTab === "ai" && /* @__PURE__ */
|
|
2672
|
-
/* @__PURE__ */
|
|
2673
|
-
/* @__PURE__ */
|
|
2674
|
-
/* @__PURE__ */
|
|
3086
|
+
activeTab === "ai" && /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-4 text-xs", children: [
|
|
3087
|
+
/* @__PURE__ */ jsxs11("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
|
|
3088
|
+
/* @__PURE__ */ jsx11("span", { children: "Results go to" }),
|
|
3089
|
+
/* @__PURE__ */ jsxs11(
|
|
2675
3090
|
"select",
|
|
2676
3091
|
{
|
|
2677
3092
|
"aria-label": "AI result target",
|
|
@@ -2679,54 +3094,54 @@ var ImageEditor = ({
|
|
|
2679
3094
|
onChange: (e) => setAiTarget(e.target.value),
|
|
2680
3095
|
className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
|
|
2681
3096
|
children: [
|
|
2682
|
-
/* @__PURE__ */
|
|
2683
|
-
/* @__PURE__ */
|
|
2684
|
-
/* @__PURE__ */
|
|
3097
|
+
/* @__PURE__ */ jsx11("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
|
|
3098
|
+
/* @__PURE__ */ jsx11("option", { value: "new-layer", children: "New layer / mask" }),
|
|
3099
|
+
/* @__PURE__ */ jsx11("option", { value: "replace", children: "Replace image" })
|
|
2685
3100
|
]
|
|
2686
3101
|
}
|
|
2687
3102
|
)
|
|
2688
3103
|
] }),
|
|
2689
|
-
/* @__PURE__ */
|
|
2690
|
-
/* @__PURE__ */
|
|
2691
|
-
/* @__PURE__ */
|
|
2692
|
-
/* @__PURE__ */
|
|
3104
|
+
/* @__PURE__ */ jsxs11("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
3105
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
|
|
3106
|
+
/* @__PURE__ */ jsxs11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
3107
|
+
/* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("path", { d: "M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" }) }),
|
|
2693
3108
|
"Background Removal"
|
|
2694
3109
|
] }),
|
|
2695
|
-
isRemovingBg && /* @__PURE__ */
|
|
3110
|
+
isRemovingBg && /* @__PURE__ */ jsx11("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse", children: "Removing..." })
|
|
2696
3111
|
] }),
|
|
2697
|
-
/* @__PURE__ */
|
|
2698
|
-
/* @__PURE__ */
|
|
3112
|
+
/* @__PURE__ */ jsx11("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
|
|
3113
|
+
/* @__PURE__ */ jsx11(
|
|
2699
3114
|
"button",
|
|
2700
3115
|
{
|
|
2701
3116
|
type: "button",
|
|
2702
3117
|
onClick: handleRemoveBackground,
|
|
2703
3118
|
disabled: isRemovingBg || isInpainting,
|
|
2704
3119
|
className: "mt-1 px-3 py-2 rounded-lg bg-indigo-600 hover:bg-indigo-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2",
|
|
2705
|
-
children: isRemovingBg ? /* @__PURE__ */
|
|
2706
|
-
/* @__PURE__ */
|
|
3120
|
+
children: isRemovingBg ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
3121
|
+
/* @__PURE__ */ jsx11("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
2707
3122
|
"Removing Background..."
|
|
2708
|
-
] }) : /* @__PURE__ */
|
|
2709
|
-
/* @__PURE__ */
|
|
3123
|
+
] }) : /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
3124
|
+
/* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
|
|
2710
3125
|
"Remove Background"
|
|
2711
3126
|
] })
|
|
2712
3127
|
}
|
|
2713
3128
|
)
|
|
2714
3129
|
] }),
|
|
2715
|
-
/* @__PURE__ */
|
|
2716
|
-
/* @__PURE__ */
|
|
2717
|
-
/* @__PURE__ */
|
|
2718
|
-
/* @__PURE__ */
|
|
2719
|
-
/* @__PURE__ */
|
|
2720
|
-
/* @__PURE__ */
|
|
3130
|
+
/* @__PURE__ */ jsxs11("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
|
|
3131
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex items-center justify-between", children: [
|
|
3132
|
+
/* @__PURE__ */ jsxs11("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
|
|
3133
|
+
/* @__PURE__ */ jsxs11("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
3134
|
+
/* @__PURE__ */ jsx11("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" }),
|
|
3135
|
+
/* @__PURE__ */ jsx11("path", { d: "m14 7 3 3" })
|
|
2721
3136
|
] }),
|
|
2722
3137
|
"Generative Inpainting"
|
|
2723
3138
|
] }),
|
|
2724
|
-
isInpainting && /* @__PURE__ */
|
|
3139
|
+
isInpainting && /* @__PURE__ */ jsx11("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse", children: "Inpainting..." })
|
|
2725
3140
|
] }),
|
|
2726
|
-
/* @__PURE__ */
|
|
2727
|
-
/* @__PURE__ */
|
|
2728
|
-
/* @__PURE__ */
|
|
2729
|
-
/* @__PURE__ */
|
|
3141
|
+
/* @__PURE__ */ jsx11("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
|
|
3142
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1", children: [
|
|
3143
|
+
/* @__PURE__ */ jsx11("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
|
|
3144
|
+
/* @__PURE__ */ jsx11(
|
|
2730
3145
|
"textarea",
|
|
2731
3146
|
{
|
|
2732
3147
|
id: "ai-inpaint-prompt-react",
|
|
@@ -2738,10 +3153,10 @@ var ImageEditor = ({
|
|
|
2738
3153
|
}
|
|
2739
3154
|
)
|
|
2740
3155
|
] }),
|
|
2741
|
-
/* @__PURE__ */
|
|
2742
|
-
/* @__PURE__ */
|
|
2743
|
-
/* @__PURE__ */
|
|
2744
|
-
/* @__PURE__ */
|
|
3156
|
+
/* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-1", children: [
|
|
3157
|
+
/* @__PURE__ */ jsx11("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
|
|
3158
|
+
/* @__PURE__ */ jsxs11("div", { className: "grid grid-cols-2 gap-1.5", children: [
|
|
3159
|
+
/* @__PURE__ */ jsxs11(
|
|
2745
3160
|
"button",
|
|
2746
3161
|
{
|
|
2747
3162
|
type: "button",
|
|
@@ -2754,7 +3169,7 @@ var ImageEditor = ({
|
|
|
2754
3169
|
]
|
|
2755
3170
|
}
|
|
2756
3171
|
),
|
|
2757
|
-
/* @__PURE__ */
|
|
3172
|
+
/* @__PURE__ */ jsxs11(
|
|
2758
3173
|
"button",
|
|
2759
3174
|
{
|
|
2760
3175
|
type: "button",
|
|
@@ -2769,25 +3184,25 @@ var ImageEditor = ({
|
|
|
2769
3184
|
)
|
|
2770
3185
|
] })
|
|
2771
3186
|
] }),
|
|
2772
|
-
/* @__PURE__ */
|
|
3187
|
+
/* @__PURE__ */ jsx11(
|
|
2773
3188
|
"button",
|
|
2774
3189
|
{
|
|
2775
3190
|
type: "button",
|
|
2776
3191
|
onClick: handleInpaint,
|
|
2777
3192
|
disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
|
|
2778
3193
|
className: "mt-1 px-3 py-2 rounded-lg bg-purple-600 hover:bg-purple-500 disabled:opacity-50 text-white font-medium shadow transition-colors flex items-center justify-center gap-2",
|
|
2779
|
-
children: isInpainting ? /* @__PURE__ */
|
|
2780
|
-
/* @__PURE__ */
|
|
3194
|
+
children: isInpainting ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
3195
|
+
/* @__PURE__ */ jsx11("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
|
|
2781
3196
|
"Generating Inpaint..."
|
|
2782
|
-
] }) : /* @__PURE__ */
|
|
2783
|
-
/* @__PURE__ */
|
|
3197
|
+
] }) : /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
3198
|
+
/* @__PURE__ */ jsx11("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx11("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
|
|
2784
3199
|
"Apply Inpainting"
|
|
2785
3200
|
] })
|
|
2786
3201
|
}
|
|
2787
3202
|
)
|
|
2788
3203
|
] }),
|
|
2789
|
-
aiError && /* @__PURE__ */
|
|
2790
|
-
aiSuccess && /* @__PURE__ */
|
|
3204
|
+
aiError && /* @__PURE__ */ jsx11("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
|
|
3205
|
+
aiSuccess && /* @__PURE__ */ jsx11("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
|
|
2791
3206
|
] })
|
|
2792
3207
|
] })
|
|
2793
3208
|
] })
|
|
@@ -2803,10 +3218,12 @@ export {
|
|
|
2803
3218
|
useImageHistogram,
|
|
2804
3219
|
CurvesEditor,
|
|
2805
3220
|
AdjustmentLayersPanel,
|
|
3221
|
+
LayerEffectsPanel,
|
|
2806
3222
|
LayersPanel,
|
|
2807
3223
|
BrushOptionsBar,
|
|
2808
3224
|
SelectionOptionsBar,
|
|
2809
3225
|
RefineEdgePanel,
|
|
3226
|
+
FreeTransformOptionsBar,
|
|
2810
3227
|
ImageEditor
|
|
2811
3228
|
};
|
|
2812
|
-
//# sourceMappingURL=chunk-
|
|
3229
|
+
//# sourceMappingURL=chunk-OSBDCFF4.js.map
|