@pixerate/editor-react 0.63.0 → 0.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -53,6 +53,7 @@ __export(src_exports, {
53
53
  ImageEditor: () => ImageEditor,
54
54
  InsertTableGrid: () => InsertTableGrid,
55
55
  JobProgress: () => JobProgress,
56
+ LayerEffectsPanel: () => LayerEffectsPanel,
56
57
  LayersPanel: () => LayersPanel,
57
58
  MergePreview: () => MergePreview,
58
59
  NameManager: () => NameManager,
@@ -2003,17 +2004,17 @@ var SpreadsheetValidationDialog = ({ prompt, onResolve }) => {
2003
2004
  style === "warning" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "mt-2", children: "Continue?" })
2004
2005
  ] })
2005
2006
  ] }),
2006
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-4 flex justify-end gap-2", children: buttons.map((button2, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2007
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-4 flex justify-end gap-2", children: buttons.map((button3, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2007
2008
  "button",
2008
2009
  {
2009
2010
  ref: i === 0 ? firstButton : void 0,
2010
2011
  type: "button",
2011
- "data-action": button2.action,
2012
+ "data-action": button3.action,
2012
2013
  className: `rounded border border-border px-3 py-1 ${i === 0 ? "bg-primary text-primary-foreground" : "hover:bg-muted"}`,
2013
- onClick: () => onResolve(button2.action),
2014
- children: button2.label
2014
+ onClick: () => onResolve(button3.action),
2015
+ children: button3.label
2015
2016
  },
2016
- button2.action
2017
+ button3.action
2017
2018
  )) })
2018
2019
  ]
2019
2020
  }
@@ -3783,8 +3784,8 @@ function useImageEditor(options = {}) {
3783
3784
  }
3784
3785
 
3785
3786
  // src/image-editor/ImageEditor.tsx
3786
- var import_react42 = __toESM(require("react"), 1);
3787
- var import_image_editor10 = require("@pixerate/editor/image-editor");
3787
+ var import_react43 = __toESM(require("react"), 1);
3788
+ var import_image_editor11 = require("@pixerate/editor/image-editor");
3788
3789
 
3789
3790
  // src/image-editor/ControlSlider.tsx
3790
3791
  var import_image_editor2 = require("@pixerate/editor/image-editor");
@@ -4216,9 +4217,198 @@ var AdjustmentLayersPanel = ({ controller, layers: layersProp, histogram }) => {
4216
4217
  };
4217
4218
 
4218
4219
  // src/image-editor/LayersPanel.tsx
4220
+ var import_react39 = require("react");
4221
+
4222
+ // src/image-editor/LayerEffectsPanel.tsx
4219
4223
  var import_react38 = require("react");
4220
4224
  var import_image_editor6 = require("@pixerate/editor/image-editor");
4221
4225
  var import_jsx_runtime21 = require("react/jsx-runtime");
4226
+ var button = "px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40";
4227
+ var LayerEffectsPanel = ({ controller, layerId, className }) => {
4228
+ const [, setTick] = (0, import_react38.useState)(0);
4229
+ (0, import_react38.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
4230
+ const [open, setOpen] = (0, import_react38.useState)(null);
4231
+ const [error, setError] = (0, import_react38.useState)(null);
4232
+ const commitNext = (0, import_react38.useRef)(true);
4233
+ const layer = layerId ? controller.getLayer(layerId) : controller.getActiveLayer();
4234
+ const model = (0, import_image_editor6.layerEffectsPanel)(layer);
4235
+ const id = layer?.id;
4236
+ const attempt = (fn) => {
4237
+ try {
4238
+ setError(null);
4239
+ fn();
4240
+ } catch (err) {
4241
+ setError(err instanceof Error ? err.message : String(err));
4242
+ }
4243
+ };
4244
+ const sliderEvents = {
4245
+ onPointerDown: () => commitNext.current = true,
4246
+ onPointerUp: () => commitNext.current = true,
4247
+ onKeyDown: () => commitNext.current = true
4248
+ };
4249
+ if (!model.available || !id) {
4250
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: `text-xs text-slate-500 ${className ?? ""}`, "data-testid": "layer-effects", children: model.reason });
4251
+ }
4252
+ const effects = controller.getLayerEffects(id);
4253
+ const patterns = controller.getDocumentPatterns();
4254
+ const change = (effectId, control, value, drag = false) => attempt(() => {
4255
+ const effect = controller.getLayerEffects(id).items.find((e) => e.id === effectId);
4256
+ controller.updateLayerEffect(id, effectId, (0, import_image_editor6.effectControlChange)(effect, control.key, value, patterns), drag ? commitNext.current : true);
4257
+ if (drag) commitNext.current = false;
4258
+ });
4259
+ const renderControl = (effectId, c) => {
4260
+ const label = `${c.label}`;
4261
+ switch (c.type) {
4262
+ case "range": {
4263
+ const k = c.percent ? 100 : 1;
4264
+ const shown = Math.round(c.value * k * 100) / 100;
4265
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
4266
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-slate-400", children: [
4267
+ label,
4268
+ " ",
4269
+ shown,
4270
+ c.unit
4271
+ ] }),
4272
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4273
+ "input",
4274
+ {
4275
+ type: "range",
4276
+ "aria-label": label,
4277
+ min: c.min * k,
4278
+ max: c.max * k,
4279
+ step: c.step * k,
4280
+ value: shown,
4281
+ disabled: model.readOnly,
4282
+ ...sliderEvents,
4283
+ onChange: (e) => change(effectId, c, Number(e.target.value) / k, true),
4284
+ className: "accent-indigo-500"
4285
+ }
4286
+ )
4287
+ ] }, c.key);
4288
+ }
4289
+ case "color":
4290
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
4291
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { type: "color", "aria-label": label, value: c.value, disabled: model.readOnly, onChange: (e) => change(effectId, c, e.target.value) }),
4292
+ label
4293
+ ] }, c.key);
4294
+ case "checkbox":
4295
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
4296
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("input", { type: "checkbox", "aria-label": label, checked: c.value, disabled: model.readOnly, onChange: (e) => change(effectId, c, e.target.checked), className: "accent-indigo-500" }),
4297
+ label
4298
+ ] }, c.key);
4299
+ case "select":
4300
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
4301
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-slate-400", children: label }),
4302
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4303
+ "select",
4304
+ {
4305
+ "aria-label": label,
4306
+ value: c.value,
4307
+ disabled: model.readOnly,
4308
+ onChange: (e) => change(effectId, c, e.target.value),
4309
+ className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
4310
+ children: c.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: o.value, children: o.label }, o.value))
4311
+ }
4312
+ )
4313
+ ] }, c.key);
4314
+ }
4315
+ };
4316
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `flex flex-col gap-1.5 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layer-effects", "aria-label": "Layer effects", role: "group", children: [
4317
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-2", children: [
4318
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "font-semibold text-slate-300", children: "fx Effects" }),
4319
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1 text-slate-300", children: [
4320
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4321
+ "input",
4322
+ {
4323
+ type: "checkbox",
4324
+ "aria-label": "Effects on",
4325
+ checked: model.enabled,
4326
+ disabled: model.readOnly,
4327
+ onChange: (e) => attempt(() => controller.setLayerEffectsEnabled(id, e.target.checked)),
4328
+ className: "accent-indigo-500"
4329
+ }
4330
+ ),
4331
+ "On"
4332
+ ] }),
4333
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
4334
+ "Scale",
4335
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4336
+ "input",
4337
+ {
4338
+ type: "number",
4339
+ "aria-label": "Scale effects",
4340
+ min: 1,
4341
+ max: 1e3,
4342
+ step: 1,
4343
+ value: Math.round(model.scale * 100),
4344
+ disabled: model.readOnly,
4345
+ onChange: (e) => {
4346
+ const v = Number(e.target.value);
4347
+ if (v >= 1 && v <= 1e3) attempt(() => controller.setLayerEffectsEnabled(id, model.enabled, v / 100));
4348
+ },
4349
+ className: "w-14 bg-slate-800 border border-slate-700 rounded px-1"
4350
+ }
4351
+ ),
4352
+ "%"
4353
+ ] }),
4354
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4355
+ "select",
4356
+ {
4357
+ "aria-label": "Add effect",
4358
+ value: "",
4359
+ disabled: model.readOnly,
4360
+ onChange: (e) => {
4361
+ const kind = e.target.value;
4362
+ if (!kind) return;
4363
+ attempt(() => setOpen(controller.addLayerEffect(id, kind).effect.id));
4364
+ },
4365
+ className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
4366
+ children: [
4367
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: "", children: "Add effect\u2026" }),
4368
+ import_image_editor6.LAYER_EFFECT_MENU.map((m) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: m.kind, children: m.label }, m.kind))
4369
+ ]
4370
+ }
4371
+ )
4372
+ ] }),
4373
+ model.readOnly && model.reason && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-slate-500", children: model.reason }),
4374
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "flex flex-col gap-1", "aria-label": "Effects", children: model.rows.map((row) => {
4375
+ const effect = effects.items.find((e) => e.id === row.id);
4376
+ const expanded = open === row.id;
4377
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("li", { "data-effect-id": row.id, className: "rounded bg-slate-900/60 ring-1 ring-slate-800", children: [
4378
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-1.5 px-1.5 py-1", children: [
4379
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4380
+ "input",
4381
+ {
4382
+ type: "checkbox",
4383
+ "aria-label": `${row.label} on`,
4384
+ checked: row.enabled,
4385
+ disabled: model.readOnly,
4386
+ onChange: (e) => attempt(() => controller.updateLayerEffect(id, row.id, { enabled: e.target.checked })),
4387
+ className: "accent-indigo-500"
4388
+ }
4389
+ ),
4390
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4391
+ "button",
4392
+ {
4393
+ type: "button",
4394
+ "aria-expanded": expanded,
4395
+ className: `flex-1 text-left ${row.enabled && model.enabled ? "" : "text-slate-500"}`,
4396
+ onClick: () => setOpen(expanded ? null : row.id),
4397
+ children: row.label
4398
+ }
4399
+ ),
4400
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: button, "aria-label": `Remove ${row.label}`, disabled: model.readOnly, onClick: () => attempt(() => controller.removeLayerEffect(id, row.id)), children: "\u2715" })
4401
+ ] }),
4402
+ expanded && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 px-1.5 pb-1.5", "data-testid": "effect-settings", children: (0, import_image_editor6.layerEffectControls)(effect, patterns).map((c) => renderControl(row.id, c)) })
4403
+ ] }, row.id);
4404
+ }) }),
4405
+ error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
4406
+ ] });
4407
+ };
4408
+
4409
+ // src/image-editor/LayersPanel.tsx
4410
+ var import_image_editor7 = require("@pixerate/editor/image-editor");
4411
+ var import_jsx_runtime22 = require("react/jsx-runtime");
4222
4412
  var iconButton = "px-1.5 py-0.5 rounded text-[10px] bg-slate-800 text-slate-300 hover:text-white disabled:opacity-40";
4223
4413
  var rowClass = (active) => `flex items-center gap-1.5 px-1.5 py-1 rounded cursor-pointer select-none ${active ? "bg-indigo-600/30 ring-1 ring-indigo-500" : "hover:bg-slate-800"}`;
4224
4414
  var Thumbnail = ({
@@ -4229,8 +4419,8 @@ var Thumbnail = ({
4229
4419
  selected,
4230
4420
  testId
4231
4421
  }) => {
4232
- const ref = (0, import_react38.useRef)(null);
4233
- (0, import_react38.useEffect)(() => {
4422
+ const ref = (0, import_react39.useRef)(null);
4423
+ (0, import_react39.useEffect)(() => {
4234
4424
  const canvas = ref.current;
4235
4425
  const ctx = canvas?.getContext("2d");
4236
4426
  if (!canvas || !ctx || !pixels || typeof ctx.createImageData !== "function") return;
@@ -4240,7 +4430,7 @@ var Thumbnail = ({
4240
4430
  img.data.set(pixels.data);
4241
4431
  ctx.putImageData(img, 0, 0);
4242
4432
  }, [pixels]);
4243
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4433
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4244
4434
  "canvas",
4245
4435
  {
4246
4436
  ref,
@@ -4253,15 +4443,15 @@ var Thumbnail = ({
4253
4443
  }
4254
4444
  );
4255
4445
  };
4256
- var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", className }) => {
4257
- const [, setTick] = (0, import_react38.useState)(0);
4258
- (0, import_react38.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
4259
- const [error, setError] = (0, import_react38.useState)(null);
4260
- const [renaming, setRenaming] = (0, import_react38.useState)(null);
4261
- const [menu, setMenu] = (0, import_react38.useState)(null);
4262
- const [drag, setDrag] = (0, import_react38.useState)(null);
4263
- const [psdNotes, setPsdNotes] = (0, import_react38.useState)([]);
4264
- const fileInput = (0, import_react38.useRef)(null);
4446
+ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "image", effects = true, className }) => {
4447
+ const [, setTick] = (0, import_react39.useState)(0);
4448
+ (0, import_react39.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
4449
+ const [error, setError] = (0, import_react39.useState)(null);
4450
+ const [renaming, setRenaming] = (0, import_react39.useState)(null);
4451
+ const [menu, setMenu] = (0, import_react39.useState)(null);
4452
+ const [drag, setDrag] = (0, import_react39.useState)(null);
4453
+ const [psdNotes, setPsdNotes] = (0, import_react39.useState)([]);
4454
+ const fileInput = (0, import_react39.useRef)(null);
4265
4455
  const psdTask = async (fn) => {
4266
4456
  try {
4267
4457
  setError(null);
@@ -4270,9 +4460,9 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4270
4460
  setError(err instanceof Error ? err.message : String(err));
4271
4461
  }
4272
4462
  };
4273
- const commitNext = (0, import_react38.useRef)(true);
4463
+ const commitNext = (0, import_react39.useRef)(true);
4274
4464
  const state = controller.getState();
4275
- const rows = (0, import_image_editor6.layerPanelRows)(state.layers, state.activeLayerId);
4465
+ const rows = (0, import_image_editor7.layerPanelRows)(state.layers, state.activeLayerId);
4276
4466
  const active = controller.getActiveLayer();
4277
4467
  const attempt = (fn) => {
4278
4468
  try {
@@ -4284,7 +4474,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4284
4474
  };
4285
4475
  const run = async (action) => {
4286
4476
  setMenu(null);
4287
- setError(await (0, import_image_editor6.runLayerMenuAction)(controller, action));
4477
+ setError(await (0, import_image_editor7.runLayerMenuAction)(controller, action));
4288
4478
  };
4289
4479
  const prop = (key, value) => attempt(() => {
4290
4480
  controller.setLayerProperties(active.id, { [key]: value }, commitNext.current);
@@ -4302,20 +4492,20 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4302
4492
  if (!id) return;
4303
4493
  const rect = e.currentTarget.getBoundingClientRect();
4304
4494
  const fraction = rect.height ? (e.clientY - rect.top) / rect.height : 0.5;
4305
- const placement = (0, import_image_editor6.dropPlacement)(state.layers, id, row.layer.id, (0, import_image_editor6.dropZone)(fraction, row.layer.type === "group"));
4495
+ const placement = (0, import_image_editor7.dropPlacement)(state.layers, id, row.layer.id, (0, import_image_editor7.dropZone)(fraction, row.layer.type === "group"));
4306
4496
  if (placement) attempt(() => controller.moveLayer(id, placement));
4307
4497
  };
4308
4498
  const thumb = (layer) => layer.type === "pixel" ? controller.getLayerThumbnail(layer.id, { maxSide: 64 }) : null;
4309
4499
  const maskThumb = (layer) => layer.mask && !layer.mask.source ? controller.getLayerThumbnail(layer.id, { maxSide: 64, mask: true }) : null;
4310
4500
  const locked = (layer) => Boolean(layer.locks?.all || layer.locks?.pixels || layer.locks?.position || layer.locks?.transparency);
4311
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layers-panel", onClick: () => menu && setMenu(null), children: [
4312
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "toolbar", "aria-label": "Layer actions", children: [
4313
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-layer"), children: "New Layer" }),
4314
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-group"), children: "New Group" }),
4315
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("duplicate"), children: "Duplicate" }),
4316
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("add-mask"), children: "Add Mask" }),
4317
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("delete"), children: "Delete" }),
4318
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4501
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "layers-panel", onClick: () => menu && setMenu(null), children: [
4502
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-wrap items-center gap-1", role: "toolbar", "aria-label": "Layer actions", children: [
4503
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-layer"), children: "New Layer" }),
4504
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, onClick: () => run("new-group"), children: "New Group" }),
4505
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("duplicate"), children: "Duplicate" }),
4506
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("add-mask"), children: "Add Mask" }),
4507
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, disabled: !active, onClick: () => run("delete"), children: "Delete" }),
4508
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4319
4509
  "button",
4320
4510
  {
4321
4511
  type: "button",
@@ -4330,39 +4520,39 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4330
4520
  children: "\u22EF"
4331
4521
  }
4332
4522
  ),
4333
- psd && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
4334
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, onClick: () => fileInput.current?.click(), children: "Open PSD\u2026" }),
4335
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: iconButton, onClick: () => psdTask(async () => (await (0, import_image_editor6.downloadPsd)(controller, psdFileName)).warnings), children: "Export PSD" }),
4336
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4523
+ psd && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
4524
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: iconButton, onClick: () => fileInput.current?.click(), children: "Open PSD\u2026" }),
4525
+ /* @__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" }),
4526
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4337
4527
  "input",
4338
4528
  {
4339
4529
  ref: fileInput,
4340
4530
  type: "file",
4341
- accept: import_image_editor6.PSD_FILE_ACCEPT,
4531
+ accept: import_image_editor7.PSD_FILE_ACCEPT,
4342
4532
  className: "hidden",
4343
4533
  "data-testid": "psd-file-input",
4344
4534
  "aria-label": "Open a PSD file",
4345
4535
  onChange: (e) => {
4346
4536
  const file = e.currentTarget.files?.[0];
4347
4537
  e.currentTarget.value = "";
4348
- if (file) psdTask(() => (0, import_image_editor6.openPsdFile)(controller, file));
4538
+ if (file) psdTask(() => (0, import_image_editor7.openPsdFile)(controller, file));
4349
4539
  }
4350
4540
  }
4351
4541
  )
4352
4542
  ] })
4353
4543
  ] }),
4354
- psdNotes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("ul", { className: "rounded bg-amber-900/30 text-amber-200 px-2 py-1 space-y-0.5", "data-testid": "psd-warnings", "aria-label": "PSD warnings", children: [
4355
- psdNotes.map((n) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("li", { children: n }, n)),
4356
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", className: "underline", onClick: () => setPsdNotes([]), children: "Dismiss" }) })
4544
+ psdNotes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("ul", { className: "rounded bg-amber-900/30 text-amber-200 px-2 py-1 space-y-0.5", "data-testid": "psd-warnings", "aria-label": "PSD warnings", children: [
4545
+ psdNotes.map((n) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("li", { children: n }, n)),
4546
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: "underline", onClick: () => setPsdNotes([]), children: "Dismiss" }) })
4357
4547
  ] }),
4358
- active && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 items-center", "data-testid": "layer-properties", children: [
4359
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
4360
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-slate-400", children: [
4548
+ active && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "grid grid-cols-2 gap-x-2 gap-y-1 items-center", "data-testid": "layer-properties", children: [
4549
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
4550
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "text-slate-400", children: [
4361
4551
  "Opacity ",
4362
4552
  Math.round(active.opacity * 100),
4363
4553
  "%"
4364
4554
  ] }),
4365
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4555
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4366
4556
  "input",
4367
4557
  {
4368
4558
  type: "range",
@@ -4376,13 +4566,13 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4376
4566
  }
4377
4567
  )
4378
4568
  ] }),
4379
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
4380
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "text-slate-400", children: [
4569
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
4570
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: "text-slate-400", children: [
4381
4571
  "Fill ",
4382
4572
  Math.round(((active.type === "pixel" ? active.fillOpacity : void 0) ?? 1) * 100),
4383
4573
  "%"
4384
4574
  ] }),
4385
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4575
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4386
4576
  "input",
4387
4577
  {
4388
4578
  type: "range",
@@ -4397,7 +4587,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4397
4587
  }
4398
4588
  )
4399
4589
  ] }),
4400
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4590
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4401
4591
  "select",
4402
4592
  {
4403
4593
  "aria-label": "Layer blend mode",
@@ -4405,13 +4595,13 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4405
4595
  value: active.blend,
4406
4596
  onChange: (e) => attempt(() => controller.setLayerProperties(active.id, { blend: e.target.value })),
4407
4597
  children: [
4408
- active.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: "pass-through", children: "Pass Through" }),
4409
- import_image_editor6.BLEND_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: m.id, children: m.label }, m.id))
4598
+ active.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("option", { value: "pass-through", children: "Pass Through" }),
4599
+ import_image_editor7.BLEND_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("option", { value: m.id, children: m.label }, m.id))
4410
4600
  ]
4411
4601
  }
4412
4602
  ),
4413
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
4414
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4603
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5 text-slate-300", children: [
4604
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4415
4605
  "input",
4416
4606
  {
4417
4607
  type: "checkbox",
@@ -4423,8 +4613,8 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4423
4613
  ),
4424
4614
  "Clip to below"
4425
4615
  ] }),
4426
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "col-span-2 flex flex-wrap gap-2 text-slate-400", role: "group", "aria-label": "Layer locks", children: ["pixels", "transparency", "position", "all"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("label", { className: "flex items-center gap-1", children: [
4427
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4616
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "col-span-2 flex flex-wrap gap-2 text-slate-400", role: "group", "aria-label": "Layer locks", children: ["pixels", "transparency", "position", "all"].map((k) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1", children: [
4617
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4428
4618
  "input",
4429
4619
  {
4430
4620
  type: "checkbox",
@@ -4437,9 +4627,10 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4437
4627
  k
4438
4628
  ] }, k)) })
4439
4629
  ] }),
4440
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("ul", { className: "flex flex-col gap-0.5", role: "tree", "aria-label": "Layers", children: rows.map((row) => {
4630
+ effects && active && active.type !== "adjustment" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(LayerEffectsPanel, { controller, className: "border-t border-slate-800 pt-1.5" }),
4631
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("ul", { className: "flex flex-col gap-0.5", role: "tree", "aria-label": "Layers", children: rows.map((row) => {
4441
4632
  const { layer } = row;
4442
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
4633
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
4443
4634
  "li",
4444
4635
  {
4445
4636
  role: "treeitem",
@@ -4469,7 +4660,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4469
4660
  className: rowClass(row.active),
4470
4661
  style: { paddingLeft: 6 + row.depth * 14 },
4471
4662
  children: [
4472
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4663
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4473
4664
  "button",
4474
4665
  {
4475
4666
  type: "button",
@@ -4483,7 +4674,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4483
4674
  children: layer.visible ? "\u25CF" : "\u25CB"
4484
4675
  }
4485
4676
  ),
4486
- layer.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4677
+ layer.type === "group" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4487
4678
  "button",
4488
4679
  {
4489
4680
  type: "button",
@@ -4496,8 +4687,8 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4496
4687
  children: layer.collapsed ? "\u25B8" : "\u25BE"
4497
4688
  }
4498
4689
  ),
4499
- row.clipped && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-slate-500", "aria-label": "Clipped", children: "\u21B3" }),
4500
- layer.type === "pixel" ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4690
+ row.clipped && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-slate-500", "aria-label": "Clipped", children: "\u21B3" }),
4691
+ layer.type === "pixel" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4501
4692
  Thumbnail,
4502
4693
  {
4503
4694
  pixels: thumb(layer),
@@ -4505,15 +4696,15 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4505
4696
  label: `${row.label} pixels`,
4506
4697
  selected: row.active && state.activeTarget === "pixels" && Boolean(layer.mask)
4507
4698
  }
4508
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4699
+ ) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4509
4700
  "span",
4510
4701
  {
4511
4702
  className: "shrink-0 grid place-items-center rounded bg-slate-800 text-[9px] text-slate-400 ring-1 ring-slate-700",
4512
4703
  style: { width: thumbnailSize, height: thumbnailSize },
4513
- children: (0, import_image_editor6.layerBadge)(layer)
4704
+ children: (0, import_image_editor7.layerBadge)(layer)
4514
4705
  }
4515
4706
  ),
4516
- layer.mask && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4707
+ layer.mask && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4517
4708
  Thumbnail,
4518
4709
  {
4519
4710
  pixels: maskThumb(layer),
@@ -4528,7 +4719,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4528
4719
  }
4529
4720
  }
4530
4721
  ),
4531
- renaming === layer.id ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4722
+ renaming === layer.id ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4532
4723
  "input",
4533
4724
  {
4534
4725
  autoFocus: true,
@@ -4545,7 +4736,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4545
4736
  if (e.key === "Escape") setRenaming(null);
4546
4737
  }
4547
4738
  }
4548
- ) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4739
+ ) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4549
4740
  "span",
4550
4741
  {
4551
4742
  className: `flex-1 min-w-0 truncate ${layer.visible ? "" : "text-slate-500"}`,
@@ -4556,15 +4747,30 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4556
4747
  children: row.label
4557
4748
  }
4558
4749
  ),
4559
- locked(layer) && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { "aria-label": "Locked", className: "text-slate-400", children: "\u{1F512}" }),
4560
- layer.blend !== "normal" && layer.blend !== "pass-through" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-[9px] text-slate-500", children: layer.blend })
4750
+ (0, import_image_editor7.layerEffectsBadge)(layer) && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4751
+ "button",
4752
+ {
4753
+ type: "button",
4754
+ "data-testid": "layer-fx-badge",
4755
+ "aria-label": (0, import_image_editor7.layerEffectsBadge)(layer) === "on" ? `Turn effects off for ${row.label}` : `Turn effects on for ${row.label}`,
4756
+ "aria-pressed": (0, import_image_editor7.layerEffectsBadge)(layer) === "on",
4757
+ className: `text-[9px] italic font-semibold ${(0, import_image_editor7.layerEffectsBadge)(layer) === "on" ? "text-indigo-300" : "text-slate-600 line-through"}`,
4758
+ onClick: (e) => {
4759
+ e.stopPropagation();
4760
+ attempt(() => controller.setLayerEffectsEnabled(layer.id, (0, import_image_editor7.layerEffectsBadge)(layer) !== "on"));
4761
+ },
4762
+ children: "fx"
4763
+ }
4764
+ ),
4765
+ locked(layer) && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { "aria-label": "Locked", className: "text-slate-400", children: "\u{1F512}" }),
4766
+ layer.blend !== "normal" && layer.blend !== "pass-through" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-[9px] text-slate-500", children: layer.blend })
4561
4767
  ]
4562
4768
  },
4563
4769
  layer.id
4564
4770
  );
4565
4771
  }) }),
4566
- error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
4567
- menu && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4772
+ error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
4773
+ menu && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4568
4774
  "div",
4569
4775
  {
4570
4776
  role: "menu",
@@ -4573,7 +4779,7 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4573
4779
  style: { left: menu.x, top: menu.y },
4574
4780
  onClick: (e) => e.stopPropagation(),
4575
4781
  onKeyDown: (e) => e.key === "Escape" && setMenu(null),
4576
- children: (0, import_image_editor6.layerMenu)(controller).map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
4782
+ children: (0, import_image_editor7.layerMenu)(controller).map((item) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4577
4783
  "button",
4578
4784
  {
4579
4785
  type: "button",
@@ -4591,14 +4797,14 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4591
4797
  };
4592
4798
 
4593
4799
  // src/image-editor/BrushOptionsBar.tsx
4594
- var import_react39 = require("react");
4595
- var import_image_editor7 = require("@pixerate/editor/image-editor");
4596
- var import_jsx_runtime22 = require("react/jsx-runtime");
4800
+ var import_react40 = require("react");
4801
+ var import_image_editor8 = require("@pixerate/editor/image-editor");
4802
+ var import_jsx_runtime23 = require("react/jsx-runtime");
4597
4803
  var chip = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
4598
4804
  var BrushOptionsBar = ({ controller, className }) => {
4599
- const [, setTick] = (0, import_react39.useState)(0);
4600
- (0, import_react39.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
4601
- const [error, setError] = (0, import_react39.useState)(null);
4805
+ const [, setTick] = (0, import_react40.useState)(0);
4806
+ (0, import_react40.useEffect)(() => controller.subscribe(() => setTick((n) => n + 1)), [controller]);
4807
+ const [error, setError] = (0, import_react40.useState)(null);
4602
4808
  const state = controller.getState();
4603
4809
  const { brush, foreground, background, mixer, mixerLoad } = state.paint;
4604
4810
  const attempt = (fn) => {
@@ -4609,8 +4815,8 @@ var BrushOptionsBar = ({ controller, className }) => {
4609
4815
  setError(err instanceof Error ? err.message : String(err));
4610
4816
  }
4611
4817
  };
4612
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
4613
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor7.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4818
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `flex flex-col gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "brush-options", children: [
4819
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex gap-1", role: "toolbar", "aria-label": "Paint tools", children: import_image_editor8.PAINT_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4614
4820
  "button",
4615
4821
  {
4616
4822
  type: "button",
@@ -4622,9 +4828,9 @@ var BrushOptionsBar = ({ controller, className }) => {
4622
4828
  },
4623
4829
  t.id
4624
4830
  )) }),
