@pixerate/editor-react 0.76.0 → 0.77.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -60,6 +60,7 @@ __export(src_exports, {
60
60
  MergePreview: () => MergePreview,
61
61
  NameManager: () => NameManager,
62
62
  OutlinePanel: () => OutlinePanel,
63
+ PaintGradientEditor: () => PaintGradientEditor,
63
64
  RecoveryPrompt: () => RecoveryPrompt,
64
65
  RefineEdgePanel: () => RefineEdgePanel,
65
66
  ReviewToolbar: () => ReviewToolbar,
@@ -2008,17 +2009,17 @@ var SpreadsheetValidationDialog = ({ prompt, onResolve }) => {
2008
2009
  style === "warning" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "mt-2", children: "Continue?" })
2009
2010
  ] })
2010
2011
  ] }),
2011
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-4 flex justify-end gap-2", children: buttons.map((button3, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2012
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-4 flex justify-end gap-2", children: buttons.map((button4, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2012
2013
  "button",
2013
2014
  {
2014
2015
  ref: i === 0 ? firstButton : void 0,
2015
2016
  type: "button",
2016
- "data-action": button3.action,
2017
+ "data-action": button4.action,
2017
2018
  className: `rounded border border-border px-3 py-1 ${i === 0 ? "bg-primary text-primary-foreground" : "hover:bg-muted"}`,
2018
- onClick: () => onResolve(button3.action),
2019
- children: button3.label
2019
+ onClick: () => onResolve(button4.action),
2020
+ children: button4.label
2020
2021
  },
2021
- button3.action
2022
+ button4.action
2022
2023
  )) })
2023
2024
  ]
2024
2025
  }
@@ -3788,8 +3789,8 @@ function useImageEditor(options = {}) {
3788
3789
  }
3789
3790
 
3790
3791
  // src/image-editor/ImageEditor.tsx
3791
- var import_react47 = __toESM(require("react"), 1);
3792
- var import_image_editor15 = require("@pixerate/editor/image-editor");
3792
+ var import_react48 = __toESM(require("react"), 1);
3793
+ var import_image_editor17 = require("@pixerate/editor/image-editor");
3793
3794
 
3794
3795
  // src/image-editor/ControlSlider.tsx
3795
3796
  var import_image_editor2 = require("@pixerate/editor/image-editor");
@@ -4839,16 +4840,148 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4839
4840
  };
4840
4841
 
4841
4842
  // src/image-editor/BrushOptionsBar.tsx
4842
- var import_react40 = require("react");
4843
+ var import_react41 = require("react");
4844
+ var import_image_editor9 = require("@pixerate/editor/image-editor");
4845
+ var import_image_editor10 = require("@pixerate/editor/image-editor");
4846
+
4847
+ // src/image-editor/PaintGradientEditor.tsx
4843
4848
  var import_image_editor8 = require("@pixerate/editor/image-editor");
4849
+
4850
+ // src/paint-editor/PaintGradientEditorView.tsx
4851
+ var import_react40 = require("react");
4844
4852
  var import_jsx_runtime23 = require("react/jsx-runtime");
4853
+ var button2 = "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-200 hover:bg-slate-700 disabled:opacity-40";
4854
+ var select = "rounded bg-slate-800 px-1 py-0.5 text-[11px]";
4855
+ var number = "w-16 rounded bg-slate-800 px-1 py-0.5 text-[11px]";
4856
+ var pct = (v) => Math.round(v * 1e3) / 10;
4857
+ var PaintGradientEditorView = ({ value, onChange, colors, className, kit }) => {
4858
+ const {
4859
+ PAINT_GRADIENT_MAPPINGS,
4860
+ PAINT_GRADIENT_MAPPING_LABELS,
4861
+ PAINT_GRADIENT_PRESETS,
4862
+ PAINT_GRADIENT_REPEATS,
4863
+ PAINT_GRADIENT_REPEAT_LABELS,
4864
+ PAINT_GRADIENT_SPACES,
4865
+ PAINT_GRADIENT_SPACE_LABELS,
4866
+ addPaintGradientStop,
4867
+ paintGradientMappingFor,
4868
+ paintSourceCss,
4869
+ removePaintGradientStop,
4870
+ reversePaintGradient,
4871
+ updatePaintGradientStop
4872
+ } = kit;
4873
+ const [selected, setSelected] = (0, import_react40.useState)(0);
4874
+ const sel = Math.min(selected, value.stops.length - 1);
4875
+ const stop = value.stops[sel];
4876
+ const map = value.map;
4877
+ const stopHex = (c) => c === "paint" ? colors.paint : c === "secondary" ? colors.secondary : c;
4878
+ const patchStop = (patch) => {
4879
+ const r = updatePaintGradientStop(value, sel, patch);
4880
+ setSelected(r.index);
4881
+ onChange(r.paint);
4882
+ };
4883
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `flex flex-col gap-1.5 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "paint-gradient-editor", "aria-label": "Gradient paint", children: [
4884
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1", children: [
4885
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("select", { "aria-label": "Gradient preset", className: select, value: "", onChange: (e) => e.target.value && (setSelected(0), onChange(PAINT_GRADIENT_PRESETS[Number(e.target.value)].paint)), children: [
4886
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "", children: "Presets\u2026" }),
4887
+ PAINT_GRADIENT_PRESETS.map((p, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: i, children: p.name }, p.name))
4888
+ ] }),
4889
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: button2, onClick: () => onChange(reversePaintGradient(value)), children: "Reverse" })
4890
+ ] }),
4891
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4892
+ "div",
4893
+ {
4894
+ role: "slider",
4895
+ tabIndex: 0,
4896
+ "aria-label": "Gradient ramp: click to add a stop",
4897
+ "aria-valuemin": 0,
4898
+ "aria-valuemax": 100,
4899
+ "aria-valuenow": pct(stop.offset),
4900
+ "data-testid": "paint-gradient-ramp",
4901
+ className: "relative h-6 cursor-copy rounded ring-1 ring-slate-700",
4902
+ style: { background: paintSourceCss(value, colors) },
4903
+ onClick: (e) => {
4904
+ const rect = e.currentTarget.getBoundingClientRect();
4905
+ const r = addPaintGradientStop(value, rect.width ? (e.clientX - rect.left) / rect.width : 0.5, colors);
4906
+ if (r.index >= 0) {
4907
+ setSelected(r.index);
4908
+ onChange(r.paint);
4909
+ }
4910
+ }
4911
+ }
4912
+ ),
4913
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "relative h-4", "aria-label": "Stops", children: value.stops.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4914
+ "button",
4915
+ {
4916
+ type: "button",
4917
+ "aria-label": `Stop ${i + 1} at ${pct(s.offset)}%`,
4918
+ "aria-pressed": i === sel,
4919
+ className: `absolute top-0 h-4 w-3 -translate-x-1/2 rounded-sm ring-1 ${i === sel ? "ring-white" : "ring-slate-600"}`,
4920
+ style: { left: `${s.offset * 100}%`, background: stopHex(s.color) },
4921
+ onClick: () => setSelected(i)
4922
+ },
4923
+ i
4924
+ )) }),
4925
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap items-center gap-1", "data-testid": "paint-gradient-stop", children: [
4926
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("select", { "aria-label": "Stop colour source", className: select, value: stop.color === "paint" || stop.color === "secondary" ? stop.color : "color", onChange: (e) => patchStop({ color: e.target.value === "color" ? stopHex(stop.color) : e.target.value }), children: [
4927
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "color", children: "Colour" }),
4928
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "paint", children: "Paint colour" }),
4929
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "secondary", children: "Second colour" })
4930
+ ] }),
4931
+ stop.color !== "paint" && stop.color !== "secondary" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "color", "aria-label": "Stop colour", value: stop.color, onChange: (e) => patchStop({ color: e.target.value }), className: "h-6 w-8 rounded bg-transparent" }),
4932
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1", children: [
4933
+ "At",
4934
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "number", "aria-label": "Stop position", min: 0, max: 100, step: 1, value: pct(stop.offset), onChange: (e) => patchStop({ offset: Number(e.target.value) / 100 }), className: number }),
4935
+ "%"
4936
+ ] }),
4937
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1", children: [
4938
+ "Opacity",
4939
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "number", "aria-label": "Stop opacity", min: 0, max: 100, step: 5, value: pct(stop.opacity ?? 1), onChange: (e) => patchStop({ opacity: Number(e.target.value) / 100 }), className: number }),
4940
+ "%"
4941
+ ] }),
4942
+ sel < value.stops.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1", children: [
4943
+ "Midpoint",
4944
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "number", "aria-label": "Stop midpoint", min: 5, max: 95, step: 1, value: pct(stop.midpoint ?? 0.5), onChange: (e) => patchStop({ midpoint: Number(e.target.value) / 100 }), className: number }),
4945
+ "%"
4946
+ ] }),
4947
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: button2, disabled: value.stops.length <= 2, onClick: () => (setSelected(Math.max(0, sel - 1)), onChange(removePaintGradientStop(value, sel))), children: "Remove stop" })
4948
+ ] }),
4949
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap items-center gap-1", "data-testid": "paint-gradient-mapping", children: [
4950
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("select", { "aria-label": "Gradient follows", className: select, value: map.by, onChange: (e) => onChange({ ...value, map: paintGradientMappingFor(e.target.value, map) }), children: PAINT_GRADIENT_MAPPINGS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: m, children: PAINT_GRADIENT_MAPPING_LABELS[m] }, m)) }),
4951
+ map.by === "distance" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
4952
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "number", "aria-label": "Gradient length", min: 1, max: 1e5, value: map.length, onChange: (e) => onChange({ ...value, map: { ...map, length: Math.max(1, Number(e.target.value) || 1) } }), className: number }),
4953
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("select", { "aria-label": "Gradient length unit", className: select, value: map.unit ?? "px", onChange: (e) => onChange({ ...value, map: { ...map, unit: e.target.value } }), children: [
4954
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "px", children: "px" }),
4955
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "dabs", children: "dabs" })
4956
+ ] })
4957
+ ] }),
4958
+ map.by === "time" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "number", "aria-label": "Gradient duration", min: 1, max: 6e5, value: map.duration, onChange: (e) => onChange({ ...value, map: { ...map, duration: Math.max(1, Number(e.target.value) || 1) } }), className: number }),
4959
+ map.by === "random" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "number", "aria-label": "Dabs per pick", min: 1, max: 500, value: map.every ?? 1, onChange: (e) => onChange({ ...value, map: { ...map, every: Math.max(1, Math.round(Number(e.target.value) || 1)) } }), className: number }),
4960
+ (map.by === "distance" || map.by === "time") && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("select", { "aria-label": "Gradient repeat", className: select, value: map.repeat ?? "clamp", onChange: (e) => onChange({ ...value, map: { ...map, repeat: e.target.value } }), children: PAINT_GRADIENT_REPEATS.map((r) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: r, children: PAINT_GRADIENT_REPEAT_LABELS[r] }, r)) })
4961
+ ] }),
4962
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-1", children: [
4963
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("select", { "aria-label": "Gradient mixing", className: select, value: value.space, onChange: (e) => onChange({ ...value, space: e.target.value }), children: PAINT_GRADIENT_SPACES.map((s) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: s, children: PAINT_GRADIENT_SPACE_LABELS[s] }, s)) }),
4964
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex flex-1 items-center gap-1", children: [
4965
+ "Softness",
4966
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "range", "aria-label": "Gradient softness", min: 0, max: 1, step: 0.05, value: value.softness ?? 1, onChange: (e) => onChange({ ...value, softness: Number(e.target.value) }), className: "flex-1 accent-indigo-500" })
4967
+ ] })
4968
+ ] })
4969
+ ] });
4970
+ };
4971
+
4972
+ // src/image-editor/PaintGradientEditor.tsx
4973
+ var import_jsx_runtime24 = require("react/jsx-runtime");
4974
+ var PaintGradientEditor = (props) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PaintGradientEditorView, { ...props, kit: import_image_editor8.PAINT_GRADIENT_KIT });
4975
+
4976
+ // src/image-editor/BrushOptionsBar.tsx
4977
+ var import_jsx_runtime25 = require("react/jsx-runtime");
4845
4978
  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"}`;
4846
4979
  var BrushOptionsBar = ({ controller, className }) => {
4847
- const [, setTick] = (0, import_react40.useState)(0);
4848
- (0, import_react40.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
4849
- const [error, setError] = (0, import_react40.useState)(null);
4980
+ const [, setTick] = (0, import_react41.useState)(0);
4981
+ (0, import_react41.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
4982
+ const [error, setError] = (0, import_react41.useState)(null);
4850
4983
  const state = controller.getState();
4851
- const { brush, foreground, background, mixer, mixerLoad, retouch, cloneSource } = state.paint;
4984
+ const { brush, foreground, background, mixer, mixerLoad, retouch, cloneSource, paint } = state.paint;
4852
4985
  const tool = state.activeTool;
4853
4986
  const attempt = (fn) => {
4854
4987
  try {
@@ -4858,8 +4991,8 @@ var BrushOptionsBar = ({ controller, className }) => {
4858
4991
  setError(err instanceof Error ? err.message : String(err));
4859
4992
  }
4860
4993
  };
4861
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
4862
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor8.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4994
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
4995
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor9.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4863
4996
  "button",
4864
4997
  {
4865
4998
  type: "button",
@@ -4871,9 +5004,9 @@ var BrushOptionsBar = ({ controller, className }) => {
4871
5004
  },
4872
5005
  t.id
4873
5006
  )) }),
4874
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
4875
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1", children: [
4876
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5007
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
5008
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-1", children: [
5009
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4877
5010
  "input",
4878
5011
  {
4879
5012
  type: "color",
@@ -4883,10 +5016,10 @@ var BrushOptionsBar = ({ controller, className }) => {
4883
5016
  className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
4884
5017
  }
4885
5018
  ),
4886
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-slate-400", children: "FG" })
5019
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-slate-400", children: "FG" })
4887
5020
  ] }),
4888
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1", children: [
4889
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5021
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-1", children: [
5022
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4890
5023
  "input",
4891
5024
  {
4892
5025
  type: "color",
@@ -4896,12 +5029,24 @@ var BrushOptionsBar = ({ controller, className }) => {
4896
5029
  className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
4897
5030
  }
4898
5031
  ),
4899
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-slate-400", children: "BG" })
5032
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-slate-400", children: "BG" })
4900
5033
  ] }),
4901
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
4902
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" })
5034
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
5035
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" }),
5036
+ state.activeTool === "brush" && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5037
+ "button",
5038
+ {
5039
+ type: "button",
5040
+ "aria-pressed": paint.type === "gradient",
5041
+ title: "Gradient paint: the brush changes colour as the stroke goes",
5042
+ className: chip(paint.type === "gradient"),
5043
+ onClick: () => attempt(() => controller.setPaintOptions(paint.type === "gradient" ? { foreground } : { paint: import_image_editor10.DEFAULT_PAINT_GRADIENT })),
5044
+ children: "Gradient"
5045
+ }
5046
+ )
4903
5047
  ] }),
4904
- import_image_editor8.BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5048
+ state.activeTool === "brush" && paint.type === "gradient" && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PaintGradientEditor, { value: paint, colors: { paint: foreground, secondary: background }, onChange: (g) => attempt(() => controller.setPaintOptions({ paint: g })) }),
5049
+ import_image_editor9.BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4905
5050
  ControlSlider,
4906
5051
  {
4907
5052
  spec,
@@ -4910,21 +5055,21 @@ var BrushOptionsBar = ({ controller, className }) => {
4910
5055
  },
4911
5056
  spec.id
4912
5057
  )),
4913
- state.activeTool === "mixer" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Mixer Brush", "data-testid": "mixer-options", children: [
4914
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", children: [
4915
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5058
+ state.activeTool === "mixer" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Mixer Brush", "data-testid": "mixer-options", children: [
5059
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2", children: [
5060
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4916
5061
  "span",
4917
5062
  {
4918
5063
  "aria-label": "Brush load",
4919
- title: mixerLoad.reservoir ? `Loaded ${(0, import_image_editor8.rgbUnitToHex)(mixerLoad.reservoir)}, ${Math.round(mixerLoad.amount * 100)}% left` : "Unloaded",
5064
+ title: mixerLoad.reservoir ? `Loaded ${(0, import_image_editor9.rgbUnitToHex)(mixerLoad.reservoir)}, ${Math.round(mixerLoad.amount * 100)}% left` : "Unloaded",
4920
5065
  className: "h-6 w-6 rounded border border-slate-700",
4921
- style: { background: mixerLoad.reservoir ? (0, import_image_editor8.rgbUnitToHex)(mixerLoad.reservoir) : "transparent" }
5066
+ style: { background: mixerLoad.reservoir ? (0, import_image_editor9.rgbUnitToHex)(mixerLoad.reservoir) : "transparent" }
4922
5067
  }
4923
5068
  ),
4924
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Fill the reservoir with the foreground colour", className: chip(false), onClick: () => controller.loadMixerBrush(), children: "Load brush" }),
4925
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Empty the picked-up colour", className: chip(false), onClick: () => controller.cleanMixerBrush(), children: "Clean brush" })
5069
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", title: "Fill the reservoir with the foreground colour", className: chip(false), onClick: () => controller.loadMixerBrush(), children: "Load brush" }),
5070
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", title: "Empty the picked-up colour", className: chip(false), onClick: () => controller.cleanMixerBrush(), children: "Clean brush" })
4926
5071
  ] }),
4927
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Mixing", children: import_image_editor8.MIXER_MIXING_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5072
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Mixing", children: import_image_editor9.MIXER_MIXING_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4928
5073
  "button",
4929
5074
  {
4930
5075
  type: "button",
@@ -4936,10 +5081,10 @@ var BrushOptionsBar = ({ controller, className }) => {
4936
5081
  },
4937
5082
  m.id
4938
5083
  )) }),
4939
- import_image_editor8.MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ControlSlider, { spec, value: mixer[spec.id], onChange: (v) => controller.setPaintOptions({ mixer: { [spec.id]: v } }) }, spec.id)),
4940
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: [
4941
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4942
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5084
+ import_image_editor9.MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ControlSlider, { spec, value: mixer[spec.id], onChange: (v) => controller.setPaintOptions({ mixer: { [spec.id]: v } }) }, spec.id)),
5085
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: [
5086
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-1.5", children: [
5087
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4943
5088
  "input",
4944
5089
  {
4945
5090
  type: "checkbox",
@@ -4951,8 +5096,8 @@ var BrushOptionsBar = ({ controller, className }) => {
4951
5096
  ),
4952
5097
  "Load each stroke"
4953
5098
  ] }),
4954
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4955
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5099
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-1.5", children: [
5100
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4956
5101
  "input",
4957
5102
  {
4958
5103
  type: "checkbox",
@@ -4966,29 +5111,29 @@ var BrushOptionsBar = ({ controller, className }) => {
4966
5111
  ] })
4967
5112
  ] })
4968
5113
  ] }),
4969
- (0, import_image_editor8.isRetouchPaintTool)(tool) && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Retouch options", "data-testid": "retouch-options", children: [
4970
- (tool === "clone" || tool === "heal") && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", children: [
4971
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-slate-400", "data-testid": "clone-source", children: (0, import_image_editor8.cloneSourceLabel)(controller) }),
4972
- cloneSource && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Forget the source point", className: chip(false), onClick: () => controller.setCloneSource(null), children: "Clear source" })
5114
+ (0, import_image_editor9.isRetouchPaintTool)(tool) && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Retouch options", "data-testid": "retouch-options", children: [
5115
+ (tool === "clone" || tool === "heal") && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2", children: [
5116
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-slate-400", "data-testid": "clone-source", children: (0, import_image_editor9.cloneSourceLabel)(controller) }),
5117
+ cloneSource && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", title: "Forget the source point", className: chip(false), onClick: () => controller.setCloneSource(null), children: "Clear source" })
4973
5118
  ] }),
4974
- import_image_editor8.RETOUCH_CHOICES.filter((c) => c.tools.includes(tool)).map((choice) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": choice.label, children: [
4975
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-slate-400", children: choice.label }),
4976
- choice.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5119
+ import_image_editor9.RETOUCH_CHOICES.filter((c) => c.tools.includes(tool)).map((choice) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": choice.label, children: [
5120
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-slate-400", children: choice.label }),
5121
+ choice.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4977
5122
  "button",
4978
5123
  {
4979
5124
  type: "button",
4980
5125
  "aria-pressed": retouch[choice.id] === o.id,
4981
5126
  title: o.title,
4982
5127
  className: chip(retouch[choice.id] === o.id),
4983
- onClick: () => (0, import_image_editor8.setRetouchChoice)(controller, choice.id, o.id),
5128
+ onClick: () => (0, import_image_editor9.setRetouchChoice)(controller, choice.id, o.id),
4984
5129
  children: o.label
4985
5130
  },
4986
5131
  o.id
4987
5132
  ))
4988
5133
  ] }, choice.id)),
4989
- import_image_editor8.RETOUCH_OPTION_CONTROLS.filter((c) => c.tools.includes(tool)).map((spec) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ControlSlider, { spec, value: retouch[spec.id], onChange: (v) => controller.setPaintOptions({ retouch: { [spec.id]: v } }) }, spec.id)),
4990
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: import_image_editor8.RETOUCH_TOGGLES.filter((t) => t.tools.includes(tool)).map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4991
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5134
+ import_image_editor9.RETOUCH_OPTION_CONTROLS.filter((c) => c.tools.includes(tool)).map((spec) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ControlSlider, { spec, value: retouch[spec.id], onChange: (v) => controller.setPaintOptions({ retouch: { [spec.id]: v } }) }, spec.id)),
5135
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: import_image_editor9.RETOUCH_TOGGLES.filter((t) => t.tools.includes(tool)).map((t) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-1.5", children: [
5136
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4992
5137
  "input",
4993
5138
  {
4994
5139
  type: "checkbox",
@@ -5001,9 +5146,9 @@ var BrushOptionsBar = ({ controller, className }) => {
5001
5146
  t.label
5002
5147
  ] }, t.id)) })
5003
5148
  ] }),
5004
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
5005
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
5006
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5149
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
5150
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-1.5", children: [
5151
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5007
5152
  "input",
5008
5153
  {
5009
5154
  type: "checkbox",
@@ -5015,8 +5160,8 @@ var BrushOptionsBar = ({ controller, className }) => {
5015
5160
  ),
5016
5161
  "Pressure size"
5017
5162
  ] }),
5018
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
5019
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5163
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-1.5", children: [
5164
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5020
5165
  "input",
5021
5166
  {
5022
5167
  type: "checkbox",
@@ -5029,28 +5174,28 @@ var BrushOptionsBar = ({ controller, className }) => {
5029
5174
  "Pressure opacity"
5030
5175
  ] })
5031
5176
  ] }),
5032
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex gap-1", children: [
5033
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
5034
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
5177
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-1", children: [
5178
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
5179
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
5035
5180
  ] }),
5036
- error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5181
+ error && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5037
5182
  ] });
5038
5183
  };
5039
5184
 
5040
5185
  // src/image-editor/ColorProfilePanel.tsx
5041
- var import_react41 = require("react");
5042
- var import_image_editor9 = require("@pixerate/editor/image-editor");
5043
- var import_jsx_runtime24 = require("react/jsx-runtime");
5186
+ var import_react42 = require("react");
5187
+ var import_image_editor11 = require("@pixerate/editor/image-editor");
5188
+ var import_jsx_runtime26 = require("react/jsx-runtime");
5044
5189
  var chip2 = "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white";
5045
- var select = "rounded bg-slate-800 px-1 py-0.5 text-[11px] text-slate-200";
5190
+ var select2 = "rounded bg-slate-800 px-1 py-0.5 text-[11px] text-slate-200";
5046
5191
  var ColorProfilePanel = ({ controller, className }) => {
5047
- const [, setTick] = (0, import_react41.useState)(0);
5048
- (0, import_react41.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5049
- const [target, setTarget] = (0, import_react41.useState)("display-p3");
5050
- const [intent, setIntent] = (0, import_react41.useState)("relative");
5051
- const [bpc, setBpc] = (0, import_react41.useState)(true);
5052
- const [error, setError] = (0, import_react41.useState)(null);
5053
- const view = (0, import_image_editor9.colorPanelView)(controller);
5192
+ const [, setTick] = (0, import_react42.useState)(0);
5193
+ (0, import_react42.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5194
+ const [target, setTarget] = (0, import_react42.useState)("display-p3");
5195
+ const [intent, setIntent] = (0, import_react42.useState)("relative");
5196
+ const [bpc, setBpc] = (0, import_react42.useState)(true);
5197
+ const [error, setError] = (0, import_react42.useState)(null);
5198
+ const view = (0, import_image_editor11.colorPanelView)(controller);
5054
5199
  const attempt = (fn) => {
5055
5200
  try {
5056
5201
  setError(null);
@@ -5071,61 +5216,61 @@ var ColorProfilePanel = ({ controller, className }) => {
5071
5216
  })
5072
5217
  );
5073
5218
  };
5074
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "color-profile-panel", children: [
5075
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-2", children: [
5076
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-slate-400", children: "Profile" }),
5077
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { "data-testid": "color-profile-name", children: view.profileName })
5219
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "color-profile-panel", children: [
5220
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2", children: [
5221
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: "Profile" }),
5222
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { "data-testid": "color-profile-name", children: view.profileName })
5078
5223
  ] }),
5079
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Colour mode", children: [
5080
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-slate-400", children: "Mode" }),
5081
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("select", { "aria-label": "Colour mode", className: select, value: view.mode, onChange: (e) => attempt(() => controller.setColorMode(e.target.value)), children: import_image_editor9.COLOR_MODE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: o.id, title: o.title, children: o.label }, o.id)) }),
5082
- view.cmykProfileName && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-slate-400", children: view.cmykProfileName })
5224
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Colour mode", children: [
5225
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: "Mode" }),
5226
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("select", { "aria-label": "Colour mode", className: select2, value: view.mode, onChange: (e) => attempt(() => controller.setColorMode(e.target.value)), children: import_image_editor11.COLOR_MODE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: o.id, title: o.title, children: o.label }, o.id)) }),
5227
+ view.cmykProfileName && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: view.cmykProfileName })
5083
5228
  ] }),
5084
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Assign or convert", children: [
5085
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("select", { "aria-label": "Target profile", className: select, value: target, onChange: (e) => setTarget(e.target.value), children: import_image_editor9.WORKING_SPACE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: o.id, children: o.label }, o.id)) }),
5086
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("select", { "aria-label": "Rendering intent", className: select, value: intent, onChange: (e) => setIntent(e.target.value), children: import_image_editor9.INTENT_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: o.id, title: o.title, children: o.label }, o.id)) }),
5087
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1", children: [
5088
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", "aria-label": "Black point compensation", checked: bpc, onChange: (e) => setBpc(e.target.checked), className: "accent-indigo-500" }),
5229
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Assign or convert", children: [
5230
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("select", { "aria-label": "Target profile", className: select2, value: target, onChange: (e) => setTarget(e.target.value), children: import_image_editor11.WORKING_SPACE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: o.id, children: o.label }, o.id)) }),
5231
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("select", { "aria-label": "Rendering intent", className: select2, value: intent, onChange: (e) => setIntent(e.target.value), children: import_image_editor11.INTENT_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: o.id, title: o.title, children: o.label }, o.id)) }),
5232
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5233
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("input", { type: "checkbox", "aria-label": "Black point compensation", checked: bpc, onChange: (e) => setBpc(e.target.checked), className: "accent-indigo-500" }),
5089
5234
  "BPC"
