ngx-json-render 0.8.2 → 0.9.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/README.md +128 -5
- package/fesm2022/ngx-json-render-router.mjs +71 -0
- package/fesm2022/ngx-json-render-router.mjs.map +1 -0
- package/fesm2022/ngx-json-render.mjs +716 -514
- package/fesm2022/ngx-json-render.mjs.map +1 -1
- package/package.json +10 -2
- package/types/ngx-json-render-router.d.ts +39 -0
- package/types/ngx-json-render.d.ts +114 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ngx-json-render",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
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",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"zod": "^4.0.0",
|
|
29
29
|
"@modelcontextprotocol/ext-apps": "^1.7.5",
|
|
30
30
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
31
|
-
"@json-render/devtools": ">=0.20.0 <0.22.0"
|
|
31
|
+
"@json-render/devtools": ">=0.20.0 <0.22.0",
|
|
32
|
+
"@angular/router": ">=19.0.0"
|
|
32
33
|
},
|
|
33
34
|
"peerDependenciesMeta": {
|
|
34
35
|
"@modelcontextprotocol/ext-apps": {
|
|
@@ -39,6 +40,9 @@
|
|
|
39
40
|
},
|
|
40
41
|
"@json-render/devtools": {
|
|
41
42
|
"optional": true
|
|
43
|
+
},
|
|
44
|
+
"@angular/router": {
|
|
45
|
+
"optional": true
|
|
42
46
|
}
|
|
43
47
|
},
|
|
44
48
|
"dependencies": {
|
|
@@ -67,6 +71,10 @@
|
|
|
67
71
|
"types": "./types/ngx-json-render-mcp.d.ts",
|
|
68
72
|
"default": "./fesm2022/ngx-json-render-mcp.mjs"
|
|
69
73
|
},
|
|
74
|
+
"./router": {
|
|
75
|
+
"types": "./types/ngx-json-render-router.d.ts",
|
|
76
|
+
"default": "./fesm2022/ngx-json-render-router.mjs"
|
|
77
|
+
},
|
|
70
78
|
"./schema": {
|
|
71
79
|
"types": "./types/ngx-json-render-schema.d.ts",
|
|
72
80
|
"default": "./fesm2022/ngx-json-render-schema.mjs"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Which paths a spec may send the app to. */
|
|
2
|
+
interface RouterNavigateOptions {
|
|
3
|
+
/**
|
|
4
|
+
* The paths a spec may navigate to. A string must equal the path exactly; a
|
|
5
|
+
* `RegExp` is tested against it; a function decides on its own. The path is
|
|
6
|
+
* what comes before any `?` or `#`, so a query string or fragment neither
|
|
7
|
+
* helps nor hurts a match, and is passed on to the router as written.
|
|
8
|
+
*
|
|
9
|
+
* Required: a spec is model output, and the app is what knows which of its
|
|
10
|
+
* routes a generated UI has any business opening.
|
|
11
|
+
*/
|
|
12
|
+
readonly allow: readonly (string | RegExp)[] | ((path: string) => boolean);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A `navigate` for `<json-render>` that hands a spec's
|
|
16
|
+
* `onSuccess: { navigate }` path to the Angular `Router`, but only a path
|
|
17
|
+
* inside the app that `allow` lets through. Anything else is refused with a
|
|
18
|
+
* warning and goes nowhere.
|
|
19
|
+
*
|
|
20
|
+
* Call it in an injection context — in the function form of
|
|
21
|
+
* `provideJsonRender`, or in a field initializer:
|
|
22
|
+
*
|
|
23
|
+
* ```ts
|
|
24
|
+
* provideJsonRender(() => ({
|
|
25
|
+
* registry,
|
|
26
|
+
* navigate: injectRouterNavigate({ allow: ['/thanks', /^\/orders\/\d+$/] }),
|
|
27
|
+
* }));
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Whatever `allow` says, a path is refused unless it starts with a single
|
|
31
|
+
* `/`: no other origin (`https://…`, `//host`), no scheme (`javascript:…`),
|
|
32
|
+
* no path relative to wherever the user happens to be. A backslash or a
|
|
33
|
+
* control character refuses it too, since browsers read `/\host` as
|
|
34
|
+
* `//host`.
|
|
35
|
+
*/
|
|
36
|
+
declare function injectRouterNavigate(options: RouterNavigateOptions): (path: string) => void;
|
|
37
|
+
|
|
38
|
+
export { injectRouterNavigate };
|
|
39
|
+
export type { RouterNavigateOptions };
|
|
@@ -2,7 +2,7 @@ import * as _json_render_core from '@json-render/core';
|
|
|
2
2
|
import { ResolvedAction, ActionHandler, ActionBinding, SpecIssue, Spec, Catalog, InferCatalogActions, InferActionParams, StateModel, InferCatalogComponents, UIElement, StateStore, ValidationFunction, ComputedFunction, DirectiveDefinition, ActionConfirm, DirectiveRegistry, ValidationResult, ValidationConfig, JsonPatch, FlatElement } from '@json-render/core';
|
|
3
3
|
export { ActionBinding, ActionHandler, InferActionParams, InferCatalogComponents, InferComponentProps, JsonPatch, Spec, SpecIssue, StateModel, StateStore, UIElement, VisibilityCondition, autoFixSpec, createStateStore, formatSpecIssues, nestedToFlat, validateSpec } from '@json-render/core';
|
|
4
4
|
import * as _angular_core from '@angular/core';
|
|
5
|
-
import { Signal, Type, Injector, InjectionToken } from '@angular/core';
|
|
5
|
+
import { Signal, Type, Injector, InjectionToken, Provider } from '@angular/core';
|
|
6
6
|
import * as ngx_json_render from 'ngx-json-render';
|
|
7
7
|
export { AngularSchema, AngularSpec, schema } from 'ngx-json-render/schema';
|
|
8
8
|
|
|
@@ -319,6 +319,14 @@ interface RegistryEntry {
|
|
|
319
319
|
component: Type<unknown>;
|
|
320
320
|
/** Slot names this component supports (from the catalog definition). */
|
|
321
321
|
slots?: string[];
|
|
322
|
+
/**
|
|
323
|
+
* Shown instead of `component` while the spec streams and this element's
|
|
324
|
+
* props do not yet pass its component's schema in the renderer's
|
|
325
|
+
* `catalog`. It gets the same render context, so it can read the props
|
|
326
|
+
* that have arrived and place `<jr-children />`. Without one, the element
|
|
327
|
+
* renders nothing until it is ready.
|
|
328
|
+
*/
|
|
329
|
+
fallback?: Type<unknown>;
|
|
322
330
|
}
|
|
323
331
|
/**
|
|
324
332
|
* Registry of component renderers: catalog type name → Angular component
|
|
@@ -327,10 +335,11 @@ interface RegistryEntry {
|
|
|
327
335
|
type ComponentRegistry = Record<string, Type<unknown> | RegistryEntry>;
|
|
328
336
|
/**
|
|
329
337
|
* Registry of all Angular components for a catalog. Keys are checked against
|
|
330
|
-
* the catalog's component names.
|
|
338
|
+
* the catalog's component names. A value is the component, or the component
|
|
339
|
+
* with a {@link RegistryEntry.fallback} to show while its props stream in.
|
|
331
340
|
*/
|
|
332
341
|
type Components<C extends Catalog> = {
|
|
333
|
-
[K in keyof InferCatalogComponents<C>]: Type<unknown>;
|
|
342
|
+
[K in keyof InferCatalogComponents<C>]: Type<unknown> | Pick<RegistryEntry, 'component' | 'fallback'>;
|
|
334
343
|
};
|
|
335
344
|
/**
|
|
336
345
|
* The repeat scope available to elements rendered inside a `repeat` block.
|
|
@@ -469,8 +478,11 @@ declare function injectBoundProp<T>(propValue: () => T | undefined, bindingPath:
|
|
|
469
478
|
declare class JsonRenderer {
|
|
470
479
|
/** The UI spec to render (may be partial while streaming). */
|
|
471
480
|
readonly spec: _angular_core.InputSignal<Spec | null>;
|
|
472
|
-
/**
|
|
473
|
-
|
|
481
|
+
/**
|
|
482
|
+
* Component registry mapping catalog type names to Angular components.
|
|
483
|
+
* Required unless a {@link provideJsonRender} above supplies one.
|
|
484
|
+
*/
|
|
485
|
+
readonly registry: _angular_core.InputSignal<ComponentRegistry | undefined>;
|
|
474
486
|
/** Whether the spec is currently loading/streaming. */
|
|
475
487
|
readonly loading: _angular_core.InputSignal<boolean>;
|
|
476
488
|
/** Fallback component for unknown types. */
|
|
@@ -487,7 +499,7 @@ declare class JsonRenderer {
|
|
|
487
499
|
* The check is skipped while `loading` is true: a spec that is still
|
|
488
500
|
* arriving is expected to reference children that have not streamed in yet.
|
|
489
501
|
*/
|
|
490
|
-
readonly validate: _angular_core.InputSignal<SpecValidationMode>;
|
|
502
|
+
readonly validate: _angular_core.InputSignal<SpecValidationMode | undefined>;
|
|
491
503
|
/**
|
|
492
504
|
* Caps on what the spec may cost the browser: `maxElements`, `maxDepth` and
|
|
493
505
|
* `maxRepeatItems`. Unset by default, and each field is independently
|
|
@@ -509,8 +521,14 @@ declare class JsonRenderer {
|
|
|
509
521
|
* `$bindState`, `$template`, a directive — has no value until render time,
|
|
510
522
|
* so it is not checked.
|
|
511
523
|
*
|
|
512
|
-
*
|
|
513
|
-
* skipped while `loading`.
|
|
524
|
+
* The check is read only when `validate` is on, and — like the rest of
|
|
525
|
+
* it — skipped while `loading`.
|
|
526
|
+
*
|
|
527
|
+
* While `loading`, the catalog also gates mounting, whatever `validate` is:
|
|
528
|
+
* an element whose props do not yet pass its component's schema shows its
|
|
529
|
+
* registry entry's `fallback`, or nothing, instead of a component with half
|
|
530
|
+
* its props. Once an element has mounted it stays mounted, and when
|
|
531
|
+
* `loading` ends every element mounts.
|
|
514
532
|
*/
|
|
515
533
|
readonly catalog: _angular_core.InputSignal<SpecCatalog | null>;
|
|
516
534
|
/**
|
|
@@ -538,6 +556,15 @@ declare class JsonRenderer {
|
|
|
538
556
|
readonly stateStore: JsonRenderStateService;
|
|
539
557
|
/** The action dispatcher of this renderer. */
|
|
540
558
|
protected readonly actions: JsonRenderActionsService;
|
|
559
|
+
/**
|
|
560
|
+
* The nearest {@link provideJsonRender}'s defaults. Every option input
|
|
561
|
+
* falls through to these when left `null` or `undefined`; see
|
|
562
|
+
* {@link JsonRenderConfig} for the merge rules.
|
|
563
|
+
*/
|
|
564
|
+
private readonly config;
|
|
565
|
+
private readonly mode;
|
|
566
|
+
private readonly limits;
|
|
567
|
+
private readonly specCatalog;
|
|
541
568
|
/**
|
|
542
569
|
* The spec as checked, and what the check found. While `loading`, the mode
|
|
543
570
|
* is forced off: the spec is still arriving, and the missing children it
|
|
@@ -562,7 +589,7 @@ declare class JsonRenderer {
|
|
|
562
589
|
*/
|
|
563
590
|
protected readonly confirmInjector: _angular_core.Signal<Injector | null>;
|
|
564
591
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<JsonRenderer, never>;
|
|
565
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<JsonRenderer, "json-render", never, { "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "registry": { "alias": "registry"; "required":
|
|
592
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<JsonRenderer, "json-render", never, { "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "registry": { "alias": "registry"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "fallback": { "alias": "fallback"; "required": false; "isSignal": true; }; "validate": { "alias": "validate"; "required": false; "isSignal": true; }; "renderLimits": { "alias": "renderLimits"; "required": false; "isSignal": true; }; "catalog": { "alias": "catalog"; "required": false; "isSignal": true; }; "state": { "alias": "state"; "required": false; "isSignal": true; }; "store": { "alias": "store"; "required": false; "isSignal": true; }; "handlers": { "alias": "handlers"; "required": false; "isSignal": true; }; "onAction": { "alias": "onAction"; "required": false; "isSignal": true; }; "navigate": { "alias": "navigate"; "required": false; "isSignal": true; }; "validationFunctions": { "alias": "validationFunctions"; "required": false; "isSignal": true; }; "functions": { "alias": "functions"; "required": false; "isSignal": true; }; "directives": { "alias": "directives"; "required": false; "isSignal": true; }; }, { "stateChange": "stateChange"; }, never, never, true, never>;
|
|
566
593
|
}
|
|
567
594
|
|
|
568
595
|
/**
|
|
@@ -700,6 +727,21 @@ declare class JrElement {
|
|
|
700
727
|
/** Two-way binding paths ($bindState / $bindItem) by prop name. */
|
|
701
728
|
readonly bindings: Signal<Record<string, string> | undefined>;
|
|
702
729
|
private readonly entry;
|
|
730
|
+
/** Set once the real component has been shown; see {@link held}. */
|
|
731
|
+
private mounted;
|
|
732
|
+
/**
|
|
733
|
+
* Whether the component waits for its props: the spec is still loading, a
|
|
734
|
+
* catalog was given, and the props written so far do not pass the
|
|
735
|
+
* component's schema (see {@link propsArrived}).
|
|
736
|
+
*
|
|
737
|
+
* One-way. Once the component has been shown it is never swapped back for
|
|
738
|
+
* the fallback, even if a later patch takes a prop away again: a component
|
|
739
|
+
* flickering out mid-stream is worse than one showing a gap. Once latched
|
|
740
|
+
* this reads no signals, so a mounted element pays nothing for the gate on
|
|
741
|
+
* later patches — and neither does any element when nothing is loading.
|
|
742
|
+
*/
|
|
743
|
+
protected readonly held: Signal<boolean>;
|
|
744
|
+
/** What the outlet shows: the component, or its fallback while held. */
|
|
703
745
|
protected readonly component: Signal<_angular_core.Type<unknown> | null>;
|
|
704
746
|
protected readonly devtoolsKey: Signal<string | null>;
|
|
705
747
|
/**
|
|
@@ -858,6 +900,62 @@ declare const JR_CONFIRM_DIALOG: InjectionToken<Type<unknown>>;
|
|
|
858
900
|
/** Inject the confirmation a replacement dialog component is rendering for. */
|
|
859
901
|
declare function injectConfirmContext(): ConfirmContext;
|
|
860
902
|
|
|
903
|
+
/**
|
|
904
|
+
* Renderer defaults for every `<json-render>` below a provider: each field is
|
|
905
|
+
* the input of the same name.
|
|
906
|
+
*
|
|
907
|
+
* An input bound on the element wins over the provided value, and a value
|
|
908
|
+
* left `null` or `undefined` on the element falls through to it. Named
|
|
909
|
+
* vocabularies — `handlers`, `functions`, `validationFunctions` and
|
|
910
|
+
* `directives` — merge by name instead, the element's entry winning a name
|
|
911
|
+
* both define. Everything else replaces: a `registry` belongs to its catalog,
|
|
912
|
+
* so two are never mixed behind your back (spread them yourself to combine).
|
|
913
|
+
*/
|
|
914
|
+
interface JsonRenderConfig {
|
|
915
|
+
registry?: ComponentRegistry;
|
|
916
|
+
fallback?: Type<unknown> | RegistryEntry | null;
|
|
917
|
+
validate?: SpecValidationMode;
|
|
918
|
+
renderLimits?: RenderLimits | null;
|
|
919
|
+
catalog?: SpecCatalog | null;
|
|
920
|
+
handlers?: Record<string, ActionHandler>;
|
|
921
|
+
onAction?: ((name: string, params?: Record<string, unknown>) => unknown) | null;
|
|
922
|
+
navigate?: ((path: string) => void) | null;
|
|
923
|
+
validationFunctions?: Record<string, ValidationFunction>;
|
|
924
|
+
functions?: Record<string, ComputedFunction>;
|
|
925
|
+
directives?: DirectiveDefinition<any>[];
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* The defaults the nearest {@link provideJsonRender} supplies, already merged
|
|
929
|
+
* with any provider above it.
|
|
930
|
+
*/
|
|
931
|
+
declare const JSON_RENDER_CONFIG: InjectionToken<JsonRenderConfig>;
|
|
932
|
+
/**
|
|
933
|
+
* Set renderer defaults once instead of on every `<json-render>`:
|
|
934
|
+
*
|
|
935
|
+
* ```ts
|
|
936
|
+
* bootstrapApplication(App, { providers: [provideJsonRender({ registry })] });
|
|
937
|
+
* ```
|
|
938
|
+
*
|
|
939
|
+
* ```html
|
|
940
|
+
* <json-render [spec]="m.spec" />
|
|
941
|
+
* ```
|
|
942
|
+
*
|
|
943
|
+
* Pass a function to build the defaults with `inject()`, for handlers that
|
|
944
|
+
* call your services:
|
|
945
|
+
*
|
|
946
|
+
* ```ts
|
|
947
|
+
* provideJsonRender(() => {
|
|
948
|
+
* const orders = inject(OrderService);
|
|
949
|
+
* return { registry, handlers: { cancelOrder: (p) => orders.cancel(p['id']) } };
|
|
950
|
+
* });
|
|
951
|
+
* ```
|
|
952
|
+
*
|
|
953
|
+
* Works in application, route and component `providers`. A provider below
|
|
954
|
+
* another extends it with the same rules an element input does: its own
|
|
955
|
+
* values replace, its named vocabularies merge.
|
|
956
|
+
*/
|
|
957
|
+
declare function provideJsonRender(config: JsonRenderConfig | (() => JsonRenderConfig)): Provider[];
|
|
958
|
+
|
|
861
959
|
/**
|
|
862
960
|
* The render context of the element currently being rendered.
|
|
863
961
|
* Provided by the renderer for every catalog component instance.
|
|
@@ -926,6 +1024,11 @@ declare class JsonRenderRootContext {
|
|
|
926
1024
|
* they apply whatever `validate` is set to.
|
|
927
1025
|
*/
|
|
928
1026
|
limits: Signal<RenderLimits | null | undefined>;
|
|
1027
|
+
/**
|
|
1028
|
+
* The catalog the spec was generated for. While loading, an element whose
|
|
1029
|
+
* props do not pass its component's schema waits for them.
|
|
1030
|
+
*/
|
|
1031
|
+
catalog: Signal<SpecCatalog | null | undefined>;
|
|
929
1032
|
/** External store (controlled mode). */
|
|
930
1033
|
store: Signal<StateStore | null | undefined>;
|
|
931
1034
|
/** Initial state (uncontrolled mode); falls back to `spec.state`. */
|
|
@@ -1382,5 +1485,5 @@ declare function injectChatUI(options: ChatUIOptions): ChatUIReturn;
|
|
|
1382
1485
|
*/
|
|
1383
1486
|
declare function injectDevtoolsActive(): Signal<boolean>;
|
|
1384
1487
|
|
|
1385
|
-
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, ɵregisterStreamObserver };
|
|
1386
|
-
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, StreamObserver, StreamObserverUsage, TokenUsage, UIStreamOptions, UIStreamReturn, UIStreamSendOptions };
|
|
1488
|
+
export { CONFIRM_CONTEXT, ELEMENT_KEY, JR_CONFIRM_DIALOG, JR_CONFIRM_LABELS, JSON_RENDER_CONFIG, 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, provideJsonRender, ɵregisterStreamObserver };
|
|
1489
|
+
export type { ActionFn, Actions, CatalogHasActions, ChatMessage, ChatUIOptions, ChatUIReturn, ComponentRegistry, Components, ConfirmContext, ConfirmLabels, DataPart, DefineRegistryResult, EventHandle, FieldValidationState, JsonRenderConfig, PendingConfirmation, RegistryEntry, RenderContext, RenderLimits, RepeatScope, SetState, SpecCatalog, SpecCheck, SpecCheckIssue, SpecCheckIssueCode, SpecCheckOptions, SpecValidationMode, StateChange, StreamObserver, StreamObserverUsage, TokenUsage, UIStreamOptions, UIStreamReturn, UIStreamSendOptions };
|