4625
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
4626
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1", children: [
4627
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4831
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", role: "group", "aria-label": "Colours", children: [
4832
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1", children: [
4833
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4628
4834
  "input",
4629
4835
  {
4630
4836
  type: "color",
@@ -4634,10 +4840,10 @@ var BrushOptionsBar = ({ controller, className }) => {
4634
4840
  className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
4635
4841
  }
4636
4842
  ),
4637
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-slate-400", children: "FG" })
4843
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-slate-400", children: "FG" })
4638
4844
  ] }),
4639
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1", children: [
4640
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4845
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1", children: [
4846
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4641
4847
  "input",
4642
4848
  {
4643
4849
  type: "color",
@@ -4647,12 +4853,12 @@ var BrushOptionsBar = ({ controller, className }) => {
4647
4853
  className: "h-6 w-8 rounded border border-slate-700 bg-transparent"
4648
4854
  }
4649
4855
  ),
4650
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-slate-400", children: "BG" })
4856
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-slate-400", children: "BG" })
4651
4857
  ] }),
4652
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
4653
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" })
4858
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Swap colours (X)", className: chip(false), onClick: () => controller.swapPaintColors(), children: "Swap" }),
4859
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Default colours (D)", className: chip(false), onClick: () => controller.resetPaintColors(), children: "Default" })
4654
4860
  ] }),
4655
- import_image_editor7.BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4861
+ import_image_editor8.BRUSH_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4656
4862
  ControlSlider,
4657
4863
  {
4658
4864
  spec,
@@ -4661,21 +4867,21 @@ var BrushOptionsBar = ({ controller, className }) => {
4661
4867
  },
4662
4868
  spec.id
4663
4869
  )),
4664
- state.activeTool === "mixer" && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Mixer Brush", "data-testid": "mixer-options", children: [
4665
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", children: [
4666
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4870
+ state.activeTool === "mixer" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2 border-t border-slate-800 pt-2", role: "group", "aria-label": "Mixer Brush", "data-testid": "mixer-options", children: [
4871
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", children: [
4872
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4667
4873
  "span",
4668
4874
  {
4669
4875
  "aria-label": "Brush load",
4670
- title: mixerLoad.reservoir ? `Loaded ${(0, import_image_editor7.rgbUnitToHex)(mixerLoad.reservoir)}, ${Math.round(mixerLoad.amount * 100)}% left` : "Unloaded",
4876
+ title: mixerLoad.reservoir ? `Loaded ${(0, import_image_editor8.rgbUnitToHex)(mixerLoad.reservoir)}, ${Math.round(mixerLoad.amount * 100)}% left` : "Unloaded",
4671
4877
  className: "h-6 w-6 rounded border border-slate-700",
4672
- style: { background: mixerLoad.reservoir ? (0, import_image_editor7.rgbUnitToHex)(mixerLoad.reservoir) : "transparent" }
4878
+ style: { background: mixerLoad.reservoir ? (0, import_image_editor8.rgbUnitToHex)(mixerLoad.reservoir) : "transparent" }
4673
4879
  }
4674
4880
  ),
4675
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", title: "Fill the reservoir with the foreground colour", className: chip(false), onClick: () => controller.loadMixerBrush(), children: "Load brush" }),
4676
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", title: "Empty the picked-up colour", className: chip(false), onClick: () => controller.cleanMixerBrush(), children: "Clean brush" })
4881
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Fill the reservoir with the foreground colour", className: chip(false), onClick: () => controller.loadMixerBrush(), children: "Load brush" }),
4882
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", title: "Empty the picked-up colour", className: chip(false), onClick: () => controller.cleanMixerBrush(), children: "Clean brush" })
4677
4883
  ] }),
4678
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Mixing", children: import_image_editor7.MIXER_MIXING_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4884
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Mixing", children: import_image_editor8.MIXER_MIXING_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4679
4885
  "button",
4680
4886
  {
4681
4887
  type: "button",
@@ -4687,10 +4893,10 @@ var BrushOptionsBar = ({ controller, className }) => {
4687
4893
  },
4688
4894
  m.id
4689
4895
  )) }),
4690
- import_image_editor7.MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ControlSlider, { spec, value: mixer[spec.id], onChange: (v) => controller.setPaintOptions({ mixer: { [spec.id]: v } }) }, spec.id)),
4691
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: [
4692
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4693
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4896
+ import_image_editor8.MIXER_OPTION_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ControlSlider, { spec, value: mixer[spec.id], onChange: (v) => controller.setPaintOptions({ mixer: { [spec.id]: v } }) }, spec.id)),
4897
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", children: [
4898
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4899
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4694
4900
  "input",
4695
4901
  {
4696
4902
  type: "checkbox",
@@ -4702,8 +4908,8 @@ var BrushOptionsBar = ({ controller, className }) => {
4702
4908
  ),
4703
4909
  "Load each stroke"
4704
4910
  ] }),
4705
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4706
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4911
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4912
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4707
4913
  "input",
4708
4914
  {
4709
4915
  type: "checkbox",
@@ -4717,9 +4923,9 @@ var BrushOptionsBar = ({ controller, className }) => {
4717
4923
  ] })
4718
4924
  ] })
4719
4925
  ] }),
4720
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
4721
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4722
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4926
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap gap-3 text-slate-300", role: "group", "aria-label": "Pressure", children: [
4927
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4928
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4723
4929
  "input",
4724
4930
  {
4725
4931
  type: "checkbox",
@@ -4731,8 +4937,8 @@ var BrushOptionsBar = ({ controller, className }) => {
4731
4937
  ),
4732
4938
  "Pressure size"
4733
4939
  ] }),
4734
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4735
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4940
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1.5", children: [
4941
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4736
4942
  "input",
4737
4943
  {
4738
4944
  type: "checkbox",
@@ -4745,18 +4951,18 @@ var BrushOptionsBar = ({ controller, className }) => {
4745
4951
  "Pressure opacity"
4746
4952
  ] })
4747
4953
  ] }),
4748
- /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex gap-1", children: [
4749
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
4750
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
4954
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex gap-1", children: [
4955
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.fillPixels()), children: "Fill" }),
4956
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: chip(false), onClick: () => attempt(() => controller.clearPixels()), children: "Clear" })
4751
4957
  ] }),
4752
- error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
4958
+ error && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { role: "alert", className: "text-rose-400", children: error })
4753
4959
  ] });
4754
4960
  };
4755
4961
 
4756
4962
  // src/image-editor/SelectionOptionsBar.tsx
