@mdxeditor/editor 2.9.1 → 2.11.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 (29) hide show
  1. package/dist/MDXEditor.js +9 -1
  2. package/dist/index.d.ts +19 -0
  3. package/dist/index.js +7 -3
  4. package/dist/plugins/core/index.js +11 -2
  5. package/dist/plugins/diff-source/DiffViewer.js +13 -5
  6. package/dist/plugins/diff-source/index.js +8 -5
  7. package/dist/plugins/frontmatter/FrontmatterEditor.js +7 -6
  8. package/dist/plugins/image/ImageDialog.js +26 -7
  9. package/dist/plugins/image/ImageEditor.js +3 -2
  10. package/dist/plugins/link-dialog/LinkDialog.js +46 -10
  11. package/dist/plugins/table/TableEditor.js +49 -10
  12. package/dist/plugins/toolbar/components/BlockTypeSelect.js +13 -6
  13. package/dist/plugins/toolbar/components/BoldItalicUnderlineToggles.js +5 -4
  14. package/dist/plugins/toolbar/components/ChangeAdmonitionType.js +17 -5
  15. package/dist/plugins/toolbar/components/ChangeCodeMirrorLanguage.js +5 -4
  16. package/dist/plugins/toolbar/components/CodeToggle.js +3 -2
  17. package/dist/plugins/toolbar/components/CreateLink.js +3 -2
  18. package/dist/plugins/toolbar/components/DiffSourceToggleWrapper.js +6 -5
  19. package/dist/plugins/toolbar/components/InsertAdmonition.js +8 -6
  20. package/dist/plugins/toolbar/components/InsertCodeBlock.js +3 -2
  21. package/dist/plugins/toolbar/components/InsertFrontmatter.js +3 -2
  22. package/dist/plugins/toolbar/components/InsertImage.js +3 -2
  23. package/dist/plugins/toolbar/components/InsertSandpack.js +3 -2
  24. package/dist/plugins/toolbar/components/InsertTable.js +3 -2
  25. package/dist/plugins/toolbar/components/InsertThematicBreak.js +3 -2
  26. package/dist/plugins/toolbar/components/ListsToggle.js +7 -6
  27. package/dist/plugins/toolbar/components/ShowSandpackInfo.js +3 -2
  28. package/dist/plugins/toolbar/components/UndoRedo.js +4 -3
  29. package/package.json +2 -1
package/dist/MDXEditor.js CHANGED
@@ -56,6 +56,13 @@ const IconFallback = () => {
56
56
  const defaultIconComponentFor = (name) => {
57
57
  return /* @__PURE__ */ React__default.createElement(React__default.Suspense, { fallback: /* @__PURE__ */ React__default.createElement(IconFallback, null) }, /* @__PURE__ */ React__default.createElement(DefaultIcon, { name }));
58
58
  };
59
+ function defaultTranslation(key, defaultValue, interpolations = {}) {
60
+ let value = defaultValue;
61
+ for (const [k, v] of Object.entries(interpolations)) {
62
+ value = value.replaceAll(`{{${k}}}`, String(v));
63
+ }
64
+ return value;
65
+ }
59
66
  const RenderRecursiveWrappers = ({ wrappers, children }) => {
60
67
  if (wrappers.length === 0) {
61
68
  return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, children);
@@ -127,7 +134,8 @@ const MDXEditor = React__default.forwardRef((props, ref) => {
127
134
  readOnly: Boolean(props.readOnly),
128
135
  iconComponentFor: props.iconComponentFor ?? defaultIconComponentFor,
129
136
  suppressHtmlProcessing: props.suppressHtmlProcessing ?? false,
130
- onError: props.onError ?? noop
137
+ onError: props.onError ?? noop,
138
+ translation: props.translation ?? defaultTranslation
131
139
  }),
132
140
  ...props.plugins || []
133
141
  ]
package/dist/index.d.ts CHANGED
@@ -240,6 +240,8 @@ export declare const AdmonitionDirectiveDescriptor: DirectiveDescriptor;
240
240
 
241
241
  /* Excluded from this release type: AdmonitionKind */
242
242
 
243
+ export declare function admonitionLabelsMap(t: Translation): Record<(typeof ADMONITION_TYPES)[number], string>;
244
+
243
245
  /**
244
246
  * @group Headings
245
247
  */
@@ -816,6 +818,11 @@ export declare const diffSourcePlugin: (params?: {
816
818
  * Optional, additional CodeMirror extensions to load in the diff/source mode.
817
819
  */
818
820
  codeMirrorExtensions?: Extension_2[] | undefined;
821
+ /**
822
+ * Set the diff editor to read-only.
823
+ * @default false
824
+ */
825
+ readOnlyDiff?: boolean | undefined;
819
826
  } | undefined) => RealmPlugin;
820
827
 
821
828
  /**
@@ -1984,6 +1991,10 @@ export declare interface MDXEditorProps {
1984
1991
  * Set to false if you want to suppress the processing of HTML tags.
1985
1992
  */
1986
1993
  suppressHtmlProcessing?: boolean;
1994
+ /**
1995
+ * Pass your own translation function if you want to localize the editor.
1996
+ */
1997
+ translation?: Translation;
1987
1998
  }
1988
1999
 
1989
2000
  /**
@@ -2198,6 +2209,8 @@ export declare const quotePlugin: (params?: unknown) => RealmPlugin;
2198
2209
  */
2199
2210
  export declare const readOnly$: NodeRef<boolean>;
2200
2211
 
2212
+ /* Excluded from this release type: readOnlyDiff$ */
2213
+
2201
2214
  /**
2202
2215
  * A plugin for the editor.
2203
2216
  * @group Core
@@ -2570,6 +2583,10 @@ export declare const TooltipWrap: React_2.ForwardRefExoticComponent<{
2570
2583
 
2571
2584
  /* Excluded from this release type: topAreaChildren$ */
2572
2585
 
2586
+ export declare const translation$: NodeRef<Translation>;
2587
+
2588
+ export declare type Translation = (key: string, defaultValue: string, interpolations?: Record<string, any>) => string;
2589
+
2573
2590
  /* Excluded from this release type: TYPE_NAME */
2574
2591
 
2575
2592
  /**
@@ -2621,6 +2638,8 @@ export declare function useMdastNodeUpdater<T extends Mdast.RootContent>(): (nod
2621
2638
  */
2622
2639
  export declare function useNestedEditorContext<T extends Mdast.RootContent>(): NestedEditorsContextValue<T>;
2623
2640
 
2641
+ export declare function useTranslation(): Translation;
2642
+
2624
2643
  /* Excluded from this release type: uuidv4 */
2625
2644
 
