@blocknote/core 0.29.1 → 0.30.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 (69) hide show
  1. package/README.md +125 -0
  2. package/dist/blocknote.cjs +9 -9
  3. package/dist/blocknote.cjs.map +1 -1
  4. package/dist/blocknote.js +1479 -1339
  5. package/dist/blocknote.js.map +1 -1
  6. package/dist/locales.cjs +1 -1
  7. package/dist/locales.cjs.map +1 -1
  8. package/dist/locales.js +751 -9
  9. package/dist/locales.js.map +1 -1
  10. package/dist/style.css +1 -1
  11. package/dist/tsconfig.tsbuildinfo +1 -1
  12. package/dist/webpack-stats.json +1 -1
  13. package/package.json +3 -6
  14. package/src/api/blockManipulation/commands/insertBlocks/__snapshots__/insertBlocks.test.ts.snap +0 -7
  15. package/src/api/blockManipulation/commands/mergeBlocks/__snapshots__/mergeBlocks.test.ts.snap +0 -5
  16. package/src/api/blockManipulation/commands/moveBlocks/__snapshots__/moveBlocks.test.ts.snap +0 -20
  17. package/src/api/blockManipulation/commands/replaceBlocks/__snapshots__/replaceBlocks.test.ts.snap +0 -12
  18. package/src/api/blockManipulation/commands/splitBlock/__snapshots__/splitBlock.test.ts.snap +0 -6
  19. package/src/api/blockManipulation/commands/updateBlock/__snapshots__/updateBlock.test.ts.snap +0 -17
  20. package/src/api/clipboard/fromClipboard/pasteExtension.ts +19 -1
  21. package/src/blocks/AudioBlockContent/AudioBlockContent.ts +5 -0
  22. package/src/blocks/CodeBlockContent/CodeBlockContent.ts +32 -18
  23. package/src/blocks/FileBlockContent/FileBlockContent.ts +5 -0
  24. package/src/blocks/FileBlockContent/helpers/render/createResizableFileBlockWrapper.ts +9 -2
  25. package/src/blocks/HeadingBlockContent/HeadingBlockContent.ts +3 -0
  26. package/src/blocks/ImageBlockContent/ImageBlockContent.ts +10 -2
  27. package/src/blocks/ListItemBlockContent/BulletListItemBlockContent/BulletListItemBlockContent.ts +9 -25
  28. package/src/blocks/ListItemBlockContent/CheckListItemBlockContent/CheckListItemBlockContent.ts +14 -3
  29. package/src/blocks/ListItemBlockContent/NumberedListItemBlockContent/NumberedListItemBlockContent.ts +9 -26
  30. package/src/blocks/ListItemBlockContent/getListItemContent.ts +115 -0
  31. package/src/blocks/ParagraphBlockContent/ParagraphBlockContent.ts +6 -2
  32. package/src/blocks/QuoteBlockContent/QuoteBlockContent.ts +6 -1
  33. package/src/blocks/TableBlockContent/TableBlockContent.ts +71 -14
  34. package/src/blocks/VideoBlockContent/VideoBlockContent.ts +10 -2
  35. package/src/blocks/defaultBlockHelpers.ts +16 -0
  36. package/src/editor/Block.css +2 -1
  37. package/src/editor/BlockNoteEditor.ts +103 -60
  38. package/src/editor/BlockNoteExtensions.ts +14 -5
  39. package/src/extensions/Collaboration/CursorPlugin.ts +152 -0
  40. package/src/extensions/Collaboration/SyncPlugin.ts +15 -0
  41. package/src/extensions/Collaboration/UndoPlugin.ts +14 -0
  42. package/src/extensions/FilePanel/FilePanelPlugin.ts +31 -22
  43. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +2 -4
  44. package/src/extensions/KeyboardShortcuts/KeyboardShortcutsExtension.ts +3 -0
  45. package/src/i18n/locales/index.ts +2 -0
  46. package/src/i18n/locales/ru.ts +2 -2
  47. package/src/i18n/locales/sk.ts +355 -0
  48. package/src/i18n/locales/zh-tw.ts +390 -0
  49. package/src/pm-nodes/BlockContainer.ts +7 -6
  50. package/src/schema/blocks/createSpec.ts +1 -1
  51. package/src/schema/blocks/internal.ts +0 -1
  52. package/src/schema/blocks/types.ts +2 -1
  53. package/types/src/api/blockManipulation/setupTestEnv.d.ts +8 -4
  54. package/types/src/blocks/ImageBlockContent/ImageBlockContent.d.ts +8 -4
  55. package/types/src/blocks/ListItemBlockContent/getListItemContent.d.ts +28 -0
  56. package/types/src/blocks/VideoBlockContent/VideoBlockContent.d.ts +8 -4
  57. package/types/src/blocks/defaultBlockHelpers.d.ts +1 -0
  58. package/types/src/blocks/defaultBlocks.d.ts +16 -8
  59. package/types/src/editor/BlockNoteEditor.d.ts +18 -1
  60. package/types/src/extensions/Collaboration/CursorPlugin.d.ts +31 -0
  61. package/types/src/extensions/Collaboration/SyncPlugin.d.ts +7 -0
  62. package/types/src/extensions/Collaboration/UndoPlugin.d.ts +6 -0
  63. package/types/src/extensions/FilePanel/FilePanelPlugin.d.ts +1 -1
  64. package/types/src/i18n/locales/index.d.ts +2 -0
  65. package/types/src/i18n/locales/sk.d.ts +313 -0
  66. package/types/src/i18n/locales/zh-tw.d.ts +2 -0
  67. package/types/src/schema/blocks/types.d.ts +2 -1
  68. package/src/extensions/Collaboration/createCollaborationExtensions.ts +0 -147
  69. package/types/src/extensions/Collaboration/createCollaborationExtensions.d.ts +0 -17
