@stonecrop/aform 0.34.0 → 0.35.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/aform.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { hasBadgeOptions, isBadgeDescriptor, lookupBadge, selectChoices } from "@stonecrop/schema";
2
2
  import { install as install$1 } from "@stonecrop/atable";
3
- import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, mergeModels, mergeProps, nextTick, normalizeClass, normalizeStyle, onMounted, openBlock, provide, reactive, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, useId, useModel, useTemplateRef, vModelCheckbox, vModelRadio, vModelSelect, vModelText, vShow, watch, watchEffect, withCtx, withDirectives, withKeys, withModifiers } from "vue";
3
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, inject, mergeModels, mergeProps, nextTick, normalizeClass, normalizeStyle, onMounted, openBlock, provide, reactive, ref, renderList, renderSlot, resolveComponent, resolveDynamicComponent, toDisplayString, unref, useId, useModel, useTemplateRef, vModelCheckbox, vModelRadio, vModelSelect, vModelText, vShow, watch, watchEffect, withCtx, withDirectives, withKeys, withModifiers } from "vue";
4
4
  import { vOnClickOutside } from "@vueuse/components";
5
5
  import { onClickOutside, useFileDialog } from "@vueuse/core";
6
6
  import './assets/index.css';//#region src/utils/deserialize.ts
@@ -115,6 +115,18 @@ function resolvedFieldsToColumns(fields) {
115
115
  return columns;
116
116
  }
117
117
  //#endregion
118
+ //#region src/composables/fieldErrorA11y.ts
119
+ function fieldErrorA11y(uuid, errorText) {
120
+ const errorId = computed(() => uuid ? `${uuid}-error` : void 0);
121
+ const hasError = computed(() => Boolean(errorText.value));
122
+ return {
123
+ errorId,
124
+ hasError,
125
+ describedBy: computed(() => hasError.value && errorId.value ? errorId.value : void 0),
126
+ invalid: computed(() => hasError.value ? true : void 0)
127
+ };
128
+ }
129
+ //#endregion
118
130
  //#region src/components/form/ACheckbox.vue?vue&type=script&setup=true&lang.ts
119
131
  var _hoisted_1$20 = { class: "aform_form-element" };
120
132
  var _hoisted_2$19 = { class: "aform_field-label" };
@@ -124,9 +136,11 @@ var _hoisted_5$16 = { class: "aform_checkbox-container aform_input-field" };
124
136
  var _hoisted_6$16 = [
125
137
  "id",
126
138
  "disabled",
127
- "required"
139
+ "required",
140
+ "aria-invalid",
141
+ "aria-describedby"
128
142
  ];
129
- var _hoisted_7$7 = ["innerHTML"];
143
+ var _hoisted_7$7 = ["id"];
130
144
  var ACheckbox_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
131
145
  __name: "ACheckbox",
132
146
  props: /*@__PURE__*/ mergeModels({
@@ -151,6 +165,7 @@ var ACheckbox_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
151
165
  emits: ["update:modelValue"],
152
166
  setup(__props) {
153
167
  const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
168
+ const { errorId, describedBy, invalid } = fieldErrorA11y(__props.uuid, errorText);
154
169
  const checkbox = useModel(__props, "modelValue");
155
170
  return (_ctx, _cache) => {
156
171
  return openBlock(), createElementBlock("div", _hoisted_1$20, [__props.mode === "display" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("label", _hoisted_2$19, toDisplayString(__props.label), 1), createElementVNode("span", _hoisted_3$17, toDisplayString(checkbox.value ? "✓" : "✗"), 1)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
@@ -164,12 +179,15 @@ var ACheckbox_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
164
179
  type: "checkbox",
165
180
  class: "aform_checkbox",
166
181
  disabled: __props.mode === "read",
167
- required: __props.required
182
+ required: __props.required,
183
+ "aria-invalid": unref(invalid),
184
+ "aria-describedby": unref(describedBy)
168
185
  }, null, 8, _hoisted_6$16), [[vModelCheckbox, checkbox.value]])]),
169
186
  withDirectives(createElementVNode("p", {
187
+ id: unref(errorId),
170
188
  class: "aform_error",
171
- innerHTML: errorText.value
172
- }, null, 8, _hoisted_7$7), [[vShow, errorText.value]])
189
+ role: "alert"
190
+ }, toDisplayString(errorText.value), 9, _hoisted_7$7), [[vShow, errorText.value]])
173
191
  ], 64))]);
174
192
  };
175
193
  }
@@ -183,17 +201,19 @@ var _plugin_vue_export_helper_default = (sfc, props) => {
183
201
  };
184
202
  //#endregion
185
203
  //#region src/components/form/ACheckbox.vue
