@pixerate/editor-react 0.72.0 → 0.74.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" }),
@@ -5025,10 +5037,95 @@ var BrushOptionsBar = ({ controller, className }) => {
5025
5037
  ] });
5026
5038
  };
5027
5039
 
5028
- // src/image-editor/SelectionOptionsBar.tsx
5040
+ // src/image-editor/ColorProfilePanel.tsx
5029
5041
  var import_react41 = require("react");
5030
5042
  var import_image_editor9 = require("@pixerate/editor/image-editor");
5031
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": "Colour mode", children: [
5080
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-slate-400", children: "Mode" }),
5081
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("select", { "aria-label": "Colour mode", className: select, value: view.mode, onChange: (e) => attempt(() => controller.setColorMode(e.target.value)), children: import_image_editor9.COLOR_MODE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: o.id, title: o.title, children: o.label }, o.id)) }),
5082
+ view.cmykProfileName && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-slate-400", children: view.cmykProfileName })
5083
+ ] }),
5084
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Assign or convert", children: [
5085
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("select", { "aria-label": "Target profile", className: select, value: target, onChange: (e) => setTarget(e.target.value), children: import_image_editor9.WORKING_SPACE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: o.id, children: o.label }, o.id)) }),
5086
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("select", { "aria-label": "Rendering intent", className: select, value: intent, onChange: (e) => setIntent(e.target.value), children: import_image_editor9.INTENT_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: o.id, title: o.title, children: o.label }, o.id)) }),
5087
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1", children: [
5088
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", "aria-label": "Black point compensation", checked: bpc, onChange: (e) => setBpc(e.target.checked), className: "accent-indigo-500" }),
5089
+ "BPC"
5090
+ ] }),
5091
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: chip2, title: "Edit \u203A Assign Profile: keep the numbers", onClick: () => attempt(() => controller.assignProfile(target)), children: "Assign" }),
5092
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: chip2, title: "Edit \u203A Convert to Profile: keep the look", onClick: () => attempt(() => controller.convertToProfile(target, { intent, bpc })), children: "Convert" })
5093
+ ] }),
5094
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "group", "aria-label": "Proof setup", children: [
5095
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-slate-400", children: "Proof" }),
5096
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5097
+ "select",
5098
+ {
5099
+ "aria-label": "Proof profile",
5100
+ className: select,
5101
+ value: view.proof?.id ?? "",
5102
+ onChange: (e) => e.target.value ? proofWith({ id: e.target.value }) : attempt(() => controller.setProofSetup(null)),
5103
+ children: [
5104
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "", children: "Off" }),
5105
+ import_image_editor9.PROOF_PROFILE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: o.id, children: o.label }, o.id))
5106
+ ]
5107
+ }
5108
+ ),
5109
+ view.proof && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
5110
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("select", { "aria-label": "Proof intent", className: select, value: view.proof.intent, onChange: (e) => proofWith({ intent: e.target.value }), children: import_image_editor9.INTENT_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: o.id, children: o.label }, o.id)) }),
5111
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1", children: [
5112
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", "aria-label": "Simulate paper colour", checked: view.proof.simulatePaper, onChange: (e) => proofWith({ simulatePaper: e.target.checked }), className: "accent-indigo-500" }),
5113
+ "Paper"
5114
+ ] }),
5115
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1", children: [
5116
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", "aria-label": "Gamut warning", checked: view.proof.gamutWarning, onChange: (e) => proofWith({ gamutWarning: e.target.checked }), className: "accent-indigo-500" }),
5117
+ "Gamut warning"
5118
+ ] })
5119
+ ] })
5120
+ ] }),
5121
+ error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5122
+ ] });
5123
+ };
5124
+
5125
+ // src/image-editor/SelectionOptionsBar.tsx
5126
+ var import_react42 = require("react");
5127
+ var import_image_editor10 = require("@pixerate/editor/image-editor");
5128
+ var import_jsx_runtime25 = require("react/jsx-runtime");
5032
5129
  var MODIFY_OPS = [
5033
5130
  { op: "grow", label: "Grow" },
5034
5131
  { op: "shrink", label: "Shrink" },
@@ -5045,20 +5142,20 @@ var SelectionOptionsBar = ({
5045
5142
  quickMask,
5046
5143
  className = ""
5047
5144
  }) => {
5048
- const [radius, setRadius] = (0, import_react41.useState)(2);
5145
+ const [radius, setRadius] = (0, import_react42.useState)(2);
5049
5146
  const set = (patch) => onOptionsChange({ ...options, ...patch });
5050
5147
  const sel = selection === void 0 ? controller.getSelection() : selection;
5051
5148
  const qm = quickMask ?? Boolean(controller.getState().quickMask);
5052
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5053
- /* @__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)) }),
5054
- /* @__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)) }),
5055
- options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col gap-2", children: [
5056
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
5057
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5058
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Tolerance" }),
5059
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "font-mono", children: options.tolerance })
5149
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5150
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: import_image_editor10.SELECTION_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", "aria-pressed": options.tool === t.id, className: btn(options.tool === t.id), onClick: () => set({ tool: t.id }), children: t.label }, t.id)) }),
5151
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: import_image_editor10.SELECTION_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: import_image_editor10.SELECTION_MODE_LABELS[m] }, m)) }),
5152
+ options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-2", children: [
5153
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5154
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5155
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Tolerance" }),
5156
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: options.tolerance })
5060
5157
  ] }),
5061
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5158
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5062
5159
  "input",
5063
5160
  {
5064
5161
  type: "range",
@@ -5072,17 +5169,17 @@ var SelectionOptionsBar = ({
5072
5169
  }
5073
5170
  )
5074
5171
  ] }),
5075
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5076
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
5172
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5173
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
5077
5174
  "Contiguous"
5078
5175
  ] }),
5079
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5080
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
5176
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5177
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
5081
5178
  "Sample adjusted image"
5082
5179
  ] }),
5083
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5180
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5084
5181
  "Sample",
5085
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
5182
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5086
5183
  "select",
5087
5184
  {
5088
5185
  "aria-label": "Sample from",
@@ -5090,27 +5187,27 @@ var SelectionOptionsBar = ({
5090
5187
  onChange: (e) => set({ sample: e.target.value }),
5091
5188
  className: "bg-slate-800 border border-slate-700 rounded px-1 py-0.5",
5092
5189
  children: [
5093
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "composite", children: "All layers" }),
5094
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "active-layer", children: "Active layer" })
5190
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "composite", children: "All layers" }),
5191
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "active-layer", children: "Active layer" })
5095
5192
  ]
5096
5193
  }
5097
5194
  )
5098
5195
  ] })
5099
5196
  ] }),
5100
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5101
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
5197
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5198
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
5102
5199
  "Anti-alias"
5103
5200
  ] }),
5104
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5105
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
5106
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
5107
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
5108
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
5201
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5202
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
5203
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
5204
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
5205
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
5109
5206
  ] }),
5110
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
5111
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
5207
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
5208
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
5112
5209
  "Radius",
5113
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5210
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5114
5211
  "input",
5115
5212
  {
5116
5213
  type: "number",
@@ -5124,24 +5221,24 @@ var SelectionOptionsBar = ({
5124
5221
  }
5125
5222
  )
5126
5223
  ] }),
5127
- 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))
5224
+ MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
5128
5225
  ] }),
5129
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor9.describeSelection)(sel) })
5226
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor10.describeSelection)(sel) })
5130
5227
  ] });
5131
5228
  };
5132
5229
 
5133
5230
  // src/image-editor/RefineEdgePanel.tsx
5134
- var import_react42 = require("react");
5135
- var import_image_editor10 = require("@pixerate/editor/image-editor");
5136
- var import_jsx_runtime25 = require("react/jsx-runtime");
5231
+ var import_react43 = require("react");
5232
+ var import_image_editor11 = require("@pixerate/editor/image-editor");
5233
+ var import_jsx_runtime26 = require("react/jsx-runtime");
5137
5234
  var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
5138
5235
  var button2 = "px-2 py-1 rounded-md border border-slate-800 bg-slate-950 text-[11px] text-slate-200 hover:text-white disabled:opacity-40";
5139
5236
  var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5140
- const [params, setParams] = (0, import_react42.useState)(DEFAULT_PARAMS);
5141
- const [busy, setBusy] = (0, import_react42.useState)(false);
5142
- const [error, setError] = (0, import_react42.useState)(null);
5143
- const [layerId, setLayerId] = (0, import_react42.useState)("");
5144
- const [newKind, setNewKind] = (0, import_react42.useState)("hueSaturation");
5237
+ const [params, setParams] = (0, import_react43.useState)(DEFAULT_PARAMS);
5238
+ const [busy, setBusy] = (0, import_react43.useState)(false);
5239
+ const [error, setError] = (0, import_react43.useState)(null);
5240
+ const [layerId, setLayerId] = (0, import_react43.useState)("");
5241
+ const [newKind, setNewKind] = (0, import_react43.useState)("hueSaturation");
5145
5242
  const sel = selection === void 0 ? controller.getSelection() : selection;
5146
5243
  const list = layers ?? controller.getAdjustmentLayers();
5147
5244
  const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
@@ -5156,17 +5253,17 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5156
5253
  setBusy(false);
5157
5254
  }
5158
5255
  };
5159
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5160
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
5161
- import_image_editor10.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5162
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5163
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: c.label }),
5164
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
5256
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5257
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
5258
+ import_image_editor11.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex flex-col gap-1", children: [
5259
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5260
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: c.label }),
5261
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono", children: [
5165
5262
  params[c.id],
5166
5263
  c.unit
5167
5264
  ] })
5168
5265
  ] }),
5169
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5266
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5170
5267
  "input",
5171
5268
  {
5172
5269
  type: "range",
@@ -5180,67 +5277,67 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5180
5277
  }
5181
5278
  )
5182
5279
  ] }, c.id)),
5183
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5184
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
5280
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5281
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
5185
5282
  "Smart Radius"
5186
5283
  ] }),
5187
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-1", children: [
5188
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
5189
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
5284
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex gap-1", children: [
5285
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
5286
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
5190
5287
  ] }),
5191
- error && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
5192
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
5193
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-1 items-center", children: [
5194
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5288
+ error && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
5289
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
5290
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex gap-1 items-center", children: [
5291
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5195
5292
  "select",
5196
5293
  {
5197
5294
  "aria-label": "New masked layer kind",
5198
5295
  value: newKind,
5199
5296
  onChange: (e) => setNewKind(e.target.value),
5200
5297
  className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
5201
- children: import_image_editor10.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: k.kind, children: k.label }, k.kind))
5298
+ children: import_image_editor11.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: k.kind, children: k.label }, k.kind))
5202
5299
  }
5203
5300
  ),
5204
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5301
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5205
5302
  "button",
5206
5303
  {
5207
5304
  type: "button",
5208
5305
  className: button2,
5209
5306
  disabled: !sel,
5210
- onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor10.layerMaskFromSelection)(sel) })),
5307
+ onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor11.layerMaskFromSelection)(sel) })),
5211
5308
  children: "New Masked Layer"
5212
5309
  }
5213
5310
  )
5214
5311
  ] }),
5215
- list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-2", children: [
5216
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5312
+ list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-2", children: [
5313
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5217
5314
  "select",
5218
5315
  {
5219
5316
  "aria-label": "Mask layer",
5220
5317
  value: target.id,
5221
5318
  onChange: (e) => setLayerId(e.target.value),
5222
5319
  className: "bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
5223
- children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("option", { value: l.id, children: [
5224
- l.name || (0, import_image_editor10.adjustmentKindLabel)(l.kind),
5320
+ children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("option", { value: l.id, children: [
5321
+ l.name || (0, import_image_editor11.adjustmentKindLabel)(l.kind),
5225
5322
  l.mask ? " (masked)" : ""
5226
5323
  ] }, l.id))
5227
5324
  }
5228
5325
  ),
5229
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5230
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
5231
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
5232
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
5326
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5327
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
5328
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
5329
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
5233
5330
  ] }),
5234
- target.mask && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5235
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5236
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5237
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Density" }),
5238
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
5331
+ target.mask && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
5332
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex flex-col gap-1", children: [
5333
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5334
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Density" }),
5335
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono", children: [
5239
5336
  Math.round((target.mask.density ?? 1) * 100),
5240
5337
  "%"
5241
5338
  ] })
5242
5339
  ] }),
5243
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5340
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5244
5341
  "input",
5245
5342
  {
5246
5343
  type: "range",
@@ -5254,15 +5351,15 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5254
5351
  }
5255
5352
  )
5256
5353
  ] }),
5257
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5258
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5259
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Mask Feather" }),
5260
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
5354
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex flex-col gap-1", children: [
5355
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5356
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Mask Feather" }),
5357
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono", children: [
5261
5358
  target.mask.feather ?? 0,
5262
5359
  "px"
5263
5360
  ] })
5264
5361
  ] }),
5265
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5362
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5266
5363
  "input",
5267
5364
  {
5268
5365
  type: "range",
@@ -5282,14 +5379,14 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5282
5379
  };
5283
5380
 
5284
5381
  // src/image-editor/FreeTransformOptionsBar.tsx
5285
- var import_react43 = require("react");
5286
- var import_image_editor11 = require("@pixerate/editor/image-editor");
5287
- var import_jsx_runtime26 = require("react/jsx-runtime");
5288
- 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"}`;
5382
+ var import_react44 = require("react");
5383
+ var import_image_editor12 = require("@pixerate/editor/image-editor");
5384
+ var import_jsx_runtime27 = require("react/jsx-runtime");
5385
+ 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"}`;
5289
5386
  var round = (v, unit) => unit === "px" ? Math.round(v * 10) / 10 : Math.round(v * 100) / 100;
5290
5387
  var FreeTransformOptionsBar = ({ tool, className }) => {
5291
- const [, setTick] = (0, import_react43.useState)(0);
5292
- (0, import_react43.useEffect)(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
5388
+ const [, setTick] = (0, import_react44.useState)(0);
5389
+ (0, import_react44.useEffect)(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
5293
5390
  const bar = tool.bar();
5294
5391
  if (!tool.active || !bar) return null;
5295
5392
  const warp = tool.warpBar();
@@ -5301,17 +5398,17 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5301
5398
  const v = Number(raw);
5302
5399
  if (raw.trim() !== "" && Number.isFinite(v) && Math.abs(v - bar[field]) > 1e-9) tool.setField(field, v);
5303
5400
  };
5304
- 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: [
5305
- /* @__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)) }),
5306
- /* @__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)) }),
5307
- 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: [
5308
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5309
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: "Warp" }),
5310
- /* @__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)) })
5401
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: `flex flex-wrap items-center gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "free-transform-options", role: "toolbar", "aria-label": "Free Transform options", children: [
5402
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Transform mode", children: import_image_editor12.FREE_TRANSFORM_MODE_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", title: m.title, "aria-pressed": tool.mode === m.id, className: chip3(tool.mode === m.id), onClick: () => tool.setMode(m.id), children: m.label }, m.id)) }),
5403
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "grid grid-cols-3 gap-px", role: "group", "aria-label": "Reference point", children: import_image_editor12.TRANSFORM_ANCHORS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", "aria-label": `Reference point ${a}`, title: `Reference point: ${a}`, className: "h-2.5 w-2.5 rounded-sm bg-slate-700 hover:bg-indigo-500", onClick: () => tool.setReference(a) }, a)) }),
5404
+ tool.mode === "warp" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-wrap items-center gap-2", role: "group", "aria-label": "Warp options", children: [
5405
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5406
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: "Warp" }),
5407
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("select", { "aria-label": "Warp style", value: warp.style, onChange: (e) => tool.setWarp({ style: e.target.value }), className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5", children: import_image_editor12.WARP_STYLE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: o.id, children: o.label }, o.id)) })
5311
5408
  ] }),
5312
- ["bend", "horizontal", "vertical"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5313
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: k === "bend" ? "Bend" : k === "horizontal" ? "H" : "V" }),
5314
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5409
+ ["bend", "horizontal", "vertical"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5410
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: k === "bend" ? "Bend" : k === "horizontal" ? "H" : "V" }),
5411
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5315
5412
  "input",
5316
5413
  {
5317
5414
  type: "number",
@@ -5332,40 +5429,40 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5332
5429
  },
5333
5430
  `${k}:${warp[k]}`
5334
5431
  ),
5335
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-500", children: "%" })
5432
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-500", children: "%" })
5336
5433
  ] }, k)),
5337
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5434
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5338
5435
  "button",
5339
5436
  {
5340
5437
  type: "button",
5341
5438
  title: "Bend along the vertical axis",
5342
5439
  "aria-pressed": warp.orientation === "vertical",
5343
5440
  disabled: warp.style === "custom",
5344
- className: chip2(warp.orientation === "vertical"),
5441
+ className: chip3(warp.orientation === "vertical"),
5345
5442
  onClick: () => tool.setWarp({ orientation: warp.orientation === "vertical" ? "horizontal" : "vertical" }),
5346
5443
  children: "Vertical"
5347
5444
  }
5348
5445
  ),
5349
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5350
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: "Grid" }),
5351
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5446
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5447
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: "Grid" }),
5448
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5352
5449
  "select",
5353
5450
  {
5354
5451
  "aria-label": "Warp grid",
5355
- value: import_image_editor11.WARP_GRID_OPTIONS.find((g) => g.columns === warp.columns && g.rows === warp.rows)?.id ?? "1x1",
5452
+ value: import_image_editor12.WARP_GRID_OPTIONS.find((g) => g.columns === warp.columns && g.rows === warp.rows)?.id ?? "1x1",
5356
5453
  onChange: (e) => {
5357
- const g = import_image_editor11.WARP_GRID_OPTIONS.find((o) => o.id === e.target.value);
5454
+ const g = import_image_editor12.WARP_GRID_OPTIONS.find((o) => o.id === e.target.value);
5358
5455
  tool.setWarp({ columns: g.columns, rows: g.rows });
5359
5456
  },
5360
5457
  className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
5361
- children: import_image_editor11.WARP_GRID_OPTIONS.map((g) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: g.id, children: g.label }, g.id))
5458
+ children: import_image_editor12.WARP_GRID_OPTIONS.map((g) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: g.id, children: g.label }, g.id))
5362
5459
  }
5363
5460
  )
5364
5461
  ] })
5365
5462
  ] }),
5366
- 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: [
5367
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: f.label }),
5368
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5463
+ tool.mode !== "warp" && import_image_editor12.FREE_TRANSFORM_FIELDS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", title: f.title, children: [
5464
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: f.label }),
5465
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5369
5466
  "input",
5370
5467
  {
5371
5468
  type: "number",
@@ -5385,14 +5482,14 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5385
5482
  },
5386
5483
  `${f.id}:${round(bar[f.id], f.unit)}`
5387
5484
  ),
5388
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-500", children: f.unit }),
5389
- f.id === "scaleX" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5485
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-500", children: f.unit }),
5486
+ f.id === "scaleX" && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5390
5487
  "button",
5391
5488
  {
5392
5489
  type: "button",
5393
5490
  "aria-label": "Keep width and height proportional",
5394
5491
  "aria-pressed": tool.proportional,
5395
- className: chip2(tool.proportional),
5492
+ className: chip3(tool.proportional),
5396
5493
  onClick: () => {
5397
5494
  tool.proportional = !tool.proportional;
5398
5495
  setTick((n) => n + 1);
@@ -5401,34 +5498,34 @@ var FreeTransformOptionsBar = ({ tool, className }) => {
5401
5498
  }
5402
5499
  )
5403
5500
  ] }, f.id)),
5404
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5405
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: "Interpolation" }),
5406
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5501
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5502
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-400", children: "Interpolation" }),
5503
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5407
5504
  "select",
5408
5505
  {
5409
5506
  "aria-label": "Interpolation",
5410
5507
  value: tool.interpolation,
5411
5508
  onChange: (e) => tool.setInterpolation(e.target.value),
5412
5509
  className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
5413
- children: import_image_editor11.INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
5510
+ children: import_image_editor12.INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
5414
5511
  }
5415
5512
  )
5416
5513
  ] }),
5417
- /* @__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" }),
5418
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", title: "Cancel (Esc)", className: chip2(false), onClick: () => tool.cancel(), children: "Cancel" }),
5419
- tool.error && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { role: "alert", className: "text-rose-400", children: tool.error })
5514
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", title: "Commit (Enter)", className: "px-2 py-1 rounded bg-emerald-600 text-white hover:bg-emerald-500", onClick: () => tool.commit(), children: "Commit" }),
5515
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", title: "Cancel (Esc)", className: chip3(false), onClick: () => tool.cancel(), children: "Cancel" }),
5516
+ tool.error && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { role: "alert", className: "text-rose-400", children: tool.error })
5420
5517
  ] });
5421
5518
  };
5422
5519
 
5423
5520
  // src/image-editor/ShapeOptionsBar.tsx
5424
- var import_react44 = require("react");
5425
- var import_image_editor12 = require("@pixerate/editor/image-editor");
5426
- var import_jsx_runtime27 = require("react/jsx-runtime");
5427
- 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"}`;
5521
+ var import_react45 = require("react");
5522
+ var import_image_editor13 = require("@pixerate/editor/image-editor");
5523
+ var import_jsx_runtime28 = require("react/jsx-runtime");
5524
+ 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"}`;
5428
5525
  var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5429
- const [, setTick] = (0, import_react44.useState)(0);
5430
- (0, import_react44.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5431
- const [error, setError] = (0, import_react44.useState)(null);
5526
+ const [, setTick] = (0, import_react45.useState)(0);
5527
+ (0, import_react45.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5528
+ const [error, setError] = (0, import_react45.useState)(null);
5432
5529
  const active = controller.getActiveLayer();
5433
5530
  const shapeId = active?.type === "shape" ? active.id : null;
5434
5531
  const set = (change) => {
@@ -5436,19 +5533,19 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5436
5533
  if (!shapeId) return;
5437
5534
  try {
5438
5535
  setError(null);
5439
- (0, import_image_editor12.applyShapeOptions)(controller, shapeId, change);
5536
+ (0, import_image_editor13.applyShapeOptions)(controller, shapeId, change);
5440
5537
  } catch (e) {
5441
5538
  setError(e instanceof Error ? e.message : String(e));
5442
5539
  }
5443
5540
  };
5444
5541
  const num = (v, min, max) => Math.max(min, Math.min(max, Number(v) || min));
5445
- 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: [
5446
- /* @__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)) }),
5447
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5448
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5449
- /* @__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 }) }),
5542
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "shape-options", children: [
5543
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex flex-wrap gap-1", role: "toolbar", "aria-label": "Shape kind", children: import_image_editor13.LIVE_SHAPE_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", "aria-pressed": options.kind === k, className: chip4(options.kind === k), onClick: () => onChange({ ...options, kind: k }), children: import_image_editor13.SHAPE_KIND_LABELS[k] }, k)) }),
5544
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5545
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5546
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "checkbox", "aria-label": "Fill", checked: options.fill !== null, onChange: (e) => set({ fill: e.target.checked ? "#4f46e5" : null }) }),
5450
5547
  "Fill",
5451
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5548
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5452
5549
  "input",
5453
5550
  {
5454
5551
  type: "color",
@@ -5460,10 +5557,10 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5460
5557
  }
5461
5558
  )
5462
5559
  ] }),
5463
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5464
- /* @__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 }) }),
5560
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5561
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "checkbox", "aria-label": "Stroke", checked: options.stroke !== null, onChange: (e) => set({ stroke: e.target.checked ? "#000000" : null }) }),
5465
5562
  "Stroke",
5466
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5563
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5467
5564
  "input",
5468
5565
  {
5469
5566
  type: "color",
@@ -5475,9 +5572,9 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5475
5572
  }
5476
5573
  )
5477
5574
  ] }),
5478
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5575
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5479
5576
  "Width",
5480
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5577
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5481
5578
  "input",
5482
5579
  {
5483
5580
  type: "number",
@@ -5491,23 +5588,23 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5491
5588
  )
5492
5589
  ] })
5493
5590
  ] }),
5494
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5495
- options.kind === "rect" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5591
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
5592
+ options.kind === "rect" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5496
5593
  "Radius",
5497
- /* @__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" })
5594
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "number", "aria-label": "Corner radius", min: 0, max: 1e3, value: options.radius, onChange: (e) => set({ radius: num(e.target.value, 0, 1e3) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5498
5595
  ] }),
5499
- options.kind === "polygon" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5596
+ options.kind === "polygon" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5500
5597
  "Sides",
5501
- /* @__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" })
5598
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "number", "aria-label": "Sides", min: 3, max: 100, value: options.sides, onChange: (e) => set({ sides: num(e.target.value, 3, 100) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5502
5599
  ] }),
5503
- options.kind === "star" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
5504
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5600
+ options.kind === "star" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
5601
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5505
5602
  "Points",
5506
- /* @__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" })
5603
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "number", "aria-label": "Points", min: 3, max: 100, value: options.points, onChange: (e) => set({ points: num(e.target.value, 3, 100) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5507
5604
  ] }),
5508
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5605
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5509
5606
  "Inner",
5510
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5607
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5511
5608
  "input",
5512
5609
  {
5513
5610
  type: "range",
@@ -5522,33 +5619,33 @@ var ShapeOptionsBar = ({ controller, options, onChange, className }) => {
5522
5619
  )
5523
5620
  ] })
5524
5621
  ] }),
5525
- options.kind === "line" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
5526
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5622
+ options.kind === "line" && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
5623
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5527
5624
  "Weight",
5528
- /* @__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" })
5625
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "number", "aria-label": "Line weight", min: 1, max: 200, value: options.weight, onChange: (e) => set({ weight: num(e.target.value, 1, 200) }), className: "w-14 rounded border border-slate-700 bg-slate-950 px-1 py-0.5" })
5529
5626
  ] }),
5530
- /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-1", children: [
5531
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("input", { type: "checkbox", "aria-label": "Arrowhead", checked: options.arrow, onChange: (e) => set({ arrow: e.target.checked }) }),
5627
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5628
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("input", { type: "checkbox", "aria-label": "Arrowhead", checked: options.arrow, onChange: (e) => set({ arrow: e.target.checked }) }),
5532
5629
  "Arrowhead"
5533
5630
  ] })
5534
5631
  ] })
5535
5632
  ] }),
5536
- /* @__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." }),
5537
- error && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5633
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-[10px] text-slate-500", children: "Drag on the image to draw. Shift: square, circle or 45\xB0 line. Alt: from the centre." }),
5634
+ error && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5538
5635
  ] });
5539
5636
  };
5540
5637
 
5541
5638
  // src/image-editor/TypeOptionsBar.tsx
5542
- var import_react45 = require("react");
5543
- var import_image_editor13 = require("@pixerate/editor/image-editor");
5544
- var import_jsx_runtime28 = require("react/jsx-runtime");
5545
- 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"}`;
5639
+ var import_react46 = require("react");
5640
+ var import_image_editor14 = require("@pixerate/editor/image-editor");
5641
+ var import_jsx_runtime29 = require("react/jsx-runtime");
5642
+ 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"}`;
5546
5643
  var ALIGN_LABELS = { left: "Left", center: "Centre", right: "Right", justify: "Justify" };
5547
5644
  var TypeOptionsBar = ({ controller, options, onChange, session, className }) => {
5548
- const [, setTick] = (0, import_react45.useState)(0);
5549
- (0, import_react45.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5550
- (0, import_react45.useEffect)(() => session?.subscribe(() => setTick((n) => n + 1)), [session]);
5551
- const [error, setError] = (0, import_react45.useState)(null);
5645
+ const [, setTick] = (0, import_react46.useState)(0);
5646
+ (0, import_react46.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
5647
+ (0, import_react46.useEffect)(() => session?.subscribe(() => setTick((n) => n + 1)), [session]);
5648
+ const [error, setError] = (0, import_react46.useState)(null);
5552
5649
  const active = controller.getActiveLayer();
5553
5650
  const typeId = !session && active?.type === "type" ? active.id : null;
5554
5651
  const here = session?.alive ? session.styleHere() : {};
@@ -5580,11 +5677,11 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
5580
5677
  setError(e instanceof Error ? e.message : String(e));
5581
5678
  }
5582
5679
  };
5583
- 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: [
5584
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
5585
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5680
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "type-options", children: [
5681
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
5682
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-1", children: [
5586
5683
  "Font",
5587
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5684
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5588
5685
  "input",
5589
5686
  {
5590
5687
  list: "pixerate-type-fonts",
@@ -5594,11 +5691,11 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
5594
5691
  className: "w-32 rounded border border-slate-700 bg-slate-950 px-1 py-0.5"
5595
5692
  }
5596
5693
  ),
5597
- /* @__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)) })
5694
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("datalist", { id: "pixerate-type-fonts", children: fonts.map((f) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: f }, f)) })
5598
5695
  ] }),
5599
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("label", { className: "flex items-center gap-1", children: [
5696
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-1", children: [
5600
5697
  "Size",
5601
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5698
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
5602
5699
  "input",
5603
5700
  {
5604
5701
  type: "number",
@@ -5611,24 +5708,24 @@ var TypeOptionsBar = ({ controller, options, onChange, session, className }) =>
5611
5708
  }
5612
5709
  )
5613
5710
  ] }),
5614
- /* @__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" }),
5615
- /* @__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" }),
5616
- /* @__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" })
5711
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", "aria-pressed": shown.fontWeight >= 600, className: `${chip5(shown.fontWeight >= 600)} font-bold`, onClick: () => style({ fontWeight: shown.fontWeight >= 600 ? 400 : 700 }), children: "B" }),
5712
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", "aria-pressed": shown.italic, className: `${chip5(shown.italic)} italic`, onClick: () => style({ italic: !shown.italic }), children: "I" }),
5713
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("input", { type: "color", "aria-label": "Text colour", value: shown.color, onChange: (e) => style({ color: e.target.value }), className: "h-6 w-8 rounded border border-slate-700 bg-transparent" })
5617
5714
  ] }),
5618
- /* @__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)) }),
5619
- /* @__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." }),
5620
- missing.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("p", { role: "status", className: "text-amber-400", "data-testid": "type-missing-fonts", children: [
5715
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Alignment", children: import_image_editor14.TEXT_ALIGNS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", "aria-pressed": options.align === a, className: chip5(options.align === a), onClick: () => style({ align: a }), children: ALIGN_LABELS[a] }, a)) }),
5716
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-[10px] text-slate-500", children: "Click to type point text, drag for a paragraph box, click text to edit it. Esc finishes." }),
5717
+ missing.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("p", { role: "status", className: "text-amber-400", "data-testid": "type-missing-fonts", children: [
5621
5718
  "Missing ",
5622
5719
  missing.length === 1 ? "font" : "fonts",
5623
5720
  ": ",
5624
5721
  missing.join(", ")
5625
5722
  ] }),
5626
- error && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5723
+ error && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
5627
5724
  ] });
5628
5725
  };
5629
5726
 
5630
5727
  // src/image-editor/ImageEditor.tsx
5631
- var import_jsx_runtime29 = require("react/jsx-runtime");
5728
+ var import_jsx_runtime30 = require("react/jsx-runtime");
5632
5729
  var ImageEditor = ({
5633
5730
  editor: externalEditor,
5634
5731
  src,
@@ -5643,65 +5740,65 @@ var ImageEditor = ({
5643
5740
  const internalEditor = useImageEditor({ image: src });
5644
5741
  const editor = externalEditor || internalEditor;
5645
5742
  const { state, controller } = editor;
5646
- const legacyProcess = (0, import_image_editor14.normalizeProcessVersion)(state.adjustments.process) < import_image_editor14.LATEST_PROCESS_VERSION;
5647
- const canvasRef = (0, import_react46.useRef)(null);
5648
- const containerRef = (0, import_react46.useRef)(null);
5649
- const [activeTab, setActiveTab] = (0, import_react46.useState)("crop");
5650
- const [activeCropRatio, setActiveCropRatio] = (0, import_react46.useState)(null);
5651
- const [selectionOptions, setSelectionOptions] = (0, import_react46.useState)(import_image_editor14.DEFAULT_SELECTION_TOOL_OPTIONS);
5652
- const selectionOptionsRef = (0, import_react46.useRef)(selectionOptions);
5743
+ const legacyProcess = (0, import_image_editor15.normalizeProcessVersion)(state.adjustments.process) < import_image_editor15.LATEST_PROCESS_VERSION;
5744
+ const canvasRef = (0, import_react47.useRef)(null);
5745
+ const containerRef = (0, import_react47.useRef)(null);
5746
+ const [activeTab, setActiveTab] = (0, import_react47.useState)("crop");
5747
+ const [activeCropRatio, setActiveCropRatio] = (0, import_react47.useState)(null);
5748
+ const [selectionOptions, setSelectionOptions] = (0, import_react47.useState)(import_image_editor15.DEFAULT_SELECTION_TOOL_OPTIONS);
5749
+ const selectionOptionsRef = (0, import_react47.useRef)(selectionOptions);
5653
5750
  selectionOptionsRef.current = selectionOptions;
5654
- const selectionGestureRef = (0, import_react46.useRef)(null);
5751
+ const selectionGestureRef = (0, import_react47.useRef)(null);
5655
5752
  if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
5656
- selectionGestureRef.current = new import_image_editor14.SelectionGesture(controller, () => selectionOptionsRef.current);
5753
+ selectionGestureRef.current = new import_image_editor15.SelectionGesture(controller, () => selectionOptionsRef.current);
5657
5754
  }
5658
- const selectionDraftRef = (0, import_react46.useRef)(null);
5659
- const [selectionError, setSelectionError] = (0, import_react46.useState)(null);
5660
- const paintGestureRef = (0, import_react46.useRef)(null);
5661
- const paintControllerRef = (0, import_react46.useRef)(controller);
5755
+ const selectionDraftRef = (0, import_react47.useRef)(null);
5756
+ const [selectionError, setSelectionError] = (0, import_react47.useState)(null);
5757
+ const paintGestureRef = (0, import_react47.useRef)(null);
5758
+ const paintControllerRef = (0, import_react47.useRef)(controller);
5662
5759
  if (!paintGestureRef.current || paintControllerRef.current !== controller) {
5663
- paintGestureRef.current = new import_image_editor14.PaintGesture(controller);
5760
+ paintGestureRef.current = new import_image_editor15.PaintGesture(controller);
5664
5761
  paintControllerRef.current = controller;
5665
5762
  }
5666
- const brushCursorRef = (0, import_react46.useRef)(null);
5667
- const [paintError, setPaintError] = (0, import_react46.useState)(null);
5668
- const transformToolRef = (0, import_react46.useRef)(null);
5669
- const transformControllerRef = (0, import_react46.useRef)(controller);
5763
+ const brushCursorRef = (0, import_react47.useRef)(null);
5764
+ const [paintError, setPaintError] = (0, import_react47.useState)(null);
5765
+ const transformToolRef = (0, import_react47.useRef)(null);
5766
+ const transformControllerRef = (0, import_react47.useRef)(controller);
5670
5767
  if (!transformToolRef.current || transformControllerRef.current !== controller) {
5671
5768
  transformToolRef.current?.cancel();
5672
- transformToolRef.current = new import_image_editor14.FreeTransformTool(controller, {
5769
+ transformToolRef.current = new import_image_editor15.FreeTransformTool(controller, {
5673
5770
  schedule: (run) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(run) : run()
5674
5771
  });
5675
5772
  transformControllerRef.current = controller;
5676
5773
  }
5677
5774
  const transformTool = transformToolRef.current;
5678
- const [, setTransformTick] = (0, import_react46.useState)(0);
5679
- const [transformCursor, setTransformCursor] = (0, import_react46.useState)("default");
5680
- const [shapeOptions, setShapeOptions] = (0, import_react46.useState)(import_image_editor14.DEFAULT_SHAPE_TOOL_OPTIONS);
5681
- const shapeOptionsRef = (0, import_react46.useRef)(shapeOptions);
5775
+ const [, setTransformTick] = (0, import_react47.useState)(0);
5776
+ const [transformCursor, setTransformCursor] = (0, import_react47.useState)("default");
5777
+ const [shapeOptions, setShapeOptions] = (0, import_react47.useState)(import_image_editor15.DEFAULT_SHAPE_TOOL_OPTIONS);
5778
+ const shapeOptionsRef = (0, import_react47.useRef)(shapeOptions);
5682
5779
  shapeOptionsRef.current = shapeOptions;
5683
- const [typeOptions, setTypeOptions] = (0, import_react46.useState)(import_image_editor14.DEFAULT_TYPE_TOOL_OPTIONS);
5684
- const typeOptionsRef = (0, import_react46.useRef)(typeOptions);
5780
+ const [typeOptions, setTypeOptions] = (0, import_react47.useState)(import_image_editor15.DEFAULT_TYPE_TOOL_OPTIONS);
5781
+ const typeOptionsRef = (0, import_react47.useRef)(typeOptions);
5685
5782
  typeOptionsRef.current = typeOptions;
5686
- const shapeGestureRef = (0, import_react46.useRef)(null);
5687
- const typeToolRef = (0, import_react46.useRef)(null);
5688
- const shapeTypeControllerRef = (0, import_react46.useRef)(controller);
5783
+ const shapeGestureRef = (0, import_react47.useRef)(null);
5784
+ const typeToolRef = (0, import_react47.useRef)(null);
5785
+ const shapeTypeControllerRef = (0, import_react47.useRef)(controller);
5689
5786
  if (!shapeGestureRef.current || !typeToolRef.current || shapeTypeControllerRef.current !== controller) {
5690
5787
  typeToolRef.current?.finish();
5691
- shapeGestureRef.current = new import_image_editor14.ShapeDrawGesture(controller, () => shapeOptionsRef.current);
5692
- typeToolRef.current = new import_image_editor14.TypeToolGesture(controller, () => typeOptionsRef.current);
5788
+ shapeGestureRef.current = new import_image_editor15.ShapeDrawGesture(controller, () => shapeOptionsRef.current);
5789
+ typeToolRef.current = new import_image_editor15.TypeToolGesture(controller, () => typeOptionsRef.current);
5693
5790
  shapeTypeControllerRef.current = controller;
5694
5791
  }
5695
- const typeInputRef = (0, import_react46.useRef)(null);
5696
- const [typeSession, setTypeSession] = (0, import_react46.useState)(typeToolRef.current.session);
5697
- const [shapeTypeError, setShapeTypeError] = (0, import_react46.useState)(null);
5698
- const [inpaintPrompt, setInpaintPrompt] = (0, import_react46.useState)("");
5699
- const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react46.useState)("annotations");
5700
- const [isRemovingBg, setIsRemovingBg] = (0, import_react46.useState)(false);
5701
- const [isInpainting, setIsInpainting] = (0, import_react46.useState)(false);
5702
- const [aiError, setAiError] = (0, import_react46.useState)(null);
5703
- const [aiSuccess, setAiSuccess] = (0, import_react46.useState)(null);
5704
- const [aiTarget, setAiTarget] = (0, import_react46.useState)("auto");
5792
+ const typeInputRef = (0, import_react47.useRef)(null);
5793
+ const [typeSession, setTypeSession] = (0, import_react47.useState)(typeToolRef.current.session);
5794
+ const [shapeTypeError, setShapeTypeError] = (0, import_react47.useState)(null);
5795
+ const [inpaintPrompt, setInpaintPrompt] = (0, import_react47.useState)("");
5796
+ const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react47.useState)("annotations");
5797
+ const [isRemovingBg, setIsRemovingBg] = (0, import_react47.useState)(false);
5798
+ const [isInpainting, setIsInpainting] = (0, import_react47.useState)(false);
5799
+ const [aiError, setAiError] = (0, import_react47.useState)(null);
5800
+ const [aiSuccess, setAiSuccess] = (0, import_react47.useState)(null);
5801
+ const [aiTarget, setAiTarget] = (0, import_react47.useState)("auto");
5705
5802
  const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
5706
5803
  const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
5707
5804
  const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
@@ -5764,18 +5861,18 @@ var ImageEditor = ({
5764
5861
  setIsInpainting(false);
5765
5862
  }
5766
5863
  };
5767
- const [activeColor, setActiveColor] = (0, import_react46.useState)("#ef4444");
5768
- const [strokeWidth, setStrokeWidth] = (0, import_react46.useState)(3);
5769
- const [fontSize, setFontSize] = (0, import_react46.useState)(24);
5770
- const [textInput, setTextInput] = (0, import_react46.useState)("");
5771
- const draftAnnotationRef = (0, import_react46.useRef)(null);
5772
- const draftCropRef = (0, import_react46.useRef)(null);
5773
- const cropDragInfoRef = (0, import_react46.useRef)(null);
5774
- const annotationDragInfoRef = (0, import_react46.useRef)(null);
5775
- const isDrawingRef = (0, import_react46.useRef)(false);
5776
- const currentPathRef = (0, import_react46.useRef)([]);
5777
- const dragStartPointRef = (0, import_react46.useRef)(null);
5778
- const renderCanvas = (0, import_react46.useCallback)(
5864
+ const [activeColor, setActiveColor] = (0, import_react47.useState)("#ef4444");
5865
+ const [strokeWidth, setStrokeWidth] = (0, import_react47.useState)(3);
5866
+ const [fontSize, setFontSize] = (0, import_react47.useState)(24);
5867
+ const [textInput, setTextInput] = (0, import_react47.useState)("");
5868
+ const draftAnnotationRef = (0, import_react47.useRef)(null);
5869
+ const draftCropRef = (0, import_react47.useRef)(null);
5870
+ const cropDragInfoRef = (0, import_react47.useRef)(null);
5871
+ const annotationDragInfoRef = (0, import_react47.useRef)(null);
5872
+ const isDrawingRef = (0, import_react47.useRef)(false);
5873
+ const currentPathRef = (0, import_react47.useRef)([]);
5874
+ const dragStartPointRef = (0, import_react47.useRef)(null);
5875
+ const renderCanvas = (0, import_react47.useCallback)(
5779
5876
  async (draftAnnotation, draftCrop) => {
5780
5877
  const canvas = canvasRef.current;
5781
5878
  const container = containerRef.current;
@@ -5798,8 +5895,8 @@ var ImageEditor = ({
5798
5895
  },
5799
5896
  [controller, activeTab, transformTool]
5800
5897
  );
5801
- (0, import_react46.useEffect)(() => typeSession?.subscribe(() => void renderCanvas()), [typeSession, renderCanvas]);
5802
- (0, import_react46.useEffect)(() => {
5898
+ (0, import_react47.useEffect)(() => typeSession?.subscribe(() => void renderCanvas()), [typeSession, renderCanvas]);
5899
+ (0, import_react47.useEffect)(() => {
5803
5900
  if (activeTab === "annotate" && state.activeTool === "type") return;
5804
5901
  if (typeToolRef.current?.session) {
5805
5902
  typeToolRef.current.finish();
@@ -5834,7 +5931,7 @@ var ImageEditor = ({
5834
5931
  el.value = "";
5835
5932
  }
5836
5933
  };
5837
- (0, import_react46.useEffect)(() => transformTool.subscribe(() => {
5934
+ (0, import_react47.useEffect)(() => transformTool.subscribe(() => {
5838
5935
  setTransformTick((n) => n + 1);
5839
5936
  void renderCanvas();
5840
5937
  }), [transformTool, renderCanvas]);
@@ -5845,8 +5942,8 @@ var ImageEditor = ({
5845
5942
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
5846
5943
  const s = controller.getState();
5847
5944
  const cropping = activeTab === "crop";
5848
- const projection = (0, import_image_editor14.getViewportProjection)(s, canvas.width, canvas.height, cropping);
5849
- 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);
5945
+ const projection = (0, import_image_editor15.getViewportProjection)(s, canvas.width, canvas.height, cropping);
5946
+ const pt = (0, import_image_editor15.canvasToImagePoint)({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
5850
5947
  transformTool.setView(projection.scale);
5851
5948
  return { pt, tolerance: 6 / (projection.scale || 1) };
5852
5949
  };
@@ -5877,7 +5974,7 @@ var ImageEditor = ({
5877
5974
  transformTool.up();
5878
5975
  return true;
5879
5976
  };
5880
- (0, import_react46.useEffect)(() => {
5977
+ (0, import_react47.useEffect)(() => {
5881
5978
  if (typeof window === "undefined") return;
5882
5979
  const onKey = (e) => {
5883
5980
  if (transformTool.key(e)) e.preventDefault();
@@ -5885,7 +5982,7 @@ var ImageEditor = ({
5885
5982
  window.addEventListener("keydown", onKey);
5886
5983
  return () => window.removeEventListener("keydown", onKey);
5887
5984
  }, [transformTool]);
5888
- (0, import_react46.useEffect)(() => {
5985
+ (0, import_react47.useEffect)(() => {
5889
5986
  const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
5890
5987
  const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
5891
5988
  const animId = raf(() => {
@@ -5893,12 +5990,12 @@ var ImageEditor = ({
5893
5990
  });
5894
5991
  return () => caf(animId);
5895
5992
  }, [renderCanvas, state]);
5896
- (0, import_react46.useEffect)(() => {
5993
+ (0, import_react47.useEffect)(() => {
5897
5994
  if (activeTab === "crop" && editor.state.activeTool !== "crop") {
5898
5995
  editor.setTool("crop");
5899
5996
  }
5900
5997
  }, [activeTab, editor]);
5901
- (0, import_react46.useEffect)(() => {
5998
+ (0, import_react47.useEffect)(() => {
5902
5999
  const container = containerRef.current;
5903
6000
  if (!container) return;
5904
6001
  if (typeof ResizeObserver !== "undefined") {
@@ -5934,8 +6031,8 @@ var ImageEditor = ({
5934
6031
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
5935
6032
  const s = controller.getState();
5936
6033
  return list.map((ev) => ({
5937
- ...(0, import_image_editor14.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
5938
- pressure: (0, import_image_editor14.pointerPressure)(ev)
6034
+ ...(0, import_image_editor15.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
6035
+ pressure: (0, import_image_editor15.pointerPressure)(ev)
5939
6036
  }));
5940
6037
  };
5941
6038
  const handlePaintPointerDown = (e) => {
@@ -5966,10 +6063,10 @@ var ImageEditor = ({
5966
6063
  if (g.error) setPaintError(g.error);
5967
6064
  }
5968
6065
  };
5969
- (0, import_react46.useEffect)(() => {
6066
+ (0, import_react47.useEffect)(() => {
5970
6067
  if (activeTab !== "paint" || typeof window === "undefined") return;
5971
6068
  const onKey = (e) => {
5972
- if ((0, import_image_editor14.handlePaintShortcut)(controller, e)) e.preventDefault();
6069
+ if ((0, import_image_editor15.handlePaintShortcut)(controller, e)) e.preventDefault();
5973
6070
  };
5974
6071
  window.addEventListener("keydown", onKey);
5975
6072
  return () => window.removeEventListener("keydown", onKey);
@@ -5980,7 +6077,7 @@ var ImageEditor = ({
5980
6077
  const canvasPt = getCanvasEventPoint(e);
5981
6078
  if (activeTab === "select") {
5982
6079
  const gesture = selectionGestureRef.current;
5983
- const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6080
+ const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5984
6081
  void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
5985
6082
  return;
5986
6083
  }
@@ -5991,8 +6088,8 @@ var ImageEditor = ({
5991
6088
  width: state.imageDimensions.width,
5992
6089
  height: state.imageDimensions.height
5993
6090
  };
5994
- const handle = (0, import_image_editor14.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
5995
- const startImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
6091
+ const handle = (0, import_image_editor15.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
6092
+ const startImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
5996
6093
  if (handle) {
5997
6094
  cropDragInfoRef.current = {
5998
6095
  handle,
@@ -6011,7 +6108,7 @@ var ImageEditor = ({
6011
6108
  return;
6012
6109
  }
6013
6110
  if (activeTab === "annotate" && (state.activeTool === "shape" || state.activeTool === "type")) {
6014
- const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6111
+ const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6015
6112
  setShapeTypeError(null);
6016
6113
  if (state.activeTool === "shape") shapeGestureRef.current.down(imgPt);
6017
6114
  else {
@@ -6022,12 +6119,12 @@ var ImageEditor = ({
6022
6119
  return;
6023
6120
  }
6024
6121
  if (activeTab === "annotate") {
6025
- const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6122
+ const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6026
6123
  dragStartPointRef.current = imgPt;
6027
6124
  if (state.activeTool === "select") {
6028
6125
  for (let i = state.annotations.length - 1; i >= 0; i--) {
6029
6126
  const ann = state.annotations[i];
6030
- if ((0, import_image_editor14.hitTestAnnotation)(imgPt, ann)) {
6127
+ if ((0, import_image_editor15.hitTestAnnotation)(imgPt, ann)) {
6031
6128
  editor.selectAnnotation(ann.id);
6032
6129
  annotationDragInfoRef.current = {
6033
6130
  annId: ann.id,
@@ -6063,7 +6160,7 @@ var ImageEditor = ({
6063
6160
  const canvasPt = getCanvasEventPoint(e);
6064
6161
  if (activeTab === "select") {
6065
6162
  const gesture = selectionGestureRef.current;
6066
- if (gesture.active && gesture.move((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
6163
+ if (gesture.active && gesture.move((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
6067
6164
  selectionDraftRef.current = gesture.draftPath;
6068
6165
  renderCanvas();
6069
6166
  }
@@ -6072,7 +6169,7 @@ var ImageEditor = ({
6072
6169
  if (activeTab === "crop") {
6073
6170
  const drag = cropDragInfoRef.current;
6074
6171
  if (drag) {
6075
- const currentImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
6172
+ const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
6076
6173
  let newCrop;
6077
6174
  if (drag.handle === "new") {
6078
6175
  const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
@@ -6086,7 +6183,7 @@ var ImageEditor = ({
6086
6183
  height: Math.round(Math.max(20, maxY - minY))
6087
6184
  };
6088
6185
  } else {
6089
- newCrop = (0, import_image_editor14.calculateCropDrag)(
6186
+ newCrop = (0, import_image_editor15.calculateCropDrag)(
6090
6187
  drag.startCrop,
6091
6188
  drag.handle,
6092
6189
  drag.startImgPt,
@@ -6106,15 +6203,15 @@ var ImageEditor = ({
6106
6203
  width: state.imageDimensions.width,
6107
6204
  height: state.imageDimensions.height
6108
6205
  };
6109
- const handle = (0, import_image_editor14.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
6110
- canvas.style.cursor = (0, import_image_editor14.getCropCursor)(handle, state.transform);
6206
+ const handle = (0, import_image_editor15.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
6207
+ canvas.style.cursor = (0, import_image_editor15.getCropCursor)(handle, state.transform);
6111
6208
  }
6112
6209
  return;
6113
6210
  }
6114
6211
  if (activeTab === "annotate" && state.activeTool === "shape") {
6115
6212
  const g = shapeGestureRef.current;
6116
6213
  if (g.active) {
6117
- g.move((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), { shift: e.shiftKey, alt: e.altKey });
6214
+ g.move((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), { shift: e.shiftKey, alt: e.altKey });
6118
6215
  if (g.error) setShapeTypeError(g.error);
6119
6216
  }
6120
6217
  return;
@@ -6122,7 +6219,7 @@ var ImageEditor = ({
6122
6219
  if (activeTab === "annotate") {
6123
6220
  if (annotationDragInfoRef.current) {
6124
6221
  const drag = annotationDragInfoRef.current;
6125
- const currentImgPt2 = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6222
+ const currentImgPt2 = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6126
6223
  const dx = currentImgPt2.x - drag.startImgPt.x;
6127
6224
  const dy = currentImgPt2.y - drag.startImgPt.y;
6128
6225
  editor.updateAnnotation(drag.annId, {
@@ -6134,10 +6231,10 @@ var ImageEditor = ({
6134
6231
  const startPt = dragStartPointRef.current;
6135
6232
  if (!startPt) {
6136
6233
  if (state.activeTool === "select") {
6137
- const imgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6234
+ const imgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6138
6235
  let hovered = false;
6139
6236
  for (let i = state.annotations.length - 1; i >= 0; i--) {
6140
- if ((0, import_image_editor14.hitTestAnnotation)(imgPt, state.annotations[i])) {
6237
+ if ((0, import_image_editor15.hitTestAnnotation)(imgPt, state.annotations[i])) {
6141
6238
  hovered = true;
6142
6239
  break;
6143
6240
  }
@@ -6148,7 +6245,7 @@ var ImageEditor = ({
6148
6245
  }
6149
6246
  return;
6150
6247
  }
6151
- const currentImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6248
+ const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6152
6249
  if (state.activeTool === "pen" && isDrawingRef.current) {
6153
6250
  currentPathRef.current.push(currentImgPt);
6154
6251
  const draft = {
@@ -6228,7 +6325,7 @@ var ImageEditor = ({
6228
6325
  if (activeTab === "select") {
6229
6326
  const gesture = selectionGestureRef.current;
6230
6327
  if (gesture.active) {
6231
- gesture.end((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
6328
+ gesture.end((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
6232
6329
  selectionDraftRef.current = null;
6233
6330
  renderCanvas();
6234
6331
  }
@@ -6251,7 +6348,7 @@ var ImageEditor = ({
6251
6348
  }
6252
6349
  if (activeTab === "annotate" && state.activeTool === "type") {
6253
6350
  const tool = typeToolRef.current;
6254
- tool.up((0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false));
6351
+ tool.up((0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false));
6255
6352
  setTypeSession(tool.session);
6256
6353
  if (tool.error) setShapeTypeError(tool.error);
6257
6354
  void renderCanvas();
@@ -6265,7 +6362,7 @@ var ImageEditor = ({
6265
6362
  }
6266
6363
  const startPt = dragStartPointRef.current;
6267
6364
  if (startPt) {
6268
- const currentImgPt = (0, import_image_editor14.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6365
+ const currentImgPt = (0, import_image_editor15.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
6269
6366
  if (state.activeTool === "pen" && isDrawingRef.current) {
6270
6367
  if (currentPathRef.current.length > 1) {
6271
6368
  editor.addAnnotation({
@@ -6361,15 +6458,15 @@ var ImageEditor = ({
6361
6458
  link.click();
6362
6459
  }
6363
6460
  };
6364
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6461
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6365
6462
  "div",
6366
6463
  {
6367
6464
  className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
6368
6465
  style,
6369
6466
  children: [
6370
- /* @__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: [
6371
- /* @__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: [
6372
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6467
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-wrap items-center justify-between px-4 py-3 bg-slate-950/80 border-b border-slate-800 gap-3", children: [
6468
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
6469
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6373
6470
  "button",
6374
6471
  {
6375
6472
  type: "button",
@@ -6381,7 +6478,7 @@ var ImageEditor = ({
6381
6478
  children: "Transform & Crop"
6382
6479
  }
6383
6480
  ),
6384
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6481
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6385
6482
  "button",
6386
6483
  {
6387
6484
  type: "button",
@@ -6393,7 +6490,7 @@ var ImageEditor = ({
6393
6490
  children: "Adjustments"
6394
6491
  }
6395
6492
  ),
6396
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6493
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6397
6494
  "button",
6398
6495
  {
6399
6496
  type: "button",
@@ -6405,7 +6502,7 @@ var ImageEditor = ({
6405
6502
  children: "Layers"
6406
6503
  }
6407
6504
  ),
6408
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6505
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6409
6506
  "button",
6410
6507
  {
6411
6508
  type: "button",
@@ -6417,7 +6514,7 @@ var ImageEditor = ({
6417
6514
  children: "Paint"
6418
6515
  }
6419
6516
  ),
6420
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6517
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6421
6518
  "button",
6422
6519
  {
6423
6520
  type: "button",
@@ -6429,7 +6526,7 @@ var ImageEditor = ({
6429
6526
  children: "Select & Mask"
6430
6527
  }
6431
6528
  ),
6432
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6529
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6433
6530
  "button",
6434
6531
  {
6435
6532
  type: "button",
@@ -6441,7 +6538,7 @@ var ImageEditor = ({
6441
6538
  children: "Annotations"
6442
6539
  }
6443
6540
  ),
6444
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6541
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6445
6542
  "button",
6446
6543
  {
6447
6544
  type: "button",
@@ -6453,7 +6550,7 @@ var ImageEditor = ({
6453
6550
  children: "Depth Mask"
6454
6551
  }
6455
6552
  ),
6456
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6553
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6457
6554
  "button",
6458
6555
  {
6459
6556
  type: "button",
@@ -6463,14 +6560,14 @@ var ImageEditor = ({
6463
6560
  },
6464
6561
  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"}`,
6465
6562
  children: [
6466
- /* @__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" }) }),
6563
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
6467
6564
  "AI Tools"
6468
6565
  ]
6469
6566
  }
6470
6567
  )
6471
6568
  ] }),
6472
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
6473
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6569
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
6570
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6474
6571
  "button",
6475
6572
  {
6476
6573
  type: "button",
@@ -6481,7 +6578,7 @@ var ImageEditor = ({
6481
6578
  children: "\u21A9"
6482
6579
  }
6483
6580
  ),
6484
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6581
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6485
6582
  "button",
6486
6583
  {
6487
6584
  type: "button",
@@ -6492,7 +6589,7 @@ var ImageEditor = ({
6492
6589
  children: "\u21AA"
6493
6590
  }
6494
6591
  ),
6495
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6592
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6496
6593
  "button",
6497
6594
  {
6498
6595
  type: "button",
@@ -6501,8 +6598,8 @@ var ImageEditor = ({
6501
6598
  children: "Reset"
6502
6599
  }
6503
6600
  ),
6504
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6505
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6601
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6602
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6506
6603
  "button",
6507
6604
  {
6508
6605
  type: "button",
@@ -6512,11 +6609,11 @@ var ImageEditor = ({
6512
6609
  children: "-"
6513
6610
  }
6514
6611
  ),
6515
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
6612
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
6516
6613
  Math.round(state.zoom * 100),
6517
6614
  "%"
6518
6615
  ] }),
6519
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6616
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6520
6617
  "button",
6521
6618
  {
6522
6619
  type: "button",
@@ -6526,8 +6623,8 @@ var ImageEditor = ({
6526
6623
  children: "+"
6527
6624
  }
6528
6625
  ),
6529
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6530
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6626
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6627
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6531
6628
  "button",
6532
6629
  {
6533
6630
  type: "button",
@@ -6538,7 +6635,7 @@ var ImageEditor = ({
6538
6635
  children: "Hold Compare"
6539
6636
  }
6540
6637
  ),
6541
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6638
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6542
6639
  "button",
6543
6640
  {
6544
6641
  type: "button",
@@ -6549,16 +6646,16 @@ var ImageEditor = ({
6549
6646
  )
6550
6647
  ] })
6551
6648
  ] }),
6552
- 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" }),
6553
- !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 }),
6554
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
6555
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6649
+ transformTool.active && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
6650
+ !transformTool.active && transformTool.error && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { role: "alert", className: "border-b border-rose-900 bg-rose-950/80 px-4 py-1.5 text-xs text-rose-200", children: transformTool.error }),
6651
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
6652
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6556
6653
  "div",
6557
6654
  {
6558
6655
  ref: containerRef,
6559
6656
  className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
6560
6657
  children: [
6561
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6658
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6562
6659
  "canvas",
6563
6660
  {
6564
6661
  ref: canvasRef,
@@ -6575,7 +6672,7 @@ var ImageEditor = ({
6575
6672
  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" : ""}`
6576
6673
  }
6577
6674
  ),
6578
- typeSession && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6675
+ typeSession && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6579
6676
  "textarea",
6580
6677
  {
6581
6678
  ref: typeInputRef,
@@ -6597,11 +6694,11 @@ var ImageEditor = ({
6597
6694
  ]
6598
6695
  }
6599
6696
  ),
6600
- /* @__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: [
6601
- activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6602
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
6603
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
6604
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6697
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "w-full md:w-80 bg-slate-900/90 border-t md:border-t-0 md:border-l border-slate-800 p-4 overflow-y-auto h-auto md:h-full md:max-h-[560px]", children: [
6698
+ activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6699
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
6700
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
6701
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6605
6702
  "button",
6606
6703
  {
6607
6704
  type: "button",
@@ -6613,7 +6710,7 @@ var ImageEditor = ({
6613
6710
  children: "Freeform"
6614
6711
  }
6615
6712
  ),
6616
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6713
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6617
6714
  "button",
6618
6715
  {
6619
6716
  type: "button",
@@ -6625,7 +6722,7 @@ var ImageEditor = ({
6625
6722
  children: "1:1 Square"
6626
6723
  }
6627
6724
  ),
6628
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6725
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6629
6726
  "button",
6630
6727
  {
6631
6728
  type: "button",
@@ -6637,7 +6734,7 @@ var ImageEditor = ({
6637
6734
  children: "4:3 Standard"
6638
6735
  }
6639
6736
  ),
6640
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6737
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6641
6738
  "button",
6642
6739
  {
6643
6740
  type: "button",
@@ -6649,7 +6746,7 @@ var ImageEditor = ({
6649
6746
  children: "16:9 Wide"
6650
6747
  }
6651
6748
  ),
6652
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6749
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6653
6750
  "button",
6654
6751
  {
6655
6752
  type: "button",
@@ -6661,7 +6758,7 @@ var ImageEditor = ({
6661
6758
  children: "3:2 Photo"
6662
6759
  }
6663
6760
  ),
6664
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6761
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6665
6762
  "button",
6666
6763
  {
6667
6764
  type: "button",
@@ -6674,10 +6771,10 @@ var ImageEditor = ({
6674
6771
  }
6675
6772
  )
6676
6773
  ] }),
6677
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6678
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
6679
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
6680
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6774
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6775
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
6776
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
6777
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6681
6778
  "button",
6682
6779
  {
6683
6780
  type: "button",
@@ -6686,7 +6783,7 @@ var ImageEditor = ({
6686
6783
  children: "Rotate -90\xB0"
6687
6784
  }
6688
6785
  ),
6689
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6786
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6690
6787
  "button",
6691
6788
  {
6692
6789
  type: "button",
@@ -6695,7 +6792,7 @@ var ImageEditor = ({
6695
6792
  children: "Rotate +90\xB0"
6696
6793
  }
6697
6794
  ),
6698
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6795
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6699
6796
  "button",
6700
6797
  {
6701
6798
  type: "button",
@@ -6704,7 +6801,7 @@ var ImageEditor = ({
6704
6801
  children: "Flip Horizontal"
6705
6802
  }
6706
6803
  ),
6707
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6804
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6708
6805
  "button",
6709
6806
  {
6710
6807
  type: "button",
@@ -6715,10 +6812,10 @@ var ImageEditor = ({
6715
6812
  )
6716
6813
  ] })
6717
6814
  ] }),
6718
- activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6719
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between", children: [
6720
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
6721
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6815
+ activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6816
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
6817
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
6818
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6722
6819
  "button",
6723
6820
  {
6724
6821
  type: "button",
@@ -6728,25 +6825,25 @@ var ImageEditor = ({
6728
6825
  }
6729
6826
  )
6730
6827
  ] }),
6731
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Histogram, { histogram: editor.histogram }),
6732
- import_image_editor14.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_react46.default.Fragment, { children: [
6733
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6828
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(Histogram, { histogram: editor.histogram }),
6829
+ import_image_editor15.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_react47.default.Fragment, { children: [
6830
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6734
6831
  ControlSlider,
6735
6832
  {
6736
6833
  spec,
6737
- value: (0, import_image_editor14.readAdjustmentControls)(state.adjustments)[spec.id],
6834
+ value: (0, import_image_editor15.readAdjustmentControls)(state.adjustments)[spec.id],
6738
6835
  disabled: spec.requiresProcess !== void 0 && legacyProcess,
6739
6836
  onChange: (v) => editor.setAdjustments({ [spec.id]: v })
6740
6837
  }
6741
6838
  ),
6742
- spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6839
+ spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6743
6840
  "div",
6744
6841
  {
6745
6842
  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",
6746
6843
  "data-testid": "image-editor-process-notice",
6747
6844
  children: [
6748
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
6749
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6845
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
6846
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6750
6847
  "button",
6751
6848
  {
6752
6849
  type: "button",
@@ -6759,7 +6856,7 @@ var ImageEditor = ({
6759
6856
  }
6760
6857
  )
6761
6858
  ] }, spec.id)),
6762
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6859
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6763
6860
  AdjustmentLayersPanel,
6764
6861
  {
6765
6862
  controller,
@@ -6768,9 +6865,9 @@ var ImageEditor = ({
6768
6865
  }
6769
6866
  ) })
6770
6867
  ] }),
6771
- activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6772
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
6773
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6868
+ activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6869
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
6870
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6774
6871
  "button",
6775
6872
  {
6776
6873
  type: "button",
@@ -6781,12 +6878,14 @@ var ImageEditor = ({
6781
6878
  children: "Free Transform"
6782
6879
  }
6783
6880
  ),
6784
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(LayersPanel, { controller })
6881
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(LayersPanel, { controller }),
6882
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Colour" }),
6883
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ColorProfilePanel, { controller })
6785
6884
  ] }),
6786
- activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6787
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
6788
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(BrushOptionsBar, { controller }),
6789
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6885
+ activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6886
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
6887
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(BrushOptionsBar, { controller }),
6888
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6790
6889
  "button",
6791
6890
  {
6792
6891
  type: "button",
@@ -6797,12 +6896,12 @@ var ImageEditor = ({
6797
6896
  children: "Free Transform"
6798
6897
  }
6799
6898
  ),
6800
- paintError && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
6801
- /* @__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 }) })
6899
+ paintError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
6900
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(LayersPanel, { controller }) })
6802
6901
  ] }),
6803
- activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6804
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Shape & Type Layers" }),
6805
- /* @__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)(
6902
+ activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6903
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Shape & Type Layers" }),
6904
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "grid grid-cols-2 gap-1.5", children: ["shape", "type"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6806
6905
  "button",
6807
6906
  {
6808
6907
  type: "button",
@@ -6813,13 +6912,13 @@ var ImageEditor = ({
6813
6912
  },
6814
6913
  t
6815
6914
  )) }),
6816
- state.activeTool === "shape" && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(ShapeOptionsBar, { controller, options: shapeOptions, onChange: setShapeOptions }),
6817
- state.activeTool === "type" && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TypeOptionsBar, { controller, options: typeOptions, onChange: setTypeOptions, session: typeSession }),
6818
- 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" }),
6819
- shapeTypeError && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "shape-type-error", children: shapeTypeError }),
6820
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6821
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
6822
- /* @__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)(
6915
+ state.activeTool === "shape" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ShapeOptionsBar, { controller, options: shapeOptions, onChange: setShapeOptions }),
6916
+ state.activeTool === "type" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TypeOptionsBar, { controller, options: typeOptions, onChange: setTypeOptions, session: typeSession }),
6917
+ state.activeTool === "type" && typeSession && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", onClick: finishTyping, className: "self-start rounded bg-slate-800 px-2 py-1 text-[11px] text-slate-200 hover:bg-slate-700", children: "Done editing text" }),
6918
+ shapeTypeError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "shape-type-error", children: shapeTypeError }),
6919
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6920
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
6921
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6823
6922
  "button",
6824
6923
  {
6825
6924
  type: "button",
@@ -6829,9 +6928,9 @@ var ImageEditor = ({
6829
6928
  },
6830
6929
  t
6831
6930
  )) }),
6832
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
6833
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("label", { className: "text-slate-400", children: "Color:" }),
6834
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6931
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
6932
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { className: "text-slate-400", children: "Color:" }),
6933
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6835
6934
  "input",
6836
6935
  {
6837
6936
  type: "color",
@@ -6840,15 +6939,15 @@ var ImageEditor = ({
6840
6939
  className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
6841
6940
  }
6842
6941
  ),
6843
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex-1 ml-2", children: [
6844
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
6845
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Width:" }),
6846
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "font-mono", children: [
6942
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex-1 ml-2", children: [
6943
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
6944
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Width:" }),
6945
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-mono", children: [
6847
6946
  strokeWidth,
6848
6947
  "px"
6849
6948
  ] })
6850
6949
  ] }),
6851
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6950
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6852
6951
  "input",
6853
6952
  {
6854
6953
  type: "range",
@@ -6861,10 +6960,10 @@ var ImageEditor = ({
6861
6960
  )
6862
6961
  ] })
6863
6962
  ] }),
6864
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6865
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
6866
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex gap-2", children: [
6867
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6963
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6964
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
6965
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex gap-2", children: [
6966
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6868
6967
  "input",
6869
6968
  {
6870
6969
  type: "text",
@@ -6875,7 +6974,7 @@ var ImageEditor = ({
6875
6974
  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"
6876
6975
  }
6877
6976
  ),
6878
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6977
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6879
6978
  "button",
6880
6979
  {
6881
6980
  type: "button",
@@ -6885,14 +6984,14 @@ var ImageEditor = ({
6885
6984
  }
6886
6985
  )
6887
6986
  ] }),
6888
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
6889
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Font Size:" }),
6890
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "font-mono", children: [
6987
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
6988
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Font Size:" }),
6989
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-mono", children: [
6891
6990
  fontSize,
6892
6991
  "px"
6893
6992
  ] })
6894
6993
  ] }),
6895
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6994
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6896
6995
  "input",
6897
6996
  {
6898
6997
  type: "range",
@@ -6903,14 +7002,14 @@ var ImageEditor = ({
6903
7002
  className: "w-full accent-indigo-500"
6904
7003
  }
6905
7004
  ),
6906
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6907
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between", children: [
6908
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { className: "text-slate-400", children: [
7005
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
7006
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7007
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "text-slate-400", children: [
6909
7008
  "Layers (",
6910
7009
  state.annotations.length,
6911
7010
  ")"
6912
7011
  ] }),
6913
- state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7012
+ state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6914
7013
  "button",
6915
7014
  {
6916
7015
  type: "button",
@@ -6919,7 +7018,7 @@ var ImageEditor = ({
6919
7018
  children: "Delete Selected"
6920
7019
  }
6921
7020
  ),
6922
- state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7021
+ state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6923
7022
  "button",
6924
7023
  {
6925
7024
  type: "button",
@@ -6930,10 +7029,10 @@ var ImageEditor = ({
6930
7029
  )
6931
7030
  ] })
6932
7031
  ] }),
6933
- activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6934
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between", children: [
6935
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
6936
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7032
+ activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
7033
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7034
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
7035
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6937
7036
  "button",
6938
7037
  {
6939
7038
  type: "button",
@@ -6943,8 +7042,8 @@ var ImageEditor = ({
6943
7042
  }
6944
7043
  )
6945
7044
  ] }),
6946
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
6947
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7045
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
7046
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6948
7047
  "input",
6949
7048
  {
6950
7049
  type: "checkbox",
@@ -6953,12 +7052,12 @@ var ImageEditor = ({
6953
7052
  className: "rounded accent-indigo-500"
6954
7053
  }
6955
7054
  ),
6956
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Enable Depth / Alpha Mask" })
7055
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Enable Depth / Alpha Mask" })
6957
7056
  ] }),
6958
- state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
6959
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { children: [
6960
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
6961
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7057
+ state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7058
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7059
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
7060
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6962
7061
  "input",
6963
7062
  {
6964
7063
  type: "text",
@@ -6969,8 +7068,8 @@ var ImageEditor = ({
6969
7068
  }
6970
7069
  )
6971
7070
  ] }),
6972
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex gap-2", children: [
6973
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7071
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex gap-2", children: [
7072
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6974
7073
  "button",
6975
7074
  {
6976
7075
  type: "button",
@@ -6979,7 +7078,7 @@ var ImageEditor = ({
6979
7078
  children: "Threshold Mode"
6980
7079
  }
6981
7080
  ),
6982
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7081
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6983
7082
  "button",
6984
7083
  {
6985
7084
  type: "button",
@@ -6989,12 +7088,12 @@ var ImageEditor = ({
6989
7088
  }
6990
7089
  )
6991
7090
  ] }),
6992
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { children: [
6993
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6994
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Depth Start (Lower):" }),
6995
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
7091
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7092
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7093
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Depth Start (Lower):" }),
7094
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
6996
7095
  ] }),
6997
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7096
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6998
7097
  "input",
6999
7098
  {
7000
7099
  type: "range",
@@ -7008,12 +7107,12 @@ var ImageEditor = ({
7008
7107
  }
7009
7108
  )
7010
7109
  ] }),
7011
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { children: [
7012
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7013
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Depth Stop (Upper):" }),
7014
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
7110
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7111
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7112
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Depth Stop (Upper):" }),
7113
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
7015
7114
  ] }),
7016
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7115
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7017
7116
  "input",
7018
7117
  {
7019
7118
  type: "range",
@@ -7027,12 +7126,12 @@ var ImageEditor = ({
7027
7126
  }
7028
7127
  )
7029
7128
  ] }),
7030
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { children: [
7031
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7032
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Softness:" }),
7033
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
7129
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
7130
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
7131
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Softness:" }),
7132
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
7034
7133
  ] }),
7035
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7134
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7036
7135
  "input",
7037
7136
  {
7038
7137
  type: "range",
@@ -7044,8 +7143,8 @@ var ImageEditor = ({
7044
7143
  }
7045
7144
  )
7046
7145
  ] }),
7047
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
7048
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7146
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
7147
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7049
7148
  "input",
7050
7149
  {
7051
7150
  type: "checkbox",
@@ -7054,12 +7153,12 @@ var ImageEditor = ({
7054
7153
  className: "rounded accent-indigo-500"
7055
7154
  }
7056
7155
  ),
7057
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Invert Mask" })
7156
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Invert Mask" })
7058
7157
  ] })
7059
7158
  ] })
7060
7159
  ] }),
7061
- activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7062
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7160
+ activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7161
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7063
7162
  SelectionOptionsBar,
7064
7163
  {
7065
7164
  controller,
@@ -7069,9 +7168,9 @@ var ImageEditor = ({
7069
7168
  quickMask: Boolean(state.quickMask)
7070
7169
  }
7071
7170
  ),
7072
- selectionError && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
7073
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex gap-1", children: [
7074
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7171
+ selectionError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
7172
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex gap-1", children: [
7173
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7075
7174
  "button",
7076
7175
  {
7077
7176
  type: "button",
@@ -7082,7 +7181,7 @@ var ImageEditor = ({
7082
7181
  children: "Transform Selection"
7083
7182
  }
7084
7183
  ),
7085
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7184
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7086
7185
  "button",
7087
7186
  {
7088
7187
  type: "button",
@@ -7094,12 +7193,12 @@ var ImageEditor = ({
7094
7193
  }
7095
7194
  )
7096
7195
  ] }),
7097
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
7196
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
7098
7197
  ] }),
7099
- activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7100
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
7101
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { children: "Results go to" }),
7102
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
7198
+ activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
7199
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
7200
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { children: "Results go to" }),
7201
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7103
7202
  "select",
7104
7203
  {
7105
7204
  "aria-label": "AI result target",
@@ -7107,54 +7206,54 @@ var ImageEditor = ({
7107
7206
  onChange: (e) => setAiTarget(e.target.value),
7108
7207
  className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
7109
7208
  children: [
7110
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
7111
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
7112
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("option", { value: "replace", children: "Replace image" })
7209
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
7210
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
7211
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("option", { value: "replace", children: "Replace image" })
7113
7212
  ]
7114
7213
  }
7115
7214
  )
7116
7215
  ] }),
7117
- /* @__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: [
7118
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between", children: [
7119
- /* @__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: [
7120
- /* @__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" }) }),
7216
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
7217
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7218
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
7219
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("svg", { className: "w-3.5 h-3.5 text-indigo-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "M6 3v12M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" }) }),
7121
7220
  "Background Removal"
7122
7221
  ] }),
7123
- 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..." })
7222
+ isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-indigo-900/60 text-indigo-300 animate-pulse", children: "Removing..." })
7124
7223
  ] }),
7125
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
7126
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7224
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
7225
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7127
7226
  "button",
7128
7227
  {
7129
7228
  type: "button",
7130
7229
  onClick: handleRemoveBackground,
7131
7230
  disabled: isRemovingBg || isInpainting,
7132
7231
  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",
7133
- children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
7134
- /* @__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" }),
7232
+ children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7233
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
7135
7234
  "Removing Background..."
7136
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
7137
- /* @__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" }) }),
7235
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7236
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
7138
7237
  "Remove Background"
7139
7238
  ] })
7140
7239
  }
7141
7240
  )
7142
7241
  ] }),
7143
- /* @__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: [
7144
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center justify-between", children: [
7145
- /* @__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: [
7146
- /* @__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: [
7147
- /* @__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" }),
7148
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("path", { d: "m14 7 3 3" })
7242
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
7243
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between", children: [
7244
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
7245
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
7246
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "m21.64 3.64-1.28-1.28a1.2 1.2 0 0 0-1.7 0l-9.72 9.72-1.94 4.86 4.86-1.94 9.72-9.72a1.2 1.2 0 0 0 .06-1.64z" }),
7247
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "m14 7 3 3" })
7149
7248
  ] }),
7150
7249
  "Generative Inpainting"
7151
7250
  ] }),
7152
- 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..." })
7251
+ isInpainting && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded text-[10px] font-medium bg-purple-900/60 text-purple-300 animate-pulse", children: "Inpainting..." })
7153
7252
  ] }),
7154
- /* @__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." }),
7155
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1", children: [
7156
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
7157
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7253
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
7254
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-1", children: [
7255
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
7256
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7158
7257
  "textarea",
7159
7258
  {
7160
7259
  id: "ai-inpaint-prompt-react",
@@ -7166,10 +7265,10 @@ var ImageEditor = ({
7166
7265
  }
7167
7266
  )
7168
7267
  ] }),
7169
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1", children: [
7170
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
7171
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
7172
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
7268
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-1", children: [
7269
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
7270
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
7271
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7173
7272
  "button",
7174
7273
  {
7175
7274
  type: "button",
@@ -7182,7 +7281,7 @@ var ImageEditor = ({
7182
7281
  ]
7183
7282
  }
7184
7283
  ),
7185
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
7284
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7186
7285
  "button",
7187
7286
  {
7188
7287
  type: "button",
@@ -7197,25 +7296,25 @@ var ImageEditor = ({
7197
7296
  )
7198
7297
  ] })
7199
7298
  ] }),
7200
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7299
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7201
7300
  "button",
7202
7301
  {
7203
7302
  type: "button",
7204
7303
  onClick: handleInpaint,
7205
7304
  disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
7206
7305
  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",
7207
- children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
7208
- /* @__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" }),
7306
+ children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7307
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
7209
7308
  "Generating Inpaint..."
7210
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
7211
- /* @__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" }) }),
7309
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
7310
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("svg", { className: "w-3.5 h-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }),
7212
7311
  "Apply Inpainting"
7213
7312
  ] })
7214
7313
  }
7215
7314
  )
7216
7315
  ] }),
7217
- 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 }),
7218
- 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 })
7316
+ aiError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
7317
+ aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
7219
7318
  ] })
7220
7319
  ] })
7221
7320
  ] })
@@ -7225,7 +7324,7 @@ var ImageEditor = ({
7225
7324
  };
7226
7325
 
7227
7326
  // src/review/useReview.ts
7228
- var import_react47 = require("react");
7327
+ var import_react48 = require("react");
7229
7328
  var import_editor12 = require("@pixerate/editor");
7230
7329
  var EMPTY_COMMENTS = Object.freeze({
7231
7330
  threads: [],
@@ -7244,23 +7343,23 @@ function isCommentStore(value) {
7244
7343
  }
7245
7344
  function useComments(source) {
7246
7345
  const store = isCommentStore(source) ? source : (0, import_editor12.getCommentStore)(source);
7247
- const subscribe = (0, import_react47.useCallback)(
7346
+ const subscribe = (0, import_react48.useCallback)(
7248
7347
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
7249
7348
  [store]
7250
7349
  );
7251
7350
  const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;
7252
- const snapshot = (0, import_react47.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7253
- return (0, import_react47.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
7351
+ const snapshot = (0, import_react48.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7352
+ return (0, import_react48.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
7254
7353
  }
7255
7354
  function useTrackChanges(editor) {
7256
7355
  const store = (0, import_editor12.getTrackChangesStore)(editor ?? null);
7257
- const subscribe = (0, import_react47.useCallback)(
7356
+ const subscribe = (0, import_react48.useCallback)(
7258
7357
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
7259
7358
  [store]
7260
7359
  );
7261
7360
  const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;
7262
- const snapshot = (0, import_react47.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7263
- return (0, import_react47.useMemo)(() => {
7361
+ const snapshot = (0, import_react48.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7362
+ return (0, import_react48.useMemo)(() => {
7264
7363
  const run = (fn) => () => {
7265
7364
  if (editor && !editor.isDestroyed) fn(editor);
7266
7365
  };
@@ -7283,9 +7382,9 @@ function useTrackChanges(editor) {
7283
7382
  }
7284
7383
 
7285
7384
  // src/review/CommentsPanel.tsx
7286
- var import_react48 = require("react");
7385
+ var import_react49 = require("react");
7287
7386
  var import_editor13 = require("@pixerate/editor");
7288
- var import_jsx_runtime30 = require("react/jsx-runtime");
7387
+ var import_jsx_runtime31 = require("react/jsx-runtime");
7289
7388
  var buttonClass2 = "rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50";
7290
7389
  var primaryButtonClass = "rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50";
7291
7390
  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";
@@ -7299,18 +7398,18 @@ var CommentsPanel = ({
7299
7398
  emptyMessage = "No comments yet. Select text and add a comment."
7300
7399
  }) => {
7301
7400
  const { threads, activeThreadId, store } = useComments(storeProp ?? editor);
7302
- const [showResolved, setShowResolved] = (0, import_react48.useState)(showResolvedInitial);
7401
+ const [showResolved, setShowResolved] = (0, import_react49.useState)(showResolvedInitial);
7303
7402
  const author = authorProp ?? (0, import_editor13.getCommentAuthor)(editor) ?? { id: "anonymous", name: "Anonymous" };
7304
7403
  const visible = threads.filter((t) => showResolved || !t.resolved);
7305
7404
  const resolvedCount = threads.filter((t) => t.resolved).length;
7306
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("aside", { className, "aria-label": "Comments", children: [
7307
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
7308
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
7405
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("aside", { className, "aria-label": "Comments", children: [
7406
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
7407
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
7309
7408
  threads.length - resolvedCount,
7310
7409
  " open",
7311
7410
  resolvedCount > 0 ? ` \xB7 ${resolvedCount} resolved` : ""
7312
7411
  ] }),
7313
- resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7412
+ resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7314
7413
  "button",
7315
7414
  {
7316
7415
  type: "button",
@@ -7321,7 +7420,7 @@ var CommentsPanel = ({
7321
7420
  }
7322
7421
  )
7323
7422
  ] }),
7324
- 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)(
7423
+ visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("ul", { className: "flex flex-col gap-2", role: "list", children: visible.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7325
7424
  CommentThreadCard,
7326
7425
  {
7327
7426
  thread,
@@ -7343,7 +7442,7 @@ var CommentThreadCard = ({
7343
7442
  author,
7344
7443
  formatTime
7345
7444
  }) => {
7346
- const [draft, setDraft] = (0, import_react48.useState)("");
7445
+ const [draft, setDraft] = (0, import_react49.useState)("");
7347
7446
  const isDraft = thread.body === "";
7348
7447
  const quote = thread.anchor?.quote ?? thread.lastQuote ?? "";
7349
7448
  const live = editor && !editor.isDestroyed ? editor : null;
@@ -7369,7 +7468,7 @@ var CommentThreadCard = ({
7369
7468
  setDraft("");
7370
7469
  };
7371
7470
  const stop = (e) => e.stopPropagation();
7372
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7471
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
7373
7472
  "li",
7374
7473
  {
7375
7474
  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" : ""}`,
@@ -7385,24 +7484,24 @@ var CommentThreadCard = ({
7385
7484
  }
7386
7485
  },
7387
7486
  children: [
7388
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
7389
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-medium", children: thread.author.name }),
7390
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
7487
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
7488
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "font-medium", children: thread.author.name }),
7489
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
7391
7490
  ] }),
7392
- 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 }),
7393
- thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
7394
- thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
7395
- !isDraft && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
7396
- 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: [
7397
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "text-xs", children: [
7398
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-medium", children: reply.author.name }),
7491
+ quote && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("blockquote", { className: "border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2", children: quote }),
7492
+ thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
7493
+ thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
7494
+ !isDraft && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
7495
+ thread.replies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("ul", { className: "flex flex-col gap-2 border-l border-border pl-3", role: "list", children: thread.replies.map((reply) => /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("li", { className: "flex flex-col gap-0.5", "data-reply-id": reply.id, children: [
7496
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "text-xs", children: [
7497
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "font-medium", children: reply.author.name }),
7399
7498
  " ",
7400
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
7499
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
7401
7500
  ] }),
7402
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
7501
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
7403
7502
  ] }, reply.id)) }),
7404
- (active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
7405
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7503
+ (active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
7504
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7406
7505
  "textarea",
7407
7506
  {
7408
7507
  className: textareaClass,
@@ -7420,9 +7519,9 @@ var CommentThreadCard = ({
7420
7519
  }
7421
7520
  }
7422
7521
  ),
7423
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-end gap-1", children: [
7424
- isDraft && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
7425
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7522
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex justify-end gap-1", children: [
7523
+ isDraft && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
7524
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7426
7525
  "button",
7427
7526
  {
7428
7527
  type: "button",
@@ -7434,9 +7533,9 @@ var CommentThreadCard = ({
7434
7533
  )
7435
7534
  ] })
7436
7535
  ] }),
7437
- !isDraft && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
7438
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
7439
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7536
+ !isDraft && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
7537
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
7538
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7440
7539
  "button",
7441
7540
  {
7442
7541
  type: "button",
@@ -7452,7 +7551,7 @@ var CommentThreadCard = ({
7452
7551
  };
7453
7552
 
7454
7553
  // src/review/ReviewToolbar.tsx
7455
- var import_jsx_runtime31 = require("react/jsx-runtime");
7554
+ var import_jsx_runtime32 = require("react/jsx-runtime");
7456
7555
  var defaultDescriptionClass = "max-w-[16rem] truncate px-1 text-xs text-muted-foreground";
7457
7556
  var buttonClass3 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
7458
7557
  var ReviewToolbar = ({
@@ -7465,8 +7564,8 @@ var ReviewToolbar = ({
7465
7564
  const count = review.changes.length;
7466
7565
  const current = review.currentChange;
7467
7566
  const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;
7468
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
7469
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7567
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
7568
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7470
7569
  "button",
7471
7570
  {
7472
7571
  type: "button",
@@ -7477,8 +7576,8 @@ var ReviewToolbar = ({
7477
7576
  children: review.enabled ? "Tracking on" : "Track changes"
7478
7577
  }
7479
7578
  ),
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)(
7579
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7580
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7482
7581
  "button",
7483
7582
  {
7484
7583
  type: "button",
@@ -7489,8 +7588,8 @@ var ReviewToolbar = ({
7489
7588
  children: "\u2039"
7490
7589
  }
7491
7590
  ),
7492
- /* @__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` }),
7493
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7591
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "min-w-[4rem] text-center text-xs text-muted-foreground", "aria-live": "polite", children: count === 0 ? "No changes" : current ? `${index} of ${count}` : `${count} changes` }),
7592
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7494
7593
  "button",
7495
7594
  {
7496
7595
  type: "button",
@@ -7501,7 +7600,7 @@ var ReviewToolbar = ({
7501
7600
  children: "\u203A"
7502
7601
  }
7503
7602
  ),
7504
- showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
7603
+ showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7505
7604
  "span",
7506
7605
  {
7507
7606
  className: descriptionClassName,
@@ -7513,8 +7612,8 @@ var ReviewToolbar = ({
7513
7612
  ]
7514
7613
  }
7515
7614
  ),
7516
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7517
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7615
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7616
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7518
7617
  "button",
7519
7618
  {
7520
7619
  type: "button",
@@ -7524,7 +7623,7 @@ var ReviewToolbar = ({
7524
7623
  children: "Accept"
7525
7624
  }
7526
7625
  ),
7527
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7626
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7528
7627
  "button",
7529
7628
  {
7530
7629
  type: "button",
@@ -7534,18 +7633,18 @@ var ReviewToolbar = ({
7534
7633
  children: "Reject"
7535
7634
  }
7536
7635
  ),
7537
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
7538
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
7636
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
7637
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
7539
7638
  ] });
7540
7639
  };
7541
7640
 
7542
7641
  // src/review/CommentButton.tsx
7543
- var import_jsx_runtime32 = require("react/jsx-runtime");
7642
+ var import_jsx_runtime33 = require("react/jsx-runtime");
7544
7643
  var CommentButton = ({
7545
7644
  editor,
7546
7645
  className = "rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted",
7547
7646
  children = "Comment"
7548
- }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7647
+ }) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7549
7648
  "button",
7550
7649
  {
7551
7650
  type: "button",
@@ -7557,13 +7656,13 @@ var CommentButton = ({
7557
7656
  );
7558
7657
 
7559
7658
  // src/review/useDocumentCompare.ts
7560
- var import_react49 = require("react");
7659
+ var import_react50 = require("react");
7561
7660
  var import_editor14 = require("@pixerate/editor");
7562
7661
  function useDocumentCompare(editor, options) {
7563
- const [summary, setSummary] = (0, import_react49.useState)(null);
7564
- const defaults = (0, import_react49.useRef)(options);
7662
+ const [summary, setSummary] = (0, import_react50.useState)(null);
7663
+ const defaults = (0, import_react50.useRef)(options);
7565
7664
  defaults.current = options;
7566
- const compare = (0, import_react49.useCallback)(
7665
+ const compare = (0, import_react50.useCallback)(
7567
7666
  (original, revised, overrides) => {
7568
7667
  if (!editor || editor.isDestroyed) return null;
7569
7668
  const result = (0, import_editor14.applyDocumentComparison)(editor, original, revised, {
@@ -7575,13 +7674,13 @@ function useDocumentCompare(editor, options) {
7575
7674
  },
7576
7675
  [editor]
7577
7676
  );
7578
- const clear = (0, import_react49.useCallback)(() => setSummary(null), []);
7579
- return (0, import_react49.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
7677
+ const clear = (0, import_react50.useCallback)(() => setSummary(null), []);
7678
+ return (0, import_react50.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
7580
7679
  }
7581
7680
 
7582
7681
  // src/review/TrackedChangesList.tsx
7583
7682
  var import_editor15 = require("@pixerate/editor");
7584
- var import_jsx_runtime33 = require("react/jsx-runtime");
7683
+ var import_jsx_runtime34 = require("react/jsx-runtime");
7585
7684
  var buttonClass4 = "rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40";
7586
7685
  var TrackedChangesList = ({
7587
7686
  editor,
@@ -7592,18 +7691,18 @@ var TrackedChangesList = ({
7592
7691
  }) => {
7593
7692
  const review = useTrackChanges(editor);
7594
7693
  if (review.changes.length === 0) {
7595
- 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 }) });
7694
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className, "data-tracked-changes-list": "", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "pixerate-changes-empty text-xs text-muted-foreground", children: emptyState }) });
7596
7695
  }
7597
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
7696
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
7598
7697
  const active = change.id === review.currentChangeId;
7599
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
7698
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7600
7699
  "li",
7601
7700
  {
7602
7701
  className: active ? `${itemClassName} ${activeItemClassName}` : itemClassName,
7603
7702
  "data-change-type": change.type,
7604
7703
  "data-change-id": change.id,
7605
7704
  children: [
7606
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
7705
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7607
7706
  "button",
7608
7707
  {
7609
7708
  type: "button",
@@ -7611,14 +7710,14 @@ var TrackedChangesList = ({
7611
7710
  title: `${change.author.name}: ${change.description}`,
7612
7711
  onClick: () => review.select(change.id),
7613
7712
  children: [
7614
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
7713
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
7615
7714
  change.author.name ? ` \xB7 ${change.author.name}` : "",
7616
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
7715
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
7617
7716
  ]
7618
7717
  }
7619
7718
  ),
7620
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
7621
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
7719
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
7720
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
7622
7721
  ]
7623
7722
  },
7624
7723
  `${change.type}:${change.id}`
@@ -7627,12 +7726,12 @@ var TrackedChangesList = ({
7627
7726
  };
7628
7727
 
7629
7728
  // src/commands/useCommandPalette.ts
7630
- var import_react50 = require("react");
7729
+ var import_react51 = require("react");
7631
7730
  var import_commands2 = require("@pixerate/editor/commands");
7632
7731
  function useCommandPalette(registry, options = {}) {
7633
- const optionsRef = (0, import_react50.useRef)(options);
7732
+ const optionsRef = (0, import_react51.useRef)(options);
7634
7733
  optionsRef.current = options;
7635
- const controller = (0, import_react50.useMemo)(
7734
+ const controller = (0, import_react51.useMemo)(
7636
7735
  () => (0, import_commands2.createCommandPaletteController)(registry, {
7637
7736
  context: () => {
7638
7737
  const c = optionsRef.current.context;
@@ -7653,9 +7752,9 @@ function useCommandPalette(registry, options = {}) {
7653
7752
  // eslint-disable-next-line react-hooks/exhaustive-deps
7654
7753
  [registry]
7655
7754
  );
7656
- const state = (0, import_react50.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
7755
+ const state = (0, import_react51.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
7657
7756
  const { hotkey, hotkeyTarget } = options;
7658
- (0, import_react50.useEffect)(() => {
7757
+ (0, import_react51.useEffect)(() => {
7659
7758
  if (!hotkey) return;
7660
7759
  const target = hotkeyTarget ?? (typeof window !== "undefined" ? window : null);
7661
7760
  if (!target) return;
@@ -7683,13 +7782,13 @@ function useCommandPalette(registry, options = {}) {
7683
7782
  }
7684
7783
 
7685
7784
  // src/commands/CommandPalette.tsx
7686
- var import_react51 = __toESM(require("react"), 1);
7687
- var import_jsx_runtime34 = require("react/jsx-runtime");
7785
+ var import_react52 = __toESM(require("react"), 1);
7786
+ var import_jsx_runtime35 = require("react/jsx-runtime");
7688
7787
  function HighlightedLabel({ item }) {
7689
- if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_jsx_runtime34.Fragment, { children: item.label });
7788
+ if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_jsx_runtime35.Fragment, { children: item.label });
7690
7789
  const marked = new Set(item.labelIndices);
7691
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_jsx_runtime34.Fragment, { children: Array.from(item.label).map(
7692
- (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)
7790
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_jsx_runtime35.Fragment, { children: Array.from(item.label).map(
7791
+ (ch, i) => marked.has(i) ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "font-semibold text-foreground", "data-match": "", children: ch }, i) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_react52.default.Fragment, { children: ch }, i)
7693
7792
  ) });
7694
7793
  }
7695
7794
  var CommandPalette = ({
@@ -7698,22 +7797,22 @@ var CommandPalette = ({
7698
7797
  emptyMessage = "No matching commands",
7699
7798
  className = ""
7700
7799
  }) => {
7701
- const inputRef = (0, import_react51.useRef)(null);
7702
- const listRef = (0, import_react51.useRef)(null);
7703
- const baseId = (0, import_react51.useId)();
7800
+ const inputRef = (0, import_react52.useRef)(null);
7801
+ const listRef = (0, import_react52.useRef)(null);
7802
+ const baseId = (0, import_react52.useId)();
7704
7803
  const listId = `${baseId}-list`;
7705
7804
  const optionId = (index) => `${baseId}-option-${index}`;
7706
7805
  const { open, query, items, activeIndex } = palette;
7707
- (0, import_react51.useEffect)(() => {
7806
+ (0, import_react52.useEffect)(() => {
7708
7807
  if (open) inputRef.current?.focus();
7709
7808
  }, [open]);
7710
- (0, import_react51.useEffect)(() => {
7809
+ (0, import_react52.useEffect)(() => {
7711
7810
  if (!open) return;
7712
7811
  const active = listRef.current?.querySelector('[aria-selected="true"]');
7713
7812
  active?.scrollIntoView?.({ block: "nearest" });
7714
7813
  }, [open, activeIndex]);
7715
7814
  if (!open) return null;
7716
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7815
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7717
7816
  "div",
7718
7817
  {
7719
7818
  className: "fixed inset-0 z-50 flex items-start justify-center bg-black/30 px-4 pt-[15vh]",
@@ -7721,7 +7820,7 @@ var CommandPalette = ({
7721
7820
  onMouseDown: (e) => {
7722
7821
  if (e.target === e.currentTarget) palette.setOpen(false);
7723
7822
  },
7724
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7823
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7725
7824
  "div",
7726
7825
  {
7727
7826
  role: "dialog",
@@ -7730,7 +7829,7 @@ var CommandPalette = ({
7730
7829
  className: `w-full max-w-lg overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-xl ${className}`,
7731
7830
  style: { background: "var(--popover, var(--background, #fff))" },
7732
7831
  children: [
7733
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7832
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7734
7833
  "input",
7735
7834
  {
7736
7835
  ref: inputRef,
@@ -7750,7 +7849,7 @@ var CommandPalette = ({
7750
7849
  className: "w-full border-b border-border bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground"
7751
7850
  }
7752
7851
  ),
7753
- 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)(
7852
+ items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { ref: listRef, id: listId, role: "listbox", "aria-label": "Commands", className: "max-h-80 overflow-y-auto py-1", children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7754
7853
  "li",
7755
7854
  {
7756
7855
  id: optionId(index),
@@ -7765,12 +7864,12 @@ var CommandPalette = ({
7765
7864
  onClick: () => palette.run(item.id),
7766
7865
  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"}`,
7767
7866
  children: [
7768
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
7769
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(HighlightedLabel, { item }),
7770
- item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
7867
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
7868
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(HighlightedLabel, { item }),
7869
+ item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
7771
7870
  ] }),
7772
- item.group && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
7773
- 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 })
7871
+ item.group && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
7872
+ item.shortcut && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("kbd", { className: "shrink-0 rounded border border-border px-1.5 font-mono text-[10px] text-muted-foreground", children: item.shortcut })
7774
7873
  ]
7775
7874
  },
7776
7875
  item.id
@@ -7783,12 +7882,12 @@ var CommandPalette = ({
7783
7882
  };
7784
7883
 
7785
7884
  // src/commands/useCommandShortcuts.ts
7786
- var import_react52 = require("react");
7885
+ var import_react53 = require("react");
7787
7886
  function useCommandShortcuts(registry, options = {}) {
7788
- const optionsRef = (0, import_react52.useRef)(options);
7887
+ const optionsRef = (0, import_react53.useRef)(options);
7789
7888
  optionsRef.current = options;
7790
7889
  const { enabled = true, target } = options;
7791
- (0, import_react52.useEffect)(() => {
7890
+ (0, import_react53.useEffect)(() => {
7792
7891
  if (!registry || !enabled) return;
7793
7892
  const eventTarget = target ?? (typeof window !== "undefined" ? window : null);
7794
7893
  if (!eventTarget) return;
@@ -7806,14 +7905,14 @@ function useCommandShortcuts(registry, options = {}) {
7806
7905
  }, [registry, enabled, target]);
7807
7906
  }
7808
7907
  function useRegisterCommands(registry, specs) {
7809
- (0, import_react52.useEffect)(() => {
7908
+ (0, import_react53.useEffect)(() => {
7810
7909
  if (!registry || !specs || specs.length === 0) return;
7811
7910
  return registry.register(specs);
7812
7911
  }, [registry, specs]);
7813
7912
  }
7814
7913
 
7815
7914
  // src/persistence/useAutosave.ts
7816
- var import_react53 = require("react");
7915
+ var import_react54 = require("react");
7817
7916
  var import_persistence = require("@pixerate/editor/persistence");
7818
7917
  var IDLE = {
7819
7918
  status: "idle",
@@ -7824,18 +7923,18 @@ var IDLE = {
7824
7923
  ready: false
7825
7924
  };
7826
7925
  function useAutosave(options) {
7827
- const optionsRef = (0, import_react53.useRef)(options);
7926
+ const optionsRef = (0, import_react54.useRef)(options);
7828
7927
  optionsRef.current = options;
7829
7928
  const { storage, key, history, dirty } = options;
7830
7929
  const recover = options.recover !== false;
7831
7930
  const flushOnHide = options.flushOnHide !== false;
7832
7931
  const ready = options.ready !== false;
7833
- const [controller, setController] = (0, import_react53.useState)(null);
7834
- const [status, setStatus] = (0, import_react53.useState)(IDLE);
7835
- const [recovery, setRecovery] = (0, import_react53.useState)(null);
7836
- const [pendingRecovery, setPendingRecovery] = (0, import_react53.useState)(recover);
7837
- const revisionsRef = (0, import_react53.useRef)(null);
7838
- (0, import_react53.useEffect)(() => {
7932
+ const [controller, setController] = (0, import_react54.useState)(null);
7933
+ const [status, setStatus] = (0, import_react54.useState)(IDLE);
7934
+ const [recovery, setRecovery] = (0, import_react54.useState)(null);
7935
+ const [pendingRecovery, setPendingRecovery] = (0, import_react54.useState)(recover);
7936
+ const revisionsRef = (0, import_react54.useRef)(null);
7937
+ (0, import_react54.useEffect)(() => {
7839
7938
  const revisions = (0, import_persistence.createRevisionTracker)({ history, dirty });
7840
7939
  const o = optionsRef.current;
7841
7940
  const instance = (0, import_persistence.createAutosaveController)({
@@ -7878,10 +7977,10 @@ function useAutosave(options) {
7878
7977
  if (revisionsRef.current === revisions) revisionsRef.current = null;
7879
7978
  };
7880
7979
  }, [storage, key, history, dirty, recover]);
7881
- (0, import_react53.useEffect)(() => {
7980
+ (0, import_react54.useEffect)(() => {
7882
7981
  if (controller && ready && !pendingRecovery) controller.ready();
7883
7982
  }, [controller, ready, pendingRecovery]);
7884
- (0, import_react53.useEffect)(() => {
7983
+ (0, import_react54.useEffect)(() => {
7885
7984
  if (!controller || !flushOnHide || typeof window === "undefined") return;
7886
7985
  const flush = () => void controller.flushNow();
7887
7986
  const onVisibility = () => {
@@ -7894,31 +7993,31 @@ function useAutosave(options) {
7894
7993
  document.removeEventListener("visibilitychange", onVisibility);
7895
7994
  };
7896
7995
  }, [controller, flushOnHide]);
7897
- const restore = (0, import_react53.useCallback)(() => {
7996
+ const restore = (0, import_react54.useCallback)(() => {
7898
7997
  const snapshot = recovery?.snapshot;
7899
7998
  setRecovery(null);
7900
7999
  setPendingRecovery(false);
7901
8000
  return snapshot;
7902
8001
  }, [recovery]);
7903
- const discard = (0, import_react53.useCallback)(async () => {
8002
+ const discard = (0, import_react54.useCallback)(async () => {
7904
8003
  if (controller) await controller.discardRecovery();
7905
8004
  setRecovery(null);
7906
8005
  setPendingRecovery(false);
7907
8006
  }, [controller]);
7908
- const flushNow = (0, import_react53.useCallback)(async () => {
8007
+ const flushNow = (0, import_react54.useCallback)(async () => {
7909
8008
  await controller?.flushNow();
7910
8009
  }, [controller]);
7911
- const markClean = (0, import_react53.useCallback)(async () => {
8010
+ const markClean = (0, import_react54.useCallback)(async () => {
7912
8011
  revisionsRef.current?.markSaved();
7913
8012
  await controller?.markClean();
7914
8013
  }, [controller]);
7915
- const notifyChange = (0, import_react53.useCallback)(() => revisionsRef.current?.bump(), []);
8014
+ const notifyChange = (0, import_react54.useCallback)(() => revisionsRef.current?.bump(), []);
7916
8015
  return { status, recovery, pendingRecovery, restore, discard, flushNow, markClean, notifyChange, controller };
7917
8016
  }
7918
8017
 
7919
8018
  // src/persistence/RecoveryPrompt.tsx
7920
8019
  var import_persistence2 = require("@pixerate/editor/persistence");
7921
- var import_jsx_runtime35 = require("react/jsx-runtime");
8020
+ var import_jsx_runtime36 = require("react/jsx-runtime");
7922
8021
  var RecoveryPrompt = ({
7923
8022
  recovery,
7924
8023
  onRestore,
@@ -7930,7 +8029,7 @@ var RecoveryPrompt = ({
7930
8029
  }) => {
7931
8030
  if (!recovery) return null;
7932
8031
  const { name } = recovery.meta;
7933
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
8032
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7934
8033
  "div",
7935
8034
  {
7936
8035
  role: "alertdialog",
@@ -7938,15 +8037,15 @@ var RecoveryPrompt = ({
7938
8037
  "data-recovery-prompt": "",
7939
8038
  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}`,
7940
8039
  children: [
7941
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "min-w-0 flex-1", children: [
8040
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "min-w-0 flex-1", children: [
7942
8041
  (0, import_persistence2.formatRecoveryMessage)(recovery.meta, formatTime),
7943
- name ? /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
8042
+ name ? /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
7944
8043
  "(",
7945
8044
  name,
7946
8045
  ")"
7947
8046
  ] }) : null
7948
8047
  ] }),
7949
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
8048
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7950
8049
  "button",
7951
8050
  {
7952
8051
  type: "button",
@@ -7956,7 +8055,7 @@ var RecoveryPrompt = ({
7956
8055
  children: restoreLabel
7957
8056
  }
7958
8057
  ),
7959
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
8058
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7960
8059
  "button",
7961
8060
  {
7962
8061
  type: "button",
@@ -7972,17 +8071,17 @@ var RecoveryPrompt = ({
7972
8071
  };
7973
8072
 
7974
8073
  // src/generation/useGenerationPlan.ts
7975
- var import_react54 = require("react");
8074
+ var import_react55 = require("react");
7976
8075
  var import_generation = require("@pixerate/editor/generation");
7977
8076
  function useGenerationPlan(request, capabilities, options = {}) {
7978
8077
  const key = JSON.stringify([request, capabilities, options]);
7979
- return (0, import_react54.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
8078
+ return (0, import_react55.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
7980
8079
  }
7981
8080
  function useJobProgress(options) {
7982
8081
  const { startedAt, expectedMs, done, now, intervalMs = 1e3 } = options;
7983
- const [tick, setTick] = (0, import_react54.useState)(() => Date.now());
8082
+ const [tick, setTick] = (0, import_react55.useState)(() => Date.now());
7984
8083
  const ticking = !done && now === void 0;
7985
- (0, import_react54.useEffect)(() => {
8084
+ (0, import_react55.useEffect)(() => {
7986
8085
  if (!ticking) return;
7987
8086
  setTick(Date.now());
7988
8087
  const id = setInterval(() => setTick(Date.now()), Math.max(16, intervalMs));
@@ -7992,9 +8091,9 @@ function useJobProgress(options) {
7992
8091
  }
7993
8092
 
7994
8093
  // src/generation/GenerationSettings.tsx
7995
- var import_react55 = require("react");
8094
+ var import_react56 = require("react");
7996
8095
  var import_generation2 = require("@pixerate/editor/generation");
7997
- var import_jsx_runtime36 = require("react/jsx-runtime");
8096
+ var import_jsx_runtime37 = require("react/jsx-runtime");
7998
8097
  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";
7999
8098
  function Control({
8000
8099
  control,
@@ -8004,7 +8103,7 @@ function Control({
8004
8103
  }) {
8005
8104
  const shown = value ?? control.defaultValue;
8006
8105
  if (control.kind === "checkbox") {
8007
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8106
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8008
8107
  "input",
8009
8108
  {
8010
8109
  id,
@@ -8016,7 +8115,7 @@ function Control({
8016
8115
  );
8017
8116
  }
8018
8117
  if (control.kind === "select") {
8019
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
8118
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
8020
8119
  "select",
8021
8120
  {
8022
8121
  id,
@@ -8025,14 +8124,14 @@ function Control({
8025
8124
  value: shown === void 0 ? "" : String(shown),
8026
8125
  onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value)),
8027
8126
  children: [
8028
- shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: "", children: "Default" }),
8029
- control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
8127
+ shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("option", { value: "", children: "Default" }),
8128
+ control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
8030
8129
  ]
8031
8130
  }
8032
8131
  );
8033
8132
  }
8034
8133
  if (control.kind === "textarea") {
8035
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8134
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8036
8135
  "textarea",
8037
8136
  {
8038
8137
  id,
@@ -8046,8 +8145,8 @@ function Control({
8046
8145
  );
8047
8146
  }
8048
8147
  const numeric = typeof shown === "number" ? shown : void 0;
8049
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-2", children: [
8050
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8148
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-2", children: [
8149
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8051
8150
  "input",
8052
8151
  {
8053
8152
  id,
@@ -8061,7 +8160,7 @@ function Control({
8061
8160
  onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value))
8062
8161
  }
8063
8162
  ),
8064
- 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" })
8163
+ control.kind === "range" && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "w-10 text-right tabular-nums text-muted-foreground", "data-field-value": "", children: numeric ?? "\u2013" })
8065
8164
  ] });
8066
8165
  }
8067
8166
  var GenerationSettings = ({
@@ -8075,17 +8174,17 @@ var GenerationSettings = ({
8075
8174
  renderReference,
8076
8175
  className = ""
8077
8176
  }) => {
8078
- const baseId = (0, import_react55.useId)();
8079
- const controls = (0, import_react55.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
8177
+ const baseId = (0, import_react56.useId)();
8178
+ const controls = (0, import_react56.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
8080
8179
  const computed = useGenerationPlan(value, capabilities, { strategy });
8081
8180
  const plan = planProp ?? computed;
8082
8181
  const slots = (0, import_generation2.getReferenceSlots)(capabilities, value);
8083
- 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: [
8182
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: `flex flex-col gap-3 text-sm ${className}`, "data-generation-settings": "", "data-model": capabilities.id, children: [
8084
8183
  controls.map((control) => {
8085
8184
  const id = `${baseId}-${control.key}`;
8086
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
8087
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
8088
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8185
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
8186
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
8187
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8089
8188
  Control,
8090
8189
  {
8091
8190
  control,
@@ -8096,23 +8195,23 @@ var GenerationSettings = ({
8096
8195
  )
8097
8196
  ] }, control.key);
8098
8197
  }),
8099
- slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
8100
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
8198
+ slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
8199
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
8101
8200
  slot.label,
8102
8201
  " ",
8103
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
8202
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
8104
8203
  "(",
8105
8204
  slot.references.length,
8106
8205
  "/",
8107
8206
  slot.max,
8108
8207
  ")"
8109
8208
  ] }),
8110
- slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-destructive", children: " *" })
8209
+ slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "text-destructive", children: " *" })
8111
8210
  ] }),
8112
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
8113
- 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: [
8114
- renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
8115
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8211
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
8212
+ slot.references.map((ref) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("li", { className: "flex items-center gap-1 rounded border border-border px-1.5 py-0.5", "data-reference-id": ref.id, children: [
8213
+ renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
8214
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8116
8215
  "button",
8117
8216
  {
8118
8217
  type: "button",
@@ -8123,7 +8222,7 @@ var GenerationSettings = ({
8123
8222
  }
8124
8223
  )
8125
8224
  ] }, ref.id)),
8126
- onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
8225
+ onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8127
8226
  "button",
8128
8227
  {
8129
8228
  type: "button",
@@ -8134,21 +8233,21 @@ var GenerationSettings = ({
8134
8233
  ) })
8135
8234
  ] })
8136
8235
  ] }, slot.role)),
8137
- 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)) }),
8138
- 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)) })
8236
+ showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ul", { role: "status", className: "flex flex-col gap-0.5 text-xs text-muted-foreground", "data-generation-adjustments": "", children: plan.adjustments.map((adjustment, index) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("li", { "data-adjustment-field": adjustment.field, "data-adjustment-kind": adjustment.kind, children: adjustment.reason }, index)) }),
8237
+ showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ul", { role: "alert", className: "flex flex-col gap-0.5 text-xs text-destructive", "data-generation-errors": "", children: plan.errors.map((error, index) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("li", { "data-error-field": error.field, children: error.message }, index)) })
8139
8238
  ] });
8140
8239
  };
8141
8240
 
8142
8241
  // src/generation/JobProgress.tsx
8143
- var import_jsx_runtime37 = require("react/jsx-runtime");
8242
+ var import_jsx_runtime38 = require("react/jsx-runtime");
8144
8243
  var JobProgress = ({ title, className = "", ...options }) => {
8145
8244
  const progress = useJobProgress(options);
8146
- 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: [
8147
- /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
8148
- title && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "truncate text-foreground", children: title }),
8149
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
8245
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: `flex flex-col gap-1 text-sm ${className}`, "data-job-progress": "", "data-done": options.done ? "" : void 0, children: [
8246
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
8247
+ title && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "truncate text-foreground", children: title }),
8248
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
8150
8249
  ] }),
8151
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8250
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8152
8251
  "div",
8153
8252
  {
8154
8253
  role: "progressbar",
@@ -8158,7 +8257,7 @@ var JobProgress = ({ title, className = "", ...options }) => {
8158
8257
  "aria-valuenow": progress.percent,
8159
8258
  "aria-valuetext": `${progress.percent}%, ${progress.label}`,
8160
8259
  className: "h-1.5 w-full overflow-hidden rounded-full bg-muted",
8161
- children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8260
+ children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8162
8261
  "div",
8163
8262
  {
8164
8263
  className: "h-full rounded-full bg-primary transition-[width] duration-500",
@@ -8171,9 +8270,9 @@ var JobProgress = ({ title, className = "", ...options }) => {
8171
8270
  };
8172
8271
 
8173
8272
  // src/generation/AssetMentionChips.tsx
8174
- var import_react56 = require("react");
8273
+ var import_react57 = require("react");
8175
8274
  var import_generation3 = require("@pixerate/editor/generation");
8176
- var import_jsx_runtime38 = require("react/jsx-runtime");
8275
+ var import_jsx_runtime39 = require("react/jsx-runtime");
8177
8276
  var AssetMentionChips = ({
8178
8277
  content,
8179
8278
  onChange,
@@ -8183,14 +8282,14 @@ var AssetMentionChips = ({
8183
8282
  renderAsset,
8184
8283
  className = ""
8185
8284
  }) => {
8186
- const [open, setOpen] = (0, import_react56.useState)(null);
8187
- const rootRef = (0, import_react56.useRef)(null);
8188
- const chips = (0, import_react56.useMemo)(
8285
+ const [open, setOpen] = (0, import_react57.useState)(null);
8286
+ const rootRef = (0, import_react57.useRef)(null);
8287
+ const chips = (0, import_react57.useMemo)(
8189
8288
  () => (0, import_generation3.describeAssetMentions)((0, import_generation3.findTextMentions)(content), assets, capabilities),
8190
8289
  [content, assets, capabilities]
8191
8290
  );
8192
8291
  const options = roles ?? (capabilities ? (0, import_generation3.getAssetRoleOptions)(capabilities) : (0, import_generation3.defaultAssetRoleOptions)());
8193
- (0, import_react56.useEffect)(() => {
8292
+ (0, import_react57.useEffect)(() => {
8194
8293
  if (open === null) return;
8195
8294
  const onPointer = (event) => {
8196
8295
  if (!rootRef.current?.contains(event.target)) setOpen(null);
@@ -8198,19 +8297,19 @@ var AssetMentionChips = ({
8198
8297
  document.addEventListener("mousedown", onPointer);
8199
8298
  return () => document.removeEventListener("mousedown", onPointer);
8200
8299
  }, [open]);
8201
- const pick = (chip5, role) => {
8300
+ const pick = (chip6, role) => {
8202
8301
  setOpen(null);
8203
- if (chip5.start === void 0) return;
8204
- onChange((0, import_generation3.setMentionRoleInText)(content, chip5.start, role));
8302
+ if (chip6.start === void 0) return;
8303
+ onChange((0, import_generation3.setMentionRoleInText)(content, chip6.start, role));
8205
8304
  };
8206
8305
  if (chips.length === 0) return null;
8207
- 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) => {
8208
- const error = chip5.issues.find((issue) => issue.severity === "error");
8209
- const warning = chip5.issues.find((issue) => issue.severity === "warning");
8306
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { ref: rootRef, className: `flex flex-wrap gap-1.5 ${className}`, "data-asset-mention-chips": "", children: chips.map((chip6) => {
8307
+ const error = chip6.issues.find((issue) => issue.severity === "error");
8308
+ const warning = chip6.issues.find((issue) => issue.severity === "warning");
8210
8309
  const problem = error ?? warning;
8211
- const isOpen = open === chip5.index;
8212
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip5.asset.id, children: [
8213
- /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
8310
+ const isOpen = open === chip6.index;
8311
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip6.asset.id, children: [
8312
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8214
8313
  "button",
8215
8314
  {
8216
8315
  type: "button",
@@ -8218,82 +8317,82 @@ var AssetMentionChips = ({
8218
8317
  "aria-expanded": isOpen,
8219
8318
  title: problem?.message,
8220
8319
  "data-issue": problem?.code,
8221
- onClick: () => setOpen(isOpen ? null : chip5.index),
8320
+ onClick: () => setOpen(isOpen ? null : chip6.index),
8222
8321
  onKeyDown: (e) => {
8223
8322
  if (e.key === "Escape") setOpen(null);
8224
8323
  },
8225
8324
  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`,
8226
8325
  children: [
8227
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { children: renderAsset ? renderAsset(chip5) : `@${chip5.asset.label ?? chip5.handle}` }),
8228
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8326
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: renderAsset ? renderAsset(chip6) : `@${chip6.asset.label ?? chip6.handle}` }),
8327
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8229
8328
  "span",
8230
8329
  {
8231
- className: `rounded px-1 text-[10px] uppercase tracking-wide ${chip5.role ? "bg-primary/15" : "opacity-60"}`,
8232
- "data-role-badge": chip5.role ?? "",
8233
- children: chip5.roleLabel ?? "No role"
8330
+ className: `rounded px-1 text-[10px] uppercase tracking-wide ${chip6.role ? "bg-primary/15" : "opacity-60"}`,
8331
+ "data-role-badge": chip6.role ?? "",
8332
+ children: chip6.roleLabel ?? "No role"
8234
8333
  }
8235
8334
  )
8236
8335
  ]
8237
8336
  }
8238
8337
  ),
8239
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
8338
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8240
8339
  "div",
8241
8340
  {
8242
8341
  role: "listbox",
8243
- "aria-label": `Role for ${chip5.asset.label ?? chip5.handle}`,
8342
+ "aria-label": `Role for ${chip6.asset.label ?? chip6.handle}`,
8244
8343
  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",
8245
8344
  "data-role-picker": "",
8246
8345
  onKeyDown: (e) => {
8247
8346
  if (e.key === "Escape") setOpen(null);
8248
8347
  },
8249
8348
  children: [
8250
- options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
8349
+ options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8251
8350
  "button",
8252
8351
  {
8253
8352
  type: "button",
8254
8353
  role: "option",
8255
- "aria-selected": chip5.role === option.role,
8354
+ "aria-selected": chip6.role === option.role,
8256
8355
  "data-role-option": option.role,
8257
8356
  title: option.description,
8258
- onClick: () => pick(chip5, option.role),
8357
+ onClick: () => pick(chip6, option.role),
8259
8358
  className: "flex items-center justify-between gap-2 rounded px-2 py-1 text-left hover:bg-muted",
8260
8359
  children: [
8261
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { children: option.label }),
8262
- option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
8360
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { children: option.label }),
8361
+ option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
8263
8362
  ]
8264
8363
  },
8265
8364
  option.role
8266
8365
  )),
8267
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8366
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8268
8367
  "button",
8269
8368
  {
8270
8369
  type: "button",
8271
8370
  role: "option",
8272
- "aria-selected": !chip5.role,
8371
+ "aria-selected": !chip6.role,
8273
8372
  "data-role-option": "",
8274
- onClick: () => pick(chip5, null),
8373
+ onClick: () => pick(chip6, null),
8275
8374
  className: "rounded px-2 py-1 text-left opacity-70 hover:bg-muted",
8276
8375
  children: "No role"
8277
8376
  }
8278
8377
  ),
8279
- 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)) })
8378
+ chip6.issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("ul", { className: "mt-1 border-t border-border px-2 pt-1 text-[10px]", "data-chip-issues": "", children: chip6.issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("li", { className: issue.severity === "error" ? "text-red-500" : "text-amber-500", children: issue.message }, i)) })
8280
8379
  ]
8281
8380
  }
8282
8381
  )
8283
- ] }, `${chip5.start}-${chip5.index}`);
8382
+ ] }, `${chip6.start}-${chip6.index}`);
8284
8383
  }) });
8285
8384
  };
8286
8385
 
8287
8386
  // src/generation/GenerationHistory.tsx
8288
- var import_react57 = require("react");
8387
+ var import_react58 = require("react");
8289
8388
  var import_generation4 = require("@pixerate/editor/generation");
8290
- var import_jsx_runtime39 = require("react/jsx-runtime");
8389
+ var import_jsx_runtime40 = require("react/jsx-runtime");
8291
8390
  function useGenerationRecords(store, filter) {
8292
- const [records, setRecords] = (0, import_react57.useState)([]);
8293
- const [loading, setLoading] = (0, import_react57.useState)(!!store);
8294
- const [error, setError] = (0, import_react57.useState)(null);
8391
+ const [records, setRecords] = (0, import_react58.useState)([]);
8392
+ const [loading, setLoading] = (0, import_react58.useState)(!!store);
8393
+ const [error, setError] = (0, import_react58.useState)(null);
8295
8394
  const filterKey = (0, import_generation4.stableStringify)(filter ?? {});
8296
- const refresh = (0, import_react57.useCallback)(async () => {
8395
+ const refresh = (0, import_react58.useCallback)(async () => {
8297
8396
  if (!store) {
8298
8397
  setRecords([]);
8299
8398
  setLoading(false);
@@ -8310,7 +8409,7 @@ function useGenerationRecords(store, filter) {
8310
8409
  setLoading(false);
8311
8410
  }
8312
8411
  }, [store, filterKey]);
8313
- (0, import_react57.useEffect)(() => {
8412
+ (0, import_react58.useEffect)(() => {
8314
8413
  void refresh();
8315
8414
  if (!store) return;
8316
8415
  return store.subscribe(() => void refresh());
@@ -8336,21 +8435,21 @@ var GenerationHistory = ({
8336
8435
  emptyText = "No generations yet.",
8337
8436
  className = ""
8338
8437
  }) => {
8339
- const [innerMode, setInnerMode] = (0, import_react57.useState)("exact");
8438
+ const [innerMode, setInnerMode] = (0, import_react58.useState)("exact");
8340
8439
  const mode = modeProp ?? innerMode;
8341
8440
  const setMode = (next) => {
8342
8441
  if (modeProp === void 0) setInnerMode(next);
8343
8442
  onModeChange?.(next);
8344
8443
  };
8345
- const options = (0, import_react57.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
8346
- const results = (0, import_react57.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
8347
- const models = (0, import_react57.useMemo)(
8444
+ const options = (0, import_react58.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
8445
+ const results = (0, import_react58.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
8446
+ const models = (0, import_react58.useMemo)(
8348
8447
  () => capabilities ? Array.isArray(capabilities) ? capabilities : [capabilities] : [],
8349
8448
  [capabilities]
8350
8449
  );
8351
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
8352
- /* @__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: [
8353
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8450
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
8451
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "flex items-center gap-2 text-xs", role: "radiogroup", "aria-label": "Recreate mode", children: ["exact", "latest"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("label", { className: "inline-flex items-center gap-1", children: [
8452
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8354
8453
  "input",
8355
8454
  {
8356
8455
  type: "radio",
@@ -8363,34 +8462,34 @@ var GenerationHistory = ({
8363
8462
  ),
8364
8463
  value === "exact" ? "Exact (recorded versions)" : "Latest templates & settings"
8365
8464
  ] }, value)) }),
8366
- records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
8367
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
8465
+ records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
8466
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
8368
8467
  const result = results[i];
8369
8468
  const model = models.find((m) => m.id === record.provenance.modelId);
8370
8469
  const blocked = !result.ok;
8371
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8470
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
8372
8471
  "li",
8373
8472
  {
8374
8473
  className: "rounded-md border border-border p-2",
8375
8474
  "data-record": record.id,
8376
8475
  "data-drift": result.drift.length,
8377
8476
  children: [
8378
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
8379
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
8380
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { className: "text-muted-foreground", children: [
8381
- record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("span", { "data-kind": "", children: [
8477
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
8478
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
8479
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { className: "text-muted-foreground", children: [
8480
+ record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("span", { "data-kind": "", children: [
8382
8481
  record.kind,
8383
8482
  " \xB7 "
8384
8483
  ] }),
8385
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
8386
- record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
8484
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
8485
+ record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
8387
8486
  " \xB7 seed ",
8388
8487
  record.seed
8389
8488
  ] })
8390
8489
  ] })
8391
8490
  ] }),
8392
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
8393
- 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)(
8491
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
8492
+ record.assets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "mt-1 flex flex-wrap gap-1", children: record.assets.map((asset) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
8394
8493
  "span",
8395
8494
  {
8396
8495
  className: "rounded-full bg-muted px-2 py-0.5 text-[10px]",
@@ -8404,16 +8503,16 @@ var GenerationHistory = ({
8404
8503
  `${asset.role}:${asset.id}`
8405
8504
  )) }),
8406
8505
  renderPreview?.(record),
8407
- 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: [
8408
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("strong", { children: [
8506
+ result.drift.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("ul", { className: "mt-1 flex flex-col gap-0.5 text-[11px]", "data-drift-report": "", children: result.drift.map((item, j) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("li", { className: severityClass[item.severity], "data-drift-type": item.type, children: [
8507
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("strong", { children: [
8409
8508
  import_generation4.DRIFT_TYPE_LABELS[item.type],
8410
8509
  ":"
8411
8510
  ] }),
8412
8511
  " ",
8413
8512
  item.message
8414
8513
  ] }, j)) }),
8415
- /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "mt-2 flex gap-2", children: [
8416
- onRecreate && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8514
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "mt-2 flex gap-2", children: [
8515
+ onRecreate && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8417
8516
  "button",
8418
8517
  {
8419
8518
  type: "button",
@@ -8425,7 +8524,7 @@ var GenerationHistory = ({
8425
8524
  children: "Recreate"
8426
8525
  }
8427
8526
  ),
8428
- onVariation && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8527
+ onVariation && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8429
8528
  "button",
8430
8529
  {
8431
8530
  type: "button",
@@ -8435,7 +8534,7 @@ var GenerationHistory = ({
8435
8534
  children: "Variation"
8436
8535
  }
8437
8536
  ),
8438
- onRemove && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8537
+ onRemove && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8439
8538
  "button",
8440
8539
  {
8441
8540
  type: "button",
@@ -8455,19 +8554,19 @@ var GenerationHistory = ({
8455
8554
  };
8456
8555
 
8457
8556
  // src/find-replace/useFindReplace.ts
8458
- var import_react58 = require("react");
8557
+ var import_react59 = require("react");
8459
8558
  var import_editor16 = require("@pixerate/editor");
8460
8559
  var noopUnsubscribe2 = () => {
8461
8560
  };
8462
8561
  function useFindReplace(editor) {
8463
8562
  const store = (0, import_editor16.getFindReplaceStore)(editor ?? null);
8464
- const subscribe = (0, import_react58.useCallback)(
8563
+ const subscribe = (0, import_react59.useCallback)(
8465
8564
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe2,
8466
8565
  [store]
8467
8566
  );
8468
8567
  const getSnapshot = () => store?.getSnapshot() ?? import_editor16.EMPTY_FIND_REPLACE_SNAPSHOT;
8469
- const snapshot = (0, import_react58.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
8470
- return (0, import_react58.useMemo)(() => {
8568
+ const snapshot = (0, import_react59.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
8569
+ return (0, import_react59.useMemo)(() => {
8471
8570
  const run = (fn) => {
8472
8571
  if (editor && !editor.isDestroyed && store) fn(editor);
8473
8572
  };
@@ -8491,9 +8590,9 @@ function useFindReplace(editor) {
8491
8590
  }
8492
8591
 
8493
8592
  // src/find-replace/FindReplaceBar.tsx
8494
- var import_react59 = require("react");
8593
+ var import_react60 = require("react");
8495
8594
  var import_editor17 = require("@pixerate/editor");
8496
- var import_jsx_runtime40 = require("react/jsx-runtime");
8595
+ var import_jsx_runtime41 = require("react/jsx-runtime");
8497
8596
  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";
8498
8597
  var buttonClass5 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
8499
8598
  var toggleClass = (on) => `${buttonClass5} font-mono ${on ? "bg-primary/10 text-primary" : "text-muted-foreground"}`;
@@ -8506,10 +8605,10 @@ var FindReplaceBar = ({
8506
8605
  onClose
8507
8606
  }) => {
8508
8607
  const find = useFindReplace(editor);
8509
- const findInput = (0, import_react59.useRef)(null);
8510
- const [moreOpen, setMoreOpen] = (0, import_react59.useState)(false);
8608
+ const findInput = (0, import_react60.useRef)(null);
8609
+ const [moreOpen, setMoreOpen] = (0, import_react60.useState)(false);
8511
8610
  const visible = find.available && (alwaysOpen || find.open);
8512
- (0, import_react59.useEffect)(() => {
8611
+ (0, import_react60.useEffect)(() => {
8513
8612
  if (!visible || find.focusRequest === 0) return;
8514
8613
  findInput.current?.focus();
8515
8614
  findInput.current?.select();
@@ -8547,9 +8646,9 @@ var FindReplaceBar = ({
8547
8646
  if (isMod(e)) find.replaceAll();
8548
8647
  else find.replace();
8549
8648
  };
8550
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
8551
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex items-center gap-1", children: [
8552
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8649
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
8650
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-1", children: [
8651
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8553
8652
  "button",
8554
8653
  {
8555
8654
  type: "button",
@@ -8560,7 +8659,7 @@ var FindReplaceBar = ({
8560
8659
  children: showReplace ? "\u25BE" : "\u25B8"
8561
8660
  }
8562
8661
  ),
8563
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8662
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8564
8663
  "input",
8565
8664
  {
8566
8665
  ref: findInput,
@@ -8574,7 +8673,7 @@ var FindReplaceBar = ({
8574
8673
  onKeyDown: onFindKeyDown
8575
8674
  }
8576
8675
  ),
8577
- import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8676
+ import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8578
8677
  "button",
8579
8678
  {
8580
8679
  type: "button",
@@ -8587,7 +8686,7 @@ var FindReplaceBar = ({
8587
8686
  },
8588
8687
  t.key
8589
8688
  )),
8590
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8689
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8591
8690
  "span",
8592
8691
  {
8593
8692
  className: `min-w-[5rem] px-1 text-center text-xs ${find.error ? "text-destructive" : "text-muted-foreground"}`,
@@ -8597,9 +8696,9 @@ var FindReplaceBar = ({
8597
8696
  children: status
8598
8697
  }
8599
8698
  ),
8600
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
8601
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
8602
- showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8699
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
8700
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
8701
+ showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8603
8702
  "button",
8604
8703
  {
8605
8704
  type: "button",
@@ -8610,10 +8709,10 @@ var FindReplaceBar = ({
8610
8709
  children: "\u2026"
8611
8710
  }
8612
8711
  ),
8613
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
8712
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
8614
8713
  ] }),
8615
- showReplace && /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
8616
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8714
+ showReplace && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
8715
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8617
8716
  "input",
8618
8717
  {
8619
8718
  type: "text",
@@ -8625,7 +8724,7 @@ var FindReplaceBar = ({
8625
8724
  onKeyDown: onReplaceKeyDown
8626
8725
  }
8627
8726
  ),
8628
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8727
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8629
8728
  "button",
8630
8729
  {
8631
8730
  type: "button",
@@ -8635,11 +8734,11 @@ var FindReplaceBar = ({
8635
8734
  children: "Replace"
8636
8735
  }
8637
8736
  ),
8638
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
8639
- 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` })
8737
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
8738
+ find.lastReplaceCount !== null && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "px-1 text-xs text-muted-foreground", "aria-live": "polite", children: find.lastReplaceCount === 1 ? "1 replaced" : `${find.lastReplaceCount} replaced` })
8640
8739
  ] }),
8641
- 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: [
8642
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8740
+ showMoreOptions && moreOpen && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 pl-7 text-xs text-muted-foreground", children: import_editor17.FIND_OPTION_TOGGLES.filter((t) => t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { className: "flex items-center gap-1", children: [
8741
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8643
8742
  "input",
8644
8743
  {
8645
8744
  type: "checkbox",
@@ -8653,12 +8752,12 @@ var FindReplaceBar = ({
8653
8752
  };
8654
8753
 
8655
8754
  // src/tables/useTableMenu.ts
8656
- var import_react60 = require("react");
8755
+ var import_react61 = require("react");
8657
8756
  var import_editor18 = require("@pixerate/editor");
8658
8757
  function useTableMenu(editor) {
8659
- const store = (0, import_react60.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
8660
- const snapshot = (0, import_react60.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
8661
- return (0, import_react60.useMemo)(
8758
+ const store = (0, import_react61.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
8759
+ const snapshot = (0, import_react61.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
8760
+ return (0, import_react61.useMemo)(
8662
8761
  () => ({
8663
8762
  ...snapshot,
8664
8763
  run: (action, params) => (0, import_editor18.runTableAction)(editor, action, params, { focus: true }),
@@ -8669,9 +8768,9 @@ function useTableMenu(editor) {
8669
8768
  }
8670
8769
 
8671
8770
  // src/tables/TableToolbar.tsx
8672
- var import_react61 = __toESM(require("react"), 1);
8771
+ var import_react62 = __toESM(require("react"), 1);
8673
8772
  var import_editor19 = require("@pixerate/editor");
8674
- var import_jsx_runtime41 = require("react/jsx-runtime");
8773
+ var import_jsx_runtime42 = require("react/jsx-runtime");
8675
8774
  var keepSelection2 = (event) => event.preventDefault();
8676
8775
  var TableToolbar = ({
8677
8776
  editor,
@@ -8685,14 +8784,14 @@ var TableToolbar = ({
8685
8784
  }) => {
8686
8785
  const table = useTableMenu(editor);
8687
8786
  if (!editor || !table.inTable && !showWhenOutside) return null;
8688
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
8787
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
8689
8788
  const status = table.check(item.action, item.params);
8690
8789
  const enabled = status === true;
8691
8790
  const active = item.active?.(table);
8692
8791
  const separator = index > 0 && items[index - 1].group !== item.group;
8693
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_react61.default.Fragment, { children: [
8694
- separator && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
8695
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8792
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_react62.default.Fragment, { children: [
8793
+ separator && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
8794
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8696
8795
  "button",
8697
8796
  {
8698
8797
  type: "button",
@@ -8714,8 +8813,8 @@ var TableToolbar = ({
8714
8813
  };
8715
8814
 
8716
8815
  // src/tables/InsertTableGrid.tsx
8717
- var import_react62 = require("react");
8718
- var import_jsx_runtime42 = require("react/jsx-runtime");
8816
+ var import_react63 = require("react");
8817
+ var import_jsx_runtime43 = require("react/jsx-runtime");
8719
8818
  var keepSelection3 = (event) => event.preventDefault();
8720
8819
  var InsertTableGrid = ({
8721
8820
  editor,
@@ -8728,14 +8827,14 @@ var InsertTableGrid = ({
8728
8827
  onInsert
8729
8828
  }) => {
8730
8829
  const table = useTableMenu(editor);
8731
- const [hover, setHover] = (0, import_react62.useState)(null);
8830
+ const [hover, setHover] = (0, import_react63.useState)(null);
8732
8831
  const status = table.actions.insertTable;
8733
8832
  const disabled = !editor || !status.enabled;
8734
8833
  const insert = (size) => {
8735
8834
  if (table.run("insertTable", { ...size, withHeaderRow })) onInsert?.(size);
8736
8835
  setHover(null);
8737
8836
  };
8738
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
8837
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
8739
8838
  "div",
8740
8839
  {
8741
8840
  className,
@@ -8745,7 +8844,7 @@ var InsertTableGrid = ({
8745
8844
  "data-insert-table-grid": "",
8746
8845
  onMouseLeave: () => setHover(null),
8747
8846
  children: [
8748
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8847
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8749
8848
  "div",
8750
8849
  {
8751
8850
  role: "grid",
@@ -8754,7 +8853,7 @@ var InsertTableGrid = ({
8754
8853
  children: Array.from({ length: rows * cols }, (_, i) => {
8755
8854
  const size = { rows: Math.floor(i / cols) + 1, cols: i % cols + 1 };
8756
8855
  const active = !!hover && size.rows <= hover.rows && size.cols <= hover.cols;
8757
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8856
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8758
8857
  "button",
8759
8858
  {
8760
8859
  type: "button",
@@ -8774,7 +8873,7 @@ var InsertTableGrid = ({
8774
8873
  })
8775
8874
  }
8776
8875
  ),
8777
- /* @__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" })
8876
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { "aria-live": "polite", "data-testid": "insert-table-size", children: disabled ? status.reason : hover ? `${hover.rows} \xD7 ${hover.cols}` : "Insert table" })
8778
8877
  ]
8779
8878
  }
8780
8879
  );
@@ -8782,31 +8881,31 @@ var InsertTableGrid = ({
8782
8881
 
8783
8882
  // src/tables/TableBubbleMenu.tsx
8784
8883
  var import_editor20 = require("@pixerate/editor");
8785
- var import_jsx_runtime43 = require("react/jsx-runtime");
8884
+ var import_jsx_runtime44 = require("react/jsx-runtime");
8786
8885
  var TableBubbleMenu = ({
8787
8886
  editor,
8788
8887
  children,
8789
8888
  toolbarProps,
8790
8889
  pluginKey = "tableBubbleMenu",
8791
8890
  ...rest
8792
- }) => /* @__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 }) });
8891
+ }) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(BubbleMenu, { editor, pluginKey, shouldShow: import_editor20.shouldShowTableBubbleMenu, ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(TableToolbar, { editor, ...toolbarProps }) });
8793
8892
 
8794
8893
  // src/chart-node/ChartNodeView.tsx
8795
8894
  var import_client = require("react-dom/client");
8796
8895
 
8797
8896
  // src/chart/ChartCanvas.tsx
8798
- var import_react64 = require("react");
8897
+ var import_react65 = require("react");
8799
8898
  var import_chart2 = require("@pixerate/editor/chart");
8800
8899
 
8801
8900
  // src/chart/useChartEditor.ts
8802
- var import_react63 = require("react");
8901
+ var import_react64 = require("react");
8803
8902
  var import_chart = require("@pixerate/editor/chart");
8804
8903
  function useChartState(controller) {
8805
- return (0, import_react63.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
8904
+ return (0, import_react64.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
8806
8905
  }
8807
8906
 
8808
8907
  // src/chart/ChartCanvas.tsx
8809
- var import_jsx_runtime44 = require("react/jsx-runtime");
8908
+ var import_jsx_runtime45 = require("react/jsx-runtime");
8810
8909
  function renderChartMark(mark, fontFamily, interactive) {
8811
8910
  const common = {
8812
8911
  "data-role": mark.role,
@@ -8818,9 +8917,9 @@ function renderChartMark(mark, fontFamily, interactive) {
8818
8917
  };
8819
8918
  switch (mark.kind) {
8820
8919
  case "rect":
8821
- 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);
8920
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("rect", { ...common, x: mark.x, y: mark.y, width: mark.width, height: mark.height, rx: mark.radius, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
8822
8921
  case "path":
8823
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8922
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
8824
8923
  "path",
8825
8924
  {
8826
8925
  ...common,
@@ -8833,11 +8932,11 @@ function renderChartMark(mark, fontFamily, interactive) {
8833
8932
  mark.key
8834
8933
  );
8835
8934
  case "circle":
8836
- 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);
8935
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("circle", { ...common, cx: mark.cx, cy: mark.cy, r: mark.r, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
8837
8936
  case "line":
8838
- 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);
8937
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("line", { ...common, x1: mark.x1, y1: mark.y1, x2: mark.x2, y2: mark.y2, strokeDasharray: mark.dash, style: { stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
8839
8938
  case "text":
8840
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8939
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
8841
8940
  "text",
8842
8941
  {
8843
8942
  ...common,
@@ -8854,23 +8953,23 @@ function renderChartMark(mark, fontFamily, interactive) {
8854
8953
  }
8855
8954
  }
8856
8955
  function ChartPresenceLayer({ presence }) {
8857
- const { actors } = (0, import_react64.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
8858
- 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: [
8859
- /* @__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 }),
8860
- /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("g", { transform: "translate(13 16)", children: [
8861
- /* @__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 } }),
8862
- /* @__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 })
8956
+ const { actors } = (0, import_react65.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
8957
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("g", { "data-chart-presence": "", pointerEvents: "none", children: actors.map((a) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("g", { transform: `translate(${a.x} ${a.y})`, "data-actor": a.id, children: [
8958
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("path", { d: "M0,0 L0,14 L4,10.5 L7,17 L9.5,16 L6.5,9.5 L11.5,9.5 Z", style: { fill: a.color, stroke: "#ffffff", strokeWidth: 1 }, transform: a.pressed ? "scale(0.9)" : void 0 }),
8959
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("g", { transform: "translate(13 16)", children: [
8960
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("rect", { x: 0, y: 0, rx: 4, height: 18, width: Math.max(28, (a.message ?? a.name).length * 6.4 + 12), style: { fill: a.color } }),
8961
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("text", { x: 6, y: 9, dominantBaseline: "central", style: { fill: "#ffffff", fontSize: 11, fontWeight: 600, fontFamily: "inherit" }, children: a.message ?? a.name })
8863
8962
  ] })
8864
8963
  ] }, a.id)) });
8865
8964
  }
8866
8965
  function ChartCanvas({ controller, width = 640, height = 400, responsive = true, theme, editable = true, measureText, emptyMessage, className, presence, sceneRef }) {
8867
8966
  const state = useChartState(controller);
8868
- const wrapper = (0, import_react64.useRef)(null);
8869
- const svg = (0, import_react64.useRef)(null);
8870
- const drag = (0, import_react64.useRef)(null);
8871
- const [measured, setMeasured] = (0, import_react64.useState)(null);
8872
- const [frozen, setFrozen] = (0, import_react64.useState)(null);
8873
- (0, import_react64.useEffect)(() => {
8967
+ const wrapper = (0, import_react65.useRef)(null);
8968
+ const svg = (0, import_react65.useRef)(null);
8969
+ const drag = (0, import_react65.useRef)(null);
8970
+ const [measured, setMeasured] = (0, import_react65.useState)(null);
8971
+ const [frozen, setFrozen] = (0, import_react65.useState)(null);
8972
+ (0, import_react65.useEffect)(() => {
8874
8973
  const el = wrapper.current;
8875
8974
  if (!responsive || !el || typeof ResizeObserver === "undefined") return;
8876
8975
  const observer = new ResizeObserver(([entry]) => {
@@ -8881,8 +8980,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8881
8980
  return () => observer.disconnect();
8882
8981
  }, [responsive]);
8883
8982
  const sceneWidth = responsive && measured || width;
8884
- const fullTheme = (0, import_react64.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
8885
- const scene = (0, import_react64.useMemo)(
8983
+ const fullTheme = (0, import_react65.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
8984
+ const scene = (0, import_react65.useMemo)(
8886
8985
  () => (0, import_chart2.layoutChart)(state.spec, {
8887
8986
  width: sceneWidth,
8888
8987
  height,
@@ -8898,8 +8997,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8898
8997
  [state.spec, state.selection, sceneWidth, height, fullTheme, editable, measureText, emptyMessage, frozen]
8899
8998
  );
8900
8999
  if (sceneRef) sceneRef.current = scene;
8901
- const byKey = (0, import_react64.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
8902
- (0, import_react64.useEffect)(() => () => drag.current?.end(), []);
9000
+ const byKey = (0, import_react65.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
9001
+ (0, import_react65.useEffect)(() => () => drag.current?.end(), []);
8903
9002
  const scenePoint = (e) => (0, import_chart2.chartClientToScene)(scene, svg.current.getBoundingClientRect(), e.clientX, e.clientY);
8904
9003
  const onPointerDown = (e) => {
8905
9004
  if (!editable || e.button !== 0) return;
@@ -8932,7 +9031,7 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8932
9031
  if (editable && (0, import_chart2.handleChartKey)(controller, scene, e)) e.preventDefault();
8933
9032
  };
8934
9033
  const label = state.spec.title || "Chart";
8935
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { ref: wrapper, className: `w-full ${className ?? ""}`, "data-chart-canvas": "", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
9034
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { ref: wrapper, className: `w-full ${className ?? ""}`, "data-chart-canvas": "", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
8936
9035
  "svg",
8937
9036
  {
8938
9037
  ref: svg,
@@ -8950,14 +9049,14 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8950
9049
  onKeyDown,
8951
9050
  children: [
8952
9051
  scene.marks.map((m) => renderChartMark(m, scene.theme.fontFamily, editable)),
8953
- presence && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartPresenceLayer, { presence })
9052
+ presence && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartPresenceLayer, { presence })
8954
9053
  ]
8955
9054
  }
8956
9055
  ) });
8957
9056
  }
8958
9057
 
8959
9058
  // src/chart/ChartDataGrid.tsx
8960
- var import_react65 = require("react");
9059
+ var import_react66 = require("react");
8961
9060
  var import_chart3 = require("@pixerate/editor/chart");
8962
9061
 
8963
9062
  // src/chart/styles.ts
@@ -8970,11 +9069,11 @@ var chartSectionClass = "space-y-2 border-b border-border pb-3 last:border-b-0";
8970
9069
  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";
8971
9070
 
8972
9071
  // src/chart/ChartDataGrid.tsx
8973
- var import_jsx_runtime45 = require("react/jsx-runtime");
9072
+ var import_jsx_runtime46 = require("react/jsx-runtime");
8974
9073
  function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
8975
- const [draft, setDraft] = (0, import_react65.useState)(value);
8976
- const typing = (0, import_react65.useRef)(false);
8977
- (0, import_react65.useEffect)(() => {
9074
+ const [draft, setDraft] = (0, import_react66.useState)(value);
9075
+ const typing = (0, import_react66.useRef)(false);
9076
+ (0, import_react66.useEffect)(() => {
8978
9077
  if (!typing.current) setDraft(value);
8979
9078
  }, [value]);
8980
9079
  const commit = () => {
@@ -8983,7 +9082,7 @@ function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
8983
9082
  if (draft === value) return;
8984
9083
  if (onCommit(draft) === false) setDraft(value);
8985
9084
  };
8986
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9085
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
8987
9086
  "input",
8988
9087
  {
8989
9088
  ...rest,
@@ -9018,15 +9117,15 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9018
9117
  e.preventDefault();
9019
9118
  controller.pasteCells(row, column, text);
9020
9119
  };
9021
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
9022
- /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
9023
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("tr", { children: [
9024
- /* @__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 }),
9120
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
9121
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
9122
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("tr", { children: [
9123
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("th", { className: "border-b border-r border-border px-2 py-1 text-left font-medium text-muted-foreground", children: categoryHeader }),
9025
9124
  spec.series.map((s, si) => {
9026
9125
  const color = (0, import_chart3.chartSeriesColor)(spec, si);
9027
9126
  const selected = selection?.kind === "series" && selection.seriesId === s.id;
9028
- 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: [
9029
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9127
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("th", { "data-series-id": s.id, className: `border-b border-r border-border px-1 py-1 font-medium ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-1", children: [
9128
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9030
9129
  "input",
9031
9130
  {
9032
9131
  type: "color",
@@ -9039,7 +9138,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9039
9138
  className: "h-5 w-5 shrink-0 cursor-pointer rounded border-0 bg-transparent p-0"
9040
9139
  }
9041
9140
  ),
9042
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9141
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9043
9142
  ChartCommitInput,
9044
9143
  {
9045
9144
  value: s.name,
@@ -9049,8 +9148,8 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9049
9148
  className: `${chartInputClass} h-6 min-w-[5rem] border-transparent bg-transparent font-medium ${s.hidden ? "text-muted-foreground line-through" : ""}`
9050
9149
  }
9051
9150
  ),
9052
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
9053
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
9151
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
9152
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9054
9153
  "button",
9055
9154
  {
9056
9155
  type: "button",
@@ -9063,16 +9162,16 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9063
9162
  children: s.hidden ? "\u25CB" : "\u25CF"
9064
9163
  }
9065
9164
  ),
9066
- /* @__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" })
9165
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete series", "aria-label": `Delete ${s.name}`, "data-action": "remove-series", onClick: () => controller.removeSeries(s.id), children: "\xD7" })
9067
9166
  ] })
9068
9167
  ] }) }, s.id);
9069
9168
  }),
9070
- !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: "+" }) })
9169
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("th", { className: "w-8 border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Add series", "aria-label": "Add series", "data-action": "add-series", onClick: () => controller.addSeries(), children: "+" }) })
9071
9170
  ] }) }),
9072
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("tbody", { children: spec.categories.map((category, i) => {
9171
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("tbody", { children: spec.categories.map((category, i) => {
9073
9172
  const rowSelected = selection?.kind === "category" && selection.index === i;
9074
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
9075
- /* @__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)(
9173
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
9174
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("th", { className: "border-b border-r border-border p-0 text-left font-normal", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9076
9175
  ChartCommitInput,
9077
9176
  {
9078
9177
  value: category,
@@ -9086,7 +9185,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9086
9185
  spec.series.map((s) => {
9087
9186
  const value = s.values[i];
9088
9187
  const selected = selection?.kind === "point" && selection.seriesId === s.id && selection.index === i;
9089
- 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)(
9188
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("td", { className: `border-b border-r border-border p-0 ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9090
9189
  ChartCommitInput,
9091
9190
  {
9092
9191
  value: value === null || value === void 0 ? "" : String(value),
@@ -9101,38 +9200,38 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
9101
9200
  }
9102
9201
  ) }, s.id);
9103
9202
  }),
9104
- !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" }) })
9203
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("td", { className: "border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete category", "aria-label": `Delete ${category}`, "data-action": "remove-category", onClick: () => controller.removeCategory(i), children: "\xD7" }) })
9105
9204
  ] }, i);
9106
9205
  }) })
9107
9206
  ] }),
9108
- !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" }) })
9207
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "p-1", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: `${chartButtonClass} h-6 border-dashed`, "data-action": "add-category", onClick: () => controller.addCategory(), children: "+ Add category" }) })
9109
9208
  ] });
9110
9209
  }
9111
9210
 
9112
9211
  // src/chart/ChartInspector.tsx
9113
- var import_react66 = require("react");
9212
+ var import_react67 = require("react");
9114
9213
  var import_chart4 = require("@pixerate/editor/chart");
9115
- var import_jsx_runtime46 = require("react/jsx-runtime");
9214
+ var import_jsx_runtime47 = require("react/jsx-runtime");
9116
9215
  var cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
9117
9216
  function Field({ label, htmlFor, children }) {
9118
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-2", children: [
9119
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
9120
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "min-w-0 flex-1", children })
9217
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
9218
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
9219
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "min-w-0 flex-1", children })
9121
9220
  ] });
9122
9221
  }
9123
9222
  function Toggle({ label, checked, onChange, name }) {
9124
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
9125
- /* @__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) }),
9223
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
9224
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("input", { type: "checkbox", className: "h-3.5 w-3.5 accent-primary", checked, "data-option": name, onChange: (e) => onChange(e.currentTarget.checked) }),
9126
9225
  label
9127
9226
  ] });
9128
9227
  }
9129
9228
  function Select({ id, value, options, onChange, name, labels }) {
9130
- 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)) });
9229
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("select", { id, className: chartInputClass, value, "data-option": name, onChange: (e) => onChange(e.currentTarget.value), children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: o, children: labels?.[o] ?? cap(o) }, o)) });
9131
9230
  }
9132
9231
  function AxisSection({ controller, axis, value, idBase, horizontal, numeric = false, scales = false }) {
9133
9232
  const set = (patch) => controller.setAxis(axis, patch);
9134
9233
  const setFormat = (patch) => set({ format: { ...value.format, ...patch } });
9135
- const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9234
+ const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9136
9235
  ChartCommitInput,
9137
9236
  {
9138
9237
  id: `${idBase}-${axis}-${key2}`,
@@ -9147,26 +9246,26 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9147
9246
  const name = axis === "x" ? numeric ? "X axis" : "Category axis" : axis === "y" ? "Value axis" : "Secondary axis";
9148
9247
  const valueAxis = axis !== "x" || numeric;
9149
9248
  const key = axis === "y2" ? "yAxis2" : `${axis}Axis`;
9150
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
9151
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center justify-between", children: [
9152
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
9249
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
9250
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center justify-between", children: [
9251
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
9153
9252
  name,
9154
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
9253
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
9155
9254
  "(",
9156
9255
  axis === "x" ? horizontal ? "left" : "bottom" : axis === "y2" ? horizontal ? "top" : "right" : horizontal ? "bottom" : "left",
9157
9256
  ")"
9158
9257
  ] })
9159
9258
  ] }),
9160
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
9259
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
9161
9260
  ] }),
9162
- /* @__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 }) }) }),
9163
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9164
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
9165
- 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 }) }),
9166
- scales && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
9167
- 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" }) })
9261
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Title", htmlFor: `${idBase}-${axis}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-title`, value: value.title, "data-option": `${axis}Axis.title`, className: chartInputClass, onCommit: (title) => void set({ title }) }) }),
9262
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9263
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
9264
+ axis === "x" && !numeric && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Dates", name: "xAxis.kind", checked: value.kind === "date", onChange: (dates) => set({ kind: dates ? "date" : void 0 }) }),
9265
+ scales && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
9266
+ scales && valueAxis && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Log scale", name: `${key}.scale`, checked: value.scale === "log", onChange: (log) => set({ scale: log ? "log" : "linear" }) })
9168
9267
  ] }),
9169
- 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)(
9268
+ scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Log base", htmlFor: `${idBase}-${axis}-log-base`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9170
9269
  ChartCommitInput,
9171
9270
  {
9172
9271
  id: `${idBase}-${axis}-log-base`,
@@ -9177,7 +9276,7 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9177
9276
  onCommit: (text) => set({ logBase: text.trim() === "" ? void 0 : Number(text) }).ok
9178
9277
  }
9179
9278
  ) }),
9180
- valueAxis && value.scale !== "log" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Step", htmlFor: `${idBase}-${axis}-step`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9279
+ valueAxis && value.scale !== "log" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Step", htmlFor: `${idBase}-${axis}-step`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9181
9280
  ChartCommitInput,
9182
9281
  {
9183
9282
  id: `${idBase}-${axis}-step`,
@@ -9189,14 +9288,14 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9189
9288
  onCommit: (text) => set({ step: text.trim() === "" ? null : Number(text) }).ok
9190
9289
  }
9191
9290
  ) }),
9192
- valueAxis && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
9193
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex gap-1", children: [
9291
+ valueAxis && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
9292
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex gap-1", children: [
9194
9293
  bound("min"),
9195
9294
  bound("max")
9196
9295
  ] }) }),
9197
- /* @__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: [
9198
- /* @__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 }) }),
9199
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9296
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Format", htmlFor: `${idBase}-${axis}-format`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex gap-1", children: [
9297
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Select, { id: `${idBase}-${axis}-format`, name: `${key}.format.style`, value: value.format.style ?? "number", options: import_chart4.CHART_NUMBER_STYLES, onChange: (style) => setFormat({ style }) }),
9298
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9200
9299
  ChartCommitInput,
9201
9300
  {
9202
9301
  value: value.format.decimals === void 0 ? "" : String(value.format.decimals),
@@ -9215,8 +9314,8 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
9215
9314
  }
9216
9315
  )
9217
9316
  ] }) }),
9218
- 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() }) }) }),
9219
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9317
+ value.format.style === "currency" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Currency", htmlFor: `${idBase}-${axis}-currency`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-currency`, value: value.format.currency ?? "USD", "data-option": `${key}.format.currency`, className: chartInputClass, onCommit: (currency) => void setFormat({ currency: currency.toUpperCase() }) }) }),
9318
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9220
9319
  ChartCommitInput,
9221
9320
  {
9222
9321
  id: `${idBase}-${axis}-code`,
@@ -9242,15 +9341,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
9242
9341
  const values = which === "xErrorBars" ? series.x ?? [] : series.values;
9243
9342
  const set = (next) => controller.updateSeries(series.id, { [which]: next });
9244
9343
  const patch = (p) => bars && set({ ...bars, ...p });
9245
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
9246
- /* @__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: [
9247
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "None" }),
9248
- 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))
9344
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
9345
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: which === "errorBars" ? "Error bars" : "X error bars", htmlFor: `${id}-type`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("select", { id: `${id}-type`, className: chartInputClass, value: bars?.type ?? "", "data-option": `${key}.type`, onChange: (e) => set((0, import_chart4.chartErrorBarsOfType)(e.currentTarget.value, bars, values)), children: [
9346
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "None" }),
9347
+ import_chart4.CHART_ERROR_BAR_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: t, children: import_chart4.CHART_ERROR_BAR_LABELS[t] }, t))
9249
9348
  ] }) }),
9250
- 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 }) }),
9251
- bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
9252
- /* @__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 }) }),
9253
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9349
+ bars && (bars.type === "fixed" || bars.type === "percent" || bars.type === "stddev") && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: bars.type === "percent" ? "Percent" : bars.type === "stddev" ? "Deviations" : "Amount", htmlFor: `${id}-value`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${id}-value`, value: String(bars.value ?? (0, import_chart4.defaultChartErrorBarValue)(bars.type)), inputMode: "decimal", "data-option": `${key}.value`, className: chartInputClass, onCommit: (text) => !!patch({ value: text.trim() === "" ? void 0 : Number(text) })?.ok }) }),
9350
+ bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
9351
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Plus", htmlFor: `${id}-plus`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${id}-plus`, value: (0, import_chart4.formatChartAmountList)(bars.plus), placeholder: "1, 2, -, 0.5", "data-option": `${key}.plus`, className: chartInputClass, onCommit: (text) => !!patch({ plus: (0, import_chart4.parseChartAmountList)(text) })?.ok }) }),
9352
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9254
9353
  ChartCommitInput,
9255
9354
  {
9256
9355
  id: `${id}-minus`,
@@ -9267,15 +9366,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
9267
9366
  }
9268
9367
  ) })
9269
9368
  ] }),
9270
- bars && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-2", children: [
9271
- /* @__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)) }),
9272
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
9369
+ bars && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-2", children: [
9370
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("select", { className: `${chartInputClass} flex-1`, "aria-label": "Error bar direction", value: bars.direction ?? "both", "data-option": `${key}.direction`, onChange: (e) => patch({ direction: e.currentTarget.value }), children: import_chart4.CHART_ERROR_BAR_DIRECTIONS.map((d) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: d, children: d === "both" ? "Both ways" : d === "plus" ? "Plus only" : "Minus only" }, d)) }),
9371
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
9273
9372
  ] })
9274
9373
  ] });
9275
9374
  }
9276
9375
  function ChartInspector({ controller, sections, className }) {
9277
9376
  const { spec, selectedSeries } = useChartState(controller);
9278
- const idBase = (0, import_react66.useId)();
9377
+ const idBase = (0, import_react67.useId)();
9279
9378
  const show = (section) => !sections || sections.includes(section);
9280
9379
  const cartesian = (0, import_chart4.isCartesianChart)(spec.type);
9281
9380
  const family = (0, import_chart4.chartFamily)(spec);
@@ -9287,29 +9386,29 @@ function ChartInspector({ controller, sections, className }) {
9287
9386
  const hasLines = cartesian && types.some((t) => t === "line" || t === "area");
9288
9387
  const seriesIndex = selectedSeries ? spec.series.findIndex((s) => s.id === selectedSeries.id) : -1;
9289
9388
  const scales = family === "cartesian" || family === "xy";
9290
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
9291
- 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)) }) }),
9292
- show("style") && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
9293
- /* @__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: [
9294
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "Quick layout\u2026" }),
9295
- 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))
9389
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
9390
+ show("type") && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: chartSectionClass, "data-section": "type", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "grid grid-cols-3 gap-0.5 rounded-md bg-muted p-0.5", role: "radiogroup", "aria-label": "Chart type", children: import_chart4.CHART_TYPES.map((type) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", role: "radio", "aria-checked": spec.type === type, "data-chart-type": type, className: chartSegmentClass(spec.type === type), onClick: () => controller.setType(type), children: import_chart4.CHART_TYPE_LABELS[type] }, type)) }) }),
9391
+ show("style") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
9392
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Layout", htmlFor: `${idBase}-layout`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("select", { id: `${idBase}-layout`, className: chartInputClass, value: "", "data-option": "preset.layout", onChange: (e) => e.currentTarget.value && controller.applyPreset({ layout: e.currentTarget.value }), children: [
9393
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Quick layout\u2026" }),
9394
+ import_chart4.CHART_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: p.id, title: p.description, children: p.label }, p.id))
9296
9395
  ] }) }),
9297
- /* @__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: [
9298
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "Custom" }),
9299
- 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))
9396
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Colours", htmlFor: `${idBase}-colors`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("select", { id: `${idBase}-colors`, className: chartInputClass, value: import_chart4.CHART_COLOR_SCHEMES.find((c) => c.palette.join() === spec.palette.join())?.id ?? "", "data-option": "preset.colors", onChange: (e) => e.currentTarget.value && controller.applyPreset({ colors: e.currentTarget.value }), children: [
9397
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Custom" }),
9398
+ import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: c.id, title: c.description, children: c.label }, c.id))
9300
9399
  ] }) }),
9301
- !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] }),
9302
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
9400
+ !colorCheck.ok && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-[11px] leading-snug text-amber-600 dark:text-amber-400", "data-chart-color-warning": "", children: colorCheck.issues[0] }),
9401
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
9303
9402
  ] }),
9304
- show("titles") && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
9305
- /* @__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) }) }),
9306
- /* @__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) }) })
9403
+ show("titles") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
9404
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Title", htmlFor: `${idBase}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-title`, value: spec.title, "data-option": "title", className: chartInputClass, onCommit: (title) => void controller.setTitle(title) }) }),
9405
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Subtitle", htmlFor: `${idBase}-subtitle`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-subtitle`, value: spec.subtitle, "data-option": "subtitle", className: chartInputClass, onCommit: (subtitle) => void controller.setSubtitle(subtitle) }) })
9307
9406
  ] }),
9308
- show("options") && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
9309
- 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 }) }) }),
9310
- 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)) }) }),
9311
- 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 }) }) }),
9312
- spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9407
+ show("options") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
9408
+ cartesian && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Stacking", htmlFor: `${idBase}-stacking`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Select, { id: `${idBase}-stacking`, name: "stacking", value: spec.stacking, options: import_chart4.CHART_STACKINGS, labels: { none: "None", stacked: "Stacked", percent: "100%" }, onChange: (stacking) => controller.update({ stacking }) }) }),
9409
+ hasBars && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Bars", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: ["vertical", "horizontal"].map((o) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", "aria-pressed": spec.orientation === o, "data-option": `orientation.${o}`, className: chartSegmentClass(spec.orientation === o), onClick: () => controller.update({ orientation: o }), children: cap(o) }, o)) }) }),
9410
+ hasLines && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Lines", htmlFor: `${idBase}-curve`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Select, { id: `${idBase}-curve`, name: "curve", value: spec.curve, options: import_chart4.CHART_CURVES, onChange: (curve) => controller.update({ curve }) }) }),
9411
+ spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9313
9412
  "input",
9314
9413
  {
9315
9414
  id: `${idBase}-hole`,
@@ -9325,7 +9424,7 @@ function ChartInspector({ controller, sections, className }) {
9325
9424
  onChange: (e) => controller.update({ innerRadius: Number(e.currentTarget.value) })
9326
9425
  }
9327
9426
  ) }),
9328
- hasBars && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9427
+ hasBars && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9329
9428
  "input",
9330
9429
  {
9331
9430
  id: `${idBase}-gap`,
@@ -9341,31 +9440,31 @@ function ChartInspector({ controller, sections, className }) {
9341
9440
  onChange: (e) => controller.update({ gapWidth: Number(e.currentTarget.value) })
9342
9441
  }
9343
9442
  ) }),
9344
- 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 }) }) }),
9345
- 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 }) }),
9346
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9347
- spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
9348
- hasLines && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
9349
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
9443
+ spec.dataLabels && hasBars && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Labels", htmlFor: `${idBase}-label-position`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Select, { id: `${idBase}-label-position`, name: "labelPosition", value: spec.labelPosition, options: import_chart4.CHART_LABEL_POSITIONS, onChange: (labelPosition) => controller.update({ labelPosition }) }) }),
9444
+ spec.type === "histogram" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Bins", htmlFor: `${idBase}-bins`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-bins`, value: spec.bins === null ? "" : String(spec.bins), placeholder: "Auto", inputMode: "numeric", "data-option": "bins", className: chartInputClass, onCommit: (text) => controller.update({ bins: text.trim() === "" ? null : Number(text) }).ok }) }),
9445
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
9446
+ spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
9447
+ hasLines && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
9448
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
9350
9449
  ] })
9351
9450
  ] }),
9352
- show("legend") && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
9353
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center justify-between", children: [
9354
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
9355
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
9451
+ show("legend") && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
9452
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center justify-between", children: [
9453
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
9454
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
9356
9455
  ] }),
9357
- 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)) })
9456
+ spec.legend.show && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: import_chart4.CHART_LEGEND_POSITIONS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", "aria-pressed": spec.legend.position === p, "data-option": `legend.${p}`, className: chartSegmentClass(spec.legend.position === p), onClick: () => controller.setLegend({ position: p }), children: cap(p) }, p)) })
9358
9457
  ] }),
9359
- show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
9360
- 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 }),
9361
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
9362
- usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
9458
+ show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
9459
+ family !== "box" && family !== "histogram" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(AxisSection, { controller, axis: "x", value: spec.xAxis, idBase, horizontal: spec.orientation === "horizontal", numeric: family === "xy", scales }),
9460
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
9461
+ usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
9363
9462
  ] }),
9364
- show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
9365
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
9366
- /* @__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 }) }) }),
9367
- /* @__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: [
9368
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
9463
+ show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
9464
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
9465
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Name", htmlFor: `${idBase}-series-name`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCommitInput, { id: `${idBase}-series-name`, value: selectedSeries.name, "data-option": "series.name", className: chartInputClass, onCommit: (name) => void controller.updateSeries(selectedSeries.id, { name }) }) }),
9466
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Colour", htmlFor: `${idBase}-series-color`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-1", children: [
9467
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9369
9468
  "input",
9370
9469
  {
9371
9470
  id: `${idBase}-series-color`,
@@ -9378,9 +9477,9 @@ function ChartInspector({ controller, sections, className }) {
9378
9477
  onChange: (e) => controller.updateSeries(selectedSeries.id, { color: e.currentTarget.value })
9379
9478
  }
9380
9479
  ),
9381
- 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" })
9480
+ selectedSeries.color && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "reset-color", onClick: () => controller.updateSeries(selectedSeries.id, { color: null }), children: "Palette" })
9382
9481
  ] }) }),
9383
- cartesian && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
9482
+ cartesian && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9384
9483
  "select",
9385
9484
  {
9386
9485
  id: `${idBase}-series-type`,
@@ -9389,12 +9488,12 @@ function ChartInspector({ controller, sections, className }) {
9389
9488
  "data-option": "series.type",
9390
9489
  onChange: (e) => controller.updateSeries(selectedSeries.id, { type: e.currentTarget.value || null }),
9391
9490
  children: [
9392
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "Chart type" }),
9393
- import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: t, children: import_chart4.CHART_TYPE_LABELS[t] }, t))
9491
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Chart type" }),
9492
+ import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: t, children: import_chart4.CHART_TYPE_LABELS[t] }, t))
9394
9493
  ]
9395
9494
  }
9396
9495
  ) }),
9397
- (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)(
9496
+ (cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Field, { label: "Marker", htmlFor: `${idBase}-series-marker`, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9398
9497
  "select",
9399
9498
  {
9400
9499
  id: `${idBase}-series-marker`,
@@ -9403,20 +9502,20 @@ function ChartInspector({ controller, sections, className }) {
9403
9502
  "data-option": "series.marker",
9404
9503
  onChange: (e) => controller.updateSeries(selectedSeries.id, { marker: e.currentTarget.value || null }),
9405
9504
  children: [
9406
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "Default" }),
9407
- import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: m, children: cap(m) }, m))
9505
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Default" }),
9506
+ import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: m, children: cap(m) }, m))
9408
9507
  ]
9409
9508
  }
9410
9509
  ) }),
9411
- scales && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
9412
- family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
9413
- (0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
9414
- (selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
9415
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
9416
- /* @__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 }) }),
9417
- /* @__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" })
9510
+ scales && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
9511
+ family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
9512
+ (0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
9513
+ (selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
9514
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
9515
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "R\xB2", name: `trendline.${i}.showR2`, checked: !!t.showR2, onChange: (showR2) => controller.updateTrendline(selectedSeries.id, i, { showR2 }) }),
9516
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, "aria-label": "Delete trendline", "data-action": "trendline-delete", onClick: () => controller.removeTrendline(selectedSeries.id, i), children: "\xD7" })
9418
9517
  ] }, i)),
9419
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
9518
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9420
9519
  "select",
9421
9520
  {
9422
9521
  className: chartInputClass,
@@ -9425,32 +9524,32 @@ function ChartInspector({ controller, sections, className }) {
9425
9524
  "data-option": "trendline.add",
9426
9525
  onChange: (e) => e.currentTarget.value && controller.addTrendline(selectedSeries.id, { type: e.currentTarget.value }),
9427
9526
  children: [
9428
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: "", children: "Add trendline\u2026" }),
9429
- import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
9527
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: "", children: "Add trendline\u2026" }),
9528
+ import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
9430
9529
  ]
9431
9530
  }
9432
9531
  )
9433
9532
  ] }),
9434
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
9435
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
9436
- 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 }) }),
9437
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "flex-1" }),
9438
- /* @__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" }),
9439
- /* @__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" }),
9440
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: `${chartButtonClass} text-destructive`, "data-action": "series-delete", onClick: () => controller.removeSeries(selectedSeries.id), children: "Delete" })
9533
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
9534
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
9535
+ family === "cartesian" && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Toggle, { label: "Secondary axis", name: "series.axis", checked: selectedSeries.axis === "secondary", onChange: (secondary) => controller.updateSeries(selectedSeries.id, { axis: secondary ? "secondary" : null }) }),
9536
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "flex-1" }),
9537
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, disabled: seriesIndex <= 0, "aria-label": "Move series earlier", "data-action": "series-up", onClick: () => controller.moveSeries(selectedSeries.id, seriesIndex - 1), children: "\u2191" }),
9538
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, disabled: seriesIndex >= spec.series.length - 1, "aria-label": "Move series later", "data-action": "series-down", onClick: () => controller.moveSeries(selectedSeries.id, seriesIndex + 1), children: "\u2193" }),
9539
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: `${chartButtonClass} text-destructive`, "data-action": "series-delete", onClick: () => controller.removeSeries(selectedSeries.id), children: "Delete" })
9441
9540
  ] })
9442
9541
  ] })
9443
9542
  ] });
9444
9543
  }
9445
9544
 
9446
9545
  // src/chart-node/ChartNodeView.tsx
9447
- var import_jsx_runtime47 = require("react/jsx-runtime");
9546
+ var import_jsx_runtime48 = require("react/jsx-runtime");
9448
9547
  function ChartNodeView({ state, theme, showDataGrid = true }) {
9449
9548
  const { controller, editing, editable, selected, width, height, setEditing } = state;
9450
9549
  const open = () => {
9451
9550
  if (editable && !editing) setEditing(true);
9452
9551
  };
9453
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
9552
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
9454
9553
  "div",
9455
9554
  {
9456
9555
  className: `not-prose my-2 rounded-md border bg-background p-1 ${selected ? "border-primary ring-1 ring-primary" : "border-border"}`,
@@ -9463,24 +9562,24 @@ function ChartNodeView({ state, theme, showDataGrid = true }) {
9463
9562
  }
9464
9563
  },
9465
9564
  children: [
9466
- 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: [
9467
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
9468
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
9565
+ editing && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "mb-1 flex items-center justify-between gap-2 px-1", "data-chart-node-toolbar": "", children: [
9566
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
9567
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
9469
9568
  ] }),
9470
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
9569
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
9471
9570
  "div",
9472
9571
  {
9473
9572
  className: editable && !editing ? "cursor-pointer" : void 0,
9474
9573
  onClick: open,
9475
9574
  title: editable && !editing ? "Click to edit the chart" : void 0,
9476
9575
  "data-chart-node-canvas": "",
9477
- children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
9576
+ children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
9478
9577
  }
9479
9578
  ),
9480
9579
  editing && // Wraps by the document's width, not the viewport's: side by side when there is room.
9481
- /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
9482
- 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 }) }),
9483
- /* @__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" })
9580
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
9581
+ showDataGrid && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "min-w-0 flex-[1_1_20rem] overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ChartDataGrid, { controller }) }),
9582
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ChartInspector, { controller, className: "max-h-96 min-w-0 flex-[1_1_16rem] overflow-y-auto rounded-md border border-border p-3" })
9484
9583
  ] })
9485
9584
  ]
9486
9585
  }
@@ -9498,7 +9597,7 @@ function createReactChartNodeView(options = {}) {
9498
9597
  scheduled = true;
9499
9598
  queueMicrotask(() => {
9500
9599
  scheduled = false;
9501
- if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(Component, { ...props, state: latest }));
9600
+ if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Component, { ...props, state: latest }));
9502
9601
  });
9503
9602
  };
9504
9603
  schedule();
@@ -9521,6 +9620,7 @@ function createReactChartNodeView(options = {}) {
9521
9620
  BrushOptionsBar,
9522
9621
  BubbleMenu,
9523
9622
  ChartNodeView,
9623
+ ColorProfilePanel,
9524
9624
  CommandPalette,
9525
9625
  CommentButton,
9526
9626
  CommentsPanel,