@blocknote/core 0.5.1 → 0.6.1

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 (39) hide show
  1. package/dist/blocknote.js +1126 -1031
  2. package/dist/blocknote.js.map +1 -1
  3. package/dist/blocknote.umd.cjs +2 -2
  4. package/dist/blocknote.umd.cjs.map +1 -1
  5. package/dist/style.css +1 -1
  6. package/package.json +2 -2
  7. package/src/BlockNoteEditor.ts +244 -3
  8. package/src/BlockNoteExtensions.ts +3 -2
  9. package/src/api/blockManipulation/__snapshots__/blockManipulation.test.ts.snap +35 -35
  10. package/src/api/formatConversions/__snapshots__/formatConversions.test.ts.snap +10 -10
  11. package/src/api/nodeConversions/__snapshots__/nodeConversions.test.ts.snap +10 -10
  12. package/src/api/nodeConversions/nodeConversions.ts +11 -10
  13. package/src/editor.module.css +11 -2
  14. package/src/extensions/Blocks/api/inlineContentTypes.ts +3 -2
  15. package/src/extensions/Blocks/api/selectionTypes.ts +5 -0
  16. package/src/extensions/Blocks/nodes/Block.module.css +20 -2
  17. package/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.ts +5 -6
  18. package/src/extensions/DraggableBlocks/DraggableBlocksExtension.ts +5 -2
  19. package/src/extensions/DraggableBlocks/DraggableBlocksPlugin.ts +76 -113
  20. package/src/extensions/FormattingToolbar/FormattingToolbarExtension.ts +6 -3
  21. package/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.ts +2 -34
  22. package/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +39 -113
  23. package/src/extensions/HyperlinkToolbar/HyperlinkToolbarPlugin.ts +56 -39
  24. package/src/extensions/UniqueID/UniqueID.ts +1 -1
  25. package/src/index.ts +1 -0
  26. package/src/shared/plugins/suggestion/SuggestionPlugin.ts +14 -2
  27. package/types/src/BlockNoteEditor.d.ts +79 -0
  28. package/types/src/extensions/Blocks/api/inlineContentTypes.d.ts +3 -2
  29. package/types/src/extensions/Blocks/api/selectionTypes.d.ts +4 -0
  30. package/types/src/extensions/DraggableBlocks/BlockSideMenuFactoryTypes.d.ts +4 -5
  31. package/types/src/extensions/DraggableBlocks/DraggableBlocksExtension.d.ts +3 -1
  32. package/types/src/extensions/DraggableBlocks/DraggableBlocksPlugin.d.ts +14 -16
  33. package/types/src/extensions/FormattingToolbar/FormattingToolbarExtension.d.ts +2 -0
  34. package/types/src/extensions/FormattingToolbar/FormattingToolbarFactoryTypes.d.ts +2 -25
  35. package/types/src/extensions/FormattingToolbar/FormattingToolbarPlugin.d.ts +9 -4
  36. package/types/src/index.d.ts +1 -0
  37. package/types/src/api/Editor.d.ts +0 -93
  38. package/types/src/extensions/SlashMenu/SlashMenuItem.d.ts +0 -24
  39. package/types/src/extensions/SlashMenu/defaultSlashCommands.d.ts +0 -5
@@ -6,8 +6,7 @@ import {
6
6
  } from "@tiptap/core";
7
7
  import { EditorState, Plugin, PluginKey } from "prosemirror-state";
8
8
  import { EditorView } from "prosemirror-view";