186
- var ACheckbox_default = /*#__PURE__*/ _plugin_vue_export_helper_default(ACheckbox_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-ca06741d"]]);
204
+ var ACheckbox_default = /*#__PURE__*/ _plugin_vue_export_helper_default(ACheckbox_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-f28e7db6"]]);
187
205
  //#endregion
188
206
  //#region src/components/form/AFormLink.vue?vue&type=script&setup=true&lang.ts
189
- var _hoisted_1$19 = {
207
+ var _hoisted_1$19 = { class: "aform_display-value" };
208
+ var _hoisted_2$18 = {
190
209
  key: 0,
191
- class: "aform_display-value"
210
+ class: "aform_field-label"
192
211
  };
193
- var _hoisted_2$18 = { class: "aform_form-link-wrapper" };
194
- var _hoisted_3$16 = { class: "input-group" };
195
- var _hoisted_4$15 = [
212
+ var _hoisted_3$16 = { class: "aform_form-link-wrapper" };
213
+ var _hoisted_4$15 = { class: "input-group" };
214
+ var _hoisted_5$15 = [
196
215
  "placeholder",
216
+ "size",
197
217
  "aria-label",
198
218
  "required",
199
219
  "aria-expanded",
@@ -202,18 +222,28 @@ var _hoisted_4$15 = [
202
222
  "disabled",
203
223
  "onKeydown"
204
224
  ];
205
- var _hoisted_5$15 = ["onKeydown"];
206
- var _hoisted_6$15 = ["aria-label"];
207
- var _hoisted_7$6 = {
225
+ var _hoisted_6$15 = ["onKeydown"];
226
+ var _hoisted_7$6 = ["data-icon"];
227
+ var _hoisted_8$6 = {
228
+ key: 0,
229
+ d: "M6 3.5 10.5 8 6 12.5"
230
+ };
231
+ var _hoisted_9$5 = {
232
+ key: 1,
233
+ d: "M2.5 8h11M9 3.5 13.5 8 9 12.5"
234
+ };
235
+ var _hoisted_10$4 = { class: "aform_form-btn-name" };
236
+ var _hoisted_11$4 = ["aria-label"];
237
+ var _hoisted_12$4 = {
208
238
  key: 0,
209
239
  class: "autocomplete-result loading"
210
240
  };
211
- var _hoisted_8$6 = [
241
+ var _hoisted_13$2 = [
212
242
  "id",
213
243
  "aria-selected",
214
244
  "onMousedown"
215
245
  ];
216
- var _hoisted_9$5 = {
246
+ var _hoisted_14$2 = {
217
247
  key: 0,
218
248
  class: "aform_field-label"
219
249
  };
@@ -274,6 +304,7 @@ var AFormLink_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
274
304
  return linkDisplayText(modelValue.value) ?? id;
275
305
  });
276
306
  const searchText = ref(hasValidId.value ? displayedText.value : "");
307
+ const embeddedSize = computed(() => __props.embedded ? Math.max((searchText.value || __props.placeholder || "").length, 1) : void 0);
277
308
  const dropdownOpen = ref(false);
278
309
  const loading = ref(false);
279
310
  const dropdownResults = ref([]);
@@ -373,7 +404,7 @@ var AFormLink_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
373
404
  if (activeIndex.value !== null && dropdownResults.value[activeIndex.value]) selectOption(dropdownResults.value[activeIndex.value]);
374
405
  };
375
406
  return (_ctx, _cache) => {
376
- return openBlock(), createElementBlock("div", { class: normalizeClass(["aform_form-element", { "aform_form-element--embedded": __props.embedded }]) }, [__props.mode === "display" ? (openBlock(), createElementBlock("span", _hoisted_1$19, toDisplayString(displayedText.value), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [withDirectives((openBlock(), createElementBlock("div", _hoisted_2$18, [createElementVNode("div", _hoisted_3$16, [withDirectives(createElementVNode("input", {
407
+ return openBlock(), createElementBlock("div", { class: normalizeClass(["aform_form-element", { "aform_form-element--embedded": __props.embedded }]) }, [__props.mode === "display" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("span", _hoisted_1$19, toDisplayString(displayedText.value), 1), __props.label && !__props.embedded ? (openBlock(), createElementBlock("label", _hoisted_2$18, toDisplayString(__props.label), 1)) : createCommentVNode("", true)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [withDirectives((openBlock(), createElementBlock("div", _hoisted_3$16, [createElementVNode("div", _hoisted_4$15, [withDirectives(createElementVNode("input", {
377
408
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => searchText.value = $event),
378
409
  type: "text",
379
410
  role: "combobox",
@@ -381,6 +412,7 @@ var AFormLink_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
381
412
  "aria-autocomplete": "list",
382
413
  class: normalizeClass(["aform_input-field", { "aform_input-field--embedded": __props.embedded }]),
383
414
  placeholder: __props.placeholder,
415
+ size: embeddedSize.value,
384
416
  "aria-label": __props.ariaLabel,
385
417
  required: __props.required,
386
418
  "aria-expanded": dropdownOpen.value,
@@ -396,19 +428,25 @@ var AFormLink_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
396
428
  withKeys(closeDropdown, ["esc"]),
397
429
  withKeys(closeDropdown, ["tab"])
398
430
  ]
399
- }, null, 42, _hoisted_4$15), [[vModelText, searchText.value]]), hasValidId.value && !__props.disabled && !__props.embedded ? (openBlock(), createElementBlock("button", {
431
+ }, null, 42, _hoisted_5$15), [[vModelText, searchText.value]]), hasValidId.value && !__props.disabled && !__props.embedded ? (openBlock(), createElementBlock("button", {
400
432
  key: 0,
401
433
  type: "button",
402
434
  class: "aform_form-btn",
403
435
  onClick: handleNavigate,
404
436
  onKeydown: withKeys(withModifiers(handleNavigate, ["prevent"]), ["enter"])
405
- }, [createElementVNode("span", null, toDisplayString(__props.icon === "chevron-right" ? "›" : "→"), 1)], 40, _hoisted_5$15)) : createCommentVNode("", true)]), dropdownOpen.value ? (openBlock(), createElementBlock("ul", {
437
+ }, [(openBlock(), createElementBlock("svg", {
438
+ class: "aform_form-btn-icon",
439
+ "data-icon": __props.icon,
440
+ viewBox: "1.75 2.75 12.5 10.5",
441
+ "aria-hidden": "true",
442
+ focusable: "false"
443
+ }, [__props.icon === "chevron-right" ? (openBlock(), createElementBlock("path", _hoisted_8$6)) : (openBlock(), createElementBlock("path", _hoisted_9$5))], 8, _hoisted_7$6)), createElementVNode("span", _hoisted_10$4, toDisplayString(__props.icon === "chevron-right" ? "›" : "→"), 1)], 40, _hoisted_6$15)) : createCommentVNode("", true)]), dropdownOpen.value ? (openBlock(), createElementBlock("ul", {
406
444
  key: 0,
407
445
  id: listboxId,
408
446
  class: "autocomplete-results",
409
447
  role: "listbox",
410
448
  "aria-label": __props.ariaLabel
411
- }, [loading.value ? (openBlock(), createElementBlock("li", _hoisted_7$6, "Loading…")) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(dropdownResults.value, (option, i) => {
449
+ }, [loading.value ? (openBlock(), createElementBlock("li", _hoisted_12$4, "Loading…")) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(dropdownResults.value, (option, i) => {
412
450
  return openBlock(), createElementBlock("li", {
413
451
  id: `${listboxId}-opt-${i}`,
414
452
  key: String(option.id),
@@ -416,11 +454,11 @@ var AFormLink_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
416
454
  "aria-selected": i === activeIndex.value,
417
455
  class: normalizeClass(["autocomplete-result", { "is-active": i === activeIndex.value }]),
418
456
  onMousedown: withModifiers(($event) => selectOption(option), ["prevent"])
419
- }, [renderSlot(_ctx.$slots, "option", { option }, () => [createTextVNode(toDisplayString(option.displayText ?? String(option.id)), 1)], true)], 42, _hoisted_8$6);
420
- }), 128))], 8, _hoisted_6$15)) : createCommentVNode("", true)])), [[unref(vOnClickOutside), onClickOutside]]), __props.label && !__props.embedded ? (openBlock(), createElementBlock("label", _hoisted_9$5, toDisplayString(__props.label), 1)) : createCommentVNode("", true)], 64))], 2);
457
+ }, [renderSlot(_ctx.$slots, "option", { option }, () => [createTextVNode(toDisplayString(option.displayText ?? String(option.id)), 1)], true)], 42, _hoisted_13$2);
458
+ }), 128))], 8, _hoisted_11$4)) : createCommentVNode("", true)])), [[unref(vOnClickOutside), onClickOutside]]), __props.label && !__props.embedded ? (openBlock(), createElementBlock("label", _hoisted_14$2, toDisplayString(__props.label), 1)) : createCommentVNode("", true)], 64))], 2);
421
459
  };
422
460
  }
423
- }), [["__scopeId", "data-v-91a761d0"]]);
461
+ }), [["__scopeId", "data-v-07d20e9b"]]);
424
462
  //#endregion
425
463
  //#region src/components/form/ACurrencyInput.vue?vue&type=script&setup=true&lang.ts
426
464
  var _hoisted_1$18 = { class: "aform_form-element acurrency" };
@@ -434,7 +472,9 @@ var _hoisted_8$5 = { class: "acurrency__amount-wrap" };
434
472
  var _hoisted_9$4 = [
435
473
  "id",
436
474
  "disabled",
437
- "required"
475
+ "required",
476
+ "aria-invalid",
477
+ "aria-describedby"
438
478
  ];
439
479
  var _hoisted_10$3 = ["for"];
440
480
  var _hoisted_11$3 = { class: "acurrency__row acurrency__row--base" };
@@ -447,7 +487,7 @@ var _hoisted_17$1 = { class: "aform_field-label" };
447
487
  var _hoisted_18$1 = { class: "acurrency__field acurrency__field--exchange-rate" };
448
488
  var _hoisted_19$1 = ["value"];
449
489
  var _hoisted_20$1 = { class: "aform_field-label" };
450
- var _hoisted_21$1 = ["innerHTML"];
490
+ var _hoisted_21$1 = ["id"];
451
491
  var FLOAT_NOISE_DECIMALS = 6;
452
492
  //#endregion
453
493
  //#region src/components/form/ACurrencyInput.vue
@@ -461,7 +501,7 @@ var ACurrencyInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
461
501
  required: { type: Boolean },
462
502
  mode: {},
463
503
  uuid: {},
464
- validation: { default: () => ({ errorMessage: " " }) },
504
+ validation: { default: () => ({ errorMessage: "" }) },
465
505
  errors: {},
466
506
  options: { default: () => ({}) },
467
507
  currencyLabel: { default: "Currency" },
@@ -480,6 +520,8 @@ var ACurrencyInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
480
520
  }),
481
521
  emits: ["update:modelValue"],
482
522
  setup(__props) {
523
+ const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
524
+ const { errorId, describedBy, invalid } = fieldErrorA11y(__props.uuid, errorText);
483
525
  const currencySymbol = (value) => value.symbol ?? value.displayText ?? String(value.id);
484
526
  const modelValue = useModel(__props, "modelValue");
485
527
  const normalizedBaseCurrency = computed(() => {
@@ -611,6 +653,8 @@ var ACurrencyInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
611
653
  type: "number",
612
654
  disabled: __props.mode === "read",
613
655
  required: __props.required,
656
+ "aria-invalid": unref(invalid),
657
+ "aria-describedby": unref(describedBy),
614
658
  onKeydown: onAmountKeydown,
615
659
  onPaste: onAmountPaste
616
660
  }, null, 40, _hoisted_9$4), [[
@@ -643,18 +687,19 @@ var ACurrencyInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
643
687
  }, null, 8, _hoisted_19$1), createElementVNode("label", _hoisted_20$1, toDisplayString(__props.exchangeRateLabel), 1)])
644
688
  ]),
