@elabs-ai/components-editor 4.0.0 → 4.2.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.
Files changed (77) hide show
  1. package/README.md +6 -7
  2. package/dist/{chunk-LBC5VJBD.js → chunk-FO5S3YZM.js} +349 -177
  3. package/dist/chunk-FO5S3YZM.js.map +1 -0
  4. package/dist/index.css +4 -2
  5. package/dist/index.css.map +1 -1
  6. package/dist/index.d.ts +5 -4
  7. package/dist/index.js +112 -57
  8. package/dist/index.js.map +1 -1
  9. package/dist/markdown/index.css +4 -2
  10. package/dist/markdown/index.css.map +1 -1
  11. package/dist/markdown/index.d.ts +2 -2
  12. package/dist/markdown/index.js +268 -191
  13. package/dist/markdown/index.js.map +1 -1
  14. package/dist/{markdown-editor-DfBZibAn.d.ts → markdown-editor-Dn-0L_MM.d.ts} +9 -2
  15. package/dist/monaco.d.ts +2 -0
  16. package/dist/monaco.js +9 -0
  17. package/dist/monaco.js.map +1 -0
  18. package/package.json +10 -6
  19. package/src/ai-objects/decision-card.tsx +15 -9
  20. package/src/ai-objects/entity.tsx +1 -1
  21. package/src/ai-objects/knowledge-card.tsx +18 -9
  22. package/src/barrel-monaco-lazy.test.ts +50 -0
  23. package/src/calc-block/calc-block.tsx +10 -4
  24. package/src/calc-block/calc-editor.css +1 -1
  25. package/src/code-editor/code-editor.stories.tsx +76 -1
  26. package/src/code-editor/code-editor.test.tsx +141 -14
  27. package/src/code-editor/code-editor.tsx +167 -36
  28. package/src/code-workspace/code-workspace.test.tsx +113 -11
  29. package/src/code-workspace/code-workspace.tsx +73 -20
  30. package/src/copy-button/copy-button.tsx +6 -3
  31. package/src/diff-editor/diff-editor.stories.tsx +9 -1
  32. package/src/diff-editor/diff-editor.test.tsx +9 -3
  33. package/src/diff-editor/diff-editor.tsx +47 -23
  34. package/src/editor-toolbar/editor-toolbar.tsx +8 -2
  35. package/src/index.ts +4 -3
  36. package/src/lib/monaco-deep-imports.d.ts +59 -0
  37. package/src/lib/monaco-theme-bridge.test.ts +307 -0
  38. package/src/lib/monaco-theme-bridge.ts +154 -10
  39. package/src/markdown-academic/citations.tsx +14 -7
  40. package/src/markdown-academic/footnotes.tsx +2 -2
  41. package/src/markdown-academic/math.tsx +7 -4
  42. package/src/markdown-academic/toc.tsx +1 -1
  43. package/src/markdown-editor/completions/completions-menu.tsx +5 -2
  44. package/src/markdown-editor/directive-views.tsx +35 -24
  45. package/src/markdown-editor/markdown-editor.css +26 -3
  46. package/src/markdown-editor/markdown-editor.focus.test.ts +49 -0
  47. package/src/markdown-editor/markdown-editor.stories.tsx +128 -7
  48. package/src/markdown-editor/markdown-editor.tsx +8 -5
  49. package/src/markdown-editor/milkdown-react/use-get-editor.timer-leak.test.ts +80 -0
  50. package/src/markdown-editor/milkdown-react/use-get-editor.ts +37 -1
  51. package/src/markdown-editor/paste-embed.ts +2 -1
  52. package/src/markdown-editor/slash/slash-menu.stories.tsx +8 -3
  53. package/src/markdown-editor/slash/slash-menu.test.tsx +27 -0
  54. package/src/markdown-editor/slash/slash-menu.tsx +18 -3
  55. package/src/markdown-editor/table-view.tsx +31 -17
  56. package/src/markdown-iteration/iteration-builder-dialog.stories.tsx +57 -19
  57. package/src/markdown-iteration/iteration-builder-dialog.tsx +39 -18
  58. package/src/markdown-iteration/template-dialog.tsx +25 -7
  59. package/src/markdown-outline/document-outline.stories.tsx +1 -1
  60. package/src/markdown-outline/document-outline.tsx +7 -3
  61. package/src/markdown-preview/markdown-preview-academic.test.tsx +3 -3
  62. package/src/markdown-preview/markdown-preview-transclusion.test.tsx +1 -1
  63. package/src/markdown-preview/markdown-preview.stories.tsx +24 -2
  64. package/src/markdown-preview/markdown-preview.test.tsx +20 -3
  65. package/src/markdown-toolbar/markdown-toolbar.stories.tsx +3 -0
  66. package/src/markdown-toolbar/markdown-toolbar.tsx +42 -24
  67. package/src/markdown-workspace/markdown-workspace.test.tsx +53 -4
  68. package/src/markdown-workspace/markdown-workspace.tsx +6 -3
  69. package/src/mermaid-diagram/mermaid-diagram-fixes.test.tsx +130 -0
  70. package/src/mermaid-diagram/mermaid-diagram.test.tsx +2 -1
  71. package/src/mermaid-diagram/mermaid-diagram.tsx +89 -40
  72. package/src/mermaid-diagram/mermaid-viewer.tsx +22 -21
  73. package/src/monaco.ts +21 -0
  74. package/src/prose/prose.stories.tsx +3 -0
  75. package/src/prose/prose.test.ts +54 -0
  76. package/src/prose/prose.tsx +7 -0
  77. package/dist/chunk-LBC5VJBD.js.map +0 -1
@@ -54,7 +54,7 @@ import {
54
54
  transposeIterationValue,
55
55
  triggerQueryStart,
56
56
  useMarkdownOutline
57
- } from "../chunk-LBC5VJBD.js";
57
+ } from "../chunk-FO5S3YZM.js";
58
58
 
59
59
  // src/lib/editor-completions-monaco.ts
60
60
  import * as monaco from "monaco-editor";
@@ -452,7 +452,8 @@ import {
452
452
  Tooltip as Tooltip2,
453
453
  TooltipContent as TooltipContent2,
454
454
  TooltipProvider as TooltipProvider2,
455
- TooltipTrigger as TooltipTrigger2
455
+ TooltipTrigger as TooltipTrigger2,
456
+ useLocale as useLocale7
456
457
  } from "@elabs-ai/components-ui";
457
458
  import { cn as cn13 } from "@elabs-ai/components-ui/lib/cn";
458
459
  import { Columns2, Eye, Focus, SquareCode } from "lucide-react";
@@ -1028,6 +1029,7 @@ function buildMarkdownPlugins(options = {}) {
1028
1029
  }
1029
1030
 
1030
1031
  // src/calc-block/calc-block.tsx
1032
+ import { useLocale } from "@elabs-ai/components-ui";
1031
1033
  import { cn as cn2 } from "@elabs-ai/components-ui/lib/cn";
1032
1034
  import { TriangleAlert } from "lucide-react";
1033
1035
  import { forwardRef, useId, useMemo } from "react";
@@ -1152,20 +1154,21 @@ function renderSource(text, tokens) {
1152
1154
  return out;
1153
1155
  }