4757
- var import_react40 = require("react");
4758
- var import_image_editor8 = require("@pixerate/editor/image-editor");
4759
- var import_jsx_runtime23 = require("react/jsx-runtime");
4963
+ var import_react41 = require("react");
4964
+ var import_image_editor9 = require("@pixerate/editor/image-editor");
4965
+ var import_jsx_runtime24 = require("react/jsx-runtime");
4760
4966
  var MODIFY_OPS = [
4761
4967
  { op: "grow", label: "Grow" },
4762
4968
  { op: "shrink", label: "Shrink" },
@@ -4773,20 +4979,20 @@ var SelectionOptionsBar = ({
4773
4979
  quickMask,
4774
4980
  className = ""
4775
4981
  }) => {
4776
- const [radius, setRadius] = (0, import_react40.useState)(2);
4982
+ const [radius, setRadius] = (0, import_react41.useState)(2);
4777
4983
  const set = (patch) => onOptionsChange({ ...options, ...patch });
4778
4984
  const sel = selection === void 0 ? controller.getSelection() : selection;
4779
4985
  const qm = quickMask ?? Boolean(controller.getState().quickMask);
4780
- return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
4781
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { role: "group", "aria-label": "Selection tool", className: "flex flex-wrap gap-1", children: import_image_editor8.SELECTION_TOOLS.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.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)) }),
4782
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { role: "group", "aria-label": "Selection mode", className: "flex flex-wrap gap-1", children: import_image_editor8.SELECTION_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", "aria-pressed": options.mode === m, className: btn(options.mode === m), onClick: () => set({ mode: m }), children: import_image_editor8.SELECTION_MODE_LABELS[m] }, m)) }),
4783
- options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col gap-2", children: [
4784
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex flex-col gap-1", children: [
4785
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
4786
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "Tolerance" }),
4787
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "font-mono", children: options.tolerance })
4986
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { "data-testid": "selection-options-bar", className: `flex flex-col gap-3 text-xs ${className}`, children: [
4987
+ /* @__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)) }),
4988
+ /* @__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)) }),
4989
+ options.tool === "wand" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col gap-2", children: [
4990
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
4991
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
4992
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Tolerance" }),
4993
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "font-mono", children: options.tolerance })
4788
4994
  ] }),
4789
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
4995
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4790
4996
  "input",
4791
4997
  {
4792
4998
  type: "range",
@@ -4800,17 +5006,17 @@ var SelectionOptionsBar = ({
4800
5006
  }
4801
5007
  )
4802
5008
  ] }),
4803
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
4804
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
5009
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5010
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.contiguous, onChange: (e) => set({ contiguous: e.target.checked }) }),
4805
5011
  "Contiguous"
4806
5012
  ] }),
4807
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
4808
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
5013
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5014
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.sampleMerged, onChange: (e) => set({ sampleMerged: e.target.checked }) }),
4809
5015
  "Sample adjusted image"
4810
5016
  ] }),
4811
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5017
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
4812
5018
  "Sample",
4813
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
5019
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
4814
5020
  "select",
4815
5021
  {
4816
5022
  "aria-label": "Sample from",
@@ -4818,27 +5024,27 @@ var SelectionOptionsBar = ({
4818
5024
  onChange: (e) => set({ sample: e.target.value }),
4819
5025
  className: "bg-slate-800 border border-slate-700 rounded px-1 py-0.5",
4820
5026
  children: [
4821
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "composite", children: "All layers" }),
4822
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "active-layer", children: "Active layer" })
5027
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "composite", children: "All layers" }),
5028
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: "active-layer", children: "Active layer" })
4823
5029
  ]
4824
5030
  }
4825
5031
  )
4826
5032
  ] })
4827
5033
  ] }),
4828
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
4829
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
5034
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5035
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: options.antiAlias, onChange: (e) => set({ antiAlias: e.target.checked }) }),
4830
5036
  "Anti-alias"
4831
5037
  ] }),
4832
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
4833
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
4834
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
4835
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
4836
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
5038
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5039
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.selectAll(), children: "Select All" }),
5040
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.deselect(), children: "Deselect" }),
5041
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: btn(false), onClick: () => controller.invertSelection(), children: "Inverse" }),
5042
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", "aria-pressed": qm, className: btn(qm), onClick: () => controller.setQuickMask(!qm), children: "Quick Mask" })
4837
5043
  ] }),
4838
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
4839
- /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
5044
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
5045
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-1 text-slate-400", children: [
4840
5046
  "Radius",
4841
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
5047
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
4842
5048
  "input",
4843
5049
  {
4844
5050
  type: "number",
@@ -4852,24 +5058,24 @@ var SelectionOptionsBar = ({
4852
5058
  }
4853
5059
  )
4854
5060
  ] }),
4855
- MODIFY_OPS.map(({ op, label }) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", className: btn(false), disabled: !sel, onClick: () => controller.modifySelection(op, radius), children: label }, op))
5061
+ 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))
4856
5062
  ] }),
4857
- /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor8.describeSelection)(sel) })
5063
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { "data-testid": "selection-status", className: "text-slate-400", children: (0, import_image_editor9.describeSelection)(sel) })
4858
5064
  ] });
4859
5065
  };
4860
5066
 
4861
5067
  // src/image-editor/RefineEdgePanel.tsx
4862
- var import_react41 = require("react");
4863
- var import_image_editor9 = require("@pixerate/editor/image-editor");
4864
- var import_jsx_runtime24 = require("react/jsx-runtime");
5068
+ var import_react42 = require("react");
5069
+ var import_image_editor10 = require("@pixerate/editor/image-editor");
5070
+ var import_jsx_runtime25 = require("react/jsx-runtime");
4865
5071
  var DEFAULT_PARAMS = { radius: 8, smartRadius: false, smooth: 0, feather: 0, contrast: 0, shiftEdge: 0 };
4866
- var button = "px-2 py-1 rounded-md border border-slate-800 bg-slate-950 text-[11px] text-slate-200 hover:text-white disabled:opacity-40";
5072
+ 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";
4867
5073
  var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
4868
- const [params, setParams] = (0, import_react41.useState)(DEFAULT_PARAMS);
4869
- const [busy, setBusy] = (0, import_react41.useState)(false);
4870
- const [error, setError] = (0, import_react41.useState)(null);
4871
- const [layerId, setLayerId] = (0, import_react41.useState)("");
4872
- const [newKind, setNewKind] = (0, import_react41.useState)("hueSaturation");
5074
+ const [params, setParams] = (0, import_react42.useState)(DEFAULT_PARAMS);
5075
+ const [busy, setBusy] = (0, import_react42.useState)(false);
5076
+ const [error, setError] = (0, import_react42.useState)(null);
5077
+ const [layerId, setLayerId] = (0, import_react42.useState)("");
5078
+ const [newKind, setNewKind] = (0, import_react42.useState)("hueSaturation");
4873
5079
  const sel = selection === void 0 ? controller.getSelection() : selection;
4874
5080
  const list = layers ?? controller.getAdjustmentLayers();
4875
5081
  const target = list.find((l) => l.id === layerId) ?? list[list.length - 1];
@@ -4884,17 +5090,17 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
4884
5090
  setBusy(false);
4885
5091
  }
4886
5092
  };
4887
- return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
4888
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
4889
- import_image_editor9.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
4890
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
4891
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: c.label }),
4892
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "font-mono", children: [
5093
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { "data-testid": "refine-edge-panel", className: `flex flex-col gap-3 text-xs ${className}`, children: [
5094
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Refine Edge" }),
5095
+ import_image_editor10.REFINE_EDGE_CONTROLS.map((c) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5096
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5097
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: c.label }),
5098
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
4893
5099
  params[c.id],
4894
5100
  c.unit
4895
5101
  ] })
4896
5102
  ] }),
4897
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5103
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4898
5104
  "input",
4899
5105
  {
4900
5106
  type: "range",
@@ -4908,67 +5114,67 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
4908
5114
  }
4909
5115
  )
4910
5116
  ] }, c.id)),
4911
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
4912
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
5117
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 text-slate-300", children: [
5118
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("input", { type: "checkbox", checked: params.smartRadius, onChange: (e) => setParams({ ...params, smartRadius: e.target.checked }) }),
4913
5119
  "Smart Radius"
4914
5120
  ] }),
4915
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-1", children: [
4916
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
4917
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
5121
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-1", children: [
5122
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !sel || busy, onClick: refine, children: "Refine Edge" }),
5123
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, onClick: () => setParams(DEFAULT_PARAMS), children: "Reset" })
4918
5124
  ] }),
4919
- error && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
4920
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
4921
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-1 items-center", children: [
4922
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5125
+ error && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-rose-400", children: error }),
5126
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] mt-2", children: "Layer Mask" }),
5127
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-1 items-center", children: [
5128
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4923
5129
  "select",
4924
5130
  {
4925
5131
  "aria-label": "New masked layer kind",
4926
5132
  value: newKind,
4927
5133
  onChange: (e) => setNewKind(e.target.value),
4928
5134
  className: "flex-1 bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
4929
- children: import_image_editor9.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: k.kind, children: k.label }, k.kind))
5135
+ children: import_image_editor10.ADJUSTMENT_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: k.kind, children: k.label }, k.kind))
4930
5136
  }
4931
5137
  ),
4932
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5138
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4933
5139
  "button",
4934
5140
  {
4935
5141
  type: "button",
4936
- className: button,
5142
+ className: button2,
4937
5143
  disabled: !sel,
4938
- onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor9.layerMaskFromSelection)(sel) })),
5144
+ onClick: () => sel && setLayerId(controller.addAdjustmentLayer({ kind: newKind, mask: (0, import_image_editor10.layerMaskFromSelection)(sel) })),
4939
5145
  children: "New Masked Layer"
4940
5146
  }
4941
5147
  )
4942
5148
  ] }),
4943
- list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col gap-2", children: [
4944
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5149
+ list.length > 0 && target && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-2", children: [
5150
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4945
5151
  "select",
4946
5152
  {
4947
5153
  "aria-label": "Mask layer",
4948
5154
  value: target.id,
4949
5155
  onChange: (e) => setLayerId(e.target.value),
4950
5156
  className: "bg-slate-950 border border-slate-800 rounded px-1 py-1 text-slate-200",
4951
- children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("option", { value: l.id, children: [
4952
- l.name || (0, import_image_editor9.adjustmentKindLabel)(l.kind),
5157
+ children: list.map((l) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("option", { value: l.id, children: [
5158
+ l.name || (0, import_image_editor10.adjustmentKindLabel)(l.kind),
4953
5159
  l.mask ? " (masked)" : ""
4954
5160
  ] }, l.id))
4955
5161
  }
4956
5162
  ),
4957
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
4958
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
4959
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
4960
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("button", { type: "button", className: button, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
5163
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-wrap gap-1", children: [
5164
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !sel, onClick: () => controller.applySelectionAsLayerMask(target.id), children: "Mask with Selection" }),
5165
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.selectionFromLayerMask(target.id), children: "Load as Selection" }),
5166
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { type: "button", className: button2, disabled: !target.mask, onClick: () => controller.setAdjustmentLayerMask(target.id, null), children: "Remove Mask" })
4961
5167
  ] }),
4962
- target.mask && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
4963
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
4964
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
4965
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Density" }),
4966
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "font-mono", children: [
5168
+ target.mask && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5169
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5170
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5171
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Density" }),
5172
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
4967
5173
  Math.round((target.mask.density ?? 1) * 100),
4968
5174
  "%"
4969
5175
  ] })
4970
5176
  ] }),
4971
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5177
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4972
5178
  "input",
4973
5179
  {
4974
5180
  type: "range",
@@ -4982,15 +5188,15 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
4982
5188
  }
4983
5189
  )
4984
5190
  ] }),
4985
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("label", { className: "flex flex-col gap-1", children: [
4986
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
4987
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: "Mask Feather" }),
4988
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "font-mono", children: [
5191
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex flex-col gap-1", children: [
5192
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "flex justify-between text-slate-400", children: [
5193
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Mask Feather" }),
5194
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
4989
5195
  target.mask.feather ?? 0,
4990
5196
  "px"
4991
5197
  ] })
4992
5198
  ] }),
4993
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
5199
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4994
5200
  "input",
4995
5201
  {
4996
5202
  type: "range",
@@ -5010,7 +5216,7 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5010
5216
  };
5011
5217
 
5012
5218
  // src/image-editor/ImageEditor.tsx
5013
- var import_jsx_runtime25 = require("react/jsx-runtime");
5219
+ var import_jsx_runtime26 = require("react/jsx-runtime");
5014
5220
  var ImageEditor = ({
5015
5221
  editor: externalEditor,
5016
5222
  src,
@@ -5025,35 +5231,35 @@ var ImageEditor = ({
5025
5231
  const internalEditor = useImageEditor({ image: src });
5026
5232
  const editor = externalEditor || internalEditor;
5027
5233
  const { state, controller } = editor;
5028
- const legacyProcess = (0, import_image_editor10.normalizeProcessVersion)(state.adjustments.process) < import_image_editor10.LATEST_PROCESS_VERSION;
5029
- const canvasRef = (0, import_react42.useRef)(null);
5030
- const containerRef = (0, import_react42.useRef)(null);
5031
- const [activeTab, setActiveTab] = (0, import_react42.useState)("crop");
5032
- const [activeCropRatio, setActiveCropRatio] = (0, import_react42.useState)(null);
5033
- const [selectionOptions, setSelectionOptions] = (0, import_react42.useState)(import_image_editor10.DEFAULT_SELECTION_TOOL_OPTIONS);
5034
- const selectionOptionsRef = (0, import_react42.useRef)(selectionOptions);
5234
+ const legacyProcess = (0, import_image_editor11.normalizeProcessVersion)(state.adjustments.process) < import_image_editor11.LATEST_PROCESS_VERSION;
5235
+ const canvasRef = (0, import_react43.useRef)(null);
5236
+ const containerRef = (0, import_react43.useRef)(null);
5237
+ const [activeTab, setActiveTab] = (0, import_react43.useState)("crop");
5238
+ const [activeCropRatio, setActiveCropRatio] = (0, import_react43.useState)(null);
5239
+ const [selectionOptions, setSelectionOptions] = (0, import_react43.useState)(import_image_editor11.DEFAULT_SELECTION_TOOL_OPTIONS);
5240
+ const selectionOptionsRef = (0, import_react43.useRef)(selectionOptions);
5035
5241
  selectionOptionsRef.current = selectionOptions;
5036
- const selectionGestureRef = (0, import_react42.useRef)(null);
5242
+ const selectionGestureRef = (0, import_react43.useRef)(null);
5037
5243
  if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
5038
- selectionGestureRef.current = new import_image_editor10.SelectionGesture(controller, () => selectionOptionsRef.current);
5244
+ selectionGestureRef.current = new import_image_editor11.SelectionGesture(controller, () => selectionOptionsRef.current);
5039
5245
  }
5040
- const selectionDraftRef = (0, import_react42.useRef)(null);
5041
- const [selectionError, setSelectionError] = (0, import_react42.useState)(null);
5042
- const paintGestureRef = (0, import_react42.useRef)(null);
5043
- const paintControllerRef = (0, import_react42.useRef)(controller);
5246
+ const selectionDraftRef = (0, import_react43.useRef)(null);
5247
+ const [selectionError, setSelectionError] = (0, import_react43.useState)(null);
5248
+ const paintGestureRef = (0, import_react43.useRef)(null);
5249
+ const paintControllerRef = (0, import_react43.useRef)(controller);
5044
5250
  if (!paintGestureRef.current || paintControllerRef.current !== controller) {
5045
- paintGestureRef.current = new import_image_editor10.PaintGesture(controller);
5251
+ paintGestureRef.current = new import_image_editor11.PaintGesture(controller);
5046
5252
  paintControllerRef.current = controller;
5047
5253
  }
5048
- const brushCursorRef = (0, import_react42.useRef)(null);
5049
- const [paintError, setPaintError] = (0, import_react42.useState)(null);
5050
- const [inpaintPrompt, setInpaintPrompt] = (0, import_react42.useState)("");
5051
- const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react42.useState)("annotations");
5052
- const [isRemovingBg, setIsRemovingBg] = (0, import_react42.useState)(false);
5053
- const [isInpainting, setIsInpainting] = (0, import_react42.useState)(false);
5054
- const [aiError, setAiError] = (0, import_react42.useState)(null);
5055
- const [aiSuccess, setAiSuccess] = (0, import_react42.useState)(null);
5056
- const [aiTarget, setAiTarget] = (0, import_react42.useState)("auto");
5254
+ const brushCursorRef = (0, import_react43.useRef)(null);
5255
+ const [paintError, setPaintError] = (0, import_react43.useState)(null);
5256
+ const [inpaintPrompt, setInpaintPrompt] = (0, import_react43.useState)("");
5257
+ const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react43.useState)("annotations");
5258
+ const [isRemovingBg, setIsRemovingBg] = (0, import_react43.useState)(false);
5259
+ const [isInpainting, setIsInpainting] = (0, import_react43.useState)(false);
5260
+ const [aiError, setAiError] = (0, import_react43.useState)(null);
5261
+ const [aiSuccess, setAiSuccess] = (0, import_react43.useState)(null);
5262
+ const [aiTarget, setAiTarget] = (0, import_react43.useState)("auto");
5057
5263
  const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
5058
5264
  const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
5059
5265
  const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
@@ -5116,18 +5322,18 @@ var ImageEditor = ({
5116
5322
  setIsInpainting(false);
5117
5323
  }
5118
5324
  };
5119
- const [activeColor, setActiveColor] = (0, import_react42.useState)("#ef4444");
5120
- const [strokeWidth, setStrokeWidth] = (0, import_react42.useState)(3);
5121
- const [fontSize, setFontSize] = (0, import_react42.useState)(24);
5122
- const [textInput, setTextInput] = (0, import_react42.useState)("");
5123
- const draftAnnotationRef = (0, import_react42.useRef)(null);
5124
- const draftCropRef = (0, import_react42.useRef)(null);
5125
- const cropDragInfoRef = (0, import_react42.useRef)(null);
5126
- const annotationDragInfoRef = (0, import_react42.useRef)(null);
5127
- const isDrawingRef = (0, import_react42.useRef)(false);
5128
- const currentPathRef = (0, import_react42.useRef)([]);
5129
- const dragStartPointRef = (0, import_react42.useRef)(null);
5130
- const renderCanvas = (0, import_react42.useCallback)(
5325
+ const [activeColor, setActiveColor] = (0, import_react43.useState)("#ef4444");
5326
+ const [strokeWidth, setStrokeWidth] = (0, import_react43.useState)(3);
5327
+ const [fontSize, setFontSize] = (0, import_react43.useState)(24);
5328
+ const [textInput, setTextInput] = (0, import_react43.useState)("");
5329
+ const draftAnnotationRef = (0, import_react43.useRef)(null);
5330
+ const draftCropRef = (0, import_react43.useRef)(null);
5331
+ const cropDragInfoRef = (0, import_react43.useRef)(null);
5332
+ const annotationDragInfoRef = (0, import_react43.useRef)(null);
5333
+ const isDrawingRef = (0, import_react43.useRef)(false);
5334
+ const currentPathRef = (0, import_react43.useRef)([]);
5335
+ const dragStartPointRef = (0, import_react43.useRef)(null);
5336
+ const renderCanvas = (0, import_react43.useCallback)(
5131
5337
  async (draftAnnotation, draftCrop) => {
5132
5338
  const canvas = canvasRef.current;
5133
5339
  const container = containerRef.current;
@@ -5148,7 +5354,7 @@ var ImageEditor = ({
5148
5354
  },
5149
5355
  [controller, activeTab]
5150
5356
  );
5151
- (0, import_react42.useEffect)(() => {
5357
+ (0, import_react43.useEffect)(() => {
5152
5358
  const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
5153
5359
  const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
5154
5360
  const animId = raf(() => {
@@ -5156,12 +5362,12 @@ var ImageEditor = ({
5156
5362
  });
5157
5363
  return () => caf(animId);
5158
5364
  }, [renderCanvas, state]);
5159
- (0, import_react42.useEffect)(() => {
5365
+ (0, import_react43.useEffect)(() => {
5160
5366
  if (activeTab === "crop" && editor.state.activeTool !== "crop") {
5161
5367
  editor.setTool("crop");
5162
5368
  }
5163
5369
  }, [activeTab, editor]);
5164
- (0, import_react42.useEffect)(() => {
5370
+ (0, import_react43.useEffect)(() => {
5165
5371
  const container = containerRef.current;
5166
5372
  if (!container) return;
5167
5373
  if (typeof ResizeObserver !== "undefined") {
@@ -5197,8 +5403,8 @@ var ImageEditor = ({
5197
5403
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
5198
5404
  const s = controller.getState();
5199
5405
  return list.map((ev) => ({
5200
- ...(0, import_image_editor10.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
5201
- pressure: (0, import_image_editor10.pointerPressure)(ev)
5406
+ ...(0, import_image_editor11.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
5407
+ pressure: (0, import_image_editor11.pointerPressure)(ev)
5202
5408
  }));
5203
5409
  };
5204
5410
  const handlePaintPointerDown = (e) => {
@@ -5226,10 +5432,10 @@ var ImageEditor = ({
5226
5432
  if (g.error) setPaintError(g.error);
5227
5433
  }
5228
5434
  };
5229
- (0, import_react42.useEffect)(() => {
5435
+ (0, import_react43.useEffect)(() => {
5230
5436
  if (activeTab !== "paint" || typeof window === "undefined") return;
5231
5437
  const onKey = (e) => {
5232
- if ((0, import_image_editor10.handlePaintShortcut)(controller, e)) e.preventDefault();
5438
+ if ((0, import_image_editor11.handlePaintShortcut)(controller, e)) e.preventDefault();
5233
5439
  };
5234
5440
  window.addEventListener("keydown", onKey);
5235
5441
  return () => window.removeEventListener("keydown", onKey);
@@ -5240,7 +5446,7 @@ var ImageEditor = ({
5240
5446
  const canvasPt = getCanvasEventPoint(e);
5241
5447
  if (activeTab === "select") {
5242
5448
  const gesture = selectionGestureRef.current;
5243
- const imgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5449
+ const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5244
5450
  void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
5245
5451
  return;
5246
5452
  }
@@ -5251,8 +5457,8 @@ var ImageEditor = ({
5251
5457
  width: state.imageDimensions.width,
5252
5458
  height: state.imageDimensions.height
5253
5459
  };
5254
- const handle = (0, import_image_editor10.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
5255
- const startImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
5460
+ const handle = (0, import_image_editor11.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
5461
+ const startImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
5256
5462
  if (handle) {
5257
5463
  cropDragInfoRef.current = {
5258
5464
  handle,
@@ -5271,12 +5477,12 @@ var ImageEditor = ({
5271
5477
  return;
5272
5478
  }
5273
5479
  if (activeTab === "annotate") {
5274
- const imgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5480
+ const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5275
5481
  dragStartPointRef.current = imgPt;
5276
5482
  if (state.activeTool === "select") {
5277
5483
  for (let i = state.annotations.length - 1; i >= 0; i--) {
5278
5484
  const ann = state.annotations[i];
5279
- if ((0, import_image_editor10.hitTestAnnotation)(imgPt, ann)) {
5485
+ if ((0, import_image_editor11.hitTestAnnotation)(imgPt, ann)) {
5280
5486
  editor.selectAnnotation(ann.id);
5281
5487
  annotationDragInfoRef.current = {
5282
5488
  annId: ann.id,
@@ -5312,7 +5518,7 @@ var ImageEditor = ({
5312
5518
  const canvasPt = getCanvasEventPoint(e);
5313
5519
  if (activeTab === "select") {
5314
5520
  const gesture = selectionGestureRef.current;
5315
- if (gesture.active && gesture.move((0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
5521
+ if (gesture.active && gesture.move((0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
5316
5522
  selectionDraftRef.current = gesture.draftPath;
5317
5523
  renderCanvas();
5318
5524
  }
@@ -5321,7 +5527,7 @@ var ImageEditor = ({
5321
5527
  if (activeTab === "crop") {
5322
5528
  const drag = cropDragInfoRef.current;
5323
5529
  if (drag) {
5324
- const currentImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
5530
+ const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
5325
5531
  let newCrop;
5326
5532
  if (drag.handle === "new") {
5327
5533
  const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
@@ -5335,7 +5541,7 @@ var ImageEditor = ({
5335
5541
  height: Math.round(Math.max(20, maxY - minY))
5336
5542
  };
5337
5543
  } else {
5338
- newCrop = (0, import_image_editor10.calculateCropDrag)(
5544
+ newCrop = (0, import_image_editor11.calculateCropDrag)(
5339
5545
  drag.startCrop,
5340
5546
  drag.handle,
5341
5547
  drag.startImgPt,
@@ -5355,15 +5561,15 @@ var ImageEditor = ({
5355
5561
  width: state.imageDimensions.width,
5356
5562
  height: state.imageDimensions.height
5357
5563
  };
5358
- const handle = (0, import_image_editor10.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
5359
- canvas.style.cursor = (0, import_image_editor10.getCropCursor)(handle, state.transform);
5564
+ const handle = (0, import_image_editor11.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
5565
+ canvas.style.cursor = (0, import_image_editor11.getCropCursor)(handle, state.transform);
5360
5566
  }
5361
5567
  return;
5362
5568
  }
5363
5569
  if (activeTab === "annotate") {
5364
5570
  if (annotationDragInfoRef.current) {
5365
5571
  const drag = annotationDragInfoRef.current;
5366
- const currentImgPt2 = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5572
+ const currentImgPt2 = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5367
5573
  const dx = currentImgPt2.x - drag.startImgPt.x;
5368
5574
  const dy = currentImgPt2.y - drag.startImgPt.y;
5369
5575
  editor.updateAnnotation(drag.annId, {
@@ -5375,10 +5581,10 @@ var ImageEditor = ({
5375
5581
  const startPt = dragStartPointRef.current;
5376
5582
  if (!startPt) {
5377
5583
  if (state.activeTool === "select") {
5378
- const imgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5584
+ const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5379
5585
  let hovered = false;
5380
5586
  for (let i = state.annotations.length - 1; i >= 0; i--) {
5381
- if ((0, import_image_editor10.hitTestAnnotation)(imgPt, state.annotations[i])) {
5587
+ if ((0, import_image_editor11.hitTestAnnotation)(imgPt, state.annotations[i])) {
5382
5588
  hovered = true;
5383
5589
  break;
5384
5590
  }
@@ -5389,7 +5595,7 @@ var ImageEditor = ({
5389
5595
  }
5390
5596
  return;
5391
5597
  }
5392
- const currentImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5598
+ const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5393
5599
  if (state.activeTool === "pen" && isDrawingRef.current) {
5394
5600
  currentPathRef.current.push(currentImgPt);
5395
5601
  const draft = {
@@ -5469,7 +5675,7 @@ var ImageEditor = ({
5469
5675
  if (activeTab === "select") {
5470
5676
  const gesture = selectionGestureRef.current;
5471
5677
  if (gesture.active) {
5472
- gesture.end((0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
5678
+ gesture.end((0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
5473
5679
  selectionDraftRef.current = null;
5474
5680
  renderCanvas();
5475
5681
  }
@@ -5493,7 +5699,7 @@ var ImageEditor = ({
5493
5699
  }
5494
5700
  const startPt = dragStartPointRef.current;
5495
5701
  if (startPt) {
5496
- const currentImgPt = (0, import_image_editor10.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5702
+ const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5497
5703
  if (state.activeTool === "pen" && isDrawingRef.current) {
5498
5704
  if (currentPathRef.current.length > 1) {
5499
5705
  editor.addAnnotation({
@@ -5589,15 +5795,15 @@ var ImageEditor = ({
5589
5795
  link.click();
5590
5796
  }
5591
5797
  };
5592
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5798
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5593
5799
  "div",
5594
5800
  {
5595
5801
  className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
5596
5802
  style,
5597
5803
  children: [
5598
- /* @__PURE__ */ (0, import_jsx_runtime25.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: [
5599
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
5600
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5804
+ /* @__PURE__ */ (0, import_jsx_runtime26.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: [
5805
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
5806
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5601
5807
  "button",
5602
5808
  {
5603
5809
  type: "button",
@@ -5609,7 +5815,7 @@ var ImageEditor = ({
5609
5815
  children: "Transform & Crop"
5610
5816
  }
5611
5817
  ),
5612
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5818
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5613
5819
  "button",
5614
5820
  {
5615
5821
  type: "button",
@@ -5621,7 +5827,7 @@ var ImageEditor = ({
5621
5827
  children: "Adjustments"
5622
5828
  }
5623
5829
  ),
5624
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5830
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5625
5831
  "button",
5626
5832
  {
5627
5833
  type: "button",
@@ -5633,7 +5839,7 @@ var ImageEditor = ({
5633
5839
  children: "Layers"
5634
5840
  }
5635
5841
  ),
5636
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5842
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5637
5843
  "button",
5638
5844
  {
5639
5845
  type: "button",
@@ -5645,7 +5851,7 @@ var ImageEditor = ({
5645
5851
  children: "Paint"
5646
5852
  }
5647
5853
  ),
5648
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5854
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5649
5855
  "button",
5650
5856
  {
5651
5857
  type: "button",
@@ -5657,7 +5863,7 @@ var ImageEditor = ({
5657
5863
  children: "Select & Mask"
5658
5864
  }
5659
5865
  ),
5660
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5866
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5661
5867
  "button",
5662
5868
  {
5663
5869
  type: "button",
@@ -5669,7 +5875,7 @@ var ImageEditor = ({
5669
5875
  children: "Annotations"
5670
5876
  }
5671
5877
  ),
5672
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5878
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5673
5879
  "button",
5674
5880
  {
5675
5881
  type: "button",
@@ -5681,7 +5887,7 @@ var ImageEditor = ({
5681
5887
  children: "Depth Mask"
5682
5888
  }
5683
5889
  ),
5684
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5890
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5685
5891
  "button",
5686
5892
  {
5687
5893
  type: "button",
@@ -5691,14 +5897,14 @@ var ImageEditor = ({
5691
5897
  },
5692
5898
  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"}`,
5693
5899
  children: [
5694
- /* @__PURE__ */ (0, import_jsx_runtime25.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_runtime25.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" }) }),
5900
+ /* @__PURE__ */ (0, import_jsx_runtime26.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_runtime26.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" }) }),
5695
5901
  "AI Tools"
5696
5902
  ]
5697
5903
  }
5698
5904
  )
5699
5905
  ] }),
5700
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
5701
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5906
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
5907
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5702
5908
  "button",
5703
5909
  {
5704
5910
  type: "button",
@@ -5709,7 +5915,7 @@ var ImageEditor = ({
5709
5915
  children: "\u21A9"
5710
5916
  }
5711
5917
  ),
5712
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5918
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5713
5919
  "button",
5714
5920
  {
5715
5921
  type: "button",
@@ -5720,7 +5926,7 @@ var ImageEditor = ({
5720
5926
  children: "\u21AA"
5721
5927
  }
5722
5928
  ),
5723
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5929
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5724
5930
  "button",
5725
5931
  {
5726
5932
  type: "button",
@@ -5729,8 +5935,8 @@ var ImageEditor = ({
5729
5935
  children: "Reset"
5730
5936
  }
5731
5937
  ),
5732
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
5733
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5938
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
5939
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5734
5940
  "button",
5735
5941
  {
5736
5942
  type: "button",
@@ -5740,11 +5946,11 @@ var ImageEditor = ({
5740
5946
  children: "-"
5741
5947
  }
5742
5948
  ),
5743
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
5949
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
5744
5950
  Math.round(state.zoom * 100),
5745
5951
  "%"
5746
5952
  ] }),
5747
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5953
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5748
5954
  "button",
5749
5955
  {
5750
5956
  type: "button",
@@ -5754,8 +5960,8 @@ var ImageEditor = ({
5754
5960
  children: "+"
5755
5961
  }
5756
5962
  ),
5757
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
5758
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5963
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
5964
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5759
5965
  "button",
5760
5966
  {
5761
5967
  type: "button",
@@ -5766,7 +5972,7 @@ var ImageEditor = ({
5766
5972
  children: "Hold Compare"
5767
5973
  }
5768
5974
  ),
5769
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5975
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5770
5976
  "button",
5771
5977
  {
5772
5978
  type: "button",
@@ -5777,13 +5983,13 @@ var ImageEditor = ({
5777
5983
  )
5778
5984
  ] })
5779
5985
  ] }),
5780
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
5781
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5986
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
5987
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5782
5988
  "div",
5783
5989
  {
5784
5990
  ref: containerRef,
5785
5991
  className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
5786
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5992
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5787
5993
  "canvas",
5788
5994
  {
5789
5995
  ref: canvasRef,
@@ -5801,11 +6007,11 @@ var ImageEditor = ({
5801
6007
  )
5802
6008
  }
5803
6009
  ),
5804
- /* @__PURE__ */ (0, import_jsx_runtime25.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: [
5805
- activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
5806
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
5807
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
5808
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6010
+ /* @__PURE__ */ (0, import_jsx_runtime26.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: [
6011
+ activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6012
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
6013
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
6014
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5809
6015
  "button",
5810
6016
  {
5811
6017
  type: "button",
@@ -5817,7 +6023,7 @@ var ImageEditor = ({
5817
6023
  children: "Freeform"
5818
6024
  }
5819
6025
  ),
5820
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6026
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5821
6027
  "button",
5822
6028
  {
5823
6029
  type: "button",
@@ -5829,7 +6035,7 @@ var ImageEditor = ({
5829
6035
  children: "1:1 Square"
5830
6036
  }
5831
6037
  ),
5832
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6038
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5833
6039
  "button",
5834
6040
  {
5835
6041
  type: "button",
@@ -5841,7 +6047,7 @@ var ImageEditor = ({
5841
6047
  children: "4:3 Standard"
5842
6048
  }
5843
6049
  ),
5844
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6050
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5845
6051
  "button",
5846
6052
  {
5847
6053
  type: "button",
@@ -5853,7 +6059,7 @@ var ImageEditor = ({
5853
6059
  children: "16:9 Wide"
5854
6060
  }
5855
6061
  ),
5856
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6062
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5857
6063
  "button",
5858
6064
  {
5859
6065
  type: "button",
@@ -5865,7 +6071,7 @@ var ImageEditor = ({
5865
6071
  children: "3:2 Photo"
5866
6072
  }
5867
6073
  ),
5868
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6074
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5869
6075
  "button",
5870
6076
  {
5871
6077
  type: "button",
@@ -5878,10 +6084,10 @@ var ImageEditor = ({
5878
6084
  }
5879
6085
  )
5880
6086
  ] }),
5881
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
5882
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
5883
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
5884
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6087
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6088
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
6089
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
6090
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5885
6091
  "button",
5886
6092
  {
5887
6093
  type: "button",
@@ -5890,7 +6096,7 @@ var ImageEditor = ({
5890
6096
  children: "Rotate -90\xB0"
5891
6097
  }
5892
6098
  ),
5893
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6099
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5894
6100
  "button",
5895
6101
  {
5896
6102
  type: "button",
@@ -5899,7 +6105,7 @@ var ImageEditor = ({
5899
6105
  children: "Rotate +90\xB0"
5900
6106
  }
5901
6107
  ),
5902
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6108
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5903
6109
  "button",
5904
6110
  {
5905
6111
  type: "button",
@@ -5908,7 +6114,7 @@ var ImageEditor = ({
5908
6114
  children: "Flip Horizontal"
5909
6115
  }
5910
6116
  ),
5911
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6117
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5912
6118
  "button",
5913
6119
  {
5914
6120
  type: "button",
@@ -5919,10 +6125,10 @@ var ImageEditor = ({
5919
6125
  )
5920
6126
  ] })
5921
6127
  ] }),
5922
- activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
5923
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
5924
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
5925
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6128
+ activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6129
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between", children: [
6130
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
6131
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5926
6132
  "button",
5927
6133
  {
5928
6134
  type: "button",
@@ -5932,25 +6138,25 @@ var ImageEditor = ({
5932
6138
  }
5933
6139
  )
5934
6140
  ] }),
5935
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Histogram, { histogram: editor.histogram }),
5936
- import_image_editor10.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_react42.default.Fragment, { children: [
5937
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6141
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Histogram, { histogram: editor.histogram }),
6142
+ import_image_editor11.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_react43.default.Fragment, { children: [
6143
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5938
6144
  ControlSlider,
5939
6145
  {
5940
6146
  spec,
5941
- value: (0, import_image_editor10.readAdjustmentControls)(state.adjustments)[spec.id],
6147
+ value: (0, import_image_editor11.readAdjustmentControls)(state.adjustments)[spec.id],
5942
6148
  disabled: spec.requiresProcess !== void 0 && legacyProcess,
5943
6149
  onChange: (v) => editor.setAdjustments({ [spec.id]: v })
5944
6150
  }
5945
6151
  ),
5946
- spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6152
+ spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5947
6153
  "div",
5948
6154
  {
5949
6155
  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",
5950
6156
  "data-testid": "image-editor-process-notice",
5951
6157
  children: [
5952
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
5953
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6158
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
6159
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5954
6160
  "button",
5955
6161
  {
5956
6162
  type: "button",
@@ -5963,7 +6169,7 @@ var ImageEditor = ({
5963
6169
  }
5964
6170
  )
5965
6171
  ] }, spec.id)),
5966
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6172
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5967
6173
  AdjustmentLayersPanel,
5968
6174
  {
5969
6175
  controller,
@@ -5972,19 +6178,19 @@ var ImageEditor = ({
5972
6178
  }
5973
6179
  ) })
5974
6180
  ] }),
5975
- activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
5976
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
5977
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LayersPanel, { controller })
6181
+ activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6182
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
6183
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(LayersPanel, { controller })
5978
6184
  ] }),
5979
- activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
5980
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
5981
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(BrushOptionsBar, { controller }),
5982
- paintError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
5983
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LayersPanel, { controller }) })
6185
+ activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6186
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
6187
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(BrushOptionsBar, { controller }),
6188
+ paintError && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
6189
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(LayersPanel, { controller }) })
5984
6190
  ] }),