645
689
  withDirectives(createElementVNode("p", {
690
+ id: unref(errorId),
646
691
  class: "aform_error",
647
- innerHTML: __props.validation.errorMessage
648
- }, null, 8, _hoisted_21$1), [[vShow, __props.validation.errorMessage]])
692
+ role: "alert"
693
+ }, toDisplayString(errorText.value), 9, _hoisted_21$1), [[vShow, errorText.value]])
649
694
  ], 64))]);
650
695
  };
651
696
  }
652
- }), [["__scopeId", "data-v-77852830"]]);
697
+ }), [["__scopeId", "data-v-f61b058f"]]);
653
698
  //#endregion
654
699
  //#region src/components/form/ADatePicker.vue?vue&type=script&setup=true&lang.ts
655
700
  var _hoisted_1$17 = { class: "aform_display-value" };
656
701
  var _hoisted_2$16 = { key: 0 };
657
- var _hoisted_3$14 = ["innerHTML"];
702
+ var _hoisted_3$14 = ["id"];
658
703
  var _hoisted_4$13 = {
659
704
  ref: "datepicker",
660
705
  class: "adatepicker",
@@ -674,7 +719,7 @@ var _hoisted_11$2 = [
674
719
  "onKeydown",
675
720
  "onMouseover"
676
721
  ];
677
- var _hoisted_12$2 = ["innerHTML"];
722
+ var _hoisted_12$2 = ["id"];
678
723
  var numberOfRows = 6;
679
724
  var numberOfColumns = 7;
680
725
  //#endregion
@@ -701,6 +746,7 @@ var ADatePicker_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__
701
746
  emits: /*@__PURE__*/ mergeModels(["get-date"], ["update:modelValue"]),
702
747
  setup(__props, { expose: __expose, emit: __emit }) {
703
748
  const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
749
+ const { errorId } = fieldErrorA11y(__props.uuid, errorText);
704
750
  const date = useModel(__props, "modelValue");
705
751
  const selectedDate = ref(new Date(date.value));
706
752
  const currentMonth = ref(selectedDate.value.getMonth());
@@ -877,9 +923,10 @@ var ADatePicker_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__
877
923
  createElementVNode("span", _hoisted_1$17, toDisplayString(date.value ? new Date(date.value).toLocaleDateString() : ""), 1),
878
924
  __props.label ? (openBlock(), createElementBlock("label", _hoisted_2$16, toDisplayString(__props.label), 1)) : createCommentVNode("", true),
879
925
  withDirectives(createElementVNode("p", {
926
+ id: unref(errorId),
880
927
  class: "aform_error",
881
- innerHTML: errorText.value
882
- }, null, 8, _hoisted_3$14), [[vShow, errorText.value]])
928
+ role: "alert"
929
+ }, toDisplayString(errorText.value), 9, _hoisted_3$14), [[vShow, errorText.value]])
883
930
  ], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createElementVNode("div", _hoisted_4$13, [createElementVNode("table", { onMousedown: preventCellSelection }, [createElementVNode("tbody", null, [
884
931
  createElementVNode("tr", null, [
885
932
  createElementVNode("td", {
@@ -947,12 +994,13 @@ var ADatePicker_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__
947
994
  }), 64))]);
948
995
  }), 64))
949
996
  ])], 32)], 512), withDirectives(createElementVNode("p", {
997
+ id: unref(errorId),
950
998
  class: "aform_error",
951
- innerHTML: errorText.value
952
- }, null, 8, _hoisted_12$2), [[vShow, errorText.value]])], 64));
999
+ role: "alert"
1000
+ }, toDisplayString(errorText.value), 9, _hoisted_12$2), [[vShow, errorText.value]])], 64));
953
1001
  };
954
1002
  }
955
- }), [["__scopeId", "data-v-ef698187"]]);
1003
+ }), [["__scopeId", "data-v-e22e44d1"]]);
956
1004
  //#endregion
957
1005
  //#region src/components/form/ADateTimeInput.vue?vue&type=script&setup=true&lang.ts
958
1006
  var _hoisted_1$16 = { class: "adate_time" };
@@ -1148,7 +1196,7 @@ var ADateTimeInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
1148
1196
  ])]);
1149
1197
  };
1150
1198
  }
1151
- }), [["__scopeId", "data-v-95ad0aa4"]]);
1199
+ }), [["__scopeId", "data-v-3a6e48db"]]);
1152
1200
  //#endregion
1153
1201
  //#region src/components/form/ADateSelection.vue?vue&type=script&setup=true&lang.ts
1154
1202
  var _hoisted_1$15 = { class: "adate-selection" };
@@ -1286,7 +1334,7 @@ var ADateSelection_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
1286
1334
  ]);
1287
1335
  };
1288
1336
  }
1289
- }), [["__scopeId", "data-v-36e737ea"]]);
1337
+ }), [["__scopeId", "data-v-48e71f28"]]);
1290
1338
  //#endregion
1291
1339
  //#region src/components/form/ADate.vue?vue&type=script&setup=true&lang.ts
1292
1340
  var _hoisted_1$14 = { class: "aform_form-element" };
@@ -1295,10 +1343,12 @@ var _hoisted_3$12 = { class: "aform_field-label" };
1295
1343
  var _hoisted_4$11 = [
1296
1344
  "id",
1297
1345
  "disabled",
1298
- "required"
1346
+ "required",
1347
+ "aria-invalid",
1348
+ "aria-describedby"
1299
1349
  ];
1300
1350
  var _hoisted_5$11 = ["for"];
1301
- var _hoisted_6$11 = ["innerHTML"];
1351
+ var _hoisted_6$11 = ["id"];
1302
1352
  //#endregion
1303
1353
  //#region src/components/form/ADate.vue
1304
1354
  var ADate_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -1320,6 +1370,7 @@ var ADate_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__
1320
1370
  emits: ["update:modelValue"],
1321
1371
  setup(__props) {
1322
1372
  const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
1373
+ const { errorId, describedBy, invalid } = fieldErrorA11y(__props.uuid, errorText);
1323
1374
  const modelValue = useModel(__props, "modelValue");
1324
1375
  const currentDate = ref(modelValue.value ? new Date(modelValue.value) : /* @__PURE__ */ new Date());
1325
1376
  const inputDate = computed({
@@ -1353,6 +1404,8 @@ var ADate_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__
1353
1404
  type: "date",
1354
1405
  disabled: __props.mode === "read",
1355
1406
  required: __props.required,
1407
+ "aria-invalid": unref(invalid),
1408
+ "aria-describedby": unref(describedBy),
1356
1409
  onClick: openPicker
1357
1410
  }, null, 8, _hoisted_4$11), [[vModelText, inputDate.value]]),
1358
1411
  createElementVNode("label", {
@@ -1360,9 +1413,10 @@ var ADate_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__
1360
1413
  for: __props.uuid
1361
1414
  }, toDisplayString(__props.label), 9, _hoisted_5$11),
1362
1415
  withDirectives(createElementVNode("p", {
1416
+ id: unref(errorId),
1363
1417
  class: "aform_error",
1364
- innerHTML: errorText.value
1365
- }, null, 8, _hoisted_6$11), [[vShow, errorText.value]]),
1418
+ role: "alert"
1419
+ }, toDisplayString(errorText.value), 9, _hoisted_6$11), [[vShow, errorText.value]]),
1366
1420
  showPicker.value ? (openBlock(), createBlock(ADateSelection_default, {
1367
1421
  key: 0,
1368
1422
  ref: "picker",
@@ -1374,7 +1428,7 @@ var ADate_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__
1374
1428
  ], 64))]);
1375
1429
  };
1376
1430
  }
1377
- }), [["__scopeId", "data-v-5de3fe7a"]]);
1431
+ }), [["__scopeId", "data-v-e1403ea0"]]);
1378
1432
  //#endregion
1379
1433
  //#region src/components/form/ADropdown.vue?vue&type=script&setup=true&lang.ts
1380
1434
  var _hoisted_1$13 = { class: "aform_form-element" };
@@ -1383,18 +1437,28 @@ var _hoisted_2$12 = {
1383
1437
  class: "aform_display-value"
1384
1438
  };
1385
1439
  var _hoisted_3$11 = { class: "aform_field-label" };
1386
- var _hoisted_4$10 = ["disabled"];
1387
- var _hoisted_5$10 = {
1388
- id: "autocomplete-results",
1389
- class: "autocomplete-results"
1390
- };
1440
+ var _hoisted_4$10 = [
1441
+ "id",
1442
+ "disabled",
1443
+ "aria-expanded",
1444
+ "aria-controls",
1445
+ "aria-activedescendant",
1446
+ "aria-invalid",
1447
+ "aria-describedby",
1448
+ "onKeydown"
1449
+ ];
1450
+ var _hoisted_5$10 = ["id", "aria-label"];
1391
1451
  var _hoisted_6$10 = {
1392
1452
  key: 0,
1393
1453
  class: "loading autocomplete-result"
1394
1454
  };
