@optionfactory/ful 5.0.3 → 5.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ful.mjs CHANGED
@@ -1688,16 +1688,18 @@ class InputFile extends Input {
1688
1688
  'dropzonelabel': 'Click or drop your files here',
1689
1689
  'unaccepptablefiletype': "Only files of type {0} are supported",
1690
1690
  'maxfilesizeexceeded': "Maximum supported file size is {0}",
1691
- 'maxtotalsizeexceeded': "Maximum supported total file size is {0}"
1691
+ 'maxtotalsizeexceeded': "Maximum supported total file size is {0}",
1692
+ 'maxfilesexceeded': "Maximum files count exceeded"
1692
1693
  },
1693
1694
  it: {
1694
1695
  'dropzonelabel': 'Clicca o trascina i file qui',
1695
1696
  'unaccepptablefiletype': "Solo i file di tipo {0} sono supportati",
1696
1697
  'maxfilesizeexceeded': "La dimensione massima di un file è di {0}",
1697
- 'maxtotalsizeexceeded': "La dimensione massima complessiva dei file è di {0}"
1698
+ 'maxtotalsizeexceeded': "La dimensione massima complessiva dei file è di {0}",
1699
+ 'maxfilesexceeded': "Numero massimo di file superato",
1698
1700
  }
1699
1701
  }
1700
- static observed = ['value', 'readonly:presence', 'required:presence', "accept:csv", 'multiple:presence', "itemlist:presence", "dropzone:presence", "maxfilesize:number", "maxtotalsize:number"];
1702
+ static observed = ['value', 'readonly:presence', 'required:presence', "accept:csv", 'multiple:presence', "itemlist:presence", "dropzone:presence", "maxfiles:number", "maxfilesize:number", "maxtotalsize:number"];
1701
1703
  #accept;
1702
1704
  #items;
1703
1705
  #dropzone;