2626
2645
  /**
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ export * from "@mdxeditor/gurx";
3
3
  import { MDXEditor } from "./MDXEditor.js";
4
4
  import { MarkdownParseError, UnrecognizedMarkdownConstructError, importMarkdownToLexical, importMdastTreeToLexical } from "./importMarkdownToLexical.js";
5
5
  import { exportLexicalTreeToMdast, exportMarkdownFromLexical } from "./exportMarkdownFromLexical.js";
6
- import { Appender, NESTED_EDITOR_UPDATED_COMMAND, activeEditor$, activeEditorSubscriptions$, activePlugins$, addActivePlugin$, addComposerChild$, addEditorWrapper$, addExportVisitor$, addImportVisitor$, addLexicalNode$, addMdastExtension$, addNestedEditorChild$, addSyntaxExtension$, addToMarkdownExtension$, addTopAreaChild$, applyBlockType$, applyFormat$, autoFocus$, codeBlockEditorDescriptors$, composerChildren$, contentEditableClassName$, convertSelectionToNode$, corePlugin, createActiveEditorSubscription$, createRootEditorSubscription$, currentBlockType$, currentFormat$, currentSelection$, directiveDescriptors$, editorInFocus$, editorRootElementRef$, editorWrappers$, exportVisitors$, historyState$, iconComponentFor$, importVisitors$, inFocus$, initialMarkdown$, initialRootEditorState$, insertDecoratorNode$, insertMarkdown$, jsxComponentDescriptors$, jsxIsAvailable$, markdown$, markdownErrorSignal$, markdownProcessingError$, markdownSourceEditorValue$, mdastExtensions$, muteChange$, nestedEditorChildren$, onBlur$, placeholder$, readOnly$, rootEditor$, rootEditorSubscriptions$, setMarkdown$, syntaxExtensions$, toMarkdownExtensions$, toMarkdownOptions$, topAreaChildren$, usedLexicalNodes$, viewMode$ } from "./plugins/core/index.js";
6
+ import { Appender, NESTED_EDITOR_UPDATED_COMMAND, activeEditor$, activeEditorSubscriptions$, activePlugins$, addActivePlugin$, addComposerChild$, addEditorWrapper$, addExportVisitor$, addImportVisitor$, addLexicalNode$, addMdastExtension$, addNestedEditorChild$, addSyntaxExtension$, addToMarkdownExtension$, addTopAreaChild$, applyBlockType$, applyFormat$, autoFocus$, codeBlockEditorDescriptors$, composerChildren$, contentEditableClassName$, convertSelectionToNode$, corePlugin, createActiveEditorSubscription$, createRootEditorSubscription$, currentBlockType$, currentFormat$, currentSelection$, directiveDescriptors$, editorInFocus$, editorRootElementRef$, editorWrappers$, exportVisitors$, historyState$, iconComponentFor$, importVisitors$, inFocus$, initialMarkdown$, initialRootEditorState$, insertDecoratorNode$, insertMarkdown$, jsxComponentDescriptors$, jsxIsAvailable$, markdown$, markdownErrorSignal$, markdownProcessingError$, markdownSourceEditorValue$, mdastExtensions$, muteChange$, nestedEditorChildren$, onBlur$, placeholder$, readOnly$, rootEditor$, rootEditorSubscriptions$, setMarkdown$, syntaxExtensions$, toMarkdownExtensions$, toMarkdownOptions$, topAreaChildren$, translation$, useTranslation, usedLexicalNodes$, viewMode$ } from "./plugins/core/index.js";
7
7
  import { ALL_HEADING_LEVELS, allowedHeadingLevels$, headingsPlugin } from "./plugins/headings/index.js";
8
8
  import { insertThematicBreak$, thematicBreakPlugin } from "./plugins/thematic-break/index.js";
9
9
  import { applyListType$, currentListType$, listsPlugin } from "./plugins/lists/index.js";
@@ -24,11 +24,11 @@ import { ADMONITION_TYPES, AdmonitionDirectiveDescriptor } from "./directive-edi
24
24
  import { GenericDirectiveEditor } from "./directive-editors/GenericDirectiveEditor.js";
25
25
  import { applyLinkChanges$, cancelLinkEdit$, linkAutocompleteSuggestions$, linkDialogPlugin, linkDialogState$, onClickLinkCallback$, onWindowChange$, openLinkEditDialog$, removeLink$, switchFromPreviewToLinkEdit$, updateLink$ } from "./plugins/link-dialog/index.js";
26
26
  import { toolbarContents$, toolbarPlugin } from "./plugins/toolbar/index.js";
27
- import { cmExtensions$, diffMarkdown$, diffSourcePlugin } from "./plugins/diff-source/index.js";
27
+ import { cmExtensions$, diffMarkdown$, diffSourcePlugin, readOnlyDiff$ } from "./plugins/diff-source/index.js";
28
28
  import { markdownShortcutPlugin } from "./plugins/markdown-shortcut/index.js";
29
29
  import { BlockTypeSelect } from "./plugins/toolbar/components/BlockTypeSelect.js";
30
30
  import { BoldItalicUnderlineToggles } from "./plugins/toolbar/components/BoldItalicUnderlineToggles.js";
31
- import { ChangeAdmonitionType } from "./plugins/toolbar/components/ChangeAdmonitionType.js";
31
+ import { ChangeAdmonitionType, admonitionLabelsMap } from "./plugins/toolbar/components/ChangeAdmonitionType.js";
32
32
  import { ChangeCodeMirrorLanguage } from "./plugins/toolbar/components/ChangeCodeMirrorLanguage.js";
33
33
  import { CodeToggle } from "./plugins/toolbar/components/CodeToggle.js";
34
34
  import { CreateLink } from "./plugins/toolbar/components/CreateLink.js";
@@ -149,6 +149,7 @@ export {
149
149
  addSyntaxExtension$,
150
150
  addToMarkdownExtension$,
151
151
  addTopAreaChild$,
152
+ admonitionLabelsMap,
152
153
  allowedHeadingLevels$,
153
154
  always,
154
155
  appendCodeBlockEditorDescriptor$,
@@ -259,6 +260,7 @@ export {
259
260
  prop,
260
261
  quotePlugin,
261
262
  readOnly$,
263
+ readOnlyDiff$,
262
264
  realmPlugin,
263
265
  removeFrontmatter$,
264
266
  removeLink$,
@@ -279,11 +281,13 @@ export {
279
281
  toolbarContents$,
280
282
  toolbarPlugin,
281
283
  topAreaChildren$,
284
+ translation$,
282
285
  updateLink$,
283
286
  useCodeBlockEditorContext,
284
287
  useLexicalNodeRemove,
285
288
  useMdastNodeUpdater,
286
289
  useNestedEditorContext,
290
+ useTranslation,
287
291
  usedLexicalNodes$,
288
292
  uuidv4,
289
293
  viewMode$,
@@ -3,7 +3,7 @@ import { createEmptyHistoryState } from "@lexical/react/LexicalHistoryPlugin.js"
3
3
  import { $isHeadingNode } from "@lexical/rich-text";
4
4
  import { $setBlocksType } from "@lexical/selection";
5
5
  import { $findMatchingParent, $wrapNodeInElement, $insertNodeToNearestRoot } from "@lexical/utils";
6
- import { Cell, withLatestFrom, Signal, filter, map, scan } from "@mdxeditor/gurx";
6
+ import { Cell, withLatestFrom, Signal, filter, map, useCellValue, scan } from "@mdxeditor/gurx";
7
7
  import { createCommand, FORMAT_TEXT_COMMAND, $isRootOrShadowRoot, $getRoot, $setSelection, $getSelection, $insertNodes, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_CRITICAL, FOCUS_COMMAND, KEY_DOWN_COMMAND, $isDecoratorNode, BLUR_COMMAND, $isRangeSelection, $createParagraphNode, ParagraphNode, TextNode } from "lexical";
8
8
  import { mdxJsxFromMarkdown, mdxJsxToMarkdown } from "mdast-util-mdx-jsx";
9
9
  import { mdxJsx } from "micromark-extension-mdx-jsx";
@@ -474,6 +474,9 @@ const markdownSourceEditorValue$ = Cell("", (r) => {
474
474
  });
475
475
  const activePlugins$ = Cell([]);
476
476
  const addActivePlugin$ = Appender(activePlugins$);
477
+ const translation$ = Cell(() => {
478
+ throw new Error("No translation function provided");
479
+ });
477
480
  const corePlugin = realmPlugin({
478
481
  init(r, params) {
479
482
  r.register(createRootEditorSubscription$);
@@ -503,7 +506,8 @@ const corePlugin = realmPlugin({
503
506
  [toMarkdownOptions$]: params == null ? void 0 : params.toMarkdownOptions,
504
507
  [autoFocus$]: params == null ? void 0 : params.autoFocus,
505
508
  [placeholder$]: params == null ? void 0 : params.placeholder,
506
- [readOnly$]: params == null ? void 0 : params.readOnly
509
+ [readOnly$]: params == null ? void 0 : params.readOnly,
510
+ [translation$]: params == null ? void 0 : params.translation
507
511
  });
508
512
  if (!(params == null ? void 0 : params.suppressHtmlProcessing)) {
509
513
  r.pubIn({
@@ -527,6 +531,9 @@ const corePlugin = realmPlugin({
527
531
  realm.singletonSub(markdownErrorSignal$, params == null ? void 0 : params.onError);
528
532
  }
529
533
  });
534
+ function useTranslation() {
535
+ return useCellValue(translation$);
536
+ }
530
537
  export {
531
538
  $createGenericHTMLNode,
532
539
  $isGenericHTMLNode,
@@ -593,6 +600,8 @@ export {
593
600
  toMarkdownExtensions$,
594
601
  toMarkdownOptions$,
595
602
  topAreaChildren$,
603
+ translation$,
604
+ useTranslation,
596
605
  usedLexicalNodes$,
597
606
  viewMode$
598
607
  };
@@ -1,6 +1,6 @@
1
1
  import React__default from "react";
2
- import { diffMarkdown$, cmExtensions$ } from "./index.js";
3
- import { markdown$, markdownSourceEditorValue$, onBlur$ } from "../core/index.js";
2
+ import { diffMarkdown$, readOnlyDiff$, cmExtensions$ } from "./index.js";
3
+ import { markdown$, readOnly$, markdownSourceEditorValue$, onBlur$ } from "../core/index.js";
4
4
  import { MergeView } from "@codemirror/merge";
5
5
  import { EditorState } from "@codemirror/state";
6
6
  import { EditorView } from "@codemirror/view";
@@ -13,7 +13,7 @@ function setContent(view, content) {
13
13
  }
14
14
  const DiffViewer = () => {
15
15
  const realm = useRealm();
16
- const [newMarkdown, oldMarkdown] = useCellValues(markdown$, diffMarkdown$);
16
+ const [newMarkdown, oldMarkdown, readOnly, readOnlyDiff] = useCellValues(markdown$, diffMarkdown$, readOnly$, readOnlyDiff$);
17
17
  const onUpdate = usePublisher(markdownSourceEditorValue$);
18
18
  const elRef = React__default.useRef(null);
19
19
  const cmMergeViewRef = React__default.useRef(null);
@@ -32,16 +32,23 @@ const DiffViewer = () => {
32
32
  });
33
33
  }, [realm]);
34
34
  React__default.useEffect(() => {
35
- cmMergeViewRef.current = new MergeView({
35
+ const isReadOnly = readOnly || readOnlyDiff;
36
+ const revertParams = isReadOnly ? {
37
+ renderRevertControl: void 0,
38
+ revertControls: void 0
39
+ } : {
36
40
  renderRevertControl: () => {
37
41
  const el = document.createElement("button");
38
42
  el.classList.add("cm-merge-revert");
39
43
  el.appendChild(document.createTextNode("⮕"));
40
44
  return el;
41
45
  },
46
+ revertControls: "a-to-b"
47
+ };
48
+ cmMergeViewRef.current = new MergeView({
49
+ ...revertParams,
42
50
  parent: elRef.current,
43
51
  orientation: "a-b",
44
- revertControls: "a-to-b",
45
52
  gutter: true,
46
53
  a: {
47
54
  doc: oldMarkdown,
@@ -52,6 +59,7 @@ const DiffViewer = () => {
52
59
  extensions: [
53
60
  ...cmExtensions,
54
61
  ...COMMON_STATE_CONFIG_EXTENSIONS,
62
+ EditorState.readOnly.of(isReadOnly),
55
63
  EditorView.updateListener.of(({ state }) => {
56
64
  const md = state.doc.toString();
57
65
  onUpdate(md);
@@ -4,21 +4,24 @@ import { Cell } from "@mdxeditor/gurx";
4
4
  import { realmPlugin } from "../../RealmWithPlugins.js";
5
5
  const diffMarkdown$ = Cell("");
6
6
  const cmExtensions$ = Cell([]);
7
+ const readOnlyDiff$ = Cell(false);
7
8
  const diffSourcePlugin = realmPlugin({
8
9
  update: (r, params) => {
9
- r.pub(diffMarkdown$, (params == null ? void 0 : params.diffMarkdown) || "");
10
+ r.pub(diffMarkdown$, (params == null ? void 0 : params.diffMarkdown) ?? "");
10
11
  },
11
12
  init(r, params) {
12
13
  r.pubIn({
13
- [diffMarkdown$]: (params == null ? void 0 : params.diffMarkdown) || "",
14
- [cmExtensions$]: (params == null ? void 0 : params.codeMirrorExtensions) || [],
14
+ [diffMarkdown$]: (params == null ? void 0 : params.diffMarkdown) ?? "",
15
+ [cmExtensions$]: (params == null ? void 0 : params.codeMirrorExtensions) ?? [],
15
16
  [addEditorWrapper$]: DiffSourceWrapper,
16
- [viewMode$]: (params == null ? void 0 : params.viewMode) || "rich-text"
17
+ [readOnlyDiff$]: (params == null ? void 0 : params.readOnlyDiff) ?? false,
18
+ [viewMode$]: (params == null ? void 0 : params.viewMode) ?? "rich-text"
17
19
  });
18
20
  }
19
21
  });
20
22
  export {
21
23
  cmExtensions$,
22
24
  diffMarkdown$,
23
- diffSourcePlugin
25
+ diffSourcePlugin,
26
+ readOnlyDiff$
24
27
  };
@@ -5,7 +5,7 @@ import React__default from "react";
5
5
  import { useForm, useFieldArray } from "react-hook-form";
6
6
  import { frontmatterDialogOpen$, removeFrontmatter$ } from "./index.js";
7
7
  import styles from "../../styles/ui.module.css.js";
8
- import { readOnly$, editorRootElementRef$, iconComponentFor$ } from "../core/index.js";
8
+ import { readOnly$, editorRootElementRef$, iconComponentFor$, useTranslation } from "../core/index.js";
9
9
  import { useCellValues, usePublisher } from "@mdxeditor/gurx";
10
10
  const FrontmatterEditor = ({ yaml, onChange }) => {
11
11
  const [readOnly, editorRootElementRef, iconComponentFor, frontmatterDialogOpen] = useCellValues(
@@ -14,6 +14,7 @@ const FrontmatterEditor = ({ yaml, onChange }) => {
14
14
  iconComponentFor$,
15
15
  frontmatterDialogOpen$
16
16
  );
17
+ const t = useTranslation();
17
18
  const setFrontmatterDialogOpen = usePublisher(frontmatterDialogOpen$);
18
19
  const removeFrontmatter = usePublisher(removeFrontmatter$);
19
20
  const yamlConfig = React__default.useMemo(() => {
@@ -52,7 +53,7 @@ const FrontmatterEditor = ({ yaml, onChange }) => {
52
53
  },
53
54
  [onChange, setFrontmatterDialogOpen, removeFrontmatter]
54
55
  );
55
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(Dialog.Root, { open: frontmatterDialogOpen, onOpenChange: (open) => setFrontmatterDialogOpen(open) }, /* @__PURE__ */ React__default.createElement(Dialog.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Dialog.Overlay, { className: styles.dialogOverlay }), /* @__PURE__ */ React__default.createElement(Dialog.Content, { className: styles.largeDialogContent, "data-editor-type": "frontmatter" }, /* @__PURE__ */ React__default.createElement(Dialog.Title, { className: styles.dialogTitle }, "Edit document frontmatter"), /* @__PURE__ */ React__default.createElement(
56
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(Dialog.Root, { open: frontmatterDialogOpen, onOpenChange: (open) => setFrontmatterDialogOpen(open) }, /* @__PURE__ */ React__default.createElement(Dialog.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Dialog.Overlay, { className: styles.dialogOverlay }), /* @__PURE__ */ React__default.createElement(Dialog.Content, { className: styles.largeDialogContent, "data-editor-type": "frontmatter" }, /* @__PURE__ */ React__default.createElement(Dialog.Title, { className: styles.dialogTitle }, t("frontmatterEditor.title", "Edit document frontmatter")), /* @__PURE__ */ React__default.createElement(
56
57
  "form",
57
58
  {
58
59
  onSubmit: (e) => {
@@ -64,7 +65,7 @@ const FrontmatterEditor = ({ yaml, onChange }) => {
64
65
  setFrontmatterDialogOpen(false);
65
66
  }
66
67
  },
67
- /* @__PURE__ */ React__default.createElement("table", { className: styles.propertyEditorTable }, /* @__PURE__ */ React__default.createElement("colgroup", null, /* @__PURE__ */ React__default.createElement("col", null), /* @__PURE__ */ React__default.createElement("col", null), /* @__PURE__ */ React__default.createElement("col", null)), /* @__PURE__ */ React__default.createElement("thead", null, /* @__PURE__ */ React__default.createElement("tr", null, /* @__PURE__ */ React__default.createElement("th", null, "Key"), /* @__PURE__ */ React__default.createElement("th", null, "Value"), /* @__PURE__ */ React__default.createElement("th", null))), /* @__PURE__ */ React__default.createElement("tbody", null, fields.map((item, index) => {
68
+ /* @__PURE__ */ React__default.createElement("table", { className: styles.propertyEditorTable }, /* @__PURE__ */ React__default.createElement("colgroup", null, /* @__PURE__ */ React__default.createElement("col", null), /* @__PURE__ */ React__default.createElement("col", null), /* @__PURE__ */ React__default.createElement("col", null)), /* @__PURE__ */ React__default.createElement("thead", null, /* @__PURE__ */ React__default.createElement("tr", null, /* @__PURE__ */ React__default.createElement("th", null, t("frontmatterEditor.key", "Key")), /* @__PURE__ */ React__default.createElement("th", null, t("frontmatterEditor.value", "Value")), /* @__PURE__ */ React__default.createElement("th", null))), /* @__PURE__ */ React__default.createElement("tbody", null, fields.map((item, index) => {
68
69
  return /* @__PURE__ */ React__default.createElement("tr", { key: item.id }, /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(TableInput, { ...register(`yamlConfig.${index}.key`, { required: true }), autofocusIfEmpty: true, readOnly })), /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(TableInput, { ...register(`yamlConfig.${index}.value`, { required: true }), readOnly })), /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement("button", { type: "button", onClick: () => remove(index), className: styles.iconButton, disabled: readOnly }, iconComponentFor("delete_big"))));
69
70
  })), /* @__PURE__ */ React__default.createElement("tfoot", null, /* @__PURE__ */ React__default.createElement("tr", null, /* @__PURE__ */ React__default.createElement("td", null, /* @__PURE__ */ React__default.createElement(
70
71
  "button",
@@ -76,10 +77,10 @@ const FrontmatterEditor = ({ yaml, onChange }) => {
76
77
  append({ key: "", value: "" });
77
78
  }
78
79
  },
79
- "Add entry"
80
+ t("frontmatterEditor.addEntry", "Add entry")
80
81
  ))))),
81
- /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: "var(--spacing-2)" } }, /* @__PURE__ */ React__default.createElement("button", { type: "submit", className: styles.primaryButton }, "Save"), /* @__PURE__ */ React__default.createElement("button", { type: "reset", className: styles.secondaryButton }, "Cancel"))
82
- ), /* @__PURE__ */ React__default.createElement(Dialog.Close, { asChild: true }, /* @__PURE__ */ React__default.createElement("button", { className: styles.dialogCloseButton, "aria-label": "Close" }, iconComponentFor("close")))))));
82
+ /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: "var(--spacing-2)" } }, /* @__PURE__ */ React__default.createElement("button", { type: "submit", className: styles.primaryButton }, t("dialogControls.save", "Save")), /* @__PURE__ */ React__default.createElement("button", { type: "reset", className: styles.secondaryButton }, t("dialogControls.cancel", "Cancel")))
83
+ ), /* @__PURE__ */ React__default.createElement(Dialog.Close, { asChild: true }, /* @__PURE__ */ React__default.createElement("button", { className: styles.dialogCloseButton, "aria-label": t("dialogControls.cancel", "Cancel") }, iconComponentFor("close")))))));
83
84
  };
