@ai-gui/vanilla 0.3.0 → 0.4.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/dist/index.cjs +61 -23
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +61 -23
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -26,7 +26,7 @@ const __ai_gui_core = __toESM(require("@ai-gui/core"));
|
|
|
26
26
|
|
|
27
27
|
//#region src/render-output.ts
|
|
28
28
|
/** Translate a framework-neutral RenderOutput (from a plugin node renderer) into a DOM element. */
|
|
29
|
-
function renderOutputToElement(out, sanitize) {
|
|
29
|
+
function renderOutputToElement(out, sanitize, mountContext = {}) {
|
|
30
30
|
switch (out.kind) {
|
|
31
31
|
case "html": {
|
|
32
32
|
const el = document.createElement("div");
|
|
@@ -37,7 +37,7 @@ function renderOutputToElement(out, sanitize) {
|
|
|
37
37
|
const el = document.createElement(out.tag);
|
|
38
38
|
for (const [key, value] of Object.entries(out.props ?? {})) if (key === "class" || key === "className") el.className = String(value);
|
|
39
39
|
else el.setAttribute(key, String(value));
|
|
40
|
-
for (const child of out.children ?? []) el.appendChild(renderOutputToElement(child, sanitize));
|
|
40
|
+
for (const child of out.children ?? []) el.appendChild(renderOutputToElement(child, sanitize, mountContext));
|
|
41
41
|
return el;
|
|
42
42
|
}
|
|
43
43
|
case "card": {
|
|
@@ -53,7 +53,7 @@ function renderOutputToElement(out, sanitize) {
|
|
|
53
53
|
el.setAttribute("data-aigui-mount", "");
|
|
54
54
|
queueMicrotask(() => {
|
|
55
55
|
if (el.__aiguiDisposed) return;
|
|
56
|
-
const c = out.mount(el);
|
|
56
|
+
const c = out.mount(el, mountContext);
|
|
57
57
|
if (typeof c === "function") if (el.__aiguiDisposed) c();
|
|
58
58
|
else el.__aiguiCleanup = c;
|
|
59
59
|
});
|
|
@@ -85,7 +85,7 @@ function renderNodeToElement(node, ctx) {
|
|
|
85
85
|
out.then((res) => {
|
|
86
86
|
if (host.__aiguiDisposed) return;
|
|
87
87
|
host.removeAttribute("data-aigui-async-pending");
|
|
88
|
-
host.replaceChildren(renderOutputToElement(res, ctx.sanitize));
|
|
88
|
+
host.replaceChildren(renderOutputToElement(res, ctx.sanitize, createRenderMountContext(ctx)));
|
|
89
89
|
}, () => {
|
|
90
90
|
if (host.__aiguiDisposed) return;
|
|
91
91
|
host.removeAttribute("data-aigui-async-pending");
|
|
@@ -93,7 +93,7 @@ function renderNodeToElement(node, ctx) {
|
|
|
93
93
|
});
|
|
94
94
|
return host;
|
|
95
95
|
}
|
|
96
|
-
return renderOutputToElement(out, ctx.sanitize);
|
|
96
|
+
return renderOutputToElement(out, ctx.sanitize, createRenderMountContext(ctx));
|
|
97
97
|
} catch {
|
|
98
98
|
return renderFallback(node, ctx);
|
|
99
99
|
}
|
|
@@ -162,6 +162,53 @@ function renderCardElement(node, ctx) {
|
|
|
162
162
|
host.__aiguiCleanup = () => controller.destroy();
|
|
163
163
|
return host;
|
|
164
164
|
}
|
|
165
|
+
function createRenderMountContext(ctx) {
|
|
166
|
+
return { mountCard(host, request) {
|
|
167
|
+
return mountCardSlot(host, request, ctx);
|
|
168
|
+
} };
|
|
169
|
+
}
|
|
170
|
+
function mountCardSlot(host, request, ctx) {
|
|
171
|
+
const factory = ctx.registry?.getRender(request.type);
|
|
172
|
+
if (!factory) return void 0;
|
|
173
|
+
return createVanillaCardSlot(host, request.data, factory, () => ({
|
|
174
|
+
state: { status: "idle" },
|
|
175
|
+
onAction: (action) => ctx.onCardAction?.({
|
|
176
|
+
...action,
|
|
177
|
+
cardType: request.type
|
|
178
|
+
})
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
function createVanillaCardSlot(host, initialData, factory, context) {
|
|
182
|
+
let destroyed = false;
|
|
183
|
+
let instance;
|
|
184
|
+
let element;
|
|
185
|
+
const mount = (data) => {
|
|
186
|
+
const rendered = factory(data, context());
|
|
187
|
+
if (isVanillaCardInstance(rendered)) {
|
|
188
|
+
instance = rendered;
|
|
189
|
+
element = rendered.element;
|
|
190
|
+
} else {
|
|
191
|
+
instance = void 0;
|
|
192
|
+
element = rendered;
|
|
193
|
+
}
|
|
194
|
+
host.replaceChildren(element);
|
|
195
|
+
};
|
|
196
|
+
mount(initialData);
|
|
197
|
+
return {
|
|
198
|
+
element: () => element,
|
|
199
|
+
update(data) {
|
|
200
|
+
if (destroyed) return;
|
|
201
|
+
if (instance) instance.update(data, context());
|
|
202
|
+
else mount(data);
|
|
203
|
+
},
|
|
204
|
+
destroy() {
|
|
205
|
+
if (destroyed) return;
|
|
206
|
+
destroyed = true;
|
|
207
|
+
instance?.destroy?.();
|
|
208
|
+
instance = void 0;
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
165
212
|
function createCardFallback(card, ctx) {
|
|
166
213
|
const pre = document.createElement("pre");
|
|
167
214
|
pre.setAttribute("data-aigui-card-fallback", "");
|
|
@@ -206,8 +253,7 @@ function createCardController(host, initialCard, factory, ctx) {
|
|
|
206
253
|
let card = initialCard;
|
|
207
254
|
let destroyed = false;
|
|
208
255
|
let unsubscribe = () => {};
|
|
209
|
-
let
|
|
210
|
-
let element;
|
|
256
|
+
let slot;
|
|
211
257
|
let missing = false;
|
|
212
258
|
const id = card.id;
|
|
213
259
|
const onAction = (action) => ctx.onCardAction?.({
|
|
@@ -229,20 +275,11 @@ function createCardController(host, initialCard, factory, ctx) {
|
|
|
229
275
|
} catch (error) {
|
|
230
276
|
registrationError = error;
|
|
231
277
|
}
|
|
232
|
-
const context = () => ({
|
|
233
|
-
state,
|
|
234
|
-
onAction
|
|
235
|
-
});
|
|
236
278
|
const mount = (nextData) => {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
} else {
|
|
242
|
-
instance = void 0;
|
|
243
|
-
element = rendered;
|
|
244
|
-
}
|
|
245
|
-
host.replaceChildren(element);
|
|
279
|
+
slot = createVanillaCardSlot(host, nextData, factory, () => ({
|
|
280
|
+
state,
|
|
281
|
+
onAction
|
|
282
|
+
}));
|
|
246
283
|
};
|
|
247
284
|
const update = (nextData, nextState) => {
|
|
248
285
|
if (destroyed) return;
|
|
@@ -252,9 +289,10 @@ function createCardController(host, initialCard, factory, ctx) {
|
|
|
252
289
|
if (missing) {
|
|
253
290
|
missing = false;
|
|
254
291
|
host.removeAttribute("data-aigui-card-missing");
|
|
292
|
+
const element = slot?.element();
|
|
255
293
|
if (element) host.replaceChildren(element);
|
|
256
294
|
}
|
|
257
|
-
if (
|
|
295
|
+
if (slot) slot.update(data);
|
|
258
296
|
else mount(data);
|
|
259
297
|
};
|
|
260
298
|
const showMissing = () => {
|
|
@@ -293,8 +331,8 @@ function createCardController(host, initialCard, factory, ctx) {
|
|
|
293
331
|
destroyed = true;
|
|
294
332
|
unsubscribe();
|
|
295
333
|
unsubscribe = () => {};
|
|
296
|
-
|
|
297
|
-
|
|
334
|
+
slot?.destroy();
|
|
335
|
+
slot = void 0;
|
|
298
336
|
}
|
|
299
337
|
};
|
|
300
338
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AIGuiPlugin, ASTNode, ActionRuntime, CardAction, CardRegistry, CardStore, DebugEventListener, FeedOptions, FeedSource, NodeRenderer, RenderOutput, RendererOptions } from "@ai-gui/core";
|
|
1
|
+
import { AIGuiPlugin, ASTNode, ActionRuntime, CardAction, CardRegistry, CardStore, DebugEventListener, FeedOptions, FeedSource, NodeRenderer, RenderMountContext, RenderOutput, RendererOptions } from "@ai-gui/core";
|
|
2
2
|
|
|
3
3
|
//#region src/render-node-dom.d.ts
|
|
4
4
|
interface VanillaCardAction {
|
|
@@ -51,7 +51,7 @@ declare function createRenderer(el: HTMLElement, options?: CreateRendererOptions
|
|
|
51
51
|
//#endregion
|
|
52
52
|
//#region src/render-output.d.ts
|
|
53
53
|
/** Translate a framework-neutral RenderOutput (from a plugin node renderer) into a DOM element. */
|
|
54
|
-
declare function renderOutputToElement(out: RenderOutput, sanitize?: RendererOptions["sanitize"]): HTMLElement;
|
|
54
|
+
declare function renderOutputToElement(out: RenderOutput, sanitize?: RendererOptions["sanitize"], mountContext?: RenderMountContext): HTMLElement;
|
|
55
55
|
|
|
56
56
|
//#endregion
|
|
57
57
|
export { CreateRendererOptions, DomRenderContext, VanillaCardAction, VanillaCardFactory, VanillaCardInstance, VanillaCardUpdateContext, VanillaRenderer, createRenderer, renderNodeToElement, renderOutputToElement };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AIGuiPlugin, ASTNode, ActionRuntime, CardAction, CardRegistry, CardStore, DebugEventListener, FeedOptions, FeedSource, NodeRenderer, RenderOutput, RendererOptions } from "@ai-gui/core";
|
|
1
|
+
import { AIGuiPlugin, ASTNode, ActionRuntime, CardAction, CardRegistry, CardStore, DebugEventListener, FeedOptions, FeedSource, NodeRenderer, RenderMountContext, RenderOutput, RendererOptions } from "@ai-gui/core";
|
|
2
2
|
|
|
3
3
|
//#region src/render-node-dom.d.ts
|
|
4
4
|
interface VanillaCardAction {
|
|
@@ -51,7 +51,7 @@ declare function createRenderer(el: HTMLElement, options?: CreateRendererOptions
|
|
|
51
51
|
//#endregion
|
|
52
52
|
//#region src/render-output.d.ts
|
|
53
53
|
/** Translate a framework-neutral RenderOutput (from a plugin node renderer) into a DOM element. */
|
|
54
|
-
declare function renderOutputToElement(out: RenderOutput, sanitize?: RendererOptions["sanitize"]): HTMLElement;
|
|
54
|
+
declare function renderOutputToElement(out: RenderOutput, sanitize?: RendererOptions["sanitize"], mountContext?: RenderMountContext): HTMLElement;
|
|
55
55
|
|
|
56
56
|
//#endregion
|
|
57
57
|
export { CreateRendererOptions, DomRenderContext, VanillaCardAction, VanillaCardFactory, VanillaCardInstance, VanillaCardUpdateContext, VanillaRenderer, createRenderer, renderNodeToElement, renderOutputToElement };
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Renderer, collectNodeRenderers, sanitizeHtml } from "@ai-gui/core";
|
|
|
2
2
|
|
|
3
3
|
//#region src/render-output.ts
|
|
4
4
|
/** Translate a framework-neutral RenderOutput (from a plugin node renderer) into a DOM element. */
|
|
5
|
-
function renderOutputToElement(out, sanitize) {
|
|
5
|
+
function renderOutputToElement(out, sanitize, mountContext = {}) {
|
|
6
6
|
switch (out.kind) {
|
|
7
7
|
case "html": {
|
|
8
8
|
const el = document.createElement("div");
|
|
@@ -13,7 +13,7 @@ function renderOutputToElement(out, sanitize) {
|
|
|
13
13
|
const el = document.createElement(out.tag);
|
|
14
14
|
for (const [key, value] of Object.entries(out.props ?? {})) if (key === "class" || key === "className") el.className = String(value);
|
|
15
15
|
else el.setAttribute(key, String(value));
|
|
16
|
-
for (const child of out.children ?? []) el.appendChild(renderOutputToElement(child, sanitize));
|
|
16
|
+
for (const child of out.children ?? []) el.appendChild(renderOutputToElement(child, sanitize, mountContext));
|
|
17
17
|
return el;
|
|
18
18
|
}
|
|
19
19
|
case "card": {
|
|
@@ -29,7 +29,7 @@ function renderOutputToElement(out, sanitize) {
|
|
|
29
29
|
el.setAttribute("data-aigui-mount", "");
|
|
30
30
|
queueMicrotask(() => {
|
|
31
31
|
if (el.__aiguiDisposed) return;
|
|
32
|
-
const c = out.mount(el);
|
|
32
|
+
const c = out.mount(el, mountContext);
|
|
33
33
|
if (typeof c === "function") if (el.__aiguiDisposed) c();
|
|
34
34
|
else el.__aiguiCleanup = c;
|
|
35
35
|
});
|
|
@@ -61,7 +61,7 @@ function renderNodeToElement(node, ctx) {
|
|
|
61
61
|
out.then((res) => {
|
|
62
62
|
if (host.__aiguiDisposed) return;
|
|
63
63
|
host.removeAttribute("data-aigui-async-pending");
|
|
64
|
-
host.replaceChildren(renderOutputToElement(res, ctx.sanitize));
|
|
64
|
+
host.replaceChildren(renderOutputToElement(res, ctx.sanitize, createRenderMountContext(ctx)));
|
|
65
65
|
}, () => {
|
|
66
66
|
if (host.__aiguiDisposed) return;
|
|
67
67
|
host.removeAttribute("data-aigui-async-pending");
|
|
@@ -69,7 +69,7 @@ function renderNodeToElement(node, ctx) {
|
|
|
69
69
|
});
|
|
70
70
|
return host;
|
|
71
71
|
}
|
|
72
|
-
return renderOutputToElement(out, ctx.sanitize);
|
|
72
|
+
return renderOutputToElement(out, ctx.sanitize, createRenderMountContext(ctx));
|
|
73
73
|
} catch {
|
|
74
74
|
return renderFallback(node, ctx);
|
|
75
75
|
}
|
|
@@ -138,6 +138,53 @@ function renderCardElement(node, ctx) {
|
|
|
138
138
|
host.__aiguiCleanup = () => controller.destroy();
|
|
139
139
|
return host;
|
|
140
140
|
}
|
|
141
|
+
function createRenderMountContext(ctx) {
|
|
142
|
+
return { mountCard(host, request) {
|
|
143
|
+
return mountCardSlot(host, request, ctx);
|
|
144
|
+
} };
|
|
145
|
+
}
|
|
146
|
+
function mountCardSlot(host, request, ctx) {
|
|
147
|
+
const factory = ctx.registry?.getRender(request.type);
|
|
148
|
+
if (!factory) return void 0;
|
|
149
|
+
return createVanillaCardSlot(host, request.data, factory, () => ({
|
|
150
|
+
state: { status: "idle" },
|
|
151
|
+
onAction: (action) => ctx.onCardAction?.({
|
|
152
|
+
...action,
|
|
153
|
+
cardType: request.type
|
|
154
|
+
})
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
function createVanillaCardSlot(host, initialData, factory, context) {
|
|
158
|
+
let destroyed = false;
|
|
159
|
+
let instance;
|
|
160
|
+
let element;
|
|
161
|
+
const mount = (data) => {
|
|
162
|
+
const rendered = factory(data, context());
|
|
163
|
+
if (isVanillaCardInstance(rendered)) {
|
|
164
|
+
instance = rendered;
|
|
165
|
+
element = rendered.element;
|
|
166
|
+
} else {
|
|
167
|
+
instance = void 0;
|
|
168
|
+
element = rendered;
|
|
169
|
+
}
|
|
170
|
+
host.replaceChildren(element);
|
|
171
|
+
};
|
|
172
|
+
mount(initialData);
|
|
173
|
+
return {
|
|
174
|
+
element: () => element,
|
|
175
|
+
update(data) {
|
|
176
|
+
if (destroyed) return;
|
|
177
|
+
if (instance) instance.update(data, context());
|
|
178
|
+
else mount(data);
|
|
179
|
+
},
|
|
180
|
+
destroy() {
|
|
181
|
+
if (destroyed) return;
|
|
182
|
+
destroyed = true;
|
|
183
|
+
instance?.destroy?.();
|
|
184
|
+
instance = void 0;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
}
|
|
141
188
|
function createCardFallback(card, ctx) {
|
|
142
189
|
const pre = document.createElement("pre");
|
|
143
190
|
pre.setAttribute("data-aigui-card-fallback", "");
|
|
@@ -182,8 +229,7 @@ function createCardController(host, initialCard, factory, ctx) {
|
|
|
182
229
|
let card = initialCard;
|
|
183
230
|
let destroyed = false;
|
|
184
231
|
let unsubscribe = () => {};
|
|
185
|
-
let
|
|
186
|
-
let element;
|
|
232
|
+
let slot;
|
|
187
233
|
let missing = false;
|
|
188
234
|
const id = card.id;
|
|
189
235
|
const onAction = (action) => ctx.onCardAction?.({
|
|
@@ -205,20 +251,11 @@ function createCardController(host, initialCard, factory, ctx) {
|
|
|
205
251
|
} catch (error) {
|
|
206
252
|
registrationError = error;
|
|
207
253
|
}
|
|
208
|
-
const context = () => ({
|
|
209
|
-
state,
|
|
210
|
-
onAction
|
|
211
|
-
});
|
|
212
254
|
const mount = (nextData) => {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
} else {
|
|
218
|
-
instance = void 0;
|
|
219
|
-
element = rendered;
|
|
220
|
-
}
|
|
221
|
-
host.replaceChildren(element);
|
|
255
|
+
slot = createVanillaCardSlot(host, nextData, factory, () => ({
|
|
256
|
+
state,
|
|
257
|
+
onAction
|
|
258
|
+
}));
|
|
222
259
|
};
|
|
223
260
|
const update = (nextData, nextState) => {
|
|
224
261
|
if (destroyed) return;
|
|
@@ -228,9 +265,10 @@ function createCardController(host, initialCard, factory, ctx) {
|
|
|
228
265
|
if (missing) {
|
|
229
266
|
missing = false;
|
|
230
267
|
host.removeAttribute("data-aigui-card-missing");
|
|
268
|
+
const element = slot?.element();
|
|
231
269
|
if (element) host.replaceChildren(element);
|
|
232
270
|
}
|
|
233
|
-
if (
|
|
271
|
+
if (slot) slot.update(data);
|
|
234
272
|
else mount(data);
|
|
235
273
|
};
|
|
236
274
|
const showMissing = () => {
|
|
@@ -269,8 +307,8 @@ function createCardController(host, initialCard, factory, ctx) {
|
|
|
269
307
|
destroyed = true;
|
|
270
308
|
unsubscribe();
|
|
271
309
|
unsubscribe = () => {};
|
|
272
|
-
|
|
273
|
-
|
|
310
|
+
slot?.destroy();
|
|
311
|
+
slot = void 0;
|
|
274
312
|
}
|
|
275
313
|
};
|
|
276
314
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-gui/vanilla",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Framework-free DOM adapter for AIGUI — stream LLM output straight into the DOM.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"llm",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"access": "public"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@ai-gui/core": "0.
|
|
53
|
+
"@ai-gui/core": "0.4.0"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "tsdown",
|