ngx-json-render 0.3.0 → 0.5.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/README.md +146 -20
- package/fesm2022/ngx-json-render-testing.mjs +232 -56
- package/fesm2022/ngx-json-render-testing.mjs.map +1 -1
- package/fesm2022/ngx-json-render.mjs +516 -49
- package/fesm2022/ngx-json-render.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ngx-json-render-testing.d.ts +110 -17
- package/types/ngx-json-render.d.ts +223 -14
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Spec, StateStore, ActionHandler, ComputedFunction, ValidationFunction, DirectiveDefinition } from '@json-render/core';
|
|
2
|
-
import {
|
|
2
|
+
import { Provider, Type } from '@angular/core';
|
|
3
3
|
import { ComponentFixture } from '@angular/core/testing';
|
|
4
|
-
import { ComponentRegistry, StateModel, RegistryEntry, JsonRenderer, JsonRenderStateService, JsonRenderValidationService, StateChange } from 'ngx-json-render';
|
|
4
|
+
import { RenderContext, ComponentRegistry, StateModel, RegistryEntry, JsonRenderer, JsonRenderStateService, JsonRenderValidationService, StateChange } from 'ngx-json-render';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* The lines of one recorded response body, in the order the server sent them,
|
|
@@ -85,6 +85,111 @@ declare function usageLine(usage: {
|
|
|
85
85
|
totalTokens?: number;
|
|
86
86
|
}): string;
|
|
87
87
|
|
|
88
|
+
/** The DOM half of a harness. */
|
|
89
|
+
interface DomQueries {
|
|
90
|
+
/** Trimmed text of the first match, or of everything when given nothing. */
|
|
91
|
+
text(selector?: string): string;
|
|
92
|
+
/** Trimmed text of every match. */
|
|
93
|
+
texts(selector: string): string[];
|
|
94
|
+
/** The first match. Throws when there is none. */
|
|
95
|
+
find<T extends HTMLElement>(selector: string): T;
|
|
96
|
+
/** Every match, possibly none. */
|
|
97
|
+
findAll<T extends HTMLElement>(selector: string): T[];
|
|
98
|
+
/** Click an element (or the first match of a selector) and settle. */
|
|
99
|
+
click(target: string | Element): Promise<void>;
|
|
100
|
+
/** Set an input's value, fire `input`, and settle. */
|
|
101
|
+
fill(target: string | Element, value: string): Promise<void>;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** One `setBound` call that reached a bound prop, in order. */
|
|
105
|
+
interface BoundWrite {
|
|
106
|
+
prop: string;
|
|
107
|
+
value: unknown;
|
|
108
|
+
}
|
|
109
|
+
/** Options for {@link renderComponent}. Everything is optional. */
|
|
110
|
+
interface RenderComponentOptions<P extends object> {
|
|
111
|
+
/** The resolved props the component sees. Defaults to `{}`. */
|
|
112
|
+
props?: P;
|
|
113
|
+
/**
|
|
114
|
+
* Which props are two-way bound, as `prop → state path` — what
|
|
115
|
+
* `$bindState` / `$bindItem` would have resolved to. A `setBound` on a prop
|
|
116
|
+
* listed here is recorded and written back into `props`; on any other prop
|
|
117
|
+
* it is a no-op, exactly as under the renderer.
|
|
118
|
+
*/
|
|
119
|
+
bindings?: Record<string, string>;
|
|
120
|
+
/**
|
|
121
|
+
* The events the spec would bind in `on`. Only affects what `ctx.on(event)`
|
|
122
|
+
* reports as `bound` — `emitted` records every event regardless.
|
|
123
|
+
*/
|
|
124
|
+
on?: readonly string[];
|
|
125
|
+
/** The loading flag the component sees. */
|
|
126
|
+
loading?: boolean;
|
|
127
|
+
/** The spec key, for components that `injectElementKey()`. */
|
|
128
|
+
key?: string;
|
|
129
|
+
/** The element's catalog type name. */
|
|
130
|
+
type?: string;
|
|
131
|
+
/** Extra TestBed providers for anything else the component injects. */
|
|
132
|
+
providers?: Provider[];
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* A catalog component mounted on its own, and what it said to the renderer
|
|
136
|
+
* it thinks it is inside.
|
|
137
|
+
*/
|
|
138
|
+
interface ComponentHarness<T, P extends object> extends DomQueries {
|
|
139
|
+
/** The fixture of the host the component is mounted in. */
|
|
140
|
+
readonly fixture: ComponentFixture<unknown>;
|
|
141
|
+
/** The host element, the root of the rendered DOM. */
|
|
142
|
+
readonly element: HTMLElement;
|
|
143
|
+
/** The component instance. */
|
|
144
|
+
readonly component: T;
|
|
145
|
+
/** The render context the component injected. */
|
|
146
|
+
readonly context: RenderContext<P>;
|
|
147
|
+
/** Every event the component emitted, bound or not, in order. */
|
|
148
|
+
readonly emitted: readonly string[];
|
|
149
|
+
/** Every `setBound` that reached a bound prop, in order. */
|
|
150
|
+
readonly writes: readonly BoundWrite[];
|
|
151
|
+
/** The props as the component currently sees them. */
|
|
152
|
+
props(): P;
|
|
153
|
+
/** Replace the props and settle. */
|
|
154
|
+
setProps(props: P): Promise<void>;
|
|
155
|
+
/** Merge into the props and settle. */
|
|
156
|
+
patchProps(patch: Partial<P>): Promise<void>;
|
|
157
|
+
/** Flip the loading flag and settle. */
|
|
158
|
+
setLoading(loading: boolean): Promise<void>;
|
|
159
|
+
/** Let effects, promises and change detection finish. */
|
|
160
|
+
settle(): Promise<void>;
|
|
161
|
+
/** Destroy the fixture. Rarely needed — TestBed resets between tests. */
|
|
162
|
+
destroy(): void;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Mount a catalog component with no renderer and no spec: hand it props, and
|
|
166
|
+
* read back the events it emitted and the values it wrote to bound props.
|
|
167
|
+
*
|
|
168
|
+
* This is the test of a component as a presentational one — what it draws
|
|
169
|
+
* for these props, and what it says when used. What the spec then does with
|
|
170
|
+
* that is the renderer's business, and `renderSpec` is where to test it.
|
|
171
|
+
*
|
|
172
|
+
* `props` is not inferred from the first value, so a later `patchProps` can
|
|
173
|
+
* set a prop the first render left out. Pass `P` to have the props typed.
|
|
174
|
+
*
|
|
175
|
+
* A component that renders `<jr-children>`, registers field validation or
|
|
176
|
+
* dispatches actions directly needs the renderer's services and fails with a
|
|
177
|
+
* message pointing at `renderSpec`.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* const button = await renderComponent(MyButton, { props: { label: 'Save' } });
|
|
182
|
+
*
|
|
183
|
+
* expect(button.text('button')).toBe('Save');
|
|
184
|
+
* await button.click('button');
|
|
185
|
+
* expect(button.emitted).toEqual(['press']);
|
|
186
|
+
*
|
|
187
|
+
* await button.patchProps({ disabled: true });
|
|
188
|
+
* expect(button.find<HTMLButtonElement>('button').disabled).toBe(true);
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
declare function renderComponent<T, P extends object = Record<string, unknown>>(component: Type<T>, options?: RenderComponentOptions<NoInfer<P>>): Promise<ComponentHarness<T, P>>;
|
|
192
|
+
|
|
88
193
|
/** One action the spec asked for, in the order it was dispatched. */
|
|
89
194
|
interface DispatchedAction {
|
|
90
195
|
name: string;
|
|
@@ -123,7 +228,7 @@ interface RenderSpecOptions {
|
|
|
123
228
|
* `fixture` and `element` are there for everything this does not cover — the
|
|
124
229
|
* harness is a shortcut, not a wall.
|
|
125
230
|
*/
|
|
126
|
-
interface SpecHarness {
|
|
231
|
+
interface SpecHarness extends DomQueries {
|
|
127
232
|
/** The fixture of the host that owns the `<json-render>`. */
|
|
128
233
|
readonly fixture: ComponentFixture<unknown>;
|
|
129
234
|
/** The host element, the root of the rendered DOM. */
|
|
@@ -150,18 +255,6 @@ interface SpecHarness {
|
|
|
150
255
|
write(path: string, value: unknown): Promise<void>;
|
|
151
256
|
/** The whole state model. */
|
|
152
257
|
state(): StateModel;
|
|
153
|
-
/** Trimmed text of the first match, or of everything when given nothing. */
|
|
154
|
-
text(selector?: string): string;
|
|
155
|
-
/** Trimmed text of every match. */
|
|
156
|
-
texts(selector: string): string[];
|
|
157
|
-
/** The first match. Throws when there is none. */
|
|
158
|
-
find<T extends HTMLElement>(selector: string): T;
|
|
159
|
-
/** Every match, possibly none. */
|
|
160
|
-
findAll<T extends HTMLElement>(selector: string): T[];
|
|
161
|
-
/** Click an element (or the first match of a selector) and settle. */
|
|
162
|
-
click(target: string | Element): Promise<void>;
|
|
163
|
-
/** Set an input's value, fire `input`, and settle. */
|
|
164
|
-
fill(target: string | Element, value: string): Promise<void>;
|
|
165
258
|
/** Destroy the fixture. Rarely needed — TestBed resets between tests. */
|
|
166
259
|
destroy(): void;
|
|
167
260
|
}
|
|
@@ -193,5 +286,5 @@ interface SpecHarness {
|
|
|
193
286
|
*/
|
|
194
287
|
declare function renderSpec(spec: Spec | null, options: RenderSpecOptions): Promise<SpecHarness>;
|
|
195
288
|
|
|
196
|
-
export { recordedTransport, renderSpec, specStream, usageLine };
|
|
197
|
-
export type { DispatchedAction, RecordedFailure, RecordedTransportOptions, Recording, Recordings, RenderSpecOptions, SpecHarness };
|
|
289
|
+
export { recordedTransport, renderComponent, renderSpec, specStream, usageLine };
|
|
290
|
+
export type { BoundWrite, ComponentHarness, DispatchedAction, RecordedFailure, RecordedTransportOptions, Recording, Recordings, RenderComponentOptions, RenderSpecOptions, SpecHarness };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _json_render_core from '@json-render/core';
|
|
2
|
-
import { ResolvedAction, ActionHandler, ActionBinding,
|
|
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, JsonPatch, Spec, SpecIssue, StateModel, StateStore, UIElement, VisibilityCondition, autoFixSpec, createStateStore, formatSpecIssues, nestedToFlat, validateSpec } from '@json-render/core';
|
|
4
4
|
import * as zod from 'zod';
|
|
5
5
|
import * as zod_v4_core from 'zod/v4/core';
|
|
@@ -69,6 +69,93 @@ declare function injectAction(binding: ActionBinding): {
|
|
|
69
69
|
isLoading: Signal<boolean>;
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Caps on what a spec is allowed to cost the browser.
|
|
74
|
+
*
|
|
75
|
+
* A spec is attacker-shaped input: whatever produced one chose its own size,
|
|
76
|
+
* its own nesting and — through `repeat` — its own array lengths. These are
|
|
77
|
+
* the three of those the renderer can enforce for you.
|
|
78
|
+
*
|
|
79
|
+
* Every field is opt-in and unset means unlimited. There are no defaults
|
|
80
|
+
* because no single number is right for every catalog, and a default would
|
|
81
|
+
* change what an existing app renders the moment it upgraded.
|
|
82
|
+
*
|
|
83
|
+
* Limits are enforced whenever they are set, whatever `validate` is: a number
|
|
84
|
+
* the app chose is a control, not advice. What "enforced" means differs by
|
|
85
|
+
* limit, because the limits differ in kind — see each field.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```html
|
|
89
|
+
* <json-render
|
|
90
|
+
* [spec]="spec()"
|
|
91
|
+
* [registry]="registry"
|
|
92
|
+
* [renderLimits]="{ maxElements: 500, maxDepth: 16, maxRepeatItems: 200 }"
|
|
93
|
+
* />
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
interface RenderLimits {
|
|
97
|
+
/**
|
|
98
|
+
* Most elements a spec may contain. A spec over the cap does not render at
|
|
99
|
+
* all: element count is a property of the whole spec, and there is no
|
|
100
|
+
* meaningful "first 500 elements" of a graph.
|
|
101
|
+
*/
|
|
102
|
+
readonly maxElements?: number;
|
|
103
|
+
/**
|
|
104
|
+
* Deepest the render tree may nest, counting the root as 1. An element
|
|
105
|
+
* below the cap does not render, and neither does anything under it; what
|
|
106
|
+
* fits still renders. Reported as an error, so `validate="strict"` refuses
|
|
107
|
+
* the spec outright rather than truncating it.
|
|
108
|
+
*
|
|
109
|
+
* A capped element does not act either — its `watch` stays unwired, so it
|
|
110
|
+
* cannot dispatch actions from behind the cap.
|
|
111
|
+
*/
|
|
112
|
+
readonly maxDepth?: number;
|
|
113
|
+
/**
|
|
114
|
+
* Most items one `repeat` may expand. The surplus items do not render.
|
|
115
|
+
*
|
|
116
|
+
* Enforced at render time only: `repeat` iterates a live state array, so no
|
|
117
|
+
* amount of inspecting the spec can predict how long it will be. Nested
|
|
118
|
+
* repeats multiply, so this is a per-repeat cap, not a total.
|
|
119
|
+
*/
|
|
120
|
+
readonly maxRepeatItems?: number;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Issue codes this package reports, widening core's set with the ones only a
|
|
124
|
+
* renderer can find.
|
|
125
|
+
*
|
|
126
|
+
* - `cycle` — an element renders itself against the same data, which cannot
|
|
127
|
+
* terminate. A tree that recurses into its items is not this.
|
|
128
|
+
* - `too_deep` / `too_many_elements` — a {@link RenderLimits} cap was passed.
|
|
129
|
+
* - `unknown_component` — a `type` the catalog does not define.
|
|
130
|
+
* - `invalid_props` — the catalog's own schema rejected part of the spec.
|
|
131
|
+
*/
|
|
132
|
+
type SpecCheckIssueCode = SpecIssue['code'] | 'cycle' | 'too_deep' | 'too_many_elements' | 'unknown_component' | 'invalid_props';
|
|
133
|
+
/**
|
|
134
|
+
* A problem found in a spec. Core's {@link SpecIssue} widened with the codes
|
|
135
|
+
* above, so a {@link SpecIssue} is always one of these.
|
|
136
|
+
*/
|
|
137
|
+
interface SpecCheckIssue {
|
|
138
|
+
readonly severity: 'error' | 'warning';
|
|
139
|
+
readonly message: string;
|
|
140
|
+
readonly elementKey?: string;
|
|
141
|
+
readonly code: SpecCheckIssueCode;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* The part of a json-render `Catalog` the check needs.
|
|
145
|
+
*
|
|
146
|
+
* Structural on purpose: a real catalog satisfies it, and the renderer stays
|
|
147
|
+
* free of any dependency on the schema library behind `validate`.
|
|
148
|
+
*/
|
|
149
|
+
interface SpecCatalog {
|
|
150
|
+
/** Component type names the catalog defines. */
|
|
151
|
+
readonly componentNames: readonly string[];
|
|
152
|
+
/** Check a spec against the catalog's own schema. */
|
|
153
|
+
validate(spec: unknown): {
|
|
154
|
+
readonly success: boolean;
|
|
155
|
+
readonly error?: unknown;
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
72
159
|
/**
|
|
73
160
|
* How much a spec has to be trusted.
|
|
74
161
|
*
|
|
@@ -77,8 +164,24 @@ declare function injectAction(binding: ActionBinding): {
|
|
|
77
164
|
* - `warn` — check the spec, apply the lossless fixes, report what is left,
|
|
78
165
|
* render it anyway.
|
|
79
166
|
* - `strict` — the same check, but an error means the spec does not render.
|
|
167
|
+
*
|
|
168
|
+
* This governs *reporting* and strict refusal. {@link RenderLimits} are a
|
|
169
|
+
* separate axis: a limit the app set is enforced in every mode, including
|
|
170
|
+
* `off`.
|
|
80
171
|
*/
|
|
81
172
|
type SpecValidationMode = 'off' | 'warn' | 'strict';
|
|
173
|
+
/** Everything {@link checkSpec} needs beyond the spec and the mode. */
|
|
174
|
+
interface SpecCheckOptions {
|
|
175
|
+
/** Caps on the spec's size, enforced whatever the mode. */
|
|
176
|
+
readonly limits?: RenderLimits | null;
|
|
177
|
+
/**
|
|
178
|
+
* The catalog the spec was generated for. Given one, the check also reports
|
|
179
|
+
* component types the catalog does not define and props its own schema
|
|
180
|
+
* rejects — the half of "is this spec renderable" that structure alone
|
|
181
|
+
* cannot answer.
|
|
182
|
+
*/
|
|
183
|
+
readonly catalog?: SpecCatalog | null;
|
|
184
|
+
}
|
|
82
185
|
/** What {@link checkSpec} found, and the spec that should render. */
|
|
83
186
|
interface SpecCheck {
|
|
84
187
|
/**
|
|
@@ -86,23 +189,41 @@ interface SpecCheck {
|
|
|
86
189
|
* untouched when validation is off.
|
|
87
190
|
*/
|
|
88
191
|
readonly spec: Spec | null;
|
|
89
|
-
/** Structural issues left after the fixes. */
|
|
90
|
-
readonly issues: readonly
|
|
192
|
+
/** Structural, limit and catalog issues left after the fixes. */
|
|
193
|
+
readonly issues: readonly SpecCheckIssue[];
|
|
91
194
|
/** Descriptions of the fixes that were applied. */
|
|
92
195
|
readonly fixes: readonly string[];
|
|
93
196
|
/** Whether an issue of `error` severity survived. */
|
|
94
197
|
readonly hasErrors: boolean;
|
|
198
|
+
/**
|
|
199
|
+
* Whether the spec is refused outright, in every mode, for breaching an
|
|
200
|
+
* enforced limit. Distinct from {@link hasErrors}, which only stops a spec
|
|
201
|
+
* under `strict`.
|
|
202
|
+
*/
|
|
203
|
+
readonly blocked: boolean;
|
|
95
204
|
}
|
|
96
205
|
/**
|
|
97
|
-
* Check a spec the way `validate`
|
|
206
|
+
* Check a spec the way `validate` and `renderLimits` ask for.
|
|
98
207
|
*
|
|
99
208
|
* Only lossless fixes are applied — `visible`, `on` and `repeat` that a model
|
|
100
209
|
* put inside `props`, which the renderer would otherwise ignore, moved back
|
|
101
210
|
* where they belong. The lossy ones prune content, and core's own guidance is
|
|
102
211
|
* to re-prompt rather than accept that; a renderer that silently deleted
|
|
103
212
|
* elements would be the worse failure.
|
|
213
|
+
*
|
|
214
|
+
* Note what is *not* here: cycles are broken as the tree renders, whatever
|
|
215
|
+
* this returns, because a spec that never stops rendering is a crash rather
|
|
216
|
+
* than an opinion about quality. This reports them so an app can see them.
|
|
217
|
+
*/
|
|
218
|
+
declare function checkSpec(spec: Spec | null, mode: SpecValidationMode, options?: SpecCheckOptions): SpecCheck;
|
|
219
|
+
/**
|
|
220
|
+
* Render issues as one indented block, errors and warnings alike.
|
|
221
|
+
*
|
|
222
|
+
* Core's `formatSpecIssues` drops warnings and only accepts core's own issue
|
|
223
|
+
* codes, so it cannot describe what this package reports. Use this instead
|
|
224
|
+
* when showing `issues()` to a developer.
|
|
104
225
|
*/
|
|
105
|
-
declare function
|
|
226
|
+
declare function formatSpecCheckIssues(issues: readonly SpecCheckIssue[]): string;
|
|
106
227
|
|
|
107
228
|
/**
|
|
108
229
|
* State setter function for updating application state.
|
|
@@ -341,6 +462,27 @@ declare class JsonRenderer {
|
|
|
341
462
|
* arriving is expected to reference children that have not streamed in yet.
|
|
342
463
|
*/
|
|
343
464
|
readonly validate: _angular_core.InputSignal<SpecValidationMode>;
|
|
465
|
+
/**
|
|
466
|
+
* Caps on what the spec may cost the browser: `maxElements`, `maxDepth` and
|
|
467
|
+
* `maxRepeatItems`. Unset by default, and each field is independently
|
|
468
|
+
* optional.
|
|
469
|
+
*
|
|
470
|
+
* Unlike `validate`, these are enforced in every mode — a number the app
|
|
471
|
+
* chose is a control, not a report. A spec over `maxElements` renders
|
|
472
|
+
* nothing; `maxDepth` and `maxRepeatItems` truncate where they are hit.
|
|
473
|
+
* They apply while `loading` too: a partial spec is a subset of the
|
|
474
|
+
* finished one, so a cap can only ever fire early, never falsely.
|
|
475
|
+
*/
|
|
476
|
+
readonly renderLimits: _angular_core.InputSignal<RenderLimits | null>;
|
|
477
|
+
/**
|
|
478
|
+
* The catalog the spec was generated for. Given one, `validate` also checks
|
|
479
|
+
* what structure alone cannot: that every `type` is a component the catalog
|
|
480
|
+
* defines, and that the props match its schema.
|
|
481
|
+
*
|
|
482
|
+
* Only read when `validate` is on, and — like the rest of the check —
|
|
483
|
+
* skipped while `loading`.
|
|
484
|
+
*/
|
|
485
|
+
readonly catalog: _angular_core.InputSignal<SpecCatalog | null>;
|
|
344
486
|
/**
|
|
345
487
|
* Initial state model (uncontrolled mode). Defaults to `spec.state`.
|
|
346
488
|
* Ignored when `store` is provided.
|
|
@@ -390,7 +532,7 @@ declare class JsonRenderer {
|
|
|
390
532
|
*/
|
|
391
533
|
protected readonly confirmInjector: _angular_core.Signal<_angular_core.DestroyableInjector | null>;
|
|
392
534
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<JsonRenderer, never>;
|
|
393
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<JsonRenderer, "json-render", never, { "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "registry": { "alias": "registry"; "required": true; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "fallback": { "alias": "fallback"; "required": false; "isSignal": true; }; "validate": { "alias": "validate"; "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>;
|
|
535
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<JsonRenderer, "json-render", never, { "spec": { "alias": "spec"; "required": true; "isSignal": true; }; "registry": { "alias": "registry"; "required": true; "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>;
|
|
394
536
|
}
|
|
395
537
|
|
|
396
538
|
/**
|
|
@@ -424,6 +566,16 @@ declare class JrChildren {
|
|
|
424
566
|
key?: string;
|
|
425
567
|
} | undefined>;
|
|
426
568
|
private readonly repeatBasePath;
|
|
569
|
+
/** Every item the repeat's state array holds, before any cap. */
|
|
570
|
+
private readonly allRepeatItems;
|
|
571
|
+
/**
|
|
572
|
+
* The items this repeat actually renders.
|
|
573
|
+
*
|
|
574
|
+
* `repeat` iterates a state array the spec may itself have supplied, which
|
|
575
|
+
* is the one place a spec sizes the render tree out of data rather than out
|
|
576
|
+
* of its own structure — so the cap has to be applied here, as it expands,
|
|
577
|
+
* rather than anywhere a spec can be inspected up front.
|
|
578
|
+
*/
|
|
427
579
|
protected readonly repeatItems: _angular_core.Signal<unknown[]>;
|
|
428
580
|
constructor();
|
|
429
581
|
protected itemPath(index: number): string;
|
|
@@ -445,6 +597,7 @@ declare class JrElement {
|
|
|
445
597
|
private readonly state;
|
|
446
598
|
private readonly actions;
|
|
447
599
|
private readonly repeatScope;
|
|
600
|
+
private readonly parentPath;
|
|
448
601
|
private readonly devtoolsActive;
|
|
449
602
|
/** The raw (unresolved) element from the spec. */
|
|
450
603
|
readonly rawElement: Signal<UIElement<string, Record<string, unknown>> | undefined>;
|
|
@@ -458,6 +611,23 @@ declare class JrElement {
|
|
|
458
611
|
private readonly entry;
|
|
459
612
|
protected readonly component: Signal<_angular_core.Type<unknown> | null>;
|
|
460
613
|
protected readonly devtoolsKey: Signal<string | null>;
|
|
614
|
+
/**
|
|
615
|
+
* Where this element sits in the tree. Passed down to everything it renders
|
|
616
|
+
* below itself, which is what lets each element see its own ancestry
|
|
617
|
+
* without the renderer holding a registry of who is drawing what.
|
|
618
|
+
*/
|
|
619
|
+
private readonly path;
|
|
620
|
+
/**
|
|
621
|
+
* Why this element is not drawn, or null when it is.
|
|
622
|
+
*
|
|
623
|
+
* The cycle half is unconditional — not something `validate` turns on. An
|
|
624
|
+
* element that renders itself without reading any deeper renders forever,
|
|
625
|
+
* and a spec that never stops rendering takes the tab with it; refusing to
|
|
626
|
+
* draw the repetition is the only outcome that leaves anything on screen.
|
|
627
|
+
* It costs one walk up a chain of parents, bounded by `maxDepth` where one
|
|
628
|
+
* is set and by the spec's own nesting where it is not.
|
|
629
|
+
*/
|
|
630
|
+
protected readonly refusal: Signal<"cycle" | "depth" | null>;
|
|
461
631
|
private readonly renderCtx;
|
|
462
632
|
protected readonly outletInjector: _angular_core.DestroyableInjector;
|
|
463
633
|
constructor();
|
|
@@ -473,6 +643,12 @@ declare class JrElement {
|
|
|
473
643
|
*/
|
|
474
644
|
private fireEvent;
|
|
475
645
|
private emitEvent;
|
|
646
|
+
/**
|
|
647
|
+
* Run an `on` or `watch` binding's actions in order. Params are resolved
|
|
648
|
+
* per action, just before it runs, so a `$state` read in a later action of
|
|
649
|
+
* the chain sees what an earlier one wrote.
|
|
650
|
+
*/
|
|
651
|
+
private dispatch;
|
|
476
652
|
private eventHandle;
|
|
477
653
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<JrElement, never>;
|
|
478
654
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<JrElement, "jr-element", never, { "elementKey": { "alias": "elementKey"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
@@ -646,6 +822,11 @@ declare class JsonRenderRootContext {
|
|
|
646
822
|
registry: Signal<ComponentRegistry | undefined>;
|
|
647
823
|
loading: Signal<boolean>;
|
|
648
824
|
fallback: Signal<Type<unknown> | RegistryEntry | null | undefined>;
|
|
825
|
+
/**
|
|
826
|
+
* Caps on what the spec may cost the browser. Read as the tree renders, so
|
|
827
|
+
* they apply whatever `validate` is set to.
|
|
828
|
+
*/
|
|
829
|
+
limits: Signal<RenderLimits | null | undefined>;
|
|
649
830
|
/** External store (controlled mode). */
|
|
650
831
|
store: Signal<StateStore | null | undefined>;
|
|
651
832
|
/** Initial state (uncontrolled mode); falls back to `spec.state`. */
|
|
@@ -901,6 +1082,18 @@ interface UIStreamOptions {
|
|
|
901
1082
|
* spec there does not persist a broken one.
|
|
902
1083
|
*/
|
|
903
1084
|
validate?: SpecValidationMode;
|
|
1085
|
+
/**
|
|
1086
|
+
* Caps on what the finished spec may cost the browser. Enforced whatever
|
|
1087
|
+
* `validate` is: a spec over `maxElements` fails the generation rather than
|
|
1088
|
+
* reaching `onComplete`.
|
|
1089
|
+
*/
|
|
1090
|
+
renderLimits?: RenderLimits | null;
|
|
1091
|
+
/**
|
|
1092
|
+
* The catalog the spec was generated for. Given one, `validate` also checks
|
|
1093
|
+
* every element `type` against the catalog and the props against its
|
|
1094
|
+
* schema — the half a structural check cannot see.
|
|
1095
|
+
*/
|
|
1096
|
+
catalog?: SpecCatalog | null;
|
|
904
1097
|
/**
|
|
905
1098
|
* Transport, defaulting to the global `fetch`.
|
|
906
1099
|
*
|
|
@@ -928,10 +1121,12 @@ interface UIStreamReturn {
|
|
|
928
1121
|
/** Raw JSONL lines received from the stream (JSON patch lines) */
|
|
929
1122
|
readonly rawLines: Signal<string[]>;
|
|
930
1123
|
/**
|
|
931
|
-
*
|
|
932
|
-
*
|
|
1124
|
+
* What the check found in the finished spec — structure, catalog and
|
|
1125
|
+
* limits alike. Empty until a generation completes; empty while `validate`
|
|
1126
|
+
* is off unless a `renderLimits` cap was passed, since those are enforced
|
|
1127
|
+
* in every mode.
|
|
933
1128
|
*/
|
|
934
|
-
readonly issues: Signal<readonly
|
|
1129
|
+
readonly issues: Signal<readonly SpecCheckIssue[]>;
|
|
935
1130
|
/** Send a prompt to generate UI */
|
|
936
1131
|
send: (prompt: string, options?: UIStreamSendOptions) => Promise<void>;
|
|
937
1132
|
/**
|
|
@@ -998,6 +1193,18 @@ interface ChatUIOptions {
|
|
|
998
1193
|
* reply that produced a spec.
|
|
999
1194
|
*/
|
|
1000
1195
|
validate?: SpecValidationMode;
|
|
1196
|
+
/**
|
|
1197
|
+
* Caps on what the finished spec may cost the browser. Enforced whatever
|
|
1198
|
+
* `validate` is: a spec over `maxElements` fails the generation rather than
|
|
1199
|
+
* reaching `onComplete`.
|
|
1200
|
+
*/
|
|
1201
|
+
renderLimits?: RenderLimits | null;
|
|
1202
|
+
/**
|
|
1203
|
+
* The catalog the spec was generated for. Given one, `validate` also checks
|
|
1204
|
+
* every element `type` against the catalog and the props against its
|
|
1205
|
+
* schema — the half a structural check cannot see.
|
|
1206
|
+
*/
|
|
1207
|
+
catalog?: SpecCatalog | null;
|
|
1001
1208
|
}
|
|
1002
1209
|
/**
|
|
1003
1210
|
* Return type for {@link injectChatUI}.
|
|
@@ -1010,10 +1217,12 @@ interface ChatUIReturn {
|
|
|
1010
1217
|
/** Error from the last request, if any */
|
|
1011
1218
|
readonly error: Signal<Error | null>;
|
|
1012
1219
|
/**
|
|
1013
|
-
*
|
|
1014
|
-
*
|
|
1220
|
+
* What the check found in the last completed reply's spec — structure,
|
|
1221
|
+
* catalog and limits alike. Empty until a reply completes; empty while
|
|
1222
|
+
* `validate` is off unless a `renderLimits` cap was passed, since those are
|
|
1223
|
+
* enforced in every mode.
|
|
1015
1224
|
*/
|
|
1016
|
-
readonly issues: Signal<readonly
|
|
1225
|
+
readonly issues: Signal<readonly SpecCheckIssue[]>;
|
|
1017
1226
|
/** Send a user message */
|
|
1018
1227
|
send: (text: string) => Promise<void>;
|
|
1019
1228
|
/**
|
|
@@ -1110,5 +1319,5 @@ type AngularSpec<TCatalog> = typeof schema extends {
|
|
|
1110
1319
|
*/
|
|
1111
1320
|
declare function injectDevtoolsActive(): Signal<boolean>;
|
|
1112
1321
|
|
|
1113
|
-
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, getTextFromParts, injectAction, injectActions, injectBoundProp, injectChatUI, injectConfirmContext, injectDevtoolsActive, injectElementKey, injectFieldValidation, injectRenderContext, injectRepeatScope, injectStateBinding, injectStateStore, injectStateValue, injectUIStream, injectValidation, isActionCancelled, jsonRenderMessage, schema };
|
|
1114
|
-
export type { ActionFn, Actions, AngularSchema, AngularSpec, CatalogHasActions, ChatMessage, ChatUIOptions, ChatUIReturn, ComponentRegistry, Components, ConfirmContext, ConfirmLabels, DataPart, DefineRegistryResult, EventHandle, FieldValidationState, PendingConfirmation, RegistryEntry, RenderContext, RepeatScope, SetState, SpecCheck, SpecValidationMode, StateChange, TokenUsage, UIStreamOptions, UIStreamReturn, UIStreamSendOptions };
|
|
1322
|
+
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 };
|
|
1323
|
+
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 };
|