@@ -1720,7 +1722,7 @@ class InputFile extends Input {
1720
1722
  <div data-ref="dropzone" class="dropzone" data-tpl-if="slots.dropzone">
1721
1723
  {{{{ slots.dropzone }}}}
1722
1724
  </div>
1723
- <div data-ref="dropzone" class="dropzone" data-tpl-if="!slots.dropzone">
1725
+ <div data-ref="dropzone" class="default-dropzone" data-tpl-if="!slots.dropzone">
1724
1726
  {{ #l10n:t('dropzonelabel') }}
1725
1727
  </div>
1726
1728
  <ful-item-list></ful-item-list>
@@ -1747,6 +1749,7 @@ class InputFile extends Input {
1747
1749
  this.multiple = observed.multiple;
1748
1750
  this.itemlist = observed.itemlist;
1749
1751
  this.dropzone = observed.dropzone;
1752
+ this.maxfiles = observed.maxfiles;
1750
1753
  this.maxfilesize = observed.maxfilesize;
1751
1754
  this.maxtotalsize = observed.maxtotalsize;
1752
1755
  this.#warnings.addEventListener('animationend', e => {
@@ -1788,13 +1791,14 @@ class InputFile extends Input {
1788
1791
  this.#ensureAcceptable();
1789
1792
  this.#ensureFileSizes();
1790
1793
  this.#ensureTotalSize();
1794
+ this.#ensureFilesCount();
1791
1795
  this.template('items').withOverlay({ files: this.files }).withModule('bytes', { format: this.#formatByteSize }).renderTo(this.#items);
1792
1796
  }
1793
1797
  warning(key, args) {
1794
1798
  this.template('warning').withOverlay({ key, args }).renderTo(this.#warnings);
1795
1799
  }
1796
1800
  #ensureAcceptable() {
1797
- if (!this.#accept) {
1801
+ if (!this.#accept.length) {
1798
1802
  return;
1799
1803
  }
1800
1804
  const unacceptable = [...this.files]
@@ -1803,11 +1807,23 @@ class InputFile extends Input {
1803
1807
  if (unacceptable.length === 0) {
1804
1808
  return;
1805
1809
  }
1806
- this.warning('unaccepptablefiletype', this.#accept.join(","));
1810
+ this.warning('unaccepptablefiletype', this.#accept.join(", "));
1807
1811
  const dt = new DataTransfer();
1808
1812
  [...this.files].filter(f => !unacceptable.includes(f)).forEach(f => dt.items.add(f));
1809
1813
  this.files = dt.files;
1810
1814
  }
1815
+ #ensureFilesCount() {
1816
+ if (this.#maxfiles === null) {
1817
+ return;
1818
+ }
1819
+ if (this.files.length <= this.#maxfiles) {
1820
+ return;
1821
+ }
1822
+ this.warning('maxfilesexceeded');
1823
+ const dt = new DataTransfer();
1824
+ this.files = dt.files;
1825
+ }
1826
+
1811
1827
  #ensureFileSizes() {
1812
1828
  if (this.#maxfilesize === null) {
1813
1829
  return;
@@ -1873,6 +1889,19 @@ class InputFile extends Input {
1873
1889
  set value(v) {
1874
1890
  //TODO:
1875
1891
  }
1892
+ get totalsize() {
1893
+ return Array.from(this.files).reduce((a, f) => a + f.size, 0);
1894
+ }
1895
+ #maxfiles;
1896
+ get maxfiles() {
1897
+ return this.#maxfiles;
1898
+ }
1899
+ set maxfiles(v) {
1900
+ this.#maxfiles = v;
1901
+ this.reflect(() => {
1902
+ Attributes.set(this, 'maxfiles', v);
1903
+ });
1904
+ }
1876
1905
  #maxfilesize;
1877
1906
  get maxfilesize() {
1878
1907
  return this.#maxfilesize;
@@ -1880,7 +1909,7 @@ class InputFile extends Input {
1880
1909
  set maxfilesize(v) {
1881
1910
  this.#maxfilesize = v;
1882
1911
  this.reflect(() => {
1883
- this.setAttribute('maxfilesize', v);
1912
+ Attributes.set(this, 'maxfilesize', v);
1884
1913
  });
1885
1914
  }
1886
1915
  #maxtotalsize;
@@ -1890,7 +1919,7 @@ class InputFile extends Input {
1890
1919
  set maxtotalsize(v) {
1891
1920
  this.#maxtotalsize = v;
1892
1921
  this.reflect(() => {
1893
- this.setAttribute('maxtotalsize', v);
1922
+ Attributes.set(this, 'maxtotalsize', v);
1894
1923
  });
1895
1924
  }
1896
1925
  #useItemlist;
@@ -1912,7 +1941,7 @@ class InputFile extends Input {
1912
1941
  this.reflect(() => {
1913
1942
  Attributes.toggle(this, "dropzone", v);
1914
1943
  });
1915
- }
1944
+ }
1916
1945
  }
1917
1946
 
1918
1947
  class RemoteLoader {
@@ -2344,7 +2373,7 @@ class Select extends ParsedElement {
2344
2373
  this.replaceChildren(fragment);
2345
2374
  }
2346
2375
  async withLoader(fn) {
2347
- await fn(this.#loader);
2376
+ return await fn(this.#loader);
2348
2377
  }
2349
2378
  #changed() {
2350
2379
  const selection = [...this.#values.entries()].map(e => ({ key: e[0], label: e[1][0], metadata: e[1].slice(1) }));
@@ -2840,8 +2869,8 @@ class TableSchemaParser {
2840
2869
  rowsTr.setAttribute(attr, value ?? '');
2841
2870
  }
2842
2871
  const columns = Nodes.queryChildrenAll(schema, "column");
2843
- const sort = columns.filter(v => v.hasAttribute('order')).map(v => ({sorter: v.getAttribute("sorter"), order: v.getAttribute("order")}))[0] ?? null;
2844
- for(var column of columns){
2872
+ const sort = columns.filter(v => v.hasAttribute('order')).map(v => ({ sorter: v.getAttribute("sorter"), order: v.getAttribute("order") }))[0] ?? null;
2873
+ for (var column of columns) {
2845
2874
  const maybeTitleTag = Nodes.queryChildren(column, 'title');
2846
2875
  const sorter = column.getAttribute("sorter");
2847
2876
  const order = column.getAttribute("order");
@@ -2850,12 +2879,12 @@ class TableSchemaParser {
2850
2879
  column.removeAttribute("sorter");
2851
2880
  column.removeAttribute("order");
2852
2881
  column.removeAttribute("title");
2853
- const wrappedTitleNode = (!sorter && !order ) ? titleNode : (() => {
2882
+ const wrappedTitleNode = (!sorter && !order) ? titleNode : (() => {
2854
2883
  const fulSorter = document.createElement("ful-sorter");
2855
- if(sorter){
2884
+ if (sorter) {
2856
2885
  fulSorter.setAttribute("sorter", sorter);
2857
2886
  }
2858
- if(order){
2887
+ if (order) {
2859
2888
  fulSorter.setAttribute("order", order);
2860
2889
  }
2861
2890
  fulSorter.append(titleNode);
@@ -2875,14 +2904,32 @@ class TableSchemaParser {
2875
2904
  }
2876
2905
 
2877
2906
  return {
2878
- headersTemplate: template.withOverlay({inHeaders: true, inRows: false}).withFragment(Fragments.from(headersTr)),
2879
- rowsTemplate: template.withOverlay({inHeaders: false, inRows: true}).withFragment(Fragments.from(rowsTr)),
2907
+ headersTemplate: template.withOverlay({ inHeaders: true, inRows: false }).withFragment(Fragments.from(headersTr)),
2908
+ rowsTemplate: template.withOverlay({ inHeaders: false, inRows: true }).withFragment(Fragments.from(rowsTr)),
2880
2909
  sort: sort,
2881
2910
  length: columns.length
2882
2911
  }
2883
2912
  }
2884
2913
  }
2885
2914
 
2915
+
2916
+
2917
+ class InMemoryTableLoader {
2918
+ #data
2919
+ constructor(data) {
2920
+ this.#data = data;
2921
+ }
2922
+ async load(pageRequest, sortRequest, filterRequest) {
2923
+ return {
2924
+ page: this.#data,
2925
+ size: this.#data.length
2926
+ };
2927
+ }
2928
+ update(data) {
2929
+ this.#data = data;
2930
+ }
2931
+ }
2932
+
2886
2933
  class RemoteTableLoader {
2887
2934
  #http;
2888
2935
  #url;
@@ -2906,10 +2953,13 @@ class RemoteTableLoader {
2906
2953
 
2907
2954
  class TableLoader {
2908
2955
  static create(el, conf) {
2909
- const http = registry.component("http-client");
2910
2956
  const url = el.getAttribute("src");
2911
- const method = el.getAttribute("method") ?? 'GET';
2912
- return new RemoteTableLoader(http, url, method);
2957
+ if (url) {
2958
+ const http = registry.component("http-client");
2959
+ const method = el.getAttribute("method") ?? 'GET';
2960
+ return new RemoteTableLoader(http, url, method);
2961
+ }
2962
+ return new InMemoryTableLoader([]);
2913
2963
  }
2914
2964
  }
2915
2965
 
@@ -2983,6 +3033,7 @@ class Table extends ParsedElement {
2983
3033
  {{{{ schema.rowsTemplate.withOverlay({'rows': pageResponse.data}).render() }}}}
2984
3034
  `
2985
3035
  };
3036
+ #loader;
2986
3037
  #schema;
2987
3038
  #body;
2988
3039
  #loading;
@@ -2998,6 +3049,8 @@ class Table extends ParsedElement {
2998
3049
  const tableWrapper = /** @type HTMLTableElement */ (Nodes.queryChildren(fragment, '.table-wrapper'));
2999
3050
  const table = /** @type HTMLTableElement */ (tableWrapper.querySelector("table"));
3000
3051
  Attributes.forward('table-', this, table);
3052
+ this.#loader = registry.component(this.getAttribute("loader") ?? 'loaders:table').create(this);
3053
+
3001
3054
  this.#schema = schema;
3002
3055
  this.#body = table.querySelector(':scope > tbody');
3003
3056
  this.#loading = table.querySelector(":scope > tbody[data-ref=loading]");
@@ -3050,8 +3103,7 @@ class Table extends ParsedElement {
3050
3103
  this.#feedback.setAttribute("hidden", "");
3051
3104
  this.#noAutoload.setAttribute("hidden", "");
3052
3105
  try {
3053
- const loader = registry.component(this.getAttribute("loader") ?? 'loaders:table').create(this);
3054
- const pageResponse = await loader.load(pageRequest, sortRequest, filterRequest);
3106
+ const pageResponse = await this.#loader.load(pageRequest, sortRequest, filterRequest);
3055
3107
  this.#latestRequest = { pageRequest, sortRequest, filterRequest };
3056
3108
  this.#update(pageRequest, sortRequest, filterRequest, pageResponse);
3057
3109
  } catch (/** @type any */error) {
@@ -3065,14 +3117,15 @@ class Table extends ParsedElement {
3065
3117
  throw error;
3066
3118
  }
3067
3119
  }
3068
-
3120
+ async withLoader(fn) {
3121
+ return await fn(this.#loader);
3122
+ }
3069
3123
  async resetWithFilter(filterRequest) {
3070
3124
  return await this.load({
3071
3125
  page: 0,
3072
3126
  size: this.#latestRequest.pageRequest.size
3073
3127
  }, this.#latestRequest.sortRequest, filterRequest);
3074
3128
  }
3075
-
3076
3129
  #update(pageRequest, sortRequest, filterRequest, pageResponse) {
3077
3130
  this.#loading.setAttribute("hidden", "");
3078
3131
  this.#body.replaceChildren(this.template('row').withOverlay({