1395
- var _hoisted_7$3 = ["onClick"];
1396
- var _hoisted_8$3 = { class: "aform_field-label" };
1397
- var _hoisted_9$2 = ["innerHTML"];
1455
+ var _hoisted_7$3 = [
1456
+ "id",
1457
+ "aria-selected",
1458
+ "onMousedown"
1459
+ ];
1460
+ var _hoisted_8$3 = ["for"];
1461
+ var _hoisted_9$2 = ["id"];
1398
1462
  //#endregion
1399
1463
  //#region src/components/form/ADropdown.vue
1400
1464
  var ADropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -1425,12 +1489,14 @@ var ADropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
1425
1489
  }),
1426
1490
  emits: ["update:modelValue"],
1427
1491
  setup(__props) {
1492
+ const listboxId = useId();
1428
1493
  const choiceList = computed(() => selectChoices(__props.options));
1429
1494
  const formatFn = computed(() => __props.format ? deserializeFunction(__props.format) : void 0);
1430
1495
  const badgeDescriptor = computed(() => resolveFieldBadge(search.value, __props.options, formatFn.value));
1431
1496
  const inputAccentStyle = computed(() => badgeInputAccentStyle(badgeDescriptor.value));
1432
1497
  const displayAccentStyle = computed(() => badgeInputAccentStyle(badgeDescriptor.value));
1433
1498
  const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
1499
+ const { errorId, describedBy, invalid } = fieldErrorA11y(__props.uuid, errorText);
1434
1500
  const search = useModel(__props, "modelValue");
1435
1501
  const committedValue = ref(search.value ?? "");
1436
1502
  const dropdown = reactive({
@@ -1508,36 +1574,57 @@ var ADropdown_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
1508
1574
  style: normalizeStyle(displayAccentStyle.value)
1509
1575
  }, toDisplayString(badgeDescriptor.value.label), 5)) : (openBlock(), createElementBlock("span", _hoisted_2$12, toDisplayString(search.value ?? ""), 1)), createElementVNode("label", _hoisted_3$11, toDisplayString(__props.label), 1)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [withDirectives((openBlock(), createElementBlock("div", { class: normalizeClass(["autocomplete", { isOpen: dropdown.open }]) }, [
1510
1576
  withDirectives(createElementVNode("input", {
1577
+ id: __props.uuid,
1511
1578
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => search.value = $event),
1512
1579
  type: "text",
1580
+ role: "combobox",
1581
+ autocomplete: "off",
1582
+ "aria-autocomplete": "list",
1513
1583
  class: "aform_input-field",
1514
1584
  disabled: __props.mode === "read",
1515
1585
  style: normalizeStyle(inputAccentStyle.value),
1586
+ "aria-expanded": dropdown.open,
1587
+ "aria-controls": dropdown.open ? unref(listboxId) : void 0,
1588
+ "aria-activedescendant": dropdown.activeItemIndex === null ? void 0 : `${unref(listboxId)}-opt-${dropdown.activeItemIndex}`,
1589
+ "aria-invalid": unref(invalid),
1590
+ "aria-describedby": unref(describedBy),
1516
1591
  onInput: filter,
1517
1592
  onFocus: openDropdown,
1518
1593
  onKeydown: [
1519
- withKeys(selectNextResult, ["down"]),
1520
- withKeys(selectPrevResult, ["up"]),
1521
- withKeys(setCurrentResult, ["enter"]),
1594
+ withKeys(withModifiers(selectNextResult, ["prevent"]), ["down"]),
1595
+ withKeys(withModifiers(selectPrevResult, ["prevent"]), ["up"]),
1596
+ withKeys(withModifiers(setCurrentResult, ["prevent"]), ["enter"]),
1522
1597
  withKeys(onClickOutside, ["esc"]),
1523
1598
  withKeys(onClickOutside, ["tab"])
1524
1599
  ]
1525
1600
  }, null, 44, _hoisted_4$10), [[vModelText, search.value]]),
1526
- withDirectives(createElementVNode("ul", _hoisted_5$10, [dropdown.loading ? (openBlock(), createElementBlock("li", _hoisted_6$10, "Loading results...")) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(dropdown.results, (result, i) => {
1601
+ withDirectives(createElementVNode("ul", {
1602
+ id: unref(listboxId),
1603
+ class: "autocomplete-results",
1604
+ role: "listbox",
1605
+ "aria-label": __props.label
1606
+ }, [dropdown.loading ? (openBlock(), createElementBlock("li", _hoisted_6$10, "Loading results...")) : (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(dropdown.results, (result, i) => {
1527
1607
  return openBlock(), createElementBlock("li", {
1608
+ id: `${unref(listboxId)}-opt-${i}`,
1528
1609
  key: result,
1610
+ role: "option",
1611
+ "aria-selected": i === dropdown.activeItemIndex,
1529
1612
  class: normalizeClass(["autocomplete-result", { "is-active": i === dropdown.activeItemIndex }]),
1530
- onClick: withModifiers(($event) => setResult(result), ["stop"])
1531
- }, toDisplayString(result), 11, _hoisted_7$3);
1532
- }), 128))], 512), [[vShow, dropdown.open]]),
1533
- createElementVNode("label", _hoisted_8$3, toDisplayString(__props.label), 1)
1613
+ onMousedown: withModifiers(($event) => setResult(result), ["prevent"])
1614
+ }, toDisplayString(result), 43, _hoisted_7$3);
1615
+ }), 128))], 8, _hoisted_5$10), [[vShow, dropdown.open]]),
1616
+ createElementVNode("label", {
1617
+ class: "aform_field-label",
1618
+ for: __props.uuid
1619
+ }, toDisplayString(__props.label), 9, _hoisted_8$3)
1534
1620
  ], 2)), [[unref(vOnClickOutside), onClickOutside]]), withDirectives(createElementVNode("p", {
1621
+ id: unref(errorId),
1535
1622
  class: "aform_error",
1536
- innerHTML: errorText.value
1537
- }, null, 8, _hoisted_9$2), [[vShow, errorText.value]])], 64))]);
1623
+ role: "alert"
1624
+ }, toDisplayString(errorText.value), 9, _hoisted_9$2), [[vShow, errorText.value]])], 64))]);
1538
1625
  };
1539
1626
  }
1540
- }), [["__scopeId", "data-v-4206fcf7"]]);
1627
+ }), [["__scopeId", "data-v-2275075e"]]);
1541
1628
  //#endregion
1542
1629
  //#region src/components/form/ABadge.vue
1543
1630
  var ABadge_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -1599,7 +1686,9 @@ var _hoisted_3$10 = [
1599
1686
  "role",
1600
1687
  "aria-labelledby",
1601
1688
  "aria-label",
1602
- "aria-busy"
1689
+ "aria-busy",
1690
+ "aria-invalid",
1691
+ "aria-describedby"
1603
1692
  ];
1604
1693
  var _hoisted_4$9 = ["data-segment-value"];
1605
1694
  var _hoisted_5$9 = [
@@ -1613,7 +1702,7 @@ var _hoisted_6$9 = [
1613
1702
  "disabled"
1614
1703
  ];
1615
1704
  var _hoisted_7$2 = { class: "aform_segmented-label" };
1616
- var _hoisted_8$2 = ["innerHTML"];
1705
+ var _hoisted_8$2 = ["id"];
1617
1706
  //#endregion
1618
1707
  //#region src/components/form/ASegmentedControl.vue
1619
1708
  var ASegmentedControl_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -1661,6 +1750,7 @@ var ASegmentedControl_default = /*#__PURE__*/ _plugin_vue_export_helper_default(
1661
1750
  }
1662
1751
  });
1663
1752
  const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
1753
+ const { errorId, describedBy, invalid } = fieldErrorA11y(__props.uuid, errorText);
1664
1754
  const fallbackId = useId();
1665
1755
  const groupName = computed(() => __props.uuid ?? `aform-segmented-${fallbackId}`);
1666
1756
  const labelId = computed(() => `${groupName.value}-label`);
