@blocknote/xl-ai 0.42.2 → 0.43.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.
@@ -13,7 +13,7 @@ import { DeleteBlockToolCall } from "../../base-tools/delete.js";
13
13
  import { tools } from "./index.js";
14
14
 
15
15
  // Helper function to create a mock stream from operations
16
- import { getAIExtension } from "../../../../AIExtension.js";
16
+ import { AIExtension } from "../../../../AIExtension.js";
17
17
  import { StreamToolExecutor } from "../../../../streamTool/StreamToolExecutor.js";
18
18
  import { StreamTool } from "../../../../streamTool/streamTool.js";
19
19
  import { getExpectedEditor } from "../../../../testUtil/cases/index.js";
@@ -64,7 +64,7 @@ async function executeTestCase(
64
64
 
65
65
  validateRejectingResultsInOriginalDoc(editor, originalDoc);
66
66
 
67
- getAIExtension(editor).acceptChanges();
67
+ editor.getExtension(AIExtension)?.acceptChanges();
68
68
  expect(editor.document).toEqual(getExpectedEditor(testCase).document);
69
69
  }
70
70
 
@@ -4,7 +4,7 @@ import { getCurrentTest, TaskContext } from "@vitest/runner";
4
4
  import path from "path";
5
5
  import { TextSelection } from "prosemirror-state";
6
6
  import { describe, expect, it } from "vitest";
7
- import { getAIExtension } from "../../../AIExtension.js";
7
+ import { AIExtension } from "../../../AIExtension.js";
8
8
  import { aiDocumentFormats, defaultAIRequestSender } from "../../../index.js";
9
9
  import { addOperationTestCases } from "../../../testUtil/cases/addOperationTestCases.js";
10
10
  import { combinedOperationsTestCases } from "../../../testUtil/cases/combinedOperationsTestCases.js";