5090
5235
  ] }),
5091
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: chip2, title: "Edit \u203A Assign Profile: keep the numbers", onClick: () => attempt(() => controller.assignProfile(target)), children: "Assign" }),
5092
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: chip2, title: "Edit \u203A Convert to Profile: keep the look", onClick: () => attempt(() => controller.convertToProfile(target, { intent, bpc })), children: "Convert" })
5236
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: chip2, title: "Edit \u203A Assign Profile: keep the numbers", onClick: () => attempt(() => controller.assignProfile(target)), children: "Assign" }),
5237
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: chip2, title: "Edit \u203A Convert to Profile: keep the look", onClick: () => attempt(() => controller.convertToProfile(target, { intent, bpc })), children: "Convert" })
5093
5238
  ] }),
5094
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Proof setup", children: [
5095
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-slate-400", children: "Proof" }),
5096
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5239
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Proof setup", children: [
5240
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: "Proof" }),
5241
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5097
5242
  "select",
5098
5243
  {
5099
5244
  "aria-label": "Proof profile",
5100
- className: select,
5245
+ className: select2,
5101
5246
  value: view.proof?.id ?? "",
5102
5247
  onChange: (e) => e.target.value ? proofWith({ id: e.target.value }) : attempt(() => controller.setProofSetup(null)),
5103
5248
  children: [
5104
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "", children: "Off" }),
5105
- import_image_editor9.PROOF_PROFILE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: o.id, children: o.label }, o.id))
5249
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: "", children: "Off" }),
5250
+ import_image_editor11.PROOF_PROFILE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: o.id, children: o.label }, o.id))
5106
5251
  ]
5107
5252
  }
5108
5253
  ),
5109
- view.proof && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
5110
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("select", { "aria-label": "Proof intent", className: select, value: view.proof.intent, onChange: (e) => proofWith({ intent: e.target.value }), children: import_image_editor9.INTENT_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: o.id, children: o.label }, o.id)) }),
5111
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1", children: [
5112
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", "aria-label": "Simulate paper colour", checked: view.proof.simulatePaper, onChange: (e) => proofWith({ simulatePaper: e.target.checked }), className: "accent-indigo-500" }),
5254
+ view.proof && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5255
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("select", { "aria-label": "Proof intent", className: select2, value: view.proof.intent, onChange: (e) => proofWith({ intent: e.target.value }), children: import_image_editor11.INTENT_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: o.id, children: o.label }, o.id)) }),
5256
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5257
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("input", { type: "checkbox", "aria-label": "Simulate paper colour", checked: view.proof.simulatePaper, onChange: (e) => proofWith({ simulatePaper: e.target.checked }), className: "accent-indigo-500" }),
5113
5258
  "Paper"
5114
5259
  ] }),
5115
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1", children: [
5116
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", "aria-label": "Gamut warning", checked: view.proof.gamutWarning, onChange: (e) => proofWith({ gamutWarning: e.target.checked }), className: "accent-indigo-500" }),
5260
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5261
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("input", { type: "checkbox", "aria-label": "Gamut warning", checked: view.proof.gamutWarning, onChange: (e) => proofWith({ gamutWarning: e.target.checked }), className: "accent-indigo-500" }),
5117
5262
  "Gamut warning"
5118
5263
  ] })
5119
5264
  ] })
5120
5265
  ] }),
5121
- error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5266
+ error && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5122
5267
  ] });
5123
5268
  };
5124
5269
 
5125
5270
  // src/image-editor/SelectionOptionsBar.tsx
5126
- var import_react42 = require("react");
5127
- var import_image_editor10 = require("@pixerate/editor/image-editor");
5128
- var import_jsx_runtime25 = require("react/jsx-runtime");
5271
+ var import_react43 = require("react");
5272
+ var import_image_editor12 = require("@pixerate/editor/image-editor");
5273
+ var import_jsx_runtime27 = require("react/jsx-runtime");
5129
5274
  var MODIFY_OPS = [
5130
5275
  { op: "grow", label: "Grow" },
5131
5276
  { op: "shrink", label: "Shrink" },
@@ -5142,20 +5287,20 @@ var SelectionOptionsBar = ({
5142
5287
  quickMask,
5143
5288
  className = ""
5144
5289
  }) => {
5145
- const [radius, setRadius] = (0, import_react42.useState)(2);
5290
+ const [radius, setRadius] = (0, import_react43.useState)(2);
5146
5291
  const set = (patch) => onOptionsChange({ ...options, ...patch });
5147
5292
  const sel = selection === void 0 ? controller.getSelection() : selection;
5148
5293
  const qm = quickMask ?? Boolean(controller.getState().quickMask);
5149
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5150
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: import_image_editor10.SELECTION_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", "aria-pressed": options.tool === t.id, className: btn(options.tool === t.id), onClick: () => set({ tool: t.id }), children: t.label }, t.id)) }),
5151
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: import_image_editor10.SELECTION_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: import_image_editor10.SELECTION_MODE_LABELS[m] }, m)) }),
5152
- options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-2", children: [
5153
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5154
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5155
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Tolerance" }),
5156
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: options.tolerance })
5294
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5295
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: import_image_editor12.SELECTION_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", "aria-pressed": options.tool === t.id, className: btn(options.tool === t.id), onClick: () => set({ tool: t.id }), children: t.label }, t.id)) }),
5296
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: import_image_editor12.SELECTION_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: import_image_editor12.SELECTION_MODE_LABELS[m] }, m)) }),
5297
+ options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-2", children: [
5298
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex flex-col gap-1", children: [
5299
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5300
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Tolerance" }),
5301
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-mono", children: options.tolerance })
5157
5302
  ] }),
5158
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5303
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5159
5304
  "input",
5160
5305
  {
5161
5306
  type: "range",
@@ -5169,17 +5314,17 @@ var SelectionOptionsBar = ({
5169
5314
  }
5170
5315
  )
5171
5316
  ] }),
5172
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5173
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
5317
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5318
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
5174
5319
  "Contiguous"
5175
5320
  ] }),
5176
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5177
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
5321
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5322
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
5178
5323
  "Sample adjusted image"
5179
5324
  ] }),
5180
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5325
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5181
5326
  "Sample",
5182
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5327
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5183
5328
  "select",
5184
5329
  {
5185
5330
  "aria-label": "Sample from",
@@ -5187,27 +5332,27 @@ var SelectionOptionsBar = ({
5187
5332
  onChange: (e) => set({ sample: e.target.value }),
5188
5333
  className: "bg-slate-800 border border-slate-700 rounded px-1 py-0.5",
5189
5334
  children: [
5190
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "composite", children: "All layers" }),
5191
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "active-layer", children: "Active layer" })
5335
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: "composite", children: "All layers" }),
5336
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: "active-layer", children: "Active layer" })
5192
5337
  ]
5193
5338
  }
5194
5339
  )
5195
5340
  ] })
5196
5341
  ] }),
5197
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5198
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
5342
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5343
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
5199
5344
  "Anti-alias"
5200
5345
  ] }),
5201
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5202
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
5203
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
5204
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
5205
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
5346
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5347
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
5348
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
5349
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
5350
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
5206
5351
  ] }),
5207
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
5208
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
5352
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
5353
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
5209
5354
  "Radius",
5210
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5355
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5211
5356
  "input",
5212
5357
  {
5213
5358
  type: "number",
@@ -5221,24 +5366,24 @@ var SelectionOptionsBar = ({
5221
5366
  }
5222
5367
  )
5223
5368
  ] }),
5224
- MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
5369
+ MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
5225
5370
  ] }),
5226
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor10.describeSelection)(sel) })
5371
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor12.describeSelection)(sel) })
5227
5372
  ] });
5228
5373
  };
5229
5374
 
5230
5375
  // src/image-editor/RefineEdgePanel.tsx
5231
- var import_react43 = require("react");
5232
- var import_image_editor11 = require("@pixerate/editor/image-editor");
5233
- var import_jsx_runtime26 = require("react/jsx-runtime");
5376
+ var import_react44 = require("react");
5377
+ var import_image_editor13 = require("@pixerate/editor/image-editor");
5378
+ var import_jsx_runtime28 = require("react/jsx-runtime");
5234
5379
  var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
5235
- 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";
5380
+ var button3 = "px-2 py-1 rounded-md border border-slate-800 bg-slate-950 text-[11px] text-slate-200 hover:text-white disabled:opacity-40";
5236
5381
  var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5237
- const [params, setParams] = (0, import_react43.useState)(DEFAULT_PARAMS);
5238
- const [busy, setBusy] = (0, import_react43.useState)(false);
5239
- const [error, setError] = (0, import_react43.useState)(null);
5240
- const [layerId, setLayerId] = (0, import_react43.useState)("");
5241
- const [newKind, setNewKind] = (0, import_react43.useState)("hueSaturation");
5382
+ const [params, setParams] = (0, import_react44.useState)(DEFAULT_PARAMS);
5383
+ const [busy, setBusy] = (0, import_react44.useState)(false);
5384
+ const [error, setError] = (0, import_react44.useState)(null);
5385
+ const [layerId, setLayerId] = (0, import_react44.useState)("");
5386
+ const [newKind, setNewKind] = (0, import_react44.useState)("hueSaturation");
5242
5387
  const sel = selection === void 0 ? controller.getSelection() : selection;
5243
5388
  const list = layers ?? controller.getAdjustmentLayers();
5244
5389
  const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
@@ -5253,17 +5398,17 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5253
5398
  setBusy(false);
5254
5399
  }
5255
5400
  };
5256
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5257
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
5258
- import_image_editor11.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex flex-col gap-1", children: [
5259
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5260
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: c.label }),
5261
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono", children: [
5401
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5402
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
5403
+ import_image_editor13.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex flex-col gap-1", children: [
5404
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5405
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { children: c.label }),
5406
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "font-mono", children: [
5262
5407
  params[c.id],
5263
5408
  c.unit
5264
5409
  ] })
5265
5410
  ] }),
5266
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5411
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5267
5412
  "input",
5268
5413
  {
5269
5414
  type: "range",
@@ -5277,67 +5422,67 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5277
5422
  }
5278
5423
  )
5279
5424
  ] }, c.id)),
5280
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5281
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
5425
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5426
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
5282
5427
  "Smart Radius"
5283
5428
  ] }),
5284
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex gap-1", children: [
5285
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
5286
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
5429
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex gap-1", children: [
5430
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: button3, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
5431
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: button3, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
5287
5432
  ] }),
5288
- error && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
5289
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
5290
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex gap-1 items-center", children: [
5291
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5433
+ error && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
5434
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
5435
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex gap-1 items-center", children: [
5436
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5292
5437
  "select",
5293
5438
  {
5294
5439
  "aria-label": "New masked layer kind",
5295
5440
  value: newKind,
5296
5441
  onChange: (e) => setNewKind(e.target.value),
5297
5442
  className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
5298
- children: import_image_editor11.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: k.kind, children: k.label }, k.kind))
5443
+ children: import_image_editor13.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("option", { value: k.kind, children: k.label }, k.kind))
5299
5444
  }
5300
5445
  ),
5301
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5446
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5302
5447
  "button",
5303
5448
  {
5304
5449
  type: "button",
5305
- className: button2,
5450
+ className: button3,
5306
5451
  disabled: !sel,
5307
- onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor11.layerMaskFromSelection)(sel) })),
5452
+ onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor13.layerMaskFromSelection)(sel) })),
5308
5453
  children: "New Masked Layer"
5309
5454
  }
5310
5455
  )
5311
5456
  ] }),
5312
- list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-2", children: [
5313
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5457
+ list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col gap-2", children: [
5458
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5314
5459
  "select",
5315
5460
  {
5316
5461
  "aria-label": "Mask layer",
5317
5462
  value: target.id,
5318
5463
  onChange: (e) => setLayerId(e.target.value),
5319
5464
  className: "bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
5320
- children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("option", { value: l.id, children: [
5321
- l.name || (0, import_image_editor11.adjustmentKindLabel)(l.kind),
5465
+ children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("option", { value: l.id, children: [
5466
+ l.name || (0, import_image_editor13.adjustmentKindLabel)(l.kind),
5322
5467
  l.mask ? " (masked)" : ""
5323
5468
  ] }, l.id))
5324
5469
  }
5325
5470
  ),
5326
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5327
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
5328
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
5329
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
5471
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5472
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: button3, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
5473
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: button3, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
5474
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: button3, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
5330
5475
  ] }),
5331
- target.mask && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5332
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex flex-col gap-1", children: [
5333
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5334
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Density" }),
5335
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono", children: [
5476
+ target.mask && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
5477
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex flex-col gap-1", children: [
5478
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5479
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { children: "Density" }),
5480
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "font-mono", children: [
5336
5481
  Math.round((target.mask.density ?? 1) * 100),
5337
5482
  "%"
5338
5483
  ] })
5339
5484
  ] }),
5340
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5485
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5341
5486
  "input",
5342
5487
  {
5343
5488
  type: "range",
@@ -5351,15 +5496,15 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5351
5496
  }
5352
5497
  )
5353
5498
  ] }),
5354
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex flex-col gap-1", children: [
5355
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5356
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Mask Feather" }),
5357
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono", children: [
5499
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex flex-col gap-1", children: [
5500
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5501
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { children: "Mask Feather" }),
5502
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "font-mono", children: [
5358
5503
  target.mask.feather ?? 0,
5359
5504
  "px"
5360
5505
  ] })
5361
5506
  ] }),
5362
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5507
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5363
5508
  "input",
5364
5509
  {
5365
5510
  type: "range",
@@ -5379,14 +5524,14 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5379
5524
  };
5380
5525
 
5381
5526
  // src/image-editor/FreeTransformOptionsBar.tsx
5382
- var import_react44 = require("react");
5383
- var import_image_editor12 = require("@pixerate/editor/image-editor");
5384
- var import_jsx_runtime27 = require("react/jsx-runtime");
5527
+ var import_react45 = require("react");
5528
+ var import_image_editor14 = require("@pixerate/editor/image-editor");
5529
+ var import_jsx_runtime29 = require("react/jsx-runtime");
5385
5530
  var chip3 = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
5386
5531
  var round = (v, unit) => unit === "px" ? Math.round(v * 10) / 10 : Math.round(v * 100) / 100;
5387
5532
  var FreeTransformOptionsBar = ({ tool, className }) => {
5388
- const [, setTick] = (0, import_react44.useState)(0);
5389
- (0, import_react44.useEffect)(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
5533
+ const [, setTick] = (0, import_react45.useState)(0);
5534
+ (0, import_react45.useEffect)(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
5390
5535
  const bar = tool.bar();
5391
5536
  if (!tool.active || !bar) return null;
5392
5537
  const warp = tool.warpBar();
@@ -5398,17 +5543,17 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5398
5543
  const v = Number(raw);
5399
5544
  if (raw.trim() !== "" && Number.isFinite(v) && Math.abs(v - bar[field]) > 1e-9) tool.setField(field, v);
5400
5545
  };
5401
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: `flex flex-wrap items-center gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "free-transform-options", role: "toolbar", "aria-label": "Free Transform options", children: [
5402
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Transform mode", children: import_image_editor12.FREE_TRANSFORM_MODE_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", title: m.title, "aria-pressed": tool.mode === m.id, className: chip3(tool.mode === m.id), onClick: () => tool.setMode(m.id), children: m.label }, m.id)) }),
5403
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "grid grid-cols-3 gap-px", role: "group", "aria-label": "Reference point", children: import_image_editor12.TRANSFORM_ANCHORS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", "aria-label": `Reference point ${a}`, title: `Reference point: ${a}`, className: "h-2.5 w-2.5 rounded-sm bg-slate-700 hover:bg-indigo-500", onClick: () => tool.setReference(a) }, a)) }),
5404
- tool.mode === "warp" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": "Warp options", children: [
5405
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5406
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: "Warp" }),
5407
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("select", { "aria-label": "Warp style", value: warp.style, onChange: (e) => tool.setWarp({ style: e.target.value }), className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5", children: import_image_editor12.WARP_STYLE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: o.id, children: o.label }, o.id)) })
5546
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: `flex flex-wrap items-center gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "free-transform-options", role: "toolbar", "aria-label": "Free Transform options", children: [
5547
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Transform mode", children: import_image_editor14.FREE_TRANSFORM_MODE_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", title: m.title, "aria-pressed": tool.mode === m.id, className: chip3(tool.mode === m.id), onClick: () => tool.setMode(m.id), children: m.label }, m.id)) }),
5548
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "grid grid-cols-3 gap-px", role: "group", "aria-label": "Reference point", children: import_image_editor14.TRANSFORM_ANCHORS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", "aria-label": `Reference point ${a}`, title: `Reference point: ${a}`, className: "h-2.5 w-2.5 rounded-sm bg-slate-700 hover:bg-indigo-500", onClick: () => tool.setReference(a) }, a)) }),
5549
+ tool.mode === "warp" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": "Warp options", children: [
5550
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-1", children: [
5551
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-slate-400", children: "Warp" }),
5552
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("select", { "aria-label": "Warp style", value: warp.style, onChange: (e) => tool.setWarp({ style: e.target.value }), className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5", children: import_image_editor14.WARP_STYLE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: o.id, children: o.label }, o.id)) })
5408
5553
  ] }),
5409
- ["bend", "horizontal", "vertical"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5410
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: k === "bend" ? "Bend" : k === "horizontal" ? "H" : "V" }),
5411
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5554
+ ["bend", "horizontal", "vertical"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-1", children: [
5555
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-slate-400", children: k === "bend" ? "Bend" : k === "horizontal" ? "H" : "V" }),
5556
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5412
5557
  "input",
5413
5558
  {
5414
5559
  type: "number",
@@ -5429,9 +5574,9 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5429
5574
  },
5430
5575
  `${k}:${warp[k]}`
5431
5576
  ),
5432
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-500", children: "%" })
5577
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-slate-500", children: "%" })
5433
5578
  ] }, k)),
5434
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5579
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5435
5580
  "button",
5436
5581
  {
5437
5582
  type: "button",
@@ -5443,26 +5588,26 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5443
5588
  children: "Vertical"
5444
5589
  }
5445
5590
  ),
5446
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5447
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: "Grid" }),
5448
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5591
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-1", children: [
5592
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-slate-400", children: "Grid" }),
5593
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5449
5594
  "select",
5450
5595
  {
5451
5596
  "aria-label": "Warp grid",
5452
- value: import_image_editor12.WARP_GRID_OPTIONS.find((g) => g.columns === warp.columns && g.rows === warp.rows)?.id ?? "1x1",
5597
+ value: import_image_editor14.WARP_GRID_OPTIONS.find((g) => g.columns === warp.columns && g.rows === warp.rows)?.id ?? "1x1",
5453
5598
  onChange: (e) => {
5454
- const g = import_image_editor12.WARP_GRID_OPTIONS.find((o) => o.id === e.target.value);
5599
+ const g = import_image_editor14.WARP_GRID_OPTIONS.find((o) => o.id === e.target.value);
5455
5600
  tool.setWarp({ columns: g.columns, rows: g.rows });
5456
5601
  },
5457
5602
  className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
5458
- children: import_image_editor12.WARP_GRID_OPTIONS.map((g) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: g.id, children: g.label }, g.id))
5603
+ children: import_image_editor14.WARP_GRID_OPTIONS.map((g) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: g.id, children: g.label }, g.id))
5459
5604
  }
5460
5605
  )
5461
5606
  ] })
5462
5607
  ] }),
5463
- tool.mode !== "warp" && import_image_editor12.FREE_TRANSFORM_FIELDS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", title: f.title, children: [
5464
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: f.label }),
5465
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5608
+ tool.mode !== "warp" && import_image_editor14.FREE_TRANSFORM_FIELDS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-1", title: f.title, children: [
5609
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-slate-400", children: f.label }),
5610
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5466
5611
  "input",
5467
5612
  {
5468
5613
  type: "number",
@@ -5482,8 +5627,8 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5482
5627
  },
5483
5628
  `${f.id}:${round(bar[f.id], f.unit)}`
5484
5629
  ),
5485
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-500", children: f.unit }),
5486
- f.id === "scaleX" && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5630
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-slate-500", children: f.unit }),
5631
+ f.id === "scaleX" && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5487
5632
  "button",
5488
5633
  {
5489
5634
  type: "button",
@@ -5498,34 +5643,34 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5498
5643
  }
5499
5644
  )
5500
5645
  ] }, f.id)),
5501
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5502
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: "Interpolation" }),
5503
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5646
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-1", children: [
5647
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-slate-400", children: "Interpolation" }),
5648
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5504
5649
  "select",
5505
5650
  {
5506
5651
  "aria-label": "Interpolation",
5507
5652
  value: tool.interpolation,
5508
5653
  onChange: (e) => tool.setInterpolation(e.target.value),
5509
5654
  className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
5510
- children: import_image_editor12.INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
5655
+ children: import_image_editor14.INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
5511
5656
  }
5512
5657
  )
5513
5658
  ] }),
5514
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", title: "Commit (Enter)", className: "px-2 py-1 rounded bg-emerald-600 text-white hover:bg-emerald-500", onClick: () => tool.commit(), children: "Commit" }),
5515
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", title: "Cancel (Esc)", className: chip3(false), onClick: () => tool.cancel(), children: "Cancel" }),
5516
- tool.error && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { role: "alert", className: "text-rose-400", children: tool.error })
5659
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", title: "Commit (Enter)", className: "px-2 py-1 rounded bg-emerald-600 text-white hover:bg-emerald-500", onClick: () => tool.commit(), children: "Commit" }),
5660
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", title: "Cancel (Esc)", className: chip3(false), onClick: () => tool.cancel(), children: "Cancel" }),
5661
+ tool.error && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { role: "alert", className: "text-rose-400", children: tool.error })
5517
5662
  ] });
5518
5663
  };
5519
5664
 
5520
5665
  // src/image-editor/ShapeOptionsBar.tsx
5521
- var import_react45 = require("react");
5522
- var import_image_editor13 = require("@pixerate/editor/image-editor");
5523
- var import_jsx_runtime28 = require("react/jsx-runtime");
5666
+ var import_react46 = require("react");
5667
+ var import_image_editor15 = require("@pixerate/editor/image-editor");
5668
+ var import_jsx_runtime30 = require("react/jsx-runtime");
5524
5669
  var chip4 = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
5525
5670
  var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5526
- const [, setTick] = (0, import_react45.useState)(0);
5527
- (0, import_react45.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5528
- const [error, setError] = (0, import_react45.useState)(null);
5671
+ const [, setTick] = (0, import_react46.useState)(0);
5672
+ (0, import_react46.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5673
+ const [error, setError] = (0, import_react46.useState)(null);
5529
5674
  const active = controller.getActiveLayer();
5530
5675
  const shapeId = active?.type === "shape" ? active.id : null;
5531
5676
  const set = (change) => {
@@ -5533,19 +5678,19 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5533
5678
  if (!shapeId) return;
5534
5679
  try {
5535
5680
  setError(null);
5536
- (0, import_image_editor13.applyShapeOptions)(controller, shapeId, change);
5681
+ (0, import_image_editor15.applyShapeOptions)(controller, shapeId, change);
5537
5682
  } catch (e) {
5538
5683
  setError(e instanceof Error ? e.message : String(e));
5539
5684
  }
5540
5685
  };
5541
5686
  const num = (v, min, max) => Math.max(min, Math.min(max, Number(v) || min));
5542
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "shape-options", children: [
5543
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Shape kind", children: import_image_editor13.LIVE_SHAPE_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", "aria-pressed": options.kind === k, className: chip4(options.kind === k), onClick: () => onChange({ ...options, kind: k }), children: import_image_editor13.SHAPE_KIND_LABELS[k] }, k)) }),
5544
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5545
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5546
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "checkbox", "aria-label": "Fill", checked: options.fill !== null, onChange: (e) => set({ fill: e.target.checked ? "#4f46e5" : null }) }),
5687
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "shape-options", children: [
5688
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Shape kind", children: import_image_editor15.LIVE_SHAPE_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", "aria-pressed": options.kind === k, className: chip4(options.kind === k), onClick: () => onChange({ ...options, kind: k }), children: import_image_editor15.SHAPE_KIND_LABELS[k] }, k)) }),
5689
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5690
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1", children: [
5691
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("input", { type: "checkbox", "aria-label": "Fill", checked: options.fill !== null, onChange: (e) => set({ fill: e.target.checked ? "#4f46e5" : null }) }),
5547
5692
  "Fill",
5548
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5693
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5549
5694
  "input",
5550
5695
  {
5551
5696
  type: "color",
@@ -5557,10 +5702,10 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5557
5702
  }
5558
5703
  )
5559
5704
  ] }),
5560
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5561
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "checkbox", "aria-label": "Stroke", checked: options.stroke !== null, onChange: (e) => set({ stroke: e.target.checked ? "#000000" : null }) }),
5705
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1", children: [
5706
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("input", { type: "checkbox", "aria-label": "Stroke", checked: options.stroke !== null, onChange: (e) => set({ stroke: e.target.checked ? "#000000" : null }) }),
5562
5707
  "Stroke",
5563
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5708
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5564
5709
  "input",
5565
5710
  {
5566
5711
  type: "color",
@@ -5572,9 +5717,9 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5572
5717
  }
5573
5718
  )
5574
5719
  ] }),
5575
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5720
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1", children: [
5576
5721
  "Width",
5577
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5722
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5578
5723
  "input",
5579
5724
  {
5580
5725
  type: "number",
@@ -5588,23 +5733,23 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5588
5733
  )
5589
5734
  ] })
5590
5735
  ] }),
5591
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5592
- options.kind === "rect" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5736
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5737
+ options.kind === "rect" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1", children: [
5593
5738
  "Radius",
5594
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "number", "aria-label": "Corner radius", min: 0, max: 1e3, value: options.radius, onChange: (e) => set({ radius: num(e.target.value, 0, 1e3) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5739
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("input", { type: "number", "aria-label": "Corner radius", min: 0, max: 1e3, value: options.radius, onChange: (e) => set({ radius: num(e.target.value, 0, 1e3) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5595
5740
  ] }),
5596
- options.kind === "polygon" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5741
+ options.kind === "polygon" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1", children: [
5597
5742
  "Sides",
5598
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "number", "aria-label": "Sides", min: 3, max: 100, value: options.sides, onChange: (e) => set({ sides: num(e.target.value, 3, 100) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5743
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("input", { type: "number", "aria-label": "Sides", min: 3, max: 100, value: options.sides, onChange: (e) => set({ sides: num(e.target.value, 3, 100) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5599
5744
  ] }),
5600
- options.kind === "star" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
5601
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5745
+ options.kind === "star" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
5746
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1", children: [
5602
5747
  "Points",
5603
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "number", "aria-label": "Points", min: 3, max: 100, value: options.points, onChange: (e) => set({ points: num(e.target.value, 3, 100) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5748
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("input", { type: "number", "aria-label": "Points", min: 3, max: 100, value: options.points, onChange: (e) => set({ points: num(e.target.value, 3, 100) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5604
5749
  ] }),
5605
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5750
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1", children: [
5606
5751
  "Inner",
5607
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5752
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
5608
5753
  "input",
5609
5754
  {
5610
5755
  type: "range",
@@ -5619,33 +5764,33 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5619
5764
  )
5620
5765
  ] })
5621
5766
  ] }),
5622
- options.kind === "line" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
5623
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5767
+ options.kind === "line" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
5768
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1", children: [
5624
5769
  "Weight",
5625
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "number", "aria-label": "Line weight", min: 1, max: 200, value: options.weight, onChange: (e) => set({ weight: num(e.target.value, 1, 200) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5770
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("input", { type: "number", "aria-label": "Line weight", min: 1, max: 200, value: options.weight, onChange: (e) => set({ weight: num(e.target.value, 1, 200) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5626
5771
  ] }),
5627
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5628
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "checkbox", "aria-label": "Arrowhead", checked: options.arrow, onChange: (e) => set({ arrow: e.target.checked }) }),
5772
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-1", children: [
5773
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("input", { type: "checkbox", "aria-label": "Arrowhead", checked: options.arrow, onChange: (e) => set({ arrow: e.target.checked }) }),
5629
5774
  "Arrowhead"
5630
5775
  ] })
5631
5776
  ] })