@@ -0,0 +1,152 @@
1
+ import { Plugin } from "prosemirror-state";
2
+ import { defaultSelectionBuilder, yCursorPlugin } from "y-prosemirror";
3
+ import { Awareness } from "y-protocols/awareness.js";
4
+ import * as Y from "yjs";
5
+
6
+ export type CollaborationUser = {
7
+ name: string;
8
+ color: string;
9
+ [key: string]: string;
10
+ };
11
+
12
+ export class CursorPlugin {
13
+ public plugin: Plugin;
14
+ private provider: { awareness: Awareness };
15
+ private recentlyUpdatedCursors: Map<
16
+ number,
17
+ { element: HTMLElement; hideTimeout: NodeJS.Timeout | undefined }
18
+ >;
19
+ constructor(
20
+ private collaboration: {
21
+ fragment: Y.XmlFragment;
22
+ user: CollaborationUser;
23
+ provider: { awareness: Awareness };
24
+ renderCursor?: (user: CollaborationUser) => HTMLElement;
25
+ showCursorLabels?: "always" | "activity";
26
+ }
27
+ ) {
28
+ this.provider = collaboration.provider;
29
+ this.recentlyUpdatedCursors = new Map();
30
+
31
+ this.provider.awareness.setLocalStateField("user", collaboration.user);
32
+
33
+ if (collaboration.showCursorLabels !== "always") {
34
+ this.provider.awareness.on(
35
+ "change",
36
+ ({
37
+ updated,
38
+ }: {
39
+ added: Array<number>;
40
+ updated: Array<number>;
41
+ removed: Array<number>;
42
+ }) => {
43
+ for (const clientID of updated) {
44
+ const cursor = this.recentlyUpdatedCursors.get(clientID);
45
+
46
+ if (cursor) {
47
+ cursor.element.setAttribute("data-active", "");
48
+
49
+ if (cursor.hideTimeout) {
50
+ clearTimeout(cursor.hideTimeout);
51
+ }
52
+
53
+ this.recentlyUpdatedCursors.set(clientID, {
54
+ element: cursor.element,
55
+ hideTimeout: setTimeout(() => {
56
+ cursor.element.removeAttribute("data-active");
57
+ }, 2000),
58
+ });
59
+ }
60
+ }
61
+ }
62
+ );
63
+ }
64
+
65
+ this.plugin = yCursorPlugin(this.provider.awareness, {
66
+ selectionBuilder: defaultSelectionBuilder,
67
+ cursorBuilder: this.renderCursor,
68
+ });
69
+ }
70
+
71
+ public get priority() {
72
+ return 999;
73
+ }
74
+
75
+ private renderCursor = (user: CollaborationUser, clientID: number) => {
76
+ let cursorData = this.recentlyUpdatedCursors.get(clientID);
77
+
78
+ if (!cursorData) {
79
+ const cursorElement = (
80
+ this.collaboration.renderCursor ?? CursorPlugin.defaultCursorRender
81
+ )(user);
82
+
83
+ if (this.collaboration.showCursorLabels !== "always") {
84
+ cursorElement.addEventListener("mouseenter", () => {
85
+ const cursor = this.recentlyUpdatedCursors.get(clientID)!;
86
+ cursor.element.setAttribute("data-active", "");
87
+
88
+ if (cursor.hideTimeout) {
89
+ clearTimeout(cursor.hideTimeout);
90
+ this.recentlyUpdatedCursors.set(clientID, {
91
+ element: cursor.element,
92
+ hideTimeout: undefined,
93
+ });
94
+ }
95
+ });
96
+
97
+ cursorElement.addEventListener("mouseleave", () => {
98
+ const cursor = this.recentlyUpdatedCursors.get(clientID)!;
99
+
100
+ this.recentlyUpdatedCursors.set(clientID, {
101
+ element: cursor.element,
102
+ hideTimeout: setTimeout(() => {
103
+ cursor.element.removeAttribute("data-active");
104
+ }, 2000),
105
+ });
106
+ });
107
+ }
108
+
109
+ cursorData = {
110
+ element: cursorElement,
111
+ hideTimeout: undefined,
112
+ };
113
+
114
+ this.recentlyUpdatedCursors.set(clientID, cursorData);
115
+ }
116
+
117
+ return cursorData.element;
118
+ };
119
+
120
+ public updateUser = (user: {
121
+ name: string;
122
+ color: string;
123
+ [key: string]: string;
124
+ }) => {
125
+ this.provider.awareness.setLocalStateField("user", user);
126
+ };
127
+
128
+ public static defaultCursorRender = (user: CollaborationUser) => {
129
+ const cursorElement = document.createElement("span");
130
+
131
+ cursorElement.classList.add("bn-collaboration-cursor__base");
132
+
133
+ const caretElement = document.createElement("span");
134
+ caretElement.setAttribute("contentedEditable", "false");
135
+ caretElement.classList.add("bn-collaboration-cursor__caret");
136
+ caretElement.setAttribute("style", `background-color: ${user.color}`);
137
+
138
+ const labelElement = document.createElement("span");
139
+
140
+ labelElement.classList.add("bn-collaboration-cursor__label");
141
+ labelElement.setAttribute("style", `background-color: ${user.color}`);
142
+ labelElement.insertBefore(document.createTextNode(user.name), null);
143
+
144
+ caretElement.insertBefore(labelElement, null);
145
+
146
+ cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space
147
+ cursorElement.insertBefore(caretElement, null);
148
+ cursorElement.insertBefore(document.createTextNode("\u2060"), null); // Non-breaking space
149
+
150
+ return cursorElement;
151
+ };
152
+ }
@@ -0,0 +1,15 @@
1
+ import { Plugin } from "prosemirror-state";
2
+ import { ySyncPlugin } from "y-prosemirror";
3
+ import type * as Y from "yjs";
4
+
5
+ export class SyncPlugin {
6
+ public plugin: Plugin;
7
+
8
+ constructor(fragment: Y.XmlFragment) {
9
+ this.plugin = ySyncPlugin(fragment);
10
+ }
11
+
12
+ public get priority() {
13
+ return 1001;
14
+ }
15
+ }
@@ -0,0 +1,14 @@
1
+ import { Plugin } from "prosemirror-state";
2
+ import { yUndoPlugin } from "y-prosemirror";
3
+
4
+ export class UndoPlugin {
5
+ public plugin: Plugin;
6
+
7
+ constructor() {
8
+ this.plugin = yUndoPlugin();
9
+ }
10
+
11
+ public get priority() {
12
+ return 1000;
13
+ }
14
+ }
@@ -10,6 +10,7 @@ import type {
10
10
  StyleSchema,
11
11
  } from "../../schema/index.js";
