@notionhq/custom-blocks 0.1.45 → 0.1.47
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.
- package/README.md +3 -4
- package/dist/bridge/SandboxBridge.d.ts +1 -1
- package/dist/bridge/SandboxBridge.d.ts.map +1 -1
- package/dist/bridge/SandboxBridge.js +3 -20
- package/dist/bridge/sandboxClient.d.ts +1 -1
- package/dist/bridge/sandboxClient.d.ts.map +1 -1
- package/dist/bridge/sandboxClient.js +2 -2
- package/dist/customBlock.d.ts +76 -3
- package/dist/customBlock.d.ts.map +1 -1
- package/dist/customBlock.js +120 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/init.d.ts +2 -14
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +7 -30
- package/dist/protocol/index.d.ts +3 -2
- package/dist/protocol/index.js +3 -2
- package/dist/protocol/messages/init.d.ts +2 -2
- package/dist/protocol/messages/isInitHandshakeMessage.d.ts +4 -0
- package/dist/protocol/messages/isInitHandshakeMessage.js +11 -0
- package/dist/protocol/{messagePayload.d.ts → messages/messagePayload.d.ts} +1 -1
- package/dist/react/NotionCustomBlock.d.ts +3 -5
- package/dist/react/NotionCustomBlock.d.ts.map +1 -1
- package/dist/react/NotionCustomBlock.js +3 -4
- package/dist/react/useCustomBlockInit.d.ts +4 -4
- package/dist/react/useCustomBlockInit.d.ts.map +1 -1
- package/dist/react/useCustomBlockInit.js +3 -4
- package/dist/react/useRuntimeState.d.ts +3 -5
- package/dist/react/useRuntimeState.d.ts.map +1 -1
- package/dist/react/useRuntimeState.js +10 -12
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/docs/block-location.md +51 -55
- package/docs/data-sources.md +3 -3
- package/docs/errors.md +1 -1
- package/docs/lifecycle.md +60 -25
- package/docs/users.md +4 -3
- package/package.json +1 -1
- package/src/bridge/SandboxBridge.ts +3 -23
- package/src/bridge/sandboxClient.ts +2 -2
- package/src/customBlock.ts +139 -3
- package/src/index.ts +0 -1
- package/src/init.ts +7 -52
- package/src/react/NotionCustomBlock.tsx +4 -6
- package/src/react/useCustomBlockInit.ts +5 -12
- package/src/react/useRuntimeState.ts +25 -12
- package/src/types.ts +1 -1
- /package/dist/protocol/{incomingType.d.ts → messages/incomingType.d.ts} +0 -0
- /package/dist/protocol/{incomingType.js → messages/incomingType.js} +0 -0
- /package/dist/protocol/{messagePayload.js → messages/messagePayload.js} +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import { type InitCustomBlockOptions } from "../init.js";
|
|
3
2
|
import "./NotionCustomBlock.css";
|
|
4
3
|
/**
|
|
5
4
|
* Props accepted by {@link NotionCustomBlock}.
|
|
6
5
|
*/
|
|
7
|
-
export type NotionCustomBlockProps =
|
|
6
|
+
export type NotionCustomBlockProps = {
|
|
8
7
|
children: ReactNode;
|
|
9
8
|
/**
|
|
10
9
|
* Rendered while the SDK ↔ host handshake is in progress. Defaults to
|
|
@@ -28,8 +27,7 @@ export type NotionCustomBlockProps = InitCustomBlockOptions & {
|
|
|
28
27
|
};
|
|
29
28
|
/**
|
|
30
29
|
* Top-level wrapper that runs the SDK ↔ host handshake and gates `children`
|
|
31
|
-
* until it resolves.
|
|
32
|
-
* {@link initCustomBlock}.
|
|
30
|
+
* until it resolves.
|
|
33
31
|
*
|
|
34
32
|
* Templates that prefer not to write a `Root` gating component (or top-level
|
|
35
33
|
* `await`) can mount their app entirely inside this provider:
|
|
@@ -45,5 +43,5 @@ export type NotionCustomBlockProps = InitCustomBlockOptions & {
|
|
|
45
43
|
* Inside `children`, every SDK hook is guaranteed to return a populated
|
|
46
44
|
* value. Outside the provider (or during the loading window), they throw.
|
|
47
45
|
*/
|
|
48
|
-
export declare function NotionCustomBlock({ children,
|
|
46
|
+
export declare function NotionCustomBlock({ children, fallback, errorFallback, autoResize, }: NotionCustomBlockProps): import("react").JSX.Element;
|
|
49
47
|
//# sourceMappingURL=NotionCustomBlock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotionCustomBlock.d.ts","sourceRoot":"","sources":["../../src/react/NotionCustomBlock.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAwC,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"NotionCustomBlock.d.ts","sourceRoot":"","sources":["../../src/react/NotionCustomBlock.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAwC,MAAM,OAAO,CAAA;AAQ5E,OAAO,yBAAyB,CAAA;AAEhC;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACpC,QAAQ,EAAE,SAAS,CAAA;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB;;;;OAIG;IACH,aAAa,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,SAAS,CAAC,CAAA;IACzD;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,EACjC,QAAQ,EACR,QAAe,EACf,aAAa,EACb,UAAiB,GACjB,EAAE,sBAAsB,+BAsExB"}
|
|
@@ -10,8 +10,7 @@ import { useCustomBlockHost } from "./useHostState.js";
|
|
|
10
10
|
import "./NotionCustomBlock.css";
|
|
11
11
|
/**
|
|
12
12
|
* Top-level wrapper that runs the SDK ↔ host handshake and gates `children`
|
|
13
|
-
* until it resolves.
|
|
14
|
-
* {@link initCustomBlock}.
|
|
13
|
+
* until it resolves.
|
|
15
14
|
*
|
|
16
15
|
* Templates that prefer not to write a `Root` gating component (or top-level
|
|
17
16
|
* `await`) can mount their app entirely inside this provider:
|
|
@@ -27,8 +26,8 @@ import "./NotionCustomBlock.css";
|
|
|
27
26
|
* Inside `children`, every SDK hook is guaranteed to return a populated
|
|
28
27
|
* value. Outside the provider (or during the loading window), they throw.
|
|
29
28
|
*/
|
|
30
|
-
export function NotionCustomBlock({ children,
|
|
31
|
-
const init = useCustomBlockInit(
|
|
29
|
+
export function NotionCustomBlock({ children, fallback = null, errorFallback, autoResize = true, }) {
|
|
30
|
+
const init = useCustomBlockInit();
|
|
32
31
|
useCustomBlockAutoResize({ enabled: init.isLoaded && autoResize });
|
|
33
32
|
// True if the block has no host (i.e. it's running in standalone preview).
|
|
34
33
|
const isStandalone = init.error instanceof NotInIframeError;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { CustomBlockInitializationError } from "../protocol/messages/init.js";
|
|
2
|
-
import { type CustomBlockInitPayload
|
|
2
|
+
import { type CustomBlockInitPayload } from "../init.js";
|
|
3
3
|
/**
|
|
4
4
|
* Discriminated state returned by {@link useCustomBlockInit}.
|
|
5
5
|
*
|
|
6
6
|
* Branch on `isLoaded`/`error`:
|
|
7
7
|
* - `{ isLoaded: false, error: undefined }` — handshake in progress.
|
|
8
|
-
* - `{ isLoaded: false, error: CustomBlockInitializationError }` — handshake failed
|
|
9
|
-
*
|
|
8
|
+
* - `{ isLoaded: false, error: CustomBlockInitializationError }` — handshake failed because
|
|
9
|
+
* the host or SDK reported a terminal initialization error.
|
|
10
10
|
* - `{ isLoaded: true, initial }` — handshake complete; safe to render
|
|
11
11
|
* children that call `useTheme`, `useBlockId`, etc.
|
|
12
12
|
*/
|
|
@@ -38,5 +38,5 @@ export type UseCustomBlockInitResult = {
|
|
|
38
38
|
* return <App />
|
|
39
39
|
* }
|
|
40
40
|
*/
|
|
41
|
-
export declare function useCustomBlockInit(
|
|
41
|
+
export declare function useCustomBlockInit(): UseCustomBlockInitResult;
|
|
42
42
|
//# sourceMappingURL=useCustomBlockInit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCustomBlockInit.d.ts","sourceRoot":"","sources":["../../src/react/useCustomBlockInit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,mDAAmD,CAAA;AAEvG,OAAO,
|
|
1
|
+
{"version":3,"file":"useCustomBlockInit.d.ts","sourceRoot":"","sources":["../../src/react/useCustomBlockInit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,mDAAmD,CAAA;AAEvG,OAAO,EAAE,KAAK,sBAAsB,EAAmB,MAAM,YAAY,CAAA;AAEzE;;;;;;;;;GASG;AACH,MAAM,MAAM,wBAAwB,GACjC;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GACrC;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,8BAA8B,CAAA;CAAE,GAC1D;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,sBAAsB,CAAA;CAAE,CAAA;AAExE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,IAAI,wBAAwB,CAwB7D"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
|
-
import { initCustomBlock
|
|
2
|
+
import { initCustomBlock } from "../init.js";
|
|
3
3
|
/**
|
|
4
4
|
* React wrapper around {@link initCustomBlock}. Kicks off the SDK ↔ host
|
|
5
5
|
* handshake on mount and returns a discriminated state object so the rest of
|
|
@@ -17,15 +17,14 @@ import { initCustomBlock, } from "../init.js";
|
|
|
17
17
|
* return <App />
|
|
18
18
|
* }
|
|
19
19
|
*/
|
|
20
|
-
export function useCustomBlockInit(
|
|
20
|
+
export function useCustomBlockInit() {
|
|
21
21
|
const [state, setState] = useState({
|
|
22
22
|
isLoaded: false,
|
|
23
23
|
error: undefined,
|
|
24
24
|
});
|
|
25
|
-
// biome-ignore lint/correctness/useExhaustiveDependencies(opts): Initialization caches its first options and promise. Later options are ignored, so changes should not resubscribe to the same promise.
|
|
26
25
|
useEffect(() => {
|
|
27
26
|
let cancelled = false;
|
|
28
|
-
initCustomBlock(
|
|
27
|
+
initCustomBlock().then(initial => {
|
|
29
28
|
if (!cancelled) {
|
|
30
29
|
setState({ isLoaded: true, error: undefined, initial });
|
|
31
30
|
}
|
|
@@ -35,7 +35,7 @@ export declare function useParent(): NotionParent;
|
|
|
35
35
|
*/
|
|
36
36
|
export declare function usePage(): CustomBlockPage;
|
|
37
37
|
/**
|
|
38
|
-
* Returns the host's current theme. Re-renders
|
|
38
|
+
* Returns the host's current theme. Re-renders when the theme changes.
|
|
39
39
|
*
|
|
40
40
|
* Throws if called before `initCustomBlock` has resolved.
|
|
41
41
|
*
|
|
@@ -44,8 +44,7 @@ export declare function usePage(): CustomBlockPage;
|
|
|
44
44
|
*/
|
|
45
45
|
export declare function useTheme(): NotionTheme;
|
|
46
46
|
/**
|
|
47
|
-
* Returns the host's contrast preference. Re-renders
|
|
48
|
-
* `contrastModeChanged` message from the host.
|
|
47
|
+
* Returns the host's contrast preference. Re-renders when the contrast preference changes.
|
|
49
48
|
*
|
|
50
49
|
* Throws if called before `initCustomBlock` has resolved.
|
|
51
50
|
*
|
|
@@ -54,8 +53,7 @@ export declare function useTheme(): NotionTheme;
|
|
|
54
53
|
*/
|
|
55
54
|
export declare function useContrastMode(): NotionContrastMode;
|
|
56
55
|
/**
|
|
57
|
-
* Returns the viewing user's Notion profile. Re-renders
|
|
58
|
-
* `currentUserChanged` message.
|
|
56
|
+
* Returns the viewing user's Notion profile. Re-renders when the profile data changes.
|
|
59
57
|
*
|
|
60
58
|
* Throws if called before `initCustomBlock` has resolved. `await` it before mounting.
|
|
61
59
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useRuntimeState.d.ts","sourceRoot":"","sources":["../../src/react/useRuntimeState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAA;AACtF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAA;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAA;AACrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAA;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAA;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gDAAgD,CAAA;AAIhF;;;;;;;GAOG;AACH,wBAAgB,UAAU,IAAI,aAAa,
|
|
1
|
+
{"version":3,"file":"useRuntimeState.d.ts","sourceRoot":"","sources":["../../src/react/useRuntimeState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAA;AACtF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAA;AAC5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8CAA8C,CAAA;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gDAAgD,CAAA;AACrF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAA;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAA;AAC5E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gDAAgD,CAAA;AAIhF;;;;;;;GAOG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAK1C;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,IAAI,YAAY,CAKxC;AAED;;;;;;;;GAQG;AACH,wBAAgB,OAAO,IAAI,eAAe,CAEzC;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,IAAI,WAAW,CAKtC;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,IAAI,kBAAkB,CAKpD;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,IAAI,UAAU,CAK3C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,IAAI,mBAAmB,CAKjD"}
|
|
@@ -9,7 +9,7 @@ import { customBlock } from "../customBlock.js";
|
|
|
9
9
|
* const blockId = useBlockId()
|
|
10
10
|
*/
|
|
11
11
|
export function useBlockId() {
|
|
12
|
-
return useSyncExternalStore(customBlock.
|
|
12
|
+
return useSyncExternalStore(customBlock.subscribeToBlockId, customBlock.getBlockId);
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* Returns the block's parent in the document tree. Re-renders when the host sends
|
|
@@ -21,7 +21,7 @@ export function useBlockId() {
|
|
|
21
21
|
* const parent = useParent()
|
|
22
22
|
*/
|
|
23
23
|
export function useParent() {
|
|
24
|
-
return useSyncExternalStore(customBlock.
|
|
24
|
+
return useSyncExternalStore(customBlock.subscribeToParent, customBlock.getParent);
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Returns the nearest enclosing page ancestor. Re-renders when the host sends
|
|
@@ -33,10 +33,10 @@ export function useParent() {
|
|
|
33
33
|
* const page = usePage()
|
|
34
34
|
*/
|
|
35
35
|
export function usePage() {
|
|
36
|
-
return useSyncExternalStore(customBlock.
|
|
36
|
+
return useSyncExternalStore(customBlock.subscribeToPage, customBlock.getPage);
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
39
|
-
* Returns the host's current theme. Re-renders
|
|
39
|
+
* Returns the host's current theme. Re-renders when the theme changes.
|
|
40
40
|
*
|
|
41
41
|
* Throws if called before `initCustomBlock` has resolved.
|
|
42
42
|
*
|
|
@@ -44,11 +44,10 @@ export function usePage() {
|
|
|
44
44
|
* const theme = useTheme()
|
|
45
45
|
*/
|
|
46
46
|
export function useTheme() {
|
|
47
|
-
return useSyncExternalStore(customBlock.
|
|
47
|
+
return useSyncExternalStore(customBlock.subscribeToTheme, customBlock.getTheme);
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
-
* Returns the host's contrast preference. Re-renders
|
|
51
|
-
* `contrastModeChanged` message from the host.
|
|
50
|
+
* Returns the host's contrast preference. Re-renders when the contrast preference changes.
|
|
52
51
|
*
|
|
53
52
|
* Throws if called before `initCustomBlock` has resolved.
|
|
54
53
|
*
|
|
@@ -56,11 +55,10 @@ export function useTheme() {
|
|
|
56
55
|
* const contrastMode = useContrastMode()
|
|
57
56
|
*/
|
|
58
57
|
export function useContrastMode() {
|
|
59
|
-
return useSyncExternalStore(customBlock.
|
|
58
|
+
return useSyncExternalStore(customBlock.subscribeToContrastMode, customBlock.getContrastMode);
|
|
60
59
|
}
|
|
61
60
|
/**
|
|
62
|
-
* Returns the viewing user's Notion profile. Re-renders
|
|
63
|
-
* `currentUserChanged` message.
|
|
61
|
+
* Returns the viewing user's Notion profile. Re-renders when the profile data changes.
|
|
64
62
|
*
|
|
65
63
|
* Throws if called before `initCustomBlock` has resolved. `await` it before mounting.
|
|
66
64
|
*
|
|
@@ -69,7 +67,7 @@ export function useContrastMode() {
|
|
|
69
67
|
* console.log(me.id, me.name, me.person.email)
|
|
70
68
|
*/
|
|
71
69
|
export function useCurrentUser() {
|
|
72
|
-
return useSyncExternalStore(customBlock.
|
|
70
|
+
return useSyncExternalStore(customBlock.subscribeToCurrentUser, customBlock.getCurrentUser);
|
|
73
71
|
}
|
|
74
72
|
/**
|
|
75
73
|
* Returns the manifest that the block declared and the host provided during initialization.
|
|
@@ -84,5 +82,5 @@ export function useCurrentUser() {
|
|
|
84
82
|
* resolved property IDs and schemas.
|
|
85
83
|
*/
|
|
86
84
|
export function useManifest() {
|
|
87
|
-
return useSyncExternalStore(customBlock.
|
|
85
|
+
return useSyncExternalStore(customBlock.subscribeToManifest, customBlock.getManifest);
|
|
88
86
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -2,12 +2,12 @@ import type { NotionCollectionSchema } from "./protocol/dataSources/dataSource.j
|
|
|
2
2
|
import type { NotionDataSourceValue } from "./protocol/dataSources/dataSourceValue.js";
|
|
3
3
|
import type { NotionPropertySchema } from "./protocol/dataSources/propertySchema.js";
|
|
4
4
|
import type { NotionDataSourceId, NotionPageId } from "./protocol/ids.js";
|
|
5
|
-
import type { BridgeMessagePayload } from "./protocol/messagePayload.js";
|
|
6
5
|
import type { NotionCreatePagePosition } from "./protocol/messages/createPage.js";
|
|
7
6
|
import type { CreatePageResultMessage, CustomBlockCreatePageErrorInfo } from "./protocol/messages/createPageResult.js";
|
|
8
7
|
import type { CustomBlockGetPageErrorInfo, GetPageResultMessage } from "./protocol/messages/getPage.js";
|
|
9
8
|
import type { CustomBlockGetUserErrorInfo, GetUserResultMessage } from "./protocol/messages/getUser.js";
|
|
10
9
|
import type { CustomBlockListUsersErrorInfo, ListUsersMessage, ListUsersResultMessage } from "./protocol/messages/listUsers.js";
|
|
10
|
+
import type { BridgeMessagePayload } from "./protocol/messages/messagePayload.js";
|
|
11
11
|
import type { CustomBlockCheckboxFilterOperator, CustomBlockContainsFilterOperator, CustomBlockDateFilterOperator, CustomBlockNumberFilterOperator, CustomBlockOptionFilterOperator, CustomBlockTextFilterOperator } from "./protocol/messages/queryDataSource.js";
|
|
12
12
|
import type { CustomBlockQueryDataSourceErrorInfo } from "./protocol/messages/queryDataSourceResult.js";
|
|
13
13
|
import type { UpdatePageMessage } from "./protocol/messages/updatePage.js";
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4DAA4D,CAAA;AACxG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iEAAiE,CAAA;AAC5G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gEAAgE,CAAA;AAC1G,OAAO,KAAK,EACX,kBAAkB,EAClB,YAAY,EACZ,MAAM,yCAAyC,CAAA;AAChD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,4DAA4D,CAAA;AACxG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iEAAiE,CAAA;AAC5G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gEAAgE,CAAA;AAC1G,OAAO,KAAK,EACX,kBAAkB,EAClB,YAAY,EACZ,MAAM,yCAAyC,CAAA;AAChD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yDAAyD,CAAA;AACvG,OAAO,KAAK,EACX,uBAAuB,EACvB,8BAA8B,EAC9B,MAAM,+DAA+D,CAAA;AACtE,OAAO,KAAK,EACX,2BAA2B,EAC3B,oBAAoB,EACpB,MAAM,sDAAsD,CAAA;AAC7D,OAAO,KAAK,EACX,2BAA2B,EAC3B,oBAAoB,EACpB,MAAM,sDAAsD,CAAA;AAC7D,OAAO,KAAK,EACX,6BAA6B,EAC7B,gBAAgB,EAChB,sBAAsB,EACtB,MAAM,wDAAwD,CAAA;AAC/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6DAA6D,CAAA;AACvG,OAAO,KAAK,EACX,iCAAiC,EACjC,iCAAiC,EACjC,6BAA6B,EAC7B,+BAA+B,EAC/B,+BAA+B,EAC/B,6BAA6B,EAC7B,MAAM,8DAA8D,CAAA;AACrE,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,oEAAoE,CAAA;AAC7H,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yDAAyD,CAAA;AAChG,OAAO,KAAK,EACX,8BAA8B,EAC9B,uBAAuB,EACvB,MAAM,+DAA+D,CAAA;AACtE,OAAO,KAAK,EACX,eAAe,EACf,cAAc,EACd,uBAAuB,EACvB,MAAM,gDAAgD,CAAA;AAEvD,YAAY,EAAE,oBAAoB,EAAE,MAAM,4CAA4C,CAAA;AACtF,YAAY,EACX,kBAAkB,EAClB,aAAa,GACb,MAAM,yCAAyC,CAAA;AAChD,YAAY,EACX,UAAU,EACV,YAAY,EACZ,cAAc,GACd,MAAM,gDAAgD,CAAA;AACvD,YAAY,EACX,8BAA8B,EAC9B,2BAA2B,EAC3B,2BAA2B,EAC3B,6BAA6B,EAC7B,mCAAmC,EACnC,8BAA8B,GAC9B,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,4BAA4B,GACvC,uBAAuB,SAAS,MAAM,aAAa,GAChD,aAAa,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GACnC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,KAAK,GACN,KAAK,CAAA;AAET,MAAM,MAAM,0BAA0B,GAAG;IACxC,CAAC,eAAe,EAAE,MAAM,GAAG,4BAA4B,CAAA;CACvD,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IAClC,EAAE,EAAE,YAAY,CAAA;IAEhB,mDAAmD;IACnD,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,cAAc,EAAE;QAAE,CAAC,UAAU,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAAA;KAAE,CAAA;IAC3E;;;OAGG;IACH,eAAe,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAAA;KAAE,CAAA;IACrE;;;OAGG;IACH,MAAM,EAAE,CAAC,IAAI,EAAE,8BAA8B,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC3E,uEAAuE;IACvE,OAAO,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACxC,0EAA0E;IAC1E,SAAS,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAA;CAC1C,CAAA;AAED,MAAM,MAAM,8BAA8B,GAAG;IAC5C,UAAU,CAAC,EAAE,0BAA0B,CAAA;IACvC,IAAI,CAAC,EAAE,cAAc,CAAA;IACrB,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,oEAAoE;IACpE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,2CAA2C;IAE3C,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,+BAA+B,GAAG,8BAA8B,CAAA;AAE5E;;;;GAIG;AACH,MAAM,MAAM,gCAAgC,GAAG,gBAAgB,CAAA;AAE/D,MAAM,MAAM,kCAAkC,GAAG,6BAA6B,CAAA;AAC9E,MAAM,MAAM,oCAAoC,GAC/C,+BAA+B,CAAA;AAChC,MAAM,MAAM,sCAAsC,GACjD,iCAAiC,CAAA;AAClC,MAAM,MAAM,oCAAoC,GAC/C,+BAA+B,CAAA;AAChC,MAAM,MAAM,sCAAsC,GACjD,iCAAiC,CAAA;AAClC,MAAM,MAAM,kCAAkC,GAAG,6BAA6B,CAAA;AAE9E,MAAM,MAAM,+BAA+B,GACxC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,KAAK,CAAA;CAAE,GACnC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,KAAK,CAAA;CAAE,CAAA;AAEtC,MAAM,MAAM,8BAA8B,GAAG,+BAA+B,GAC3E,CACG;IAAE,KAAK,EAAE,kCAAkC,CAAA;CAAE,GAC7C;IAAE,SAAS,EAAE,kCAAkC,CAAA;CAAE,GACjD;IAAE,GAAG,EAAE,kCAAkC,CAAA;CAAE,GAC3C;IAAE,KAAK,EAAE,kCAAkC,CAAA;CAAE,GAC7C;IAAE,YAAY,EAAE,kCAAkC,CAAA;CAAE,GACpD;IAAE,MAAM,EAAE,oCAAoC,CAAA;CAAE,GAChD;IAAE,QAAQ,EAAE,sCAAsC,CAAA;CAAE,GACpD;IAAE,MAAM,EAAE,oCAAoC,CAAA;CAAE,GAChD;IAAE,YAAY,EAAE,sCAAsC,CAAA;CAAE,GACxD;IAAE,MAAM,EAAE,oCAAoC,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,kCAAkC,CAAA;CAAE,CAC9C,CAAA;AAEF,MAAM,MAAM,oBAAoB,GAAG,+BAA+B,GAAG;IACpE,SAAS,EAAE,WAAW,GAAG,YAAY,CAAA;CACrC,CAAA;AAED,MAAM,MAAM,sBAAsB,GAC/B,8BAA8B,GAC9B;IAAE,GAAG,EAAE,8BAA8B,EAAE,CAAA;CAAE,CAAA;AAE5C;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAChC,KAAK,EAAE,oBAAoB,EAAE,CAAA;IAC7B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,sBAAsB,CAAA;IACzC;;;OAGG;IACH,mBAAmB,EAAE;QAAE,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,CAAA;KAAE,CAAA;IACnE;;;OAGG;IACH,gBAAgB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,CAAA;IACvD;;;;OAIG;IACH,oBAAoB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAAA;KAAE,CAAA;IACzE,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,mCAAmC,CAAA;CAC3C,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACpC,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,0FAA0F;IAC1F,MAAM,CAAC,EAAE,sBAAsB,CAAA;IAC/B,qEAAqE;IACrE,KAAK,CAAC,EAAE,oBAAoB,EAAE,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACvC,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAClD,OAAO,CAAC,EAAE,sBAAsB,CAAA;CAChC,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,CAAA;AAEpD,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,CAAA;AAEzD;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,gBAAgB,GACzB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,cAAc,EAAE,kBAAkB,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC5B,MAAM,EAAE,gBAAgB,CAAA;IACxB,UAAU,EAAE,0BAA0B,CAAA;IACtC,QAAQ,CAAC,EAAE,wBAAwB,CAAA;CACnC,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,cAAc,CAAA;AAE5C;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,CAClD,uBAAuB,EACvB,8BAA8B,CAC9B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,IAAI,CAChC,iBAAiB,EACjB,MAAM,GAAG,WAAW,GAAG,UAAU,CACjC,GAAG;IACH,oEAAoE;IACpE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,2CAA2C;IAE3C,QAAQ,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,cAAc,CAAA;AAE5C;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,oBAAoB,CAC/C,oBAAoB,EACpB,2BAA2B,CAC3B,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,CAClD,uBAAuB,EACvB,8BAA8B,CAC9B,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,WAAW,CAAC,CAAA;AAExE;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,aAAa,CAAA;AAE1C,MAAM,MAAM,eAAe,GAAG,oBAAoB,CACjD,sBAAsB,EACtB,6BAA6B,CAC7B,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,oBAAoB,CAC/C,oBAAoB,EACpB,2BAA2B,CAC3B,CAAA"}
|
package/dist/version.js
CHANGED
package/docs/block-location.md
CHANGED
|
@@ -1,38 +1,59 @@
|
|
|
1
|
-
# Block
|
|
1
|
+
# Block location and appearance
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Block and app context describes where the block runs and the host's appearance. Use getters for current values, subscriptions for initial values and later changes, or React hooks in components.
|
|
4
4
|
|
|
5
|
-
## API
|
|
5
|
+
## API overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Import `customBlock` from `@notionhq/custom-blocks` for getters and subscriptions. Import React hooks from `@notionhq/custom-blocks/react`.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The getter and subscription names below are methods on `customBlock`.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
| Context | Getter | Subscription | React hook |
|
|
12
|
+
| --- | --- | --- | --- |
|
|
13
|
+
| Current user | `getCurrentUser()` | `subscribeToCurrentUser(callback)` | `useCurrentUser()` |
|
|
14
|
+
| Custom block ID | `getBlockId()` | `subscribeToBlockId(callback)` | `useBlockId()` |
|
|
15
|
+
| Parent | `getParent()` | `subscribeToParent(callback)` | `useParent()` |
|
|
16
|
+
| Containing page | `getPage()` | `subscribeToPage(callback)` | `usePage()` |
|
|
17
|
+
| Theme | `getTheme()` | `subscribeToTheme(callback)` | `useTheme()` |
|
|
18
|
+
| Contrast mode | `getContrastMode()` | `subscribeToContrastMode(callback)` | `useContrastMode()` |
|
|
19
|
+
| Manifest | `getManifest()` | `subscribeToManifest(callback)` | `useManifest()` |
|
|
12
20
|
|
|
13
|
-
|
|
21
|
+
## Reading values and following changes
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
function useBlockId(): NotionBlockId;
|
|
17
|
-
```
|
|
23
|
+
Getters return the current value and throw before initialization completes. In React, call context hooks inside `NotionCustomBlock`, which waits for initialization before rendering its children.
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
Subscriptions can register before initialization. They wait for initialization before delivering the initial value, or deliver immediately if initialization is complete. Start initialization with `initCustomBlock()` or `NotionCustomBlock`. Subscriptions do not start it themselves. These initialization APIs also report failures. Each subscription returns an unsubscribe function. Repeated cleanup calls have no effect.
|
|
26
|
+
|
|
27
|
+
After initial delivery, subscriptions compare values with `Object.is`. Objects use referential equality: a new reference triggers a callback even if its contents are unchanged. Updates to other context values do not trigger the callback. React hooks follow the same comparison rules.
|
|
20
28
|
|
|
21
29
|
```ts
|
|
22
|
-
|
|
30
|
+
import { customBlock, initCustomBlock } from "@notionhq/custom-blocks"
|
|
31
|
+
|
|
32
|
+
const unsubscribe = customBlock.subscribeToTheme(theme => {
|
|
33
|
+
console.log(theme) // Initial theme, then later changes.
|
|
34
|
+
})
|
|
23
35
|
|
|
24
|
-
|
|
36
|
+
await initCustomBlock()
|
|
37
|
+
console.log(customBlock.getTheme()) // Read the current theme once.
|
|
38
|
+
|
|
39
|
+
// Call unsubscribe() when the view is removed.
|
|
25
40
|
```
|
|
26
41
|
|
|
27
|
-
|
|
42
|
+
## Current user
|
|
28
43
|
|
|
29
|
-
|
|
44
|
+
Use `getCurrentUser()`, `subscribeToCurrentUser()`, and `useCurrentUser()` to access the viewing user's `NotionUser`. See [users](./users.md#reading-the-current-user) for profile fields and user APIs.
|
|
30
45
|
|
|
31
|
-
|
|
46
|
+
## Custom block ID
|
|
32
47
|
|
|
33
|
-
|
|
34
|
-
|
|
48
|
+
Use `getBlockId()`, `subscribeToBlockId()`, and `useBlockId()` to access the custom block's own `NotionBlockId`.
|
|
49
|
+
|
|
50
|
+
The ID is stable for the lifetime of the block. Each subscription delivers once, unless cancelled before initialization. You can register before initialization without an error.
|
|
35
51
|
|
|
52
|
+
## Parent
|
|
53
|
+
|
|
54
|
+
Use `getParent()`, `subscribeToParent()`, and `useParent()` to access the block's `NotionParent` in the document tree. For a custom collection view, the parent identifies the data source associated with the view.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
36
57
|
type NotionParent =
|
|
37
58
|
| { type: "page_id"; page_id: string } // inline custom block under a page
|
|
38
59
|
| { type: "block_id"; block_id: NotionBlockId } // inline custom block under a toggle/column/callout/...
|
|
@@ -42,8 +63,6 @@ type NotionParent =
|
|
|
42
63
|
| { type: "unavailable" }; // access denied; no parent ID or kind
|
|
43
64
|
```
|
|
44
65
|
|
|
45
|
-
For non-React renderers, use `customBlock.getParent()` after `initCustomBlock()` resolves.
|
|
46
|
-
|
|
47
66
|
To identify custom blocks in agent-owned instruction content:
|
|
48
67
|
|
|
49
68
|
```tsx
|
|
@@ -60,15 +79,11 @@ export function AgentInstructionBadge() {
|
|
|
60
79
|
}
|
|
61
80
|
```
|
|
62
81
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Returns the nearest enclosing `page` / `collection_view_page` ancestor.
|
|
82
|
+
## Containing page
|
|
66
83
|
|
|
67
|
-
|
|
84
|
+
Use `getPage()`, `subscribeToPage()`, and `usePage()` to access the nearest enclosing page or collection view page. The page's parent can change even when its ID stays the same.
|
|
68
85
|
|
|
69
86
|
```ts
|
|
70
|
-
function usePage(): CustomBlockPage;
|
|
71
|
-
|
|
72
87
|
type CustomBlockPage = {
|
|
73
88
|
id: NotionPageId;
|
|
74
89
|
parent: NotionParent; // the containing page's own parent
|
|
@@ -77,15 +92,10 @@ type CustomBlockPage = {
|
|
|
77
92
|
|
|
78
93
|
`page.parent` allows determining if the custom block is in a freestanding page or part of a database. Don't confuse it with `useParent()`, which is the custom block's own parent.
|
|
79
94
|
|
|
80
|
-
|
|
81
|
-
const page = usePage();
|
|
82
|
-
const isInsideDatabaseRow = page.parent.type === "data_source_id";
|
|
83
|
-
```
|
|
95
|
+
A containing page whose parent has `type: "data_source_id"` belongs to a data source.
|
|
84
96
|
|
|
85
97
|
For anything beyond location — title, icon, properties — fetch the page through the pages API: `pages.get(page.id)`.
|
|
86
98
|
|
|
87
|
-
For non-React renderers, use `customBlock.getPage()` after `initCustomBlock()` resolves.
|
|
88
|
-
|
|
89
99
|
When the viewer cannot access the parent resource, the host returns
|
|
90
100
|
`{ type: "unavailable" }`, including on `usePage().parent`. This applies to every
|
|
91
101
|
parent kind, including data sources, even when the readable child identifies
|
|
@@ -97,25 +107,13 @@ Treat `unavailable` as unknown when branching on location: it does not establish
|
|
|
97
107
|
whether the containing page is a database row. A parent that is still loading
|
|
98
108
|
is not reported as access denied.
|
|
99
109
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
Returns the host's current theme.
|
|
110
|
+
## Theme and contrast
|
|
103
111
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
```ts
|
|
107
|
-
function useTheme(): NotionTheme; // "light" | "dark"
|
|
108
|
-
```
|
|
112
|
+
Use design tokens to style the block. When your code needs the current appearance, use a getter, subscription, or React hook from the [API overview](#api-overview).
|
|
109
113
|
|
|
110
|
-
|
|
114
|
+
`NotionTheme` is `"light"` or `"dark"`. `NotionContrastMode` is `"standard"` or `"high"`. Hosts that omit a contrast mode use `"standard"`.
|
|
111
115
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
```ts
|
|
115
|
-
await initCustomBlock();
|
|
116
|
-
|
|
117
|
-
const theme = customBlock.getTheme();
|
|
118
|
-
```
|
|
116
|
+
Getters read the current value after initialization. Subscriptions can register earlier. They deliver the initial value once initialized, then later changes. React hooks keep components current when called inside `NotionCustomBlock`.
|
|
119
117
|
|
|
120
118
|
```tsx
|
|
121
119
|
import { usePage, useTheme } from "@notionhq/custom-blocks/react";
|
|
@@ -127,14 +125,12 @@ export function Header() {
|
|
|
127
125
|
}
|
|
128
126
|
```
|
|
129
127
|
|
|
130
|
-
|
|
128
|
+
For styling, `NotionTokenScope` applies theme and contrast mode to the bundled Notion CSS variables automatically. The stylesheet uses `data-display-mode` for light and dark mode. The separate `data-theme` attribute selects content color palettes such as `blue`, `red`, and `gray`.
|
|
131
129
|
|
|
132
|
-
|
|
130
|
+
See [Reading values and following changes](#reading-values-and-following-changes) for a getter and subscription example, including cleanup.
|
|
133
131
|
|
|
134
|
-
|
|
135
|
-
function useContrastMode(): NotionContrastMode; // "standard" | "high"
|
|
136
|
-
```
|
|
132
|
+
## Manifest
|
|
137
133
|
|
|
138
|
-
|
|
134
|
+
Use `getManifest()`, `subscribeToManifest()`, and `useManifest()` to access the declared `CustomBlockManifest`. The manifest stays fixed for the lifetime of the running block, so each subscription delivers it once. You can register before initialization without an error.
|
|
139
135
|
|
|
140
|
-
|
|
136
|
+
See [data sources](./data-sources.md) for manifest details and `subscribeToDataSource()` for query snapshots.
|
package/docs/data-sources.md
CHANGED
|
@@ -60,8 +60,6 @@ const unsubscribe = customBlock.subscribeToDataSource({
|
|
|
60
60
|
},
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
-
// When the renderer unmounts:
|
|
64
|
-
unsubscribe();
|
|
65
63
|
```
|
|
66
64
|
|
|
67
65
|
To change the query or request more rows, unsubscribe and create a new subscription with different options.
|
|
@@ -235,7 +233,9 @@ Returns the block manifest received from the host during initialization. The man
|
|
|
235
233
|
function customBlock.getManifest(): CustomBlockManifest;
|
|
236
234
|
```
|
|
237
235
|
|
|
238
|
-
Framework-neutral getter for the same manifest returned by `useManifest()`.
|
|
236
|
+
Framework-neutral getter for the same manifest returned by `useManifest()`.
|
|
237
|
+
`customBlock.subscribeToManifest(callback)` follows the [context subscription contract](./block-location.md#reading-values-and-following-changes).
|
|
238
|
+
The manifest stays fixed for the lifetime of the running block, so each subscription delivers it once. You can register before initialization without an error.
|
|
239
239
|
|
|
240
240
|
## Example: querying a data source
|
|
241
241
|
|
package/docs/errors.md
CHANGED
|
@@ -35,7 +35,7 @@ Each API narrows `code` to its own open string union. The known literals provide
|
|
|
35
35
|
|
|
36
36
|
## Initialization errors
|
|
37
37
|
|
|
38
|
-
Unlike request helpers, `initCustomBlock` rejects with `CustomBlockInitializationError`. Its `code` type is `CustomBlockInitializationErrorCode`, which covers failures reported by either side of the handshake plus SDK-local
|
|
38
|
+
Unlike request helpers, `initCustomBlock` rejects with `CustomBlockInitializationError`. Its `code` type is `CustomBlockInitializationErrorCode`, which covers failures reported by either side of the handshake plus SDK-local iframe errors. For example, hosts can report `init_timeout` when Notion did not finish loading host dependencies in time.
|
|
39
39
|
|
|
40
40
|
`CustomBlockInitializationErrorInfo` is the matching `{ code, message, isRetryable }` object type.
|
|
41
41
|
|
package/docs/lifecycle.md
CHANGED
|
@@ -34,8 +34,9 @@ The initialization promise resolves after the SDK applies the host state.
|
|
|
34
34
|
Await it before rendering code that reads initialized state. The SDK sends
|
|
35
35
|
`initResult` after the initial render.
|
|
36
36
|
|
|
37
|
-
- The
|
|
38
|
-
|
|
37
|
+
- The SDK waits for the host to respond with `init` or `init.error`, without
|
|
38
|
+
an SDK-local timeout. Host-owned timeout errors such as `init_timeout` reject
|
|
39
|
+
the promise with `CustomBlockInitializationError`.
|
|
39
40
|
- If a matching `init` is malformed, the SDK sends `initResult.error` with code
|
|
40
41
|
`invalid_init_payload` and rejects with the same structured error.
|
|
41
42
|
- If the host sends incomplete or invalid data source bindings, the SDK sends
|
|
@@ -91,21 +92,19 @@ values.
|
|
|
91
92
|
### `<NotionCustomBlock>`
|
|
92
93
|
|
|
93
94
|
```ts
|
|
94
|
-
type NotionCustomBlockProps =
|
|
95
|
+
type NotionCustomBlockProps = {
|
|
95
96
|
children: ReactNode;
|
|
96
97
|
fallback?: ReactNode;
|
|
97
98
|
errorFallback?: ReactNode | ((error: Error) => ReactNode);
|
|
98
99
|
};
|
|
99
100
|
```
|
|
100
101
|
|
|
101
|
-
Top-level wrapper. It starts the handshake and renders `children` after init. It measures `#root` before it shows the iframe and when content height changes. `fallback` replaces the loading view. Its default is `null`. `errorFallback` replaces the error message if init fails.
|
|
102
|
+
Top-level wrapper. It starts the handshake and renders `children` after init. It measures `#root` before it shows the iframe and when content height changes. `fallback` replaces the loading view. Its default is `null`. `errorFallback` replaces the error message if init fails.
|
|
102
103
|
|
|
103
|
-
### `useCustomBlockInit(
|
|
104
|
+
### `useCustomBlockInit()`
|
|
104
105
|
|
|
105
106
|
```ts
|
|
106
|
-
function useCustomBlockInit(
|
|
107
|
-
opts?: InitCustomBlockOptions,
|
|
108
|
-
): UseCustomBlockInitResult;
|
|
107
|
+
function useCustomBlockInit(): UseCustomBlockInitResult;
|
|
109
108
|
|
|
110
109
|
type UseCustomBlockInitResult =
|
|
111
110
|
| { isLoaded: false; error: undefined }
|
|
@@ -124,14 +123,10 @@ function Root() {
|
|
|
124
123
|
}
|
|
125
124
|
```
|
|
126
125
|
|
|
127
|
-
### `initCustomBlock(
|
|
126
|
+
### `initCustomBlock()`
|
|
128
127
|
|
|
129
128
|
```ts
|
|
130
|
-
function initCustomBlock(
|
|
131
|
-
opts?: InitCustomBlockOptions,
|
|
132
|
-
): Promise<CustomBlockInitPayload>;
|
|
133
|
-
|
|
134
|
-
type InitCustomBlockOptions = { timeoutMs?: number };
|
|
129
|
+
function initCustomBlock(): Promise<CustomBlockInitPayload>;
|
|
135
130
|
```
|
|
136
131
|
|
|
137
132
|
The lower-level promise API. `<NotionCustomBlock>` and `useCustomBlockInit` both call it for you. Reach for it directly only when you want to `await` init at module scope (e.g. before `ReactDOM.createRoot`). Expected failures reject with `CustomBlockInitializationError`.
|
|
@@ -142,26 +137,67 @@ The `CustomBlockInitializationErrorCode` tells you where initialization failed:
|
|
|
142
137
|
|
|
143
138
|
- The host rejected initialization.
|
|
144
139
|
- The SDK could not apply the host's state.
|
|
145
|
-
- The SDK failed before the handshake completed, such as `not_in_iframe
|
|
140
|
+
- The SDK failed before the handshake completed, such as `not_in_iframe`.
|
|
146
141
|
|
|
147
142
|
All code types are open string unions, so keep a default branch. Use `isRetryable` to decide whether offering a retry makes sense, and treat `message` as display text rather than a stable identifier. See [Error handling](./errors.md) for the shared error contract.
|
|
148
143
|
|
|
149
144
|
### `customBlock`
|
|
150
145
|
|
|
151
|
-
|
|
146
|
+
The SDK provides getters, subscriptions, and React hooks for block and app context. Use `customBlock` for getters and subscriptions.
|
|
147
|
+
|
|
148
|
+
#### Getter
|
|
152
149
|
|
|
153
|
-
|
|
150
|
+
Getters return the current value, such as the theme, current user, or containing page. They throw if called before initialization completes.
|
|
154
151
|
|
|
155
152
|
```ts
|
|
156
|
-
|
|
153
|
+
import { customBlock, initCustomBlock } from "@notionhq/custom-blocks"
|
|
157
154
|
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
155
|
+
await initCustomBlock()
|
|
156
|
+
const theme = customBlock.getTheme()
|
|
157
|
+
console.log(theme)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### Subscription
|
|
161
|
+
|
|
162
|
+
Subscriptions deliver the initial value and later changes. You can register them before initialization. They wait for initialization before delivering the initial value, or deliver immediately if initialization is complete.
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
import { customBlock, initCustomBlock } from "@notionhq/custom-blocks"
|
|
166
|
+
|
|
167
|
+
const unsubscribe = customBlock.subscribeToTheme(theme => {
|
|
168
|
+
console.log(theme)
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
await initCustomBlock()
|
|
172
|
+
|
|
173
|
+
// Call unsubscribe() when the view is removed to stop future callbacks.
|
|
163
174
|
```
|
|
164
175
|
|
|
176
|
+
#### React hook
|
|
177
|
+
|
|
178
|
+
In React, use context hooks inside `NotionCustomBlock`. The wrapper waits for initialization, and the hooks keep components current as values change. React handles subscription cleanup when the component unmounts.
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
import { NotionCustomBlock, useTheme } from "@notionhq/custom-blocks/react"
|
|
182
|
+
|
|
183
|
+
export function App() {
|
|
184
|
+
return (
|
|
185
|
+
<NotionCustomBlock>
|
|
186
|
+
<ThemeLabel />
|
|
187
|
+
</NotionCustomBlock>
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function ThemeLabel() {
|
|
192
|
+
const theme = useTheme()
|
|
193
|
+
return <p>Current theme: {theme}</p>
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
See [Block location and appearance](./block-location.md#reading-values-and-following-changes) for the available getters, subscriptions, and React hooks.
|
|
198
|
+
|
|
199
|
+
### `customBlock.autoResize()`
|
|
200
|
+
|
|
165
201
|
For non-React auto-resize, pass the element whose content height should drive the host iframe. The helper posts one initial measurement, observes later size changes when `ResizeObserver` is available, dedupes unchanged heights, and returns a cleanup function:
|
|
166
202
|
|
|
167
203
|
```ts
|
|
@@ -169,8 +205,7 @@ const stopAutoResize = customBlock.autoResize({
|
|
|
169
205
|
target: document.getElementById("root"),
|
|
170
206
|
});
|
|
171
207
|
|
|
172
|
-
//
|
|
173
|
-
stopAutoResize();
|
|
208
|
+
// Call stopAutoResize() when your renderer is removed.
|
|
174
209
|
```
|
|
175
210
|
|
|
176
211
|
### `NotInIframeError`
|