@ai-gui/plugin-form 0.6.1 → 0.7.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 CHANGED
@@ -318,22 +318,45 @@ function mountForm(host, definition, options) {
318
318
  formElement.setAttribute("data-aigui-form-instance", instanceId);
319
319
  const controls = new Map();
320
320
  const errorElements = new Map();
321
+ const fieldContainers = new Map();
321
322
  for (const field of definition.fields) {
322
323
  const rendered = createField(instancePrefix, field);
323
324
  formElement.appendChild(rendered.container);
324
325
  controls.set(field.name, rendered.control);
325
326
  errorElements.set(field.name, rendered.error);
327
+ fieldContainers.set(field.name, rendered.container);
326
328
  }
327
329
  const actionError = document.createElement("div");
328
330
  actionError.setAttribute("data-aigui-form-action-error", "");
329
331
  actionError.setAttribute("role", "alert");
330
332
  actionError.hidden = true;
331
333
  formElement.appendChild(actionError);
334
+ const outcomeMessage = document.createElement("div");
335
+ outcomeMessage.setAttribute("data-aigui-form-outcome-message", "");
336
+ outcomeMessage.setAttribute("aria-live", "polite");
337
+ outcomeMessage.hidden = true;
338
+ formElement.appendChild(outcomeMessage);
332
339
  const submit = document.createElement("button");
333
340
  submit.type = "button";
334
341
  submit.setAttribute("data-aigui-form-submit", "");
335
342
  submit.textContent = definition.submitLabel ?? "Submit";
336
343
  formElement.appendChild(submit);
344
+ /**
345
+ * Show how the submission turned out, when the handler judged it.
346
+ *
347
+ * The result used to be discarded, so an app that knew the answer was wrong had no way to say so
348
+ * — the form simply disabled itself and read "Submitted" whether the answer was right or not.
349
+ */
350
+ const applyOutcome = (result) => {
351
+ const outcome = (0, __ai_gui_core.actionOutcome)(result);
352
+ if (!outcome || disposed) return;
353
+ formElement.setAttribute("data-aigui-form-outcome", outcome.tone);
354
+ if (outcome.message) {
355
+ outcomeMessage.textContent = outcome.message;
356
+ outcomeMessage.hidden = false;
357
+ }
358
+ for (const [name, tone] of Object.entries(outcome.fields ?? {})) fieldContainers.get(name)?.setAttribute("data-aigui-form-field-outcome", tone);
359
+ };
337
360
  const markSubmitted = () => {
338
361
  if (disposed) return;
339
362
  pending = false;
@@ -375,7 +398,10 @@ function mountForm(host, definition, options) {
375
398
  }, {
376
399
  owner,
377
400
  signal: controller.signal
378
- }).then(markSubmitted, (error) => {
401
+ }).then((result) => {
402
+ markSubmitted();
403
+ applyOutcome(result);
404
+ }, (error) => {
379
405
  if (!disposed && !controller.signal.aborted) {
380
406
  actionError.textContent = actionErrorMessage(error);
381
407
  actionError.hidden = false;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ActionRuntimeError } from "@ai-gui/core";
1
+ import { ActionRuntimeError, actionOutcome } from "@ai-gui/core";
2
2
 
3
3
  //#region src/index.ts
4
4
  const FIELD_TYPES = new Set([
@@ -294,22 +294,45 @@ function mountForm(host, definition, options) {
294
294
  formElement.setAttribute("data-aigui-form-instance", instanceId);
295
295
  const controls = new Map();
296
296
  const errorElements = new Map();
297
+ const fieldContainers = new Map();
297
298
  for (const field of definition.fields) {
298
299
  const rendered = createField(instancePrefix, field);
299
300
  formElement.appendChild(rendered.container);
300
301
  controls.set(field.name, rendered.control);
301
302
  errorElements.set(field.name, rendered.error);
303
+ fieldContainers.set(field.name, rendered.container);
302
304
  }
303
305
  const actionError = document.createElement("div");
304
306
  actionError.setAttribute("data-aigui-form-action-error", "");
305
307
  actionError.setAttribute("role", "alert");
306
308
  actionError.hidden = true;
307
309
  formElement.appendChild(actionError);
310
+ const outcomeMessage = document.createElement("div");
311
+ outcomeMessage.setAttribute("data-aigui-form-outcome-message", "");
312
+ outcomeMessage.setAttribute("aria-live", "polite");
313
+ outcomeMessage.hidden = true;
314
+ formElement.appendChild(outcomeMessage);
308
315
  const submit = document.createElement("button");
309
316
  submit.type = "button";
310
317
  submit.setAttribute("data-aigui-form-submit", "");
311
318
  submit.textContent = definition.submitLabel ?? "Submit";
312
319
  formElement.appendChild(submit);
320
+ /**
321
+ * Show how the submission turned out, when the handler judged it.
322
+ *
323
+ * The result used to be discarded, so an app that knew the answer was wrong had no way to say so
324
+ * — the form simply disabled itself and read "Submitted" whether the answer was right or not.
325
+ */
326
+ const applyOutcome = (result) => {
327
+ const outcome = actionOutcome(result);
328
+ if (!outcome || disposed) return;
329
+ formElement.setAttribute("data-aigui-form-outcome", outcome.tone);
330
+ if (outcome.message) {
331
+ outcomeMessage.textContent = outcome.message;
332
+ outcomeMessage.hidden = false;
333
+ }
334
+ for (const [name, tone] of Object.entries(outcome.fields ?? {})) fieldContainers.get(name)?.setAttribute("data-aigui-form-field-outcome", tone);
335
+ };
313
336
  const markSubmitted = () => {
314
337
  if (disposed) return;
315
338
  pending = false;
@@ -351,7 +374,10 @@ function mountForm(host, definition, options) {
351
374
  }, {
352
375
  owner,
353
376
  signal: controller.signal
354
- }).then(markSubmitted, (error) => {
377
+ }).then((result) => {
378
+ markSubmitted();
379
+ applyOutcome(result);
380
+ }, (error) => {
355
381
  if (!disposed && !controller.signal.aborted) {
356
382
  actionError.textContent = actionErrorMessage(error);
357
383
  actionError.hidden = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-gui/plugin-form",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
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.6.1"
52
+ "@ai-gui/core": "0.7.0"
53
53
  },
54
54
  "scripts": {
55
55
  "build": "tsdown",