@ai-gui/plugin-form 0.4.2 → 0.4.4
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 +16 -5
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +16 -5
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -94,7 +94,7 @@ function form(options) {
|
|
|
94
94
|
}
|
|
95
95
|
const output = {
|
|
96
96
|
kind: "mount",
|
|
97
|
-
mount: (host) => mountForm(host, parsed.data, options
|
|
97
|
+
mount: (host) => mountForm(host, parsed.data, options)
|
|
98
98
|
};
|
|
99
99
|
outputs.set(node, output);
|
|
100
100
|
return output;
|
|
@@ -303,13 +303,14 @@ function parseOptions(value, path, issues) {
|
|
|
303
303
|
}] : [];
|
|
304
304
|
});
|
|
305
305
|
}
|
|
306
|
-
function mountForm(host, definition,
|
|
306
|
+
function mountForm(host, definition, options) {
|
|
307
307
|
const instanceId = String(++nextFormInstanceId);
|
|
308
308
|
const instancePrefix = `aigui-form-${instanceId}-${definition.id}`;
|
|
309
309
|
const cardType = `form:${definition.id}:${instanceId}`;
|
|
310
310
|
const owner = {};
|
|
311
311
|
const controller = new AbortController();
|
|
312
312
|
let pending = false;
|
|
313
|
+
let submitted = options.submitted === true;
|
|
313
314
|
let disposed = false;
|
|
314
315
|
const formElement = document.createElement("form");
|
|
315
316
|
formElement.noValidate = true;
|
|
@@ -333,6 +334,16 @@ function mountForm(host, definition, runtime) {
|
|
|
333
334
|
submit.setAttribute("data-aigui-form-submit", "");
|
|
334
335
|
submit.textContent = definition.submitLabel ?? "Submit";
|
|
335
336
|
formElement.appendChild(submit);
|
|
337
|
+
const markSubmitted = () => {
|
|
338
|
+
if (disposed) return;
|
|
339
|
+
pending = false;
|
|
340
|
+
submitted = true;
|
|
341
|
+
formElement.removeAttribute("aria-busy");
|
|
342
|
+
formElement.setAttribute("data-aigui-form-submitted", "");
|
|
343
|
+
for (const element of Array.from(formElement.elements)) if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement || element instanceof HTMLButtonElement || element instanceof HTMLFieldSetElement) element.disabled = true;
|
|
344
|
+
submit.textContent = options.submittedLabel ?? "Submitted";
|
|
345
|
+
};
|
|
346
|
+
if (submitted) markSubmitted();
|
|
336
347
|
const onInput = (event) => {
|
|
337
348
|
const control = event.target;
|
|
338
349
|
if (!(control instanceof HTMLInputElement || control instanceof HTMLTextAreaElement || control instanceof HTMLSelectElement)) return;
|
|
@@ -340,7 +351,7 @@ function mountForm(host, definition, runtime) {
|
|
|
340
351
|
actionError.hidden = true;
|
|
341
352
|
};
|
|
342
353
|
const onSubmit = () => {
|
|
343
|
-
if (pending || disposed) return;
|
|
354
|
+
if (pending || submitted || disposed) return;
|
|
344
355
|
const validation = validateFormValues(definition, readControls(definition, controls));
|
|
345
356
|
renderErrors(validation.errors, controls, errorElements);
|
|
346
357
|
actionError.hidden = true;
|
|
@@ -357,14 +368,14 @@ function mountForm(host, definition, runtime) {
|
|
|
357
368
|
submit.disabled = false;
|
|
358
369
|
formElement.removeAttribute("aria-busy");
|
|
359
370
|
};
|
|
360
|
-
|
|
371
|
+
options.actionRuntime.dispatch({
|
|
361
372
|
type: definition.submitAction,
|
|
362
373
|
params: validation.values,
|
|
363
374
|
cardType
|
|
364
375
|
}, {
|
|
365
376
|
owner,
|
|
366
377
|
signal: controller.signal
|
|
367
|
-
}).then(
|
|
378
|
+
}).then(markSubmitted, (error) => {
|
|
368
379
|
if (!disposed && !controller.signal.aborted) {
|
|
369
380
|
actionError.textContent = actionErrorMessage(error);
|
|
370
381
|
actionError.hidden = false;
|
package/dist/index.d.cts
CHANGED
|
@@ -56,6 +56,10 @@ interface FormValidationResult {
|
|
|
56
56
|
interface FormPluginOptions {
|
|
57
57
|
/** Shared core runtime whose registry is the only allowlist for submitAction. */
|
|
58
58
|
actionRuntime: ActionRuntime;
|
|
59
|
+
/** Mount forms as already submitted, useful when restoring persisted conversations. */
|
|
60
|
+
submitted?: boolean;
|
|
61
|
+
/** Label shown after a successful or restored submission. */
|
|
62
|
+
submittedLabel?: string;
|
|
59
63
|
}
|
|
60
64
|
declare function formPromptSpec(): string;
|
|
61
65
|
declare function form(options: FormPluginOptions): AIGuiPlugin;
|
package/dist/index.d.ts
CHANGED
|
@@ -56,6 +56,10 @@ interface FormValidationResult {
|
|
|
56
56
|
interface FormPluginOptions {
|
|
57
57
|
/** Shared core runtime whose registry is the only allowlist for submitAction. */
|
|
58
58
|
actionRuntime: ActionRuntime;
|
|
59
|
+
/** Mount forms as already submitted, useful when restoring persisted conversations. */
|
|
60
|
+
submitted?: boolean;
|
|
61
|
+
/** Label shown after a successful or restored submission. */
|
|
62
|
+
submittedLabel?: string;
|
|
59
63
|
}
|
|
60
64
|
declare function formPromptSpec(): string;
|
|
61
65
|
declare function form(options: FormPluginOptions): AIGuiPlugin;
|
package/dist/index.js
CHANGED
|
@@ -70,7 +70,7 @@ function form(options) {
|
|
|
70
70
|
}
|
|
71
71
|
const output = {
|
|
72
72
|
kind: "mount",
|
|
73
|
-
mount: (host) => mountForm(host, parsed.data, options
|
|
73
|
+
mount: (host) => mountForm(host, parsed.data, options)
|
|
74
74
|
};
|
|
75
75
|
outputs.set(node, output);
|
|
76
76
|
return output;
|
|
@@ -279,13 +279,14 @@ function parseOptions(value, path, issues) {
|
|
|
279
279
|
}] : [];
|
|
280
280
|
});
|
|
281
281
|
}
|
|
282
|
-
function mountForm(host, definition,
|
|
282
|
+
function mountForm(host, definition, options) {
|
|
283
283
|
const instanceId = String(++nextFormInstanceId);
|
|
284
284
|
const instancePrefix = `aigui-form-${instanceId}-${definition.id}`;
|
|
285
285
|
const cardType = `form:${definition.id}:${instanceId}`;
|
|
286
286
|
const owner = {};
|
|
287
287
|
const controller = new AbortController();
|
|
288
288
|
let pending = false;
|
|
289
|
+
let submitted = options.submitted === true;
|
|
289
290
|
let disposed = false;
|
|
290
291
|
const formElement = document.createElement("form");
|
|
291
292
|
formElement.noValidate = true;
|
|
@@ -309,6 +310,16 @@ function mountForm(host, definition, runtime) {
|
|
|
309
310
|
submit.setAttribute("data-aigui-form-submit", "");
|
|
310
311
|
submit.textContent = definition.submitLabel ?? "Submit";
|
|
311
312
|
formElement.appendChild(submit);
|
|
313
|
+
const markSubmitted = () => {
|
|
314
|
+
if (disposed) return;
|
|
315
|
+
pending = false;
|
|
316
|
+
submitted = true;
|
|
317
|
+
formElement.removeAttribute("aria-busy");
|
|
318
|
+
formElement.setAttribute("data-aigui-form-submitted", "");
|
|
319
|
+
for (const element of Array.from(formElement.elements)) if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement || element instanceof HTMLButtonElement || element instanceof HTMLFieldSetElement) element.disabled = true;
|
|
320
|
+
submit.textContent = options.submittedLabel ?? "Submitted";
|
|
321
|
+
};
|
|
322
|
+
if (submitted) markSubmitted();
|
|
312
323
|
const onInput = (event) => {
|
|
313
324
|
const control = event.target;
|
|
314
325
|
if (!(control instanceof HTMLInputElement || control instanceof HTMLTextAreaElement || control instanceof HTMLSelectElement)) return;
|
|
@@ -316,7 +327,7 @@ function mountForm(host, definition, runtime) {
|
|
|
316
327
|
actionError.hidden = true;
|
|
317
328
|
};
|
|
318
329
|
const onSubmit = () => {
|
|
319
|
-
if (pending || disposed) return;
|
|
330
|
+
if (pending || submitted || disposed) return;
|
|
320
331
|
const validation = validateFormValues(definition, readControls(definition, controls));
|
|
321
332
|
renderErrors(validation.errors, controls, errorElements);
|
|
322
333
|
actionError.hidden = true;
|
|
@@ -333,14 +344,14 @@ function mountForm(host, definition, runtime) {
|
|
|
333
344
|
submit.disabled = false;
|
|
334
345
|
formElement.removeAttribute("aria-busy");
|
|
335
346
|
};
|
|
336
|
-
|
|
347
|
+
options.actionRuntime.dispatch({
|
|
337
348
|
type: definition.submitAction,
|
|
338
349
|
params: validation.values,
|
|
339
350
|
cardType
|
|
340
351
|
}, {
|
|
341
352
|
owner,
|
|
342
353
|
signal: controller.signal
|
|
343
|
-
}).then(
|
|
354
|
+
}).then(markSubmitted, (error) => {
|
|
344
355
|
if (!disposed && !controller.signal.aborted) {
|
|
345
356
|
actionError.textContent = actionErrorMessage(error);
|
|
346
357
|
actionError.hidden = false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-gui/plugin-form",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "Safe interactive form blocks for AIGUI, backed by the core ActionRuntime.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"llm",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"access": "public"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@ai-gui/core": "0.4.
|
|
52
|
+
"@ai-gui/core": "0.4.4"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "tsdown",
|