84
85
  const TableInput = React__default.forwardRef(({ className, autofocusIfEmpty: _, ...props }, ref) => {
85
86
  return /* @__PURE__ */ React__default.createElement("input", { className: classNames(styles.propertyEditorInput, className), ...props, ref });
@@ -3,7 +3,7 @@ import classNames from "classnames";
3
3
  import React__default from "react";
4
4
  import { useForm } from "react-hook-form";
5
5
  import styles from "../../styles/ui.module.css.js";
6
- import { editorRootElementRef$ } from "../core/index.js";
6
+ import { editorRootElementRef$, useTranslation } from "../core/index.js";
7
7
  import { imageAutocompleteSuggestions$, imageDialogState$, saveImage$, closeImageDialog$ } from "./index.js";
8
8
  import { DownshiftAutoComplete } from "../core/ui/DownshiftAutoComplete.js";
9
9
  import { useCellValues, usePublisher } from "@mdxeditor/gurx";
@@ -15,6 +15,7 @@ const ImageDialog = () => {
15
15
  );
16
16
  const saveImage = usePublisher(saveImage$);
17
17
  const closeImageDialog = usePublisher(closeImageDialog$);
18
+ const t = useTranslation();
18
19
  const { register, handleSubmit, control, setValue, reset } = useForm({
19
20
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
20
21
  values: state.type === "editing" ? state.initialValues : {}
@@ -49,8 +50,8 @@ const ImageDialog = () => {
49
50
  },
50
51
  className: styles.multiFieldForm
51
52
  },
52
- /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "file" }, "Upload an image from your device:"), /* @__PURE__ */ React__default.createElement("input", { type: "file", ...register("file") })),
53
- /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "src" }, "Or add an image from an URL:"), /* @__PURE__ */ React__default.createElement(
53
+ /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "file" }, t("uploadImage.uploadInstructions", "Upload an image from your device:")), /* @__PURE__ */ React__default.createElement("input", { type: "file", ...register("file") })),
54
+ /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "src" }, t("uploadImage.addViaUrlInstructions", "Or add an image from an URL:")), /* @__PURE__ */ React__default.createElement(
54
55
  DownshiftAutoComplete,
55
56
  {
56
57
  register,
@@ -59,12 +60,30 @@ const ImageDialog = () => {
59
60
  suggestions: imageAutocompleteSuggestions,
60
61
  setValue,
61
62
  control,
62
- placeholder: "Select or paste an image src"
63
+ placeholder: t("uploadImage.autoCompletePlaceholder", "Select or paste an image src")
63
64
  }
64
65
  )),