1154
1156
  function ResultCell({ result }) {
1157
+ const { t } = useLocale();
1155
1158
  if (result.error) {
1156
1159
  return /* @__PURE__ */ jsx2(
1157
1160
  "span",
1158
1161
  {
1159
1162
  className: "inline-flex shrink-0 text-calc-warning",
1160
1163
  title: result.error.message,
1161
- "aria-label": `Error: ${result.error.message}`,
1164
+ "aria-label": t("editor.calcBlock.error", { message: result.error.message }),
1162
1165
  children: /* @__PURE__ */ jsx2(TriangleAlert, { className: "size-3.5", "aria-hidden": "true" })
1163
1166
  }
1164
1167
  );
1165
1168
  }
1166
1169
  if (result.value) {
1167
1170
  return /* @__PURE__ */ jsxs2("div", { className: "brand-calc-tok--result shrink-0 tabular-nums text-calc-result", children: [
1168
- /* @__PURE__ */ jsx2("span", { className: "sr-only", children: "equals " }),
1171
+ /* @__PURE__ */ jsx2("span", { className: "sr-only", children: t("editor.calcBlock.equals") }),
1169
1172
  /* @__PURE__ */ jsx2("span", { children: result.value.display })
1170
1173
  ] });
1171
1174
  }
@@ -1177,12 +1180,14 @@ var CalcBlock = forwardRef(function CalcBlock2({
1177
1180
  title,
1178
1181
  showTotal = true,
1179
1182
  total,
1180
- totalLabel = "Total",
1183
+ totalLabel: totalLabelProp,
1181
1184
  markers = true,
1182
1185
  readOnly: _readOnly,
1183
1186
  className,
1184
1187
  ...props
1185
1188
  }, ref) {
1189
+ const { t } = useLocale();
1190
+ const totalLabel = totalLabelProp ?? t("editor.calcBlock.total");
1186
1191
  const { lines, evalSource, hints } = useMemo(() => {
1187
1192
  const raw = source.split("\n");
1188
1193
  if (!markers) return { lines: raw, evalSource: source, hints: [] };
@@ -1264,7 +1269,7 @@ var CalcBlock = forwardRef(function CalcBlock2({
1264
1269
  children: resolvedTitle
1265
1270
  }
1266
1271
  ) }),
1267
- empty ? /* @__PURE__ */ jsx2("p", { className: "px-4 py-6 text-body text-muted-foreground", children: "Empty calc block." }) : /* @__PURE__ */ jsx2("div", { className: "flex flex-col gap-y-1 px-4 py-3 font-mono text-code leading-relaxed", children: rows }),
1272
+ empty ? /* @__PURE__ */ jsx2("p", { className: "px-4 py-6 text-body text-muted-foreground", children: t("editor.calcBlock.emptyBlock") }) : /* @__PURE__ */ jsx2("div", { className: "flex flex-col gap-y-1 px-4 py-3 font-mono text-code leading-relaxed", children: rows }),
1268
1273
  showTotal && resolvedTotal != null && !empty ? /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between border-t border-border px-4 py-2", children: [
1269
1274
  /* @__PURE__ */ jsx2("span", { className: "text-meta font-medium uppercase tracking-wide text-muted-foreground", children: totalLabel }),
1270
1275
  /* @__PURE__ */ jsx2("span", { className: "font-mono text-code font-medium tabular-nums text-foreground", children: totalDisplay })
@@ -1323,14 +1328,14 @@ var CalcInline = forwardRef2(function CalcInline2({ source, evaluate, className,
1323
1328
  });
1324
1329
 
1325
1330
  // src/mermaid-diagram/mermaid-diagram.tsx
1326
- import { Button as Button2, Dialog, DialogContent, DialogTitle } from "@elabs-ai/components-ui";
1331
+ import { Button as Button2, Dialog, DialogContent, DialogTitle, useLocale as useLocale3 } from "@elabs-ai/components-ui";
1327
1332
  import { cn as cn5 } from "@elabs-ai/components-ui/lib/cn";
1328
1333
  import { Download, Maximize2 } from "lucide-react";
1329
1334
  import { forwardRef as forwardRef3, useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
1330
1335
  import { oklchToHex } from "@elabs-ai/components-tokens";
1331
1336
 
1332
1337
  // src/mermaid-diagram/mermaid-viewer.tsx
1333
- import { Button, Input } from "@elabs-ai/components-ui";
1338
+ import { Button, Input, useLocale as useLocale2 } from "@elabs-ai/components-ui";
1334
1339
  import { cn as cn4 } from "@elabs-ai/components-ui/lib/cn";
1335
1340
  import { Maximize, Minus, Plus } from "lucide-react";
1336
1341
  import {
@@ -1366,6 +1371,7 @@ function diagramNodeLabel(node) {
1366
1371
  return parts.join(" \xB7 ");
1367
1372
  }
1368
1373
  function MermaidViewer({ svg, label }) {
1374
+ const { t } = useLocale2();
1369
1375
  const containerRef = useRef2(null);
1370
1376
  const stageRef = useRef2(null);
1371
1377
  const [transform, setTransform] = useState2({ scale: 1, tx: 0, ty: 0 });
@@ -1450,10 +1456,10 @@ function MermaidViewer({ svg, label }) {
1450
1456
  if (!container) return;
1451
1457
  userDrivenRef.current = true;
1452
1458
  const rect = container.getBoundingClientRect();
1453
- setTransform((t) => {
1454
- const scale = clampScale(t.scale * factor);
1455
- const px = (clientX - rect.left - t.tx) / t.scale;
1456
- const py = (clientY - rect.top - t.ty) / t.scale;
1459
+ setTransform((prev) => {
1460
+ const scale = clampScale(prev.scale * factor);
1461
+ const px = (clientX - rect.left - prev.tx) / prev.scale;
1462
+ const py = (clientY - rect.top - prev.ty) / prev.scale;
1457
1463
  return { scale, tx: clientX - rect.left - px * scale, ty: clientY - rect.top - py * scale };
1458
1464
  });
1459
1465
  }, []);
@@ -1470,12 +1476,12 @@ function MermaidViewer({ svg, label }) {
1470
1476
  if (!container || !svgEl || !node) return;
1471
1477
  userDrivenRef.current = true;
1472
1478
  setActiveHit(id);
1473
- setTransform((t) => {
1479
+ setTransform((prev) => {
1474
1480
  const nodeRect = node.getBoundingClientRect();
1475
1481
  const containerRect = container.getBoundingClientRect();
1476
- const cx = (nodeRect.left + nodeRect.width / 2 - containerRect.left - t.tx) / t.scale;
1477
- const cy = (nodeRect.top + nodeRect.height / 2 - containerRect.top - t.ty) / t.scale;
1478
- const scale = clampScale(Math.max(t.scale, 1.25));
1482
+ const cx = (nodeRect.left + nodeRect.width / 2 - containerRect.left - prev.tx) / prev.scale;
1483
+ const cy = (nodeRect.top + nodeRect.height / 2 - containerRect.top - prev.ty) / prev.scale;
1484
+ const scale = clampScale(Math.max(prev.scale, 1.25));
1479
1485
  return {
1480
1486
  scale,
1481
1487
  tx: containerRect.width / 2 - cx * scale,
@@ -1496,8 +1502,8 @@ function MermaidViewer({ svg, label }) {
1496
1502
  const onPointerMove = (e) => {
1497
1503
  const drag = dragRef.current;
1498
1504
  if (!drag) return;
1499
- setTransform((t) => ({
1500
- ...t,
1505
+ setTransform((prev) => ({
1506
+ ...prev,
1501
1507
  tx: drag.tx + (e.clientX - drag.x),
1502
1508
  ty: drag.ty + (e.clientY - drag.y)
1503
1509
  }));
@@ -1512,15 +1518,15 @@ function MermaidViewer({ svg, label }) {
1512
1518
  {
1513
1519
  autoFocus: true,
1514
1520
  type: "search",
1515
- placeholder: "Find in diagram\u2026",
1516
- "aria-label": "Find in diagram",
1521
+ placeholder: t("editor.mermaidViewer.findPlaceholder"),
1522
+ "aria-label": t("editor.mermaidViewer.findLabel"),
1517
1523
  value: query,
1518
1524
  onChange: (e) => setQuery(e.target.value),
1519
1525
  spellCheck: false,
1520
1526
  className: "h-8 text-body"
1521
1527
  }
1522
1528
  ),
1523
- /* @__PURE__ */ jsx4("p", { "aria-live": "polite", className: "px-1 pt-1.5 text-meta text-muted-foreground tabular-nums", children: q.length >= 2 ? `${matches.length} ${matches.length === 1 ? "node" : "nodes"}` : `${hits.length} nodes \xB7 type to filter` }),
1529
+ /* @__PURE__ */ jsx4("p", { "aria-live": "polite", className: "px-1 pt-1.5 text-meta text-muted-foreground tabular-nums", children: q.length >= 2 ? t("editor.mermaidViewer.matchCount", { count: matches.length }) : t("editor.mermaidViewer.nodeCountHint", { count: hits.length }) }),
1524
1530
  /* @__PURE__ */ jsx4("ul", { className: "m-0 mt-1 min-h-0 flex-1 list-none overflow-auto p-0", children: (q.length >= 2 ? matches : hits).map((hit) => /* @__PURE__ */ jsx4("li", { children: /* @__PURE__ */ jsx4(
1525
1531
  "button",
1526
1532
  {
@@ -1530,7 +1536,7 @@ function MermaidViewer({ svg, label }) {
1530
1536
  className: cn4(
1531
1537
  "w-full truncate rounded-md px-2 py-1.5 text-start text-caption transition-colors duration-fast ease-standard motion-reduce:transition-none",
1532
1538
  "hover:bg-accent hover:text-accent-foreground",
1533
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
1539
+ "focus-ring-inset",
1534
1540
  activeHit === hit.id ? "bg-accent font-medium text-foreground" : "text-muted-foreground"
1535
1541
  ),
1536
1542
  children: hit.label
@@ -1544,7 +1550,7 @@ function MermaidViewer({ svg, label }) {
1544
1550
  {
1545
1551
  variant: "outline",
1546
1552
  size: "icon-sm",
1547
- "aria-label": "Zoom out",
1553
+ "aria-label": t("editor.mermaidViewer.zoomOut"),
1548
1554
  onClick: () => zoomCenter(1 / 1.25),
1549
1555
  children: /* @__PURE__ */ jsx4(Minus, { className: "size-3.5" })
1550
1556
  }
@@ -1554,7 +1560,7 @@ function MermaidViewer({ svg, label }) {
1554
1560
  {
1555
1561
  variant: "outline",
1556
1562
  size: "icon-sm",
1557
- "aria-label": "Zoom in",
1563
+ "aria-label": t("editor.mermaidViewer.zoomIn"),
1558
1564
  onClick: () => zoomCenter(1.25),
1559
1565
  children: /* @__PURE__ */ jsx4(Plus, { className: "size-3.5" })
1560
1566
  }
@@ -1565,10 +1571,10 @@ function MermaidViewer({ svg, label }) {
1565
1571
  variant: "outline",
1566
1572
  size: "sm",
1567
1573
  className: "h-7 px-2 font-mono text-meta tabular-nums",
1568
- "aria-label": "Reset zoom to 100%",
1574
+ "aria-label": t("editor.mermaidViewer.resetZoom"),
1569
1575
  onClick: () => {
1570
1576
  userDrivenRef.current = true;
1571
- setTransform((t) => ({ ...t, scale: 1 }));
1577
+ setTransform((prev) => ({ ...prev, scale: 1 }));
1572
1578
  },
1573
1579
  children: [
1574
1580
  Math.round(transform.scale * 100),
@@ -1581,7 +1587,7 @@ function MermaidViewer({ svg, label }) {
1581
1587
  {
1582
1588
  variant: "outline",
1583
1589
  size: "icon-sm",
1584
- "aria-label": "Fit diagram",
1590
+ "aria-label": t("editor.mermaidViewer.fitDiagram"),
1585
1591
  onClick: () => {
1586
1592
  userDrivenRef.current = false;
1587
1593
  fit();
@@ -1735,6 +1741,16 @@ var TOKEN_VARS = {
1735
1741
  errorTextColor: "--destructive-foreground"
1736
1742
  };
1737
1743
  var renderSeq = 0;
1744
+ var mermaidRenderQueue = Promise.resolve();
1745
+ function withMermaidLock(task) {
1746
+ const result = mermaidRenderQueue.then(task, task);
1747
+ mermaidRenderQueue = result.then(
1748
+ () => void 0,
1749
+ () => void 0
1750
+ );
1751
+ return result;
1752
+ }
1753
+ var RENDER_DEBOUNCE_MS = 300;
1738
1754
  var HIT_CSS = `
1739
1755
  .wb-dg-hit :is(rect, polygon, circle, ellipse, path.basic) { stroke: var(--warning) !important; stroke-width: 2.5px !important; }
1740
1756
  .wb-dg-hit-active :is(rect, polygon, circle, ellipse, path.basic) { stroke: var(--primary) !important; stroke-width: 3px !important; }
@@ -1777,7 +1793,7 @@ function resolveThemeVariables(el) {
1777
1793
  var MermaidDiagram = forwardRef3(
1778
1794
  function MermaidDiagram2({
1779
1795
  chart,
1780
- label = "Diagram",
1796
+ label: labelProp,
1781
1797
  copyable = true,
1782
1798
  expandable = true,
1783
1799
  highlightTerm,
@@ -1785,6 +1801,8 @@ var MermaidDiagram = forwardRef3(
1785
1801
  className,
1786
1802
  ...props
1787
1803
  }, ref) {
1804
+ const { t } = useLocale3();
1805
+ const label = labelProp ?? t("editor.mermaidDiagram.label");
1788
1806
  const hostRef = useRef3(null);
1789
1807
  const svgHostRef = useRef3(null);
1790
1808
  const [svg, setSvg] = useState3(null);
@@ -1798,7 +1816,7 @@ var MermaidDiagram = forwardRef3(
1798
1816
  a.href = url;
1799
1817
  a.download = `${label.toLowerCase().replace(/[^a-z0-9]+/g, "-") || "diagram"}.svg`;
1800
1818
  a.click();
1801
- URL.revokeObjectURL(url);
1819
+ setTimeout(() => URL.revokeObjectURL(url), 0);
1802
1820
  };
1803
1821
  const [themeVersion, setThemeVersion] = useState3(0);
1804
1822
  useEffect3(() => {
@@ -1817,40 +1835,44 @@ var MermaidDiagram = forwardRef3(
1817
1835
  setError(null);
1818
1836
  return;
1819
1837
  }
1820
- (async () => {
1821
- try {
1822
- const mermaid = (await import("mermaid")).default;
1838
+ const timer = setTimeout(() => {
1839
+ void withMermaidLock(async () => {
1823
1840
  if (cancelled) return;
1824
- mermaid.initialize({
1825
- startOnLoad: false,
1826
- securityLevel: "strict",
1827
- suppressErrorRendering: true,
1828
- theme: "base",
1829
- themeVariables: resolveThemeVariables(host)
1830
- });
1831
- const render = (source) => mermaid.render(`brand-mermaid-${++renderSeq}`, source);
1832
- let out;
1833
1841
  try {
1834
- out = await render(chart);
1835
- } catch (firstErr) {
1836
- const token = offendingToken(
1837
- firstErr instanceof Error ? firstErr.message : String(firstErr)
1838
- );
1839
- const fixed = token ? remediateReservedIds(chart, token) : null;
1840
- if (!fixed) throw firstErr;
1841
- out = await render(fixed);
1842
+ const mermaid = (await import("mermaid")).default;
1843
+ if (cancelled) return;
1844
+ mermaid.initialize({
1845
+ startOnLoad: false,
1846
+ securityLevel: "strict",
1847
+ suppressErrorRendering: true,
1848
+ theme: "base",
1849
+ themeVariables: resolveThemeVariables(host)
1850
+ });
1851
+ const render = (source) => mermaid.render(`brand-mermaid-${++renderSeq}`, source);
1852
+ let out;
1853
+ try {
1854
+ out = await render(chart);
1855
+ } catch (firstErr) {
1856
+ const token = offendingToken(
1857
+ firstErr instanceof Error ? firstErr.message : String(firstErr)
1858
+ );
1859
+ const fixed = token ? remediateReservedIds(chart, token) : null;
1860
+ if (!fixed) throw firstErr;
1861
+ out = await render(fixed);
1862
+ }
1863
+ if (cancelled) return;
1864
+ setSvg(out.svg);
1865
+ setError(null);
1866
+ } catch (err) {
1867
+ if (cancelled) return;
1868
+ setSvg(null);
1869
+ setError(err instanceof Error ? err.message : String(err));
1842
1870
  }
1843
- if (cancelled) return;
1844
- setSvg(out.svg);
1845
- setError(null);
1846
- } catch (err) {
1847
- if (cancelled) return;
1848
- setSvg(null);
1849
- setError(err instanceof Error ? err.message : String(err));
1850
- }
1851
- })();
1871
+ });
1872
+ }, RENDER_DEBOUNCE_MS);
1852
1873
  return () => {
1853
1874
  cancelled = true;
1875
+ clearTimeout(timer);
1854
1876
  };
1855
1877
  }, [chart, themeVersion]);
1856
1878
  useEffect3(() => {
@@ -1886,7 +1908,7 @@ var MermaidDiagram = forwardRef3(
1886
1908
  {
1887
1909
  variant: "outline",
1888
1910
  size: "icon-sm",
1889
- "aria-label": "Expand diagram",
1911
+ "aria-label": t("editor.mermaidDiagram.expand"),
1890
1912
  onClick: () => setExpanded(true),
1891
1913
  children: /* @__PURE__ */ jsx5(Maximize2, { className: "size-3.5" })
1892
1914
  }
@@ -1896,7 +1918,7 @@ var MermaidDiagram = forwardRef3(
1896
1918
  {
1897
1919
  variant: "outline",
1898
1920
  size: "icon-sm",
1899
- "aria-label": "Download diagram as SVG",
1921
+ "aria-label": t("editor.mermaidDiagram.downloadSvg"),
1900
1922
  onClick: downloadSvg,
1901
1923
  children: /* @__PURE__ */ jsx5(Download, { className: "size-3.5" })
1902
1924
  }
@@ -1906,7 +1928,7 @@ var MermaidDiagram = forwardRef3(
1906
1928
  {
1907
1929
  value: chart,
1908
1930
  label: false,
1909
- "aria-label": "Copy diagram source",
1931
+ "aria-label": t("editor.mermaidDiagram.copySource"),
1910
1932
  size: "icon-sm"
1911
1933
  }
1912
1934
  ) : null
@@ -1917,7 +1939,7 @@ var MermaidDiagram = forwardRef3(
1917
1939
  role: "alert",
1918
1940
  className: "space-y-2 border-s-2 border-s-destructive bg-destructive/10 p-3 text-body",
1919
1941
  children: [
1920
- /* @__PURE__ */ jsx5("p", { className: "font-medium text-destructive-text", children: "Diagram failed to render" }),
1942
+ /* @__PURE__ */ jsx5("p", { className: "font-medium text-destructive-text", children: t("editor.mermaidDiagram.renderFailed") }),
1921
1943
  /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground", children: error }),
1922
1944
  /* @__PURE__ */ jsx5("pre", { className: "overflow-x-auto rounded bg-muted p-2 font-mono text-code text-foreground", children: chart })
1923
1945
  ]
@@ -1938,7 +1960,7 @@ var MermaidDiagram = forwardRef3(
1938
1960
  "div",
1939
1961
  {
1940
1962
  role: "status",
1941
- "aria-label": "Rendering diagram\u2026",
1963
+ "aria-label": t("editor.mermaidDiagram.rendering"),
1942
1964
  className: "h-24 animate-pulse rounded-md bg-surface-muted motion-reduce:animate-none"
1943
1965
  }
1944
1966
  ),
@@ -2098,7 +2120,7 @@ import remarkMath from "remark-math";
2098
2120
 
2099
2121
  // src/markdown-academic/citations.tsx
2100
2122
  import { cn as cn7 } from "@elabs-ai/components-ui/lib/cn";
2101
- import { Separator } from "@elabs-ai/components-ui";
2123
+ import { Separator, useLocale as useLocale4 } from "@elabs-ai/components-ui";
2102
2124
  import {
2103
2125
  createContext,
2104
2126
  forwardRef as forwardRef4,
@@ -2198,14 +2220,15 @@ function hoverTitle(data) {
2198
2220
  return parts.join(". ");
2199
2221
  }
2200
2222
  function CiteLink({ entry, label }) {
2223
+ const { t } = useLocale4();
2201
2224
  const name = entry.data ? hoverTitle(entry.data) : entry.key;
2202
2225
  return /* @__PURE__ */ jsx7(
2203
2226
  "a",
2204
2227
  {
2205
2228
  href: `#ref-${cssId(entry.key)}`,
2206
2229
  title: entry.data ? hoverTitle(entry.data) : void 0,
2207
- "aria-label": `Citation: ${name}`,
2208
- className: "text-primary-text underline hover:underline focus-visible:rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2230
+ "aria-label": t("editor.citations.citationLabel", { name }),
2231
+ className: "text-link underline hover:underline focus-visible:rounded-sm focus-ring",
2209
2232
  children: label
2210
2233
  }
2211
2234
  );
@@ -2223,6 +2246,7 @@ function readCite(rest) {
2223
2246
  }
2224
2247
  }
2225
2248
  function InlineCite({ node: _n, children: _c, ...rest }) {
2249
+ const { t } = useLocale4();
2226
2250
  const ctx = useContext(CitationContext);
2227
2251
  const payload = readCite(rest);
2228
2252
  if (!payload) return null;
@@ -2230,7 +2254,7 @@ function InlineCite({ node: _n, children: _c, ...rest }) {
2230
2254
  const resolved = payload.items.map((it) => ({ it, entry: ctx.byKey.get(it.key) }));
2231
2255
  const anyResolved = resolved.some((r) => r.entry?.data);
2232
2256
  if (!anyResolved) {
2233
- return /* @__PURE__ */ jsx7("span", { className: "text-muted-foreground", title: "Unresolved citation", children: payload.original });
2257
+ return /* @__PURE__ */ jsx7("span", { className: "text-muted-foreground", title: t("editor.citations.unresolvedCitation"), children: payload.original });
2234
2258
  }
2235
2259
  const numeric = ctx.style === "numeric";
2236
2260
  const open = numeric ? "[" : "(";
@@ -2242,7 +2266,14 @@ function InlineCite({ node: _n, children: _c, ...rest }) {
2242
2266
  const label = numeric ? numericLabel(it, entry) : authorYearLabel(it, entry);
2243
2267
  return /* @__PURE__ */ jsxs7("span", { children: [
2244
2268
  i > 0 ? sep : null,
2245
- entry?.data ? /* @__PURE__ */ jsx7(CiteLink, { entry, label }) : /* @__PURE__ */ jsx7("span", { className: "text-muted-foreground", title: `Unresolved: @${it.key}`, children: label })
2269
+ entry?.data ? /* @__PURE__ */ jsx7(CiteLink, { entry, label }) : /* @__PURE__ */ jsx7(
2270
+ "span",
2271
+ {
2272
+ className: "text-muted-foreground",
2273
+ title: t("editor.citations.unresolvedKey", { key: it.key }),
2274
+ children: label
2275
+ }
2276
+ )
2246
2277
  ] }, `${it.key}-${i}`);
2247
2278
  }),
2248
2279
  close
@@ -2276,7 +2307,9 @@ function referenceHref(data) {
2276
2307
  if (data.doi) return `https://doi.org/${data.doi}`;
2277
2308
  return void 0;
2278
2309
  }
2279
- var Bibliography = forwardRef4(function Bibliography2({ entries, style, title = "References", className, ...props }, ref) {
2310
+ var Bibliography = forwardRef4(function Bibliography2({ entries, style, title: titleProp, className, ...props }, ref) {
2311
+ const { t } = useLocale4();
2312
+ const title = titleProp ?? t("editor.citations.references");
2280
2313
  const ctx = useContext(CitationContext);
2281
2314
  const labelId = useId2();
2282
2315
  const list = entries ?? ctx?.order ?? [];
@@ -2310,7 +2343,7 @@ var Bibliography = forwardRef4(function Bibliography2({ entries, style, title =
2310
2343
  href,
2311
2344
  target: "_blank",
2312
2345
  rel: "noopener noreferrer",
2313
- className: "break-words text-primary-text underline underline-offset-2 hover:underline focus-visible:rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2346
+ className: "break-words text-link underline underline-offset-2 hover:underline focus-visible:rounded-sm focus-ring",
2314
2347
  children: data.url ?? `doi:${data.doi}`
2315
2348
  }
2316
2349
  ) : null
@@ -2413,7 +2446,7 @@ function FootnoteRef({ node: _n, children: _c, ...rest }) {
2413
2446
  href: `#fn-${id}`,
2414
2447
  "data-footnote-ref": "",
2415
2448
  "aria-label": `Footnote ${n}`,
2416
- className: "px-0.5 font-medium text-primary-text underline tabular-nums hover:underline focus-visible:rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2449
+ className: "px-0.5 font-medium text-link underline tabular-nums hover:underline focus-visible:rounded-sm focus-ring",
2417
2450
  children: n
2418
2451
  }
2419
2452
  ) });
@@ -2437,7 +2470,7 @@ function FootnoteItem({ node: _n, children, ...rest }) {
2437
2470
  href: `#${refId}`,
2438
2471
  "data-footnote-backref": "",
2439
2472
  "aria-label": refList.length > 1 ? `Back to reference ${n}, mention ${i + 1}` : `Back to reference ${n}`,
2440
- className: "ms-0.5 inline-flex items-center text-muted-foreground no-underline hover:text-foreground focus-visible:rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2473
+ className: "ms-0.5 inline-flex items-center text-muted-foreground no-underline hover:text-foreground focus-visible:rounded-sm focus-ring",
2441
2474
  children: [
2442
2475
  /* @__PURE__ */ jsx8("span", { "aria-hidden": "true", children: "\u21A9" }),
2443
2476
  refList.length > 1 ? /* @__PURE__ */ jsx8("sub", { className: "ms-0.5 leading-none tabular-nums", children: i + 1 }) : null
@@ -2459,6 +2492,7 @@ var FootnoteList = forwardRef5(function FootnoteList2({ className, children, ...
2459
2492
  });
2460
2493
 
2461
2494
  // src/markdown-academic/math.tsx
2495
+ import { useLocale as useLocale5 } from "@elabs-ai/components-ui";
2462
2496
  import { cn as cn9 } from "@elabs-ai/components-ui/lib/cn";
2463
2497
  import katex from "katex";
2464
2498
  import { useMemo as useMemo4 } from "react";
@@ -2508,14 +2542,15 @@ function renderKatex(tex, displayMode) {
2508
2542
  }
2509
2543
  }
2510
2544
  function MathInline({ tex, className, ...props }) {
2545
+ const { t } = useLocale5();
2511
2546
  const { html, error } = useMemo4(() => renderKatex(tex, false), [tex]);
2512
2547
  if (error) {
2513
2548
  return /* @__PURE__ */ jsx9(
2514
2549
  "code",
2515
2550
  {
2516
2551
  className: cn9("text-destructive-text", className),
2517
- "aria-label": `Math (could not render): ${tex}`,
2518
- title: "Could not render math",
2552
+ "aria-label": t("editor.math.renderErrorLabel", { tex }),
2553
+ title: t("editor.math.renderError"),
2519
2554
  ...props,
2520
2555
  children: tex
2521
2556
  }
@@ -2533,6 +2568,7 @@ function MathInline({ tex, className, ...props }) {
2533
2568
  );
2534
2569
  }
2535
2570
  function MathBlock({ tex, className, ...props }) {
2571
+ const { t } = useLocale5();
2536
2572
  const { html, error } = useMemo4(() => renderKatex(tex, true), [tex]);
2537
2573
  if (error) {
2538
2574
  return /* @__PURE__ */ jsx9(
@@ -2542,8 +2578,8 @@ function MathBlock({ tex, className, ...props }) {
2542
2578
  "overflow-x-auto rounded-md bg-surface-muted p-3 text-destructive-text",
2543
2579
  className
2544
2580
  ),
2545
- "aria-label": `Math (could not render): ${tex}`,
2546
- title: "Could not render math",
2581
+ "aria-label": t("editor.math.renderErrorLabel", { tex }),
2582
+ title: t("editor.math.renderError"),
2547
2583
  ...props,
2548
2584
  children: /* @__PURE__ */ jsx9("code", { children: tex })
2549
2585
  }
@@ -2596,7 +2632,7 @@ var TableOfContents = forwardRef6(
2596
2632
  "a",
2597
2633
  {
2598
2634
  href: `#${it.id}`,
2599
- className: "text-muted-foreground underline hover:text-foreground hover:underline focus-visible:rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
2635
+ className: "text-muted-foreground underline hover:text-foreground hover:underline focus-visible:rounded-sm focus-ring",
2600
2636
  children: it.text
2601
2637
  }
2602
2638
  ) }, it.id)) })
@@ -3453,7 +3489,8 @@ import {
3453
3489
  Tooltip,
3454
3490
  TooltipContent,
3455
3491
  TooltipProvider,
3456
- TooltipTrigger
3492
+ TooltipTrigger,
3493
+ useLocale as useLocale6
3457
3494
  } from "@elabs-ai/components-ui";
3458
3495
  import { cn as cn12 } from "@elabs-ai/components-ui/lib/cn";
3459
3496
  import {
@@ -3472,24 +3509,38 @@ import {
3472
3509
  import { forwardRef as forwardRef8, Fragment as Fragment3 } from "react";
3473
3510
  import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
3474
3511
  var DIRECTIVE_SNIPPETS = [
3475
- { label: "Card", snippet: `:::card{title="Title"}
3512
+ {
3513
+ labelKey: "editor.markdownToolbar.directiveCard",
3514
+ snippet: `:::card{title="Title"}
3476
3515
  Content
3477
- :::` },
3478
- { label: "Callout", snippet: `:::callout{type="info" title="Note"}
3516
+ :::`
3517
+ // i18n-exempt: example document content
3518
+ },
3519
+ {
3520
+ labelKey: "editor.markdownToolbar.directiveCallout",
3521
+ snippet: `:::callout{type="info" title="Note"}
3479
3522
  Message
3480
- :::` },
3481
- { label: "Metric", snippet: `::metric{label="Label" value="0" description="detail"}` },
3523
+ :::`
3524
+ // i18n-exempt: example document content
3525
+ },
3526
+ {
3527
+ labelKey: "editor.markdownToolbar.directiveMetric",
3528
+ snippet: `::metric{label="Label" value="0" description="detail"}`
3529
+ // i18n-exempt: example document content
3530
+ },
3482
3531
  {
3483
- label: "Timeline",
3532
+ labelKey: "editor.markdownToolbar.directiveTimeline",
3484
3533
  snippet: `:::timeline
3485
3534
  - (done) Step one
3486
3535
  - (active) Step two
3487
3536
  - (pending) Step three
3488
3537
  :::`
3538
+ // i18n-exempt: example document content
3489
3539
  }
3490
3540
  ];
3491
3541
  var MarkdownToolbar = forwardRef8(
3492
3542
  function MarkdownToolbar2({ editor: editor2, actions, insertCommands, className, ...props }, ref) {
3543
+ const { t } = useLocale6();
3493
3544
  const disabled = !editor2;
3494
3545
  const run = (fn) => () => {
3495
3546
  if (editor2) fn(editor2);
@@ -3521,7 +3572,7 @@ var MarkdownToolbar = forwardRef8(
3521
3572
  {
3522
3573
  ref,
3523
3574
  role: "toolbar",
3524
- "aria-label": "Markdown formatting",
3575
+ "aria-label": t("editor.markdownToolbar.label"),
3525
3576
  className: cn12(
3526
3577
  "flex h-10 shrink-0 items-center gap-0.5 border-b border-border bg-surface px-2",
3527
3578
  className
@@ -3531,7 +3582,7 @@ var MarkdownToolbar = forwardRef8(
3531
3582
  /* @__PURE__ */ jsx13(
3532
3583
  IconButton,
3533
3584
  {
3534
- label: "Bold",
3585
+ label: t("editor.markdownToolbar.bold"),
3535
3586
  icon: /* @__PURE__ */ jsx13(Bold, { className: "size-4" }),
3536
3587
  onClick: run((e) => wrapSelection(e, "**"))
3537
3588
  }
@@ -3539,7 +3590,7 @@ var MarkdownToolbar = forwardRef8(
3539
3590
  /* @__PURE__ */ jsx13(
3540
3591
  IconButton,
3541
3592
  {
3542
- label: "Italic",
3593
+ label: t("editor.markdownToolbar.italic"),
3543
3594
  icon: /* @__PURE__ */ jsx13(Italic, { className: "size-4" }),
3544
3595
  onClick: run((e) => wrapSelection(e, "*"))
3545
3596
  }
@@ -3547,12 +3598,19 @@ var MarkdownToolbar = forwardRef8(
3547
3598
  /* @__PURE__ */ jsx13(
3548
3599
  IconButton,
3549
3600
  {
3550
- label: "Inline code",
3601
+ label: t("editor.markdownToolbar.inlineCode"),
3551
3602
  icon: /* @__PURE__ */ jsx13(Code2, { className: "size-4" }),
3552
3603
  onClick: run((e) => wrapSelection(e, "`"))
3553
3604
  }
3554
3605
  ),
3555
- /* @__PURE__ */ jsx13(IconButton, { label: "Link", icon: /* @__PURE__ */ jsx13(Link2, { className: "size-4" }), onClick: run(insertLink) }),
3606
+ /* @__PURE__ */ jsx13(
3607
+ IconButton,
3608
+ {
3609
+ label: t("editor.markdownToolbar.link"),
3610
+ icon: /* @__PURE__ */ jsx13(Link2, { className: "size-4" }),
3611
+ onClick: run(insertLink)
3612
+ }
3613
+ ),
3556
3614
  /* @__PURE__ */ jsx13(Separator4, { orientation: "vertical", className: "mx-1 h-5" }),
3557
3615
  /* @__PURE__ */ jsxs11(DropdownMenu, { children: [
3558
3616
  /* @__PURE__ */ jsxs11(Tooltip, { children: [
@@ -3564,23 +3622,20 @@ var MarkdownToolbar = forwardRef8(
3564
3622
  size: "sm",
3565
3623
  disabled,
3566
3624
  className: "gap-1",
3567
- "aria-label": "Heading level",
3625
+ "aria-label": t("editor.markdownToolbar.headingLevel"),
3568
3626
  children: [
3569
3627
  /* @__PURE__ */ jsx13(Heading, { className: "size-4" }),
3570
3628
  /* @__PURE__ */ jsx13(ChevronDown, { className: "size-3" })
3571
3629
  ]
3572
3630
  }
3573
3631
  ) }) }),
3574
- /* @__PURE__ */ jsx13(TooltipContent, { children: "Heading" })
3632
+ /* @__PURE__ */ jsx13(TooltipContent, { children: t("editor.markdownToolbar.heading") })
3575
3633
  ] }),
3576
- /* @__PURE__ */ jsx13(DropdownMenuContent, { align: "start", children: [1, 2, 3].map((level) => /* @__PURE__ */ jsxs11(
3634
+ /* @__PURE__ */ jsx13(DropdownMenuContent, { align: "start", children: [1, 2, 3].map((level) => /* @__PURE__ */ jsx13(
3577
3635
  DropdownMenuItem,
3578
3636
  {
3579
3637
  onSelect: run((e) => toggleLinePrefix(e, `${"#".repeat(level)} `)),
3580
- children: [
3581
- "Heading ",
3582
- level
3583
- ]
3638
+ children: t("editor.markdownToolbar.headingLevelItem", { level })
3584
3639
  },
3585
3640
  level
3586
3641
  )) })
@@ -3588,7 +3643,7 @@ var MarkdownToolbar = forwardRef8(
3588
3643
  /* @__PURE__ */ jsx13(
3589
3644
  IconButton,
3590
3645
  {
3591
- label: "Quote",
3646
+ label: t("editor.markdownToolbar.quote"),
3592
3647
  icon: /* @__PURE__ */ jsx13(Quote, { className: "size-4" }),
3593
3648
  onClick: run((e) => toggleLinePrefix(e, "> "))
3594
3649
  }
@@ -3596,7 +3651,7 @@ var MarkdownToolbar = forwardRef8(
3596
3651
  /* @__PURE__ */ jsx13(
3597
3652
  IconButton,
3598
3653
  {
3599
- label: "Bullet list",
3654
+ label: t("editor.markdownToolbar.bulletList"),
3600
3655
  icon: /* @__PURE__ */ jsx13(List, { className: "size-4" }),
3601
3656
  onClick: run((e) => toggleLinePrefix(e, "- "))
3602
3657
  }
@@ -3604,7 +3659,7 @@ var MarkdownToolbar = forwardRef8(
3604
3659
  /* @__PURE__ */ jsx13(
3605
3660
  IconButton,
3606
3661
  {
3607
- label: "Numbered list",
3662
+ label: t("editor.markdownToolbar.numberedList"),
3608
3663
  icon: /* @__PURE__ */ jsx13(ListOrdered, { className: "size-4" }),
3609
3664
  onClick: run((e) => toggleLinePrefix(e, "1. "))
3610
3665
  }
@@ -3612,7 +3667,7 @@ var MarkdownToolbar = forwardRef8(
3612
3667
  /* @__PURE__ */ jsx13(
3613
3668
  IconButton,
3614
3669
  {
3615
- label: "Divider",
3670
+ label: t("editor.markdownToolbar.divider"),
3616
3671
  icon: /* @__PURE__ */ jsx13(Minus2, { className: "size-4" }),
3617
3672
  onClick: run(insertHorizontalRule)
3618
3673
  }
@@ -3628,14 +3683,14 @@ var MarkdownToolbar = forwardRef8(
3628
3683
  size: "sm",
3629
3684
  disabled,
3630
3685
  className: "gap-1",
3631
- "aria-label": "Insert block",
3686
+ "aria-label": t("editor.markdownToolbar.insertBlock"),
3632
3687
  children: [
3633
3688
  /* @__PURE__ */ jsx13(SquarePlus, { className: "size-4" }),
3634
- /* @__PURE__ */ jsx13("span", { className: "text-xs", children: "Insert" })
3689
+ /* @__PURE__ */ jsx13("span", { className: "text-xs", children: t("editor.markdownToolbar.insert") })
3635
3690
  ]
3636
3691
  }
3637
3692
  ) }) }),
3638
- /* @__PURE__ */ jsx13(TooltipContent, { children: "Insert brand block" })
3693
+ /* @__PURE__ */ jsx13(TooltipContent, { children: t("editor.markdownToolbar.insertBrandBlock") })
3639
3694
  ] }),
3640
3695
  /* @__PURE__ */ jsx13(DropdownMenuContent, { align: "start", children: insertGroups && insertGroups.length > 0 ? insertGroups.map(({ group, commands }, gi) => /* @__PURE__ */ jsxs11(Fragment3, { children: [
3641
3696
  gi > 0 ? /* @__PURE__ */ jsx13(DropdownMenuSeparator, {}) : null,
@@ -3652,13 +3707,13 @@ var MarkdownToolbar = forwardRef8(
3652
3707
  },
3653
3708
  cmd.id
3654
3709
  ))
3655
- ] }, group)) : DIRECTIVE_SNIPPETS.map(({ label, snippet }) => /* @__PURE__ */ jsx13(
3710
+ ] }, group)) : DIRECTIVE_SNIPPETS.map(({ labelKey, snippet }) => /* @__PURE__ */ jsx13(
3656
3711
  DropdownMenuItem,
3657
3712
  {
3658
3713
  onSelect: run((e) => insertDirective(e, snippet)),
3659
- children: label
3714
+ children: t(labelKey)
3660
3715
  },
3661
- label
3716
+ labelKey
3662
3717
  )) })
3663
3718
  ] }),
3664
3719
  actions ? /* @__PURE__ */ jsx13("div", { className: "ml-auto flex items-center gap-1.5", children: actions }) : null
@@ -3712,6 +3767,7 @@ var MarkdownWorkspace = forwardRef9(
3712
3767
  className,
3713
3768
  ...props
3714
3769
  }, ref) {
3770
+ const { t } = useLocale7();
3715
3771
  const slashCommandList = typeof slashMenu === "object" && slashMenu.commands ? slashMenu.commands : BRAND_SLASH_COMMANDS;
3716
3772
  const toolbarInsertCommands = insertCommands ?? slashCommandList;
3717
3773
  const isControlled = value !== void 0;
@@ -4052,15 +4108,16 @@ var MarkdownWorkspace = forwardRef9(
4052
4108
  size: "sm",
4053
4109
  pressed: focusWritingOn,
4054
4110
  onPressedChange: setFocusWritingOn,
4055
- "aria-label": "Focus writing",
4111
+ "aria-label": t("editor.markdownWorkspace.focusWriting"),
4056
4112
  className: "h-6 gap-1.5 px-2 text-caption",
4057
4113
  children: [
4058
4114
  /* @__PURE__ */ jsx14(Focus, { className: "size-3.5", "aria-hidden": "true" }),
4059
- " Focus"
4115
+ " ",
4116
+ t("editor.markdownWorkspace.focus")
4060
4117
  ]
4061
4118
  }
4062
4119
  ) }),
4063
- /* @__PURE__ */ jsx14(TooltipContent2, { children: "Typewriter scrolling \xB7 inactive paragraphs dim" })
4120
+ /* @__PURE__ */ jsx14(TooltipContent2, { children: t("editor.markdownWorkspace.focusWritingHint") })
4064
4121
  ] }) }) : null,
4065
4122
  trailing
4066
4123
  ] }) : /* @__PURE__ */ jsx14(
@@ -4177,7 +4234,8 @@ import {
4177
4234
  Card as Card2,
4178
4235
  CardContent as CardContent2,
4179
4236
  CardHeader as CardHeader2,
4180
- Separator as Separator5
4237
+ Separator as Separator5,
4238
+ useLocale as useLocale8
4181
4239
  } from "@elabs-ai/components-ui";
4182
4240
  import { cn as cn15 } from "@elabs-ai/components-ui/lib/cn";
4183
4241
  import { cva } from "class-variance-authority";
@@ -4193,11 +4251,11 @@ var STATUS_BADGE_VARIANT = {
4193
4251
  proposed: "info",
4194
4252
  superseded: "secondary"
4195
4253
  };
4196
- var STATUS_LABELS = {
4197
- accepted: "Accepted",
4198
- rejected: "Rejected",
4199
- proposed: "Proposed",
4200
- superseded: "Superseded"
4254
+ var STATUS_LABEL_KEYS = {
4255
+ accepted: "editor.decisionCard.statusAccepted",
4256
+ rejected: "editor.decisionCard.statusRejected",
4257
+ proposed: "editor.decisionCard.statusProposed",
4258
+ superseded: "editor.decisionCard.statusSuperseded"
4201
4259
  };
4202
4260
  var STATUS_ICONS = {
4203
4261
  accepted: CheckCircle2,
@@ -4220,16 +4278,17 @@ var decisionCardVariants = cva("border-s-4", {
4220
4278
  defaultVariants: { status: "proposed" }
4221
4279
  });
4222
4280
  var DecisionCard = forwardRef11(function DecisionCard2({ status: rawStatus, date, alternatives, children, className, ...props }, ref) {
4281
+ const { t } = useLocale8();
4223
4282
  const status = isDecisionStatus(rawStatus ?? "") ? rawStatus : "proposed";
4224
4283
  const badgeVariant = STATUS_BADGE_VARIANT[status];
4225
- const label = STATUS_LABELS[status];
4284
+ const label = t(STATUS_LABEL_KEYS[status]);
4226
4285
  const Icon = STATUS_ICONS[status];
4227
4286
  const altItems = alternatives ? alternatives.split(",").map((s) => s.trim()).filter(Boolean) : [];
4228
4287
  return /* @__PURE__ */ jsx16(
4229
4288
  "section",
4230
4289
  {
4231
4290
  ref,
4232
- "aria-label": `Decision: ${label}`,
4291
+ "aria-label": t("editor.decisionCard.label", { label }),
4233
4292
  className: cn15("not-prose", className),
4234
4293
  ...props,
4235
4294
  children: /* @__PURE__ */ jsxs14(Card2, { className: cn15(decisionCardVariants({ status })), children: [
@@ -4244,8 +4303,15 @@ var DecisionCard = forwardRef11(function DecisionCard2({ status: rawStatus, date
4244
4303
  altItems.length > 0 ? /* @__PURE__ */ jsxs14(Fragment5, { children: [
4245
4304
  /* @__PURE__ */ jsx16(Separator5, {}),
4246
4305
  /* @__PURE__ */ jsxs14("div", { className: "px-6 py-4", children: [
4247
- /* @__PURE__ */ jsx16("p", { className: "mb-2 text-meta font-medium text-muted-foreground", children: "Alternatives considered" }),
4248
- /* @__PURE__ */ jsx16("ul", { className: "flex flex-wrap gap-1.5", "aria-label": "Alternatives considered", children: altItems.map((alt) => /* @__PURE__ */ jsx16("li", { children: /* @__PURE__ */ jsx16(Badge, { variant: "outline", className: "text-meta", children: alt }) }, alt)) })
4306
+ /* @__PURE__ */ jsx16("p", { className: "mb-2 text-meta font-medium text-muted-foreground", children: t("editor.decisionCard.alternativesConsidered") }),
4307
+ /* @__PURE__ */ jsx16(
4308
+ "ul",
4309
+ {
4310
+ className: "flex flex-wrap gap-1.5",
4311
+ "aria-label": t("editor.decisionCard.alternativesConsidered"),
4312
+ children: altItems.map((alt) => /* @__PURE__ */ jsx16("li", { children: /* @__PURE__ */ jsx16(Badge, { variant: "outline", className: "text-meta", children: alt }) }, alt))
4313
+ }
4314
+ )
4249
4315
  ] })
4250
4316
  ] }) : null
4251
4317
  ] })
@@ -4277,7 +4343,7 @@ function kindMeta(kind) {
4277
4343
  var entityChipVariants = cva2(
4278
4344
  // inline-flex + align-middle keeps the chip in the text baseline;
4279
4345
  // no `block` wrapper so it is valid inside <p>.
4280
- "inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 text-meta font-medium align-middle focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
4346
+ "inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 text-meta font-medium align-middle focus-ring",
4281
4347
  {
4282
4348
  variants: {
4283
4349
  kind: {
@@ -4360,12 +4426,13 @@ var EntityCard = forwardRef12(function EntityCard2({ kind: rawKind, name, childr
4360
4426
  });
4361
4427
 
4362
4428
  // src/ai-objects/knowledge-card.tsx
4363
- import { Card as Card4, CardContent as CardContent4, CardFooter } from "@elabs-ai/components-ui";
4429
+ import { Card as Card4, CardContent as CardContent4, CardFooter, useLocale as useLocale9 } from "@elabs-ai/components-ui";
4364
4430
  import { cn as cn17 } from "@elabs-ai/components-ui/lib/cn";
4365
4431
  import { BookOpen, FileText } from "lucide-react";
4366
4432
  import { forwardRef as forwardRef13 } from "react";
4367
4433
  import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
4368
4434
  function SourceRow({ path, resolve }) {
4435
+ const { t } = useLocale9();
4369
4436
  const resolved = resolve ? resolve(path) : null;
4370
4437
  const display = resolved?.title ?? path;
4371
4438
  if (resolved) {
@@ -4375,8 +4442,8 @@ function SourceRow({ path, resolve }) {
4375
4442
  href: resolved.href,
4376
4443
  rel: "noopener noreferrer",
4377
4444
  target: "_blank",
4378
- className: "flex min-w-0 items-center gap-1.5 text-meta text-primary-text underline-offset-2 hover:underline focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
4379
- "aria-label": `Source: ${display}`,
4445
+ className: "flex min-w-0 items-center gap-1.5 text-meta text-link underline-offset-2 hover:underline focus-ring",
4446
+ "aria-label": t("editor.knowledgeCard.source", { name: display }),
4380
4447
  children: [
4381
4448
  /* @__PURE__ */ jsx18(FileText, { className: "size-3 shrink-0", "aria-hidden": "true" }),
4382
4449
  /* @__PURE__ */ jsx18("span", { className: "truncate", children: display })
@@ -4388,7 +4455,7 @@ function SourceRow({ path, resolve }) {
4388
4455
  "span",
4389
4456
  {
4390
4457
  className: "flex min-w-0 items-center gap-1.5 text-meta text-muted-foreground",
4391
- "aria-label": `Source (unresolved): ${display}`,
4458
+ "aria-label": t("editor.knowledgeCard.sourceUnresolved", { name: display }),
4392
4459
  children: [
4393
4460
  /* @__PURE__ */ jsx18(FileText, { className: "size-3 shrink-0", "aria-hidden": "true" }),
4394
4461
  /* @__PURE__ */ jsx18("span", { className: "truncate", children: display })
@@ -4397,25 +4464,33 @@ function SourceRow({ path, resolve }) {
4397
4464
  );
4398
4465
  }
4399
4466
  var KnowledgeCard = forwardRef13(function KnowledgeCard2({ sources, resolve, children, className, ...props }, ref) {
4467
+ const { t } = useLocale9();
4400
4468
  const sourcePaths = sources ? sources.split(",").map((s) => s.trim()).filter(Boolean) : [];
4401
4469
  return /* @__PURE__ */ jsx18(
4402
4470
  "section",
4403
4471
  {
4404
4472
  ref,
4405
- "aria-label": "Knowledge fact",
4473
+ "aria-label": t("editor.knowledgeCard.label"),
4406
4474
  className: cn17("not-prose", className),
4407
4475
  ...props,
4408
4476
  children: /* @__PURE__ */ jsxs16(Card4, { className: "border-s-4 border-s-info", children: [
4409
4477
  /* @__PURE__ */ jsxs16(CardContent4, { className: "pt-4", children: [
4410
4478
  /* @__PURE__ */ jsxs16("div", { className: "mb-2 flex items-center gap-1.5", children: [
4411
4479
  /* @__PURE__ */ jsx18(BookOpen, { className: "size-3.5 shrink-0 text-info-text", "aria-hidden": "true" }),
4412
- /* @__PURE__ */ jsx18("span", { className: "text-meta font-medium text-info-text", children: "Knowledge" })
4480
+ /* @__PURE__ */ jsx18("span", { className: "text-meta font-medium text-info-text", children: t("editor.knowledgeCard.heading") })
4413
4481
  ] }),
4414
4482
  /* @__PURE__ */ jsx18("div", { className: "text-body text-foreground", children })
4415
4483
  ] }),
4416
4484
  sourcePaths.length > 0 ? /* @__PURE__ */ jsxs16(CardFooter, { className: "flex-col items-start gap-1 border-t border-border pt-3", children: [
4417
- /* @__PURE__ */ jsx18("p", { className: "text-meta font-medium text-muted-foreground", children: "Sources" }),
4418
- /* @__PURE__ */ jsx18("ul", { className: "flex w-full flex-col gap-1", "aria-label": "Sources", children: sourcePaths.map((path) => /* @__PURE__ */ jsx18("li", { className: "min-w-0", children: /* @__PURE__ */ jsx18(SourceRow, { path, resolve }) }, path)) })
4485
+ /* @__PURE__ */ jsx18("p", { className: "text-meta font-medium text-muted-foreground", children: t("editor.knowledgeCard.sources") }),
4486
+ /* @__PURE__ */ jsx18(
4487
+ "ul",
4488
+ {
4489
+ className: "flex w-full flex-col gap-1",
4490
+ "aria-label": t("editor.knowledgeCard.sources"),
4491
+ children: sourcePaths.map((path) => /* @__PURE__ */ jsx18("li", { className: "min-w-0", children: /* @__PURE__ */ jsx18(SourceRow, { path, resolve }) }, path))
4492
+ }
4493
+ )
4419
4494
  ] }) : null
4420
4495
  ] })
4421
4496
  }
@@ -4484,7 +4559,8 @@ import {
4484
4559
  DialogDescription,
4485
4560
  DialogFooter,
4486
4561
  DialogHeader,
4487
- DialogTitle as DialogTitle2
4562
+ DialogTitle as DialogTitle2,
4563
+ useLocale as useLocale10
4488
4564
  } from "@elabs-ai/components-ui";
4489
4565
  import { useEffect as useEffect7, useState as useState7 } from "react";
4490
4566
  import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
@@ -4496,6 +4572,7 @@ function IterationTemplateDialog({
4496
4572
  kind = "iterate",
4497
4573
  mode = "split"
4498
4574
  }) {
4575
+ const { t } = useLocale10();
4499
4576
  const [draft, setDraft] = useState7(template);
4500
4577
  useEffect7(() => {
4501
4578
  if (open) setDraft(template);
@@ -4505,41 +4582,42 @@ function IterationTemplateDialog({
4505
4582
  onSave(draft);
4506
4583
  onOpenChange(false);
4507
4584
  };
4508
- return /* @__PURE__ */ jsx19(Dialog2, { open, onOpenChange, children: /* @__PURE__ */ jsxs17(DialogContent2, { className: "flex max-h-[85vh] w-[min(48rem,92vw)] max-w-none flex-col", children: [
4509
- /* @__PURE__ */ jsxs17(DialogHeader, { children: [
4510
- /* @__PURE__ */ jsxs17(DialogTitle2, { children: [
4511
- "Edit ",
4512
- kind === "pivot" ? "pivot" : "iteration",
4513
- " template"
4514
- ] }),
4515
- /* @__PURE__ */ jsxs17(DialogDescription, { children: [
4516
- "The per-",
4517
- unit,
4518
- " template. Use ",
4519
- /* @__PURE__ */ jsx19("code", { children: "{{token}}" }),
4520
- " placeholders (e.g.",
4521
- " ",
4522
- /* @__PURE__ */ jsx19("code", { children: "{{item.name}}" }),
4523
- ") \u2014 each is filled per ",
4524
- unit,
4525
- " when the block renders."
4526
- ] })
4527
- ] }),
4528
- /* @__PURE__ */ jsx19("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx19(
4529
- MarkdownWorkspace,
4530
- {
4531
- value: draft,
4532
- onChange: setDraft,
4533
- defaultMode: mode,
4534
- className: "h-full",
4535
- "aria-label": "Iteration template editor"
4536
- }
4537
- ) }),
4538
- /* @__PURE__ */ jsxs17(DialogFooter, { children: [
4539
- /* @__PURE__ */ jsx19(Button4, { variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
4540
- /* @__PURE__ */ jsx19(Button4, { onClick: save, children: "Save template" })
4541
- ] })
4542
- ] }) });
4585
+ return /* @__PURE__ */ jsx19(Dialog2, { open, onOpenChange, children: /* @__PURE__ */ jsxs17(
4586
+ DialogContent2,
4587
+ {
4588
+ className: "flex max-h-[85vh] w-[min(48rem,92vw)] max-w-none flex-col",
4589
+ onOpenAutoFocus: (event) => {
4590
+ event.preventDefault();
4591
+ event.currentTarget?.focus();
4592
+ },
4593
+ children: [
4594
+ /* @__PURE__ */ jsxs17(DialogHeader, { children: [
4595
+ /* @__PURE__ */ jsx19(DialogTitle2, { children: kind === "pivot" ? t("editor.templateDialog.editPivotTitle") : t("editor.templateDialog.editIterationTitle") }),
4596
+ /* @__PURE__ */ jsxs17(DialogDescription, { children: [
4597
+ t("editor.templateDialog.descriptionPrefix", { unit }),
4598
+ /* @__PURE__ */ jsx19("code", { children: "{{token}}" }),
4599
+ t("editor.templateDialog.descriptionMiddle"),
4600
+ /* @__PURE__ */ jsx19("code", { children: "{{item.name}}" }),
4601
+ t("editor.templateDialog.descriptionSuffix", { unit })
4602
+ ] })
4603
+ ] }),
4604
+ /* @__PURE__ */ jsx19("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx19(
4605
+ MarkdownWorkspace,
4606
+ {
4607
+ value: draft,
4608
+ onChange: setDraft,
4609
+ defaultMode: mode,
4610
+ className: "h-full",
4611
+ "aria-label": t("editor.templateDialog.editorLabel")
4612
+ }
4613
+ ) }),
4614
+ /* @__PURE__ */ jsxs17(DialogFooter, { children: [
4615
+ /* @__PURE__ */ jsx19(Button4, { variant: "ghost", onClick: () => onOpenChange(false), children: t("editor.templateDialog.cancel") }),
4616
+ /* @__PURE__ */ jsx19(Button4, { onClick: save, children: t("editor.templateDialog.saveTemplate") })
4617
+ ] })
4618
+ ]
4619
+ }
4620
+ ) });
4543
4621
  }
4544
4622
  function IterationTemplateProvider({ children }) {
4545
4623
  const [request, setRequest] = useState7(null);
@@ -4574,7 +4652,8 @@ import {
4574
4652
  Label,
4575
4653
  TagInput,
4576
4654
  ToggleGroup as ToggleGroup2,
4577
- ToggleGroupItem as ToggleGroupItem2
4655
+ ToggleGroupItem as ToggleGroupItem2,
4656
+ useLocale as useLocale11
4578
4657
  } from "@elabs-ai/components-ui";
4579
4658
  import { useEffect as useEffect8, useId as useId4, useMemo as useMemo7, useState as useState8 } from "react";
4580
4659
  import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
@@ -4588,6 +4667,7 @@ function IterationBuilderDialog({
4588
4667
  evaluate,
4589
4668
  interpolate
4590
4669
  }) {
4670
+ const { t } = useLocale11();
4591
4671
  const kind = value?.kind ?? kindProp;
4592
4672
  const isPivot = kind === "pivot";
4593
4673
  const ids = useId4();
@@ -4624,20 +4704,21 @@ function IterationBuilderDialog({
4624
4704
  onSave(serializeIterationDirective(draft));
4625
4705
  onOpenChange(false);
4626
4706
  };
4627
- const noun = isPivot ? "pivot" : "iteration";
4707
+ const noun = isPivot ? t("editor.iterationBuilder.pivotNoun") : t("editor.iterationBuilder.iterationNoun");
4628
4708
  return /* @__PURE__ */ jsx20(Dialog3, { open, onOpenChange, children: /* @__PURE__ */ jsxs18(DialogContent3, { className: "flex max-h-[88vh] w-[min(56rem,94vw)] max-w-none flex-col", children: [
4629
4709
  /* @__PURE__ */ jsxs18(DialogHeader2, { children: [
4630
- /* @__PURE__ */ jsxs18(DialogTitle3, { children: [
4631
- value ? "Edit" : "Insert",
4632
- " ",
4633
- noun
4634
- ] }),
4635
- /* @__PURE__ */ jsx20(DialogDescription2, { children: isPivot ? "Pick the row and column values, then write the per-cell template. The matrix below fills in live." : "Add the list values, then write the per-row template. The result below fills in live." })
4710
+ /* @__PURE__ */ jsx20(DialogTitle3, { children: t(
4711
+ value ? "editor.iterationBuilder.editTitle" : "editor.iterationBuilder.insertTitle",
4712
+ {
4713
+ noun
4714
+ }
4715
+ ) }),
4716
+ /* @__PURE__ */ jsx20(DialogDescription2, { children: isPivot ? t("editor.iterationBuilder.pivotDescription") : t("editor.iterationBuilder.iterationDescription") })
4636
4717
  ] }),
4637
4718
  /* @__PURE__ */ jsxs18(DialogBody, { className: "grid gap-4 md:grid-cols-2", children: [
4638
4719
  /* @__PURE__ */ jsxs18("div", { className: "flex min-w-0 flex-col gap-4", children: [
4639
4720
  !isPivot ? /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-1.5", children: [
4640
- /* @__PURE__ */ jsx20(Label, { htmlFor: `${ids}-as`, children: "Bind name" }),
4721
+ /* @__PURE__ */ jsx20(Label, { htmlFor: `${ids}-as`, children: t("editor.iterationBuilder.bindName") }),
4641
4722
  /* @__PURE__ */ jsx20(
4642
4723
  Input2,
4643
4724
  {
@@ -4645,18 +4726,18 @@ function IterationBuilderDialog({
4645
4726
  value: asName,
4646
4727
  spellCheck: false,
4647
4728
  autoComplete: "off",
4648
- placeholder: "item",
4729
+ placeholder: t("editor.iterationBuilder.bindNamePlaceholder"),
4649
4730
  onChange: (e) => setAsName(e.target.value)
4650
4731
  }
4651
4732
  ),
4652
4733
  /* @__PURE__ */ jsxs18("p", { className: "text-meta text-muted-foreground", children: [
4653
- "Use ",
4734
+ t("editor.iterationBuilder.bindNameHintPrefix"),
4654
4735
  /* @__PURE__ */ jsx20("code", { children: `{{${asName.trim() || "item"}.name}}` }),
4655
- " in the template."
4736
+ t("editor.iterationBuilder.bindNameHintSuffix")
4656
4737
  ] })
4657
4738
  ] }) : null,
4658
4739
  /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-1.5", children: [
4659
- /* @__PURE__ */ jsx20(Label, { htmlFor: `${ids}-values`, children: isPivot ? "Row values" : "Values" }),
4740
+ /* @__PURE__ */ jsx20(Label, { htmlFor: `${ids}-values`, children: isPivot ? t("editor.iterationBuilder.rowValues") : t("editor.iterationBuilder.values") }),
4660
4741
  /* @__PURE__ */ jsx20(
4661
4742
  TagInput,
4662
4743
  {
@@ -4664,12 +4745,12 @@ function IterationBuilderDialog({
4664
4745
  value: values,
4665
4746
  onValueChange: setValues,
4666
4747
  delimiter: [",", "\n"],
4667
- placeholder: "Type a value, press Enter\u2026"
4748
+ placeholder: t("editor.iterationBuilder.valuePlaceholder")
4668
4749
  }
4669
4750
  )
4670
4751
  ] }),
4671
4752
  isPivot ? /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-1.5", children: [
4672
- /* @__PURE__ */ jsx20(Label, { htmlFor: `${ids}-cols`, children: "Column values" }),
4753
+ /* @__PURE__ */ jsx20(Label, { htmlFor: `${ids}-cols`, children: t("editor.iterationBuilder.columnValues") }),
4673
4754
  /* @__PURE__ */ jsx20(
4674
4755
  TagInput,
4675
4756
  {
@@ -4677,12 +4758,12 @@ function IterationBuilderDialog({
4677
4758
  value: cols,
4678
4759
  onValueChange: setCols,
4679
4760
  delimiter: [",", "\n"],
4680
- placeholder: "Type a value, press Enter\u2026"
4761
+ placeholder: t("editor.iterationBuilder.valuePlaceholder")
4681
4762
  }
4682
4763
  )
4683
4764
  ] }) : null,
4684
4765
  /* @__PURE__ */ jsxs18("div", { className: "flex flex-col gap-1.5", children: [
4685
- /* @__PURE__ */ jsx20(Label, { id: `${ids}-layout`, children: "Layout" }),
4766
+ /* @__PURE__ */ jsx20(Label, { id: `${ids}-layout`, children: t("editor.iterationBuilder.layout") }),
4686
4767
  /* @__PURE__ */ jsx20(
4687
4768
  ToggleGroup2,
4688
4769
  {
@@ -4701,11 +4782,7 @@ function IterationBuilderDialog({
4701
4782
  ] }),
4702
4783
  /* @__PURE__ */ jsxs18("div", { className: "flex min-h-0 min-w-0 flex-col gap-4", children: [
4703
4784
  /* @__PURE__ */ jsxs18("div", { className: "flex min-h-0 flex-col gap-1.5", children: [
4704
- /* @__PURE__ */ jsxs18(Label, { children: [
4705
- "Per-",
4706
- isPivot ? "cell" : "row",
4707
- " template"
4708
- ] }),
4785
+ /* @__PURE__ */ jsx20(Label, { children: isPivot ? t("editor.iterationBuilder.perCellTemplate") : t("editor.iterationBuilder.perRowTemplate") }),
4709
4786
  /* @__PURE__ */ jsx20("div", { className: "h-44 min-h-0 overflow-hidden rounded-md border border-border", children: /* @__PURE__ */ jsx20(
4710
4787
  MarkdownWorkspace,
4711
4788
  {
@@ -4713,17 +4790,17 @@ function IterationBuilderDialog({
4713
4790
  onChange: setTemplate,
4714
4791
  defaultMode: "source",
4715
4792
  className: "h-full",
4716
- "aria-label": "Per-cell template"
4793
+ "aria-label": t("editor.iterationBuilder.perCellTemplate")
4717
4794
  }
4718
4795
  ) })
4719
4796
  ] }),
4720
4797
  /* @__PURE__ */ jsxs18("div", { className: "flex min-h-0 flex-col gap-1.5", children: [
4721
- /* @__PURE__ */ jsx20(Label, { children: "Live preview" }),
4798
+ /* @__PURE__ */ jsx20(Label, { children: t("editor.iterationBuilder.livePreview") }),
4722
4799
  /* @__PURE__ */ jsx20(
4723
4800
  "div",
4724
4801
  {
4725
4802
  role: "region",
4726
- "aria-label": "Live preview",
4803
+ "aria-label": t("editor.iterationBuilder.livePreview"),
4727
4804
  className: "min-h-0 flex-1 overflow-auto rounded-md border border-border bg-card p-3",
4728
4805
  children: /* @__PURE__ */ jsx20(
4729
4806
  MarkdownPreview,
@@ -4740,8 +4817,8 @@ function IterationBuilderDialog({
4740
4817
  ] })
4741
4818
  ] }),
4742
4819
  /* @__PURE__ */ jsxs18(DialogFooter2, { children: [
4743
- /* @__PURE__ */ jsx20(Button5, { variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
4744
- /* @__PURE__ */ jsx20(Button5, { onClick: save, children: value ? "Save" : "Insert" })
4820
+ /* @__PURE__ */ jsx20(Button5, { variant: "ghost", onClick: () => onOpenChange(false), children: t("editor.iterationBuilder.cancel") }),
4821
+ /* @__PURE__ */ jsx20(Button5, { onClick: save, children: value ? t("editor.iterationBuilder.save") : t("editor.iterationBuilder.insert") })
4745
4822
  ] })
4746
4823
  ] }) });
4747
4824
  }