create-ncblock 0.0.22 → 0.0.23
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/package.json +1 -1
- package/scripts/scaffold-assets/AGENTS.md +1 -1
- package/sdk-version.json +1 -1
- package/templates/debug/README.md +1 -1
- package/templates/debug/src/index.tsx +13 -17
- package/templates/radar-chart/README.md +1 -1
- package/templates/radar-chart/src/index.tsx +4 -3
- package/templates/table-view/README.md +1 -1
- package/templates/table-view/src/index.tsx +20 -19
package/package.json
CHANGED
|
@@ -22,7 +22,7 @@ Hooks at a glance:
|
|
|
22
22
|
- `useCustomBlockContext()` — `{ customBlockId, parent, page }`.
|
|
23
23
|
- `useTheme()` — `"light" | "dark"`.
|
|
24
24
|
- `useDataSource(key, initialLimit?)` — `{ items, isLoading, hasMore, fetchMore, error }`.
|
|
25
|
-
- `
|
|
25
|
+
- `useManifest()` — the declared manifest: data-source keys plus their property declarations.
|
|
26
26
|
- `pages.create(input)` — creates a page; pass `parent: { type: "data_source_key", key }` to target the block's wired data source.
|
|
27
27
|
|
|
28
28
|
`<NotionCustomBlock>` runs `useCustomBlockAutoResize` for you by default — no extra wiring needed. Pass `autoResize={false}` for full-bleed views. Full signatures live in `node_modules/ncblock/docs/*.md` and the `.d.ts` files.
|
package/sdk-version.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.0.
|
|
1
|
+
{"version":"0.0.21"}
|
|
@@ -32,5 +32,5 @@ The debug template includes a message log that intercepts and displays all incom
|
|
|
32
32
|
|
|
33
33
|
- **`useCustomBlockContext()`** -- returns `{ customBlockId, parent, page }` describing the block's location in the document tree
|
|
34
34
|
- **`useTheme()`** -- returns the host's current theme (`"light"` or `"dark"`)
|
|
35
|
-
- **`
|
|
35
|
+
- **`useManifest()`** -- returns the declared manifest (data-source keys + property declarations)
|
|
36
36
|
- **`useDataSource(key)`** -- returns `{ items, collectionSchema, propertySchemasById, propertySchemasByKey, isLoading, hasMore, fetchMore, error }`. Each `item` has `{ id, propertiesById, propertiesByKey }`. The four built-ins (`created_time`, `last_edited_time`, `created_by`, `last_edited_by`) appear in `propertiesById` / `propertySchemasById`, never in the `*ByKey` views.
|
|
@@ -2,14 +2,13 @@ import {
|
|
|
2
2
|
type NotionCreatePagePosition,
|
|
3
3
|
NotionCustomBlock,
|
|
4
4
|
type NotionCustomBlockContext,
|
|
5
|
-
type NotionDataSource,
|
|
6
5
|
type NotionDataSourceId,
|
|
7
6
|
type NotionPage,
|
|
8
7
|
type NotionPageId,
|
|
9
8
|
pages,
|
|
10
9
|
useCurrentUser,
|
|
11
10
|
useCustomBlockContext,
|
|
12
|
-
|
|
11
|
+
useManifest,
|
|
13
12
|
useTheme,
|
|
14
13
|
} from "ncblock"
|
|
15
14
|
import React, {
|
|
@@ -56,7 +55,8 @@ function App() {
|
|
|
56
55
|
const ctx = useCustomBlockContext()
|
|
57
56
|
const currentUser = useCurrentUser()
|
|
58
57
|
const hostThemeValue = useTheme()
|
|
59
|
-
const
|
|
58
|
+
const manifest = useManifest()
|
|
59
|
+
const dataSourceKeys = Object.keys(manifest?.dataSources ?? {})
|
|
60
60
|
const [isPaused, setIsPaused] = useState(false)
|
|
61
61
|
const { log, initData, send, clearLog } = useMessageLog(isPaused)
|
|
62
62
|
const [themeOverride, setThemeOverride] = useState<ThemeOverride>("host")
|
|
@@ -87,7 +87,7 @@ function App() {
|
|
|
87
87
|
parent: ctx?.parent,
|
|
88
88
|
page: ctx?.page,
|
|
89
89
|
currentUser,
|
|
90
|
-
|
|
90
|
+
manifest,
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
const metadataRows: Array<[string, string]> = [
|
|
@@ -180,7 +180,7 @@ function App() {
|
|
|
180
180
|
</CollapsibleCard>
|
|
181
181
|
|
|
182
182
|
{/* Create page */}
|
|
183
|
-
<CreatePageCard context={ctx}
|
|
183
|
+
<CreatePageCard context={ctx} dataSourceKeys={dataSourceKeys} />
|
|
184
184
|
|
|
185
185
|
{/* Send message */}
|
|
186
186
|
<SendMessageCard onSend={send} />
|
|
@@ -1610,7 +1610,7 @@ class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
|
1610
1610
|
|
|
1611
1611
|
type CreatePageCardProps = {
|
|
1612
1612
|
context: NotionCustomBlockContext | undefined
|
|
1613
|
-
|
|
1613
|
+
dataSourceKeys: string[]
|
|
1614
1614
|
}
|
|
1615
1615
|
|
|
1616
1616
|
type CreatePagePreset = {
|
|
@@ -1738,7 +1738,7 @@ function pageIconFromInput(raw: string): NotionPage["icon"] | undefined {
|
|
|
1738
1738
|
* SDK resolve the key to the configured data source ID locally before sending the request to the
|
|
1739
1739
|
* Notion host.
|
|
1740
1740
|
*/
|
|
1741
|
-
function CreatePageCard({ context,
|
|
1741
|
+
function CreatePageCard({ context, dataSourceKeys }: CreatePageCardProps) {
|
|
1742
1742
|
const [status, setStatus] = useState<string | null>(null)
|
|
1743
1743
|
const [busy, setBusy] = useState(false)
|
|
1744
1744
|
const [dataSourceId, setDataSourceId] = useState("")
|
|
@@ -1975,27 +1975,23 @@ function CreatePageCard({ context, dataSources }: CreatePageCardProps) {
|
|
|
1975
1975
|
Create in data source
|
|
1976
1976
|
</button>
|
|
1977
1977
|
</div>
|
|
1978
|
-
{
|
|
1978
|
+
{dataSourceKeys.length > 0 && (
|
|
1979
1979
|
<div className="mb-2 flex flex-wrap items-center gap-1.5">
|
|
1980
1980
|
<span className="font-mono text-[11px] text-(--muted)">
|
|
1981
1981
|
by data source key:
|
|
1982
1982
|
</span>
|
|
1983
|
-
{
|
|
1983
|
+
{dataSourceKeys.map(key => (
|
|
1984
1984
|
<button
|
|
1985
|
-
key={
|
|
1985
|
+
key={key}
|
|
1986
1986
|
type="button"
|
|
1987
1987
|
disabled={disabled}
|
|
1988
|
-
title={
|
|
1989
|
-
source.collectionPointer !== undefined
|
|
1990
|
-
? `Create a page in data source ${source.collectionPointer.id} via key "${source.key}"`
|
|
1991
|
-
: `Key "${source.key}" has no collection pointer yet; request will resolve with an error`
|
|
1992
|
-
}
|
|
1988
|
+
title={`Create a page via data source key "${key}" (resolves to an error if the key is not mapped to a database yet)`}
|
|
1993
1989
|
className="rounded-md border border-(--border) bg-transparent px-2 py-1 font-mono text-[11px] text-(--muted) transition-colors hover:border-(--foreground)/20 hover:bg-(--hover-bg) hover:text-(--foreground) disabled:cursor-not-allowed disabled:opacity-50"
|
|
1994
1990
|
onClick={() => {
|
|
1995
|
-
void handleCreateForKey(
|
|
1991
|
+
void handleCreateForKey(key)
|
|
1996
1992
|
}}
|
|
1997
1993
|
>
|
|
1998
|
-
{
|
|
1994
|
+
{key}
|
|
1999
1995
|
</button>
|
|
2000
1996
|
))}
|
|
2001
1997
|
</div>
|
|
@@ -51,5 +51,5 @@ If the mapped collection is missing any of those fields, the template shows a se
|
|
|
51
51
|
|
|
52
52
|
- **`useCustomBlockContext()`** -- returns `{ customBlockId, parent, page }` describing the block's location in the document tree
|
|
53
53
|
- **`useTheme()`** -- returns the host's current theme (`"light"` or `"dark"`)
|
|
54
|
-
- **`
|
|
54
|
+
- **`useManifest()`** -- returns the declared manifest (data-source keys + property declarations)
|
|
55
55
|
- **`useDataSource(key)`** -- returns `{ items, collectionSchema, propertySchemasById, propertySchemasByKey, isLoading, hasMore, fetchMore, error }`. Each `item` has `{ id, propertiesById, propertiesByKey }`. The four built-ins (`created_time`, `last_edited_time`, `created_by`, `last_edited_by`) appear in `propertiesById` / `propertySchemasById`, never in the `*ByKey` views.
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
type NotionDataSourcePage,
|
|
4
4
|
type NotionPageId,
|
|
5
5
|
useDataSource,
|
|
6
|
-
|
|
6
|
+
useManifest,
|
|
7
7
|
useTheme,
|
|
8
8
|
} from "ncblock"
|
|
9
9
|
import React from "react"
|
|
@@ -445,8 +445,9 @@ function SetupHint(props: {
|
|
|
445
445
|
|
|
446
446
|
function App() {
|
|
447
447
|
const theme = useTheme()
|
|
448
|
-
const
|
|
449
|
-
const activeDataSourceKey =
|
|
448
|
+
const manifest = useManifest()
|
|
449
|
+
const activeDataSourceKey =
|
|
450
|
+
Object.keys(manifest?.dataSources ?? {})[0] ?? "default"
|
|
450
451
|
const query = useDataSource(activeDataSourceKey)
|
|
451
452
|
const colorTheme = theme === "dark" ? "dark" : "light"
|
|
452
453
|
const mappedAnalysis = analyzeRadarSchema(query.items)
|
|
@@ -39,5 +39,5 @@ related page is loaded or `-> uuid` when it is not.
|
|
|
39
39
|
|
|
40
40
|
- **`useCustomBlockContext()`** -- returns `{ customBlockId, parent, page }` describing the block's location in the document tree
|
|
41
41
|
- **`useTheme()`** -- returns the host's current theme (`"light"` or `"dark"`)
|
|
42
|
-
- **`
|
|
42
|
+
- **`useManifest()`** -- returns the declared manifest (data-source keys + property declarations)
|
|
43
43
|
- **`useDataSource(key)`** -- returns `{ items, collectionSchema, propertySchemasById, propertySchemasByKey, isLoading, hasMore, fetchMore, error }`. Each `item` has `{ id, propertiesById, propertiesByKey }`. The four built-ins (`created_time`, `last_edited_time`, `created_by`, `last_edited_by`) appear in `propertiesById` / `propertySchemasById`, never in the `*ByKey` views.
|
|
@@ -8,13 +8,12 @@ import {
|
|
|
8
8
|
} from "@tanstack/react-table"
|
|
9
9
|
import {
|
|
10
10
|
NotionCustomBlock,
|
|
11
|
-
type NotionDataSource,
|
|
12
11
|
type NotionPagePropertyInputMap,
|
|
13
12
|
type NotionPagePropertyInputValue,
|
|
14
13
|
type NotionPropertySchema,
|
|
15
14
|
pages,
|
|
16
15
|
useDataSource,
|
|
17
|
-
|
|
16
|
+
useManifest,
|
|
18
17
|
useTheme,
|
|
19
18
|
} from "ncblock"
|
|
20
19
|
import React from "react"
|
|
@@ -1004,7 +1003,7 @@ function DataWorkspace(props: {
|
|
|
1004
1003
|
onColumnOrderChange: (next: string[]) => void
|
|
1005
1004
|
onHiddenColumnsChange: (next: Set<string>) => void
|
|
1006
1005
|
activeDataSourceKey: string
|
|
1007
|
-
|
|
1006
|
+
dataSourceKeys: string[]
|
|
1008
1007
|
onSelectDataSource: (key: string) => void
|
|
1009
1008
|
hasMore: boolean
|
|
1010
1009
|
isLoading: boolean
|
|
@@ -1023,7 +1022,7 @@ function DataWorkspace(props: {
|
|
|
1023
1022
|
onColumnOrderChange,
|
|
1024
1023
|
onHiddenColumnsChange,
|
|
1025
1024
|
activeDataSourceKey,
|
|
1026
|
-
|
|
1025
|
+
dataSourceKeys,
|
|
1027
1026
|
onSelectDataSource,
|
|
1028
1027
|
hasMore,
|
|
1029
1028
|
isLoading,
|
|
@@ -1417,7 +1416,7 @@ function DataWorkspace(props: {
|
|
|
1417
1416
|
<span className="eyebrow ml-1.5">rows</span>
|
|
1418
1417
|
</div>
|
|
1419
1418
|
|
|
1420
|
-
{
|
|
1419
|
+
{dataSourceKeys.length > 1 ? (
|
|
1421
1420
|
<label className="block">
|
|
1422
1421
|
<span className="sr-only">Choose data source</span>
|
|
1423
1422
|
<select
|
|
@@ -1425,9 +1424,9 @@ function DataWorkspace(props: {
|
|
|
1425
1424
|
onChange={event => onSelectDataSource(event.target.value)}
|
|
1426
1425
|
className="field-control min-h-9 w-full rounded-md border border-(--line) bg-(--surface-bg) px-2 text-sm text-(--foreground) outline-none hover:border-(--line-strong)"
|
|
1427
1426
|
>
|
|
1428
|
-
{
|
|
1429
|
-
<option key={
|
|
1430
|
-
{
|
|
1427
|
+
{dataSourceKeys.map(key => (
|
|
1428
|
+
<option key={key} value={key}>
|
|
1429
|
+
{key}
|
|
1431
1430
|
</option>
|
|
1432
1431
|
))}
|
|
1433
1432
|
</select>
|
|
@@ -1682,30 +1681,32 @@ function DataWorkspace(props: {
|
|
|
1682
1681
|
|
|
1683
1682
|
function App() {
|
|
1684
1683
|
const theme = useTheme()
|
|
1685
|
-
const
|
|
1684
|
+
const manifest = useManifest()
|
|
1685
|
+
const dataSourceKeys = React.useMemo(
|
|
1686
|
+
() => Object.keys(manifest?.dataSources ?? {}),
|
|
1687
|
+
[manifest],
|
|
1688
|
+
)
|
|
1686
1689
|
const [activeDataSourceKey, setActiveDataSourceKey] = React.useState(
|
|
1687
|
-
|
|
1690
|
+
dataSourceKeys[0] ?? "default",
|
|
1688
1691
|
)
|
|
1689
1692
|
|
|
1690
1693
|
React.useEffect(() => {
|
|
1691
|
-
if (
|
|
1694
|
+
if (dataSourceKeys.length === 0) {
|
|
1692
1695
|
setActiveDataSourceKey("default")
|
|
1693
1696
|
return
|
|
1694
1697
|
}
|
|
1695
1698
|
|
|
1696
|
-
if (
|
|
1697
|
-
|
|
1698
|
-
) {
|
|
1699
|
-
setActiveDataSourceKey(dataSources[0].key)
|
|
1699
|
+
if (!dataSourceKeys.includes(activeDataSourceKey)) {
|
|
1700
|
+
setActiveDataSourceKey(dataSourceKeys[0])
|
|
1700
1701
|
}
|
|
1701
|
-
}, [activeDataSourceKey,
|
|
1702
|
+
}, [activeDataSourceKey, dataSourceKeys])
|
|
1702
1703
|
|
|
1703
|
-
const queryKey =
|
|
1704
|
+
const queryKey = dataSourceKeys.length === 0 ? "default" : activeDataSourceKey
|
|
1704
1705
|
const query = useDataSource(queryKey)
|
|
1705
1706
|
const colorTheme = theme === "dark" ? "dark" : "light"
|
|
1706
1707
|
|
|
1707
1708
|
const mappedItems = query.items as TableRow[]
|
|
1708
|
-
const isUsingFallbackData =
|
|
1709
|
+
const isUsingFallbackData = dataSourceKeys.length === 0
|
|
1709
1710
|
const isCollectionEmpty =
|
|
1710
1711
|
!isUsingFallbackData && !query.isLoading && mappedItems.length === 0
|
|
1711
1712
|
const items = isUsingFallbackData ? SAMPLE_ITEMS : mappedItems
|
|
@@ -1793,7 +1794,7 @@ function App() {
|
|
|
1793
1794
|
onColumnOrderChange={setColumnOrder}
|
|
1794
1795
|
onHiddenColumnsChange={setHiddenColumns}
|
|
1795
1796
|
activeDataSourceKey={queryKey}
|
|
1796
|
-
|
|
1797
|
+
dataSourceKeys={dataSourceKeys}
|
|
1797
1798
|
onSelectDataSource={setActiveDataSourceKey}
|
|
1798
1799
|
hasMore={query.hasMore}
|
|
1799
1800
|
isLoading={query.isLoading}
|