@notionhq/custom-blocks 0.1.1 → 0.1.3
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/HOST.md +29 -18
- package/README.md +56 -15
- package/dist/bridge/SandboxBridge.d.ts.map +1 -1
- package/dist/bridge/SandboxBridge.js +11 -0
- package/dist/bridge/contrast.d.ts +5 -0
- package/dist/bridge/contrast.d.ts.map +1 -0
- package/dist/bridge/contrast.js +3 -0
- package/dist/bridge/hostState.d.ts +3 -0
- package/dist/bridge/hostState.d.ts.map +1 -1
- package/dist/bridge/loadManifest.d.ts +9 -8
- package/dist/bridge/loadManifest.d.ts.map +1 -1
- package/dist/bridge/loadManifest.js +6 -14
- package/dist/bridge/manifest.d.ts +3 -8
- package/dist/bridge/manifest.d.ts.map +1 -1
- package/dist/bridge/manifest.js +0 -8
- package/dist/bridge/messages/contrastModeChanged.d.ts +8 -0
- package/dist/bridge/messages/contrastModeChanged.d.ts.map +1 -0
- package/dist/bridge/messages/contrastModeChanged.js +7 -0
- package/dist/bridge/messages/hostToSandbox.d.ts +4 -0
- package/dist/bridge/messages/hostToSandbox.d.ts.map +1 -1
- package/dist/bridge/messages/hostToSandbox.js +2 -0
- package/dist/bridge/messages/init.d.ts +4 -1
- package/dist/bridge/messages/init.d.ts.map +1 -1
- package/dist/bridge/messages/init.js +6 -1
- package/dist/customBlock.d.ts +4 -0
- package/dist/customBlock.d.ts.map +1 -1
- package/dist/customBlock.js +5 -0
- package/dist/host/createCustomBlockHost.d.ts +2 -0
- package/dist/host/createCustomBlockHost.d.ts.map +1 -1
- package/dist/host/createCustomBlockHost.js +22 -0
- package/dist/host/lifecycle/types.d.ts +2 -0
- package/dist/host/lifecycle/types.d.ts.map +1 -1
- package/dist/host.d.ts +4 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/init.d.ts +7 -6
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +20 -10
- package/dist/react/NotionTokenScope.d.ts +10 -0
- package/dist/react/NotionTokenScope.d.ts.map +1 -0
- package/dist/react/NotionTokenScope.js +11 -0
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -1
- package/dist/react/standalonePreview.d.ts.map +1 -1
- package/dist/react/standalonePreview.js +2 -0
- package/dist/react/useRuntimeState.d.ts +11 -0
- package/dist/react/useRuntimeState.d.ts.map +1 -1
- package/dist/react/useRuntimeState.js +12 -0
- package/dist/styles/nds.css +1 -0
- package/dist/version.js +1 -1
- package/docs/block-location.md +17 -3
- package/docs/deployment.md +41 -0
- package/docs/lifecycle.md +3 -2
- package/docs/vite-plugin.md +5 -29
- package/package.json +2 -1
- package/src/bridge/SandboxBridge.ts +12 -0
- package/src/bridge/contrast.ts +6 -0
- package/src/bridge/hostState.ts +3 -0
- package/src/bridge/loadManifest.ts +8 -17
- package/src/bridge/manifest.ts +3 -9
- package/src/bridge/messages/contrastModeChanged.ts +12 -0
- package/src/bridge/messages/hostToSandbox.ts +2 -0
- package/src/bridge/messages/init.ts +6 -1
- package/src/customBlock.ts +13 -1
- package/src/host/createCustomBlockHost.ts +27 -0
- package/src/host/lifecycle/types.ts +3 -0
- package/src/host.ts +4 -0
- package/src/index.ts +1 -0
- package/src/init.ts +22 -10
- package/src/react/NotionTokenScope.tsx +25 -0
- package/src/react/index.ts +5 -0
- package/src/react/standalonePreview.ts +2 -0
- package/src/react/useRuntimeState.ts +17 -0
- package/src/styles/nds.css +1 -0
- package/src/styles/nds.css.metadata.json +6 -0
- package/vite-plugin/index.d.ts +2 -2
- package/vite-plugin/index.js +8 -7
package/HOST.md
CHANGED
|
@@ -28,6 +28,7 @@ const host = createCustomBlockHost({
|
|
|
28
28
|
minBridgeProtocolVersion: 3,
|
|
29
29
|
initialState: {
|
|
30
30
|
theme,
|
|
31
|
+
contrastMode,
|
|
31
32
|
blockId,
|
|
32
33
|
parent,
|
|
33
34
|
page,
|
|
@@ -43,6 +44,9 @@ const host = createCustomBlockHost({
|
|
|
43
44
|
}),
|
|
44
45
|
},
|
|
45
46
|
});
|
|
47
|
+
|
|
48
|
+
// Live state pushes are emitted only after initResult.success.
|
|
49
|
+
host.setContrastMode("high");
|
|
46
50
|
```
|
|
47
51
|
|
|
48
52
|
Use it when the generic protocol loop is helpful. Hosts with more specialized runtime needs can keep using the schemas and message types directly.
|
|
@@ -69,6 +73,8 @@ Initialization has three steps. A sandbox-generated `initializationId` identifie
|
|
|
69
73
|
{ type: "connect", initializationId, status: "success", bridgeProtocolVersion, sdkVersion, manifest: { /* ... */ } }
|
|
70
74
|
```
|
|
71
75
|
|
|
76
|
+
The `manifest` property is optional for `connect` messages. If provided, hosts can ignore it and still return a different `manifest` in the `init` message. This sandbox-defined manifest option is included for locally-hosted custom blocks.
|
|
77
|
+
|
|
72
78
|
If `connect.status` is `"error"`, reply with `init.error` using the same `initializationId` and forward its complete error payload unchanged.
|
|
73
79
|
|
|
74
80
|
#### 2. Host sends `init`
|
|
@@ -77,11 +83,11 @@ The host sends exactly one `init` containing its authoritative manifest. It may
|
|
|
77
83
|
use the manifest from `connect` as input, but the manifest it returns may differ;
|
|
78
84
|
the sandbox applies the host's version.
|
|
79
85
|
|
|
80
|
-
`init.success` carries the chosen manifest together with the initial
|
|
86
|
+
`init.success` carries the chosen manifest together with the initial display and contrast modes, block context, current user, and data-source bindings:
|
|
81
87
|
|
|
82
88
|
```ts
|
|
83
89
|
// host → sandbox
|
|
84
|
-
{ type: "init", initializationId, status: "success", theme, blockId, parent, page: { id, parent }, currentUser, manifest, dataSources: { bindings } }
|
|
90
|
+
{ type: "init", initializationId, status: "success", theme, contrastMode, blockId, parent, page: { id, parent }, currentUser, manifest, dataSources: { bindings } }
|
|
85
91
|
```
|
|
86
92
|
|
|
87
93
|
If the host cannot initialize the block, send `init.error` instead:
|
|
@@ -109,11 +115,12 @@ Use `CustomBlockInitResultErrorCode` / `CustomBlockInitResultErrorInfo` to const
|
|
|
109
115
|
|
|
110
116
|
Wait for `initResult.success` before uncovering the iframe or sending live updates. `initResult.error` is terminal.
|
|
111
117
|
|
|
112
|
-
After `initResult.success`, narrower messages update live state without re-running the handshake — `themeChanged`, `parentChanged`, `pageChanged`, `currentUserChanged`, and `dataSourcesChanged`. Each replaces just its slice of state:
|
|
118
|
+
After `initResult.success`, narrower messages update live state without re-running the handshake — `themeChanged`, `contrastModeChanged`, `parentChanged`, `pageChanged`, `currentUserChanged`, and `dataSourcesChanged`. Each replaces just its slice of state:
|
|
113
119
|
|
|
114
120
|
```ts
|
|
115
121
|
// host → sandbox, any time after init
|
|
116
122
|
{ type: "themeChanged", theme }
|
|
123
|
+
{ type: "contrastModeChanged", contrastMode }
|
|
117
124
|
{ type: "parentChanged", parent }
|
|
118
125
|
{ type: "pageChanged", page: { id, parent } }
|
|
119
126
|
{ type: "dataSourcesChanged", dataSources: { bindings } }
|
|
@@ -125,13 +132,15 @@ After `initResult.success`, narrower messages update live state without re-runni
|
|
|
125
132
|
|
|
126
133
|
If the sandbox reports a version below the host's supported minimum, reply with `init.status: "error"` and `error.code: "unsupported_protocol_version"`. If the reported version is structurally invalid (not a positive integer — e.g. `0`, negative, fractional, `NaN`, or `Infinity`), reply with `error.code: "invalid_protocol_version"` instead.
|
|
127
134
|
|
|
135
|
+
The additive `contrastMode: "standard" | "high"` field defaults to `"standard"` when omitted, so hosts that predate contrast support can still initialize current sandboxes. After `initResult.success`, hosts may send `contrastModeChanged` without inspecting the reported protocol version; sandboxes that do not recognize it will NACK or ignore it.
|
|
136
|
+
|
|
128
137
|
### Conventions
|
|
129
138
|
|
|
130
139
|
One-shot RPC request/result pairs use a string `requestId`. The sender tracks pending requests by id, and the receiver echoes the id on the matching result. Lifecycle and one-way messages use neither request nor subscription identity.
|
|
131
140
|
|
|
132
141
|
`queryDataSource` is a long-lived subscription rather than a one-shot RPC. It and every `queryDataSourceResult` update use only a stable string `subscriptionId`. The host may push additional results for that subscription whenever its data changes; the sandbox ignores results for subscriptions it no longer recognizes.
|
|
133
142
|
|
|
134
|
-
Hosts key query state by `subscriptionId`, not `dataSourceId`: multiple subscriptions may target the same data source, and a data-source refresh must update all of them. A new request with an existing `subscriptionId` replaces that subscription, so hosts must suppress an older handler result that resolves after the replacement. Subscription lifetime ends when the host/bridge is torn down; protocol
|
|
143
|
+
Hosts key query state by `subscriptionId`, not `dataSourceId`: multiple subscriptions may target the same data source, and a data-source refresh must update all of them. A new request with an existing `subscriptionId` replaces that subscription, so hosts must suppress an older handler result that resolves after the replacement. Subscription lifetime ends when the host/bridge is torn down; the current protocol has no unsubscribe message.
|
|
135
144
|
|
|
136
145
|
Both sides validate inbound messages with valibot schemas. Failed parses are logged and NACKed with `invalidHostMessage` or `invalidSandboxMessage`. Never answer a NACK with another NACK.
|
|
137
146
|
|
|
@@ -168,23 +177,24 @@ Schemas:
|
|
|
168
177
|
- `notionDataSourcePageBridgeSchema`
|
|
169
178
|
- `notionPageIdSchema`
|
|
170
179
|
- `notionParentSchema`
|
|
180
|
+
- `notionContrastModeSchema` — validates `NotionContrastMode` (`"standard" | "high"`).
|
|
171
181
|
|
|
172
182
|
## Sandbox → host messages
|
|
173
183
|
|
|
174
184
|
Messages sent from the sandbox to the host. Parse `window` `message` events with `sandboxToHostMessageSchema` (or per-message schemas). The type / schema column points to the payload shape.
|
|
175
185
|
|
|
176
|
-
| Wire type | Type / schema | Behavior
|
|
177
|
-
| -------------------- | --------------------------------------------------------- |
|
|
178
|
-
| `connect` | `ConnectMessage` / `connectMessageSchema` | Starts the one-shot handshake with a sandbox-generated `initializationId`; carries `bridgeProtocolVersion`, `sdkVersion`, and the manifest.
|
|
179
|
-
| `initResult` | `InitResultMessage` / `initResultMessageSchema` | Echoes the handshake `initializationId` and reports whether the sandbox applied `init.success`.
|
|
180
|
-
| `queryDataSource` | `QueryDataSourceMessage` / `queryDataSourceMessageSchema` | Starts or updates a `subscriptionId`-keyed subscription for rows in a raw `dataSourceId`. Later results for the same subscription replace its current value.
|
|
181
|
-
| `createPage` | `CreatePageMessage` / `createPageMessageSchema` | `requestId`-keyed page creation with properties and optional position; parent is `page_id` or `data_source_id`. Create-time icon and cover are not supported.
|
|
182
|
-
| `getPage` | `GetPageMessage` / `getPageMessageSchema` | `requestId`-keyed page fetch by page id.
|
|
183
|
-
| `updatePage` | `UpdatePageMessage` / `updatePageMessageSchema` | `requestId`-keyed patch (properties, icon, cover, or `archived`).
|
|
184
|
-
| `getUser` | `GetUserMessage` / `getUserMessageSchema` | `requestId`-keyed user fetch by user id.
|
|
185
|
-
| `listUsers` | `ListUsersMessage` / `listUsersMessageSchema` | `requestId`-keyed user list with optional `startCursor` and `pageSize`.
|
|
186
|
-
| `resize` | `ResizeMessage` / `resizeMessageSchema` | Latest measured content height from auto-resize.
|
|
187
|
-
| `invalidHostMessage` | `InvalidHostMessage` / `invalidHostMessageSchema` | Sandbox-side NACK for a host message it could not parse.
|
|
186
|
+
| Wire type | Type / schema | Behavior |
|
|
187
|
+
| -------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
188
|
+
| `connect` | `ConnectMessage` / `connectMessageSchema` | Starts the one-shot handshake with a sandbox-generated `initializationId`; carries `bridgeProtocolVersion`, `sdkVersion`, and the manifest. |
|
|
189
|
+
| `initResult` | `InitResultMessage` / `initResultMessageSchema` | Echoes the handshake `initializationId` and reports whether the sandbox applied `init.success`. |
|
|
190
|
+
| `queryDataSource` | `QueryDataSourceMessage` / `queryDataSourceMessageSchema` | Starts or updates a `subscriptionId`-keyed subscription for rows in a raw `dataSourceId`. Later results for the same subscription replace its current value. |
|
|
191
|
+
| `createPage` | `CreatePageMessage` / `createPageMessageSchema` | `requestId`-keyed page creation with properties and optional position; parent is `page_id` or `data_source_id`. Create-time icon and cover are not supported. |
|
|
192
|
+
| `getPage` | `GetPageMessage` / `getPageMessageSchema` | `requestId`-keyed page fetch by page id. |
|
|
193
|
+
| `updatePage` | `UpdatePageMessage` / `updatePageMessageSchema` | `requestId`-keyed patch (properties, icon, cover, or `archived`). |
|
|
194
|
+
| `getUser` | `GetUserMessage` / `getUserMessageSchema` | `requestId`-keyed user fetch by user id. |
|
|
195
|
+
| `listUsers` | `ListUsersMessage` / `listUsersMessageSchema` | `requestId`-keyed user list with optional `startCursor` and `pageSize`. |
|
|
196
|
+
| `resize` | `ResizeMessage` / `resizeMessageSchema` | Latest measured content height from auto-resize. |
|
|
197
|
+
| `invalidHostMessage` | `InvalidHostMessage` / `invalidHostMessageSchema` | Sandbox-side NACK for a host message it could not parse. |
|
|
188
198
|
|
|
189
199
|
`SandboxToHostMessage` / `sandboxToHostMessageSchema` is the discriminated union over all of the above.
|
|
190
200
|
|
|
@@ -196,17 +206,18 @@ Messages sent from the host to the sandbox. Same `{ wire type, type / schema, be
|
|
|
196
206
|
| ----------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
197
207
|
| `init` | `InitMessage` / `initMessageSchema` | Sent exactly once in response to `connect`; echoes its `initializationId` and carries the success/error payload described under [Lifecycle](#lifecycle). |
|
|
198
208
|
| `themeChanged` | `ThemeChangedMessage` / `themeChangedMessageSchema` | Replaces the current theme. |
|
|
209
|
+
| `contrastModeChanged` | `ContrastModeChangedMessage` / `contrastModeChangedMessageSchema` | Replaces contrast mode without changing display mode or other state. |
|
|
199
210
|
| `parentChanged` | `ParentChangedMessage` / `parentChangedMessageSchema` | Replaces the custom block parent without disturbing theme, block ID, page ID, user, or query state. |
|
|
200
211
|
| `pageChanged` | `PageChangedMessage` / `pageChangedMessageSchema` | Replaces the nearest page ancestor without disturbing theme, block ID, parent, user, or query state. |
|
|
201
212
|
| `currentUserChanged` | `CurrentUserChangedMessage` / `currentUserChangedMessageSchema` | Replaces the current viewer record. Send when any viewer field changes (name, avatar, email). |
|
|
202
213
|
| `dataSourcesChanged` | `DataSourcesChangedMessage` / `dataSourcesChangedMessageSchema` | Replaces data-source bindings; the sandbox preserves cached query state for keys that still exist and drops removed keys. |
|
|
203
|
-
| `queryDataSourceResult` | `QueryDataSourceResultMessage` / `queryDataSourceResultMessageSchema` | `subscriptionId`-keyed update with `status: "success"`, `items`, and `hasMore`, or `status: "error"` and `error`.
|
|
214
|
+
| `queryDataSourceResult` | `QueryDataSourceResultMessage` / `queryDataSourceResultMessageSchema` | `subscriptionId`-keyed update with `status: "success"`, `items`, and `hasMore`, or `status: "error"` and `error`. |
|
|
204
215
|
| `createPageResult` | `CreatePageResultMessage` / `createPageResultMessageSchema` | `requestId`-keyed page response with `status: "success"` or `status: "error"`. |
|
|
205
216
|
| `getPageResult` | `GetPageResultMessage` / `getPageResultMessageSchema` | Same success/error shape as `createPageResult`. |
|
|
206
217
|
| `updatePageResult` | `UpdatePageResultMessage` / `updatePageResultMessageSchema` | Same success/error shape as `createPageResult`. |
|
|
207
218
|
| `getUserResult` | `GetUserResultMessage` / `getUserResultMessageSchema` | `requestId`-keyed user response with `status: "success"` or `status: "error"`. |
|
|
208
219
|
| `listUsersResult` | `ListUsersResultMessage` / `listUsersResultMessageSchema` | Same success/error shape as `getUserResult`. |
|
|
209
|
-
| `invalidSandboxMessage` | `InvalidSandboxMessage` / `invalidSandboxMessageSchema` | Host-side NACK for a sandbox message it could not parse.
|
|
220
|
+
| `invalidSandboxMessage` | `InvalidSandboxMessage` / `invalidSandboxMessageSchema` | Host-side NACK for a sandbox message it could not parse. |
|
|
210
221
|
|
|
211
222
|
`HostToSandboxMessage` / `hostToSandboxMessageSchema` is the discriminated union over all of the above.
|
|
212
223
|
|
package/README.md
CHANGED
|
@@ -1,55 +1,96 @@
|
|
|
1
1
|
# @notionhq/custom-blocks
|
|
2
2
|
|
|
3
3
|
> [!NOTE]
|
|
4
|
-
>
|
|
4
|
+
> **Pre-release.** Custom blocks are in private alpha. Breaking changes may land at any time.
|
|
5
5
|
|
|
6
6
|
SDK for building Notion custom blocks.
|
|
7
7
|
|
|
8
|
-
A custom block runs as a sandboxed `<iframe>` inside
|
|
9
|
-
|
|
10
|
-
> **Pre-release.** Breaking changes may land at any time before 1.0.
|
|
8
|
+
A custom block runs as a sandboxed `<iframe>` inside the Notion app that has no direct access to the internet. The only channel between your block and Notion is a local `postMessage` bridge. This library implements the sandbox side of the bridge protocol and wraps it in a framework-neutral TypeScript API (`@notionhq/custom-blocks`) and typed React hooks (`@notionhq/custom-blocks/react`).
|
|
11
9
|
|
|
12
10
|
## Quick start
|
|
13
11
|
|
|
12
|
+
Declare your custom block along with the rest of your worker definition:
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
// src/index.ts
|
|
16
|
+
import { Worker } from "@notionhq/workers";
|
|
17
|
+
|
|
18
|
+
const worker = new Worker();
|
|
19
|
+
export default worker;
|
|
20
|
+
|
|
21
|
+
worker.customBlock("hello", {
|
|
22
|
+
path: "./blocks/hello",
|
|
23
|
+
command: "npx vite build",
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
In the block's entry point defined above, wrap your React code in `<NotionCustomBlock>` so the SDK connects with Notion before anything renders:
|
|
28
|
+
|
|
14
29
|
```tsx
|
|
15
|
-
// src/index.tsx
|
|
16
|
-
import
|
|
30
|
+
// blocks/hello/src/index.tsx
|
|
31
|
+
import "@notionhq/custom-blocks/nds.css";
|
|
32
|
+
import {
|
|
33
|
+
NotionCustomBlock,
|
|
34
|
+
NotionTokenScope,
|
|
35
|
+
} from "@notionhq/custom-blocks/react";
|
|
17
36
|
import ReactDOM from "react-dom/client";
|
|
18
37
|
import { App } from "./App";
|
|
19
38
|
|
|
20
39
|
ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
21
40
|
<NotionCustomBlock>
|
|
22
|
-
<
|
|
41
|
+
<NotionTokenScope>
|
|
42
|
+
<App />
|
|
43
|
+
</NotionTokenScope>
|
|
23
44
|
</NotionCustomBlock>,
|
|
24
45
|
);
|
|
25
46
|
```
|
|
26
47
|
|
|
48
|
+
Hooks can then read live content directly from Notion:
|
|
49
|
+
|
|
27
50
|
```tsx
|
|
28
|
-
// src/App.tsx
|
|
29
|
-
import { useBlockId
|
|
51
|
+
// blocks/hello/src/App.tsx
|
|
52
|
+
import { useBlockId } from "@notionhq/custom-blocks/react";
|
|
30
53
|
|
|
31
54
|
export function App() {
|
|
32
55
|
const blockId = useBlockId();
|
|
33
|
-
|
|
34
|
-
|
|
56
|
+
return <div className="app">Hello from {blockId}.</div>;
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```css
|
|
61
|
+
.app {
|
|
62
|
+
color: var(--content-primary);
|
|
63
|
+
background: var(--bg-base);
|
|
64
|
+
padding: var(--spacing-12);
|
|
65
|
+
border: 1px solid var(--border-primary);
|
|
66
|
+
border-radius: var(--radius-12);
|
|
35
67
|
}
|
|
36
68
|
```
|
|
37
69
|
|
|
38
70
|
`<NotionCustomBlock>` runs the SDK ↔ host handshake (`connect` → `init` → `initResult`) and only mounts `children` once it resolves. Inside the wrapper, every hook returns non-nullable values — there's no separate gating component to write. It also runs `useCustomBlockAutoResize` for you by default; pass `autoResize={false}` to opt out.
|
|
39
71
|
|
|
72
|
+
## Notion design tokens
|
|
73
|
+
|
|
74
|
+
The optional `@notionhq/custom-blocks/nds.css` stylesheet provides the colors, spacing, typography, borders, and other design tokens used by Notion. Import it once, then put token-consuming UI inside `<NotionTokenScope>` as shown above.
|
|
75
|
+
|
|
76
|
+
`<NotionTokenScope>` applies the display and contrast modes selected by the host, so variables such as `--content-primary` and `--bg-base` stay in sync with Notion automatically. Hosts that do not provide a contrast mode use standard contrast.
|
|
77
|
+
|
|
78
|
+
`NotionTokenScopeProps` has one required `children` prop.
|
|
79
|
+
|
|
80
|
+
The stylesheet is scoped rather than installed globally. Render portals inside `<NotionTokenScope>`, or wrap the portal container in another scope. Framework-neutral renderers can read the current appearance with `customBlock.getTheme()` and `customBlock.getContrastMode()`; see [Block Location & Appearance](./docs/block-location.md).
|
|
81
|
+
|
|
40
82
|
## Reference
|
|
41
83
|
|
|
42
84
|
API surface, one page per category. Import framework-neutral APIs from `@notionhq/custom-blocks`; import React hooks and components from `@notionhq/custom-blocks/react`. Hover docs in your editor cover the per-field detail; these pages cover usage shape and the gotchas.
|
|
43
85
|
|
|
44
86
|
- [`docs/lifecycle.md`](./docs/lifecycle.md) — `<NotionCustomBlock>`, `useCustomBlockInit`, `initCustomBlock`, `customBlock.autoResize`, `NotInIframeError`, `useCustomBlockAutoResize`. The handshake, the React wrapper, sizing.
|
|
45
|
-
- [`docs/block-location.md`](./docs/block-location.md) — `useBlockId`, `useParent`, `usePage`, `useTheme`. Where the block sits
|
|
87
|
+
- [`docs/block-location.md`](./docs/block-location.md) — `useBlockId`, `useParent`, `usePage`, `useTheme`, and `useContrastMode`. Where the block sits and how to read the host's appearance.
|
|
46
88
|
- [`docs/data-sources.md`](./docs/data-sources.md) — `useDataSource`, `useManifest`, `customBlock.getManifest`, the row, property, and date-value types, plus a worked example.
|
|
47
89
|
- [`docs/pages.md`](./docs/pages.md) — `pages.create / get / update / delete`, parent variants (including the recommended `data_source_key`), property input shapes.
|
|
48
90
|
- [`docs/users.md`](./docs/users.md) — `users.list / get`, the `NotionUser` shape, paging.
|
|
49
91
|
- [`docs/errors.md`](./docs/errors.md) — request results, error format, error codes, retries, and initialization failures.
|
|
50
|
-
- [`docs/
|
|
51
|
-
|
|
52
|
-
Declare the block source and data-source schema in the worker file with `worker.customBlock(...)`, then build and deploy it with `ntn workers deploy`. The worker definition is the source of truth; the iframe frontend uses semantic keys from that definition with APIs such as `useDataSource`. For local previews, the Vite plugin serves the block's `custom_blocks.json` — see [`docs/vite-plugin.md`](./docs/vite-plugin.md).
|
|
92
|
+
- [`docs/deployment.md`](./docs/deployment.md) — worker-backed deploys, localhost self-hosted fallback, where the manifest comes from.
|
|
93
|
+
- [`docs/vite-plugin.md`](./docs/vite-plugin.md) — the `notionCustomBlock()` Vite plugin.
|
|
53
94
|
|
|
54
95
|
## Forbidden APIs
|
|
55
96
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SandboxBridge.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/SandboxBridge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"SandboxBridge.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/SandboxBridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
2
|
import { unreachable } from "../utils.js";
|
|
3
3
|
import { CUSTOM_BLOCKS_SDK_VERSION } from "../version.js";
|
|
4
|
+
import { DEFAULT_CONTRAST_MODE } from "./contrast.js";
|
|
4
5
|
import { resolveDataSources } from "./dataSources/resolve.js";
|
|
5
6
|
import { resolvePropertyWriteMapForDataSource } from "./dataSources/resolveProperty.js";
|
|
6
7
|
import { createEmptyDataSourceQueryState, } from "./hostState.js";
|
|
@@ -19,6 +20,7 @@ export class SandboxBridge {
|
|
|
19
20
|
this.hostState = {
|
|
20
21
|
status: "uninitialized",
|
|
21
22
|
theme: "light",
|
|
23
|
+
contrastMode: DEFAULT_CONTRAST_MODE,
|
|
22
24
|
};
|
|
23
25
|
this.listeners = new Set();
|
|
24
26
|
this.messageLog = [];
|
|
@@ -109,6 +111,14 @@ export class SandboxBridge {
|
|
|
109
111
|
this.notify();
|
|
110
112
|
return;
|
|
111
113
|
}
|
|
114
|
+
case "contrastModeChanged": {
|
|
115
|
+
this.hostState = {
|
|
116
|
+
...hostState,
|
|
117
|
+
contrastMode: message.contrastMode,
|
|
118
|
+
};
|
|
119
|
+
this.notify();
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
112
122
|
case "parentChanged": {
|
|
113
123
|
this.hostState = {
|
|
114
124
|
...hostState,
|
|
@@ -394,6 +404,7 @@ export class SandboxBridge {
|
|
|
394
404
|
this.hostState = {
|
|
395
405
|
status: "initialized",
|
|
396
406
|
theme: message.theme,
|
|
407
|
+
contrastMode: message.contrastMode,
|
|
397
408
|
blockId,
|
|
398
409
|
parent,
|
|
399
410
|
page,
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
export declare const notionContrastModeSchema: v.PicklistSchema<["standard", "high"], undefined>;
|
|
3
|
+
export type NotionContrastMode = v.InferOutput<typeof notionContrastModeSchema>;
|
|
4
|
+
export declare const DEFAULT_CONTRAST_MODE: NotionContrastMode;
|
|
5
|
+
//# sourceMappingURL=contrast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contrast.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/contrast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAE5B,eAAO,MAAM,wBAAwB,mDAAmC,CAAA;AACxE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAE/E,eAAO,MAAM,qBAAqB,EAAE,kBAA+B,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { NotionContrastMode } from "./contrast.js";
|
|
1
2
|
import type { NotionDataSource } from "./dataSources/dataSource.js";
|
|
2
3
|
import type { NotionDataSourcePage, NotionDataSourcePageBridge, NotionDataSourcePageUpdateInput, NotionDataSourcePageUpdateResult } from "./dataSources/dataSourcePage.js";
|
|
3
4
|
import type { NotionPropertySchema } from "./dataSources/propertySchema.js";
|
|
@@ -12,10 +13,12 @@ export type CustomBlockHostState = UninitializedHostState | InitializedHostState
|
|
|
12
13
|
export type UninitializedHostState = {
|
|
13
14
|
status: "uninitialized";
|
|
14
15
|
theme: NotionTheme;
|
|
16
|
+
contrastMode: NotionContrastMode;
|
|
15
17
|
};
|
|
16
18
|
export type InitializedHostState = {
|
|
17
19
|
status: "initialized";
|
|
18
20
|
theme: NotionTheme;
|
|
21
|
+
contrastMode: NotionContrastMode;
|
|
19
22
|
blockId: NotionBlockId;
|
|
20
23
|
parent: NotionParent;
|
|
21
24
|
page: CustomBlockPage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hostState.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/hostState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,KAAK,EACX,oBAAoB,EACpB,0BAA0B,EAC1B,+BAA+B,EAC/B,gCAAgC,EAChC,MAAM,iCAAiC,CAAA;AAExC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAC7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACxD,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,qCAAqC,CAAA;AAC9F,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,GAAG,oBAAoB,CAAA;AAEhF,MAAM,MAAM,sBAAsB,GAAG;IACpC,MAAM,EAAE,eAAe,CAAA;IACvB,KAAK,EAAE,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"hostState.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/hostState.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CustomBlockErrorInfo } from "./errors.js";
|
|
2
2
|
import { type CustomBlockManifest } from "./manifest.js";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
type CustomBlockConnectErrorCode = "manifest_unavailable" | "manifest_invalid" | (string & {});
|
|
4
|
+
type CustomBlockConnectError = CustomBlockErrorInfo<CustomBlockConnectErrorCode>;
|
|
5
5
|
export type ManifestLoadResult = {
|
|
6
6
|
manifest: CustomBlockManifest | null;
|
|
7
7
|
error?: undefined;
|
|
@@ -10,11 +10,12 @@ export type ManifestLoadResult = {
|
|
|
10
10
|
error: CustomBlockConnectError;
|
|
11
11
|
};
|
|
12
12
|
/**
|
|
13
|
-
* Attempts to load
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
13
|
+
* Attempts to load the custom block's optional self-hosted manifest, co-located with the bundle at
|
|
14
|
+
* `/custom_blocks.json`. This is to support local development where the block is served from a
|
|
15
|
+
* local dev server.
|
|
16
|
+
*
|
|
17
|
+
* It is up to the host to decide whether to use this manifest or provide its own persisted manifest.
|
|
18
18
|
*/
|
|
19
|
-
export declare function
|
|
19
|
+
export declare function attemptToLoadSelfHostedManifest(): Promise<ManifestLoadResult>;
|
|
20
|
+
export {};
|
|
20
21
|
//# sourceMappingURL=loadManifest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadManifest.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/loadManifest.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAAE,KAAK,mBAAmB,EAAkB,MAAM,eAAe,CAAA;AAIxE,
|
|
1
|
+
{"version":3,"file":"loadManifest.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/loadManifest.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,EAAE,KAAK,mBAAmB,EAAkB,MAAM,eAAe,CAAA;AAIxE,KAAK,2BAA2B,GAC7B,sBAAsB,GACtB,kBAAkB,GAClB,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEhB,KAAK,uBAAuB,GAAG,oBAAoB,CAAC,2BAA2B,CAAC,CAAA;AAEhF,MAAM,MAAM,kBAAkB,GAC3B;IACA,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAA;IACpC,KAAK,CAAC,EAAE,SAAS,CAAA;CAChB,GACD;IACA,QAAQ,EAAE,IAAI,CAAA;IACd,KAAK,EAAE,uBAAuB,CAAA;CAC7B,CAAA;AAEJ;;;;;;GAMG;AACH,wBAAsB,+BAA+B,IAAI,OAAO,CAAC,kBAAkB,CAAC,CA0DnF"}
|
|
@@ -2,21 +2,13 @@ import * as v from "valibot";
|
|
|
2
2
|
import { manifestSchema } from "./manifest.js";
|
|
3
3
|
const MANIFEST_URL = "custom_blocks.json";
|
|
4
4
|
/**
|
|
5
|
-
* Attempts to load
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Attempts to load the custom block's optional self-hosted manifest, co-located with the bundle at
|
|
6
|
+
* `/custom_blocks.json`. This is to support local development where the block is served from a
|
|
7
|
+
* local dev server.
|
|
8
|
+
*
|
|
9
|
+
* It is up to the host to decide whether to use this manifest or provide its own persisted manifest.
|
|
10
10
|
*/
|
|
11
|
-
export async function
|
|
12
|
-
if (typeof fetch !== "function") {
|
|
13
|
-
const message = `No fetch API available; cannot load ${MANIFEST_URL}.`;
|
|
14
|
-
console.warn(`[custom-blocks-sdk] ${message}`);
|
|
15
|
-
return {
|
|
16
|
-
manifest: null,
|
|
17
|
-
error: { code: "manifest_unavailable", message, isRetryable: true },
|
|
18
|
-
};
|
|
19
|
-
}
|
|
11
|
+
export async function attemptToLoadSelfHostedManifest() {
|
|
20
12
|
let response;
|
|
21
13
|
try {
|
|
22
14
|
response = await fetch(MANIFEST_URL, { credentials: "omit" });
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
|
-
/**
|
|
3
|
-
* User-authored manifest declaring the data sources the custom block expects.
|
|
4
|
-
* Lives at `custom_blocks.json` in the project root. The sandbox may send it in
|
|
5
|
-
* `connect`, and the host returns the authoritative manifest in `init`. The
|
|
6
|
-
* `notionCustomBlock` Vite plugin from
|
|
7
|
-
* `@notionhq/custom-blocks/vite` wires the JSON file into the dev server and
|
|
8
|
-
* the build output.
|
|
9
|
-
*/
|
|
10
2
|
/**
|
|
11
3
|
* Decorative icon attached to a manifest data source. Mirrors the
|
|
12
4
|
* `emoji` / `external` icon variants the public Notion API uses, so the host
|
|
@@ -62,5 +54,8 @@ export declare const manifestSchema: v.ObjectSchema<{
|
|
|
62
54
|
}, undefined>, undefined>, {}>;
|
|
63
55
|
}, undefined>, undefined>;
|
|
64
56
|
}, undefined>;
|
|
57
|
+
/**
|
|
58
|
+
* Manifest declaring the data sources required by a custom block.
|
|
59
|
+
*/
|
|
65
60
|
export type CustomBlockManifest = v.InferOutput<typeof manifestSchema>;
|
|
66
61
|
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAG5B
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAG5B;;;;GAIG;AACH,eAAO,MAAM,kBAAkB;;;;;;0BAS7B,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAEnE,eAAO,MAAM,sBAAsB;;;;aAIjC,CAAA;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAE3E,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;aAKnC,CAAA;AAEF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,wBAAwB,CAAC,CAAA;AAE/E,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;aAGzB,CAAA;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,cAAc,CAAC,CAAA"}
|
package/dist/bridge/manifest.js
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
2
|
import { notionPropertyTypeSchema } from "./dataSources/propertySchema.js";
|
|
3
|
-
/**
|
|
4
|
-
* User-authored manifest declaring the data sources the custom block expects.
|
|
5
|
-
* Lives at `custom_blocks.json` in the project root. The sandbox may send it in
|
|
6
|
-
* `connect`, and the host returns the authoritative manifest in `init`. The
|
|
7
|
-
* `notionCustomBlock` Vite plugin from
|
|
8
|
-
* `@notionhq/custom-blocks/vite` wires the JSON file into the dev server and
|
|
9
|
-
* the build output.
|
|
10
|
-
*/
|
|
11
3
|
/**
|
|
12
4
|
* Decorative icon attached to a manifest data source. Mirrors the
|
|
13
5
|
* `emoji` / `external` icon variants the public Notion API uses, so the host
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
/** Message sent by the host when contrast changes after initialization. */
|
|
3
|
+
export declare const contrastModeChangedMessageSchema: v.ObjectSchema<{
|
|
4
|
+
readonly type: v.LiteralSchema<"contrastModeChanged", undefined>;
|
|
5
|
+
readonly contrastMode: v.PicklistSchema<["standard", "high"], undefined>;
|
|
6
|
+
}, undefined>;
|
|
7
|
+
export type ContrastModeChangedMessage = v.InferOutput<typeof contrastModeChangedMessageSchema>;
|
|
8
|
+
//# sourceMappingURL=contrastModeChanged.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contrastModeChanged.d.ts","sourceRoot":"","sources":["../../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/messages/contrastModeChanged.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAG5B,2EAA2E;AAC3E,eAAO,MAAM,gCAAgC;;;aAG3C,CAAA;AAEF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,WAAW,CACrD,OAAO,gCAAgC,CACvC,CAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
import { notionContrastModeSchema } from "../contrast.js";
|
|
3
|
+
/** Message sent by the host when contrast changes after initialization. */
|
|
4
|
+
export const contrastModeChangedMessageSchema = v.object({
|
|
5
|
+
type: v.literal("contrastModeChanged"),
|
|
6
|
+
contrastMode: notionContrastModeSchema,
|
|
7
|
+
});
|
|
@@ -7,6 +7,7 @@ export declare const hostToSandboxMessageSchema: v.VariantSchema<"type", [v.Vari
|
|
|
7
7
|
readonly initializationId: v.StringSchema<undefined>;
|
|
8
8
|
readonly status: v.LiteralSchema<"success", undefined>;
|
|
9
9
|
readonly theme: v.PicklistSchema<["light", "dark"], undefined>;
|
|
10
|
+
readonly contrastMode: v.OptionalSchema<v.PicklistSchema<["standard", "high"], undefined>, "standard" | "high">;
|
|
10
11
|
readonly blockId: v.CustomSchema<import("../ids.js").NotionBlockId, v.ErrorMessage<v.CustomIssue> | undefined>;
|
|
11
12
|
readonly parent: v.VariantSchema<"type", [v.ObjectSchema<{
|
|
12
13
|
readonly type: v.LiteralSchema<"page_id", undefined>;
|
|
@@ -231,6 +232,9 @@ export declare const hostToSandboxMessageSchema: v.VariantSchema<"type", [v.Vari
|
|
|
231
232
|
}, undefined>], undefined>, v.ObjectSchema<{
|
|
232
233
|
readonly type: v.LiteralSchema<"themeChanged", undefined>;
|
|
233
234
|
readonly theme: v.PicklistSchema<["light", "dark"], undefined>;
|
|
235
|
+
}, undefined>, v.ObjectSchema<{
|
|
236
|
+
readonly type: v.LiteralSchema<"contrastModeChanged", undefined>;
|
|
237
|
+
readonly contrastMode: v.PicklistSchema<["standard", "high"], undefined>;
|
|
234
238
|
}, undefined>, v.ObjectSchema<{
|
|
235
239
|
readonly type: v.LiteralSchema<"parentChanged", undefined>;
|
|
236
240
|
readonly parent: v.VariantSchema<"type", [v.ObjectSchema<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hostToSandbox.d.ts","sourceRoot":"","sources":["../../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/messages/hostToSandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"hostToSandbox.d.ts","sourceRoot":"","sources":["../../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/messages/hostToSandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAgB5B;;GAEG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAerC,CAAA;AAEF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,WAAW,CAC/C,OAAO,0BAA0B,CACjC,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
|
+
import { contrastModeChangedMessageSchema } from "./contrastModeChanged.js";
|
|
2
3
|
import { createPageResultMessageSchema } from "./createPageResult.js";
|
|
3
4
|
import { currentUserChangedMessageSchema } from "./currentUserChanged.js";
|
|
4
5
|
import { dataSourcesChangedMessageSchema } from "./dataSourcesChanged.js";
|
|
@@ -18,6 +19,7 @@ import { updatePageResultMessageSchema } from "./updatePageResult.js";
|
|
|
18
19
|
export const hostToSandboxMessageSchema = v.variant("type", [
|
|
19
20
|
initMessageSchema,
|
|
20
21
|
themeChangedMessageSchema,
|
|
22
|
+
contrastModeChangedMessageSchema,
|
|
21
23
|
parentChangedMessageSchema,
|
|
22
24
|
pageChangedMessageSchema,
|
|
23
25
|
currentUserChangedMessageSchema,
|
|
@@ -24,13 +24,16 @@ export declare class CustomBlockInitializationError extends Error implements Cus
|
|
|
24
24
|
/**
|
|
25
25
|
* Initialization message sent by the host to the sandbox exactly once, in response to the
|
|
26
26
|
* sandbox's `connect` message. The sandbox echoes `initializationId` in `initResult`. After
|
|
27
|
-
* successful initialization, live updates flow through narrower messages
|
|
27
|
+
* successful initialization, live updates flow through narrower messages
|
|
28
|
+
* (`themeChanged`, `contrastModeChanged`, `parentChanged`, `pageChanged`,
|
|
29
|
+
* `dataSourcesChanged`).
|
|
28
30
|
*/
|
|
29
31
|
export declare const initMessageSchema: v.VariantSchema<"status", [v.ObjectSchema<{
|
|
30
32
|
readonly type: v.LiteralSchema<"init", undefined>;
|
|
31
33
|
readonly initializationId: v.StringSchema<undefined>;
|
|
32
34
|
readonly status: v.LiteralSchema<"success", undefined>;
|
|
33
35
|
readonly theme: v.PicklistSchema<["light", "dark"], undefined>;
|
|
36
|
+
readonly contrastMode: v.OptionalSchema<v.PicklistSchema<["standard", "high"], undefined>, "standard" | "high">;
|
|
34
37
|
readonly blockId: v.CustomSchema<import("../ids.js").NotionBlockId, v.ErrorMessage<v.CustomIssue> | undefined>;
|
|
35
38
|
readonly parent: v.VariantSchema<"type", [v.ObjectSchema<{
|
|
36
39
|
readonly type: v.LiteralSchema<"page_id", undefined>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/messages/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/messages/init.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAG5B,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAO9E,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,iBAAiB,CAAA;AAIrE,eAAO,MAAM,8BAA8B,2BAAa,CAAA;AAExD,MAAM,MAAM,wBAAwB,GAAG,oBAAoB,CACxD,sBAAsB,GACtB,kBAAkB,GAClB,0BAA0B,GAC1B,8BAA8B,GAC9B,qBAAqB,GACrB,0BAA0B,GAC1B,6BAA6B,GAC7B,yBAAyB,GACzB,0BAA0B,GAC1B,0BAA0B,CAC5B,CAAA;AAED,MAAM,MAAM,wBAAwB,GACnC,oBAAoB,CAAC,wBAAwB,CAAC,CAAA;AAE/C;;;;GAIG;AACH,MAAM,MAAM,kCAAkC,GAC3C,wBAAwB,GACxB,8BAA8B,GAC9B,oBAAoB,CAAC,eAAe,GAAG,cAAc,CAAC,CAAA;AAEzD,MAAM,MAAM,kCAAkC,GAC7C,oBAAoB,CAAC,kCAAkC,CAAC,CAAA;AAEzD,eAAO,MAAM,8BAA8B;;;;aAIzC,CAAA;AAEF,qBAAa,8BACZ,SAAQ,KACR,YAAW,oBAAoB;gBAEnB,KAAK,EAAE,kCAAkC;IAOrD,IAAI,EAAE,kCAAkC,CAAA;IACxC,WAAW,EAAE,OAAO,CAAA;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BAuB5B,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,iBAAiB,CAAC,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as v from "valibot";
|
|
2
|
+
import { DEFAULT_CONTRAST_MODE, notionContrastModeSchema } from "../contrast.js";
|
|
2
3
|
import { notionDataSourceBindingsSchema } from "../dataSources/dataSource.js";
|
|
3
4
|
import { notionBlockIdSchema } from "../ids.js";
|
|
4
5
|
import { manifestSchema } from "../manifest.js";
|
|
@@ -25,7 +26,9 @@ export class CustomBlockInitializationError extends Error {
|
|
|
25
26
|
/**
|
|
26
27
|
* Initialization message sent by the host to the sandbox exactly once, in response to the
|
|
27
28
|
* sandbox's `connect` message. The sandbox echoes `initializationId` in `initResult`. After
|
|
28
|
-
* successful initialization, live updates flow through narrower messages
|
|
29
|
+
* successful initialization, live updates flow through narrower messages
|
|
30
|
+
* (`themeChanged`, `contrastModeChanged`, `parentChanged`, `pageChanged`,
|
|
31
|
+
* `dataSourcesChanged`).
|
|
29
32
|
*/
|
|
30
33
|
export const initMessageSchema = v.variant("status", [
|
|
31
34
|
v.object({
|
|
@@ -33,6 +36,8 @@ export const initMessageSchema = v.variant("status", [
|
|
|
33
36
|
initializationId: v.string(),
|
|
34
37
|
status: v.literal("success"),
|
|
35
38
|
theme: notionThemeSchema,
|
|
39
|
+
// TODO(custom-blocks): Make this required when next bumping the protocol version.
|
|
40
|
+
contrastMode: v.optional(notionContrastModeSchema, DEFAULT_CONTRAST_MODE),
|
|
36
41
|
blockId: notionBlockIdSchema,
|
|
37
42
|
parent: notionParentSchema,
|
|
38
43
|
page: customBlockPageSchema,
|