5985
- activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
5986
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
5987
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6191
+ activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6192
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
6193
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5988
6194
  "button",
5989
6195
  {
5990
6196
  type: "button",
@@ -5994,9 +6200,9 @@ var ImageEditor = ({
5994
6200
  },
5995
6201
  t
5996
6202
  )) }),
5997
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
5998
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { className: "text-slate-400", children: "Color:" }),
5999
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6203
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
6204
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("label", { className: "text-slate-400", children: "Color:" }),
6205
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6000
6206
  "input",
6001
6207
  {
6002
6208
  type: "color",
@@ -6005,15 +6211,15 @@ var ImageEditor = ({
6005
6211
  className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
6006
6212
  }
6007
6213
  ),
6008
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex-1 ml-2", children: [
6009
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
6010
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Width:" }),
6011
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
6214
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex-1 ml-2", children: [
6215
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
6216
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Width:" }),
6217
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono", children: [
6012
6218
  strokeWidth,
6013
6219
  "px"
6014
6220
  ] })
6015
6221
  ] }),
6016
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6222
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6017
6223
  "input",
6018
6224
  {
6019
6225
  type: "range",
@@ -6026,10 +6232,10 @@ var ImageEditor = ({
6026
6232
  )
6027
6233
  ] })
6028
6234
  ] }),
6029
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6030
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
6031
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-2", children: [
6032
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6235
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6236
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
6237
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex gap-2", children: [
6238
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6033
6239
  "input",
6034
6240
  {
6035
6241
  type: "text",
@@ -6040,7 +6246,7 @@ var ImageEditor = ({
6040
6246
  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"
6041
6247
  }
6042
6248
  ),
6043
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6249
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6044
6250
  "button",
6045
6251
  {
6046
6252
  type: "button",
@@ -6050,14 +6256,14 @@ var ImageEditor = ({
6050
6256
  }
6051
6257
  )
6052
6258
  ] }),
6053
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
6054
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Font Size:" }),
6055
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-mono", children: [
6259
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
6260
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Font Size:" }),
6261
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono", children: [
6056
6262
  fontSize,
6057
6263
  "px"
6058
6264
  ] })
6059
6265
  ] }),
6060
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6266
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6061
6267
  "input",
6062
6268
  {
6063
6269
  type: "range",
@@ -6068,14 +6274,14 @@ var ImageEditor = ({
6068
6274
  className: "w-full accent-indigo-500"
6069
6275
  }
6070
6276
  ),
6071
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6072
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
6073
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "text-slate-400", children: [
6277
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6278
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between", children: [
6279
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "text-slate-400", children: [
6074
6280
  "Layers (",
6075
6281
  state.annotations.length,
6076
6282
  ")"
6077
6283
  ] }),
6078
- state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6284
+ state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6079
6285
  "button",
6080
6286
  {
6081
6287
  type: "button",
@@ -6084,7 +6290,7 @@ var ImageEditor = ({
6084
6290
  children: "Delete Selected"
6085
6291
  }
6086
6292
  ),
6087
- state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6293
+ state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6088
6294
  "button",
6089
6295
  {
6090
6296
  type: "button",
@@ -6095,10 +6301,10 @@ var ImageEditor = ({
6095
6301
  )
6096
6302
  ] })
6097
6303
  ] }),
6098
- activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6099
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
6100
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
6101
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6304
+ activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6305
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between", children: [
6306
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
6307
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6102
6308
  "button",
6103
6309
  {
6104
6310
  type: "button",
@@ -6108,8 +6314,8 @@ var ImageEditor = ({
6108
6314
  }
6109
6315
  )
6110
6316
  ] }),
6111
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
6112
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6317
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
6318
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6113
6319
  "input",
6114
6320
  {
6115
6321
  type: "checkbox",
@@ -6118,12 +6324,12 @@ var ImageEditor = ({
6118
6324
  className: "rounded accent-indigo-500"
6119
6325
  }
6120
6326
  ),
6121
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Enable Depth / Alpha Mask" })
6327
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Enable Depth / Alpha Mask" })
6122
6328
  ] }),
6123
- state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
6124
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
6125
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
6126
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6329
+ state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
6330
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
6331
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
6332
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6127
6333
  "input",
6128
6334
  {
6129
6335
  type: "text",
@@ -6134,8 +6340,8 @@ var ImageEditor = ({
6134
6340
  }
6135
6341
  )
6136
6342
  ] }),
6137
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex gap-2", children: [
6138
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6343
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex gap-2", children: [
6344
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6139
6345
  "button",
6140
6346
  {
6141
6347
  type: "button",
@@ -6144,7 +6350,7 @@ var ImageEditor = ({
6144
6350
  children: "Threshold Mode"
6145
6351
  }
6146
6352
  ),
6147
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6353
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6148
6354
  "button",
6149
6355
  {
6150
6356
  type: "button",
@@ -6154,12 +6360,12 @@ var ImageEditor = ({
6154
6360
  }
6155
6361
  )
6156
6362
  ] }),
6157
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
6158
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6159
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Depth Start (Lower):" }),
6160
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
6363
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
6364
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6365
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Depth Start (Lower):" }),
6366
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
6161
6367
  ] }),
6162
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6368
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6163
6369
  "input",
6164
6370
  {
6165
6371
  type: "range",
@@ -6173,12 +6379,12 @@ var ImageEditor = ({
6173
6379
  }
6174
6380
  )
6175
6381
  ] }),
6176
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
6177
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6178
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Depth Stop (Upper):" }),
6179
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
6382
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
6383
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6384
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Depth Stop (Upper):" }),
6385
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
6180
6386
  ] }),
6181
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6387
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6182
6388
  "input",
6183
6389
  {
6184
6390
  type: "range",
@@ -6192,12 +6398,12 @@ var ImageEditor = ({
6192
6398
  }
6193
6399
  )
6194
6400
  ] }),
6195
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
6196
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6197
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Softness:" }),
6198
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
6401
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
6402
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6403
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Softness:" }),
6404
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
6199
6405
  ] }),
6200
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6406
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6201
6407
  "input",
6202
6408
  {
6203
6409
  type: "range",
@@ -6209,8 +6415,8 @@ var ImageEditor = ({
6209
6415
  }
6210
6416
  )
6211
6417
  ] }),
6212
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
6213
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6418
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
6419
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6214
6420
  "input",
6215
6421
  {
6216
6422
  type: "checkbox",
@@ -6219,12 +6425,12 @@ var ImageEditor = ({
6219
6425
  className: "rounded accent-indigo-500"
6220
6426
  }
6221
6427
  ),
6222
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Invert Mask" })
6428
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Invert Mask" })
6223
6429
  ] })
6224
6430
  ] })
6225
6431
  ] }),
6226
- activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6227
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6432
+ activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6433
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6228
6434
  SelectionOptionsBar,
6229
6435
  {
6230
6436
  controller,
@@ -6234,13 +6440,13 @@ var ImageEditor = ({
6234
6440
  quickMask: Boolean(state.quickMask)
6235
6441
  }
6236
6442
  ),
6237
- selectionError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
6238
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
6443
+ selectionError && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
6444
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
6239
6445
  ] }),
6240
- activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6241
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
6242
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Results go to" }),
6243
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6446
+ activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6447
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
6448
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Results go to" }),
6449
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6244
6450
  "select",
6245
6451
  {
6246
6452
  "aria-label": "AI result target",
@@ -6248,54 +6454,54 @@ var ImageEditor = ({
6248
6454
  onChange: (e) => setAiTarget(e.target.value),
6249
6455
  className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
6250
6456
  children: [
6251
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
6252
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
6253
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: "replace", children: "Replace image" })
6457
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
6458
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
6459
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: "replace", children: "Replace image" })
6254
6460
  ]
6255
6461
  }
6256
6462
  )
6257
6463
  ] }),
6258
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
6259
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
6260
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
6261
- /* @__PURE__ */ (0, import_jsx_runtime25.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_runtime25.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" }) }),
6464
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
6465
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between", children: [
6466
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
6467
+ /* @__PURE__ */ (0, import_jsx_runtime26.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_runtime26.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" }) }),
6262
6468
  "Background Removal"
6263
6469
  ] }),
6264
- isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime25.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..." })
6470
+ isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime26.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..." })
6265
6471
  ] }),
6266
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
6267
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6472
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
6473
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6268
6474
  "button",
6269
6475
  {
6270
6476
  type: "button",
6271
6477
  onClick: handleRemoveBackground,
6272
6478
  disabled: isRemovingBg || isInpainting,
6273
6479
  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",
6274
- children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
6275
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
6480
+ children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
6481
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
6276
6482
  "Removing Background..."
6277
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
6278
- /* @__PURE__ */ (0, import_jsx_runtime25.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_runtime25.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" }) }),
6483
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
6484
+ /* @__PURE__ */ (0, import_jsx_runtime26.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_runtime26.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" }) }),
6279
6485
  "Remove Background"
6280
6486
  ] })
6281
6487
  }
6282
6488
  )
6283
6489
  ] }),
6284
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
6285
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between", children: [
6286
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
6287
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
6288
- /* @__PURE__ */ (0, import_jsx_runtime25.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" }),
6289
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "m14 7 3 3" })
6490
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
6491
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between", children: [
6492
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
6493
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
6494
+ /* @__PURE__ */ (0, import_jsx_runtime26.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" }),
6495
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("path", { d: "m14 7 3 3" })
6290
6496
  ] }),
6291
6497
  "Generative Inpainting"
6292
6498
  ] }),
6293
- isInpainting && /* @__PURE__ */ (0, import_jsx_runtime25.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..." })
6499
+ isInpainting && /* @__PURE__ */ (0, import_jsx_runtime26.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..." })
6294
6500
  ] }),
6295
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
6296
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-1", children: [
6297
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
6298
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6501
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
6502
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-1", children: [
6503
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
6504
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6299
6505
  "textarea",
6300
6506
  {
6301
6507
  id: "ai-inpaint-prompt-react",
@@ -6307,10 +6513,10 @@ var ImageEditor = ({
6307
6513
  }
6308
6514
  )
6309
6515
  ] }),
6310
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-1", children: [
6311
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
6312
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
6313
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6516
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-1", children: [
6517
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
6518
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
6519
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6314
6520
  "button",
6315
6521
  {
6316
6522
  type: "button",
@@ -6323,7 +6529,7 @@ var ImageEditor = ({
6323
6529
  ]
6324
6530
  }
6325
6531
  ),
6326
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
6532
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6327
6533
  "button",
6328
6534
  {
6329
6535
  type: "button",
@@ -6338,25 +6544,25 @@ var ImageEditor = ({
6338
6544
  )
6339
6545
  ] })
6340
6546
  ] }),
6341
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
6547
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6342
6548
  "button",
6343
6549
  {
6344
6550
  type: "button",
6345
6551
  onClick: handleInpaint,
6346
6552
  disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
6347
6553
  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",
6348
- children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
6349
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
6554
+ children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
6555
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
6350
6556
  "Generating Inpaint..."
6351
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
6352
- /* @__PURE__ */ (0, import_jsx_runtime25.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_runtime25.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" }) }),
6557
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
6558
+ /* @__PURE__ */ (0, import_jsx_runtime26.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_runtime26.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" }) }),
6353
6559
  "Apply Inpainting"
6354
6560
  ] })
6355
6561
  }
6356
6562
  )
6357
6563
  ] }),
6358
- aiError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
6359
- aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
6564
+ aiError && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
6565
+ aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
6360
6566
  ] })
6361
6567
  ] })
6362
6568
  ] })
