@pixerate/editor-react 0.71.0 → 0.73.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
@@ -35,6 +35,7 @@ __export(src_exports, {
35
35
  BrushOptionsBar: () => BrushOptionsBar,
36
36
  BubbleMenu: () => BubbleMenu,
37
37
  ChartNodeView: () => ChartNodeView,
38
+ ColorProfilePanel: () => ColorProfilePanel,
38
39
  CommandPalette: () => CommandPalette,
39
40
  CommentButton: () => CommentButton,
40
41
  CommentsPanel: () => CommentsPanel,
@@ -3787,8 +3788,8 @@ function useImageEditor(options = {}) {
3787
3788
  }
3788
3789
 
3789
3790
  // src/image-editor/ImageEditor.tsx
3790
- var import_react46 = __toESM(require("react"), 1);
3791
- var import_image_editor14 = require("@pixerate/editor/image-editor");
3791
+ var import_react47 = __toESM(require("react"), 1);
3792
+ var import_image_editor15 = require("@pixerate/editor/image-editor");
3792
3793
 
3793
3794
  // src/image-editor/ControlSlider.tsx
3794
3795
  var import_image_editor2 = require("@pixerate/editor/image-editor");
@@ -4523,6 +4524,17 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4523
4524
  children: "\u22EF"
4524
4525
  }
4525
4526
  ),
4527
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4528
+ "select",
4529
+ {
4530
+ "aria-label": "Bits per channel",
4531
+ title: "Image \u203A Mode: bits per channel",
4532
+ className: "rounded bg-slate-800 px-1 py-0.5 text-[11px] text-slate-200",
4533
+ value: controller.bitDepth,
4534
+ onChange: (e) => attempt(() => controller.setBitDepth(Number(e.target.value))),
4535
+ children: import_image_editor7.BIT_DEPTH_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("option", { value: o.depth, title: o.title, children: o.label }, o.depth))
4536
+ }
4537
+ ),
4526
4538
  psd && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
4527
4539
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, onClick: () => fileInput.current?.click(), children: "Open PSD\u2026" }),
4528
4540
  /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, onClick: () => psdTask(async () => (await (0, import_image_editor7.downloadPsd)(controller, psdFileName)).warnings), children: "Export PSD" }),
@@ -4836,7 +4848,8 @@ var BrushOptionsBar = ({ controller, className }) => {
4836
4848
  (0, import_react40.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
4837
4849
  const [error, setError] = (0, import_react40.useState)(null);
4838
4850
  const state = controller.getState();
4839
- const { brush, foreground, background, mixer, mixerLoad } = state.paint;
4851
+ const { brush, foreground, background, mixer, mixerLoad, retouch, cloneSource } = state.paint;
4852
+ const tool = state.activeTool;
4840
4853
  const attempt = (fn) => {
4841
4854
  try {
4842
4855
  setError(null);
@@ -4846,12 +4859,12 @@ var BrushOptionsBar = ({ controller, className }) => {
4846
4859
  }
4847
4860
  };
4848
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: [
4849
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor8.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
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)(
4850
4863
  "button",
4851
4864
  {
4852
4865
  type: "button",
4853
4866
  "aria-pressed": state.activeTool === t.id,
4854
- title: `${t.label} (${t.shortcut})`,
4867
+ title: t.shortcut ? `${t.label} (${t.shortcut})` : t.label,
4855
4868
  className: chip(state.activeTool === t.id),
4856
4869
  onClick: () => controller.setTool(t.id),
4857
4870
  children: t.label
@@ -4953,6 +4966,41 @@ var BrushOptionsBar = ({ controller, className }) => {
4953
4966
  ] })
4954
4967
  ] })
4955
4968
  ] }),
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" })
4973
+ ] }),
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)(
4977
+ "button",
4978
+ {
4979
+ type: "button",
4980
+ "aria-pressed": retouch[choice.id] === o.id,
4981
+ title: o.title,
4982
+ className: chip(retouch[choice.id] === o.id),
4983
+ onClick: () => (0, import_image_editor8.setRetouchChoice)(controller, choice.id, o.id),
4984
+ children: o.label
4985
+ },
4986
+ o.id
4987
+ ))
4988
+ ] }, 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)(
4992
+ "input",
4993
+ {
4994
+ type: "checkbox",
4995
+ "aria-label": t.label,
4996
+ checked: retouch[t.id],
4997
+ onChange: (e) => controller.setPaintOptions({ retouch: { [t.id]: e.target.checked } }),
4998
+ className: "accent-indigo-500"
4999
+ }
5000
+ ),
5001
+ t.label
5002
+ ] }, t.id)) })
5003
+ ] }),
4956
5004
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
4957
5005
  /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4958
5006
  /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
@@ -4989,10 +5037,90 @@ var BrushOptionsBar = ({ controller, className }) => {
4989
5037
  ] });
4990
5038
  };
4991
5039
 
4992
- // src/image-editor/SelectionOptionsBar.tsx
5040
+ // src/image-editor/ColorProfilePanel.tsx
4993
5041
  var import_react41 = require("react");
4994
5042
  var import_image_editor9 = require("@pixerate/editor/image-editor");
4995
5043
  var import_jsx_runtime24 = require("react/jsx-runtime");
