@pixerate/editor-react 0.64.0 → 0.65.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
@@ -46,6 +46,7 @@ __export(src_exports, {
46
46
  ExportDocxButton: () => ExportDocxButton,
47
47
  FindReplaceBar: () => FindReplaceBar,
48
48
  FormulaHints: () => FormulaHints,
49
+ FreeTransformOptionsBar: () => FreeTransformOptionsBar,
49
50
  GenerationHistory: () => GenerationHistory,
50
51
  GenerationSettings: () => GenerationSettings,
51
52
  Histogram: () => Histogram,
@@ -3784,8 +3785,8 @@ function useImageEditor(options = {}) {
3784
3785
  }
3785
3786
 
3786
3787
  // src/image-editor/ImageEditor.tsx
3787
- var import_react43 = __toESM(require("react"), 1);
3788
- var import_image_editor11 = require("@pixerate/editor/image-editor");
3788
+ var import_react44 = __toESM(require("react"), 1);
3789
+ var import_image_editor12 = require("@pixerate/editor/image-editor");
3789
3790
 
3790
3791
  // src/image-editor/ControlSlider.tsx
3791
3792
  var import_image_editor2 = require("@pixerate/editor/image-editor");
@@ -4704,6 +4705,22 @@ var LayersPanel = ({ controller, thumbnailSize = 32, psd = true, psdFileName = "
4704
4705
  children: (0, import_image_editor7.layerBadge)(layer)
4705
4706
  }
4706
4707
  ),
4708
+ layer.mask && !layer.mask.source && layer.type === "pixel" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4709
+ "button",
4710
+ {
4711
+ type: "button",
4712
+ "aria-label": `${layer.mask.linked === false ? "Link" : "Unlink"} ${row.label} mask`,
4713
+ "aria-pressed": layer.mask.linked !== false,
4714
+ title: layer.mask.linked === false ? "Mask unlinked: it stays put when the layer moves or transforms. Click to link." : "Mask linked: it moves with the layer. Click to unlink.",
4715
+ "data-testid": "layer-mask-link",
4716
+ className: `shrink-0 text-[10px] leading-none ${layer.mask.linked === false ? "text-slate-600" : "text-slate-300"}`,
4717
+ onClick: (e) => {
4718
+ e.stopPropagation();
4719
+ attempt(() => controller.setLayerMaskProps(layer.id, { linked: layer.mask.linked === false }));
4720
+ },
4721
+ children: layer.mask.linked === false ? "\u26D3\uFE0E\u0338" : "\u26D3\uFE0E"
4722
+ }
4723
+ ),
4707
4724
  layer.mask && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
4708
4725
  Thumbnail,
4709
4726
  {
@@ -5215,8 +5232,83 @@ var RefineEdgePanel = ({ controller, selection, layers, className = "" }) => {
5215
5232
  ] });
5216
5233
  };
5217
5234
 
5218
- // src/image-editor/ImageEditor.tsx
5235
+ // src/image-editor/FreeTransformOptionsBar.tsx
5236
+ var import_react43 = require("react");
5237
+ var import_image_editor11 = require("@pixerate/editor/image-editor");
5219
5238
  var import_jsx_runtime26 = require("react/jsx-runtime");