12
12
  import { EventEmitter } from "../../util/EventEmitter.js";
13
+ import { ySyncPluginKey } from "y-prosemirror";
13
14
 
14
15
  export type FilePanelState<
15
16
  I extends InlineContentSchema,
@@ -31,7 +32,7 @@ export class FilePanelView<I extends InlineContentSchema, S extends StyleSchema>
31
32
  I,
32
33
  S
33
34
  >,
34
- private readonly pluginKey: PluginKey,
35
+ private readonly pluginKey: PluginKey<FilePanelState<I, S>>,
35
36
  private readonly pmView: EditorView,
36
37
  emitUpdate: (state: FilePanelState<I, S>) => void
37
38
  ) {
@@ -81,11 +82,10 @@ export class FilePanelView<I extends InlineContentSchema, S extends StyleSchema>
81
82
  };
82
83
 
83
84
  update(view: EditorView, prevState: EditorState) {
84
- const pluginState: {
85
- block: BlockFromConfig<FileBlockConfig, I, S>;
86
- } = this.pluginKey.getState(view.state);
85
+ const pluginState = this.pluginKey.getState(view.state);
86
+ const prevPluginState = this.pluginKey.getState(prevState);
87
87
 
88
- if (!this.state?.show && pluginState.block && this.editor.isEditable) {
88
+ if (!this.state?.show && pluginState?.block && this.editor.isEditable) {
89
89
  const blockElement = this.pmView.root.querySelector(
90
90
  `[data-node-type="blockContainer"][data-id="${pluginState.block.id}"]`
91
91
  );
@@ -103,16 +103,15 @@ export class FilePanelView<I extends InlineContentSchema, S extends StyleSchema>
103
103
  return;
104
104
  }
105
105
 
106
- if (
107
- !view.state.selection.eq(prevState.selection) ||
108
- !view.state.doc.eq(prevState.doc) ||
109
- !this.editor.isEditable
110
- ) {
111
- if (this.state?.show) {
112
- this.state.show = false;
113
-
114
- this.emitUpdate();
115
- }
106
+ const isOpening = pluginState?.block && !prevPluginState?.block;
107
+ const isClosing = !pluginState?.block && prevPluginState?.block;
108
+ if (isOpening && this.state && !this.state.show) {
109
+ this.state.show = true;
110
+ this.emitUpdate();
111
+ }
112
+ if (isClosing && this.state?.show) {
113
+ this.state.show = false;
114
+ this.emitUpdate();
116
115
  }
117
116
  }
118
117
 
@@ -132,7 +131,9 @@ export class FilePanelView<I extends InlineContentSchema, S extends StyleSchema>
132
131
  }
133
132
  }