5632
5777
  ] }),
5633
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-[10px] text-slate-500", children: "Drag on the image to draw. Shift: square, circle or 45\xB0 line. Alt: from the centre." }),
5634
- error && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5778
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-[10px] text-slate-500", children: "Drag on the image to draw. Shift: square, circle or 45\xB0 line. Alt: from the centre." }),
5779
+ error && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5635
5780
  ] });
5636
5781
  };
5637
5782
 
5638
5783
  // src/image-editor/TypeOptionsBar.tsx
5639
- var import_react46 = require("react");
5640
- var import_image_editor14 = require("@pixerate/editor/image-editor");
5641
- var import_jsx_runtime29 = require("react/jsx-runtime");
5784
+ var import_react47 = require("react");
5785
+ var import_image_editor16 = require("@pixerate/editor/image-editor");
5786
+ var import_jsx_runtime31 = require("react/jsx-runtime");
5642
5787
  var chip5 = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
5643
5788
  var ALIGN_LABELS = { left: "Left", center: "Centre", right: "Right", justify: "Justify" };
5644
5789
  var TypeOptionsBar = ({ controller, options, onChange, session, className }) => {
5645
- const [, setTick] = (0, import_react46.useState)(0);
5646
- (0, import_react46.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5647
- (0, import_react46.useEffect)(() => session?.subscribe(() => setTick((n) => n + 1)), [session]);
5648
- const [error, setError] = (0, import_react46.useState)(null);
5790
+ const [, setTick] = (0, import_react47.useState)(0);
5791
+ (0, import_react47.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5792
+ (0, import_react47.useEffect)(() => session?.subscribe(() => setTick((n) => n + 1)), [session]);
5793
+ const [error, setError] = (0, import_react47.useState)(null);
5649
5794
  const active = controller.getActiveLayer();
5650
5795
  const typeId = !session && active?.type === "type" ? active.id : null;
5651
5796
  const here = session?.alive ? session.styleHere() : {};
@@ -5677,11 +5822,11 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
5677
5822
  setError(e instanceof Error ? e.message : String(e));
5678
5823
  }
5679
5824
  };
5680
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "type-options", children: [
5681
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
5682
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-1", children: [
5825
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "type-options", children: [
5826
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
5827
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("label", { className: "flex items-center gap-1", children: [
5683
5828
  "Font",
5684
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5829
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5685
5830
  "input",
5686
5831
  {
5687
5832
  list: "pixerate-type-fonts",
@@ -5691,11 +5836,11 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
5691
5836
  className: "w-32 rounded border border-slate-700 bg-slate-950 px-1 py-0.5"
5692
5837
  }
5693
5838
  ),
5694
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("datalist", { id: "pixerate-type-fonts", children: fonts.map((f) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: f }, f)) })
5839
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("datalist", { id: "pixerate-type-fonts", children: fonts.map((f) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("option", { value: f }, f)) })
5695
5840
  ] }),
5696
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-1", children: [
5841
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("label", { className: "flex items-center gap-1", children: [
5697
5842
  "Size",
5698
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5843
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
5699
5844
  "input",
5700
5845
  {
5701
5846
  type: "number",
@@ -5708,24 +5853,24 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
5708
5853
  }
5709
5854
  )
5710
5855
  ] }),
5711
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", "aria-pressed": shown.fontWeight >= 600, className: `${chip5(shown.fontWeight >= 600)} font-bold`, onClick: () => style({ fontWeight: shown.fontWeight >= 600 ? 400 : 700 }), children: "B" }),
5712
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", "aria-pressed": shown.italic, className: `${chip5(shown.italic)} italic`, onClick: () => style({ italic: !shown.italic }), children: "I" }),
5713
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("input", { type: "color", "aria-label": "Text colour", value: shown.color, onChange: (e) => style({ color: e.target.value }), className: "h-6 w-8 rounded border border-slate-700 bg-transparent" })
5856
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", "aria-pressed": shown.fontWeight >= 600, className: `${chip5(shown.fontWeight >= 600)} font-bold`, onClick: () => style({ fontWeight: shown.fontWeight >= 600 ? 400 : 700 }), children: "B" }),
5857
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", "aria-pressed": shown.italic, className: `${chip5(shown.italic)} italic`, onClick: () => style({ italic: !shown.italic }), children: "I" }),
5858
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("input", { type: "color", "aria-label": "Text colour", value: shown.color, onChange: (e) => style({ color: e.target.value }), className: "h-6 w-8 rounded border border-slate-700 bg-transparent" })
5714
5859
  ] }),
5715
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Alignment", children: import_image_editor14.TEXT_ALIGNS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", "aria-pressed": options.align === a, className: chip5(options.align === a), onClick: () => style({ align: a }), children: ALIGN_LABELS[a] }, a)) }),
5716
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-[10px] text-slate-500", children: "Click to type point text, drag for a paragraph box, click text to edit it. Esc finishes." }),
5717
- missing.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("p", { role: "status", className: "text-amber-400", "data-testid": "type-missing-fonts", children: [
5860
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Alignment", children: import_image_editor16.TEXT_ALIGNS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", "aria-pressed": options.align === a, className: chip5(options.align === a), onClick: () => style({ align: a }), children: ALIGN_LABELS[a] }, a)) }),
5861
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "text-[10px] text-slate-500", children: "Click to type point text, drag for a paragraph box, click text to edit it. Esc finishes." }),
5862
+ missing.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("p", { role: "status", className: "text-amber-400", "data-testid": "type-missing-fonts", children: [
5718
5863
  "Missing ",
5719
5864
  missing.length === 1 ? "font" : "fonts",
5720
5865
  ": ",
5721
5866
  missing.join(", ")
5722
5867
  ] }),
5723
- error && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5868
+ error && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5724
5869
  ] });
5725
5870
  };
5726
5871
 
5727
5872
  // src/image-editor/ImageEditor.tsx