@@ -6366,7 +6572,7 @@ var ImageEditor = ({
6366
6572
  };
6367
6573
 
6368
6574
  // src/review/useReview.ts
6369
- var import_react43 = require("react");
6575
+ var import_react44 = require("react");
6370
6576
  var import_editor12 = require("@pixerate/editor");
6371
6577
  var EMPTY_COMMENTS = Object.freeze({
6372
6578
  threads: [],
@@ -6385,23 +6591,23 @@ function isCommentStore(value) {
6385
6591
  }
6386
6592
  function useComments(source) {
6387
6593
  const store = isCommentStore(source) ? source : (0, import_editor12.getCommentStore)(source);
6388
- const subscribe = (0, import_react43.useCallback)(
6594
+ const subscribe = (0, import_react44.useCallback)(
6389
6595
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
6390
6596
  [store]
6391
6597
  );
6392
6598
  const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;
6393
- const snapshot = (0, import_react43.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
6394
- return (0, import_react43.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
6599
+ const snapshot = (0, import_react44.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
6600
+ return (0, import_react44.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
6395
6601
  }
6396
6602
  function useTrackChanges(editor) {
6397
6603
  const store = (0, import_editor12.getTrackChangesStore)(editor ?? null);
6398
- const subscribe = (0, import_react43.useCallback)(
6604
+ const subscribe = (0, import_react44.useCallback)(
6399
6605
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
6400
6606
  [store]
6401
6607
  );
6402
6608
  const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;
6403
- const snapshot = (0, import_react43.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
6404
- return (0, import_react43.useMemo)(() => {
6609
+ const snapshot = (0, import_react44.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
6610
+ return (0, import_react44.useMemo)(() => {
6405
6611
  const run = (fn) => () => {
6406
6612
  if (editor && !editor.isDestroyed) fn(editor);
6407
6613
  };
@@ -6424,9 +6630,9 @@ function useTrackChanges(editor) {
6424
6630
  }
6425
6631
 
6426
6632
  // src/review/CommentsPanel.tsx
6427
- var import_react44 = require("react");
6633
+ var import_react45 = require("react");
6428
6634
  var import_editor13 = require("@pixerate/editor");
6429
- var import_jsx_runtime26 = require("react/jsx-runtime");
6635
+ var import_jsx_runtime27 = require("react/jsx-runtime");
6430
6636
  var buttonClass2 = "rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50";
6431
6637
  var primaryButtonClass = "rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50";
6432
6638
  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";
@@ -6440,18 +6646,18 @@ var CommentsPanel = ({
6440
6646
  emptyMessage = "No comments yet. Select text and add a comment."
6441
6647
  }) => {
6442
6648
  const { threads, activeThreadId, store } = useComments(storeProp ?? editor);
6443
- const [showResolved, setShowResolved] = (0, import_react44.useState)(showResolvedInitial);
6649
+ const [showResolved, setShowResolved] = (0, import_react45.useState)(showResolvedInitial);
6444
6650
  const author = authorProp ?? (0, import_editor13.getCommentAuthor)(editor) ?? { id: "anonymous", name: "Anonymous" };
6445
6651
  const visible = threads.filter((t) => showResolved || !t.resolved);
6446
6652
  const resolvedCount = threads.filter((t) => t.resolved).length;
6447
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("aside", { className, "aria-label": "Comments", children: [
6448
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
6449
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
6653
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("aside", { className, "aria-label": "Comments", children: [
6654
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
6655
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
6450
6656
  threads.length - resolvedCount,
6451
6657
  " open",
6452
6658
  resolvedCount > 0 ? ` \xB7 ${resolvedCount} resolved` : ""
6453
6659
  ] }),
6454
- resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6660
+ resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6455
6661
  "button",
6456
6662
  {
6457
6663
  type: "button",
@@ -6462,7 +6668,7 @@ var CommentsPanel = ({
6462
6668
  }
6463
6669
  )
6464
6670
  ] }),
6465
- visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("ul", { className: "flex flex-col gap-2", role: "list", children: visible.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6671
+ visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("ul", { className: "flex flex-col gap-2", role: "list", children: visible.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6466
6672
  CommentThreadCard,
6467
6673
  {
6468
6674
  thread,
@@ -6484,7 +6690,7 @@ var CommentThreadCard = ({
6484
6690
  author,
6485
6691
  formatTime
6486
6692
  }) => {
6487
- const [draft, setDraft] = (0, import_react44.useState)("");
6693
+ const [draft, setDraft] = (0, import_react45.useState)("");
6488
6694
  const isDraft = thread.body === "";
6489
6695
  const quote = thread.anchor?.quote ?? thread.lastQuote ?? "";
6490
6696
  const live = editor && !editor.isDestroyed ? editor : null;
@@ -6510,7 +6716,7 @@ var CommentThreadCard = ({
6510
6716
  setDraft("");
6511
6717
  };
6512
6718
  const stop = (e) => e.stopPropagation();
6513
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6719
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6514
6720
  "li",
6515
6721
  {
6516
6722
  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" : ""}`,
@@ -6526,24 +6732,24 @@ var CommentThreadCard = ({
6526
6732
  }
6527
6733
  },
6528
6734
  children: [
6529
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
6530
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-medium", children: thread.author.name }),
6531
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
6735
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
6736
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-medium", children: thread.author.name }),
6737
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
6532
6738
  ] }),
6533
- quote && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("blockquote", { className: "border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2", children: quote }),
6534
- thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
6535
- thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
6536
- !isDraft && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
6537
- thread.replies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.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_runtime26.jsxs)("li", { className: "flex flex-col gap-0.5", "data-reply-id": reply.id, children: [
6538
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "text-xs", children: [
6539
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "font-medium", children: reply.author.name }),
6739
+ quote && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("blockquote", { className: "border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2", children: quote }),
6740
+ thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
6741
+ thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
6742
+ !isDraft && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
6743
+ thread.replies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.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_runtime27.jsxs)("li", { className: "flex flex-col gap-0.5", "data-reply-id": reply.id, children: [
6744
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "text-xs", children: [
6745
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-medium", children: reply.author.name }),
6540
6746
  " ",
6541
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
6747
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
6542
6748
  ] }),
6543
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
6749
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
6544
6750
  ] }, reply.id)) }),
6545
- (active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
6546
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6751
+ (active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
6752
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6547
6753
  "textarea",
6548
6754
  {
6549
6755
  className: textareaClass,
@@ -6561,9 +6767,9 @@ var CommentThreadCard = ({
6561
6767
  }
6562
6768
  }
6563
6769
  ),
6564
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex justify-end gap-1", children: [
6565
- isDraft && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
6566
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6770
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex justify-end gap-1", children: [
6771
+ isDraft && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
6772
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6567
6773
  "button",
6568
6774
  {
6569
6775
  type: "button",
@@ -6575,9 +6781,9 @@ var CommentThreadCard = ({
6575
6781
  )
6576
6782
  ] })
6577
6783
  ] }),
6578
- !isDraft && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
6579
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
6580
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6784
+ !isDraft && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
6785
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
6786
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6581
6787
  "button",
6582
6788
  {
6583
6789
  type: "button",
@@ -6593,7 +6799,7 @@ var CommentThreadCard = ({
6593
6799
  };
6594
6800
 
6595
6801
  // src/review/ReviewToolbar.tsx
6596
- var import_jsx_runtime27 = require("react/jsx-runtime");
6802
+ var import_jsx_runtime28 = require("react/jsx-runtime");
6597
6803
  var defaultDescriptionClass = "max-w-[16rem] truncate px-1 text-xs text-muted-foreground";
6598
6804
  var buttonClass3 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
6599
6805
  var ReviewToolbar = ({
@@ -6606,8 +6812,8 @@ var ReviewToolbar = ({
6606
6812
  const count = review.changes.length;
6607
6813
  const current = review.currentChange;
6608
6814
  const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;
6609
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
6610
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6815
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
6816
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6611
6817
  "button",
6612
6818
  {
6613
6819
  type: "button",
@@ -6618,8 +6824,8 @@ var ReviewToolbar = ({
6618
6824
  children: review.enabled ? "Tracking on" : "Track changes"
6619
6825
  }
6620
6826
  ),
6621
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
6622
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6827
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
6828
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6623
6829
  "button",
6624
6830
  {
6625
6831
  type: "button",
@@ -6630,8 +6836,8 @@ var ReviewToolbar = ({
6630
6836
  children: "\u2039"
6631
6837
  }
6632
6838
  ),
6633
- /* @__PURE__ */ (0, import_jsx_runtime27.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` }),
6634
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6839
+ /* @__PURE__ */ (0, import_jsx_runtime28.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` }),
6840
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6635
6841
  "button",
6636
6842
  {
6637
6843
  type: "button",
@@ -6642,7 +6848,7 @@ var ReviewToolbar = ({
6642
6848
  children: "\u203A"
6643
6849
  }
6644
6850
  ),
6645
- showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6851
+ showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
6646
6852
  "span",
6647
6853
  {
6648
6854
  className: descriptionClassName,
@@ -6654,8 +6860,8 @@ var ReviewToolbar = ({
6654
6860
  ]
6655
6861
  }
6656
6862
  ),
6657
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
6658
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6863
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
6864
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6659
6865
  "button",
6660
6866
  {
6661
6867
  type: "button",
@@ -6665,7 +6871,7 @@ var ReviewToolbar = ({
6665
6871
  children: "Accept"
6666
6872
  }
6667
6873
  ),
6668
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6874
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6669
6875
  "button",
6670
6876
  {
6671
6877
  type: "button",
@@ -6675,18 +6881,18 @@ var ReviewToolbar = ({
6675
6881
  children: "Reject"
6676
6882
  }
6677
6883
  ),
6678
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
6679
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
6884
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
6885
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
6680
6886
  ] });
6681
6887
  };
6682
6888
 
6683
6889
  // src/review/CommentButton.tsx
6684
- var import_jsx_runtime28 = require("react/jsx-runtime");
6890
+ var import_jsx_runtime29 = require("react/jsx-runtime");
6685
6891
  var CommentButton = ({
6686
6892
  editor,
6687
6893
  className = "rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted",
6688
6894
  children = "Comment"
6689
- }) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6895
+ }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6690
6896
  "button",
6691
6897
  {
6692
6898
  type: "button",
@@ -6698,13 +6904,13 @@ var CommentButton = ({
6698
6904
  );
6699
6905
 
6700
6906
  // src/review/useDocumentCompare.ts
6701
- var import_react45 = require("react");
6907
+ var import_react46 = require("react");
6702
6908
  var import_editor14 = require("@pixerate/editor");
6703
6909
  function useDocumentCompare(editor, options) {
6704
- const [summary, setSummary] = (0, import_react45.useState)(null);
6705
- const defaults = (0, import_react45.useRef)(options);
6910
+ const [summary, setSummary] = (0, import_react46.useState)(null);
6911
+ const defaults = (0, import_react46.useRef)(options);
6706
6912
  defaults.current = options;
6707
- const compare = (0, import_react45.useCallback)(
6913
+ const compare = (0, import_react46.useCallback)(
6708
6914
  (original, revised, overrides) => {
6709
6915
  if (!editor || editor.isDestroyed) return null;
6710
6916
  const result = (0, import_editor14.applyDocumentComparison)(editor, original, revised, {
@@ -6716,13 +6922,13 @@ function useDocumentCompare(editor, options) {
6716
6922
  },
6717
6923
  [editor]
6718
6924
  );
6719
- const clear = (0, import_react45.useCallback)(() => setSummary(null), []);
6720
- return (0, import_react45.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
6925
+ const clear = (0, import_react46.useCallback)(() => setSummary(null), []);
6926
+ return (0, import_react46.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
6721
6927
  }
6722
6928
 
6723
6929
  // src/review/TrackedChangesList.tsx
6724
6930
  var import_editor15 = require("@pixerate/editor");
6725
- var import_jsx_runtime29 = require("react/jsx-runtime");
6931
+ var import_jsx_runtime30 = require("react/jsx-runtime");
6726
6932
  var buttonClass4 = "rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40";
6727
6933
  var TrackedChangesList = ({
6728
6934
  editor,
@@ -6733,18 +6939,18 @@ var TrackedChangesList = ({
6733
6939
  }) => {
6734
6940
  const review = useTrackChanges(editor);
6735
6941
  if (review.changes.length === 0) {
6736
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className, "data-tracked-changes-list": "", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "pixerate-changes-empty text-xs text-muted-foreground", children: emptyState }) });
6942
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className, "data-tracked-changes-list": "", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "pixerate-changes-empty text-xs text-muted-foreground", children: emptyState }) });
6737
6943
  }
6738
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
6944
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
6739
6945
  const active = change.id === review.currentChangeId;
6740
- return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6946
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6741
6947
  "li",
6742
6948
  {
6743
6949
  className: active ? `${itemClassName} ${activeItemClassName}` : itemClassName,
6744
6950
  "data-change-type": change.type,
6745
6951
  "data-change-id": change.id,
6746
6952
  children: [
6747
- /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6953
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
6748
6954
  "button",
6749
6955
  {
6750
6956
  type: "button",
@@ -6752,14 +6958,14 @@ var TrackedChangesList = ({
6752
6958
  title: `${change.author.name}: ${change.description}`,
6753
6959
  onClick: () => review.select(change.id),
6754
6960
  children: [
6755
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
6961
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
6756
6962
  change.author.name ? ` \xB7 ${change.author.name}` : "",
6757
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
6963
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
6758
6964
  ]
6759
6965
  }
6760
6966
  ),
6761
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
6762
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
6967
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
6968
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
6763
6969
  ]
6764
6970
  },
6765
6971
  `${change.type}:${change.id}`
@@ -6768,12 +6974,12 @@ var TrackedChangesList = ({
6768
6974
  };
6769
6975
 
6770
6976
  // src/commands/useCommandPalette.ts
6771
- var import_react46 = require("react");
6977
+ var import_react47 = require("react");
6772
6978
  var import_commands2 = require("@pixerate/editor/commands");
6773
6979
  function useCommandPalette(registry, options = {}) {
6774
- const optionsRef = (0, import_react46.useRef)(options);
6980
+ const optionsRef = (0, import_react47.useRef)(options);
6775
6981
  optionsRef.current = options;
6776
- const controller = (0, import_react46.useMemo)(
6982
+ const controller = (0, import_react47.useMemo)(
6777
6983
  () => (0, import_commands2.createCommandPaletteController)(registry, {
6778
6984
  context: () => {
6779
6985
  const c = optionsRef.current.context;
@@ -6794,9 +7000,9 @@ function useCommandPalette(registry, options = {}) {
6794
7000
  // eslint-disable-next-line react-hooks/exhaustive-deps
6795
7001
  [registry]
6796
7002
  );
6797
- const state = (0, import_react46.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
7003
+ const state = (0, import_react47.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
6798
7004
  const { hotkey, hotkeyTarget } = options;
6799
- (0, import_react46.useEffect)(() => {
7005
+ (0, import_react47.useEffect)(() => {
6800
7006
  if (!hotkey) return;
6801
7007
  const target = hotkeyTarget ?? (typeof window !== "undefined" ? window : null);
6802
7008
  if (!target) return;
@@ -6824,13 +7030,13 @@ function useCommandPalette(registry, options = {}) {
6824
7030
  }
6825
7031
 
6826
7032
  // src/commands/CommandPalette.tsx
6827
- var import_react47 = __toESM(require("react"), 1);
6828
- var import_jsx_runtime30 = require("react/jsx-runtime");
7033
+ var import_react48 = __toESM(require("react"), 1);
7034
+ var import_jsx_runtime31 = require("react/jsx-runtime");
6829
7035
  function HighlightedLabel({ item }) {
6830
- if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: item.label });
7036
+ if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_jsx_runtime31.Fragment, { children: item.label });
6831
7037
  const marked = new Set(item.labelIndices);
6832
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: Array.from(item.label).map(
6833
- (ch, i) => marked.has(i) ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-semibold text-foreground", "data-match": "", children: ch }, i) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react47.default.Fragment, { children: ch }, i)
7038
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_jsx_runtime31.Fragment, { children: Array.from(item.label).map(
7039
+ (ch, i) => marked.has(i) ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "font-semibold text-foreground", "data-match": "", children: ch }, i) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react48.default.Fragment, { children: ch }, i)
6834
7040
  ) });
6835
7041
  }
6836
7042
  var CommandPalette = ({
@@ -6839,22 +7045,22 @@ var CommandPalette = ({
6839
7045
  emptyMessage = "No matching commands",
6840
7046
  className = ""
6841
7047
  }) => {
6842
- const inputRef = (0, import_react47.useRef)(null);
6843
- const listRef = (0, import_react47.useRef)(null);
6844
- const baseId = (0, import_react47.useId)();
7048
+ const inputRef = (0, import_react48.useRef)(null);
7049
+ const listRef = (0, import_react48.useRef)(null);
7050
+ const baseId = (0, import_react48.useId)();
6845
7051
  const listId = `${baseId}-list`;
6846
7052
  const optionId = (index) => `${baseId}-option-${index}`;
6847
7053
  const { open, query, items, activeIndex } = palette;
6848
- (0, import_react47.useEffect)(() => {
7054
+ (0, import_react48.useEffect)(() => {
6849
7055
  if (open) inputRef.current?.focus();
6850
7056
  }, [open]);
6851
- (0, import_react47.useEffect)(() => {
7057
+ (0, import_react48.useEffect)(() => {
6852
7058
  if (!open) return;
6853
7059
  const active = listRef.current?.querySelector('[aria-selected="true"]');
6854
7060
  active?.scrollIntoView?.({ block: "nearest" });
6855
7061
  }, [open, activeIndex]);
6856
7062
  if (!open) return null;
6857
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7063
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6858
7064
  "div",
6859
7065
  {
6860
7066
  className: "fixed inset-0 z-50 flex items-start justify-center bg-black/30 px-4 pt-[15vh]",
@@ -6862,7 +7068,7 @@ var CommandPalette = ({
6862
7068
  onMouseDown: (e) => {
6863
7069
  if (e.target === e.currentTarget) palette.setOpen(false);
6864
7070
  },
6865
- children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7071
+ children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
6866
7072
  "div",
6867
7073
  {
6868
7074
  role: "dialog",
@@ -6871,7 +7077,7 @@ var CommandPalette = ({
6871
7077
  className: `w-full max-w-lg overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-xl ${className}`,
6872
7078
  style: { background: "var(--popover, var(--background, #fff))" },
6873
7079
  children: [
6874
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
7080
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
6875
7081
  "input",
6876
7082
  {
6877
7083
  ref: inputRef,
@@ -6891,7 +7097,7 @@ var CommandPalette = ({
6891
7097
  className: "w-full border-b border-border bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground"
6892
7098
  }
6893
7099
  ),
6894
- items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime30.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_runtime30.jsxs)(
7100
+ items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime31.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_runtime31.jsxs)(
6895
7101
  "li",
6896
7102
  {
6897
7103
  id: optionId(index),
@@ -6906,12 +7112,12 @@ var CommandPalette = ({
6906
7112
  onClick: () => palette.run(item.id),
6907
7113
  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"}`,
6908
7114
  children: [
6909
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
6910
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(HighlightedLabel, { item }),
6911
- item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
7115
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
7116
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(HighlightedLabel, { item }),
7117
+ item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
6912
7118
  ] }),
6913
- item.group && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
6914
- item.shortcut && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("kbd", { className: "shrink-0 rounded border border-border px-1.5 font-mono text-[10px] text-muted-foreground", children: item.shortcut })
7119
+ item.group && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
7120
+ item.shortcut && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("kbd", { className: "shrink-0 rounded border border-border px-1.5 font-mono text-[10px] text-muted-foreground", children: item.shortcut })
6915
7121
  ]
6916
7122
  },
6917
7123
  item.id
@@ -6924,12 +7130,12 @@ var CommandPalette = ({
6924
7130
  };
6925
7131
 
6926
7132
  // src/commands/useCommandShortcuts.ts
6927
- var import_react48 = require("react");
7133
+ var import_react49 = require("react");
6928
7134
  function useCommandShortcuts(registry, options = {}) {
6929
- const optionsRef = (0, import_react48.useRef)(options);
7135
+ const optionsRef = (0, import_react49.useRef)(options);
6930
7136
  optionsRef.current = options;
6931
7137
  const { enabled = true, target } = options;
6932
- (0, import_react48.useEffect)(() => {
7138
+ (0, import_react49.useEffect)(() => {
6933
7139
  if (!registry || !enabled) return;
6934
7140
  const eventTarget = target ?? (typeof window !== "undefined" ? window : null);
6935
7141
  if (!eventTarget) return;
@@ -6947,14 +7153,14 @@ function useCommandShortcuts(registry, options = {}) {
6947
7153
  }, [registry, enabled, target]);
6948
7154
  }
6949
7155
  function useRegisterCommands(registry, specs) {
6950
- (0, import_react48.useEffect)(() => {
7156
+ (0, import_react49.useEffect)(() => {
6951
7157
  if (!registry || !specs || specs.length === 0) return;
6952
7158
  return registry.register(specs);
6953
7159
  }, [registry, specs]);
6954
7160
  }
6955
7161
 
6956
7162
  // src/persistence/useAutosave.ts
6957
- var import_react49 = require("react");
7163
+ var import_react50 = require("react");
6958
7164
  var import_persistence = require("@pixerate/editor/persistence");
6959
7165
  var IDLE = {
6960
7166
  status: "idle",
@@ -6965,18 +7171,18 @@ var IDLE = {
6965
7171
  ready: false
6966
7172
  };
6967
7173
  function useAutosave(options) {
6968
- const optionsRef = (0, import_react49.useRef)(options);
7174
+ const optionsRef = (0, import_react50.useRef)(options);
6969
7175
  optionsRef.current = options;
6970
7176
  const { storage, key, history, dirty } = options;
6971
7177
  const recover = options.recover !== false;
6972
7178
  const flushOnHide = options.flushOnHide !== false;
6973
7179
  const ready = options.ready !== false;
6974
- const [controller, setController] = (0, import_react49.useState)(null);
6975
- const [status, setStatus] = (0, import_react49.useState)(IDLE);
6976
- const [recovery, setRecovery] = (0, import_react49.useState)(null);
6977
- const [pendingRecovery, setPendingRecovery] = (0, import_react49.useState)(recover);
6978
- const revisionsRef = (0, import_react49.useRef)(null);
6979
- (0, import_react49.useEffect)(() => {
7180
+ const [controller, setController] = (0, import_react50.useState)(null);
7181
+ const [status, setStatus] = (0, import_react50.useState)(IDLE);
7182
+ const [recovery, setRecovery] = (0, import_react50.useState)(null);
7183
+ const [pendingRecovery, setPendingRecovery] = (0, import_react50.useState)(recover);
7184
+ const revisionsRef = (0, import_react50.useRef)(null);
7185
+ (0, import_react50.useEffect)(() => {
6980
7186
  const revisions = (0, import_persistence.createRevisionTracker)({ history, dirty });
6981
7187
  const o = optionsRef.current;
6982
7188
  const instance = (0, import_persistence.createAutosaveController)({
@@ -7019,10 +7225,10 @@ function useAutosave(options) {
7019
7225
  if (revisionsRef.current === revisions) revisionsRef.current = null;
7020
7226
  };
7021
7227
  }, [storage, key, history, dirty, recover]);
7022
- (0, import_react49.useEffect)(() => {
7228
+ (0, import_react50.useEffect)(() => {
7023
7229
  if (controller && ready && !pendingRecovery) controller.ready();
7024
7230
  }, [controller, ready, pendingRecovery]);
7025
- (0, import_react49.useEffect)(() => {
7231
+ (0, import_react50.useEffect)(() => {
7026
7232
  if (!controller || !flushOnHide || typeof window === "undefined") return;
7027
7233
  const flush = () => void controller.flushNow();
7028
7234
  const onVisibility = () => {
@@ -7035,31 +7241,31 @@ function useAutosave(options) {
7035
7241
  document.removeEventListener("visibilitychange", onVisibility);
7036
7242
  };
7037
7243
  }, [controller, flushOnHide]);
7038
- const restore = (0, import_react49.useCallback)(() => {
7244
+ const restore = (0, import_react50.useCallback)(() => {
7039
7245
  const snapshot = recovery?.snapshot;
7040
7246
  setRecovery(null);
7041
7247
  setPendingRecovery(false);
7042
7248
  return snapshot;
7043
7249
  }, [recovery]);
7044
- const discard = (0, import_react49.useCallback)(async () => {
7250
+ const discard = (0, import_react50.useCallback)(async () => {
7045
7251
  if (controller) await controller.discardRecovery();
7046
7252
  setRecovery(null);
7047
7253
  setPendingRecovery(false);
7048
7254
  }, [controller]);
7049
- const flushNow = (0, import_react49.useCallback)(async () => {
7255
+ const flushNow = (0, import_react50.useCallback)(async () => {
7050
7256
  await controller?.flushNow();
7051
7257
  }, [controller]);
7052
- const markClean = (0, import_react49.useCallback)(async () => {
7258
+ const markClean = (0, import_react50.useCallback)(async () => {
7053
7259
  revisionsRef.current?.markSaved();
7054
7260
  await controller?.markClean();
7055
7261
  }, [controller]);
7056
- const notifyChange = (0, import_react49.useCallback)(() => revisionsRef.current?.bump(), []);
7262
+ const notifyChange = (0, import_react50.useCallback)(() => revisionsRef.current?.bump(), []);
7057
7263
  return { status, recovery, pendingRecovery, restore, discard, flushNow, markClean, notifyChange, controller };
7058
7264
  }
7059
7265
 
7060
7266
  // src/persistence/RecoveryPrompt.tsx
7061
7267
  var import_persistence2 = require("@pixerate/editor/persistence");
7062
- var import_jsx_runtime31 = require("react/jsx-runtime");
7268
+ var import_jsx_runtime32 = require("react/jsx-runtime");
7063
7269
  var RecoveryPrompt = ({
7064
7270
  recovery,
7065
7271
  onRestore,
@@ -7071,7 +7277,7 @@ var RecoveryPrompt = ({
7071
7277
  }) => {
7072
7278
  if (!recovery) return null;
7073
7279
  const { name } = recovery.meta;
7074
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
7280
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7075
7281
  "div",
7076
7282
  {
7077
7283
  role: "alertdialog",
@@ -7079,15 +7285,15 @@ var RecoveryPrompt = ({
7079
7285
  "data-recovery-prompt": "",
7080
7286
  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}`,
7081
7287
  children: [
7082
- /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "min-w-0 flex-1", children: [
7288
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "min-w-0 flex-1", children: [
7083
7289
  (0, import_persistence2.formatRecoveryMessage)(recovery.meta, formatTime),
7084
- name ? /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
7290
+ name ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
7085
7291
  "(",
7086
7292
  name,
7087
7293
  ")"
7088
7294
  ] }) : null
7089
7295
  ] }),
7090
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7296
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7091
7297
  "button",
7092
7298
  {
7093
7299
  type: "button",
@@ -7097,7 +7303,7 @@ var RecoveryPrompt = ({
7097
7303
  children: restoreLabel
7098
7304
  }
7099
7305
  ),
7100
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7306
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7101
7307
  "button",
7102
7308
  {
7103
7309
  type: "button",
@@ -7113,17 +7319,17 @@ var RecoveryPrompt = ({
7113
7319
  };
7114
7320
 
7115
7321
  // src/generation/useGenerationPlan.ts
7116
- var import_react50 = require("react");
7322
+ var import_react51 = require("react");
7117
7323
  var import_generation = require("@pixerate/editor/generation");
7118
7324
  function useGenerationPlan(request, capabilities, options = {}) {
7119
7325
  const key = JSON.stringify([request, capabilities, options]);
7120
- return (0, import_react50.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
7326
+ return (0, import_react51.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
7121
7327
  }
7122
7328
  function useJobProgress(options) {
7123
7329
  const { startedAt, expectedMs, done, now, intervalMs = 1e3 } = options;
7124
- const [tick, setTick] = (0, import_react50.useState)(() => Date.now());
7330
+ const [tick, setTick] = (0, import_react51.useState)(() => Date.now());
7125
7331
  const ticking = !done && now === void 0;
7126
- (0, import_react50.useEffect)(() => {
7332
+ (0, import_react51.useEffect)(() => {
7127
7333
  if (!ticking) return;
7128
7334
  setTick(Date.now());
7129
7335
  const id = setInterval(() => setTick(Date.now()), Math.max(16, intervalMs));
@@ -7133,9 +7339,9 @@ function useJobProgress(options) {
7133
7339
  }
7134
7340
 
7135
7341
  // src/generation/GenerationSettings.tsx
7136
- var import_react51 = require("react");
7342
+ var import_react52 = require("react");
7137
7343
  var import_generation2 = require("@pixerate/editor/generation");
7138
- var import_jsx_runtime32 = require("react/jsx-runtime");
7344
+ var import_jsx_runtime33 = require("react/jsx-runtime");
7139
7345
  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";
7140
7346
  function Control({
7141
7347
  control,
@@ -7145,7 +7351,7 @@ function Control({
7145
7351
  }) {
7146
7352
  const shown = value ?? control.defaultValue;
7147
7353
  if (control.kind === "checkbox") {
7148
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7354
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7149
7355
  "input",
7150
7356
  {
7151
7357
  id,
@@ -7157,7 +7363,7 @@ function Control({
7157
7363
  );
7158
7364
  }
7159
7365
  if (control.kind === "select") {
7160
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7366
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
7161
7367
  "select",
7162
7368
  {
7163
7369
  id,
@@ -7166,14 +7372,14 @@ function Control({
7166
7372
  value: shown === void 0 ? "" : String(shown),
7167
7373
  onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value)),
7168
7374
  children: [
7169
- shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: "", children: "Default" }),
7170
- control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
7375
+ shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("option", { value: "", children: "Default" }),
7376
+ control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
7171
7377
  ]
7172
7378
  }
7173
7379
  );
7174
7380
  }
7175
7381
  if (control.kind === "textarea") {
7176
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7382
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7177
7383
  "textarea",
7178
7384
  {
7179
7385
  id,
@@ -7187,8 +7393,8 @@ function Control({
7187
7393
  );
7188
7394
  }
7189
7395
  const numeric = typeof shown === "number" ? shown : void 0;
7190
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2", children: [
7191
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7396
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-2", children: [
7397
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7192
7398
  "input",
7193
7399
  {
7194
7400
  id,
@@ -7202,7 +7408,7 @@ function Control({
7202
7408
  onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value))
7203
7409
  }
7204
7410
  ),
7205
- control.kind === "range" && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "w-10 text-right tabular-nums text-muted-foreground", "data-field-value": "", children: numeric ?? "\u2013" })
7411
+ control.kind === "range" && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "w-10 text-right tabular-nums text-muted-foreground", "data-field-value": "", children: numeric ?? "\u2013" })
7206
7412
  ] });
7207
7413
  }
7208
7414
  var GenerationSettings = ({
@@ -7216,17 +7422,17 @@ var GenerationSettings = ({
7216
7422
  renderReference,
7217
7423
  className = ""
7218
7424
  }) => {
7219
- const baseId = (0, import_react51.useId)();
7220
- const controls = (0, import_react51.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
7425
+ const baseId = (0, import_react52.useId)();
7426
+ const controls = (0, import_react52.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
7221
7427
  const computed = useGenerationPlan(value, capabilities, { strategy });
7222
7428
  const plan = planProp ?? computed;
7223
7429
  const slots = (0, import_generation2.getReferenceSlots)(capabilities, value);
7224
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: `flex flex-col gap-3 text-sm ${className}`, "data-generation-settings": "", "data-model": capabilities.id, children: [
7430
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: `flex flex-col gap-3 text-sm ${className}`, "data-generation-settings": "", "data-model": capabilities.id, children: [
7225
7431
  controls.map((control) => {
7226
7432
  const id = `${baseId}-${control.key}`;
7227
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
7228
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
7229
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7433
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
7434
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
7435
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7230
7436
  Control,
7231
7437
  {
7232
7438
  control,
@@ -7237,23 +7443,23 @@ var GenerationSettings = ({
7237
7443
  )
7238
7444
  ] }, control.key);
7239
7445
  }),
7240
- slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
7241
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
7446
+ slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
7447
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
7242
7448
  slot.label,
7243
7449
  " ",
7244
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
7450
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
7245
7451
  "(",
7246
7452
  slot.references.length,
7247
7453
  "/",
7248
7454
  slot.max,
7249
7455
  ")"
7250
7456
  ] }),
7251
- slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-destructive", children: " *" })
7457
+ slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-destructive", children: " *" })
7252
7458
  ] }),
7253
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
7254
- slot.references.map((ref) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("li", { className: "flex items-center gap-1 rounded border border-border px-1.5 py-0.5", "data-reference-id": ref.id, children: [
7255
- renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
7256
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7459
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
7460
+ slot.references.map((ref) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("li", { className: "flex items-center gap-1 rounded border border-border px-1.5 py-0.5", "data-reference-id": ref.id, children: [
7461
+ renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
7462
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7257
7463
  "button",
7258
7464
  {
7259
7465
  type: "button",
@@ -7264,7 +7470,7 @@ var GenerationSettings = ({
7264
7470
  }
7265
7471
  )
7266
7472
  ] }, ref.id)),
7267
- onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7473
+ onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7268
7474
  "button",
7269
7475
  {
7270
7476
  type: "button",
@@ -7275,21 +7481,21 @@ var GenerationSettings = ({
7275
7481
  ) })
7276
7482
  ] })
7277
7483
  ] }, slot.role)),
7278
- showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.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_runtime32.jsx)("li", { "data-adjustment-field": adjustment.field, "data-adjustment-kind": adjustment.kind, children: adjustment.reason }, index)) }),
7279
- showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.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_runtime32.jsx)("li", { "data-error-field": error.field, children: error.message }, index)) })
7484
+ showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.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_runtime33.jsx)("li", { "data-adjustment-field": adjustment.field, "data-adjustment-kind": adjustment.kind, children: adjustment.reason }, index)) }),
7485
+ showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.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_runtime33.jsx)("li", { "data-error-field": error.field, children: error.message }, index)) })
7280
7486
  ] });
7281
7487
  };
7282
7488
 
7283
7489
  // src/generation/JobProgress.tsx
7284
- var import_jsx_runtime33 = require("react/jsx-runtime");
7490
+ var import_jsx_runtime34 = require("react/jsx-runtime");
7285
7491
  var JobProgress = ({ title, className = "", ...options }) => {
7286
7492
  const progress = useJobProgress(options);
7287
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: `flex flex-col gap-1 text-sm ${className}`, "data-job-progress": "", "data-done": options.done ? "" : void 0, children: [
7288
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
7289
- title && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "truncate text-foreground", children: title }),
7290
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
7493
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: `flex flex-col gap-1 text-sm ${className}`, "data-job-progress": "", "data-done": options.done ? "" : void 0, children: [
7494
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
7495
+ title && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "truncate text-foreground", children: title }),
7496
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
7291
7497
  ] }),
7292
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7498
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7293
7499
  "div",
7294
7500
  {
7295
7501
  role: "progressbar",
@@ -7299,7 +7505,7 @@ var JobProgress = ({ title, className = "", ...options }) => {
7299
7505
  "aria-valuenow": progress.percent,
7300
7506
  "aria-valuetext": `${progress.percent}%, ${progress.label}`,
7301
7507
  className: "h-1.5 w-full overflow-hidden rounded-full bg-muted",
7302
- children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7508
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7303
7509
  "div",
7304
7510
  {
7305
7511
  className: "h-full rounded-full bg-primary transition-[width] duration-500",
@@ -7312,9 +7518,9 @@ var JobProgress = ({ title, className = "", ...options }) => {
7312
7518
  };
7313
7519
 
7314
7520
  // src/generation/AssetMentionChips.tsx
7315
- var import_react52 = require("react");
7521
+ var import_react53 = require("react");
7316
7522
  var import_generation3 = require("@pixerate/editor/generation");
7317
- var import_jsx_runtime34 = require("react/jsx-runtime");
7523
+ var import_jsx_runtime35 = require("react/jsx-runtime");
7318
7524
  var AssetMentionChips = ({
7319
7525
  content,
7320
7526
  onChange,
@@ -7324,14 +7530,14 @@ var AssetMentionChips = ({
7324
7530
  renderAsset,
7325
7531
  className = ""
7326
7532
  }) => {
7327
- const [open, setOpen] = (0, import_react52.useState)(null);
7328
- const rootRef = (0, import_react52.useRef)(null);
7329
- const chips = (0, import_react52.useMemo)(
7533
+ const [open, setOpen] = (0, import_react53.useState)(null);
7534
+ const rootRef = (0, import_react53.useRef)(null);
7535
+ const chips = (0, import_react53.useMemo)(
7330
7536
  () => (0, import_generation3.describeAssetMentions)((0, import_generation3.findTextMentions)(content), assets, capabilities),
7331
7537
  [content, assets, capabilities]
7332
7538
  );
7333
7539
  const options = roles ?? (capabilities ? (0, import_generation3.getAssetRoleOptions)(capabilities) : (0, import_generation3.defaultAssetRoleOptions)());
7334
- (0, import_react52.useEffect)(() => {
7540
+ (0, import_react53.useEffect)(() => {
7335
7541
  if (open === null) return;
7336
7542
  const onPointer = (event) => {
7337
7543
  if (!rootRef.current?.contains(event.target)) setOpen(null);
@@ -7345,13 +7551,13 @@ var AssetMentionChips = ({
7345
7551
  onChange((0, import_generation3.setMentionRoleInText)(content, chip2.start, role));
7346
7552
  };
7347
7553
  if (chips.length === 0) return null;
7348
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { ref: rootRef, className: `flex flex-wrap gap-1.5 ${className}`, "data-asset-mention-chips": "", children: chips.map((chip2) => {
7554
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { ref: rootRef, className: `flex flex-wrap gap-1.5 ${className}`, "data-asset-mention-chips": "", children: chips.map((chip2) => {
7349
7555
  const error = chip2.issues.find((issue) => issue.severity === "error");
7350
7556
  const warning = chip2.issues.find((issue) => issue.severity === "warning");
7351
7557
  const problem = error ?? warning;
7352
7558
  const isOpen = open === chip2.index;
7353
- return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip2.asset.id, children: [
7354
- /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7559
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip2.asset.id, children: [
7560
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7355
7561
  "button",
7356
7562
  {
7357
7563
  type: "button",
@@ -7365,8 +7571,8 @@ var AssetMentionChips = ({
7365
7571
  },
7366
7572
  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`,
7367
7573
  children: [
7368
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: renderAsset ? renderAsset(chip2) : `@${chip2.asset.label ?? chip2.handle}` }),
7369
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7574
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: renderAsset ? renderAsset(chip2) : `@${chip2.asset.label ?? chip2.handle}` }),
7575
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7370
7576
  "span",
7371
7577
  {
7372
7578
  className: `rounded px-1 text-[10px] uppercase tracking-wide ${chip2.role ? "bg-primary/15" : "opacity-60"}`,
@@ -7377,7 +7583,7 @@ var AssetMentionChips = ({
7377
7583
  ]
7378
7584
  }
7379
7585
  ),
7380
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7586
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7381
7587
  "div",
7382
7588
  {
7383
7589
  role: "listbox",
@@ -7388,7 +7594,7 @@ var AssetMentionChips = ({
7388
7594
  if (e.key === "Escape") setOpen(null);
7389
7595
  },
7390
7596
  children: [
7391
- options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7597
+ options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7392
7598
  "button",
7393
7599
  {
7394
7600
  type: "button",
@@ -7399,13 +7605,13 @@ var AssetMentionChips = ({
7399
7605
  onClick: () => pick(chip2, option.role),
7400
7606
  className: "flex items-center justify-between gap-2 rounded px-2 py-1 text-left hover:bg-muted",
7401
7607
  children: [
7402
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { children: option.label }),
7403
- option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
7608
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: option.label }),
7609
+ option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
7404
7610
  ]
7405
7611
  },
7406
7612
  option.role
7407
7613
  )),
7408
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7614
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7409
7615
  "button",
7410
7616
  {
7411
7617
  type: "button",
@@ -7417,7 +7623,7 @@ var AssetMentionChips = ({
7417
7623
  children: "No role"
7418
7624
  }
7419
7625
  ),
7420
- chip2.issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("ul", { className: "mt-1 border-t border-border px-2 pt-1 text-[10px]", "data-chip-issues": "", children: chip2.issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("li", { className: issue.severity === "error" ? "text-red-500" : "text-amber-500", children: issue.message }, i)) })
7626
+ chip2.issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { className: "mt-1 border-t border-border px-2 pt-1 text-[10px]", "data-chip-issues": "", children: chip2.issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("li", { className: issue.severity === "error" ? "text-red-500" : "text-amber-500", children: issue.message }, i)) })
7421
7627
  ]
7422
7628
  }
7423
7629
  )
@@ -7426,15 +7632,15 @@ var AssetMentionChips = ({
7426
7632
  };
7427
7633
 
7428
7634
  // src/generation/GenerationHistory.tsx
7429
- var import_react53 = require("react");
7635
+ var import_react54 = require("react");
7430
7636
  var import_generation4 = require("@pixerate/editor/generation");
7431
- var import_jsx_runtime35 = require("react/jsx-runtime");
7637
+ var import_jsx_runtime36 = require("react/jsx-runtime");
7432
7638
  function useGenerationRecords(store, filter) {
7433
- const [records, setRecords] = (0, import_react53.useState)([]);
7434
- const [loading, setLoading] = (0, import_react53.useState)(!!store);
7435
- const [error, setError] = (0, import_react53.useState)(null);
7639
+ const [records, setRecords] = (0, import_react54.useState)([]);
7640
+ const [loading, setLoading] = (0, import_react54.useState)(!!store);
7641
+ const [error, setError] = (0, import_react54.useState)(null);
7436
7642
  const filterKey = (0, import_generation4.stableStringify)(filter ?? {});
7437
- const refresh = (0, import_react53.useCallback)(async () => {
7643
+ const refresh = (0, import_react54.useCallback)(async () => {
7438
7644
  if (!store) {
7439
7645
  setRecords([]);
7440
7646
  setLoading(false);
@@ -7451,7 +7657,7 @@ function useGenerationRecords(store, filter) {
7451
7657
  setLoading(false);
7452
7658
  }
7453
7659
  }, [store, filterKey]);
7454
- (0, import_react53.useEffect)(() => {
7660
+ (0, import_react54.useEffect)(() => {
7455
7661
  void refresh();
7456
7662
  if (!store) return;
7457
7663
  return store.subscribe(() => void refresh());
@@ -7477,21 +7683,21 @@ var GenerationHistory = ({
7477
7683
  emptyText = "No generations yet.",
7478
7684
  className = ""
7479
7685
  }) => {
7480
- const [innerMode, setInnerMode] = (0, import_react53.useState)("exact");
7686
+ const [innerMode, setInnerMode] = (0, import_react54.useState)("exact");
7481
7687
  const mode = modeProp ?? innerMode;
7482
7688
  const setMode = (next) => {
7483
7689
  if (modeProp === void 0) setInnerMode(next);
7484
7690
  onModeChange?.(next);
7485
7691
  };
7486
- const options = (0, import_react53.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
7487
- const results = (0, import_react53.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
7488
- const models = (0, import_react53.useMemo)(
7692
+ const options = (0, import_react54.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
7693
+ const results = (0, import_react54.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
7694
+ const models = (0, import_react54.useMemo)(
7489
7695
  () => capabilities ? Array.isArray(capabilities) ? capabilities : [capabilities] : [],
7490
7696
  [capabilities]
7491
7697
  );
7492
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
7493
- /* @__PURE__ */ (0, import_jsx_runtime35.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_runtime35.jsxs)("label", { className: "inline-flex items-center gap-1", children: [
7494
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7698
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
7699
+ /* @__PURE__ */ (0, import_jsx_runtime36.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_runtime36.jsxs)("label", { className: "inline-flex items-center gap-1", children: [
7700
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7495
7701
  "input",
7496
7702
  {
7497
7703
  type: "radio",
@@ -7504,34 +7710,34 @@ var GenerationHistory = ({
7504
7710
  ),
7505
7711
  value === "exact" ? "Exact (recorded versions)" : "Latest templates & settings"
7506
7712
  ] }, value)) }),
7507
- records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
7508
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
7713
+ records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
7714
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
7509
7715
  const result = results[i];
7510
7716
  const model = models.find((m) => m.id === record.provenance.modelId);
7511
7717
  const blocked = !result.ok;
7512
- return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7718
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7513
7719
  "li",
7514
7720
  {
7515
7721
  className: "rounded-md border border-border p-2",
7516
7722
  "data-record": record.id,
7517
7723
  "data-drift": result.drift.length,
7518
7724
  children: [
7519
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
7520
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
7521
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "text-muted-foreground", children: [
7522
- record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { "data-kind": "", children: [
7725
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
7726
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
7727
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "text-muted-foreground", children: [
7728
+ record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { "data-kind": "", children: [
7523
7729
  record.kind,
7524
7730
  " \xB7 "
7525
7731
  ] }),
7526
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
7527
- record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
7732
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
7733
+ record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
7528
7734
  " \xB7 seed ",
7529
7735
  record.seed
7530
7736
  ] })
7531
7737
  ] })
7532
7738
  ] }),
7533
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
7534
- record.assets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { className: "mt-1 flex flex-wrap gap-1", children: record.assets.map((asset) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7739
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
7740
+ record.assets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { className: "mt-1 flex flex-wrap gap-1", children: record.assets.map((asset) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7535
7741
  "span",
7536
7742
  {
7537
7743
  className: "rounded-full bg-muted px-2 py-0.5 text-[10px]",
@@ -7545,16 +7751,16 @@ var GenerationHistory = ({
7545
7751
  `${asset.role}:${asset.id}`
7546
7752
  )) }),
7547
7753
  renderPreview?.(record),
7548
- result.drift.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.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_runtime35.jsxs)("li", { className: severityClass[item.severity], "data-drift-type": item.type, children: [
7549
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("strong", { children: [
7754
+ result.drift.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime36.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_runtime36.jsxs)("li", { className: severityClass[item.severity], "data-drift-type": item.type, children: [
7755
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("strong", { children: [
7550
7756
  import_generation4.DRIFT_TYPE_LABELS[item.type],
7551
7757
  ":"
7552
7758
  ] }),
7553
7759
  " ",
7554
7760
  item.message
7555
7761
  ] }, j)) }),
7556
- /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "mt-2 flex gap-2", children: [
7557
- onRecreate && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7762
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "mt-2 flex gap-2", children: [
7763
+ onRecreate && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7558
7764
  "button",
7559
7765
  {
7560
7766
  type: "button",
@@ -7566,7 +7772,7 @@ var GenerationHistory = ({
7566
7772
  children: "Recreate"
7567
7773
  }
7568
7774
  ),
7569
- onVariation && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7775
+ onVariation && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7570
7776
  "button",
7571
7777
  {
7572
7778
  type: "button",
@@ -7576,7 +7782,7 @@ var GenerationHistory = ({
7576
7782
  children: "Variation"
7577
7783
  }
7578
7784
  ),
7579
- onRemove && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7785
+ onRemove && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7580
7786
  "button",
7581
7787
  {
7582
7788
  type: "button",
@@ -7596,19 +7802,19 @@ var GenerationHistory = ({
7596
7802
  };
7597
7803
 
7598
7804
  // src/find-replace/useFindReplace.ts
7599
- var import_react54 = require("react");
7805
+ var import_react55 = require("react");
7600
7806
  var import_editor16 = require("@pixerate/editor");
7601
7807
  var noopUnsubscribe2 = () => {
7602
7808
  };
7603
7809
  function useFindReplace(editor) {
7604
7810
  const store = (0, import_editor16.getFindReplaceStore)(editor ?? null);
7605
- const subscribe = (0, import_react54.useCallback)(
7811
+ const subscribe = (0, import_react55.useCallback)(
7606
7812
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe2,
7607
7813
  [store]
7608
7814
  );
7609
7815
  const getSnapshot = () => store?.getSnapshot() ?? import_editor16.EMPTY_FIND_REPLACE_SNAPSHOT;
7610
- const snapshot = (0, import_react54.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7611
- return (0, import_react54.useMemo)(() => {
7816
+ const snapshot = (0, import_react55.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7817
+ return (0, import_react55.useMemo)(() => {
7612
7818
  const run = (fn) => {
7613
7819
  if (editor && !editor.isDestroyed && store) fn(editor);
7614
7820
  };
@@ -7632,9 +7838,9 @@ function useFindReplace(editor) {
7632
7838
  }
7633
7839
 
7634
7840
  // src/find-replace/FindReplaceBar.tsx
7635
- var import_react55 = require("react");
7841
+ var import_react56 = require("react");
7636
7842
  var import_editor17 = require("@pixerate/editor");
7637
- var import_jsx_runtime36 = require("react/jsx-runtime");
7843
+ var import_jsx_runtime37 = require("react/jsx-runtime");
7638
7844
  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";
7639
7845
  var buttonClass5 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
7640
7846
  var toggleClass = (on) => `${buttonClass5} font-mono ${on ? "bg-primary/10 text-primary" : "text-muted-foreground"}`;
@@ -7647,10 +7853,10 @@ var FindReplaceBar = ({
7647
7853
  onClose
7648
7854
  }) => {
7649
7855
  const find = useFindReplace(editor);
7650
- const findInput = (0, import_react55.useRef)(null);
7651
- const [moreOpen, setMoreOpen] = (0, import_react55.useState)(false);
7856
+ const findInput = (0, import_react56.useRef)(null);
7857
+ const [moreOpen, setMoreOpen] = (0, import_react56.useState)(false);
7652
7858
  const visible = find.available && (alwaysOpen || find.open);
7653
- (0, import_react55.useEffect)(() => {
7859
+ (0, import_react56.useEffect)(() => {
7654
7860
  if (!visible || find.focusRequest === 0) return;
7655
7861
  findInput.current?.focus();
7656
7862
  findInput.current?.select();
@@ -7688,9 +7894,9 @@ var FindReplaceBar = ({
7688
7894
  if (isMod(e)) find.replaceAll();
7689
7895
  else find.replace();
7690
7896
  };
7691
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
7692
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-1", children: [
7693
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7897
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
7898
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-1", children: [
7899
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7694
7900
  "button",
7695
7901
  {
7696
7902
  type: "button",
@@ -7701,7 +7907,7 @@ var FindReplaceBar = ({
7701
7907
  children: showReplace ? "\u25BE" : "\u25B8"
7702
7908
  }
7703
7909
  ),
7704
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7910
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7705
7911
  "input",
7706
7912
  {
7707
7913
  ref: findInput,
@@ -7715,7 +7921,7 @@ var FindReplaceBar = ({
7715
7921
  onKeyDown: onFindKeyDown
7716
7922
  }
7717
7923
  ),
7718
- import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7924
+ import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7719
7925
  "button",
7720
7926
  {
7721
7927
  type: "button",
@@ -7728,7 +7934,7 @@ var FindReplaceBar = ({
7728
7934
  },
7729
7935
  t.key
7730
7936
  )),
7731
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7937
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7732
7938
  "span",
7733
7939
  {
7734
7940
  className: `min-w-[5rem] px-1 text-center text-xs ${find.error ? "text-destructive" : "text-muted-foreground"}`,
@@ -7738,9 +7944,9 @@ var FindReplaceBar = ({
7738
7944
  children: status
7739
7945
  }
7740
7946
  ),
7741
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
7742
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
7743
- showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7947
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
7948
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
7949
+ showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7744
7950
  "button",
7745
7951
  {
7746
7952
  type: "button",
@@ -7751,10 +7957,10 @@ var FindReplaceBar = ({
7751
7957
  children: "\u2026"
7752
7958
  }
7753
7959
  ),
7754
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
7960
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
7755
7961
  ] }),
7756
- showReplace && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
7757
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7962
+ showReplace && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
7963
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7758
7964
  "input",
7759
7965
  {
7760
7966
  type: "text",
@@ -7766,7 +7972,7 @@ var FindReplaceBar = ({
7766
7972
  onKeyDown: onReplaceKeyDown
7767
7973
  }
7768
7974
  ),
7769
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7975
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7770
7976
  "button",
7771
7977
  {
7772
7978
  type: "button",
@@ -7776,11 +7982,11 @@ var FindReplaceBar = ({
7776
7982
  children: "Replace"
7777
7983
  }
7778
7984
  ),
7779
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
7780
- find.lastReplaceCount !== null && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "px-1 text-xs text-muted-foreground", "aria-live": "polite", children: find.lastReplaceCount === 1 ? "1 replaced" : `${find.lastReplaceCount} replaced` })
7985
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
7986
+ find.lastReplaceCount !== null && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "px-1 text-xs text-muted-foreground", "aria-live": "polite", children: find.lastReplaceCount === 1 ? "1 replaced" : `${find.lastReplaceCount} replaced` })
7781
7987
  ] }),
7782
- showMoreOptions && moreOpen && /* @__PURE__ */ (0, import_jsx_runtime36.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_runtime36.jsxs)("label", { className: "flex items-center gap-1", children: [
7783
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7988
+ showMoreOptions && moreOpen && /* @__PURE__ */ (0, import_jsx_runtime37.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_runtime37.jsxs)("label", { className: "flex items-center gap-1", children: [
7989
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7784
7990
  "input",
7785
7991
  {
7786
7992
  type: "checkbox",
@@ -7794,12 +8000,12 @@ var FindReplaceBar = ({
7794
8000
  };
7795
8001
 
7796
8002
  // src/tables/useTableMenu.ts
7797
- var import_react56 = require("react");
8003
+ var import_react57 = require("react");
7798
8004
  var import_editor18 = require("@pixerate/editor");
7799
8005
  function useTableMenu(editor) {
7800
- const store = (0, import_react56.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
7801
- const snapshot = (0, import_react56.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
7802
- return (0, import_react56.useMemo)(
8006
+ const store = (0, import_react57.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
8007
+ const snapshot = (0, import_react57.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
8008
+ return (0, import_react57.useMemo)(
7803
8009
  () => ({
7804
8010
  ...snapshot,
7805
8011
  run: (action, params) => (0, import_editor18.runTableAction)(editor, action, params, { focus: true }),
@@ -7810,9 +8016,9 @@ function useTableMenu(editor) {
7810
8016
  }
7811
8017
 
7812
8018
  // src/tables/TableToolbar.tsx
7813
- var import_react57 = __toESM(require("react"), 1);
8019
+ var import_react58 = __toESM(require("react"), 1);
7814
8020
  var import_editor19 = require("@pixerate/editor");
7815
- var import_jsx_runtime37 = require("react/jsx-runtime");
8021
+ var import_jsx_runtime38 = require("react/jsx-runtime");
7816
8022
  var keepSelection2 = (event) => event.preventDefault();
7817
8023
  var TableToolbar = ({
7818
8024
  editor,
@@ -7826,14 +8032,14 @@ var TableToolbar = ({
7826
8032
  }) => {
7827
8033
  const table = useTableMenu(editor);
7828
8034
  if (!editor || !table.inTable && !showWhenOutside) return null;
7829
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
8035
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
7830
8036
  const status = table.check(item.action, item.params);
7831
8037
  const enabled = status === true;
7832
8038
  const active = item.active?.(table);
7833
8039
  const separator = index > 0 && items[index - 1].group !== item.group;
7834
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_react57.default.Fragment, { children: [
7835
- separator && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
7836
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8040
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_react58.default.Fragment, { children: [
8041
+ separator && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
8042
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
7837
8043
  "button",
7838
8044
  {
7839
8045
  type: "button",
@@ -7855,8 +8061,8 @@ var TableToolbar = ({
7855
8061
  };
7856
8062
 
7857
8063
  // src/tables/InsertTableGrid.tsx
7858
- var import_react58 = require("react");
7859
- var import_jsx_runtime38 = require("react/jsx-runtime");
8064
+ var import_react59 = require("react");
8065
+ var import_jsx_runtime39 = require("react/jsx-runtime");
7860
8066
  var keepSelection3 = (event) => event.preventDefault();
7861
8067
  var InsertTableGrid = ({
7862
8068
  editor,
@@ -7869,14 +8075,14 @@ var InsertTableGrid = ({
7869
8075
  onInsert
7870
8076
  }) => {
7871
8077
  const table = useTableMenu(editor);
7872
- const [hover, setHover] = (0, import_react58.useState)(null);
8078
+ const [hover, setHover] = (0, import_react59.useState)(null);
7873
8079
  const status = table.actions.insertTable;
7874
8080
  const disabled = !editor || !status.enabled;
7875
8081
  const insert = (size) => {
7876
8082
  if (table.run("insertTable", { ...size, withHeaderRow })) onInsert?.(size);
7877
8083
  setHover(null);
7878
8084
  };
7879
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
8085
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
7880
8086
  "div",
7881
8087
  {
7882
8088
  className,
@@ -7886,7 +8092,7 @@ var InsertTableGrid = ({
7886
8092
  "data-insert-table-grid": "",
7887
8093
  onMouseLeave: () => setHover(null),
7888
8094
  children: [
7889
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8095
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
7890
8096
  "div",
7891
8097
  {
7892
8098
  role: "grid",
@@ -7895,7 +8101,7 @@ var InsertTableGrid = ({
7895
8101
  children: Array.from({ length: rows * cols }, (_, i) => {
7896
8102
  const size = { rows: Math.floor(i / cols) + 1, cols: i % cols + 1 };
7897
8103
  const active = !!hover && size.rows <= hover.rows && size.cols <= hover.cols;
7898
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
8104
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
7899
8105
  "button",
7900
8106
  {
7901
8107
  type: "button",
@@ -7915,7 +8121,7 @@ var InsertTableGrid = ({
7915
8121
  })
7916
8122
  }
7917
8123
  ),
7918
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { "aria-live": "polite", "data-testid": "insert-table-size", children: disabled ? status.reason : hover ? `${hover.rows} \xD7 ${hover.cols}` : "Insert table" })
8124
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { "aria-live": "polite", "data-testid": "insert-table-size", children: disabled ? status.reason : hover ? `${hover.rows} \xD7 ${hover.cols}` : "Insert table" })
7919
8125
  ]
7920
8126
  }
7921
8127
  );
@@ -7923,31 +8129,31 @@ var InsertTableGrid = ({
7923
8129
 
7924
8130
  // src/tables/TableBubbleMenu.tsx
7925
8131
  var import_editor20 = require("@pixerate/editor");
7926
- var import_jsx_runtime39 = require("react/jsx-runtime");
8132
+ var import_jsx_runtime40 = require("react/jsx-runtime");
7927
8133
  var TableBubbleMenu = ({
7928
8134
  editor,
7929
8135
  children,
7930
8136
  toolbarProps,
7931
8137
  pluginKey = "tableBubbleMenu",
7932
8138
  ...rest
7933
- }) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(BubbleMenu, { editor, pluginKey, shouldShow: import_editor20.shouldShowTableBubbleMenu, ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(TableToolbar, { editor, ...toolbarProps }) });
8139
+ }) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(BubbleMenu, { editor, pluginKey, shouldShow: import_editor20.shouldShowTableBubbleMenu, ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(TableToolbar, { editor, ...toolbarProps }) });
7934
8140
 
7935
8141
  // src/chart-node/ChartNodeView.tsx
7936
8142
  var import_client = require("react-dom/client");
7937
8143
 
7938
8144
  // src/chart/ChartCanvas.tsx
7939
- var import_react60 = require("react");
8145
+ var import_react61 = require("react");
7940
8146
  var import_chart2 = require("@pixerate/editor/chart");
7941
8147
 
7942
8148
  // src/chart/useChartEditor.ts
7943
- var import_react59 = require("react");
8149
+ var import_react60 = require("react");
7944
8150
  var import_chart = require("@pixerate/editor/chart");
7945
8151
  function useChartState(controller) {
7946
- return (0, import_react59.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
8152
+ return (0, import_react60.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
7947
8153
  }
7948
8154
 
7949
8155
  // src/chart/ChartCanvas.tsx
7950
- var import_jsx_runtime40 = require("react/jsx-runtime");
8156
+ var import_jsx_runtime41 = require("react/jsx-runtime");
7951
8157
  function renderChartMark(mark, fontFamily, interactive) {
7952
8158
  const common = {
7953
8159
  "data-role": mark.role,
@@ -7959,9 +8165,9 @@ function renderChartMark(mark, fontFamily, interactive) {
7959
8165
  };
7960
8166
  switch (mark.kind) {
7961
8167
  case "rect":
7962
- return /* @__PURE__ */ (0, import_jsx_runtime40.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);
8168
+ return /* @__PURE__ */ (0, import_jsx_runtime41.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);
7963
8169
  case "path":
7964
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8170
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7965
8171
  "path",
7966
8172
  {
7967
8173
  ...common,
@@ -7974,11 +8180,11 @@ function renderChartMark(mark, fontFamily, interactive) {
7974
8180
  mark.key
7975
8181
  );
7976
8182
  case "circle":
7977
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("circle", { ...common, cx: mark.cx, cy: mark.cy, r: mark.r, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
8183
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("circle", { ...common, cx: mark.cx, cy: mark.cy, r: mark.r, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
7978
8184
  case "line":
7979
- return /* @__PURE__ */ (0, import_jsx_runtime40.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);
8185
+ return /* @__PURE__ */ (0, import_jsx_runtime41.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);
7980
8186
  case "text":
7981
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8187
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
7982
8188
  "text",
7983
8189
  {
7984
8190
  ...common,
@@ -7995,23 +8201,23 @@ function renderChartMark(mark, fontFamily, interactive) {
7995
8201
  }
7996
8202
  }
7997
8203
  function ChartPresenceLayer({ presence }) {
7998
- const { actors } = (0, import_react60.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
7999
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("g", { "data-chart-presence": "", pointerEvents: "none", children: actors.map((a) => /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("g", { transform: `translate(${a.x} ${a.y})`, "data-actor": a.id, children: [
8000
- /* @__PURE__ */ (0, import_jsx_runtime40.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 }),
8001
- /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("g", { transform: "translate(13 16)", children: [
8002
- /* @__PURE__ */ (0, import_jsx_runtime40.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 } }),
8003
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("text", { x: 6, y: 9, dominantBaseline: "central", style: { fill: "#ffffff", fontSize: 11, fontWeight: 600, fontFamily: "inherit" }, children: a.message ?? a.name })
8204
+ const { actors } = (0, import_react61.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
8205
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("g", { "data-chart-presence": "", pointerEvents: "none", children: actors.map((a) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("g", { transform: `translate(${a.x} ${a.y})`, "data-actor": a.id, children: [
8206
+ /* @__PURE__ */ (0, import_jsx_runtime41.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 }),
8207
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("g", { transform: "translate(13 16)", children: [
8208
+ /* @__PURE__ */ (0, import_jsx_runtime41.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 } }),
8209
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("text", { x: 6, y: 9, dominantBaseline: "central", style: { fill: "#ffffff", fontSize: 11, fontWeight: 600, fontFamily: "inherit" }, children: a.message ?? a.name })
8004
8210
  ] })
8005
8211
  ] }, a.id)) });
8006
8212
  }
8007
8213
  function ChartCanvas({ controller, width = 640, height = 400, responsive = true, theme, editable = true, measureText, emptyMessage, className, presence, sceneRef }) {
8008
8214
  const state = useChartState(controller);
8009
- const wrapper = (0, import_react60.useRef)(null);
8010
- const svg = (0, import_react60.useRef)(null);
8011
- const drag = (0, import_react60.useRef)(null);
8012
- const [measured, setMeasured] = (0, import_react60.useState)(null);
8013
- const [frozen, setFrozen] = (0, import_react60.useState)(null);
8014
- (0, import_react60.useEffect)(() => {
8215
+ const wrapper = (0, import_react61.useRef)(null);
8216
+ const svg = (0, import_react61.useRef)(null);
8217
+ const drag = (0, import_react61.useRef)(null);
8218
+ const [measured, setMeasured] = (0, import_react61.useState)(null);
8219
+ const [frozen, setFrozen] = (0, import_react61.useState)(null);
8220
+ (0, import_react61.useEffect)(() => {
8015
8221
  const el = wrapper.current;
8016
8222
  if (!responsive || !el || typeof ResizeObserver === "undefined") return;
8017
8223
  const observer = new ResizeObserver(([entry]) => {
@@ -8022,8 +8228,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8022
8228
  return () => observer.disconnect();
8023
8229
  }, [responsive]);
8024
8230
  const sceneWidth = responsive && measured || width;
8025
- const fullTheme = (0, import_react60.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
8026
- const scene = (0, import_react60.useMemo)(
8231
+ const fullTheme = (0, import_react61.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
8232
+ const scene = (0, import_react61.useMemo)(
8027
8233
  () => (0, import_chart2.layoutChart)(state.spec, {
8028
8234
  width: sceneWidth,
8029
8235
  height,
@@ -8039,8 +8245,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8039
8245
  [state.spec, state.selection, sceneWidth, height, fullTheme, editable, measureText, emptyMessage, frozen]
8040
8246
  );
8041
8247
  if (sceneRef) sceneRef.current = scene;
8042
- const byKey = (0, import_react60.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
8043
- (0, import_react60.useEffect)(() => () => drag.current?.end(), []);
8248
+ const byKey = (0, import_react61.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
8249
+ (0, import_react61.useEffect)(() => () => drag.current?.end(), []);
8044
8250
  const scenePoint = (e) => (0, import_chart2.chartClientToScene)(scene, svg.current.getBoundingClientRect(), e.clientX, e.clientY);
8045
8251
  const onPointerDown = (e) => {
8046
8252
  if (!editable || e.button !== 0) return;
@@ -8073,7 +8279,7 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8073
8279
  if (editable && (0, import_chart2.handleChartKey)(controller, scene, e)) e.preventDefault();
8074
8280
  };
8075
8281
  const label = state.spec.title || "Chart";
8076
- return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { ref: wrapper, className: `w-full ${className ?? ""}`, "data-chart-canvas": "", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
8282
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { ref: wrapper, className: `w-full ${className ?? ""}`, "data-chart-canvas": "", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
8077
8283
  "svg",
8078
8284
  {
8079
8285
  ref: svg,
@@ -8091,14 +8297,14 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8091
8297
  onKeyDown,
8092
8298
  children: [
8093
8299
  scene.marks.map((m) => renderChartMark(m, scene.theme.fontFamily, editable)),
8094
- presence && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ChartPresenceLayer, { presence })
8300
+ presence && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ChartPresenceLayer, { presence })
8095
8301
  ]
8096
8302
  }
8097
8303
  ) });
8098
8304
  }
8099
8305
 
8100
8306
  // src/chart/ChartDataGrid.tsx
8101
- var import_react61 = require("react");
8307
+ var import_react62 = require("react");
8102
8308
  var import_chart3 = require("@pixerate/editor/chart");
8103
8309
 
8104
8310
  // src/chart/styles.ts
@@ -8111,11 +8317,11 @@ var chartSectionClass = "space-y-2 border-b border-border pb-3 last:border-b-0";
8111
8317
  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";
8112
8318
 
8113
8319
  // src/chart/ChartDataGrid.tsx
8114
- var import_jsx_runtime41 = require("react/jsx-runtime");
8320
+ var import_jsx_runtime42 = require("react/jsx-runtime");
8115
8321
  function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
8116
- const [draft, setDraft] = (0, import_react61.useState)(value);
8117
- const typing = (0, import_react61.useRef)(false);
8118
- (0, import_react61.useEffect)(() => {
8322
+ const [draft, setDraft] = (0, import_react62.useState)(value);
8323
+ const typing = (0, import_react62.useRef)(false);
8324
+ (0, import_react62.useEffect)(() => {
8119
8325
  if (!typing.current) setDraft(value);
8120
8326
  }, [value]);
8121
8327
  const commit = () => {
@@ -8124,7 +8330,7 @@ function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
8124
8330
  if (draft === value) return;
8125
8331
  if (onCommit(draft) === false) setDraft(value);
8126
8332
  };
8127
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8333
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8128
8334
  "input",
8129
8335
  {
8130
8336
  ...rest,
@@ -8159,15 +8365,15 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8159
8365
  e.preventDefault();
8160
8366
  controller.pasteCells(row, column, text);
8161
8367
  };
8162
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
8163
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
8164
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("tr", { children: [
8165
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("th", { className: "border-b border-r border-border px-2 py-1 text-left font-medium text-muted-foreground", children: categoryHeader }),
8368
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
8369
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
8370
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("tr", { children: [
8371
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("th", { className: "border-b border-r border-border px-2 py-1 text-left font-medium text-muted-foreground", children: categoryHeader }),
8166
8372
  spec.series.map((s, si) => {
8167
8373
  const color = (0, import_chart3.chartSeriesColor)(spec, si);
8168
8374
  const selected = selection?.kind === "series" && selection.seriesId === s.id;
8169
- return /* @__PURE__ */ (0, import_jsx_runtime41.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_runtime41.jsxs)("div", { className: "flex items-center gap-1", children: [
8170
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8375
+ return /* @__PURE__ */ (0, import_jsx_runtime42.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_runtime42.jsxs)("div", { className: "flex items-center gap-1", children: [
8376
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8171
8377
  "input",
8172
8378
  {
8173
8379
  type: "color",
@@ -8180,7 +8386,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8180
8386
  className: "h-5 w-5 shrink-0 cursor-pointer rounded border-0 bg-transparent p-0"
8181
8387
  }
8182
8388
  ),
8183
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8389
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8184
8390
  ChartCommitInput,
8185
8391
  {
8186
8392
  value: s.name,
@@ -8190,8 +8396,8 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8190
8396
  className: `${chartInputClass} h-6 min-w-[5rem] border-transparent bg-transparent font-medium ${s.hidden ? "text-muted-foreground line-through" : ""}`
8191
8397
  }
8192
8398
  ),
8193
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
8194
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8399
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
8400
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8195
8401
  "button",
8196
8402
  {
8197
8403
  type: "button",
@@ -8204,16 +8410,16 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8204
8410
  children: s.hidden ? "\u25CB" : "\u25CF"
8205
8411
  }
8206
8412
  ),
8207
- /* @__PURE__ */ (0, import_jsx_runtime41.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" })
8413
+ /* @__PURE__ */ (0, import_jsx_runtime42.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" })
8208
8414
  ] })
8209
8415
  ] }) }, s.id);
8210
8416
  }),
8211
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("th", { className: "w-8 border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Add series", "aria-label": "Add series", "data-action": "add-series", onClick: () => controller.addSeries(), children: "+" }) })
8417
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("th", { className: "w-8 border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Add series", "aria-label": "Add series", "data-action": "add-series", onClick: () => controller.addSeries(), children: "+" }) })
8212
8418
  ] }) }),
8213
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("tbody", { children: spec.categories.map((category, i) => {
8419
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("tbody", { children: spec.categories.map((category, i) => {
8214
8420
  const rowSelected = selection?.kind === "category" && selection.index === i;
8215
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
8216
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("th", { className: "border-b border-r border-border p-0 text-left font-normal", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8421
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
8422
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("th", { className: "border-b border-r border-border p-0 text-left font-normal", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8217
8423
  ChartCommitInput,
8218
8424
  {
8219
8425
  value: category,
@@ -8227,7 +8433,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8227
8433
  spec.series.map((s) => {
8228
8434
  const value = s.values[i];
8229
8435
  const selected = selection?.kind === "point" && selection.seriesId === s.id && selection.index === i;
8230
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("td", { className: `border-b border-r border-border p-0 ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8436
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", { className: `border-b border-r border-border p-0 ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8231
8437
  ChartCommitInput,
8232
8438
  {
8233
8439
  value: value === null || value === void 0 ? "" : String(value),
@@ -8242,38 +8448,38 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8242
8448
  }
8243
8449
  ) }, s.id);
8244
8450
  }),
8245
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("td", { className: "border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete category", "aria-label": `Delete ${category}`, "data-action": "remove-category", onClick: () => controller.removeCategory(i), children: "\xD7" }) })
8451
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("td", { className: "border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete category", "aria-label": `Delete ${category}`, "data-action": "remove-category", onClick: () => controller.removeCategory(i), children: "\xD7" }) })
8246
8452
  ] }, i);
8247
8453
  }) })
8248
8454
  ] }),
8249
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "p-1", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", className: `${chartButtonClass} h-6 border-dashed`, "data-action": "add-category", onClick: () => controller.addCategory(), children: "+ Add category" }) })
8455
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "p-1", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: `${chartButtonClass} h-6 border-dashed`, "data-action": "add-category", onClick: () => controller.addCategory(), children: "+ Add category" }) })
8250
8456
  ] });
8251
8457
  }
8252
8458
 
8253
8459
  // src/chart/ChartInspector.tsx
8254
- var import_react62 = require("react");
8460
+ var import_react63 = require("react");
8255
8461
  var import_chart4 = require("@pixerate/editor/chart");
8256
- var import_jsx_runtime42 = require("react/jsx-runtime");
8462
+ var import_jsx_runtime43 = require("react/jsx-runtime");
8257
8463
  var cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
8258
8464
  function Field({ label, htmlFor, children }) {
8259
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-2", children: [
8260
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
8261
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "min-w-0 flex-1", children })
8465
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-2", children: [
8466
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
8467
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "min-w-0 flex-1", children })
8262
8468
  ] });
8263
8469
  }
8264
8470
  function Toggle({ label, checked, onChange, name }) {
8265
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
8266
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("input", { type: "checkbox", className: "h-3.5 w-3.5 accent-primary", checked, "data-option": name, onChange: (e) => onChange(e.currentTarget.checked) }),
8471
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
8472
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("input", { type: "checkbox", className: "h-3.5 w-3.5 accent-primary", checked, "data-option": name, onChange: (e) => onChange(e.currentTarget.checked) }),
8267
8473
  label
8268
8474
  ] });
8269
8475
  }
8270
8476
  function Select({ id, value, options, onChange, name, labels }) {
8271
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("select", { id, className: chartInputClass, value, "data-option": name, onChange: (e) => onChange(e.currentTarget.value), children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: o, children: labels?.[o] ?? cap(o) }, o)) });
8477
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("select", { id, className: chartInputClass, value, "data-option": name, onChange: (e) => onChange(e.currentTarget.value), children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: o, children: labels?.[o] ?? cap(o) }, o)) });
8272
8478
  }
8273
8479
  function AxisSection({ controller, axis, value, idBase, horizontal, numeric = false, scales = false }) {
8274
8480
  const set = (patch) => controller.setAxis(axis, patch);
8275
8481
  const setFormat = (patch) => set({ format: { ...value.format, ...patch } });
8276
- const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8482
+ const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8277
8483
  ChartCommitInput,
8278
8484
  {
8279
8485
  id: `${idBase}-${axis}-${key2}`,
@@ -8288,26 +8494,26 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
8288
8494
  const name = axis === "x" ? numeric ? "X axis" : "Category axis" : axis === "y" ? "Value axis" : "Secondary axis";
8289
8495
  const valueAxis = axis !== "x" || numeric;
8290
8496
  const key = axis === "y2" ? "yAxis2" : `${axis}Axis`;
8291
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
8292
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between", children: [
8293
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
8497
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
8498
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center justify-between", children: [
8499
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
8294
8500
  name,
8295
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
8501
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
8296
8502
  "(",
8297
8503
  axis === "x" ? horizontal ? "left" : "bottom" : axis === "y2" ? horizontal ? "top" : "right" : horizontal ? "bottom" : "left",
8298
8504
  ")"
8299
8505
  ] })
8300
8506
  ] }),
8301
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
8507
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
8302
8508
  ] }),
8303
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Title", htmlFor: `${idBase}-${axis}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-title`, value: value.title, "data-option": `${axis}Axis.title`, className: chartInputClass, onCommit: (title) => void set({ title }) }) }),
8304
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
8305
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
8306
- axis === "x" && !numeric && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Dates", name: "xAxis.kind", checked: value.kind === "date", onChange: (dates) => set({ kind: dates ? "date" : void 0 }) }),
8307
- scales && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
8308
- scales && valueAxis && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Log scale", name: `${key}.scale`, checked: value.scale === "log", onChange: (log) => set({ scale: log ? "log" : "linear" }) })
8509
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Title", htmlFor: `${idBase}-${axis}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-title`, value: value.title, "data-option": `${axis}Axis.title`, className: chartInputClass, onCommit: (title) => void set({ title }) }) }),
8510
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
8511
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
8512
+ axis === "x" && !numeric && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Dates", name: "xAxis.kind", checked: value.kind === "date", onChange: (dates) => set({ kind: dates ? "date" : void 0 }) }),
8513
+ scales && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
8514
+ scales && valueAxis && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Log scale", name: `${key}.scale`, checked: value.scale === "log", onChange: (log) => set({ scale: log ? "log" : "linear" }) })
8309
8515
  ] }),
8310
- scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Log base", htmlFor: `${idBase}-${axis}-log-base`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8516
+ scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Log base", htmlFor: `${idBase}-${axis}-log-base`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8311
8517
  ChartCommitInput,
8312
8518
  {
8313
8519
  id: `${idBase}-${axis}-log-base`,
@@ -8318,7 +8524,7 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
8318
8524
  onCommit: (text) => set({ logBase: text.trim() === "" ? void 0 : Number(text) }).ok
8319
8525
  }
8320
8526
  ) }),
8321
- valueAxis && value.scale !== "log" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Step", htmlFor: `${idBase}-${axis}-step`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8527
+ valueAxis && value.scale !== "log" && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Step", htmlFor: `${idBase}-${axis}-step`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8322
8528
  ChartCommitInput,
8323
8529
  {
8324
8530
  id: `${idBase}-${axis}-step`,
@@ -8330,14 +8536,14 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
8330
8536
  onCommit: (text) => set({ step: text.trim() === "" ? null : Number(text) }).ok
8331
8537
  }
8332
8538
  ) }),
8333
- valueAxis && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
8334
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex gap-1", children: [
8539
+ valueAxis && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
8540
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex gap-1", children: [
8335
8541
  bound("min"),
8336
8542
  bound("max")
8337
8543
  ] }) }),
8338
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Format", htmlFor: `${idBase}-${axis}-format`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex gap-1", children: [
8339
- /* @__PURE__ */ (0, import_jsx_runtime42.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 }) }),
8340
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8544
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Format", htmlFor: `${idBase}-${axis}-format`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex gap-1", children: [
8545
+ /* @__PURE__ */ (0, import_jsx_runtime43.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 }) }),
8546
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8341
8547
  ChartCommitInput,
8342
8548
  {
8343
8549
  value: value.format.decimals === void 0 ? "" : String(value.format.decimals),
@@ -8356,8 +8562,8 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
8356
8562
  }
8357
8563
  )
8358
8564
  ] }) }),
8359
- value.format.style === "currency" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Currency", htmlFor: `${idBase}-${axis}-currency`, children: /* @__PURE__ */ (0, import_jsx_runtime42.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() }) }) }),
8360
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8565
+ value.format.style === "currency" && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Currency", htmlFor: `${idBase}-${axis}-currency`, children: /* @__PURE__ */ (0, import_jsx_runtime43.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() }) }) }),
8566
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8361
8567
  ChartCommitInput,
8362
8568
  {
8363
8569
  id: `${idBase}-${axis}-code`,
@@ -8383,15 +8589,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
8383
8589
  const values = which === "xErrorBars" ? series.x ?? [] : series.values;
8384
8590
  const set = (next) => controller.updateSeries(series.id, { [which]: next });
8385
8591
  const patch = (p) => bars && set({ ...bars, ...p });
8386
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
8387
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: which === "errorBars" ? "Error bars" : "X error bars", htmlFor: `${id}-type`, children: /* @__PURE__ */ (0, import_jsx_runtime42.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: [
8388
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "None" }),
8389
- import_chart4.CHART_ERROR_BAR_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: t, children: import_chart4.CHART_ERROR_BAR_LABELS[t] }, t))
8592
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
8593
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: which === "errorBars" ? "Error bars" : "X error bars", htmlFor: `${id}-type`, children: /* @__PURE__ */ (0, import_jsx_runtime43.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: [
8594
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: "", children: "None" }),
8595
+ import_chart4.CHART_ERROR_BAR_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: t, children: import_chart4.CHART_ERROR_BAR_LABELS[t] }, t))
8390
8596
  ] }) }),
8391
- bars && (bars.type === "fixed" || bars.type === "percent" || bars.type === "stddev") && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: bars.type === "percent" ? "Percent" : bars.type === "stddev" ? "Deviations" : "Amount", htmlFor: `${id}-value`, children: /* @__PURE__ */ (0, import_jsx_runtime42.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 }) }),
8392
- bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
8393
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Plus", htmlFor: `${id}-plus`, children: /* @__PURE__ */ (0, import_jsx_runtime42.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 }) }),
8394
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8597
+ bars && (bars.type === "fixed" || bars.type === "percent" || bars.type === "stddev") && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: bars.type === "percent" ? "Percent" : bars.type === "stddev" ? "Deviations" : "Amount", htmlFor: `${id}-value`, children: /* @__PURE__ */ (0, import_jsx_runtime43.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 }) }),
8598
+ bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
8599
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Plus", htmlFor: `${id}-plus`, children: /* @__PURE__ */ (0, import_jsx_runtime43.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 }) }),
8600
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8395
8601
  ChartCommitInput,
8396
8602
  {
8397
8603
  id: `${id}-minus`,
@@ -8408,15 +8614,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
8408
8614
  }
8409
8615
  ) })
8410
8616
  ] }),
8411
- bars && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-2", children: [
8412
- /* @__PURE__ */ (0, import_jsx_runtime42.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_runtime42.jsx)("option", { value: d, children: d === "both" ? "Both ways" : d === "plus" ? "Plus only" : "Minus only" }, d)) }),
8413
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
8617
+ bars && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-2", children: [
8618
+ /* @__PURE__ */ (0, import_jsx_runtime43.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_runtime43.jsx)("option", { value: d, children: d === "both" ? "Both ways" : d === "plus" ? "Plus only" : "Minus only" }, d)) }),
8619
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
8414
8620
  ] })
8415
8621
  ] });
8416
8622
  }
8417
8623
  function ChartInspector({ controller, sections, className }) {
8418
8624
  const { spec, selectedSeries } = useChartState(controller);
8419
- const idBase = (0, import_react62.useId)();
8625
+ const idBase = (0, import_react63.useId)();
8420
8626
  const show = (section) => !sections || sections.includes(section);
8421
8627
  const cartesian = (0, import_chart4.isCartesianChart)(spec.type);
8422
8628
  const family = (0, import_chart4.chartFamily)(spec);
@@ -8428,29 +8634,29 @@ function ChartInspector({ controller, sections, className }) {
8428
8634
  const hasLines = cartesian && types.some((t) => t === "line" || t === "area");
8429
8635
  const seriesIndex = selectedSeries ? spec.series.findIndex((s) => s.id === selectedSeries.id) : -1;
8430
8636
  const scales = family === "cartesian" || family === "xy";
8431
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
8432
- show("type") && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: chartSectionClass, "data-section": "type", children: /* @__PURE__ */ (0, import_jsx_runtime42.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_runtime42.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)) }) }),
8433
- show("style") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
8434
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Layout", htmlFor: `${idBase}-layout`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("select", { id: `${idBase}-layout`, className: chartInputClass, value: "", "data-option": "preset.layout", onChange: (e) => e.currentTarget.value && controller.applyPreset({ layout: e.currentTarget.value }), children: [
8435
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Quick layout\u2026" }),
8436
- import_chart4.CHART_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: p.id, title: p.description, children: p.label }, p.id))
8637
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
8638
+ show("type") && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: chartSectionClass, "data-section": "type", children: /* @__PURE__ */ (0, import_jsx_runtime43.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_runtime43.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)) }) }),
8639
+ show("style") && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
8640
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Layout", htmlFor: `${idBase}-layout`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("select", { id: `${idBase}-layout`, className: chartInputClass, value: "", "data-option": "preset.layout", onChange: (e) => e.currentTarget.value && controller.applyPreset({ layout: e.currentTarget.value }), children: [
8641
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: "", children: "Quick layout\u2026" }),
8642
+ import_chart4.CHART_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: p.id, title: p.description, children: p.label }, p.id))
8437
8643
  ] }) }),
8438
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Colours", htmlFor: `${idBase}-colors`, children: /* @__PURE__ */ (0, import_jsx_runtime42.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: [
8439
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Custom" }),
8440
- import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: c.id, title: c.description, children: c.label }, c.id))
8644
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Colours", htmlFor: `${idBase}-colors`, children: /* @__PURE__ */ (0, import_jsx_runtime43.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: [
8645
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: "", children: "Custom" }),
8646
+ import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: c.id, title: c.description, children: c.label }, c.id))
8441
8647
  ] }) }),
8442
- !colorCheck.ok && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-[11px] leading-snug text-amber-600 dark:text-amber-400", "data-chart-color-warning": "", children: colorCheck.issues[0] }),
8443
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
8648
+ !colorCheck.ok && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-[11px] leading-snug text-amber-600 dark:text-amber-400", "data-chart-color-warning": "", children: colorCheck.issues[0] }),
8649
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
8444
8650
  ] }),
8445
- show("titles") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
8446
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Title", htmlFor: `${idBase}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${idBase}-title`, value: spec.title, "data-option": "title", className: chartInputClass, onCommit: (title) => void controller.setTitle(title) }) }),
8447
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Subtitle", htmlFor: `${idBase}-subtitle`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${idBase}-subtitle`, value: spec.subtitle, "data-option": "subtitle", className: chartInputClass, onCommit: (subtitle) => void controller.setSubtitle(subtitle) }) })
8651
+ show("titles") && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
8652
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Title", htmlFor: `${idBase}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ChartCommitInput, { id: `${idBase}-title`, value: spec.title, "data-option": "title", className: chartInputClass, onCommit: (title) => void controller.setTitle(title) }) }),
8653
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Subtitle", htmlFor: `${idBase}-subtitle`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ChartCommitInput, { id: `${idBase}-subtitle`, value: spec.subtitle, "data-option": "subtitle", className: chartInputClass, onCommit: (subtitle) => void controller.setSubtitle(subtitle) }) })
8448
8654
  ] }),
8449
- show("options") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
8450
- cartesian && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Stacking", htmlFor: `${idBase}-stacking`, children: /* @__PURE__ */ (0, import_jsx_runtime42.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 }) }) }),
8451
- hasBars && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Bars", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: ["vertical", "horizontal"].map((o) => /* @__PURE__ */ (0, import_jsx_runtime42.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)) }) }),
8452
- hasLines && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Lines", htmlFor: `${idBase}-curve`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Select, { id: `${idBase}-curve`, name: "curve", value: spec.curve, options: import_chart4.CHART_CURVES, onChange: (curve) => controller.update({ curve }) }) }),
8453
- spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8655
+ show("options") && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
8656
+ cartesian && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Stacking", htmlFor: `${idBase}-stacking`, children: /* @__PURE__ */ (0, import_jsx_runtime43.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 }) }) }),
8657
+ hasBars && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Bars", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: ["vertical", "horizontal"].map((o) => /* @__PURE__ */ (0, import_jsx_runtime43.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)) }) }),
8658
+ hasLines && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Lines", htmlFor: `${idBase}-curve`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Select, { id: `${idBase}-curve`, name: "curve", value: spec.curve, options: import_chart4.CHART_CURVES, onChange: (curve) => controller.update({ curve }) }) }),
8659
+ spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8454
8660
  "input",
8455
8661
  {
8456
8662
  id: `${idBase}-hole`,
@@ -8466,7 +8672,7 @@ function ChartInspector({ controller, sections, className }) {
8466
8672
  onChange: (e) => controller.update({ innerRadius: Number(e.currentTarget.value) })
8467
8673
  }
8468
8674
  ) }),
8469
- hasBars && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8675
+ hasBars && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8470
8676
  "input",
8471
8677
  {
8472
8678
  id: `${idBase}-gap`,
@@ -8482,31 +8688,31 @@ function ChartInspector({ controller, sections, className }) {
8482
8688
  onChange: (e) => controller.update({ gapWidth: Number(e.currentTarget.value) })
8483
8689
  }
8484
8690
  ) }),
8485
- spec.dataLabels && hasBars && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Labels", htmlFor: `${idBase}-label-position`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Select, { id: `${idBase}-label-position`, name: "labelPosition", value: spec.labelPosition, options: import_chart4.CHART_LABEL_POSITIONS, onChange: (labelPosition) => controller.update({ labelPosition }) }) }),
8486
- spec.type === "histogram" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Bins", htmlFor: `${idBase}-bins`, children: /* @__PURE__ */ (0, import_jsx_runtime42.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 }) }),
8487
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
8488
- spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
8489
- hasLines && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
8490
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
8691
+ spec.dataLabels && hasBars && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Labels", htmlFor: `${idBase}-label-position`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Select, { id: `${idBase}-label-position`, name: "labelPosition", value: spec.labelPosition, options: import_chart4.CHART_LABEL_POSITIONS, onChange: (labelPosition) => controller.update({ labelPosition }) }) }),
8692
+ spec.type === "histogram" && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Bins", htmlFor: `${idBase}-bins`, children: /* @__PURE__ */ (0, import_jsx_runtime43.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 }) }),
8693
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
8694
+ spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
8695
+ hasLines && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
8696
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
8491
8697
  ] })
8492
8698
  ] }),
8493
- show("legend") && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
8494
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between", children: [
8495
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
8496
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
8699
+ show("legend") && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
8700
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center justify-between", children: [
8701
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
8702
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
8497
8703
  ] }),
8498
- spec.legend.show && /* @__PURE__ */ (0, import_jsx_runtime42.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_runtime42.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)) })
8704
+ spec.legend.show && /* @__PURE__ */ (0, import_jsx_runtime43.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_runtime43.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)) })
8499
8705
  ] }),
