ngx-json-render 0.7.7 → 0.8.0

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-json-render",
3
- "version": "0.7.7",
3
+ "version": "0.8.0",
4
4
  "description": "Angular renderer for json-render — stream AI-generated JSON specs into real Angular components with signals.",
5
5
  "keywords": [
6
6
  "angular",
@@ -25,7 +25,17 @@
25
25
  "@angular/common": ">=19.0.0",
26
26
  "@angular/core": ">=19.0.0",
27
27
  "@json-render/core": ">=0.20.0 <0.22.0",
28
- "zod": "^4.0.0"
28
+ "zod": "^4.0.0",
29
+ "@modelcontextprotocol/ext-apps": "^1.7.5",
30
+ "@modelcontextprotocol/sdk": "^1.29.0"
31
+ },
32
+ "peerDependenciesMeta": {
33
+ "@modelcontextprotocol/ext-apps": {
34
+ "optional": true
35
+ },
36
+ "@modelcontextprotocol/sdk": {
37
+ "optional": true
38
+ }
29
39
  },
30
40
  "dependencies": {
31
41
  "tslib": "^2.3.0"
@@ -45,6 +55,14 @@
45
55
  "types": "./types/ngx-json-render.d.ts",
46
56
  "default": "./fesm2022/ngx-json-render.mjs"
47
57
  },