5728
- var import_jsx_runtime30 = require("react/jsx-runtime");
5873
+ var import_jsx_runtime32 = require("react/jsx-runtime");
5729
5874
  var ImageEditor = ({
5730
5875
  editor: externalEditor,
5731
5876
  src,
@@ -5740,65 +5885,65 @@ var ImageEditor = ({
5740
5885
  const internalEditor = useImageEditor({ image: src });
5741
5886
  const editor = externalEditor || internalEditor;
5742
5887
  const { state, controller } = editor;
5743
- const legacyProcess = (0, import_image_editor15.normalizeProcessVersion)(state.adjustments.process) < import_image_editor15.LATEST_PROCESS_VERSION;
5744
- const canvasRef = (0, import_react47.useRef)(null);
5745
- const containerRef = (0, import_react47.useRef)(null);
5746
- const [activeTab, setActiveTab] = (0, import_react47.useState)("crop");
5747
- const [activeCropRatio, setActiveCropRatio] = (0, import_react47.useState)(null);
5748
- const [selectionOptions, setSelectionOptions] = (0, import_react47.useState)(import_image_editor15.DEFAULT_SELECTION_TOOL_OPTIONS);
5749
- const selectionOptionsRef = (0, import_react47.useRef)(selectionOptions);
5888
+ const legacyProcess = (0, import_image_editor17.normalizeProcessVersion)(state.adjustments.process) < import_image_editor17.LATEST_PROCESS_VERSION;
5889
+ const canvasRef = (0, import_react48.useRef)(null);
5890
+ const containerRef = (0, import_react48.useRef)(null);
5891
+ const [activeTab, setActiveTab] = (0, import_react48.useState)("crop");
5892
+ const [activeCropRatio, setActiveCropRatio] = (0, import_react48.useState)(null);
5893
+ const [selectionOptions, setSelectionOptions] = (0, import_react48.useState)(import_image_editor17.DEFAULT_SELECTION_TOOL_OPTIONS);
5894
+ const selectionOptionsRef = (0, import_react48.useRef)(selectionOptions);
5750
5895
  selectionOptionsRef.current = selectionOptions;
5751
- const selectionGestureRef = (0, import_react47.useRef)(null);
5896
+ const selectionGestureRef = (0, import_react48.useRef)(null);
5752
5897
  if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
5753
- selectionGestureRef.current = new import_image_editor15.SelectionGesture(controller, () => selectionOptionsRef.current);
5898
+ selectionGestureRef.current = new import_image_editor17.SelectionGesture(controller, () => selectionOptionsRef.current);
5754
5899
  }
5755
- const selectionDraftRef = (0, import_react47.useRef)(null);
5756
- const [selectionError, setSelectionError] = (0, import_react47.useState)(null);
5757
- const paintGestureRef = (0, import_react47.useRef)(null);
5758
- const paintControllerRef = (0, import_react47.useRef)(controller);
5900
+ const selectionDraftRef = (0, import_react48.useRef)(null);
5901
+ const [selectionError, setSelectionError] = (0, import_react48.useState)(null);
5902
+ const paintGestureRef = (0, import_react48.useRef)(null);
5903
+ const paintControllerRef = (0, import_react48.useRef)(controller);
5759
5904
  if (!paintGestureRef.current || paintControllerRef.current !== controller) {
5760
- paintGestureRef.current = new import_image_editor15.PaintGesture(controller);
5905
+ paintGestureRef.current = new import_image_editor17.PaintGesture(controller);
5761
5906
  paintControllerRef.current = controller;
5762
5907
  }
5763
- const brushCursorRef = (0, import_react47.useRef)(null);
5764
- const [paintError, setPaintError] = (0, import_react47.useState)(null);
5765
- const transformToolRef = (0, import_react47.useRef)(null);
5766
- const transformControllerRef = (0, import_react47.useRef)(controller);
5908
+ const brushCursorRef = (0, import_react48.useRef)(null);
5909
+ const [paintError, setPaintError] = (0, import_react48.useState)(null);
5910
+ const transformToolRef = (0, import_react48.useRef)(null);
5911
+ const transformControllerRef = (0, import_react48.useRef)(controller);
5767
5912
  if (!transformToolRef.current || transformControllerRef.current !== controller) {
5768
5913
  transformToolRef.current?.cancel();
5769
- transformToolRef.current = new import_image_editor15.FreeTransformTool(controller, {
5914
+ transformToolRef.current = new import_image_editor17.FreeTransformTool(controller, {
5770
5915
  schedule: (run) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(run) : run()
5771
5916
  });
5772
5917
  transformControllerRef.current = controller;
5773
5918
  }
5774
5919
  const transformTool = transformToolRef.current;
5775
- const [, setTransformTick] = (0, import_react47.useState)(0);
5776
- const [transformCursor, setTransformCursor] = (0, import_react47.useState)("default");
5777
- const [shapeOptions, setShapeOptions] = (0, import_react47.useState)(import_image_editor15.DEFAULT_SHAPE_TOOL_OPTIONS);
5778
- const shapeOptionsRef = (0, import_react47.useRef)(shapeOptions);
5920
+ const [, setTransformTick] = (0, import_react48.useState)(0);
5921
+ const [transformCursor, setTransformCursor] = (0, import_react48.useState)("default");
5922
+ const [shapeOptions, setShapeOptions] = (0, import_react48.useState)(import_image_editor17.DEFAULT_SHAPE_TOOL_OPTIONS);
5923
+ const shapeOptionsRef = (0, import_react48.useRef)(shapeOptions);
5779
5924
  shapeOptionsRef.current = shapeOptions;
5780
- const [typeOptions, setTypeOptions] = (0, import_react47.useState)(import_image_editor15.DEFAULT_TYPE_TOOL_OPTIONS);
5781
- const typeOptionsRef = (0, import_react47.useRef)(typeOptions);
5925
+ const [typeOptions, setTypeOptions] = (0, import_react48.useState)(import_image_editor17.DEFAULT_TYPE_TOOL_OPTIONS);
5926
+ const typeOptionsRef = (0, import_react48.useRef)(typeOptions);
5782
5927
  typeOptionsRef.current = typeOptions;
5783
- const shapeGestureRef = (0, import_react47.useRef)(null);
5784
- const typeToolRef = (0, import_react47.useRef)(null);
5785
- const shapeTypeControllerRef = (0, import_react47.useRef)(controller);
5928
+ const shapeGestureRef = (0, import_react48.useRef)(null);
5929
+ const typeToolRef = (0, import_react48.useRef)(null);
5930
+ const shapeTypeControllerRef = (0, import_react48.useRef)(controller);
5786
5931
  if (!shapeGestureRef.current || !typeToolRef.current || shapeTypeControllerRef.current !== controller) {
5787
5932
  typeToolRef.current?.finish();
5788
- shapeGestureRef.current = new import_image_editor15.ShapeDrawGesture(controller, () => shapeOptionsRef.current);
5789
- typeToolRef.current = new import_image_editor15.TypeToolGesture(controller, () => typeOptionsRef.current);
5933
+ shapeGestureRef.current = new import_image_editor17.ShapeDrawGesture(controller, () => shapeOptionsRef.current);
5934
+ typeToolRef.current = new import_image_editor17.TypeToolGesture(controller, () => typeOptionsRef.current);
5790
5935
  shapeTypeControllerRef.current = controller;
5791
5936
  }
5792
- const typeInputRef = (0, import_react47.useRef)(null);
5793
- const [typeSession, setTypeSession] = (0, import_react47.useState)(typeToolRef.current.session);
5794
- const [shapeTypeError, setShapeTypeError] = (0, import_react47.useState)(null);
5795
- const [inpaintPrompt, setInpaintPrompt] = (0, import_react47.useState)("");
5796
- const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react47.useState)("annotations");
5797
- const [isRemovingBg, setIsRemovingBg] = (0, import_react47.useState)(false);
5798
- const [isInpainting, setIsInpainting] = (0, import_react47.useState)(false);
5799
- const [aiError, setAiError] = (0, import_react47.useState)(null);
5800
- const [aiSuccess, setAiSuccess] = (0, import_react47.useState)(null);
5801
- const [aiTarget, setAiTarget] = (0, import_react47.useState)("auto");
5937
+ const typeInputRef = (0, import_react48.useRef)(null);
5938
+ const [typeSession, setTypeSession] = (0, import_react48.useState)(typeToolRef.current.session);
5939
+ const [shapeTypeError, setShapeTypeError] = (0, import_react48.useState)(null);
5940
+ const [inpaintPrompt, setInpaintPrompt] = (0, import_react48.useState)("");
5941
+ const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react48.useState)("annotations");
5942
+ const [isRemovingBg, setIsRemovingBg] = (0, import_react48.useState)(false);
5943
+ const [isInpainting, setIsInpainting] = (0, import_react48.useState)(false);
5944
+ const [aiError, setAiError] = (0, import_react48.useState)(null);
5945
+ const [aiSuccess, setAiSuccess] = (0, import_react48.useState)(null);
5946
+ const [aiTarget, setAiTarget] = (0, import_react48.useState)("auto");
5802
5947
  const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
5803
5948
  const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
5804
5949
  const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
@@ -5861,18 +6006,18 @@ var ImageEditor = ({
5861
6006
  setIsInpainting(false);
5862
6007
  }
5863
6008
  };
5864
- const [activeColor, setActiveColor] = (0, import_react47.useState)("#ef4444");
5865
- const [strokeWidth, setStrokeWidth] = (0, import_react47.useState)(3);
5866
- const [fontSize, setFontSize] = (0, import_react47.useState)(24);
5867
- const [textInput, setTextInput] = (0, import_react47.useState)("");
5868
- const draftAnnotationRef = (0, import_react47.useRef)(null);
5869
- const draftCropRef = (0, import_react47.useRef)(null);
5870
- const cropDragInfoRef = (0, import_react47.useRef)(null);
5871
- const annotationDragInfoRef = (0, import_react47.useRef)(null);
5872
- const isDrawingRef = (0, import_react47.useRef)(false);
5873
- const currentPathRef = (0, import_react47.useRef)([]);
5874
- const dragStartPointRef = (0, import_react47.useRef)(null);
5875
- const renderCanvas = (0, import_react47.useCallback)(
6009
+ const [activeColor, setActiveColor] = (0, import_react48.useState)("#ef4444");
6010
+ const [strokeWidth, setStrokeWidth] = (0, import_react48.useState)(3);
6011
+ const [fontSize, setFontSize] = (0, import_react48.useState)(24);
6012
+ const [textInput, setTextInput] = (0, import_react48.useState)("");
6013
+ const draftAnnotationRef = (0, import_react48.useRef)(null);
6014
+ const draftCropRef = (0, import_react48.useRef)(null);
6015
+ const cropDragInfoRef = (0, import_react48.useRef)(null);
6016
+ const annotationDragInfoRef = (0, import_react48.useRef)(null);
6017
+ const isDrawingRef = (0, import_react48.useRef)(false);
6018
+ const currentPathRef = (0, import_react48.useRef)([]);
6019
+ const dragStartPointRef = (0, import_react48.useRef)(null);
6020
+ const renderCanvas = (0, import_react48.useCallback)(
5876
6021
  async (draftAnnotation, draftCrop) => {
5877
6022
  const canvas = canvasRef.current;
5878
6023
  const container = containerRef.current;
@@ -5895,8 +6040,8 @@ var ImageEditor = ({
5895
6040
  },
5896
6041
  [controller, activeTab, transformTool]
5897
6042
  );
5898
- (0, import_react47.useEffect)(() => typeSession?.subscribe(() => void renderCanvas()), [typeSession, renderCanvas]);
5899
- (0, import_react47.useEffect)(() => {
6043
+ (0, import_react48.useEffect)(() => typeSession?.subscribe(() => void renderCanvas()), [typeSession, renderCanvas]);
6044
+ (0, import_react48.useEffect)(() => {
5900
6045
  if (activeTab === "annotate" && state.activeTool === "type") return;
5901
6046
  if (typeToolRef.current?.session) {
5902
6047
  typeToolRef.current.finish();
@@ -5931,7 +6076,7 @@ var ImageEditor = ({
5931
6076
  el.value = "";
5932
6077
  }
5933
6078
  };
5934
- (0, import_react47.useEffect)(() => transformTool.subscribe(() => {
6079
+ (0, import_react48.useEffect)(() => transformTool.subscribe(() => {
5935
6080
  setTransformTick((n) => n + 1);
5936
6081
  void renderCanvas();
5937
6082
  }), [transformTool, renderCanvas]);
@@ -5942,8 +6087,8 @@ var ImageEditor = ({
5942
6087
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
5943
6088
  const s = controller.getState();
5944
6089
  const cropping = activeTab === "crop";
5945
- const projection = (0, import_image_editor15.getViewportProjection)(s, canvas.width, canvas.height, cropping);
5946
- const pt = (0, import_image_editor15.canvasToImagePoint)({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
6090
+ const projection = (0, import_image_editor17.getViewportProjection)(s, canvas.width, canvas.height, cropping);
6091
+ const pt = (0, import_image_editor17.canvasToImagePoint)({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
5947
6092
  transformTool.setView(projection.scale);
5948
6093
  return { pt, tolerance: 6 / (projection.scale || 1) };
5949
6094
  };
@@ -5974,7 +6119,7 @@ var ImageEditor = ({
5974
6119
  transformTool.up();
5975
6120
  return true;
5976
6121
  };
5977
- (0, import_react47.useEffect)(() => {
6122
+ (0, import_react48.useEffect)(() => {
5978
6123
  if (typeof window === "undefined") return;
5979
6124
  const onKey = (e) => {
5980
6125
  if (transformTool.key(e)) e.preventDefault();
@@ -5982,7 +6127,7 @@ var ImageEditor = ({
5982
6127
  window.addEventListener("keydown", onKey);
5983
6128
  return () => window.removeEventListener("keydown", onKey);
5984
6129
  }, [transformTool]);
5985
- (0, import_react47.useEffect)(() => {
6130
+ (0, import_react48.useEffect)(() => {
5986
6131
  const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
5987
6132
  const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
5988
6133
  const animId = raf(() => {
@@ -5990,12 +6135,12 @@ var ImageEditor = ({
5990
6135
  });
5991
6136
  return () => caf(animId);
5992
6137
  }, [renderCanvas, state]);
5993
- (0, import_react47.useEffect)(() => {
6138
+ (0, import_react48.useEffect)(() => {
5994
6139
  if (activeTab === "crop" && editor.state.activeTool !== "crop") {
5995
6140
  editor.setTool("crop");
5996
6141
  }
5997
6142
  }, [activeTab, editor]);
5998
- (0, import_react47.useEffect)(() => {
6143
+ (0, import_react48.useEffect)(() => {
5999
6144
  const container = containerRef.current;
6000
6145
  if (!container) return;
6001
6146
  if (typeof ResizeObserver !== "undefined") {
@@ -6031,8 +6176,8 @@ var ImageEditor = ({
6031
6176
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
6032
6177
  const s = controller.getState();
6033
6178
  return list.map((ev) => ({
6034
- ...(0, import_image_editor15.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
6035
- pressure: (0, import_image_editor15.pointerPressure)(ev)
6179
+ ...(0, import_image_editor17.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
6180
+ pressure: (0, import_image_editor17.pointerPressure)(ev)
6036
6181
  }));
6037
6182
  };
6038
6183
  const handlePaintPointerDown = (e) => {
@@ -6063,10 +6208,10 @@ var ImageEditor = ({
6063
6208
  if (g.error) setPaintError(g.error);
6064
6209
  }
6065
6210
  };
6066
- (0, import_react47.useEffect)(() => {
6211
+ (0, import_react48.useEffect)(() => {
6067
6212
  if (activeTab !== "paint" || typeof window === "undefined") return;
6068
6213
  const onKey = (e) => {
6069
- if ((0, import_image_editor15.handlePaintShortcut)(controller, e)) e.preventDefault();
6214
+ if ((0, import_image_editor17.handlePaintShortcut)(controller, e)) e.preventDefault();
6070
6215
  };
6071
6216
  window.addEventListener("keydown", onKey);
6072
6217
  return () => window.removeEventListener("keydown", onKey);
@@ -6077,7 +6222,7 @@ var ImageEditor = ({
6077
6222
  const canvasPt = getCanvasEventPoint(e);
6078
6223
  if (activeTab === "select") {
6079
6224
  const gesture = selectionGestureRef.current;
6080
- const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6225
+ const imgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6081
6226
  void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
6082
6227
  return;
6083
6228
  }
@@ -6088,8 +6233,8 @@ var ImageEditor = ({
6088
6233
  width: state.imageDimensions.width,
6089
6234
  height: state.imageDimensions.height
6090
6235
  };
6091
- const handle = (0, import_image_editor15.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
6092
- const startImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
6236
+ const handle = (0, import_image_editor17.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
6237
+ const startImgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
6093
6238
  if (handle) {
6094
6239
  cropDragInfoRef.current = {
6095
6240
  handle,
@@ -6108,7 +6253,7 @@ var ImageEditor = ({
6108
6253
  return;
6109
6254
  }
6110
6255
  if (activeTab === "annotate" && (state.activeTool === "shape" || state.activeTool === "type")) {
6111
- const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6256
+ const imgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6112
6257
  setShapeTypeError(null);
6113
6258
  if (state.activeTool === "shape") shapeGestureRef.current.down(imgPt);
6114
6259
  else {
@@ -6119,12 +6264,12 @@ var ImageEditor = ({
6119
6264
  return;
6120
6265
  }
6121
6266
  if (activeTab === "annotate") {
6122
- const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6267
+ const imgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6123
6268
  dragStartPointRef.current = imgPt;
6124
6269
  if (state.activeTool === "select") {
6125
6270
  for (let i = state.annotations.length - 1; i >= 0; i--) {
6126
6271
  const ann = state.annotations[i];
6127
- if ((0, import_image_editor15.hitTestAnnotation)(imgPt, ann)) {
6272
+ if ((0, import_image_editor17.hitTestAnnotation)(imgPt, ann)) {
6128
6273
  editor.selectAnnotation(ann.id);
6129
6274
  annotationDragInfoRef.current = {
6130
6275
  annId: ann.id,
@@ -6160,7 +6305,7 @@ var ImageEditor = ({
6160
6305
  const canvasPt = getCanvasEventPoint(e);
6161
6306
  if (activeTab === "select") {
6162
6307
  const gesture = selectionGestureRef.current;
6163
- if (gesture.active && gesture.move((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
6308
+ if (gesture.active && gesture.move((0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
6164
6309
  selectionDraftRef.current = gesture.draftPath;
6165
6310
  renderCanvas();
6166
6311
  }
@@ -6169,7 +6314,7 @@ var ImageEditor = ({
6169
6314
  if (activeTab === "crop") {
6170
6315
  const drag = cropDragInfoRef.current;
6171
6316
  if (drag) {
6172
- const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
6317
+ const currentImgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
6173
6318
  let newCrop;
6174
6319
  if (drag.handle === "new") {
6175
6320
  const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
@@ -6183,7 +6328,7 @@ var ImageEditor = ({
6183
6328
  height: Math.round(Math.max(20, maxY - minY))
6184
6329
  };
6185
6330
  } else {
6186
- newCrop = (0, import_image_editor15.calculateCropDrag)(
6331
+ newCrop = (0, import_image_editor17.calculateCropDrag)(
6187
6332
  drag.startCrop,
6188
6333
  drag.handle,
6189
6334
  drag.startImgPt,
@@ -6203,15 +6348,15 @@ var ImageEditor = ({
6203
6348
  width: state.imageDimensions.width,
6204
6349
  height: state.imageDimensions.height
6205
6350
  };
6206
- const handle = (0, import_image_editor15.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
6207
- canvas.style.cursor = (0, import_image_editor15.getCropCursor)(handle, state.transform);
6351
+ const handle = (0, import_image_editor17.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
6352
+ canvas.style.cursor = (0, import_image_editor17.getCropCursor)(handle, state.transform);
6208
6353
  }
6209
6354
  return;
6210
6355
  }
6211
6356
  if (activeTab === "annotate" && state.activeTool === "shape") {
6212
6357
  const g = shapeGestureRef.current;
6213
6358
  if (g.active) {
6214
- g.move((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), { shift: e.shiftKey, alt: e.altKey });
6359
+ g.move((0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), { shift: e.shiftKey, alt: e.altKey });
6215
6360
  if (g.error) setShapeTypeError(g.error);
6216
6361
  }
6217
6362
  return;
@@ -6219,7 +6364,7 @@ var ImageEditor = ({
6219
6364
  if (activeTab === "annotate") {
6220
6365
  if (annotationDragInfoRef.current) {
6221
6366
  const drag = annotationDragInfoRef.current;
6222
- const currentImgPt2 = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6367
+ const currentImgPt2 = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6223
6368
  const dx = currentImgPt2.x - drag.startImgPt.x;
6224
6369
  const dy = currentImgPt2.y - drag.startImgPt.y;
6225
6370
  editor.updateAnnotation(drag.annId, {
@@ -6231,10 +6376,10 @@ var ImageEditor = ({
6231
6376
  const startPt = dragStartPointRef.current;
6232
6377
  if (!startPt) {
6233
6378
  if (state.activeTool === "select") {
6234
- const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6379
+ const imgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6235
6380
  let hovered = false;
6236
6381
  for (let i = state.annotations.length - 1; i >= 0; i--) {
6237
- if ((0, import_image_editor15.hitTestAnnotation)(imgPt, state.annotations[i])) {
6382
+ if ((0, import_image_editor17.hitTestAnnotation)(imgPt, state.annotations[i])) {
6238
6383
  hovered = true;
6239
6384
  break;
6240
6385
  }
@@ -6245,7 +6390,7 @@ var ImageEditor = ({
6245
6390
  }
6246
6391
  return;
6247
6392
  }
6248
- const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6393
+ const currentImgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6249
6394
  if (state.activeTool === "pen" && isDrawingRef.current) {
6250
6395
  currentPathRef.current.push(currentImgPt);
6251
6396
  const draft = {
@@ -6325,7 +6470,7 @@ var ImageEditor = ({
6325
6470
  if (activeTab === "select") {
6326
6471
  const gesture = selectionGestureRef.current;
6327
6472
  if (gesture.active) {
6328
- gesture.end((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
6473
+ gesture.end((0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
6329
6474
  selectionDraftRef.current = null;
6330
6475
  renderCanvas();
6331
6476
  }
@@ -6348,7 +6493,7 @@ var ImageEditor = ({
6348
6493
  }
6349
6494
  if (activeTab === "annotate" && state.activeTool === "type") {
6350
6495
  const tool = typeToolRef.current;
6351
- tool.up((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false));
6496
+ tool.up((0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false));
6352
6497
  setTypeSession(tool.session);
6353
6498
  if (tool.error) setShapeTypeError(tool.error);
6354
6499
  void renderCanvas();
@@ -6362,7 +6507,7 @@ var ImageEditor = ({
6362
6507
  }
6363
6508
  const startPt = dragStartPointRef.current;
6364
6509
  if (startPt) {
6365
- const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6510
+ const currentImgPt = (0, import_image_editor17.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6366
6511
  if (state.activeTool === "pen" && isDrawingRef.current) {
6367
6512
  if (currentPathRef.current.length > 1) {
6368
6513
  editor.addAnnotation({
@@ -6458,15 +6603,15 @@ var ImageEditor = ({
6458
6603
  link.click();
6459
6604
  }
6460
6605
  };
6461
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6606
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
6462
6607
  "div",
6463
6608
  {
6464
6609
  className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
6465
6610
  style,
6466
6611
  children: [
6467
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-wrap items-center justify-between px-4 py-3 bg-slate-950/80 border-b border-slate-800 gap-3", children: [
6468
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
6469
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6612
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-wrap items-center justify-between px-4 py-3 bg-slate-950/80 border-b border-slate-800 gap-3", children: [
6613
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
6614
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6470
6615
  "button",
6471
6616
  {
6472
6617
  type: "button",
@@ -6478,7 +6623,7 @@ var ImageEditor = ({
6478
6623
  children: "Transform & Crop"
6479
6624
  }
6480
6625
  ),
6481
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6626
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6482
6627
  "button",
6483
6628
  {
6484
6629
  type: "button",
@@ -6490,7 +6635,7 @@ var ImageEditor = ({
6490
6635
  children: "Adjustments"
6491
6636
  }
6492
6637
  ),
6493
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6638
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6494
6639
  "button",
6495
6640
  {
6496
6641
  type: "button",
@@ -6502,7 +6647,7 @@ var ImageEditor = ({
6502
6647
  children: "Layers"
6503
6648
  }
6504
6649
  ),
6505
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6650
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6506
6651
  "button",
6507
6652
  {
6508
6653
  type: "button",
@@ -6514,7 +6659,7 @@ var ImageEditor = ({
6514
6659
  children: "Paint"
6515
6660
  }
6516
6661
  ),
6517
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6662
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6518
6663
  "button",
6519
6664
  {
6520
6665
  type: "button",
@@ -6526,7 +6671,7 @@ var ImageEditor = ({
6526
6671
  children: "Select & Mask"
6527
6672
  }
6528
6673
  ),
6529
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6674
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6530
6675
  "button",
6531
6676
  {
6532
6677
  type: "button",
@@ -6538,7 +6683,7 @@ var ImageEditor = ({
6538
6683
  children: "Annotations"
6539
6684
  }
6540
6685
  ),
6541
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6686
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6542
6687
  "button",
6543
6688
  {
6544
6689
  type: "button",
@@ -6550,7 +6695,7 @@ var ImageEditor = ({
6550
6695
  children: "Depth Mask"
6551
6696
  }
6552
6697
  ),
6553
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6698
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
6554
6699
  "button",
6555
6700
  {
6556
6701
  type: "button",
@@ -6560,14 +6705,14 @@ var ImageEditor = ({
6560
6705
  },
6561
6706
  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"}`,
6562
6707
  children: [
6563
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
6708
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
6564
6709
  "AI Tools"
6565
6710
  ]
6566
6711
  }
6567
6712
  )
6568
6713
  ] }),
6569
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
6570
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6714
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
6715
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6571
6716
  "button",
6572
6717
  {
6573
6718
  type: "button",
@@ -6578,7 +6723,7 @@ var ImageEditor = ({
6578
6723
  children: "\u21A9"
6579
6724
  }
6580
6725
  ),
6581
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6726
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6582
6727
  "button",
6583
6728
  {
6584
6729
  type: "button",
@@ -6589,7 +6734,7 @@ var ImageEditor = ({
6589
6734
  children: "\u21AA"
6590
6735
  }
6591
6736
  ),
6592
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6737
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6593
6738
  "button",
6594
6739
  {
6595
6740
  type: "button",
@@ -6598,8 +6743,8 @@ var ImageEditor = ({
6598
6743
  children: "Reset"
6599
6744
  }
6600
6745
  ),
6601
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6602
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6746
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6747
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6603
6748
  "button",
6604
6749
  {
6605
6750
  type: "button",
@@ -6609,11 +6754,11 @@ var ImageEditor = ({
6609
6754
  children: "-"
6610
6755
  }
6611
6756
  ),
6612
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
6757
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
6613
6758
  Math.round(state.zoom * 100),
6614
6759
  "%"
6615
6760
  ] }),
6616
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6761
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6617
6762
  "button",
6618
6763
  {
6619
6764
  type: "button",
@@ -6623,8 +6768,8 @@ var ImageEditor = ({
6623
6768
  children: "+"
6624
6769
  }
6625
6770
  ),
6626
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6627
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6771
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6772
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6628
6773
  "button",
6629
6774
  {
6630
6775
  type: "button",
@@ -6635,7 +6780,7 @@ var ImageEditor = ({
6635
6780
  children: "Hold Compare"
6636
6781
  }
6637
6782
  ),
6638
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6783
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6639
6784
  "button",
6640
6785
  {
6641
6786
  type: "button",
@@ -6646,16 +6791,16 @@ var ImageEditor = ({
6646
6791
  )
6647
6792
  ] })
6648
6793
  ] }),
6649
- transformTool.active && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
6650
- !transformTool.active && transformTool.error && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { role: "alert", className: "border-b border-rose-900 bg-rose-950/80 px-4 py-1.5 text-xs text-rose-200", children: transformTool.error }),
6651
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
6652
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6794
+ transformTool.active && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
6795
+ !transformTool.active && transformTool.error && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { role: "alert", className: "border-b border-rose-900 bg-rose-950/80 px-4 py-1.5 text-xs text-rose-200", children: transformTool.error }),
6796
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
6797
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
6653
6798
  "div",
6654
6799
  {
6655
6800
  ref: containerRef,
6656
6801
  className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
6657
6802
  children: [
6658
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6803
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6659
6804
  "canvas",
6660
6805
  {
6661
6806
  ref: canvasRef,
@@ -6672,7 +6817,7 @@ var ImageEditor = ({
6672
6817
  className: `absolute inset-0 w-full h-full block ${transformTool.active ? "touch-none" : activeTab === "paint" ? "touch-none cursor-crosshair" : activeTab === "annotate" && state.activeTool === "type" ? "cursor-text" : activeTab === "annotate" && state.activeTool === "shape" ? "cursor-crosshair" : ""}`
6673
6818
  }
6674
6819
  ),
6675
- typeSession && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6820
+ typeSession && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6676
6821
  "textarea",
6677
6822
  {
6678
6823
  ref: typeInputRef,
@@ -6694,11 +6839,11 @@ var ImageEditor = ({
6694
6839
  ]
6695
6840
  }
6696
6841
  ),
6697
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "w-full md:w-80 bg-slate-900/90 border-t md:border-t-0 md:border-l border-slate-800 p-4 overflow-y-auto h-auto md:h-full md:max-h-[560px]", children: [
6698
- activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6699
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
6700
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
6701
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6842
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "w-full md:w-80 bg-slate-900/90 border-t md:border-t-0 md:border-l border-slate-800 p-4 overflow-y-auto h-auto md:h-full md:max-h-[560px]", children: [
6843
+ activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6844
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
6845
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
6846
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6702
6847
  "button",
6703
6848
  {
6704
6849
  type: "button",
@@ -6710,7 +6855,7 @@ var ImageEditor = ({
6710
6855
  children: "Freeform"
6711
6856
  }
6712
6857
  ),
6713
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6858
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6714
6859
  "button",
6715
6860
  {
6716
6861
  type: "button",
@@ -6722,7 +6867,7 @@ var ImageEditor = ({
6722
6867
  children: "1:1 Square"
6723
6868
  }
6724
6869
  ),
6725
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6870
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6726
6871
  "button",
6727
6872
  {
6728
6873
  type: "button",
@@ -6734,7 +6879,7 @@ var ImageEditor = ({
6734
6879
  children: "4:3 Standard"
6735
6880
  }
6736
6881
  ),
6737
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6882
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6738
6883
  "button",
6739
6884
  {
6740
6885
  type: "button",
@@ -6746,7 +6891,7 @@ var ImageEditor = ({
6746
6891
  children: "16:9 Wide"
6747
6892
  }
6748
6893
  ),
6749
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6894
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6750
6895
  "button",
6751
6896
  {
6752
6897
  type: "button",
@@ -6758,7 +6903,7 @@ var ImageEditor = ({
6758
6903
  children: "3:2 Photo"
6759
6904
  }
6760
6905
  ),
6761
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6906
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6762
6907
  "button",
6763
6908
  {
6764
6909
  type: "button",
@@ -6771,10 +6916,10 @@ var ImageEditor = ({
6771
6916
  }
6772
6917
  )
6773
6918
  ] }),
6774
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6775
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
6776
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
6777
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6919
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6920
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
6921
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
6922
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6778
6923
  "button",
6779
6924
  {
6780
6925
  type: "button",
@@ -6783,7 +6928,7 @@ var ImageEditor = ({
6783
6928
  children: "Rotate -90\xB0"
6784
6929
  }
6785
6930
  ),
6786
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6931
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6787
6932
  "button",
6788
6933
  {
6789
6934
  type: "button",
@@ -6792,7 +6937,7 @@ var ImageEditor = ({
6792
6937
  children: "Rotate +90\xB0"
6793
6938
  }
6794
6939
  ),
6795
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6940
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6796
6941
  "button",
6797
6942
  {
6798
6943
  type: "button",
@@ -6801,7 +6946,7 @@ var ImageEditor = ({
6801
6946
  children: "Flip Horizontal"
6802
6947
  }
6803
6948
  ),
6804
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6949
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6805
6950
  "button",
6806
6951
  {
6807
6952
  type: "button",
@@ -6812,10 +6957,10 @@ var ImageEditor = ({
6812
6957
  )
6813
6958
  ] })
6814
6959
  ] }),
6815
- activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6816
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
6817
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
6818
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6960
+ activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6961
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between", children: [
6962
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
6963
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6819
6964
  "button",
6820
6965
  {
6821
6966
  type: "button",
@@ -6825,25 +6970,25 @@ var ImageEditor = ({
6825
6970
  }
6826
6971
  )
6827
6972
  ] }),
6828
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Histogram, { histogram: editor.histogram }),
6829
- import_image_editor15.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_react47.default.Fragment, { children: [
6830
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6973
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Histogram, { histogram: editor.histogram }),
6974
+ import_image_editor17.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react48.default.Fragment, { children: [
6975
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6831
6976
  ControlSlider,
6832
6977
  {
6833
6978
  spec,
6834
- value: (0, import_image_editor15.readAdjustmentControls)(state.adjustments)[spec.id],
6979
+ value: (0, import_image_editor17.readAdjustmentControls)(state.adjustments)[spec.id],
6835
6980
  disabled: spec.requiresProcess !== void 0 && legacyProcess,
6836
6981
  onChange: (v) => editor.setAdjustments({ [spec.id]: v })
6837
6982
  }
6838
6983
  ),
6839
- spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6984
+ spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
6840
6985
  "div",
6841
6986
  {
6842
6987
  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",
6843
6988
  "data-testid": "image-editor-process-notice",
6844
6989
  children: [
6845
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
6846
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6990
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
6991
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6847
6992
  "button",
6848
6993
  {
6849
6994
  type: "button",
@@ -6856,7 +7001,7 @@ var ImageEditor = ({
6856
7001
  }
6857
7002
  )
6858
7003
  ] }, spec.id)),
6859
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7004
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6860
7005
  AdjustmentLayersPanel,
6861
7006
  {
6862
7007
  controller,
@@ -6865,9 +7010,9 @@ var ImageEditor = ({
6865
7010
  }
6866
7011
  ) })
6867
7012
  ] }),
6868
- activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6869
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
6870
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7013
+ activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
7014
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
7015
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6871
7016
  "button",
6872
7017
  {
6873
7018
  type: "button",
@@ -6878,14 +7023,14 @@ var ImageEditor = ({
6878
7023
  children: "Free Transform"
6879
7024
  }
6880
7025
  ),
6881
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(LayersPanel, { controller }),
6882
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Colour" }),
6883
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ColorProfilePanel, { controller })
7026
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(LayersPanel, { controller }),
7027
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Colour" }),
7028
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ColorProfilePanel, { controller })
6884
7029
  ] }),
6885
- activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6886
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
6887
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(BrushOptionsBar, { controller }),
6888
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7030
+ activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
7031
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
7032
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(BrushOptionsBar, { controller }),
7033
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6889
7034
  "button",
6890
7035
  {
6891
7036
  type: "button",
@@ -6896,12 +7041,12 @@ var ImageEditor = ({
6896
7041
  children: "Free Transform"
6897
7042
  }
6898
7043
  ),
6899
- paintError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
6900
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(LayersPanel, { controller }) })
7044
+ paintError && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
7045
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(LayersPanel, { controller }) })
6901
7046
  ] }),
6902
- activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6903
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Shape & Type Layers" }),
6904
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "grid grid-cols-2 gap-1.5", children: ["shape", "type"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7047
+ activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
7048
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Shape & Type Layers" }),
7049
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "grid grid-cols-2 gap-1.5", children: ["shape", "type"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6905
7050
  "button",
6906
7051
  {
6907
7052
  type: "button",
@@ -6912,13 +7057,13 @@ var ImageEditor = ({
6912
7057
  },
6913
7058
  t
6914
7059
  )) }),
6915
- state.activeTool === "shape" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ShapeOptionsBar, { controller, options: shapeOptions, onChange: setShapeOptions }),
6916
- state.activeTool === "type" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TypeOptionsBar, { controller, options: typeOptions, onChange: setTypeOptions, session: typeSession }),
6917
- state.activeTool === "type" && typeSession && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", onClick: finishTyping, className: "self-start rounded bg-slate-800 px-2 py-1 text-[11px] text-slate-200 hover:bg-slate-700", children: "Done editing text" }),
6918
- shapeTypeError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "shape-type-error", children: shapeTypeError }),
6919
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6920
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
6921
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7060
+ state.activeTool === "shape" && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ShapeOptionsBar, { controller, options: shapeOptions, onChange: setShapeOptions }),
7061
+ state.activeTool === "type" && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TypeOptionsBar, { controller, options: typeOptions, onChange: setTypeOptions, session: typeSession }),
7062
+ state.activeTool === "type" && typeSession && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "button", onClick: finishTyping, className: "self-start rounded bg-slate-800 px-2 py-1 text-[11px] text-slate-200 hover:bg-slate-700", children: "Done editing text" }),
7063
+ shapeTypeError && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "shape-type-error", children: shapeTypeError }),
7064
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
7065
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
7066
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6922
7067
  "button",
6923
7068
  {
6924
7069
  type: "button",
@@ -6928,9 +7073,9 @@ var ImageEditor = ({
6928
7073
  },
6929
7074
  t
6930
7075
  )) }),
6931
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
6932
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { className: "text-slate-400", children: "Color:" }),
6933
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7076
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
7077
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("label", { className: "text-slate-400", children: "Color:" }),
7078
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6934
7079
  "input",
6935
7080
  {
6936
7081
  type: "color",
@@ -6939,15 +7084,15 @@ var ImageEditor = ({
6939
7084
  className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
6940
7085
  }
6941
7086
  ),
6942
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex-1 ml-2", children: [
6943
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
6944
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Width:" }),
6945
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-mono", children: [
7087
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex-1 ml-2", children: [
7088
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
7089
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Width:" }),
7090
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "font-mono", children: [
6946
7091
  strokeWidth,
6947
7092
  "px"
6948
7093
  ] })
6949
7094
  ] }),
6950
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7095
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6951
7096
  "input",
6952
7097
  {
6953
7098
  type: "range",
@@ -6960,10 +7105,10 @@ var ImageEditor = ({
6960
7105
  )
6961
7106
  ] })
6962
7107
  ] }),
6963
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6964
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
6965
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex gap-2", children: [
6966
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7108
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
7109
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
7110
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex gap-2", children: [
7111
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6967
7112
  "input",
6968
7113
  {
6969
7114
  type: "text",
@@ -6974,7 +7119,7 @@ var ImageEditor = ({
6974
7119
  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"
6975
7120
  }
6976
7121
  ),
6977
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7122
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6978
7123
  "button",
6979
7124
  {
6980
7125
  type: "button",
@@ -6984,14 +7129,14 @@ var ImageEditor = ({
6984
7129
  }
6985
7130
  )
6986
7131
  ] }),
6987
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
6988
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Font Size:" }),
6989
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-mono", children: [
7132
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
7133
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Font Size:" }),
7134
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "font-mono", children: [
6990
7135
  fontSize,
6991
7136
  "px"
6992
7137
  ] })
6993
7138
  ] }),
6994
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7139
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6995
7140
  "input",
6996
7141
  {
6997
7142
  type: "range",
@@ -7002,14 +7147,14 @@ var ImageEditor = ({
7002
7147
  className: "w-full accent-indigo-500"
7003
7148
  }
7004
7149
  ),
7005
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
7006
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7007
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "text-slate-400", children: [
7150
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
7151
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between", children: [
7152
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-slate-400", children: [
7008
7153
  "Layers (",
7009
7154
  state.annotations.length,
7010
7155
  ")"
7011
7156
  ] }),
7012
- state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7157
+ state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7013
7158
  "button",
7014
7159
  {
7015
7160
  type: "button",
@@ -7018,7 +7163,7 @@ var ImageEditor = ({
7018
7163
  children: "Delete Selected"
7019
7164
  }
7020
7165
  ),
7021
- state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7166
+ state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7022
7167
  "button",
7023
7168
  {
7024
7169
  type: "button",
@@ -7029,10 +7174,10 @@ var ImageEditor = ({
7029
7174
  )
7030
7175
  ] })
7031
7176
  ] }),
7032
- activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
7033
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7034
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
7035
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7177
+ activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
7178
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between", children: [
7179
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
7180
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7036
7181
  "button",
7037
7182
  {
7038
7183
  type: "button",
@@ -7042,8 +7187,8 @@ var ImageEditor = ({
7042
7187
  }
7043
7188
  )
7044
7189
  ] }),
7045
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
7046
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7190
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
7191
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7047
7192
  "input",
7048
7193
  {
7049
7194
  type: "checkbox",
@@ -7052,12 +7197,12 @@ var ImageEditor = ({
7052
7197
  className: "rounded accent-indigo-500"
7053
7198
  }
7054
7199
  ),
7055
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Enable Depth / Alpha Mask" })
7200
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Enable Depth / Alpha Mask" })
7056
7201
  ] }),
7057
- state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7058
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7059
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
7060
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7202
+ state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
7203
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { children: [
7204
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
7205
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7061
7206
  "input",
7062
7207
  {
7063
7208
  type: "text",
@@ -7068,8 +7213,8 @@ var ImageEditor = ({
7068
7213
  }
7069
7214
  )
7070
7215
  ] }),
7071
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex gap-2", children: [
7072
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7216
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex gap-2", children: [
7217
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7073
7218
  "button",
7074
7219
  {
7075
7220
  type: "button",
@@ -7078,7 +7223,7 @@ var ImageEditor = ({
7078
7223
  children: "Threshold Mode"
7079
7224
  }
7080
7225
  ),
7081
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7226
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7082
7227
  "button",
7083
7228
  {
7084
7229
  type: "button",
@@ -7088,12 +7233,12 @@ var ImageEditor = ({
7088
7233
  }
7089
7234
  )
7090
7235
  ] }),
7091
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7092
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7093
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Depth Start (Lower):" }),
7094
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
7236
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { children: [
7237
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7238
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Depth Start (Lower):" }),
7239
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
7095
7240
  ] }),
7096
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7241
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7097
7242
  "input",
7098
7243
  {
7099
7244
  type: "range",
@@ -7107,12 +7252,12 @@ var ImageEditor = ({
7107
7252
  }
7108
7253
  )
7109
7254
  ] }),
7110
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7111
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7112
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Depth Stop (Upper):" }),
7113
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
7255
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { children: [
7256
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7257
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Depth Stop (Upper):" }),
7258
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
7114
7259
  ] }),
7115
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7260
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7116
7261
  "input",
7117
7262
  {
7118
7263
  type: "range",
@@ -7126,12 +7271,12 @@ var ImageEditor = ({
7126
7271
  }
7127
7272
  )
7128
7273
  ] }),
7129
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7130
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7131
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Softness:" }),
7132
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
7274
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { children: [
7275
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7276
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Softness:" }),
7277
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
7133
7278
  ] }),
7134
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7279
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7135
7280
  "input",
7136
7281
  {
7137
7282
  type: "range",
@@ -7143,8 +7288,8 @@ var ImageEditor = ({
7143
7288
  }
7144
7289
  )
7145
7290
  ] }),
7146
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
7147
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7291
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
7292
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7148
7293
  "input",
7149
7294
  {
7150
7295
  type: "checkbox",
@@ -7153,12 +7298,12 @@ var ImageEditor = ({
7153
7298
  className: "rounded accent-indigo-500"
7154
7299
  }
7155
7300
  ),
7156
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Invert Mask" })
7301
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Invert Mask" })
7157
7302
  ] })
7158
7303
  ] })
7159
7304
  ] }),
7160
- activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7161
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7305
+ activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7306
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7162
7307
  SelectionOptionsBar,
7163
7308
  {
7164
7309
  controller,
@@ -7168,9 +7313,9 @@ var ImageEditor = ({
7168
7313
  quickMask: Boolean(state.quickMask)
7169
7314
  }
7170
7315
  ),
7171
- selectionError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
7172
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex gap-1", children: [
7173
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7316
+ selectionError && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
7317
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex gap-1", children: [
7318
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7174
7319
  "button",
7175
7320
  {
7176
7321
  type: "button",
@@ -7181,7 +7326,7 @@ var ImageEditor = ({
7181
7326
  children: "Transform Selection"
7182
7327
  }
7183
7328
  ),
7184
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7329
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7185
7330
  "button",
7186
7331
  {
7187
7332
  type: "button",
@@ -7193,12 +7338,12 @@ var ImageEditor = ({
7193
7338
  }
7194
7339
  )
7195
7340
  ] }),
7196
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
7341
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
7197
7342
  ] }),
7198
- activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7199
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
7200
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Results go to" }),
7201
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7343
+ activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7344
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
7345
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { children: "Results go to" }),
7346
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7202
7347
  "select",
7203
7348
  {
7204
7349
  "aria-label": "AI result target",
@@ -7206,54 +7351,54 @@ var ImageEditor = ({
7206
7351
  onChange: (e) => setAiTarget(e.target.value),
7207
7352
  className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
7208
7353
  children: [
7209
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
7210
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
7211
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("option", { value: "replace", children: "Replace image" })
7354
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
7355
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
7356
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: "replace", children: "Replace image" })
7212
7357
  ]
7213
7358
  }
7214
7359
  )
7215
7360
  ] }),
7216
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
7217
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7218
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
7219
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" }) }),
7361
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
7362
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between", children: [
7363
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
7364
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { d: "M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" }) }),
7220
7365
  "Background Removal"
7221
7366
  ] }),
7222
- isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse", children: "Removing..." })
7367
+ isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse", children: "Removing..." })
7223
7368
  ] }),
7224
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
7225
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7369
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
7370
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7226
7371
  "button",
7227
7372
  {
7228
7373
  type: "button",
7229
7374
  onClick: handleRemoveBackground,
7230
7375
  disabled: isRemovingBg || isInpainting,
7231
7376
  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",
7232
- children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7233
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
7377
+ children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
7378
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
7234
7379
  "Removing Background..."
7235
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7236
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
7380
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
7381
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
7237
7382
  "Remove Background"
7238
7383
  ] })
7239
7384
  }
7240
7385
  )
7241
7386
  ] }),
7242
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
7243
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7244
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
7245
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
7246
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "m21.64 3.64-1.28-1.28a1.2 1.2 0 0 0-1.7 0l-9.72 9.72-1.94 4.86 4.86-1.94 9.72-9.72a1.2 1.2 0 0 0 .06-1.64z" }),
7247
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "m14 7 3 3" })
7387
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
7388
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between", children: [
7389
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
7390
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
7391
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { d: "m21.64 3.64-1.28-1.28a1.2 1.2 0 0 0-1.7 0l-9.72 9.72-1.94 4.86 4.86-1.94 9.72-9.72a1.2 1.2 0 0 0 .06-1.64z" }),
7392
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { d: "m14 7 3 3" })
7248
7393
  ] }),
7249
7394
  "Generative Inpainting"
7250
7395
  ] }),
7251
- isInpainting && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse", children: "Inpainting..." })
7396
+ isInpainting && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse", children: "Inpainting..." })
7252
7397
  ] }),
7253
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
7254
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-1", children: [
7255
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
7256
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7398
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
7399
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", children: [
7400
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
7401
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7257
7402
  "textarea",
7258
7403
  {
7259
7404
  id: "ai-inpaint-prompt-react",
@@ -7265,10 +7410,10 @@ var ImageEditor = ({
7265
7410
  }
7266
7411
  )
7267
7412
  ] }),
7268
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-1", children: [
7269
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
7270
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
7271
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7413
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", children: [
7414
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
7415
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
7416
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7272
7417
  "button",
7273
7418
  {
7274
7419
  type: "button",
@@ -7281,7 +7426,7 @@ var ImageEditor = ({
7281
7426
  ]
7282
7427
  }
7283
7428
  ),
7284
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7429
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7285
7430
  "button",
7286
7431
  {
7287
7432
  type: "button",
@@ -7296,25 +7441,25 @@ var ImageEditor = ({
7296
7441
  )
7297
7442
  ] })
7298
7443
  ] }),
7299
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7444
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7300
7445
  "button",
7301
7446
  {
7302
7447
  type: "button",
7303
7448
  onClick: handleInpaint,
7304
7449
  disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
7305
7450
  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",
7306
- children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7307
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
7451
+ children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
7452
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
7308
7453
  "Generating Inpaint..."
7309
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7310
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
7454
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
7455
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
7311
7456
  "Apply Inpainting"
7312
7457
  ] })
7313
7458
  }
7314
7459
  )
7315
7460
  ] }),