8500
- show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
8501
- family !== "box" && family !== "histogram" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(AxisSection, { controller, axis: "x", value: spec.xAxis, idBase, horizontal: spec.orientation === "horizontal", numeric: family === "xy", scales }),
8502
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
8503
- usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
8706
+ show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
8707
+ family !== "box" && family !== "histogram" && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(AxisSection, { controller, axis: "x", value: spec.xAxis, idBase, horizontal: spec.orientation === "horizontal", numeric: family === "xy", scales }),
8708
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
8709
+ usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
8504
8710
  ] }),
8505
- show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
8506
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
8507
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Name", htmlFor: `${idBase}-series-name`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartCommitInput, { id: `${idBase}-series-name`, value: selectedSeries.name, "data-option": "series.name", className: chartInputClass, onCommit: (name) => void controller.updateSeries(selectedSeries.id, { name }) }) }),
8508
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Colour", htmlFor: `${idBase}-series-color`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-1", children: [
8509
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8711
+ show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
8712
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
8713
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Name", htmlFor: `${idBase}-series-name`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ChartCommitInput, { id: `${idBase}-series-name`, value: selectedSeries.name, "data-option": "series.name", className: chartInputClass, onCommit: (name) => void controller.updateSeries(selectedSeries.id, { name }) }) }),
8714
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Colour", htmlFor: `${idBase}-series-color`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-1", children: [
8715
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8510
8716
  "input",
8511
8717
  {
8512
8718
  id: `${idBase}-series-color`,
@@ -8519,9 +8725,9 @@ function ChartInspector({ controller, sections, className }) {
8519
8725
  onChange: (e) => controller.updateSeries(selectedSeries.id, { color: e.currentTarget.value })
8520
8726
  }
8521
8727
  ),
8522
- selectedSeries.color && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "reset-color", onClick: () => controller.updateSeries(selectedSeries.id, { color: null }), children: "Palette" })
8728
+ selectedSeries.color && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "reset-color", onClick: () => controller.updateSeries(selectedSeries.id, { color: null }), children: "Palette" })
8523
8729
  ] }) }),