5239
+ var chip2 = (on) => `px-2 py-1 rounded text-[11px] ${on ? "bg-indigo-600 text-white" : "bg-slate-800 text-slate-300 hover:text-white"}`;
5240
+ var round = (v, unit) => unit === "px" ? Math.round(v * 10) / 10 : Math.round(v * 100) / 100;
5241
+ var FreeTransformOptionsBar = ({ tool, className }) => {
5242
+ const [, setTick] = (0, import_react43.useState)(0);
5243
+ (0, import_react43.useEffect)(() => tool.subscribe(() => setTick((n) => n + 1)), [tool]);
5244
+ const bar = tool.bar();
5245
+ if (!tool.active || !bar) return null;
5246
+ const apply = (field, raw) => {
5247
+ const v = Number(raw);
5248
+ if (raw.trim() !== "" && Number.isFinite(v) && Math.abs(v - bar[field]) > 1e-9) tool.setField(field, v);
5249
+ };
5250
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: `flex flex-wrap items-center gap-2 text-xs text-slate-200 ${className ?? ""}`, "data-testid": "free-transform-options", role: "toolbar", "aria-label": "Free Transform options", children: [
5251
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex gap-1", role: "group", "aria-label": "Transform mode", children: import_image_editor11.FREE_TRANSFORM_MODE_OPTIONS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", title: m.title, "aria-pressed": tool.mode === m.id, className: chip2(tool.mode === m.id), onClick: () => tool.setMode(m.id), children: m.label }, m.id)) }),
5252
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "grid grid-cols-3 gap-px", role: "group", "aria-label": "Reference point", children: import_image_editor11.TRANSFORM_ANCHORS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", "aria-label": `Reference point ${a}`, title: `Reference point: ${a}`, className: "h-2.5 w-2.5 rounded-sm bg-slate-700 hover:bg-indigo-500", onClick: () => tool.setReference(a) }, a)) }),
5253
+ import_image_editor11.FREE_TRANSFORM_FIELDS.map((f) => /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", title: f.title, children: [
5254
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: f.label }),
5255
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5256
+ "input",
5257
+ {
5258
+ type: "number",
5259
+ "aria-label": f.title,
5260
+ defaultValue: round(bar[f.id], f.unit),
5261
+ disabled: !bar.affine,
5262
+ step: f.unit === "px" ? 1 : 0.1,
5263
+ className: "w-16 rounded border border-slate-700 bg-slate-900 px-1 py-0.5 text-right disabled:opacity-40",
5264
+ onBlur: (e) => apply(f.id, e.currentTarget.value),
5265
+ onKeyDown: (e) => {
5266
+ if (e.key === "Enter") {
5267
+ e.preventDefault();
5268
+ e.stopPropagation();
5269
+ apply(f.id, e.currentTarget.value);
5270
+ }
5271
+ }
5272
+ },
5273
+ `${f.id}:${round(bar[f.id], f.unit)}`
5274
+ ),
5275
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-500", children: f.unit }),
5276
+ f.id === "scaleX" && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5277
+ "button",
5278
+ {
5279
+ type: "button",
5280
+ "aria-label": "Keep width and height proportional",
5281
+ "aria-pressed": tool.proportional,
5282
+ className: chip2(tool.proportional),
5283
+ onClick: () => {
5284
+ tool.proportional = !tool.proportional;
5285
+ setTick((n) => n + 1);
5286
+ },
5287
+ children: "\u26D3\uFE0E"
5288
+ }
5289
+ )
5290
+ ] }, f.id)),
5291
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("label", { className: "flex items-center gap-1", children: [
5292
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "text-slate-400", children: "Interpolation" }),
5293
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5294
+ "select",
5295
+ {
5296
+ "aria-label": "Interpolation",
5297
+ value: tool.interpolation,
5298
+ onChange: (e) => tool.setInterpolation(e.target.value),
5299
+ className: "rounded border border-slate-700 bg-slate-900 px-1 py-0.5",
5300
+ children: import_image_editor11.INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: i, children: i[0].toUpperCase() + i.slice(1) }, i))
5301
+ }
5302
+ )
5303
+ ] }),
5304
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", title: "Commit (Enter)", className: "px-2 py-1 rounded bg-emerald-600 text-white hover:bg-emerald-500", onClick: () => tool.commit(), children: "Commit" }),
5305
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", title: "Cancel (Esc)", className: chip2(false), onClick: () => tool.cancel(), children: "Cancel" }),
5306
+ tool.error && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { role: "alert", className: "text-rose-400", children: tool.error })
5307
+ ] });
5308
+ };
5309
+
5310
+ // src/image-editor/ImageEditor.tsx
5311
+ var import_jsx_runtime27 = require("react/jsx-runtime");
5220
5312
  var ImageEditor = ({
5221
5313
  editor: externalEditor,
5222
5314
  src,
@@ -5231,35 +5323,47 @@ var ImageEditor = ({
5231
5323
  const internalEditor = useImageEditor({ image: src });
5232
5324
  const editor = externalEditor || internalEditor;
5233
5325
  const { state, controller } = editor;
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);
5326
+ const legacyProcess = (0, import_image_editor12.normalizeProcessVersion)(state.adjustments.process) < import_image_editor12.LATEST_PROCESS_VERSION;
5327
+ const canvasRef = (0, import_react44.useRef)(null);
5328
+ const containerRef = (0, import_react44.useRef)(null);
5329
+ const [activeTab, setActiveTab] = (0, import_react44.useState)("crop");
5330
+ const [activeCropRatio, setActiveCropRatio] = (0, import_react44.useState)(null);
5331
+ const [selectionOptions, setSelectionOptions] = (0, import_react44.useState)(import_image_editor12.DEFAULT_SELECTION_TOOL_OPTIONS);
5332
+ const selectionOptionsRef = (0, import_react44.useRef)(selectionOptions);
5241
5333
  selectionOptionsRef.current = selectionOptions;
5242
- const selectionGestureRef = (0, import_react43.useRef)(null);
5334
+ const selectionGestureRef = (0, import_react44.useRef)(null);
5243
5335
  if (!selectionGestureRef.current || selectionGestureRef.current.controller !== controller) {
5244
- selectionGestureRef.current = new import_image_editor11.SelectionGesture(controller, () => selectionOptionsRef.current);
5336
+ selectionGestureRef.current = new import_image_editor12.SelectionGesture(controller, () => selectionOptionsRef.current);
5245
5337
  }
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);
5338
+ const selectionDraftRef = (0, import_react44.useRef)(null);
5339
+ const [selectionError, setSelectionError] = (0, import_react44.useState)(null);
5340
+ const paintGestureRef = (0, import_react44.useRef)(null);
5341
+ const paintControllerRef = (0, import_react44.useRef)(controller);
5250
5342
  if (!paintGestureRef.current || paintControllerRef.current !== controller) {
5251
- paintGestureRef.current = new import_image_editor11.PaintGesture(controller);
5343
+ paintGestureRef.current = new import_image_editor12.PaintGesture(controller);
5252
5344
  paintControllerRef.current = controller;
5253
5345
  }
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");
5346
+ const brushCursorRef = (0, import_react44.useRef)(null);
5347
+ const [paintError, setPaintError] = (0, import_react44.useState)(null);
5348
+ const transformToolRef = (0, import_react44.useRef)(null);
5349
+ const transformControllerRef = (0, import_react44.useRef)(controller);
5350
+ if (!transformToolRef.current || transformControllerRef.current !== controller) {
5351
+ transformToolRef.current?.cancel();
5352
+ transformToolRef.current = new import_image_editor12.FreeTransformTool(controller, {
5353
+ schedule: (run) => typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame(run) : run()
5354
+ });
5355
+ transformControllerRef.current = controller;
5356
+ }
5357
+ const transformTool = transformToolRef.current;
5358
+ const [, setTransformTick] = (0, import_react44.useState)(0);
5359
+ const [transformCursor, setTransformCursor] = (0, import_react44.useState)("default");
5360
+ const [inpaintPrompt, setInpaintPrompt] = (0, import_react44.useState)("");
5361
+ const [inpaintMaskMode, setInpaintMaskMode] = (0, import_react44.useState)("annotations");
5362
+ const [isRemovingBg, setIsRemovingBg] = (0, import_react44.useState)(false);
5363
+ const [isInpainting, setIsInpainting] = (0, import_react44.useState)(false);
5364
+ const [aiError, setAiError] = (0, import_react44.useState)(null);
5365
+ const [aiSuccess, setAiSuccess] = (0, import_react44.useState)(null);
5366
+ const [aiTarget, setAiTarget] = (0, import_react44.useState)("auto");
5263
5367
  const aiOptions = aiTarget === "auto" ? {} : { target: aiTarget };
5264
5368
  const effectiveOnInpaint = onInpaint || aiHooks?.onInpaint;
5265
5369
  const effectiveOnRemoveBg = onRemoveBackground || aiHooks?.onRemoveBackground;
@@ -5322,18 +5426,18 @@ var ImageEditor = ({
5322
5426
  setIsInpainting(false);
5323
5427
  }
5324
5428
  };
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)(
5429
+ const [activeColor, setActiveColor] = (0, import_react44.useState)("#ef4444");
5430
+ const [strokeWidth, setStrokeWidth] = (0, import_react44.useState)(3);
5431
+ const [fontSize, setFontSize] = (0, import_react44.useState)(24);
5432
+ const [textInput, setTextInput] = (0, import_react44.useState)("");
5433
+ const draftAnnotationRef = (0, import_react44.useRef)(null);
5434
+ const draftCropRef = (0, import_react44.useRef)(null);
5435
+ const cropDragInfoRef = (0, import_react44.useRef)(null);
5436
+ const annotationDragInfoRef = (0, import_react44.useRef)(null);
5437
+ const isDrawingRef = (0, import_react44.useRef)(false);
5438
+ const currentPathRef = (0, import_react44.useRef)([]);
5439
+ const dragStartPointRef = (0, import_react44.useRef)(null);
5440
+ const renderCanvas = (0, import_react44.useCallback)(
5337
5441
  async (draftAnnotation, draftCrop) => {
5338
5442
  const canvas = canvasRef.current;
5339
5443
  const container = containerRef.current;
@@ -5349,12 +5453,64 @@ var ImageEditor = ({
5349
5453
  draftAnnotation: draftAnnotation !== void 0 ? draftAnnotation : draftAnnotationRef.current,
5350
5454
  draftCrop: draftCrop !== void 0 ? draftCrop : draftCropRef.current,
5351
5455
  draftSelectionPath: selectionDraftRef.current,
5352
- brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null
5456
+ brushCursor: activeTab === "paint" && brushCursorRef.current && controller.getState().activeTool !== "move" && !transformTool.active ? { ...brushCursorRef.current, diameter: controller.getState().paint.brush.size } : null,
5457
+ freeTransform: transformTool.overlay()
5353
5458
  });
5354
5459
  },
5355
- [controller, activeTab]
5460
+ [controller, activeTab, transformTool]
5356
5461
  );
5357
- (0, import_react43.useEffect)(() => {
5462
+ (0, import_react44.useEffect)(() => transformTool.subscribe(() => {
5463
+ setTransformTick((n) => n + 1);
5464
+ void renderCanvas();
5465
+ }), [transformTool, renderCanvas]);
5466
+ const transformPoint = (e) => {
5467
+ const canvas = canvasRef.current;
5468
+ const rect = canvas.getBoundingClientRect();
5469
+ const sx = rect.width > 0 ? canvas.width / rect.width : 1;
5470
+ const sy = rect.height > 0 ? canvas.height / rect.height : 1;
5471
+ const s = controller.getState();
5472
+ const cropping = activeTab === "crop";
5473
+ const projection = (0, import_image_editor12.getViewportProjection)(s, canvas.width, canvas.height, cropping);
5474
+ const pt = (0, import_image_editor12.canvasToImagePoint)({ x: (e.clientX - rect.left) * sx, y: (e.clientY - rect.top) * sy }, s, canvas.width, canvas.height, cropping);
5475
+ transformTool.setView(projection.scale);
5476
+ return { pt, tolerance: 6 / (projection.scale || 1) };
5477
+ };
5478
+ const handleTransformPointerDown = (e) => {
5479
+ if (!transformTool.active) return false;
5480
+ if (e.button !== 0) return true;
5481
+ e.preventDefault();
5482
+ try {
5483
+ e.currentTarget.setPointerCapture?.(e.pointerId);
5484
+ } catch {
5485
+ }
5486
+ const { pt, tolerance } = transformPoint(e);
5487
+ transformTool.down(pt, tolerance);
5488
+ return true;
5489
+ };
5490
+ const handleTransformPointerMove = (e) => {
5491
+ if (!transformTool.active) return false;
5492
+ const { pt, tolerance } = transformPoint(e);
5493
+ if (e.buttons & 1) transformTool.move(pt, e);
5494
+ else {
5495
+ const over = transformTool.hit(pt, tolerance);
5496
+ setTransformCursor(transformTool.cursor(over));
5497
+ }
5498
+ return true;
5499
+ };
5500
+ const handleTransformPointerUp = () => {
5501
+ if (!transformTool.active) return false;
5502
+ transformTool.up();
5503
+ return true;
5504
+ };
5505
+ (0, import_react44.useEffect)(() => {
5506
+ if (typeof window === "undefined") return;
5507
+ const onKey = (e) => {
5508
+ if (transformTool.key(e)) e.preventDefault();
5509
+ };
5510
+ window.addEventListener("keydown", onKey);
5511
+ return () => window.removeEventListener("keydown", onKey);
5512
+ }, [transformTool]);
5513
+ (0, import_react44.useEffect)(() => {
5358
5514
  const raf = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : (cb) => setTimeout(cb, 0);
5359
5515
  const caf = typeof cancelAnimationFrame !== "undefined" ? cancelAnimationFrame : (id) => clearTimeout(id);
5360
5516
  const animId = raf(() => {
@@ -5362,12 +5518,12 @@ var ImageEditor = ({
5362
5518
  });
5363
5519
  return () => caf(animId);
5364
5520
  }, [renderCanvas, state]);
5365
- (0, import_react43.useEffect)(() => {
5521
+ (0, import_react44.useEffect)(() => {
5366
5522
  if (activeTab === "crop" && editor.state.activeTool !== "crop") {
5367
5523
  editor.setTool("crop");
5368
5524
  }
5369
5525
  }, [activeTab, editor]);
5370
- (0, import_react43.useEffect)(() => {
5526
+ (0, import_react44.useEffect)(() => {
5371
5527
  const container = containerRef.current;
5372
5528
  if (!container) return;
5373
5529
  if (typeof ResizeObserver !== "undefined") {
@@ -5403,11 +5559,12 @@ var ImageEditor = ({
5403
5559
  const sy = rect.height > 0 ? canvas.height / rect.height : 1;
5404
5560
  const s = controller.getState();
5405
5561
  return list.map((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)
5562
+ ...(0, import_image_editor12.canvasToImagePoint)({ x: (ev.clientX - rect.left) * sx, y: (ev.clientY - rect.top) * sy }, s, canvas.width, canvas.height, false),
5563
+ pressure: (0, import_image_editor12.pointerPressure)(ev)
5408
5564
  }));
5409
5565
  };
5410
5566
  const handlePaintPointerDown = (e) => {
5567
+ if (handleTransformPointerDown(e)) return;
5411
5568
  if (activeTab !== "paint" || e.button !== 0) return;
5412
5569
  e.preventDefault();
5413
5570
  try {
@@ -5418,6 +5575,7 @@ var ImageEditor = ({
5418
5575
  setPaintError(paintGestureRef.current.down(first));
5419
5576
  };
5420
5577
  const handlePaintPointerMove = (e) => {
5578
+ if (handleTransformPointerMove(e)) return;
5421
5579
  if (activeTab !== "paint") return;
5422
5580
  const samples = paintSamples(e);
5423
5581
  brushCursorRef.current = samples[samples.length - 1] ?? null;
@@ -5425,6 +5583,7 @@ var ImageEditor = ({
5425
5583
  else void renderCanvas();
5426
5584
  };
5427
5585
  const handlePaintPointerUp = () => {
5586
+ if (handleTransformPointerUp()) return;
5428
5587
  if (activeTab !== "paint") return;
5429
5588
  const g = paintGestureRef.current;
5430
5589
  if (g.active) {
@@ -5432,21 +5591,21 @@ var ImageEditor = ({
5432
5591
  if (g.error) setPaintError(g.error);
5433
5592
  }
5434
5593
  };
5435
- (0, import_react43.useEffect)(() => {
5594
+ (0, import_react44.useEffect)(() => {
5436
5595
  if (activeTab !== "paint" || typeof window === "undefined") return;
5437
5596
  const onKey = (e) => {
5438
- if ((0, import_image_editor11.handlePaintShortcut)(controller, e)) e.preventDefault();
5597
+ if ((0, import_image_editor12.handlePaintShortcut)(controller, e)) e.preventDefault();
5439
5598
  };
5440
5599
  window.addEventListener("keydown", onKey);
5441
5600
  return () => window.removeEventListener("keydown", onKey);
5442
5601
  }, [activeTab, controller]);
5443
5602
  const handleMouseDown = (e) => {
5444
5603
  const canvas = canvasRef.current;
5445
- if (!canvas) return;
5604
+ if (!canvas || transformTool.active) return;
5446
5605
  const canvasPt = getCanvasEventPoint(e);
5447
5606
  if (activeTab === "select") {
5448
5607
  const gesture = selectionGestureRef.current;
5449
- const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5608
+ const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5450
5609
  void gesture.begin(imgPt, e).then(() => setSelectionError(gesture.error));
5451
5610
  return;
5452
5611
  }
@@ -5457,8 +5616,8 @@ var ImageEditor = ({
5457
5616
  width: state.imageDimensions.width,
5458
5617
  height: state.imageDimensions.height
5459
5618
  };
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);
5619
+ const handle = (0, import_image_editor12.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
5620
+ const startImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
5462
5621
  if (handle) {
5463
5622
  cropDragInfoRef.current = {
5464
5623
  handle,
@@ -5477,12 +5636,12 @@ var ImageEditor = ({
5477
5636
  return;
5478
5637
  }
5479
5638
  if (activeTab === "annotate") {
5480
- const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5639
+ const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5481
5640
  dragStartPointRef.current = imgPt;
5482
5641
  if (state.activeTool === "select") {
5483
5642
  for (let i = state.annotations.length - 1; i >= 0; i--) {
5484
5643
  const ann = state.annotations[i];
5485
- if ((0, import_image_editor11.hitTestAnnotation)(imgPt, ann)) {
5644
+ if ((0, import_image_editor12.hitTestAnnotation)(imgPt, ann)) {
5486
5645
  editor.selectAnnotation(ann.id);
5487
5646
  annotationDragInfoRef.current = {
5488
5647
  annId: ann.id,
@@ -5514,11 +5673,11 @@ var ImageEditor = ({
5514
5673
  };
5515
5674
  const handleMouseMove = (e) => {
5516
5675
  const canvas = canvasRef.current;
5517
- if (!canvas) return;
5676
+ if (!canvas || transformTool.active) return;
5518
5677
  const canvasPt = getCanvasEventPoint(e);
5519
5678
  if (activeTab === "select") {
5520
5679
  const gesture = selectionGestureRef.current;
5521
- if (gesture.active && gesture.move((0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
5680
+ if (gesture.active && gesture.move((0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false))) {
5522
5681
  selectionDraftRef.current = gesture.draftPath;
5523
5682
  renderCanvas();
5524
5683
  }
@@ -5527,7 +5686,7 @@ var ImageEditor = ({
5527
5686
  if (activeTab === "crop") {
5528
5687
  const drag = cropDragInfoRef.current;
5529
5688
  if (drag) {
5530
- const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
5689
+ const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, true);
5531
5690
  let newCrop;
5532
5691
  if (drag.handle === "new") {
5533
5692
  const minX = Math.max(0, Math.min(drag.startImgPt.x, currentImgPt.x));
@@ -5541,7 +5700,7 @@ var ImageEditor = ({
5541
5700
  height: Math.round(Math.max(20, maxY - minY))
5542
5701
  };
5543
5702
  } else {
5544
- newCrop = (0, import_image_editor11.calculateCropDrag)(
5703
+ newCrop = (0, import_image_editor12.calculateCropDrag)(
5545
5704
  drag.startCrop,
5546
5705
  drag.handle,
5547
5706
  drag.startImgPt,
@@ -5561,15 +5720,15 @@ var ImageEditor = ({
5561
5720
  width: state.imageDimensions.width,
5562
5721
  height: state.imageDimensions.height
5563
5722
  };
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);
5723
+ const handle = (0, import_image_editor12.hitTestCrop)(canvasPt, state, canvas.width, canvas.height, 14, activeCrop);
5724
+ canvas.style.cursor = (0, import_image_editor12.getCropCursor)(handle, state.transform);
5566
5725
  }
5567
5726
  return;
5568
5727
  }
5569
5728
  if (activeTab === "annotate") {
5570
5729
  if (annotationDragInfoRef.current) {
5571
5730
  const drag = annotationDragInfoRef.current;
5572
- const currentImgPt2 = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5731
+ const currentImgPt2 = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5573
5732
  const dx = currentImgPt2.x - drag.startImgPt.x;
5574
5733
  const dy = currentImgPt2.y - drag.startImgPt.y;
5575
5734
  editor.updateAnnotation(drag.annId, {
@@ -5581,10 +5740,10 @@ var ImageEditor = ({
5581
5740
  const startPt = dragStartPointRef.current;
5582
5741
  if (!startPt) {
5583
5742
  if (state.activeTool === "select") {
5584
- const imgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5743
+ const imgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5585
5744
  let hovered = false;
5586
5745
  for (let i = state.annotations.length - 1; i >= 0; i--) {
5587
- if ((0, import_image_editor11.hitTestAnnotation)(imgPt, state.annotations[i])) {
5746
+ if ((0, import_image_editor12.hitTestAnnotation)(imgPt, state.annotations[i])) {
5588
5747
  hovered = true;
5589
5748
  break;
5590
5749
  }
@@ -5595,7 +5754,7 @@ var ImageEditor = ({
5595
5754
  }
5596
5755
  return;
5597
5756
  }
5598
- const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5757
+ const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5599
5758
  if (state.activeTool === "pen" && isDrawingRef.current) {
5600
5759
  currentPathRef.current.push(currentImgPt);
5601
5760
  const draft = {
@@ -5670,12 +5829,12 @@ var ImageEditor = ({
5670
5829
  };
5671
5830
  const handleMouseUp = (e) => {
5672
5831
  const canvas = canvasRef.current;
5673
- if (!canvas) return;
5832
+ if (!canvas || transformTool.active) return;
5674
5833
  const canvasPt = getCanvasEventPoint(e);
5675
5834
  if (activeTab === "select") {
5676
5835
  const gesture = selectionGestureRef.current;
5677
5836
  if (gesture.active) {
5678
- gesture.end((0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
5837
+ gesture.end((0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false), e);
5679
5838
  selectionDraftRef.current = null;
5680
5839
  renderCanvas();
5681
5840
  }
@@ -5699,7 +5858,7 @@ var ImageEditor = ({
5699
5858
  }
5700
5859
  const startPt = dragStartPointRef.current;
5701
5860
  if (startPt) {
5702
- const currentImgPt = (0, import_image_editor11.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5861
+ const currentImgPt = (0, import_image_editor12.canvasToImagePoint)(canvasPt, state, canvas.width, canvas.height, false);
5703
5862
  if (state.activeTool === "pen" && isDrawingRef.current) {
5704
5863
  if (currentPathRef.current.length > 1) {
5705
5864
  editor.addAnnotation({
@@ -5795,15 +5954,15 @@ var ImageEditor = ({
5795
5954
  link.click();
5796
5955
  }
5797
5956
  };
5798
- return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
5957
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5799
5958
  "div",
5800
5959
  {
5801
5960
  className: `flex flex-col bg-slate-900 border border-slate-800 rounded-xl overflow-hidden shadow-2xl text-slate-100 ${className}`,
5802
5961
  style,
5803
5962
  children: [
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)(
5963
+ /* @__PURE__ */ (0, import_jsx_runtime27.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: [
5964
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-1 bg-slate-900 p-1 rounded-lg border border-slate-800 text-xs", children: [
5965
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5807
5966
  "button",
5808
5967
  {
5809
5968
  type: "button",
@@ -5815,7 +5974,7 @@ var ImageEditor = ({
5815
5974
  children: "Transform & Crop"
5816
5975
  }
5817
5976
  ),
5818
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5977
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5819
5978
  "button",
5820
5979
  {
5821
5980
  type: "button",
@@ -5827,7 +5986,7 @@ var ImageEditor = ({
5827
5986
  children: "Adjustments"
5828
5987
  }
5829
5988
  ),
5830
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
5989
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5831
5990
  "button",
5832
5991
  {
5833
5992
  type: "button",
@@ -5839,7 +5998,7 @@ var ImageEditor = ({
5839
5998
  children: "Layers"
5840
5999
  }
5841
6000
  ),
5842
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6001
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5843
6002
  "button",
5844
6003
  {
5845
6004
  type: "button",
@@ -5851,7 +6010,7 @@ var ImageEditor = ({
5851
6010
  children: "Paint"
5852
6011
  }
5853
6012
  ),
5854
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6013
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5855
6014
  "button",
5856
6015
  {
5857
6016
  type: "button",
@@ -5863,7 +6022,7 @@ var ImageEditor = ({
5863
6022
  children: "Select & Mask"
5864
6023
  }
5865
6024
  ),
5866
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6025
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5867
6026
  "button",
5868
6027
  {
5869
6028
  type: "button",
@@ -5875,7 +6034,7 @@ var ImageEditor = ({
5875
6034
  children: "Annotations"
5876
6035
  }
5877
6036
  ),
5878
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6037
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5879
6038
  "button",
5880
6039
  {
5881
6040
  type: "button",
@@ -5887,7 +6046,7 @@ var ImageEditor = ({
5887
6046
  children: "Depth Mask"
5888
6047
  }
5889
6048
  ),
5890
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6049
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
5891
6050
  "button",
5892
6051
  {
5893
6052
  type: "button",
@@ -5897,14 +6056,14 @@ var ImageEditor = ({
5897
6056
  },
5898
6057
  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"}`,
5899
6058
  children: [
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" }) }),
6059
+ /* @__PURE__ */ (0, import_jsx_runtime27.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_runtime27.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" }) }),
5901
6060
  "AI Tools"
5902
6061
  ]
5903
6062
  }
5904
6063
  )
5905
6064
  ] }),
5906
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
5907
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6065
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
6066
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5908
6067
  "button",
5909
6068
  {
5910
6069
  type: "button",
@@ -5915,7 +6074,7 @@ var ImageEditor = ({
5915
6074
  children: "\u21A9"
5916
6075
  }
5917
6076
  ),
5918
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6077
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5919
6078
  "button",
5920
6079
  {
5921
6080
  type: "button",
@@ -5926,7 +6085,7 @@ var ImageEditor = ({
5926
6085
  children: "\u21AA"
5927
6086
  }
5928
6087
  ),
5929
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6088
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5930
6089
  "button",
5931
6090
  {
5932
6091
  type: "button",
@@ -5935,8 +6094,8 @@ var ImageEditor = ({
5935
6094
  children: "Reset"
5936
6095
  }
5937
6096
  ),
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)(
6097
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6098
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5940
6099
  "button",
5941
6100
  {
5942
6101
  type: "button",
@@ -5946,11 +6105,11 @@ var ImageEditor = ({
5946
6105
  children: "-"
5947
6106
  }
5948
6107
  ),
5949
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
6108
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "font-mono text-slate-400 w-10 text-center", children: [
5950
6109
  Math.round(state.zoom * 100),
5951
6110
  "%"
5952
6111
  ] }),
5953
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6112
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5954
6113
  "button",
5955
6114
  {
5956
6115
  type: "button",
@@ -5960,8 +6119,8 @@ var ImageEditor = ({
5960
6119
  children: "+"
5961
6120
  }
5962
6121
  ),
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)(
6122
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-4 w-px bg-slate-800 mx-1" }),
6123
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5965
6124
  "button",
5966
6125
  {
5967
6126
  type: "button",
@@ -5972,7 +6131,7 @@ var ImageEditor = ({
5972
6131
  children: "Hold Compare"
5973
6132
  }
5974
6133
  ),
5975
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6134
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5976
6135
  "button",
5977
6136
  {
5978
6137
  type: "button",
@@ -5983,13 +6142,15 @@ var ImageEditor = ({
5983
6142
  )
5984
6143
  ] })
5985
6144
  ] }),
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)(
6145
+ transformTool.active && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(FreeTransformOptionsBar, { tool: transformTool, className: "border-b border-slate-800 bg-slate-900/95 px-4 py-2" }),
6146
+ !transformTool.active && transformTool.error && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { role: "alert", className: "border-b border-rose-900 bg-rose-950/80 px-4 py-1.5 text-xs text-rose-200", children: transformTool.error }),
6147
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col md:flex-row flex-1 min-h-[520px] md:h-[560px]", children: [
6148
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5988
6149
  "div",
5989
6150
  {
5990
6151
  ref: containerRef,
5991
6152
  className: "relative flex-1 h-[360px] md:h-full min-h-[320px] bg-slate-950 overflow-hidden select-none",
5992
- children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6153
+ children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
5993
6154
  "canvas",
5994
6155
  {
5995
6156
  ref: canvasRef,
@@ -6002,16 +6163,17 @@ var ImageEditor = ({
6002
6163
  onPointerUp: handlePaintPointerUp,
6003
6164
  onPointerCancel: () => paintGestureRef.current?.cancel(),
6004
6165
  "data-testid": "image-editor-canvas",
6005
- className: `absolute inset-0 w-full h-full block ${activeTab === "paint" ? "touch-none cursor-crosshair" : ""}`
6166
+ style: transformTool.active ? { cursor: transformCursor } : void 0,
6167
+ className: `absolute inset-0 w-full h-full block ${transformTool.active ? "touch-none" : activeTab === "paint" ? "touch-none cursor-crosshair" : ""}`
6006
6168
  }
6007
6169
  )
6008
6170
  }
6009
6171
  ),
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)(
6172
+ /* @__PURE__ */ (0, import_jsx_runtime27.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: [
6173
+ activeTab === "crop" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6174
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Aspect Ratio Presets" }),
6175
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "grid grid-cols-3 gap-2", children: [
6176
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6015
6177
  "button",
6016
6178
  {
6017
6179
  type: "button",
@@ -6023,7 +6185,7 @@ var ImageEditor = ({
6023
6185
  children: "Freeform"
6024
6186
  }
6025
6187
  ),
6026
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6188
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6027
6189
  "button",
6028
6190
  {
6029
6191
  type: "button",
@@ -6035,7 +6197,7 @@ var ImageEditor = ({
6035
6197
  children: "1:1 Square"
6036
6198
  }
6037
6199
  ),
6038
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6200
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6039
6201
  "button",
6040
6202
  {
6041
6203
  type: "button",
@@ -6047,7 +6209,7 @@ var ImageEditor = ({
6047
6209
  children: "4:3 Standard"
6048
6210
  }
6049
6211
  ),
6050
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6212
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6051
6213
  "button",
6052
6214
  {
6053
6215
  type: "button",
@@ -6059,7 +6221,7 @@ var ImageEditor = ({
6059
6221
  children: "16:9 Wide"
6060
6222
  }
6061
6223
  ),
6062
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6224
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6063
6225
  "button",
6064
6226
  {
6065
6227
  type: "button",
@@ -6071,7 +6233,7 @@ var ImageEditor = ({
6071
6233
  children: "3:2 Photo"
6072
6234
  }
6073
6235
  ),
6074
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6236
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6075
6237
  "button",
6076
6238
  {
6077
6239
  type: "button",
@@ -6084,10 +6246,10 @@ var ImageEditor = ({
6084
6246
  }
6085
6247
  )
6086
6248
  ] }),
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)(
6249
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6250
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Orientation & Flips" }),
6251
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
6252
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6091
6253
  "button",
6092
6254
  {
6093
6255
  type: "button",
@@ -6096,7 +6258,7 @@ var ImageEditor = ({
6096
6258
  children: "Rotate -90\xB0"
6097
6259
  }
6098
6260
  ),
6099
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6261
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6100
6262
  "button",
6101
6263
  {
6102
6264
  type: "button",
@@ -6105,7 +6267,7 @@ var ImageEditor = ({
6105
6267
  children: "Rotate +90\xB0"
6106
6268
  }
6107
6269
  ),
6108
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6270
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6109
6271
  "button",
6110
6272
  {
6111
6273
  type: "button",
@@ -6114,7 +6276,7 @@ var ImageEditor = ({
6114
6276
  children: "Flip Horizontal"
6115
6277
  }
6116
6278
  ),
6117
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6279
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6118
6280
  "button",
6119
6281
  {
6120
6282
  type: "button",
@@ -6125,10 +6287,10 @@ var ImageEditor = ({
6125
6287
  )
6126
6288
  ] })
6127
6289
  ] }),
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)(
6290
+ activeTab === "adjust" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6291
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between", children: [
6292
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Color Adjustments" }),
6293
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6132
6294
  "button",
6133
6295
  {
6134
6296
  type: "button",
@@ -6138,25 +6300,25 @@ var ImageEditor = ({
6138
6300
  }
6139
6301
  )
6140
6302
  ] }),
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)(
6303
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Histogram, { histogram: editor.histogram }),
6304
+ import_image_editor12.IMAGE_ADJUSTMENT_CONTROLS.map((spec) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_react44.default.Fragment, { children: [
6305
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6144
6306
  ControlSlider,
6145
6307
  {
6146
6308
  spec,
6147
- value: (0, import_image_editor11.readAdjustmentControls)(state.adjustments)[spec.id],
6309
+ value: (0, import_image_editor12.readAdjustmentControls)(state.adjustments)[spec.id],
6148
6310
  disabled: spec.requiresProcess !== void 0 && legacyProcess,
6149
6311
  onChange: (v) => editor.setAdjustments({ [spec.id]: v })
6150
6312
  }
6151
6313
  ),
6152
- spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6314
+ spec.id === "tint" && legacyProcess && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6153
6315
  "div",
6154
6316
  {
6155
6317
  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",
6156
6318
  "data-testid": "image-editor-process-notice",
6157
6319
  children: [
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)(
6320
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Legacy rendering (process 1). Tint needs the current process." }),
6321
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6160
6322
  "button",
6161
6323
  {
6162
6324
  type: "button",
@@ -6169,7 +6331,7 @@ var ImageEditor = ({
6169
6331
  }
6170
6332
  )
6171
6333
  ] }, spec.id)),
6172
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6334
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6173
6335
  AdjustmentLayersPanel,
6174
6336
  {
6175
6337
  controller,
@@ -6178,19 +6340,41 @@ var ImageEditor = ({
6178
6340
  }
6179
6341
  ) })
6180
6342
  ] }),
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 })
6343
+ activeTab === "layers" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6344
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Layers" }),
6345
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6346
+ "button",
6347
+ {
6348
+ type: "button",
6349
+ title: "Edit \u203A Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer",
6350
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
6351
+ disabled: transformTool.active,
6352
+ onClick: () => transformTool.begin(),
6353
+ children: "Free Transform"
6354
+ }
6355
+ ),
6356
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(LayersPanel, { controller })
6184
6357
  ] }),
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 }) })
6358
+ activeTab === "paint" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6359
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Paint" }),
6360
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(BrushOptionsBar, { controller }),
6361
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6362
+ "button",
6363
+ {
6364
+ type: "button",
6365
+ title: "Edit \u203A Free Transform (Ctrl/Cmd+T): the selected pixels, or the whole active layer",
6366
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start",
6367
+ disabled: transformTool.active,
6368
+ onClick: () => transformTool.begin(),
6369
+ children: "Free Transform"
6370
+ }
6371
+ ),
6372
+ paintError && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { role: "alert", className: "text-rose-400", "data-testid": "paint-error", children: paintError }),
6373
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "border-t border-slate-700/60 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(LayersPanel, { controller }) })
6190
6374
  ] }),
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)(
6375
+ activeTab === "annotate" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6376
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Draw & Annotate" }),
6377
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "grid grid-cols-3 gap-1.5", children: ["pen", "rect", "circle", "arrow", "line"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6194
6378
  "button",
6195
6379
  {
6196
6380
  type: "button",
@@ -6200,9 +6384,9 @@ var ImageEditor = ({
6200
6384
  },
6201
6385
  t
6202
6386
  )) }),
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)(
6387
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center gap-2 mt-2", children: [
6388
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("label", { className: "text-slate-400", children: "Color:" }),
6389
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6206
6390
  "input",
6207
6391
  {
6208
6392
  type: "color",
@@ -6211,15 +6395,15 @@ var ImageEditor = ({
6211
6395
  className: "w-8 h-8 rounded border border-slate-700 cursor-pointer bg-transparent"
6212
6396
  }
6213
6397
  ),
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: [
6398
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex-1 ml-2", children: [
6399
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex justify-between text-slate-400 mb-0.5", children: [
6400
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Width:" }),
6401
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "font-mono", children: [
6218
6402
  strokeWidth,
6219
6403
  "px"
6220
6404
  ] })
6221
6405
  ] }),
6222
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6406
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6223
6407
  "input",
6224
6408
  {
6225
6409
  type: "range",
@@ -6232,10 +6416,10 @@ var ImageEditor = ({
6232
6416
  )
6233
6417
  ] })
6234
6418
  ] }),
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)(
6419
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6420
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Add Text" }),
6421
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex gap-2", children: [
6422
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6239
6423
  "input",
6240
6424
  {
6241
6425
  type: "text",
@@ -6246,7 +6430,7 @@ var ImageEditor = ({
6246
6430
  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"
6247
6431
  }
6248
6432
  ),
6249
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6433
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6250
6434
  "button",
6251
6435
  {
6252
6436
  type: "button",
@@ -6256,14 +6440,14 @@ var ImageEditor = ({
6256
6440
  }
6257
6441
  )
6258
6442
  ] }),
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: [
6443
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between text-slate-400", children: [
6444
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Font Size:" }),
6445
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "font-mono", children: [
6262
6446
  fontSize,
6263
6447
  "px"
6264
6448
  ] })
6265
6449
  ] }),
6266
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6450
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6267
6451
  "input",
6268
6452
  {
6269
6453
  type: "range",
@@ -6274,14 +6458,14 @@ var ImageEditor = ({
6274
6458
  className: "w-full accent-indigo-500"
6275
6459
  }
6276
6460
  ),
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: [
6461
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "h-px bg-slate-800 my-1" }),
6462
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between", children: [
6463
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "text-slate-400", children: [
6280
6464
  "Layers (",
6281
6465
  state.annotations.length,
6282
6466
  ")"
6283
6467
  ] }),
6284
- state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6468
+ state.selectedAnnotationId && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6285
6469
  "button",
6286
6470
  {
6287
6471
  type: "button",
@@ -6290,7 +6474,7 @@ var ImageEditor = ({
6290
6474
  children: "Delete Selected"
6291
6475
  }
6292
6476
  ),
6293
- state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6477
+ state.annotations.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6294
6478
  "button",
6295
6479
  {
6296
6480
  type: "button",
@@ -6301,10 +6485,10 @@ var ImageEditor = ({
6301
6485
  )
6302
6486
  ] })
6303
6487
  ] }),
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)(
6488
+ activeTab === "depth" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-3 text-xs", children: [
6489
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between", children: [
6490
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px]", children: "Depth Masking" }),
6491
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6308
6492
  "button",
6309
6493
  {
6310
6494
  type: "button",
@@ -6314,8 +6498,8 @@ var ImageEditor = ({
6314
6498
  }
6315
6499
  )
6316
6500
  ] }),
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)(
6501
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300", children: [
6502
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6319
6503
  "input",
6320
6504
  {
6321
6505
  type: "checkbox",
@@ -6324,12 +6508,12 @@ var ImageEditor = ({
6324
6508
  className: "rounded accent-indigo-500"
6325
6509
  }
6326
6510
  ),
6327
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Enable Depth / Alpha Mask" })
6511
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Enable Depth / Alpha Mask" })
6328
6512
  ] }),
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)(
6513
+ state.depthMask.enabled && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6514
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { children: [
6515
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("label", { className: "text-slate-400 block mb-1", children: "Mask Image URL:" }),
6516
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6333
6517
  "input",
6334
6518
  {
6335
6519
  type: "text",
@@ -6340,8 +6524,8 @@ var ImageEditor = ({
6340
6524
  }
6341
6525
  )
6342
6526
  ] }),
6343
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex gap-2", children: [
6344
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6527
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex gap-2", children: [
6528
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6345
6529
  "button",
6346
6530
  {
6347
6531
  type: "button",
@@ -6350,7 +6534,7 @@ var ImageEditor = ({
6350
6534
  children: "Threshold Mode"
6351
6535
  }
6352
6536
  ),
6353
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6537
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6354
6538
  "button",
6355
6539
  {
6356
6540
  type: "button",
@@ -6360,12 +6544,12 @@ var ImageEditor = ({
6360
6544
  }
6361
6545
  )
6362
6546
  ] }),
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] })
6547
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { children: [
6548
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6549
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Depth Start (Lower):" }),
6550
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[0] })
6367
6551
  ] }),
6368
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6552
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6369
6553
  "input",
6370
6554
  {
6371
6555
  type: "range",
@@ -6379,12 +6563,12 @@ var ImageEditor = ({
6379
6563
  }
6380
6564
  )
6381
6565
  ] }),
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] })
6566
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { children: [
6567
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6568
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Depth Stop (Upper):" }),
6569
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-mono", children: state.depthMask.depthRange[1] })
6386
6570
  ] }),
6387
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6571
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6388
6572
  "input",
6389
6573
  {
6390
6574
  type: "range",
@@ -6398,12 +6582,12 @@ var ImageEditor = ({
6398
6582
  }
6399
6583
  )
6400
6584
  ] }),
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 })
6585
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { children: [
6586
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex justify-between text-slate-400 mb-1", children: [
6587
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Softness:" }),
6588
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "font-mono", children: state.depthMask.softness })
6405
6589
  ] }),
6406
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6590
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6407
6591
  "input",
6408
6592
  {
6409
6593
  type: "range",
@@ -6415,8 +6599,8 @@ var ImageEditor = ({
6415
6599
  }
6416
6600
  )
6417
6601
  ] }),
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)(
6602
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer text-slate-300 mt-1", children: [
6603
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6420
6604
  "input",
6421
6605
  {
6422
6606
  type: "checkbox",
@@ -6425,12 +6609,12 @@ var ImageEditor = ({
6425
6609
  className: "rounded accent-indigo-500"
6426
6610
  }
6427
6611
  ),
6428
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "Invert Mask" })
6612
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Invert Mask" })
6429
6613
  ] })
6430
6614
  ] })
6431
6615
  ] }),
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)(
6616
+ activeTab === "select" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6617
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6434
6618
  SelectionOptionsBar,
6435
6619
  {
6436
6620
  controller,
@@ -6440,13 +6624,37 @@ var ImageEditor = ({
6440
6624
  quickMask: Boolean(state.quickMask)
6441
6625
  }
6442
6626
  ),
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 })
6627
+ selectionError && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { role: "alert", className: "text-rose-400", children: selectionError }),
6628
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex gap-1", children: [
6629
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6630
+ "button",
6631
+ {
6632
+ type: "button",
6633
+ title: "Select \u203A Transform Selection: the outline only",
6634
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
6635
+ disabled: transformTool.active,
6636
+ onClick: () => transformTool.begin({ content: "selection-outline" }),
6637
+ children: "Transform Selection"
6638
+ }
6639
+ ),
6640
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6641
+ "button",
6642
+ {
6643
+ type: "button",
6644
+ title: "Edit \u203A Free Transform: the selected pixels of the active layer",
6645
+ className: "px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-300 hover:text-white self-start disabled:opacity-40",
6646
+ disabled: transformTool.active,
6647
+ onClick: () => transformTool.begin({ content: "selection" }),
6648
+ children: "Free Transform Pixels"
6649
+ }
6650
+ )
6651
+ ] }),
6652
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(RefineEdgePanel, { controller, selection: state.selection ?? null, layers: state.adjustments.layers })
6445
6653
  ] }),
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)(
6654
+ activeTab === "ai" && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-4 text-xs", children: [
6655
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("label", { className: "flex items-center justify-between gap-2 text-slate-300", children: [
6656
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: "Results go to" }),
6657
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6450
6658
  "select",
6451
6659
  {
6452
6660
  "aria-label": "AI result target",
@@ -6454,54 +6662,54 @@ var ImageEditor = ({
6454
6662
  onChange: (e) => setAiTarget(e.target.value),
6455
6663
  className: "bg-slate-800 border border-slate-700 rounded px-1.5 py-1",
6456
6664
  children: [
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" })
6665
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: "auto", children: controller.isMultiLayer ? "Auto (new layer)" : "Auto (replace image)" }),
6666
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: "new-layer", children: "New layer / mask" }),
6667
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("option", { value: "replace", children: "Replace image" })
6460
6668
  ]
6461
6669
  }