7316
- aiError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
7317
- aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
7461
+ aiError && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
7462
+ aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
7318
7463
  ] })
7319
7464
  ] })
7320
7465
  ] })
@@ -7324,7 +7469,7 @@ var ImageEditor = ({
7324
7469
  };
7325
7470
 
7326
7471
  // src/review/useReview.ts
7327
- var import_react48 = require("react");
7472
+ var import_react49 = require("react");
7328
7473
  var import_editor12 = require("@pixerate/editor");
7329
7474
  var EMPTY_COMMENTS = Object.freeze({
7330
7475
  threads: [],
@@ -7343,23 +7488,23 @@ function isCommentStore(value) {
7343
7488
  }
7344
7489
  function useComments(source) {
7345
7490
  const store = isCommentStore(source) ? source : (0, import_editor12.getCommentStore)(source);
7346
- const subscribe = (0, import_react48.useCallback)(
7491
+ const subscribe = (0, import_react49.useCallback)(
7347
7492
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
7348
7493
  [store]
7349
7494
  );
7350
7495
  const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;
7351
- const snapshot = (0, import_react48.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7352
- return (0, import_react48.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
7496
+ const snapshot = (0, import_react49.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7497
+ return (0, import_react49.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
7353
7498
  }
7354
7499
  function useTrackChanges(editor) {
7355
7500
  const store = (0, import_editor12.getTrackChangesStore)(editor ?? null);
7356
- const subscribe = (0, import_react48.useCallback)(
7501
+ const subscribe = (0, import_react49.useCallback)(
7357
7502
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
7358
7503
  [store]
7359
7504
  );
7360
7505
  const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;
7361
- const snapshot = (0, import_react48.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7362
- return (0, import_react48.useMemo)(() => {
7506
+ const snapshot = (0, import_react49.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7507
+ return (0, import_react49.useMemo)(() => {
7363
7508
  const run = (fn) => () => {
7364
7509
  if (editor && !editor.isDestroyed) fn(editor);
7365
7510
  };
@@ -7382,9 +7527,9 @@ function useTrackChanges(editor) {
7382
7527
  }
7383
7528
 
7384
7529
  // src/review/CommentsPanel.tsx
7385
- var import_react49 = require("react");
7530
+ var import_react50 = require("react");
7386
7531
  var import_editor13 = require("@pixerate/editor");
7387
- var import_jsx_runtime31 = require("react/jsx-runtime");
7532
+ var import_jsx_runtime33 = require("react/jsx-runtime");
7388
7533
  var buttonClass2 = "rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50";
7389
7534
  var primaryButtonClass = "rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50";
7390
7535
  var textareaClass = "w-full resize-y rounded-md border border-input bg-background p-2 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary";
@@ -7398,18 +7543,18 @@ var CommentsPanel = ({
7398
7543
  emptyMessage = "No comments yet. Select text and add a comment."
7399
7544
  }) => {
7400
7545
  const { threads, activeThreadId, store } = useComments(storeProp ?? editor);
7401
- const [showResolved, setShowResolved] = (0, import_react49.useState)(showResolvedInitial);
7546
+ const [showResolved, setShowResolved] = (0, import_react50.useState)(showResolvedInitial);
7402
7547
  const author = authorProp ?? (0, import_editor13.getCommentAuthor)(editor) ?? { id: "anonymous", name: "Anonymous" };
7403
7548
  const visible = threads.filter((t) => showResolved || !t.resolved);
7404
7549
  const resolvedCount = threads.filter((t) => t.resolved).length;
7405
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("aside", { className, "aria-label": "Comments", children: [
7406
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
7407
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
7550
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("aside", { className, "aria-label": "Comments", children: [
7551
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
7552
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
7408
7553
  threads.length - resolvedCount,
7409
7554
  " open",
7410
7555
  resolvedCount > 0 ? ` \xB7 ${resolvedCount} resolved` : ""
7411
7556
  ] }),
7412
- resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7557
+ resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7413
7558
  "button",
7414
7559
  {
7415
7560
  type: "button",
@@ -7420,7 +7565,7 @@ var CommentsPanel = ({
7420
7565
  }
7421
7566
  )
7422
7567
  ] }),
7423
- visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("ul", { className: "flex flex-col gap-2", role: "list", children: visible.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7568
+ visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("ul", { className: "flex flex-col gap-2", role: "list", children: visible.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7424
7569
  CommentThreadCard,
7425
7570
  {
7426
7571
  thread,
@@ -7442,7 +7587,7 @@ var CommentThreadCard = ({
7442
7587
  author,
7443
7588
  formatTime
7444
7589
  }) => {
7445
- const [draft, setDraft] = (0, import_react49.useState)("");
7590
+ const [draft, setDraft] = (0, import_react50.useState)("");
7446
7591
  const isDraft = thread.body === "";
7447
7592
  const quote = thread.anchor?.quote ?? thread.lastQuote ?? "";
7448
7593
  const live = editor && !editor.isDestroyed ? editor : null;
@@ -7468,7 +7613,7 @@ var CommentThreadCard = ({
7468
7613
  setDraft("");
7469
7614
  };
7470
7615
  const stop = (e) => e.stopPropagation();
7471
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
7616
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
7472
7617
  "li",
7473
7618
  {
7474
7619
  className: `flex flex-col gap-2 rounded-md border bg-background p-3 cursor-pointer ${active ? "border-primary ring-1 ring-primary" : "border-border"} ${thread.resolved ? "opacity-70" : ""}`,
@@ -7484,24 +7629,24 @@ var CommentThreadCard = ({
7484
7629
  }
7485
7630
  },
7486
7631
  children: [
7487
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
7488
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "font-medium", children: thread.author.name }),
7489
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
7632
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
7633
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "font-medium", children: thread.author.name }),
7634
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
7490
7635
  ] }),
7491
- quote && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("blockquote", { className: "border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2", children: quote }),
7492
- thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
7493
- thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
7494
- !isDraft && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
7495
- thread.replies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("ul", { className: "flex flex-col gap-2 border-l border-border pl-3", role: "list", children: thread.replies.map((reply) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("li", { className: "flex flex-col gap-0.5", "data-reply-id": reply.id, children: [
7496
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-xs", children: [
7497
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "font-medium", children: reply.author.name }),
7636
+ quote && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("blockquote", { className: "border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2", children: quote }),
7637
+ thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
7638
+ thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
7639
+ !isDraft && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
7640
+ thread.replies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("ul", { className: "flex flex-col gap-2 border-l border-border pl-3", role: "list", children: thread.replies.map((reply) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("li", { className: "flex flex-col gap-0.5", "data-reply-id": reply.id, children: [
7641
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "text-xs", children: [
7642
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "font-medium", children: reply.author.name }),
7498
7643
  " ",
7499
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
7644
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
7500
7645
  ] }),
7501
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
7646
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
7502
7647
  ] }, reply.id)) }),
7503
- (active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
7504
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7648
+ (active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
7649
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7505
7650
  "textarea",
7506
7651
  {
7507
7652
  className: textareaClass,
@@ -7519,9 +7664,9 @@ var CommentThreadCard = ({
7519
7664
  }
7520
7665
  }
7521
7666
  ),
7522
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex justify-end gap-1", children: [
7523
- isDraft && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
7524
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7667
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex justify-end gap-1", children: [
7668
+ isDraft && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
7669
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7525
7670
  "button",
7526
7671
  {
7527
7672
  type: "button",
@@ -7533,9 +7678,9 @@ var CommentThreadCard = ({
7533
7678
  )
7534
7679
  ] })
7535
7680
  ] }),
7536
- !isDraft && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
7537
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
7538
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7681
+ !isDraft && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
7682
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
7683
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7539
7684
  "button",
7540
7685
  {
7541
7686
  type: "button",
@@ -7551,7 +7696,7 @@ var CommentThreadCard = ({
7551
7696
  };
7552
7697
 
7553
7698
  // src/review/ReviewToolbar.tsx
7554
- var import_jsx_runtime32 = require("react/jsx-runtime");
7699
+ var import_jsx_runtime34 = require("react/jsx-runtime");
7555
7700
  var defaultDescriptionClass = "max-w-[16rem] truncate px-1 text-xs text-muted-foreground";
7556
7701
  var buttonClass3 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
7557
7702
  var ReviewToolbar = ({
@@ -7564,8 +7709,8 @@ var ReviewToolbar = ({
7564
7709
  const count = review.changes.length;
7565
7710
  const current = review.currentChange;
7566
7711
  const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;
7567
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
7568
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7712
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
7713
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7569
7714
  "button",
7570
7715
  {
7571
7716
  type: "button",
@@ -7576,8 +7721,8 @@ var ReviewToolbar = ({
7576
7721
  children: review.enabled ? "Tracking on" : "Track changes"
7577
7722
  }
7578
7723
  ),
7579
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7580
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7724
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7725
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7581
7726
  "button",
7582
7727
  {
7583
7728
  type: "button",
@@ -7588,8 +7733,8 @@ var ReviewToolbar = ({
7588
7733
  children: "\u2039"
7589
7734
  }
7590
7735
  ),
7591
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "min-w-[4rem] text-center text-xs text-muted-foreground", "aria-live": "polite", children: count === 0 ? "No changes" : current ? `${index} of ${count}` : `${count} changes` }),
7592
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7736
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "min-w-[4rem] text-center text-xs text-muted-foreground", "aria-live": "polite", children: count === 0 ? "No changes" : current ? `${index} of ${count}` : `${count} changes` }),
7737
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7593
7738
  "button",
7594
7739
  {
7595
7740
  type: "button",
@@ -7600,7 +7745,7 @@ var ReviewToolbar = ({
7600
7745
  children: "\u203A"
7601
7746
  }
7602
7747
  ),
7603
- showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7748
+ showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7604
7749
  "span",
7605
7750
  {
7606
7751
  className: descriptionClassName,
@@ -7612,8 +7757,8 @@ var ReviewToolbar = ({
7612
7757
  ]
7613
7758
  }
7614
7759
  ),
7615
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7616
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7760
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7761
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7617
7762
  "button",
7618
7763
  {
7619
7764
  type: "button",
@@ -7623,7 +7768,7 @@ var ReviewToolbar = ({
7623
7768
  children: "Accept"
7624
7769
  }
7625
7770
  ),
7626
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7771
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7627
7772
  "button",
7628
7773
  {
7629
7774
  type: "button",
@@ -7633,18 +7778,18 @@ var ReviewToolbar = ({
7633
7778
  children: "Reject"
7634
7779
  }
7635
7780
  ),
7636
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
7637
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
7781
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
7782
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
7638
7783
  ] });
7639
7784
  };
7640
7785
 
7641
7786
  // src/review/CommentButton.tsx
7642
- var import_jsx_runtime33 = require("react/jsx-runtime");
7787
+ var import_jsx_runtime35 = require("react/jsx-runtime");
7643
7788
  var CommentButton = ({
7644
7789
  editor,
7645
7790
  className = "rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted",
7646
7791
  children = "Comment"
7647
- }) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7792
+ }) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7648
7793
  "button",
7649
7794
  {
7650
7795
  type: "button",
@@ -7656,13 +7801,13 @@ var CommentButton = ({
7656
7801
  );
7657
7802
 
7658
7803
  // src/review/useDocumentCompare.ts
7659
- var import_react50 = require("react");
7804
+ var import_react51 = require("react");
7660
7805
  var import_editor14 = require("@pixerate/editor");
7661
7806
  function useDocumentCompare(editor, options) {
7662
- const [summary, setSummary] = (0, import_react50.useState)(null);
7663
- const defaults = (0, import_react50.useRef)(options);
7807
+ const [summary, setSummary] = (0, import_react51.useState)(null);
7808
+ const defaults = (0, import_react51.useRef)(options);
7664
7809
  defaults.current = options;
7665
- const compare = (0, import_react50.useCallback)(
7810
+ const compare = (0, import_react51.useCallback)(
7666
7811
  (original, revised, overrides) => {
7667
7812
  if (!editor || editor.isDestroyed) return null;
7668
7813
  const result = (0, import_editor14.applyDocumentComparison)(editor, original, revised, {
@@ -7674,13 +7819,13 @@ function useDocumentCompare(editor, options) {
7674
7819
  },
7675
7820
  [editor]
7676
7821
  );
7677
- const clear = (0, import_react50.useCallback)(() => setSummary(null), []);
7678
- return (0, import_react50.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
7822
+ const clear = (0, import_react51.useCallback)(() => setSummary(null), []);
7823
+ return (0, import_react51.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
7679
7824
  }
7680
7825
 
7681
7826
  // src/review/TrackedChangesList.tsx
7682
7827
  var import_editor15 = require("@pixerate/editor");
7683
- var import_jsx_runtime34 = require("react/jsx-runtime");
7828
+ var import_jsx_runtime36 = require("react/jsx-runtime");
7684
7829
  var buttonClass4 = "rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40";
7685
7830
  var TrackedChangesList = ({
7686
7831
  editor,
@@ -7691,18 +7836,18 @@ var TrackedChangesList = ({
7691
7836
  }) => {
7692
7837
  const review = useTrackChanges(editor);
7693
7838
  if (review.changes.length === 0) {
7694
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className, "data-tracked-changes-list": "", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "pixerate-changes-empty text-xs text-muted-foreground", children: emptyState }) });
7839
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className, "data-tracked-changes-list": "", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "pixerate-changes-empty text-xs text-muted-foreground", children: emptyState }) });
7695
7840
  }
7696
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
7841
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
7697
7842
  const active = change.id === review.currentChangeId;
7698
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7843
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7699
7844
  "li",
7700
7845
  {
7701
7846
  className: active ? `${itemClassName} ${activeItemClassName}` : itemClassName,
7702
7847
  "data-change-type": change.type,
7703
7848
  "data-change-id": change.id,
7704
7849
  children: [
7705
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7850
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7706
7851
  "button",
7707
7852
  {
7708
7853
  type: "button",
@@ -7710,14 +7855,14 @@ var TrackedChangesList = ({
7710
7855
  title: `${change.author.name}: ${change.description}`,
7711
7856
  onClick: () => review.select(change.id),
7712
7857
  children: [
7713
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
7858
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
7714
7859
  change.author.name ? ` \xB7 ${change.author.name}` : "",
7715
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
7860
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
7716
7861
  ]
7717
7862
  }
7718
7863
  ),
7719
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
7720
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
7864
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
7865
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
7721
7866
  ]
7722
7867
  },
7723
7868
  `${change.type}:${change.id}`
@@ -7726,12 +7871,12 @@ var TrackedChangesList = ({
7726
7871
  };
7727
7872
 
7728
7873
  // src/commands/useCommandPalette.ts
7729
- var import_react51 = require("react");
7874
+ var import_react52 = require("react");
7730
7875
  var import_commands2 = require("@pixerate/editor/commands");
7731
7876
  function useCommandPalette(registry, options = {}) {
7732
- const optionsRef = (0, import_react51.useRef)(options);
7877
+ const optionsRef = (0, import_react52.useRef)(options);
7733
7878
  optionsRef.current = options;
7734
- const controller = (0, import_react51.useMemo)(
7879
+ const controller = (0, import_react52.useMemo)(
7735
7880
  () => (0, import_commands2.createCommandPaletteController)(registry, {
7736
7881
  context: () => {
7737
7882
  const c = optionsRef.current.context;
@@ -7752,9 +7897,9 @@ function useCommandPalette(registry, options = {}) {
7752
7897
  // eslint-disable-next-line react-hooks/exhaustive-deps
7753
7898
  [registry]
7754
7899
  );
7755
- const state = (0, import_react51.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
7900
+ const state = (0, import_react52.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
7756
7901
  const { hotkey, hotkeyTarget } = options;
7757
- (0, import_react51.useEffect)(() => {
7902
+ (0, import_react52.useEffect)(() => {
7758
7903
  if (!hotkey) return;
7759
7904
  const target = hotkeyTarget ?? (typeof window !== "undefined" ? window : null);
7760
7905
  if (!target) return;
@@ -7782,13 +7927,13 @@ function useCommandPalette(registry, options = {}) {
7782
7927
  }
7783
7928
 
7784
7929
  // src/commands/CommandPalette.tsx
7785
- var import_react52 = __toESM(require("react"), 1);
7786
- var import_jsx_runtime35 = require("react/jsx-runtime");
7930
+ var import_react53 = __toESM(require("react"), 1);
7931
+ var import_jsx_runtime37 = require("react/jsx-runtime");
7787
7932
  function HighlightedLabel({ item }) {
7788
- if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_jsx_runtime35.Fragment, { children: item.label });
7933
+ if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_jsx_runtime37.Fragment, { children: item.label });
7789
7934
  const marked = new Set(item.labelIndices);
7790
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_jsx_runtime35.Fragment, { children: Array.from(item.label).map(
7791
- (ch, i) => marked.has(i) ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "font-semibold text-foreground", "data-match": "", children: ch }, i) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react52.default.Fragment, { children: ch }, i)
7935
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_jsx_runtime37.Fragment, { children: Array.from(item.label).map(
7936
+ (ch, i) => marked.has(i) ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "font-semibold text-foreground", "data-match": "", children: ch }, i) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_react53.default.Fragment, { children: ch }, i)
7792
7937
  ) });
7793
7938
  }
7794
7939
  var CommandPalette = ({
@@ -7797,22 +7942,22 @@ var CommandPalette = ({
7797
7942
  emptyMessage = "No matching commands",
7798
7943
  className = ""
7799
7944
  }) => {
7800
- const inputRef = (0, import_react52.useRef)(null);
7801
- const listRef = (0, import_react52.useRef)(null);
7802
- const baseId = (0, import_react52.useId)();
7945
+ const inputRef = (0, import_react53.useRef)(null);
7946
+ const listRef = (0, import_react53.useRef)(null);
7947
+ const baseId = (0, import_react53.useId)();
7803
7948
  const listId = `${baseId}-list`;
7804
7949
  const optionId = (index) => `${baseId}-option-${index}`;
7805
7950
  const { open, query, items, activeIndex } = palette;
7806
- (0, import_react52.useEffect)(() => {
7951
+ (0, import_react53.useEffect)(() => {
7807
7952
  if (open) inputRef.current?.focus();
7808
7953
  }, [open]);
7809
- (0, import_react52.useEffect)(() => {
7954
+ (0, import_react53.useEffect)(() => {
7810
7955
  if (!open) return;
7811
7956
  const active = listRef.current?.querySelector('[aria-selected="true"]');
7812
7957
  active?.scrollIntoView?.({ block: "nearest" });
7813
7958
  }, [open, activeIndex]);
7814
7959
  if (!open) return null;
7815
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7960
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7816
7961
  "div",
7817
7962
  {
7818
7963
  className: "fixed inset-0 z-50 flex items-start justify-center bg-black/30 px-4 pt-[15vh]",
@@ -7820,7 +7965,7 @@ var CommandPalette = ({
7820
7965
  onMouseDown: (e) => {
7821
7966
  if (e.target === e.currentTarget) palette.setOpen(false);
7822
7967
  },
7823
- children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7968
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
7824
7969
  "div",
7825
7970
  {
7826
7971
  role: "dialog",
@@ -7829,7 +7974,7 @@ var CommandPalette = ({
7829
7974
  className: `w-full max-w-lg overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-xl ${className}`,
7830
7975
  style: { background: "var(--popover, var(--background, #fff))" },
7831
7976
  children: [
7832
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7977
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7833
7978
  "input",
7834
7979
  {
7835
7980
  ref: inputRef,
@@ -7849,7 +7994,7 @@ var CommandPalette = ({
7849
7994
  className: "w-full border-b border-border bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground"
7850
7995
  }
7851
7996
  ),
7852
- items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { ref: listRef, id: listId, role: "listbox", "aria-label": "Commands", className: "max-h-80 overflow-y-auto py-1", children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7997
+ items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ul", { ref: listRef, id: listId, role: "listbox", "aria-label": "Commands", className: "max-h-80 overflow-y-auto py-1", children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
7853
7998
  "li",
7854
7999
  {
7855
8000
  id: optionId(index),
@@ -7864,12 +8009,12 @@ var CommandPalette = ({
7864
8009
  onClick: () => palette.run(item.id),
7865
8010
  className: `flex cursor-pointer items-center gap-2 px-3 py-1.5 text-sm ${index === activeIndex ? "bg-muted" : ""} ${item.enabled ? "" : "cursor-default opacity-50"}`,
7866
8011
  children: [
7867
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
7868
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HighlightedLabel, { item }),
7869
- item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
8012
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
8013
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(HighlightedLabel, { item }),
8014
+ item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
7870
8015
  ] }),
7871
- item.group && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
7872
- item.shortcut && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("kbd", { className: "shrink-0 rounded border border-border px-1.5 font-mono text-[10px] text-muted-foreground", children: item.shortcut })
8016
+ item.group && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
8017
+ item.shortcut && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("kbd", { className: "shrink-0 rounded border border-border px-1.5 font-mono text-[10px] text-muted-foreground", children: item.shortcut })
7873
8018
  ]
7874
8019
  },
7875
8020
  item.id
@@ -7882,12 +8027,12 @@ var CommandPalette = ({
7882
8027
  };
7883
8028
 
7884
8029
  // src/commands/useCommandShortcuts.ts
7885
- var import_react53 = require("react");
8030
+ var import_react54 = require("react");
7886
8031
  function useCommandShortcuts(registry, options = {}) {
7887
- const optionsRef = (0, import_react53.useRef)(options);
8032
+ const optionsRef = (0, import_react54.useRef)(options);
7888
8033
  optionsRef.current = options;
7889
8034
  const { enabled = true, target } = options;
7890
- (0, import_react53.useEffect)(() => {
8035
+ (0, import_react54.useEffect)(() => {
7891
8036
  if (!registry || !enabled) return;
7892
8037
  const eventTarget = target ?? (typeof window !== "undefined" ? window : null);
7893
8038
  if (!eventTarget) return;
@@ -7905,14 +8050,14 @@ function useCommandShortcuts(registry, options = {}) {
7905
8050
  }, [registry, enabled, target]);
7906
8051
  }
7907
8052
  function useRegisterCommands(registry, specs) {
7908
- (0, import_react53.useEffect)(() => {
8053
+ (0, import_react54.useEffect)(() => {
7909
8054
  if (!registry || !specs || specs.length === 0) return;
7910
8055
  return registry.register(specs);
7911
8056
  }, [registry, specs]);
7912
8057
  }
7913
8058
 
7914
8059
  // src/persistence/useAutosave.ts
7915
- var import_react54 = require("react");
8060
+ var import_react55 = require("react");
7916
8061
  var import_persistence = require("@pixerate/editor/persistence");
7917
8062
  var IDLE = {
7918
8063
  status: "idle",
@@ -7923,18 +8068,18 @@ var IDLE = {
7923
8068
  ready: false
7924
8069
  };
7925
8070
  function useAutosave(options) {
7926
- const optionsRef = (0, import_react54.useRef)(options);
8071
+ const optionsRef = (0, import_react55.useRef)(options);
7927
8072
  optionsRef.current = options;
7928
8073
  const { storage, key, history, dirty } = options;
7929
8074
  const recover = options.recover !== false;
7930
8075
  const flushOnHide = options.flushOnHide !== false;
7931
8076
  const ready = options.ready !== false;
7932
- const [controller, setController] = (0, import_react54.useState)(null);
7933
- const [status, setStatus] = (0, import_react54.useState)(IDLE);
7934
- const [recovery, setRecovery] = (0, import_react54.useState)(null);
7935
- const [pendingRecovery, setPendingRecovery] = (0, import_react54.useState)(recover);
7936
- const revisionsRef = (0, import_react54.useRef)(null);
7937
- (0, import_react54.useEffect)(() => {
8077
+ const [controller, setController] = (0, import_react55.useState)(null);
8078
+ const [status, setStatus] = (0, import_react55.useState)(IDLE);
8079
+ const [recovery, setRecovery] = (0, import_react55.useState)(null);
8080
+ const [pendingRecovery, setPendingRecovery] = (0, import_react55.useState)(recover);
8081
+ const revisionsRef = (0, import_react55.useRef)(null);
8082
+ (0, import_react55.useEffect)(() => {
7938
8083
  const revisions = (0, import_persistence.createRevisionTracker)({ history, dirty });
7939
8084
  const o = optionsRef.current;
7940
8085
  const instance = (0, import_persistence.createAutosaveController)({
@@ -7977,10 +8122,10 @@ function useAutosave(options) {
7977
8122
  if (revisionsRef.current === revisions) revisionsRef.current = null;
7978
8123
  };
7979
8124
  }, [storage, key, history, dirty, recover]);
7980
- (0, import_react54.useEffect)(() => {
8125
+ (0, import_react55.useEffect)(() => {
7981
8126
  if (controller && ready && !pendingRecovery) controller.ready();
7982
8127
  }, [controller, ready, pendingRecovery]);
7983
- (0, import_react54.useEffect)(() => {
8128
+ (0, import_react55.useEffect)(() => {
7984
8129
  if (!controller || !flushOnHide || typeof window === "undefined") return;
7985
8130
  const flush = () => void controller.flushNow();
7986
8131
  const onVisibility = () => {
@@ -7993,31 +8138,31 @@ function useAutosave(options) {
7993
8138
  document.removeEventListener("visibilitychange", onVisibility);
7994
8139
  };
7995
8140
  }, [controller, flushOnHide]);
7996
- const restore = (0, import_react54.useCallback)(() => {
8141
+ const restore = (0, import_react55.useCallback)(() => {
7997
8142
  const snapshot = recovery?.snapshot;
7998
8143
  setRecovery(null);
7999
8144
  setPendingRecovery(false);
8000
8145
  return snapshot;
8001
8146
  }, [recovery]);
8002
- const discard = (0, import_react54.useCallback)(async () => {
8147
+ const discard = (0, import_react55.useCallback)(async () => {
8003
8148
  if (controller) await controller.discardRecovery();
8004
8149
  setRecovery(null);
8005
8150
  setPendingRecovery(false);
8006
8151
  }, [controller]);
8007
- const flushNow = (0, import_react54.useCallback)(async () => {
8152
+ const flushNow = (0, import_react55.useCallback)(async () => {
8008
8153
  await controller?.flushNow();
8009
8154
  }, [controller]);
8010
- const markClean = (0, import_react54.useCallback)(async () => {
8155
+ const markClean = (0, import_react55.useCallback)(async () => {
8011
8156
  revisionsRef.current?.markSaved();
8012
8157
  await controller?.markClean();
8013
8158
  }, [controller]);
8014
- const notifyChange = (0, import_react54.useCallback)(() => revisionsRef.current?.bump(), []);
8159
+ const notifyChange = (0, import_react55.useCallback)(() => revisionsRef.current?.bump(), []);
8015
8160
  return { status, recovery, pendingRecovery, restore, discard, flushNow, markClean, notifyChange, controller };
8016
8161
  }
8017
8162
 
8018
8163
  // src/persistence/RecoveryPrompt.tsx
8019
8164
  var import_persistence2 = require("@pixerate/editor/persistence");
8020
- var import_jsx_runtime36 = require("react/jsx-runtime");
8165
+ var import_jsx_runtime38 = require("react/jsx-runtime");
8021
8166
  var RecoveryPrompt = ({
8022
8167
  recovery,
8023
8168
  onRestore,
@@ -8029,7 +8174,7 @@ var RecoveryPrompt = ({
8029
8174
  }) => {
8030
8175
  if (!recovery) return null;
8031
8176
  const { name } = recovery.meta;
8032
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
8177
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
8033
8178
  "div",
8034
8179
  {
8035
8180
  role: "alertdialog",
@@ -8037,15 +8182,15 @@ var RecoveryPrompt = ({
8037
8182
  "data-recovery-prompt": "",
8038
8183
  className: `flex flex-wrap items-center gap-3 rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground shadow-sm ${className}`,
8039
8184
  children: [
8040
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "min-w-0 flex-1", children: [
8185
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "min-w-0 flex-1", children: [
8041
8186
  (0, import_persistence2.formatRecoveryMessage)(recovery.meta, formatTime),
8042
- name ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
8187
+ name ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
8043
8188
  "(",
8044
8189
  name,
8045
8190
  ")"
8046
8191
  ] }) : null
8047
8192
  ] }),
8048
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8193
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8049
8194
  "button",
8050
8195
  {
8051
8196
  type: "button",
@@ -8055,7 +8200,7 @@ var RecoveryPrompt = ({
8055
8200
  children: restoreLabel
8056
8201
  }
8057
8202
  ),
8058
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8203
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8059
8204
  "button",
8060
8205
  {
8061
8206
  type: "button",
@@ -8071,17 +8216,17 @@ var RecoveryPrompt = ({
8071
8216
  };
8072
8217
 
8073
8218
  // src/generation/useGenerationPlan.ts
8074
- var import_react55 = require("react");
8219
+ var import_react56 = require("react");
8075
8220
  var import_generation = require("@pixerate/editor/generation");
8076
8221
  function useGenerationPlan(request, capabilities, options = {}) {
8077
8222
  const key = JSON.stringify([request, capabilities, options]);
8078
- return (0, import_react55.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
8223
+ return (0, import_react56.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
8079
8224
  }
8080
8225
  function useJobProgress(options) {
8081
8226
  const { startedAt, expectedMs, done, now, intervalMs = 1e3 } = options;
8082
- const [tick, setTick] = (0, import_react55.useState)(() => Date.now());
8227
+ const [tick, setTick] = (0, import_react56.useState)(() => Date.now());
8083
8228
  const ticking = !done && now === void 0;
8084
- (0, import_react55.useEffect)(() => {
8229
+ (0, import_react56.useEffect)(() => {
8085
8230
  if (!ticking) return;
8086
8231
  setTick(Date.now());
8087
8232
  const id = setInterval(() => setTick(Date.now()), Math.max(16, intervalMs));
@@ -8091,9 +8236,9 @@ function useJobProgress(options) {
8091
8236
  }
8092
8237
 
8093
8238
  // src/generation/GenerationSettings.tsx
8094
- var import_react56 = require("react");
8239
+ var import_react57 = require("react");
8095
8240
  var import_generation2 = require("@pixerate/editor/generation");
8096
- var import_jsx_runtime37 = require("react/jsx-runtime");
8241
+ var import_jsx_runtime39 = require("react/jsx-runtime");
8097
8242
  var inputClass2 = "w-full rounded-md border border-border bg-background px-2 py-1 text-sm outline-none focus:ring-1 focus:ring-ring";
8098
8243
  function Control({
8099
8244
  control,
@@ -8103,7 +8248,7 @@ function Control({
8103
8248
  }) {
8104
8249
  const shown = value ?? control.defaultValue;
8105
8250
  if (control.kind === "checkbox") {
8106
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8251
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8107
8252
  "input",
8108
8253
  {
8109
8254
  id,
@@ -8115,7 +8260,7 @@ function Control({
8115
8260
  );
8116
8261
  }
8117
8262
  if (control.kind === "select") {
8118
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
8263
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8119
8264
  "select",
8120
8265
  {
8121
8266
  id,
@@ -8124,14 +8269,14 @@ function Control({
8124
8269
  value: shown === void 0 ? "" : String(shown),
8125
8270
  onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value)),
8126
8271
  children: [
8127
- shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("option", { value: "", children: "Default" }),
8128
- control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
8272
+ shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("option", { value: "", children: "Default" }),
8273
+ control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
8129
8274
  ]
8130
8275
  }
8131
8276
  );
8132
8277
  }
8133
8278
  if (control.kind === "textarea") {
8134
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8279
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8135
8280
  "textarea",
8136
8281
  {
8137
8282
  id,
@@ -8145,8 +8290,8 @@ function Control({
8145
8290
  );
8146
8291
  }
8147
8292
  const numeric = typeof shown === "number" ? shown : void 0;
8148
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-2", children: [
8149
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8293
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex items-center gap-2", children: [
8294
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8150
8295
  "input",
8151
8296
  {
8152
8297
  id,
@@ -8160,7 +8305,7 @@ function Control({
8160
8305
  onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value))
8161
8306
  }
8162
8307
  ),
8163
- control.kind === "range" && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "w-10 text-right tabular-nums text-muted-foreground", "data-field-value": "", children: numeric ?? "\u2013" })
8308
+ control.kind === "range" && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "w-10 text-right tabular-nums text-muted-foreground", "data-field-value": "", children: numeric ?? "\u2013" })
8164
8309
  ] });
8165
8310
  }
8166
8311
  var GenerationSettings = ({
@@ -8174,17 +8319,17 @@ var GenerationSettings = ({
8174
8319
  renderReference,
8175
8320
  className = ""
8176
8321
  }) => {
8177
- const baseId = (0, import_react56.useId)();
8178
- const controls = (0, import_react56.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
8322
+ const baseId = (0, import_react57.useId)();
8323
+ const controls = (0, import_react57.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
8179
8324
  const computed = useGenerationPlan(value, capabilities, { strategy });
8180
8325
  const plan = planProp ?? computed;
8181
8326
  const slots = (0, import_generation2.getReferenceSlots)(capabilities, value);
8182
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: `flex flex-col gap-3 text-sm ${className}`, "data-generation-settings": "", "data-model": capabilities.id, children: [
8327
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: `flex flex-col gap-3 text-sm ${className}`, "data-generation-settings": "", "data-model": capabilities.id, children: [
8183
8328
  controls.map((control) => {
8184
8329
  const id = `${baseId}-${control.key}`;
8185
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
8186
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
8187
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8330
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
8331
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
8332
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8188
8333
  Control,
8189
8334
  {
8190
8335
  control,
@@ -8195,23 +8340,23 @@ var GenerationSettings = ({
8195
8340
  )
8196
8341
  ] }, control.key);
8197
8342
  }),
8198
- slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
8199
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
8343
+ slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
8344
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
8200
8345
  slot.label,
8201
8346
  " ",
8202
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
8347
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
8203
8348
  "(",
8204
8349
  slot.references.length,
8205
8350
  "/",
8206
8351
  slot.max,
8207
8352
  ")"
8208
8353
  ] }),
8209
- slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-destructive", children: " *" })
8354
+ slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-destructive", children: " *" })
8210
8355
  ] }),
8211
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
8212
- slot.references.map((ref) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("li", { className: "flex items-center gap-1 rounded border border-border px-1.5 py-0.5", "data-reference-id": ref.id, children: [
8213
- renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
8214
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8356
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
8357
+ slot.references.map((ref) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("li", { className: "flex items-center gap-1 rounded border border-border px-1.5 py-0.5", "data-reference-id": ref.id, children: [
8358
+ renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
8359
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8215
8360
  "button",
8216
8361
  {
8217
8362
  type: "button",
@@ -8222,7 +8367,7 @@ var GenerationSettings = ({
8222
8367
  }
8223
8368
  )
8224
8369
  ] }, ref.id)),
8225
- onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8370
+ onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8226
8371
  "button",
8227
8372
  {
8228
8373
  type: "button",
@@ -8233,21 +8378,21 @@ var GenerationSettings = ({
8233
8378
  ) })
8234
8379
  ] })
8235
8380
  ] }, slot.role)),
8236
- showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ul", { role: "status", className: "flex flex-col gap-0.5 text-xs text-muted-foreground", "data-generation-adjustments": "", children: plan.adjustments.map((adjustment, index) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("li", { "data-adjustment-field": adjustment.field, "data-adjustment-kind": adjustment.kind, children: adjustment.reason }, index)) }),
8237
- showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ul", { role: "alert", className: "flex flex-col gap-0.5 text-xs text-destructive", "data-generation-errors": "", children: plan.errors.map((error, index) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("li", { "data-error-field": error.field, children: error.message }, index)) })
8381
+ showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("ul", { role: "status", className: "flex flex-col gap-0.5 text-xs text-muted-foreground", "data-generation-adjustments": "", children: plan.adjustments.map((adjustment, index) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("li", { "data-adjustment-field": adjustment.field, "data-adjustment-kind": adjustment.kind, children: adjustment.reason }, index)) }),
8382
+ showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("ul", { role: "alert", className: "flex flex-col gap-0.5 text-xs text-destructive", "data-generation-errors": "", children: plan.errors.map((error, index) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("li", { "data-error-field": error.field, children: error.message }, index)) })
8238
8383
  ] });
8239
8384
  };
8240
8385
 
8241
8386
  // src/generation/JobProgress.tsx
8242
- var import_jsx_runtime38 = require("react/jsx-runtime");
8387
+ var import_jsx_runtime40 = require("react/jsx-runtime");
8243
8388
  var JobProgress = ({ title, className = "", ...options }) => {
8244
8389
  const progress = useJobProgress(options);
8245
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: `flex flex-col gap-1 text-sm ${className}`, "data-job-progress": "", "data-done": options.done ? "" : void 0, children: [
8246
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
8247
- title && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "truncate text-foreground", children: title }),
8248
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
8390
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: `flex flex-col gap-1 text-sm ${className}`, "data-job-progress": "", "data-done": options.done ? "" : void 0, children: [
8391
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
8392
+ title && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "truncate text-foreground", children: title }),
8393
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
8249
8394
  ] }),
8250
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8395
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8251
8396
  "div",
8252
8397
  {
8253
8398
  role: "progressbar",
@@ -8257,7 +8402,7 @@ var JobProgress = ({ title, className = "", ...options }) => {
8257
8402
  "aria-valuenow": progress.percent,
8258
8403
  "aria-valuetext": `${progress.percent}%, ${progress.label}`,
8259
8404
  className: "h-1.5 w-full overflow-hidden rounded-full bg-muted",
8260
- children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8405
+ children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8261
8406
  "div",
8262
8407
  {
8263
8408
  className: "h-full rounded-full bg-primary transition-[width] duration-500",
@@ -8270,9 +8415,9 @@ var JobProgress = ({ title, className = "", ...options }) => {
8270
8415
  };
8271
8416
 
8272
8417
  // src/generation/AssetMentionChips.tsx
8273
- var import_react57 = require("react");
8418
+ var import_react58 = require("react");
8274
8419
  var import_generation3 = require("@pixerate/editor/generation");
8275
- var import_jsx_runtime39 = require("react/jsx-runtime");
8420
+ var import_jsx_runtime41 = require("react/jsx-runtime");
8276
8421
  var AssetMentionChips = ({
8277
8422
  content,
8278
8423
  onChange,
@@ -8282,14 +8427,14 @@ var AssetMentionChips = ({
8282
8427
  renderAsset,
8283
8428
  className = ""
8284
8429
  }) => {
8285
- const [open, setOpen] = (0, import_react57.useState)(null);
8286
- const rootRef = (0, import_react57.useRef)(null);
8287
- const chips = (0, import_react57.useMemo)(
8430
+ const [open, setOpen] = (0, import_react58.useState)(null);
8431
+ const rootRef = (0, import_react58.useRef)(null);
8432
+ const chips = (0, import_react58.useMemo)(
8288
8433
  () => (0, import_generation3.describeAssetMentions)((0, import_generation3.findTextMentions)(content), assets, capabilities),
8289
8434
  [content, assets, capabilities]
8290
8435
  );
8291
8436
  const options = roles ?? (capabilities ? (0, import_generation3.getAssetRoleOptions)(capabilities) : (0, import_generation3.defaultAssetRoleOptions)());
8292
- (0, import_react57.useEffect)(() => {
8437
+ (0, import_react58.useEffect)(() => {
8293
8438
  if (open === null) return;
8294
8439
  const onPointer = (event) => {
8295
8440
  if (!rootRef.current?.contains(event.target)) setOpen(null);
@@ -8303,13 +8448,13 @@ var AssetMentionChips = ({
8303
8448
  onChange((0, import_generation3.setMentionRoleInText)(content, chip6.start, role));
8304
8449
  };
8305
8450
  if (chips.length === 0) return null;
8306
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { ref: rootRef, className: `flex flex-wrap gap-1.5 ${className}`, "data-asset-mention-chips": "", children: chips.map((chip6) => {
8451
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { ref: rootRef, className: `flex flex-wrap gap-1.5 ${className}`, "data-asset-mention-chips": "", children: chips.map((chip6) => {
8307
8452
  const error = chip6.issues.find((issue) => issue.severity === "error");
8308
8453
  const warning = chip6.issues.find((issue) => issue.severity === "warning");
8309
8454
  const problem = error ?? warning;
8310
8455
  const isOpen = open === chip6.index;
8311
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip6.asset.id, children: [
8312
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8456
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip6.asset.id, children: [
8457
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
8313
8458
  "button",
8314
8459
  {
8315
8460
  type: "button",
@@ -8323,8 +8468,8 @@ var AssetMentionChips = ({
8323
8468
  },
8324
8469
  className: `inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs ${error ? "border-red-500/60" : warning ? "border-amber-500/60" : "border-border"} bg-muted/40 hover:bg-muted`,
8325
8470
  children: [
8326
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: renderAsset ? renderAsset(chip6) : `@${chip6.asset.label ?? chip6.handle}` }),
8327
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8471
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: renderAsset ? renderAsset(chip6) : `@${chip6.asset.label ?? chip6.handle}` }),
8472
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8328
8473
  "span",
8329
8474
  {
8330
8475
  className: `rounded px-1 text-[10px] uppercase tracking-wide ${chip6.role ? "bg-primary/15" : "opacity-60"}`,
@@ -8335,7 +8480,7 @@ var AssetMentionChips = ({
8335
8480
  ]
8336
8481
  }
8337
8482
  ),
8338
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8483
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
8339
8484
  "div",
8340
8485
  {
8341
8486
  role: "listbox",
@@ -8346,7 +8491,7 @@ var AssetMentionChips = ({
8346
8491
  if (e.key === "Escape") setOpen(null);
8347
8492
  },
8348
8493
  children: [
8349
- options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8494
+ options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
8350
8495
  "button",
8351
8496
  {
8352
8497
  type: "button",
@@ -8357,13 +8502,13 @@ var AssetMentionChips = ({
8357
8502
  onClick: () => pick(chip6, option.role),
8358
8503
  className: "flex items-center justify-between gap-2 rounded px-2 py-1 text-left hover:bg-muted",
8359
8504
  children: [
8360
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: option.label }),
8361
- option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
8505
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: option.label }),
8506
+ option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
8362
8507
  ]
8363
8508
  },
8364
8509
  option.role
8365
8510
  )),
8366
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8511
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8367
8512
  "button",
8368
8513
  {
8369
8514
  type: "button",
@@ -8375,7 +8520,7 @@ var AssetMentionChips = ({
8375
8520
  children: "No role"
8376
8521
  }
8377
8522
  ),
8378
- chip6.issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("ul", { className: "mt-1 border-t border-border px-2 pt-1 text-[10px]", "data-chip-issues": "", children: chip6.issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("li", { className: issue.severity === "error" ? "text-red-500" : "text-amber-500", children: issue.message }, i)) })
8523
+ chip6.issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("ul", { className: "mt-1 border-t border-border px-2 pt-1 text-[10px]", "data-chip-issues": "", children: chip6.issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("li", { className: issue.severity === "error" ? "text-red-500" : "text-amber-500", children: issue.message }, i)) })
8379
8524
  ]
8380
8525
  }
8381
8526
  )
@@ -8384,15 +8529,15 @@ var AssetMentionChips = ({
8384
8529
  };
8385
8530
 
8386
8531
  // src/generation/GenerationHistory.tsx
8387
- var import_react58 = require("react");
8532
+ var import_react59 = require("react");
8388
8533
  var import_generation4 = require("@pixerate/editor/generation");
8389
- var import_jsx_runtime40 = require("react/jsx-runtime");
8534
+ var import_jsx_runtime42 = require("react/jsx-runtime");
8390
8535
  function useGenerationRecords(store, filter) {
8391
- const [records, setRecords] = (0, import_react58.useState)([]);
8392
- const [loading, setLoading] = (0, import_react58.useState)(!!store);
8393
- const [error, setError] = (0, import_react58.useState)(null);
8536
+ const [records, setRecords] = (0, import_react59.useState)([]);
8537
+ const [loading, setLoading] = (0, import_react59.useState)(!!store);
8538
+ const [error, setError] = (0, import_react59.useState)(null);
8394
8539
  const filterKey = (0, import_generation4.stableStringify)(filter ?? {});
8395
- const refresh = (0, import_react58.useCallback)(async () => {
8540
+ const refresh = (0, import_react59.useCallback)(async () => {
8396
8541
  if (!store) {
8397
8542
  setRecords([]);
8398
8543
  setLoading(false);
@@ -8409,7 +8554,7 @@ function useGenerationRecords(store, filter) {
8409
8554
  setLoading(false);
8410
8555
  }
8411
8556
  }, [store, filterKey]);
8412
- (0, import_react58.useEffect)(() => {
8557
+ (0, import_react59.useEffect)(() => {
8413
8558
  void refresh();
8414
8559
  if (!store) return;
8415
8560
  return store.subscribe(() => void refresh());
@@ -8435,21 +8580,21 @@ var GenerationHistory = ({
8435
8580
  emptyText = "No generations yet.",
8436
8581
  className = ""
8437
8582
  }) => {
8438
- const [innerMode, setInnerMode] = (0, import_react58.useState)("exact");
8583
+ const [innerMode, setInnerMode] = (0, import_react59.useState)("exact");
8439
8584
  const mode = modeProp ?? innerMode;
8440
8585
  const setMode = (next) => {
8441
8586
  if (modeProp === void 0) setInnerMode(next);
8442
8587
  onModeChange?.(next);
8443
8588
  };
8444
- const options = (0, import_react58.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
8445
- const results = (0, import_react58.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
8446
- const models = (0, import_react58.useMemo)(
8589
+ const options = (0, import_react59.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
8590
+ const results = (0, import_react59.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
8591
+ const models = (0, import_react59.useMemo)(
8447
8592
  () => capabilities ? Array.isArray(capabilities) ? capabilities : [capabilities] : [],
8448
8593
  [capabilities]
8449
8594
  );
8450
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
8451
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "flex items-center gap-2 text-xs", role: "radiogroup", "aria-label": "Recreate mode", children: ["exact", "latest"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("label", { className: "inline-flex items-center gap-1", children: [
8452
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8595
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
8596
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex items-center gap-2 text-xs", role: "radiogroup", "aria-label": "Recreate mode", children: ["exact", "latest"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("label", { className: "inline-flex items-center gap-1", children: [
8597
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8453
8598
  "input",
8454
8599
  {
8455
8600
  type: "radio",
@@ -8462,34 +8607,34 @@ var GenerationHistory = ({
8462
8607
  ),
8463
8608
  value === "exact" ? "Exact (recorded versions)" : "Latest templates & settings"
8464
8609
  ] }, value)) }),
8465
- records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
8466
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
8610
+ records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
8611
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
8467
8612
  const result = results[i];
8468
8613
  const model = models.find((m) => m.id === record.provenance.modelId);
8469
8614
  const blocked = !result.ok;
8470
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
8615
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
8471
8616
  "li",
8472
8617
  {
8473
8618
  className: "rounded-md border border-border p-2",
8474
8619
  "data-record": record.id,
8475
8620
  "data-drift": result.drift.length,
8476
8621
  children: [
8477
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
8478
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
8479
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "text-muted-foreground", children: [
8480
- record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { "data-kind": "", children: [
8622
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
8623
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
8624
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-muted-foreground", children: [
8625
+ record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { "data-kind": "", children: [
8481
8626
  record.kind,
8482
8627
  " \xB7 "
8483
8628
  ] }),
8484
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
8485
- record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
8629
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
8630
+ record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
8486
8631
  " \xB7 seed ",
8487
8632
  record.seed
8488
8633
  ] })
8489
8634
  ] })
8490
8635
  ] }),
8491
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
8492
- record.assets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "mt-1 flex flex-wrap gap-1", children: record.assets.map((asset) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
8636
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
8637
+ record.assets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "mt-1 flex flex-wrap gap-1", children: record.assets.map((asset) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
8493
8638
  "span",
8494
8639
  {
8495
8640
  className: "rounded-full bg-muted px-2 py-0.5 text-[10px]",
@@ -8503,16 +8648,16 @@ var GenerationHistory = ({
8503
8648
  `${asset.role}:${asset.id}`
8504
8649
  )) }),
8505
8650
  renderPreview?.(record),
8506
- result.drift.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("ul", { className: "mt-1 flex flex-col gap-0.5 text-[11px]", "data-drift-report": "", children: result.drift.map((item, j) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("li", { className: severityClass[item.severity], "data-drift-type": item.type, children: [
8507
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("strong", { children: [
8651
+ result.drift.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { className: "mt-1 flex flex-col gap-0.5 text-[11px]", "data-drift-report": "", children: result.drift.map((item, j) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("li", { className: severityClass[item.severity], "data-drift-type": item.type, children: [
8652
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("strong", { children: [
8508
8653
  import_generation4.DRIFT_TYPE_LABELS[item.type],
8509
8654
  ":"
8510
8655
  ] }),
8511
8656
  " ",
8512
8657
  item.message
8513
8658
  ] }, j)) }),
8514
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "mt-2 flex gap-2", children: [
8515
- onRecreate && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8659
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "mt-2 flex gap-2", children: [
8660
+ onRecreate && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8516
8661
  "button",
8517
8662
  {
8518
8663
  type: "button",
@@ -8524,7 +8669,7 @@ var GenerationHistory = ({
8524
8669
  children: "Recreate"
8525
8670
  }
8526
8671
  ),
8527
- onVariation && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8672
+ onVariation && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8528
8673
  "button",
8529
8674
  {
8530
8675
  type: "button",
@@ -8534,7 +8679,7 @@ var GenerationHistory = ({
8534
8679
  children: "Variation"
8535
8680
  }
8536
8681
  ),
8537
- onRemove && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8682
+ onRemove && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8538
8683
  "button",
8539
8684
  {
8540
8685
  type: "button",
@@ -8554,19 +8699,19 @@ var GenerationHistory = ({
8554
8699
  };
8555
8700
 
8556
8701
  // src/find-replace/useFindReplace.ts
8557
- var import_react59 = require("react");
8702
+ var import_react60 = require("react");
8558
8703
  var import_editor16 = require("@pixerate/editor");
8559
8704
  var noopUnsubscribe2 = () => {
8560
8705
  };
8561
8706
  function useFindReplace(editor) {
8562
8707
  const store = (0, import_editor16.getFindReplaceStore)(editor ?? null);
8563
- const subscribe = (0, import_react59.useCallback)(
8708
+ const subscribe = (0, import_react60.useCallback)(
8564
8709
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe2,
8565
8710
  [store]
8566
8711
  );
8567
8712
  const getSnapshot = () => store?.getSnapshot() ?? import_editor16.EMPTY_FIND_REPLACE_SNAPSHOT;
8568
- const snapshot = (0, import_react59.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
8569
- return (0, import_react59.useMemo)(() => {
8713
+ const snapshot = (0, import_react60.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
8714
+ return (0, import_react60.useMemo)(() => {
8570
8715
  const run = (fn) => {
8571
8716
  if (editor && !editor.isDestroyed && store) fn(editor);
8572
8717
  };
@@ -8590,9 +8735,9 @@ function useFindReplace(editor) {
8590
8735
  }
8591
8736
 
8592
8737
  // src/find-replace/FindReplaceBar.tsx
8593
- var import_react60 = require("react");
8738
+ var import_react61 = require("react");
8594
8739
  var import_editor17 = require("@pixerate/editor");
8595
- var import_jsx_runtime41 = require("react/jsx-runtime");
8740
+ var import_jsx_runtime43 = require("react/jsx-runtime");
8596
8741
  var inputClass3 = "min-w-0 flex-1 rounded border border-input bg-background px-2 py-1 text-xs text-foreground focus:outline-none focus:ring-1 focus:ring-ring";
8597
8742
  var buttonClass5 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
8598
8743
  var toggleClass = (on) => `${buttonClass5} font-mono ${on ? "bg-primary/10 text-primary" : "text-muted-foreground"}`;
@@ -8605,10 +8750,10 @@ var FindReplaceBar = ({
8605
8750
  onClose
8606
8751
  }) => {
8607
8752
  const find = useFindReplace(editor);
8608
- const findInput = (0, import_react60.useRef)(null);
8609
- const [moreOpen, setMoreOpen] = (0, import_react60.useState)(false);
8753
+ const findInput = (0, import_react61.useRef)(null);
8754
+ const [moreOpen, setMoreOpen] = (0, import_react61.useState)(false);
8610
8755
  const visible = find.available && (alwaysOpen || find.open);
8611
- (0, import_react60.useEffect)(() => {
8756
+ (0, import_react61.useEffect)(() => {
8612
8757
  if (!visible || find.focusRequest === 0) return;
8613
8758
  findInput.current?.focus();
8614
8759
  findInput.current?.select();
@@ -8646,9 +8791,9 @@ var FindReplaceBar = ({
8646
8791
  if (isMod(e)) find.replaceAll();
8647
8792
  else find.replace();
8648
8793
  };
8649
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
8650
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-1", children: [
8651
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8794
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
8795
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-1", children: [
8796
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8652
8797
  "button",
8653
8798
  {
8654
8799
  type: "button",
@@ -8659,7 +8804,7 @@ var FindReplaceBar = ({
8659
8804
  children: showReplace ? "\u25BE" : "\u25B8"
8660
8805
  }
8661
8806
  ),
8662
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8807
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8663
8808
  "input",
8664
8809
  {
8665
8810
  ref: findInput,
@@ -8673,7 +8818,7 @@ var FindReplaceBar = ({
8673
8818
  onKeyDown: onFindKeyDown
8674
8819
  }
8675
8820
  ),
8676
- import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8821
+ import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8677
8822
  "button",
8678
8823
  {
8679
8824
  type: "button",
@@ -8686,7 +8831,7 @@ var FindReplaceBar = ({
8686
8831
  },
8687
8832
  t.key
8688
8833
  )),
8689
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8834
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8690
8835
  "span",
8691
8836
  {
8692
8837
  className: `min-w-[5rem] px-1 text-center text-xs ${find.error ? "text-destructive" : "text-muted-foreground"}`,
@@ -8696,9 +8841,9 @@ var FindReplaceBar = ({
8696
8841
  children: status
8697
8842
  }
8698
8843
  ),
8699
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
8700
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
8701
- showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8844
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
8845
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
8846
+ showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8702
8847
  "button",
8703
8848
  {
8704
8849
  type: "button",
@@ -8709,10 +8854,10 @@ var FindReplaceBar = ({
8709
8854
  children: "\u2026"
8710
8855
  }
8711
8856
  ),
8712
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
8857
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
8713
8858
  ] }),
8714
- showReplace && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
8715
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8859
+ showReplace && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
8860
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8716
8861
  "input",
8717
8862
  {
8718
8863
  type: "text",
@@ -8724,7 +8869,7 @@ var FindReplaceBar = ({
8724
8869
  onKeyDown: onReplaceKeyDown
8725
8870
  }
8726
8871
  ),
8727
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8872
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8728
8873
  "button",
8729
8874
  {
8730
8875
  type: "button",
@@ -8734,11 +8879,11 @@ var FindReplaceBar = ({
8734
8879
  children: "Replace"
8735
8880
  }
8736
8881
  ),
8737
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
8738
- find.lastReplaceCount !== null && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "px-1 text-xs text-muted-foreground", "aria-live": "polite", children: find.lastReplaceCount === 1 ? "1 replaced" : `${find.lastReplaceCount} replaced` })
8882
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
8883
+ find.lastReplaceCount !== null && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "px-1 text-xs text-muted-foreground", "aria-live": "polite", children: find.lastReplaceCount === 1 ? "1 replaced" : `${find.lastReplaceCount} replaced` })
8739
8884
  ] }),
8740
- showMoreOptions && moreOpen && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 pl-7 text-xs text-muted-foreground", children: import_editor17.FIND_OPTION_TOGGLES.filter((t) => t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { className: "flex items-center gap-1", children: [
8741
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8885
+ showMoreOptions && moreOpen && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 pl-7 text-xs text-muted-foreground", children: import_editor17.FIND_OPTION_TOGGLES.filter((t) => t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("label", { className: "flex items-center gap-1", children: [
8886
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8742
8887
  "input",
8743
8888
  {
8744
8889
  type: "checkbox",
@@ -8752,12 +8897,12 @@ var FindReplaceBar = ({
8752
8897
  };
8753
8898
 
8754
8899
  // src/tables/useTableMenu.ts
8755
- var import_react61 = require("react");
8900
+ var import_react62 = require("react");
8756
8901
  var import_editor18 = require("@pixerate/editor");
8757
8902
  function useTableMenu(editor) {
8758
- const store = (0, import_react61.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
8759
- const snapshot = (0, import_react61.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
8760
- return (0, import_react61.useMemo)(
8903
+ const store = (0, import_react62.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
8904
+ const snapshot = (0, import_react62.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
8905
+ return (0, import_react62.useMemo)(
8761
8906
  () => ({
8762
8907
  ...snapshot,
8763
8908
  run: (action, params) => (0, import_editor18.runTableAction)(editor, action, params, { focus: true }),
@@ -8768,9 +8913,9 @@ function useTableMenu(editor) {
8768
8913
  }
8769
8914
 
8770
8915
  // src/tables/TableToolbar.tsx
8771
- var import_react62 = __toESM(require("react"), 1);
8916
+ var import_react63 = __toESM(require("react"), 1);
8772
8917
  var import_editor19 = require("@pixerate/editor");
8773
- var import_jsx_runtime42 = require("react/jsx-runtime");
8918
+ var import_jsx_runtime44 = require("react/jsx-runtime");
8774
8919
  var keepSelection2 = (event) => event.preventDefault();
8775
8920
  var TableToolbar = ({
8776
8921
  editor,
@@ -8784,14 +8929,14 @@ var TableToolbar = ({
8784
8929
  }) => {
8785
8930
  const table = useTableMenu(editor);
8786
8931
  if (!editor || !table.inTable && !showWhenOutside) return null;
8787
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
8932
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
8788
8933
  const status = table.check(item.action, item.params);
8789
8934
  const enabled = status === true;
8790
8935
  const active = item.active?.(table);
8791
8936
  const separator = index > 0 && items[index - 1].group !== item.group;
8792
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react62.default.Fragment, { children: [
8793
- separator && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
8794
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8937
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_react63.default.Fragment, { children: [
8938
+ separator && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
8939
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8795
8940
  "button",
8796
8941
  {
8797
8942
  type: "button",
@@ -8813,8 +8958,8 @@ var TableToolbar = ({
8813
8958
  };
8814
8959
 
8815
8960
  // src/tables/InsertTableGrid.tsx
8816
- var import_react63 = require("react");
8817
- var import_jsx_runtime43 = require("react/jsx-runtime");
8961
+ var import_react64 = require("react");
8962
+ var import_jsx_runtime45 = require("react/jsx-runtime");
8818
8963
  var keepSelection3 = (event) => event.preventDefault();
8819
8964
  var InsertTableGrid = ({
8820
8965
  editor,
@@ -8827,14 +8972,14 @@ var InsertTableGrid = ({
8827
8972
  onInsert
8828
8973
  }) => {
8829
8974
  const table = useTableMenu(editor);
8830
- const [hover, setHover] = (0, import_react63.useState)(null);
8975
+ const [hover, setHover] = (0, import_react64.useState)(null);
8831
8976
  const status = table.actions.insertTable;
8832
8977
  const disabled = !editor || !status.enabled;
8833
8978
  const insert = (size) => {
8834
8979
  if (table.run("insertTable", { ...size, withHeaderRow })) onInsert?.(size);
8835
8980
  setHover(null);
8836
8981
  };
8837
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
8982
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
8838
8983
  "div",
8839
8984
  {
8840
8985
  className,
@@ -8844,7 +8989,7 @@ var InsertTableGrid = ({
8844
8989
  "data-insert-table-grid": "",
8845
8990
  onMouseLeave: () => setHover(null),
8846
8991
  children: [
8847
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8992
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
8848
8993
  "div",
8849
8994
  {
8850
8995
  role: "grid",
@@ -8853,7 +8998,7 @@ var InsertTableGrid = ({
8853
8998
  children: Array.from({ length: rows * cols }, (_, i) => {
8854
8999
  const size = { rows: Math.floor(i / cols) + 1, cols: i % cols + 1 };
8855
9000
  const active = !!hover && size.rows <= hover.rows && size.cols <= hover.cols;
8856
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
9001
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
8857
9002
  "button",
8858
9003
  {
8859
9004
  type: "button",
@@ -8873,7 +9018,7 @@ var InsertTableGrid = ({
8873
9018
  })
8874
9019
  }
8875
9020
  ),
8876
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { "aria-live": "polite", "data-testid": "insert-table-size", children: disabled ? status.reason : hover ? `${hover.rows} \xD7 ${hover.cols}` : "Insert table" })
9021
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { "aria-live": "polite", "data-testid": "insert-table-size", children: disabled ? status.reason : hover ? `${hover.rows} \xD7 ${hover.cols}` : "Insert table" })
8877
9022
  ]
8878
9023
  }
8879
9024
  );
@@ -8881,31 +9026,31 @@ var InsertTableGrid = ({
8881
9026
 
8882
9027
  // src/tables/TableBubbleMenu.tsx
8883
9028
  var import_editor20 = require("@pixerate/editor");
8884
- var import_jsx_runtime44 = require("react/jsx-runtime");
9029
+ var import_jsx_runtime46 = require("react/jsx-runtime");
8885
9030
  var TableBubbleMenu = ({
8886
9031
  editor,
8887
9032
  children,
8888
9033
  toolbarProps,
8889
9034
  pluginKey = "tableBubbleMenu",
8890
9035
  ...rest
8891
- }) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(BubbleMenu, { editor, pluginKey, shouldShow: import_editor20.shouldShowTableBubbleMenu, ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(TableToolbar, { editor, ...toolbarProps }) });
9036
+ }) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(BubbleMenu, { editor, pluginKey, shouldShow: import_editor20.shouldShowTableBubbleMenu, ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(TableToolbar, { editor, ...toolbarProps }) });
8892
9037
 
8893
9038
  // src/chart-node/ChartNodeView.tsx
8894
9039
  var import_client = require("react-dom/client");
8895
9040
 
8896
9041
  // src/chart/ChartCanvas.tsx
8897
- var import_react65 = require("react");
9042
+ var import_react66 = require("react");
8898
9043
  var import_chart2 = require("@pixerate/editor/chart");
8899
9044
 
8900
9045
  // src/chart/useChartEditor.ts
8901
- var import_react64 = require("react");
9046
+ var import_react65 = require("react");
8902
9047
  var import_chart = require("@pixerate/editor/chart");
8903
9048
  function useChartState(controller) {
8904
- return (0, import_react64.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
9049
+ return (0, import_react65.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
8905
9050
  }
8906
9051
 
8907
9052
  // src/chart/ChartCanvas.tsx
8908
- var import_jsx_runtime45 = require("react/jsx-runtime");
9053
+ var import_jsx_runtime47 = require("react/jsx-runtime");
8909
9054
  function renderChartMark(mark, fontFamily, interactive) {
8910
9055
  const common = {
8911
9056
  "data-role": mark.role,
@@ -8917,9 +9062,9 @@ function renderChartMark(mark, fontFamily, interactive) {
8917
9062
  };
8918
9063
  switch (mark.kind) {
8919
9064
  case "rect":
8920
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("rect", { ...common, x: mark.x, y: mark.y, width: mark.width, height: mark.height, rx: mark.radius, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
9065
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("rect", { ...common, x: mark.x, y: mark.y, width: mark.width, height: mark.height, rx: mark.radius, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
8921
9066
  case "path":
8922
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9067
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
8923
9068
  "path",
8924
9069
  {
8925
9070
  ...common,
@@ -8932,11 +9077,11 @@ function renderChartMark(mark, fontFamily, interactive) {
8932
9077
  mark.key
8933
9078
  );
8934
9079
  case "circle":
8935
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("circle", { ...common, cx: mark.cx, cy: mark.cy, r: mark.r, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
9080
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("circle", { ...common, cx: mark.cx, cy: mark.cy, r: mark.r, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
8936
9081
  case "line":
8937
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("line", { ...common, x1: mark.x1, y1: mark.y1, x2: mark.x2, y2: mark.y2, strokeDasharray: mark.dash, style: { stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
9082
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("line", { ...common, x1: mark.x1, y1: mark.y1, x2: mark.x2, y2: mark.y2, strokeDasharray: mark.dash, style: { stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
8938
9083
  case "text":
8939
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9084
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
8940
9085
  "text",
8941
9086
  {
8942
9087
  ...common,
@@ -8953,23 +9098,23 @@ function renderChartMark(mark, fontFamily, interactive) {
8953
9098
  }
8954
9099
  }
8955
9100
  function ChartPresenceLayer({ presence }) {
8956
- const { actors } = (0, import_react65.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
8957
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("g", { "data-chart-presence": "", pointerEvents: "none", children: actors.map((a) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("g", { transform: `translate(${a.x} ${a.y})`, "data-actor": a.id, children: [
8958
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("path", { d: "M0,0 L0,14 L4,10.5 L7,17 L9.5,16 L6.5,9.5 L11.5,9.5 Z", style: { fill: a.color, stroke: "#ffffff", strokeWidth: 1 }, transform: a.pressed ? "scale(0.9)" : void 0 }),
8959
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("g", { transform: "translate(13 16)", children: [
8960
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("rect", { x: 0, y: 0, rx: 4, height: 18, width: Math.max(28, (a.message ?? a.name).length * 6.4 + 12), style: { fill: a.color } }),
8961
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("text", { x: 6, y: 9, dominantBaseline: "central", style: { fill: "#ffffff", fontSize: 11, fontWeight: 600, fontFamily: "inherit" }, children: a.message ?? a.name })
9101
+ const { actors } = (0, import_react66.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
9102
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("g", { "data-chart-presence": "", pointerEvents: "none", children: actors.map((a) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("g", { transform: `translate(${a.x} ${a.y})`, "data-actor": a.id, children: [
9103
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("path", { d: "M0,0 L0,14 L4,10.5 L7,17 L9.5,16 L6.5,9.5 L11.5,9.5 Z", style: { fill: a.color, stroke: "#ffffff", strokeWidth: 1 }, transform: a.pressed ? "scale(0.9)" : void 0 }),
9104
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("g", { transform: "translate(13 16)", children: [
9105
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("rect", { x: 0, y: 0, rx: 4, height: 18, width: Math.max(28, (a.message ?? a.name).length * 6.4 + 12), style: { fill: a.color } }),
9106
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("text", { x: 6, y: 9, dominantBaseline: "central", style: { fill: "#ffffff", fontSize: 11, fontWeight: 600, fontFamily: "inherit" }, children: a.message ?? a.name })
8962
9107
  ] })
8963
9108
  ] }, a.id)) });
8964
9109
  }
8965
9110
  function ChartCanvas({ controller, width = 640, height = 400, responsive = true, theme, editable = true, measureText, emptyMessage, className, presence, sceneRef }) {
8966
9111
  const state = useChartState(controller);
8967
- const wrapper = (0, import_react65.useRef)(null);
8968
- const svg = (0, import_react65.useRef)(null);
8969
- const drag = (0, import_react65.useRef)(null);
8970
- const [measured, setMeasured] = (0, import_react65.useState)(null);
8971
- const [frozen, setFrozen] = (0, import_react65.useState)(null);
8972
- (0, import_react65.useEffect)(() => {
9112
+ const wrapper = (0, import_react66.useRef)(null);
9113
+ const svg = (0, import_react66.useRef)(null);
9114
+ const drag = (0, import_react66.useRef)(null);
9115
+ const [measured, setMeasured] = (0, import_react66.useState)(null);
9116
+ const [frozen, setFrozen] = (0, import_react66.useState)(null);
9117
+ (0, import_react66.useEffect)(() => {
8973
9118
  const el = wrapper.current;
8974
9119
  if (!responsive || !el || typeof ResizeObserver === "undefined") return;
8975
9120
  const observer = new ResizeObserver(([entry]) => {
@@ -8980,8 +9125,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8980
9125
  return () => observer.disconnect();
8981
9126
  }, [responsive]);
8982
9127
  const sceneWidth = responsive && measured || width;
8983
- const fullTheme = (0, import_react65.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
8984
- const scene = (0, import_react65.useMemo)(
9128
+ const fullTheme = (0, import_react66.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
9129
+ const scene = (0, import_react66.useMemo)(
8985
9130
  () => (0, import_chart2.layoutChart)(state.spec, {
8986
9131
  width: sceneWidth,
8987
9132
  height,
@@ -8997,8 +9142,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8997
9142
  [state.spec, state.selection, sceneWidth, height, fullTheme, editable, measureText, emptyMessage, frozen]
8998
9143
  );
8999
9144
  if (sceneRef) sceneRef.current = scene;
9000
- const byKey = (0, import_react65.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
9001
- (0, import_react65.useEffect)(() => () => drag.current?.end(), []);
9145
+ const byKey = (0, import_react66.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
9146
+ (0, import_react66.useEffect)(() => () => drag.current?.end(), []);
9002
9147
  const scenePoint = (e) => (0, import_chart2.chartClientToScene)(scene, svg.current.getBoundingClientRect(), e.clientX, e.clientY);
9003
9148
  const onPointerDown = (e) => {
9004
9149
  if (!editable || e.button !== 0) return;
@@ -9031,7 +9176,7 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
9031
9176
  if (editable && (0, import_chart2.handleChartKey)(controller, scene, e)) e.preventDefault();
9032
9177
  };
9033
9178
  const label = state.spec.title || "Chart";
9034
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { ref: wrapper, className: `w-full ${className ?? ""}`, "data-chart-canvas": "", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
9179
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { ref: wrapper, className: `w-full ${className ?? ""}`, "data-chart-canvas": "", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9035
9180
  "svg",
9036
9181
  {
9037
9182
  ref: svg,
@@ -9049,14 +9194,14 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
9049
9194
  onKeyDown,
9050
9195
  children: [
9051
9196
  scene.marks.map((m) => renderChartMark(m, scene.theme.fontFamily, editable)),
9052
- presence && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartPresenceLayer, { presence })
9197
+ presence && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartPresenceLayer, { presence })
9053
9198
  ]
9054
9199
  }
9055
9200
  ) });
9056
9201
  }
9057
9202
 
9058
9203
  // src/chart/ChartDataGrid.tsx
9059
- var import_react66 = require("react");
9204
+ var import_react67 = require("react");
9060
9205
  var import_chart3 = require("@pixerate/editor/chart");
9061
9206
 
9062
9207
  // src/chart/styles.ts
@@ -9069,11 +9214,11 @@ var chartSectionClass = "space-y-2 border-b border-border pb-3 last:border-b-0";
9069
9214
  var chartCellClass = "h-7 w-full min-w-[4.5rem] bg-transparent px-2 text-right text-xs tabular-nums text-foreground focus-visible:bg-background focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-primary";
9070
9215
 
9071
9216
  // src/chart/ChartDataGrid.tsx
9072
- var import_jsx_runtime46 = require("react/jsx-runtime");
9217
+ var import_jsx_runtime48 = require("react/jsx-runtime");
9073
9218
  function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
9074
- const [draft, setDraft] = (0, import_react66.useState)(value);
9075
- const typing = (0, import_react66.useRef)(false);
9076
- (0, import_react66.useEffect)(() => {
9219
+ const [draft, setDraft] = (0, import_react67.useState)(value);
9220
+ const typing = (0, import_react67.useRef)(false);
9221
+ (0, import_react67.useEffect)(() => {
9077
9222
  if (!typing.current) setDraft(value);
9078
9223
  }, [value]);
9079
9224
  const commit = () => {
@@ -9082,7 +9227,7 @@ function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
9082
9227
  if (draft === value) return;
9083
9228
  if (onCommit(draft) === false) setDraft(value);
9084
9229
  };
9085
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9230
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
9086
9231
  "input",
9087
9232
  {
9088
9233
  ...rest,
@@ -9117,15 +9262,15 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9117
9262
  e.preventDefault();
9118
9263
  controller.pasteCells(row, column, text);
9119
9264
  };
9120
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
9121
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
9122
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("tr", { children: [
9123
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("th", { className: "border-b border-r border-border px-2 py-1 text-left font-medium text-muted-foreground", children: categoryHeader }),
9265
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
9266
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
9267
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("tr", { children: [
9268
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("th", { className: "border-b border-r border-border px-2 py-1 text-left font-medium text-muted-foreground", children: categoryHeader }),
9124
9269
  spec.series.map((s, si) => {
9125
9270
  const color = (0, import_chart3.chartSeriesColor)(spec, si);
9126
9271
  const selected = selection?.kind === "series" && selection.seriesId === s.id;
9127
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("th", { "data-series-id": s.id, className: `border-b border-r border-border px-1 py-1 font-medium ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-1", children: [
9128
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9272
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("th", { "data-series-id": s.id, className: `border-b border-r border-border px-1 py-1 font-medium ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex items-center gap-1", children: [
9273
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
9129
9274
  "input",
9130
9275
  {
9131
9276
  type: "color",
@@ -9138,7 +9283,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9138
9283
  className: "h-5 w-5 shrink-0 cursor-pointer rounded border-0 bg-transparent p-0"
9139
9284
  }
9140
9285
  ),
9141
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9286
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
9142
9287
  ChartCommitInput,
9143
9288
  {
9144
9289
  value: s.name,
@@ -9148,8 +9293,8 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9148
9293
  className: `${chartInputClass} h-6 min-w-[5rem] border-transparent bg-transparent font-medium ${s.hidden ? "text-muted-foreground line-through" : ""}`
9149
9294
  }
9150
9295
  ),
9151
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
9152
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9296
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
9297
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
9153
9298
  "button",
9154
9299
  {
9155
9300
  type: "button",
@@ -9162,16 +9307,16 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9162
9307
  children: s.hidden ? "\u25CB" : "\u25CF"
9163
9308
  }
9164
9309
  ),
9165
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete series", "aria-label": `Delete ${s.name}`, "data-action": "remove-series", onClick: () => controller.removeSeries(s.id), children: "\xD7" })
9310
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete series", "aria-label": `Delete ${s.name}`, "data-action": "remove-series", onClick: () => controller.removeSeries(s.id), children: "\xD7" })
9166
9311
  ] })
9167
9312
  ] }) }, s.id);
9168
9313
  }),
9169
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("th", { className: "w-8 border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Add series", "aria-label": "Add series", "data-action": "add-series", onClick: () => controller.addSeries(), children: "+" }) })
9314
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("th", { className: "w-8 border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Add series", "aria-label": "Add series", "data-action": "add-series", onClick: () => controller.addSeries(), children: "+" }) })
9170
9315
  ] }) }),
9171
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("tbody", { children: spec.categories.map((category, i) => {
9316
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("tbody", { children: spec.categories.map((category, i) => {
9172
9317
  const rowSelected = selection?.kind === "category" && selection.index === i;
9173
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
9174
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("th", { className: "border-b border-r border-border p-0 text-left font-normal", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9318
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
9319
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("th", { className: "border-b border-r border-border p-0 text-left font-normal", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
9175
9320
  ChartCommitInput,
9176
9321
  {
9177
9322
  value: category,
@@ -9185,7 +9330,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9185
9330
  spec.series.map((s) => {
9186
9331
  const value = s.values[i];
9187
9332
  const selected = selection?.kind === "point" && selection.seriesId === s.id && selection.index === i;
9188
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("td", { className: `border-b border-r border-border p-0 ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9333
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("td", { className: `border-b border-r border-border p-0 ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
9189
9334
  ChartCommitInput,
9190
9335
  {
9191
9336
  value: value === null || value === void 0 ? "" : String(value),
@@ -9200,38 +9345,38 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9200
9345
  }
9201
9346
  ) }, s.id);
9202
9347
  }),
9203
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("td", { className: "border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete category", "aria-label": `Delete ${category}`, "data-action": "remove-category", onClick: () => controller.removeCategory(i), children: "\xD7" }) })
9348
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("td", { className: "border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete category", "aria-label": `Delete ${category}`, "data-action": "remove-category", onClick: () => controller.removeCategory(i), children: "\xD7" }) })
9204
9349
  ] }, i);
9205
9350
  }) })
9206
9351
  ] }),
9207
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "p-1", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: `${chartButtonClass} h-6 border-dashed`, "data-action": "add-category", onClick: () => controller.addCategory(), children: "+ Add category" }) })
9352
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "p-1", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", className: `${chartButtonClass} h-6 border-dashed`, "data-action": "add-category", onClick: () => controller.addCategory(), children: "+ Add category" }) })
9208
9353
  ] });
9209
9354
  }
9210
9355
 
9211
9356
  // src/chart/ChartInspector.tsx
9212
- var import_react67 = require("react");
9357
+ var import_react68 = require("react");
9213
9358
  var import_chart4 = require("@pixerate/editor/chart");
9214
- var import_jsx_runtime47 = require("react/jsx-runtime");
9359
+ var import_jsx_runtime49 = require("react/jsx-runtime");
9215
9360
  var cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
9216
9361
  function Field({ label, htmlFor, children }) {
9217
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
9218
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
9219
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "min-w-0 flex-1", children })
9362
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center gap-2", children: [
9363
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
9364
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "min-w-0 flex-1", children })
9220
9365
  ] });
9221
9366
  }
9222
9367
  function Toggle({ label, checked, onChange, name }) {
9223
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
9224
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("input", { type: "checkbox", className: "h-3.5 w-3.5 accent-primary", checked, "data-option": name, onChange: (e) => onChange(e.currentTarget.checked) }),
9368
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
9369
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("input", { type: "checkbox", className: "h-3.5 w-3.5 accent-primary", checked, "data-option": name, onChange: (e) => onChange(e.currentTarget.checked) }),
9225
9370
  label
9226
9371
  ] });
9227
9372
  }
9228
9373
  function Select({ id, value, options, onChange, name, labels }) {
9229
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("select", { id, className: chartInputClass, value, "data-option": name, onChange: (e) => onChange(e.currentTarget.value), children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: o, children: labels?.[o] ?? cap(o) }, o)) });
9374
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("select", { id, className: chartInputClass, value, "data-option": name, onChange: (e) => onChange(e.currentTarget.value), children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: o, children: labels?.[o] ?? cap(o) }, o)) });
9230
9375
  }
9231
9376
  function AxisSection({ controller, axis, value, idBase, horizontal, numeric = false, scales = false }) {
9232
9377
  const set = (patch) => controller.setAxis(axis, patch);
9233
9378
  const setFormat = (patch) => set({ format: { ...value.format, ...patch } });
9234
- const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9379
+ const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
9235
9380
  ChartCommitInput,
9236
9381
  {
9237
9382
  id: `${idBase}-${axis}-${key2}`,
@@ -9246,26 +9391,26 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9246
9391
  const name = axis === "x" ? numeric ? "X axis" : "Category axis" : axis === "y" ? "Value axis" : "Secondary axis";
9247
9392
  const valueAxis = axis !== "x" || numeric;
9248
9393
  const key = axis === "y2" ? "yAxis2" : `${axis}Axis`;
9249
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
9250
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center justify-between", children: [
9251
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
9394
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
9395
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center justify-between", children: [
9396
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
9252
9397
  name,
9253
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
9398
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
9254
9399
  "(",
9255
9400
  axis === "x" ? horizontal ? "left" : "bottom" : axis === "y2" ? horizontal ? "top" : "right" : horizontal ? "bottom" : "left",
9256
9401
  ")"
9257
9402
  ] })
9258
9403
  ] }),
9259
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
9404
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
9260
9405
  ] }),
9261
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Title", htmlFor: `${idBase}-${axis}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-title`, value: value.title, "data-option": `${axis}Axis.title`, className: chartInputClass, onCommit: (title) => void set({ title }) }) }),
9262
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9263
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
9264
- axis === "x" && !numeric && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Dates", name: "xAxis.kind", checked: value.kind === "date", onChange: (dates) => set({ kind: dates ? "date" : void 0 }) }),
9265
- scales && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
9266
- scales && valueAxis && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Log scale", name: `${key}.scale`, checked: value.scale === "log", onChange: (log) => set({ scale: log ? "log" : "linear" }) })
9406
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Title", htmlFor: `${idBase}-${axis}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-title`, value: value.title, "data-option": `${axis}Axis.title`, className: chartInputClass, onCommit: (title) => void set({ title }) }) }),
9407
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9408
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
9409
+ axis === "x" && !numeric && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Dates", name: "xAxis.kind", checked: value.kind === "date", onChange: (dates) => set({ kind: dates ? "date" : void 0 }) }),
9410
+ scales && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
9411
+ scales && valueAxis && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Log scale", name: `${key}.scale`, checked: value.scale === "log", onChange: (log) => set({ scale: log ? "log" : "linear" }) })
9267
9412
  ] }),
9268
- scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Log base", htmlFor: `${idBase}-${axis}-log-base`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9413
+ scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Log base", htmlFor: `${idBase}-${axis}-log-base`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
9269
9414
  ChartCommitInput,
9270
9415
  {
9271
9416
  id: `${idBase}-${axis}-log-base`,
@@ -9276,7 +9421,7 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9276
9421
  onCommit: (text) => set({ logBase: text.trim() === "" ? void 0 : Number(text) }).ok
9277
9422
  }
9278
9423
  ) }),
9279
- valueAxis && value.scale !== "log" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Step", htmlFor: `${idBase}-${axis}-step`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9424
+ valueAxis && value.scale !== "log" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Step", htmlFor: `${idBase}-${axis}-step`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
9280
9425
  ChartCommitInput,
9281
9426
  {
9282
9427
  id: `${idBase}-${axis}-step`,
@@ -9288,14 +9433,14 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9288
9433
  onCommit: (text) => set({ step: text.trim() === "" ? null : Number(text) }).ok
9289
9434
  }
9290
9435
  ) }),
9291
- valueAxis && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
9292
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex gap-1", children: [
9436
+ valueAxis && /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
9437
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex gap-1", children: [
9293
9438
  bound("min"),
9294
9439
  bound("max")
9295
9440
  ] }) }),
9296
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Format", htmlFor: `${idBase}-${axis}-format`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex gap-1", children: [
9297
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Select, { id: `${idBase}-${axis}-format`, name: `${key}.format.style`, value: value.format.style ?? "number", options: import_chart4.CHART_NUMBER_STYLES, onChange: (style) => setFormat({ style }) }),
9298
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9441
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Format", htmlFor: `${idBase}-${axis}-format`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex gap-1", children: [
9442
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Select, { id: `${idBase}-${axis}-format`, name: `${key}.format.style`, value: value.format.style ?? "number", options: import_chart4.CHART_NUMBER_STYLES, onChange: (style) => setFormat({ style }) }),
9443
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
9299
9444
  ChartCommitInput,
9300
9445
  {
9301
9446
  value: value.format.decimals === void 0 ? "" : String(value.format.decimals),
@@ -9314,8 +9459,8 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9314
9459
  }
9315
9460
  )
9316
9461
  ] }) }),
9317
- value.format.style === "currency" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Currency", htmlFor: `${idBase}-${axis}-currency`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-currency`, value: value.format.currency ?? "USD", "data-option": `${key}.format.currency`, className: chartInputClass, onCommit: (currency) => void setFormat({ currency: currency.toUpperCase() }) }) }),
9318
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9462
+ value.format.style === "currency" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Currency", htmlFor: `${idBase}-${axis}-currency`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-currency`, value: value.format.currency ?? "USD", "data-option": `${key}.format.currency`, className: chartInputClass, onCommit: (currency) => void setFormat({ currency: currency.toUpperCase() }) }) }),
9463
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
9319
9464
  ChartCommitInput,
9320
9465
  {
9321
9466
  id: `${idBase}-${axis}-code`,
@@ -9341,15 +9486,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
9341
9486
  const values = which === "xErrorBars" ? series.x ?? [] : series.values;
9342
9487
  const set = (next) => controller.updateSeries(series.id, { [which]: next });
9343
9488
  const patch = (p) => bars && set({ ...bars, ...p });
9344
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
9345
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: which === "errorBars" ? "Error bars" : "X error bars", htmlFor: `${id}-type`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("select", { id: `${id}-type`, className: chartInputClass, value: bars?.type ?? "", "data-option": `${key}.type`, onChange: (e) => set((0, import_chart4.chartErrorBarsOfType)(e.currentTarget.value, bars, values)), children: [
9346
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "None" }),
9347
- import_chart4.CHART_ERROR_BAR_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: t, children: import_chart4.CHART_ERROR_BAR_LABELS[t] }, t))
9489
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
9490
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: which === "errorBars" ? "Error bars" : "X error bars", htmlFor: `${id}-type`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("select", { id: `${id}-type`, className: chartInputClass, value: bars?.type ?? "", "data-option": `${key}.type`, onChange: (e) => set((0, import_chart4.chartErrorBarsOfType)(e.currentTarget.value, bars, values)), children: [
9491
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: "", children: "None" }),
9492
+ import_chart4.CHART_ERROR_BAR_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: t, children: import_chart4.CHART_ERROR_BAR_LABELS[t] }, t))
9348
9493
  ] }) }),
9349
- bars && (bars.type === "fixed" || bars.type === "percent" || bars.type === "stddev") && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: bars.type === "percent" ? "Percent" : bars.type === "stddev" ? "Deviations" : "Amount", htmlFor: `${id}-value`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${id}-value`, value: String(bars.value ?? (0, import_chart4.defaultChartErrorBarValue)(bars.type)), inputMode: "decimal", "data-option": `${key}.value`, className: chartInputClass, onCommit: (text) => !!patch({ value: text.trim() === "" ? void 0 : Number(text) })?.ok }) }),
9350
- bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
9351
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Plus", htmlFor: `${id}-plus`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${id}-plus`, value: (0, import_chart4.formatChartAmountList)(bars.plus), placeholder: "1, 2, -, 0.5", "data-option": `${key}.plus`, className: chartInputClass, onCommit: (text) => !!patch({ plus: (0, import_chart4.parseChartAmountList)(text) })?.ok }) }),
9352
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9494
+ bars && (bars.type === "fixed" || bars.type === "percent" || bars.type === "stddev") && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: bars.type === "percent" ? "Percent" : bars.type === "stddev" ? "Deviations" : "Amount", htmlFor: `${id}-value`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChartCommitInput, { id: `${id}-value`, value: String(bars.value ?? (0, import_chart4.defaultChartErrorBarValue)(bars.type)), inputMode: "decimal", "data-option": `${key}.value`, className: chartInputClass, onCommit: (text) => !!patch({ value: text.trim() === "" ? void 0 : Number(text) })?.ok }) }),
9495
+ bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
9496
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Plus", htmlFor: `${id}-plus`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChartCommitInput, { id: `${id}-plus`, value: (0, import_chart4.formatChartAmountList)(bars.plus), placeholder: "1, 2, -, 0.5", "data-option": `${key}.plus`, className: chartInputClass, onCommit: (text) => !!patch({ plus: (0, import_chart4.parseChartAmountList)(text) })?.ok }) }),
9497
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
9353
9498
  ChartCommitInput,
9354
9499
  {
9355
9500
  id: `${id}-minus`,
@@ -9366,15 +9511,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
9366
9511
  }
9367
9512
  ) })
9368
9513
  ] }),
9369
- bars && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
9370
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("select", { className: `${chartInputClass} flex-1`, "aria-label": "Error bar direction", value: bars.direction ?? "both", "data-option": `${key}.direction`, onChange: (e) => patch({ direction: e.currentTarget.value }), children: import_chart4.CHART_ERROR_BAR_DIRECTIONS.map((d) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: d, children: d === "both" ? "Both ways" : d === "plus" ? "Plus only" : "Minus only" }, d)) }),
9371
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
9514
+ bars && /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center gap-2", children: [
9515
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("select", { className: `${chartInputClass} flex-1`, "aria-label": "Error bar direction", value: bars.direction ?? "both", "data-option": `${key}.direction`, onChange: (e) => patch({ direction: e.currentTarget.value }), children: import_chart4.CHART_ERROR_BAR_DIRECTIONS.map((d) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: d, children: d === "both" ? "Both ways" : d === "plus" ? "Plus only" : "Minus only" }, d)) }),
9516
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
9372
9517
  ] })
9373
9518
  ] });
9374
9519
  }
9375
9520
  function ChartInspector({ controller, sections, className }) {
9376
9521
  const { spec, selectedSeries } = useChartState(controller);
9377
- const idBase = (0, import_react67.useId)();
9522
+ const idBase = (0, import_react68.useId)();
9378
9523
  const show = (section) => !sections || sections.includes(section);
9379
9524
  const cartesian = (0, import_chart4.isCartesianChart)(spec.type);
9380
9525
  const family = (0, import_chart4.chartFamily)(spec);
@@ -9386,29 +9531,29 @@ function ChartInspector({ controller, sections, className }) {
9386
9531
  const hasLines = cartesian && types.some((t) => t === "line" || t === "area");
9387
9532
  const seriesIndex = selectedSeries ? spec.series.findIndex((s) => s.id === selectedSeries.id) : -1;
9388
9533
  const scales = family === "cartesian" || family === "xy";
9389
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
9390
- show("type") && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: chartSectionClass, "data-section": "type", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "grid grid-cols-3 gap-0.5 rounded-md bg-muted p-0.5", role: "radiogroup", "aria-label": "Chart type", children: import_chart4.CHART_TYPES.map((type) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", role: "radio", "aria-checked": spec.type === type, "data-chart-type": type, className: chartSegmentClass(spec.type === type), onClick: () => controller.setType(type), children: import_chart4.CHART_TYPE_LABELS[type] }, type)) }) }),
9391
- show("style") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
9392
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Layout", htmlFor: `${idBase}-layout`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("select", { id: `${idBase}-layout`, className: chartInputClass, value: "", "data-option": "preset.layout", onChange: (e) => e.currentTarget.value && controller.applyPreset({ layout: e.currentTarget.value }), children: [
9393
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Quick layout\u2026" }),
9394
- import_chart4.CHART_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: p.id, title: p.description, children: p.label }, p.id))
9534
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
9535
+ show("type") && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: chartSectionClass, "data-section": "type", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "grid grid-cols-3 gap-0.5 rounded-md bg-muted p-0.5", role: "radiogroup", "aria-label": "Chart type", children: import_chart4.CHART_TYPES.map((type) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", role: "radio", "aria-checked": spec.type === type, "data-chart-type": type, className: chartSegmentClass(spec.type === type), onClick: () => controller.setType(type), children: import_chart4.CHART_TYPE_LABELS[type] }, type)) }) }),
9536
+ show("style") && /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
9537
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Layout", htmlFor: `${idBase}-layout`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("select", { id: `${idBase}-layout`, className: chartInputClass, value: "", "data-option": "preset.layout", onChange: (e) => e.currentTarget.value && controller.applyPreset({ layout: e.currentTarget.value }), children: [
9538
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: "", children: "Quick layout\u2026" }),
9539
+ import_chart4.CHART_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: p.id, title: p.description, children: p.label }, p.id))
9395
9540
  ] }) }),
9396
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Colours", htmlFor: `${idBase}-colors`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("select", { id: `${idBase}-colors`, className: chartInputClass, value: import_chart4.CHART_COLOR_SCHEMES.find((c) => c.palette.join() === spec.palette.join())?.id ?? "", "data-option": "preset.colors", onChange: (e) => e.currentTarget.value && controller.applyPreset({ colors: e.currentTarget.value }), children: [
9397
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Custom" }),
9398
- import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: c.id, title: c.description, children: c.label }, c.id))
9541
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Colours", htmlFor: `${idBase}-colors`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("select", { id: `${idBase}-colors`, className: chartInputClass, value: import_chart4.CHART_COLOR_SCHEMES.find((c) => c.palette.join() === spec.palette.join())?.id ?? "", "data-option": "preset.colors", onChange: (e) => e.currentTarget.value && controller.applyPreset({ colors: e.currentTarget.value }), children: [
9542
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: "", children: "Custom" }),
9543
+ import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: c.id, title: c.description, children: c.label }, c.id))
9399
9544
  ] }) }),
9400
- !colorCheck.ok && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-[11px] leading-snug text-amber-600 dark:text-amber-400", "data-chart-color-warning": "", children: colorCheck.issues[0] }),
9401
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
9545
+ !colorCheck.ok && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-[11px] leading-snug text-amber-600 dark:text-amber-400", "data-chart-color-warning": "", children: colorCheck.issues[0] }),
9546
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
9402
9547
  ] }),
9403
- show("titles") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
9404
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Title", htmlFor: `${idBase}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-title`, value: spec.title, "data-option": "title", className: chartInputClass, onCommit: (title) => void controller.setTitle(title) }) }),
9405
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Subtitle", htmlFor: `${idBase}-subtitle`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-subtitle`, value: spec.subtitle, "data-option": "subtitle", className: chartInputClass, onCommit: (subtitle) => void controller.setSubtitle(subtitle) }) })
9548
+ show("titles") && /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
9549
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Title", htmlFor: `${idBase}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChartCommitInput, { id: `${idBase}-title`, value: spec.title, "data-option": "title", className: chartInputClass, onCommit: (title) => void controller.setTitle(title) }) }),
9550
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Subtitle", htmlFor: `${idBase}-subtitle`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChartCommitInput, { id: `${idBase}-subtitle`, value: spec.subtitle, "data-option": "subtitle", className: chartInputClass, onCommit: (subtitle) => void controller.setSubtitle(subtitle) }) })
9406
9551
  ] }),
9407
- show("options") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
9408
- cartesian && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Stacking", htmlFor: `${idBase}-stacking`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Select, { id: `${idBase}-stacking`, name: "stacking", value: spec.stacking, options: import_chart4.CHART_STACKINGS, labels: { none: "None", stacked: "Stacked", percent: "100%" }, onChange: (stacking) => controller.update({ stacking }) }) }),
9409
- hasBars && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Bars", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: ["vertical", "horizontal"].map((o) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", "aria-pressed": spec.orientation === o, "data-option": `orientation.${o}`, className: chartSegmentClass(spec.orientation === o), onClick: () => controller.update({ orientation: o }), children: cap(o) }, o)) }) }),
9410
- hasLines && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Lines", htmlFor: `${idBase}-curve`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Select, { id: `${idBase}-curve`, name: "curve", value: spec.curve, options: import_chart4.CHART_CURVES, onChange: (curve) => controller.update({ curve }) }) }),
9411
- spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9552
+ show("options") && /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
9553
+ cartesian && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Stacking", htmlFor: `${idBase}-stacking`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Select, { id: `${idBase}-stacking`, name: "stacking", value: spec.stacking, options: import_chart4.CHART_STACKINGS, labels: { none: "None", stacked: "Stacked", percent: "100%" }, onChange: (stacking) => controller.update({ stacking }) }) }),
9554
+ hasBars && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Bars", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: ["vertical", "horizontal"].map((o) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", "aria-pressed": spec.orientation === o, "data-option": `orientation.${o}`, className: chartSegmentClass(spec.orientation === o), onClick: () => controller.update({ orientation: o }), children: cap(o) }, o)) }) }),
9555
+ hasLines && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Lines", htmlFor: `${idBase}-curve`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Select, { id: `${idBase}-curve`, name: "curve", value: spec.curve, options: import_chart4.CHART_CURVES, onChange: (curve) => controller.update({ curve }) }) }),
9556
+ spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
9412
9557
  "input",
9413
9558
  {
9414
9559
  id: `${idBase}-hole`,
@@ -9424,7 +9569,7 @@ function ChartInspector({ controller, sections, className }) {
9424
9569
  onChange: (e) => controller.update({ innerRadius: Number(e.currentTarget.value) })
9425
9570
  }
9426
9571
  ) }),
9427
- hasBars && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9572
+ hasBars && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
9428
9573
  "input",
9429
9574
  {
9430
9575
  id: `${idBase}-gap`,
@@ -9440,31 +9585,31 @@ function ChartInspector({ controller, sections, className }) {
9440
9585
  onChange: (e) => controller.update({ gapWidth: Number(e.currentTarget.value) })
9441
9586
  }
9442
9587
  ) }),
9443
- spec.dataLabels && hasBars && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Labels", htmlFor: `${idBase}-label-position`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Select, { id: `${idBase}-label-position`, name: "labelPosition", value: spec.labelPosition, options: import_chart4.CHART_LABEL_POSITIONS, onChange: (labelPosition) => controller.update({ labelPosition }) }) }),
9444
- spec.type === "histogram" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Bins", htmlFor: `${idBase}-bins`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-bins`, value: spec.bins === null ? "" : String(spec.bins), placeholder: "Auto", inputMode: "numeric", "data-option": "bins", className: chartInputClass, onCommit: (text) => controller.update({ bins: text.trim() === "" ? null : Number(text) }).ok }) }),
9445
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9446
- spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
9447
- hasLines && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
9448
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
9588
+ spec.dataLabels && hasBars && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Labels", htmlFor: `${idBase}-label-position`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Select, { id: `${idBase}-label-position`, name: "labelPosition", value: spec.labelPosition, options: import_chart4.CHART_LABEL_POSITIONS, onChange: (labelPosition) => controller.update({ labelPosition }) }) }),
9589
+ spec.type === "histogram" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Bins", htmlFor: `${idBase}-bins`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChartCommitInput, { id: `${idBase}-bins`, value: spec.bins === null ? "" : String(spec.bins), placeholder: "Auto", inputMode: "numeric", "data-option": "bins", className: chartInputClass, onCommit: (text) => controller.update({ bins: text.trim() === "" ? null : Number(text) }).ok }) }),
9590
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9591
+ spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
9592
+ hasLines && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
9593
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
9449
9594
  ] })
9450
9595
  ] }),
9451
- show("legend") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
9452
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center justify-between", children: [
9453
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
9454
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
9596
+ show("legend") && /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
9597
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center justify-between", children: [
9598
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
9599
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
9455
9600
  ] }),
9456
- spec.legend.show && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: import_chart4.CHART_LEGEND_POSITIONS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", "aria-pressed": spec.legend.position === p, "data-option": `legend.${p}`, className: chartSegmentClass(spec.legend.position === p), onClick: () => controller.setLegend({ position: p }), children: cap(p) }, p)) })
9601
+ spec.legend.show && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: import_chart4.CHART_LEGEND_POSITIONS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", "aria-pressed": spec.legend.position === p, "data-option": `legend.${p}`, className: chartSegmentClass(spec.legend.position === p), onClick: () => controller.setLegend({ position: p }), children: cap(p) }, p)) })
9457
9602
  ] }),
9458
- show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
9459
- family !== "box" && family !== "histogram" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(AxisSection, { controller, axis: "x", value: spec.xAxis, idBase, horizontal: spec.orientation === "horizontal", numeric: family === "xy", scales }),
9460
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
9461
- usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
9603
+ show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
9604
+ family !== "box" && family !== "histogram" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(AxisSection, { controller, axis: "x", value: spec.xAxis, idBase, horizontal: spec.orientation === "horizontal", numeric: family === "xy", scales }),
9605
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
9606
+ usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
9462
9607
  ] }),
9463
- show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
9464
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
9465
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Name", htmlFor: `${idBase}-series-name`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-series-name`, value: selectedSeries.name, "data-option": "series.name", className: chartInputClass, onCommit: (name) => void controller.updateSeries(selectedSeries.id, { name }) }) }),
9466
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Colour", htmlFor: `${idBase}-series-color`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-1", children: [
9467
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9608
+ show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
9609
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
9610
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Name", htmlFor: `${idBase}-series-name`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ChartCommitInput, { id: `${idBase}-series-name`, value: selectedSeries.name, "data-option": "series.name", className: chartInputClass, onCommit: (name) => void controller.updateSeries(selectedSeries.id, { name }) }) }),
9611
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Colour", htmlFor: `${idBase}-series-color`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center gap-1", children: [
9612
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
9468
9613
  "input",
9469
9614
  {
9470
9615
  id: `${idBase}-series-color`,
@@ -9477,9 +9622,9 @@ function ChartInspector({ controller, sections, className }) {
9477
9622
  onChange: (e) => controller.updateSeries(selectedSeries.id, { color: e.currentTarget.value })
9478
9623
  }
9479
9624
  ),
9480
- selectedSeries.color && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "reset-color", onClick: () => controller.updateSeries(selectedSeries.id, { color: null }), children: "Palette" })
9625
+ selectedSeries.color && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "reset-color", onClick: () => controller.updateSeries(selectedSeries.id, { color: null }), children: "Palette" })
9481
9626
  ] }) }),
9482
- cartesian && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9627
+ cartesian && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
9483
9628
  "select",
9484
9629
  {
9485
9630
  id: `${idBase}-series-type`,
@@ -9488,12 +9633,12 @@ function ChartInspector({ controller, sections, className }) {
9488
9633
  "data-option": "series.type",
9489
9634
  onChange: (e) => controller.updateSeries(selectedSeries.id, { type: e.currentTarget.value || null }),
9490
9635
  children: [
9491
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Chart type" }),
9492
- import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: t, children: import_chart4.CHART_TYPE_LABELS[t] }, t))
9636
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: "", children: "Chart type" }),
9637
+ import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: t, children: import_chart4.CHART_TYPE_LABELS[t] }, t))
9493
9638
  ]
9494
9639
  }
9495
9640
  ) }),
9496
- (cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Marker", htmlFor: `${idBase}-series-marker`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9641
+ (cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Field, { label: "Marker", htmlFor: `${idBase}-series-marker`, children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
9497
9642
  "select",
9498
9643
  {
9499
9644
  id: `${idBase}-series-marker`,
@@ -9502,20 +9647,20 @@ function ChartInspector({ controller, sections, className }) {
9502
9647
  "data-option": "series.marker",
9503
9648
  onChange: (e) => controller.updateSeries(selectedSeries.id, { marker: e.currentTarget.value || null }),
9504
9649
  children: [
9505
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Default" }),
9506
- import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: m, children: cap(m) }, m))
9650
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: "", children: "Default" }),
9651
+ import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: m, children: cap(m) }, m))
9507
9652
  ]
9508
9653
  }
9509
9654
  ) }),
9510
- scales && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
9511
- family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
9512
- (0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
9513
- (selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
9514
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
9515
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "R\xB2", name: `trendline.${i}.showR2`, checked: !!t.showR2, onChange: (showR2) => controller.updateTrendline(selectedSeries.id, i, { showR2 }) }),
9516
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, "aria-label": "Delete trendline", "data-action": "trendline-delete", onClick: () => controller.removeTrendline(selectedSeries.id, i), children: "\xD7" })
9655
+ scales && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
9656
+ family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
9657
+ (0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
9658
+ (selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
9659
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
9660
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "R\xB2", name: `trendline.${i}.showR2`, checked: !!t.showR2, onChange: (showR2) => controller.updateTrendline(selectedSeries.id, i, { showR2 }) }),
9661
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", className: chartButtonClass, "aria-label": "Delete trendline", "data-action": "trendline-delete", onClick: () => controller.removeTrendline(selectedSeries.id, i), children: "\xD7" })
9517
9662
  ] }, i)),