65
- /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "alt" }, "Alt:"), /* @__PURE__ */ React__default.createElement("input", { type: "text", ...register("altText"), className: styles.textInput })),
66
- /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "title" }, "Title:"), /* @__PURE__ */ React__default.createElement("input", { type: "text", ...register("title"), className: styles.textInput })),
67
- /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: "var(--spacing-2)" } }, /* @__PURE__ */ React__default.createElement("button", { type: "submit", title: "Save", "aria-label": "Save", className: classNames(styles.primaryButton) }, "Save"), /* @__PURE__ */ React__default.createElement(Dialog.Close, { asChild: true }, /* @__PURE__ */ React__default.createElement("button", { type: "reset", title: "Cancel", "aria-label": "Cancel", className: classNames(styles.secondaryButton) }, "Cancel")))
66
+ /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "alt" }, t("uploadImage.alt", "Alt:")), /* @__PURE__ */ React__default.createElement("input", { type: "text", ...register("altText"), className: styles.textInput })),
67
+ /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "title" }, t("uploadImage.title", "Title:")), /* @__PURE__ */ React__default.createElement("input", { type: "text", ...register("title"), className: styles.textInput })),
68
+ /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: "var(--spacing-2)" } }, /* @__PURE__ */ React__default.createElement(
69
+ "button",
70
+ {
71
+ type: "submit",
72
+ title: t("dialogControls.save", "Save"),
73
+ "aria-label": t("dialogControls.save", "Save"),
74
+ className: classNames(styles.primaryButton)
75
+ },
76
+ t("dialogControls.save", "Save")
77
+ ), /* @__PURE__ */ React__default.createElement(Dialog.Close, { asChild: true }, /* @__PURE__ */ React__default.createElement(
78
+ "button",
79
+ {
80
+ type: "reset",
81
+ title: t("dialogControls.cancel", "Cancel"),
82
+ "aria-label": t("dialogControls.cancel", "Cancel"),
83
+ className: classNames(styles.secondaryButton)
84
+ },
85
+ t("dialogControls.cancel", "Cancel")
86
+ )))
68
87
  )
69
88
  ))
70
89
  );
@@ -6,7 +6,7 @@ import classNames from "classnames";
6
6
  import { $isNodeSelection, $getSelection, $getNodeByKey, $setSelection, SELECTION_CHANGE_COMMAND, COMMAND_PRIORITY_LOW, CLICK_COMMAND, DRAGSTART_COMMAND, KEY_DELETE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND } from "lexical";
7
7
  import { disableImageResize$, imagePreviewHandler$, openEditImageDialog$ } from "./index.js";
8
8
  import styles from "../../styles/ui.module.css.js";
9
- import { iconComponentFor$, readOnly$ } from "../core/index.js";
9
+ import { iconComponentFor$, readOnly$, useTranslation } from "../core/index.js";
10
10
  import { $isImageNode } from "./ImageNode.js";
11
11
  import ImageResizer from "./ImageResizer.js";
12
12
  import { useCellValues, usePublisher } from "@mdxeditor/gurx";
@@ -64,6 +64,7 @@ function ImageEditor({ src, title, alt, nodeKey, width, height }) {
64
64
  const [isResizing, setIsResizing] = React__default.useState(false);
65
65
  const [imageSource, setImageSource] = React__default.useState(null);
66
66
  const [initialImagePath, setInitialImagePath] = React__default.useState(null);
67
+ const t = useTranslation();
67
68
  const onDelete = React__default.useCallback(
68
69
  (payload) => {
69
70
  if (isSelected && $isNodeSelection($getSelection())) {
@@ -214,7 +215,7 @@ function ImageEditor({ src, title, alt, nodeKey, width, height }) {
214
215
  {
215
216
  type: "button",
216
217
  className: classNames(styles.iconButton, styles.editImageButton),
217
- title: "Edit image",
218
+ title: t("imageEditor.editImage", "Edit image"),
218
219
  disabled: readOnly,
219
220
  onClick: () => {
220
221
  openEditImageDialog({
@@ -1,7 +1,7 @@
1
1
  import * as RadixPopover from "@radix-ui/react-popover";
2
2
  import * as Tooltip from "@radix-ui/react-tooltip";
3
3
  import React__default from "react";
4
- import { editorRootElementRef$, activeEditor$, iconComponentFor$ } from "../core/index.js";
4
+ import { editorRootElementRef$, activeEditor$, iconComponentFor$, useTranslation } from "../core/index.js";
5
5
  import { DownshiftAutoComplete } from "../core/ui/DownshiftAutoComplete.js";
6
6
  import styles from "../../styles/ui.module.css.js";
7
7
  import classNames from "classnames";
@@ -23,6 +23,7 @@ function LinkEditForm({ url, title, onSubmit, onCancel, linkAutocompleteSuggesti
23
23
  title
24
24
  }
25
25
  });
26
+ const t = useTranslation();
26
27
  return /* @__PURE__ */ React__default.createElement(
27
28
  "form",
28
29
  {
@@ -37,7 +38,7 @@ function LinkEditForm({ url, title, onSubmit, onCancel, linkAutocompleteSuggesti
37
38
  },
38
39
  className: classNames(styles.multiFieldForm, styles.linkDialogEditForm)
39
40
  },
40
- /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "link-url" }, "URL"), /* @__PURE__ */ React__default.createElement(
41
+ /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "link-url" }, t("createLink.url", "URL")), /* @__PURE__ */ React__default.createElement(
41
42
  DownshiftAutoComplete,
42
43
  {
43
44
  register,
@@ -46,12 +47,30 @@ function LinkEditForm({ url, title, onSubmit, onCancel, linkAutocompleteSuggesti
46
47
  suggestions: linkAutocompleteSuggestions,
47
48
  setValue,
48
49
  control,
49
- placeholder: "Select or paste an URL",
50
+ placeholder: t("createLink.urlPlaceholder", "Select or paste an URL"),
50
51
  autofocus: true
51
52
  }
52
53
  )),
53
- /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "link-title" }, "Title"), /* @__PURE__ */ React__default.createElement("input", { id: "link-title", className: styles.textInput, size: 40, ...register("title") })),
54
- /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: "var(--spacing-2)" } }, /* @__PURE__ */ React__default.createElement("button", { type: "submit", title: "Set URL", "aria-label": "Set URL", className: classNames(styles.primaryButton) }, "Save"), /* @__PURE__ */ React__default.createElement("button", { type: "reset", title: "Cancel change", "aria-label": "Cancel change", className: classNames(styles.secondaryButton) }, "Cancel"))
54
+ /* @__PURE__ */ React__default.createElement("div", { className: styles.formField }, /* @__PURE__ */ React__default.createElement("label", { htmlFor: "link-title" }, t("createLink.title", "Title")), /* @__PURE__ */ React__default.createElement("input", { id: "link-title", className: styles.textInput, size: 40, ...register("title") })),
55
+ /* @__PURE__ */ React__default.createElement("div", { style: { display: "flex", justifyContent: "flex-end", gap: "var(--spacing-2)" } }, /* @__PURE__ */ React__default.createElement(
56
+ "button",
57
+ {
58
+ type: "submit",
59
+ title: t("createLink.saveTooltip", "Set URL"),
60
+ "aria-label": t("createLink.saveTooltip", "Set URL"),
61
+ className: classNames(styles.primaryButton)
62
+ },
63
+ t("dialogControls.save", "Save")
64
+ ), /* @__PURE__ */ React__default.createElement(
65
+ "button",
66
+ {
67
+ type: "reset",
68
+ title: t("createLink.cancelTooltip", "Cancel change"),
69
+ "aria-label": t("createLink.cancelTooltip", "Cancel change"),
70
+ className: classNames(styles.secondaryButton)
71
+ },
72
+ t("dialogControls.cancel", "Cancel")
73
+ ))
55
74
  );
56
75
  }
57
76
  const LinkDialog = () => {
@@ -82,6 +101,7 @@ const LinkDialog = () => {
82
101
  };
83
102
  }, [activeEditor, publishWindowChange]);
84
103
  const [copyUrlTooltipOpen, setCopyUrlTooltipOpen] = React__default.useState(false);
104
+ const t = useTranslation();
85
105
  const theRect = linkDialogState == null ? void 0 : linkDialogState.rectangle;
86
106
  const urlIsExternal = linkDialogState.type === "preview" && linkDialogState.url.startsWith("http");
87
107
  return /* @__PURE__ */ React__default.createElement(RadixPopover.Root, { open: linkDialogState.type !== "inactive" }, /* @__PURE__ */ React__default.createElement(
@@ -126,15 +146,23 @@ const LinkDialog = () => {
126
146
  onClickLinkCallback(linkDialogState.url);
127
147
  }
128
148
  },
129
- title: urlIsExternal ? `Open ${linkDialogState.url} in new window` : linkDialogState.url
149
+ title: urlIsExternal ? t("linkPreview.open", `Open {{url}} in new window`, { url: linkDialogState.url }) : linkDialogState.url
130
150
  },
131
151
  /* @__PURE__ */ React__default.createElement("span", null, linkDialogState.url),
132
152
  urlIsExternal && iconComponentFor("open_in_new")