9
- import { Block, PartialBlock } from "../Blocks/api/blockTypes";
10
- import { getBlockInfoFromPos } from "../Blocks/helpers/getBlockInfoFromPos";
9
+ import { BlockNoteEditor } from "../..";
11
10
  import {
12
11
  FormattingToolbar,
13
12
  FormattingToolbarDynamicParams,
@@ -19,11 +18,12 @@ import {
19
18
  // https://github.com/ueberdosis/tiptap/pull/2596/files
20
19
  export interface FormattingToolbarPluginProps {
21
20
  pluginKey: PluginKey;
22
- editor: Editor;
21
+ tiptapEditor: Editor;
22
+ editor: BlockNoteEditor;
23
23
  formattingToolbarFactory: FormattingToolbarFactory;
24
24
  shouldShow?:
25
25
  | ((props: {
26
- editor: Editor;
26
+ editor: BlockNoteEditor;
27
27
  view: EditorView;
28
28
  state: EditorState;
29
29
  oldState?: EditorState;
@@ -38,7 +38,8 @@ export type FormattingToolbarViewProps = FormattingToolbarPluginProps & {
38
38
  };
39
39
 
40
40
  export class FormattingToolbarView {
41
- public editor: Editor;
41
+ public editor: BlockNoteEditor;
42
+ private ttEditor: Editor;
42
43
 
43
44
  public view: EditorView;
44
45
 
@@ -50,6 +51,8 @@ export class FormattingToolbarView {
50
51
 
51
52
  public toolbarIsOpen = false;
52
53
 
54
+ public prevWasEditable: boolean | null = null;
55
+
53
56
  public shouldShow: Exclude<FormattingToolbarPluginProps["shouldShow"], null> =
54
57
  ({ view, state, from, to }) => {
55
58
  const { doc, selection } = state;
@@ -66,11 +69,13 @@ export class FormattingToolbarView {
66
69
 
67
70
  constructor({
68
71
  editor,
72
+ tiptapEditor,
69
73
  formattingToolbarFactory,
70
74
  view,
71
75
  shouldShow,
72
76
  }: FormattingToolbarViewProps) {
73
77
  this.editor = editor;
78
+ this.ttEditor = tiptapEditor;
74
79
  this.view = view;
75
80
 
76
81
  this.formattingToolbar = formattingToolbarFactory(this.getStaticParams());
@@ -83,8 +88,10 @@ export class FormattingToolbarView {
83
88
  this.view.dom.addEventListener("mouseup", this.viewMouseupHandler);
84
89
  this.view.dom.addEventListener("dragstart", this.dragstartHandler);
85
90
 
86
- this.editor.on("focus", this.focusHandler);
87
- this.editor.on("blur", this.blurHandler);
91
+ this.ttEditor.on("focus", this.focusHandler);
92
+ this.ttEditor.on("blur", this.blurHandler);
93
+
94
+ document.addEventListener("scroll", this.scrollHandler);
88
95
  }
89
96
 
90
97
  viewMousedownHandler = () => {
@@ -93,7 +100,7 @@ export class FormattingToolbarView {
93
100
 
94
101
  viewMouseupHandler = () => {
95
102
  this.preventShow = false;
96
- setTimeout(() => this.update(this.editor.view));
103
+ setTimeout(() => this.update(this.ttEditor.view));
97
104
  };
98
105
 
99
106
  dragstartHandler = () => {
@@ -103,7 +110,7 @@ export class FormattingToolbarView {
103
110
 
104
111
  focusHandler = () => {
105
112
  // we use `setTimeout` to make sure `selection` is already updated
106
- setTimeout(() => this.update(this.editor.view));
113
+ setTimeout(() => this.update(this.ttEditor.view));
107
114
  };
108
115
 
109
116
  blurHandler = ({ event }: { event: FocusEvent }) => {
@@ -128,16 +135,28 @@ export class FormattingToolbarView {
128
135
  }
129
136
  };
130
137
 
138
+ scrollHandler = () => {
139
+ if (this.toolbarIsOpen) {
140
+ this.formattingToolbar.render(this.getDynamicParams(), false);
141
+ }
142
+ };
143
+
131
144
  update(view: EditorView, oldState?: EditorState) {
132
145
  const { state, composing } = view;
133
146
  const { doc, selection } = state;
134
147
  const isSame =
135
148
  oldState && oldState.doc.eq(doc) && oldState.selection.eq(selection);
136
149
 
137
- if (composing || isSame) {
150
+ if (
151
+ (this.prevWasEditable === null ||
152
+ this.prevWasEditable === this.editor.isEditable) &&
153
+ (composing || isSame)
154
+ ) {
138
155
  return;
139
156
  }
140
157
 
158
+ this.prevWasEditable = this.editor.isEditable;
159
+
141
160
  // support for CellSelections
142
161
  const { ranges } = selection;
143
162
  const from = Math.min(...ranges.map((range) => range.$from.pos));
@@ -154,6 +173,7 @@ export class FormattingToolbarView {
154
173
 
155
174
  // Checks if menu should be shown.
156
175
  if (
176
+ this.editor.isEditable &&
157
177
  !this.toolbarIsOpen &&
158
178
  !this.preventShow &&
159
179
  (shouldShow || this.preventHide)
@@ -184,7 +204,7 @@ export class FormattingToolbarView {
184
204
  if (
185
205
  this.toolbarIsOpen &&
186
206
  !this.preventHide &&
187
- (!shouldShow || this.preventShow)
207
+ (!shouldShow || this.preventShow || !this.editor.isEditable)
188
208
  ) {
189
209
  this.formattingToolbar.hide();
190
210
  this.toolbarIsOpen = false;
@@ -204,12 +224,14 @@ export class FormattingToolbarView {
204
224
  this.view.dom.removeEventListener("mouseup", this.viewMouseupHandler);
205
225
  this.view.dom.removeEventListener("dragstart", this.dragstartHandler);
206
226
 
207
- this.editor.off("focus", this.focusHandler);
208
- this.editor.off("blur", this.blurHandler);
227
+ this.ttEditor.off("focus", this.focusHandler);
228
+ this.ttEditor.off("blur", this.blurHandler);
229
+
230
+ document.removeEventListener("scroll", this.scrollHandler);
209
231
  }
210
232
 
211
233
  getSelectionBoundingBox() {
212
- const { state } = this.editor.view;
234
+ const { state } = this.ttEditor.view;
213
235
  const { selection } = state;
214
236
 
215
237
  // support for CellSelections
@@ -218,120 +240,24 @@ export class FormattingToolbarView {
218
240
  const to = Math.max(...ranges.map((range) => range.$to.pos));
219
241
 
220
242
  if (isNodeSelection(selection)) {
221
- const node = this.editor.view.nodeDOM(from) as HTMLElement;
243
+ const node = this.ttEditor.view.nodeDOM(from) as HTMLElement;
222
244
 
223
245
  if (node) {
224
246
  return node.getBoundingClientRect();
225
247
  }
226
248
  }
227
249
 
228
- return posToDOMRect(this.editor.view, from, to);
250
+ return posToDOMRect(this.ttEditor.view, from, to);
229
251
  }
230
252
 
231
253
  getStaticParams(): FormattingToolbarStaticParams {
232
254
  return {
233
- toggleBold: () => {
234
- this.editor.view.focus();
235
- this.editor.commands.toggleBold();
236
- },
237
- toggleItalic: () => {
238
- this.editor.view.focus();
239
- this.editor.commands.toggleItalic();
240
- },
241
- toggleUnderline: () => {
242
- this.editor.view.focus();
243
- this.editor.commands.toggleUnderline();
244
- },
245
- toggleStrike: () => {
246
- this.editor.view.focus();
247
- this.editor.commands.toggleStrike();
248
- },
249
- setHyperlink: (url: string, text?: string) => {
250
- if (url === "") {
251
- return;
252
- }
253
-
254
- let { from, to } = this.editor.state.selection;
255
-
256
- if (!text) {
257
- text = this.editor.state.doc.textBetween(from, to);
258
- }
259
-
260
- const mark = this.editor.schema.mark("link", { href: url });
261
-
262
- this.editor.view.dispatch(
263
- this.editor.view.state.tr
264
- .insertText(text, from, to)
265
- .addMark(from, from + text.length, mark)
266
- );
267
- this.editor.view.focus();
268
- },
269
- setTextColor: (color: string) => {
270
- this.editor.view.focus();
271
- this.editor.commands.setTextColor(color);
272
- },
273
- setBackgroundColor: (color: string) => {
274
- this.editor.view.focus();
275
- this.editor.commands.setBackgroundColor(color);
276
- },
277
- setTextAlignment: (
278
- textAlignment: "left" | "center" | "right" | "justify"
279
- ) => {
280
- this.editor.view.focus();
281
- this.editor.commands.setTextAlignment(textAlignment);
282
- },
283
- increaseBlockIndent: () => {
284
- this.editor.view.focus();
285
- this.editor.commands.sinkListItem("blockContainer");
286
- },
287
- decreaseBlockIndent: () => {
288
- this.editor.view.focus();
289
- this.editor.commands.liftListItem("blockContainer");
290
- },
291
- updateBlock: (updatedBlock: PartialBlock) => {
292
- this.editor.view.focus();
293
- this.editor.commands.BNUpdateBlock(
294
- this.editor.state.selection.from,
295
- updatedBlock
296
- );
297
- },
255
+ editor: this.editor,
298
256
  };
299
257
  }
300
258
 
301
259
  getDynamicParams(): FormattingToolbarDynamicParams {
302
- const blockInfo = getBlockInfoFromPos(
303
- this.editor.state.doc,
304
- this.editor.state.selection.from
305
- )!;
306
-
307
260
  return {
308
- boldIsActive: this.editor.isActive("bold"),
309
- italicIsActive: this.editor.isActive("italic"),
310
- underlineIsActive: this.editor.isActive("underline"),
311
- strikeIsActive: this.editor.isActive("strike"),
312
- hyperlinkIsActive: this.editor.isActive("link"),
313
- activeHyperlinkUrl: this.editor.getAttributes("link").href || "",
314
- activeHyperlinkText: this.editor.state.doc.textBetween(
315
- this.editor.state.selection.from,
316
- this.editor.state.selection.to
317
- ),
318
- textColor: this.editor.getAttributes("textColor").color || "default",
319
- backgroundColor:
320
- this.editor.getAttributes("backgroundColor").color || "default",
321
- textAlignment:
322
- this.editor.getAttributes(blockInfo.contentType).textAlignment ||
323
- "left",
324
- canIncreaseBlockIndent:
325
- this.editor.state.doc
326
- .resolve(blockInfo.startPos)
327
- .index(blockInfo.depth - 1) > 0,
328
- canDecreaseBlockIndent: blockInfo.depth > 2,
329
- // Needs type cast as there is no way to create a type that dynamically updates based on which extensions are
330
- // loaded by the editor.
331
- block: {
332
- type: blockInfo.contentType.name,
333
- props: blockInfo.contentNode.attrs,
334
- } as Block,
335
261
  referenceRect: this.getSelectionBoundingBox(),
336
262
  };
337
263
  }
@@ -56,47 +56,56 @@ class HyperlinkToolbarView {
56
56
  return false;
57
57
  };
58
58
 
59
- editor.view.dom.addEventListener("mouseover", (event) => {
60
- // Resets the hyperlink mark currently hovered by the mouse cursor.
61
- this.mouseHoveredHyperlinkMark = undefined;
62
- this.mouseHoveredHyperlinkMarkRange = undefined;
63
-
64
- this.stopMenuUpdateTimer();
65
-
66
- if (
67
- event.target instanceof HTMLAnchorElement &&
68
- event.target.nodeName === "A"
69
- ) {
70
- // Finds link mark at the hovered element's position to update mouseHoveredHyperlinkMark and
71
- // mouseHoveredHyperlinkMarkRange.
72
- const hoveredHyperlinkElement = event.target;
73
- const posInHoveredHyperlinkMark =
74
- editor.view.posAtDOM(hoveredHyperlinkElement, 0) + 1;
75
- const resolvedPosInHoveredHyperlinkMark = editor.state.doc.resolve(
76
- posInHoveredHyperlinkMark
77
- );
78
- const marksAtPos = resolvedPosInHoveredHyperlinkMark.marks();
79
-
80
- for (const mark of marksAtPos) {
81
- if (mark.type.name === editor.schema.mark("link").type.name) {
82
- this.mouseHoveredHyperlinkMark = mark;
83
- this.mouseHoveredHyperlinkMarkRange =
84
- getMarkRange(
85
- resolvedPosInHoveredHyperlinkMark,
86
- mark.type,
87
- mark.attrs
88
- ) || undefined;
89
-
90
- break;
91
- }
59
+ this.editor.view.dom.addEventListener("mouseover", this.mouseOverHandler);
60
+ document.addEventListener("scroll", this.scrollHandler);
61
+ }
62
+
63
+ mouseOverHandler = (event: MouseEvent) => {
64
+ // Resets the hyperlink mark currently hovered by the mouse cursor.
65
+ this.mouseHoveredHyperlinkMark = undefined;
66
+ this.mouseHoveredHyperlinkMarkRange = undefined;
67
+
68
+ this.stopMenuUpdateTimer();
69
+
70
+ if (
71
+ event.target instanceof HTMLAnchorElement &&
72
+ event.target.nodeName === "A"
73
+ ) {
74
+ // Finds link mark at the hovered element's position to update mouseHoveredHyperlinkMark and
75
+ // mouseHoveredHyperlinkMarkRange.
76
+ const hoveredHyperlinkElement = event.target;
77
+ const posInHoveredHyperlinkMark =
78
+ this.editor.view.posAtDOM(hoveredHyperlinkElement, 0) + 1;
79
+ const resolvedPosInHoveredHyperlinkMark = this.editor.state.doc.resolve(
80
+ posInHoveredHyperlinkMark
81
+ );
82
+ const marksAtPos = resolvedPosInHoveredHyperlinkMark.marks();
83
+
84
+ for (const mark of marksAtPos) {
85
+ if (mark.type.name === this.editor.schema.mark("link").type.name) {
86
+ this.mouseHoveredHyperlinkMark = mark;
87
+ this.mouseHoveredHyperlinkMarkRange =
88
+ getMarkRange(
89
+ resolvedPosInHoveredHyperlinkMark,
90
+ mark.type,
91
+ mark.attrs
92
+ ) || undefined;
93
+
94
+ break;
92
95
  }
93
96
  }
97
+ }
94
98
 
95
- this.startMenuUpdateTimer();
99
+ this.startMenuUpdateTimer();
96
100
 
97
- return false;
98
- });
99
- }
101
+ return false;
102
+ };
103
+
104
+ scrollHandler = () => {
105
+ if (this.hyperlinkMark !== undefined) {
106
+ this.hyperlinkToolbar.render(this.getDynamicParams(), false);
107
+ }
108
+ };
100
109
 
101
110
  update() {
102
111
  if (!this.editor.view.hasFocus()) {
@@ -145,7 +154,7 @@ class HyperlinkToolbarView {
145
154
  this.hyperlinkMarkRange = this.keyboardHoveredHyperlinkMarkRange;
146
155
  }
147
156
 
148
- if (this.hyperlinkMark) {
157
+ if (this.hyperlinkMark && this.editor.isEditable) {
149
158
  this.getDynamicParams();
150
159
 
151
160
  // Shows menu.
@@ -171,7 +180,7 @@ class HyperlinkToolbarView {
171
180
  }
172
181
 
173
182
  // Hides menu.
174
- if (!this.hyperlinkMark && prevHyperlinkMark) {
183
+ if (prevHyperlinkMark && (!this.hyperlinkMark || !this.editor.isEditable)) {
175
184
  this.hyperlinkToolbar.element?.removeEventListener(
176
185
  "mouseleave",
177
186
  this.startMenuUpdateTimer
@@ -187,6 +196,14 @@ class HyperlinkToolbarView {
187
196
  }
188
197
  }
189
198
 
199
+ destroy() {
200
+ this.editor.view.dom.removeEventListener(
201
+ "mouseover",
202
+ this.mouseOverHandler
203
+ );
204
+ document.removeEventListener("scroll", this.scrollHandler);
205
+ }
206
+
190
207
  getStaticParams(): HyperlinkToolbarStaticParams {
191
208
  return {
192
209
  editHyperlink: (url: string, text: string) => {
@@ -60,7 +60,7 @@ const UniqueID = Extension.create({
60
60
  (window as any).__TEST_OPTIONS.mockID++;
61
61
  }
62
62
 
63
- return parseInt((window as any).__TEST_OPTIONS.mockID);
63
+ return (window as any).__TEST_OPTIONS.mockID.toString() as string;
64
64
  }
65
65
 
66
66
  return v4();
package/src/index.ts CHANGED
@@ -9,3 +9,4 @@ export * from "./extensions/SlashMenu/BaseSlashMenuItem";
9
9
  export * from "./shared/EditorElement";
10
10
  export type { SuggestionItem } from "./shared/plugins/suggestion/SuggestionItem";
11
11
  export * from "./shared/plugins/suggestion/SuggestionsMenuFactoryTypes";
12
+ export * from "./extensions/Blocks/api/inlineContentTypes";
@@ -127,8 +127,16 @@ class SuggestionPluginView<T extends SuggestionItem> {
127
127
  };
128
128
 
129
129
  this.suggestionsMenu = suggestionsMenuFactory(this.getStaticParams());
130
+
131
+ document.addEventListener("scroll", this.handleScroll);
130
132
  }
131
133
 
134
+ handleScroll = () => {
135
+ if (this.pluginKey.getState(this.editor._tiptapEditor.state).active) {
136
+ this.suggestionsMenu.render(this.getDynamicParams(), false);
137
+ }
138
+ };
139
+
132
140
  update(view: EditorView, prevState: EditorState) {
133
141
  const prev = this.pluginKey.getState(prevState);
134
142
  const next = this.pluginKey.getState(view.state);
@@ -147,7 +155,7 @@ class SuggestionPluginView<T extends SuggestionItem> {
147
155
 
148
156
  this.pluginState = stopped ? prev : next;
149
157
 
150
- if (stopped) {
158
+ if (stopped || !this.editor.isEditable) {
151
159
  this.suggestionsMenu.hide();
152
160
 
153
161
  // Listener stops focus moving to the menu on click.
@@ -160,7 +168,7 @@ class SuggestionPluginView<T extends SuggestionItem> {
160
168
  this.suggestionsMenu.render(this.getDynamicParams(), false);
161
169
  }
162
170
 
163
- if (started) {
171
+ if (started && this.editor.isEditable) {
164
172
  this.suggestionsMenu.render(this.getDynamicParams(), true);
165
173
 
166
174
  // Listener stops focus moving to the menu on click.
@@ -170,6 +178,10 @@ class SuggestionPluginView<T extends SuggestionItem> {
170
178
  }
171
179
  }
172
180
 
181
+ destroy() {
182
+ document.removeEventListener("scroll", this.handleScroll);
183
+ }
184
+
173
185
  getStaticParams(): SuggestionsMenuStaticParams<T> {
174
186
  return {
175
187
  itemCallback: (item: T) => this.itemCallback(item),
@@ -1,7 +1,9 @@
1
1
  import { Editor as TiptapEditor } from "@tiptap/core/dist/packages/core/src/Editor";
2
2
  import { UiFactories } from "./BlockNoteExtensions";
3
3
  import { Block, BlockIdentifier, PartialBlock } from "./extensions/Blocks/api/blockTypes";
4
+ import { Styles } from "./extensions/Blocks/api/inlineContentTypes";
4
5
  import { TextCursorPosition } from "./extensions/Blocks/api/cursorPositionTypes";
6
+ import { Selection } from "./extensions/Blocks/api/selectionTypes";
5
7
  import { BaseSlashMenuItem } from "./extensions/SlashMenu";
6
8
  export type BlockNoteEditorOptions = {
7
9
  enableBlockNoteExtensions: boolean;
@@ -40,6 +42,13 @@ export type BlockNoteEditorOptions = {
40
42
  * A callback function that runs whenever the text cursor position changes.
41
43
  */
42
44
  onTextCursorPositionChange: (editor: BlockNoteEditor) => void;
45
+ /**
46
+ * Locks the editor from being editable by the user if set to `false`.
47
+ */
48
+ editable: boolean;
49
+ /**
50
+ * The content that should be in the editor when it's created, represented as an array of partial block objects.
51
+ */
43
52
  initialContent: PartialBlock[];
44
53
  /**
45
54
  * Use default BlockNote font and reset the styles of <p> <li> <h1> elements etc., that are used in BlockNote.
@@ -47,6 +56,12 @@ export type BlockNoteEditorOptions = {
47
56
  * @default true
48
57
  */
49
58
  defaultStyles: boolean;
59
+ /**
60
+ * Whether to use the light or dark theme.
61
+ *
62
+ * @default "light"
63
+ */
64
+ theme: "light" | "dark";
50
65
  _tiptapOptions: any;
51
66
  };
52
67
  export declare class BlockNoteEditor {
@@ -55,6 +70,7 @@ export declare class BlockNoteEditor {
55
70
  };
56
71
  private blockCache;
57
72
  get domElement(): HTMLDivElement;
73
+ focus(): void;
58
74
  constructor(options?: Partial<BlockNoteEditorOptions>);
59
75
  /**
60
76
  * Gets a snapshot of all top-level (non-nested) blocks in the editor.
@@ -85,6 +101,20 @@ export declare class BlockNoteEditor {
85
101
  * @param placement Whether the text cursor should be placed at the start or end of the block.
86
102
  */
87
103
  setTextCursorPosition(targetBlock: BlockIdentifier, placement?: "start" | "end"): void;
104
+ /**
105
+ * Gets a snapshot of the current selection.
106
+ */
107
+ getSelection(): Selection | undefined;
108
+ /**
109
+ * Checks if the editor is currently editable, or if it's locked.
110
+ * @returns True if the editor is editable, false otherwise.
111
+ */
112
+ get isEditable(): boolean;
113
+ /**
114
+ * Makes the editor editable or locks it, depending on the argument passed.
115
+ * @param editable True to make the editor editable, or false to lock it.
116
+ */
117
+ set isEditable(editable: boolean);
88
118
  /**
89
119
  * Inserts new blocks into the editor. If a block's `id` is undefined, BlockNote generates one automatically. Throws an
90
120
  * error if the reference block could not be found.
@@ -115,6 +145,55 @@ export declare class BlockNoteEditor {
115
145
  * @param blocksToInsert An array of partial blocks to replace the old ones with.
116
146
  */
117
147
  replaceBlocks(blocksToRemove: BlockIdentifier[], blocksToInsert: PartialBlock[]): void;
148
+ /**
149
+ * Gets the active text styles at the text cursor position or at the end of the current selection if it's active.
150
+ */
151
+ getActiveStyles(): Styles;
152
+ /**
153
+ * Adds styles to the currently selected content.
154
+ * @param styles The styles to add.
155
+ */
156
+ addStyles(styles: Styles): void;
157
+ /**
158
+ * Removes styles from the currently selected content.
159
+ * @param styles The styles to remove.
160
+ */
161
+ removeStyles(styles: Styles): void;
162
+ /**
163
+ * Toggles styles on the currently selected content.
164
+ * @param styles The styles to toggle.
165
+ */
166
+ toggleStyles(styles: Styles): void;
167
+ /**
168
+ * Gets the currently selected text.
169
+ */
170
+ getSelectedText(): string;
171
+ /**
172
+ * Gets the URL of the last link in the current selection, or `undefined` if there are no links in the selection.
173
+ */
174
+ getSelectedLinkUrl(): string | undefined;
175
+ /**
176
+ * Creates a new link to replace the selected content.
177
+ * @param url The link URL.
178
+ * @param text The text to display the link with.
179
+ */
180
+ createLink(url: string, text?: string): void;
181
+ /**
182
+ * Checks if the block containing the text cursor can be nested.
183
+ */
184
+ canNestBlock(): boolean;
185
+ /**
186
+ * Nests the block containing the text cursor into the block above it.
187
+ */
188
+ nestBlock(): void;
189
+ /**
190
+ * Checks if the block containing the text cursor is nested.
191
+ */
192
+ canUnnestBlock(): boolean;
193
+ /**
194
+ * Lifts the block containing the text cursor out of its parent.
195
+ */
196
+ unnestBlock(): void;
118
197
  /**
119
198
  * Serializes blocks into an HTML string. To better conform to HTML standards, children of blocks which aren't list
120
199
  * items are un-nested in the output HTML.
@@ -3,13 +3,14 @@ export type Styles = {
3
3
  italic?: true;
4
4
  underline?: true;
5
5
  strike?: true;
6
+ code?: true;
6
7
  textColor?: string;
7
8
  backgroundColor?: string;
8
9
  };
9
- export type ToggledStyles = {
10
+ export type ToggledStyle = {
10
11
  [K in keyof Styles]-?: Required<Styles>[K] extends true ? K : never;
11
12
  }[keyof Styles];
12
- export type ColorStyles = {
13
+ export type ColorStyle = {
13
14
  [K in keyof Styles]-?: Required<Styles>[K] extends string ? K : never;
14
15
  }[keyof Styles];
15
16
  export type StyledText = {
@@ -0,0 +1,4 @@
1
+ import { Block } from "./blockTypes";
2
+ export type Selection = {
3
+ blocks: Block[];
4
+ };
@@ -1,17 +1,16 @@
1
1
  import { EditorElement, ElementFactory } from "../../shared/EditorElement";
2
+ import { BlockNoteEditor } from "../../BlockNoteEditor";
3
+ import { Block } from "../Blocks/api/blockTypes";
2
4
  export type BlockSideMenuStaticParams = {
5
+ editor: BlockNoteEditor;
3
6
  addBlock: () => void;
4
- deleteBlock: () => void;
5
7
  blockDragStart: (event: DragEvent) => void;
6
8
  blockDragEnd: () => void;
7
9
  freezeMenu: () => void;
8
10
  unfreezeMenu: () => void;
9
- setBlockTextColor: (color: string) => void;
10
- setBlockBackgroundColor: (color: string) => void;
11
11
  };
12
12
  export type BlockSideMenuDynamicParams = {
13
- blockTextColor: string;
14
- blockBackgroundColor: string;
13
+ block: Block;
15
14
  referenceRect: DOMRect;
16
15
  };
17
16
  export type BlockSideMenu = EditorElement<BlockSideMenuDynamicParams>;
@@ -1,7 +1,9 @@
1
1
  import { Editor, Extension } from "@tiptap/core";
2
2
  import { BlockSideMenuFactory } from "./BlockSideMenuFactoryTypes";
3
+ import { BlockNoteEditor } from "../../BlockNoteEditor";
3
4
  export type DraggableBlocksOptions = {
4
- editor: Editor;
5
+ tiptapEditor: Editor;
6
+ editor: BlockNoteEditor;
5
7
  blockSideMenuFactory: BlockSideMenuFactory;
6
8
  };
7
9
  /**