@optionfactory/ful 1.0.12 → 1.0.13

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/ful.iife.js CHANGED
@@ -1413,16 +1413,16 @@ var ful = (function (exports, ftl) {
1413
1413
  static observed = ['value', 'readonly:presence'];
1414
1414
  static slots = true;
1415
1415
  static template = `
1416
- <label data-tpl-for="id" class="form-label">{{{{ slots.default }}}}</label>
1416
+ <label class="form-label">{{{{ slots.default }}}}</label>
1417
1417
  <div class="input-group">
1418
1418
  <span data-tpl-if="slots.ibefore" class="input-group-text">{{{{ slots.ibefore }}}}</span>
1419
1419
  {{{{ slots.before }}}}
1420
- <input data-tpl-if="type != 'textarea'" class="form-control" data-tpl-id="id" data-tpl-type="type" placeholder=" " data-tpl-aria-describedby="fieldErrorId" form="">
1421
- <textarea data-tpl-if="type == 'textarea'" class="form-control" data-tpl-id="id" placeholder=" " data-tpl-aria-describedby="fieldErrorId" form=""></textarea>
1420
+ <input data-tpl-if="type != 'textarea'" class="form-control" data-tpl-type="type" placeholder=" " form="">
1421
+ <textarea data-tpl-if="type == 'textarea'" class="form-control" placeholder=" " form=""></textarea>
1422
1422
  {{{{ slots.after }}}}
1423
1423
  <span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>
1424
1424
  </div>
1425
- <ful-field-error data-tpl-id="fieldErrorId"></ful-field-error>
1425
+ <ful-field-error></ful-field-error>
1426
1426
  `;
1427
1427
  static formAssociated = true;
1428
1428
  #input;
@@ -1430,13 +1430,11 @@ var ful = (function (exports, ftl) {
1430
1430
  constructor() {
1431
1431
  super();
1432
1432
  this.internals = this.attachInternals();
1433
- this.internals.role = 'textbox';
1433
+ this.internals.role = 'presentation';
1434
1434
  }
1435
1435
  render({ slots }) {
1436
- const id = ftl.Attributes.uid('ful-input');
1437
- const fieldErrorId = `${id}-error`;
1438
1436
  const type = this.getAttribute("type") ?? 'text';
1439
- const fragment = this.template().withOverlay({ id, type, fieldErrorId, slots }).render();
1437
+ const fragment = this.template().withOverlay({ type, slots }).render();
1440
1438
  this.#input = fragment.querySelector("input,textarea");
1441
1439
  ftl.Attributes.forward('input-', this, this.#input);
1442
1440
  this.#input.addEventListener('change', (evt) => {
@@ -1449,7 +1447,11 @@ var ful = (function (exports, ftl) {
1449
1447
  }
1450
1448
  }));
1451
1449
  });
1450
+ const label = fragment.querySelector('label');
1451
+ label.addEventListener('click', () => this.focus());
1452
1452
  this.#fieldError = fragment.querySelector('ful-field-error');
1453
+ this.#input.ariaDescribedByElements = [this.#fieldError];
1454
+ this.#input.ariaLabelledByElements = [label];
1453
1455
  this.replaceChildren(fragment);
1454
1456
  }
1455
1457
  get value() {
@@ -1565,11 +1567,9 @@ var ful = (function (exports, ftl) {
1565
1567
  this.#data = data;
1566
1568
  }
1567
1569
  async exact(...keys) {
1568
- await timing.sleep(500);
1569
1570
  return this.#data.filter(([k, v]) => keys.includes(k));
1570
1571
  }
1571
1572
  async load(needle) {
1572
- await timing.sleep(500);
1573
1573
  return this.#data.filter(([k, v]) => v.includes(needle?.toLowerCase()));
1574
1574
  }
1575
1575
  }
@@ -1681,19 +1681,19 @@ var ful = (function (exports, ftl) {
1681
1681
  static observed = ['value:csvm']
1682
1682
  static slots = true
1683
1683
  static template = `
1684
- <label data-tpl-for="id" class="form-label">{{{{ slots.default }}}}</label>
1684
+ <label class="form-label">{{{{ slots.default }}}}</label>
1685
1685
  <div class="input-group flex-nowrap" tabindex="-1">
1686
1686
  <span data-tpl-if="slots.ibefore" class="input-group-text">{{{{ slots.ibefore }}}}</span>
1687
1687
  {{{{ slots.before }}}}
1688
1688
  <div class="ful-select-input">
1689
1689
  <badges></badges>
1690
- <input data-tpl-id="id" data-tpl-ariadesribed-by="fieldErrorId" type="text" form="">
1690
+ <input type="text" form="">
1691
1691
  </div>
1692
1692
  {{{{ slots.after }}}}
1693
1693
  <span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>
1694
1694
  </div>
1695
1695
  <ful-dropdown hidden></ful-dropdown>
1696
- <ful-field-error data-tpl-id="fieldErrorId"></ful-field-error>
1696
+ <ful-field-error></ful-field-error>
1697
1697
  `;
1698
1698
  static mappers = {
1699
1699
  "csvm": (v, name, el) => {
@@ -1715,20 +1715,23 @@ var ful = (function (exports, ftl) {
1715
1715
  constructor() {
1716
1716
  super();
1717
1717
  this.internals = this.attachInternals();
1718
- this.internals.role = 'combobox';
1718
+ this.internals.role = 'presentation';
1719
1719
  }
1720
1720
  async render({ slots, observed }) {
1721
1721
  const name = this.getAttribute("name");
1722
- const id = ftl.Attributes.uid('ful-select');
1723
- const fieldErrorId = id + "-error";
1724
1722
  this.#loader = Loaders.fromAttributes(this, 'loaders:select', { options: slots.options });
1725
1723
  await this.#loader.prefetch?.();
1726
- const fragment = this.template().withOverlay({ slots, name, id, fieldErrorId }).render();
1724
+ const fragment = this.template().withOverlay({ slots, name }).render();
1727
1725
  this.#input = fragment.querySelector('input');
1728
1726
  this.#badges = fragment.querySelector('badges');
1729
1727
  this.#ddmenu = fragment.querySelector('ful-dropdown');
1730
1728
  this.#multiple = this.hasAttribute("multiple");
1729
+ const label = fragment.querySelector('label');
1730
+ label.addEventListener('click', () => this.focus());
1731
1731
  this.#fieldError = fragment.querySelector('ful-field-error');
1732
+ this.#input.ariaDescribedByElements = [this.#fieldError];
1733
+ this.#input.ariaLabelledByElements = [label];
1734
+
1732
1735
 
1733
1736
  const self = this;
1734
1737
  const [dload, abortdload] = timing.debounce(400, () => self.#ddmenu.show(() => self.#loader.load(self.#input.value)));
@@ -1852,7 +1855,7 @@ var ful = (function (exports, ftl) {
1852
1855
  static observed = ['value'];
1853
1856
  static slots = true;
1854
1857
  static template = `
1855
- <fieldset data-tpl-aria-describedby="fieldErrorId">
1858
+ <fieldset>
1856
1859
  <legend class="form-label">
1857
1860
  {{{{ slots.default }}}}
1858
1861
  </legend>
@@ -1867,7 +1870,7 @@ var ful = (function (exports, ftl) {
1867
1870
  </label>
1868
1871
  </div>
1869
1872
  </section>
1870
- <ful-field-error data-tpl-id="fieldErrorId"></ful-field-error>
1873
+ <ful-field-error></ful-field-error>
1871
1874
  <footer data-tpl-if="slots.footer">
1872
1875
  {{{{ slots.footer }}}}
1873
1876
  </footer>
@@ -1908,9 +1911,9 @@ var ful = (function (exports, ftl) {
1908
1911
  });
1909
1912
 
1910
1913
  radioEls.forEach(el => el.remove());
1911
- const fieldErrorId = ftl.Attributes.uid("ful-error");
1912
- this.template().withOverlay({ name, fieldErrorId, slots, inputsAndLabels }).renderTo(this);
1914
+ this.template().withOverlay({ name, slots, inputsAndLabels }).renderTo(this);
1913
1915
  this.#fieldError = this.querySelector('ful-field-error');
1916
+ this.ariaDescribedByElements = [this.#fieldError];
1914
1917
  this.#firstRadio = this.querySelector('input[type=radio]');
1915
1918
  this.#booleanType = this.getAttribute('type') === 'boolean';
1916
1919
  }
@@ -1952,11 +1955,11 @@ var ful = (function (exports, ftl) {
1952
1955
  static template = `
1953
1956
  <div data-tpl-class="klass">
1954
1957
  <div class="input-container">
1955
- <input data-tpl-id="id" class="form-check-input" type="checkbox" role="switch" form="" placeholder=" " data-tpl-aria-describedby="fieldErrorId">
1958
+ <input class="form-check-input" type="checkbox" role="switch" form="" placeholder=" ">
1956
1959
  </div>
1957
- <label data-tpl-for="id" class="form-check-label">{{{{ slots.default }}}}</label>
1960
+ <label class="form-check-label">{{{{ slots.default }}}}</label>
1958
1961
  </div>
1959
- <ful-field-error data-tpl-if="fieldErrorId"></ful-field-error>
1962
+ <ful-field-error></ful-field-error>
1960
1963
  `;
1961
1964
  #input;
1962
1965
  #fieldError;
@@ -1964,17 +1967,13 @@ var ful = (function (exports, ftl) {
1964
1967
  constructor() {
1965
1968
  super();
1966
1969
  this.internals = this.attachInternals();
1967
- this.internals.role = 'checkbox';
1970
+ this.internals.role = 'presentation';
1968
1971
  }
1969
1972
  render({ slots }) {
1970
- const id = ftl.Attributes.uid("ful-checkbox");
1971
- const fieldErrorId = id + "-error";
1972
1973
  const klass = this.getAttribute('type') == 'switch' ? "form-check form-switch" : "form-check";
1973
- this.internals.role = this.getAttribute('type') == 'switch' ? 'switch' : 'checkbox';
1974
- const fragment = this.template().withOverlay({ slots, klass, id, fieldErrorId }).render();
1974
+ const fragment = this.template().withOverlay({ slots, klass }).render();
1975
1975
  this.#input = fragment.querySelector("input");
1976
1976
  ftl.Attributes.forward('input-', this, this.#input);
1977
- this.#fieldError = fragment.querySelector('ful-field-error');
1978
1977
  this.#input.addEventListener('change', (evt) => {
1979
1978
  evt.stopPropagation();
1980
1979
  this.dispatchEvent(new CustomEvent('change', {
@@ -1984,7 +1983,12 @@ var ful = (function (exports, ftl) {
1984
1983
  value: this.value
1985
1984
  }
1986
1985
  }));
1987
- });
1986
+ });
1987
+ const label = fragment.querySelector('label');
1988
+ label.addEventListener('click', () => { this.focus(); this.value = !this.value; });
1989
+ this.#fieldError = fragment.querySelector('ful-field-error');
1990
+ this.#input.ariaDescribedByElements = [this.#fieldError];
1991
+ this.#input.ariaLabelledByElements = [label];
1988
1992
  this.replaceChildren(fragment);
1989
1993
  }
1990
1994
  get value() {
@@ -2216,48 +2220,50 @@ var ful = (function (exports, ftl) {
2216
2220
  <ful-form data-tpl-if="slots.filters">
2217
2221
  {{{{ slots.filters }}}}
2218
2222
  </ful-form>
2219
- <table class="table">
2220
- <caption data-tpl-if="slots.caption">{{{{ slots.caption }}}}</caption>
2221
- <thead>
2222
- <tr>
2223
- <th data-tpl-each="schema" scope="col" data-tpl-class="title.classes">
2224
- {{{{ title.fragment }}}}
2225
- <ful-sorter data-tpl-if="sorter || order" data-tpl-sorter="sorter" data-tpl-order="order"></ful-sorter>
2226
- </th>
2227
- </tr>
2228
- </thead>
2229
- <tbody></tbody>
2230
- <tbody data-ref="no-autoload">
2231
- <tr>
2232
- <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2233
- <i class="bi bi-search" style="font-size: 40px; color: #BDC3CA"></i>
2234
- <p class="mt-3 mb-0" style="color: #BDC3CA">
2235
- Avvia la ricerca per visualizzare i risultati...
2236
- </p>
2237
- </td>
2238
- </tr>
2239
- </tbody>
2240
- <tbody data-ref="loading" hidden>
2241
- <tr>
2242
- <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2243
- <ful-spinner class="big"></ful-spinner>
2244
- </td>
2245
- </tr>
2246
- </tbody>
2247
- <tbody data-ref="feedback" hidden>
2248
- <tr>
2249
- <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2250
- <div class="alert alert-danger">
2251
- <p>Errore nel caricamento della tabella:</p>
2252
- <p class="mb-0" data-ref="feedback-error"></p>
2253
- </div>
2254
- </td>
2255
- </tr>
2256
- </tbody>
2257
- <tfoot data-tpl-if="slots.footer">
2258
- {{{{ slots.footer }}}}
2259
- </tfoot>
2260
- </table>
2223
+ <div class="table-wrapper">
2224
+ <table class="table">
2225
+ <caption data-tpl-if="slots.caption">{{{{ slots.caption }}}}</caption>
2226
+ <thead>
2227
+ <tr>
2228
+ <th data-tpl-each="schema" scope="col" data-tpl-class="title.classes">
2229
+ {{{{ title.fragment }}}}
2230
+ <ful-sorter data-tpl-if="sorter || order" data-tpl-sorter="sorter" data-tpl-order="order"></ful-sorter>
2231
+ </th>
2232
+ </tr>
2233
+ </thead>
2234
+ <tbody></tbody>
2235
+ <tbody data-ref="no-autoload">
2236
+ <tr>
2237
+ <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2238
+ <i class="bi bi-search" style="font-size: 40px; color: #BDC3CA"></i>
2239
+ <p class="mt-3 mb-0" style="color: #BDC3CA">
2240
+ Avvia la ricerca per visualizzare i risultati...
2241
+ </p>
2242
+ </td>
2243
+ </tr>
2244
+ </tbody>
2245
+ <tbody data-ref="loading" hidden>
2246
+ <tr>
2247
+ <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2248
+ <ful-spinner class="big"></ful-spinner>
2249
+ </td>
2250
+ </tr>
2251
+ </tbody>
2252
+ <tbody data-ref="feedback" hidden>
2253
+ <tr>
2254
+ <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">
2255
+ <div class="alert alert-danger">
2256
+ <p>Errore nel caricamento della tabella:</p>
2257
+ <p class="mb-0" data-ref="feedback-error"></p>
2258
+ </div>
2259
+ </td>
2260
+ </tr>
2261
+ </tbody>
2262
+ <tfoot data-tpl-if="slots.footer">
2263
+ {{{{ slots.footer }}}}
2264
+ </tfoot>
2265
+ </table>
2266
+ </div>
2261
2267
  <ful-pagination current="0" total="1"></ful-pagination>
2262
2268
  `;
2263
2269
  static templates = {
@@ -2286,7 +2292,8 @@ var ful = (function (exports, ftl) {
2286
2292
  const template = this.template();
2287
2293
  const schema = TableSchemaParser.parse(slots.default, template);
2288
2294
  const fragment = template.withOverlay({ slots, schema }).render();
2289
- const table = /** @type HTMLTableElement */ (ftl.Nodes.queryChildren(fragment, 'table'));
2295
+ const tableWrapper = /** @type HTMLTableElement */ (ftl.Nodes.queryChildren(fragment, '.table-wrapper'));
2296
+ const table = /** @type HTMLTableElement */ (tableWrapper.querySelector("table"));
2290
2297
  ftl.Attributes.forward('table-', this, table);
2291
2298
  this.#schema = schema;
2292
2299
  this.#body = table.querySelector(':scope > tbody');
@@ -2379,7 +2386,7 @@ var ful = (function (exports, ftl) {
2379
2386
  static observed = ["value:json"];
2380
2387
  static slots = true;
2381
2388
  static template = `
2382
- <label data-tpl-for="id" class="form-label" data-tpl-if="label">{{{{ label }}}}</label>
2389
+ <label class="form-label" data-tpl-if="label">{{{{ label }}}}</label>
2383
2390
  <div class="input-group">
2384
2391
  <button data-ref="operator" class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" value="LTE" form="">&PrecedesSlantEqual;</button>
2385
2392
  <ul class="dropdown-menu">
@@ -2391,7 +2398,7 @@ var ful = (function (exports, ftl) {
2391
2398
  <li><a class="dropdown-item" role="button" value="GTE">&SucceedsSlantEqual;</a></li>
2392
2399
  <li><a class="dropdown-item" role="button" value="BETWEEN">&LeftRightArrow;</a></li>
2393
2400
  </ul>
2394
- <input data-tpl-id="id" data-ref="value1" type="datetime-local" class="form-control" form="">
2401
+ <input data-ref="value1" type="datetime-local" class="form-control" form="">
2395
2402
  <input data-ref="value2" type="datetime-local" class="form-control" form="" hidden>
2396
2403
  <span class="input-group-text"><i class="bi bi-search"></i></span>
2397
2404
  </div>
@@ -2407,15 +2414,18 @@ var ful = (function (exports, ftl) {
2407
2414
  this.internals = this.attachInternals();
2408
2415
  }
2409
2416
  render({ slots }) {
2410
- const id = ftl.Attributes.uid('instant-filter');
2411
2417
  const label = ftl.Fragments.toHtml(slots.default.cloneNode(true)).trim().length === 0 ? null : slots.default;
2412
2418
  const name = this.getAttribute("name");
2413
- const fragment = this.template().withOverlay({ id, label, name }).render(this);
2419
+ const fragment = this.template().withOverlay({ label, name }).render(this);
2414
2420
  this.#operator = fragment.querySelector('[data-ref=operator]');
2415
2421
  this.#value1 = fragment.querySelector('[data-ref=value1]');
2416
2422
  this.#value2 = fragment.querySelector('[data-ref=value2]');
2423
+ this.#fieldError = fragment.querySelector('ful-field-error');
2424
+ const labelEl = fragment.querySelector('label');
2425
+ labelEl?.addEventListener('click', () => this.focus());
2426
+ this.#value1.ariaDescribedByElements = [this.#fieldError];
2427
+ this.#value1.ariaLabelledByElements = labelEl ? [labelEl] : [];
2417
2428
  this.replaceChildren(fragment);
2418
- this.#fieldError = this.querySelector('ful-field-error');
2419
2429
  this.addEventListener('click', (evt) => {
2420
2430
  const target = /** @type HTMLElement */ (evt.target);
2421
2431
  if (!target.matches('ul > li > a')) {
@@ -2478,7 +2488,7 @@ var ful = (function (exports, ftl) {
2478
2488
  static observed = ["value:json"];
2479
2489
  static slots = true;
2480
2490
  static template = `
2481
- <label data-tpl-for="id" class="form-label" data-tpl-if="label">{{{{ label }}}}</label>
2491
+ <label class="form-label" data-tpl-if="label">{{{{ label }}}}</label>
2482
2492
  <div class="input-group">
2483
2493
  <button data-ref="operator" class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" value="EQ" form="">=</button>
2484
2494
  <ul class="dropdown-menu">
@@ -2490,10 +2500,9 @@ var ful = (function (exports, ftl) {
2490
2500
  <li><a class="dropdown-item" role="button" value="GTE">&SucceedsSlantEqual;</a></li>
2491
2501
  <li><a class="dropdown-item" role="button" value="BETWEEN">&LeftRightArrow;</a></li>
2492
2502
  </ul>
2493
- <input data-tpl-id="id" data-ref="value1" type="date" class="form-control" form="">
2503
+ <input data-ref="value1" type="date" class="form-control" form="">
2494
2504
  <input data-ref="value2" type="date" class="form-control" form="" hidden>
2495
2505
  <span class="input-group-text"><i class="bi bi-search"></i></span>
2496
-
2497
2506
  </div>
2498
2507
  <ful-field-error></ful-field-error>
2499
2508
  `;
@@ -2507,15 +2516,18 @@ var ful = (function (exports, ftl) {
2507
2516
  this.internals = this.attachInternals();
2508
2517
  }
2509
2518
  render({ slots }) {
2510
- const id = ftl.Attributes.uid('instant-filter');
2511
2519
  const label = ftl.Fragments.toHtml(slots.default.cloneNode(true)).trim().length === 0 ? null : slots.default;
2512
2520
  const name = this.getAttribute("name");
2513
- const fragment = this.template().withOverlay({ id, label, name }).render(this);
2521
+ const fragment = this.template().withOverlay({ label, name }).render(this);
2514
2522
  this.#operator = fragment.querySelector('[data-ref=operator]');
2515
2523
  this.#value1 = fragment.querySelector('[data-ref=value1]');
2516
2524
  this.#value2 = fragment.querySelector('[data-ref=value2]');
2525
+ this.#fieldError = fragment.querySelector('ful-field-error');
2526
+ const labelEl = fragment.querySelector('label');
2527
+ labelEl?.addEventListener('click', () => this.focus());
2528
+ this.#value1.ariaDescribedByElements = [this.#fieldError];
2529
+ this.#value1.ariaLabelledByElements = labelEl ? [labelEl] : [];
2517
2530
  this.replaceChildren(fragment);
2518
- this.#fieldError = this.querySelector('ful-field-error');
2519
2531
  this.addEventListener('click', (evt) => {
2520
2532
  const target = /** @type HTMLElement */(evt.target);
2521
2533
  if (!target.matches('ul > li > a')) {
@@ -2568,7 +2580,7 @@ var ful = (function (exports, ftl) {
2568
2580
  static observed = ["value:json"];
2569
2581
  static slots = true;
2570
2582
  static template = `
2571
- <label data-tpl-for="id" class="form-label" data-tpl-if="label">{{{{ label }}}}</label>
2583
+ <label class="form-label" data-tpl-if="label">{{{{ label }}}}</label>
2572
2584
  <div class="input-group">
2573
2585
  <button data-ref="operator" class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" value="CONTAINS" form="">&mldr;a&mldr;</button>
2574
2586
  <ul class="dropdown-menu">
@@ -2577,7 +2589,7 @@ var ful = (function (exports, ftl) {
2577
2589
  <li><a class="dropdown-item" role="button" value="ENDS_WITH">&mldr;a</a></li>
2578
2590
  <li><a class="dropdown-item" role="button" value="EQ">=</a></li>
2579
2591
  </ul>
2580
- <input data-tpl-id="id" data-ref="value" type="text" class="form-control" form="">
2592
+ <input data-ref="value" type="text" class="form-control" form="">
2581
2593
  <span class="input-group-text"><i class="bi bi-search"></i></span>
2582
2594
  </div>
2583
2595
  <ful-field-error></ful-field-error>
@@ -2591,14 +2603,17 @@ var ful = (function (exports, ftl) {
2591
2603
  this.internals = this.attachInternals();
2592
2604
  }
2593
2605
  render({ slots }) {
2594
- const id = ftl.Attributes.uid('string-filter');
2595
2606
  const label = ftl.Fragments.toHtml(slots.default.cloneNode(true)).trim().length === 0 ? null : slots.default;
2596
2607
  const name = this.getAttribute("name");
2597
- const fragment = this.template().withOverlay({ id, label, name }).render(this);
2608
+ const fragment = this.template().withOverlay({ label, name }).render(this);
2598
2609
  this.#operator = fragment.querySelector('[data-ref=operator]');
2599
2610
  this.#value = fragment.querySelector('[data-ref=value]');
2611
+ this.#fieldError = fragment.querySelector('ful-field-error');
2612
+ const labelEl = fragment.querySelector('label');
2613
+ labelEl?.addEventListener('click', () => this.focus());
2614
+ this.#value.ariaDescribedByElements = [this.#fieldError];
2615
+ this.#value.ariaLabelledByElements = labelEl ? [labelEl] : [];
2600
2616
  this.replaceChildren(fragment);
2601
- this.#fieldError = this.querySelector('ful-field-error');
2602
2617
  this.addEventListener('click', (evt) => {
2603
2618
  const target = /** @type HTMLElement */(evt.target);
2604
2619
  if (!target.matches('ul > li > a')) {