133
- ), /* @__PURE__ */ React__default.createElement(ActionButton, { onClick: () => switchFromPreviewToLinkEdit(), title: "Edit link URL", "aria-label": "Edit link URL" }, iconComponentFor("edit")), /* @__PURE__ */ React__default.createElement(Tooltip.Provider, null, /* @__PURE__ */ React__default.createElement(Tooltip.Root, { open: copyUrlTooltipOpen }, /* @__PURE__ */ React__default.createElement(Tooltip.Trigger, { asChild: true }, /* @__PURE__ */ React__default.createElement(
153
+ ), /* @__PURE__ */ React__default.createElement(
134
154
  ActionButton,
135
155
  {
136
- title: "Copy to clipboard",
137
- "aria-label": "Copy link URL",
156
+ onClick: () => switchFromPreviewToLinkEdit(),
157
+ title: t("linkPreview.edit", "Edit link URL"),
158
+ "aria-label": t("linkPreview.edit", "Edit link URL")
159
+ },
160
+ iconComponentFor("edit")
161
+ ), /* @__PURE__ */ React__default.createElement(Tooltip.Provider, null, /* @__PURE__ */ React__default.createElement(Tooltip.Root, { open: copyUrlTooltipOpen }, /* @__PURE__ */ React__default.createElement(Tooltip.Trigger, { asChild: true }, /* @__PURE__ */ React__default.createElement(
162
+ ActionButton,
163
+ {
164
+ title: t("linkPreview.copyToClipboard", "Copy to clipboard"),
165
+ "aria-label": t("linkPreview.copyToClipboard", "Copy to clipboard"),
138
166
  onClick: () => {
139
167
  void window.navigator.clipboard.writeText(linkDialogState.url).then(() => {
140
168
  setCopyUrlTooltipOpen(true);
@@ -143,7 +171,15 @@ const LinkDialog = () => {
143
171
  }
144
172
  },
145
173
  copyUrlTooltipOpen ? iconComponentFor("check") : iconComponentFor("content_copy")
146
- )), /* @__PURE__ */ React__default.createElement(Tooltip.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Tooltip.Content, { className: classNames(styles.tooltipContent), sideOffset: 5 }, "Copied!", /* @__PURE__ */ React__default.createElement(Tooltip.Arrow, null))))), /* @__PURE__ */ React__default.createElement(ActionButton, { title: "Remove link", "aria-label": "Remove link", onClick: () => removeLink() }, iconComponentFor("link_off"))),
174
+ )), /* @__PURE__ */ React__default.createElement(Tooltip.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(Tooltip.Content, { className: classNames(styles.tooltipContent), sideOffset: 5 }, t("linkPreview.copied", "Copied!"), /* @__PURE__ */ React__default.createElement(Tooltip.Arrow, null))))), /* @__PURE__ */ React__default.createElement(
175
+ ActionButton,
176
+ {
177
+ title: t("linkPreview.remove", "Remove link"),
178
+ "aria-label": t("linkPreview.remove", "Remove link"),
179
+ onClick: () => removeLink()
180
+ },
181
+ iconComponentFor("link_off")
182
+ )),
147
183
  /* @__PURE__ */ React__default.createElement(RadixPopover.Arrow, { className: styles.popoverArrow })
148
184
  )));
149
185
  };
@@ -15,7 +15,7 @@ import classNames from "classnames";
15
15
  import styles from "../../styles/ui.module.css.js";
16
16
  import { isPartOftheEditorUI } from "../../utils/isPartOftheEditorUI.js";
17
17
  import { uuidv4 } from "../../utils/uuid4.js";
18
- import { iconComponentFor$, readOnly$, importVisitors$, exportVisitors$, usedLexicalNodes$, jsxComponentDescriptors$, directiveDescriptors$, codeBlockEditorDescriptors$, jsxIsAvailable$, rootEditor$, NESTED_EDITOR_UPDATED_COMMAND, editorRootElementRef$ } from "../core/index.js";
18
+ import { iconComponentFor$, readOnly$, useTranslation, importVisitors$, exportVisitors$, usedLexicalNodes$, jsxComponentDescriptors$, directiveDescriptors$, codeBlockEditorDescriptors$, jsxIsAvailable$, rootEditor$, NESTED_EDITOR_UPDATED_COMMAND, editorRootElementRef$ } from "../core/index.js";
19
19
  import { useCellValues } from "@mdxeditor/gurx";
20
20
  const AlignToTailwindClassMap = {
21
21
  center: styles.centeredCell,
@@ -115,6 +115,7 @@ const TableEditor = ({ mdastNode, parentEditor, lexicalTable }) => {
115
115
  const rowIndex = tableCell.tagName === "TH" ? -1 : Array.from(tableRow.parentElement.children).indexOf(tableRow);
116
116
  setHighlightedCoordinates([colIndex, rowIndex]);
117
117
  }, []);
118
+ const t = useTranslation();
118
119
  return /* @__PURE__ */ React__default.createElement("table", { className: styles.tableEditor, onMouseOver: onTableMouseOver, onMouseLeave: () => setHighlightedCoordinates([-1, -1]) }, /* @__PURE__ */ React__default.createElement("colgroup", null, readOnly ? null : /* @__PURE__ */ React__default.createElement("col", null), Array.from({ length: mdastNode.children[0].children.length }, (_, colIndex) => {
119
120
  const align = mdastNode.align || [];
120
121
  const currentColumnAlign = align[colIndex] || "left";
@@ -125,7 +126,7 @@ const TableEditor = ({ mdastNode, parentEditor, lexicalTable }) => {
125
126
  {
126
127
  className: styles.iconButton,
127
128
  type: "button",
128
- title: "Delete table",
129
+ title: t("table.deleteTable", "Delete table"),
129
130
  onClick: (e) => {
130
131
  e.preventDefault();
131
132
  parentEditor.update(() => {
@@ -332,12 +333,13 @@ const ColumnEditor = ({
332
333
  },
333
334
  [parentEditor, lexicalTable]
334
335
  );
336
+ const t = useTranslation();
335
337
  return /* @__PURE__ */ React__default.createElement(RadixPopover.Root, null, /* @__PURE__ */ React__default.createElement(
336
338
  RadixPopover.PopoverTrigger,
337
339
  {
338
340
  className: styles.tableColumnEditorTrigger,
339
341
  "data-active": highlightedCoordinates[0] === colIndex + 1,
340
- title: "Column menu"
342
+ title: t("table.columnMenu", "Column menu")
341
343
  },
342
344
  iconComponentFor("more_horiz")
343
345
  ), /* @__PURE__ */ React__default.createElement(RadixPopover.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(
@@ -357,12 +359,26 @@ const ColumnEditor = ({
357
359
  },
358
360
  value: align || "left",
359
361
  type: "single",
360
- "aria-label": "Text alignment"
362
+ "aria-label": t("table.textAlignment", "Text alignment")
361
363
  },
362
- /* @__PURE__ */ React__default.createElement(RadixToolbar.ToggleItem, { value: "left", title: "Align left" }, iconComponentFor("format_align_left")),
363
- /* @__PURE__ */ React__default.createElement(RadixToolbar.ToggleItem, { value: "center", title: "Align center" }, iconComponentFor("format_align_center")),
364
- /* @__PURE__ */ React__default.createElement(RadixToolbar.ToggleItem, { value: "right", title: "Align right" }, iconComponentFor("format_align_right"))
365
- ), /* @__PURE__ */ React__default.createElement(RadixToolbar.Separator, null), /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { onClick: insertColumnAt.bind(null, colIndex), title: "Insert a column to the left of this one" }, iconComponentFor("insert_col_left")), /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { onClick: insertColumnAt.bind(null, colIndex + 1), title: "Insert a column to the right of this one" }, iconComponentFor("insert_col_right")), /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { onClick: deleteColumnAt.bind(null, colIndex), title: "Delete this column" }, iconComponentFor("delete_small"))),
364
+ /* @__PURE__ */ React__default.createElement(RadixToolbar.ToggleItem, { value: "left", title: t("table.alignLeft", "Align left") }, iconComponentFor("format_align_left")),
365
+ /* @__PURE__ */ React__default.createElement(RadixToolbar.ToggleItem, { value: "center", title: t("table.alignCenter", "Align center") }, iconComponentFor("format_align_center")),
366
+ /* @__PURE__ */ React__default.createElement(RadixToolbar.ToggleItem, { value: "right", title: t("table.alignRight", "Align right") }, iconComponentFor("format_align_right"))
367
+ ), /* @__PURE__ */ React__default.createElement(RadixToolbar.Separator, null), /* @__PURE__ */ React__default.createElement(
368
+ RadixToolbar.Button,
369
+ {
370
+ onClick: insertColumnAt.bind(null, colIndex),
371
+ title: t("table.insertColumnLeft", "Insert a column to the left of this one")
372
+ },
373
+ iconComponentFor("insert_col_left")
374
+ ), /* @__PURE__ */ React__default.createElement(
375
+ RadixToolbar.Button,
376
+ {
377
+ onClick: insertColumnAt.bind(null, colIndex + 1),
378
+ title: t("table.insertColumnRight", "Insert a column to the right of this one")
379
+ },
380
+ iconComponentFor("insert_col_right")
381
+ ), /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { onClick: deleteColumnAt.bind(null, colIndex), title: t("table.deleteColumn", "Delete this column") }, iconComponentFor("delete_small"))),
366
382
  /* @__PURE__ */ React__default.createElement(RadixPopover.Arrow, { className: styles.popoverArrow })
367
383
  )));
368
384
  };
@@ -391,7 +407,16 @@ const RowEditor = ({
391
407
  },
392
408
  [parentEditor, lexicalTable]
393
409
  );