6462
6670
  )
6463
6671
  ] }),
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" }) }),
6672
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
6673
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between", children: [
6674
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
6675
+ /* @__PURE__ */ (0, import_jsx_runtime27.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_runtime27.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" }) }),
6468
6676
  "Background Removal"
6469
6677
  ] }),
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..." })
6678
+ isRemovingBg && /* @__PURE__ */ (0, import_jsx_runtime27.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..." })
6471
6679
  ] }),
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)(
6680
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Isolate foreground subject with AI alpha transparency segmentation." }),
6681
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6474
6682
  "button",
6475
6683
  {
6476
6684
  type: "button",
6477
6685
  onClick: handleRemoveBackground,
6478
6686
  disabled: isRemovingBg || isInpainting,
6479
6687
  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",
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" }),
6688
+ children: isRemovingBg ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6689
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
6482
6690
  "Removing Background..."
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" }) }),
6691
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6692
+ /* @__PURE__ */ (0, import_jsx_runtime27.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_runtime27.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" }) }),
6485
6693
  "Remove Background"
6486
6694
  ] })
6487
6695
  }
6488
6696
  )
6489
6697
  ] }),
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" })
6698
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "p-3 rounded-lg bg-slate-950/60 border border-slate-800 flex flex-col gap-2.5", children: [
6699
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center justify-between", children: [
6700
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "font-semibold text-slate-200 uppercase tracking-wider text-[11px] flex items-center gap-1.5", children: [
6701
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("svg", { className: "w-3.5 h-3.5 text-purple-400", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
6702
+ /* @__PURE__ */ (0, import_jsx_runtime27.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" }),
6703
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("path", { d: "m14 7 3 3" })
6496
6704
  ] }),
6497
6705
  "Generative Inpainting"
6498
6706
  ] }),
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..." })
6707
+ isInpainting && /* @__PURE__ */ (0, import_jsx_runtime27.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..." })
6500
6708
  ] }),
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)(
6709
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-slate-400 text-[11px] leading-relaxed", children: "Replace, modify, or fill selected regions using prompt-guided generative inpainting." }),
6710
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-1", children: [
6711
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("label", { htmlFor: "ai-inpaint-prompt-react", className: "text-slate-300 text-[11px] font-medium", children: "Prompt" }),
6712
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6505
6713
  "textarea",
6506
6714
  {
6507
6715
  id: "ai-inpaint-prompt-react",
@@ -6513,10 +6721,10 @@ var ImageEditor = ({
6513
6721
  }
6514
6722
  )
6515
6723
  ] }),
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)(
6724
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-1", children: [
6725
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-slate-300 text-[11px] font-medium", children: "Target Mask Region" }),
6726
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "grid grid-cols-2 gap-1.5", children: [
6727
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6520
6728
  "button",
6521
6729
  {
6522
6730
  type: "button",
@@ -6529,7 +6737,7 @@ var ImageEditor = ({
6529
6737
  ]
6530
6738
  }
6531
6739
  ),
6532
- /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
6740
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6533
6741
  "button",
6534
6742
  {
6535
6743
  type: "button",
@@ -6544,25 +6752,25 @@ var ImageEditor = ({
6544
6752
  )
6545
6753
  ] })
6546
6754
  ] }),
6547
- /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
6755
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6548
6756
  "button",
6549
6757
  {
6550
6758
  type: "button",
6551
6759
  onClick: handleInpaint,
6552
6760
  disabled: isInpainting || isRemovingBg || !inpaintPrompt.trim(),
6553
6761
  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",
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" }),
6762
+ children: isInpainting ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6763
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin" }),
6556
6764
  "Generating Inpaint..."
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" }) }),
6765
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
6766
+ /* @__PURE__ */ (0, import_jsx_runtime27.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_runtime27.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" }) }),
6559
6767
  "Apply Inpainting"
6560
6768
  ] })
6561
6769
  }
6562
6770
  )
6563
6771
  ] }),
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 })
6772
+ aiError && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "p-2.5 rounded-lg bg-rose-950/60 border border-rose-800 text-rose-300 text-[11px]", children: aiError }),
6773
+ aiSuccess && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "p-2.5 rounded-lg bg-emerald-950/60 border border-emerald-800 text-emerald-300 text-[11px]", children: aiSuccess })
6566
6774
  ] })
6567
6775
  ] })
6568
6776
  ] })
@@ -6572,7 +6780,7 @@ var ImageEditor = ({
6572
6780
  };
6573
6781
 
6574
6782
  // src/review/useReview.ts
6575
- var import_react44 = require("react");
6783
+ var import_react45 = require("react");
6576
6784
  var import_editor12 = require("@pixerate/editor");
6577
6785
  var EMPTY_COMMENTS = Object.freeze({
6578
6786
  threads: [],
@@ -6591,23 +6799,23 @@ function isCommentStore(value) {
6591
6799
  }
6592
6800
  function useComments(source) {
6593
6801
  const store = isCommentStore(source) ? source : (0, import_editor12.getCommentStore)(source);
6594
- const subscribe = (0, import_react44.useCallback)(
6802
+ const subscribe = (0, import_react45.useCallback)(
6595
6803
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
6596
6804
  [store]
6597
6805
  );
6598
6806
  const getSnapshot = () => store?.getSnapshot() ?? EMPTY_COMMENTS;
6599
- const snapshot = (0, import_react44.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
6600
- return (0, import_react44.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
6807
+ const snapshot = (0, import_react45.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
6808
+ return (0, import_react45.useMemo)(() => ({ ...snapshot, store }), [snapshot, store]);
6601
6809
  }
6602
6810
  function useTrackChanges(editor) {
6603
6811
  const store = (0, import_editor12.getTrackChangesStore)(editor ?? null);
6604
- const subscribe = (0, import_react44.useCallback)(
6812
+ const subscribe = (0, import_react45.useCallback)(
6605
6813
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe,
6606
6814
  [store]
6607
6815
  );
6608
6816
  const getSnapshot = () => store?.getSnapshot() ?? EMPTY_TRACK_CHANGES;
6609
- const snapshot = (0, import_react44.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
6610
- return (0, import_react44.useMemo)(() => {
6817
+ const snapshot = (0, import_react45.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
6818
+ return (0, import_react45.useMemo)(() => {
6611
6819
  const run = (fn) => () => {
6612
6820
  if (editor && !editor.isDestroyed) fn(editor);
6613
6821
  };
@@ -6630,9 +6838,9 @@ function useTrackChanges(editor) {
6630
6838
  }
6631
6839
 
6632
6840
  // src/review/CommentsPanel.tsx
6633
- var import_react45 = require("react");
6841
+ var import_react46 = require("react");
6634
6842
  var import_editor13 = require("@pixerate/editor");
6635
- var import_jsx_runtime27 = require("react/jsx-runtime");
6843
+ var import_jsx_runtime28 = require("react/jsx-runtime");
6636
6844
  var buttonClass2 = "rounded px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground disabled:opacity-50";
6637
6845
  var primaryButtonClass = "rounded px-2 py-1 text-xs bg-primary/10 text-primary hover:bg-primary/20 disabled:opacity-50";
6638
6846
  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";
@@ -6646,18 +6854,18 @@ var CommentsPanel = ({
6646
6854
  emptyMessage = "No comments yet. Select text and add a comment."
6647
6855
  }) => {
6648
6856
  const { threads, activeThreadId, store } = useComments(storeProp ?? editor);
6649
- const [showResolved, setShowResolved] = (0, import_react45.useState)(showResolvedInitial);
6857
+ const [showResolved, setShowResolved] = (0, import_react46.useState)(showResolvedInitial);
6650
6858
  const author = authorProp ?? (0, import_editor13.getCommentAuthor)(editor) ?? { id: "anonymous", name: "Anonymous" };
6651
6859
  const visible = threads.filter((t) => showResolved || !t.resolved);
6652
6860
  const resolvedCount = threads.filter((t) => t.resolved).length;
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: [
6861
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("aside", { className, "aria-label": "Comments", children: [
6862
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
6863
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "text-xs font-medium text-muted-foreground", children: [
6656
6864
  threads.length - resolvedCount,
6657
6865
  " open",
6658
6866
  resolvedCount > 0 ? ` \xB7 ${resolvedCount} resolved` : ""
6659
6867
  ] }),
6660
- resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
6868
+ resolvedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6661
6869
  "button",
6662
6870
  {
6663
6871
  type: "button",
@@ -6668,7 +6876,7 @@ var CommentsPanel = ({
6668
6876
  }
6669
6877
  )
6670
6878
  ] }),
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)(
6879
+ visible.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("ul", { className: "flex flex-col gap-2", role: "list", children: visible.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6672
6880
  CommentThreadCard,
6673
6881
  {
6674
6882
  thread,
@@ -6690,7 +6898,7 @@ var CommentThreadCard = ({
6690
6898
  author,
6691
6899
  formatTime
6692
6900
  }) => {
6693
- const [draft, setDraft] = (0, import_react45.useState)("");
6901
+ const [draft, setDraft] = (0, import_react46.useState)("");
6694
6902
  const isDraft = thread.body === "";
6695
6903
  const quote = thread.anchor?.quote ?? thread.lastQuote ?? "";
6696
6904
  const live = editor && !editor.isDestroyed ? editor : null;
@@ -6716,7 +6924,7 @@ var CommentThreadCard = ({
6716
6924
  setDraft("");
6717
6925
  };
6718
6926
  const stop = (e) => e.stopPropagation();
6719
- return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
6927
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
6720
6928
  "li",
6721
6929
  {
6722
6930
  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" : ""}`,
@@ -6732,24 +6940,24 @@ var CommentThreadCard = ({
6732
6940
  }
6733
6941
  },
6734
6942
  children: [
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) })
6943
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex items-baseline justify-between gap-2", children: [
6944
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "font-medium", children: thread.author.name }),
6945
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-xs text-muted-foreground", children: formatTime(thread.createdAt) })
6738
6946
  ] }),
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 }),
6947
+ quote && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("blockquote", { className: "border-l-2 border-border pl-2 text-xs text-muted-foreground line-clamp-2", children: quote }),
6948
+ thread.orphaned && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-xs text-destructive", children: "The commented text was deleted." }),
6949
+ thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-xs text-muted-foreground", children: "Resolved" }),
6950
+ !isDraft && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "whitespace-pre-wrap break-words", children: thread.body }),
6951
+ thread.replies.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime28.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_runtime28.jsxs)("li", { className: "flex flex-col gap-0.5", "data-reply-id": reply.id, children: [
6952
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("span", { className: "text-xs", children: [
6953
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "font-medium", children: reply.author.name }),
6746
6954
  " ",
6747
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
6955
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "text-muted-foreground", children: formatTime(reply.createdAt) })
6748
6956
  ] }),
6749
- /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
6957
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "whitespace-pre-wrap break-words", children: reply.body })
6750
6958
  ] }, reply.id)) }),
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)(
6959
+ (active || isDraft) && !thread.resolved && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col gap-1", onClick: stop, children: [
6960
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6753
6961
  "textarea",
6754
6962
  {
6755
6963
  className: textareaClass,
@@ -6767,9 +6975,9 @@ var CommentThreadCard = ({
6767
6975
  }
6768
6976
  }
6769
6977
  ),
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)(
6978
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex justify-end gap-1", children: [
6979
+ isDraft && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: buttonClass2, onClick: remove, children: "Cancel" }),
6980
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6773
6981
  "button",