58
+ "./mcp": {
59
+ "types": "./types/ngx-json-render-mcp.d.ts",
60
+ "default": "./fesm2022/ngx-json-render-mcp.mjs"
61
+ },
62
+ "./schema": {
63
+ "types": "./types/ngx-json-render-schema.d.ts",
64
+ "default": "./fesm2022/ngx-json-render-schema.mjs"
65
+ },
48
66
  "./testing": {
49
67
  "types": "./types/ngx-json-render-testing.d.ts",
50
68
  "default": "./fesm2022/ngx-json-render-testing.mjs"
@@ -0,0 +1,93 @@
1
+ import { Signal } from '@angular/core';
2
+ import { Spec } from '@json-render/core';
3
+ import { App } from '@modelcontextprotocol/ext-apps';
4
+ import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
5
+
6
+ /** Options for {@link injectJsonRenderApp}. */
7
+ interface JsonRenderAppOptions {
8
+ /** App name sent to the host during initialization. Defaults to `"json-render"`. */
9
+ name?: string;
10
+ /** App version sent to the host. Defaults to `"1.0.0"`. */
11
+ version?: string;
12
+ /**
13
+ * Render the spec while the model is still writing the tool call, from the
14
+ * host's `toolinputpartial` notifications. The host "heals" the truncated
15
+ * JSON, so each partial spec is valid but may end in a half-written
16
+ * element; the renderer skips children that do not exist yet. Defaults to
17
+ * `true`. `useJsonRenderApp` in `@json-render/mcp/app` has no equivalent —
18
+ * it waits for the tool result.
19
+ */
20
+ streamPartialInput?: boolean;
21
+ /**
22
+ * Transport to the host. Omit it inside a real MCP Apps iframe: `App`
23
+ * then talks to `window.parent` over `postMessage`. Tests pass one end of
24
+ * an in-memory pair here and an `AppBridge` on the other.
25
+ */
26
+ transport?: Transport;
27
+ /**
28
+ * Report the page's size to the host as it changes, so the iframe grows
29
+ * with the rendered UI. Defaults to `true`; needs `ResizeObserver`.
30
+ */
31
+ autoResize?: boolean;
32
+ }
33
+ /**
34
+ * What {@link injectJsonRenderApp} returns — the fields of
35
+ * `UseJsonRenderAppReturn` from `@json-render/mcp/app`, as signals.
36
+ */
37
+ interface JsonRenderApp {
38
+ /** The current spec; `null` until the first tool input or result. */
39
+ readonly spec: Signal<Spec | null>;
40
+ /** Whether the app is still connecting to the host. */
41
+ readonly connecting: Signal<boolean>;
42
+ /** Whether the app is connected to the host. */
43
+ readonly connected: Signal<boolean>;
44
+ /** Connection error, if any. */
45
+ readonly error: Signal<Error | null>;
46
+ /** Whether the spec is still arriving: pass it to `<json-render [loading]>`. */
47
+ readonly loading: Signal<boolean>;
48
+ /** The underlying MCP Apps `App`. */
49
+ readonly app: App;
50
+ /**
51
+ * Call a tool on the MCP server and replace the spec with its result —
52
+ * for refresh and drill-down interactions.
53
+ */
54
+ callServerTool(name: string, args?: Record<string, unknown>): Promise<void>;
55
+ /**
56
+ * Post a user message to the host's chat, so the model answers what the
57
+ * user did in the view. `data`, if given, follows the text as a JSON block.
58
+ * Rejects when the host does not accept messages from views or turns this
59
+ * one down, so an action's `onError` runs.
60
+ */
61
+ sendMessage(text: string, data?: Record<string, unknown>): Promise<void>;
62
+ }
63
+ /** The text of a {@link JsonRenderApp.sendMessage} message. */
64
+ declare function messageText(text: string, data?: Record<string, unknown>): string;
65
+ interface ToolResultLike {
66
+ content?: {
67
+ type: string;
68
+ text?: string;
69
+ }[];
70
+ }
71
+ /**
72
+ * Read a spec out of a tool result. Same rule as `@json-render/mcp/app`: the
73
+ * first text block, parsed as JSON, either a bare spec or `{ spec }`.
74
+ */
75
+ declare function parseSpecFromToolResult(result: ToolResultLike): Spec | null;
76
+ /**
77
+ * Connect an Angular app running inside an MCP Apps iframe to its host and
78
+ * keep the json-render spec the model sent in a signal. The Angular
79
+ * counterpart of `useJsonRenderApp` from `@json-render/mcp/app`; the server
80
+ * side is `createMcpApp` from `@json-render/mcp`, unchanged.
81
+ *
82
+ * Call it in an injection context. The connection closes when the injector
83
+ * that created it is destroyed.
84
+ *
85
+ * ```ts
86
+ * readonly mcp = injectJsonRenderApp();
87
+ * // <json-render [spec]="mcp.spec()" [loading]="mcp.loading()" [registry]="registry" />
88
+ * ```
89
+ */
90
+ declare function injectJsonRenderApp(options?: JsonRenderAppOptions): JsonRenderApp;
91
+
92
+ export { injectJsonRenderApp, messageText, parseSpecFromToolResult };
93
+ export type { JsonRenderApp, JsonRenderAppOptions };
@@ -0,0 +1,74 @@
1
+ import * as _json_render_core from '@json-render/core';
2
+
3
+ /**
4
+ * The schema for ngx-json-render.
5
+ *
6
+ * Defines:
7
+ * - Spec: A flat tree of elements with keys, types, props, and children references
8
+ * - Catalog: Components with props schemas, and optional actions
9
+ *
10
+ * This is the same spec grammar the other json-render renderers use, so
11
+ * catalogs and specs are portable across frameworks.
12
+ */
13
+ declare const schema: _json_render_core.Schema<{
14
+ spec: _json_render_core.SchemaType<"object", {
15
+ /** Root element key */
16
+ root: _json_render_core.SchemaType<"string", unknown>;
17
+ /** Flat map of elements by key */
18
+ elements: _json_render_core.SchemaType<"record", _json_render_core.SchemaType<"object", {
19
+ /** Component type from catalog */
20
+ type: _json_render_core.SchemaType<"ref", string>;
21
+ /** Component props */
22
+ props: _json_render_core.SchemaType<"propsOf", string>;
23
+ /** Child element keys (flat reference) */
24
+ children: _json_render_core.SchemaType<"array", _json_render_core.SchemaType<"string", unknown>>;
25
+ /** Visibility condition */
26
+ visible: {
27
+ optional: true;
28
+ kind: "any";
29
+ inner?: unknown;
30
+ };
31
+ /** Repeat children from a state array */
32
+ repeat: {
33
+ optional: true;
34
+ kind: "any";
35
+ inner?: unknown;
36
+ };
37
+ }>>;
38
+ }>;
39
+ catalog: _json_render_core.SchemaType<"object", {
40
+ /** Component definitions */
41
+ components: _json_render_core.SchemaType<"map", {
42
+ /** Zod schema for component props */
43
+ props: _json_render_core.SchemaType<"zod", unknown>;
44
+ /** Slots for this component. Use ['default'] for children, or named slots like ['header', 'footer'] */
45
+ slots: _json_render_core.SchemaType<"array", _json_render_core.SchemaType<"string", unknown>>;
46
+ /** Description for AI generation hints */
47
+ description: _json_render_core.SchemaType<"string", unknown>;
48
+ /** Example prop values used in prompt examples (auto-generated from Zod schema if omitted) */
49
+ example: _json_render_core.SchemaType<"any", unknown>;
50
+ }>;
51
+ /** Action definitions (optional) */
52
+ actions: _json_render_core.SchemaType<"map", {
53
+ /** Zod schema for action params */
54
+ params: _json_render_core.SchemaType<"zod", unknown>;
55
+ /** Description for AI generation hints */
56
+ description: _json_render_core.SchemaType<"string", unknown>;
57
+ }>;
58
+ }>;
59
+ }>;
60
+ /**
61
+ * Type for the Angular schema
62
+ */
63
+ type AngularSchema = typeof schema;
64
+ /**
65
+ * Infer the spec type from a catalog
66
+ */
67
+ type AngularSpec<TCatalog> = typeof schema extends {
68
+ createCatalog: (catalog: TCatalog) => {
69
+ _specType: infer S;
70
+ };
71
+ } ? S : never;
72
+
73
+ export { schema };
74
+ export type { AngularSchema, AngularSpec };
@@ -4,6 +4,7 @@ export { ActionBinding, ActionHandler, InferActionParams, InferCatalogComponents
4
4
  import * as _angular_core from '@angular/core';
5
5
  import { Signal, Type, Injector, InjectionToken } from '@angular/core';
6
6
  import * as ngx_json_render from 'ngx-json-render';
7
+ export { AngularSchema, AngularSpec, schema } from 'ngx-json-render/schema';
7
8
 
8
9
  interface PendingConfirmation {
9
10
  action: ResolvedAction;
@@ -628,7 +629,16 @@ declare class JrElement {
628
629
  private readonly repeatScope;
629
630
  private readonly parentPath;
630
631
  private readonly devtoolsActive;
631
- /** The raw (unresolved) element from the spec. */
632
+ /**
633
+ * The raw (unresolved) element from the spec.
634
+ *
635
+ * Compared by content, not identity. A streamed patch shares every element
636
+ * it did not touch, and the identity check settles those at once; but a
637
+ * spec can also arrive as all-new objects — a whole-spec part, a host that
638
+ * fetches it again, `buildSpecFromParts` replaying a message — and then an
639
+ * element whose content is unchanged would resolve, and every container
640
+ * with a fresh `children` array re-render, for nothing.
641
+ */
632
642
  readonly rawElement: Signal<UIElement<string, Record<string, unknown>> | undefined>;
633
643
  /**
634
644
  * The state paths this element's expressions can read, or null when the
@@ -662,21 +672,30 @@ declare class JrElement {
662
672
  private readonly resolutionCtx;
663
673
  protected readonly visible: Signal<boolean>;
664
674
  /**
665
- * The element with all prop expressions resolved.
675
+ * How many state writes have touched a path this element is two-way bound
676
+ * to. See {@link resolution} for why those writes count on their own.
677
+ */
678
+ private readonly boundWrites;
679
+ /**
680
+ * The element with all prop expressions resolved, and the bound writes it
681
+ * was resolved after.
666
682
  *
667
- * Resolving builds a new props object on every state write, whatever the
668
- * write touched. Handing that on as a change would re-run every catalog
669
- * template in the tree for one keystroke, so a result that holds the same
670
- * values as the last one counts as unchanged and keeps the old object.
683
+ * Resolving builds a new props object every time, so a result that holds
684
+ * the same values as the last one counts as unchanged and keeps the old
685
+ * object; otherwise one keystroke would re-run every catalog template that
686
+ * happened to resolve.
671
687
  *
672
- * Two-way bound elements are the exception, and keep treating every
673
- * resolution as a change. Their component writes the user's input into the
674
- * DOM before it reaches state, so the DOM can differ from a prop whose
675
- * value never did: typing and a `clearStatePath` in the same turn take
676
- * the prop from '' through 'milk' back to '' with nobody reading 'milk'.
677
- * The README tells catalog authors to sync such inputs with an effect on
678
- * props, and that effect only gets to put the DOM right if it runs.
688
+ * A write to a path the element is bound to always counts, though. Its
689
+ * component writes the user's input into the DOM before it reaches state,
690
+ * so the DOM can differ from a prop whose value never did: typing and a
691
+ * `clearStatePath` in the same turn take the prop from '' through 'milk'
692
+ * back to '' with nobody reading 'milk'. The README tells catalog authors
693
+ * to sync such inputs with an effect on props, and that effect only gets to
694
+ * put the DOM right if it runs. Writes anywhere else compare by value, like
695
+ * any element's.
679
696
  */
697
+ private readonly resolution;
698
+ /** The element with all prop expressions resolved. */
680
699
  readonly resolvedElement: Signal<UIElement<string, Record<string, unknown>> | undefined>;
681
700
  /** Two-way binding paths ($bindState / $bindItem) by prop name. */
682
701
  readonly bindings: Signal<Record<string, string> | undefined>;
@@ -1327,81 +1346,11 @@ interface ChatUIReturn {
1327
1346
  */
1328
1347
  declare function injectChatUI(options: ChatUIOptions): ChatUIReturn;
1329
1348
 
1330
- /**
1331
- * The schema for ngx-json-render.
1332
- *
1333
- * Defines:
1334
- * - Spec: A flat tree of elements with keys, types, props, and children references
1335
- * - Catalog: Components with props schemas, and optional actions
1336
- *
1337
- * This is the same spec grammar the other json-render renderers use, so
1338
- * catalogs and specs are portable across frameworks.
1339
- */
1340
- declare const schema: _json_render_core.Schema<{
1341
- spec: _json_render_core.SchemaType<"object", {
1342
- /** Root element key */
1343
- root: _json_render_core.SchemaType<"string", unknown>;
1344
- /** Flat map of elements by key */
1345
- elements: _json_render_core.SchemaType<"record", _json_render_core.SchemaType<"object", {
1346
- /** Component type from catalog */
1347
- type: _json_render_core.SchemaType<"ref", string>;
1348
- /** Component props */
1349
- props: _json_render_core.SchemaType<"propsOf", string>;
1350
- /** Child element keys (flat reference) */
1351
- children: _json_render_core.SchemaType<"array", _json_render_core.SchemaType<"string", unknown>>;
1352
- /** Visibility condition */
1353
- visible: {
1354
- optional: true;
1355
- kind: "any";
1356
- inner?: unknown;
1357
- };
1358
- /** Repeat children from a state array */
1359
- repeat: {
1360
- optional: true;
1361
- kind: "any";
1362
- inner?: unknown;
1363
- };
1364
- }>>;
1365
- }>;
1366
- catalog: _json_render_core.SchemaType<"object", {
1367
- /** Component definitions */
1368
- components: _json_render_core.SchemaType<"map", {
1369
- /** Zod schema for component props */
1370
- props: _json_render_core.SchemaType<"zod", unknown>;
1371
- /** Slots for this component. Use ['default'] for children, or named slots like ['header', 'footer'] */
1372
- slots: _json_render_core.SchemaType<"array", _json_render_core.SchemaType<"string", unknown>>;
1373
- /** Description for AI generation hints */
1374
- description: _json_render_core.SchemaType<"string", unknown>;
1375
- /** Example prop values used in prompt examples (auto-generated from Zod schema if omitted) */
1376
- example: _json_render_core.SchemaType<"any", unknown>;
1377
- }>;
1378
- /** Action definitions (optional) */
1379
- actions: _json_render_core.SchemaType<"map", {
1380
- /** Zod schema for action params */
1381
- params: _json_render_core.SchemaType<"zod", unknown>;
1382
- /** Description for AI generation hints */
1383
- description: _json_render_core.SchemaType<"string", unknown>;
1384
- }>;
1385
- }>;
1386
- }>;
1387
- /**
1388
- * Type for the Angular schema
1389
- */
1390
- type AngularSchema = typeof schema;
1391
- /**
1392
- * Infer the spec type from a catalog
1393
- */
1394
- type AngularSpec<TCatalog> = typeof schema extends {
1395
- createCatalog: (catalog: TCatalog) => {
1396
- _specType: infer S;
1397
- };
1398
- } ? S : never;
1399
-
1400
1349
  /**
1401
1350
  * Reactive mirror of the json-render devtools-active flag. When active, the
1402
1351
  * renderer wraps each element with a `data-jr-key` attribute for the picker.
1403
1352
  */
1404
1353
  declare function injectDevtoolsActive(): Signal<boolean>;
1405
1354
 
1406
- export { CONFIRM_CONTEXT, ELEMENT_KEY, JR_CONFIRM_DIALOG, JR_CONFIRM_LABELS, JrChildren, JrConfirmDialog, JrElement, JrRepeatScope, JsonRenderActionsService, JsonRenderRootContext, JsonRenderStateService, JsonRenderValidationService, JsonRenderer, RENDER_CONTEXT, REPEAT_SCOPE, applyPatch, buildSpecFromParts, checkSpec, createStoreSetState, defineRegistry, flatToTree, formatSpecCheckIssues, getTextFromParts, injectAction, injectActions, injectBoundProp, injectChatUI, injectConfirmContext, injectDevtoolsActive, injectElementKey, injectFieldValidation, injectRenderContext, injectRepeatScope, injectStateBinding, injectStateStore, injectStateValue, injectUIStream, injectValidation, isActionCancelled, jsonRenderMessage, schema };
1407
- export type { ActionFn, Actions, AngularSchema, AngularSpec, CatalogHasActions, ChatMessage, ChatUIOptions, ChatUIReturn, ComponentRegistry, Components, ConfirmContext, ConfirmLabels, DataPart, DefineRegistryResult, EventHandle, FieldValidationState, PendingConfirmation, RegistryEntry, RenderContext, RenderLimits, RepeatScope, SetState, SpecCatalog, SpecCheck, SpecCheckIssue, SpecCheckIssueCode, SpecCheckOptions, SpecValidationMode, StateChange, TokenUsage, UIStreamOptions, UIStreamReturn, UIStreamSendOptions };
1355
+ export { CONFIRM_CONTEXT, ELEMENT_KEY, JR_CONFIRM_DIALOG, JR_CONFIRM_LABELS, JrChildren, JrConfirmDialog, JrElement, JrRepeatScope, JsonRenderActionsService, JsonRenderRootContext, JsonRenderStateService, JsonRenderValidationService, JsonRenderer, RENDER_CONTEXT, REPEAT_SCOPE, applyPatch, buildSpecFromParts, checkSpec, createStoreSetState, defineRegistry, flatToTree, formatSpecCheckIssues, getTextFromParts, injectAction, injectActions, injectBoundProp, injectChatUI, injectConfirmContext, injectDevtoolsActive, injectElementKey, injectFieldValidation, injectRenderContext, injectRepeatScope, injectStateBinding, injectStateStore, injectStateValue, injectUIStream, injectValidation, isActionCancelled, jsonRenderMessage };
1356
+ export type { ActionFn, Actions, CatalogHasActions, ChatMessage, ChatUIOptions, ChatUIReturn, ComponentRegistry, Components, ConfirmContext, ConfirmLabels, DataPart, DefineRegistryResult, EventHandle, FieldValidationState, PendingConfirmation, RegistryEntry, RenderContext, RenderLimits, RepeatScope, SetState, SpecCatalog, SpecCheck, SpecCheckIssue, SpecCheckIssueCode, SpecCheckOptions, SpecValidationMode, StateChange, TokenUsage, UIStreamOptions, UIStreamReturn, UIStreamSendOptions };