9518
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9663
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
9519
9664
  "select",
9520
9665
  {
9521
9666
  className: chartInputClass,
@@ -9524,32 +9669,32 @@ function ChartInspector({ controller, sections, className }) {
9524
9669
  "data-option": "trendline.add",
9525
9670
  onChange: (e) => e.currentTarget.value && controller.addTrendline(selectedSeries.id, { type: e.currentTarget.value }),
9526
9671
  children: [
9527
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Add trendline\u2026" }),
9528
- import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
9672
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: "", children: "Add trendline\u2026" }),
9673
+ import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
9529
9674
  ]
9530
9675
  }
9531
9676
  )
9532
9677
  ] }),
9533
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
9534
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
9535
- family === "cartesian" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Secondary axis", name: "series.axis", checked: selectedSeries.axis === "secondary", onChange: (secondary) => controller.updateSeries(selectedSeries.id, { axis: secondary ? "secondary" : null }) }),
9536
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "flex-1" }),
9537
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, disabled: seriesIndex <= 0, "aria-label": "Move series earlier", "data-action": "series-up", onClick: () => controller.moveSeries(selectedSeries.id, seriesIndex - 1), children: "\u2191" }),
9538
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, disabled: seriesIndex >= spec.series.length - 1, "aria-label": "Move series later", "data-action": "series-down", onClick: () => controller.moveSeries(selectedSeries.id, seriesIndex + 1), children: "\u2193" }),
9539
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: `${chartButtonClass} text-destructive`, "data-action": "series-delete", onClick: () => controller.removeSeries(selectedSeries.id), children: "Delete" })
9678
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
9679
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
9680
+ family === "cartesian" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(Toggle, { label: "Secondary axis", name: "series.axis", checked: selectedSeries.axis === "secondary", onChange: (secondary) => controller.updateSeries(selectedSeries.id, { axis: secondary ? "secondary" : null }) }),
9681
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "flex-1" }),
9682
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", className: chartButtonClass, disabled: seriesIndex <= 0, "aria-label": "Move series earlier", "data-action": "series-up", onClick: () => controller.moveSeries(selectedSeries.id, seriesIndex - 1), children: "\u2191" }),
9683
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", className: chartButtonClass, disabled: seriesIndex >= spec.series.length - 1, "aria-label": "Move series later", "data-action": "series-down", onClick: () => controller.moveSeries(selectedSeries.id, seriesIndex + 1), children: "\u2193" }),
9684
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", className: `${chartButtonClass} text-destructive`, "data-action": "series-delete", onClick: () => controller.removeSeries(selectedSeries.id), children: "Delete" })
9540
9685
  ] })