394
- return /* @__PURE__ */ React__default.createElement(RadixPopover.Root, null, /* @__PURE__ */ React__default.createElement(RadixPopover.PopoverTrigger, { className: styles.tableColumnEditorTrigger, "data-active": highlightedCoordinates[1] === rowIndex }, iconComponentFor("more_horiz")), /* @__PURE__ */ React__default.createElement(RadixPopover.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(
410
+ const t = useTranslation();
411
+ return /* @__PURE__ */ React__default.createElement(RadixPopover.Root, null, /* @__PURE__ */ React__default.createElement(
412
+ RadixPopover.PopoverTrigger,
413
+ {
414
+ className: styles.tableColumnEditorTrigger,
415
+ "data-active": highlightedCoordinates[1] === rowIndex,
416
+ title: t("table.rowMenu", "Row menu")
417
+ },
418
+ iconComponentFor("more_horiz")
419
+ ), /* @__PURE__ */ React__default.createElement(RadixPopover.Portal, { container: editorRootElementRef == null ? void 0 : editorRootElementRef.current }, /* @__PURE__ */ React__default.createElement(
395
420
  RadixPopover.PopoverContent,
396
421
  {
397
422
  className: classNames(styles.tableColumnEditorPopoverContent),
@@ -399,7 +424,21 @@ const RowEditor = ({
399
424
  sideOffset: 5,
400
425
  side: "bottom"
401
426
  },
402
- /* @__PURE__ */ React__default.createElement(RadixToolbar.Root, { className: styles.tableColumnEditorToolbar }, /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { onClick: insertRowAt.bind(null, rowIndex), title: "Insert a row above this one" }, iconComponentFor("insert_row_above")), /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { onClick: insertRowAt.bind(null, rowIndex + 1), title: "Insert a row below this one" }, iconComponentFor("insert_row_below")), /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { onClick: deleteRowAt.bind(null, rowIndex), title: "Delete this row" }, iconComponentFor("delete_small"))),
427
+ /* @__PURE__ */ React__default.createElement(RadixToolbar.Root, { className: styles.tableColumnEditorToolbar }, /* @__PURE__ */ React__default.createElement(
428
+ RadixToolbar.Button,
429
+ {
430
+ onClick: insertRowAt.bind(null, rowIndex),
431
+ title: t("table.insertRowAbove", "Insert a row above this one")
432
+ },
433
+ iconComponentFor("insert_row_above")
434
+ ), /* @__PURE__ */ React__default.createElement(
435
+ RadixToolbar.Button,
436
+ {
437
+ onClick: insertRowAt.bind(null, rowIndex + 1),
438
+ title: t("table.insertRowBelow", "Insert a row below this one")
439
+ },
440
+ iconComponentFor("insert_row_below")
441
+ ), /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { onClick: deleteRowAt.bind(null, rowIndex), title: t("table.deleteRow", "Delete this row") }, iconComponentFor("delete_small"))),
403
442
  /* @__PURE__ */ React__default.createElement(RadixPopover.Arrow, { className: styles.popoverArrow })
404
443
  )));
405
444
  };
@@ -2,7 +2,7 @@ import { $createHeadingNode, $createQuoteNode } from "@lexical/rich-text";
2
2
  import { usePublisher, useCellValue } from "@mdxeditor/gurx";
3
3
  import { $createParagraphNode } from "lexical";
4
4
  import React__default from "react";
5
- import { convertSelectionToNode$, currentBlockType$, activePlugins$ } from "../../core/index.js";
5
+ import { convertSelectionToNode$, currentBlockType$, activePlugins$, useTranslation } from "../../core/index.js";
6
6
  import { allowedHeadingLevels$ } from "../../headings/index.js";
7
7
  import { Select } from "../primitives/select.js";
8
8
  const BlockTypeSelect = () => {
@@ -11,16 +11,23 @@ const BlockTypeSelect = () => {
11
11
  const activePlugins = useCellValue(activePlugins$);
12
12
  const hasQuote = activePlugins.includes("quote");
13
13
  const hasHeadings = activePlugins.includes("headings");
14
+ const t = useTranslation();
14
15
  if (!hasQuote && !hasHeadings) {
15
16
  return null;
16
17
  }
17
- const items = [{ label: "Paragraph", value: "paragraph" }];
18
+ const items = [
19
+ { label: t("toolbar.blockTypes.paragraph", "Paragraph"), value: "paragraph" }
20
+ ];
18
21
  if (hasQuote) {
19
- items.push({ label: "Quote", value: "quote" });
22
+ items.push({ label: t("toolbar.blockTypes.quote", "Quote"), value: "quote" });
20
23
  }
21
24
  if (hasHeadings) {
22
25
  const allowedHeadingLevels = useCellValue(allowedHeadingLevels$);
23
- items.push(...allowedHeadingLevels.map((n) => ({ label: `Heading ${n}`, value: `h${n}` })));
26
+ items.push(
27
+ ...allowedHeadingLevels.map(
28
+ (n) => ({ label: t("toolbar.blockTypes.heading", "Heading {{level}}", { level: n }), value: `h${n}` })
29
+ )
30
+ );
24
31
  }
25
32
  return /* @__PURE__ */ React__default.createElement(
26
33
  Select,
@@ -44,8 +51,8 @@ const BlockTypeSelect = () => {
44
51
  }
45
52
  }
46
53
  },
47
- triggerTitle: "Select block type",
48
- placeholder: "Block type",
54
+ triggerTitle: t("toolbar.blockTypeSelect.selectBlockTypeTooltip", "Select block type"),
55
+ placeholder: t("toolbar.blockTypeSelect.placeholder", "Block type"),
49
56
  items
50
57
  }
51
58
  );
@@ -1,4 +1,4 @@
1
- import { currentFormat$, iconComponentFor$, applyFormat$ } from "../../core/index.js";
1
+ import { currentFormat$, iconComponentFor$, applyFormat$, useTranslation } from "../../core/index.js";
2
2
  import { useCellValues, usePublisher } from "@mdxeditor/gurx";
3
3
  import React__default from "react";
4
4
  import { IS_BOLD, IS_ITALIC, IS_UNDERLINE } from "../../../FormatConstants.js";
@@ -6,12 +6,13 @@ import { MultipleChoiceToggleGroup } from "../primitives/toolbar.js";
6
6
  const BoldItalicUnderlineToggles = () => {
7
7
  const [currentFormat, iconComponentFor] = useCellValues(currentFormat$, iconComponentFor$);
8
8
  const applyFormat = usePublisher(applyFormat$);
9
+ const t = useTranslation();
9
10
  const boldIsOn = (currentFormat & IS_BOLD) !== 0;
10
11
  const italicIsOn = (currentFormat & IS_ITALIC) !== 0;
11
12
  const underlineIsOn = (currentFormat & IS_UNDERLINE) !== 0;
12
- const boldTitle = boldIsOn ? "Remove bold" : "Bold";
13
- const italicTitle = italicIsOn ? "Remove italic" : "Italic";
14
- const underlineTitle = underlineIsOn ? "Remove underline" : "Underline";
13
+ const boldTitle = boldIsOn ? t("toolbar.removeBold", "Remove bold") : t("toolbar.bold", "Bold");
14
+ const italicTitle = italicIsOn ? t("toolbar.removeItalic", "Remove italic") : t("toolbar.italic", "Italic");
15
+ const underlineTitle = underlineIsOn ? t("toolbar.underline", "Remove underline") : t("toolbar.removeUnderline", "Underline");
15
16
  return /* @__PURE__ */ React__default.createElement(
16
17
  MultipleChoiceToggleGroup,
17
18
  {
@@ -1,11 +1,22 @@
1
1
  import React__default from "react";
2
- import { editorInFocus$, rootEditor$ } from "../../core/index.js";
2
+ import { editorInFocus$, rootEditor$, useTranslation } from "../../core/index.js";
3
3
  import { Select } from "../primitives/select.js";
4
4
  import { ADMONITION_TYPES } from "../../../directive-editors/AdmonitionDirectiveDescriptor.js";
5
5
  import { useCellValues } from "@mdxeditor/gurx";
6
+ function admonitionLabelsMap(t) {
7
+ return {
8
+ note: t("admonitions.note", "Note"),
9
+ tip: t("admonitions.tip", "Tip"),
10
+ danger: t("admonitions.danger", "Danger"),
11
+ info: t("admonitions.info", "Info"),
12
+ caution: t("admonitions.caution", "Caution")
13
+ };
14
+ }
6
15
  const ChangeAdmonitionType = () => {
7
16
  const [editorInFocus, rootEditor] = useCellValues(editorInFocus$, rootEditor$);
8
17
  const admonitionNode = editorInFocus.rootNode;
18
+ const t = useTranslation();
19
+ const labels = admonitionLabelsMap(t);
9
20
  return /* @__PURE__ */ React__default.createElement(
10
21
  Select,
11
22
  {
@@ -20,12 +31,13 @@ const ChangeAdmonitionType = () => {
20
31
  }, 80);
21
32
  });
22
33
  },
23
- triggerTitle: "Select admonition type",
24
- placeholder: "Admonition type",
25
- items: ADMONITION_TYPES.map((type) => ({ label: type.replace(/^./, (l) => l.toUpperCase()), value: type }))
34
+ triggerTitle: t("admonitions.changeType", "Select admonition type"),
35
+ placeholder: t("admonitions.placeholder", "Admonition type"),
36
+ items: ADMONITION_TYPES.map((type) => ({ label: labels[type], value: type }))
26
37
  }
27
38
  );
28
39
  };
29
40
  export {
30
- ChangeAdmonitionType
41
+ ChangeAdmonitionType,
42
+ admonitionLabelsMap
31
43
  };
@@ -2,17 +2,18 @@ import { useCellValues } from "@mdxeditor/gurx";
2
2
  import React__default from "react";
3
3
  import styles from "../../../styles/ui.module.css.js";
4
4
  import { codeBlockLanguages$ } from "../../codemirror/index.js";
5
- import { editorInFocus$, activeEditor$ } from "../../core/index.js";
5
+ import { editorInFocus$, activeEditor$, useTranslation } from "../../core/index.js";
6
6
  import { Select } from "../primitives/select.js";
7
7
  const EMPTY_VALUE = "__EMPTY_VALUE__";
8
8
  const ChangeCodeMirrorLanguage = () => {
9
9
  const [editorInFocus, theEditor, codeBlockLanguages] = useCellValues(editorInFocus$, activeEditor$, codeBlockLanguages$);
10
10
  const codeBlockNode = editorInFocus.rootNode;
11
+ const t = useTranslation();
11
12
  let currentLanguage = codeBlockNode.getLanguage();
12
13
  if (currentLanguage === "") {
13
14
  currentLanguage = EMPTY_VALUE;
14
15
  }
15
- return /* @__PURE__ */ React__default.createElement("div", { className: styles.selectWithLabel }, /* @__PURE__ */ React__default.createElement("label", null, "Code block language:"), /* @__PURE__ */ React__default.createElement(
16
+ return /* @__PURE__ */ React__default.createElement("div", { className: styles.selectWithLabel }, /* @__PURE__ */ React__default.createElement("label", null, t("codeBlock.language", "Code block language")), /* @__PURE__ */ React__default.createElement(
16
17
  Select,
17
18
  {
18
19
  value: currentLanguage,
@@ -26,8 +27,8 @@ const ChangeCodeMirrorLanguage = () => {
26
27
  });
27
28
  });
28
29
  },
29
- triggerTitle: "Select code block language",
30
- placeholder: "Code block language",
30
+ triggerTitle: t("codeBlock.selectLanguage", "Select code block language"),
31
+ placeholder: t("codeBlock.language", "Code block language"),
31
32
  items: Object.entries(codeBlockLanguages).map(([value, label]) => ({ value: value ? value : EMPTY_VALUE, label }))
32
33
  }
33
34
  ));
