Skip to content

Commit 536ea9d

Browse files
committed
docs: how to export extension methods
1 parent 24517fb commit 536ea9d

File tree

4 files changed

+34
-0
lines changed

4 files changed

+34
-0
lines changed

adr/2025_06_13-extensions.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,11 @@ Zustand is a popular library, but allowing partial states makes it somewhat unsa
3939

4040
Jotai is probably my second choice, but it makes it a bit awkward to update states because it relies on a separate store instance rather than the "atom" being able to update itself <https://jotai.org/docs/guides/using-store-outside-react>.
4141
</details>
42+
43+
## Exposing extension methods
44+
45+
Not everything can be communicated through just state, so we need to be able to expose additional methods to the application.
46+
47+
I propose that we have a `extensions` property on the `BlockNoteEditor` instance, which is a map of the extension key to the extension instance, but filtered out to only include non-blocknote methods (as defined by the `ExtensionMethods` type).
48+
49+
This will allow the application to access the extension methods, and also allows us to keep the extension instance private to the editor (type-wise).

adr/BlockNoteExtension.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ export class MyExtension extends BlockNoteExtension<{ abc: number[] }> {
149149
constructor(_extensionOptions: { myCustomOption: string }) {
150150
super();
151151
}
152+
153+
getFoo() {
154+
return 8;
155+
}
152156
}
153157

154158
/**
@@ -167,3 +171,18 @@ export function myExtension(_extensionOptions: {
167171
},
168172
};
169173
}
174+
175+
/**
176+
* This type exposes the public API of an extension, excluding any {@link BlockNoteExtension} methods (for cleaner typing)
177+
*/
178+
export type ExtensionMethods<Extension extends BlockNoteExtension<any>> =
179+
Extension extends BlockNoteExtension<infer State>
180+
? Omit<Extension, Exclude<keyof BlockNoteExtension<State>, "store" | "key">>
181+
: never;
182+
183+
/**
184+
* You'll notice that the `getFoo` method is the only included type in the `MyExtensionMethods` type,
185+
* This makes it convenient to expose the right amount of details to the rest of the application (keeping the blocknote called methods hidden)
186+
*/
187+
export type MyExtensionMethods = ExtensionMethods<MyExtension>;
188+
// editor.extensions.myExtension.getFoo();

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,8 @@
5454
"start": "serve playground/dist -c ../serve.json",
5555
"test": "nx run-many --target=test",
5656
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,css,scss,md}\""
57+
},
58+
"dependencies": {
59+
"@tanstack/store": "0.7.1"
5760
}
5861
}

pnpm-lock.yaml

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)