9541
9686
  ] })
9542
9687
  ] });
9543
9688
  }
9544
9689
 
9545
9690
  // src/chart-node/ChartNodeView.tsx
9546
- var import_jsx_runtime48 = require("react/jsx-runtime");
9691
+ var import_jsx_runtime50 = require("react/jsx-runtime");
9547
9692
  function ChartNodeView({ state, theme, showDataGrid = true }) {
9548
9693
  const { controller, editing, editable, selected, width, height, setEditing } = state;
9549
9694
  const open = () => {
9550
9695
  if (editable && !editing) setEditing(true);
9551
9696
  };
9552
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
9697
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
9553
9698
  "div",
9554
9699
  {
9555
9700
  className: `not-prose my-2 rounded-md border bg-background p-1 ${selected ? "border-primary ring-1 ring-primary" : "border-border"}`,
@@ -9562,24 +9707,24 @@ function ChartNodeView({ state, theme, showDataGrid = true }) {
9562
9707
  }
9563
9708
  },
9564
9709
  children: [
9565
- editing && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "mb-1 flex items-center justify-between gap-2 px-1", "data-chart-node-toolbar": "", children: [
9566
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
9567
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
9710
+ editing && /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "mb-1 flex items-center justify-between gap-2 px-1", "data-chart-node-toolbar": "", children: [
9711
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
9712
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
9568
9713
  ] }),
9569
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
9714
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
9570
9715
  "div",
9571
9716
  {
9572
9717
  className: editable && !editing ? "cursor-pointer" : void 0,
9573
9718
  onClick: open,
9574
9719
  title: editable && !editing ? "Click to edit the chart" : void 0,
9575
9720
  "data-chart-node-canvas": "",
9576
- children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
9721
+ children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
9577
9722
  }
9578
9723
  ),