@@ -1,13 +1,14 @@
1
1
  import React__default from "react";
2
2
  import { IS_CODE } from "../../../FormatConstants.js";
3
- import { currentFormat$, iconComponentFor$, applyFormat$ } from "../../core/index.js";
3
+ import { currentFormat$, iconComponentFor$, applyFormat$, useTranslation } from "../../core/index.js";
4
4
  import { MultipleChoiceToggleGroup } from "../primitives/toolbar.js";
5
5
  import { useCellValues, usePublisher } from "@mdxeditor/gurx";
6
6
  const CodeToggle = () => {
7
7
  const [currentFormat, iconComponentFor] = useCellValues(currentFormat$, iconComponentFor$);
8
8
  const applyFormat = usePublisher(applyFormat$);
9
+ const t = useTranslation();
9
10
  const codeIsOn = (currentFormat & IS_CODE) !== 0;
10
- const title = codeIsOn ? "Remove code format" : "Inline code format";
11
+ const title = codeIsOn ? t("toolbar.removeInlineCode", "Remove code format") : t("toolbar.inlineCode", "Inline code format");
11
12
  return /* @__PURE__ */ React__default.createElement(
12
13
  MultipleChoiceToggleGroup,
13
14
  {
@@ -2,14 +2,15 @@ import React__default from "react";
2
2
  import { ButtonWithTooltip } from "../primitives/toolbar.js";
3
3
  import { openLinkEditDialog$ } from "../../link-dialog/index.js";
4
4
  import { usePublisher, useCellValue } from "@mdxeditor/gurx";
5
- import { iconComponentFor$ } from "../../core/index.js";
5
+ import { iconComponentFor$, useTranslation } from "../../core/index.js";
6
6
  const CreateLink = () => {
7
7
  const openLinkDialog = usePublisher(openLinkEditDialog$);
8
8
  const iconComponentFor = useCellValue(iconComponentFor$);
9
+ const t = useTranslation();
9
10
  return /* @__PURE__ */ React__default.createElement(
10
11
  ButtonWithTooltip,
11
12
  {
12
- title: "Create link",
13
+ title: t("toolbar.link", "Create link"),
13
14
  onClick: (_) => {
14
15
  openLinkDialog();
15
16
  }
@@ -1,4 +1,4 @@
1
- import { viewMode$, iconComponentFor$ } from "../../core/index.js";
1
+ import { viewMode$, iconComponentFor$, useTranslation } from "../../core/index.js";
2
2
  import { useCellValues, usePublisher } from "@mdxeditor/gurx";
3
3
  import React__default from "react";
4
4
  import styles from "../../../styles/ui.module.css.js";
@@ -9,17 +9,18 @@ const DiffSourceToggleWrapper = ({
9
9
  }) => {
10
10
  const [viewMode, iconComponentFor] = useCellValues(viewMode$, iconComponentFor$);
11
11
  const changeViewMode = usePublisher(viewMode$);
12
+ const t = useTranslation();
12
13
  const toggleGroupItems = [];
13
14
  if (options.includes("rich-text")) {
14
- toggleGroupItems.push({ title: "Rich text", contents: iconComponentFor("rich_text"), value: "rich-text" });
15
+ toggleGroupItems.push({ title: t("toolbar.richText", "Rich text"), contents: iconComponentFor("rich_text"), value: "rich-text" });
15
16
  }
16
17
  if (options.includes("diff")) {
17
- toggleGroupItems.push({ title: "Diff mode", contents: iconComponentFor("difference"), value: "diff" });
18
+ toggleGroupItems.push({ title: t("toolbar.diffMode", "Diff mode"), contents: iconComponentFor("difference"), value: "diff" });
18
19
  }
19
20
  if (options.includes("source")) {
20
- toggleGroupItems.push({ title: "Source", contents: iconComponentFor("markdown"), value: "source" });
21
+ toggleGroupItems.push({ title: t("toolbar.source", "Source mode"), contents: iconComponentFor("markdown"), value: "source" });
21
22
  }
22
- return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, viewMode === "rich-text" ? children : viewMode === "diff" ? /* @__PURE__ */ React__default.createElement("span", { className: styles.toolbarTitleMode }, "Diff mode") : /* @__PURE__ */ React__default.createElement("span", { className: styles.toolbarTitleMode }, "Source mode"), /* @__PURE__ */ React__default.createElement("div", { style: { marginLeft: "auto", pointerEvents: "auto", opacity: 1 } }, /* @__PURE__ */ React__default.createElement(
23
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, viewMode === "rich-text" ? children : viewMode === "diff" ? /* @__PURE__ */ React__default.createElement("span", { className: styles.toolbarTitleMode }, t("toolbar.diffMode", "Diff mode")) : /* @__PURE__ */ React__default.createElement("span", { className: styles.toolbarTitleMode }, t("toolbar.source", "Source mode")), /* @__PURE__ */ React__default.createElement("div", { style: { marginLeft: "auto", pointerEvents: "auto", opacity: 1 } }, /* @__PURE__ */ React__default.createElement(
23
24
  SingleChoiceToggleGroup,
24
25
  {
25
26
  className: styles.diffSourceToggle,
@@ -3,18 +3,20 @@ import { ButtonOrDropdownButton } from "../primitives/toolbar.js";
3
3
  import { insertDirective$ } from "../../directives/index.js";
4
4
  import { ADMONITION_TYPES } from "../../../directive-editors/AdmonitionDirectiveDescriptor.js";
5
5
  import { usePublisher, useCellValue } from "@mdxeditor/gurx";
6
- import { iconComponentFor$ } from "../../core/index.js";
6
+ import { iconComponentFor$, useTranslation } from "../../core/index.js";
7
+ import { admonitionLabelsMap } from "./ChangeAdmonitionType.js";
7
8
  const InsertAdmonition = () => {
8
9
  const insertDirective = usePublisher(insertDirective$);
9
10
  const iconComponentFor = useCellValue(iconComponentFor$);
10
- const items = React__default.useMemo(
11
- () => ADMONITION_TYPES.map((type) => ({ value: type, label: type.replace(/^./, (l) => l.toUpperCase()) })),
12
- []
13
- );
11
+ const t = useTranslation();
12
+ const items = React__default.useMemo(() => {
13
+ const labels = admonitionLabelsMap(t);
14
+ return ADMONITION_TYPES.map((type) => ({ value: type, label: labels[type] }));
15
+ }, [t]);
14
16
  return /* @__PURE__ */ React__default.createElement(
15
17
  ButtonOrDropdownButton,
16
18
  {
17
- title: "Insert admonition",
19
+ title: t("toolbar.admonition", "Insert Admonition"),
18
20
  onChoose: (admonitionName) => {
19
21
  insertDirective({
20
22
  type: "containerDirective",
@@ -2,14 +2,15 @@ import React__default from "react";
2
2
  import { ButtonWithTooltip } from "../primitives/toolbar.js";
3
3
  import { insertCodeBlock$ } from "../../codeblock/index.js";
4
4
  import { usePublisher, useCellValue } from "@mdxeditor/gurx";
5
- import { iconComponentFor$ } from "../../core/index.js";
5
+ import { iconComponentFor$, useTranslation } from "../../core/index.js";
6
6
  const InsertCodeBlock = () => {
7
7
  const insertCodeBlock = usePublisher(insertCodeBlock$);
8
8
  const iconComponentFor = useCellValue(iconComponentFor$);
9
+ const t = useTranslation();
9
10
  return /* @__PURE__ */ React__default.createElement(
10
11
  ButtonWithTooltip,
11
12
  {
12
- title: "Insert code block",
13
+ title: t("toolbar.codeBlock", "Insert Code Block"),
13
14
  onClick: () => {
14
15
  insertCodeBlock({});
15
16
  }
@@ -4,14 +4,15 @@ import { insertFrontmatter$, hasFrontmatter$ } from "../../frontmatter/index.js"
4
4
  import styles from "../../../styles/ui.module.css.js";
5
5
  import classNames from "classnames";
6
6
  import { usePublisher, useCellValues } from "@mdxeditor/gurx";
7
- import { iconComponentFor$ } from "../../core/index.js";
7
+ import { iconComponentFor$, useTranslation } from "../../core/index.js";
8
8
  const InsertFrontmatter = () => {
9
9
  const insertFrontmatter = usePublisher(insertFrontmatter$);
10
10
  const [hasFrontmatter, iconComponentFor] = useCellValues(hasFrontmatter$, iconComponentFor$);
11
+ const t = useTranslation();
11
12
  return /* @__PURE__ */ React__default.createElement(
12
13
  ButtonWithTooltip,
13
14
  {
14
- title: hasFrontmatter ? "Edit frontmatter" : "Insert frontmatter",
15
+ title: hasFrontmatter ? t("toolbar.editFrontmatter", "Edit frontmatter") : t("toolbar.insertFrontmatter", "Insert frontmatter"),
15
16
  className: classNames({
16
17
  [styles.activeToolbarButton]: hasFrontmatter
17
18
  }),
@@ -2,13 +2,14 @@ import React__default from "react";
2
2
  import { openNewImageDialog$ } from "../../image/index.js";
3
3
  import * as RadixToolbar from "@radix-ui/react-toolbar";
4
4
  import styles from "../../../styles/ui.module.css.js";
5
- import { readOnly$, iconComponentFor$ } from "../../core/index.js";
5
+ import { readOnly$, iconComponentFor$, useTranslation } from "../../core/index.js";
6
6
  import { TooltipWrap } from "../primitives/TooltipWrap.js";
7
7
  import { usePublisher, useCellValues } from "@mdxeditor/gurx";
8
8
  const InsertImage = React__default.forwardRef((_, forwardedRef) => {
9
9
  const openNewImageDialog = usePublisher(openNewImageDialog$);
10
10
  const [readOnly, iconComponentFor] = useCellValues(readOnly$, iconComponentFor$);
11
- return /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { className: styles.toolbarButton, ref: forwardedRef, disabled: readOnly, onClick: () => openNewImageDialog() }, /* @__PURE__ */ React__default.createElement(TooltipWrap, { title: "Insert image" }, iconComponentFor("add_photo")));
11
+ const t = useTranslation();
12
+ return /* @__PURE__ */ React__default.createElement(RadixToolbar.Button, { className: styles.toolbarButton, ref: forwardedRef, disabled: readOnly, onClick: () => openNewImageDialog() }, /* @__PURE__ */ React__default.createElement(TooltipWrap, { title: t("toolbar.image", "Insert image") }, iconComponentFor("add_photo")));
12
13
  });
13
14
  export {
14
15
  InsertImage
@@ -2,12 +2,13 @@ import React__default from "react";
2
2
  import { ButtonOrDropdownButton } from "../primitives/toolbar.js";
3
3
  import { sandpackConfig$, insertSandpack$ } from "../../sandpack/index.js";
4
4
  import { useCellValues, usePublisher } from "@mdxeditor/gurx";
5
- import { iconComponentFor$ } from "../../core/index.js";
5
+ import { iconComponentFor$, useTranslation } from "../../core/index.js";
6
6
  const InsertSandpack = () => {
7
7
  const [sandpackConfig, iconComponentFor] = useCellValues(sandpackConfig$, iconComponentFor$);
8
8
  const insertSandpack = usePublisher(insertSandpack$);
9
9
  const items = React__default.useMemo(() => sandpackConfig.presets.map((preset) => ({ value: preset.name, label: preset.label })), [sandpackConfig]);
10
- return /* @__PURE__ */ React__default.createElement(ButtonOrDropdownButton, { title: "Insert Sandpack", onChoose: insertSandpack, items }, iconComponentFor("sandpack"));
10
+ const t = useTranslation();
11
+ return /* @__PURE__ */ React__default.createElement(ButtonOrDropdownButton, { title: t("toolbar.insertSandpack", "Insert Sandpack"), onChoose: insertSandpack, items }, iconComponentFor("sandpack"));
11
12
  };
12
13
  export {
13
14
  InsertSandpack
@@ -2,14 +2,15 @@ import { ButtonWithTooltip } from "../primitives/toolbar.js";
2
2
  import React__default from "react";
3
3
  import { insertTable$ } from "../../table/index.js";
4
4
  import { useCellValue, usePublisher } from "@mdxeditor/gurx";
5
- import { iconComponentFor$ } from "../../core/index.js";
5
+ import { iconComponentFor$, useTranslation } from "../../core/index.js";
6
6
  const InsertTable = () => {
7
7
  const iconComponentFor = useCellValue(iconComponentFor$);
8
8
  const insertTable = usePublisher(insertTable$);
9
+ const t = useTranslation();
9
10
  return /* @__PURE__ */ React__default.createElement(
10
11
  ButtonWithTooltip,
11
12
  {
12
- title: "Insert table",
13
+ title: t("toolbar.table", "Insert Table"),
13
14
  onClick: () => {
14
15
  insertTable({ rows: 3, columns: 3 });
15
16
  }
@@ -2,11 +2,12 @@ import React__default from "react";
2
2
  import { insertThematicBreak$ } from "../../thematic-break/index.js";
3
3
  import { ButtonWithTooltip } from "../primitives/toolbar.js";
4
4
  import { usePublisher, useCellValue } from "@mdxeditor/gurx";
5
- import { iconComponentFor$ } from "../../core/index.js";
5
+ import { iconComponentFor$, useTranslation } from "../../core/index.js";
6
6
  const InsertThematicBreak = () => {
7
7
  const insertThematicBreak = usePublisher(insertThematicBreak$);
8
8
  const iconComponentFor = useCellValue(iconComponentFor$);
9
- return /* @__PURE__ */ React__default.createElement(ButtonWithTooltip, { title: "Insert thematic break", onClick: () => insertThematicBreak() }, iconComponentFor("horizontal_rule"));
9
+ const t = useTranslation();
10
+ return /* @__PURE__ */ React__default.createElement(ButtonWithTooltip, { title: t("toolbar.thematicBreak", "Insert thematic break"), onClick: () => insertThematicBreak() }, iconComponentFor("horizontal_rule"));
10
11
  };
11
12
  export {
12
13
  InsertThematicBreak
@@ -2,12 +2,7 @@ import React__default from "react";
2
2
  import { currentListType$, applyListType$ } from "../../lists/index.js";
3
3
  import { SingleChoiceToggleGroup } from "../primitives/toolbar.js";
4
4
  import { useCellValues, usePublisher } from "@mdxeditor/gurx";
5
- import { iconComponentFor$ } from "../../core/index.js";
6
- const LIST_TITLE_MAP = {
7
- bullet: "Bulleted list",
8
- number: "Numbered list",
9
- check: "Check list"
10
- };
5
+ import { iconComponentFor$, useTranslation } from "../../core/index.js";
11
6
  const ICON_NAME_MAP = {
12
7
  bullet: "format_list_bulleted",
13
8
  number: "format_list_numbered",
@@ -16,6 +11,12 @@ const ICON_NAME_MAP = {
16
11
  const ListsToggle = ({ options = ["bullet", "number", "check"] }) => {
17
12
  const [currentListType, iconComponentFor] = useCellValues(currentListType$, iconComponentFor$);
18
13
  const applyListType = usePublisher(applyListType$);
14
+ const t = useTranslation();
15
+ const LIST_TITLE_MAP = {
16
+ bullet: t("toolbar.bulletedList", "Bulleted list"),
17
+ number: t("toolbar.numberedList", "Numbered list"),
18
+ check: t("toolbar.checkList", "Check list")
19
+ };
19
20
  const items = options.map((type) => ({
20
21
  value: type,
21
22
  title: LIST_TITLE_MAP[type],
@@ -1,6 +1,6 @@
1
1
  import React__default from "react";
2
2
  import styles from "../../../styles/ui.module.css.js";
3
- import { editorInFocus$, activeEditor$, iconComponentFor$ } from "../../core/index.js";
3
+ import { editorInFocus$, activeEditor$, iconComponentFor$, useTranslation } from "../../core/index.js";
4
4
  import { sandpackConfig$ } from "../../sandpack/index.js";
5
5
  import { ButtonWithTooltip } from "../primitives/toolbar.js";
6
6
  import { useCellValues } from "@mdxeditor/gurx";
@@ -12,11 +12,12 @@ const ShowSandpackInfo = () => {
12
12
  sandpackConfig$
13
13
  );
14
14
  const sandpackNode = editorInFocus.rootNode;
15
+ const t = useTranslation();
15
16
  const preset = sandpackConfig.presets.find((preset2) => preset2.meta === sandpackNode.getMeta());
16
17
  return /* @__PURE__ */ React__default.createElement("div", { className: styles.selectWithLabel }, /* @__PURE__ */ React__default.createElement(
17
18
  ButtonWithTooltip,
18
19
  {
19
- title: "Delete this code block",
20
+ title: t("toolbar.deleteSandpack", "Delete this code block"),
20
21
  onClick: () => {
21
22
  theEditor == null ? void 0 : theEditor.update(() => {
22
23
  if (sandpackNode.getNextSibling()) {
@@ -3,12 +3,13 @@ import { useCellValues } from "@mdxeditor/gurx";
3
3
  import { CAN_UNDO_COMMAND, COMMAND_PRIORITY_CRITICAL, CAN_REDO_COMMAND, UNDO_COMMAND, REDO_COMMAND } from "lexical";
4
4
  import React__default from "react";
5
5
  import { IS_APPLE } from "../../../utils/detectMac.js";
6
- import { iconComponentFor$, activeEditor$ } from "../../core/index.js";
6
+ import { iconComponentFor$, activeEditor$, useTranslation } from "../../core/index.js";
7
7
  import { MultipleChoiceToggleGroup } from "../primitives/toolbar.js";
8
8
  const UndoRedo = () => {
9
9
  const [iconComponentFor, activeEditor] = useCellValues(iconComponentFor$, activeEditor$);
10
10
  const [canUndo, setCanUndo] = React__default.useState(false);
11
11
  const [canRedo, setCanRedo] = React__default.useState(false);
12
+ const t = useTranslation();
12
13
  React__default.useEffect(() => {
13
14
  if (activeEditor) {
14
15
  return mergeRegister(
@@ -36,14 +37,14 @@ const UndoRedo = () => {
36
37
  {
37
38
  items: [
38
39
  {
39
- title: IS_APPLE ? "Undo (⌘Z)" : "Undo (Ctrl+Z)",
40
+ title: t("toolbar.undo", "Undo {{shortcut}}", { shortcut: IS_APPLE ? "⌘Z" : "Ctrl+Z" }),
40
41
  disabled: !canUndo,
41
42
  contents: iconComponentFor("undo"),
42
43
  active: false,
43
44
  onChange: () => activeEditor == null ? void 0 : activeEditor.dispatchCommand(UNDO_COMMAND, void 0)
44
45
  },
45
46
  {
46
- title: IS_APPLE ? "Redo (⌘Y)" : "Redo (Ctrl+Y)",
47
+ title: t("toolbar.redo", "Redo {{shortcut}}", { shortcut: IS_APPLE ? "⌘Y" : "Ctrl+Y" }),
47
48
  disabled: !canRedo,
48
49
  contents: iconComponentFor("redo"),
49
50
  active: false,
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "*.css"
12
12
  ],
13
13
  "type": "module",
14
- "version": "2.9.1",
14
+ "version": "2.11.0",
15
15
  "description": "React component for rich text markdown editing",
16
16
  "scripts": {
17
17
  "build": "vite build",
@@ -126,6 +126,7 @@
126
126
  "eslint-plugin-react": "^7.33.2",
127
127
  "eslint-plugin-react-hooks": "^4.6.0",
128
128
  "express": "^4.18.2",
129
+ "i18next": "^23.10.0",
129
130
  "jsdom": "^23.0.1",
130
131
  "mermaid": "^10.6.1",
131
132
  "micromark-util-types": "^2.0.0",