@@ -118,7 +118,7 @@ export function generateSharedTestCases(
118
118
  validateRejectingResultsInOriginalDoc(editor, originalDoc);
119
119
 
120
120
  // we first need to accept changes to get the correct result
121
- getAIExtension(editor).acceptChanges();
121
+ editor.getExtension(AIExtension)?.acceptChanges();
122
122
  expect(editor.document).toEqual(
123
123
  getExpectedEditor(test, {
124
124
  deleteEmptyCursorBlock: true,
@@ -1,10 +1,14 @@
1
1
  import { BlockNoteEditor } from "@blocknote/core";
2
- import { useBlockNoteEditor, useComponentsContext } from "@blocknote/react";
2
+ import {
3
+ useBlockNoteEditor,
4
+ useComponentsContext,
5
+ useExtension,
6
+ useExtensionState,
7
+ } from "@blocknote/react";
3
8
  import { useCallback, useEffect, useMemo, useState } from "react";
4
9
  import { RiSparkling2Fill } from "react-icons/ri";
5
- import { useStore } from "zustand";
6
10
 
7
- import { getAIExtension } from "../../AIExtension.js";
11
+ import { AIExtension } from "../../AIExtension.js";
8
12
  import { useAIDictionary } from "../../i18n/useAIDictionary.js";
9
13
  import { PromptSuggestionMenu } from "./PromptSuggestionMenu.js";
10
14
  import {
@@ -33,11 +37,12 @@ export const AIMenu = (props: AIMenuProps) => {
33
37
 
34
38
  const Components = useComponentsContext()!;
35
39
 
36
- const ai = getAIExtension(editor);
40
+ const ai = useExtension(AIExtension);
37
41
 
38
- const aiResponseStatus = useStore(ai.store, (state) =>
39
- state.aiMenuState !== "closed" ? state.aiMenuState.status : "closed",
40
- );
42
+ const aiResponseStatus = useExtensionState(AIExtension, {
43
+ selector: (state) =>
44
+ state.aiMenuState !== "closed" ? state.aiMenuState.status : "closed",
45
+ });
41
46
 
42
47
  const { items: externalItems } = props;
43
48
  // note, technically there might be a bug with this useMemo when quickly changing the selection and opening the menu
@@ -74,7 +79,11 @@ export const AIMenu = (props: AIMenuProps) => {
74
79
 
75
80
  useEffect(() => {
76
81
  // this is a bit hacky to run a useeffect to reset the prompt when the AI response is done
77
- if (aiResponseStatus === "user-reviewing" || aiResponseStatus === "error") {
82
+ if (
83
+ aiResponseStatus === "ai-writing" ||
84
+ aiResponseStatus === "user-reviewing" ||
85
+ aiResponseStatus === "error"
86
+ ) {
78
87
  setPrompt("");
79
88
  }
80
89
  }, [aiResponseStatus]);
@@ -1,42 +1,96 @@
1
- import { useBlockNoteEditor } from "@blocknote/react";
2
- import { FC } from "react";
3
- import { useStore } from "zustand";
1
+ import {
2
+ BlockPopover,
3
+ FloatingUIOptions,
4
+ useBlockNoteEditor,
5
+ useExtension,
6
+ useExtensionState,
7
+ } from "@blocknote/react";
8
+ import { offset, size } from "@floating-ui/react";
9
+ import { FC, useMemo } from "react";
4
10
 
5
- import { getAIExtension } from "../../AIExtension.js";
11
+ import { AIExtension } from "../../AIExtension.js";
6
12
  import { AIMenu, AIMenuProps } from "./AIMenu.js";
7
- import { BlockPositioner } from "./BlockPositioner.js";
8
13
 
9
- export const AIMenuController = (props: { aiMenu?: FC<AIMenuProps> }) => {
14
+ export const AIMenuController = (props: {
15
+ aiMenu?: FC<AIMenuProps>;
16
+ floatingUIOptions?: FloatingUIOptions;
17
+ }) => {
10
18
  const editor = useBlockNoteEditor();
11
- const ai = getAIExtension(editor);
19
+ const ai = useExtension(AIExtension);
12
20
 
13
- const aiMenuState = useStore(ai.store, (state) => state.aiMenuState);
21
+ const aiMenuState = useExtensionState(AIExtension, {
22
+ editor,
23
+ selector: (state) => state.aiMenuState,
24
+ });
14
25
 
15
26
  const blockId = aiMenuState === "closed" ? undefined : aiMenuState.blockId;
16
27
 
28
+ const floatingUIOptions = useMemo<FloatingUIOptions>(
29
+ () => ({
30
+ useFloatingOptions: {
31
+ open: aiMenuState !== "closed",
32
+ placement: "bottom",
33
+ middleware: [
34
+ offset(10),
35
+ // flip(),
36
+ size({
37
+ apply({ rects, elements }) {
38
+ Object.assign(elements.floating.style, {
39
+ width: `${rects.reference.width}px`,
40
+ });
41
+ },
42
+ }),
43
+ ],
44
+ onOpenChange: (open) => {
45
+ if (open || aiMenuState === "closed") {
46
+ return;
47
+ }
48
+
49
+ if (aiMenuState.status === "user-input") {
50
+ ai.closeAIMenu();
51
+ } else if (
52
+ aiMenuState.status === "user-reviewing" ||
53
+ aiMenuState.status === "error"
54
+ ) {
55
+ ai.rejectChanges();
56
+ }
57
+ },
58
+ },
59
+ useDismissProps: {
60
+ enabled:
61
+ aiMenuState === "closed" || aiMenuState.status === "user-input",
62
+ // We should just be able to set `referencePress: true` instead of
63
+ // using this listener, but this doesn't seem to trigger.
64
+ // (probably because we don't assign the referenceProps to the reference element)
65
+ outsidePress: (event) => {
66
+ if (event.target instanceof Element) {
67
+ const blockElement = event.target.closest(".bn-block");
68
+ if (
69
+ blockElement &&
70
+ blockElement.getAttribute("data-id") === blockId
71
+ ) {
72
+ ai.closeAIMenu();
73
+ }
74
+ }
75
+
76
+ return true;
77
+ },
78
+ },
79
+ elementProps: {
80
+ style: {
81
+ zIndex: 100,
82
+ },
83
+ },
84
+ ...props.floatingUIOptions,
85
+ }),
86
+ [ai, aiMenuState, blockId, props.floatingUIOptions],
87
+ );
88
+
17
89
  const Component = props.aiMenu || AIMenu;
18
90
 
19
91
  return (
20
- <BlockPositioner
21
- canDismissViaOutsidePress={
22
- aiMenuState === "closed" || aiMenuState.status === "user-input"
23
- }
24
- blockID={blockId}
25
- onOpenChange={(open) => {
26
- if (open || aiMenuState === "closed") {
27
- return;
28
- }
29
- if (aiMenuState.status === "user-input") {
30
- ai.closeAIMenu();
31
- } else if (
32
- aiMenuState.status === "user-reviewing" ||
33
- aiMenuState.status === "error"
34
- ) {
35
- ai.rejectChanges();
36
- }
37
- }}
38
- >
39
- <Component />
40
- </BlockPositioner>
92
+ <BlockPopover blockId={blockId} {...floatingUIOptions}>
93
+ {aiMenuState !== "closed" && <Component />}
94
+ </BlockPopover>
41
95
  );
42
96
  };
@@ -1,4 +1,5 @@
1
- import { filterSuggestionItems, mergeCSSClasses } from "@blocknote/core";
1
+ import { mergeCSSClasses } from "@blocknote/core";
2
+ import { filterSuggestionItems } from "@blocknote/core/extensions";
2
3
  import {
3
4
  DefaultReactSuggestionItem,
4
5
  useComponentsContext,
@@ -111,7 +112,8 @@ export const PromptSuggestionMenu = (props: PromptSuggestionMenuProps) => {
111
112
  </Components.Generic.Form.Root>
112
113
  <Components.SuggestionMenu.Root
113
114
  className={"bn-combobox-items"}
114
- id={"ai-suggestion-menu"}>
115
+ id={"ai-suggestion-menu"}
116
+ >
115
117
  {items.map((item, i) => (
116
118
  <Components.SuggestionMenu.Item
117
119
  key={item.title}
@@ -18,7 +18,7 @@ import {
18
18
  RiTextWrap,
19
19
  } from "react-icons/ri";
20
20
 
21
- import { getAIExtension } from "../../AIExtension.js";
21
+ import { AIExtension } from "../../AIExtension.js";
22
22
  import { aiDocumentFormats } from "../../api/index.js";
23
23
  import { getAIDictionary } from "../../i18n/dictionary.js";
24
24
 
@@ -40,7 +40,10 @@ function getDefaultAIMenuItemsWithoutSelection<
40
40
  S extends StyleSchema,
41
41
  >(editor: BlockNoteEditor<BSchema, I, S>): AIMenuSuggestionItem[] {
42
42
  const dict = getAIDictionary(editor);
43
- const ai = getAIExtension(editor);
43
+ const ai = editor.getExtension(AIExtension);
44
+ if (!ai) {
45
+ return [];
46
+ }
44
47
  return [
45
48
  {
46
49
  key: "continue_writing",
@@ -128,7 +131,10 @@ function getDefaultAIMenuItemsWithSelection<
128
131
  >(editor: BlockNoteEditor<BSchema, I, S>): AIMenuSuggestionItem[] {
129
132
  const dict = getAIDictionary(editor);
130
133
 
131
- const ai = getAIExtension(editor);
134
+ const ai = editor.getExtension(AIExtension);
135
+ if (!ai) {
136
+ return [];
137
+ }
132
138
 
133
139
  return [
134
140
  {
@@ -216,7 +222,10 @@ function getDefaultAIMenuItemsForReview<
216
222
  S extends StyleSchema,
217
223
  >(editor: BlockNoteEditor<BSchema, I, S>): AIMenuSuggestionItem[] {
218
224
  const dict = getAIDictionary(editor);
219
- const ai = getAIExtension(editor);
225
+ const ai = editor.getExtension(AIExtension);
226
+ if (!ai) {
227
+ return [];
228
+ }
220
229
 
221
230
  return [
222
231
  {
@@ -251,7 +260,10 @@ function getDefaultAIMenuItemsForError<
251
260
  S extends StyleSchema,
252
261
  >(editor: BlockNoteEditor<BSchema, I, S>): AIMenuSuggestionItem[] {
253
262
  const dict = getAIDictionary(editor);
254
- const ai = getAIExtension(editor);
263
+ const ai = editor.getExtension(AIExtension);
264
+ if (!ai) {
265
+ return [];
266
+ }
255
267
 
256
268
  return [
257
269
  {
@@ -1,10 +1,11 @@
1
1
  import { BlockSchema, InlineContentSchema, StyleSchema } from "@blocknote/core";
2
- import { useComponentsContext } from "@blocknote/react";
2
+ import { FormattingToolbarExtension } from "@blocknote/core/extensions";
3
+ import { useComponentsContext, useExtension } from "@blocknote/react";
3
4
  import { RiSparkling2Fill } from "react-icons/ri";
4
5
 
5
6
  import { useBlockNoteEditor } from "@blocknote/react";
6
7
 
7
- import { getAIExtension } from "../../AIExtension.js";
8
+ import { AIExtension } from "../../AIExtension.js";
8
9
  import { useAIDictionary } from "../../i18n/useAIDictionary.js";
9
10
 
10
11
  export const AIToolbarButton = () => {
@@ -17,16 +18,19 @@ export const AIToolbarButton = () => {
17
18
  StyleSchema
18
19
  >();
19
20
 
20
- const ai = getAIExtension(editor);
21
+ const ai = useExtension(AIExtension);
22
+ const formattingToolbar = useExtension(FormattingToolbarExtension);
21
23
 
22
24
  const onClick = () => {
23
- editor.formattingToolbar.closeMenu();
24
25
  const selection = editor.getSelection();
25
26
  if (!selection) {
26
27
  throw new Error("No selection");
27
28
  }
29
+
28
30
  const position = selection.blocks[selection.blocks.length - 1].id;
31
+
29
32
  ai.openAIMenuAtBlock(position);
33
+ formattingToolbar.store.setState(false);
30
34
  };
31
35
 
32
36
  if (!editor.isEditable) {
@@ -7,7 +7,7 @@ import {
7
7
  import { DefaultReactSuggestionItem } from "@blocknote/react";
8
8
  import { RiSparkling2Fill } from "react-icons/ri";
9
9
 
10
- import { getAIExtension } from "../../AIExtension.js";
10
+ import { AIExtension } from "../../AIExtension.js";
11
11
  import { getAIDictionary } from "../../i18n/dictionary.js";
12
12
  const Icons = {
13
13
  AI: RiSparkling2Fill,
@@ -21,7 +21,10 @@ export function getAISlashMenuItems<
21
21
  I extends InlineContentSchema,
22
22
  S extends StyleSchema,
23
23
  >(editor: BlockNoteEditor<BSchema, I, S>): DefaultReactSuggestionItem[] {
24
- const ai = getAIExtension(editor);
24
+ const ai = editor.getExtension(AIExtension);
25
+ if (!ai) {
26
+ return [];
27
+ }
25
28
  const items = [
26
29
  {
27
30
  key: "ai",
package/src/index.ts CHANGED
@@ -5,7 +5,6 @@ export * from "./api/index.js";
5
5
  export * from "./blocknoteAIClient/client.js";
6
6
  export * from "./components/AIMenu/AIMenu.js";
7
7
  export * from "./components/AIMenu/AIMenuController.js";
8
- export * from "./components/AIMenu/BlockPositioner.js";
9
8
  export * from "./components/AIMenu/getDefaultAIMenuItems.js";
10
9
  export * from "./components/AIMenu/PromptSuggestionMenu.js";
11
10
  export * from "./components/FormattingToolbar/AIToolbarButton.js";
@@ -2,7 +2,7 @@ import { BlockNoteEditor, getBlockInfo, getNodeById } from "@blocknote/core";
2
2
  import { Fragment, Slice } from "prosemirror-model";
3
3
  import { ReplaceStep, Transform } from "prosemirror-transform";
4
4
  import { describe, expect, it } from "vitest";
5
- import { getAIExtension } from "../AIExtension.js";
5
+ import { AIExtension } from "../AIExtension.js";
6
6
  import {
7
7
  DocumentOperationTestCase,
8
8
  getExpectedEditor,
@@ -247,7 +247,7 @@ async function executeTestCase(
247
247
  validateRejectingResultsInOriginalDoc(editor, doc);
248
248
  expect(results).toMatchSnapshot();
249
249
 
250
- getAIExtension(editor).acceptChanges();
250
+ editor.getExtension(AIExtension)?.acceptChanges();
251
251
  expect(editor.document).toEqual(getExpectedEditor(test).document);
252
252
 
253
253
  return results;
@@ -1,5 +1,5 @@
1
1
  import { BlockNoteEditor } from "@blocknote/core";
2
- import { createAIExtension } from "../../../AIExtension.js";
2
+ import { AIExtension } from "../../../AIExtension.js";
3
3
  import { schemaWithMention as schema } from "../schemas/mention.js";
4
4
 
5
5
  export function getEditorWithBlockFormatting() {
@@ -22,7 +22,7 @@ export function getEditorWithBlockFormatting() {
22
22
  ],
23
23
  trailingBlock: false,
24
24
  schema,
25
- extensions: [createAIExtension({})],
25
+ extensions: [AIExtension()],
26
26
  });
27
27
  return editor;
28
28
  }
@@ -1,5 +1,5 @@
1
1
  import { BlockNoteEditor } from "@blocknote/core";
2
- import { createAIExtension } from "../../../AIExtension.js";
2
+ import { AIExtension } from "../../../AIExtension.js";
3
3
 
4
4
  export function getEmptyEditor() {
5
5
  const editor = BlockNoteEditor.create({
@@ -10,7 +10,7 @@ export function getEmptyEditor() {
10
10
  },
11
11
  ],
12
12
  trailingBlock: false,
13
- extensions: [createAIExtension({})],
13
+ extensions: [AIExtension()],
14
14
  });
15
15
  return editor;
16
16
  }
@@ -1,5 +1,5 @@
1
1
  import { BlockNoteEditor } from "@blocknote/core";
2
- import { createAIExtension } from "../../../AIExtension.js";
2
+ import { AIExtension } from "../../../AIExtension.js";
3
3
  import { schemaWithMention as schema } from "../schemas/mention.js";
4
4
 
5
5
  export function getEditorWithFormattingAndMentions() {
@@ -72,7 +72,7 @@ export function getEditorWithFormattingAndMentions() {
72
72
  ],
73
73
  trailingBlock: false,
74
74
  schema,
75
- extensions: [createAIExtension({})],
75
+ extensions: [AIExtension()],
76
76
  });
77
77
  return editor;
78
78
  }
@@ -1,5 +1,5 @@
1
1
  import { BlockNoteEditor } from "@blocknote/core";
2
- import { createAIExtension } from "../../../AIExtension.js";
2
+ import { AIExtension } from "../../../AIExtension.js";
3
3
  import { schemaWithMention as schema } from "../schemas/mention.js";
4
4
 
5
5
  export function getSimpleEditor() {
@@ -16,7 +16,7 @@ export function getSimpleEditor() {
16
16
  ],
17
17
  trailingBlock: false,
18
18
  schema,
19
- extensions: [createAIExtension({})],
19
+ extensions: [AIExtension()],
20
20
  });
21
21
  return editor;
22
22
  }
@@ -39,7 +39,7 @@ export function getSimpleEditorWithCursorBetweenBlocks() {
39
39
  ],
40
40
  trailingBlock: false,
41
41
  schema,
42
- extensions: [createAIExtension({})],
42
+ extensions: [AIExtension()],
43
43
  });
44
44
  editor.setTextCursorPosition("ref2");
45
45
  return editor;
@@ -1,5 +1,5 @@
1
1
  import { BlockNoteEditor } from "@blocknote/core";
2
- import { createAIExtension } from "../../../AIExtension.js";
2
+ import { AIExtension } from "../../../AIExtension.js";
3
3
  import { schemaWithMention as schema } from "../schemas/mention.js";
4
4
 
5
5
  export function getEditorWithTables() {
@@ -38,7 +38,7 @@ export function getEditorWithTables() {
38
38
  ],
39
39
  schema,
40
40
  trailingBlock: false,
41
- extensions: [createAIExtension({})],
41
+ extensions: [AIExtension()],
42
42
  });
43
43
  return editor;
44
44
  }
@@ -1,5 +1,5 @@
1
1
  import { BlockNoteEditor, getBlockInfo, getNodeById } from "@blocknote/core";
2
- import { createAIExtension } from "../../AIExtension.js";
2
+ import { AIExtension } from "../../AIExtension.js";
3
3
  import { getEditorWithBlockFormatting } from "./editors/blockFormatting.js";
4
4
  import { getEditorWithFormattingAndMentions } from "./editors/formattingAndMentions.js";
5
5
  import { DocumentOperationTestCase } from "./index.js";
@@ -683,7 +683,7 @@ export const updateOperationTestCases: DocumentOperationTestCase[] = [
683
683
  },
684
684
  ],
685
685
  schema,
686
- extensions: [createAIExtension({})],
686
+ extensions: [AIExtension()],
687
687
  });
688
688
  return editor;
689
689
  },
@@ -736,7 +736,7 @@ export const updateOperationTestCases: DocumentOperationTestCase[] = [
736
736
  },
737
737
  ],
738
738
  schema,
739
- extensions: [createAIExtension({})],
739
+ extensions: [AIExtension()],
740
740
  });
741
741
  return editor;
742
742
  },
@@ -771,7 +771,7 @@ export const updateOperationTestCases: DocumentOperationTestCase[] = [
771
771
  },
772
772
  ],
773
773
  schema,
774
- extensions: [createAIExtension({})],
774
+ extensions: [AIExtension()],
775
775
  });
776
776
  return editor;
777
777
  },
@@ -1,7 +1,5 @@
1
- import { BlockNoteEditor, BlockNoteExtension } from "@blocknote/core";
2
- import { createStore, StoreApi } from "zustand/vanilla";
1
+ import { Plugin } from "prosemirror-state";
3
2
  import { AIRequestHelpers, InvokeAIOptions } from "./types.js";
4
- type ReadonlyStoreApi<T> = Pick<StoreApi<T>, "getState" | "getInitialState" | "subscribe">;
5
3
  type AIPluginState = {
6
4
  aiMenuState: ({
7
5
  /**
@@ -16,58 +14,53 @@ type AIPluginState = {
16
14
  status: "user-input" | "thinking" | "ai-writing" | "user-reviewing";
17
15
  })) | "closed";
18
16
  };
19
- export declare class AIExtension extends BlockNoteExtension {
20
- readonly editor: BlockNoteEditor<any, any, any>;
21
- private chatSession;
22
- private scrollInProgress;
23
- private autoScroll;
24
- static key(): string;
25
- private readonly _store;
17
+ export declare const AIExtension: (options?: (AIRequestHelpers & {
26
18
  /**
27
- * Returns a read-only zustand store with the state of the AI Extension
28
- */
29
- get store(): ReadonlyStoreApi<AIPluginState>;
30
- /**
31
- * Returns a zustand store with the global configuration of the AI Extension.
32
- * These options are used by default across all LLM calls when calling {@link executeLLMRequest}
33
- */
34
- readonly options: ReturnType<ReturnType<typeof createStore<AIRequestHelpers>>>;
35
- /**
36
- * @internal use `createAIExtension` instead
19
+ * The name and color of the agent cursor
20
+ *
21
+ * @default { name: "AI", color: "#8bc6ff" }
37
22
  */
38
- constructor(editor: BlockNoteEditor<any, any, any>, options: AIRequestHelpers & {
39
- /**
40
- * The name and color of the agent cursor
41
- *
42
- * @default { name: "AI", color: "#8bc6ff" }
43
- */
44
- agentCursor?: {
45
- name: string;
46
- color: string;
47
- };
48
- });
23
+ agentCursor?: {
24
+ name: string;
25
+ color: string;
26
+ };
27
+ }) | undefined) => import("@blocknote/core").ExtensionFactoryInstance<{
28
+ readonly key: "ai";
29
+ readonly options: import("@tanstack/store").Store<AIRequestHelpers, (cb: AIRequestHelpers) => AIRequestHelpers>;
30
+ readonly store: import("@tanstack/store").Store<AIPluginState, (cb: AIPluginState) => AIPluginState>;
31
+ readonly mount: ({ signal }: {
32
+ signal: AbortSignal;
33
+ }) => void;
34
+ readonly prosemirrorPlugins: readonly [Plugin<any>, Plugin<{
35
+ enabled: boolean;
36
+ }>, Plugin<{
37
+ selection: {
38
+ anchor: number;
39
+ head: number;
40
+ } | undefined;
41
+ }>];
49
42
  /**
50
43
  * Open the AI menu at a specific block
51
44
  */
52
- openAIMenuAtBlock(blockID: string): void;
45
+ readonly openAIMenuAtBlock: (blockID: string) => void;
53
46
  /**
54
47
  * Close the AI menu
55
48
  */
56
- closeAIMenu(): void;
49
+ readonly closeAIMenu: () => void;
57
50
  /**
58
51
  * Accept the changes made by the LLM
59
52
  */
60
- acceptChanges(): void;
53
+ readonly acceptChanges: () => void;
61
54
  /**
62
55
  * Reject the changes made by the LLM
63
56
  */
64
- rejectChanges(): void;
57
+ readonly rejectChanges: () => void;
65
58
  /**
66
59
  * Retry the previous LLM call.
67
60
  *
68
61
  * Only valid if the current status is "error"
69
62
  */
70
- retry(): Promise<void>;
63
+ readonly retry: () => Promise<void>;
71
64
  /**
72
65
  * Update the status of a call to an LLM
73
66
  *
@@ -75,25 +68,17 @@ export declare class AIExtension extends BlockNoteExtension {
75
68
  * if you want to implement how an LLM call is executed. Usually, you should
76
69
  * use {@link executeLLMRequest} instead which will handle the status updates for you.
77
70
  */
78
- setAIResponseStatus(status: "user-input" | "thinking" | "ai-writing" | "user-reviewing" | {
71
+ readonly setAIResponseStatus: (status: "user-input" | "thinking" | "ai-writing" | "user-reviewing" | {
79
72
  status: "error";
80
73
  error: any;
81
- }): void;
74
+ }) => void;
82
75
  /**
83
76
  * @deprecated Use {@link invokeAI} instead
84
77
  */
85
- callLLM(opts: InvokeAIOptions): Promise<void>;
78
+ readonly callLLM: (opts: InvokeAIOptions) => Promise<void>;
86
79
  /**
87
80
  * Execute a call to an LLM and apply the result to the editor
88
81
  */
89
- invokeAI(opts: InvokeAIOptions): Promise<void>;
90
- }
91
- /**
92
- * Create a new AIExtension instance, this can be passed to the BlockNote editor via the `extensions` option
93
- */
94
- export declare function createAIExtension(options: ConstructorParameters<typeof AIExtension>[1]): (editor: BlockNoteEditor<any, any, any>) => AIExtension;
95
- /**
96
- * Return the AIExtension instance from the editor
97
- */
98
- export declare function getAIExtension(editor: BlockNoteEditor<any, any, any>): AIExtension;
82
+ readonly invokeAI: (opts: InvokeAIOptions) => Promise<void>;
83
+ }>;
99
84
  export {};
@@ -1,5 +1,7 @@
1
+ import { FloatingUIOptions } from "@blocknote/react";
1
2
  import { FC } from "react";
2
3
  import { AIMenuProps } from "./AIMenu.js";
3
4
  export declare const AIMenuController: (props: {
4
5
  aiMenu?: FC<AIMenuProps>;
6
+ floatingUIOptions?: FloatingUIOptions;
5
7
  }) => import("react/jsx-runtime").JSX.Element;
@@ -4,7 +4,6 @@ export * from "./api/index.js";
4
4
  export * from "./blocknoteAIClient/client.js";
5
5
  export * from "./components/AIMenu/AIMenu.js";
6
6
  export * from "./components/AIMenu/AIMenuController.js";
7
- export * from "./components/AIMenu/BlockPositioner.js";
8
7
  export * from "./components/AIMenu/getDefaultAIMenuItems.js";
9
8
  export * from "./components/AIMenu/PromptSuggestionMenu.js";
10
9
  export * from "./components/FormattingToolbar/AIToolbarButton.js";