134
133
 
135
- const filePanelPluginKey = new PluginKey("FilePanelPlugin");
134
+ const filePanelPluginKey = new PluginKey<FilePanelState<any, any>>(
135
+ "FilePanelPlugin"
136
+ );
136
137
 
137
138
  export class FilePanelProsemirrorPlugin<
138
139
  I extends InlineContentSchema,
@@ -173,13 +174,21 @@ export class FilePanelProsemirrorPlugin<
173
174
  block: undefined,
174
175
  };
175
176
  },
176
- apply: (transaction) => {
177
- const block: BlockFromConfig<FileBlockConfig, I, S> | undefined =
178
- transaction.getMeta(filePanelPluginKey)?.block;
177
+ apply: (transaction, prev) => {
178
+ const state: FilePanelState<I, S> | undefined =
179
+ transaction.getMeta(filePanelPluginKey);
179
180
 
180
- return {
181
- block,
182
- };
181
+ if (state) {
182
+ return state;
183
+ }
184
+
185
+ if (
186
+ !transaction.getMeta(ySyncPluginKey) &&
187
+ (transaction.selectionSet || transaction.docChanged)
188
+ ) {
189
+ return { block: undefined };
190
+ }
191
+ return prev;
183
192
  },
184
193
  },
185
194
  });
