blocks-renderer 0.1.1 → 0.3.1

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/types.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ import type { UIAction, UIDocument, UINode, UINodeProps } from 'blocks-schema';
2
+ import type { BindingScope, NodeRegistry, RenderContext } from 'json-renderer';
3
+ import type { ComponentType, ReactNode } from 'react';
4
+ export type RenderMode = 'preview' | 'edit';
5
+ /**
6
+ * Props every block component receives. Children are already rendered, and
7
+ * `props` has the node's bindings resolved against the current scope.
8
+ */
9
+ export interface BlockProps {
10
+ node: UINode;
11
+ props: UINodeProps;
12
+ children?: ReactNode;
13
+ }
14
+ export type BlockComponent = ComponentType<BlockProps>;
15
+ /** Node type → component. Layered by {@link composeRegistry}. */
16
+ export type BlockRegistry = NodeRegistry<BlockComponent>;
17
+ /**
18
+ * The React adapter's render context: `json-renderer`'s generic
19
+ * {@link RenderContext} plus the field state a form needs while rendering.
20
+ */
21
+ export interface RendererContextValue extends RenderContext<BlockComponent, UIDocument, UIAction> {
22
+ document: UIDocument;
23
+ registry: BlockRegistry;
24
+ mode: RenderMode;
25
+ values: Record<string, unknown>;
26
+ errors: Record<string, string>;
27
+ setValue: (name: string, value: unknown) => void;
28
+ setError: (name: string, error: string | null) => void;
29
+ /** Scope for binding expressions (`{{ row.title }}`), merged with `values`. */
30
+ scope: BindingScope;
31
+ onAction?: (action: UIAction, event: string) => void;
32
+ }
package/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ import type { UINode } from 'blocks-schema';
2
+ /**
3
+ * Rendered when no registry layer satisfies a node type. A document may name
4
+ * blocks a given host has not installed, so an unknown type is a visible gap,
5
+ * never a thrown render.
6
+ */
7
+ export declare function UnknownBlock({ node }: {
8
+ node: UINode;
9
+ }): import("react").JSX.Element;
@@ -0,0 +1,13 @@
1
+ 'use client';
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.UnknownBlock = UnknownBlock;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * Rendered when no registry layer satisfies a node type. A document may name
8
+ * blocks a given host has not installed, so an unknown type is a visible gap,
9
+ * never a thrown render.
10
+ */
11
+ function UnknownBlock({ node }) {
12
+ return ((0, jsx_runtime_1.jsxs)("div", { "data-block-unknown": node.type, role: "note", children: ["Unknown block: ", node.type] }));
13
+ }
package/dist/index.cjs DELETED
@@ -1,214 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- BlockRenderer: () => BlockRenderer,
24
- DocumentRenderer: () => DocumentRenderer,
25
- RendererProvider: () => RendererProvider,
26
- UnknownBlock: () => UnknownBlock,
27
- composeRegistry: () => composeRegistry,
28
- readPath: () => readPath,
29
- registeredTypes: () => registeredTypes,
30
- resolveBinding: () => resolveBinding,
31
- resolveBlock: () => resolveBlock,
32
- resolveNodeProps: () => resolveNodeProps,
33
- useBlockField: () => useBlockField,
34
- useRenderer: () => useRenderer
35
- });
36
- module.exports = __toCommonJS(index_exports);
37
-
38
- // src/bindings.ts
39
- var TEMPLATE = /\{\{\s*([^}\s]+)\s*\}\}/g;
40
- function readPath(scope, path) {
41
- let current = scope;
42
- for (const segment of path.split(".")) {
43
- if (current == null || typeof current !== "object") return void 0;
44
- current = current[segment];
45
- }
46
- return current;
47
- }
48
- function resolveBinding(expression, scope) {
49
- const single = expression.match(/^\{\{\s*([^}\s]+)\s*\}\}$/);
50
- if (single) {
51
- return readPath(scope, single[1]);
52
- }
53
- return expression.replace(TEMPLATE, (_match, path) => {
54
- const value = readPath(scope, path);
55
- return value == null ? "" : String(value);
56
- });
57
- }
58
- function resolveNodeProps(node, scope) {
59
- if (!node.bindings) return node.props ?? {};
60
- const resolved = { ...node.props ?? {} };
61
- for (const [prop, expression] of Object.entries(node.bindings)) {
62
- resolved[prop] = resolveBinding(expression, scope);
63
- }
64
- return resolved;
65
- }
66
-
67
- // src/context.tsx
68
- var import_react = require("react");
69
- var import_jsx_runtime = require("react/jsx-runtime");
70
- var RendererContext = (0, import_react.createContext)(null);
71
- function RendererProvider({ children, value }) {
72
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RendererContext.Provider, { value, children });
73
- }
74
- function useRenderer() {
75
- const context = (0, import_react.useContext)(RendererContext);
76
- if (!context) {
77
- throw new Error("useRenderer must be used within a RendererProvider (or a DocumentRenderer)");
78
- }
79
- return context;
80
- }
81
- function useBlockField(name) {
82
- const { values, errors, setValue, setError, mode } = useRenderer();
83
- if (!name) {
84
- return { value: void 0, error: void 0, setValue: () => {
85
- }, setError: () => {
86
- }, mode };
87
- }
88
- return {
89
- value: values[name],
90
- error: errors[name],
91
- setValue: (value) => setValue(name, value),
92
- setError: (error) => setError(name, error),
93
- mode
94
- };
95
- }
96
-
97
- // src/registry.ts
98
- function composeRegistry(...layers) {
99
- const composed = {};
100
- for (const layer of layers) {
101
- if (!layer) continue;
102
- Object.assign(composed, layer);
103
- }
104
- return composed;
105
- }
106
- function resolveBlock(registry, type) {
107
- return registry[type];
108
- }
109
- function registeredTypes(registry) {
110
- return Object.keys(registry).sort();
111
- }
112
-
113
- // src/renderer.tsx
114
- var import_blocks_schema = require("blocks-schema");
115
- var import_react2 = require("react");
116
-
117
- // src/unknown-block.tsx
118
- var import_jsx_runtime2 = require("react/jsx-runtime");
119
- function UnknownBlock({ node }) {
120
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { "data-block-unknown": node.type, role: "note", children: [
121
- "Unknown block: ",
122
- node.type
123
- ] });
124
- }
125
-
126
- // src/renderer.tsx
127
- var import_jsx_runtime3 = require("react/jsx-runtime");
128
- function BlockRenderer({ node }) {
129
- const { registry, scope } = useRenderer();
130
- const Component = registry[node.type];
131
- if (!Component) {
132
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(UnknownBlock, { node });
133
- }
134
- const children = node.children?.length ? node.children.map((child) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BlockRenderer, { node: child }, child.key)) : void 0;
135
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Component, { node, props: resolveNodeProps(node, scope), children });
136
- }
137
- function DocumentRenderer({
138
- document,
139
- registry,
140
- initialValues,
141
- scope: externalScope,
142
- onSubmit,
143
- onChange,
144
- onAction,
145
- mode = "preview",
146
- className
147
- }) {
148
- const defaults = (0, import_react2.useMemo)(() => (0, import_blocks_schema.collectDefaultValues)(document.page), [document]);
149
- const constraints = (0, import_react2.useMemo)(() => (0, import_blocks_schema.collectFieldConstraints)(document.page), [document]);
150
- const [values, setValues] = (0, import_react2.useState)(() => ({ ...defaults, ...initialValues }));
151
- const [errors, setErrors] = (0, import_react2.useState)({});
152
- (0, import_react2.useEffect)(() => {
153
- setValues((previous) => ({ ...defaults, ...initialValues, ...previous }));
154
- }, [defaults, initialValues]);
155
- const setError = (0, import_react2.useCallback)((name, error) => {
156
- setErrors((previous) => {
157
- if (error) return { ...previous, [name]: error };
158
- if (!(name in previous)) return previous;
159
- const next = { ...previous };
160
- delete next[name];
161
- return next;
162
- });
163
- }, []);
164
- const setValue = (0, import_react2.useCallback)(
165
- (name, value) => {
166
- setValues((previous) => {
167
- const next = { ...previous, [name]: value };
168
- onChange?.(next);
169
- return next;
170
- });
171
- const field = constraints[name];
172
- if (field) {
173
- setError(name, (0, import_blocks_schema.validateField)(value, field.constraints, field.required));
174
- }
175
- },
176
- [onChange, constraints, setError]
177
- );
178
- const handleAction = (0, import_react2.useCallback)(
179
- (action, event) => {
180
- if (event === "submit" && onSubmit) {
181
- const failures = {};
182
- for (const name of (0, import_blocks_schema.collectFieldNames)(document.page)) {
183
- const field = constraints[name];
184
- if (!field) continue;
185
- const error = (0, import_blocks_schema.validateField)(values[name], field.constraints, field.required);
186
- if (error) failures[name] = error;
187
- }
188
- if (Object.keys(failures).length > 0) {
189
- setErrors(failures);
190
- return;
191
- }
192
- onSubmit(values);
193
- }
194
- onAction?.(action, event);
195
- },
196
- [onSubmit, onAction, values, document.page, constraints]
197
- );
198
- const contextValue = (0, import_react2.useMemo)(
199
- () => ({
200
- document,
201
- registry,
202
- mode,
203
- values,
204
- errors,
205
- setValue,
206
- setError,
207
- scope: { ...externalScope, values, ...values },
208
- onAction: handleAction
209
- }),
210
- [document, registry, mode, values, errors, setValue, setError, externalScope, handleAction]
211
- );
212
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RendererProvider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BlockRenderer, { node: document.page }) }) });
213
- }
214
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/bindings.ts","../src/context.tsx","../src/registry.ts","../src/renderer.tsx","../src/unknown-block.tsx"],"sourcesContent":["export { readPath, resolveBinding, resolveNodeProps } from './bindings';\nexport { RendererProvider, useBlockField, useRenderer } from './context';\nexport { composeRegistry, registeredTypes, resolveBlock } from './registry';\nexport { BlockRenderer, DocumentRenderer } from './renderer';\nexport type { DocumentRendererProps } from './renderer';\nexport { UnknownBlock } from './unknown-block';\nexport type { BlockComponent, BlockProps, BlockRegistry, RenderMode, RendererContextValue } from './types';\n","import type { UINode, UINodeProps } from 'blocks-schema';\n\nconst TEMPLATE = /\\{\\{\\s*([^}\\s]+)\\s*\\}\\}/g;\n\n/** Read a dotted path (`row.author.name`) out of a scope object. */\nexport function readPath(scope: Record<string, unknown>, path: string): unknown {\n\tlet current: unknown = scope;\n\tfor (const segment of path.split('.')) {\n\t\tif (current == null || typeof current !== 'object') return undefined;\n\t\tcurrent = (current as Record<string, unknown>)[segment];\n\t}\n\treturn current;\n}\n\n/**\n * Resolve a binding expression. A template that is exactly one placeholder\n * yields the raw value (so a boolean or an object survives); a template mixed\n * with text is interpolated as a string.\n */\nexport function resolveBinding(expression: string, scope: Record<string, unknown>): unknown {\n\tconst single = expression.match(/^\\{\\{\\s*([^}\\s]+)\\s*\\}\\}$/);\n\tif (single) {\n\t\treturn readPath(scope, single[1]);\n\t}\n\n\treturn expression.replace(TEMPLATE, (_match, path: string) => {\n\t\tconst value = readPath(scope, path);\n\t\treturn value == null ? '' : String(value);\n\t});\n}\n\n/** Apply a node's `bindings` over its static props. */\nexport function resolveNodeProps(node: UINode, scope: Record<string, unknown>): UINodeProps {\n\tif (!node.bindings) return node.props ?? {};\n\n\tconst resolved: UINodeProps = { ...(node.props ?? {}) };\n\tfor (const [prop, expression] of Object.entries(node.bindings)) {\n\t\tresolved[prop] = resolveBinding(expression, scope);\n\t}\n\treturn resolved;\n}\n","'use client';\n\nimport { createContext, useContext } from 'react';\nimport type { ReactNode } from 'react';\n\nimport type { RendererContextValue } from './types';\n\nconst RendererContext = createContext<RendererContextValue | null>(null);\n\nexport function RendererProvider({ children, value }: { children: ReactNode; value: RendererContextValue }) {\n\treturn <RendererContext.Provider value={value}>{children}</RendererContext.Provider>;\n}\n\nexport function useRenderer(): RendererContextValue {\n\tconst context = useContext(RendererContext);\n\tif (!context) {\n\t\tthrow new Error('useRenderer must be used within a RendererProvider (or a DocumentRenderer)');\n\t}\n\treturn context;\n}\n\n/**\n * Resolved props plus the value/error wiring for a field node. Widget\n * implementations use this instead of reaching into the document themselves.\n */\nexport function useBlockField(name: string | undefined) {\n\tconst { values, errors, setValue, setError, mode } = useRenderer();\n\tif (!name) {\n\t\treturn { value: undefined, error: undefined, setValue: () => {}, setError: () => {}, mode };\n\t}\n\treturn {\n\t\tvalue: values[name],\n\t\terror: errors[name],\n\t\tsetValue: (value: unknown) => setValue(name, value),\n\t\tsetError: (error: string | null) => setError(name, error),\n\t\tmode,\n\t};\n}\n","import type { BlockComponent, BlockRegistry } from './types';\n\n/**\n * Layer registries left-to-right, later layers winning. This is how a host\n * customizes rendering: base primitives, then an app registry, then per-document\n * overrides — no forking of the renderer, and no single global map.\n */\nexport function composeRegistry(...layers: (BlockRegistry | undefined)[]): BlockRegistry {\n\tconst composed: BlockRegistry = {};\n\tfor (const layer of layers) {\n\t\tif (!layer) continue;\n\t\tObject.assign(composed, layer);\n\t}\n\treturn composed;\n}\n\nexport function resolveBlock(registry: BlockRegistry, type: string): BlockComponent | undefined {\n\treturn registry[type];\n}\n\n/** Node types the registry can render, sorted for stable output. */\nexport function registeredTypes(registry: BlockRegistry): string[] {\n\treturn Object.keys(registry).sort();\n}\n","'use client';\n\nimport {\n\tcollectDefaultValues,\n\tcollectFieldConstraints,\n\tcollectFieldNames,\n\tvalidateField,\n\ttype UIAction,\n\ttype UIDocument,\n\ttype UINode,\n} from 'blocks-schema';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport { resolveNodeProps } from './bindings';\nimport { RendererProvider, useRenderer } from './context';\nimport { UnknownBlock } from './unknown-block';\nimport type { BlockRegistry, RenderMode, RendererContextValue } from './types';\n\n/**\n * Renders one node and, recursively, its children: resolve the node type in the\n * registry, resolve bindings against the current scope, render children first,\n * fall back to {@link UnknownBlock}.\n */\nexport function BlockRenderer({ node }: { node: UINode }) {\n\tconst { registry, scope } = useRenderer();\n\tconst Component = registry[node.type];\n\n\tif (!Component) {\n\t\treturn <UnknownBlock node={node} />;\n\t}\n\n\tconst children = node.children?.length\n\t\t? node.children.map((child) => <BlockRenderer key={child.key} node={child} />)\n\t\t: undefined;\n\n\treturn (\n\t\t<Component node={node} props={resolveNodeProps(node, scope)}>\n\t\t\t{children}\n\t\t</Component>\n\t);\n}\n\nexport interface DocumentRendererProps {\n\tdocument: UIDocument;\n\tregistry: BlockRegistry;\n\tinitialValues?: Record<string, unknown>;\n\t/** Extra data for binding expressions, e.g. `{ row, user, params }`. */\n\tscope?: Record<string, unknown>;\n\tonSubmit?: (values: Record<string, unknown>) => void;\n\tonChange?: (values: Record<string, unknown>) => void;\n\tonAction?: (action: UIAction, event: string) => void;\n\tmode?: RenderMode;\n\tclassName?: string;\n}\n\nexport function DocumentRenderer({\n\tdocument,\n\tregistry,\n\tinitialValues,\n\tscope: externalScope,\n\tonSubmit,\n\tonChange,\n\tonAction,\n\tmode = 'preview',\n\tclassName,\n}: DocumentRendererProps) {\n\tconst defaults = useMemo(() => collectDefaultValues(document.page), [document]);\n\tconst constraints = useMemo(() => collectFieldConstraints(document.page), [document]);\n\n\tconst [values, setValues] = useState<Record<string, unknown>>(() => ({ ...defaults, ...initialValues }));\n\tconst [errors, setErrors] = useState<Record<string, string>>({});\n\n\tuseEffect(() => {\n\t\tsetValues((previous) => ({ ...defaults, ...initialValues, ...previous }));\n\t}, [defaults, initialValues]);\n\n\tconst setError = useCallback((name: string, error: string | null) => {\n\t\tsetErrors((previous) => {\n\t\t\tif (error) return { ...previous, [name]: error };\n\t\t\tif (!(name in previous)) return previous;\n\t\t\tconst next = { ...previous };\n\t\t\tdelete next[name];\n\t\t\treturn next;\n\t\t});\n\t}, []);\n\n\tconst setValue = useCallback(\n\t\t(name: string, value: unknown) => {\n\t\t\tsetValues((previous) => {\n\t\t\t\tconst next = { ...previous, [name]: value };\n\t\t\t\tonChange?.(next);\n\t\t\t\treturn next;\n\t\t\t});\n\n\t\t\tconst field = constraints[name];\n\t\t\tif (field) {\n\t\t\t\tsetError(name, validateField(value, field.constraints, field.required));\n\t\t\t}\n\t\t},\n\t\t[onChange, constraints, setError],\n\t);\n\n\tconst handleAction = useCallback(\n\t\t(action: UIAction, event: string) => {\n\t\t\tif (event === 'submit' && onSubmit) {\n\t\t\t\tconst failures: Record<string, string> = {};\n\t\t\t\tfor (const name of collectFieldNames(document.page)) {\n\t\t\t\t\tconst field = constraints[name];\n\t\t\t\t\tif (!field) continue;\n\t\t\t\t\tconst error = validateField(values[name], field.constraints, field.required);\n\t\t\t\t\tif (error) failures[name] = error;\n\t\t\t\t}\n\n\t\t\t\tif (Object.keys(failures).length > 0) {\n\t\t\t\t\tsetErrors(failures);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tonSubmit(values);\n\t\t\t}\n\n\t\t\tonAction?.(action, event);\n\t\t},\n\t\t[onSubmit, onAction, values, document.page, constraints],\n\t);\n\n\tconst contextValue: RendererContextValue = useMemo(\n\t\t() => ({\n\t\t\tdocument,\n\t\t\tregistry,\n\t\t\tmode,\n\t\t\tvalues,\n\t\t\terrors,\n\t\t\tsetValue,\n\t\t\tsetError,\n\t\t\tscope: { ...externalScope, values, ...values },\n\t\t\tonAction: handleAction,\n\t\t}),\n\t\t[document, registry, mode, values, errors, setValue, setError, externalScope, handleAction],\n\t);\n\n\treturn (\n\t\t<RendererProvider value={contextValue}>\n\t\t\t<div className={className}>\n\t\t\t\t<BlockRenderer node={document.page} />\n\t\t\t</div>\n\t\t</RendererProvider>\n\t);\n}\n","'use client';\n\nimport type { UINode } from 'blocks-schema';\n\n/**\n * Rendered when no registry layer satisfies a node type. A document may name\n * blocks a given host has not installed, so an unknown type is a visible gap,\n * never a thrown render.\n */\nexport function UnknownBlock({ node }: { node: UINode }) {\n\treturn (\n\t\t<div data-block-unknown={node.type} role=\"note\">\n\t\t\tUnknown block: {node.type}\n\t\t</div>\n\t);\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","import_jsx_runtime"]}
package/dist/index.d.cts DELETED
@@ -1,106 +0,0 @@
1
- import { UINode, UINodeProps, UIDocument, UIAction } from 'blocks-schema';
2
- import * as react from 'react';
3
- import { ComponentType, ReactNode } from 'react';
4
-
5
- /** Read a dotted path (`row.author.name`) out of a scope object. */
6
- declare function readPath(scope: Record<string, unknown>, path: string): unknown;
7
- /**
8
- * Resolve a binding expression. A template that is exactly one placeholder
9
- * yields the raw value (so a boolean or an object survives); a template mixed
10
- * with text is interpolated as a string.
11
- */
12
- declare function resolveBinding(expression: string, scope: Record<string, unknown>): unknown;
13
- /** Apply a node's `bindings` over its static props. */
14
- declare function resolveNodeProps(node: UINode, scope: Record<string, unknown>): UINodeProps;
15
-
16
- type RenderMode = 'preview' | 'edit';
17
- /**
18
- * Props every block component receives. Children are already rendered, and
19
- * `props` has the node's bindings resolved against the current scope.
20
- */
21
- interface BlockProps {
22
- node: UINode;
23
- props: UINodeProps;
24
- children?: ReactNode;
25
- }
26
- type BlockComponent = ComponentType<BlockProps>;
27
- /** Node type → component. Layered by {@link composeRegistry}. */
28
- type BlockRegistry = Record<string, BlockComponent>;
29
- interface RendererContextValue {
30
- document: UIDocument;
31
- registry: BlockRegistry;
32
- mode: RenderMode;
33
- values: Record<string, unknown>;
34
- errors: Record<string, string>;
35
- setValue: (name: string, value: unknown) => void;
36
- setError: (name: string, error: string | null) => void;
37
- /** Scope for binding expressions (`{{ row.title }}`), merged with `values`. */
38
- scope: Record<string, unknown>;
39
- onAction?: (action: UIAction, event: string) => void;
40
- }
41
-
42
- declare function RendererProvider({ children, value }: {
43
- children: ReactNode;
44
- value: RendererContextValue;
45
- }): react.JSX.Element;
46
- declare function useRenderer(): RendererContextValue;
47
- /**
48
- * Resolved props plus the value/error wiring for a field node. Widget
49
- * implementations use this instead of reaching into the document themselves.
50
- */
51
- declare function useBlockField(name: string | undefined): {
52
- value: undefined;
53
- error: undefined;
54
- setValue: () => void;
55
- setError: () => void;
56
- mode: RenderMode;
57
- } | {
58
- value: unknown;
59
- error: string;
60
- setValue: (value: unknown) => void;
61
- setError: (error: string | null) => void;
62
- mode: RenderMode;
63
- };
64
-
65
- /**
66
- * Layer registries left-to-right, later layers winning. This is how a host
67
- * customizes rendering: base primitives, then an app registry, then per-document
68
- * overrides — no forking of the renderer, and no single global map.
69
- */
70
- declare function composeRegistry(...layers: (BlockRegistry | undefined)[]): BlockRegistry;
71
- declare function resolveBlock(registry: BlockRegistry, type: string): BlockComponent | undefined;
72
- /** Node types the registry can render, sorted for stable output. */
73
- declare function registeredTypes(registry: BlockRegistry): string[];
74
-
75
- /**
76
- * Renders one node and, recursively, its children: resolve the node type in the
77
- * registry, resolve bindings against the current scope, render children first,
78
- * fall back to {@link UnknownBlock}.
79
- */
80
- declare function BlockRenderer({ node }: {
81
- node: UINode;
82
- }): react.JSX.Element;
83
- interface DocumentRendererProps {
84
- document: UIDocument;
85
- registry: BlockRegistry;
86
- initialValues?: Record<string, unknown>;
87
- /** Extra data for binding expressions, e.g. `{ row, user, params }`. */
88
- scope?: Record<string, unknown>;
89
- onSubmit?: (values: Record<string, unknown>) => void;
90
- onChange?: (values: Record<string, unknown>) => void;
91
- onAction?: (action: UIAction, event: string) => void;
92
- mode?: RenderMode;
93
- className?: string;
94
- }
95
- declare function DocumentRenderer({ document, registry, initialValues, scope: externalScope, onSubmit, onChange, onAction, mode, className, }: DocumentRendererProps): react.JSX.Element;
96
-
97
- /**
98
- * Rendered when no registry layer satisfies a node type. A document may name
99
- * blocks a given host has not installed, so an unknown type is a visible gap,
100
- * never a thrown render.
101
- */
102
- declare function UnknownBlock({ node }: {
103
- node: UINode;
104
- }): react.JSX.Element;
105
-
106
- export { type BlockComponent, type BlockProps, type BlockRegistry, BlockRenderer, DocumentRenderer, type DocumentRendererProps, type RenderMode, type RendererContextValue, RendererProvider, UnknownBlock, composeRegistry, readPath, registeredTypes, resolveBinding, resolveBlock, resolveNodeProps, useBlockField, useRenderer };
package/dist/index.d.ts DELETED
@@ -1,106 +0,0 @@
1
- import { UINode, UINodeProps, UIDocument, UIAction } from 'blocks-schema';
2
- import * as react from 'react';
3
- import { ComponentType, ReactNode } from 'react';
4
-
5
- /** Read a dotted path (`row.author.name`) out of a scope object. */
6
- declare function readPath(scope: Record<string, unknown>, path: string): unknown;
7
- /**
8
- * Resolve a binding expression. A template that is exactly one placeholder
9
- * yields the raw value (so a boolean or an object survives); a template mixed
10
- * with text is interpolated as a string.
11
- */
12
- declare function resolveBinding(expression: string, scope: Record<string, unknown>): unknown;
13
- /** Apply a node's `bindings` over its static props. */
14
- declare function resolveNodeProps(node: UINode, scope: Record<string, unknown>): UINodeProps;
15
-
16
- type RenderMode = 'preview' | 'edit';
17
- /**
18
- * Props every block component receives. Children are already rendered, and
19
- * `props` has the node's bindings resolved against the current scope.
20
- */
21
- interface BlockProps {
22
- node: UINode;
23
- props: UINodeProps;
24
- children?: ReactNode;
25
- }
26
- type BlockComponent = ComponentType<BlockProps>;
27
- /** Node type → component. Layered by {@link composeRegistry}. */
28
- type BlockRegistry = Record<string, BlockComponent>;
29
- interface RendererContextValue {
30
- document: UIDocument;
31
- registry: BlockRegistry;
32
- mode: RenderMode;
33
- values: Record<string, unknown>;
34
- errors: Record<string, string>;
35
- setValue: (name: string, value: unknown) => void;
36
- setError: (name: string, error: string | null) => void;
37
- /** Scope for binding expressions (`{{ row.title }}`), merged with `values`. */
38
- scope: Record<string, unknown>;
39
- onAction?: (action: UIAction, event: string) => void;
40
- }
41
-
42
- declare function RendererProvider({ children, value }: {
43
- children: ReactNode;
44
- value: RendererContextValue;
45
- }): react.JSX.Element;
46
- declare function useRenderer(): RendererContextValue;
47
- /**
48
- * Resolved props plus the value/error wiring for a field node. Widget
49
- * implementations use this instead of reaching into the document themselves.
50
- */
51
- declare function useBlockField(name: string | undefined): {
52
- value: undefined;
53
- error: undefined;
54
- setValue: () => void;
55
- setError: () => void;
56
- mode: RenderMode;
57
- } | {
58
- value: unknown;
59
- error: string;
60
- setValue: (value: unknown) => void;
61
- setError: (error: string | null) => void;
62
- mode: RenderMode;
63
- };
64
-
65
- /**
66
- * Layer registries left-to-right, later layers winning. This is how a host
67
- * customizes rendering: base primitives, then an app registry, then per-document
68
- * overrides — no forking of the renderer, and no single global map.
69
- */
70
- declare function composeRegistry(...layers: (BlockRegistry | undefined)[]): BlockRegistry;
71
- declare function resolveBlock(registry: BlockRegistry, type: string): BlockComponent | undefined;
72
- /** Node types the registry can render, sorted for stable output. */
73
- declare function registeredTypes(registry: BlockRegistry): string[];
74
-
75
- /**
76
- * Renders one node and, recursively, its children: resolve the node type in the
77
- * registry, resolve bindings against the current scope, render children first,
78
- * fall back to {@link UnknownBlock}.
79
- */
80
- declare function BlockRenderer({ node }: {
81
- node: UINode;
82
- }): react.JSX.Element;
83
- interface DocumentRendererProps {
84
- document: UIDocument;
85
- registry: BlockRegistry;
86
- initialValues?: Record<string, unknown>;
87
- /** Extra data for binding expressions, e.g. `{ row, user, params }`. */
88
- scope?: Record<string, unknown>;
89
- onSubmit?: (values: Record<string, unknown>) => void;
90
- onChange?: (values: Record<string, unknown>) => void;
91
- onAction?: (action: UIAction, event: string) => void;
92
- mode?: RenderMode;
93
- className?: string;
94
- }
95
- declare function DocumentRenderer({ document, registry, initialValues, scope: externalScope, onSubmit, onChange, onAction, mode, className, }: DocumentRendererProps): react.JSX.Element;
96
-
97
- /**
98
- * Rendered when no registry layer satisfies a node type. A document may name
99
- * blocks a given host has not installed, so an unknown type is a visible gap,
100
- * never a thrown render.
101
- */
102
- declare function UnknownBlock({ node }: {
103
- node: UINode;
104
- }): react.JSX.Element;
105
-
106
- export { type BlockComponent, type BlockProps, type BlockRegistry, BlockRenderer, DocumentRenderer, type DocumentRendererProps, type RenderMode, type RendererContextValue, RendererProvider, UnknownBlock, composeRegistry, readPath, registeredTypes, resolveBinding, resolveBlock, resolveNodeProps, useBlockField, useRenderer };