@@ -1729,7 +1819,9 @@ var ASegmentedControl_default = /*#__PURE__*/ _plugin_vue_export_helper_default(
1729
1819
  class: "aform_segmented-track",
1730
1820
  "aria-labelledby": groupAriaLabel.value ? void 0 : labelId.value,
1731
1821
  "aria-label": groupAriaLabel.value,
1732
- "aria-busy": __props.busy || void 0
1822
+ "aria-busy": __props.busy || void 0,
1823
+ "aria-invalid": unref(invalid),
1824
+ "aria-describedby": unref(describedBy)
1733
1825
  }, [(openBlock(true), createElementBlock(Fragment, null, renderList(choices.value, (choice) => {
1734
1826
  return openBlock(), createElementBlock("label", {
1735
1827
  key: choice,
@@ -1755,13 +1847,14 @@ var ASegmentedControl_default = /*#__PURE__*/ _plugin_vue_export_helper_default(
1755
1847
  }, null, 8, _hoisted_6$9)), [[vModelRadio, selected.value]]), createElementVNode("span", _hoisted_7$2, toDisplayString(segmentLabel(choice)), 1)], 14, _hoisted_4$9);
1756
1848
  }), 128))], 8, _hoisted_3$10),
1757
1849
  withDirectives(createElementVNode("p", {
1850
+ id: unref(errorId),
1758
1851
  class: "aform_error",
1759
- innerHTML: errorText.value
1760
- }, null, 8, _hoisted_8$2), [[vShow, errorText.value]])
1852
+ role: "alert"
1853
+ }, toDisplayString(errorText.value), 9, _hoisted_8$2), [[vShow, errorText.value]])
1761
1854
  ], 64))], 2);
1762
1855
  };
1763
1856
  }
1764
- }), [["__scopeId", "data-v-23f09651"]]);
1857
+ }), [["__scopeId", "data-v-8b740fd8"]]);
1765
1858
  //#endregion
1766
1859
  //#region src/components/form/ADateTime.vue?vue&type=script&setup=true&lang.ts
1767
1860
  var _hoisted_1$11 = { class: "aform_form-element" };
@@ -1770,10 +1863,12 @@ var _hoisted_3$9 = { class: "aform_field-label" };
1770
1863
  var _hoisted_4$8 = [
1771
1864
  "id",
1772
1865
  "value",
1773
- "disabled"
1866
+ "disabled",
1867
+ "aria-invalid",
1868
+ "aria-describedby"
1774
1869
  ];
1775
1870
  var _hoisted_5$8 = ["for"];
1776
- var _hoisted_6$8 = ["innerHTML"];
1871
+ var _hoisted_6$8 = ["id"];
1777
1872
  //#endregion
1778
1873
  //#region src/components/form/ADateTime.vue
1779
1874
  var ADateTime_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -1803,6 +1898,7 @@ var ADateTime_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
1803
1898
  emits: ["update:modelValue"],
1804
1899
  setup(__props) {
1805
1900
  const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
1901
+ const { errorId, describedBy, invalid } = fieldErrorA11y(__props.uuid, errorText);
1806
1902
  const modelValue = useModel(__props, "modelValue");
1807
1903
  const currentDateTime = ref(modelValue.value ? new Date(modelValue.value) : /* @__PURE__ */ new Date());
1808
1904
  const showPicker = ref(false);
@@ -1858,6 +1954,8 @@ var ADateTime_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
1858
1954
  placeholder: "Select date and time",
1859
1955
  disabled: __props.mode === "read",
1860
1956
  readonly: "",
1957
+ "aria-invalid": unref(invalid),
1958
+ "aria-describedby": unref(describedBy),
1861
1959
  onClick: openPicker
1862
1960
  }, null, 8, _hoisted_4$8),
1863
1961
  createElementVNode("label", {
@@ -1865,9 +1963,10 @@ var ADateTime_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
1865
1963
  for: __props.uuid
1866
1964
  }, toDisplayString(__props.label), 9, _hoisted_5$8),
1867
1965
  withDirectives(createElementVNode("p", {
1966
+ id: unref(errorId),
1868
1967
  class: "aform_error",
1869
- innerHTML: errorText.value
1870
- }, null, 8, _hoisted_6$8), [[vShow, errorText.value]]),
1968
+ role: "alert"
1969
+ }, toDisplayString(errorText.value), 9, _hoisted_6$8), [[vShow, errorText.value]]),
1871
1970
  showPicker.value ? (openBlock(), createBlock(ADateSelection_default, {
1872
1971
  key: 0,
1873
1972
  ref_key: "pickerRef",
@@ -1895,7 +1994,7 @@ var ADateTime_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
1895
1994
  ], 64))]);
1896
1995
  };
1897
1996
  }
1898
- }), [["__scopeId", "data-v-b0fa488b"]]);
1997
+ }), [["__scopeId", "data-v-427253ba"]]);
1899
1998
  //#endregion
1900
1999
  //#region src/components/form/ADuration.vue?vue&type=script&setup=true&lang.ts
1901
2000
  var _hoisted_1$10 = { class: "aduration" };
@@ -1989,7 +2088,7 @@ var ADuration_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
1989
2088
  ])) : createCommentVNode("", true)])], 64))]);
1990
2089
  };
1991
2090
  }
1992
- }), [["__scopeId", "data-v-43788a3d"]]);
2091
+ }), [["__scopeId", "data-v-64f6240e"]]);
1993
2092
  //#endregion
1994
2093
  //#region src/components/form/ADateRange.vue?vue&type=script&setup=true&lang.ts
1995
2094
  var _hoisted_1$9 = { class: "aform_form-element" };
@@ -1998,10 +2097,12 @@ var _hoisted_3$7 = { class: "aform_field-label" };
1998
2097
  var _hoisted_4$6 = [
1999
2098
  "id",
2000
2099
  "value",
2001
- "disabled"
2100
+ "disabled",
2101
+ "aria-invalid",
2102
+ "aria-describedby"
2002
2103
  ];
2003
2104
  var _hoisted_5$6 = ["for"];
2004
- var _hoisted_6$6 = ["innerHTML"];
2105
+ var _hoisted_6$6 = ["id"];
2005
2106
  //#endregion
2006
2107
  //#region src/components/form/ADateRange.vue
2007
2108
  var ADateRange_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -2027,6 +2128,7 @@ var ADateRange_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__P
2027
2128
  setup(__props) {
2028
2129
  const fmt = (d) => new Date(d).toLocaleDateString();
2029
2130
  const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
2131
+ const { errorId, describedBy, invalid } = fieldErrorA11y(__props.uuid, errorText);
2030
2132
  const modelValue = useModel(__props, "modelValue");
2031
2133
  const startDate = ref(modelValue.value.start_date ? new Date(modelValue.value.start_date) : null);
2032
2134
  const endDate = ref(modelValue.value.end_date ? new Date(modelValue.value.end_date) : null);
@@ -2090,6 +2192,8 @@ var ADateRange_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__P
2090
2192
  placeholder: "Select date range",
2091
2193
  disabled: __props.mode === "read",
2092
2194
  readonly: "",
2195
+ "aria-invalid": unref(invalid),
2196
+ "aria-describedby": unref(describedBy),
2093
2197
  onClick: openPicker
2094
2198
  }, null, 8, _hoisted_4$6),
2095
2199
  createElementVNode("label", {
@@ -2097,9 +2201,10 @@ var ADateRange_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__P
2097
2201
  for: __props.uuid
2098
2202
  }, toDisplayString(__props.label), 9, _hoisted_5$6),
2099
2203
  withDirectives(createElementVNode("p", {
2204
+ id: unref(errorId),
2100
2205
  class: "aform_error",
2101
- innerHTML: errorText.value
2102
- }, null, 8, _hoisted_6$6), [[vShow, errorText.value]]),
2206
+ role: "alert"
2207
+ }, toDisplayString(errorText.value), 9, _hoisted_6$6), [[vShow, errorText.value]]),
2103
2208
  showPicker.value ? (openBlock(), createBlock(ADateSelection_default, {
2104
2209
  key: 0,
2105
2210
  ref_key: "pickerRef",
@@ -2112,7 +2217,7 @@ var ADateRange_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__P
2112
2217
  ], 64))]);
2113
2218
  };
2114
2219
  }
2115
- }), [["__scopeId", "data-v-f8dad4d3"]]);
2220
+ }), [["__scopeId", "data-v-b7560709"]]);
2116
2221
  //#endregion
2117
2222
  //#region src/components/AForm.vue?vue&type=script&setup=true&lang.ts
2118
2223
  var _hoisted_1$8 = { class: "aform" };