6774
6982
  {
6775
6983
  type: "button",
@@ -6781,9 +6989,9 @@ var CommentThreadCard = ({
6781
6989
  )
6782
6990
  ] })
6783
6991
  ] }),
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)(
6992
+ !isDraft && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex justify-end gap-1", onClick: stop, children: [
6993
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("button", { type: "button", className: buttonClass2, onClick: () => setResolved(!thread.resolved), children: thread.resolved ? "Reopen" : "Resolve" }),
6994
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6787
6995
  "button",
6788
6996
  {
6789
6997
  type: "button",
@@ -6799,7 +7007,7 @@ var CommentThreadCard = ({
6799
7007
  };
6800
7008
 
6801
7009
  // src/review/ReviewToolbar.tsx
6802
- var import_jsx_runtime28 = require("react/jsx-runtime");
7010
+ var import_jsx_runtime29 = require("react/jsx-runtime");
6803
7011
  var defaultDescriptionClass = "max-w-[16rem] truncate px-1 text-xs text-muted-foreground";
6804
7012
  var buttonClass3 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
6805
7013
  var ReviewToolbar = ({
@@ -6812,8 +7020,8 @@ var ReviewToolbar = ({
6812
7020
  const count = review.changes.length;
6813
7021
  const current = review.currentChange;
6814
7022
  const index = current ? review.changes.findIndex((c) => c.id === current.id) + 1 : 0;
6815
- return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
6816
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7023
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className, role: "toolbar", "aria-label": "Review", children: [
7024
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6817
7025
  "button",
6818
7026
  {
6819
7027
  type: "button",
@@ -6824,8 +7032,8 @@ var ReviewToolbar = ({
6824
7032
  children: review.enabled ? "Tracking on" : "Track changes"
6825
7033
  }
6826
7034
  ),
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)(
7035
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7036
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6829
7037
  "button",
6830
7038
  {
6831
7039
  type: "button",
@@ -6836,8 +7044,8 @@ var ReviewToolbar = ({
6836
7044
  children: "\u2039"
6837
7045
  }
6838
7046
  ),
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)(
7047
+ /* @__PURE__ */ (0, import_jsx_runtime29.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` }),
7048
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6841
7049
  "button",
6842
7050
  {
6843
7051
  type: "button",
@@ -6848,7 +7056,7 @@ var ReviewToolbar = ({
6848
7056
  children: "\u203A"
6849
7057
  }
6850
7058
  ),
6851
- showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
7059
+ showDescription && current && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
6852
7060
  "span",
6853
7061
  {
6854
7062
  className: descriptionClassName,
@@ -6860,8 +7068,8 @@ var ReviewToolbar = ({
6860
7068
  ]
6861
7069
  }
6862
7070
  ),
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)(
7071
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": "true" }),
7072
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6865
7073
  "button",
6866
7074
  {
6867
7075
  type: "button",
@@ -6871,7 +7079,7 @@ var ReviewToolbar = ({
6871
7079
  children: "Accept"
6872
7080
  }
6873
7081
  ),
6874
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
7082
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
6875
7083
  "button",
6876
7084
  {
6877
7085
  type: "button",
@@ -6881,18 +7089,18 @@ var ReviewToolbar = ({
6881
7089
  children: "Reject"
6882
7090
  }
6883
7091
  ),
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" })
7092
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.acceptAll, children: "Accept all" }),
7093
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: buttonClass3, disabled: count === 0, onClick: review.rejectAll, children: "Reject all" })
6886
7094
  ] });
6887
7095
  };
6888
7096
 
6889
7097
  // src/review/CommentButton.tsx
6890
- var import_jsx_runtime29 = require("react/jsx-runtime");
7098
+ var import_jsx_runtime30 = require("react/jsx-runtime");
6891
7099
  var CommentButton = ({
6892
7100
  editor,
6893
7101
  className = "rounded px-2 py-1 text-xs text-popover-foreground hover:bg-muted",
6894
7102
  children = "Comment"
6895
- }) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
7103
+ }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
6896
7104
  "button",
6897
7105
  {
6898
7106
  type: "button",
@@ -6904,13 +7112,13 @@ var CommentButton = ({
6904
7112
  );
6905
7113
 
6906
7114
  // src/review/useDocumentCompare.ts
6907
- var import_react46 = require("react");
7115
+ var import_react47 = require("react");
6908
7116
  var import_editor14 = require("@pixerate/editor");
6909
7117
  function useDocumentCompare(editor, options) {
6910
- const [summary, setSummary] = (0, import_react46.useState)(null);
6911
- const defaults = (0, import_react46.useRef)(options);
7118
+ const [summary, setSummary] = (0, import_react47.useState)(null);
7119
+ const defaults = (0, import_react47.useRef)(options);
6912
7120
  defaults.current = options;
6913
- const compare = (0, import_react46.useCallback)(
7121
+ const compare = (0, import_react47.useCallback)(
6914
7122
  (original, revised, overrides) => {
6915
7123
  if (!editor || editor.isDestroyed) return null;
6916
7124
  const result = (0, import_editor14.applyDocumentComparison)(editor, original, revised, {
@@ -6922,13 +7130,13 @@ function useDocumentCompare(editor, options) {
6922
7130
  },
6923
7131
  [editor]
6924
7132
  );
6925
- const clear = (0, import_react46.useCallback)(() => setSummary(null), []);
6926
- return (0, import_react46.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
7133
+ const clear = (0, import_react47.useCallback)(() => setSummary(null), []);
7134
+ return (0, import_react47.useMemo)(() => ({ summary, compare, clear }), [summary, compare, clear]);
6927
7135
  }
6928
7136
 
6929
7137
  // src/review/TrackedChangesList.tsx
6930
7138
  var import_editor15 = require("@pixerate/editor");
6931
- var import_jsx_runtime30 = require("react/jsx-runtime");
7139
+ var import_jsx_runtime31 = require("react/jsx-runtime");
6932
7140
  var buttonClass4 = "rounded px-1.5 py-0.5 text-xs text-foreground hover:bg-muted disabled:opacity-40";
6933
7141
  var TrackedChangesList = ({
6934
7142
  editor,
@@ -6939,18 +7147,18 @@ var TrackedChangesList = ({
6939
7147
  }) => {
6940
7148
  const review = useTrackChanges(editor);
6941
7149
  if (review.changes.length === 0) {
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 }) });
7150
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className, "data-tracked-changes-list": "", children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { className: "pixerate-changes-empty text-xs text-muted-foreground", children: emptyState }) });
6943
7151
  }
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) => {
7152
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("ul", { className, role: "list", "aria-label": "Tracked changes", "data-tracked-changes-list": "", children: review.changes.map((change) => {
6945
7153
  const active = change.id === review.currentChangeId;
6946
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7154
+ return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
6947
7155
  "li",
6948
7156
  {
6949
7157
  className: active ? `${itemClassName} ${activeItemClassName}` : itemClassName,
6950
7158
  "data-change-type": change.type,
6951
7159
  "data-change-id": change.id,
6952
7160
  children: [
6953
- /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
7161
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
6954
7162
  "button",
6955
7163
  {
6956
7164
  type: "button",
@@ -6958,14 +7166,14 @@ var TrackedChangesList = ({
6958
7166
  title: `${change.author.name}: ${change.description}`,
6959
7167
  onClick: () => review.select(change.id),
6960
7168
  children: [
6961
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
7169
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "font-medium", children: (0, import_editor15.trackedChangeLabel)(change) }),
6962
7170
  change.author.name ? ` \xB7 ${change.author.name}` : "",
6963
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
7171
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("span", { className: "block truncate text-muted-foreground", children: change.description })
6964
7172
  ]
6965
7173
  }
6966
7174
  ),
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" })
7175
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.accept(change.id), children: "Accept" }),
7176
+ /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("button", { type: "button", className: buttonClass4, onClick: () => review.reject(change.id), children: "Reject" })
6969
7177
  ]
6970
7178
  },
6971
7179
  `${change.type}:${change.id}`
@@ -6974,12 +7182,12 @@ var TrackedChangesList = ({
6974
7182
  };
6975
7183
 
6976
7184
  // src/commands/useCommandPalette.ts
6977
- var import_react47 = require("react");
7185
+ var import_react48 = require("react");
6978
7186
  var import_commands2 = require("@pixerate/editor/commands");
6979
7187
  function useCommandPalette(registry, options = {}) {
6980
- const optionsRef = (0, import_react47.useRef)(options);
7188
+ const optionsRef = (0, import_react48.useRef)(options);
6981
7189
  optionsRef.current = options;
6982
- const controller = (0, import_react47.useMemo)(
7190
+ const controller = (0, import_react48.useMemo)(
6983
7191
  () => (0, import_commands2.createCommandPaletteController)(registry, {
6984
7192
  context: () => {
6985
7193
  const c = optionsRef.current.context;
@@ -7000,9 +7208,9 @@ function useCommandPalette(registry, options = {}) {
7000
7208
  // eslint-disable-next-line react-hooks/exhaustive-deps
7001
7209
  [registry]
7002
7210
  );
7003
- const state = (0, import_react47.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
7211
+ const state = (0, import_react48.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
7004
7212
  const { hotkey, hotkeyTarget } = options;
7005
- (0, import_react47.useEffect)(() => {
7213
+ (0, import_react48.useEffect)(() => {
7006
7214
  if (!hotkey) return;
7007
7215
  const target = hotkeyTarget ?? (typeof window !== "undefined" ? window : null);
7008
7216
  if (!target) return;
@@ -7030,13 +7238,13 @@ function useCommandPalette(registry, options = {}) {
7030
7238
  }
7031
7239
 
7032
7240
  // src/commands/CommandPalette.tsx
7033
- var import_react48 = __toESM(require("react"), 1);
7034
- var import_jsx_runtime31 = require("react/jsx-runtime");
7241
+ var import_react49 = __toESM(require("react"), 1);
7242
+ var import_jsx_runtime32 = require("react/jsx-runtime");
7035
7243
  function HighlightedLabel({ item }) {
7036
- if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_jsx_runtime31.Fragment, { children: item.label });
7244
+ if (item.labelIndices.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, { children: item.label });
7037
7245
  const marked = new Set(item.labelIndices);
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)
7246
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, { children: Array.from(item.label).map(
7247
+ (ch, i) => marked.has(i) ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "font-semibold text-foreground", "data-match": "", children: ch }, i) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react49.default.Fragment, { children: ch }, i)
7040
7248
  ) });
7041
7249
  }
7042
7250
  var CommandPalette = ({
@@ -7045,22 +7253,22 @@ var CommandPalette = ({
7045
7253
  emptyMessage = "No matching commands",
7046
7254
  className = ""
7047
7255
  }) => {
7048
- const inputRef = (0, import_react48.useRef)(null);
7049
- const listRef = (0, import_react48.useRef)(null);
7050
- const baseId = (0, import_react48.useId)();
7256
+ const inputRef = (0, import_react49.useRef)(null);
7257
+ const listRef = (0, import_react49.useRef)(null);
7258
+ const baseId = (0, import_react49.useId)();
7051
7259
  const listId = `${baseId}-list`;
7052
7260
  const optionId = (index) => `${baseId}-option-${index}`;
7053
7261
  const { open, query, items, activeIndex } = palette;
7054
- (0, import_react48.useEffect)(() => {
7262
+ (0, import_react49.useEffect)(() => {
7055
7263
  if (open) inputRef.current?.focus();
7056
7264
  }, [open]);
7057
- (0, import_react48.useEffect)(() => {
7265
+ (0, import_react49.useEffect)(() => {
7058
7266
  if (!open) return;
7059
7267
  const active = listRef.current?.querySelector('[aria-selected="true"]');
7060
7268
  active?.scrollIntoView?.({ block: "nearest" });
7061
7269
  }, [open, activeIndex]);
7062
7270
  if (!open) return null;
7063
- return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7271
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7064
7272
  "div",
7065
7273
  {
7066
7274
  className: "fixed inset-0 z-50 flex items-start justify-center bg-black/30 px-4 pt-[15vh]",
@@ -7068,7 +7276,7 @@ var CommandPalette = ({
7068
7276
  onMouseDown: (e) => {
7069
7277
  if (e.target === e.currentTarget) palette.setOpen(false);
7070
7278
  },
7071
- children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
7279
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7072
7280
  "div",
7073
7281
  {
7074
7282
  role: "dialog",
@@ -7077,7 +7285,7 @@ var CommandPalette = ({
7077
7285
  className: `w-full max-w-lg overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-xl ${className}`,
7078
7286
  style: { background: "var(--popover, var(--background, #fff))" },
7079
7287
  children: [
7080
- /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
7288
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7081
7289
  "input",
7082
7290
  {
7083
7291
  ref: inputRef,
@@ -7097,7 +7305,7 @@ var CommandPalette = ({
7097
7305
  className: "w-full border-b border-border bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground"
7098
7306
  }
7099
7307
  ),
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)(
7308
+ items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "px-3 py-6 text-center text-sm text-muted-foreground", children: emptyMessage }) : /* @__PURE__ */ (0, import_jsx_runtime32.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_runtime32.jsxs)(
7101
7309
  "li",
7102
7310
  {
7103
7311
  id: optionId(index),
@@ -7112,12 +7320,12 @@ var CommandPalette = ({
7112
7320
  onClick: () => palette.run(item.id),
7113
7321
  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"}`,
7114
7322
  children: [
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 })
7323
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "min-w-0 flex-1 truncate", children: [
7324
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(HighlightedLabel, { item }),
7325
+ item.disabledReason && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "ml-2 text-xs text-muted-foreground", "data-disabled-reason": "", children: item.disabledReason })
7118
7326
  ] }),
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 })
7327
+ item.group && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground", children: item.group }),
7328
+ item.shortcut && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("kbd", { className: "shrink-0 rounded border border-border px-1.5 font-mono text-[10px] text-muted-foreground", children: item.shortcut })
7121
7329
  ]
7122
7330
  },
7123
7331
  item.id
@@ -7130,12 +7338,12 @@ var CommandPalette = ({
7130
7338
  };
7131
7339
 
7132
7340
  // src/commands/useCommandShortcuts.ts
7133
- var import_react49 = require("react");
7341
+ var import_react50 = require("react");
7134
7342
  function useCommandShortcuts(registry, options = {}) {
7135
- const optionsRef = (0, import_react49.useRef)(options);
7343
+ const optionsRef = (0, import_react50.useRef)(options);
7136
7344
  optionsRef.current = options;
7137
7345
  const { enabled = true, target } = options;
7138
- (0, import_react49.useEffect)(() => {
7346
+ (0, import_react50.useEffect)(() => {
7139
7347
  if (!registry || !enabled) return;
7140
7348
  const eventTarget = target ?? (typeof window !== "undefined" ? window : null);
7141
7349
  if (!eventTarget) return;
@@ -7153,14 +7361,14 @@ function useCommandShortcuts(registry, options = {}) {
7153
7361
  }, [registry, enabled, target]);
7154
7362
  }
7155
7363
  function useRegisterCommands(registry, specs) {
7156
- (0, import_react49.useEffect)(() => {
7364
+ (0, import_react50.useEffect)(() => {
7157
7365
  if (!registry || !specs || specs.length === 0) return;
7158
7366
  return registry.register(specs);
7159
7367
  }, [registry, specs]);
7160
7368
  }
7161
7369
 
7162
7370
  // src/persistence/useAutosave.ts
7163
- var import_react50 = require("react");
7371
+ var import_react51 = require("react");
7164
7372
  var import_persistence = require("@pixerate/editor/persistence");
7165
7373
  var IDLE = {
7166
7374
  status: "idle",
@@ -7171,18 +7379,18 @@ var IDLE = {
7171
7379
  ready: false
7172
7380
  };
7173
7381
  function useAutosave(options) {
7174
- const optionsRef = (0, import_react50.useRef)(options);
7382
+ const optionsRef = (0, import_react51.useRef)(options);
7175
7383
  optionsRef.current = options;
7176
7384
  const { storage, key, history, dirty } = options;
7177
7385
  const recover = options.recover !== false;
7178
7386
  const flushOnHide = options.flushOnHide !== false;
7179
7387
  const ready = options.ready !== false;
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)(() => {
7388
+ const [controller, setController] = (0, import_react51.useState)(null);
7389
+ const [status, setStatus] = (0, import_react51.useState)(IDLE);
7390
+ const [recovery, setRecovery] = (0, import_react51.useState)(null);
7391
+ const [pendingRecovery, setPendingRecovery] = (0, import_react51.useState)(recover);
7392
+ const revisionsRef = (0, import_react51.useRef)(null);
7393
+ (0, import_react51.useEffect)(() => {
7186
7394
  const revisions = (0, import_persistence.createRevisionTracker)({ history, dirty });
7187
7395
  const o = optionsRef.current;
7188
7396
  const instance = (0, import_persistence.createAutosaveController)({
@@ -7225,10 +7433,10 @@ function useAutosave(options) {
7225
7433
  if (revisionsRef.current === revisions) revisionsRef.current = null;
7226
7434
  };
7227
7435
  }, [storage, key, history, dirty, recover]);
7228
- (0, import_react50.useEffect)(() => {
7436
+ (0, import_react51.useEffect)(() => {
7229
7437
  if (controller && ready && !pendingRecovery) controller.ready();
7230
7438
  }, [controller, ready, pendingRecovery]);
7231
- (0, import_react50.useEffect)(() => {
7439
+ (0, import_react51.useEffect)(() => {
7232
7440
  if (!controller || !flushOnHide || typeof window === "undefined") return;
7233
7441
  const flush = () => void controller.flushNow();
7234
7442
  const onVisibility = () => {
@@ -7241,31 +7449,31 @@ function useAutosave(options) {
7241
7449
  document.removeEventListener("visibilitychange", onVisibility);
7242
7450
  };
7243
7451
  }, [controller, flushOnHide]);
7244
- const restore = (0, import_react50.useCallback)(() => {
7452
+ const restore = (0, import_react51.useCallback)(() => {
7245
7453
  const snapshot = recovery?.snapshot;
7246
7454
  setRecovery(null);
7247
7455
  setPendingRecovery(false);
7248
7456
  return snapshot;
7249
7457
  }, [recovery]);
7250
- const discard = (0, import_react50.useCallback)(async () => {
7458
+ const discard = (0, import_react51.useCallback)(async () => {
7251
7459
  if (controller) await controller.discardRecovery();
7252
7460
  setRecovery(null);
7253
7461
  setPendingRecovery(false);
7254
7462
  }, [controller]);
7255
- const flushNow = (0, import_react50.useCallback)(async () => {
7463
+ const flushNow = (0, import_react51.useCallback)(async () => {
7256
7464
  await controller?.flushNow();
7257
7465
  }, [controller]);
7258
- const markClean = (0, import_react50.useCallback)(async () => {
7466
+ const markClean = (0, import_react51.useCallback)(async () => {
7259
7467
  revisionsRef.current?.markSaved();
7260
7468
  await controller?.markClean();
7261
7469
  }, [controller]);
7262
- const notifyChange = (0, import_react50.useCallback)(() => revisionsRef.current?.bump(), []);
7470
+ const notifyChange = (0, import_react51.useCallback)(() => revisionsRef.current?.bump(), []);
7263
7471
  return { status, recovery, pendingRecovery, restore, discard, flushNow, markClean, notifyChange, controller };
7264
7472
  }
7265
7473
 
7266
7474
  // src/persistence/RecoveryPrompt.tsx
7267
7475
  var import_persistence2 = require("@pixerate/editor/persistence");
7268
- var import_jsx_runtime32 = require("react/jsx-runtime");
7476
+ var import_jsx_runtime33 = require("react/jsx-runtime");
7269
7477
  var RecoveryPrompt = ({
7270
7478
  recovery,
7271
7479
  onRestore,
@@ -7277,7 +7485,7 @@ var RecoveryPrompt = ({
7277
7485
  }) => {
7278
7486
  if (!recovery) return null;
7279
7487
  const { name } = recovery.meta;
7280
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7488
+ return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
7281
7489
  "div",
7282
7490
  {
7283
7491
  role: "alertdialog",
@@ -7285,15 +7493,15 @@ var RecoveryPrompt = ({
7285
7493
  "data-recovery-prompt": "",
7286
7494
  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}`,
7287
7495
  children: [
7288
- /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "min-w-0 flex-1", children: [
7496
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "min-w-0 flex-1", children: [
7289
7497
  (0, import_persistence2.formatRecoveryMessage)(recovery.meta, formatTime),
7290
- name ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
7498
+ name ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "ml-1 text-xs text-muted-foreground", children: [
7291
7499
  "(",
7292
7500
  name,
7293
7501
  ")"
7294
7502
  ] }) : null
7295
7503
  ] }),
7296
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7504
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7297
7505
  "button",
7298
7506
  {
7299
7507
  type: "button",
@@ -7303,7 +7511,7 @@ var RecoveryPrompt = ({
7303
7511
  children: restoreLabel
7304
7512
  }
7305
7513
  ),
7306
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7514
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7307
7515
  "button",
7308
7516
  {
7309
7517
  type: "button",
@@ -7319,17 +7527,17 @@ var RecoveryPrompt = ({
7319
7527
  };
7320
7528
 
7321
7529
  // src/generation/useGenerationPlan.ts
7322
- var import_react51 = require("react");
7530
+ var import_react52 = require("react");
7323
7531
  var import_generation = require("@pixerate/editor/generation");
7324
7532
  function useGenerationPlan(request, capabilities, options = {}) {
7325
7533
  const key = JSON.stringify([request, capabilities, options]);
7326
- return (0, import_react51.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
7534
+ return (0, import_react52.useMemo)(() => (0, import_generation.planGenerationRequest)(request, capabilities, options), [key]);
7327
7535
  }
7328
7536
  function useJobProgress(options) {
7329
7537
  const { startedAt, expectedMs, done, now, intervalMs = 1e3 } = options;
7330
- const [tick, setTick] = (0, import_react51.useState)(() => Date.now());
7538
+ const [tick, setTick] = (0, import_react52.useState)(() => Date.now());
7331
7539
  const ticking = !done && now === void 0;
7332
- (0, import_react51.useEffect)(() => {
7540
+ (0, import_react52.useEffect)(() => {
7333
7541
  if (!ticking) return;
7334
7542
  setTick(Date.now());
7335
7543
  const id = setInterval(() => setTick(Date.now()), Math.max(16, intervalMs));
@@ -7339,9 +7547,9 @@ function useJobProgress(options) {
7339
7547
  }
7340
7548
 
7341
7549
  // src/generation/GenerationSettings.tsx
7342
- var import_react52 = require("react");
7550
+ var import_react53 = require("react");
7343
7551
  var import_generation2 = require("@pixerate/editor/generation");
7344
- var import_jsx_runtime33 = require("react/jsx-runtime");
7552
+ var import_jsx_runtime34 = require("react/jsx-runtime");
7345
7553
  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";
7346
7554
  function Control({
7347
7555
  control,
@@ -7351,7 +7559,7 @@ function Control({
7351
7559
  }) {
7352
7560
  const shown = value ?? control.defaultValue;
7353
7561
  if (control.kind === "checkbox") {
7354
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7562
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7355
7563
  "input",
7356
7564
  {
7357
7565
  id,
@@ -7363,7 +7571,7 @@ function Control({
7363
7571
  );
7364
7572
  }
7365
7573
  if (control.kind === "select") {
7366
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
7574
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
7367
7575
  "select",
7368
7576
  {
7369
7577
  id,
@@ -7372,14 +7580,14 @@ function Control({
7372
7580
  value: shown === void 0 ? "" : String(shown),
7373
7581
  onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value)),
7374
7582
  children: [
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)))
7583
+ shown === void 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("option", { value: "", children: "Default" }),
7584
+ control.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("option", { value: String(option.value), children: option.label }, String(option.value)))
7377
7585
  ]
7378
7586
  }
7379
7587
  );
7380
7588
  }
7381
7589
  if (control.kind === "textarea") {
7382
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7590
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7383
7591
  "textarea",
7384
7592
  {
7385
7593
  id,
@@ -7393,8 +7601,8 @@ function Control({
7393
7601
  );
7394
7602
  }
7395
7603
  const numeric = typeof shown === "number" ? shown : void 0;
7396
- return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex items-center gap-2", children: [
7397
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7604
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-2", children: [
7605
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7398
7606
  "input",
7399
7607
  {
7400
7608
  id,
@@ -7408,7 +7616,7 @@ function Control({
7408
7616
  onChange: (e) => onValue((0, import_generation2.parseControlValue)(control, e.target.value))
7409
7617
  }
7410
7618
  ),
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" })
7619
+ control.kind === "range" && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "w-10 text-right tabular-nums text-muted-foreground", "data-field-value": "", children: numeric ?? "\u2013" })
7412
7620
  ] });
7413
7621
  }
7414
7622
  var GenerationSettings = ({
@@ -7422,17 +7630,17 @@ var GenerationSettings = ({
7422
7630
  renderReference,
7423
7631
  className = ""
7424
7632
  }) => {
7425
- const baseId = (0, import_react52.useId)();
7426
- const controls = (0, import_react52.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
7633
+ const baseId = (0, import_react53.useId)();
7634
+ const controls = (0, import_react53.useMemo)(() => (0, import_generation2.getGenerationControls)(capabilities), [capabilities]);
7427
7635
  const computed = useGenerationPlan(value, capabilities, { strategy });
7428
7636
  const plan = planProp ?? computed;
7429
7637
  const slots = (0, import_generation2.getReferenceSlots)(capabilities, value);
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: [
7638
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: `flex flex-col gap-3 text-sm ${className}`, "data-generation-settings": "", "data-model": capabilities.id, children: [
7431
7639
  controls.map((control) => {
7432
7640
  const id = `${baseId}-${control.key}`;
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)(
7641
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex flex-col gap-1", "data-control": control.key, children: [
7642
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("label", { htmlFor: id, className: "text-xs font-medium text-muted-foreground", title: control.description, children: control.label }),
7643
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7436
7644
  Control,
7437
7645
  {
7438
7646
  control,
@@ -7443,23 +7651,23 @@ var GenerationSettings = ({
7443
7651
  )
7444
7652
  ] }, control.key);
7445
7653
  }),
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: [
7654
+ slots.map((slot) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("fieldset", { className: "flex flex-col gap-1", "data-reference-role": slot.role, children: [
7655
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("legend", { className: "text-xs font-medium text-muted-foreground", title: slot.description, children: [
7448
7656
  slot.label,
7449
7657
  " ",
7450
- /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
7658
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: "tabular-nums", "data-reference-count": "", children: [
7451
7659
  "(",
7452
7660
  slot.references.length,
7453
7661
  "/",
7454
7662
  slot.max,
7455
7663
  ")"
7456
7664
  ] }),
7457
- slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "text-destructive", children: " *" })
7665
+ slot.min > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-destructive", children: " *" })
7458
7666
  ] }),
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)(
7667
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("ul", { className: "flex flex-wrap gap-1", children: [
7668
+ slot.references.map((ref) => /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("li", { className: "flex items-center gap-1 rounded border border-border px-1.5 py-0.5", "data-reference-id": ref.id, children: [
7669
+ renderReference ? renderReference(ref) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "max-w-[10rem] truncate", children: ref.id }),
7670
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7463
7671
  "button",
7464
7672
  {
7465
7673
  type: "button",
@@ -7470,7 +7678,7 @@ var GenerationSettings = ({
7470
7678
  }
7471
7679
  )
7472
7680
  ] }, ref.id)),
7473
- onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
7681
+ onAddReference && slot.canAdd && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7474
7682
  "button",
7475
7683
  {
7476
7684
  type: "button",
@@ -7481,21 +7689,21 @@ var GenerationSettings = ({
7481
7689
  ) })
7482
7690
  ] })
7483
7691
  ] }, slot.role)),
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)) })
7692
+ showAdjustments && plan.adjustments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.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_runtime34.jsx)("li", { "data-adjustment-field": adjustment.field, "data-adjustment-kind": adjustment.kind, children: adjustment.reason }, index)) }),
7693
+ showAdjustments && plan.errors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime34.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_runtime34.jsx)("li", { "data-error-field": error.field, children: error.message }, index)) })
7486
7694
  ] });
7487
7695
  };
7488
7696
 
7489
7697
  // src/generation/JobProgress.tsx
7490
- var import_jsx_runtime34 = require("react/jsx-runtime");
7698
+ var import_jsx_runtime35 = require("react/jsx-runtime");
7491
7699
  var JobProgress = ({ title, className = "", ...options }) => {
7492
7700
  const progress = useJobProgress(options);
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 })
7701
+ return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: `flex flex-col gap-1 text-sm ${className}`, "data-job-progress": "", "data-done": options.done ? "" : void 0, children: [
7702
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex items-center justify-between gap-2 text-muted-foreground", children: [
7703
+ title && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "truncate text-foreground", children: title }),
7704
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { "data-job-progress-label": "", "aria-live": "polite", children: progress.label })
7497
7705
  ] }),
7498
- /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7706
+ /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7499
7707
  "div",
7500
7708
  {
7501
7709
  role: "progressbar",
@@ -7505,7 +7713,7 @@ var JobProgress = ({ title, className = "", ...options }) => {
7505
7713
  "aria-valuenow": progress.percent,
7506
7714
  "aria-valuetext": `${progress.percent}%, ${progress.label}`,
7507
7715
  className: "h-1.5 w-full overflow-hidden rounded-full bg-muted",
7508
- children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
7716
+ children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7509
7717
  "div",
7510
7718
  {
7511
7719
  className: "h-full rounded-full bg-primary transition-[width] duration-500",
@@ -7518,9 +7726,9 @@ var JobProgress = ({ title, className = "", ...options }) => {
7518
7726
  };
7519
7727
 
7520
7728
  // src/generation/AssetMentionChips.tsx
7521
- var import_react53 = require("react");
7729
+ var import_react54 = require("react");
7522
7730
  var import_generation3 = require("@pixerate/editor/generation");
7523
- var import_jsx_runtime35 = require("react/jsx-runtime");
7731
+ var import_jsx_runtime36 = require("react/jsx-runtime");
7524
7732
  var AssetMentionChips = ({
7525
7733
  content,
7526
7734
  onChange,
@@ -7530,14 +7738,14 @@ var AssetMentionChips = ({
7530
7738
  renderAsset,
7531
7739
  className = ""
7532
7740
  }) => {
7533
- const [open, setOpen] = (0, import_react53.useState)(null);
7534
- const rootRef = (0, import_react53.useRef)(null);
7535
- const chips = (0, import_react53.useMemo)(
7741
+ const [open, setOpen] = (0, import_react54.useState)(null);
7742
+ const rootRef = (0, import_react54.useRef)(null);
7743
+ const chips = (0, import_react54.useMemo)(
7536
7744
  () => (0, import_generation3.describeAssetMentions)((0, import_generation3.findTextMentions)(content), assets, capabilities),
7537
7745
  [content, assets, capabilities]
7538
7746
  );
7539
7747
  const options = roles ?? (capabilities ? (0, import_generation3.getAssetRoleOptions)(capabilities) : (0, import_generation3.defaultAssetRoleOptions)());
7540
- (0, import_react53.useEffect)(() => {
7748
+ (0, import_react54.useEffect)(() => {
7541
7749
  if (open === null) return;
7542
7750
  const onPointer = (event) => {
7543
7751
  if (!rootRef.current?.contains(event.target)) setOpen(null);
@@ -7545,19 +7753,19 @@ var AssetMentionChips = ({
7545
7753
  document.addEventListener("mousedown", onPointer);
7546
7754
  return () => document.removeEventListener("mousedown", onPointer);
7547
7755
  }, [open]);
7548
- const pick = (chip2, role) => {
7756
+ const pick = (chip3, role) => {
7549
7757
  setOpen(null);
7550
- if (chip2.start === void 0) return;
7551
- onChange((0, import_generation3.setMentionRoleInText)(content, chip2.start, role));
7758
+ if (chip3.start === void 0) return;
7759
+ onChange((0, import_generation3.setMentionRoleInText)(content, chip3.start, role));
7552
7760
  };
7553
7761
  if (chips.length === 0) return null;
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) => {
7555
- const error = chip2.issues.find((issue) => issue.severity === "error");
7556
- const warning = chip2.issues.find((issue) => issue.severity === "warning");
7762
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { ref: rootRef, className: `flex flex-wrap gap-1.5 ${className}`, "data-asset-mention-chips": "", children: chips.map((chip3) => {
7763
+ const error = chip3.issues.find((issue) => issue.severity === "error");
7764
+ const warning = chip3.issues.find((issue) => issue.severity === "warning");
7557
7765
  const problem = error ?? warning;
7558
- const isOpen = open === chip2.index;
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)(
7766
+ const isOpen = open === chip3.index;
7767
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "relative inline-flex", "data-asset-chip": chip3.asset.id, children: [
7768
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7561
7769
  "button",
7562
7770
  {
7563
7771
  type: "button",
@@ -7565,82 +7773,82 @@ var AssetMentionChips = ({
7565
7773
  "aria-expanded": isOpen,
7566
7774
  title: problem?.message,
7567
7775
  "data-issue": problem?.code,
7568
- onClick: () => setOpen(isOpen ? null : chip2.index),
7776
+ onClick: () => setOpen(isOpen ? null : chip3.index),
7569
7777
  onKeyDown: (e) => {
7570
7778
  if (e.key === "Escape") setOpen(null);
7571
7779
  },
7572
7780
  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`,
7573
7781
  children: [
7574
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { children: renderAsset ? renderAsset(chip2) : `@${chip2.asset.label ?? chip2.handle}` }),
7575
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7782
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children: renderAsset ? renderAsset(chip3) : `@${chip3.asset.label ?? chip3.handle}` }),
7783
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7576
7784
  "span",
7577
7785
  {
7578
- className: `rounded px-1 text-[10px] uppercase tracking-wide ${chip2.role ? "bg-primary/15" : "opacity-60"}`,
7579
- "data-role-badge": chip2.role ?? "",
7580
- children: chip2.roleLabel ?? "No role"
7786
+ className: `rounded px-1 text-[10px] uppercase tracking-wide ${chip3.role ? "bg-primary/15" : "opacity-60"}`,
7787
+ "data-role-badge": chip3.role ?? "",
7788
+ children: chip3.roleLabel ?? "No role"
7581
7789
  }
7582
7790
  )
7583
7791
  ]
7584
7792
  }
7585
7793
  ),
7586
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7794
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7587
7795
  "div",
7588
7796
  {
7589
7797
  role: "listbox",
7590
- "aria-label": `Role for ${chip2.asset.label ?? chip2.handle}`,
7798
+ "aria-label": `Role for ${chip3.asset.label ?? chip3.handle}`,
7591
7799
  className: "absolute left-0 top-full z-50 mt-1 flex min-w-[12rem] flex-col rounded-md border border-border bg-background p-1 text-xs shadow-lg",
7592
7800
  "data-role-picker": "",
7593
7801
  onKeyDown: (e) => {
7594
7802
  if (e.key === "Escape") setOpen(null);
7595
7803
  },
7596
7804
  children: [
7597
- options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
7805
+ options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7598
7806
  "button",
7599
7807
  {
7600
7808
  type: "button",
7601
7809
  role: "option",
7602
- "aria-selected": chip2.role === option.role,
7810
+ "aria-selected": chip3.role === option.role,
7603
7811
  "data-role-option": option.role,
7604
7812
  title: option.description,
7605
- onClick: () => pick(chip2, option.role),
7813
+ onClick: () => pick(chip3, option.role),
7606
7814
  className: "flex items-center justify-between gap-2 rounded px-2 py-1 text-left hover:bg-muted",
7607
7815
  children: [
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
7816
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { children: option.label }),
7817
+ option.accepts?.length ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "text-[10px] opacity-60", children: option.accepts.join(", ") }) : null
7610
7818
  ]
7611
7819
  },
7612
7820
  option.role
7613
7821
  )),
7614
- /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
7822
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7615
7823
  "button",
7616
7824
  {
7617
7825
  type: "button",
7618
7826
  role: "option",
7619
- "aria-selected": !chip2.role,
7827
+ "aria-selected": !chip3.role,
7620
7828
  "data-role-option": "",
7621
- onClick: () => pick(chip2, null),
7829
+ onClick: () => pick(chip3, null),
7622
7830
  className: "rounded px-2 py-1 text-left opacity-70 hover:bg-muted",
7623
7831
  children: "No role"
7624
7832
  }
7625
7833
  ),
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)) })
7834
+ chip3.issues.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("ul", { className: "mt-1 border-t border-border px-2 pt-1 text-[10px]", "data-chip-issues": "", children: chip3.issues.map((issue, i) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("li", { className: issue.severity === "error" ? "text-red-500" : "text-amber-500", children: issue.message }, i)) })
7627
7835
  ]
7628
7836
  }
7629
7837
  )
7630
- ] }, `${chip2.start}-${chip2.index}`);
7838
+ ] }, `${chip3.start}-${chip3.index}`);
7631
7839
  }) });
7632
7840
  };
7633
7841
 
7634
7842
  // src/generation/GenerationHistory.tsx
7635
- var import_react54 = require("react");
7843
+ var import_react55 = require("react");
7636
7844
  var import_generation4 = require("@pixerate/editor/generation");
7637
- var import_jsx_runtime36 = require("react/jsx-runtime");
7845
+ var import_jsx_runtime37 = require("react/jsx-runtime");
7638
7846
  function useGenerationRecords(store, filter) {
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);
7847
+ const [records, setRecords] = (0, import_react55.useState)([]);
7848
+ const [loading, setLoading] = (0, import_react55.useState)(!!store);
7849
+ const [error, setError] = (0, import_react55.useState)(null);
7642
7850
  const filterKey = (0, import_generation4.stableStringify)(filter ?? {});
7643
- const refresh = (0, import_react54.useCallback)(async () => {
7851
+ const refresh = (0, import_react55.useCallback)(async () => {
7644
7852
  if (!store) {
7645
7853
  setRecords([]);
7646
7854
  setLoading(false);
@@ -7657,7 +7865,7 @@ function useGenerationRecords(store, filter) {
7657
7865
  setLoading(false);
7658
7866
  }
7659
7867
  }, [store, filterKey]);
7660
- (0, import_react54.useEffect)(() => {
7868
+ (0, import_react55.useEffect)(() => {
7661
7869
  void refresh();
7662
7870
  if (!store) return;
7663
7871
  return store.subscribe(() => void refresh());
@@ -7683,21 +7891,21 @@ var GenerationHistory = ({
7683
7891
  emptyText = "No generations yet.",
7684
7892
  className = ""
7685
7893
  }) => {
7686
- const [innerMode, setInnerMode] = (0, import_react54.useState)("exact");
7894
+ const [innerMode, setInnerMode] = (0, import_react55.useState)("exact");
7687
7895
  const mode = modeProp ?? innerMode;
7688
7896
  const setMode = (next) => {
7689
7897
  if (modeProp === void 0) setInnerMode(next);
7690
7898
  onModeChange?.(next);
7691
7899
  };
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)(
7900
+ const options = (0, import_react55.useMemo)(() => ({ templates, capabilities, assets, mode }), [templates, capabilities, assets, mode]);
7901
+ const results = (0, import_react55.useMemo)(() => records.map((record) => (0, import_generation4.recreateRequest)(record, options)), [records, options]);
7902
+ const models = (0, import_react55.useMemo)(
7695
7903
  () => capabilities ? Array.isArray(capabilities) ? capabilities : [capabilities] : [],
7696
7904
  [capabilities]
7697
7905
  );
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)(
7906
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: `flex flex-col gap-2 text-sm ${className}`, "data-generation-history": "", children: [
7907
+ /* @__PURE__ */ (0, import_jsx_runtime37.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_runtime37.jsxs)("label", { className: "inline-flex items-center gap-1", children: [
7908
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7701
7909
  "input",
7702
7910
  {
7703
7911
  type: "radio",
@@ -7710,34 +7918,34 @@ var GenerationHistory = ({
7710
7918
  ),
7711
7919
  value === "exact" ? "Exact (recorded versions)" : "Latest templates & settings"
7712
7920
  ] }, value)) }),
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) => {
7921
+ records.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "text-xs text-muted-foreground", children: emptyText }),
7922
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ul", { className: "flex flex-col gap-2", children: records.map((record, i) => {
7715
7923
  const result = results[i];
7716
7924
  const model = models.find((m) => m.id === record.provenance.modelId);
7717
7925
  const blocked = !result.ok;
7718
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(
7926
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
7719
7927
  "li",
7720
7928
  {
7721
7929
  className: "rounded-md border border-border p-2",
7722
7930
  "data-record": record.id,
7723
7931
  "data-drift": result.drift.length,
7724
7932
  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: [
7933
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 text-xs", children: [
7934
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "font-medium", children: model?.name ?? record.provenance.modelId }),
7935
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { className: "text-muted-foreground", children: [
7936
+ record.kind !== "generate" && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("span", { "data-kind": "", children: [
7729
7937
  record.kind,
7730
7938
  " \xB7 "
7731
7939
  ] }),
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: [
7940
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("time", { dateTime: record.createdAt, children: record.createdAt.replace("T", " ").slice(0, 16) }),
7941
+ record.seed !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
7734
7942
  " \xB7 seed ",
7735
7943
  record.seed
7736
7944
  ] })
7737
7945
  ] })
7738
7946
  ] }),
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)(
7947
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "mt-1 line-clamp-3 break-words text-xs", "data-record-prompt": "", children: record.provenance.resolvedPrompt }),
7948
+ record.assets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "mt-1 flex flex-wrap gap-1", children: record.assets.map((asset) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
7741
7949
  "span",
7742
7950
  {
7743
7951
  className: "rounded-full bg-muted px-2 py-0.5 text-[10px]",
@@ -7751,16 +7959,16 @@ var GenerationHistory = ({
7751
7959
  `${asset.role}:${asset.id}`
7752
7960
  )) }),
7753
7961
  renderPreview?.(record),
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: [
7962
+ result.drift.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.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_runtime37.jsxs)("li", { className: severityClass[item.severity], "data-drift-type": item.type, children: [
7963
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("strong", { children: [
7756
7964
  import_generation4.DRIFT_TYPE_LABELS[item.type],
7757
7965
  ":"
7758
7966
  ] }),
7759
7967
  " ",
7760
7968
  item.message
7761
7969
  ] }, j)) }),
