@pixerate/editor-react 0.63.0 → 0.64.0

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