@@ -140,11 +140,9 @@ export class FormattingToolbarView implements PluginView {
140
140
  // Wrapping in a setTimeout gives enough time to wait for the blur event to
141
141
  // occur before updating the toolbar.
142
142
  const { state, composing } = view;
143
- const { selection } = state;
143
+ const { doc, selection } = state;
144
144
  const isSame =
145
- oldState &&
146
- oldState.selection.from === state.selection.from &&
147
- oldState.selection.to === state.selection.to;
145
+ oldState && oldState.doc.eq(doc) && oldState.selection.eq(selection);
148
146
 
149
147
  if (composing || isSame) {
150
148
  return;
@@ -605,6 +605,9 @@ export const KeyboardShortcutsExtension = Extension.create<{
605
605
  this.options.editor.moveBlocksDown();
606
606
  return true;
607
607
  },
608
+ "Mod-z": () => this.options.editor.undo(),
609
+ "Mod-y": () => this.options.editor.redo(),
610
+ "Shift-Mod-z": () => this.options.editor.redo(),
608
611
  };
609
612
  },
610
613
  });
@@ -13,6 +13,8 @@ export * from "./no.js";
13
13
  export * from "./pl.js";
14
14
  export * from "./pt.js";
15
15
  export * from "./ru.js";
16
+ export * from "./sk.js";
16
17
  export * from "./uk.js";
17
18
  export * from "./vi.js";
18
19
  export * from "./zh.js";
20
+ export * from "./zh-tw.js";
@@ -42,7 +42,7 @@ export const ru: Dictionary = {
42
42
  },
