@elabs-ai/components-editor 4.1.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 (45) hide show
  1. package/dist/{chunk-C62O7IOQ.js → chunk-FO5S3YZM.js} +241 -158
  2. package/dist/chunk-FO5S3YZM.js.map +1 -0
  3. package/dist/index.d.ts +5 -4
  4. package/dist/index.js +57 -39
  5. package/dist/index.js.map +1 -1
  6. package/dist/markdown/index.d.ts +2 -2
  7. package/dist/markdown/index.js +264 -187
  8. package/dist/markdown/index.js.map +1 -1
  9. package/dist/{markdown-editor-CBp_4eDv.d.ts → markdown-editor-Dn-0L_MM.d.ts} +8 -1
  10. package/dist/monaco.d.ts +2 -0
  11. package/dist/monaco.js +9 -0
  12. package/dist/monaco.js.map +1 -0
  13. package/package.json +9 -5
  14. package/src/ai-objects/decision-card.tsx +15 -9
  15. package/src/ai-objects/knowledge-card.tsx +18 -9
  16. package/src/barrel-monaco-lazy.test.ts +50 -0
  17. package/src/calc-block/calc-block.tsx +10 -4
  18. package/src/code-editor/code-editor.test.tsx +141 -14
  19. package/src/code-editor/code-editor.tsx +166 -35
  20. package/src/code-workspace/code-workspace.test.tsx +31 -12
  21. package/src/copy-button/copy-button.tsx +6 -3
  22. package/src/diff-editor/diff-editor.test.tsx +9 -3
  23. package/src/diff-editor/diff-editor.tsx +47 -23
  24. package/src/editor-toolbar/editor-toolbar.tsx +8 -2
  25. package/src/index.ts +4 -3
  26. package/src/markdown-academic/citations.tsx +14 -7
  27. package/src/markdown-academic/footnotes.tsx +1 -1
  28. package/src/markdown-academic/math.tsx +7 -4
  29. package/src/markdown-editor/completions/completions-menu.tsx +5 -2
  30. package/src/markdown-editor/directive-views.tsx +33 -19
  31. package/src/markdown-editor/slash/slash-menu.tsx +5 -2
  32. package/src/markdown-editor/table-view.tsx +28 -15
  33. package/src/markdown-iteration/iteration-builder-dialog.tsx +39 -18
  34. package/src/markdown-iteration/template-dialog.tsx +25 -7
  35. package/src/markdown-outline/document-outline.tsx +6 -2
  36. package/src/markdown-preview/markdown-preview-academic.test.tsx +3 -3
  37. package/src/markdown-toolbar/markdown-toolbar.tsx +42 -24
  38. package/src/markdown-workspace/markdown-workspace.test.tsx +22 -3
  39. package/src/markdown-workspace/markdown-workspace.tsx +6 -3
  40. package/src/mermaid-diagram/mermaid-diagram-fixes.test.tsx +130 -0
  41. package/src/mermaid-diagram/mermaid-diagram.test.tsx +2 -1
  42. package/src/mermaid-diagram/mermaid-diagram.tsx +89 -40
  43. package/src/mermaid-diagram/mermaid-viewer.tsx +21 -20
  44. package/src/monaco.ts +21 -0
  45. package/dist/chunk-C62O7IOQ.js.map +0 -1
@@ -11,12 +11,12 @@ import {
11
11
  } from "@elabs-ai/components-ui";
12
12
  import "react";
13
13
  import { jsx, jsxs } from "react/jsx-runtime";