5044
+ 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";
5046
+ 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);
5054
+ const attempt = (fn) => {
5055
+ try {
5056
+ setError(null);
5057
+ fn();
5058
+ } catch (err) {
5059
+ setError(err instanceof Error ? err.message : String(err));
5060
+ }
5061
+ };
5062
+ const proofWith = (patch) => {
5063
+ const cur = view.proof;
5064
+ const id = patch.id ?? cur?.id ?? "coated-cmyk";
5065
+ attempt(
5066
+ () => controller.setProofSetup({
5067
+ profile: id,
5068
+ intent: patch.intent ?? cur?.intent ?? "relative",
5069
+ simulatePaper: patch.simulatePaper ?? cur?.simulatePaper ?? false,
5070
+ gamutWarning: patch.gamutWarning ?? cur?.gamutWarning ?? false
5071
+ })
5072
+ );
5073
+ };
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 })
5078
+ ] }),
5079
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Assign or convert", children: [
5080
+ /* @__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)) }),
5081
+ /* @__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)) }),
5082
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1", children: [
5083
+ /* @__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" }),
5084
+ "BPC"
5085
+ ] }),
5086
+ /* @__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" }),
5087
+ /* @__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" })
5088
+ ] }),
5089
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Proof setup", children: [
5090
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-slate-400", children: "Proof" }),
5091
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5092
+ "select",
5093
+ {
5094
+ "aria-label": "Proof profile",
5095
+ className: select,
5096
+ value: view.proof?.id ?? "",
5097
+ onChange: (e) => e.target.value ? proofWith({ id: e.target.value }) : attempt(() => controller.setProofSetup(null)),
5098
+ children: [
5099
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "", children: "Off" }),
5100
+ import_image_editor9.PROOF_PROFILE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: o.id, children: o.label }, o.id))
5101
+ ]
5102
+ }
5103
+ ),
5104
+ view.proof && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
5105
+ /* @__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)) }),
5106
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1", children: [
5107
+ /* @__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" }),
5108
+ "Paper"
5109
+ ] }),
5110
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1", children: [
5111
+ /* @__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" }),
5112
+ "Gamut warning"
5113
+ ] })
5114
+ ] })
5115
+ ] }),
5116
+ error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5117
+ ] });
5118
+ };
5119
+
5120
+ // src/image-editor/SelectionOptionsBar.tsx
5121
+ var import_react42 = require("react");
5122
+ var import_image_editor10 = require("@pixerate/editor/image-editor");
5123
+ var import_jsx_runtime25 = require("react/jsx-runtime");
4996
5124
  var MODIFY_OPS = [
4997
5125
  { op: "grow", label: "Grow" },
4998
5126
  { op: "shrink", label: "Shrink" },
@@ -5009,20 +5137,20 @@ var SelectionOptionsBar = ({
5009
5137
  quickMask,
5010
5138
  className = ""
5011
5139
  }) => {
5012
- const [radius, setRadius] = (0, import_react41.useState)(2);
5140
+ const [radius, setRadius] = (0, import_react42.useState)(2);
5013
5141
  const set = (patch) => onOptionsChange({ ...options, ...patch });
5014
5142
  const sel = selection === void 0 ? controller.getSelection() : selection;
5015
5143
  const qm = quickMask ?? Boolean(controller.getState().quickMask);
5016
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5017
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: import_image_editor9.SELECTION_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime24.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)) }),
5018
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: import_image_editor9.SELECTION_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: import_image_editor9.SELECTION_MODE_LABELS[m] }, m)) }),
5019
- options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col gap-2", children: [
5020
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
5021
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5022
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Tolerance" }),
5023
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "font-mono", children: options.tolerance })
5144
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5145
+ /* @__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)) }),
5146
+ /* @__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)) }),
5147
+ options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-2", children: [
5148
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5149
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5150
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Tolerance" }),
5151
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: options.tolerance })
5024
5152
  ] }),
5025
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5153
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5026
5154
  "input",
5027
5155
  {
5028
5156
  type: "range",
@@ -5036,17 +5164,17 @@ var SelectionOptionsBar = ({
5036
5164
  }
5037
5165
  )
5038
5166
  ] }),
5039
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5040
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
5167
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5168
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
5041
5169
  "Contiguous"
5042
5170
  ] }),
5043
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5044
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
5171
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5172
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
5045
5173
  "Sample adjusted image"
5046
5174
  ] }),
5047
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5175
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5048
5176
  "Sample",
5049
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5177
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5050
5178
  "select",
5051
5179
  {
5052
5180
  "aria-label": "Sample from",
@@ -5054,27 +5182,27 @@ var SelectionOptionsBar = ({
5054
5182
  onChange: (e) => set({ sample: e.target.value }),
5055
5183
  className: "bg-slate-800 border border-slate-700 rounded px-1 py-0.5",
5056
5184
  children: [
5057
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "composite", children: "All layers" }),
5058
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "active-layer", children: "Active layer" })
5185
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "composite", children: "All layers" }),
5186
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "active-layer", children: "Active layer" })
5059
5187
  ]
5060
5188
  }
5061
5189
  )
5062
5190
  ] })
5063
5191
  ] }),
5064
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5065
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
5192
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5193
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
5066
5194
  "Anti-alias"
5067
5195
  ] }),
5068
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5069
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
5070
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
5071
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
5072
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
5196
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5197
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
5198
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
5199
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
5200
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
5073
5201
  ] }),
5074
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
5075
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
5202
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
5203
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
5076
5204
  "Radius",
5077
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5205
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5078
5206
  "input",
5079
5207
  {
5080
5208
  type: "number",
@@ -5088,24 +5216,24 @@ var SelectionOptionsBar = ({
5088
5216
  }
5089
5217
  )
5090
5218
  ] }),
5091
- MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
5219
+ 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))
5092
5220
  ] }),
5093
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor9.describeSelection)(sel) })
5221
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor10.describeSelection)(sel) })
5094
5222
  ] });
5095
5223
  };
5096
5224
 
5097
5225
  // src/image-editor/RefineEdgePanel.tsx
5098
- var import_react42 = require("react");
5099
- var import_image_editor10 = require("@pixerate/editor/image-editor");
5100
- var import_jsx_runtime25 = require("react/jsx-runtime");
5226
+ var import_react43 = require("react");
5227
+ var import_image_editor11 = require("@pixerate/editor/image-editor");
5228
+ var import_jsx_runtime26 = require("react/jsx-runtime");
5101
5229
  var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
5102
5230
  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";
5103
5231
  var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5104
- const [params, setParams] = (0, import_react42.useState)(DEFAULT_PARAMS);
5105
- const [busy, setBusy] = (0, import_react42.useState)(false);
5106
- const [error, setError] = (0, import_react42.useState)(null);
5107
- const [layerId, setLayerId] = (0, import_react42.useState)("");
5108
- const [newKind, setNewKind] = (0, import_react42.useState)("hueSaturation");
5232
+ const [params, setParams] = (0, import_react43.useState)(DEFAULT_PARAMS);
5233
+ const [busy, setBusy] = (0, import_react43.useState)(false);
5234
+ const [error, setError] = (0, import_react43.useState)(null);
5235
+ const [layerId, setLayerId] = (0, import_react43.useState)("");
5236
+ const [newKind, setNewKind] = (0, import_react43.useState)("hueSaturation");
5109
5237
  const sel = selection === void 0 ? controller.getSelection() : selection;
5110
5238
  const list = layers ?? controller.getAdjustmentLayers();
5111
5239
  const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
@@ -5120,17 +5248,17 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5120
5248
  setBusy(false);
5121
5249
  }
5122
5250
  };
5123
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5124
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
5125
- import_image_editor10.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5126
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5127
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: c.label }),
5128
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
5251
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5252
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
5253
+ import_image_editor11.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex flex-col gap-1", children: [
5254
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5255
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: c.label }),
5256
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono", children: [
5129
5257
  params[c.id],
5130
5258
  c.unit
5131
5259
  ] })
5132
5260
  ] }),
5133
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5261
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5134
5262
  "input",
5135
5263
  {
5136
5264
  type: "range",
@@ -5144,67 +5272,67 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5144
5272
  }
5145
5273
  )
5146
5274
  ] }, c.id)),
5147
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5148
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
5275
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5276
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
5149
5277
  "Smart Radius"
5150
5278
  ] }),
5151
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-1", children: [
5152
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
5153
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
5279
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex gap-1", children: [
5280
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
5281
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
5154
5282
  ] }),
5155
- error && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
5156
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
5157
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-1 items-center", children: [
5158
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5283
+ error && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
5284
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
5285
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex gap-1 items-center", children: [
5286
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5159
5287
  "select",
5160
5288
  {
5161
5289
  "aria-label": "New masked layer kind",
5162
5290
  value: newKind,
5163
5291
  onChange: (e) => setNewKind(e.target.value),
5164
5292
  className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
5165
- children: import_image_editor10.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: k.kind, children: k.label }, k.kind))
5293
+ children: import_image_editor11.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: k.kind, children: k.label }, k.kind))
5166
5294
  }
5167
5295
  ),
5168
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5296
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5169
5297
  "button",
5170
5298
  {
5171
5299
  type: "button",
5172
5300
  className: button2,
5173
5301
  disabled: !sel,
5174
- onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor10.layerMaskFromSelection)(sel) })),
5302
+ onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor11.layerMaskFromSelection)(sel) })),
5175
5303
  children: "New Masked Layer"
5176
5304
  }
5177
5305
  )
5178
5306
  ] }),
5179
- list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-2", children: [
5180
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5307
+ list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-2", children: [
5308
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5181
5309
  "select",
5182
5310
  {
5183
5311
  "aria-label": "Mask layer",
5184
5312
  value: target.id,
5185
5313
  onChange: (e) => setLayerId(e.target.value),
5186
5314
  className: "bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
5187
- children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("option", { value: l.id, children: [
5188
- l.name || (0, import_image_editor10.adjustmentKindLabel)(l.kind),
5315
+ children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("option", { value: l.id, children: [
5316
+ l.name || (0, import_image_editor11.adjustmentKindLabel)(l.kind),
5189
5317
  l.mask ? " (masked)" : ""
5190
5318
  ] }, l.id))
5191
5319
  }
5192
5320
  ),
5193
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5194
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
5195
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
5196
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
5321
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5322
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
5323
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
5324
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
5197
5325
  ] }),
5198
- target.mask && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5199
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5200
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5201
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Density" }),
5202
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
5326
+ target.mask && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5327
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex flex-col gap-1", children: [
5328
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5329
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Density" }),
5330
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono", children: [
5203
5331
  Math.round((target.mask.density ?? 1) * 100),
5204
5332
  "%"
5205
5333
  ] })
5206
5334
  ] }),
5207
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5335
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5208
5336
  "input",
5209
5337
  {
5210
5338
  type: "range",
@@ -5218,15 +5346,15 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5218
5346
  }
5219
5347
  )
5220
5348
  ] }),
5221
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5222
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5223
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Mask Feather" }),
5224
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
5349
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex flex-col gap-1", children: [
5350
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5351
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Mask Feather" }),
5352
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono", children: [
5225
5353
  target.mask.feather ?? 0,
5226
5354
  "px"
5227
5355
  ] })
5228
5356
  ] }),
5229
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5357
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5230
5358
  "input",
5231
5359
  {
5232
5360
  type: "range",
@@ -5246,14 +5374,14 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5246
5374
  };
5247
5375
 
5248
5376
  // src/image-editor/FreeTransformOptionsBar.tsx
5249
- var import_react43 = require("react");
5250
- var import_image_editor11 = require("@pixerate/editor/image-editor");
5251
- var import_jsx_runtime26 = require("react/jsx-runtime");
5252
- var chip2 = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
5377
+ var import_react44 = require("react");
5378
+ var import_image_editor12 = require("@pixerate/editor/image-editor");
5379
+ var import_jsx_runtime27 = require("react/jsx-runtime");
5380
+ 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"}`;
5253
5381
  var round = (v, unit) => unit === "px" ? Math.round(v * 10) / 10 : Math.round(v * 100) / 100;
5254
5382
  var FreeTransformOptionsBar = ({ tool, className }) => {
5255
- const [, setTick] = (0, import_react43.useState)(0);
5256
- (0, import_react43.useEffect)(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
5383
+ const [, setTick] = (0, import_react44.useState)(0);
5384
+ (0, import_react44.useEffect)(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
5257
5385
  const bar = tool.bar();
5258
5386
  if (!tool.active || !bar) return null;
5259
5387
  const warp = tool.warpBar();
@@ -5265,17 +5393,17 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5265
5393
  const v = Number(raw);
5266
5394
  if (raw.trim() !== "" && Number.isFinite(v) && Math.abs(v - bar[field]) > 1e-9) tool.setField(field, v);
5267
5395
  };
5268
- return /* @__PURE__ */ (0, import_jsx_runtime26.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: [
5269
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Transform mode", children: import_image_editor11.FREE_TRANSFORM_MODE_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", title: m.title, "aria-pressed": tool.mode === m.id, className: chip2(tool.mode === m.id), onClick: () => tool.setMode(m.id), children: m.label }, m.id)) }),
5270
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "grid grid-cols-3 gap-px", role: "group", "aria-label": "Reference point", children: import_image_editor11.TRANSFORM_ANCHORS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime26.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)) }),
5271
- tool.mode === "warp" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": "Warp options", children: [
5272
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5273
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: "Warp" }),
5274
- /* @__PURE__ */ (0, import_jsx_runtime26.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_editor11.WARP_STYLE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: o.id, children: o.label }, o.id)) })
5396
+ 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: [
5397
+ /* @__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)) }),
5398
+ /* @__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)) }),
5399
+ 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: [
5400
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5401
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: "Warp" }),
5402
+ /* @__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)) })
5275
5403
  ] }),
5276
- ["bend", "horizontal", "vertical"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5277
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: k === "bend" ? "Bend" : k === "horizontal" ? "H" : "V" }),
5278
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5404
+ ["bend", "horizontal", "vertical"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5405
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: k === "bend" ? "Bend" : k === "horizontal" ? "H" : "V" }),
5406
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5279
5407
  "input",
5280
5408
  {
5281
5409
  type: "number",
@@ -5296,40 +5424,40 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5296
5424
  },
5297
5425
  `${k}:${warp[k]}`
5298
5426
  ),
5299
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-500", children: "%" })
5427
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-500", children: "%" })
5300
5428
  ] }, k)),
5301
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5429
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5302
5430
  "button",
5303
5431
  {
5304
5432
  type: "button",
5305
5433
  title: "Bend along the vertical axis",
5306
5434
  "aria-pressed": warp.orientation === "vertical",
5307
5435
  disabled: warp.style === "custom",
5308
- className: chip2(warp.orientation === "vertical"),
5436
+ className: chip3(warp.orientation === "vertical"),
5309
5437
  onClick: () => tool.setWarp({ orientation: warp.orientation === "vertical" ? "horizontal" : "vertical" }),
5310
5438
  children: "Vertical"
5311
5439
  }
5312
5440
  ),
5313
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5314
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: "Grid" }),
5315
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5441
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5442
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: "Grid" }),
5443
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5316
5444
  "select",
5317
5445
  {
5318
5446
  "aria-label": "Warp grid",
5319
- value: import_image_editor11.WARP_GRID_OPTIONS.find((g) => g.columns === warp.columns && g.rows === warp.rows)?.id ?? "1x1",
5447
+ value: import_image_editor12.WARP_GRID_OPTIONS.find((g) => g.columns === warp.columns && g.rows === warp.rows)?.id ?? "1x1",
5320
5448
  onChange: (e) => {
5321
- const g = import_image_editor11.WARP_GRID_OPTIONS.find((o) => o.id === e.target.value);
5449
+ const g = import_image_editor12.WARP_GRID_OPTIONS.find((o) => o.id === e.target.value);
5322
5450
  tool.setWarp({ columns: g.columns, rows: g.rows });
5323
5451
  },
5324
5452
  className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
5325
- children: import_image_editor11.WARP_GRID_OPTIONS.map((g) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: g.id, children: g.label }, g.id))
5453
+ children: import_image_editor12.WARP_GRID_OPTIONS.map((g) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: g.id, children: g.label }, g.id))
5326
5454
  }
5327
5455
  )
5328
5456
  ] })
5329
5457
  ] }),
5330
- tool.mode !== "warp" && import_image_editor11.FREE_TRANSFORM_FIELDS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", title: f.title, children: [
5331
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: f.label }),
5332
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5458
+ 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: [
5459
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: f.label }),
5460
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5333
5461
  "input",
5334
5462
  {
5335
5463
  type: "number",
@@ -5349,14 +5477,14 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5349
5477
  },
5350
5478
  `${f.id}:${round(bar[f.id], f.unit)}`
5351
5479
  ),
5352
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-500", children: f.unit }),
5353
- f.id === "scaleX" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5480
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-500", children: f.unit }),
5481
+ f.id === "scaleX" && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5354
5482
  "button",
5355
5483
  {
5356
5484
  type: "button",
5357
5485
  "aria-label": "Keep width and height proportional",
5358
5486
  "aria-pressed": tool.proportional,
5359
- className: chip2(tool.proportional),
5487
+ className: chip3(tool.proportional),
5360
5488
  onClick: () => {
5361
5489
  tool.proportional = !tool.proportional;
5362
5490
  setTick((n) => n + 1);
@@ -5365,34 +5493,34 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5365
5493
  }
5366
5494
  )
5367
5495
  ] }, f.id)),
5368
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5369
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: "Interpolation" }),
5370
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5496
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5497
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: "Interpolation" }),
5498
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5371
5499
  "select",
5372
5500
  {
5373
5501
  "aria-label": "Interpolation",
5374
5502
  value: tool.interpolation,
5375
5503
  onChange: (e) => tool.setInterpolation(e.target.value),
5376
5504
  className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
5377
- children: import_image_editor11.INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
5505
+ children: import_image_editor12.INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
5378
5506
  }
5379
5507
  )
5380
5508
  ] }),
5381
- /* @__PURE__ */ (0, import_jsx_runtime26.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" }),
5382
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", title: "Cancel (Esc)", className: chip2(false), onClick: () => tool.cancel(), children: "Cancel" }),
5383
- tool.error && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { role: "alert", className: "text-rose-400", children: tool.error })
5509
+ /* @__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" }),
5510
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", title: "Cancel (Esc)", className: chip3(false), onClick: () => tool.cancel(), children: "Cancel" }),
5511
+ tool.error && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { role: "alert", className: "text-rose-400", children: tool.error })
5384
5512
  ] });
5385
5513
  };
5386
5514
 
5387
5515
  // src/image-editor/ShapeOptionsBar.tsx
5388
- var import_react44 = require("react");
5389
- var import_image_editor12 = require("@pixerate/editor/image-editor");
5390
- var import_jsx_runtime27 = require("react/jsx-runtime");
5391
- 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"}`;
5516
+ var import_react45 = require("react");
5517
+ var import_image_editor13 = require("@pixerate/editor/image-editor");
5518
+ var import_jsx_runtime28 = require("react/jsx-runtime");
5519
+ 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"}`;
5392
5520
  var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5393
- const [, setTick] = (0, import_react44.useState)(0);
5394
- (0, import_react44.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5395
- const [error, setError] = (0, import_react44.useState)(null);
5521
+ const [, setTick] = (0, import_react45.useState)(0);
5522
+ (0, import_react45.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5523
+ const [error, setError] = (0, import_react45.useState)(null);
5396
5524
  const active = controller.getActiveLayer();
5397
5525
  const shapeId = active?.type === "shape" ? active.id : null;
5398
5526
  const set = (change) => {
@@ -5400,19 +5528,19 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5400
5528
  if (!shapeId) return;
5401
5529
  try {
5402
5530
  setError(null);
5403
- (0, import_image_editor12.applyShapeOptions)(controller, shapeId, change);
5531
+ (0, import_image_editor13.applyShapeOptions)(controller, shapeId, change);
5404
5532
  } catch (e) {
5405
5533
  setError(e instanceof Error ? e.message : String(e));
5406
5534
  }
5407
5535
  };
5408
5536
  const num = (v, min, max) => Math.max(min, Math.min(max, Number(v) || min));
5409
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "shape-options", children: [
5410
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Shape kind", children: import_image_editor12.LIVE_SHAPE_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", "aria-pressed": options.kind === k, className: chip3(options.kind === k), onClick: () => onChange({ ...options, kind: k }), children: import_image_editor12.SHAPE_KIND_LABELS[k] }, k)) }),
5411
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5412
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5413
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("input", { type: "checkbox", "aria-label": "Fill", checked: options.fill !== null, onChange: (e) => set({ fill: e.target.checked ? "#4f46e5" : null }) }),
5537
+ 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: [
5538
+ /* @__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)) }),
5539
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5540
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5541
+ /* @__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 }) }),
5414
5542
  "Fill",
5415
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5543
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5416
5544
  "input",
5417
5545
  {
5418
5546
  type: "color",
@@ -5424,10 +5552,10 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5424
5552
  }
5425
5553
  )
5426
5554
  ] }),
5427
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5428
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("input", { type: "checkbox", "aria-label": "Stroke", checked: options.stroke !== null, onChange: (e) => set({ stroke: e.target.checked ? "#000000" : null }) }),
5555
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5556
+ /* @__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 }) }),
5429
5557
  "Stroke",
5430
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5558
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5431
5559
  "input",
5432
5560
  {
5433
5561
  type: "color",
@@ -5439,9 +5567,9 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5439
5567
  }
5440
5568
  )
5441
5569
  ] }),
5442
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5570
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5443
5571
  "Width",
5444
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5572
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5445
5573
  "input",
5446
5574
  {
5447
5575
  type: "number",
@@ -5455,23 +5583,23 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5455
5583
  )
5456
5584
  ] })
5457
5585
  ] }),
5458
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5459
- options.kind === "rect" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5586
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5587
+ options.kind === "rect" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5460
5588
  "Radius",
5461
- /* @__PURE__ */ (0, import_jsx_runtime27.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" })
5589
+ /* @__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" })
5462
5590
  ] }),
5463
- options.kind === "polygon" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5591
+ options.kind === "polygon" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5464
5592
  "Sides",
5465
- /* @__PURE__ */ (0, import_jsx_runtime27.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" })
5593
+ /* @__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" })
5466
5594
  ] }),
5467
- options.kind === "star" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
5468
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5595
+ options.kind === "star" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
5596
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5469
5597
  "Points",
5470
- /* @__PURE__ */ (0, import_jsx_runtime27.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" })
5598
+ /* @__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" })
5471
5599
  ] }),
5472
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5600
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5473
5601
  "Inner",
5474
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5602
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5475
5603
  "input",
5476
5604
  {
5477
5605
  type: "range",
@@ -5486,33 +5614,33 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5486
5614
  )
5487
5615
  ] })
5488
5616
  ] }),
5489
- options.kind === "line" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
5490
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5617
+ options.kind === "line" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
5618
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5491
5619
  "Weight",
5492
- /* @__PURE__ */ (0, import_jsx_runtime27.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" })
5620
+ /* @__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" })
5493
5621
  ] }),
5494
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5495
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("input", { type: "checkbox", "aria-label": "Arrowhead", checked: options.arrow, onChange: (e) => set({ arrow: e.target.checked }) }),
5622
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5623
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "checkbox", "aria-label": "Arrowhead", checked: options.arrow, onChange: (e) => set({ arrow: e.target.checked }) }),
5496
5624
  "Arrowhead"
5497
5625
  ] })
5498
5626
  ] })
5499
5627
  ] }),
5500
- /* @__PURE__ */ (0, import_jsx_runtime27.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." }),
5501
- error && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5628
+ /* @__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." }),
5629
+ error && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5502
5630
  ] });
5503
5631
  };
5504
5632
 
5505
5633
  // src/image-editor/TypeOptionsBar.tsx
5506
- var import_react45 = require("react");
5507
- var import_image_editor13 = require("@pixerate/editor/image-editor");
5508
- var import_jsx_runtime28 = require("react/jsx-runtime");
5509
- 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"}`;
5634
+ var import_react46 = require("react");
5635
+ var import_image_editor14 = require("@pixerate/editor/image-editor");
5636
+ var import_jsx_runtime29 = require("react/jsx-runtime");
5637
+ 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"}`;
5510
5638
  var ALIGN_LABELS = { left: "Left", center: "Centre", right: "Right", justify: "Justify" };
5511
5639
  var TypeOptionsBar = ({ controller, options, onChange, session, className }) => {
5512
- const [, setTick] = (0, import_react45.useState)(0);
5513
- (0, import_react45.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5514
- (0, import_react45.useEffect)(() => session?.subscribe(() => setTick((n) => n + 1)), [session]);
5515
- const [error, setError] = (0, import_react45.useState)(null);
5640
+ const [, setTick] = (0, import_react46.useState)(0);
5641
+ (0, import_react46.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5642
+ (0, import_react46.useEffect)(() => session?.subscribe(() => setTick((n) => n + 1)), [session]);
5643
+ const [error, setError] = (0, import_react46.useState)(null);
5516
5644
  const active = controller.getActiveLayer();
5517
5645
  const typeId = !session && active?.type === "type" ? active.id : null;
5518
5646
  const here = session?.alive ? session.styleHere() : {};
@@ -5544,11 +5672,11 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
5544
5672
  setError(e instanceof Error ? e.message : String(e));
5545
5673
  }
5546
5674
  };
5547
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "type-options", children: [
5548
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
5549
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5675
+ 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: [
5676
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
5677
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-1", children: [
5550
5678
  "Font",
5551
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5679
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5552
5680
  "input",
5553
5681
  {
5554
5682
  list: "pixerate-type-fonts",
@@ -5558,11 +5686,11 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
5558
5686
  className: "w-32 rounded border border-slate-700 bg-slate-950 px-1 py-0.5"
5559
5687
  }
5560
5688
  ),
5561
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("datalist", { id: "pixerate-type-fonts", children: fonts.map((f) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("option", { value: f }, f)) })
5689
+ /* @__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)) })
5562
5690
  ] }),
5563
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5691
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-1", children: [
5564
5692
  "Size",
5565
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5693
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5566
5694
  "input",
5567
5695
  {
5568
5696
  type: "number",
@@ -5575,24 +5703,24 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
5575
5703
  }
5576
5704
  )
5577
5705
  ] }),
5578
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", "aria-pressed": shown.fontWeight >= 600, className: `${chip4(shown.fontWeight >= 600)} font-bold`, onClick: () => style({ fontWeight: shown.fontWeight >= 600 ? 400 : 700 }), children: "B" }),
5579
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", "aria-pressed": shown.italic, className: `${chip4(shown.italic)} italic`, onClick: () => style({ italic: !shown.italic }), children: "I" }),
5580
- /* @__PURE__ */ (0, import_jsx_runtime28.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" })
5706
+ /* @__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" }),
5707
+ /* @__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" }),
5708
+ /* @__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" })
5581
5709
  ] }),
5582
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Alignment", children: import_image_editor13.TEXT_ALIGNS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", "aria-pressed": options.align === a, className: chip4(options.align === a), onClick: () => style({ align: a }), children: ALIGN_LABELS[a] }, a)) }),
5583
- /* @__PURE__ */ (0, import_jsx_runtime28.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." }),
5584
- missing.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("p", { role: "status", className: "text-amber-400", "data-testid": "type-missing-fonts", children: [
5710
+ /* @__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)) }),
5711
+ /* @__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." }),
5712
+ missing.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("p", { role: "status", className: "text-amber-400", "data-testid": "type-missing-fonts", children: [
5585
5713
  "Missing ",
5586
5714
  missing.length === 1 ? "font" : "fonts",
5587
5715
  ": ",
5588
5716
  missing.join(", ")
5589
5717
  ] }),
5590
- error && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5718
+ error && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5591
5719
  ] });
5592
5720
  };
5593
5721
 
5594
5722
  // src/image-editor/ImageEditor.tsx
5595
- var import_jsx_runtime29 = require("react/jsx-runtime");
5723
+ var import_jsx_runtime30 = require("react/jsx-runtime");
5596
5724
  var ImageEditor = ({
5597
5725
  editor: externalEditor,
5598
5726
  src,
@@ -5607,65 +5735,65 @@ var ImageEditor = ({
5607
5735
  const internalEditor = useImageEditor({ image: src });
5608
5736
  const editor = externalEditor || internalEditor;
5609
5737
  const { state, controller } = editor;
5610
- const legacyProcess = (0, import_image_editor14.normalizeProcessVersion)(state.adjustments.process) < import_image_editor14.LATEST_PROCESS_VERSION;
5611
- const canvasRef = (0, import_react46.useRef)(null);
5612
- const containerRef = (0, import_react46.useRef)(null);
5613
- const [activeTab, setActiveTab] = (0, import_react46.useState)("crop");
5614
- const [activeCropRatio, setActiveCropRatio] = (0, import_react46.useState)(null);
5615
- const [selectionOptions, setSelectionOptions] = (0, import_react46.useState)(import_image_editor14.DEFAULT_SELECTION_TOOL_OPTIONS);
5616
- const selectionOptionsRef = (0, import_react46.useRef)(selectionOptions);
5738
+ const legacyProcess = (0, import_image_editor15.normalizeProcessVersion)(state.adjustments.process) < import_image_editor15.LATEST_PROCESS_VERSION;
5739
+ const canvasRef = (0, import_react47.useRef)(null);
5740
+ const containerRef = (0, import_react47.useRef)(null);
5741
+ const [activeTab, setActiveTab] = (0, import_react47.useState)("crop");
5742
+ const [activeCropRatio, setActiveCropRatio] = (0, import_react47.useState)(null);
5743
+ const [selectionOptions, setSelectionOptions] = (0, import_react47.useState)(import_image_editor15.DEFAULT_SELECTION_TOOL_OPTIONS);
5744
+ const selectionOptionsRef = (0, import_react47.useRef)(selectionOptions);
5617
5745
  selectionOptionsRef.current = selectionOptions;
5618
- const selectionGestureRef = (0, import_react46.useRef)(null);
5746
+ const selectionGestureRef = (0, import_react47.useRef)(null);
5619
5747
  if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
5620
- selectionGestureRef.current = new import_image_editor14.SelectionGesture(controller, () => selectionOptionsRef.current);
5748
+ selectionGestureRef.current = new import_image_editor15.SelectionGesture(controller, () => selectionOptionsRef.current);
5621
5749
  }
5622
- const selectionDraftRef = (0, import_react46.useRef)(null);
5623
- const [selectionError, setSelectionError] = (0, import_react46.useState)(null);
5624
- const paintGestureRef = (0, import_react46.useRef)(null);
5625
- const paintControllerRef = (0, import_react46.useRef)(controller);
5750
+ const selectionDraftRef = (0, import_react47.useRef)(null);
5751
+ const [selectionError, setSelectionError] = (0, import_react47.useState)(null);
5752
+ const paintGestureRef = (0, import_react47.useRef)(null);
5753
+ const paintControllerRef = (0, import_react47.useRef)(controller);
5626
5754
  if (!paintGestureRef.current || paintControllerRef.current !== controller) {
5627
- paintGestureRef.current = new import_image_editor14.PaintGesture(controller);
5755
+ paintGestureRef.current = new import_image_editor15.PaintGesture(controller);
5628
5756
  paintControllerRef.current = controller;
5629
5757
  }
5630
- const brushCursorRef = (0, import_react46.useRef)(null);
5631
- const [paintError, setPaintError] = (0, import_react46.useState)(null);
5632
- const transformToolRef = (0, import_react46.useRef)(null);
5633
- const transformControllerRef = (0, import_react46.useRef)(controller);
5758
+ const brushCursorRef = (0, import_react47.useRef)(null);
5759
+ const [paintError, setPaintError] = (0, import_react47.useState)(null);
5760
+ const transformToolRef = (0, import_react47.useRef)(null);
5761
+ const transformControllerRef = (0, import_react47.useRef)(controller);
5634
5762
  if (!transformToolRef.current || transformControllerRef.current !== controller) {
5635
5763
  transformToolRef.current?.cancel();
5636
- transformToolRef.current = new import_image_editor14.FreeTransformTool(controller, {
5764
+ transformToolRef.current = new import_image_editor15.FreeTransformTool(controller, {
5637
5765
  schedule: (run) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(run) : run()
5638
5766
  });
5639
5767
  transformControllerRef.current = controller;
5640
5768
  }
5641
5769
  const transformTool = transformToolRef.current;
5642
- const [, setTransformTick] = (0, import_react46.useState)(0);
5643
- const [transformCursor, setTransformCursor] = (0, import_react46.useState)("default");
5644
- const [shapeOptions, setShapeOptions] = (0, import_react46.useState)(import_image_editor14.DEFAULT_SHAPE_TOOL_OPTIONS);
5645
- const shapeOptionsRef = (0, import_react46.useRef)(shapeOptions);
5770
+ const [, setTransformTick] = (0, import_react47.useState)(0);
5771
+ const [transformCursor, setTransformCursor] = (0, import_react47.useState)("default");
5772
+ const [shapeOptions, setShapeOptions] = (0, import_react47.useState)(import_image_editor15.DEFAULT_SHAPE_TOOL_OPTIONS);
5773
+ const shapeOptionsRef = (0, import_react47.useRef)(shapeOptions);
5646
5774
  shapeOptionsRef.current = shapeOptions;
5647
- const [typeOptions, setTypeOptions] = (0, import_react46.useState)(import_image_editor14.DEFAULT_TYPE_TOOL_OPTIONS);
5648
- const typeOptionsRef = (0, import_react46.useRef)(typeOptions);
5775
+ const [typeOptions, setTypeOptions] = (0, import_react47.useState)(import_image_editor15.DEFAULT_TYPE_TOOL_OPTIONS);
5776
+ const typeOptionsRef = (0, import_react47.useRef)(typeOptions);
5649
5777
  typeOptionsRef.current = typeOptions;
5650
- const shapeGestureRef = (0, import_react46.useRef)(null);
5651
- const typeToolRef = (0, import_react46.useRef)(null);
5652
- const shapeTypeControllerRef = (0, import_react46.useRef)(controller);
5778
+ const shapeGestureRef = (0, import_react47.useRef)(null);
5779
+ const typeToolRef = (0, import_react47.useRef)(null);
5780
+ const shapeTypeControllerRef = (0, import_react47.useRef)(controller);
5653
5781
  if (!shapeGestureRef.current || !typeToolRef.current || shapeTypeControllerRef.current !== controller) {
5654
5782
  typeToolRef.current?.finish();
5655
- shapeGestureRef.current = new import_image_editor14.ShapeDrawGesture(controller, () => shapeOptionsRef.current);
5656
- typeToolRef.current = new import_image_editor14.TypeToolGesture(controller, () => typeOptionsRef.current);
5783
+ shapeGestureRef.current = new import_image_editor15.ShapeDrawGesture(controller, () => shapeOptionsRef.current);
5784
+ typeToolRef.current = new import_image_editor15.TypeToolGesture(controller, () => typeOptionsRef.current);
5657
5785
  shapeTypeControllerRef.current = controller;
5658
5786
  }
5659
- const typeInputRef = (0, import_react46.useRef)(null);
5660
- const [typeSession, setTypeSession] = (0, import_react46.useState)(typeToolRef.current.session);
5661
- const [shapeTypeError, setShapeTypeError] = (0, import_react46.useState)(null);
5662
- const [inpaintPrompt, setInpaintPrompt] = (0, import_react46.useState)("");
5663
- const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react46.useState)("annotations");
5664
- const [isRemovingBg, setIsRemovingBg] = (0, import_react46.useState)(false);
5665
- const [isInpainting, setIsInpainting] = (0, import_react46.useState)(false);
5666
- const [aiError, setAiError] = (0, import_react46.useState)(null);
5667
- const [aiSuccess, setAiSuccess] = (0, import_react46.useState)(null);
5668
- const [aiTarget, setAiTarget] = (0, import_react46.useState)("auto");
5787
+ const typeInputRef = (0, import_react47.useRef)(null);
5788
+ const [typeSession, setTypeSession] = (0, import_react47.useState)(typeToolRef.current.session);
5789
+ const [shapeTypeError, setShapeTypeError] = (0, import_react47.useState)(null);
5790
+ const [inpaintPrompt, setInpaintPrompt] = (0, import_react47.useState)("");
5791
+ const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react47.useState)("annotations");
5792
+ const [isRemovingBg, setIsRemovingBg] = (0, import_react47.useState)(false);
5793
+ const [isInpainting, setIsInpainting] = (0, import_react47.useState)(false);
5794
+ const [aiError, setAiError] = (0, import_react47.useState)(null);
5795
+ const [aiSuccess, setAiSuccess] = (0, import_react47.useState)(null);
5796
+ const [aiTarget, setAiTarget] = (0, import_react47.useState)("auto");
5669
5797
  const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
5670
5798
  const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
5671
5799
  const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
@@ -5728,18 +5856,18 @@ var ImageEditor = ({
5728
5856
  setIsInpainting(false);
5729
5857
  }
5730
5858
  };
5731
- const [activeColor, setActiveColor] = (0, import_react46.useState)("#ef4444");
5732
- const [strokeWidth, setStrokeWidth] = (0, import_react46.useState)(3);
5733
- const [fontSize, setFontSize] = (0, import_react46.useState)(24);
5734
- const [textInput, setTextInput] = (0, import_react46.useState)("");
5735
- const draftAnnotationRef = (0, import_react46.useRef)(null);
5736
- const draftCropRef = (0, import_react46.useRef)(null);
5737
- const cropDragInfoRef = (0, import_react46.useRef)(null);
5738
- const annotationDragInfoRef = (0, import_react46.useRef)(null);
5739
- const isDrawingRef = (0, import_react46.useRef)(false);
5740
- const currentPathRef = (0, import_react46.useRef)([]);
5741
- const dragStartPointRef = (0, import_react46.useRef)(null);
5742
- const renderCanvas = (0, import_react46.useCallback)(
5859
+ const [activeColor, setActiveColor] = (0, import_react47.useState)("#ef4444");
5860
+ const [strokeWidth, setStrokeWidth] = (0, import_react47.useState)(3);
5861
+ const [fontSize, setFontSize] = (0, import_react47.useState)(24);
5862
+ const [textInput, setTextInput] = (0, import_react47.useState)("");
5863
+ const draftAnnotationRef = (0, import_react47.useRef)(null);
5864
+ const draftCropRef = (0, import_react47.useRef)(null);
5865
+ const cropDragInfoRef = (0, import_react47.useRef)(null);
5866
+ const annotationDragInfoRef = (0, import_react47.useRef)(null);
5867
+ const isDrawingRef = (0, import_react47.useRef)(false);
5868
+ const currentPathRef = (0, import_react47.useRef)([]);
5869
+ const dragStartPointRef = (0, import_react47.useRef)(null);
5870
+ const renderCanvas = (0, import_react47.useCallback)(
5743
5871
  async (draftAnnotation, draftCrop) => {
5744
5872
  const canvas = canvasRef.current;
5745
5873
  const container = containerRef.current;
@@ -5762,8 +5890,8 @@ var ImageEditor = ({
5762
5890
  },
5763
5891
  [controller, activeTab, transformTool]
5764
5892
  );
5765
- (0, import_react46.useEffect)(() => typeSession?.subscribe(() => void renderCanvas()), [typeSession, renderCanvas]);
5766
- (0, import_react46.useEffect)(() => {
5893
+ (0, import_react47.useEffect)(() => typeSession?.subscribe(() => void renderCanvas()), [typeSession, renderCanvas]);
5894
+ (0, import_react47.useEffect)(() => {
5767
5895
  if (activeTab === "annotate" && state.activeTool === "type") return;
5768
5896
  if (typeToolRef.current?.session) {
5769
5897
  typeToolRef.current.finish();
@@ -5798,7 +5926,7 @@ var ImageEditor = ({
5798
5926
  el.value = "";
5799
5927
  }
5800
5928
  };
5801
- (0, import_react46.useEffect)(() => transformTool.subscribe(() => {
5929
+ (0, import_react47.useEffect)(() => transformTool.subscribe(() => {
5802
5930
  setTransformTick((n) => n + 1);
5803
5931
  void renderCanvas();
5804
5932
  }), [transformTool, renderCanvas]);
@@ -5809,8 +5937,8 @@ var ImageEditor = ({
5809
5937
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
5810
5938
  const s = controller.getState();
5811
5939
  const cropping = activeTab === "crop";
5812
- const projection = (0, import_image_editor14.getViewportProjection)(s, canvas.width, canvas.height, cropping);
5813
- const pt = (0, import_image_editor14.canvasToImagePoint)({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
5940
+ const projection = (0, import_image_editor15.getViewportProjection)(s, canvas.width, canvas.height, cropping);
5941
+ 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);
5814
5942
  transformTool.setView(projection.scale);
5815
5943
  return { pt, tolerance: 6 / (projection.scale || 1) };
5816
5944
  };
@@ -5841,7 +5969,7 @@ var ImageEditor = ({
5841
5969
  transformTool.up();
5842
5970
  return true;
5843
5971
  };
5844
- (0, import_react46.useEffect)(() => {
5972
+ (0, import_react47.useEffect)(() => {
5845
5973
  if (typeof window === "undefined") return;
5846
5974
  const onKey = (e) => {
5847
5975
  if (transformTool.key(e)) e.preventDefault();
@@ -5849,7 +5977,7 @@ var ImageEditor = ({
5849
5977
  window.addEventListener("keydown", onKey);
5850
5978
  return () => window.removeEventListener("keydown", onKey);
5851
5979
  }, [transformTool]);
5852
- (0, import_react46.useEffect)(() => {
5980
+ (0, import_react47.useEffect)(() => {
5853
5981
  const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
5854
5982
  const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
5855
5983
  const animId = raf(() => {
@@ -5857,12 +5985,12 @@ var ImageEditor = ({
5857
5985
  });
5858
5986
  return () => caf(animId);
5859
5987
  }, [renderCanvas, state]);
5860
- (0, import_react46.useEffect)(() => {
5988
+ (0, import_react47.useEffect)(() => {
5861
5989
  if (activeTab === "crop" && editor.state.activeTool !== "crop") {
5862
5990
  editor.setTool("crop");
5863
5991
  }
5864
5992
  }, [activeTab, editor]);
5865
- (0, import_react46.useEffect)(() => {
5993
+ (0, import_react47.useEffect)(() => {
5866
5994
  const container = containerRef.current;
5867
5995
  if (!container) return;
5868
5996
  if (typeof ResizeObserver !== "undefined") {
@@ -5898,8 +6026,8 @@ var ImageEditor = ({
5898
6026
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
5899
6027
  const s = controller.getState();
5900
6028
  return list.map((ev) => ({
5901
- ...(0, import_image_editor14.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
5902
- pressure: (0, import_image_editor14.pointerPressure)(ev)
6029
+ ...(0, import_image_editor15.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
6030
+ pressure: (0, import_image_editor15.pointerPressure)(ev)
5903
6031
  }));
5904
6032
  };
5905
6033
  const handlePaintPointerDown = (e) => {
@@ -5911,7 +6039,7 @@ var ImageEditor = ({
5911
6039
  } catch {
5912
6040
  }
5913
6041
  const [first] = paintSamples(e);
5914
- setPaintError(paintGestureRef.current.down(first));
6042
+ setPaintError(paintGestureRef.current.down({ ...first, altKey: e.altKey }));
5915
6043
  };
5916
6044
  const handlePaintPointerMove = (e) => {
5917
6045
  if (handleTransformPointerMove(e)) return;
@@ -5930,10 +6058,10 @@ var ImageEditor = ({
5930
6058
  if (g.error) setPaintError(g.error);
5931
6059
  }
5932
6060
  };
5933
- (0, import_react46.useEffect)(() => {
6061
+ (0, import_react47.useEffect)(() => {
5934
6062
  if (activeTab !== "paint" || typeof window === "undefined") return;
5935
6063
  const onKey = (e) => {
5936
- if ((0, import_image_editor14.handlePaintShortcut)(controller, e)) e.preventDefault();
6064
+ if ((0, import_image_editor15.handlePaintShortcut)(controller, e)) e.preventDefault();
5937
6065
  };
5938
6066
  window.addEventListener("keydown", onKey);
5939
6067
  return () => window.removeEventListener("keydown", onKey);
@@ -5944,7 +6072,7 @@ var ImageEditor = ({
5944
6072
  const canvasPt = getCanvasEventPoint(e);
5945
6073
  if (activeTab === "select") {
5946
6074
  const gesture = selectionGestureRef.current;
5947
- const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6075
+ const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5948
6076
  void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
5949
6077
  return;
5950
6078
  }
@@ -5955,8 +6083,8 @@ var ImageEditor = ({
5955
6083
  width: state.imageDimensions.width,
5956
6084
  height: state.imageDimensions.height
5957
6085
  };
5958
- const handle = (0, import_image_editor14.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
5959
- const startImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
6086
+ const handle = (0, import_image_editor15.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
6087
+ const startImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
5960
6088
  if (handle) {
5961
6089
  cropDragInfoRef.current = {
5962
6090
  handle,
@@ -5975,7 +6103,7 @@ var ImageEditor = ({
5975
6103
  return;
5976
6104
  }
5977
6105
  if (activeTab === "annotate" && (state.activeTool === "shape" || state.activeTool === "type")) {
5978
- const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6106
+ const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5979
6107
  setShapeTypeError(null);
5980
6108
  if (state.activeTool === "shape") shapeGestureRef.current.down(imgPt);
5981
6109
  else {
@@ -5986,12 +6114,12 @@ var ImageEditor = ({
5986
6114
  return;
5987
6115
  }
5988
6116
  if (activeTab === "annotate") {
5989
- const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6117
+ const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5990
6118
  dragStartPointRef.current = imgPt;
5991
6119
  if (state.activeTool === "select") {
5992
6120
  for (let i = state.annotations.length - 1; i >= 0; i--) {
5993
6121
  const ann = state.annotations[i];
5994
- if ((0, import_image_editor14.hitTestAnnotation)(imgPt, ann)) {
6122
+ if ((0, import_image_editor15.hitTestAnnotation)(imgPt, ann)) {
5995
6123
  editor.selectAnnotation(ann.id);
5996
6124
  annotationDragInfoRef.current = {
5997
6125
  annId: ann.id,
@@ -6027,7 +6155,7 @@ var ImageEditor = ({
6027
6155
  const canvasPt = getCanvasEventPoint(e);
6028
6156
  if (activeTab === "select") {
6029
6157
  const gesture = selectionGestureRef.current;
6030
- if (gesture.active && gesture.move((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
6158
+ if (gesture.active && gesture.move((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
6031
6159
  selectionDraftRef.current = gesture.draftPath;
6032
6160
  renderCanvas();
6033
6161
  }
@@ -6036,7 +6164,7 @@ var ImageEditor = ({
6036
6164
  if (activeTab === "crop") {
6037
6165
  const drag = cropDragInfoRef.current;
6038
6166
  if (drag) {
6039
- const currentImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
6167
+ const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
6040
6168
  let newCrop;
6041
6169
  if (drag.handle === "new") {
6042
6170
  const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
@@ -6050,7 +6178,7 @@ var ImageEditor = ({
6050
6178
  height: Math.round(Math.max(20, maxY - minY))
6051
6179
  };
6052
6180
  } else {
6053
- newCrop = (0, import_image_editor14.calculateCropDrag)(
6181
+ newCrop = (0, import_image_editor15.calculateCropDrag)(
6054
6182
  drag.startCrop,
6055
6183
  drag.handle,
6056
6184
  drag.startImgPt,
@@ -6070,15 +6198,15 @@ var ImageEditor = ({
6070
6198
  width: state.imageDimensions.width,
6071
6199
  height: state.imageDimensions.height
6072
6200
  };
6073
- const handle = (0, import_image_editor14.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
6074
- canvas.style.cursor = (0, import_image_editor14.getCropCursor)(handle, state.transform);
6201
+ const handle = (0, import_image_editor15.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
6202
+ canvas.style.cursor = (0, import_image_editor15.getCropCursor)(handle, state.transform);
6075
6203
  }
6076
6204
  return;
6077
6205
  }
6078
6206
  if (activeTab === "annotate" && state.activeTool === "shape") {
6079
6207
  const g = shapeGestureRef.current;
6080
6208
  if (g.active) {
6081
- g.move((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), { shift: e.shiftKey, alt: e.altKey });
6209
+ g.move((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), { shift: e.shiftKey, alt: e.altKey });
6082
6210
  if (g.error) setShapeTypeError(g.error);
6083
6211
  }
6084
6212
  return;
@@ -6086,7 +6214,7 @@ var ImageEditor = ({
6086
6214
  if (activeTab === "annotate") {
6087
6215
  if (annotationDragInfoRef.current) {
6088
6216
  const drag = annotationDragInfoRef.current;
6089
- const currentImgPt2 = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6217
+ const currentImgPt2 = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6090
6218
  const dx = currentImgPt2.x - drag.startImgPt.x;
6091
6219
  const dy = currentImgPt2.y - drag.startImgPt.y;
6092
6220
  editor.updateAnnotation(drag.annId, {
@@ -6098,10 +6226,10 @@ var ImageEditor = ({
6098
6226
  const startPt = dragStartPointRef.current;
6099
6227
  if (!startPt) {
6100
6228
  if (state.activeTool === "select") {
6101
- const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6229
+ const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6102
6230
  let hovered = false;
6103
6231
  for (let i = state.annotations.length - 1; i >= 0; i--) {
6104
- if ((0, import_image_editor14.hitTestAnnotation)(imgPt, state.annotations[i])) {
6232
+ if ((0, import_image_editor15.hitTestAnnotation)(imgPt, state.annotations[i])) {
6105
6233
  hovered = true;
6106
6234
  break;
6107
6235
  }
@@ -6112,7 +6240,7 @@ var ImageEditor = ({
6112
6240
  }
6113
6241
  return;
6114
6242
  }
6115
- const currentImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6243
+ const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6116
6244
  if (state.activeTool === "pen" && isDrawingRef.current) {
6117
6245
  currentPathRef.current.push(currentImgPt);
6118
6246
  const draft = {
@@ -6192,7 +6320,7 @@ var ImageEditor = ({
6192
6320
  if (activeTab === "select") {
6193
6321
  const gesture = selectionGestureRef.current;
6194
6322
  if (gesture.active) {
6195
- gesture.end((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
6323
+ gesture.end((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
6196
6324
  selectionDraftRef.current = null;
6197
6325
  renderCanvas();
6198
6326
  }
@@ -6215,7 +6343,7 @@ var ImageEditor = ({
6215
6343
  }
6216
6344
  if (activeTab === "annotate" && state.activeTool === "type") {
6217
6345
  const tool = typeToolRef.current;
6218
- tool.up((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false));
6346
+ tool.up((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false));
6219
6347
  setTypeSession(tool.session);
6220
6348
  if (tool.error) setShapeTypeError(tool.error);
6221
6349
  void renderCanvas();
@@ -6229,7 +6357,7 @@ var ImageEditor = ({
6229
6357
  }
6230
6358
  const startPt = dragStartPointRef.current;
6231
6359
  if (startPt) {
6232
- const currentImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6360
+ const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6233
6361
  if (state.activeTool === "pen" && isDrawingRef.current) {
6234
6362
  if (currentPathRef.current.length > 1) {
6235
6363
  editor.addAnnotation({
@@ -6325,15 +6453,15 @@ var ImageEditor = ({
6325
6453
  link.click();
6326
6454
  }
6327
6455
  };
6328
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6456
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6329
6457
  "div",
6330
6458
  {
6331
6459
  className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
6332
6460
  style,
6333
6461
  children: [
6334
- /* @__PURE__ */ (0, import_jsx_runtime29.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: [
6335
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
6336
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6462
+ /* @__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: [
6463
+ /* @__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: [
6464
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6337
6465
  "button",
6338
6466
  {
6339
6467
  type: "button",
@@ -6345,7 +6473,7 @@ var ImageEditor = ({
6345
6473
  children: "Transform & Crop"
6346
6474
  }
6347
6475
  ),
6348
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6476
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6349
6477
  "button",
6350
6478
  {
6351
6479
  type: "button",
@@ -6357,7 +6485,7 @@ var ImageEditor = ({
6357
6485
  children: "Adjustments"
6358
6486
  }
6359
6487
  ),
6360
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6488
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6361
6489
  "button",
6362
6490
  {
6363
6491
  type: "button",
@@ -6369,7 +6497,7 @@ var ImageEditor = ({
6369
6497
  children: "Layers"
6370
6498
  }
6371
6499
  ),
6372
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6500
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6373
6501
  "button",
6374
6502
  {
6375
6503
  type: "button",
@@ -6381,7 +6509,7 @@ var ImageEditor = ({
6381
6509
  children: "Paint"
6382
6510
  }
6383
6511
  ),
6384
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6512
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6385
6513
  "button",
6386
6514
  {
6387
6515
  type: "button",
@@ -6393,7 +6521,7 @@ var ImageEditor = ({
6393
6521
  children: "Select & Mask"
6394
6522
  }
6395
6523
  ),
6396
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6524
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6397
6525
  "button",
6398
6526
  {
6399
6527
  type: "button",
@@ -6405,7 +6533,7 @@ var ImageEditor = ({
6405
6533
  children: "Annotations"
6406
6534
  }
6407
6535
  ),
6408
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6536
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6409
6537
  "button",
6410
6538
  {
6411
6539
  type: "button",
@@ -6417,7 +6545,7 @@ var ImageEditor = ({
6417
6545
  children: "Depth Mask"
6418
6546
  }
6419
6547
  ),
6420
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6548
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6421
6549
  "button",
6422
6550
  {
6423
6551
  type: "button",
@@ -6427,14 +6555,14 @@ var ImageEditor = ({
6427
6555
  },
6428
6556
  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"}`,
6429
6557
  children: [
6430
- /* @__PURE__ */ (0, import_jsx_runtime29.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_runtime29.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" }) }),
6558
+ /* @__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" }) }),
6431
6559
  "AI Tools"
6432
6560
  ]
6433
6561
  }
6434
6562
  )
6435
6563
  ] }),
6436
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
6437
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6564
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
6565
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6438
6566
  "button",
6439
6567
  {
6440
6568
  type: "button",
@@ -6445,7 +6573,7 @@ var ImageEditor = ({
6445
6573
  children: "\u21A9"
6446
6574
  }
6447
6575
  ),
6448
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6576
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6449
6577
  "button",
6450
6578
  {
6451
6579
  type: "button",
@@ -6456,7 +6584,7 @@ var ImageEditor = ({
6456
6584
  children: "\u21AA"
6457
6585
  }
6458
6586
  ),
6459
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6587
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6460
6588
  "button",
6461
6589
  {
6462
6590
  type: "button",
@@ -6465,8 +6593,8 @@ var ImageEditor = ({
6465
6593
  children: "Reset"
6466
6594
  }
6467
6595
  ),
6468
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6469
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6596
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6597
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6470
6598
  "button",
6471
6599
  {
6472
6600
  type: "button",
@@ -6476,11 +6604,11 @@ var ImageEditor = ({
6476
6604
  children: "-"
6477
6605
  }
6478
6606
  ),
6479
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
6607
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
6480
6608
  Math.round(state.zoom * 100),
6481
6609
  "%"
6482
6610
  ] }),
6483
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6611
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6484
6612
  "button",
6485
6613
  {
6486
6614
  type: "button",
@@ -6490,8 +6618,8 @@ var ImageEditor = ({
6490
6618
  children: "+"
6491
6619
  }
6492
6620
  ),
6493
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6494
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6621
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6622
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6495
6623
  "button",
6496
6624
  {
6497
6625
  type: "button",
@@ -6502,7 +6630,7 @@ var ImageEditor = ({
6502
6630
  children: "Hold Compare"
6503
6631
  }
6504
6632
  ),
6505
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6633
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6506
6634
  "button",
6507
6635
  {
6508
6636
  type: "button",
@@ -6513,16 +6641,16 @@ var ImageEditor = ({
6513
6641
  )
6514
6642
  ] })
6515
6643
  ] }),
6516
- transformTool.active && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
6517
- !transformTool.active && transformTool.error && /* @__PURE__ */ (0, import_jsx_runtime29.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 }),
6518
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
6519
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6644
+ 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" }),
6645
+ !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 }),
6646
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
6647
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6520
6648
  "div",
6521
6649
  {
6522
6650
  ref: containerRef,
6523
6651
  className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
6524
6652
  children: [
6525
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6653
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6526
6654
  "canvas",
6527
6655
  {
6528
6656
  ref: canvasRef,
@@ -6539,7 +6667,7 @@ var ImageEditor = ({
6539
6667
  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" : ""}`
6540
6668
  }
6541
6669
  ),
6542
- typeSession && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6670
+ typeSession && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6543
6671
  "textarea",
6544
6672
  {
6545
6673
  ref: typeInputRef,
@@ -6561,11 +6689,11 @@ var ImageEditor = ({
6561
6689
  ]
6562
6690
  }
6563
6691
  ),
6564
- /* @__PURE__ */ (0, import_jsx_runtime29.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: [
6565
- activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6566
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
6567
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
6568
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6692
+ /* @__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: [
6693
+ activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6694
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
6695
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
6696
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6569
6697
  "button",
6570
6698
  {
6571
6699
  type: "button",
@@ -6577,7 +6705,7 @@ var ImageEditor = ({
6577
6705
  children: "Freeform"
6578
6706
  }
6579
6707
  ),
6580
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6708
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6581
6709
  "button",
6582
6710
  {
6583
6711
  type: "button",
@@ -6589,7 +6717,7 @@ var ImageEditor = ({
6589
6717
  children: "1:1 Square"
6590
6718
  }
6591
6719
  ),
6592
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6720
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6593
6721
  "button",
6594
6722
  {
6595
6723
  type: "button",
@@ -6601,7 +6729,7 @@ var ImageEditor = ({
6601
6729
  children: "4:3 Standard"
6602
6730
  }
6603
6731
  ),
6604
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6732
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6605
6733
  "button",
6606
6734
  {
6607
6735
  type: "button",
@@ -6613,7 +6741,7 @@ var ImageEditor = ({
6613
6741
  children: "16:9 Wide"
6614
6742
  }
6615
6743
  ),
6616
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6744
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6617
6745
  "button",
6618
6746
  {
6619
6747
  type: "button",
@@ -6625,7 +6753,7 @@ var ImageEditor = ({
6625
6753
  children: "3:2 Photo"
6626
6754
  }
6627
6755
  ),
6628
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6756
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6629
6757
  "button",
6630
6758
  {
6631
6759
  type: "button",
@@ -6638,10 +6766,10 @@ var ImageEditor = ({
6638
6766
  }
6639
6767
  )
6640
6768
  ] }),
6641
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6642
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
6643
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
6644
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6769
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6770
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
6771
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
6772
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6645
6773
  "button",
6646
6774
  {
6647
6775
  type: "button",
@@ -6650,7 +6778,7 @@ var ImageEditor = ({
6650
6778
  children: "Rotate -90\xB0"
6651
6779
  }
6652
6780
  ),
6653
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6781
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6654
6782
  "button",
6655
6783
  {
6656
6784
  type: "button",
@@ -6659,7 +6787,7 @@ var ImageEditor = ({
6659
6787
  children: "Rotate +90\xB0"
6660
6788
  }
6661
6789
  ),
6662
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6790
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6663
6791
  "button",
6664
6792
  {
6665
6793
  type: "button",
@@ -6668,7 +6796,7 @@ var ImageEditor = ({
6668
6796
  children: "Flip Horizontal"
6669
6797
  }
6670
6798
  ),
6671
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6799
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6672
6800
  "button",
6673
6801
  {
6674
6802
  type: "button",
@@ -6679,10 +6807,10 @@ var ImageEditor = ({
6679
6807
  )
6680
6808
  ] })
6681
6809
  ] }),
6682
- activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6683
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between", children: [
6684
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
6685
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6810
+ activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6811
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
6812
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
6813
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6686
6814
  "button",
6687
6815
  {
6688
6816
  type: "button",
@@ -6692,25 +6820,25 @@ var ImageEditor = ({
6692
6820
  }
6693
6821
  )
6694
6822
  ] }),
6695
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Histogram, { histogram: editor.histogram }),
6696
- import_image_editor14.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react46.default.Fragment, { children: [
6697
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6823
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Histogram, { histogram: editor.histogram }),
6824
+ import_image_editor15.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_react47.default.Fragment, { children: [
6825
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6698
6826
  ControlSlider,
6699
6827
  {
6700
6828
  spec,
6701
- value: (0, import_image_editor14.readAdjustmentControls)(state.adjustments)[spec.id],
6829
+ value: (0, import_image_editor15.readAdjustmentControls)(state.adjustments)[spec.id],
6702
6830
  disabled: spec.requiresProcess !== void 0 && legacyProcess,
6703
6831
  onChange: (v) => editor.setAdjustments({ [spec.id]: v })
6704
6832
  }
6705
6833
  ),
6706
- spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6834
+ spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6707
6835
  "div",
6708
6836
  {
6709
6837
  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",
6710
6838
  "data-testid": "image-editor-process-notice",
6711
6839
  children: [
6712
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
6713
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6840
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
6841
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6714
6842
  "button",
6715
6843
  {
6716
6844
  type: "button",
@@ -6723,7 +6851,7 @@ var ImageEditor = ({
6723
6851
  }
6724
6852
  )
6725
6853
  ] }, spec.id)),
6726
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6854
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6727
6855
  AdjustmentLayersPanel,
6728
6856
  {
6729
6857
  controller,
@@ -6732,9 +6860,9 @@ var ImageEditor = ({
6732
6860
  }
6733
6861
  ) })
6734
6862
  ] }),
6735
- activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6736
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
6737
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6863
+ activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6864
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
6865
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6738
6866
  "button",
6739
6867
  {
6740
6868
  type: "button",
@@ -6745,12 +6873,14 @@ var ImageEditor = ({
6745
6873
  children: "Free Transform"
6746
6874
  }
6747
6875
  ),
6748
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(LayersPanel, { controller })
6876
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(LayersPanel, { controller }),
6877
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Colour" }),
6878
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ColorProfilePanel, { controller })
6749
6879
  ] }),
6750
- activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6751
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
6752
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(BrushOptionsBar, { controller }),
6753
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6880
+ activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6881
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
6882
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(BrushOptionsBar, { controller }),
6883
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6754
6884
  "button",
6755
6885
  {
6756
6886
  type: "button",
@@ -6761,12 +6891,12 @@ var ImageEditor = ({
6761
6891
  children: "Free Transform"
6762
6892
  }
6763
6893
  ),
6764
- paintError && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
6765
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(LayersPanel, { controller }) })
6894
+ paintError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
6895
+ /* @__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 }) })
6766
6896
  ] }),
6767
- activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6768
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Shape & Type Layers" }),
6769
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "grid grid-cols-2 gap-1.5", children: ["shape", "type"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6897
+ activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6898
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Shape & Type Layers" }),
6899
+ /* @__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)(
6770
6900
  "button",
6771
6901
  {
6772
6902
  type: "button",
@@ -6777,13 +6907,13 @@ var ImageEditor = ({
6777
6907
  },
6778
6908
  t
6779
6909
  )) }),
6780
- state.activeTool === "shape" && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ShapeOptionsBar, { controller, options: shapeOptions, onChange: setShapeOptions }),
6781
- state.activeTool === "type" && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TypeOptionsBar, { controller, options: typeOptions, onChange: setTypeOptions, session: typeSession }),
6782
- state.activeTool === "type" && typeSession && /* @__PURE__ */ (0, import_jsx_runtime29.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" }),
6783
- shapeTypeError && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "shape-type-error", children: shapeTypeError }),
6784
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6785
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
6786
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6910
+ state.activeTool === "shape" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ShapeOptionsBar, { controller, options: shapeOptions, onChange: setShapeOptions }),
6911
+ state.activeTool === "type" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TypeOptionsBar, { controller, options: typeOptions, onChange: setTypeOptions, session: typeSession }),
6912
+ 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" }),
6913
+ shapeTypeError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "shape-type-error", children: shapeTypeError }),
6914
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6915
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
6916
+ /* @__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)(
6787
6917
  "button",
6788
6918
  {
6789
6919
  type: "button",
@@ -6793,9 +6923,9 @@ var ImageEditor = ({
6793
6923
  },
6794
6924
  t
6795
6925
  )) }),
6796
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
6797
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("label", { className: "text-slate-400", children: "Color:" }),
6798
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6926
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
6927
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { className: "text-slate-400", children: "Color:" }),
6928
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6799
6929
  "input",
6800
6930
  {
6801
6931
  type: "color",
@@ -6804,15 +6934,15 @@ var ImageEditor = ({
6804
6934
  className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
6805
6935
  }
6806
6936
  ),
6807
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex-1 ml-2", children: [
6808
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
6809
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Width:" }),
6810
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "font-mono", children: [
6937
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex-1 ml-2", children: [
6938
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
6939
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Width:" }),
6940
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-mono", children: [
6811
6941
  strokeWidth,
6812
6942
  "px"
6813
6943
  ] })
6814
6944
  ] }),
6815
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6945
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6816
6946
  "input",
6817
6947
  {
6818
6948
  type: "range",
@@ -6825,10 +6955,10 @@ var ImageEditor = ({
6825
6955
  )
6826
6956
  ] })
6827
6957
  ] }),
6828
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6829
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
6830
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex gap-2", children: [
6831
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6958
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6959
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
6960
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex gap-2", children: [
6961
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6832
6962
  "input",
6833
6963
  {
6834
6964
  type: "text",
@@ -6839,7 +6969,7 @@ var ImageEditor = ({
6839
6969
  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"
6840
6970
  }
6841
6971
  ),
6842
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6972
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6843
6973
  "button",
6844
6974
  {
6845
6975
  type: "button",
@@ -6849,14 +6979,14 @@ var ImageEditor = ({
6849
6979
  }
6850
6980
  )
6851
6981
  ] }),
6852
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
6853
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Font Size:" }),
6854
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "font-mono", children: [
6982
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
6983
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Font Size:" }),
6984
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-mono", children: [
6855
6985
  fontSize,
6856
6986
  "px"
6857
6987
  ] })
6858
6988
  ] }),
6859
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6989
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6860
6990
  "input",
6861
6991
  {
6862
6992
  type: "range",
@@ -6867,14 +6997,14 @@ var ImageEditor = ({
6867
6997
  className: "w-full accent-indigo-500"
6868
6998
  }
6869
6999
  ),
6870
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6871
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between", children: [
6872
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "text-slate-400", children: [
7000
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
7001
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7002
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "text-slate-400", children: [
6873
7003
  "Layers (",
6874
7004
  state.annotations.length,
6875
7005
  ")"
6876
7006
  ] }),
6877
- state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7007
+ state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6878
7008
  "button",
6879
7009
  {
6880
7010
  type: "button",
@@ -6883,7 +7013,7 @@ var ImageEditor = ({
6883
7013
  children: "Delete Selected"
6884
7014
  }
6885
7015
  ),
6886
- state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7016
+ state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6887
7017
  "button",
6888
7018
  {
6889
7019
  type: "button",
@@ -6894,10 +7024,10 @@ var ImageEditor = ({
6894
7024
  )
6895
7025
  ] })
6896
7026
  ] }),
6897
- activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6898
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between", children: [
6899
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
6900
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7027
+ activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
7028
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7029
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
7030
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6901
7031
  "button",
6902
7032
  {
6903
7033
  type: "button",
@@ -6907,8 +7037,8 @@ var ImageEditor = ({
6907
7037
  }
6908
7038
  )
6909
7039
  ] }),
6910
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
6911
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7040
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
7041
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6912
7042
  "input",
6913
7043
  {
6914
7044
  type: "checkbox",
@@ -6917,12 +7047,12 @@ var ImageEditor = ({
6917
7047
  className: "rounded accent-indigo-500"
6918
7048
  }
6919
7049
  ),
6920
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Enable Depth / Alpha Mask" })
7050
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Enable Depth / Alpha Mask" })
6921
7051
  ] }),
6922
- state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
6923
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { children: [
6924
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
6925
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7052
+ state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7053
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7054
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
7055
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6926
7056
  "input",
6927
7057
  {
6928
7058
  type: "text",
@@ -6933,8 +7063,8 @@ var ImageEditor = ({
6933
7063
  }
6934
7064
  )
6935
7065
  ] }),
6936
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex gap-2", children: [
6937
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7066
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex gap-2", children: [
7067
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6938
7068
  "button",
6939
7069
  {
6940
7070
  type: "button",
@@ -6943,7 +7073,7 @@ var ImageEditor = ({
6943
7073
  children: "Threshold Mode"
6944
7074
  }
6945
7075
  ),
6946
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7076
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6947
7077
  "button",
6948
7078
  {
6949
7079
  type: "button",
@@ -6953,12 +7083,12 @@ var ImageEditor = ({
6953
7083
  }
6954
7084
  )
6955
7085
  ] }),
6956
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { children: [
6957
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6958
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Depth Start (Lower):" }),
6959
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
7086
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7087
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7088
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Depth Start (Lower):" }),
7089
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
6960
7090
  ] }),
6961
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7091
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6962
7092
  "input",
6963
7093
  {
6964
7094
  type: "range",
@@ -6972,12 +7102,12 @@ var ImageEditor = ({
6972
7102
  }
6973
7103
  )
6974
7104
  ] }),
6975
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { children: [
6976
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6977
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Depth Stop (Upper):" }),
6978
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
7105
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7106
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7107
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Depth Stop (Upper):" }),
7108
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
6979
7109
  ] }),
6980
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7110
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6981
7111
  "input",
6982
7112
  {
6983
7113
  type: "range",
@@ -6991,12 +7121,12 @@ var ImageEditor = ({
6991
7121
  }
6992
7122
  )
6993
7123
  ] }),
6994
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { children: [
6995
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6996
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Softness:" }),
6997
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
7124
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7125
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7126
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Softness:" }),
7127
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
6998
7128
  ] }),
6999
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7129
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7000
7130
  "input",
7001
7131
  {
7002
7132
  type: "range",
@@ -7008,8 +7138,8 @@ var ImageEditor = ({
7008
7138
  }
7009
7139
  )
7010
7140
  ] }),
7011
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
7012
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7141
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
7142
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7013
7143
  "input",
7014
7144
  {
7015
7145
  type: "checkbox",
@@ -7018,12 +7148,12 @@ var ImageEditor = ({
7018
7148
  className: "rounded accent-indigo-500"
7019
7149
  }
7020
7150
  ),
7021
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Invert Mask" })
7151
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Invert Mask" })
7022
7152
  ] })
7023
7153
  ] })
7024
7154
  ] }),
7025
- activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7026
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7155
+ activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7156
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7027
7157
  SelectionOptionsBar,
7028
7158
  {
7029
7159
  controller,
@@ -7033,9 +7163,9 @@ var ImageEditor = ({
7033
7163
  quickMask: Boolean(state.quickMask)
7034
7164
  }
7035
7165
  ),
7036
- selectionError && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
7037
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex gap-1", children: [
7038
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7166
+ selectionError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
7167
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex gap-1", children: [
7168
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7039
7169
  "button",
7040
7170
  {
7041
7171
  type: "button",
@@ -7046,7 +7176,7 @@ var ImageEditor = ({
7046
7176
  children: "Transform Selection"
7047
7177
  }
7048
7178
  ),
7049
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7179
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7050
7180
  "button",
7051
7181
  {
7052
7182
  type: "button",
@@ -7058,12 +7188,12 @@ var ImageEditor = ({
7058
7188
  }
7059
7189
  )
7060
7190
  ] }),
7061
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
7191
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
7062
7192
  ] }),
7063
- activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7064
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
7065
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Results go to" }),
7066
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
7193
+ activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7194
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
7195
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Results go to" }),
7196
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7067
7197
  "select",
7068
7198
  {
7069
7199
  "aria-label": "AI result target",
@@ -7071,54 +7201,54 @@ var ImageEditor = ({
7071
7201
  onChange: (e) => setAiTarget(e.target.value),
7072
7202
  className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
7073
7203
  children: [
7074
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
7075
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
7076
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: "replace", children: "Replace image" })
7204
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
7205
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
7206
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("option", { value: "replace", children: "Replace image" })
7077
7207
  ]
7078
7208
  }
7079
7209
  )
7080
7210
  ] }),
7081
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
7082
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between", children: [
7083
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
7084
- /* @__PURE__ */ (0, import_jsx_runtime29.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_runtime29.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" }) }),
7211
+ /* @__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: [
7212
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7213
+ /* @__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: [
7214
+ /* @__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" }) }),
7085
7215
  "Background Removal"
7086
7216
  ] }),
7087
- isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime29.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..." })
7217
+ 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..." })
7088
7218
  ] }),
7089
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
7090
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7219
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
7220
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7091
7221
  "button",
7092
7222
  {
7093
7223
  type: "button",
7094
7224
  onClick: handleRemoveBackground,
7095
7225
  disabled: isRemovingBg || isInpainting,
7096
7226
  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",
7097
- children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
7098
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
7227
+ children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7228
+ /* @__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" }),
7099
7229
  "Removing Background..."
7100
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
7101
- /* @__PURE__ */ (0, import_jsx_runtime29.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_runtime29.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" }) }),
7230
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7231
+ /* @__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" }) }),
7102
7232
  "Remove Background"
7103
7233
  ] })
7104
7234
  }
7105
7235
  )
7106
7236
  ] }),
7107
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
7108
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between", children: [
7109
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
7110
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
7111
- /* @__PURE__ */ (0, import_jsx_runtime29.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" }),
7112
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("path", { d: "m14 7 3 3" })
7237
+ /* @__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: [
7238
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7239
+ /* @__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: [
7240
+ /* @__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: [
7241
+ /* @__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" }),
7242
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "m14 7 3 3" })
7113
7243
  ] }),
7114
7244
  "Generative Inpainting"
7115
7245
  ] }),
7116
- isInpainting && /* @__PURE__ */ (0, import_jsx_runtime29.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..." })
7246
+ 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..." })
7117
7247
  ] }),
7118
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
7119
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1", children: [
7120
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
7121
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7248
+ /* @__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." }),
7249
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-1", children: [
7250
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
7251
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7122
7252
  "textarea",
7123
7253
  {
7124
7254
  id: "ai-inpaint-prompt-react",
@@ -7130,10 +7260,10 @@ var ImageEditor = ({
7130
7260
  }
7131
7261
  )
7132
7262
  ] }),
7133
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1", children: [
7134
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
7135
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
7136
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
7263
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-1", children: [
7264
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
7265
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
7266
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7137
7267
  "button",
7138
7268
  {
7139
7269
  type: "button",
@@ -7146,7 +7276,7 @@ var ImageEditor = ({
7146
7276
  ]
7147
7277
  }
7148
7278
  ),
7149
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
7279
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7150
7280
  "button",
7151
7281
  {
7152
7282
  type: "button",
@@ -7161,25 +7291,25 @@ var ImageEditor = ({
7161
7291
  )
7162
7292
  ] })
7163
7293
  ] }),
7164
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7294
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7165
7295
  "button",
7166
7296
  {
7167
7297
  type: "button",
7168
7298
  onClick: handleInpaint,
7169
7299
  disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
7170
7300
  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",
7171
- children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
7172
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
7301
+ children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7302
+ /* @__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" }),
7173
7303
  "Generating Inpaint..."
7174
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
7175
- /* @__PURE__ */ (0, import_jsx_runtime29.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_runtime29.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" }) }),
7304
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7305
+ /* @__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" }) }),
7176
7306
  "Apply Inpainting"
7177
7307
  ] })
7178
7308
  }
7179
7309
  )
7180
7310
  ] }),
7181
- aiError && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
7182
- aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
7311
+ 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 }),
7312
+ 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 })
7183
7313
  ] })
7184
7314
  ] })
7185
7315
  ] })
@@ -7189,7 +7319,7 @@ var ImageEditor = ({
7189
7319
  };
7190
7320
 
7191
7321
  // src/review/useReview.ts
7192
- var import_react47 = require("react");
7322
+ var import_react48 = require("react");
7193
7323
  var import_editor12 = require("@pixerate/editor");
7194
7324
  var EMPTY_COMMENTS = Object.freeze({
7195
7325
  threads: [],
@@ -7208,23 +7338,23 @@ function isCommentStore(value) {
7208
7338
  }
7209
7339
  function useComments(source) {
7210
7340
  const store = isCommentStore(source) ? source : (0, import_editor12.getCommentStore)(source);
7211
- const subscribe = (0, import_react47.useCallback)(
7341
+ const subscribe = (0, import_react48.useCallback)(
7212
7342
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
7213
7343
  [store]
7214
7344
  );
7215
7345
  const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;
7216
- const snapshot = (0, import_react47.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7217
- return (0, import_react47.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
7346
+ const snapshot = (0, import_react48.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7347
+ return (0, import_react48.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
7218
7348
  }
7219
7349
  function useTrackChanges(editor) {
7220
7350
  const store = (0, import_editor12.getTrackChangesStore)(editor ?? null);
7221
- const subscribe = (0, import_react47.useCallback)(
7351
+ const subscribe = (0, import_react48.useCallback)(
7222
7352
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
7223
7353
  [store]
7224
7354
  );
7225
7355
  const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;
7226
- const snapshot = (0, import_react47.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7227
- return (0, import_react47.useMemo)(() => {
7356
+ const snapshot = (0, import_react48.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7357
+ return (0, import_react48.useMemo)(() => {
7228
7358
  const run = (fn) => () => {
7229
7359
  if (editor && !editor.isDestroyed) fn(editor);
7230
7360
  };
@@ -7247,9 +7377,9 @@ function useTrackChanges(editor) {
7247
7377
  }
7248
7378
 
7249
7379
  // src/review/CommentsPanel.tsx
7250
- var import_react48 = require("react");
7380
+ var import_react49 = require("react");
7251
7381
  var import_editor13 = require("@pixerate/editor");
7252
- var import_jsx_runtime30 = require("react/jsx-runtime");
7382
+ var import_jsx_runtime31 = require("react/jsx-runtime");
7253
7383
  var buttonClass2 = "rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50";
7254
7384
  var primaryButtonClass = "rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50";
7255
7385
  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";
@@ -7263,18 +7393,18 @@ var CommentsPanel = ({
7263
7393
  emptyMessage = "No comments yet. Select text and add a comment."
7264
7394
  }) => {
7265
7395
  const { threads, activeThreadId, store } = useComments(storeProp ?? editor);
7266
- const [showResolved, setShowResolved] = (0, import_react48.useState)(showResolvedInitial);
7396
+ const [showResolved, setShowResolved] = (0, import_react49.useState)(showResolvedInitial);
7267
7397
  const author = authorProp ?? (0, import_editor13.getCommentAuthor)(editor) ?? { id: "anonymous", name: "Anonymous" };
7268
7398
  const visible = threads.filter((t) => showResolved || !t.resolved);
7269
7399
  const resolvedCount = threads.filter((t) => t.resolved).length;
7270
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("aside", { className, "aria-label": "Comments", children: [
7271
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
7272
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
7400
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("aside", { className, "aria-label": "Comments", children: [
7401
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
7402
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
7273
7403
  threads.length - resolvedCount,
7274
7404
  " open",
7275
7405
  resolvedCount > 0 ? ` \xB7 ${resolvedCount} resolved` : ""
7276
7406
  ] }),
7277
- resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7407
+ resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7278
7408
  "button",
7279
7409
  {
7280
7410
  type: "button",
@@ -7285,7 +7415,7 @@ var CommentsPanel = ({
7285
7415
  }
7286
7416
  )
7287
7417
  ] }),
7288
- visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("ul", { className: "flex flex-col gap-2", role: "list", children: visible.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7418
+ 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)(
7289
7419
  CommentThreadCard,
7290
7420
  {
7291
7421
  thread,
@@ -7307,7 +7437,7 @@ var CommentThreadCard = ({
7307
7437
  author,
7308
7438
  formatTime
7309
7439
  }) => {
7310
- const [draft, setDraft] = (0, import_react48.useState)("");
7440
+ const [draft, setDraft] = (0, import_react49.useState)("");
7311
7441
  const isDraft = thread.body === "";
7312
7442
  const quote = thread.anchor?.quote ?? thread.lastQuote ?? "";
7313
7443
  const live = editor && !editor.isDestroyed ? editor : null;
@@ -7333,7 +7463,7 @@ var CommentThreadCard = ({
7333
7463
  setDraft("");
7334
7464
  };
7335
7465
  const stop = (e) => e.stopPropagation();
7336
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7466
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
7337
7467
  "li",
7338
7468
  {
7339
7469
  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" : ""}`,
@@ -7349,24 +7479,24 @@ var CommentThreadCard = ({
7349
7479
  }
7350
7480
  },
7351
7481
  children: [
7352
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
7353
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-medium", children: thread.author.name }),
7354
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
7482
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
7483
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "font-medium", children: thread.author.name }),
7484
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
7355
7485
  ] }),
7356
- quote && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("blockquote", { className: "border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2", children: quote }),
7357
- thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
7358
- thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
7359
- !isDraft && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
7360
- thread.replies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.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_runtime30.jsxs)("li", { className: "flex flex-col gap-0.5", "data-reply-id": reply.id, children: [
7361
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "text-xs", children: [
7362
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-medium", children: reply.author.name }),
7486
+ 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 }),
7487
+ thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
7488
+ thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
7489
+ !isDraft && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
7490
+ 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: [
7491
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-xs", children: [
7492
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "font-medium", children: reply.author.name }),
7363
7493
  " ",
7364
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
7494
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
7365
7495
  ] }),
7366
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
7496
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
7367
7497
  ] }, reply.id)) }),
7368
- (active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
7369
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7498
+ (active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
7499
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7370
7500
  "textarea",
7371
7501
  {
7372
7502
  className: textareaClass,
@@ -7384,9 +7514,9 @@ var CommentThreadCard = ({
7384
7514
  }
7385
7515
  }
7386
7516
  ),
7387
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-end gap-1", children: [
7388
- isDraft && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
7389
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7517
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex justify-end gap-1", children: [
7518
+ isDraft && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
7519
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7390
7520
  "button",
7391
7521
  {
7392
7522
  type: "button",
@@ -7398,9 +7528,9 @@ var CommentThreadCard = ({
7398
7528
  )
7399
7529
  ] })
7400
7530
  ] }),
7401
- !isDraft && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
7402
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
7403
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7531
+ !isDraft && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
7532
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
7533
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7404
7534
  "button",
7405
7535
  {
7406
7536
  type: "button",
@@ -7416,7 +7546,7 @@ var CommentThreadCard = ({
7416
7546
  };
7417
7547
 
7418
7548
  // src/review/ReviewToolbar.tsx
7419
- var import_jsx_runtime31 = require("react/jsx-runtime");
7549
+ var import_jsx_runtime32 = require("react/jsx-runtime");
7420
7550
  var defaultDescriptionClass = "max-w-[16rem] truncate px-1 text-xs text-muted-foreground";
7421
7551
  var buttonClass3 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
7422
7552
  var ReviewToolbar = ({
@@ -7429,8 +7559,8 @@ var ReviewToolbar = ({
7429
7559
  const count = review.changes.length;
7430
7560
  const current = review.currentChange;
7431
7561
  const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;
7432
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
7433
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7562
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
7563
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7434
7564
  "button",
7435
7565
  {
7436
7566
  type: "button",
@@ -7441,8 +7571,8 @@ var ReviewToolbar = ({
7441
7571
  children: review.enabled ? "Tracking on" : "Track changes"
7442
7572
  }
7443
7573
  ),
7444
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7445
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7574
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7575
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7446
7576
  "button",
7447
7577
  {
7448
7578
  type: "button",
@@ -7453,8 +7583,8 @@ var ReviewToolbar = ({
7453
7583
  children: "\u2039"
7454
7584
  }
7455
7585
  ),
7456
- /* @__PURE__ */ (0, import_jsx_runtime31.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` }),
7457
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7586
+ /* @__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` }),
7587
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7458
7588
  "button",
7459
7589
  {
7460
7590
  type: "button",
@@ -7465,7 +7595,7 @@ var ReviewToolbar = ({
7465
7595
  children: "\u203A"
7466
7596
  }
7467
7597
  ),
7468
- showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
7598
+ showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7469
7599
  "span",
7470
7600
  {
7471
7601
  className: descriptionClassName,
@@ -7477,8 +7607,8 @@ var ReviewToolbar = ({
7477
7607
  ]
7478
7608
  }
7479
7609
  ),
7480
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7481
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7610
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7611
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7482
7612
  "button",
7483
7613
  {
7484
7614
  type: "button",
@@ -7488,7 +7618,7 @@ var ReviewToolbar = ({
7488
7618
  children: "Accept"
7489
7619
  }
7490
7620
  ),
7491
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7621
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7492
7622
  "button",
7493
7623
  {
7494
7624
  type: "button",
@@ -7498,18 +7628,18 @@ var ReviewToolbar = ({
7498
7628
  children: "Reject"
7499
7629
  }
7500
7630
  ),
7501
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
7502
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
7631
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
7632
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
7503
7633
  ] });
7504
7634
  };
7505
7635
 
7506
7636
  // src/review/CommentButton.tsx
7507
- var import_jsx_runtime32 = require("react/jsx-runtime");
7637
+ var import_jsx_runtime33 = require("react/jsx-runtime");
7508
7638
  var CommentButton = ({
7509
7639
  editor,
7510
7640
  className = "rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted",
7511
7641
  children = "Comment"
7512
- }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7642
+ }) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7513
7643
  "button",
7514
7644
  {
7515
7645
  type: "button",
@@ -7521,13 +7651,13 @@ var CommentButton = ({
7521
7651
  );
7522
7652
 
7523
7653
  // src/review/useDocumentCompare.ts
7524
- var import_react49 = require("react");
7654
+ var import_react50 = require("react");
7525
7655
  var import_editor14 = require("@pixerate/editor");
7526
7656
  function useDocumentCompare(editor, options) {
7527
- const [summary, setSummary] = (0, import_react49.useState)(null);
7528
- const defaults = (0, import_react49.useRef)(options);
7657
+ const [summary, setSummary] = (0, import_react50.useState)(null);
7658
+ const defaults = (0, import_react50.useRef)(options);
7529
7659
  defaults.current = options;
7530
- const compare = (0, import_react49.useCallback)(
7660
+ const compare = (0, import_react50.useCallback)(
7531
7661
  (original, revised, overrides) => {
7532
7662
  if (!editor || editor.isDestroyed) return null;
7533
7663
  const result = (0, import_editor14.applyDocumentComparison)(editor, original, revised, {
@@ -7539,13 +7669,13 @@ function useDocumentCompare(editor, options) {
7539
7669
  },
7540
7670
  [editor]
7541
7671
  );
7542
- const clear = (0, import_react49.useCallback)(() => setSummary(null), []);
7543
- return (0, import_react49.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
7672
+ const clear = (0, import_react50.useCallback)(() => setSummary(null), []);
7673
+ return (0, import_react50.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
7544
7674
  }
7545
7675
 
7546
7676
  // src/review/TrackedChangesList.tsx
7547
7677
  var import_editor15 = require("@pixerate/editor");
7548
- var import_jsx_runtime33 = require("react/jsx-runtime");
7678
+ var import_jsx_runtime34 = require("react/jsx-runtime");
7549
7679
  var buttonClass4 = "rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40";
7550
7680
  var TrackedChangesList = ({
7551
7681
  editor,
@@ -7556,18 +7686,18 @@ var TrackedChangesList = ({
7556
7686
  }) => {
7557
7687
  const review = useTrackChanges(editor);
7558
7688
  if (review.changes.length === 0) {
7559
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className, "data-tracked-changes-list": "", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "pixerate-changes-empty text-xs text-muted-foreground", children: emptyState }) });
7689
+ 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 }) });
7560
7690
  }
7561
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
7691
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
7562
7692
  const active = change.id === review.currentChangeId;
7563
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
7693
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7564
7694
  "li",
7565
7695
  {
7566
7696
  className: active ? `${itemClassName} ${activeItemClassName}` : itemClassName,
7567
7697
  "data-change-type": change.type,
7568
7698
  "data-change-id": change.id,
7569
7699
  children: [
7570
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
7700
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7571
7701
  "button",
7572
7702
  {
7573
7703
  type: "button",
@@ -7575,14 +7705,14 @@ var TrackedChangesList = ({
7575
7705
  title: `${change.author.name}: ${change.description}`,
7576
7706
  onClick: () => review.select(change.id),
7577
7707
  children: [
7578
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
7708
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
7579
7709
  change.author.name ? ` \xB7 ${change.author.name}` : "",
7580
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
7710
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
7581
7711
  ]
7582
7712
  }
7583
7713
  ),
7584
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
7585
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
7714
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
7715
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
7586
7716
  ]
7587
7717
  },
7588
7718
  `${change.type}:${change.id}`
@@ -7591,12 +7721,12 @@ var TrackedChangesList = ({
7591
7721
  };
7592
7722
 
7593
7723
  // src/commands/useCommandPalette.ts
7594
- var import_react50 = require("react");
7724
+ var import_react51 = require("react");
7595
7725
  var import_commands2 = require("@pixerate/editor/commands");
7596
7726
  function useCommandPalette(registry, options = {}) {
7597
- const optionsRef = (0, import_react50.useRef)(options);
7727
+ const optionsRef = (0, import_react51.useRef)(options);
7598
7728
  optionsRef.current = options;
7599
- const controller = (0, import_react50.useMemo)(
7729
+ const controller = (0, import_react51.useMemo)(
7600
7730
  () => (0, import_commands2.createCommandPaletteController)(registry, {
7601
7731
  context: () => {
7602
7732
  const c = optionsRef.current.context;
@@ -7617,9 +7747,9 @@ function useCommandPalette(registry, options = {}) {
7617
7747
  // eslint-disable-next-line react-hooks/exhaustive-deps
7618
7748
  [registry]
7619
7749
  );
7620
- const state = (0, import_react50.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
7750
+ const state = (0, import_react51.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
7621
7751
  const { hotkey, hotkeyTarget } = options;
7622
- (0, import_react50.useEffect)(() => {
7752
+ (0, import_react51.useEffect)(() => {
7623
7753
  if (!hotkey) return;
7624
7754
  const target = hotkeyTarget ?? (typeof window !== "undefined" ? window : null);
7625
7755
  if (!target) return;
@@ -7647,13 +7777,13 @@ function useCommandPalette(registry, options = {}) {
7647
7777
  }
7648
7778
 
7649
7779
  // src/commands/CommandPalette.tsx
7650
- var import_react51 = __toESM(require("react"), 1);
7651
- var import_jsx_runtime34 = require("react/jsx-runtime");
7780
+ var import_react52 = __toESM(require("react"), 1);
7781
+ var import_jsx_runtime35 = require("react/jsx-runtime");
7652
7782
  function HighlightedLabel({ item }) {
7653
- if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_jsx_runtime34.Fragment, { children: item.label });
7783
+ if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_jsx_runtime35.Fragment, { children: item.label });
7654
7784
  const marked = new Set(item.labelIndices);
7655
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_jsx_runtime34.Fragment, { children: Array.from(item.label).map(
7656
- (ch, i) => marked.has(i) ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "font-semibold text-foreground", "data-match": "", children: ch }, i) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react51.default.Fragment, { children: ch }, i)
7785
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_jsx_runtime35.Fragment, { children: Array.from(item.label).map(
7786
+ (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)
7657
7787
  ) });
7658
7788
  }
7659
7789
  var CommandPalette = ({
@@ -7662,22 +7792,22 @@ var CommandPalette = ({
7662
7792
  emptyMessage = "No matching commands",
7663
7793
  className = ""
7664
7794
  }) => {
7665
- const inputRef = (0, import_react51.useRef)(null);
7666
- const listRef = (0, import_react51.useRef)(null);
7667
- const baseId = (0, import_react51.useId)();
7795
+ const inputRef = (0, import_react52.useRef)(null);
7796
+ const listRef = (0, import_react52.useRef)(null);
7797
+ const baseId = (0, import_react52.useId)();
7668
7798
  const listId = `${baseId}-list`;
7669
7799
  const optionId = (index) => `${baseId}-option-${index}`;
7670
7800
  const { open, query, items, activeIndex } = palette;
7671
- (0, import_react51.useEffect)(() => {
7801
+ (0, import_react52.useEffect)(() => {
7672
7802
  if (open) inputRef.current?.focus();
7673
7803
  }, [open]);
7674
- (0, import_react51.useEffect)(() => {
7804
+ (0, import_react52.useEffect)(() => {
7675
7805
  if (!open) return;
7676
7806
  const active = listRef.current?.querySelector('[aria-selected="true"]');
7677
7807
  active?.scrollIntoView?.({ block: "nearest" });
7678
7808
  }, [open, activeIndex]);
7679
7809
  if (!open) return null;
7680
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7810
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7681
7811
  "div",
7682
7812
  {
7683
7813
  className: "fixed inset-0 z-50 flex items-start justify-center bg-black/30 px-4 pt-[15vh]",
@@ -7685,7 +7815,7 @@ var CommandPalette = ({
7685
7815
  onMouseDown: (e) => {
7686
7816
  if (e.target === e.currentTarget) palette.setOpen(false);
7687
7817
  },
7688
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7818
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7689
7819
  "div",
7690
7820
  {
7691
7821
  role: "dialog",
@@ -7694,7 +7824,7 @@ var CommandPalette = ({
7694
7824
  className: `w-full max-w-lg overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-xl ${className}`,
7695
7825
  style: { background: "var(--popover, var(--background, #fff))" },
7696
7826
  children: [
7697
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7827
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7698
7828
  "input",
7699
7829
  {
7700
7830
  ref: inputRef,
@@ -7714,7 +7844,7 @@ var CommandPalette = ({
7714
7844
  className: "w-full border-b border-border bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground"
7715
7845
  }
7716
7846
  ),
7717
- items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime34.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_runtime34.jsxs)(
7847
+ 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)(
7718
7848
  "li",
7719
7849
  {
7720
7850
  id: optionId(index),
@@ -7729,12 +7859,12 @@ var CommandPalette = ({
7729
7859
  onClick: () => palette.run(item.id),
7730
7860
  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"}`,
7731
7861
  children: [
7732
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
7733
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HighlightedLabel, { item }),
7734
- item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
7862
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
7863
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HighlightedLabel, { item }),
7864
+ item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
7735
7865
  ] }),
7736
- item.group && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
7737
- item.shortcut && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("kbd", { className: "shrink-0 rounded border border-border px-1.5 font-mono text-[10px] text-muted-foreground", children: item.shortcut })
7866
+ item.group && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
7867
+ 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 })
7738
7868
  ]
7739
7869
  },
7740
7870
  item.id
@@ -7747,12 +7877,12 @@ var CommandPalette = ({
7747
7877
  };
7748
7878
 
7749
7879
  // src/commands/useCommandShortcuts.ts
7750
- var import_react52 = require("react");
7880
+ var import_react53 = require("react");
7751
7881
  function useCommandShortcuts(registry, options = {}) {
7752
- const optionsRef = (0, import_react52.useRef)(options);
7882
+ const optionsRef = (0, import_react53.useRef)(options);
7753
7883
  optionsRef.current = options;
7754
7884
  const { enabled = true, target } = options;
7755
- (0, import_react52.useEffect)(() => {
7885
+ (0, import_react53.useEffect)(() => {
7756
7886
  if (!registry || !enabled) return;
7757
7887
  const eventTarget = target ?? (typeof window !== "undefined" ? window : null);
7758
7888
  if (!eventTarget) return;
@@ -7770,14 +7900,14 @@ function useCommandShortcuts(registry, options = {}) {
7770
7900
  }, [registry, enabled, target]);
7771
7901
  }
7772
7902
  function useRegisterCommands(registry, specs) {
7773
- (0, import_react52.useEffect)(() => {
7903
+ (0, import_react53.useEffect)(() => {
7774
7904
  if (!registry || !specs || specs.length === 0) return;
7775
7905
  return registry.register(specs);
7776
7906
  }, [registry, specs]);
7777
7907
  }
7778
7908
 
7779
7909
  // src/persistence/useAutosave.ts
7780
- var import_react53 = require("react");
7910
+ var import_react54 = require("react");
7781
7911
  var import_persistence = require("@pixerate/editor/persistence");
7782
7912
  var IDLE = {
7783
7913
  status: "idle",
@@ -7788,18 +7918,18 @@ var IDLE = {
7788
7918
  ready: false
7789
7919
  };
7790
7920
  function useAutosave(options) {
7791
- const optionsRef = (0, import_react53.useRef)(options);
7921
+ const optionsRef = (0, import_react54.useRef)(options);
7792
7922
  optionsRef.current = options;
7793
7923
  const { storage, key, history, dirty } = options;
7794
7924
  const recover = options.recover !== false;
7795
7925
  const flushOnHide = options.flushOnHide !== false;
7796
7926
  const ready = options.ready !== false;
7797
- const [controller, setController] = (0, import_react53.useState)(null);
7798
- const [status, setStatus] = (0, import_react53.useState)(IDLE);
7799
- const [recovery, setRecovery] = (0, import_react53.useState)(null);
7800
- const [pendingRecovery, setPendingRecovery] = (0, import_react53.useState)(recover);
7801
- const revisionsRef = (0, import_react53.useRef)(null);
7802
- (0, import_react53.useEffect)(() => {
7927
+ const [controller, setController] = (0, import_react54.useState)(null);
7928
+ const [status, setStatus] = (0, import_react54.useState)(IDLE);
7929
+ const [recovery, setRecovery] = (0, import_react54.useState)(null);
7930
+ const [pendingRecovery, setPendingRecovery] = (0, import_react54.useState)(recover);
7931
+ const revisionsRef = (0, import_react54.useRef)(null);
7932
+ (0, import_react54.useEffect)(() => {
7803
7933
  const revisions = (0, import_persistence.createRevisionTracker)({ history, dirty });
7804
7934
  const o = optionsRef.current;
7805
7935
  const instance = (0, import_persistence.createAutosaveController)({
@@ -7842,10 +7972,10 @@ function useAutosave(options) {
7842
7972
  if (revisionsRef.current === revisions) revisionsRef.current = null;
7843
7973
  };
7844
7974
  }, [storage, key, history, dirty, recover]);
7845
- (0, import_react53.useEffect)(() => {
7975
+ (0, import_react54.useEffect)(() => {
7846
7976
  if (controller && ready && !pendingRecovery) controller.ready();
7847
7977
  }, [controller, ready, pendingRecovery]);
7848
- (0, import_react53.useEffect)(() => {
7978
+ (0, import_react54.useEffect)(() => {
7849
7979
  if (!controller || !flushOnHide || typeof window === "undefined") return;
7850
7980
  const flush = () => void controller.flushNow();
7851
7981
  const onVisibility = () => {
@@ -7858,31 +7988,31 @@ function useAutosave(options) {
7858
7988
  document.removeEventListener("visibilitychange", onVisibility);
7859
7989
  };
7860
7990
  }, [controller, flushOnHide]);
7861
- const restore = (0, import_react53.useCallback)(() => {
7991
+ const restore = (0, import_react54.useCallback)(() => {
7862
7992
  const snapshot = recovery?.snapshot;
7863
7993
  setRecovery(null);
7864
7994
  setPendingRecovery(false);
7865
7995
  return snapshot;
7866
7996
  }, [recovery]);
7867
- const discard = (0, import_react53.useCallback)(async () => {
7997
+ const discard = (0, import_react54.useCallback)(async () => {
7868
7998
  if (controller) await controller.discardRecovery();
7869
7999
  setRecovery(null);
7870
8000
  setPendingRecovery(false);
7871
8001
  }, [controller]);
7872
- const flushNow = (0, import_react53.useCallback)(async () => {
8002
+ const flushNow = (0, import_react54.useCallback)(async () => {
7873
8003
  await controller?.flushNow();
7874
8004
  }, [controller]);
7875
- const markClean = (0, import_react53.useCallback)(async () => {
8005
+ const markClean = (0, import_react54.useCallback)(async () => {
7876
8006
  revisionsRef.current?.markSaved();
7877
8007
  await controller?.markClean();
7878
8008
  }, [controller]);
7879
- const notifyChange = (0, import_react53.useCallback)(() => revisionsRef.current?.bump(), []);
8009
+ const notifyChange = (0, import_react54.useCallback)(() => revisionsRef.current?.bump(), []);
7880
8010
  return { status, recovery, pendingRecovery, restore, discard, flushNow, markClean, notifyChange, controller };
7881
8011
  }
7882
8012
 
7883
8013
  // src/persistence/RecoveryPrompt.tsx
7884
8014
  var import_persistence2 = require("@pixerate/editor/persistence");
7885
- var import_jsx_runtime35 = require("react/jsx-runtime");
8015
+ var import_jsx_runtime36 = require("react/jsx-runtime");
7886
8016
  var RecoveryPrompt = ({
7887
8017
  recovery,
7888
8018
  onRestore,
@@ -7894,7 +8024,7 @@ var RecoveryPrompt = ({
7894
8024
  }) => {
7895
8025
  if (!recovery) return null;
7896
8026
  const { name } = recovery.meta;
7897
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
8027
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7898
8028
  "div",
7899
8029
  {
7900
8030
  role: "alertdialog",
@@ -7902,15 +8032,15 @@ var RecoveryPrompt = ({
7902
8032
  "data-recovery-prompt": "",
7903
8033
  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}`,
7904
8034
  children: [
7905
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "min-w-0 flex-1", children: [
8035
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "min-w-0 flex-1", children: [
7906
8036
  (0, import_persistence2.formatRecoveryMessage)(recovery.meta, formatTime),
7907
- name ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
8037
+ name ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
7908
8038
  "(",
7909
8039
  name,
7910
8040
  ")"
7911
8041
  ] }) : null
7912
8042
  ] }),
7913
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
8043
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7914
8044
  "button",
7915
8045
  {
7916
8046
  type: "button",
@@ -7920,7 +8050,7 @@ var RecoveryPrompt = ({
7920
8050
  children: restoreLabel
7921
8051
  }
7922
8052
  ),
7923
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
8053
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7924
8054
  "button",
7925
8055
  {
7926
8056
  type: "button",
@@ -7936,17 +8066,17 @@ var RecoveryPrompt = ({
7936
8066
  };
7937
8067
 
7938
8068
  // src/generation/useGenerationPlan.ts
7939
- var import_react54 = require("react");
8069
+ var import_react55 = require("react");
7940
8070
  var import_generation = require("@pixerate/editor/generation");
7941
8071
  function useGenerationPlan(request, capabilities, options = {}) {
7942
8072
  const key = JSON.stringify([request, capabilities, options]);
7943
- return (0, import_react54.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
8073
+ return (0, import_react55.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
7944
8074
  }
7945
8075
  function useJobProgress(options) {
7946
8076
  const { startedAt, expectedMs, done, now, intervalMs = 1e3 } = options;
7947
- const [tick, setTick] = (0, import_react54.useState)(() => Date.now());
8077
+ const [tick, setTick] = (0, import_react55.useState)(() => Date.now());
7948
8078
  const ticking = !done && now === void 0;
7949
- (0, import_react54.useEffect)(() => {
8079
+ (0, import_react55.useEffect)(() => {
7950
8080
  if (!ticking) return;
7951
8081
  setTick(Date.now());
7952
8082
  const id = setInterval(() => setTick(Date.now()), Math.max(16, intervalMs));
@@ -7956,9 +8086,9 @@ function useJobProgress(options) {
7956
8086
  }
7957
8087
 
7958
8088
  // src/generation/GenerationSettings.tsx
7959
- var import_react55 = require("react");
8089
+ var import_react56 = require("react");
7960
8090
  var import_generation2 = require("@pixerate/editor/generation");
7961
- var import_jsx_runtime36 = require("react/jsx-runtime");
8091
+ var import_jsx_runtime37 = require("react/jsx-runtime");
7962
8092
  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";
7963
8093
  function Control({
7964
8094
  control,
@@ -7968,7 +8098,7 @@ function Control({
7968
8098
  }) {
7969
8099
  const shown = value ?? control.defaultValue;
7970
8100
  if (control.kind === "checkbox") {
7971
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8101
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7972
8102
  "input",
7973
8103
  {
7974
8104
  id,
@@ -7980,7 +8110,7 @@ function Control({
7980
8110
  );
7981
8111
  }
7982
8112
  if (control.kind === "select") {
7983
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
8113
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
7984
8114
  "select",
7985
8115
  {
7986
8116
  id,
@@ -7989,14 +8119,14 @@ function Control({
7989
8119
  value: shown === void 0 ? "" : String(shown),
7990
8120
  onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value)),
7991
8121
  children: [
7992
- shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: "", children: "Default" }),
7993
- control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
8122
+ shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("option", { value: "", children: "Default" }),
8123
+ control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
7994
8124
  ]
7995
8125
  }
7996
8126
  );
7997
8127
  }
7998
8128
  if (control.kind === "textarea") {
7999
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8129
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8000
8130
  "textarea",
8001
8131
  {
8002
8132
  id,
@@ -8010,8 +8140,8 @@ function Control({
8010
8140
  );
8011
8141
  }
8012
8142
  const numeric = typeof shown === "number" ? shown : void 0;
8013
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-2", children: [
8014
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8143
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-2", children: [
8144
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8015
8145
  "input",
8016
8146
  {
8017
8147
  id,
@@ -8025,7 +8155,7 @@ function Control({
8025
8155
  onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value))
8026
8156
  }
8027
8157
  ),
8028
- control.kind === "range" && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "w-10 text-right tabular-nums text-muted-foreground", "data-field-value": "", children: numeric ?? "\u2013" })
8158
+ 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" })
8029
8159
  ] });
8030
8160
  }
8031
8161
  var GenerationSettings = ({
@@ -8039,17 +8169,17 @@ var GenerationSettings = ({
8039
8169
  renderReference,
8040
8170
  className = ""
8041
8171
  }) => {
8042
- const baseId = (0, import_react55.useId)();
8043
- const controls = (0, import_react55.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
8172
+ const baseId = (0, import_react56.useId)();
8173
+ const controls = (0, import_react56.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
8044
8174
  const computed = useGenerationPlan(value, capabilities, { strategy });
8045
8175
  const plan = planProp ?? computed;
8046
8176
  const slots = (0, import_generation2.getReferenceSlots)(capabilities, value);
8047
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: `flex flex-col gap-3 text-sm ${className}`, "data-generation-settings": "", "data-model": capabilities.id, children: [
8177
+ 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: [
8048
8178
  controls.map((control) => {
8049
8179
  const id = `${baseId}-${control.key}`;
8050
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
8051
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
8052
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8180
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
8181
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
8182
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8053
8183
  Control,
8054
8184
  {
8055
8185
  control,
@@ -8060,23 +8190,23 @@ var GenerationSettings = ({
8060
8190
  )
8061
8191
  ] }, control.key);
8062
8192
  }),
8063
- slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
8064
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
8193
+ slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
8194
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
8065
8195
  slot.label,
8066
8196
  " ",
8067
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
8197
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
8068
8198
  "(",
8069
8199
  slot.references.length,
8070
8200
  "/",
8071
8201
  slot.max,
8072
8202
  ")"
8073
8203
  ] }),
8074
- slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-destructive", children: " *" })
8204
+ slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-destructive", children: " *" })
8075
8205
  ] }),
8076
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
8077
- slot.references.map((ref) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("li", { className: "flex items-center gap-1 rounded border border-border px-1.5 py-0.5", "data-reference-id": ref.id, children: [
8078
- renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
8079
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8206
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
8207
+ 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: [
8208
+ renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
8209
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8080
8210
  "button",
8081
8211
  {
8082
8212
  type: "button",
@@ -8087,7 +8217,7 @@ var GenerationSettings = ({
8087
8217
  }
8088
8218
  )
8089
8219
  ] }, ref.id)),
8090
- onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8220
+ onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8091
8221
  "button",
8092
8222
  {
8093
8223
  type: "button",
@@ -8098,21 +8228,21 @@ var GenerationSettings = ({
8098
8228
  ) })
8099
8229
  ] })
8100
8230
  ] }, slot.role)),
8101
- showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime36.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_runtime36.jsx)("li", { "data-adjustment-field": adjustment.field, "data-adjustment-kind": adjustment.kind, children: adjustment.reason }, index)) }),
8102
- showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime36.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_runtime36.jsx)("li", { "data-error-field": error.field, children: error.message }, index)) })
8231
+ 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)) }),
8232
+ 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)) })
8103
8233
  ] });
8104
8234
  };
8105
8235
 
8106
8236
  // src/generation/JobProgress.tsx
8107
- var import_jsx_runtime37 = require("react/jsx-runtime");
8237
+ var import_jsx_runtime38 = require("react/jsx-runtime");
8108
8238
  var JobProgress = ({ title, className = "", ...options }) => {
8109
8239
  const progress = useJobProgress(options);
8110
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: `flex flex-col gap-1 text-sm ${className}`, "data-job-progress": "", "data-done": options.done ? "" : void 0, children: [
8111
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
8112
- title && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "truncate text-foreground", children: title }),
8113
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
8240
+ 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: [
8241
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
8242
+ title && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "truncate text-foreground", children: title }),
8243
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
8114
8244
  ] }),
8115
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8245
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8116
8246
  "div",
8117
8247
  {
8118
8248
  role: "progressbar",
@@ -8122,7 +8252,7 @@ var JobProgress = ({ title, className = "", ...options }) => {
8122
8252
  "aria-valuenow": progress.percent,
8123
8253
  "aria-valuetext": `${progress.percent}%, ${progress.label}`,
8124
8254
  className: "h-1.5 w-full overflow-hidden rounded-full bg-muted",
8125
- children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8255
+ children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8126
8256
  "div",
8127
8257
  {
8128
8258
  className: "h-full rounded-full bg-primary transition-[width] duration-500",
@@ -8135,9 +8265,9 @@ var JobProgress = ({ title, className = "", ...options }) => {
8135
8265
  };
8136
8266
 
8137
8267
  // src/generation/AssetMentionChips.tsx
8138
- var import_react56 = require("react");
8268
+ var import_react57 = require("react");
8139
8269
  var import_generation3 = require("@pixerate/editor/generation");
8140
- var import_jsx_runtime38 = require("react/jsx-runtime");
8270
+ var import_jsx_runtime39 = require("react/jsx-runtime");
8141
8271
  var AssetMentionChips = ({
8142
8272
  content,
8143
8273
  onChange,
@@ -8147,14 +8277,14 @@ var AssetMentionChips = ({
8147
8277
  renderAsset,
8148
8278
  className = ""
8149
8279
  }) => {
8150
- const [open, setOpen] = (0, import_react56.useState)(null);
8151
- const rootRef = (0, import_react56.useRef)(null);
8152
- const chips = (0, import_react56.useMemo)(
8280
+ const [open, setOpen] = (0, import_react57.useState)(null);
8281
+ const rootRef = (0, import_react57.useRef)(null);
8282
+ const chips = (0, import_react57.useMemo)(
8153
8283
  () => (0, import_generation3.describeAssetMentions)((0, import_generation3.findTextMentions)(content), assets, capabilities),
8154
8284
  [content, assets, capabilities]
8155
8285
  );
8156
8286
  const options = roles ?? (capabilities ? (0, import_generation3.getAssetRoleOptions)(capabilities) : (0, import_generation3.defaultAssetRoleOptions)());
8157
- (0, import_react56.useEffect)(() => {
8287
+ (0, import_react57.useEffect)(() => {
8158
8288
  if (open === null) return;
8159
8289
  const onPointer = (event) => {
8160
8290
  if (!rootRef.current?.contains(event.target)) setOpen(null);
@@ -8162,19 +8292,19 @@ var AssetMentionChips = ({
8162
8292
  document.addEventListener("mousedown", onPointer);
8163
8293
  return () => document.removeEventListener("mousedown", onPointer);
8164
8294
  }, [open]);
8165
- const pick = (chip5, role) => {
8295
+ const pick = (chip6, role) => {
8166
8296
  setOpen(null);
8167
- if (chip5.start === void 0) return;
8168
- onChange((0, import_generation3.setMentionRoleInText)(content, chip5.start, role));
8297
+ if (chip6.start === void 0) return;
8298
+ onChange((0, import_generation3.setMentionRoleInText)(content, chip6.start, role));
8169
8299
  };
8170
8300
  if (chips.length === 0) return null;
8171
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { ref: rootRef, className: `flex flex-wrap gap-1.5 ${className}`, "data-asset-mention-chips": "", children: chips.map((chip5) => {
8172
- const error = chip5.issues.find((issue) => issue.severity === "error");
8173
- const warning = chip5.issues.find((issue) => issue.severity === "warning");
8301
+ 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) => {
8302
+ const error = chip6.issues.find((issue) => issue.severity === "error");
8303
+ const warning = chip6.issues.find((issue) => issue.severity === "warning");
8174
8304
  const problem = error ?? warning;
8175
- const isOpen = open === chip5.index;
8176
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip5.asset.id, children: [
8177
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
8305
+ const isOpen = open === chip6.index;
8306
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip6.asset.id, children: [
8307
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8178
8308
  "button",
8179
8309
  {
8180
8310
  type: "button",
@@ -8182,82 +8312,82 @@ var AssetMentionChips = ({
8182
8312
  "aria-expanded": isOpen,
8183
8313
  title: problem?.message,
8184
8314
  "data-issue": problem?.code,
8185
- onClick: () => setOpen(isOpen ? null : chip5.index),
8315
+ onClick: () => setOpen(isOpen ? null : chip6.index),
8186
8316
  onKeyDown: (e) => {
8187
8317
  if (e.key === "Escape") setOpen(null);
8188
8318
  },
8189
8319
  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`,
8190
8320
  children: [
8191
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { children: renderAsset ? renderAsset(chip5) : `@${chip5.asset.label ?? chip5.handle}` }),
8192
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8321
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: renderAsset ? renderAsset(chip6) : `@${chip6.asset.label ?? chip6.handle}` }),
8322
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8193
8323
  "span",
8194
8324
  {
8195
- className: `rounded px-1 text-[10px] uppercase tracking-wide ${chip5.role ? "bg-primary/15" : "opacity-60"}`,
8196
- "data-role-badge": chip5.role ?? "",
8197
- children: chip5.roleLabel ?? "No role"
8325
+ className: `rounded px-1 text-[10px] uppercase tracking-wide ${chip6.role ? "bg-primary/15" : "opacity-60"}`,
8326
+ "data-role-badge": chip6.role ?? "",
8327
+ children: chip6.roleLabel ?? "No role"
8198
8328
  }
8199
8329
  )
8200
8330
  ]
8201
8331
  }
8202
8332
  ),
8203
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
8333
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8204
8334
  "div",
8205
8335
  {
8206
8336
  role: "listbox",
8207
- "aria-label": `Role for ${chip5.asset.label ?? chip5.handle}`,
8337
+ "aria-label": `Role for ${chip6.asset.label ?? chip6.handle}`,
8208
8338
  className: "absolute left-0 top-full z-50 mt-1 flex min-w-[12rem] flex-col rounded-md border border-border bg-background p-1 text-xs shadow-lg",
8209
8339
  "data-role-picker": "",
8210
8340
  onKeyDown: (e) => {
8211
8341
  if (e.key === "Escape") setOpen(null);
8212
8342
  },
8213
8343
  children: [
8214
- options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
8344
+ options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8215
8345
  "button",
8216
8346
  {
8217
8347
  type: "button",
8218
8348
  role: "option",
8219
- "aria-selected": chip5.role === option.role,
8349
+ "aria-selected": chip6.role === option.role,
8220
8350
  "data-role-option": option.role,
8221
8351
  title: option.description,
8222
- onClick: () => pick(chip5, option.role),
8352
+ onClick: () => pick(chip6, option.role),
8223
8353
  className: "flex items-center justify-between gap-2 rounded px-2 py-1 text-left hover:bg-muted",
8224
8354
  children: [
8225
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { children: option.label }),
8226
- option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
8355
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: option.label }),
8356
+ option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
8227
8357
  ]
8228
8358
  },
8229
8359
  option.role
8230
8360
  )),
8231
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8361
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8232
8362
  "button",
8233
8363
  {
8234
8364
  type: "button",
8235
8365
  role: "option",
8236
- "aria-selected": !chip5.role,
8366
+ "aria-selected": !chip6.role,
8237
8367
  "data-role-option": "",
8238
- onClick: () => pick(chip5, null),
8368
+ onClick: () => pick(chip6, null),
8239
8369
  className: "rounded px-2 py-1 text-left opacity-70 hover:bg-muted",
8240
8370
  children: "No role"
8241
8371
  }
8242
8372
  ),
8243
- chip5.issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("ul", { className: "mt-1 border-t border-border px-2 pt-1 text-[10px]", "data-chip-issues": "", children: chip5.issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("li", { className: issue.severity === "error" ? "text-red-500" : "text-amber-500", children: issue.message }, i)) })
8373
+ 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)) })
8244
8374
  ]
8245
8375
  }
8246
8376
  )
8247
- ] }, `${chip5.start}-${chip5.index}`);
8377
+ ] }, `${chip6.start}-${chip6.index}`);
8248
8378
  }) });
8249
8379
  };
8250
8380
 
8251
8381
  // src/generation/GenerationHistory.tsx
8252
- var import_react57 = require("react");
8382
+ var import_react58 = require("react");
8253
8383
  var import_generation4 = require("@pixerate/editor/generation");
8254
- var import_jsx_runtime39 = require("react/jsx-runtime");
8384
+ var import_jsx_runtime40 = require("react/jsx-runtime");
8255
8385
  function useGenerationRecords(store, filter) {
8256
- const [records, setRecords] = (0, import_react57.useState)([]);
8257
- const [loading, setLoading] = (0, import_react57.useState)(!!store);
8258
- const [error, setError] = (0, import_react57.useState)(null);
8386
+ const [records, setRecords] = (0, import_react58.useState)([]);
8387
+ const [loading, setLoading] = (0, import_react58.useState)(!!store);
8388
+ const [error, setError] = (0, import_react58.useState)(null);
8259
8389
  const filterKey = (0, import_generation4.stableStringify)(filter ?? {});
8260
- const refresh = (0, import_react57.useCallback)(async () => {
8390
+ const refresh = (0, import_react58.useCallback)(async () => {
8261
8391
  if (!store) {
8262
8392
  setRecords([]);
8263
8393
  setLoading(false);
@@ -8274,7 +8404,7 @@ function useGenerationRecords(store, filter) {
8274
8404
  setLoading(false);
8275
8405
  }
8276
8406
  }, [store, filterKey]);
8277
- (0, import_react57.useEffect)(() => {
8407
+ (0, import_react58.useEffect)(() => {
8278
8408
  void refresh();
8279
8409
  if (!store) return;
8280
8410
  return store.subscribe(() => void refresh());
@@ -8300,21 +8430,21 @@ var GenerationHistory = ({
8300
8430
  emptyText = "No generations yet.",
8301
8431
  className = ""
8302
8432
  }) => {
8303
- const [innerMode, setInnerMode] = (0, import_react57.useState)("exact");
8433
+ const [innerMode, setInnerMode] = (0, import_react58.useState)("exact");
8304
8434
  const mode = modeProp ?? innerMode;
8305
8435
  const setMode = (next) => {
8306
8436
  if (modeProp === void 0) setInnerMode(next);
8307
8437
  onModeChange?.(next);
8308
8438
  };
8309
- const options = (0, import_react57.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
8310
- const results = (0, import_react57.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
8311
- const models = (0, import_react57.useMemo)(
8439
+ const options = (0, import_react58.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
8440
+ const results = (0, import_react58.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
8441
+ const models = (0, import_react58.useMemo)(
8312
8442
  () => capabilities ? Array.isArray(capabilities) ? capabilities : [capabilities] : [],
8313
8443
  [capabilities]
8314
8444
  );
8315
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
8316
- /* @__PURE__ */ (0, import_jsx_runtime39.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_runtime39.jsxs)("label", { className: "inline-flex items-center gap-1", children: [
8317
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8445
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
8446
+ /* @__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: [
8447
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8318
8448
  "input",
8319
8449
  {
8320
8450
  type: "radio",
@@ -8327,34 +8457,34 @@ var GenerationHistory = ({
8327
8457
  ),
8328
8458
  value === "exact" ? "Exact (recorded versions)" : "Latest templates & settings"
8329
8459
  ] }, value)) }),
8330
- records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
8331
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
8460
+ records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
8461
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
8332
8462
  const result = results[i];
8333
8463
  const model = models.find((m) => m.id === record.provenance.modelId);
8334
8464
  const blocked = !result.ok;
8335
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8465
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
8336
8466
  "li",
8337
8467
  {
8338
8468
  className: "rounded-md border border-border p-2",
8339
8469
  "data-record": record.id,
8340
8470
  "data-drift": result.drift.length,
8341
8471
  children: [
8342
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
8343
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
8344
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "text-muted-foreground", children: [
8345
- record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { "data-kind": "", children: [
8472
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
8473
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
8474
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "text-muted-foreground", children: [
8475
+ record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { "data-kind": "", children: [
8346
8476
  record.kind,
8347
8477
  " \xB7 "
8348
8478
  ] }),
8349
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
8350
- record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
8479
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
8480
+ record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
8351
8481
  " \xB7 seed ",
8352
8482
  record.seed
8353
8483
  ] })
8354
8484
  ] })
8355
8485
  ] }),
8356
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
8357
- record.assets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "mt-1 flex flex-wrap gap-1", children: record.assets.map((asset) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8486
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
8487
+ 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)(
8358
8488
  "span",
8359
8489
  {
8360
8490
  className: "rounded-full bg-muted px-2 py-0.5 text-[10px]",
@@ -8368,16 +8498,16 @@ var GenerationHistory = ({
8368
8498
  `${asset.role}:${asset.id}`
8369
8499
  )) }),
8370
8500
  renderPreview?.(record),
8371
- result.drift.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime39.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_runtime39.jsxs)("li", { className: severityClass[item.severity], "data-drift-type": item.type, children: [
8372
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("strong", { children: [
8501
+ 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: [
8502
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("strong", { children: [
8373
8503
  import_generation4.DRIFT_TYPE_LABELS[item.type],
8374
8504
  ":"
8375
8505
  ] }),
8376
8506
  " ",
8377
8507
  item.message
8378
8508
  ] }, j)) }),
8379
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "mt-2 flex gap-2", children: [
8380
- onRecreate && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8509
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "mt-2 flex gap-2", children: [
8510
+ onRecreate && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8381
8511
  "button",
8382
8512
  {
8383
8513
  type: "button",
@@ -8389,7 +8519,7 @@ var GenerationHistory = ({
8389
8519
  children: "Recreate"
8390
8520
  }
8391
8521
  ),
8392
- onVariation && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8522
+ onVariation && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8393
8523
  "button",
8394
8524
  {
8395
8525
  type: "button",
@@ -8399,7 +8529,7 @@ var GenerationHistory = ({
8399
8529
  children: "Variation"
8400
8530
  }
8401
8531
  ),
8402
- onRemove && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8532
+ onRemove && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8403
8533
  "button",
8404
8534
  {
8405
8535
  type: "button",
@@ -8419,19 +8549,19 @@ var GenerationHistory = ({
8419
8549
  };
8420
8550
 
8421
8551
  // src/find-replace/useFindReplace.ts
8422
- var import_react58 = require("react");
8552
+ var import_react59 = require("react");
8423
8553
  var import_editor16 = require("@pixerate/editor");
8424
8554
  var noopUnsubscribe2 = () => {
8425
8555
  };
8426
8556
  function useFindReplace(editor) {
8427
8557
  const store = (0, import_editor16.getFindReplaceStore)(editor ?? null);
8428
- const subscribe = (0, import_react58.useCallback)(
8558
+ const subscribe = (0, import_react59.useCallback)(
8429
8559
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe2,
8430
8560
  [store]
8431
8561
  );
8432
8562
  const getSnapshot = () => store?.getSnapshot() ?? import_editor16.EMPTY_FIND_REPLACE_SNAPSHOT;
8433
- const snapshot = (0, import_react58.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
8434
- return (0, import_react58.useMemo)(() => {
8563
+ const snapshot = (0, import_react59.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
8564
+ return (0, import_react59.useMemo)(() => {
8435
8565
  const run = (fn) => {
8436
8566
  if (editor && !editor.isDestroyed && store) fn(editor);
8437
8567
  };
@@ -8455,9 +8585,9 @@ function useFindReplace(editor) {
8455
8585
  }
8456
8586
 
8457
8587
  // src/find-replace/FindReplaceBar.tsx
8458
- var import_react59 = require("react");
8588
+ var import_react60 = require("react");
8459
8589
  var import_editor17 = require("@pixerate/editor");
8460
- var import_jsx_runtime40 = require("react/jsx-runtime");
8590
+ var import_jsx_runtime41 = require("react/jsx-runtime");
8461
8591
  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";
8462
8592
  var buttonClass5 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
8463
8593
  var toggleClass = (on) => `${buttonClass5} font-mono ${on ? "bg-primary/10 text-primary" : "text-muted-foreground"}`;
@@ -8470,10 +8600,10 @@ var FindReplaceBar = ({
8470
8600
  onClose
8471
8601
  }) => {
8472
8602
  const find = useFindReplace(editor);
8473
- const findInput = (0, import_react59.useRef)(null);
8474
- const [moreOpen, setMoreOpen] = (0, import_react59.useState)(false);
8603
+ const findInput = (0, import_react60.useRef)(null);
8604
+ const [moreOpen, setMoreOpen] = (0, import_react60.useState)(false);
8475
8605
  const visible = find.available && (alwaysOpen || find.open);
8476
- (0, import_react59.useEffect)(() => {
8606
+ (0, import_react60.useEffect)(() => {
8477
8607
  if (!visible || find.focusRequest === 0) return;
8478
8608
  findInput.current?.focus();
8479
8609
  findInput.current?.select();
@@ -8511,9 +8641,9 @@ var FindReplaceBar = ({
8511
8641
  if (isMod(e)) find.replaceAll();
8512
8642
  else find.replace();
8513
8643
  };
8514
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
8515
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex items-center gap-1", children: [
8516
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8644
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
8645
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-1", children: [
8646
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8517
8647
  "button",
8518
8648
  {
8519
8649
  type: "button",
@@ -8524,7 +8654,7 @@ var FindReplaceBar = ({
8524
8654
  children: showReplace ? "\u25BE" : "\u25B8"
8525
8655
  }
8526
8656
  ),
8527
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8657
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8528
8658
  "input",
8529
8659
  {
8530
8660
  ref: findInput,
@@ -8538,7 +8668,7 @@ var FindReplaceBar = ({
8538
8668
  onKeyDown: onFindKeyDown
8539
8669
  }
8540
8670
  ),
8541
- import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8671
+ import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8542
8672
  "button",
8543
8673
  {
8544
8674
  type: "button",
@@ -8551,7 +8681,7 @@ var FindReplaceBar = ({
8551
8681
  },
8552
8682
  t.key
8553
8683
  )),
8554
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8684
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8555
8685
  "span",
8556
8686
  {
8557
8687
  className: `min-w-[5rem] px-1 text-center text-xs ${find.error ? "text-destructive" : "text-muted-foreground"}`,
@@ -8561,9 +8691,9 @@ var FindReplaceBar = ({
8561
8691
  children: status
8562
8692
  }
8563
8693
  ),
8564
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
8565
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
8566
- showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8694
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
8695
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
8696
+ showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8567
8697
  "button",
8568
8698
  {
8569
8699
  type: "button",
@@ -8574,10 +8704,10 @@ var FindReplaceBar = ({
8574
8704
  children: "\u2026"
8575
8705
  }
8576
8706
  ),
8577
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
8707
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
8578
8708
  ] }),
8579
- showReplace && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
8580
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8709
+ showReplace && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
8710
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8581
8711
  "input",
8582
8712
  {
8583
8713
  type: "text",
@@ -8589,7 +8719,7 @@ var FindReplaceBar = ({
8589
8719
  onKeyDown: onReplaceKeyDown
8590
8720
  }
8591
8721
  ),
8592
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8722
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8593
8723
  "button",
8594
8724
  {
8595
8725
  type: "button",
@@ -8599,11 +8729,11 @@ var FindReplaceBar = ({
8599
8729
  children: "Replace"
8600
8730
  }
8601
8731
  ),
8602
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
8603
- find.lastReplaceCount !== null && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "px-1 text-xs text-muted-foreground", "aria-live": "polite", children: find.lastReplaceCount === 1 ? "1 replaced" : `${find.lastReplaceCount} replaced` })
8732
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
8733
+ 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` })
8604
8734
  ] }),
8605
- showMoreOptions && moreOpen && /* @__PURE__ */ (0, import_jsx_runtime40.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_runtime40.jsxs)("label", { className: "flex items-center gap-1", children: [
8606
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8735
+ 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: [
8736
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8607
8737
  "input",
8608
8738
  {
8609
8739
  type: "checkbox",
@@ -8617,12 +8747,12 @@ var FindReplaceBar = ({
8617
8747
  };
8618
8748
 
8619
8749
  // src/tables/useTableMenu.ts
8620
- var import_react60 = require("react");
8750
+ var import_react61 = require("react");
8621
8751
  var import_editor18 = require("@pixerate/editor");
8622
8752
  function useTableMenu(editor) {
8623
- const store = (0, import_react60.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
8624
- const snapshot = (0, import_react60.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
8625
- return (0, import_react60.useMemo)(
8753
+ const store = (0, import_react61.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
8754
+ const snapshot = (0, import_react61.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
8755
+ return (0, import_react61.useMemo)(
8626
8756
  () => ({
8627
8757
  ...snapshot,
8628
8758
  run: (action, params) => (0, import_editor18.runTableAction)(editor, action, params, { focus: true }),
@@ -8633,9 +8763,9 @@ function useTableMenu(editor) {
8633
8763
  }
8634
8764
 
8635
8765
  // src/tables/TableToolbar.tsx
8636
- var import_react61 = __toESM(require("react"), 1);
8766
+ var import_react62 = __toESM(require("react"), 1);
8637
8767
  var import_editor19 = require("@pixerate/editor");
8638
- var import_jsx_runtime41 = require("react/jsx-runtime");
8768
+ var import_jsx_runtime42 = require("react/jsx-runtime");
8639
8769
  var keepSelection2 = (event) => event.preventDefault();
8640
8770
  var TableToolbar = ({
8641
8771
  editor,
@@ -8649,14 +8779,14 @@ var TableToolbar = ({
8649
8779
  }) => {
8650
8780
  const table = useTableMenu(editor);
8651
8781
  if (!editor || !table.inTable && !showWhenOutside) return null;
8652
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
8782
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
8653
8783
  const status = table.check(item.action, item.params);
8654
8784
  const enabled = status === true;
8655
8785
  const active = item.active?.(table);
8656
8786
  const separator = index > 0 && items[index - 1].group !== item.group;
8657
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_react61.default.Fragment, { children: [
8658
- separator && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
8659
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8787
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react62.default.Fragment, { children: [
8788
+ separator && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
8789
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8660
8790
  "button",
8661
8791
  {
8662
8792
  type: "button",
@@ -8678,8 +8808,8 @@ var TableToolbar = ({
8678
8808
  };
8679
8809
 
8680
8810
  // src/tables/InsertTableGrid.tsx
8681
- var import_react62 = require("react");
8682
- var import_jsx_runtime42 = require("react/jsx-runtime");
8811
+ var import_react63 = require("react");
8812
+ var import_jsx_runtime43 = require("react/jsx-runtime");
8683
8813
  var keepSelection3 = (event) => event.preventDefault();
8684
8814
  var InsertTableGrid = ({
8685
8815
  editor,
@@ -8692,14 +8822,14 @@ var InsertTableGrid = ({
8692
8822
  onInsert
8693
8823
  }) => {
8694
8824
  const table = useTableMenu(editor);
8695
- const [hover, setHover] = (0, import_react62.useState)(null);
8825
+ const [hover, setHover] = (0, import_react63.useState)(null);
8696
8826
  const status = table.actions.insertTable;
8697
8827
  const disabled = !editor || !status.enabled;
8698
8828
  const insert = (size) => {
8699
8829
  if (table.run("insertTable", { ...size, withHeaderRow })) onInsert?.(size);
8700
8830
  setHover(null);
8701
8831
  };
8702
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
8832
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
8703
8833
  "div",
8704
8834
  {
8705
8835
  className,
@@ -8709,7 +8839,7 @@ var InsertTableGrid = ({
8709
8839
  "data-insert-table-grid": "",
8710
8840
  onMouseLeave: () => setHover(null),
8711
8841
  children: [
8712
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8842
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8713
8843
  "div",
8714
8844
  {
8715
8845
  role: "grid",
@@ -8718,7 +8848,7 @@ var InsertTableGrid = ({
8718
8848
  children: Array.from({ length: rows * cols }, (_, i) => {
8719
8849
  const size = { rows: Math.floor(i / cols) + 1, cols: i % cols + 1 };
8720
8850
  const active = !!hover && size.rows <= hover.rows && size.cols <= hover.cols;
8721
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8851
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8722
8852
  "button",
8723
8853
  {
8724
8854
  type: "button",
@@ -8738,7 +8868,7 @@ var InsertTableGrid = ({
8738
8868
  })
8739
8869
  }
8740
8870
  ),
8741
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { "aria-live": "polite", "data-testid": "insert-table-size", children: disabled ? status.reason : hover ? `${hover.rows} \xD7 ${hover.cols}` : "Insert table" })
8871
+ /* @__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" })
8742
8872
  ]
8743
8873
  }
8744
8874
  );
@@ -8746,31 +8876,31 @@ var InsertTableGrid = ({
8746
8876
 
8747
8877
  // src/tables/TableBubbleMenu.tsx
8748
8878
  var import_editor20 = require("@pixerate/editor");
8749
- var import_jsx_runtime43 = require("react/jsx-runtime");
8879
+ var import_jsx_runtime44 = require("react/jsx-runtime");
8750
8880
  var TableBubbleMenu = ({
8751
8881
  editor,
8752
8882
  children,
8753
8883
  toolbarProps,
8754
8884
  pluginKey = "tableBubbleMenu",
8755
8885
  ...rest
8756
- }) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(BubbleMenu, { editor, pluginKey, shouldShow: import_editor20.shouldShowTableBubbleMenu, ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(TableToolbar, { editor, ...toolbarProps }) });
8886
+ }) => /* @__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 }) });
8757
8887
 
8758
8888
  // src/chart-node/ChartNodeView.tsx
8759
8889
  var import_client = require("react-dom/client");
8760
8890
 
8761
8891
  // src/chart/ChartCanvas.tsx
8762
- var import_react64 = require("react");
8892
+ var import_react65 = require("react");
8763
8893
  var import_chart2 = require("@pixerate/editor/chart");
8764
8894
 
8765
8895
  // src/chart/useChartEditor.ts
8766
- var import_react63 = require("react");
8896
+ var import_react64 = require("react");
8767
8897
  var import_chart = require("@pixerate/editor/chart");
8768
8898
  function useChartState(controller) {
8769
- return (0, import_react63.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
8899
+ return (0, import_react64.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
8770
8900
  }
8771
8901
 
8772
8902
  // src/chart/ChartCanvas.tsx
8773
- var import_jsx_runtime44 = require("react/jsx-runtime");
8903
+ var import_jsx_runtime45 = require("react/jsx-runtime");
8774
8904
  function renderChartMark(mark, fontFamily, interactive) {
8775
8905
  const common = {
8776
8906
  "data-role": mark.role,
@@ -8782,9 +8912,9 @@ function renderChartMark(mark, fontFamily, interactive) {
8782
8912
  };
8783
8913
  switch (mark.kind) {
8784
8914
  case "rect":
8785
- return /* @__PURE__ */ (0, import_jsx_runtime44.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);
8915
+ 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);
8786
8916
  case "path":
8787
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8917
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
8788
8918
  "path",
8789
8919
  {
8790
8920
  ...common,
@@ -8797,11 +8927,11 @@ function renderChartMark(mark, fontFamily, interactive) {
8797
8927
  mark.key
8798
8928
  );
8799
8929
  case "circle":
8800
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("circle", { ...common, cx: mark.cx, cy: mark.cy, r: mark.r, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
8930
+ 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);
8801
8931
  case "line":
8802
- return /* @__PURE__ */ (0, import_jsx_runtime44.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);
8932
+ 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);
8803
8933
  case "text":
8804
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8934
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
8805
8935
  "text",
8806
8936
  {
8807
8937
  ...common,
@@ -8818,23 +8948,23 @@ function renderChartMark(mark, fontFamily, interactive) {
8818
8948
  }
8819
8949
  }
8820
8950
  function ChartPresenceLayer({ presence }) {
8821
- const { actors } = (0, import_react64.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
8822
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("g", { "data-chart-presence": "", pointerEvents: "none", children: actors.map((a) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("g", { transform: `translate(${a.x} ${a.y})`, "data-actor": a.id, children: [
8823
- /* @__PURE__ */ (0, import_jsx_runtime44.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 }),
8824
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("g", { transform: "translate(13 16)", children: [
8825
- /* @__PURE__ */ (0, import_jsx_runtime44.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 } }),
8826
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("text", { x: 6, y: 9, dominantBaseline: "central", style: { fill: "#ffffff", fontSize: 11, fontWeight: 600, fontFamily: "inherit" }, children: a.message ?? a.name })
8951
+ const { actors } = (0, import_react65.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
8952
+ 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: [
8953
+ /* @__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 }),
8954
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("g", { transform: "translate(13 16)", children: [
8955
+ /* @__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 } }),
8956
+ /* @__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 })
8827
8957
  ] })
8828
8958
  ] }, a.id)) });
8829
8959
  }
8830
8960
  function ChartCanvas({ controller, width = 640, height = 400, responsive = true, theme, editable = true, measureText, emptyMessage, className, presence, sceneRef }) {
8831
8961
  const state = useChartState(controller);
8832
- const wrapper = (0, import_react64.useRef)(null);
8833
- const svg = (0, import_react64.useRef)(null);
8834
- const drag = (0, import_react64.useRef)(null);
8835
- const [measured, setMeasured] = (0, import_react64.useState)(null);
8836
- const [frozen, setFrozen] = (0, import_react64.useState)(null);
8837
- (0, import_react64.useEffect)(() => {
8962
+ const wrapper = (0, import_react65.useRef)(null);
8963
+ const svg = (0, import_react65.useRef)(null);
8964
+ const drag = (0, import_react65.useRef)(null);
8965
+ const [measured, setMeasured] = (0, import_react65.useState)(null);
8966
+ const [frozen, setFrozen] = (0, import_react65.useState)(null);
8967
+ (0, import_react65.useEffect)(() => {
8838
8968
  const el = wrapper.current;
8839
8969
  if (!responsive || !el || typeof ResizeObserver === "undefined") return;
8840
8970
  const observer = new ResizeObserver(([entry]) => {
@@ -8845,8 +8975,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8845
8975
  return () => observer.disconnect();
8846
8976
  }, [responsive]);
8847
8977
  const sceneWidth = responsive && measured || width;
8848
- const fullTheme = (0, import_react64.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
8849
- const scene = (0, import_react64.useMemo)(
8978
+ const fullTheme = (0, import_react65.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
8979
+ const scene = (0, import_react65.useMemo)(
8850
8980
  () => (0, import_chart2.layoutChart)(state.spec, {
8851
8981
  width: sceneWidth,
8852
8982
  height,
@@ -8862,8 +8992,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8862
8992
  [state.spec, state.selection, sceneWidth, height, fullTheme, editable, measureText, emptyMessage, frozen]
8863
8993
  );
8864
8994
  if (sceneRef) sceneRef.current = scene;
8865
- const byKey = (0, import_react64.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
8866
- (0, import_react64.useEffect)(() => () => drag.current?.end(), []);
8995
+ const byKey = (0, import_react65.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
8996
+ (0, import_react65.useEffect)(() => () => drag.current?.end(), []);
8867
8997
  const scenePoint = (e) => (0, import_chart2.chartClientToScene)(scene, svg.current.getBoundingClientRect(), e.clientX, e.clientY);
8868
8998
  const onPointerDown = (e) => {
8869
8999
  if (!editable || e.button !== 0) return;
@@ -8896,7 +9026,7 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8896
9026
  if (editable && (0, import_chart2.handleChartKey)(controller, scene, e)) e.preventDefault();
8897
9027
  };
8898
9028
  const label = state.spec.title || "Chart";
8899
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { ref: wrapper, className: `w-full ${className ?? ""}`, "data-chart-canvas": "", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
9029
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { ref: wrapper, className: `w-full ${className ?? ""}`, "data-chart-canvas": "", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
8900
9030
  "svg",
8901
9031
  {
8902
9032
  ref: svg,
@@ -8914,14 +9044,14 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8914
9044
  onKeyDown,
8915
9045
  children: [
8916
9046
  scene.marks.map((m) => renderChartMark(m, scene.theme.fontFamily, editable)),
8917
- presence && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartPresenceLayer, { presence })
9047
+ presence && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartPresenceLayer, { presence })
8918
9048
  ]
8919
9049
  }
8920
9050
  ) });
8921
9051
  }
8922
9052
 
8923
9053
  // src/chart/ChartDataGrid.tsx
8924
- var import_react65 = require("react");
9054
+ var import_react66 = require("react");
8925
9055
  var import_chart3 = require("@pixerate/editor/chart");
8926
9056
 
8927
9057
  // src/chart/styles.ts
@@ -8934,11 +9064,11 @@ var chartSectionClass = "space-y-2 border-b border-border pb-3 last:border-b-0";
8934
9064
  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";
8935
9065
 
8936
9066
  // src/chart/ChartDataGrid.tsx
8937
- var import_jsx_runtime45 = require("react/jsx-runtime");
9067
+ var import_jsx_runtime46 = require("react/jsx-runtime");
8938
9068
  function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
8939
- const [draft, setDraft] = (0, import_react65.useState)(value);
8940
- const typing = (0, import_react65.useRef)(false);
8941
- (0, import_react65.useEffect)(() => {
9069
+ const [draft, setDraft] = (0, import_react66.useState)(value);
9070
+ const typing = (0, import_react66.useRef)(false);
9071
+ (0, import_react66.useEffect)(() => {
8942
9072
  if (!typing.current) setDraft(value);
8943
9073
  }, [value]);
8944
9074
  const commit = () => {
@@ -8947,7 +9077,7 @@ function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
8947
9077
  if (draft === value) return;
8948
9078
  if (onCommit(draft) === false) setDraft(value);
8949
9079
  };
8950
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9080
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
8951
9081
  "input",
8952
9082
  {
8953
9083
  ...rest,
@@ -8982,15 +9112,15 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8982
9112
  e.preventDefault();
8983
9113
  controller.pasteCells(row, column, text);
8984
9114
  };
8985
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
8986
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
8987
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("tr", { children: [
8988
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("th", { className: "border-b border-r border-border px-2 py-1 text-left font-medium text-muted-foreground", children: categoryHeader }),
9115
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
9116
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
9117
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("tr", { children: [
9118
+ /* @__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 }),
8989
9119
  spec.series.map((s, si) => {
8990
9120
  const color = (0, import_chart3.chartSeriesColor)(spec, si);
8991
9121
  const selected = selection?.kind === "series" && selection.seriesId === s.id;
8992
- return /* @__PURE__ */ (0, import_jsx_runtime45.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_runtime45.jsxs)("div", { className: "flex items-center gap-1", children: [
8993
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9122
+ 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: [
9123
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
8994
9124
  "input",
8995
9125
  {
8996
9126
  type: "color",
@@ -9003,7 +9133,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9003
9133
  className: "h-5 w-5 shrink-0 cursor-pointer rounded border-0 bg-transparent p-0"
9004
9134
  }
9005
9135
  ),
9006
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9136
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9007
9137
  ChartCommitInput,
9008
9138
  {
9009
9139
  value: s.name,
@@ -9013,8 +9143,8 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9013
9143
  className: `${chartInputClass} h-6 min-w-[5rem] border-transparent bg-transparent font-medium ${s.hidden ? "text-muted-foreground line-through" : ""}`
9014
9144
  }
9015
9145
  ),
9016
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
9017
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9146
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
9147
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9018
9148
  "button",
9019
9149
  {
9020
9150
  type: "button",
@@ -9027,16 +9157,16 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9027
9157
  children: s.hidden ? "\u25CB" : "\u25CF"
9028
9158
  }
9029
9159
  ),
9030
- /* @__PURE__ */ (0, import_jsx_runtime45.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" })
9160
+ /* @__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" })
9031
9161
  ] })
9032
9162
  ] }) }, s.id);
9033
9163
  }),
9034
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("th", { className: "w-8 border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Add series", "aria-label": "Add series", "data-action": "add-series", onClick: () => controller.addSeries(), children: "+" }) })
9164
+ !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: "+" }) })
9035
9165
  ] }) }),
9036
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("tbody", { children: spec.categories.map((category, i) => {
9166
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("tbody", { children: spec.categories.map((category, i) => {
9037
9167
  const rowSelected = selection?.kind === "category" && selection.index === i;
9038
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
9039
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("th", { className: "border-b border-r border-border p-0 text-left font-normal", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9168
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
9169
+ /* @__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)(
9040
9170
  ChartCommitInput,
9041
9171
  {
9042
9172
  value: category,
@@ -9050,7 +9180,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9050
9180
  spec.series.map((s) => {
9051
9181
  const value = s.values[i];
9052
9182
  const selected = selection?.kind === "point" && selection.seriesId === s.id && selection.index === i;
9053
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("td", { className: `border-b border-r border-border p-0 ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9183
+ 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)(
9054
9184
  ChartCommitInput,
9055
9185
  {
9056
9186
  value: value === null || value === void 0 ? "" : String(value),
@@ -9065,38 +9195,38 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9065
9195
  }
9066
9196
  ) }, s.id);
9067
9197
  }),
9068
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("td", { className: "border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete category", "aria-label": `Delete ${category}`, "data-action": "remove-category", onClick: () => controller.removeCategory(i), children: "\xD7" }) })
9198
+ !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" }) })
9069
9199
  ] }, i);
9070
9200
  }) })
9071
9201
  ] }),
9072
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "p-1", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("button", { type: "button", className: `${chartButtonClass} h-6 border-dashed`, "data-action": "add-category", onClick: () => controller.addCategory(), children: "+ Add category" }) })
9202
+ !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" }) })
9073
9203
  ] });
9074
9204
  }
9075
9205
 
9076
9206
  // src/chart/ChartInspector.tsx
9077
- var import_react66 = require("react");
9207
+ var import_react67 = require("react");
9078
9208
  var import_chart4 = require("@pixerate/editor/chart");
9079
- var import_jsx_runtime46 = require("react/jsx-runtime");
9209
+ var import_jsx_runtime47 = require("react/jsx-runtime");
9080
9210
  var cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
9081
9211
  function Field({ label, htmlFor, children }) {
9082
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-2", children: [
9083
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
9084
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "min-w-0 flex-1", children })
9212
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
9213
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
9214
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "min-w-0 flex-1", children })
9085
9215
  ] });
9086
9216
  }
9087
9217
  function Toggle({ label, checked, onChange, name }) {
9088
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
9089
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("input", { type: "checkbox", className: "h-3.5 w-3.5 accent-primary", checked, "data-option": name, onChange: (e) => onChange(e.currentTarget.checked) }),
9218
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
9219
+ /* @__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) }),
9090
9220
  label
9091
9221
  ] });
9092
9222
  }
9093
9223
  function Select({ id, value, options, onChange, name, labels }) {
9094
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("select", { id, className: chartInputClass, value, "data-option": name, onChange: (e) => onChange(e.currentTarget.value), children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: o, children: labels?.[o] ?? cap(o) }, o)) });
9224
+ 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)) });
9095
9225
  }
9096
9226
  function AxisSection({ controller, axis, value, idBase, horizontal, numeric = false, scales = false }) {
9097
9227
  const set = (patch) => controller.setAxis(axis, patch);
9098
9228
  const setFormat = (patch) => set({ format: { ...value.format, ...patch } });
9099
- const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9229
+ const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9100
9230
  ChartCommitInput,
9101
9231
  {
9102
9232
  id: `${idBase}-${axis}-${key2}`,
@@ -9111,26 +9241,26 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9111
9241
  const name = axis === "x" ? numeric ? "X axis" : "Category axis" : axis === "y" ? "Value axis" : "Secondary axis";
9112
9242
  const valueAxis = axis !== "x" || numeric;
9113
9243
  const key = axis === "y2" ? "yAxis2" : `${axis}Axis`;
9114
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
9115
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center justify-between", children: [
9116
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
9244
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
9245
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center justify-between", children: [
9246
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
9117
9247
  name,
9118
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
9248
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
9119
9249
  "(",
9120
9250
  axis === "x" ? horizontal ? "left" : "bottom" : axis === "y2" ? horizontal ? "top" : "right" : horizontal ? "bottom" : "left",
9121
9251
  ")"
9122
9252
  ] })
9123
9253
  ] }),
9124
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
9254
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
9125
9255
  ] }),
9126
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Title", htmlFor: `${idBase}-${axis}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-title`, value: value.title, "data-option": `${axis}Axis.title`, className: chartInputClass, onCommit: (title) => void set({ title }) }) }),
9127
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9128
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
9129
- axis === "x" && !numeric && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Dates", name: "xAxis.kind", checked: value.kind === "date", onChange: (dates) => set({ kind: dates ? "date" : void 0 }) }),
9130
- scales && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
9131
- scales && valueAxis && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Log scale", name: `${key}.scale`, checked: value.scale === "log", onChange: (log) => set({ scale: log ? "log" : "linear" }) })
9256
+ /* @__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 }) }) }),
9257
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9258
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
9259
+ 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 }) }),
9260
+ scales && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
9261
+ 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" }) })
9132
9262
  ] }),
9133
- scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Log base", htmlFor: `${idBase}-${axis}-log-base`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9263
+ 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)(
9134
9264
  ChartCommitInput,
9135
9265
  {
9136
9266
  id: `${idBase}-${axis}-log-base`,
@@ -9141,7 +9271,7 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9141
9271
  onCommit: (text) => set({ logBase: text.trim() === "" ? void 0 : Number(text) }).ok
9142
9272
  }
9143
9273
  ) }),
9144
- valueAxis && value.scale !== "log" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Step", htmlFor: `${idBase}-${axis}-step`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9274
+ valueAxis && value.scale !== "log" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Step", htmlFor: `${idBase}-${axis}-step`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9145
9275
  ChartCommitInput,
9146
9276
  {
9147
9277
  id: `${idBase}-${axis}-step`,
@@ -9153,14 +9283,14 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9153
9283
  onCommit: (text) => set({ step: text.trim() === "" ? null : Number(text) }).ok
9154
9284
  }
9155
9285
  ) }),
9156
- valueAxis && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
9157
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex gap-1", children: [
9286
+ valueAxis && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
9287
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex gap-1", children: [
9158
9288
  bound("min"),
9159
9289
  bound("max")
9160
9290
  ] }) }),
9161
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Format", htmlFor: `${idBase}-${axis}-format`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex gap-1", children: [
9162
- /* @__PURE__ */ (0, import_jsx_runtime46.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 }) }),
9163
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9291
+ /* @__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: [
9292
+ /* @__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 }) }),
9293
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9164
9294
  ChartCommitInput,
9165
9295
  {
9166
9296
  value: value.format.decimals === void 0 ? "" : String(value.format.decimals),
@@ -9179,8 +9309,8 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9179
9309
  }
9180
9310
  )
9181
9311
  ] }) }),
9182
- value.format.style === "currency" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Currency", htmlFor: `${idBase}-${axis}-currency`, children: /* @__PURE__ */ (0, import_jsx_runtime46.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() }) }) }),
9183
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9312
+ 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() }) }) }),
9313
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9184
9314
  ChartCommitInput,
9185
9315
  {
9186
9316
  id: `${idBase}-${axis}-code`,
@@ -9206,15 +9336,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
9206
9336
  const values = which === "xErrorBars" ? series.x ?? [] : series.values;
9207
9337
  const set = (next) => controller.updateSeries(series.id, { [which]: next });
9208
9338
  const patch = (p) => bars && set({ ...bars, ...p });
9209
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
9210
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: which === "errorBars" ? "Error bars" : "X error bars", htmlFor: `${id}-type`, children: /* @__PURE__ */ (0, import_jsx_runtime46.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: [
9211
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "None" }),
9212
- import_chart4.CHART_ERROR_BAR_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: t, children: import_chart4.CHART_ERROR_BAR_LABELS[t] }, t))
9339
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
9340
+ /* @__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: [
9341
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "None" }),
9342
+ 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))
9213
9343
  ] }) }),
9214
- bars && (bars.type === "fixed" || bars.type === "percent" || bars.type === "stddev") && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: bars.type === "percent" ? "Percent" : bars.type === "stddev" ? "Deviations" : "Amount", htmlFor: `${id}-value`, children: /* @__PURE__ */ (0, import_jsx_runtime46.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 }) }),
9215
- bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
9216
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Plus", htmlFor: `${id}-plus`, children: /* @__PURE__ */ (0, import_jsx_runtime46.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 }) }),
9217
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9344
+ 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 }) }),
9345
+ bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
9346
+ /* @__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 }) }),
9347
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9218
9348
  ChartCommitInput,
9219
9349
  {
9220
9350
  id: `${id}-minus`,
@@ -9231,15 +9361,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
9231
9361
  }
9232
9362
  ) })
9233
9363
  ] }),
9234
- bars && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-2", children: [
9235
- /* @__PURE__ */ (0, import_jsx_runtime46.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_runtime46.jsx)("option", { value: d, children: d === "both" ? "Both ways" : d === "plus" ? "Plus only" : "Minus only" }, d)) }),
9236
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
9364
+ bars && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
9365
+ /* @__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)) }),
9366
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
9237
9367
  ] })
9238
9368
  ] });
9239
9369
  }
9240
9370
  function ChartInspector({ controller, sections, className }) {
9241
9371
  const { spec, selectedSeries } = useChartState(controller);
9242
- const idBase = (0, import_react66.useId)();
9372
+ const idBase = (0, import_react67.useId)();
9243
9373
  const show = (section) => !sections || sections.includes(section);
9244
9374
  const cartesian = (0, import_chart4.isCartesianChart)(spec.type);
9245
9375
  const family = (0, import_chart4.chartFamily)(spec);
@@ -9251,29 +9381,29 @@ function ChartInspector({ controller, sections, className }) {
9251
9381
  const hasLines = cartesian && types.some((t) => t === "line" || t === "area");
9252
9382
  const seriesIndex = selectedSeries ? spec.series.findIndex((s) => s.id === selectedSeries.id) : -1;
9253
9383
  const scales = family === "cartesian" || family === "xy";
9254
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
9255
- show("type") && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: chartSectionClass, "data-section": "type", children: /* @__PURE__ */ (0, import_jsx_runtime46.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_runtime46.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)) }) }),
9256
- show("style") && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
9257
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Layout", htmlFor: `${idBase}-layout`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("select", { id: `${idBase}-layout`, className: chartInputClass, value: "", "data-option": "preset.layout", onChange: (e) => e.currentTarget.value && controller.applyPreset({ layout: e.currentTarget.value }), children: [
9258
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "Quick layout\u2026" }),
9259
- import_chart4.CHART_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: p.id, title: p.description, children: p.label }, p.id))
9384
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
9385
+ 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)) }) }),
9386
+ show("style") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
9387
+ /* @__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: [
9388
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Quick layout\u2026" }),
9389
+ 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))
9260
9390
  ] }) }),
9261
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Colours", htmlFor: `${idBase}-colors`, children: /* @__PURE__ */ (0, import_jsx_runtime46.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: [
9262
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "Custom" }),
9263
- import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: c.id, title: c.description, children: c.label }, c.id))
9391
+ /* @__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: [
9392
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Custom" }),
9393
+ 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))
9264
9394
  ] }) }),
9265
- !colorCheck.ok && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-[11px] leading-snug text-amber-600 dark:text-amber-400", "data-chart-color-warning": "", children: colorCheck.issues[0] }),
9266
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
9395
+ !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] }),
9396
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
9267
9397
  ] }),
9268
- show("titles") && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
9269
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Title", htmlFor: `${idBase}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ChartCommitInput, { id: `${idBase}-title`, value: spec.title, "data-option": "title", className: chartInputClass, onCommit: (title) => void controller.setTitle(title) }) }),
9270
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Subtitle", htmlFor: `${idBase}-subtitle`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ChartCommitInput, { id: `${idBase}-subtitle`, value: spec.subtitle, "data-option": "subtitle", className: chartInputClass, onCommit: (subtitle) => void controller.setSubtitle(subtitle) }) })
9398
+ show("titles") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
9399
+ /* @__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) }) }),
9400
+ /* @__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) }) })
9271
9401
  ] }),
9272
- show("options") && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
9273
- cartesian && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Stacking", htmlFor: `${idBase}-stacking`, children: /* @__PURE__ */ (0, import_jsx_runtime46.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 }) }) }),
9274
- hasBars && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Bars", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: ["vertical", "horizontal"].map((o) => /* @__PURE__ */ (0, import_jsx_runtime46.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)) }) }),
9275
- hasLines && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Lines", htmlFor: `${idBase}-curve`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Select, { id: `${idBase}-curve`, name: "curve", value: spec.curve, options: import_chart4.CHART_CURVES, onChange: (curve) => controller.update({ curve }) }) }),
9276
- spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9402
+ show("options") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
9403
+ 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 }) }) }),
9404
+ 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)) }) }),
9405
+ 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 }) }) }),
9406
+ spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9277
9407
  "input",
9278
9408
  {
9279
9409
  id: `${idBase}-hole`,
@@ -9289,7 +9419,7 @@ function ChartInspector({ controller, sections, className }) {
9289
9419
  onChange: (e) => controller.update({ innerRadius: Number(e.currentTarget.value) })
9290
9420
  }
9291
9421
  ) }),
9292
- hasBars && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9422
+ hasBars && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9293
9423
  "input",
9294
9424
  {
9295
9425
  id: `${idBase}-gap`,
@@ -9305,31 +9435,31 @@ function ChartInspector({ controller, sections, className }) {
9305
9435
  onChange: (e) => controller.update({ gapWidth: Number(e.currentTarget.value) })
9306
9436
  }
9307
9437
  ) }),
9308
- spec.dataLabels && hasBars && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Labels", htmlFor: `${idBase}-label-position`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Select, { id: `${idBase}-label-position`, name: "labelPosition", value: spec.labelPosition, options: import_chart4.CHART_LABEL_POSITIONS, onChange: (labelPosition) => controller.update({ labelPosition }) }) }),
9309
- spec.type === "histogram" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Bins", htmlFor: `${idBase}-bins`, children: /* @__PURE__ */ (0, import_jsx_runtime46.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 }) }),
9310
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9311
- spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
9312
- hasLines && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
9313
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
9438
+ 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 }) }) }),
9439
+ 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 }) }),
9440
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9441
+ spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
9442
+ hasLines && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
9443
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
9314
9444
  ] })
9315
9445
  ] }),
9316
- show("legend") && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
9317
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center justify-between", children: [
9318
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
9319
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
9446
+ show("legend") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
9447
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center justify-between", children: [
9448
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
9449
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
9320
9450
  ] }),
9321
- spec.legend.show && /* @__PURE__ */ (0, import_jsx_runtime46.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_runtime46.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)) })
9451
+ 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)) })
9322
9452
  ] }),