7762
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "mt-2 flex gap-2", children: [
7763
- onRecreate && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7970
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "mt-2 flex gap-2", children: [
7971
+ onRecreate && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7764
7972
  "button",
7765
7973
  {
7766
7974
  type: "button",
@@ -7772,7 +7980,7 @@ var GenerationHistory = ({
7772
7980
  children: "Recreate"
7773
7981
  }
7774
7982
  ),
7775
- onVariation && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7983
+ onVariation && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7776
7984
  "button",
7777
7985
  {
7778
7986
  type: "button",
@@ -7782,7 +7990,7 @@ var GenerationHistory = ({
7782
7990
  children: "Variation"
7783
7991
  }
7784
7992
  ),
7785
- onRemove && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
7993
+ onRemove && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7786
7994
  "button",
7787
7995
  {
7788
7996
  type: "button",
@@ -7802,19 +8010,19 @@ var GenerationHistory = ({
7802
8010
  };
7803
8011
 
7804
8012
  // src/find-replace/useFindReplace.ts
7805
- var import_react55 = require("react");
8013
+ var import_react56 = require("react");
7806
8014
  var import_editor16 = require("@pixerate/editor");
7807
8015
  var noopUnsubscribe2 = () => {
7808
8016
  };
7809
8017
  function useFindReplace(editor) {
7810
8018
  const store = (0, import_editor16.getFindReplaceStore)(editor ?? null);
7811
- const subscribe = (0, import_react55.useCallback)(
8019
+ const subscribe = (0, import_react56.useCallback)(
7812
8020
  (onChange) => store ? store.subscribe(() => onChange()) : noopUnsubscribe2,
7813
8021
  [store]
7814
8022
  );
7815
8023
  const getSnapshot = () => store?.getSnapshot() ?? import_editor16.EMPTY_FIND_REPLACE_SNAPSHOT;
7816
- const snapshot = (0, import_react55.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
7817
- return (0, import_react55.useMemo)(() => {
8024
+ const snapshot = (0, import_react56.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
8025
+ return (0, import_react56.useMemo)(() => {
7818
8026
  const run = (fn) => {
7819
8027
  if (editor && !editor.isDestroyed && store) fn(editor);
7820
8028
  };
@@ -7838,9 +8046,9 @@ function useFindReplace(editor) {
7838
8046
  }
7839
8047
 
7840
8048
  // src/find-replace/FindReplaceBar.tsx
7841
- var import_react56 = require("react");
8049
+ var import_react57 = require("react");
7842
8050
  var import_editor17 = require("@pixerate/editor");
7843
- var import_jsx_runtime37 = require("react/jsx-runtime");
8051
+ var import_jsx_runtime38 = require("react/jsx-runtime");
7844
8052
  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";
7845
8053
  var buttonClass5 = "rounded px-2 py-1 text-xs text-foreground hover:bg-muted disabled:opacity-40 disabled:hover:bg-transparent";
7846
8054
  var toggleClass = (on) => `${buttonClass5} font-mono ${on ? "bg-primary/10 text-primary" : "text-muted-foreground"}`;
@@ -7853,10 +8061,10 @@ var FindReplaceBar = ({
7853
8061
  onClose
7854
8062
  }) => {
7855
8063
  const find = useFindReplace(editor);
7856
- const findInput = (0, import_react56.useRef)(null);
7857
- const [moreOpen, setMoreOpen] = (0, import_react56.useState)(false);
8064
+ const findInput = (0, import_react57.useRef)(null);
8065
+ const [moreOpen, setMoreOpen] = (0, import_react57.useState)(false);
7858
8066
  const visible = find.available && (alwaysOpen || find.open);
7859
- (0, import_react56.useEffect)(() => {
8067
+ (0, import_react57.useEffect)(() => {
7860
8068
  if (!visible || find.focusRequest === 0) return;
7861
8069
  findInput.current?.focus();
7862
8070
  findInput.current?.select();
@@ -7894,9 +8102,9 @@ var FindReplaceBar = ({
7894
8102
  if (isMod(e)) find.replaceAll();
7895
8103
  else find.replace();
7896
8104
  };
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)(
8105
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className, role: "search", "aria-label": "Find and replace", onKeyDown: onBarKeyDown, children: [
8106
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-1", children: [
8107
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
7900
8108
  "button",
7901
8109
  {
7902
8110
  type: "button",
@@ -7907,7 +8115,7 @@ var FindReplaceBar = ({
7907
8115
  children: showReplace ? "\u25BE" : "\u25B8"
7908
8116
  }
7909
8117
  ),
7910
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8118
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
7911
8119
  "input",
7912
8120
  {
7913
8121
  ref: findInput,
@@ -7921,7 +8129,7 @@ var FindReplaceBar = ({
7921
8129
  onKeyDown: onFindKeyDown
7922
8130
  }
7923
8131
  ),
7924
- import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8132
+ import_editor17.FIND_OPTION_TOGGLES.filter((t) => !t.advanced).map((t) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
7925
8133
  "button",
7926
8134
  {
7927
8135
  type: "button",
@@ -7934,7 +8142,7 @@ var FindReplaceBar = ({
7934
8142
  },
7935
8143
  t.key
7936
8144
  )),
7937
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8145
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
7938
8146
  "span",
7939
8147
  {
7940
8148
  className: `min-w-[5rem] px-1 text-center text-xs ${find.error ? "text-destructive" : "text-muted-foreground"}`,
@@ -7944,9 +8152,9 @@ var FindReplaceBar = ({
7944
8152
  children: status
7945
8153
  }
7946
8154
  ),
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)(
8155
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Previous match", disabled: !hasMatches, onClick: find.previous, children: "\u2191" }),
8156
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Next match", disabled: !hasMatches, onClick: find.next, children: "\u2193" }),
8157
+ showMoreOptions && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
7950
8158
  "button",
7951
8159
  {
7952
8160
  type: "button",
@@ -7957,10 +8165,10 @@ var FindReplaceBar = ({
7957
8165
  children: "\u2026"
7958
8166
  }
7959
8167
  ),
7960
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
8168
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { type: "button", className: buttonClass5, "aria-label": "Close find", onClick: close, children: "\xD7" })
7961
8169
  ] }),
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)(
8170
+ showReplace && /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "flex items-center gap-1 pl-7", children: [
8171
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
7964
8172
  "input",
7965
8173
  {
7966
8174
  type: "text",
@@ -7972,7 +8180,7 @@ var FindReplaceBar = ({
7972
8180
  onKeyDown: onReplaceKeyDown
7973
8181
  }
7974
8182
  ),
7975
- /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
8183
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
7976
8184
  "button",
7977
8185
  {
7978
8186
  type: "button",
@@ -7982,11 +8190,11 @@ var FindReplaceBar = ({
7982
8190
  children: "Replace"
7983
8191
  }
7984
8192
  ),
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` })
8193
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("button", { type: "button", className: buttonClass5, disabled: !hasMatches, onClick: find.replaceAll, children: "Replace all" }),
8194
+ find.lastReplaceCount !== null && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "px-1 text-xs text-muted-foreground", "aria-live": "polite", children: find.lastReplaceCount === 1 ? "1 replaced" : `${find.lastReplaceCount} replaced` })
7987
8195
  ] }),
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)(
8196
+ showMoreOptions && moreOpen && /* @__PURE__ */ (0, import_jsx_runtime38.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_runtime38.jsxs)("label", { className: "flex items-center gap-1", children: [
8197
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
7990
8198
  "input",
7991
8199
  {
7992
8200
  type: "checkbox",
@@ -8000,12 +8208,12 @@ var FindReplaceBar = ({
8000
8208
  };
8001
8209
 
8002
8210
  // src/tables/useTableMenu.ts
8003
- var import_react57 = require("react");
8211
+ var import_react58 = require("react");
8004
8212
  var import_editor18 = require("@pixerate/editor");
8005
8213
  function useTableMenu(editor) {
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)(
8214
+ const store = (0, import_react58.useMemo)(() => (0, import_editor18.createTableStore)(editor), [editor]);
8215
+ const snapshot = (0, import_react58.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
8216
+ return (0, import_react58.useMemo)(
8009
8217
  () => ({
8010
8218
  ...snapshot,
8011
8219
  run: (action, params) => (0, import_editor18.runTableAction)(editor, action, params, { focus: true }),
@@ -8016,9 +8224,9 @@ function useTableMenu(editor) {
8016
8224
  }
8017
8225
 
8018
8226
  // src/tables/TableToolbar.tsx
8019
- var import_react58 = __toESM(require("react"), 1);
8227
+ var import_react59 = __toESM(require("react"), 1);
8020
8228
  var import_editor19 = require("@pixerate/editor");
8021
- var import_jsx_runtime38 = require("react/jsx-runtime");
8229
+ var import_jsx_runtime39 = require("react/jsx-runtime");
8022
8230
  var keepSelection2 = (event) => event.preventDefault();
8023
8231
  var TableToolbar = ({
8024
8232
  editor,
@@ -8032,14 +8240,14 @@ var TableToolbar = ({
8032
8240
  }) => {
8033
8241
  const table = useTableMenu(editor);
8034
8242
  if (!editor || !table.inTable && !showWhenOutside) return null;
8035
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
8243
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className, role: "toolbar", "aria-label": "Table", "data-table-toolbar": "", children: items.map((item, index) => {
8036
8244
  const status = table.check(item.action, item.params);
8037
8245
  const enabled = status === true;
8038
8246
  const active = item.active?.(table);
8039
8247
  const separator = index > 0 && items[index - 1].group !== item.group;
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)(
8248
+ return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_react59.default.Fragment, { children: [
8249
+ separator && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("span", { className: separatorClassName, "aria-hidden": "true" }),
8250
+ /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8043
8251
  "button",
8044
8252
  {
8045
8253
  type: "button",
@@ -8061,8 +8269,8 @@ var TableToolbar = ({
8061
8269
  };
8062
8270
 
8063
8271
  // src/tables/InsertTableGrid.tsx
8064
- var import_react59 = require("react");
8065
- var import_jsx_runtime39 = require("react/jsx-runtime");
8272
+ var import_react60 = require("react");
8273
+ var import_jsx_runtime40 = require("react/jsx-runtime");
8066
8274
  var keepSelection3 = (event) => event.preventDefault();
8067
8275
  var InsertTableGrid = ({
8068
8276
  editor,
@@ -8075,14 +8283,14 @@ var InsertTableGrid = ({
8075
8283
  onInsert
8076
8284
  }) => {
8077
8285
  const table = useTableMenu(editor);
8078
- const [hover, setHover] = (0, import_react59.useState)(null);
8286
+ const [hover, setHover] = (0, import_react60.useState)(null);
8079
8287
  const status = table.actions.insertTable;
8080
8288
  const disabled = !editor || !status.enabled;
8081
8289
  const insert = (size) => {
8082
8290
  if (table.run("insertTable", { ...size, withHeaderRow })) onInsert?.(size);
8083
8291
  setHover(null);
8084
8292
  };
8085
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
8293
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
8086
8294
  "div",
8087
8295
  {
8088
8296
  className,
@@ -8092,7 +8300,7 @@ var InsertTableGrid = ({
8092
8300
  "data-insert-table-grid": "",
8093
8301
  onMouseLeave: () => setHover(null),
8094
8302
  children: [
8095
- /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8303
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8096
8304
  "div",
8097
8305
  {
8098
8306
  role: "grid",
@@ -8101,7 +8309,7 @@ var InsertTableGrid = ({
8101
8309
  children: Array.from({ length: rows * cols }, (_, i) => {
8102
8310
  const size = { rows: Math.floor(i / cols) + 1, cols: i % cols + 1 };
8103
8311
  const active = !!hover && size.rows <= hover.rows && size.cols <= hover.cols;
8104
- return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
8312
+ return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
8105
8313
  "button",
8106
8314
  {
8107
8315
  type: "button",
@@ -8121,7 +8329,7 @@ var InsertTableGrid = ({
8121
8329
  })
8122
8330
  }
8123
8331
  ),
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" })
8332
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { "aria-live": "polite", "data-testid": "insert-table-size", children: disabled ? status.reason : hover ? `${hover.rows} \xD7 ${hover.cols}` : "Insert table" })
8125
8333
  ]
8126
8334
  }
8127
8335
  );
@@ -8129,31 +8337,31 @@ var InsertTableGrid = ({
8129
8337
 
8130
8338
  // src/tables/TableBubbleMenu.tsx
8131
8339
  var import_editor20 = require("@pixerate/editor");
8132
- var import_jsx_runtime40 = require("react/jsx-runtime");
8340
+ var import_jsx_runtime41 = require("react/jsx-runtime");
8133
8341
  var TableBubbleMenu = ({
8134
8342
  editor,
8135
8343
  children,
8136
8344
  toolbarProps,
8137
8345
  pluginKey = "tableBubbleMenu",
8138
8346
  ...rest
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 }) });
8347
+ }) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(BubbleMenu, { editor, pluginKey, shouldShow: import_editor20.shouldShowTableBubbleMenu, ...rest, children: children ?? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(TableToolbar, { editor, ...toolbarProps }) });
8140
8348
 
8141
8349
  // src/chart-node/ChartNodeView.tsx
8142
8350
  var import_client = require("react-dom/client");
8143
8351
 
8144
8352
  // src/chart/ChartCanvas.tsx
8145
- var import_react61 = require("react");
8353
+ var import_react62 = require("react");
8146
8354
  var import_chart2 = require("@pixerate/editor/chart");
8147
8355
 
8148
8356
  // src/chart/useChartEditor.ts
8149
- var import_react60 = require("react");
8357
+ var import_react61 = require("react");
8150
8358
  var import_chart = require("@pixerate/editor/chart");
8151
8359
  function useChartState(controller) {
8152
- return (0, import_react60.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
8360
+ return (0, import_react61.useSyncExternalStore)(controller.subscribe, controller.getState, controller.getState);
8153
8361
  }
8154
8362
 
8155
8363
  // src/chart/ChartCanvas.tsx
8156
- var import_jsx_runtime41 = require("react/jsx-runtime");
8364
+ var import_jsx_runtime42 = require("react/jsx-runtime");
8157
8365
  function renderChartMark(mark, fontFamily, interactive) {
8158
8366
  const common = {
8159
8367
  "data-role": mark.role,
@@ -8165,9 +8373,9 @@ function renderChartMark(mark, fontFamily, interactive) {
8165
8373
  };
8166
8374
  switch (mark.kind) {
8167
8375
  case "rect":
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);
8376
+ return /* @__PURE__ */ (0, import_jsx_runtime42.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);
8169
8377
  case "path":
8170
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8378
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8171
8379
  "path",
8172
8380
  {
8173
8381
  ...common,
@@ -8180,11 +8388,11 @@ function renderChartMark(mark, fontFamily, interactive) {
8180
8388
  mark.key
8181
8389
  );
8182
8390
  case "circle":
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);
8391
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("circle", { ...common, cx: mark.cx, cy: mark.cy, r: mark.r, style: { fill: mark.fill, stroke: mark.stroke, strokeWidth: mark.strokeWidth } }, mark.key);
8184
8392
  case "line":
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);
8393
+ return /* @__PURE__ */ (0, import_jsx_runtime42.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);
8186
8394
  case "text":
8187
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8395
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8188
8396
  "text",
8189
8397
  {
8190
8398
  ...common,
@@ -8201,23 +8409,23 @@ function renderChartMark(mark, fontFamily, interactive) {
8201
8409
  }
8202
8410
  }
8203
8411
  function ChartPresenceLayer({ presence }) {
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 })
8412
+ const { actors } = (0, import_react62.useSyncExternalStore)(presence.subscribe, presence.getState, presence.getState);
8413
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("g", { "data-chart-presence": "", pointerEvents: "none", children: actors.map((a) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("g", { transform: `translate(${a.x} ${a.y})`, "data-actor": a.id, children: [
8414
+ /* @__PURE__ */ (0, import_jsx_runtime42.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 }),
8415
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("g", { transform: "translate(13 16)", children: [
8416
+ /* @__PURE__ */ (0, import_jsx_runtime42.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 } }),
8417
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("text", { x: 6, y: 9, dominantBaseline: "central", style: { fill: "#ffffff", fontSize: 11, fontWeight: 600, fontFamily: "inherit" }, children: a.message ?? a.name })
8210
8418
  ] })
8211
8419
  ] }, a.id)) });
8212
8420
  }
8213
8421
  function ChartCanvas({ controller, width = 640, height = 400, responsive = true, theme, editable = true, measureText, emptyMessage, className, presence, sceneRef }) {
8214
8422
  const state = useChartState(controller);
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)(() => {
8423
+ const wrapper = (0, import_react62.useRef)(null);
8424
+ const svg = (0, import_react62.useRef)(null);
8425
+ const drag = (0, import_react62.useRef)(null);
8426
+ const [measured, setMeasured] = (0, import_react62.useState)(null);
8427
+ const [frozen, setFrozen] = (0, import_react62.useState)(null);
8428
+ (0, import_react62.useEffect)(() => {
8221
8429
  const el = wrapper.current;
8222
8430
  if (!responsive || !el || typeof ResizeObserver === "undefined") return;
8223
8431
  const observer = new ResizeObserver(([entry]) => {
@@ -8228,8 +8436,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8228
8436
  return () => observer.disconnect();
8229
8437
  }, [responsive]);
8230
8438
  const sceneWidth = responsive && measured || width;
8231
- const fullTheme = (0, import_react61.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
8232
- const scene = (0, import_react61.useMemo)(
8439
+ const fullTheme = (0, import_react62.useMemo)(() => ({ ...import_chart2.CSS_VARIABLE_CHART_THEME, ...theme }), [theme]);
8440
+ const scene = (0, import_react62.useMemo)(
8233
8441
  () => (0, import_chart2.layoutChart)(state.spec, {
8234
8442
  width: sceneWidth,
8235
8443
  height,
@@ -8245,8 +8453,8 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8245
8453
  [state.spec, state.selection, sceneWidth, height, fullTheme, editable, measureText, emptyMessage, frozen]
8246
8454
  );
8247
8455
  if (sceneRef) sceneRef.current = scene;
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(), []);
8456
+ const byKey = (0, import_react62.useMemo)(() => new Map(scene.marks.map((m) => [m.key, m])), [scene]);
8457
+ (0, import_react62.useEffect)(() => () => drag.current?.end(), []);
8250
8458
  const scenePoint = (e) => (0, import_chart2.chartClientToScene)(scene, svg.current.getBoundingClientRect(), e.clientX, e.clientY);
8251
8459
  const onPointerDown = (e) => {
8252
8460
  if (!editable || e.button !== 0) return;
@@ -8279,7 +8487,7 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8279
8487
  if (editable && (0, import_chart2.handleChartKey)(controller, scene, e)) e.preventDefault();
8280
8488
  };
8281
8489
  const label = state.spec.title || "Chart";
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)(
8490
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { ref: wrapper, className: `w-full ${className ?? ""}`, "data-chart-canvas": "", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
8283
8491
  "svg",
8284
8492
  {
8285
8493
  ref: svg,
@@ -8297,14 +8505,14 @@ function ChartCanvas({ controller, width = 640, height = 400, responsive = true,
8297
8505
  onKeyDown,
8298
8506
  children: [
8299
8507
  scene.marks.map((m) => renderChartMark(m, scene.theme.fontFamily, editable)),
8300
- presence && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ChartPresenceLayer, { presence })
8508
+ presence && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ChartPresenceLayer, { presence })
8301
8509
  ]
8302
8510
  }
8303
8511
  ) });
8304
8512
  }
8305
8513
 
8306
8514
  // src/chart/ChartDataGrid.tsx
8307
- var import_react62 = require("react");
8515
+ var import_react63 = require("react");
8308
8516
  var import_chart3 = require("@pixerate/editor/chart");
8309
8517
 
8310
8518
  // src/chart/styles.ts
@@ -8317,11 +8525,11 @@ var chartSectionClass = "space-y-2 border-b border-border pb-3 last:border-b-0";
8317
8525
  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";
8318
8526
 
8319
8527
  // src/chart/ChartDataGrid.tsx
8320
- var import_jsx_runtime42 = require("react/jsx-runtime");
8528
+ var import_jsx_runtime43 = require("react/jsx-runtime");
8321
8529
  function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
8322
- const [draft, setDraft] = (0, import_react62.useState)(value);
8323
- const typing = (0, import_react62.useRef)(false);
8324
- (0, import_react62.useEffect)(() => {
8530
+ const [draft, setDraft] = (0, import_react63.useState)(value);
8531
+ const typing = (0, import_react63.useRef)(false);
8532
+ (0, import_react63.useEffect)(() => {
8325
8533
  if (!typing.current) setDraft(value);
8326
8534
  }, [value]);
8327
8535
  const commit = () => {
@@ -8330,7 +8538,7 @@ function ChartCommitInput({ value, onCommit, onKeyDown, onBlur, ...rest }) {
8330
8538
  if (draft === value) return;
8331
8539
  if (onCommit(draft) === false) setDraft(value);
8332
8540
  };
8333
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8541
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8334
8542
  "input",
8335
8543
  {
8336
8544
  ...rest,
@@ -8365,15 +8573,15 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8365
8573
  e.preventDefault();
8366
8574
  controller.pasteCells(row, column, text);
8367
8575
  };
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 }),
8576
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: `overflow-auto rounded-md border border-border ${className ?? ""}`, "data-chart-grid": "", children: [
8577
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("table", { className: "w-full border-collapse text-xs", children: [
8578
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("thead", { className: "bg-muted/50", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("tr", { children: [
8579
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("th", { className: "border-b border-r border-border px-2 py-1 text-left font-medium text-muted-foreground", children: categoryHeader }),
8372
8580
  spec.series.map((s, si) => {
8373
8581
  const color = (0, import_chart3.chartSeriesColor)(spec, si);
8374
8582
  const selected = selection?.kind === "series" && selection.seriesId === s.id;
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)(
8583
+ return /* @__PURE__ */ (0, import_jsx_runtime43.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_runtime43.jsxs)("div", { className: "flex items-center gap-1", children: [
8584
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8377
8585
  "input",
8378
8586
  {
8379
8587
  type: "color",
@@ -8386,7 +8594,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8386
8594
  className: "h-5 w-5 shrink-0 cursor-pointer rounded border-0 bg-transparent p-0"
8387
8595
  }
8388
8596
  ),
8389
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8597
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8390
8598
  ChartCommitInput,
8391
8599
  {
8392
8600
  value: s.name,
@@ -8396,8 +8604,8 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8396
8604
  className: `${chartInputClass} h-6 min-w-[5rem] border-transparent bg-transparent font-medium ${s.hidden ? "text-muted-foreground line-through" : ""}`
8397
8605
  }
8398
8606
  ),
8399
- !readOnly && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
8400
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
8607
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
8608
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8401
8609
  "button",
8402
8610
  {
8403
8611
  type: "button",
@@ -8410,16 +8618,16 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8410
8618
  children: s.hidden ? "\u25CB" : "\u25CF"
8411
8619
  }
8412
8620
  ),
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" })
8621
+ /* @__PURE__ */ (0, import_jsx_runtime43.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" })
8414
8622
  ] })
8415
8623
  ] }) }, s.id);
8416
8624
  }),
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: "+" }) })
8625
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("th", { className: "w-8 border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Add series", "aria-label": "Add series", "data-action": "add-series", onClick: () => controller.addSeries(), children: "+" }) })
8418
8626
  ] }) }),
8419
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("tbody", { children: spec.categories.map((category, i) => {
8627
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("tbody", { children: spec.categories.map((category, i) => {
8420
8628
  const rowSelected = selection?.kind === "category" && selection.index === i;
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)(
8629
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("tr", { "data-category-index": i, className: rowSelected ? "bg-primary/10" : void 0, children: [
8630
+ /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("th", { className: "border-b border-r border-border p-0 text-left font-normal", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8423
8631
  ChartCommitInput,
8424
8632
  {
8425
8633
  value: category,
@@ -8433,7 +8641,7 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8433
8641
  spec.series.map((s) => {
8434
8642
  const value = s.values[i];
8435
8643
  const selected = selection?.kind === "point" && selection.seriesId === s.id && selection.index === i;
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)(
8644
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("td", { className: `border-b border-r border-border p-0 ${selected ? "bg-primary/10" : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8437
8645
  ChartCommitInput,
8438
8646
  {
8439
8647
  value: value === null || value === void 0 ? "" : String(value),
@@ -8448,38 +8656,38 @@ function ChartDataGrid({ controller, categoryHeader = "Category", readOnly = fal
8448
8656
  }
8449
8657
  ) }, s.id);
8450
8658
  }),
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" }) })
8659
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("td", { className: "border-b border-border px-1", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: chartIconButtonClass, title: "Delete category", "aria-label": `Delete ${category}`, "data-action": "remove-category", onClick: () => controller.removeCategory(i), children: "\xD7" }) })
8452
8660
  ] }, i);
8453
8661
  }) })
8454
8662
  ] }),
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" }) })
8663
+ !readOnly && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "p-1", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", className: `${chartButtonClass} h-6 border-dashed`, "data-action": "add-category", onClick: () => controller.addCategory(), children: "+ Add category" }) })
8456
8664
  ] });
8457
8665
  }
8458
8666
 
8459
8667
  // src/chart/ChartInspector.tsx
8460
- var import_react63 = require("react");
8668
+ var import_react64 = require("react");
8461
8669
  var import_chart4 = require("@pixerate/editor/chart");
8462
- var import_jsx_runtime43 = require("react/jsx-runtime");
8670
+ var import_jsx_runtime44 = require("react/jsx-runtime");
8463
8671
  var cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
8464
8672
  function Field({ label, htmlFor, 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 })
8673
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
8674
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("label", { htmlFor, className: `${chartLabelClass} w-20 shrink-0`, children: label }),
8675
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "min-w-0 flex-1", children })
8468
8676
  ] });
8469
8677
  }
8470
8678
  function Toggle({ label, checked, onChange, name }) {
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) }),
8679
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { className: "flex cursor-pointer items-center gap-2 text-xs text-foreground", children: [
8680
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { type: "checkbox", className: "h-3.5 w-3.5 accent-primary", checked, "data-option": name, onChange: (e) => onChange(e.currentTarget.checked) }),
8473
8681
  label
8474
8682
  ] });
