@notionhq/custom-blocks 0.0.58

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 (298) hide show
  1. package/HOST.md +171 -0
  2. package/README.md +57 -0
  3. package/bin/cli/attach.js +180 -0
  4. package/bin/cli/cli.js +248 -0
  5. package/bin/cli/create.js +106 -0
  6. package/bin/cli/datasources.js +255 -0
  7. package/bin/cli/deploy.js +109 -0
  8. package/bin/cli/ids.js +13 -0
  9. package/bin/cli/ntn.js +95 -0
  10. package/bin/cli/pullData.js +76 -0
  11. package/bin/cli/pullManifest.js +158 -0
  12. package/bin/cli/target.js +95 -0
  13. package/bin/src/bridge/dataSources/propertySchema.js +148 -0
  14. package/bin/src/bridge/manifest.js +40 -0
  15. package/dist/autoResize.d.ts +4 -0
  16. package/dist/autoResize.d.ts.map +1 -0
  17. package/dist/autoResize.js +71 -0
  18. package/dist/bridge/SandboxBridge.d.ts +92 -0
  19. package/dist/bridge/SandboxBridge.d.ts.map +1 -0
  20. package/dist/bridge/SandboxBridge.js +718 -0
  21. package/dist/bridge/dataSources/dataSource.d.ts +732 -0
  22. package/dist/bridge/dataSources/dataSource.d.ts.map +1 -0
  23. package/dist/bridge/dataSources/dataSource.js +37 -0
  24. package/dist/bridge/dataSources/dataSourcePage.d.ts +118 -0
  25. package/dist/bridge/dataSources/dataSourcePage.d.ts.map +1 -0
  26. package/dist/bridge/dataSources/dataSourcePage.js +14 -0
  27. package/dist/bridge/dataSources/dataSourceValue.d.ts +67 -0
  28. package/dist/bridge/dataSources/dataSourceValue.d.ts.map +1 -0
  29. package/dist/bridge/dataSources/dataSourceValue.js +14 -0
  30. package/dist/bridge/dataSources/dateValue.d.ts +158 -0
  31. package/dist/bridge/dataSources/dateValue.d.ts.map +1 -0
  32. package/dist/bridge/dataSources/dateValue.js +59 -0
  33. package/dist/bridge/dataSources/errors.d.ts +6 -0
  34. package/dist/bridge/dataSources/errors.d.ts.map +1 -0
  35. package/dist/bridge/dataSources/errors.js +4 -0
  36. package/dist/bridge/dataSources/propertySchema.d.ts +191 -0
  37. package/dist/bridge/dataSources/propertySchema.d.ts.map +1 -0
  38. package/dist/bridge/dataSources/propertySchema.js +148 -0
  39. package/dist/bridge/dataSources/recordPointer.d.ts +10 -0
  40. package/dist/bridge/dataSources/recordPointer.d.ts.map +1 -0
  41. package/dist/bridge/dataSources/recordPointer.js +8 -0
  42. package/dist/bridge/dataSources/resolve.d.ts +22 -0
  43. package/dist/bridge/dataSources/resolve.d.ts.map +1 -0
  44. package/dist/bridge/dataSources/resolve.js +65 -0
  45. package/dist/bridge/dataSources/resolveProperty.d.ts +41 -0
  46. package/dist/bridge/dataSources/resolveProperty.d.ts.map +1 -0
  47. package/dist/bridge/dataSources/resolveProperty.js +73 -0
  48. package/dist/bridge/errors.d.ts +12 -0
  49. package/dist/bridge/errors.d.ts.map +1 -0
  50. package/dist/bridge/errors.js +6 -0
  51. package/dist/bridge/hostState.d.ts +65 -0
  52. package/dist/bridge/hostState.d.ts.map +1 -0
  53. package/dist/bridge/hostState.js +65 -0
  54. package/dist/bridge/ids.d.ts +39 -0
  55. package/dist/bridge/ids.d.ts.map +1 -0
  56. package/dist/bridge/ids.js +5 -0
  57. package/dist/bridge/incomingType.d.ts +10 -0
  58. package/dist/bridge/incomingType.d.ts.map +1 -0
  59. package/dist/bridge/incomingType.js +17 -0
  60. package/dist/bridge/loadManifest.d.ts +25 -0
  61. package/dist/bridge/loadManifest.d.ts.map +1 -0
  62. package/dist/bridge/loadManifest.js +68 -0
  63. package/dist/bridge/manifest.d.ts +66 -0
  64. package/dist/bridge/manifest.d.ts.map +1 -0
  65. package/dist/bridge/manifest.js +40 -0
  66. package/dist/bridge/messages/createPage.d.ts +225 -0
  67. package/dist/bridge/messages/createPage.d.ts.map +1 -0
  68. package/dist/bridge/messages/createPage.js +46 -0
  69. package/dist/bridge/messages/createPageResult.d.ts +211 -0
  70. package/dist/bridge/messages/createPageResult.d.ts.map +1 -0
  71. package/dist/bridge/messages/createPageResult.js +28 -0
  72. package/dist/bridge/messages/currentUserChanged.d.ts +19 -0
  73. package/dist/bridge/messages/currentUserChanged.d.ts.map +1 -0
  74. package/dist/bridge/messages/currentUserChanged.js +9 -0
  75. package/dist/bridge/messages/dataSourcesChanged.d.ts +158 -0
  76. package/dist/bridge/messages/dataSourcesChanged.d.ts.map +1 -0
  77. package/dist/bridge/messages/dataSourcesChanged.js +13 -0
  78. package/dist/bridge/messages/getPage.d.ts +216 -0
  79. package/dist/bridge/messages/getPage.d.ts.map +1 -0
  80. package/dist/bridge/messages/getPage.js +33 -0
  81. package/dist/bridge/messages/getUser.d.ts +45 -0
  82. package/dist/bridge/messages/getUser.d.ts.map +1 -0
  83. package/dist/bridge/messages/getUser.js +32 -0
  84. package/dist/bridge/messages/hostToSandbox.d.ts +1089 -0
  85. package/dist/bridge/messages/hostToSandbox.d.ts.map +1 -0
  86. package/dist/bridge/messages/hostToSandbox.js +32 -0
  87. package/dist/bridge/messages/init.d.ts +209 -0
  88. package/dist/bridge/messages/init.d.ts.map +1 -0
  89. package/dist/bridge/messages/init.js +47 -0
  90. package/dist/bridge/messages/invalidHostMessage.d.ts +15 -0
  91. package/dist/bridge/messages/invalidHostMessage.d.ts.map +1 -0
  92. package/dist/bridge/messages/invalidHostMessage.js +13 -0
  93. package/dist/bridge/messages/invalidSandboxMessage.d.ts +15 -0
  94. package/dist/bridge/messages/invalidSandboxMessage.d.ts.map +1 -0
  95. package/dist/bridge/messages/invalidSandboxMessage.js +13 -0
  96. package/dist/bridge/messages/listUsers.d.ts +53 -0
  97. package/dist/bridge/messages/listUsers.d.ts.map +1 -0
  98. package/dist/bridge/messages/listUsers.js +33 -0
  99. package/dist/bridge/messages/pageChanged.d.ts +12 -0
  100. package/dist/bridge/messages/pageChanged.d.ts.map +1 -0
  101. package/dist/bridge/messages/pageChanged.js +9 -0
  102. package/dist/bridge/messages/parentChanged.d.ts +22 -0
  103. package/dist/bridge/messages/parentChanged.d.ts.map +1 -0
  104. package/dist/bridge/messages/parentChanged.js +9 -0
  105. package/dist/bridge/messages/queryDataSource.d.ts +20 -0
  106. package/dist/bridge/messages/queryDataSource.d.ts.map +1 -0
  107. package/dist/bridge/messages/queryDataSource.js +19 -0
  108. package/dist/bridge/messages/queryDataSourceResult.d.ts +90 -0
  109. package/dist/bridge/messages/queryDataSourceResult.d.ts.map +1 -0
  110. package/dist/bridge/messages/queryDataSourceResult.js +21 -0
  111. package/dist/bridge/messages/ready.d.ts +45 -0
  112. package/dist/bridge/messages/ready.d.ts.map +1 -0
  113. package/dist/bridge/messages/ready.js +37 -0
  114. package/dist/bridge/messages/resize.d.ts +12 -0
  115. package/dist/bridge/messages/resize.d.ts.map +1 -0
  116. package/dist/bridge/messages/resize.js +10 -0
  117. package/dist/bridge/messages/sandboxToHost.d.ts +410 -0
  118. package/dist/bridge/messages/sandboxToHost.d.ts.map +1 -0
  119. package/dist/bridge/messages/sandboxToHost.js +25 -0
  120. package/dist/bridge/messages/themeChanged.d.ts +11 -0
  121. package/dist/bridge/messages/themeChanged.d.ts.map +1 -0
  122. package/dist/bridge/messages/themeChanged.js +10 -0
  123. package/dist/bridge/messages/updatePage.d.ts +171 -0
  124. package/dist/bridge/messages/updatePage.d.ts.map +1 -0
  125. package/dist/bridge/messages/updatePage.js +15 -0
  126. package/dist/bridge/messages/updatePageResult.d.ts +210 -0
  127. package/dist/bridge/messages/updatePageResult.d.ts.map +1 -0
  128. package/dist/bridge/messages/updatePageResult.js +27 -0
  129. package/dist/bridge/pages/page.d.ts +600 -0
  130. package/dist/bridge/pages/page.d.ts.map +1 -0
  131. package/dist/bridge/pages/page.js +217 -0
  132. package/dist/bridge/parent.d.ts +25 -0
  133. package/dist/bridge/parent.d.ts.map +1 -0
  134. package/dist/bridge/parent.js +11 -0
  135. package/dist/bridge/pendingRequests.d.ts +14 -0
  136. package/dist/bridge/pendingRequests.d.ts.map +1 -0
  137. package/dist/bridge/pendingRequests.js +27 -0
  138. package/dist/bridge/sandboxClient.d.ts +63 -0
  139. package/dist/bridge/sandboxClient.d.ts.map +1 -0
  140. package/dist/bridge/sandboxClient.js +92 -0
  141. package/dist/bridge/theme.d.ts +4 -0
  142. package/dist/bridge/theme.d.ts.map +1 -0
  143. package/dist/bridge/theme.js +2 -0
  144. package/dist/bridge/users/user.d.ts +36 -0
  145. package/dist/bridge/users/user.d.ts.map +1 -0
  146. package/dist/bridge/users/user.js +19 -0
  147. package/dist/customBlock.d.ts +36 -0
  148. package/dist/customBlock.d.ts.map +1 -0
  149. package/dist/customBlock.js +65 -0
  150. package/dist/host/createCustomBlockHost.d.ts +34 -0
  151. package/dist/host/createCustomBlockHost.d.ts.map +1 -0
  152. package/dist/host/createCustomBlockHost.js +278 -0
  153. package/dist/host/lifecycle/initErrors.d.ts +10 -0
  154. package/dist/host/lifecycle/initErrors.d.ts.map +1 -0
  155. package/dist/host/lifecycle/initErrors.js +123 -0
  156. package/dist/host/lifecycle/ready.d.ts +8 -0
  157. package/dist/host/lifecycle/ready.d.ts.map +1 -0
  158. package/dist/host/lifecycle/ready.js +24 -0
  159. package/dist/host/lifecycle/types.d.ts +24 -0
  160. package/dist/host/lifecycle/types.d.ts.map +1 -0
  161. package/dist/host/lifecycle/types.js +1 -0
  162. package/dist/host/messages/invalidSandboxMessage.d.ts +7 -0
  163. package/dist/host/messages/invalidSandboxMessage.d.ts.map +1 -0
  164. package/dist/host/messages/invalidSandboxMessage.js +24 -0
  165. package/dist/host/messages/types.d.ts +60 -0
  166. package/dist/host/messages/types.d.ts.map +1 -0
  167. package/dist/host/messages/types.js +1 -0
  168. package/dist/host/queries/querySubscriptions.d.ts +20 -0
  169. package/dist/host/queries/querySubscriptions.d.ts.map +1 -0
  170. package/dist/host/queries/querySubscriptions.js +29 -0
  171. package/dist/host/queries/types.d.ts +9 -0
  172. package/dist/host/queries/types.d.ts.map +1 -0
  173. package/dist/host/queries/types.js +1 -0
  174. package/dist/host.d.ts +73 -0
  175. package/dist/host.d.ts.map +1 -0
  176. package/dist/host.js +42 -0
  177. package/dist/index.d.ts +37 -0
  178. package/dist/index.d.ts.map +1 -0
  179. package/dist/index.js +14 -0
  180. package/dist/init.d.ts +53 -0
  181. package/dist/init.d.ts.map +1 -0
  182. package/dist/init.js +87 -0
  183. package/dist/react/DebugMessageLog.d.ts +2 -0
  184. package/dist/react/DebugMessageLog.d.ts.map +1 -0
  185. package/dist/react/DebugMessageLog.js +22 -0
  186. package/dist/react/NotionCustomBlock.css +110 -0
  187. package/dist/react/NotionCustomBlock.d.ts +50 -0
  188. package/dist/react/NotionCustomBlock.d.ts.map +1 -0
  189. package/dist/react/NotionCustomBlock.js +81 -0
  190. package/dist/react/index.d.ts +14 -0
  191. package/dist/react/index.d.ts.map +1 -0
  192. package/dist/react/index.js +13 -0
  193. package/dist/react/standalonePreview.d.ts +2 -0
  194. package/dist/react/standalonePreview.d.ts.map +1 -0
  195. package/dist/react/standalonePreview.js +26 -0
  196. package/dist/react/useCustomBlockAutoResize.d.ts +30 -0
  197. package/dist/react/useCustomBlockAutoResize.d.ts.map +1 -0
  198. package/dist/react/useCustomBlockAutoResize.js +35 -0
  199. package/dist/react/useCustomBlockInit.d.ts +43 -0
  200. package/dist/react/useCustomBlockInit.d.ts.map +1 -0
  201. package/dist/react/useCustomBlockInit.js +60 -0
  202. package/dist/react/useDataSource.d.ts +13 -0
  203. package/dist/react/useDataSource.d.ts.map +1 -0
  204. package/dist/react/useDataSource.js +37 -0
  205. package/dist/react/useHostState.d.ts +2 -0
  206. package/dist/react/useHostState.d.ts.map +1 -0
  207. package/dist/react/useHostState.js +5 -0
  208. package/dist/react/useRuntimeState.d.ts +66 -0
  209. package/dist/react/useRuntimeState.d.ts.map +1 -0
  210. package/dist/react/useRuntimeState.js +73 -0
  211. package/dist/types.d.ts +154 -0
  212. package/dist/types.d.ts.map +1 -0
  213. package/dist/types.js +1 -0
  214. package/dist/utils.d.ts +9 -0
  215. package/dist/utils.d.ts.map +1 -0
  216. package/dist/utils.js +10 -0
  217. package/dist/version.d.ts +9 -0
  218. package/dist/version.d.ts.map +1 -0
  219. package/dist/version.js +7 -0
  220. package/docs/block-location.md +83 -0
  221. package/docs/data-sources.md +186 -0
  222. package/docs/lifecycle.md +172 -0
  223. package/docs/manifest.md +42 -0
  224. package/docs/pages.md +143 -0
  225. package/docs/users.md +92 -0
  226. package/package.json +69 -0
  227. package/src/autoResize.ts +84 -0
  228. package/src/bridge/SandboxBridge.ts +921 -0
  229. package/src/bridge/dataSources/dataSource.ts +63 -0
  230. package/src/bridge/dataSources/dataSourcePage.ts +71 -0
  231. package/src/bridge/dataSources/dataSourceValue.ts +19 -0
  232. package/src/bridge/dataSources/dateValue.ts +96 -0
  233. package/src/bridge/dataSources/errors.ts +14 -0
  234. package/src/bridge/dataSources/propertySchema.ts +186 -0
  235. package/src/bridge/dataSources/recordPointer.ts +13 -0
  236. package/src/bridge/dataSources/resolve.ts +99 -0
  237. package/src/bridge/dataSources/resolveProperty.ts +130 -0
  238. package/src/bridge/errors.ts +13 -0
  239. package/src/bridge/hostState.ts +154 -0
  240. package/src/bridge/ids.ts +58 -0
  241. package/src/bridge/incomingType.ts +19 -0
  242. package/src/bridge/loadManifest.ts +89 -0
  243. package/src/bridge/manifest.ts +53 -0
  244. package/src/bridge/messages/createPage.ts +67 -0
  245. package/src/bridge/messages/createPageResult.ts +52 -0
  246. package/src/bridge/messages/currentUserChanged.ts +14 -0
  247. package/src/bridge/messages/dataSourcesChanged.ts +18 -0
  248. package/src/bridge/messages/getPage.ts +52 -0
  249. package/src/bridge/messages/getUser.ts +48 -0
  250. package/src/bridge/messages/hostToSandbox.ts +37 -0
  251. package/src/bridge/messages/init.ts +81 -0
  252. package/src/bridge/messages/invalidHostMessage.ts +16 -0
  253. package/src/bridge/messages/invalidSandboxMessage.ts +18 -0
  254. package/src/bridge/messages/listUsers.ts +49 -0
  255. package/src/bridge/messages/pageChanged.ts +12 -0
  256. package/src/bridge/messages/parentChanged.ts +14 -0
  257. package/src/bridge/messages/queryDataSource.ts +24 -0
  258. package/src/bridge/messages/queryDataSourceResult.ts +38 -0
  259. package/src/bridge/messages/ready.ts +41 -0
  260. package/src/bridge/messages/resize.ts +13 -0
  261. package/src/bridge/messages/sandboxToHost.ts +30 -0
  262. package/src/bridge/messages/themeChanged.ts +15 -0
  263. package/src/bridge/messages/updatePage.ts +22 -0
  264. package/src/bridge/messages/updatePageResult.ts +49 -0
  265. package/src/bridge/pages/page.ts +281 -0
  266. package/src/bridge/parent.ts +27 -0
  267. package/src/bridge/pendingRequests.ts +28 -0
  268. package/src/bridge/sandboxClient.ts +137 -0
  269. package/src/bridge/theme.ts +5 -0
  270. package/src/bridge/users/user.ts +31 -0
  271. package/src/css.d.ts +1 -0
  272. package/src/customBlock.ts +102 -0
  273. package/src/host/createCustomBlockHost.ts +392 -0
  274. package/src/host/lifecycle/initErrors.ts +132 -0
  275. package/src/host/lifecycle/ready.ts +36 -0
  276. package/src/host/lifecycle/types.ts +28 -0
  277. package/src/host/messages/invalidSandboxMessage.ts +38 -0
  278. package/src/host/messages/types.ts +67 -0
  279. package/src/host/queries/querySubscriptions.ts +52 -0
  280. package/src/host/queries/types.ts +16 -0
  281. package/src/host.ts +167 -0
  282. package/src/index.ts +115 -0
  283. package/src/init.ts +143 -0
  284. package/src/react/DebugMessageLog.tsx +30 -0
  285. package/src/react/NotionCustomBlock.css +110 -0
  286. package/src/react/NotionCustomBlock.tsx +151 -0
  287. package/src/react/index.ts +28 -0
  288. package/src/react/standalonePreview.ts +28 -0
  289. package/src/react/useCustomBlockAutoResize.ts +46 -0
  290. package/src/react/useCustomBlockInit.ts +91 -0
  291. package/src/react/useDataSource.ts +47 -0
  292. package/src/react/useHostState.ts +9 -0
  293. package/src/react/useRuntimeState.ts +85 -0
  294. package/src/types.ts +175 -0
  295. package/src/utils.ts +13 -0
  296. package/src/version.ts +8 -0
  297. package/vite-plugin/index.d.ts +46 -0
  298. package/vite-plugin/index.js +115 -0