43
43
  bullet_list: {
44
44
  title: "Маркированный список",
45
- subtext: "Для отображения неупорядоченного списка.",
45
+ subtext: "Для отображения неупорядоченного списка",
46
46
  aliases: [
47
47
  "ul",
48
48
  "li",
@@ -158,7 +158,7 @@ export const ru: Dictionary = {
158
158
  },
159
159
  },
160
160
  placeholders: {
161
- default: "Ведите текст или введите «/» для команд",
161
+ default: "Введите текст или введите «/» для команд",
162
162
  heading: "Заголовок",
163
163
  bulletListItem: "Список",
164
164
  numberedListItem: "Список",
@@ -0,0 +1,355 @@
1
+ export const sk = {
2
+ slash_menu: {
3
+ heading: {
4
+ title: "Nadpis 1",
5
+ subtext: "Nadpis najvyššej úrovne",
6
+ aliases: ["h", "nadpis1", "h1"],
7
+ group: "Nadpisy",
8
+ },
9
+ heading_2: {
10
+ title: "Nadpis 2",
11
+ subtext: "Kľúčový nadpis sekcie",
12
+ aliases: ["h2", "nadpis2", "podnadpis"],
13
+ group: "Nadpisy",
14
+ },
15
+ heading_3: {
16
+ title: "Nadpis 3",
17
+ subtext: "Podsekcia alebo skupinový nadpis",
18
+ aliases: ["h3", "nadpis3", "podnadpis"],
19
+ group: "Nadpisy",
20
+ },
21
+ quote: {
22
+ title: "Citát",
23
+ subtext: "Citát alebo výňatok",
24
+ aliases: ["citácia", "blockquote", "bq"],
25
+ group: "Základné bloky",
26
+ },
27
+ numbered_list: {
28
+ title: "Číslovaný zoznam",
29
+ subtext: "Zoznam s očíslovanými položkami",
30
+ aliases: ["ol", "li", "zoznam", "číslovanýzoznam", "číslovaný zoznam"],
31
+ group: "Základné bloky",
32
+ },
33
+ bullet_list: {
34
+ title: "Odrážkový zoznam",
35
+ subtext: "Zoznam s nečíslovanými položkami",
36
+ aliases: ["ul", "li", "zoznam", "odrážkovýzoznam", "odrážkový zoznam"],
37
+ group: "Základné bloky",
38
+ },
39
+ check_list: {
40
+ title: "Kontrolný zoznam",
41
+ subtext: "Zoznam s checkboxmi",
42
+ aliases: [
43
+ "ul",
44
+ "li",
45
+ "zoznam",
46
+ "kontrolnýzoznam",
47
+ "kontrolný zoznam",
48
+ "zaškrtnutý zoznam",
49
+ "checkbox",
50
+ ],
51
+ group: "Základné bloky",
52
+ },
53
+ paragraph: {
54
+ title: "Odstavec",
55
+ subtext: "Telo dokumentu",
56
+ aliases: ["p", "odstavec"],
57
+ group: "Základné bloky",
58
+ },
59
+ code_block: {
60
+ title: "Blok kódu",
61
+ subtext: "Blok kódu so zvýraznením syntaxe",
62
+ aliases: ["kód", "pre"],
63
+ group: "Základné bloky",
64
+ },
65
+ page_break: {
66
+ title: "Zlom strany",
67
+ subtext: "Oddeľovač strán",
68
+ aliases: ["strana", "zlom", "oddeľovač"],
69
+ group: "Základné bloky",
70
+ },
71
+ table: {
72
+ title: "Tabuľka",
73
+ subtext: "Tabuľka s editovateľnými bunkami",
74
+ aliases: ["tabuľka"],
75
+ group: "Pokročilé",
76
+ },
77
+ image: {
78
+ title: "Obrázok",
79
+ subtext: "Meniteľný obrázok s popisom",
80
+ aliases: [
81
+ "obrázok",
82
+ "nahratieObrázka",
83
+ "nahratie",
84
+ "img",
85
+ "obrázok",
86
+ "média",
87
+ "url",
88
+ ],
89
+ group: "Médiá",
90
+ },
91
+ video: {
92
+ title: "Video",
93
+ subtext: "Meniteľné video s popisom",
94
+ aliases: [
95
+ "video",
96
+ "nahratieVidea",
97
+ "nahratie",
98
+ "mp4",
99
+ "film",
100
+ "média",
101
+ "url",
102
+ ],
103
+ group: "Médiá",
104
+ },
105
+ audio: {
106
+ title: "Audio",
107
+ subtext: "Vložený zvuk s popisom",
108
+ aliases: [
109
+ "audio",
110
+ "nahratieAudia",
111
+ "nahratie",
112
+ "mp3",
113
+ "zvuk",
114
+ "média",
115
+ "url",
116
+ ],
117
+ group: "Médiá",
118
+ },
119
+ file: {
120
+ title: "Súbor",
121
+ subtext: "Vložený súbor",
122
+ aliases: ["súbor", "nahratie", "vloženie", "média", "url"],
123
+ group: "Médiá",
124
+ },
125
+ emoji: {
126
+ title: "Emoji",
127
+ subtext: "Vyhľadať a vložiť emoji",
128
+ aliases: ["emoji", "emócia", "tvár"],
129
+ group: "Ostatné",
130
+ },
131
+ },
132
+ placeholders: {
133
+ default: "Zadajte text alebo napíšte '/' pre príkazy",
134
+ heading: "Nadpis",
135
+ bulletListItem: "Zoznam",
136
+ numberedListItem: "Zoznam",
137
+ checkListItem: "Zoznam",
138
+ emptyDocument: undefined,
139
+ new_comment: "Napíšte komentár...",
140
+ edit_comment: "Upravte komentár...",
141
+ comment_reply: "Pridať komentár...",
142
+ } as Record<string | "default" | "emptyDocument", string | undefined>,
143
+ file_blocks: {
144
+ image: {
145
+ add_button_text: "Pridať obrázok",
146
+ },
147
+ video: {
148
+ add_button_text: "Pridať video",
149
+ },
150
+ audio: {
151
+ add_button_text: "Pridať audio",
152
+ },
153
+ file: {
154
+ add_button_text: "Pridať súbor",
155
+ },
156
+ },
157
+ side_menu: {
158
+ add_block_label: "Pridať blok",
159
+ drag_handle_label: "Otvoriť menu bloku",
160
+ },
161
+ drag_handle: {
162
+ delete_menuitem: "Vymazať",
163
+ colors_menuitem: "Farby",
164
+ header_row_menuitem: "Hlavičkový riadok",
165
+ header_column_menuitem: "Hlavičkový stĺpec",
166
+ },
167
+ table_handle: {
168
+ delete_column_menuitem: "Vymazať stĺpec",
169
+ delete_row_menuitem: "Vymazať riadok",
170
+ add_left_menuitem: "Pridať stĺpec vľavo",
171
+ add_right_menuitem: "Pridať stĺpec vpravo",
172
+ add_above_menuitem: "Pridať riadok nad",
173
+ add_below_menuitem: "Pridať riadok pod",
174
+ split_cell_menuitem: "Rozdeliť bunku",
175
+ merge_cells_menuitem: "Zlúčiť bunky",
176
+ background_color_menuitem: "Farba pozadia",
177
+ },
178
+ suggestion_menu: {
179
+ no_items_title: "Nenašli sa žiadne položky",
180
+ loading: "Načítava sa…",
181
+ },
182
+ color_picker: {
183
+ text_title: "Text",
184
+ background_title: "Pozadie",
185
+ colors: {
186
+ default: "Predvolená",
187
+ gray: "Sivá",
188
+ brown: "Hnedá",
189
+ red: "Červená",
190
+ orange: "Oranžová",
191
+ yellow: "Žltá",
192
+ green: "Zelená",
193
+ blue: "Modrá",
194
+ purple: "Fialová",
195
+ pink: "Ružová",
196
+ },
197
+ },
198
+ formatting_toolbar: {
199
+ bold: {
200
+ tooltip: "Tučné",
201
+ secondary_tooltip: "Mod+B",
202
+ },
203
+ italic: {
204
+ tooltip: "Kurzíva",
205
+ secondary_tooltip: "Mod+I",
206
+ },
207
+ underline: {
208
+ tooltip: "Podčiarknuté",
209
+ secondary_tooltip: "Mod+U",
210
+ },
211
+ strike: {
212
+ tooltip: "Prečiarknuté",
213
+ secondary_tooltip: "Mod+Shift+S",
214
+ },
215
+ code: {
216
+ tooltip: "Kód",
217
+ secondary_tooltip: "",
218
+ },
219
+ colors: {
220
+ tooltip: "Farby",
221
+ },
222
+ link: {
223
+ tooltip: "Vytvoriť odkaz",
224
+ secondary_tooltip: "Mod+K",
225
+ },
226
+ file_caption: {
227
+ tooltip: "Upraviť popis",
228
+ input_placeholder: "Upraviť popis",
229
+ },
230
+ file_replace: {
231
+ tooltip: {
232
+ image: "Nahradiť obrázok",
233
+ video: "Nahradiť video",
234
+ audio: "Nahradiť audio",
235
+ file: "Nahradiť súbor",
236
+ },
237
+ },
238
+ file_rename: {
239
+ tooltip: {
240
+ image: "Premenovať obrázok",
241
+ video: "Premenovať video",
242
+ audio: "Premenovať audio",
243
+ file: "Premenovať súbor",
244
+ },
245
+ input_placeholder: {
246
+ image: "Premenovať obrázok",
247
+ video: "Premenovať video",
248
+ audio: "Premenovať audio",
249
+ file: "Premenovať súbor",
250
+ },
251
+ },
252
+ file_download: {
253
+ tooltip: {
254
+ image: "Stiahnuť obrázok",
255
+ video: "Stiahnuť video",
256
+ audio: "Stiahnuť audio",
257
+ file: "Stiahnuť súbor",
258
+ },
259
+ },
260
+ file_delete: {
261
+ tooltip: {
262
+ image: "Vymazať obrázok",
263
+ video: "Vymazať video",
264
+ audio: "Vymazať audio",
265
+ file: "Vymazať súbor",
266
+ },
267
+ },
268
+ file_preview_toggle: {
269
+ tooltip: "Prepnúť náhľad",
270
+ },
271
+ nest: {
272
+ tooltip: "Zarovnať blok",
273
+ secondary_tooltip: "Tab",
274
+ },
275
+ unnest: {
276
+ tooltip: "Odzarovnať blok",
277
+ secondary_tooltip: "Shift+Tab",
278
+ },
279
+ align_left: {
280
+ tooltip: "Zarovnať text vľavo",
281
+ },
282
+ align_center: {
283
+ tooltip: "Zarovnať text na stred",
284
+ },
285
+ align_right: {
286
+ tooltip: "Zarovnať text vpravo",
287
+ },
288
+ align_justify: {
289
+ tooltip: "Zarovnať text do bloku",
290
+ },
291
+ table_cell_merge: {
292
+ tooltip: "Zlúčiť bunky",
293
+ },
294
+ comment: {
295
+ tooltip: "Pridať komentár",
296
+ },
297
+ },
298
+ file_panel: {
299
+ upload: {
300
+ title: "Nahratie",
301
+ file_placeholder: {
302
+ image: "Nahrať obrázok",
303
+ video: "Nahrať video",
304
+ audio: "Nahrať audio",
305
+ file: "Nahrať súbor",
306
+ },
307
+ upload_error: "Chyba: Nahratie zlyhalo",
308
+ },
309
+ embed: {
310
+ title: "Vložiť",
311
+ embed_button: {
312
+ image: "Vložiť obrázok",
313
+ video: "Vložiť video",
314
+ audio: "Vložiť audio",
315
+ file: "Vložiť súbor",
316
+ },
317
+ url_placeholder: "Zadajte URL",
318
+ },
319
+ },
320
+ link_toolbar: {
321
+ delete: {
322
+ tooltip: "Odstrániť odkaz",
323
+ },
324
+ edit: {
325
+ text: "Upraviť odkaz",
326
+ tooltip: "Upraviť",
327
+ },
328
+ open: {
329
+ tooltip: "Otvoriť v novom okne",
330
+ },
331
+ form: {
332
+ title_placeholder: "Upraviť názov",
333
+ url_placeholder: "Upraviť URL",
334
+ },
335
+ },
336
+ comments: {
337
+ actions: {
338
+ add_reaction: "Pridať reakciu",
339
+ resolve: "Vyriešiť",
340
+ edit_comment: "Upraviť komentár",
341
+ delete_comment: "Vymazať komentár",
342
+ more_actions: "Ďalšie akcie",
343
+ },
344
+ reactions: {
345
+ reacted_by: "Reagoval/a",
346
+ },
347
+ sidebar: {
348
+ marked_as_resolved: "Označené ako vyriešené",
349
+ more_replies: (count: number) => `${count} ďalších odpovedí`,
350
+ },
351
+ },
352
+ generic: {
353
+ ctrl_shortcut: "Ctrl",
354
+ },
355
+ };