8475
8683
  }
8476
8684
  function Select({ id, value, options, onChange, name, labels }) {
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)) });
8685
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("select", { id, className: chartInputClass, value, "data-option": name, onChange: (e) => onChange(e.currentTarget.value), children: options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: o, children: labels?.[o] ?? cap(o) }, o)) });
8478
8686
  }
8479
8687
  function AxisSection({ controller, axis, value, idBase, horizontal, numeric = false, scales = false }) {
8480
8688
  const set = (patch) => controller.setAxis(axis, patch);
8481
8689
  const setFormat = (patch) => set({ format: { ...value.format, ...patch } });
8482
- const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8690
+ const bound = (key2) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8483
8691
  ChartCommitInput,
8484
8692
  {
8485
8693
  id: `${idBase}-${axis}-${key2}`,
@@ -8494,26 +8702,26 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
8494
8702
  const name = axis === "x" ? numeric ? "X axis" : "Category axis" : axis === "y" ? "Value axis" : "Secondary axis";
8495
8703
  const valueAxis = axis !== "x" || numeric;
8496
8704
  const key = axis === "y2" ? "yAxis2" : `${axis}Axis`;
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: [
8705
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": `axis-${axis}`, children: [
8706
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center justify-between", children: [
8707
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("h4", { className: "text-xs font-semibold text-foreground", children: [
8500
8708
  name,
8501
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
8709
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "ml-1 font-normal text-muted-foreground", children: [
8502
8710
  "(",
8503
8711
  axis === "x" ? horizontal ? "left" : "bottom" : axis === "y2" ? horizontal ? "top" : "right" : horizontal ? "bottom" : "left",
8504
8712
  ")"
8505
8713
  ] })
8506
8714
  ] }),
8507
- /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
8715
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Show", name: `${axis}Axis.show`, checked: value.show, onChange: (show) => set({ show }) })
8508
8716
  ] }),
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" }) })
8717
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Title", htmlFor: `${idBase}-${axis}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartCommitInput, { id: `${idBase}-${axis}-title`, value: value.title, "data-option": `${axis}Axis.title`, className: chartInputClass, onCommit: (title) => void set({ title }) }) }),
8718
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
8719
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Grid lines", name: `${key}.gridlines`, checked: value.gridlines, onChange: (gridlines) => set({ gridlines }) }),
8720
+ axis === "x" && !numeric && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Dates", name: "xAxis.kind", checked: value.kind === "date", onChange: (dates) => set({ kind: dates ? "date" : void 0 }) }),
8721
+ scales && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Reverse", name: `${key}.reverse`, checked: !!value.reverse, onChange: (reverse) => set({ reverse }) }),
8722
+ scales && valueAxis && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Log scale", name: `${key}.scale`, checked: value.scale === "log", onChange: (log) => set({ scale: log ? "log" : "linear" }) })
8515
8723
  ] }),
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)(
8724
+ scales && valueAxis && value.scale === "log" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Log base", htmlFor: `${idBase}-${axis}-log-base`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8517
8725
  ChartCommitInput,
8518
8726
  {
8519
8727
  id: `${idBase}-${axis}-log-base`,
@@ -8524,7 +8732,7 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
8524
8732
  onCommit: (text) => set({ logBase: text.trim() === "" ? void 0 : Number(text) }).ok
8525
8733
  }
8526
8734
  ) }),
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)(
8735
+ valueAxis && value.scale !== "log" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Step", htmlFor: `${idBase}-${axis}-step`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8528
8736
  ChartCommitInput,
8529
8737
  {
8530
8738
  id: `${idBase}-${axis}-step`,
@@ -8536,14 +8744,14 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
8536
8744
  onCommit: (text) => set({ step: text.trim() === "" ? null : Number(text) }).ok
8537
8745
  }
8538
8746
  ) }),
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: [
8747
+ valueAxis && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
8748
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Min / max", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex gap-1", children: [
8541
8749
  bound("min"),
8542
8750
  bound("max")
8543
8751
  ] }) }),
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)(
8752
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Format", htmlFor: `${idBase}-${axis}-format`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex gap-1", children: [
8753
+ /* @__PURE__ */ (0, import_jsx_runtime44.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 }) }),
8754
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8547
8755
  ChartCommitInput,