@@ -0,0 +1,154 @@
1
+ import type { NotionCollectionSchema } from "./bridge/dataSources/dataSource.js";
2
+ import type { NotionDataSourcePage, NotionDataSourcePageUpdateInput, NotionDataSourcePageUpdateResult } from "./bridge/dataSources/dataSourcePage.js";
3
+ import type { NotionPropertySchema } from "./bridge/dataSources/propertySchema.js";
4
+ import type { CustomBlockErrorInfo } from "./bridge/errors.js";
5
+ import type { NotionDataSourceId } from "./bridge/ids.js";
6
+ import type { NotionCreatePagePosition } from "./bridge/messages/createPage.js";
7
+ import type { CustomBlockCreatePageErrorInfo } from "./bridge/messages/createPageResult.js";
8
+ import type { CustomBlockGetPageErrorInfo } from "./bridge/messages/getPage.js";
9
+ import type { CustomBlockGetUserErrorInfo } from "./bridge/messages/getUser.js";
10
+ import type { CustomBlockListUsersErrorInfo } from "./bridge/messages/listUsers.js";
11
+ import type { CustomBlockQueryDataSourceErrorInfo } from "./bridge/messages/queryDataSourceResult.js";
12
+ import type { CustomBlockUpdatePageErrorInfo } from "./bridge/messages/updatePageResult.js";
13
+ import type { NotionPage, NotionPageCover, NotionPageIcon, NotionPageId, NotionPagePropertyInputMap, NotionPagePropertyWriteMap } from "./bridge/pages/page.js";
14
+ import type { NotionUser, NotionUserList } from "./bridge/users/user.js";
15
+ export type { NotionDataSourceId, NotionSpaceId } from "./bridge/ids.js";
16
+ export type { NotionPageId } from "./bridge/pages/page.js";
17
+ export type { NotionUser, NotionUserId, NotionUserList, } from "./bridge/users/user.js";
18
+ export type { CustomBlockCreatePageErrorInfo, CustomBlockErrorInfo, CustomBlockGetPageErrorInfo, CustomBlockGetUserErrorInfo, CustomBlockListUsersErrorInfo, CustomBlockQueryDataSourceErrorInfo, CustomBlockUpdatePageErrorInfo, NotionDataSourcePageUpdateInput, NotionDataSourcePageUpdateResult, };
19
+ /**
20
+ * Return shape of `useDataSource`.
21
+ *
22
+ * - `items` — the rows the host has returned so far. Empty until the first response arrives.
23
+ * - `isLoading` — `true` while a query is in flight.
24
+ * - `hasMore` — `true` if the host indicated more rows are available beyond the current page.
25
+ * - `error` — structured error information if the most recent query failed.
26
+ */
27
+ export type UseDataSourceResult = {
28
+ items: NotionDataSourcePage[];
29
+ /**
30
+ * Collection/data-source schema for the bound Notion data source, including raw property
31
+ * schemas. Undefined when the semantic data-source key has not been bound.
32
+ */
33
+ collectionSchema?: NotionCollectionSchema;
34
+ /**
35
+ * Per-property schemas keyed by raw property ID, including the four synthetic built-ins
36
+ * (`created_time`, `last_edited_time`, `created_by`, `last_edited_by`).
37
+ */
38
+ propertySchemasById: {
39
+ [propertyId: string]: NotionPropertySchema;
40
+ };
41
+ /**
42
+ * Per-property schemas keyed by user-defined keys from the data source's `propertyIdsByKey`.
43
+ * Built-ins are NOT included here. Keys mapped to `undefined` indicate a declared-but-unbound
44
+ * slot.
45
+ */
46
+ propertySchemasByKey: {
47
+ [key: string]: NotionPropertySchema | undefined;
48
+ };
49
+ isLoading: boolean;
50
+ hasMore: boolean;
51
+ error?: CustomBlockQueryDataSourceErrorInfo;
52
+ };
53
+ export type UseDataSourceOptions = {
54
+ /**
55
+ * Maximum number of rows to request from the host. Defaults to 20.
56
+ */
57
+ limit?: number;
58
+ };
59
+ /**
60
+ * Parent reference accepted by `sdk.pages.create`. Mirrors Notion's public `POST /v1/pages`
61
+ * parent shape; see https://developers.notion.com/reference/data-source.
62
+ *
63
+ * - `page_id`: Create a child page under the given Notion page.
64
+ * - `data_source_id`: Create a row inside the given Notion data source (aka the internal
65
+ * collection). The public API's `data_source_id` is the same UUID as the `collectionPointer.id`
66
+ * exposed in `dataSources`, so either value works here.
67
+ * - `data_source_key`: Create a row inside the data source that the custom block was configured with
68
+ * under this semantic key. The SDK resolves the key to a `data_source_id` locally before
69
+ * sending the request to the host.
70
+ */
71
+ export type CreatePageParent = {
72
+ type: "page_id";
73
+ page_id: NotionPageId;
74
+ } | {
75
+ type: "data_source_id";
76
+ data_source_id: NotionDataSourceId;
77
+ } | {
78
+ type: "data_source_key";
79
+ key: string;
80
+ };
81
+ /**
82
+ * Input accepted by `sdk.pages.create`. Mirrors the Notion public API `POST /v1/pages` API.
83
+ */
84
+ export type CreatePageInput = {
85
+ parent: CreatePageParent;
86
+ properties: NotionPagePropertyInputMap;
87
+ icon?: NotionPageIcon;
88
+ cover?: NotionPageCover;
89
+ position?: NotionCreatePagePosition;
90
+ };
91
+ /**
92
+ * The result of a `sdk.pages.create` API call.
93
+ */
94
+ export type CreatePageResult = {
95
+ status: "success";
96
+ /** The newly created page. */
97
+ page: NotionPage;
98
+ } | {
99
+ status: "error";
100
+ error: CustomBlockCreatePageErrorInfo;
101
+ };
102
+ /**
103
+ * Input accepted by `sdk.pages.update`.
104
+ *
105
+ * `properties` is keyed by raw Notion property ID. To update a row with configured
106
+ * custom-block property keys, use the `update` helper on pages returned from
107
+ * `useDataSource`.
108
+ */
109
+ export type UpdatePageInput = {
110
+ pageId: NotionPageId;
111
+ properties?: NotionPagePropertyWriteMap;
112
+ icon?: NotionPageIcon;
113
+ cover?: NotionPageCover;
114
+ archived?: boolean;
115
+ };
116
+ /**
117
+ * Result of `sdk.pages.get`.
118
+ */
119
+ export type GetPageResult = {
120
+ status: "success";
121
+ page: NotionPage;
122
+ } | {
123
+ status: "error";
124
+ error: CustomBlockGetPageErrorInfo;
125
+ };
126
+ /**
127
+ * Result of `sdk.pages.update` / `sdk.pages.delete`.
128
+ */
129
+ export type UpdatePageResult = {
130
+ status: "success";
131
+ page: NotionPage;
132
+ } | {
133
+ status: "error";
134
+ error: CustomBlockUpdatePageErrorInfo;
135
+ };
136
+ export type ListUsersInput = {
137
+ startCursor?: string;
138
+ pageSize?: number;
139
+ };
140
+ export type ListUsersResult = {
141
+ status: "success";
142
+ list: NotionUserList;
143
+ } | {
144
+ status: "error";
145
+ error: CustomBlockListUsersErrorInfo;
146
+ };
147
+ export type GetUserResult = {
148
+ status: "success";
149
+ user: NotionUser;
150
+ } | {
151
+ status: "error";
152
+ error: CustomBlockGetUserErrorInfo;
153
+ };
154
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../../Users/nsarkar/work/custom-blocks/sdk/src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Internal helpers shared across the SDK.
3
+ */
4
+ /**
5
+ * Throws an error when an unexpected value is encountered. This is used to ensure all code paths
6
+ * are covered when using discriminated unions.
7
+ */
8
+ export declare function unreachable(value: never): never;
9
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../../../Users/nsarkar/work/custom-blocks/sdk/src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAI/C"}
package/dist/utils.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Internal helpers shared across the SDK.
3
+ */
4
+ /**
5
+ * Throws an error when an unexpected value is encountered. This is used to ensure all code paths
6
+ * are covered when using discriminated unions.
7
+ */
8
+ export function unreachable(value) {
9
+ throw new Error(`[notion-custom-sdk] Unexpected value encountered: ${JSON.stringify(value)}`);
10
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Runtime SDK package version. Sent over the bridge for host-side analytics only. Business logic
3
+ * should compare against the bridge protocol version instead of this value.
4
+ *
5
+ * This checked-in value intentionally stays generic for local development. The SDK publish build
6
+ * overwrites the compiled runtime module with package.json's semver before publishing.
7
+ */
8
+ export declare const NCBLOCK_SDK_VERSION: string;
9
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../../../../../../Users/nsarkar/work/custom-blocks/sdk/src/version.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,EAAE,MAAgB,CAAA"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Runtime SDK package version. Sent over the bridge for host-side analytics only.
3
+ * Business logic should compare against the bridge protocol version instead of this value.
4
+ *
5
+ * WARNING: Generated during SDK publish. Do not edit in the published package.
6
+ */
7
+ export const NCBLOCK_SDK_VERSION = "0.0.58"
@@ -0,0 +1,83 @@
1
+ # Block Location & Theme
2
+
3
+ Every custom block runs inside a larger Notion document. These hooks expose the block's own ID, the container it sits inside, the nearest enclosing page ID, and how the surrounding Notion app is currently presented (e.g. light vs. dark theme).
4
+
5
+ ## API
6
+
7
+ The host bridge carries these values as explicit `blockId`, `parent`, and `page` fields.
8
+
9
+ ### `useBlockId()`
10
+
11
+ Returns the custom block's own ID.
12
+
13
+ Re-renders when the host sends a block location update.
14
+
15
+ ```ts
16
+ function useBlockId(): NotionBlockId;
17
+ ```
18
+
19
+ For non-React renderers, use `customBlock.getBlockId()` after `initCustomBlock()` resolves:
20
+
21
+ ```ts
22
+ await initCustomBlock();
23
+
24
+ const blockId = customBlock.getBlockId();
25
+ ```
26
+
27
+ ### `useParent()`
28
+
29
+ Returns the block's parent in the document tree.
30
+
31
+ Re-renders when the host sends a block location update.
32
+
33
+ ```ts
34
+ function useParent(): NotionParent;
35
+
36
+ type NotionParent =
37
+ | { type: "page_id"; page_id: string } // inline custom block under a page
38
+ | { type: "block_id"; block_id: NotionBlockId } // inline custom block under a toggle/column/callout/...
39
+ | { type: "data_source_id"; data_source_id: string } // custom block backing a custom collection view
40
+ | { type: "workspace"; workspace: true }; // top-level block parented by a team / workspace
41
+ ```
42
+
43
+ For non-React renderers, use `customBlock.getParent()` after `initCustomBlock()` resolves.
44
+
45
+ ### `usePage()`
46
+
47
+ Returns the nearest enclosing `page` / `collection_view_page` ancestor.
48
+
49
+ Re-renders when the host sends a block location update.
50
+
51
+ ```ts
52
+ function usePage(): { id: NotionPageId };
53
+ ```
54
+
55
+ For non-React renderers, use `customBlock.getPage()` after `initCustomBlock()` resolves.
56
+
57
+ ### `useTheme()`
58
+
59
+ Returns the host's current theme.
60
+
61
+ Re-renders on every `themeChanged` message.
62
+
63
+ ```ts
64
+ function useTheme(): NotionTheme; // "light" | "dark"
65
+ ```
66
+
67
+ For non-React renderers, use `customBlock.getTheme()`:
68
+
69
+ ```ts
70
+ await initCustomBlock();
71
+
72
+ const theme = customBlock.getTheme();
73
+ ```
74
+
75
+ ```tsx
76
+ import { usePage, useTheme } from "@notionhq/custom-blocks";
77
+
78
+ export function Header() {
79
+ const page = usePage();
80
+ const theme = useTheme();
81
+ return <header data-theme={theme}>Page: {page.id}</header>;
82
+ }
83
+ ```
@@ -0,0 +1,186 @@
1
+ # Data sources
2
+
3
+ A custom block declares its **data sources** — semantic keys like `people` or `tasks` — in `custom_blocks.json`.
4
+
5
+ Data source mapping - resolving keys to ids - is stored on the block itself. This can be read/written programmatically using the `ncblock` CLI (try `npx ncblock --help`) or in the Notion UI.
6
+
7
+ At runtime, your code references the semantic key and the SDK handles the lookup for you. Use `useDataSource(key)` for the rows themselves (it also exposes the resolved schema), and `useManifest()` when you need the declared data-source keys and their declarations (e.g. picking a default key, or rendering a key switcher). For non-React renderers, `customBlock.getManifest()` exposes the same manifest, but row querying is currently only exposed through the React `useDataSource` hook.
8
+
9
+ ## Pages within a data source
10
+
11
+ Each row returned by `useDataSource` is a `NotionDataSourcePage` — `{ id, propertiesById, propertiesByKey, update }`. Read property values through either of the two views:
12
+
13
+ - `propertiesByKey[key]` — keyed by the semantic property keys you declared in the manifest.
14
+ - `propertiesById[propertyId]` — keyed by the raw Notion property ID.
15
+
16
+ The four built-ins (`created_time`, `last_edited_time`, `created_by`, `last_edited_by`) are always present in `propertiesById` (and `collectionSchema.propertiesById`), never in the `*ByKey` views — they don't have semantic keys.
17
+
18
+ ### Updating a row
19
+
20
+ Each page carries its own `update` helper:
21
+
22
+ ```ts
23
+ await row.update({
24
+ properties: {
25
+ score: { type: "number", number: 8 }, // semantic key
26
+ },
27
+ icon: { type: "emoji", emoji: "✅" },
28
+ });
29
+ ```
30
+
31
+ Because the helper is bound to its data source, you can write property values keyed by **either** semantic keys or raw IDs — the SDK resolves them before sending the request. The input and result shapes are `NotionDataSourcePageUpdateInput` and `NotionDataSourcePageUpdateResult`.
32
+
33
+ Use `row.update(...)` whenever you already have a row in hand. For pages you don't have a row for (e.g. you only have a `pageId`), drop down to the top-level [`pages` API](./pages.md) — it covers create / get / update / delete and accepts raw property IDs only.
34
+
35
+ ## API
36
+
37
+ ### `useDataSource(key, options?)`
38
+
39
+ ```ts
40
+ function useDataSource(key: string, options?: { limit?: number }): UseDataSourceResult;
41
+
42
+ type UseDataSourceResult = {
43
+ items: NotionDataSourcePage[];
44
+ collectionSchema?: NotionCollectionSchema;
45
+ propertySchemasById: { [propertyId: string]: NotionPropertySchema };
46
+ propertySchemasByKey: { [key: string]: NotionPropertySchema | undefined };
47
+ isLoading: boolean;
48
+ hasMore: boolean;
49
+ error?: CustomBlockQueryDataSourceErrorInfo;
50
+ };
51
+ ```
52
+
53
+ Reads the data source mapped to `key`. `limit` defaults to 20 and is capped at 999. To show more rows, keep the desired limit in your own component state and pass the larger value back into `useDataSource(key, { limit })`. `propertySchemasByKey` is `undefined` for declared-but-unbound slots. When the host reports a query failure, `error` is `{ code, message, isRetryable }` with `code` narrowed to `CustomBlockQueryDataSourceErrorCode`.
54
+
55
+ ### `useManifest()`
56
+
57
+ ```ts
58
+ function useManifest(): CustomBlockManifest | null;
59
+ ```
60
+
61
+ Returns the author-declared manifest loaded from `custom_blocks.json` — the semantic data-source keys plus their declared `name`, `description`, and property declarations. `null` when the block ships no manifest. This is the configuration the block _declared_, not host-resolved bindings; use `useDataSource(key)` for rows and resolved schema. Handy for enumerating declared keys:
62
+
63
+ ```tsx
64
+ const manifest = useManifest();
65
+ const keys = Object.keys(manifest?.dataSources ?? {});
66
+ const activeKey = keys[0] ?? "default";
67
+ ```
68
+
69
+ ### `customBlock.getManifest()`
70
+
71
+ ```ts
72
+ function customBlock.getManifest(): CustomBlockManifest | null;
73
+ ```
74
+
75
+ Framework-neutral getter for the same manifest returned by `useManifest()`. The manifest is static for the lifetime of the sandbox, so there is nothing to subscribe to.
76
+
77
+ ```ts
78
+ await initCustomBlock();
79
+
80
+ renderManifest(customBlock.getManifest());
81
+ ```
82
+
83
+ `customBlock` does not yet expose a non-React equivalent of `useDataSource(key)`: querying rows, tracking `isLoading` / `hasMore`, and using row-level `update` helpers still require the React hook.
84
+
85
+ ## Example: querying a data source
86
+
87
+ A typical data-driven view picks a key, calls `useDataSource`, schema-checks the rows, and surfaces a setup hint when the mapped collection is missing the expected fields. Trimmed from `templates/radar-chart`:
88
+
89
+ ```tsx
90
+ import type { NotionDataSourcePage } from "@notionhq/custom-blocks";
91
+ import { useDataSource } from "@notionhq/custom-blocks/react";
92
+
93
+ const KEY = "people";
94
+
95
+ function isComplete(item: NotionDataSourcePage): boolean {
96
+ return (
97
+ typeof item.propertiesByKey.name === "string" &&
98
+ typeof item.propertiesByKey.score === "number" &&
99
+ Number.isFinite(item.propertiesByKey.score)
100
+ );
101
+ }
102
+
103
+ export function ScoreList() {
104
+ const [limit, setLimit] = useState(20);
105
+ const { items, isLoading, hasMore, error } = useDataSource(KEY, { limit });
106
+
107
+ if (error) return <div role="alert">Couldn't load: {error.message}</div>;
108
+ if (isLoading && items.length === 0) return <div>Loading…</div>;
109
+
110
+ const ready = items.filter(isComplete);
111
+ if (ready.length === 0) {
112
+ return (
113
+ <div>
114
+ Map a data source with key <code>{KEY}</code> exposing <code>name</code>{" "}
115
+ (text) and <code>score</code> (number).
116
+ </div>
117
+ );
118
+ }
119
+
120
+ return (
121
+ <div>
122
+ <ul>
123
+ {ready.map((item) => (
124
+ <li key={item.id}>
125
+ {String(item.propertiesByKey.name)} —{" "}
126
+ {Number(item.propertiesByKey.score)}
127
+ </li>
128
+ ))}
129
+ </ul>
130
+ {hasMore ? (
131
+ <button type="button" onClick={() => setLimit(limit + 20)} disabled={isLoading}>
132
+ {isLoading ? "Loading…" : "Load more"}
133
+ </button>
134
+ ) : null}
135
+ </div>
136
+ );
137
+ }
138
+ ```
139
+
140
+ ## Types
141
+
142
+ ### Rows & values
143
+
144
+ - `NotionDataSource` — a resolved data source: semantic key, `collectionSchema`, `propertyIdsByKey`, `propertySchemasById`.
145
+ - `NotionDataSourcePage` — a single row exposed to app code: `{ id, propertiesById, propertiesByKey, update }`.
146
+ - `NotionDataSourceValue` — the discriminated union of values that can appear inside `propertiesById[propertyId]`. Date values branch into the `NotionDateValue` union below.
147
+ - `NotionDataSourcePageUpdateInput` / `NotionDataSourcePageUpdateResult` — input and result for the per-page `update` helper.
148
+ - `UseDataSourceOptions` — options accepted by `useDataSource`, currently `{ limit?: number }`.
149
+
150
+ ### Property schemas
151
+
152
+ - `NotionPropertySchema` — schema for a single property (type plus type-specific config like `select` options).
153
+ - `NotionPropertyType` — string-literal union of every supported property type.
154
+ - `NOTION_PROPERTY_TYPES` — runtime list of those literals (handy for switch coverage and validation).
155
+ - `NotionPropertyOption` — a single `select` / `multi_select` / `status` option (`{ id, name, color }`).
156
+ - `NotionPropertyColor` — the color literal used by options and groups.
157
+ - `NotionStatusGroup` — the `status` property's "To do / In progress / Done" grouping.
158
+ - `NotionDualProperty` — properties that have both a primary and a secondary axis (e.g. `unique_id` prefix + number).
159
+ - `NotionBuiltinPropertyId` — string-literal union of the four synthetic property IDs (`created_time`, `last_edited_time`, `created_by`, `last_edited_by`).
160
+ - `NOTION_BUILTIN_PROPERTY_IDS` — runtime list of the four built-in IDs.
161
+
162
+ ### Collection schema & pointers
163
+
164
+ - `NotionCollectionSchema` — host-supplied schema for the bound collection, including raw property schemas.
165
+ - `NotionRecordPointer` — `{ id, table }`. Generic reference to any Notion record (page, block, collection row). Exported for convenience; `useDataSource` and the `pages` API don't take one as input.
166
+
167
+ ### IDs
168
+
169
+ Branded string types — they're plain strings at runtime but TypeScript distinguishes them.
170
+
171
+ - `NotionDataSourceId`
172
+ - `NotionSpaceId`
173
+
174
+ ### Date values
175
+
176
+ Returned wherever a date / date-range value appears (e.g. inside `propertiesByKey` for a `date` property). All-day values use `NotionDate*` shapes; values with a time component use `NotionDateTime*`.
177
+
178
+ - `NotionDateValue` — discriminated union covering every date-shaped value below.
179
+ - `NotionDate`
180
+ - `NotionDateRange`
181
+ - `NotionDateTime`
182
+ - `NotionDateTimeRange`
183
+ - `NotionDateReminder`
184
+ - `NotionDateTimeReminder`
185
+ - `NotionTimeReminder`
186
+ - `NotionNoReminder`
@@ -0,0 +1,172 @@
1
+ # Lifecycle
2
+
3
+ The SDK ↔ host handshake, the React wrapper that runs it, and the auto-resize hook that keeps the iframe in sync with your content.
4
+
5
+ ## Handshake
6
+
7
+ `initCustomBlock()` posts `ready` to `window.parent` and awaits the host's `init` (theme, block ID/parent/page ID, current user, and `dataSources: { bindings }` keyed by semantic data-source key, which the SDK resolves against the manifest). The promise resolves with the normalized initial state, captured in `CustomBlockInitial` — `await` it before mounting React so hooks always see populated state.
8
+
9
+ - Default `timeoutMs` is 15000; rejects with `CustomBlockInitError` code `init_timeout` if the host doesn't respond.
10
+ - In a top-level browser tab (no parent frame), rejects with `NotInIframeError` code `not_in_iframe`. `<NotionCustomBlock>` catches this, seeds placeholders, and renders `children` behind a warning banner so dev-time previews still work.
11
+ - After init, `*Changed` events (e.g. `themeChanged`, `parentChanged`, `dataSourcesChanged`) push updates and the relevant hooks re-render.
12
+ - `initCustomBlock` is idempotent; subsequent calls return the same promise.
13
+
14
+ ## Sizing
15
+
16
+ The host owns width and height. Inside the iframe, `100vh` ≠ a screen and there's no meaningful "device width" — only iframe width. Layouts must reflow from a phone column to a desktop block.
17
+
18
+ - **Self-sizing content** is the default — `<NotionCustomBlock>` measures `#root` and posts `resize` messages so the iframe tracks your content. Pass `autoResize={false}` for full-bleed views, or to drive `useCustomBlockAutoResize` yourself.
19
+ - Prefer container queries (`@container`) over viewport queries.
20
+
21
+ ## API
22
+
23
+ Import framework-neutral APIs from `@notionhq/custom-blocks`; import React hooks and components from `@notionhq/custom-blocks/react`. The runtime APIs below assume `initCustomBlock()` has resolved — initialized-only hooks and `customBlock` getters throw if called before that. Inside `<NotionCustomBlock>` (or past the `isLoaded` gate of `useCustomBlockInit`), single-value hooks return non-nullable values.
24
+
25
+ ### `<NotionCustomBlock>`
26
+
27
+ ```ts
28
+ type NotionCustomBlockProps = InitCustomBlockOptions & {
29
+ children: ReactNode;
30
+ fallback?: ReactNode;
31
+ errorFallback?: ReactNode | ((error: Error) => ReactNode);
32
+ autoResize?: boolean; // defaults to true
33
+ };
34
+ ```
35
+
36
+ Top-level wrapper. Runs the handshake, gates `children`, and (by default) drives auto-resize. `fallback` replaces the loading view (default `null`); `errorFallback` replaces the inline `<p role="alert">` shown if init rejects. `timeoutMs` flows through to `initCustomBlock`. Pass `autoResize={false}` for full-bleed views or to call `useCustomBlockAutoResize` yourself.
37
+
38
+ ### `useCustomBlockInit(opts?)`
39
+
40
+ ```ts
41
+ function useCustomBlockInit(
42
+ opts?: InitCustomBlockOptions,
43
+ ): UseCustomBlockInitResult;
44
+
45
+ type UseCustomBlockInitResult =
46
+ | { isLoaded: false; error: undefined }
47
+ | { isLoaded: false; error: CustomBlockInitFailure }
48
+ | { isLoaded: true; error: undefined; initial: CustomBlockInitial };
49
+ ```
50
+
51
+ React wrapper around `initCustomBlock` for templates that prefer not to use top-level `await`. Multiple components calling it share the same handshake.
52
+
53
+ ```tsx
54
+ function Root() {
55
+ const init = useCustomBlockInit();
56
+ if (init.error) return <p role="alert">Init failed: {init.error.message}</p>;
57
+ if (!init.isLoaded) return null;
58
+ return <App />;
59
+ }
60
+ ```
61
+
62
+ ### `initCustomBlock(opts?)`
63
+
64
+ ```ts
65
+ function initCustomBlock(
66
+ opts?: InitCustomBlockOptions,
67
+ ): Promise<CustomBlockInitial>;
68
+
69
+ type InitCustomBlockOptions = { timeoutMs?: number };
70
+ ```
71
+
72
+ 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`). If the host replies with an init error, the promise rejects with `CustomBlockInitError`.
73
+
74
+ ### `CustomBlockInitError`
75
+
76
+ ```ts
77
+ class CustomBlockInitError extends Error {
78
+ code: CustomBlockInitErrorCode;
79
+ isRetryable: boolean;
80
+ }
81
+
82
+ type CustomBlockErrorInfo<TCode extends string = string> = {
83
+ code: TCode;
84
+ message: string;
85
+ isRetryable: boolean;
86
+ };
87
+
88
+ type CustomBlockInitErrorInfo = CustomBlockErrorInfo<CustomBlockInitErrorCode>;
89
+
90
+ type CustomBlockInitErrorCode =
91
+ | "no_ready"
92
+ | "invalid_ready"
93
+ | "manifest_unavailable"
94
+ | "manifest_invalid"
95
+ | "invalid_protocol_version"
96
+ | "unsupported_protocol_version"
97
+ | "context_unavailable"
98
+ | "current_user_unavailable"
99
+ | "missing_data_source_binding"
100
+ | "data_source_unavailable"
101
+ | "missing_property_binding"
102
+ | "invalid_property_binding"
103
+ | "not_in_iframe"
104
+ | "init_timeout"
105
+ | "unknown_error";
106
+ ```
107
+
108
+ Thrown when the host rejects initialization instead of returning the initial theme, block location, current user, and data sources. `CustomBlockInitErrorInfo` uses the same structured error payload as every other API, with `code` narrowed to `CustomBlockInitErrorCode`. Use `error instanceof CustomBlockInitError`, `error.code`, and `error.isRetryable` to branch on host-reported setup failures.
109
+
110
+ Runtime APIs use the same `CustomBlockErrorInfo<TCode>` envelope with their own code unions, such as `CustomBlockCreatePageErrorCode`, `CustomBlockUpdatePageErrorCode`, and `CustomBlockQueryDataSourceErrorCode`.
111
+
112
+ The public API-specific runtime aliases are `CustomBlockCreatePageErrorInfo`, `CustomBlockGetPageErrorInfo`, `CustomBlockGetUserErrorInfo`, `CustomBlockListUsersErrorInfo`, `CustomBlockQueryDataSourceErrorInfo`, and `CustomBlockUpdatePageErrorInfo`. Their `code` fields are narrowed by `CustomBlockCreatePageErrorCode`, `CustomBlockGetPageErrorCode`, `CustomBlockGetUserErrorCode`, `CustomBlockListUsersErrorCode`, `CustomBlockQueryDataSourceErrorCode`, and `CustomBlockUpdatePageErrorCode`. Shared categories include `CustomBlockPropertyErrorCode` / `CustomBlockPropertyErrorInfo` and `CustomBlockDataSourceResolutionErrorCode` / `CustomBlockDataSourceResolutionErrorInfo`.
113
+
114
+ ### `customBlock`
115
+
116
+ Framework-neutral runtime APIs for renderers that do not use React hooks. `customBlock.getState()` returns a `CustomBlockState` snapshot that hides internal query cache details. Initialized-only getters (`getTheme`, `getBlockId`, `getParent`, `getPage`, and `getCurrentUser`) throw until `initCustomBlock()` resolves. `getManifest()` is not gated on init — it returns the declared manifest (or `null`) regardless.
117
+
118
+ `customBlock` covers runtime state and sizing. Row querying still goes through `useDataSource`, while imperative APIs such as `pages.*` and `users.*` are already framework-neutral functions.
119
+
120
+ ```ts
121
+ await initCustomBlock();
122
+
123
+ const theme = customBlock.getTheme();
124
+ const unsubscribe = customBlock.subscribe(() => {
125
+ render(customBlock.getState());
126
+ });
127
+ ```
128
+
129
+ 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:
130
+
131
+ ```ts
132
+ const stopAutoResize = customBlock.autoResize({
133
+ target: document.getElementById("root"),
134
+ });
135
+
136
+ // Later, if your renderer unmounts:
137
+ stopAutoResize();
138
+ ```
139
+
140
+ ### `NotInIframeError`
141
+
142
+ Thrown when `initCustomBlock` is called in a top-level tab (no parent frame). It has `code: "not_in_iframe"` and `isRetryable: false`. `<NotionCustomBlock>` catches it and falls back to a standalone preview with a warning banner; direct callers can `instanceof NotInIframeError` to apply their own policy.
143
+
144
+ ### `useCustomBlockAutoResize({ enabled? })`
145
+
146
+ ```ts
147
+ function useCustomBlockAutoResize(args?: { enabled?: boolean }): void;
148
+ ```
149
+
150
+ React wrapper around `customBlock.autoResize({ target: document.getElementById("root") })`. Measures `#root`'s height and posts `resize` messages, deduping unchanged values. `<NotionCustomBlock>` runs this for you — only call it directly when you want to drive `enabled` yourself (e.g. a debug toggle), and pair with `autoResize={false}` so it doesn't run twice. The target must have intrinsic height; do not give it `height: 100%` or `100vh`.
151
+
152
+ ```tsx
153
+ <NotionCustomBlock autoResize={false}>
154
+ <App />
155
+ </NotionCustomBlock>;
156
+
157
+ function App() {
158
+ const [enabled, setEnabled] = useState(true);
159
+ useCustomBlockAutoResize({ enabled });
160
+ return <div>…</div>;
161
+ }
162
+ ```
163
+
164
+ ## Debug console
165
+
166
+ Press `\` while focused in a custom block to toggle a debug overlay that replaces the block's children with a `<pre>` log of every `postMessage` sent and received over the bridge. Each line is formatted as:
167
+
168
+ ```
169
+ [ISO timestamp] sent/received: {"type":"ready", …}
170
+ ```
171
+
172
+ The log is intentionally plain — no filtering or decoration — so it can be copied and pasted directly to a local coding agent for debugging.