8524
- cartesian && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
8730
+ cartesian && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
8525
8731
  "select",
8526
8732
  {
8527
8733
  id: `${idBase}-series-type`,
@@ -8530,12 +8736,12 @@ function ChartInspector({ controller, sections, className }) {
8530
8736
  "data-option": "series.type",
8531
8737
  onChange: (e) => controller.updateSeries(selectedSeries.id, { type: e.currentTarget.value || null }),
8532
8738
  children: [
8533
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Chart type" }),
8534
- import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: t, children: import_chart4.CHART_TYPE_LABELS[t] }, t))
8739
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: "", children: "Chart type" }),
8740
+ import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: t, children: import_chart4.CHART_TYPE_LABELS[t] }, t))
8535
8741
  ]
8536
8742
  }
8537
8743
  ) }),
8538
- (cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Field, { label: "Marker", htmlFor: `${idBase}-series-marker`, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
8744
+ (cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Marker", htmlFor: `${idBase}-series-marker`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
8539
8745
  "select",
8540
8746
  {
8541
8747
  id: `${idBase}-series-marker`,
@@ -8544,20 +8750,20 @@ function ChartInspector({ controller, sections, className }) {
8544
8750
  "data-option": "series.marker",
8545
8751
  onChange: (e) => controller.updateSeries(selectedSeries.id, { marker: e.currentTarget.value || null }),
8546
8752
  children: [
8547
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Default" }),
8548
- import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: m, children: cap(m) }, m))
8753
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: "", children: "Default" }),
8754
+ import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: m, children: cap(m) }, m))
8549
8755
  ]