9323
- show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
9324
- family !== "box" && family !== "histogram" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(AxisSection, { controller, axis: "x", value: spec.xAxis, idBase, horizontal: spec.orientation === "horizontal", numeric: family === "xy", scales }),
9325
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
9326
- usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
9453
+ show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
9454
+ 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 }),
9455
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
9456
+ usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
9327
9457
  ] }),
9328
- show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
9329
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
9330
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Name", htmlFor: `${idBase}-series-name`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ChartCommitInput, { id: `${idBase}-series-name`, value: selectedSeries.name, "data-option": "series.name", className: chartInputClass, onCommit: (name) => void controller.updateSeries(selectedSeries.id, { name }) }) }),
9331
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Colour", htmlFor: `${idBase}-series-color`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-1", children: [
9332
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9458
+ show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
9459
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
9460
+ /* @__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 }) }) }),
9461
+ /* @__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: [
9462
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9333
9463
  "input",
9334
9464
  {
9335
9465
  id: `${idBase}-series-color`,
@@ -9342,9 +9472,9 @@ function ChartInspector({ controller, sections, className }) {
9342
9472
  onChange: (e) => controller.updateSeries(selectedSeries.id, { color: e.currentTarget.value })
9343
9473
  }
9344
9474
  ),
9345
- selectedSeries.color && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "reset-color", onClick: () => controller.updateSeries(selectedSeries.id, { color: null }), children: "Palette" })
9475
+ 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" })
9346
9476
  ] }) }),
9347
- cartesian && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
9477
+ cartesian && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9348
9478
  "select",
9349
9479
  {
9350
9480
  id: `${idBase}-series-type`,
@@ -9353,12 +9483,12 @@ function ChartInspector({ controller, sections, className }) {
9353
9483
  "data-option": "series.type",
9354
9484
  onChange: (e) => controller.updateSeries(selectedSeries.id, { type: e.currentTarget.value || null }),
9355
9485
  children: [
9356
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "Chart type" }),
9357
- import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: t, children: import_chart4.CHART_TYPE_LABELS[t] }, t))
9486
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Chart type" }),
9487
+ import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: t, children: import_chart4.CHART_TYPE_LABELS[t] }, t))
9358
9488
  ]
9359
9489
  }
9360
9490
  ) }),
9361
- (cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Marker", htmlFor: `${idBase}-series-marker`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
9491
+ (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)(
9362
9492
  "select",
9363
9493
  {
9364
9494
  id: `${idBase}-series-marker`,
@@ -9367,20 +9497,20 @@ function ChartInspector({ controller, sections, className }) {
9367
9497
  "data-option": "series.marker",
9368
9498
  onChange: (e) => controller.updateSeries(selectedSeries.id, { marker: e.currentTarget.value || null }),
9369
9499
  children: [
9370
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "Default" }),
9371
- import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: m, children: cap(m) }, m))
9500
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Default" }),
9501
+ import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: m, children: cap(m) }, m))
9372
9502
  ]
9373
9503
  }
9374
9504
  ) }),
9375
- scales && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
9376
- family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
9377
- (0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
9378
- (selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
9379
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
9380
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "R\xB2", name: `trendline.${i}.showR2`, checked: !!t.showR2, onChange: (showR2) => controller.updateTrendline(selectedSeries.id, i, { showR2 }) }),
9381
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: chartButtonClass, "aria-label": "Delete trendline", "data-action": "trendline-delete", onClick: () => controller.removeTrendline(selectedSeries.id, i), children: "\xD7" })
9505
+ scales && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
9506
+ family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
9507
+ (0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
9508
+ (selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
9509
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
9510
+ /* @__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 }) }),
9511
+ /* @__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" })
9382
9512
  ] }, i)),
9383
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
9513
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9384
9514
  "select",
9385
9515
  {
9386
9516
  className: chartInputClass,
@@ -9389,32 +9519,32 @@ function ChartInspector({ controller, sections, className }) {
9389
9519
  "data-option": "trendline.add",
9390
9520
  onChange: (e) => e.currentTarget.value && controller.addTrendline(selectedSeries.id, { type: e.currentTarget.value }),
9391
9521
  children: [
9392
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "Add trendline\u2026" }),
9393
- import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
9522
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Add trendline\u2026" }),
9523
+ import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
9394
9524
  ]
9395
9525
  }
9396
9526
  )
9397
9527
  ] }),
9398
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
9399
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
9400
- family === "cartesian" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Secondary axis", name: "series.axis", checked: selectedSeries.axis === "secondary", onChange: (secondary) => controller.updateSeries(selectedSeries.id, { axis: secondary ? "secondary" : null }) }),
9401
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "flex-1" }),
9402
- /* @__PURE__ */ (0, import_jsx_runtime46.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" }),
9403
- /* @__PURE__ */ (0, import_jsx_runtime46.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" }),
9404
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: `${chartButtonClass} text-destructive`, "data-action": "series-delete", onClick: () => controller.removeSeries(selectedSeries.id), children: "Delete" })
9528
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
9529
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
9530
+ 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 }) }),
9531
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "flex-1" }),
9532
+ /* @__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" }),
9533
+ /* @__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" }),
9534
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: `${chartButtonClass} text-destructive`, "data-action": "series-delete", onClick: () => controller.removeSeries(selectedSeries.id), children: "Delete" })
9405
9535
  ] })
9406
9536
  ] })
9407
9537
  ] });
9408
9538
  }
9409
9539
 
9410
9540
  // src/chart-node/ChartNodeView.tsx
9411
- var import_jsx_runtime47 = require("react/jsx-runtime");
9541
+ var import_jsx_runtime48 = require("react/jsx-runtime");
9412
9542
  function ChartNodeView({ state, theme, showDataGrid = true }) {
9413
9543
  const { controller, editing, editable, selected, width, height, setEditing } = state;
9414
9544
  const open = () => {
9415
9545
  if (editable && !editing) setEditing(true);
9416
9546
  };
9417
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9547
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
9418
9548
  "div",
9419
9549
  {
9420
9550
  className: `not-prose my-2 rounded-md border bg-background p-1 ${selected ? "border-primary ring-1 ring-primary" : "border-border"}`,
@@ -9427,24 +9557,24 @@ function ChartNodeView({ state, theme, showDataGrid = true }) {
9427
9557
  }
9428
9558
  },
9429
9559
  children: [
9430
- editing && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "mb-1 flex items-center justify-between gap-2 px-1", "data-chart-node-toolbar": "", children: [
9431
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
9432
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
9560
+ 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: [
9561
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
9562
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
9433
9563
  ] }),
9434
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9564
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
9435
9565
  "div",
9436
9566
  {
9437
9567
  className: editable && !editing ? "cursor-pointer" : void 0,
9438
9568
  onClick: open,
9439
9569
  title: editable && !editing ? "Click to edit the chart" : void 0,
9440
9570
  "data-chart-node-canvas": "",
9441
- children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
9571
+ children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
9442
9572
  }
9443
9573
  ),
9444
9574
  editing && // Wraps by the document's width, not the viewport's: side by side when there is room.
9445
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
9446
- showDataGrid && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "min-w-0 flex-[1_1_20rem] overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartDataGrid, { controller }) }),
9447
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartInspector, { controller, className: "max-h-96 min-w-0 flex-[1_1_16rem] overflow-y-auto rounded-md border border-border p-3" })
9575
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
9576
+ 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 }) }),
9577
+ /* @__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" })
9448
9578
  ] })
9449
9579
  ]
9450
9580
  }
@@ -9462,7 +9592,7 @@ function createReactChartNodeView(options = {}) {
9462
9592
  scheduled = true;
9463
9593
  queueMicrotask(() => {
9464
9594
  scheduled = false;
9465
- if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Component, { ...props, state: latest }));
9595
+ if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Component, { ...props, state: latest }));
9466
9596
  });
9467
9597
  };
9468
9598
  schedule();
@@ -9485,6 +9615,7 @@ function createReactChartNodeView(options = {}) {
9485
9615
  BrushOptionsBar,
9486
9616
  BubbleMenu,
9487
9617
  ChartNodeView,
9618
+ ColorProfilePanel,
9488
9619
  CommandPalette,
9489
9620
  CommentButton,
9490
9621
  CommentsPanel,