9579
9724
  editing && // Wraps by the document's width, not the viewport's: side by side when there is room.
9580
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
9581
- showDataGrid && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "min-w-0 flex-[1_1_20rem] overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ChartDataGrid, { controller }) }),
9582
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ChartInspector, { controller, className: "max-h-96 min-w-0 flex-[1_1_16rem] overflow-y-auto rounded-md border border-border p-3" })
9725
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
9726
+ showDataGrid && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "min-w-0 flex-[1_1_20rem] overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ChartDataGrid, { controller }) }),
9727
+ /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(ChartInspector, { controller, className: "max-h-96 min-w-0 flex-[1_1_16rem] overflow-y-auto rounded-md border border-border p-3" })
9583
9728
  ] })
9584
9729
  ]
9585
9730
  }
@@ -9597,7 +9742,7 @@ function createReactChartNodeView(options = {}) {
9597
9742
  scheduled = true;
9598
9743
  queueMicrotask(() => {
9599
9744
  scheduled = false;
9600
- if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Component, { ...props, state: latest }));
9745
+ if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(Component, { ...props, state: latest }));
9601
9746
  });
9602
9747
  };
9603
9748
  schedule();
@@ -9645,6 +9790,7 @@ function createReactChartNodeView(options = {}) {
9645
9790
  MergePreview,
9646
9791
  NameManager,
9647
9792
  OutlinePanel,
9793
+ PaintGradientEditor,
9648
9794
  RecoveryPrompt,
9649
9795
  RefineEdgePanel,
9650
9796
  ReviewToolbar,