8550
8756
  }
8551
8757
  ) }),
8552
- scales && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
8553
- family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
8554
- (0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
8555
- (selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
8556
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
8557
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "R\xB2", name: `trendline.${i}.showR2`, checked: !!t.showR2, onChange: (showR2) => controller.updateTrendline(selectedSeries.id, i, { showR2 }) }),
8558
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: chartButtonClass, "aria-label": "Delete trendline", "data-action": "trendline-delete", onClick: () => controller.removeTrendline(selectedSeries.id, i), children: "\xD7" })
8758
+ scales && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
8759
+ family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
8760
+ (0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
8761
+ (selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
8762
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
8763
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "R\xB2", name: `trendline.${i}.showR2`, checked: !!t.showR2, onChange: (showR2) => controller.updateTrendline(selectedSeries.id, i, { showR2 }) }),
8764
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: chartButtonClass, "aria-label": "Delete trendline", "data-action": "trendline-delete", onClick: () => controller.removeTrendline(selectedSeries.id, i), children: "\xD7" })
8559
8765
  ] }, i)),
8560
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
8766
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
8561
8767
  "select",
8562
8768
  {
8563
8769
  className: chartInputClass,
@@ -8566,32 +8772,32 @@ function ChartInspector({ controller, sections, className }) {
8566
8772
  "data-option": "trendline.add",
8567
8773
  onChange: (e) => e.currentTarget.value && controller.addTrendline(selectedSeries.id, { type: e.currentTarget.value }),
8568
8774
  children: [
8569
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: "", children: "Add trendline\u2026" }),
8570
- import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
8775
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: "", children: "Add trendline\u2026" }),
8776
+ import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
8571
8777
  ]
8572
8778
  }
8573
8779
  )
8574
8780
  ] }),
8575
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
8576
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
8577
- family === "cartesian" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Toggle, { label: "Secondary axis", name: "series.axis", checked: selectedSeries.axis === "secondary", onChange: (secondary) => controller.updateSeries(selectedSeries.id, { axis: secondary ? "secondary" : null }) }),
8578
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "flex-1" }),
8579
- /* @__PURE__ */ (0, import_jsx_runtime42.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" }),
8580
- /* @__PURE__ */ (0, import_jsx_runtime42.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" }),
8581
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", className: `${chartButtonClass} text-destructive`, "data-action": "series-delete", onClick: () => controller.removeSeries(selectedSeries.id), children: "Delete" })
8781
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
8782
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
8783
+ family === "cartesian" && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Secondary axis", name: "series.axis", checked: selectedSeries.axis === "secondary", onChange: (secondary) => controller.updateSeries(selectedSeries.id, { axis: secondary ? "secondary" : null }) }),
8784
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "flex-1" }),
8785
+ /* @__PURE__ */ (0, import_jsx_runtime43.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" }),
8786
+ /* @__PURE__ */ (0, import_jsx_runtime43.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" }),
8787
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: `${chartButtonClass} text-destructive`, "data-action": "series-delete", onClick: () => controller.removeSeries(selectedSeries.id), children: "Delete" })
8582
8788
  ] })
8583
8789
  ] })
8584
8790
  ] });
8585
8791
  }
8586
8792
 
8587
8793
  // src/chart-node/ChartNodeView.tsx
8588
- var import_jsx_runtime43 = require("react/jsx-runtime");
8794
+ var import_jsx_runtime44 = require("react/jsx-runtime");
8589
8795
  function ChartNodeView({ state, theme, showDataGrid = true }) {
8590
8796
  const { controller, editing, editable, selected, width, height, setEditing } = state;
8591
8797
  const open = () => {
8592
8798
  if (editable && !editing) setEditing(true);
8593
8799
  };
8594
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
8800
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
8595
8801
  "div",
8596
8802
  {
8597
8803
  className: `not-prose my-2 rounded-md border bg-background p-1 ${selected ? "border-primary ring-1 ring-primary" : "border-border"}`,
@@ -8604,24 +8810,24 @@ function ChartNodeView({ state, theme, showDataGrid = true }) {
8604
8810
  }
8605
8811
  },
8606
8812
  children: [
8607
- editing && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "mb-1 flex items-center justify-between gap-2 px-1", "data-chart-node-toolbar": "", children: [
8608
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
8609
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
8813
+ editing && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "mb-1 flex items-center justify-between gap-2 px-1", "data-chart-node-toolbar": "", children: [
8814
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
8815
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
8610
8816
  ] }),
8611
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8817
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8612
8818
  "div",
8613
8819
  {
8614
8820
  className: editable && !editing ? "cursor-pointer" : void 0,
8615
8821
  onClick: open,
8616
8822
  title: editable && !editing ? "Click to edit the chart" : void 0,
8617
8823
  "data-chart-node-canvas": "",
8618
- children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
8824
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
8619
8825
  }
8620
8826
  ),
8621
8827
  editing && // Wraps by the document's width, not the viewport's: side by side when there is room.
8622
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
8623
- showDataGrid && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "min-w-0 flex-[1_1_20rem] overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ChartDataGrid, { controller }) }),
8624
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(ChartInspector, { controller, className: "max-h-96 min-w-0 flex-[1_1_16rem] overflow-y-auto rounded-md border border-border p-3" })
8828
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
8829
+ showDataGrid && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "min-w-0 flex-[1_1_20rem] overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartDataGrid, { controller }) }),
8830
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartInspector, { controller, className: "max-h-96 min-w-0 flex-[1_1_16rem] overflow-y-auto rounded-md border border-border p-3" })
8625
8831
  ] })
8626
8832
  ]
8627
8833
  }
@@ -8639,7 +8845,7 @@ function createReactChartNodeView(options = {}) {
8639
8845
  scheduled = true;
8640
8846
  queueMicrotask(() => {
8641
8847
  scheduled = false;
8642
- if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Component, { ...props, state: latest }));
8848
+ if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Component, { ...props, state: latest }));
8643
8849
  });
8644
8850
  };
8645
8851
  schedule();
@@ -8680,6 +8886,7 @@ function createReactChartNodeView(options = {}) {
8680
8886
  ImageEditor,
8681
8887
  InsertTableGrid,
8682
8888
  JobProgress,
8889
+ LayerEffectsPanel,
8683
8890
  LayersPanel,
8684
8891
  MergePreview,
8685
8892
  NameManager,