ngx-json-render 0.8.2 → 0.9.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 +66 -1
- package/fesm2022/ngx-json-render.mjs +1202 -1125
- package/fesm2022/ngx-json-render.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ngx-json-render.d.ts +39 -4
package/README.md
CHANGED
|
@@ -273,6 +273,40 @@ export class GeneratePage {
|
|
|
273
273
|
}
|
|
274
274
|
```
|
|
275
275
|
|
|
276
|
+
### Placeholders while props stream
|
|
277
|
+
|
|
278
|
+
An element can arrive before its props do: a Card with no `title` yet, a Text
|
|
279
|
+
with no `content`. By default the component mounts anyway and renders what it
|
|
280
|
+
has. Pass the `catalog` and the renderer waits instead: while `loading` is
|
|
281
|
+
true, an element whose props do not pass its component's schema shows its
|
|
282
|
+
registry entry's `fallback`, or nothing, and the component mounts once they
|
|
283
|
+
do.
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
export const { registry } = defineRegistry(catalog, {
|
|
287
|
+
components: {
|
|
288
|
+
Card: { component: CardComponent, fallback: CardSkeleton },
|
|
289
|
+
Text: TextComponent, // nothing on screen until `content` arrives
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
```html
|
|
295
|
+
<json-render [spec]="ui.spec()" [registry]="registry" [catalog]="catalog" [loading]="ui.isStreaming()" />
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
- The fallback gets the same render context as the component: it can read
|
|
299
|
+
the props that have arrived, and a `<jr-children />` in it lays out the
|
|
300
|
+
children that have.
|
|
301
|
+
- Props are checked as the spec writes them. `{ "$state": "/title" }` counts
|
|
302
|
+
as arrived, whatever it resolves to.
|
|
303
|
+
- Once an element's component has mounted it stays, even if a later patch
|
|
304
|
+
takes a prop away again.
|
|
305
|
+
- When `loading` turns false every element mounts, valid or not; reporting
|
|
306
|
+
what is wrong with the finished spec is `validate`'s job.
|
|
307
|
+
- Without a `catalog`, or for a type the catalog has no props schema for,
|
|
308
|
+
nothing is held back.
|
|
309
|
+
|
|
276
310
|
### The server side
|
|
277
311
|
|
|
278
312
|
`injectUIStream` POSTs `{ prompt, context, currentSpec }` to your endpoint and expects the response body to be SpecStream JSONL — one RFC 6902 patch per line. Any server that can stream text works; with the [AI SDK](https://ai-sdk.dev) it's a few lines — `catalog.prompt()` teaches the model your component vocabulary and the patch protocol:
|
|
@@ -744,6 +778,37 @@ value it derives updates when that state does.
|
|
|
744
778
|
`projects/ngx-json-render/src/lib/directives.spec.ts` renders every one of
|
|
745
779
|
them through the renderer, which is what keeps this paragraph honest.
|
|
746
780
|
|
|
781
|
+
### Switching language
|
|
782
|
+
|
|
783
|
+
Where a spec's text comes from decides how it follows a language switch.
|
|
784
|
+
|
|
785
|
+
**Keys, translated on the client.** A spec that says
|
|
786
|
+
`{ "$t": "greeting", "params": { "name": { "$state": "/name" } } }` instead of
|
|
787
|
+
the words themselves switches in place. Derive `directives` from your locale
|
|
788
|
+
signal, and every prop re-resolves when it changes, with no new spec and
|
|
789
|
+
nothing remounted:
|
|
790
|
+
|
|
791
|
+
```ts
|
|
792
|
+
readonly locale = signal('en');
|
|
793
|
+
readonly directives = computed(() => [
|
|
794
|
+
...standardDirectives,
|
|
795
|
+
createI18nDirective({ locale: this.locale(), messages }),
|
|
796
|
+
]);
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
`$format` takes a `locale` the same way, for numbers, currency and dates.
|
|
800
|
+
|
|
801
|
+
**Words, written by the model.** Most generated UIs are this kind: the model
|
|
802
|
+
writes "Save" or "Сохранить" straight into the props. Tell it the language
|
|
803
|
+
through `context` (`ui.send(prompt, { context: { locale } })`) and say what to
|
|
804
|
+
do with it in your server's prompt. Text already on screen stays in the
|
|
805
|
+
language it was written in; switching means asking again, and
|
|
806
|
+
`previousSpec` keeps the layout while the model rewrites the words.
|
|
807
|
+
|
|
808
|
+
Text inside your catalog components is your app's own i18n, as it would be
|
|
809
|
+
anywhere else. The confirm dialog's two default words are `JR_CONFIRM_LABELS`
|
|
810
|
+
(see [Confirmation dialogs](#confirmation-dialogs)).
|
|
811
|
+
|
|
747
812
|
## State
|
|
748
813
|
|
|
749
814
|
Each `<json-render>` owns a state store (JSON Pointer addressed). Seeding order: `store` input (controlled) → `state` input → `spec.state`.
|
|
@@ -982,7 +1047,7 @@ Everything from `@json-render/core` (types, `createStateStore`, `nestedToFlat`,
|
|
|
982
1047
|
| `fallback` | `Type<unknown>` | Component for unknown types |
|
|
983
1048
|
| `validate` | `'off' \| 'warn' \| 'strict'` | Check the settled spec's structure (default `'off'`) |
|
|
984
1049
|
| `renderLimits` | `RenderLimits` | Cap elements, depth and repeat expansion (default none) |
|
|
985
|
-
| `catalog` | `Catalog` |
|
|
1050
|
+
| `catalog` | `Catalog` | Check types and props; hold back half-streamed props |
|
|
986
1051
|
| `state` | `StateModel` | Initial state (uncontrolled; defaults to `spec.state`) |
|
|
987
1052
|
| `store` | `StateStore` | External store (controlled mode) |
|
|
988
1053
|
| `handlers` | `Record<string, ActionHandler>` | Action handlers |
|