ngx-json-render 0.8.1 → 0.8.2
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
CHANGED
|
@@ -8,7 +8,7 @@ Built on `@json-render/core` (the same spec format, expressions, state store, ac
|
|
|
8
8
|
|
|
9
9
|
This is an Angular **adapter over the official core**, not a second implementation of it — `@json-render/core` is a peer dependency, and the spec your model emits is the same one the React, Vue, Solid and Svelte renderers consume. A catalog and a spec written here move to another framework unchanged.
|
|
10
10
|
|
|
11
|
-
**[Live demo](https://shteynu.github.io/ngx-json-render/)** —
|
|
11
|
+
**[Live demo](https://shteynu.github.io/ngx-json-render/)** — opens on a sales dashboard streaming in patch by patch, which you can stop mid-generation; plus a playground, an interactive spec (bindings, repeat, confirm, watch), and a chat where prose and UI patches arrive in one reply. Both streaming tabs replay a recording, or call a real model on your own key ([source](https://github.com/shteynu/ngx-json-render/tree/main/projects/demo)) — or [](https://stackblitz.com/github/shteynu/ngx-json-render)
|
|
12
12
|
|
|
13
13
|

|
|
14
14
|
|
|
@@ -3166,6 +3166,39 @@ function notifyStreamObservers(event, ...args) {
|
|
|
3166
3166
|
}
|
|
3167
3167
|
}
|
|
3168
3168
|
}
|
|
3169
|
+
/**
|
|
3170
|
+
* The start and end of one hook's generations, as observers see them.
|
|
3171
|
+
*
|
|
3172
|
+
* A superseded or stopped request only settles once its abort has gone
|
|
3173
|
+
* through, after the next generation may already have started. Reporting its
|
|
3174
|
+
* end from there would close the new generation instead of the old one, so a
|
|
3175
|
+
* generation ends here the moment it is superseded or stopped, and its own
|
|
3176
|
+
* late end is dropped.
|
|
3177
|
+
*/
|
|
3178
|
+
function createObservedRuns() {
|
|
3179
|
+
let endOpen = null;
|
|
3180
|
+
return {
|
|
3181
|
+
start() {
|
|
3182
|
+
endOpen?.();
|
|
3183
|
+
let ended = false;
|
|
3184
|
+
const end = (ok) => {
|
|
3185
|
+
if (ended)
|
|
3186
|
+
return;
|
|
3187
|
+
ended = true;
|
|
3188
|
+
if (endOpen === stop)
|
|
3189
|
+
endOpen = null;
|
|
3190
|
+
notifyStreamObservers('onEnd', ok);
|
|
3191
|
+
};
|
|
3192
|
+
const stop = () => end(true);
|
|
3193
|
+
endOpen = stop;
|
|
3194
|
+
notifyStreamObservers('onStart');
|
|
3195
|
+
return end;
|
|
3196
|
+
},
|
|
3197
|
+
stop() {
|
|
3198
|
+
endOpen?.();
|
|
3199
|
+
},
|
|
3200
|
+
};
|
|
3201
|
+
}
|
|
3169
3202
|
|
|
3170
3203
|
/**
|
|
3171
3204
|
* Convert a flat element list to a Spec.
|
|
@@ -3463,9 +3496,11 @@ function injectUIStream(options) {
|
|
|
3463
3496
|
catalog: options.catalog ?? null,
|
|
3464
3497
|
};
|
|
3465
3498
|
const session = createStreamSession();
|
|
3499
|
+
const runs = createObservedRuns();
|
|
3466
3500
|
inject(DestroyRef).onDestroy(() => session.cancel());
|
|
3467
3501
|
const stop = () => {
|
|
3468
3502
|
session.cancel();
|
|
3503
|
+
runs.stop();
|
|
3469
3504
|
isStreaming.set(false);
|
|
3470
3505
|
};
|
|
3471
3506
|
const clear = () => {
|
|
@@ -3490,7 +3525,7 @@ function injectUIStream(options) {
|
|
|
3490
3525
|
? { ...previousSpec, elements: { ...previousSpec.elements } }
|
|
3491
3526
|
: { root: '', elements: {} };
|
|
3492
3527
|
spec.set(currentSpec);
|
|
3493
|
-
|
|
3528
|
+
const end = runs.start();
|
|
3494
3529
|
let failed = false;
|
|
3495
3530
|
const handleLine = (line) => {
|
|
3496
3531
|
const parsed = parseLine(line);
|
|
@@ -3556,7 +3591,7 @@ function injectUIStream(options) {
|
|
|
3556
3591
|
}
|
|
3557
3592
|
finally {
|
|
3558
3593
|
gate.commit(() => isStreaming.set(false));
|
|
3559
|
-
|
|
3594
|
+
end(!failed);
|
|
3560
3595
|
}
|
|
3561
3596
|
};
|
|
3562
3597
|
return {
|
|
@@ -3600,9 +3635,11 @@ function injectChatUI(options) {
|
|
|
3600
3635
|
catalog: options.catalog ?? null,
|
|
3601
3636
|
};
|
|
3602
3637
|
const session = createStreamSession();
|
|
3638
|
+
const runs = createObservedRuns();
|
|
3603
3639
|
inject(DestroyRef).onDestroy(() => session.cancel());
|
|
3604
3640
|
const stop = () => {
|
|
3605
3641
|
session.cancel();
|
|
3642
|
+
runs.stop();
|
|
3606
3643
|
isStreaming.set(false);
|
|
3607
3644
|
};
|
|
3608
3645
|
const clear = () => {
|
|
@@ -3657,7 +3694,7 @@ function injectChatUI(options) {
|
|
|
3657
3694
|
messages.update((prev) => [...prev, userMessage, assistantMessage]);
|
|
3658
3695
|
isStreaming.set(true);
|
|
3659
3696
|
error.set(null);
|
|
3660
|
-
|
|
3697
|
+
const end = runs.start();
|
|
3661
3698
|
let failed = false;
|
|
3662
3699
|
// Mutable state for accumulating the assistant response
|
|
3663
3700
|
let accumulatedText = '';
|
|
@@ -3740,7 +3777,7 @@ function injectChatUI(options) {
|
|
|
3740
3777
|
}
|
|
3741
3778
|
finally {
|
|
3742
3779
|
gate.commit(() => isStreaming.set(false));
|
|
3743
|
-
|
|
3780
|
+
end(!failed);
|
|
3744
3781
|
}
|
|
3745
3782
|
};
|
|
3746
3783
|
return {
|