@@ -2155,6 +2260,23 @@ var AForm_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__
2155
2260
  emit("update:data", { ...dataModel.value });
2156
2261
  }
2157
2262
  };
2263
+ const isListExpansionTable = (componentObj) => componentObj.kind === "table" && componentObj.config?.view === "list-expansion";
2264
+ const tableExpansionSchema = (table) => table.schema.filter((col) => Boolean(col.component)).map(({ fieldname, component, ...rest }) => Object.assign(rest, {
2265
+ kind: "field",
2266
+ fieldname,
2267
+ component
2268
+ }));
2269
+ const updateTableRow = (fieldname, rowIndex, val) => {
2270
+ const rows = Array.isArray(dataModel.value?.[fieldname]) ? [...dataModel.value[fieldname]] : [];
2271
+ rows[rowIndex] = {
2272
+ ...rows[rowIndex],
2273
+ ...val
2274
+ };
2275
+ if (dataModel.value) {
2276
+ dataModel.value[fieldname] = rows;
2277
+ emit("update:data", { ...dataModel.value });
2278
+ }
2279
+ };
2158
2280
  const componentProps = (componentObj) => {
2159
2281
  const propsToPass = {};
2160
2282
  for (const [key, value] of Object.entries(componentObj)) if (![
@@ -2212,6 +2334,7 @@ var AForm_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__
2212
2334
  });
2213
2335
  const childModels = computed(() => childModelsCache.value);
2214
2336
  return (_ctx, _cache) => {
2337
+ const _component_AForm = resolveComponent("AForm", true);
2215
2338
  return openBlock(), createElementBlock("form", _hoisted_1$8, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.schema, (componentObj, key) => {
2216
2339
  return openBlock(), createElementBlock(Fragment, { key }, [isNestedSection(componentObj) ? (openBlock(), createElementBlock("div", _hoisted_2$7, [componentObj.label && componentObj.kind !== "fieldset" ? (openBlock(), createElementBlock("h4", _hoisted_3$6, toDisplayString(componentObj.label), 1)) : createCommentVNode("", true), (openBlock(), createBlock(resolveDynamicComponent(componentObj.component ?? "AForm"), {
2217
2340
  data: nestedData.value[componentObj.fieldname],
@@ -2238,7 +2361,22 @@ var AForm_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__
2238
2361
  data: dataModel.value[componentObj.fieldname],
2239
2362
  mode: resolvedMode(componentObj),
2240
2363
  errors: __props.errors?.[componentObj.fieldname]
2241
- }, { ref_for: true }, componentProps(componentObj)), null, 16, [
2364
+ }, { ref_for: true }, componentProps(componentObj)), createSlots({ _: 2 }, [isListExpansionTable(componentObj) ? {
2365
+ name: "content",
2366
+ fn: withCtx(({ row, rowIndex }) => [createVNode(_component_AForm, {
2367
+ class: "aform-table-expansion",
2368
+ data: row,
2369
+ schema: tableExpansionSchema(componentObj),
2370
+ mode: resolvedMode(componentObj),
2371
+ "onUpdate:data": (val) => updateTableRow(componentObj.fieldname, rowIndex, val)
2372
+ }, null, 8, [
2373
+ "data",
2374
+ "schema",
2375
+ "mode",
2376
+ "onUpdate:data"
2377
+ ])]),
2378
+ key: "0"
2379
+ } : void 0]), 1040, [
2242
2380
  "modelValue",
2243
2381
  "onUpdate:modelValue",
2244
2382
  "style",
@@ -2250,7 +2388,7 @@ var AForm_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__
2250
2388
  }), 128))]);
2251
2389
  };
2252
2390
  }
2253
- }), [["__scopeId", "data-v-713aca93"]]);
2391
+ }), [["__scopeId", "data-v-dbfe4358"]]);
2254
2392
  //#endregion
2255
2393
  //#region src/components/base/CollapseButton.vue
2256
2394
  var CollapseButton_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -2364,7 +2502,7 @@ var AFileAttach_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__
2364
2502
  ], 64))]);
2365
2503
  };
2366
2504
  }
2367
- }), [["__scopeId", "data-v-8eefd179"]]);
2505
+ }), [["__scopeId", "data-v-79ce33a7"]]);
2368
2506
  //#endregion
2369
2507
  //#region src/components/form/ANumericInput.vue?vue&type=script&setup=true&lang.ts
2370
2508
  var _hoisted_1$6 = { class: "aform_form-element" };
@@ -2373,10 +2511,12 @@ var _hoisted_3$4 = { class: "aform_field-label" };
2373
2511
  var _hoisted_4$4 = [
2374
2512
  "id",
2375
2513
  "disabled",
2376
- "required"
2514
+ "required",
2515
+ "aria-invalid",
2516
+ "aria-describedby"
2377
2517
  ];
2378
2518
  var _hoisted_5$4 = ["for"];
2379
- var _hoisted_6$4 = ["innerHTML"];
2519
+ var _hoisted_6$4 = ["id"];
2380
2520
  //#endregion
2381
2521
  //#region src/components/form/ANumericInput.vue
2382
2522
  var ANumericInput_default = /* @__PURE__ */ defineComponent({
@@ -2398,6 +2538,7 @@ var ANumericInput_default = /* @__PURE__ */ defineComponent({
2398
2538
  emits: ["update:modelValue"],
2399
2539
  setup(__props) {
2400
2540
  const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
2541
+ const { errorId, describedBy, invalid } = fieldErrorA11y(__props.uuid, errorText);
2401
2542
  const inputNumber = useModel(__props, "modelValue");
2402
2543
  return (_ctx, _cache) => {
2403
2544
  return openBlock(), createElementBlock("div", _hoisted_1$6, [__props.mode === "display" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("span", _hoisted_2$5, toDisplayString(inputNumber.value ?? ""), 1), createElementVNode("label", _hoisted_3$4, toDisplayString(__props.label), 1)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
@@ -2407,16 +2548,19 @@ var ANumericInput_default = /* @__PURE__ */ defineComponent({
2407
2548
  class: "aform_input-field",
2408
2549
  type: "number",
2409
2550
  disabled: __props.mode === "read",
2410
- required: __props.required
2551
+ required: __props.required,
2552
+ "aria-invalid": unref(invalid),
2553
+ "aria-describedby": unref(describedBy)
2411
2554
  }, null, 8, _hoisted_4$4), [[vModelText, inputNumber.value]]),
2412
2555
  createElementVNode("label", {
2413
2556
  class: "aform_field-label",
2414
2557
  for: __props.uuid
2415
2558
  }, toDisplayString(__props.label), 9, _hoisted_5$4),
2416
2559
  withDirectives(createElementVNode("p", {
2560
+ id: unref(errorId),
2417
2561
  class: "aform_error",
2418
- innerHTML: errorText.value
2419
- }, null, 8, _hoisted_6$4), [[vShow, errorText.value]])
2562
+ role: "alert"
2563
+ }, toDisplayString(errorText.value), 9, _hoisted_6$4), [[vShow, errorText.value]])
2420
2564
  ], 64))]);
2421
2565
  };
2422
2566
  }
@@ -2432,7 +2576,9 @@ var _hoisted_6$3 = { class: "aquantity__group" };
2432
2576
  var _hoisted_7$1 = [
2433
2577
  "id",
2434
2578
  "disabled",
2435
- "required"
2579
+ "required",
2580
+ "aria-invalid",
2581
+ "aria-describedby"
2436
2582
  ];
2437
2583
  var _hoisted_8$1 = { class: "aquantity__uom" };
2438
2584
  var _hoisted_9$1 = [
@@ -2461,7 +2607,7 @@ var _hoisted_20 = { class: "aform_field-label" };
2461
2607
  var _hoisted_21 = { class: "aquantity__field aquantity__field--conversion" };
2462
2608
  var _hoisted_22 = ["value"];
2463
2609
  var _hoisted_23 = { class: "aform_field-label" };
2464
- var _hoisted_24 = ["innerHTML"];
2610
+ var _hoisted_24 = ["id"];
2465
2611
  //#endregion
2466
2612
  //#region src/components/form/AQuantityInput.vue
2467
2613
  var AQuantityInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -2474,7 +2620,7 @@ var AQuantityInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
2474
2620
  required: { type: Boolean },
2475
2621
  mode: {},
2476
2622
  uuid: {},
2477
- validation: { default: () => ({ errorMessage: " " }) },
2623
+ validation: { default: () => ({ errorMessage: "" }) },
2478
2624
  errors: {},
2479
2625
  options: { default: () => ({}) },
2480
2626
  uomLabel: { default: "UOM" },
@@ -2493,6 +2639,8 @@ var AQuantityInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
2493
2639
  }),