8548
8756
  {
8549
8757
  value: value.format.decimals === void 0 ? "" : String(value.format.decimals),
@@ -8562,8 +8770,8 @@ function AxisSection({ controller, axis, value, idBase, horizontal, numeric = fa
8562
8770
  }
8563
8771
  )
8564
8772
  ] }) }),
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)(
8773
+ value.format.style === "currency" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Currency", htmlFor: `${idBase}-${axis}-currency`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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() }) }) }),
8774
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Code", htmlFor: `${idBase}-${axis}-code`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8567
8775
  ChartCommitInput,
8568
8776
  {
8569
8777
  id: `${idBase}-${axis}-code`,
@@ -8589,15 +8797,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
8589
8797
  const values = which === "xErrorBars" ? series.x ?? [] : series.values;
8590
8798
  const set = (next) => controller.updateSeries(series.id, { [which]: next });
8591
8799
  const patch = (p) => bars && set({ ...bars, ...p });
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))
8800
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "space-y-1.5", "data-section": which === "errorBars" ? "error-bars" : "x-error-bars", children: [
8801
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: which === "errorBars" ? "Error bars" : "X error bars", htmlFor: `${id}-type`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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: [
8802
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "None" }),
8803
+ import_chart4.CHART_ERROR_BAR_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: t, children: import_chart4.CHART_ERROR_BAR_LABELS[t] }, t))
8596
8804
  ] }) }),
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)(
8805
+ bars && (bars.type === "fixed" || bars.type === "percent" || bars.type === "stddev") && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: bars.type === "percent" ? "Percent" : bars.type === "stddev" ? "Deviations" : "Amount", htmlFor: `${id}-value`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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 }) }),
8806
+ bars?.type === "custom" && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
8807
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Plus", htmlFor: `${id}-plus`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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 }) }),
8808
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Minus", htmlFor: `${id}-minus`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8601
8809
  ChartCommitInput,
