@optionfactory/ful 4.0.13 → 4.0.14

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.mjs CHANGED
@@ -1724,24 +1724,24 @@ class InputFile extends Input {
1724
1724
  <div data-ref="dropzone" class="dropzone" data-tpl-if="!slots.dropzone">
1725
1725
  {{ #l10n:t('dropzonelabel') }}
1726
1726
  </div>
1727
- <div data-ref="items" class="items"></div>
1727
+ <ful-item-list></ful-item-list>
1728
1728
  <ful-field-warnings></ful-field-warnings>
1729
1729
  <ful-field-error></ful-field-error>
1730
1730
  `;
1731
1731
  static templates = {
1732
1732
  items: `
1733
- <div class="item" data-tpl-each="files" data-tpl-var="file" data-tpl-data-name="file.name">
1734
- <div class="filename"><span>{{ file.name }}</span></div>
1735
- <div class="size">{{ #bytes:format(file.size) }}</div>
1736
- <button class="btn btn-sm btn-outline-danger"><i class="bi bi-x-lg"></i></button>
1737
- </div>
1733
+ <ful-item data-tpl-each="files" data-tpl-var="file" data-tpl-data-name="file.name">
1734
+ <div>{{ file.name }}</div>
1735
+ <div>{{ #bytes:format(file.size) }}</div>
1736
+ <button type="button" class="btn btn-sm btn-outline-danger bi bi-x-lg"></button>
1737
+ </ful-item>
1738
1738
  `,
1739
1739
  warning: `<ful-field-warning>{{ #l10n:t(key, args) }}</ful-field-warning>`
1740
1740
  }
1741
1741
  render(conf) {
1742
1742
  const { observed } = conf;
1743
1743
  super.render(conf);
1744
- this.#items = this.querySelector("[data-ref=items]");
1744
+ this.#items = this.querySelector("ful-item-list");
1745
1745
  this.#dropzone = this.querySelector("[data-ref=dropzone]");
1746
1746
  this.#warnings = this.querySelector("ful-field-warnings");
1747
1747
  this.accept = observed.accept;
@@ -1757,7 +1757,7 @@ class InputFile extends Input {
1757
1757
  if (!e.target.closest("button")) {
1758
1758
  return;
1759
1759
  }
1760
- const fileName = e.target.closest(".item").dataset.name;
1760
+ const fileName = e.target.closest("ful-item").dataset.name;
1761
1761
  const dt = new DataTransfer();
1762
1762
  [...this.files].filter(f => f.name !== fileName).forEach(f => dt.items.add(f));
1763
1763
  this.files = dt.files;
@@ -1789,11 +1789,7 @@ class InputFile extends Input {
1789
1789
  this.#ensureAcceptable();
1790
1790
  this.#ensureFileSizes();
1791
1791
  this.#ensureTotalSize();
1792
- if(this.#useItemlist){
1793
- this.template('items').withOverlay({ files: this.files }).withModule('bytes', { format: this.#formatByteSize }).renderTo(this.#items);
1794
- }else {
1795
- this.#items.replaceChildren();
1796
- }
1792
+ this.template('items').withOverlay({ files: this.files }).withModule('bytes', { format: this.#formatByteSize }).renderTo(this.#items);
1797
1793
  }
1798
1794
  warning(key, args) {
1799
1795
  this.template('warning').withOverlay({ key, args }).renderTo(this.#warnings);
@@ -1854,7 +1850,7 @@ class InputFile extends Input {
1854
1850
  set multiple(v) {
1855
1851
  this._input.multiple = v;
1856
1852
  this.reflect(() => {
1857
- this.setAttribute('multiple', this._input.multiple);
1853
+ Attributes.toggle(this, "multiple", v);
1858
1854
  });
1859
1855
  }
1860
1856
  get files() {
@@ -1887,7 +1883,6 @@ class InputFile extends Input {
1887
1883
  this.reflect(() => {
1888
1884
  this.setAttribute('maxfilesize', v);
1889
1885
  });
1890
-
1891
1886
  }
1892
1887
  #maxtotalsize;
1893
1888
  get maxtotalsize() {
@@ -1905,7 +1900,6 @@ class InputFile extends Input {
1905
1900
  }
1906
1901
  set itemlist(v) {
1907
1902
  this.#useItemlist = v;
1908
- Attributes.toggle(this.#items, "hidden", !v);
1909
1903
  this.reflect(() => {
1910
1904
  Attributes.toggle(this, "itemlist", v);
1911
1905
  });
@@ -1916,7 +1910,6 @@ class InputFile extends Input {
1916
1910
  }
1917
1911
  set dropzone(v) {
1918
1912
  this.#useDropzone = v;
1919
- Attributes.toggle(this.#dropzone, "hidden", !v);
1920
1913
  this.reflect(() => {
1921
1914
  Attributes.toggle(this, "dropzone", v);
1922
1915
  });
@@ -2145,7 +2138,7 @@ class Dropdown extends ParsedElement {
2145
2138
  }
2146
2139
 
2147
2140
  class Select extends ParsedElement {
2148
- static observed = ['value:csvm', 'readonly:presence']
2141
+ static observed = ['value:csvm', 'readonly:presence', 'itemlist:presence']
2149
2142
  static slots = true
2150
2143
  static template = `
2151
2144
  <div class="form-label">
@@ -2165,8 +2158,17 @@ class Select extends ParsedElement {
2165
2158
  {{{{ slots.after }}}}
2166
2159
  <span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>
2167
2160
  </div>
2161
+ <ful-item-list></ful-item-list>
2168
2162
  <ful-field-error></ful-field-error>
2169
2163
  `;
2164
+ static templates = {
2165
+ items: `
2166
+ <ful-item data-tpl-each="entries" data-tpl-var="entry" data-tpl-data-key="entry[0]">
2167
+ <div>{{ entry[1] }}</div>
2168
+ <button type="button" class="btn btn-sm btn-outline-danger bi bi-x-lg"></button>
2169
+ </ful-item>
2170
+ `
2171
+ }
2170
2172
  static mappers = {
2171
2173
  "csvm": (v, name, el) => {
2172
2174
  if (el.hasAttribute("multiple")) {
@@ -2181,6 +2183,7 @@ class Select extends ParsedElement {
2181
2183
  #badges
2182
2184
  #ddmenu
2183
2185
  #input
2186
+ #items;
2184
2187
  #multiple
2185
2188
  #fieldError
2186
2189
  #values = new Map()
@@ -2196,12 +2199,14 @@ class Select extends ParsedElement {
2196
2199
  await this.#loader.prefetch?.();
2197
2200
  const fragment = this.template().withOverlay({ slots, name }).render();
2198
2201
  this.#input = fragment.querySelector('input');
2202
+ this.#items = fragment.querySelector("ful-item-list");
2199
2203
  Attributes.forward('input-', this, this.#input);
2200
2204
  this.#badges = fragment.querySelector('badges');
2201
2205
 
2202
2206
  this.value = observed.value;
2203
2207
  this.disabled = disabled;
2204
2208
  this.readonly = observed.readonly;
2209
+ this.itemlist = observed.itemlist;
2205
2210
 
2206
2211
  this.#ddmenu = fragment.querySelector('ful-dropdown');
2207
2212
  const label = fragment.querySelector('label');
@@ -2226,6 +2231,22 @@ class Select extends ParsedElement {
2226
2231
  this.#input.focus();
2227
2232
  dload();
2228
2233
  });
2234
+ this.#items.addEventListener('click', (e) => {
2235
+ e.stopPropagation();
2236
+ if (!e.target.closest("button")) {
2237
+ return;
2238
+ }
2239
+ if(this.disabled || this.readonly){
2240
+ return;
2241
+ }
2242
+ const idx = [...this.#items.children].indexOf(e.target.closest('ful-item'));
2243
+ if (idx === -1) {
2244
+ return;
2245
+ }
2246
+ this.#values.delete(Array.from(this.#values.keys()).pop());
2247
+ this.#changed();
2248
+ this.#syncBadges();
2249
+ });
2229
2250
  this.#badges.addEventListener('click', (e) => {
2230
2251
  e.stopPropagation();
2231
2252
  if(this.disabled || this.readonly){
@@ -2333,6 +2354,8 @@ class Select extends ParsedElement {
2333
2354
  });
2334
2355
  this.#badges.replaceChildren();
2335
2356
  this.#badges.append(...badges);
2357
+ this.#items.replaceChildren();
2358
+ this.template('items').withOverlay({ entries: this.#values.entries() }).renderTo(this.#items);
2336
2359
  }
2337
2360
  set value(vs) {
2338
2361
  if(vs === null){
@@ -2374,6 +2397,16 @@ class Select extends ParsedElement {
2374
2397
  Attributes.toggle(this, 'readonly', v);
2375
2398
  });
2376
2399
  }
2400
+ #useItemlist;
2401
+ get itemlist() {
2402
+ return this.#useItemlist;
2403
+ }
2404
+ set itemlist(v) {
2405
+ this.#useItemlist = v;
2406
+ this.reflect(() => {
2407
+ Attributes.toggle(this, "itemlist", v);
2408
+ });
2409
+ }
2377
2410
  focus(options) {
2378
2411
  this.#input.focus(options);
2379
2412
  }