14
- function EditorContextMenu({ editor: editor2, readOnly = false, children }) {
14
+ function EditorContextMenu({ editor, readOnly = false, children }) {
15
15
  const selection = () => {
16
- if (!editor2) return null;
17
- const model = editor2.getModel();
18
- const sel = editor2.getSelection();
19
- return model && sel ? { editor: editor2, model, sel } : null;
16
+ if (!editor) return null;
17
+ const model = editor.getModel();
18
+ const sel = editor.getSelection();
19
+ return model && sel ? { editor, model, sel } : null;
20
20
  };
21
21
  const copy = async () => {
22
22
  const ctx2 = selection();
@@ -51,8 +51,8 @@ function EditorContextMenu({ editor: editor2, readOnly = false, children }) {
51
51
  ctx2.editor.focus();
52
52
  };
53
53
  const runAction = (id) => {
54
- editor2?.focus();
55
- void editor2?.getAction(id)?.run();
54
+ editor?.focus();
55
+ void editor?.getAction(id)?.run();
56
56
  };
57
57
  return /* @__PURE__ */ jsxs(ContextMenu, { children: [
58
58
  /* @__PURE__ */ jsx(ContextMenuTrigger, { asChild: true, children }),
@@ -360,12 +360,12 @@ function buildBrandThemeData(rootEl) {
360
360
  function brandThemeId(theme) {
361
361
  return `brand-${theme}`;
362
362
  }
363
- function applyBrandTheme(monaco2, theme, rootEl) {
363
+ function applyBrandTheme(monaco, theme, rootEl) {
364
364
  const id = brandThemeId(theme);
365
365
  const data = buildBrandThemeData(rootEl);
366
366
  data.base = builtinBase(rootEl);
367
- monaco2.editor.defineTheme(id, data);
368
- monaco2.editor.setTheme(id);
367
+ monaco.editor.defineTheme(id, data);
368
+ monaco.editor.setTheme(id);
369
369
  return id;
370
370
  }
371
371
 
@@ -402,7 +402,6 @@ function useDataTheme(target) {
402
402
  }
403
403
 
404
404
  // src/code-editor/code-editor.tsx
405
- import * as monaco from "monaco-editor";
406
405
  import { cn } from "@elabs-ai/components-ui/lib/cn";
407
406
  import {
408
407
  forwardRef,
@@ -412,6 +411,20 @@ import {
412
411
  useState as useState2
413
412
  } from "react";
414
413
  import { jsx as jsx2 } from "react/jsx-runtime";
414
+ function computeMinimalEdit(oldValue, newValue) {
415
+ const maxCommon = Math.min(oldValue.length, newValue.length);
416
+ let start = 0;
417
+ while (start < maxCommon && oldValue.charCodeAt(start) === newValue.charCodeAt(start)) {
418
+ start++;
419
+ }
420
+ let endOld = oldValue.length;
421
+ let endNew = newValue.length;
422
+ while (endOld > start && endNew > start && oldValue.charCodeAt(endOld - 1) === newValue.charCodeAt(endNew - 1)) {
423
+ endOld--;
424
+ endNew--;
425
+ }
426
+ return { start, endOld, text: newValue.slice(start, endNew) };
427
+ }
415
428
  var BASE_OPTIONS = {
416
429
  automaticLayout: true,
417
430
  minimap: { enabled: false },
@@ -443,70 +456,123 @@ var CodeEditor = forwardRef(function CodeEditor2({
443
456
  ...props
444
457
  }, ref) {
445
458
  const containerRef = useRef(null);
446
- const [editor2, setEditor] = useState2(null);
459
+ const [editor, setEditor] = useState2(null);
447
460
  const { theme, revision } = useDataTheme();
461
+ const modelRef = useRef(null);
462
+ const monacoRef = useRef(null);
448
463
  const onChangeRef = useRef(onChange);
449
464
  onChangeRef.current = onChange;
450
465
  const onMountRef = useRef(onMount);
451
466
  onMountRef.current = onMount;
452
- useImperativeHandle(ref, () => editor2, [
453
- editor2
467
+ useImperativeHandle(ref, () => editor, [
468
+ editor
454
469
  ]);
455
470
  useEffect2(() => {
456
471
  const container = containerRef.current;
457
472
  if (!container) return;
458
- const model = monaco.editor.createModel(
459
- value ?? defaultValue ?? "",
460
- language,
461
- path ? monaco.Uri.parse(`inmemory://brand/${path}`) : void 0
462
- );
463
- const instance = monaco.editor.create(container, {
464
- ...BASE_OPTIONS,
465
- readOnly,
466
- // Disable Monaco's own menu unless explicitly opted into; "brand" renders
467
- // brand-ui's ContextMenu around the editor instead.
468
- contextmenu: contextMenu === "monaco",
469
- // Monaco's accessible name comes from this construction option (it writes it
470
- // onto its inner screen-reader <textarea>), not from a wrapper-div attribute.
471
- ...ariaLabel !== void 0 ? { ariaLabel } : null,
472
- model,
473
- ...options
474
- });
475
- const sub = instance.onDidChangeModelContent(() => {
476
- onChangeRef.current?.(instance.getValue());
473
+ let cancelled = false;
474
+ let instance = null;
475
+ let model = null;
476
+ let sub = null;
477
+ import("monaco-editor").then((monacoApi) => {
478
+ if (cancelled) return;
479
+ monacoRef.current = monacoApi;
480
+ model = monacoApi.editor.createModel(
481
+ value ?? defaultValue ?? "",
482
+ language,
483
+ path ? monacoApi.Uri.parse(`inmemory://brand/${path}`) : void 0
484
+ );
485
+ modelRef.current = model;
486
+ instance = monacoApi.editor.create(container, {
487
+ ...BASE_OPTIONS,
488
+ readOnly,
489
+ // Disable Monaco's own menu unless explicitly opted into; "brand" renders
490
+ // brand-ui's ContextMenu around the editor instead.
491
+ contextmenu: contextMenu === "monaco",
492
+ // Monaco's accessible name comes from this construction option (it writes it
493
+ // onto its inner screen-reader <textarea>), not from a wrapper-div attribute.
494
+ ...ariaLabel !== void 0 ? { ariaLabel } : null,
495
+ model,
496
+ ...options
497
+ });
498
+ sub = instance.onDidChangeModelContent(() => {
499
+ onChangeRef.current?.(instance.getValue());
500
+ });
501
+ const textarea = instance.getDomNode()?.querySelector("textarea");
502
+ if (textarea) {
503
+ if (ariaLabel !== void 0) textarea.setAttribute("aria-label", ariaLabel);
504
+ if (ariaInvalid !== void 0) textarea.setAttribute("aria-invalid", String(ariaInvalid));
505
+ if (ariaDescribedBy !== void 0)
506
+ textarea.setAttribute("aria-describedby", ariaDescribedBy);
507
+ }
508
+ setEditor(instance);
509
+ onMountRef.current?.(instance, monacoApi);
477
510
  });
478
- setEditor(instance);
479
- onMountRef.current?.(instance, monaco);
480
511
  return () => {
481
- sub.dispose();
482
- instance.dispose();
483
- model.dispose();
512
+ cancelled = true;
513
+ sub?.dispose();
514
+ instance?.dispose();
515
+ model?.dispose();
516
+ modelRef.current = null;
517
+ monacoRef.current = null;
484
518
  setEditor(null);
485
519
  };
486
520
  }, []);
487
521
  useEffect2(() => {
488
- if (!editor2 || value === void 0) return;
489
- if (value !== editor2.getValue()) editor2.setValue(value);
490
- }, [editor2, value]);
522
+ const monacoApi = monacoRef.current;
523
+ if (!editor || !monacoApi) return;
524
+ const current = modelRef.current;
525
+ const currentUri = current?.uri?.toString();
526
+ const nextUri = path ? monacoApi.Uri.parse(`inmemory://brand/${path}`).toString() : void 0;
527
+ if (currentUri === nextUri) return;
528
+ const nextModel = monacoApi.editor.createModel(
529
+ current?.getValue() ?? value ?? defaultValue ?? "",
530
+ language,
531
+ path ? monacoApi.Uri.parse(`inmemory://brand/${path}`) : void 0
532
+ );
533
+ editor.setModel(nextModel);
534
+ modelRef.current = nextModel;
535
+ current?.dispose();
536
+ }, [editor, path]);
537
+ useEffect2(() => {
538
+ const monacoApi = monacoRef.current;
539
+ if (!editor || !monacoApi || value === void 0) return;
540
+ const model = editor.getModel();
541
+ if (!model) return;
542
+ const current = model.getValue();
543
+ if (value === current) return;
544
+ const { start, endOld, text } = computeMinimalEdit(current, value);
545
+ const range = monacoApi.Range.fromPositions(
546
+ model.getPositionAt(start),
547
+ model.getPositionAt(endOld)
548
+ );
549
+ editor.executeEdits("controlled-value-sync", [{ range, text }]);
550
+ }, [editor, value]);
551
+ useEffect2(() => {
552
+ const monacoApi = monacoRef.current;
553
+ const model = editor?.getModel();
554
+ if (model && monacoApi) monacoApi.editor.setModelLanguage(model, language);
555
+ }, [editor, language]);
491
556
  useEffect2(() => {
492
- const model = editor2?.getModel();
493
- if (model) monaco.editor.setModelLanguage(model, language);
494
- }, [editor2, language]);
557
+ editor?.updateOptions({ readOnly, contextmenu: contextMenu === "monaco" });
558
+ }, [editor, readOnly, contextMenu]);
495
559
  useEffect2(() => {
496
- editor2?.updateOptions({ readOnly, contextmenu: contextMenu === "monaco" });
497
- }, [editor2, readOnly, contextMenu]);
560
+ if (!editor || !options) return;
561
+ editor.updateOptions(options);
562
+ }, [editor, options]);
498
563
  useEffect2(() => {
499
- if (!editor2) return;
564
+ const monacoApi = monacoRef.current;
565
+ if (!editor || !monacoApi) return;
500
566
  try {
501
- applyBrandTheme(monaco, theme);
567
+ applyBrandTheme(monacoApi, theme);
502
568
  } catch (err) {
503
569
  console.error("[@elabs-ai/components-editor] failed to apply brand theme", err);
504
570
  }
505
- }, [editor2, theme, revision]);
571
+ }, [editor, theme, revision]);
506
572
  useEffect2(() => {
507
- if (!editor2) return;
508
- if (ariaLabel !== void 0) editor2.updateOptions({ ariaLabel });
509
- const textarea = editor2.getDomNode()?.querySelector("textarea");
573
+ if (!editor) return;
574
+ if (ariaLabel !== void 0) editor.updateOptions({ ariaLabel });
575
+ const textarea = editor.getDomNode()?.querySelector("textarea");
510
576
  if (!textarea) return;
511
577
  if (ariaLabel === void 0) textarea.removeAttribute("aria-label");
512
578
  else textarea.setAttribute("aria-label", ariaLabel);
@@ -514,12 +580,12 @@ var CodeEditor = forwardRef(function CodeEditor2({
514
580
  else textarea.setAttribute("aria-invalid", String(ariaInvalid));
515
581
  if (ariaDescribedBy === void 0) textarea.removeAttribute("aria-describedby");
516
582
  else textarea.setAttribute("aria-describedby", ariaDescribedBy);
517
- }, [editor2, ariaLabel, ariaInvalid, ariaDescribedBy]);
583
+ }, [editor, ariaLabel, ariaInvalid, ariaDescribedBy]);
518
584
  useEffect2(() => {
519
- if (!editor2 || !actions || actions.length === 0) return;
520
- const disposables = actions.map((a) => editor2.addAction(a));
585
+ if (!editor || !actions || actions.length === 0) return;
586
+ const disposables = actions.map((a) => editor.addAction(a));
521
587
  return () => disposables.forEach((d) => d.dispose());
522
- }, [editor2, actions]);
588
+ }, [editor, actions]);
523
589
  const resolvedStyle = {
524
590
  height: typeof height === "number" ? `${height}px` : height,
525
591
  ...style
@@ -535,7 +601,7 @@ var CodeEditor = forwardRef(function CodeEditor2({
535
601
  }
536
602
  );
537
603
  if (contextMenu === "brand") {
538
- return /* @__PURE__ */ jsx2(EditorContextMenu, { editor: editor2, readOnly, children: editorEl });
604
+ return /* @__PURE__ */ jsx2(EditorContextMenu, { editor, readOnly, children: editorEl });
539
605
  }
540
606
  return editorEl;
541
607
  });
@@ -950,6 +1016,7 @@ function parseMarkdownOutline(markdown) {
950
1016
  }
951
1017
 
952
1018
  // src/markdown-outline/document-outline.tsx
1019
+ import { useLocale } from "@elabs-ai/components-ui";
953
1020
  import { cn as cn2 } from "@elabs-ai/components-ui/lib/cn";
954
1021
  import { forwardRef as forwardRef2, useMemo } from "react";
955
1022
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
@@ -958,12 +1025,13 @@ function useMarkdownOutline(markdown) {
958
1025
  }
959
1026
  var DocumentOutline = forwardRef2(
960
1027
  function DocumentOutline2({ items, activeId, onSelect, itemActions, className, ...props }, ref) {
1028
+ const { t } = useLocale();
961
1029
  const minLevel = items.reduce((min, it) => Math.min(min, it.level), 6);
962
1030
  return /* @__PURE__ */ jsxs2(
963
1031
  "nav",
964
1032
  {
965
1033
  ref,
966
- "aria-label": "Document outline",
1034
+ "aria-label": t("editor.documentOutline.label"),
967
1035
  className: cn2("text-body", className),
968
1036
  ...props,
969
1037
  children: [
@@ -990,7 +1058,7 @@ var DocumentOutline = forwardRef2(
990
1058
  actions ? /* @__PURE__ */ jsx3("span", { className: "absolute end-0.5 top-1/2 -translate-y-1/2 opacity-0 transition-opacity duration-fast ease-standard focus-within:opacity-100 group-hover/outline-item:opacity-100 has-[[aria-pressed=true]]:opacity-100 motion-reduce:transition-none", children: actions }) : null
991
1059
  ] }, item.id);
992
1060
  }) }),
993
- items.length === 0 ? /* @__PURE__ */ jsx3("p", { className: "px-2 py-1 text-caption text-muted-foreground", children: "No headings yet." }) : null
1061
+ items.length === 0 ? /* @__PURE__ */ jsx3("p", { className: "px-2 py-1 text-caption text-muted-foreground", children: t("editor.documentOutline.empty") }) : null
994
1062
  ]
995
1063
  }
996
1064
  );
@@ -1765,6 +1833,7 @@ function groupSlashCommands(commands) {
1765
1833
  }
1766
1834
 
1767
1835
  // src/markdown-editor/slash/slash-menu.tsx
1836
+ import { useLocale as useLocale2 } from "@elabs-ai/components-ui";
1768
1837
  import { cn as cn4 } from "@elabs-ai/components-ui/lib/cn";
1769
1838
  import { forwardRef as forwardRef4 } from "react";
1770
1839
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
@@ -1776,17 +1845,19 @@ var SlashMenu = forwardRef4(function SlashMenu2({
1776
1845
  activeId,
1777
1846
  onSelect,
1778
1847
  idPrefix = "brand-slash",
1779
- emptyLabel = "No matching blocks",
1848
+ emptyLabel: emptyLabelProp,
1780
1849
  className,
1781
1850
  ...props
1782
1851
  }, ref) {
1852
+ const { t } = useLocale2();
1853
+ const emptyLabel = emptyLabelProp ?? t("editor.slashMenu.noMatchingBlocks");
1783
1854
  const groups = groupSlashCommands(commands);
1784
1855
  return /* @__PURE__ */ jsx5(
1785
1856
  "div",
1786
1857
  {
1787
1858
  ref,
1788
1859
  role: "listbox",
1789
- "aria-label": "Insert block",
1860
+ "aria-label": t("editor.slashMenu.insertBlock"),
1790
1861
  className: cn4(
1791
1862
  "max-h-[min(320px,60vh)] w-72 overflow-y-auto overflow-x-hidden rounded-md bg-popover p-1 text-popover-foreground shadow-ring-md",
1792
1863
  className
@@ -2335,6 +2406,7 @@ import { useWidgetViewContext as useWidgetViewContext2 } from "@prosemirror-adap
2335
2406
  import { useLayoutEffect as useLayoutEffect2, useRef as useRef3 } from "react";
2336
2407
 
2337
2408
  // src/markdown-editor/completions/completions-menu.tsx
2409
+ import { useLocale as useLocale3 } from "@elabs-ai/components-ui";
2338
2410
  import { cn as cn5 } from "@elabs-ai/components-ui/lib/cn";
2339
2411
  import { forwardRef as forwardRef5 } from "react";
2340
2412
  import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
@@ -2347,16 +2419,18 @@ var CompletionMenu = forwardRef5(
2347
2419
  activeIndex,
2348
2420
  onSelect,
2349
2421
  idPrefix = "brand-completions",
2350
- emptyLabel = "No suggestions",
2422
+ emptyLabel: emptyLabelProp,
2351
2423
  className,
2352
2424
  ...props
2353
2425
  }, ref) {
2426
+ const { t } = useLocale3();
2427
+ const emptyLabel = emptyLabelProp ?? t("editor.completions.noSuggestions");
2354
2428
  return /* @__PURE__ */ jsx7(
2355
2429
  "div",
2356
2430
  {
2357
2431
  ref,
2358
2432
  role: "listbox",
2359
- "aria-label": "Suggestions",
2433
+ "aria-label": t("editor.completions.suggestions"),
2360
2434
  className: cn5(
2361
2435
  "max-h-[min(280px,50vh)] w-64 overflow-y-auto overflow-x-hidden rounded-md bg-popover p-1 text-popover-foreground shadow-ring-md",
2362
2436
  className
@@ -2474,7 +2548,8 @@ import {
2474
2548
  DropdownMenuSub,
2475
2549
  DropdownMenuSubContent,
2476
2550
  DropdownMenuSubTrigger,
2477
- DropdownMenuTrigger
2551
+ DropdownMenuTrigger,
2552
+ useLocale as useLocale4
2478
2553
  } from "@elabs-ai/components-ui";
2479
2554
  import { cn as cn6 } from "@elabs-ai/components-ui/lib/cn";
2480
2555
  import { editorViewCtx as editorViewCtx2, parserCtx as parserCtx2, serializerCtx } from "@milkdown/kit/core";
@@ -2511,16 +2586,16 @@ function useGetEditor() {
2511
2586
  if (!getEditor) return;
2512
2587
  if (!div) return;
2513
2588
  dom.current = div;
2514
- const editor2 = getEditor(div);
2515
- if (!editor2) return;
2589
+ const editor = getEditor(div);
2590
+ if (!editor) return;
2516
2591
  setLoading(true);
2517
- editor2.create().then((editor3) => {
2518
- editorRef.current = editor3;
2592
+ editor.create().then((editor2) => {
2593
+ editorRef.current = editor2;
2519
2594
  }).finally(() => {
2520
2595
  setLoading(false);
2521
2596
  }).catch(console.error);
2522
2597
  return () => {
2523
- const destroyPromise = editor2.destroy().catch(console.error);
2598
+ const destroyPromise = editor.destroy().catch(console.error);
2524
2599
  pendingDestroys.add(destroyPromise);
2525
2600
  void destroyPromise.finally(() => {
2526
2601
  pendingDestroys.delete(destroyPromise);
@@ -2539,10 +2614,10 @@ var Milkdown = () => {
2539
2614
  var MilkdownProvider = ({ children }) => {
2540
2615
  const dom = useRef5(void 0);
2541
2616
  const [editorFactory, setEditorFactory] = useState3(void 0);
2542
- const editor2 = useRef5(void 0);
2617
+ const editor = useRef5(void 0);
2543
2618
  const [loading, setLoading] = useState3(true);
2544
2619
  const editorInfoCtx = useMemo2(
2545
- () => ({ loading, dom, editor: editor2, setLoading, editorFactory, setEditorFactory }),
2620
+ () => ({ loading, dom, editor, setLoading, editorFactory, setEditorFactory }),
2546
2621
  [loading, editorFactory]
2547
2622
  );
2548
2623
  return /* @__PURE__ */ jsx9(editorInfoContext.Provider, { value: editorInfoCtx, children });
@@ -2642,6 +2717,7 @@ function InlineEdit({ value, onCommit, ariaLabel, placeholder, className }) {
2642
2717
  );
2643
2718
  }
2644
2719
  function ContainerDirectiveView() {
2720
+ const { t } = useLocale4();
2645
2721
  const { contentRef } = useNodeViewContext();
2646
2722
  const { name, attributes, update } = useDirectiveAttrs();
2647
2723
  const body = /* @__PURE__ */ jsx10("div", { className: "brand-directive__body", ref: contentRef });
@@ -2650,8 +2726,8 @@ function ContainerDirectiveView() {
2650
2726
  /* @__PURE__ */ jsx10(CardHeader, { className: "pb-3", children: /* @__PURE__ */ jsx10(CardTitle, { children: /* @__PURE__ */ jsx10(
2651
2727
  InlineEdit,
2652
2728
  {
2653
- ariaLabel: "Card title",
2654
- placeholder: "Card title",
2729
+ ariaLabel: t("editor.directiveViews.cardTitle"),
2730
+ placeholder: t("editor.directiveViews.cardTitle"),
2655
2731
  value: attributes.title ?? "",
2656
2732
  onCommit: (v) => update("title", v)
2657
2733
  }
@@ -2671,7 +2747,7 @@ function ContainerDirectiveView() {
2671
2747
  /* @__PURE__ */ jsx10("div", { className: "mb-1 font-medium leading-none tracking-tight", children: /* @__PURE__ */ jsx10(
2672
2748
  InlineEdit,
2673
2749
  {
2674
- ariaLabel: "Callout title",
2750
+ ariaLabel: t("editor.directiveViews.calloutTitle"),
2675
2751
  placeholder: capitalize(attributes.type ?? "note"),
2676
2752
  value: attributes.title ?? "",
2677
2753
  onCommit: (v) => update("title", v)
@@ -2696,10 +2772,7 @@ function ContainerDirectiveView() {
2696
2772
  className: "brand-directive brand-directive--unknown",
2697
2773
  "data-brand-directive": name,
2698
2774
  children: [
2699
- /* @__PURE__ */ jsxs6("div", { className: "mb-1 font-medium leading-none tracking-tight", children: [
2700
- "Unknown block: ",
2701
- name
2702
- ] }),
2775
+ /* @__PURE__ */ jsx10("div", { className: "mb-1 font-medium leading-none tracking-tight", children: t("editor.directiveViews.unknownBlock", { name }) }),
2703
2776
  /* @__PURE__ */ jsx10(AlertDescription, { children: body })
2704
2777
  ]
2705
2778
  }
@@ -2707,9 +2780,9 @@ function ContainerDirectiveView() {
2707
2780
  }
2708
2781
  function readBodyMarkdown(getInstance, node) {
2709
2782
  try {
2710
- const editor2 = getInstance();
2711
- if (!editor2) return node.textContent;
2712
- return editor2.action((ctx2) => {
2783
+ const editor = getInstance();
2784
+ if (!editor) return node.textContent;
2785
+ return editor.action((ctx2) => {
2713
2786
  const serialize = ctx2.get(
2714
2787
  serializerCtx
2715
2788
  );
@@ -2722,10 +2795,10 @@ function readBodyMarkdown(getInstance, node) {
2722
2795
  }
2723
2796
  function writeBodyMarkdown(getInstance, getPos, template) {
2724
2797
  try {
2725
- const editor2 = getInstance();
2798
+ const editor = getInstance();
2726
2799
  const pos = getPos();
2727
- if (!editor2 || pos == null) return;
2728
- editor2.action((ctx2) => {
2800
+ if (!editor || pos == null) return;
2801
+ editor.action((ctx2) => {
2729
2802
  const parse = ctx2.get(
2730
2803
  parserCtx2
2731
2804
  );
@@ -2753,10 +2826,10 @@ function mergeAttrsOmittingEmpty(attrs, next) {
2753
2826
  function replaceNodeWithMarkdown(getInstance, getPos, markdown) {
2754
2827
  if (!markdown.trim()) return;
2755
2828
  try {
2756
- const editor2 = getInstance();
2829
+ const editor = getInstance();
2757
2830
  const pos = getPos();
2758
- if (!editor2 || pos == null) return;
2759
- editor2.action((ctx2) => {
2831
+ if (!editor || pos == null) return;
2832
+ editor.action((ctx2) => {
2760
2833
  const parse = ctx2.get(
2761
2834
  parserCtx2
2762
2835
  );
@@ -2806,6 +2879,7 @@ function IterationMenuItems({
2806
2879
  }) });
2807
2880
  }
2808
2881
  function IterationDirectiveView() {
2882
+ const { t } = useLocale4();
2809
2883
  const { contentRef, node, getPos, setAttrs } = useNodeViewContext();
2810
2884
  const { name, attributes } = useDirectiveAttrs();
2811
2885
  const [, getInstance] = useInstance();
@@ -2860,7 +2934,7 @@ function IterationDirectiveView() {
2860
2934
  as: attributes.as || "item",
2861
2935
  attributes
2862
2936
  }).cells.length > 0;
2863
- const disabledHint = "\u2014 needs embedded values";
2937
+ const disabledHint = t("editor.directiveViews.needsEmbeddedValues");
2864
2938
  const convertToStatic = () => {
2865
2939
  const template = readBodyMarkdown(getInstance, node);
2866
2940
  const value = builderValueFromParts(kind, attributes, template);
@@ -2870,14 +2944,14 @@ function IterationDirectiveView() {
2870
2944
  {
2871
2945
  type: "item",
2872
2946
  id: "edit",
2873
- label: "Edit iteration\u2026",
2947
+ label: t("editor.directiveViews.editIteration"),
2874
2948
  icon: /* @__PURE__ */ jsx10(Pencil, { className: "size-4", "aria-hidden": "true" }),
2875
2949
  onSelect: requestEdit
2876
2950
  },
2877
2951
  {
2878
2952
  type: "layout",
2879
2953
  id: "layout",
2880
- label: "Change layout",
2954
+ label: t("editor.directiveViews.changeLayout"),
2881
2955
  icon: /* @__PURE__ */ jsx10(LayoutGrid, { className: "size-4", "aria-hidden": "true" }),
2882
2956
  value: attributes.layout || ITERATION_LAYOUTS[kind][0],
2883
2957
  options: ITERATION_LAYOUTS[kind],
@@ -2887,7 +2961,7 @@ function IterationDirectiveView() {
2887
2961
  {
2888
2962
  type: "item",
2889
2963
  id: "transpose",
2890
- label: hasEmbeddedData ? "Transpose" : `Transpose ${disabledHint}`,
2964
+ label: hasEmbeddedData ? t("editor.directiveViews.transpose") : `${t("editor.directiveViews.transpose")} ${disabledHint}`,
2891
2965
  icon: /* @__PURE__ */ jsx10(ArrowLeftRight, { className: "size-4", "aria-hidden": "true" }),
2892
2966
  onSelect: transpose,
2893
2967
  disabled: !hasEmbeddedData
@@ -2896,7 +2970,7 @@ function IterationDirectiveView() {
2896
2970
  {
2897
2971
  type: "item",
2898
2972
  id: "convert-to-static",
2899
- label: hasEmbeddedData ? "Convert to static" : `Convert to static ${disabledHint}`,
2973
+ label: hasEmbeddedData ? t("editor.directiveViews.convertToStatic") : `${t("editor.directiveViews.convertToStatic")} ${disabledHint}`,
2900
2974
  icon: /* @__PURE__ */ jsx10(FileText, { className: "size-4", "aria-hidden": "true" }),
2901
2975
  onSelect: convertToStatic,
2902
2976
  disabled: !hasEmbeddedData
@@ -2904,20 +2978,17 @@ function IterationDirectiveView() {
2904
2978
  ];
2905
2979
  const header = /* @__PURE__ */ jsxs6("div", { className: "mb-1.5 flex items-center gap-1.5 text-meta font-medium text-info-text", children: [
2906
2980
  /* @__PURE__ */ jsx10(Icon, { className: "size-3.5 shrink-0", "aria-hidden": "true" }),
2907
- /* @__PURE__ */ jsx10("span", { children: isPivot ? "Pivot" : "Iterate" }),
2908
- !isPivot && attributes.as ? /* @__PURE__ */ jsxs6("span", { className: "font-normal text-muted-foreground", children: [
2909
- "\xB7 per ",
2910
- attributes.as
2911
- ] }) : null,
2912
- /* @__PURE__ */ jsx10("span", { className: "font-normal text-muted-foreground", children: "\u2014 template" }),
2981
+ /* @__PURE__ */ jsx10("span", { children: isPivot ? t("editor.directiveViews.pivot") : t("editor.directiveViews.iterate") }),
2982
+ !isPivot && attributes.as ? /* @__PURE__ */ jsx10("span", { className: "font-normal text-muted-foreground", children: t("editor.directiveViews.perItem", { as: attributes.as }) }) : null,
2983
+ /* @__PURE__ */ jsx10("span", { className: "font-normal text-muted-foreground", children: t("editor.directiveViews.templateSuffix") }),
2913
2984
  onEdit ? /* @__PURE__ */ jsxs6(DropdownMenu, { children: [
2914
2985
  /* @__PURE__ */ jsx10(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx10(
2915
2986
  "button",
2916
2987
  {
2917
2988
  type: "button",
2918
2989
  "data-directive-chrome": "",
2919
- "aria-label": "Iteration actions",
2920
- title: "Iteration actions\u2026",
2990
+ "aria-label": t("editor.directiveViews.iterationActions"),
2991
+ title: t("editor.directiveViews.iterationActionsTitle"),
2921
2992
  className: "ms-auto inline-flex size-5 items-center justify-center rounded-sm text-muted-foreground hover:bg-accent hover:text-foreground focus-ring",
2922
2993
  children: /* @__PURE__ */ jsx10(MoreHorizontal, { className: "size-4", "aria-hidden": "true" })
2923
2994
  }
@@ -2958,6 +3029,7 @@ function IterationDirectiveView() {
2958
3029
  ] });
2959
3030
  }
2960
3031
  function LeafDirectiveView() {
3032
+ const { t } = useLocale4();
2961
3033
  const { name, attributes, update } = useDirectiveAttrs();
2962
3034
  if (name !== "metric") {
2963
3035
  return /* @__PURE__ */ jsxs6(
@@ -2966,7 +3038,8 @@ function LeafDirectiveView() {
2966
3038
  className: "brand-directive brand-directive--leaf brand-directive--unknown rounded-md border border-destructive/40 bg-surface-muted p-3 text-sm text-muted-foreground",
2967
3039
  "data-brand-leaf": name,
2968
3040
  children: [
2969
- "Unknown inline block: ",
3041
+ t("editor.directiveViews.unknownInlineBlock"),
3042
+ " ",
2970
3043
  /* @__PURE__ */ jsxs6("code", { children: [
2971
3044
  "::",
2972
3045
  name
@@ -2984,8 +3057,8 @@ function LeafDirectiveView() {
2984
3057
  label: /* @__PURE__ */ jsx10(
2985
3058
  InlineEdit,
2986
3059
  {
2987
- ariaLabel: "Metric label",
2988
- placeholder: "Label",
3060
+ ariaLabel: t("editor.directiveViews.metricLabel"),
3061
+ placeholder: t("editor.directiveViews.metricLabelPlaceholder"),
2989
3062
  value: attributes.label ?? "",
2990
3063
  onCommit: (v) => update("label", v)
2991
3064
  }
@@ -2993,8 +3066,8 @@ function LeafDirectiveView() {
2993
3066
  value: /* @__PURE__ */ jsx10(
2994
3067
  InlineEdit,
2995
3068
  {
2996
- ariaLabel: "Metric value",
2997
- placeholder: "0",
3069
+ ariaLabel: t("editor.directiveViews.metricValue"),
3070
+ placeholder: t("editor.directiveViews.metricValuePlaceholder"),
2998
3071
  value: attributes.value ?? "",
2999
3072
  onCommit: (v) => update("value", v),
3000
3073
  className: "min-w-[1ch]"
@@ -3313,6 +3386,7 @@ import {
3313
3386
  import { Plugin as Plugin7, PluginKey as PluginKey6 } from "@milkdown/kit/prose/state";
3314
3387
  import { $prose as $prose7 } from "@milkdown/kit/utils";
3315
3388
  import { isInTable } from "@milkdown/kit/prose/tables";
3389
+ import { useLocale as useLocale5 } from "@elabs-ai/components-ui";
3316
3390
  import { cn as cn7 } from "@elabs-ai/components-ui/lib/cn";
3317
3391
  import { usePluginViewContext } from "@prosemirror-adapter/react";
3318
3392
  import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
@@ -3358,25 +3432,32 @@ function ToolbarDivider() {
3358
3432
  }
3359
3433
  function TableControlsView() {
3360
3434
  const { view } = usePluginViewContext();
3435
+ const { t } = useLocale5();
3361
3436
  const inTable = isInTable(view.state);
3362
3437
  const run = (key) => () => dispatchCommand(view, key);
3363
3438
  if (!inTable) return null;
3439
+ const addRowAbove = t("editor.tableView.addRowAbove");
3440
+ const addRowBelow = t("editor.tableView.addRowBelow");
3441
+ const deleteRow = t("editor.tableView.deleteRow");
3442
+ const addColLeft = t("editor.tableView.addColumnLeft");
3443
+ const addColRight = t("editor.tableView.addColumnRight");
3444
+ const deleteCol = t("editor.tableView.deleteColumn");
3364
3445
  return /* @__PURE__ */ jsxs7(
3365
3446
  "div",
3366
3447
  {
3367
3448
  role: "toolbar",
3368
- "aria-label": "Table controls",
3449
+ "aria-label": t("editor.tableView.tableControls"),
3369
3450
  className: cn7(
3370
3451
  "flex flex-wrap items-center gap-1 px-2 py-1.5",
3371
3452
  "border-t border-border-strong bg-surface-muted"
3372
3453
  ),
3373
3454
  children: [
3374
- /* @__PURE__ */ jsx11("span", { className: "mr-1 select-none text-caption text-muted-foreground", children: "Row" }),
3455
+ /* @__PURE__ */ jsx11("span", { className: "mr-1 select-none text-caption text-muted-foreground", children: t("editor.tableView.row") }),
3375
3456
  /* @__PURE__ */ jsx11(
3376
3457
  ToolbarButton,
3377
3458
  {
3378
- ariaLabel: "Add row above",
3379
- title: "Add row above",
3459
+ ariaLabel: addRowAbove,
3460
+ title: addRowAbove,
3380
3461
  onClick: run(addRowBeforeCommand.key),
3381
3462
  children: "\u2191+"
3382
3463
  }
@@ -3384,8 +3465,8 @@ function TableControlsView() {
3384
3465
  /* @__PURE__ */ jsx11(
3385
3466
  ToolbarButton,
3386
3467
  {
3387
- ariaLabel: "Add row below",
3388
- title: "Add row below",
3468
+ ariaLabel: addRowBelow,
3469
+ title: addRowBelow,
3389
3470
  onClick: run(addRowAfterCommand.key),
3390
3471
  children: "\u2193+"
3391
3472
  }
@@ -3393,20 +3474,20 @@ function TableControlsView() {
3393
3474
  /* @__PURE__ */ jsx11(
3394
3475
  ToolbarButton,
3395
3476
  {
3396
- ariaLabel: "Delete row",
3397
- title: "Delete row",
3477
+ ariaLabel: deleteRow,
3478
+ title: deleteRow,
3398
3479
  variant: "destructive",
3399
3480
  onClick: run(deleteSelectedCellsCommand.key),
3400
3481
  children: "\xD7row"
3401
3482
  }
3402
3483
  ),
3403
3484
  /* @__PURE__ */ jsx11(ToolbarDivider, {}),
3404
- /* @__PURE__ */ jsx11("span", { className: "mr-1 select-none text-caption text-muted-foreground", children: "Col" }),
3485
+ /* @__PURE__ */ jsx11("span", { className: "mr-1 select-none text-caption text-muted-foreground", children: t("editor.tableView.col") }),
3405
3486
  /* @__PURE__ */ jsx11(
3406
3487
  ToolbarButton,
3407
3488
  {
3408
- ariaLabel: "Add column left",
3409
- title: "Add column left",
3489
+ ariaLabel: addColLeft,
3490
+ title: addColLeft,
3410
3491
  onClick: run(addColBeforeCommand.key),
3411
3492
  children: "\u2190+"
3412
3493
  }
@@ -3414,8 +3495,8 @@ function TableControlsView() {
3414
3495
  /* @__PURE__ */ jsx11(
3415
3496
  ToolbarButton,
3416
3497
  {
3417
- ariaLabel: "Add column right",
3418
- title: "Add column right",
3498
+ ariaLabel: addColRight,
3499
+ title: addColRight,
3419
3500
  onClick: run(addColAfterCommand.key),
3420
3501
  children: "\u2192+"
3421
3502
  }
@@ -3423,8 +3504,8 @@ function TableControlsView() {
3423
3504
  /* @__PURE__ */ jsx11(
3424
3505
  ToolbarButton,
3425
3506
  {
3426
- ariaLabel: "Delete column",
3427
- title: "Delete column",
3507
+ ariaLabel: deleteCol,
3508
+ title: deleteCol,
3428
3509
  variant: "destructive",
3429
3510
  onClick: run(deleteSelectedCellsCommand.key),
3430
3511
  children: "\xD7col"
@@ -3460,8 +3541,8 @@ function tableViewPlugins(pluginViewFactory) {
3460
3541
 
3461
3542
  // src/markdown-editor/markdown-editor.tsx
3462
3543
  import { jsx as jsx12 } from "react/jsx-runtime";
3463
- function scrollHeadingBySlug(editor2, slug) {
3464
- editor2.action((ctx2) => {
3544
+ function scrollHeadingBySlug(editor, slug) {
3545
+ editor.action((ctx2) => {
3465
3546
  const view = ctx2.get(editorViewCtx3);
3466
3547
  const { doc } = view.state;
3467
3548
  const used = /* @__PURE__ */ new Map();
@@ -3521,7 +3602,7 @@ var MarkdownEditorView = forwardRef6(function MarkdownEditorView2({
3521
3602
  const embedPlugin = pasteEmbedPlugin(
3522
3603
  onEmbedAssetRef.current ? (file) => onEmbedAssetRef.current(file) : void 0
3523
3604
  );
3524
- let editor2 = Editor.make().config((ctx2) => {
3605
+ let editor = Editor.make().config((ctx2) => {
3525
3606
  ctx2.set(rootCtx, root);
3526
3607
  ctx2.set(defaultValueCtx, lastMarkdown.current);
3527
3608
  ctx2.update(editorViewOptionsCtx, (prev) => ({
@@ -3542,7 +3623,7 @@ var MarkdownEditorView = forwardRef6(function MarkdownEditorView2({
3542
3623
  )
3543
3624
  );
3544
3625
  if (slashEnabled) {
3545
- editor2 = editor2.use(
3626
+ editor = editor.use(
3546
3627
  brandSlashViewPlugins(widgetViewFactory, {
3547
3628
  ...slashConfigRef.current,
3548
3629
  getIterationEditHandler: () => iterationEditHandlerRef.current
@@ -3550,14 +3631,14 @@ var MarkdownEditorView = forwardRef6(function MarkdownEditorView2({
3550
3631
  );
3551
3632
  }
3552
3633
  if (calcEnabled) {
3553
- editor2 = editor2.use(calcProsePlugins(() => calcRef.current));
3634
+ editor = editor.use(calcProsePlugins(() => calcRef.current));
3554
3635
  }
3555
3636
  if (completionsEnabled) {
3556
- editor2 = editor2.use(
3637
+ editor = editor.use(
3557
3638
  completionsViewPlugins(widgetViewFactory, () => completionsRef.current)
3558
3639
  );
3559
3640
  }
3560
- return editor2;
3641
+ return editor;
3561
3642
  },
3562
3643
  [readOnly, ariaLabel, slashEnabled, calcEnabled, completionsEnabled]
3563
3644
  );
@@ -3565,21 +3646,21 @@ var MarkdownEditorView = forwardRef6(function MarkdownEditorView2({
3565
3646
  useEffect5(() => {
3566
3647
  if (loading || value === void 0) return;
3567
3648
  if (value === lastMarkdown.current) return;
3568
- const editor2 = getInstance();
3569
- if (!editor2) return;
3649
+ const editor = getInstance();
3650
+ if (!editor) return;
3570
3651
  lastMarkdown.current = value;
3571
- editor2.action(replaceAll(value));
3652
+ editor.action(replaceAll(value));
3572
3653
  }, [loading, value, getInstance]);
3573
3654
  useImperativeHandle2(
3574
3655
  ref,
3575
3656
  () => {
3576
3657
  const serializeSlice = (view) => {
3577
- const editor2 = getInstance();
3578
- if (!editor2) return "";
3658
+ const editor = getInstance();
3659
+ if (!editor) return "";
3579
3660
  const { selection } = view.state;
3580
3661
  if (selection.empty) return "";
3581
3662
  try {
3582
- return editor2.action((ctx2) => {
3663
+ return editor.action((ctx2) => {
3583
3664
  const serialize = ctx2.get(serializerCtx2);
3584
3665
  const doc = selection.content().content;
3585
3666
  const wrapper = view.state.doc.type.schema.topNodeType.create(null, doc);
@@ -3591,10 +3672,10 @@ var MarkdownEditorView = forwardRef6(function MarkdownEditorView2({
3591
3672
  };
3592
3673
  serializeSliceRef.current = serializeSlice;
3593
3674
  const parseAndReplace = (view, md) => {
3594
- const editor2 = getInstance();
3595
- if (!editor2) return;
3675
+ const editor = getInstance();
3676
+ if (!editor) return;
3596
3677
  try {
3597
- editor2.action((ctx2) => {
3678
+ editor.action((ctx2) => {
3598
3679
  const parse = ctx2.get(parserCtx3);
3599
3680
  const parsed = parse(md);
3600
3681
  if (!parsed) {
@@ -3612,10 +3693,10 @@ var MarkdownEditorView = forwardRef6(function MarkdownEditorView2({
3612
3693
  }
3613
3694
  };
3614
3695
  const getView = () => {
3615
- const editor2 = getInstance();
3616
- if (!editor2) return null;
3696
+ const editor = getInstance();
3697
+ if (!editor) return null;
3617
3698
  try {
3618
- return editor2.action((ctx2) => ctx2.get(editorViewCtx3));
3699
+ return editor.action((ctx2) => ctx2.get(editorViewCtx3));
3619
3700
  } catch {
3620
3701
  return null;
3621
3702
  }
@@ -3639,15 +3720,15 @@ var MarkdownEditorView = forwardRef6(function MarkdownEditorView2({
3639
3720
  getMarkdown: () => getInstance()?.action(getMarkdown()) ?? lastMarkdown.current,
3640
3721
  serialized: () => getInstance()?.action(getMarkdown()) ?? null,
3641
3722
  scrollToHeading: (slug) => {
3642
- const editor2 = getInstance();
3643
- if (editor2) scrollHeadingBySlug(editor2, slug);
3723
+ const editor = getInstance();
3724
+ if (editor) scrollHeadingBySlug(editor, slug);
3644
3725
  },
3645
3726
  revealLine: (line, _opts) => {
3646
- const editor2 = getInstance();
3647
- if (!editor2) return;
3648
- const md = editor2.action(getMarkdown());
3727
+ const editor = getInstance();
3728
+ if (!editor) return;
3729
+ const md = editor.action(getMarkdown());
3649
3730
  const preceding = parseMarkdownOutline(md).filter((item) => item.line <= line).at(-1);
3650
- if (preceding) scrollHeadingBySlug(editor2, preceding.id);
3731
+ if (preceding) scrollHeadingBySlug(editor, preceding.id);
3651
3732
  }
3652
3733
  };
3653
3734
  },
@@ -3709,16 +3790,18 @@ var MarkdownEditor = forwardRef6(
3709
3790
  );
3710
3791
 
3711
3792
  // src/copy-button/copy-button.tsx
3712
- import { Button, useCopyToClipboard } from "@elabs-ai/components-ui";
3793
+ import { Button, useCopyToClipboard, useLocale as useLocale6 } from "@elabs-ai/components-ui";
3713
3794
  import { cn as cn9 } from "@elabs-ai/components-ui/lib/cn";
3714
3795
  import { CheckIcon, CopyIcon } from "lucide-react";
3715
3796
  import { useCallback as useCallback3 } from "react";
3716
3797
  import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
3717
3798
  function CopyButton({ value, label = true, className, ...props }) {
3718
3799
  const { copied, copy } = useCopyToClipboard();
3800
+ const { t } = useLocale6();
3719
3801
  const onClick = useCallback3(() => {
3720
3802
  void copy(value);
3721
3803
  }, [copy, value]);
3804
+ const text = copied ? t("editor.copyButton.copied") : t("copy");
3722
3805
  return /* @__PURE__ */ jsxs8(
3723
3806
  Button,
3724
3807
  {
@@ -3728,7 +3811,7 @@ function CopyButton({ value, label = true, className, ...props }) {
3728
3811
  type: "button",
3729
3812
  className: cn9("h-7 gap-1.5", className),
3730
3813
  onClick,
3731
- "aria-label": copied ? "Copied" : "Copy",
3814
+ "aria-label": text,
3732
3815
  children: [
3733
3816
  copied ? /* @__PURE__ */ jsx13(
3734
3817
  CheckIcon,
@@ -3738,37 +3821,37 @@ function CopyButton({ value, label = true, className, ...props }) {
3738
3821
  },
3739
3822
  String(copied)
3740
3823
  ) : /* @__PURE__ */ jsx13(CopyIcon, { className: "size-4", "aria-hidden": "true" }),
3741
- label ? /* @__PURE__ */ jsx13("span", { className: "text-xs", children: copied ? "Copied" : "Copy" }) : null
3824
+ label ? /* @__PURE__ */ jsx13("span", { className: "text-xs", children: text }) : null
3742
3825
  ]
3743
3826
  }
3744
3827
  );
3745
3828
  }
3746
3829
 
3747
3830
  // src/lib/editor-content-access.ts
3748
- function monacoContentAccess(editor2) {
3831
+ function monacoContentAccess(editor) {
3749
3832
  const readSelection = () => {
3750
- const model = editor2.getModel();
3751
- const selection = editor2.getSelection();
3833
+ const model = editor.getModel();
3834
+ const selection = editor.getSelection();
3752
3835
  if (!model || !selection) return { text: "", empty: true };
3753
3836
  const text = model.getValueInRange(selection);
3754
3837
  return { text, empty: selection.isEmpty() };
3755
3838
  };
3756
3839
  const applyAtSelection = (text) => {
3757
- const selection = editor2.getSelection();
3840
+ const selection = editor.getSelection();
3758
3841
  if (!selection) return;
3759
- editor2.executeEdits("editor-content-access", [
3842
+ editor.executeEdits("editor-content-access", [
3760
3843
  { range: selection, text, forceMoveMarkers: true }
3761
3844
  ]);
3762
- editor2.pushUndoStop();
3845
+ editor.pushUndoStop();
3763
3846
  };
3764
3847
  return {
3765
- getText: () => editor2.getValue(),
3848
+ getText: () => editor.getValue(),
3766
3849
  getSelection: readSelection,
3767
3850
  replaceSelection: applyAtSelection,
3768
3851
  insertAtCursor: applyAtSelection,
3769
- focus: () => editor2.focus(),
3852
+ focus: () => editor.focus(),
3770
3853
  onSelectionChange: (listener2) => {
3771
- const sub = editor2.onDidChangeCursorSelection(() => listener2(readSelection()));
3854
+ const sub = editor.onDidChangeCursorSelection(() => listener2(readSelection()));
3772
3855
  return () => sub.dispose();
3773
3856
  }
3774
3857
  };
@@ -3834,4 +3917,4 @@ export {
3834
3917
  CopyButton,
3835
3918
  monacoContentAccess
3836
3919
  };
3837
- //# sourceMappingURL=chunk-C62O7IOQ.js.map
3920
+ //# sourceMappingURL=chunk-FO5S3YZM.js.map