2494
2640
  emits: ["update:modelValue"],
2495
2641
  setup(__props) {
2642
+ const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
2643
+ const { errorId, describedBy, invalid } = fieldErrorA11y(__props.uuid, errorText);
2496
2644
  const modelValue = useModel(__props, "modelValue");
2497
2645
  const uoms = computed(() => __props.options.uoms ?? []);
2498
2646
  const roundQty = (value) => Number(value.toFixed(6));
@@ -2595,56 +2743,62 @@ var AQuantityInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
2595
2743
  });
2596
2744
  return (_ctx, _cache) => {
2597
2745
  return openBlock(), createElementBlock("div", _hoisted_1$5, [__props.mode === "display" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("span", _hoisted_2$4, toDisplayString(displayText.value), 1), createElementVNode("label", _hoisted_3$3, toDisplayString(__props.label), 1)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
2598
- createElementVNode("div", _hoisted_4$3, [createElementVNode("div", _hoisted_5$3, [createElementVNode("div", _hoisted_6$3, [withDirectives(createElementVNode("input", {
2599
- id: __props.uuid,
2600
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => qty.value = $event),
2601
- class: "aquantity__qty",
2602
- type: "number",
2603
- disabled: __props.mode === "read",
2604
- required: __props.required,
2605
- onKeydown: onQtyKeydown,
2606
- onPaste: onQtyPaste
2607
- }, null, 40, _hoisted_7$1), [[
2608
- vModelText,
2609
- qty.value,
2610
- void 0,
2611
- { number: true }
2612
- ]]), withDirectives((openBlock(), createElementBlock("div", _hoisted_8$1, [createElementVNode("button", {
2613
- id: `${__props.uuid}-uom`,
2614
- type: "button",
2615
- class: "aquantity__uom-toggle",
2616
- disabled: __props.mode === "read",
2617
- "aria-haspopup": "listbox",
2618
- "aria-expanded": dropdown.open,
2619
- "aria-activedescendant": dropdown.open && dropdown.activeIndex >= 0 ? `${__props.uuid}-uom-opt-${dropdown.activeIndex}` : void 0,
2620
- onClick: toggleDropdown,
2621
- onKeydown: [
2622
- _cache[1] || (_cache[1] = withKeys(withModifiers(($event) => moveActive(1), ["prevent"]), ["down"])),
2623
- _cache[2] || (_cache[2] = withKeys(withModifiers(($event) => moveActive(-1), ["prevent"]), ["up"])),
2624
- withKeys(withModifiers(selectActive, ["prevent"]), ["enter"]),
2625
- withKeys(closeDropdown, ["esc"])
2626
- ]
2627
- }, [createElementVNode("span", _hoisted_10$1, toDisplayString(uom.value || __props.uomLabel), 1), _cache[3] || (_cache[3] = createElementVNode("span", {
2628
- class: "aquantity__caret",
2629
- "aria-hidden": "true"
2630
- }, null, -1))], 40, _hoisted_9$1), withDirectives(createElementVNode("ul", {
2631
- class: "aquantity__uom-menu",
2632
- role: "listbox",
2633
- "aria-label": __props.uomLabel
2634
- }, [(openBlock(true), createElementBlock(Fragment, null, renderList(uoms.value, (option, i) => {
2635
- return openBlock(), createElementBlock("li", {
2636
- id: `${__props.uuid}-uom-opt-${i}`,
2637
- key: option,
2638
- role: "option",
2639
- "aria-selected": option === uom.value,
2640
- class: normalizeClass(["aquantity__uom-option", { "is-active": i === dropdown.activeIndex }]),
2641
- onMouseenter: ($event) => dropdown.activeIndex = i,
2642
- onClick: ($event) => selectUom(option)
2643
- }, toDisplayString(option), 43, _hoisted_12$1);
2644
- }), 128))], 8, _hoisted_11$1), [[vShow, dropdown.open]])])), [[unref(vOnClickOutside), closeDropdown]])]), createElementVNode("label", {
2645
- class: "aform_field-label",
2646
- for: __props.uuid
2647
- }, toDisplayString(__props.label), 9, _hoisted_13)])]),
2746
+ createElementVNode("div", _hoisted_4$3, [createElementVNode("div", _hoisted_5$3, [createElementVNode("div", _hoisted_6$3, [
2747
+ withDirectives(createElementVNode("input", {
2748
+ id: __props.uuid,
2749
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => qty.value = $event),
2750
+ class: "aquantity__qty",
2751
+ type: "number",
2752
+ disabled: __props.mode === "read",
2753
+ required: __props.required,
2754
+ "aria-invalid": unref(invalid),
2755
+ "aria-describedby": unref(describedBy),
2756
+ onKeydown: onQtyKeydown,
2757
+ onPaste: onQtyPaste
2758
+ }, null, 40, _hoisted_7$1), [[
2759
+ vModelText,
2760
+ qty.value,
2761
+ void 0,
2762
+ { number: true }
2763
+ ]]),
2764
+ withDirectives((openBlock(), createElementBlock("div", _hoisted_8$1, [createElementVNode("button", {
2765
+ id: `${__props.uuid}-uom`,
2766
+ type: "button",
2767
+ class: "aquantity__uom-toggle",
2768
+ disabled: __props.mode === "read",
2769
+ "aria-haspopup": "listbox",
2770
+ "aria-expanded": dropdown.open,
2771
+ "aria-activedescendant": dropdown.open && dropdown.activeIndex >= 0 ? `${__props.uuid}-uom-opt-${dropdown.activeIndex}` : void 0,
2772
+ onClick: toggleDropdown,
2773
+ onKeydown: [
2774
+ _cache[1] || (_cache[1] = withKeys(withModifiers(($event) => moveActive(1), ["prevent"]), ["down"])),
2775
+ _cache[2] || (_cache[2] = withKeys(withModifiers(($event) => moveActive(-1), ["prevent"]), ["up"])),
2776
+ withKeys(withModifiers(selectActive, ["prevent"]), ["enter"]),
2777
+ withKeys(closeDropdown, ["esc"])
2778
+ ]
2779
+ }, [createElementVNode("span", _hoisted_10$1, toDisplayString(uom.value || __props.uomLabel), 1), _cache[3] || (_cache[3] = createElementVNode("span", {
2780
+ class: "aquantity__caret",
2781
+ "aria-hidden": "true"
2782
+ }, null, -1))], 40, _hoisted_9$1), withDirectives(createElementVNode("ul", {
2783
+ class: "aquantity__uom-menu",
2784
+ role: "listbox",
2785
+ "aria-label": __props.uomLabel
2786
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(uoms.value, (option, i) => {
2787
+ return openBlock(), createElementBlock("li", {
2788
+ id: `${__props.uuid}-uom-opt-${i}`,
2789
+ key: option,
2790
+ role: "option",
2791
+ "aria-selected": option === uom.value,
2792
+ class: normalizeClass(["aquantity__uom-option", { "is-active": i === dropdown.activeIndex }]),
2793
+ onMouseenter: ($event) => dropdown.activeIndex = i,
2794
+ onClick: ($event) => selectUom(option)
2795
+ }, toDisplayString(option), 43, _hoisted_12$1);
2796
+ }), 128))], 8, _hoisted_11$1), [[vShow, dropdown.open]])])), [[unref(vOnClickOutside), closeDropdown]]),
2797
+ createElementVNode("label", {
2798
+ class: "aform_field-label",
2799
+ for: __props.uuid
2800
+ }, toDisplayString(__props.label), 9, _hoisted_13)
2801
+ ])])]),
2648
2802
  createElementVNode("div", _hoisted_14, [
2649
2803
  createElementVNode("div", _hoisted_15, [createElementVNode("input", {
2650
2804
  value: modelValue.value.stockUom,
@@ -2666,13 +2820,14 @@ var AQuantityInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/*
2666
2820
  }, null, 8, _hoisted_22), createElementVNode("label", _hoisted_23, toDisplayString(__props.conversionFactorLabel), 1)])
2667
2821
  ]),
2668
2822
  withDirectives(createElementVNode("p", {
2823
+ id: unref(errorId),
2669
2824
  class: "aform_error",
2670
- innerHTML: __props.validation.errorMessage
2671
- }, null, 8, _hoisted_24), [[vShow, __props.validation.errorMessage]])
2825
+ role: "alert"
2826
+ }, toDisplayString(errorText.value), 9, _hoisted_24), [[vShow, errorText.value]])
2672
2827
  ], 64))]);
2673
2828
  };
2674
2829
  }
2675
- }), [["__scopeId", "data-v-f16b20ca"]]);
2830
+ }), [["__scopeId", "data-v-a904c817"]]);
2676
2831
  //#endregion
2677
2832
  //#region src/directives/mask.ts
2678
2833
  /**
@@ -2771,10 +2926,12 @@ var _hoisted_4$2 = [
2771
2926
  "id",
2772
2927
  "disabled",
2773
2928
  "maxlength",
2774
- "required"
2929
+ "required",
2930
+ "aria-invalid",
2931
+ "aria-describedby"
2775
2932
  ];
2776
2933
  var _hoisted_5$2 = ["for"];
2777
- var _hoisted_6$2 = ["innerHTML"];
2934
+ var _hoisted_6$2 = ["id"];
2778
2935
  //#endregion
2779
2936
  //#region src/components/form/ATextInput.vue
2780
2937
  var ATextInput_default = /* @__PURE__ */ defineComponent({
@@ -2796,6 +2953,7 @@ var ATextInput_default = /* @__PURE__ */ defineComponent({
2796
2953
  emits: ["update:modelValue"],
2797
2954
  setup(__props) {
2798
2955
  const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
2956
+ const { errorId, describedBy, invalid } = fieldErrorA11y(__props.uuid, errorText);
2799
2957
  const maskFilled = ref(true);
2800
2958
  const inputText = useModel(__props, "modelValue");
2801
2959
  return (_ctx, _cache) => {
@@ -2806,16 +2964,19 @@ var ATextInput_default = /* @__PURE__ */ defineComponent({
2806
2964
  class: "aform_input-field",
2807
2965
  disabled: __props.mode === "read",
2808
2966
  maxlength: __props.mask ? maskFilled.value ? __props.mask.length : void 0 : void 0,
2809
- required: __props.required
2967
+ required: __props.required,
2968
+ "aria-invalid": unref(invalid),
2969
+ "aria-describedby": unref(describedBy)
2810
2970
  }, null, 8, _hoisted_4$2), [[vModelText, inputText.value], [unref(useStringMask), __props.mask]]),
2811
2971
  createElementVNode("label", {
2812
2972
  class: "aform_field-label",
2813
2973
  for: __props.uuid
2814
2974
  }, toDisplayString(__props.label), 9, _hoisted_5$2),
2815
2975
  withDirectives(createElementVNode("p", {
2976
+ id: unref(errorId),
2816
2977
  class: "aform_error",
2817
- innerHTML: errorText.value
2818
- }, null, 8, _hoisted_6$2), [[vShow, errorText.value]])
2978
+ role: "alert"
2979
+ }, toDisplayString(errorText.value), 9, _hoisted_6$2), [[vShow, errorText.value]])
2819
2980
  ], 64))]);
2820
2981
  };
2821
2982
  }
@@ -2831,10 +2992,12 @@ var _hoisted_4$1 = [
2831
2992
  "rows",
2832
2993
  "maxlength",
2833
2994
  "disabled",
2834
- "required"
2995
+ "required",
2996
+ "aria-invalid",
2997
+ "aria-describedby"
2835
2998
  ];
2836
2999
  var _hoisted_5$1 = ["for"];
2837
- var _hoisted_6$1 = ["innerHTML"];
3000
+ var _hoisted_6$1 = ["id"];
2838
3001
  //#endregion
2839
3002
  //#region src/components/form/ATextboxInput.vue
2840
3003
  var ATextboxInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
@@ -2859,6 +3022,7 @@ var ATextboxInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
2859
3022
  emits: ["update:modelValue"],
2860
3023
  setup(__props) {
2861
3024
  const errorText = computed(() => __props.errors?.length ? __props.errors.join("; ") : __props.validation.errorMessage ?? "");
3025
+ const { errorId, describedBy, invalid } = fieldErrorA11y(__props.uuid, errorText);
2862
3026
  const inputText = useModel(__props, "modelValue");
2863
3027
  return (_ctx, _cache) => {
2864
3028
  return openBlock(), createElementBlock("div", _hoisted_1$3, [__props.mode === "display" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createElementVNode("span", _hoisted_2$2, toDisplayString(inputText.value ?? ""), 1), createElementVNode("label", _hoisted_3$1, toDisplayString(__props.label), 1)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
@@ -2870,20 +3034,23 @@ var ATextboxInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @
2870
3034
  rows: __props.rows,
2871
3035
  maxlength: __props.maxlength,
2872
3036
  disabled: __props.mode === "read",
2873
- required: __props.required
3037
+ required: __props.required,
3038
+ "aria-invalid": unref(invalid),
3039
+ "aria-describedby": unref(describedBy)
2874
3040
  }, null, 8, _hoisted_4$1), [[vModelText, inputText.value]]),
2875
3041
  createElementVNode("label", {
2876
3042
  class: "aform_field-label",
2877
3043
  for: __props.uuid
2878
3044
  }, toDisplayString(__props.label), 9, _hoisted_5$1),
2879
3045
  withDirectives(createElementVNode("p", {
3046
+ id: unref(errorId),
2880
3047
  class: "aform_error",
2881
- innerHTML: errorText.value
2882
- }, null, 8, _hoisted_6$1), [[vShow, errorText.value]])
3048
+ role: "alert"
3049
+ }, toDisplayString(errorText.value), 9, _hoisted_6$1), [[vShow, errorText.value]])
2883
3050
  ], 64))]);