8602
8810
  {
8603
8811
  id: `${id}-minus`,
@@ -8614,15 +8822,15 @@ function ErrorBarFields({ controller, series, which, idBase }) {
8614
8822
  }
8615
8823
  ) })
8616
8824
  ] }),
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 }) })
8825
+ bars && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
8826
+ /* @__PURE__ */ (0, import_jsx_runtime44.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_runtime44.jsx)("option", { value: d, children: d === "both" ? "Both ways" : d === "plus" ? "Plus only" : "Minus only" }, d)) }),
8827
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Caps", name: `${key}.cap`, checked: bars.cap !== false, onChange: (cap2) => patch({ cap: cap2 }) })
8620
8828
  ] })
8621
8829
  ] });
8622
8830
  }
8623
8831
  function ChartInspector({ controller, sections, className }) {
8624
8832
  const { spec, selectedSeries } = useChartState(controller);
8625
- const idBase = (0, import_react63.useId)();
8833
+ const idBase = (0, import_react64.useId)();
8626
8834
  const show = (section) => !sections || sections.includes(section);
8627
8835
  const cartesian = (0, import_chart4.isCartesianChart)(spec.type);
8628
8836
  const family = (0, import_chart4.chartFamily)(spec);
@@ -8634,29 +8842,29 @@ function ChartInspector({ controller, sections, className }) {
8634
8842
  const hasLines = cartesian && types.some((t) => t === "line" || t === "area");
8635
8843
  const seriesIndex = selectedSeries ? spec.series.findIndex((s) => s.id === selectedSeries.id) : -1;
8636
8844
  const scales = family === "cartesian" || family === "xy";
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))
8845
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: `space-y-3 text-xs ${className ?? ""}`, "data-chart-inspector": "", children: [
8846
+ show("type") && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: chartSectionClass, "data-section": "type", children: /* @__PURE__ */ (0, import_jsx_runtime44.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_runtime44.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)) }) }),
8847
+ show("style") && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": "style", children: [
8848
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Layout", htmlFor: `${idBase}-layout`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("select", { id: `${idBase}-layout`, className: chartInputClass, value: "", "data-option": "preset.layout", onChange: (e) => e.currentTarget.value && controller.applyPreset({ layout: e.currentTarget.value }), children: [
8849
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "Quick layout\u2026" }),
8850
+ import_chart4.CHART_LAYOUT_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: p.id, title: p.description, children: p.label }, p.id))
8643
8851
  ] }) }),
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))
8852
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Colours", htmlFor: `${idBase}-colors`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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: [
8853
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "Custom" }),
8854
+ import_chart4.CHART_COLOR_SCHEMES.map((c) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: c.id, title: c.description, children: c.label }, c.id))
8647
8855
  ] }) }),
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" })
8856
+ !colorCheck.ok && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-[11px] leading-snug text-amber-600 dark:text-amber-400", "data-chart-color-warning": "", children: colorCheck.issues[0] }),
8857
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "transpose", onClick: () => controller.transpose(), children: "Switch rows and columns" })
8650
8858
  ] }),
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) }) })
8859
+ show("titles") && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": "titles", children: [
8860
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Title", htmlFor: `${idBase}-title`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartCommitInput, { id: `${idBase}-title`, value: spec.title, "data-option": "title", className: chartInputClass, onCommit: (title) => void controller.setTitle(title) }) }),
8861
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Subtitle", htmlFor: `${idBase}-subtitle`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartCommitInput, { id: `${idBase}-subtitle`, value: spec.subtitle, "data-option": "subtitle", className: chartInputClass, onCommit: (subtitle) => void controller.setSubtitle(subtitle) }) })
8654
8862
  ] }),
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)(
8863
+ show("options") && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": "options", children: [
8864
+ cartesian && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Stacking", htmlFor: `${idBase}-stacking`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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 }) }) }),
8865
+ hasBars && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Bars", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "flex gap-0.5 rounded-md bg-muted p-0.5", children: ["vertical", "horizontal"].map((o) => /* @__PURE__ */ (0, import_jsx_runtime44.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)) }) }),
8866
+ hasLines && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Lines", htmlFor: `${idBase}-curve`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Select, { id: `${idBase}-curve`, name: "curve", value: spec.curve, options: import_chart4.CHART_CURVES, onChange: (curve) => controller.update({ curve }) }) }),
8867
+ spec.type === "donut" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Hole", htmlFor: `${idBase}-hole`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8660
8868
  "input",
8661
8869
  {
8662
8870
  id: `${idBase}-hole`,
@@ -8672,7 +8880,7 @@ function ChartInspector({ controller, sections, className }) {
8672
8880
  onChange: (e) => controller.update({ innerRadius: Number(e.currentTarget.value) })
8673
8881
  }
8674
8882
  ) }),
8675
- hasBars && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
8883
+ hasBars && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Spacing", htmlFor: `${idBase}-gap`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8676
8884
  "input",
8677
8885
  {
8678
8886
  id: `${idBase}-gap`,
@@ -8688,31 +8896,31 @@ function ChartInspector({ controller, sections, className }) {
8688
8896
  onChange: (e) => controller.update({ gapWidth: Number(e.currentTarget.value) })
8689
8897
  }
8690
8898
  ) }),
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 }) })
8899
+ spec.dataLabels && hasBars && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Labels", htmlFor: `${idBase}-label-position`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Select, { id: `${idBase}-label-position`, name: "labelPosition", value: spec.labelPosition, options: import_chart4.CHART_LABEL_POSITIONS, onChange: (labelPosition) => controller.update({ labelPosition }) }) }),
8900
+ spec.type === "histogram" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Bins", htmlFor: `${idBase}-bins`, children: /* @__PURE__ */ (0, import_jsx_runtime44.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 }) }),
8901
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex flex-wrap gap-x-4 gap-y-1", children: [
8902
+ spec.type === "waterfall" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Total bar", name: "showTotal", checked: spec.showTotal, onChange: (showTotal) => controller.update({ showTotal }) }),
8903
+ hasLines && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Points", name: "points", checked: spec.points, onChange: (points) => controller.update({ points }) }),
8904
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Data labels", name: "dataLabels", checked: spec.dataLabels, onChange: (dataLabels) => controller.update({ dataLabels }) })
8697
8905
  ] })
8698
8906
  ] }),
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 }) })
8907
+ show("legend") && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": "legend", children: [
8908
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center justify-between", children: [
8909
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Legend" }),
8910
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Show", name: "legend.show", checked: spec.legend.show, onChange: (v) => controller.setLegend({ show: v }) })
8703
8911
  ] }),
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)) })
8912
+ spec.legend.show && /* @__PURE__ */ (0, import_jsx_runtime44.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_runtime44.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)) })
8705
8913
  ] }),
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 })
8914
+ show("axes") && hasAxes && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
8915
+ family !== "box" && family !== "histogram" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(AxisSection, { controller, axis: "x", value: spec.xAxis, idBase, horizontal: spec.orientation === "horizontal", numeric: family === "xy", scales }),
8916
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(AxisSection, { controller, axis: "y", value: spec.yAxis, idBase, horizontal: spec.orientation === "horizontal", scales }),
8917
+ usesSecondary && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(AxisSection, { controller, axis: "y2", value: spec.yAxis2, idBase, horizontal: spec.orientation === "horizontal", scales })
8710
8918
  ] }),
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)(
8919
+ show("series") && selectedSeries && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: chartSectionClass, "data-section": "series", "data-series-id": selectedSeries.id, children: [
8920
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("h4", { className: "text-xs font-semibold text-foreground", children: "Series" }),
8921
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Name", htmlFor: `${idBase}-series-name`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartCommitInput, { id: `${idBase}-series-name`, value: selectedSeries.name, "data-option": "series.name", className: chartInputClass, onCommit: (name) => void controller.updateSeries(selectedSeries.id, { name }) }) }),
8922
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Colour", htmlFor: `${idBase}-series-color`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-1", children: [
8923
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
8716
8924
  "input",
8717
8925
  {
8718
8926
  id: `${idBase}-series-color`,
@@ -8725,9 +8933,9 @@ function ChartInspector({ controller, sections, className }) {
8725
8933
  onChange: (e) => controller.updateSeries(selectedSeries.id, { color: e.currentTarget.value })
8726
8934
  }
8727
8935
  ),
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" })
8936
+ selectedSeries.color && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "reset-color", onClick: () => controller.updateSeries(selectedSeries.id, { color: null }), children: "Palette" })
8729
8937
  ] }) }),
8730
- cartesian && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
8938
+ cartesian && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Draw as", htmlFor: `${idBase}-series-type`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
8731
8939
  "select",
8732
8940
  {
8733
8941
  id: `${idBase}-series-type`,
@@ -8736,12 +8944,12 @@ function ChartInspector({ controller, sections, className }) {
8736
8944
  "data-option": "series.type",
8737
8945
  onChange: (e) => controller.updateSeries(selectedSeries.id, { type: e.currentTarget.value || null }),
8738
8946
  children: [
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))
8947
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "Chart type" }),
8948
+ import_chart4.CHART_SERIES_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: t, children: import_chart4.CHART_TYPE_LABELS[t] }, t))
8741
8949
  ]
8742
8950
  }
8743
8951
  ) }),
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)(
8952
+ (cartesian || family === "xy") && ["line", "area", "scatter"].includes((0, import_chart4.chartSeriesType)(spec, selectedSeries)) && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Field, { label: "Marker", htmlFor: `${idBase}-series-marker`, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
8745
8953
  "select",
8746
8954
  {
8747
8955
  id: `${idBase}-series-marker`,
@@ -8750,20 +8958,20 @@ function ChartInspector({ controller, sections, className }) {
8750
8958
  "data-option": "series.marker",
8751
8959
  onChange: (e) => controller.updateSeries(selectedSeries.id, { marker: e.currentTarget.value || null }),
8752
8960
  children: [
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))
8961
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "Default" }),
8962
+ import_chart4.CHART_MARKERS.map((m) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: m, children: cap(m) }, m))
8755
8963
  ]
8756
8964
  }
8757
8965
  ) }),
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" })
8966
+ scales && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "errorBars", idBase }),
8967
+ family === "xy" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ErrorBarFields, { controller, series: selectedSeries, which: "xErrorBars", idBase }),
8968
+ (0, import_chart4.chartSupportsTrendlines)(spec.type, spec.stacking) && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "space-y-1", "data-section": "trendlines", children: [
8969
+ (selectedSeries.trendlines ?? []).map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-1", "data-trendline": i, children: [
8970
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "flex-1 truncate text-muted-foreground", children: (0, import_chart4.chartTrendlineName)(t, selectedSeries.name) }),
8971
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "R\xB2", name: `trendline.${i}.showR2`, checked: !!t.showR2, onChange: (showR2) => controller.updateTrendline(selectedSeries.id, i, { showR2 }) }),
8972
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: chartButtonClass, "aria-label": "Delete trendline", "data-action": "trendline-delete", onClick: () => controller.removeTrendline(selectedSeries.id, i), children: "\xD7" })
8765
8973
  ] }, i)),
8766
- /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
8974
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
8767
8975
  "select",
8768
8976
  {
8769
8977
  className: chartInputClass,
@@ -8772,32 +8980,32 @@ function ChartInspector({ controller, sections, className }) {
8772
8980
  "data-option": "trendline.add",
8773
8981
  onChange: (e) => e.currentTarget.value && controller.addTrendline(selectedSeries.id, { type: e.currentTarget.value }),
8774
8982
  children: [
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))
8983
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: "", children: "Add trendline\u2026" }),
8984
+ import_chart4.CHART_TRENDLINE_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: t, children: cap(t.replace("-", " ")) }, t))
8777
8985
  ]
8778
8986
  }
8779
8987
  )
8780
8988
  ] }),
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" })
8989
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
8990
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Hidden", name: "series.hidden", checked: !!selectedSeries.hidden, onChange: (hidden) => controller.updateSeries(selectedSeries.id, { hidden }) }),
8991
+ family === "cartesian" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Toggle, { label: "Secondary axis", name: "series.axis", checked: selectedSeries.axis === "secondary", onChange: (secondary) => controller.updateSeries(selectedSeries.id, { axis: secondary ? "secondary" : null }) }),
8992
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "flex-1" }),
8993
+ /* @__PURE__ */ (0, import_jsx_runtime44.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" }),
8994
+ /* @__PURE__ */ (0, import_jsx_runtime44.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" }),
8995
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: `${chartButtonClass} text-destructive`, "data-action": "series-delete", onClick: () => controller.removeSeries(selectedSeries.id), children: "Delete" })
8788
8996
  ] })
8789
8997
  ] })
8790
8998
  ] });
8791
8999
  }
8792
9000
 
8793
9001
  // src/chart-node/ChartNodeView.tsx
8794
- var import_jsx_runtime44 = require("react/jsx-runtime");
9002
+ var import_jsx_runtime45 = require("react/jsx-runtime");
8795
9003
  function ChartNodeView({ state, theme, showDataGrid = true }) {
8796
9004
  const { controller, editing, editable, selected, width, height, setEditing } = state;
8797
9005
  const open = () => {
8798
9006
  if (editable && !editing) setEditing(true);
8799
9007
  };
8800
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
9008
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
8801
9009
  "div",
8802
9010
  {
8803
9011
  className: `not-prose my-2 rounded-md border bg-background p-1 ${selected ? "border-primary ring-1 ring-primary" : "border-border"}`,
@@ -8810,24 +9018,24 @@ function ChartNodeView({ state, theme, showDataGrid = true }) {
8810
9018
  }
8811
9019
  },
8812
9020
  children: [
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" })
9021
+ editing && /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "mb-1 flex items-center justify-between gap-2 px-1", "data-chart-node-toolbar": "", children: [
9022
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "text-xs text-muted-foreground", children: "Editing chart" }),
9023
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("button", { type: "button", className: chartButtonClass, "data-action": "done", onClick: () => setEditing(false), children: "Done" })
8816
9024
  ] }),
8817
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
9025
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
8818
9026
  "div",
8819
9027
  {
8820
9028
  className: editable && !editing ? "cursor-pointer" : void 0,
8821
9029
  onClick: open,
8822
9030
  title: editable && !editing ? "Click to edit the chart" : void 0,
8823
9031
  "data-chart-node-canvas": "",
8824
- children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
9032
+ children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartCanvas, { controller, width: width ?? 640, height, responsive: width === null, editable: editing, theme })
8825
9033
  }
8826
9034
  ),
8827
9035
  editing && // Wraps by the document's width, not the viewport's: side by side when there is room.
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" })
9036
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "mt-2 flex flex-wrap items-start gap-2", "data-chart-node-panel": "", children: [
9037
+ showDataGrid && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "min-w-0 flex-[1_1_20rem] overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartDataGrid, { controller }) }),
9038
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(ChartInspector, { controller, className: "max-h-96 min-w-0 flex-[1_1_16rem] overflow-y-auto rounded-md border border-border p-3" })
8831
9039
  ] })
8832
9040
  ]
8833
9041
  }
@@ -8845,7 +9053,7 @@ function createReactChartNodeView(options = {}) {
8845
9053
  scheduled = true;
8846
9054
  queueMicrotask(() => {
8847
9055
  scheduled = false;
8848
- if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Component, { ...props, state: latest }));
9056
+ if (!destroyed) root.render(/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(Component, { ...props, state: latest }));
8849
9057
  });
8850
9058
  };
8851
9059
  schedule();
@@ -8879,6 +9087,7 @@ function createReactChartNodeView(options = {}) {
8879
9087
  ExportDocxButton,
8880
9088
  FindReplaceBar,
8881
9089
  FormulaHints,
9090
+ FreeTransformOptionsBar,
8882
9091
  GenerationHistory,
8883
9092
  GenerationSettings,
8884
9093
  Histogram,