2884
3051
  };
2885
3052
  }
2886
- }), [["__scopeId", "data-v-2a9c793b"]]);
3053
+ }), [["__scopeId", "data-v-19e611fa"]]);
2887
3054
  //#endregion
2888
3055
  //#region src/components/utilities/Login.vue?vue&type=script&setup=true&lang.ts
2889
3056
  var _hoisted_1$2 = { class: "login-container" };
@@ -2942,9 +3109,9 @@ var Login_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__
2942
3109
  name: "email",
2943
3110
  placeholder: "name@example.com",
2944
3111
  type: "email",
2945
- "auto-capitalize": "none",
2946
- "auto-complete": "email",
2947
- "auto-correct": "off",
3112
+ autocomplete: "email",
3113
+ autocapitalize: "none",
3114
+ autocorrect: "off",
2948
3115
  disabled: isLoading.value
2949
3116
  }, null, 8, _hoisted_8), [[vModelText, email.value]])]),
2950
3117
  createElementVNode("div", _hoisted_9, [_cache[3] || (_cache[3] = createElementVNode("label", {
@@ -2957,19 +3124,23 @@ var Login_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__
2957
3124
  class: "aform_input-field",
2958
3125
  name: "password",
2959
3126
  type: "password",
3127
+ autocomplete: "current-password",
2960
3128
  disabled: isLoading.value
2961
3129
  }, null, 8, _hoisted_10), [[vModelText, password.value]])]),
2962
3130
  createElementVNode("button", {
3131
+ type: "submit",
2963
3132
  class: "btn",
2964
- disabled: isLoading.value || !email.value || !password.value,
2965
- onClick: onSubmit
3133
+ disabled: isLoading.value || !email.value || !password.value
2966
3134
  }, [isLoading.value ? (openBlock(), createElementBlock("span", _hoisted_12, "progress_activity")) : createCommentVNode("", true), _cache[4] || (_cache[4] = createElementVNode("span", { id: "login-form-button" }, "Login", -1))], 8, _hoisted_11)
2967
3135
  ])], 32),
2968
- _cache[5] || (_cache[5] = createElementVNode("button", { class: "btn" }, [createElementVNode("span", { id: "forgot-password-button" }, "Forgot password?")], -1))
3136
+ _cache[5] || (_cache[5] = createElementVNode("button", {
3137
+ type: "button",
3138
+ class: "btn"
3139
+ }, [createElementVNode("span", { id: "forgot-password-button" }, "Forgot password?")], -1))
2969
3140
  ])])]);
2970
3141
  };
2971
3142
  }
2972
- }), [["__scopeId", "data-v-2c0f0634"]]);
3143
+ }), [["__scopeId", "data-v-555c3224"]]);
2973
3144
  //#endregion
2974
3145
  //#region src/components/AFormLoading.vue
2975
3146
  var _sfc_main = {};