@optionfactory/fml 8.0.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/LICENSE.md +21 -0
- package/README.md +22 -0
- package/dist/client-errors.iife.js +109 -0
- package/dist/client-errors.iife.js.map +1 -0
- package/dist/client-errors.iife.min.js +2 -0
- package/dist/client-errors.iife.min.js.map +1 -0
- package/dist/fml.css +2 -0
- package/dist/fml.css.map +1 -0
- package/dist/fml.d.mts +1241 -0
- package/dist/fml.iife.js +8340 -0
- package/dist/fml.iife.js.map +1 -0
- package/dist/fml.iife.min.js +2 -0
- package/dist/fml.iife.min.js.map +1 -0
- package/dist/fml.min.mjs +2 -0
- package/dist/fml.min.mjs.map +1 -0
- package/dist/fml.mjs +8284 -0
- package/dist/fml.mjs.map +1 -0
- package/dist/ftl.d.mts +361 -0
- package/dist/ftl.iife.js +4719 -0
- package/dist/ftl.iife.js.map +1 -0
- package/dist/ftl.iife.min.js +2 -0
- package/dist/ftl.iife.min.js.map +1 -0
- package/dist/ftl.min.mjs +2 -0
- package/dist/ftl.min.mjs.map +1 -0
- package/dist/ftl.mjs +4700 -0
- package/dist/ftl.mjs.map +1 -0
- package/dist/ful.css +2 -0
- package/dist/ful.css.map +1 -0
- package/dist/ful.d.mts +581 -0
- package/dist/ful.iife.js +2814 -0
- package/dist/ful.iife.js.map +1 -0
- package/dist/ful.iife.min.js +2 -0
- package/dist/ful.iife.min.js.map +1 -0
- package/dist/ful.min.mjs +2 -0
- package/dist/ful.min.mjs.map +1 -0
- package/dist/ful.mjs +2780 -0
- package/dist/ful.mjs.map +1 -0
- package/dist/httpc.d.mts +306 -0
- package/dist/httpc.iife.js +755 -0
- package/dist/httpc.iife.js.map +1 -0
- package/dist/httpc.iife.min.js +2 -0
- package/dist/httpc.iife.min.js.map +1 -0
- package/dist/httpc.min.mjs +2 -0
- package/dist/httpc.min.mjs.map +1 -0
- package/dist/httpc.mjs +743 -0
- package/dist/httpc.mjs.map +1 -0
- package/package.json +72 -0
package/dist/ful.min.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{ParsedElement as e,Attributes as t,registry as s,Fragments as i,Templates as r,Nodes as a,Rendering as n}from"./ftl.min.mjs";import{Failure as l,HttpClient as o}from"./httpc.min.mjs";class d extends Storage{static save(e,t){localStorage.setItem(e,JSON.stringify(t))}static load(e){const t=localStorage.getItem(e);return null===t?void 0:JSON.parse(t)}static remove(e){localStorage.removeItem(e)}static pop(e){const t=d.load(e);return d.remove(e),t}}class u extends Storage{static save(e,t){sessionStorage.setItem(e,JSON.stringify(t))}static load(e){const t=sessionStorage.getItem(e);return null===t?void 0:JSON.parse(t)}static remove(e){sessionStorage.removeItem(e)}static pop(e){const t=u.load(e);return u.remove(e),t}}class c{static save(e,t,s){d.save(e,{revision:t,data:s})}static load(e,t){const s=d.load(e);if(void 0!==s){if(s.revision===t)return s.data;localStorage.removeItem(e)}}}class h{static save(e,t,s){u.save(e,{revision:t,data:s})}static load(e,t){const s=u.load(e);if(void 0!==s){if(s.revision===t)return s.data;localStorage.removeItem(e)}}}class p{static async fireAsync(e,t,s){e.dispatchEvent(t);const i=t.async?.promises??[],r=s?.mode??"broadcast";if("pipeline"===r&&i.length>1)throw new Error(`[AsyncEvents] Event "${t.type}" is configured in 'pipeline' mode and expects at most one async listener, but ${i.length} listeners were triggered on this element.`);if("delegate"===r&&1!==i.length)throw new Error(`[AsyncEvents] Event "${t.type}" is configured in 'delegate' mode and requires exactly one async listener, but ${i.length} were registered.`);return"broadcast"===r?Promise.all(i):Promise.resolve(i[0])}static asyncOn(e,t,s,i){const r=async e=>{const t=e;t.async||(t.async={promises:[]});const{promise:i,resolve:r,reject:a}=Promise.withResolvers();t.async.promises.push(i);try{r(await s(t))}catch(e){a(e)}};return e.addEventListener(t,r,i),r}static asyncOff(e,t,s,i){e.removeEventListener(t,s,i)}static mixInto(...e){for(const t of e)Object.assign(t.prototype,{async fireAsync(e,t){return await p.fireAsync(this,e,t)},asyncOn(e,t,s){return p.asyncOn(this,e,t,s)},asyncOff(e,t,s){p.asyncOff(this,e,t,s)}})}}class f{static sleep(e){return new Promise(t=>setTimeout(t,e))}static DEBOUNCE_DEFAULT=0;static DEBOUNCE_IMMEDIATE=1;static debounce(e,t,s){const i=s??f.DEBOUNCE_DEFAULT;let r=null,a=[],n=0;const l=()=>{const s=performance.now()-n;e>s?r=setTimeout(l,e-s):(r=null,i!==f.DEBOUNCE_IMMEDIATE&&t(...a),null===r&&(a=[]))};return[function(){a=[...arguments],n=performance.now(),null===r&&(r=setTimeout(l,e),i===f.DEBOUNCE_IMMEDIATE&&t(...a))},()=>clearTimeout(r)]}static THROTTLE_DEFAULT=0;static THROTTLE_NO_LEADING=1;static THROTTLE_NO_TRAILING=2;static throttle(e,t,s){const i=s??f.THROTTLE_DEFAULT;let r=null,a=[],n=0;const l=()=>{n=i&f.THROTTLE_NO_LEADING?0:performance.now(),r=null,t(...a),null===r&&(a=[])};return[function(){const s=performance.now();!n&&i&f.THROTTLE_NO_LEADING&&(n=s);const o=0===n?0:e-(s-n);a=[...arguments],o<=0||o>e?(null!==r&&(clearTimeout(r),r=null),n=s,t(...a),null===r&&(a=[])):null!==r||i&f.THROTTLE_NO_TRAILING||(r=setTimeout(l,o))},()=>clearTimeout(r)]}}class m{static flatten(e,t,s){return Object.keys(e).reduce((i,r)=>{const a=t.length?t+"."+r:r;return s.has(a)||"object"!=typeof e[r]||null===e[r]?i[a]=e[r]:Object.assign(i,m.flatten(e[r],a,s)),i},{})}static providePath(e,t,s){const i=t.split(".").map(e=>/^[0-9]+$/.test(e)?+e:e);let r=e??{},a=null;for(let t=0;;++t){const n=i[t],l=i[t-1];if(Number.isInteger(n)&&!Array.isArray(r)&&(null!==a?a[l]=r=[]:e=r=[]),t===i.length-1)return r[n]=void 0!==s?s:n in r?r[n]:null,e;void 0===r[n]&&(r[n]={}),a=r,r=r[n]}}static extract(e){if("radio"===e.getAttribute("type")){if(!e.checked)return;return"boolean"===e.dataset.fulBindType?"true"===e.value:e.value}return"checkbox"===e.getAttribute("type")?e.checked:"boolean"===e.dataset.fulBindType?e.value?"true"===e.value:null:!("INPUT"!==e.tagName&&"SELECT"!==e.tagName&&"TEXTAREA"!==e.tagName||""!==e.value&&void 0!==e.value)?null:e.value}static extractFrom(e,t){let s={};for(const i of e.elements)!i.hasAttribute("name")||i.matches(":disabled")&&i!==t||(s=m.providePath(s,i.getAttribute("name"),m.extract(i)));return s}static mutate(e,t){"radio"!==e.getAttribute("type")?"checkbox"!==e.getAttribute("type")?e.value=t:e.checked=t:e.checked=e.getAttribute("value")===t}static mutateIn(e,t){const s=Array.from(e.elements).map(e=>e.getAttribute("name")).filter(e=>e);for(const[i,r]of Object.entries(m.flatten(t,"",new Set(s))))for(const t of e.querySelectorAll(`[name='${CSS.escape(i)}']`))m.mutate(t,r)}static errors(e,t,s){const i=t.filter(e=>"FIELD_ERROR"===e.type||"INVALID_FORMAT"===e.type),r=t.filter(e=>"FIELD_ERROR"!==e.type&&"INVALID_FORMAT"!==e.type);e.querySelectorAll("[name]").forEach(e=>e.setCustomValidity?.("")),e.querySelectorAll("ful-errors").forEach(e=>{e.replaceChildren(),e.setAttribute("hidden","")}),i.forEach(t=>{const s=t.context.replace(/\[/g,".").replace(/\]\./g,".").replace(/\]/g,"").split(".");for(let i=s.length;0!=i;--i){const r=s.slice(0,i).join("."),a=s.slice(i,s.length).join(".");e.querySelectorAll(`[name='${CSS.escape(r)}']`).forEach(e=>e.setCustomValidity?.(t.reason,a))}}),e.querySelectorAll("ful-errors").forEach(e=>{e.innerText=r.map(e=>e.reason).join("\n"),0!==r.length&&e.removeAttribute("hidden")}),0!=t.length&&s&&Array.from(e.querySelectorAll(":invalid")).sort((e,t)=>e.getBoundingClientRect().y-t.getBoundingClientRect().y)[0]?.focus()}}class b{#e;#t;#s;#i;#r;constructor(e,t,s,i,r){this.#e=e,this.#t=t,this.#s=s,this.#i=i,this.#r=r}prepare(e,t){return this.#i(e,t)}async submit(e,t){return await this.#e.request(this.#s,this.#t).json(e).fetch()}transform(e,t){return this.#r(e,t)}}class v{#i;#r;constructor(e,t){this.#i=e,this.#r=t}async prepare(e,t){return await this.#i(e,t)}async submit(e,t,s){return s}async transform(e,t){return await this.#r(e,t)}}class g{static create(e,t){const i=s.component("http-client"),r=e.hasAttribute("request-mapper")?s.component(e.getAttribute("request-mapper")):e=>e,a=e.hasAttribute("response-mapper")?s.component(e.getAttribute("response-mapper")):e=>e,n=e.getAttribute("action");if(!n)return new v(r,a);const l=e.getAttribute("method")??"POST";return new b(i,n,l,r,a)}}class y extends e{form;render(){const e=this.form=document.createElement("form");e.setAttribute("novalidate",""),t.forward("form-",this,e),e.replaceChildren(...this.childNodes),e.addEventListener("submit",async e=>{e.preventDefault(),e.stopPropagation(),await this.submit(e.submitter??void 0)}),this.hasAttribute("clear-invalid-on-change")&&this.addEventListener("change",e=>{e.target.setCustomValidity?.("")}),this.replaceChildren(e)}async submit(e){this.spinner(!0);try{const t=s.component(this.getAttribute("loader")??"loaders:form").create(this),i=m.extractFrom(this.form,e);let r=await t.prepare(i,this);try{const s=new CustomEvent("submit",{bubbles:!0,cancelable:!0,detail:{submitter:e,values:i,request:r}});if(!this.dispatchEvent(s))return;this.errors=[];const a=new CustomEvent("submit:requested",{bubbles:!0,cancelable:!1,detail:{submitter:e,values:s.detail.values,request:s.detail.request}});let n=await p.fireAsync(this,a,{mode:"pipeline"});r=a.detail.request,n=await t.submit(r,this,n);const l=await t.transform(n,this);this.dispatchEvent(new CustomEvent("submit:success",{bubbles:!0,cancelable:!1,detail:{submitter:e,values:i,request:r,response:l}}))}catch(t){this.dispatchEvent(new CustomEvent("submit:failure",{bubbles:!0,cancelable:!1,detail:{submitter:e,values:i,request:r,exception:t}})),t instanceof l&&(this.errors=t.problems),console.warn("failed to submit form",this,"reason:",t)}}finally{this.spinner(!1)}}reset(){this.form.reset()}spinner(e){this.querySelectorAll("ful-spinner").forEach(t=>{t.hidden=!e}),this.querySelectorAll("input,button").forEach(t=>{const s=t;"submit"!==s.type&&"reset"!==s.type||(e?(s.dataset.wd=String(s.disabled),s.disabled=!0):(s.disabled="true"===s.dataset.wd,delete s.dataset.wd))})}set values(e){m.mutateIn(this.form,e)}get values(){return m.extractFrom(this.form)}set errors(e){m.errors(this.form,e,this.hasAttribute("scroll-on-error"))}}class E extends e{static observed=["value","readonly:presence","required:presence"];static slots=!0;static template='\n <div class="form-label">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class="input-group">\n <span data-tpl-if="slots.ibefore" class="input-group-text">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <input data-tpl-if="type != \'textarea\'" class="form-control" data-tpl-type="type" placeholder=" " form="">\n <textarea data-tpl-if="type == \'textarea\'" class="form-control" placeholder=" " form=""></textarea>\n {{{{ slots.after }}}}\n <span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>\n </div>\n <ful-field-error></ful-field-error>\n ';static formAssociated=!0;_input;_fieldError;constructor(){super(),this.internals=this.attachInternals(),this.internals.role="presentation"}_type(){return this.getAttribute("type")??"text"}_fragment(e,t){return this.template().withOverlay({type:e,slots:t}).render()}render({slots:e,observed:s,disabled:i,skipObservedSetup:r}){const a=this._type(),n=this._fragment(a,e);this._input=n.querySelector("input,textarea"),t.forward("input-",this,this._input),r||(this.disabled=i,this.readonly=s.readonly,this.required=s.required,this.value=s.value),this._input.addEventListener("keydown",e=>{if("Enter"!==e.key||"textarea"===this._type())return;const t=this.internals.form;if(!t)return;const s=Array.from(t.querySelectorAll("button:not(:disabled), input:not(:disabled)")).find(e=>"submit"===e.type);t.requestSubmit(s)}),this._input.addEventListener("input",e=>{const t=this.getAttribute("mask");if(!t)return;const s=e.target.value,i=s.replace(new RegExp(t,"g"),"");if(s===i)return;const r=e.target.selectionStart,a=s.length-i.length;e.target.value=i,e.target.setSelectionRange(r-a,r-a)}),this._input.addEventListener("change",e=>{e.stopPropagation(),this.dispatchEvent(new CustomEvent("change",{bubbles:!0,cancelable:!1,detail:{value:this.value}}))});const l=n.querySelector("label");l.addEventListener("click",()=>this.focus()),this._fieldError=n.querySelector("ful-field-error"),this._input.ariaDescribedByElements=[this._fieldError],this._input.ariaLabelledByElements=[l],this.replaceChildren(n)}get value(){const e=this.hasAttribute("uppercase"),t=this.hasAttribute("trim"),s=this._input.value,i=e?s.toUpperCase():s,r=t?i.trim():i;return""===r?null:r}set value(e){this._input.value=""===e?null:e}get readonly(){return this._input.readOnly}set readonly(e){this._input.readOnly=e,this.reflect(()=>{t.toggle(this,"readonly",e)})}get disabled(){return this._input.hasAttribute("disabled")}set disabled(e){t.toggle(this._input,"disabled",e)}get required(){return"true"===this._input.getAttribute("aria-required")}set required(e){t.set(this._input,"aria-required",e?"true":null),this.reflect(()=>{t.toggle(this,"required",e)})}focus(e){this._input.focus(e)}setCustomValidity(e){if(!e)return this.internals.setValidity({}),void(this._fieldError.innerText="");this.internals.setValidity({customError:!0}," "),this._fieldError.innerText=e}formResetCallback(){this.value=this.unmarshal("value",this.getAttribute("value"))}}class x extends e{render(){const e=this.innerHTML.trim();if(""===e)return void(this.innerHTML=this.getAttribute("default")??"");const t=this.getAttribute("locale")??Intl.DateTimeFormat().resolvedOptions().locale,s=new Intl.DateTimeFormat(t,{year:"numeric",month:"numeric",day:"numeric"}),[i,r,a]=e.split("-").map(Number);this.innerHTML=s.format(new Date(i,r-1,a))}}class w extends e{render(){const e=this.innerHTML.trim();if(""===e)return void(this.innerHTML=this.getAttribute("default")??"");const t=this.getAttribute("locale")??Intl.DateTimeFormat().resolvedOptions().locale,s=new Intl.DateTimeFormat(t,{year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric",hour12:!1});this.innerHTML=s.format(new Date(w.isoToLocal(e)))}static isoToLocal(e){const t=new Date(e),s=(e,t)=>String(t).padStart(e,"0");return`${`${t.getFullYear()}-${s(2,t.getMonth()+1)}-${s(2,t.getDate())}`}T${`${s(2,t.getHours())}:${s(2,t.getMinutes())}:${s(2,t.getSeconds())}.${s(3,t.getMilliseconds())}`}`}}class A extends E{static observed=["value","readonly:presence","required:presence","min","max","step"];_type(){return"date"}render(e){const{observed:t}=e;super.render(e),this.min=t.min,this.max=t.max,this.step=t.step}get min(){const e=this._input.min;return""===e?null:e}set min(e){this._input.min=A.#a(e)}get max(){const e=this._input.max;return""===e?null:e}set max(e){this._input.max=A.#a(e)}get step(){const e=this._input.step;return""===e?null:e}set step(e){this._input.step=e??""}static#a(e){if(!e)return"";const t=e=>new Date(e.getTime()-6e4*e.getTimezoneOffset()).toISOString().split("T")[0];if("now"===e)return t(new Date);const s=/^([+-])(\d+)([dmy])$/.exec(e);if(!s)return e;const i="-"===s[1]?-1:1,r=+s[2],a=new Date;switch(a.setHours(0,0,0,0),s[3]){case"d":a.setDate(a.getDate()+r*i);break;case"m":const e=a.getDate();a.setMonth(a.getMonth()+r*i),a.getDate()!==e&&a.setDate(0);break;case"y":a.setFullYear(a.getFullYear()+r*i)}return t(a)}}class q extends A{_type(){return"time"}}class S extends E{static observed=["value","readonly:presence","required:presence","min","max","step"];_type(){return"datetime-local"}render(e){const{observed:t}=e;super.render(e),this.min=t.min,this.max=t.max,this.step=t.step}get value(){const e=this._input.value;return""===e?null:new Date(e).toISOString()}set value(e){this._input.value=e?w.isoToLocal(e):""}get min(){const e=this._input.min;return""===e?null:new Date(e).toISOString()}set min(e){this._input.min=e?w.isoToLocal(e):""}get max(){const e=this._input.max;return""===e?null:new Date(e).toISOString()}set max(e){this._input.max=e?w.isoToLocal(e):""}get step(){const e=this._input.step;return""===e?null:e}set step(e){this._input.step=e??""}}class T extends E{static l10n={en:{dropzonelabel:"Click or drop your files here",unaccepptablefiletype:"Only files of type {0} are supported",maxfilesizeexceeded:"Maximum supported file size is {0}",maxtotalsizeexceeded:"Maximum supported total file size is {0}",maxfilesexceeded:"Maximum files count exceeded"},it:{dropzonelabel:"Clicca o trascina i file qui",unaccepptablefiletype:"Solo i file di tipo {0} sono supportati",maxfilesizeexceeded:"La dimensione massima di un file è di {0}",maxtotalsizeexceeded:"La dimensione massima complessiva dei file è di {0}",maxfilesexceeded:"Numero massimo di file superato"},es:{dropzonelabel:"Haz clic o arrastra tus archivos aquí",unaccepptablefiletype:"Solo se admiten archivos de tipo {0}",maxfilesizeexceeded:"El tamaño máximo de archivo admitido es {0}",maxtotalsizeexceeded:"El tamaño total máximo admitido es {0}",maxfilesexceeded:"Se ha superado el número máximo de archivos"},fr:{dropzonelabel:"Cliquez ou déposez vos fichiers ici",unaccepptablefiletype:"Seuls les fichiers de type {0} sont pris en charge",maxfilesizeexceeded:"La taille maximale de fichier prise en charge est {0}",maxtotalsizeexceeded:"La taille totale maximale prise en charge est {0}",maxfilesexceeded:"Nombre maximal de fichiers dépassé"}};static observed=["value","readonly:presence","required:presence","accept:csv","multiple:presence","itemlist:presence","dropzone:presence","maxfiles:number","maxfilesize:number","maxtotalsize:number"];#n;#l;#o;#d;_type(){return"file"}static template='\n <div class="form-label">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class="input-group">\n <span data-tpl-if="slots.ibefore" class="input-group-text">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <input class="form-control" data-tpl-type="type" placeholder=" " form="">\n {{{{ slots.after }}}}\n <span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>\n </div>\n <div data-ref="dropzone" class="dropzone" data-tpl-if="slots.dropzone">\n {{{{ slots.dropzone }}}}\n </div>\n <div data-ref="dropzone" class="default-dropzone" data-tpl-if="!slots.dropzone">\n {{ #l10n:t(\'dropzonelabel\') }}\n </div>\n <ful-item-list></ful-item-list>\n <ful-field-warnings></ful-field-warnings>\n <ful-field-error></ful-field-error>\n ';static templates={items:'\n <ful-item data-tpl-each="files" data-tpl-var="file" data-tpl-data-name="file.name">\n <div>{{ file.name }}</div>\n <div>{{ #bytes:format(file.size) }}</div>\n <button type="button" class="btn btn-sm btn-outline-danger bi bi-x-lg" alt="Rimuovi"></button>\n </ful-item>\n ',warning:"<ful-field-warning>{{ #l10n:t(key, args) }}</ful-field-warning>"};render(e){const{observed:t}=e;super.render(e),this.#l=this.querySelector("ful-item-list"),this.#o=this.querySelector("[data-ref=dropzone]"),this.#d=this.querySelector("ful-field-warnings"),this.accept=t.accept,this.multiple=t.multiple,this.itemlist=t.itemlist,this.dropzone=t.dropzone,this.maxfiles=t.maxfiles,this.maxfilesize=t.maxfilesize,this.maxtotalsize=t.maxtotalsize,this.#d.addEventListener("animationend",e=>{e.target.remove()}),this.#l.addEventListener("click",e=>{if(!e.target.closest("button"))return;const t=e.target.closest("ful-item").dataset.name,s=new DataTransfer;[...this.files].filter(e=>e.name!==t).forEach(e=>s.items.add(e)),this.files=s.files,this.#u()}),this.#o.addEventListener("click",e=>{this.querySelector("input")?.click()}),this.#o.addEventListener("dragover",e=>{e.preventDefault()}),this.#o.addEventListener("drop",e=>{e.preventDefault();const t=new DataTransfer;[...e.dataTransfer.items].filter(e=>"file"===e.kind).forEach(e=>t.items.add(e.getAsFile())),this.files=t.files,this.#u()}),this._input.addEventListener("change",e=>{this.#u()})}#c(e){return e>1048576?Math.round(e/1024/1024*100)/100+"MiB":e>1024?Math.round(e/1024*100)/100+"KiB":`${e}B`}#u(){this.setCustomValidity(),this.#h(),this.#p(),this.#f(),this.#m(),this.template("items").withOverlay({files:this.files}).withModule("bytes",{format:this.#c}).renderTo(this.#l)}warning(e,t){this.template("warning").withOverlay({key:e,args:t}).renderTo(this.#d)}#h(){if(!this.#n.length)return;const e=[...this.files].filter(e=>!this.#n.some(t=>e.name.toLowerCase().endsWith(t.toLowerCase())));if(0===e.length)return;this.warning("unaccepptablefiletype",this.#n.join(", "));const t=new DataTransfer;[...this.files].filter(t=>!e.includes(t)).forEach(e=>t.items.add(e)),this.files=t.files}#m(){if(null===this.#b)return;if(this.files.length<=this.#b)return;this.warning("maxfilesexceeded");const e=new DataTransfer;this.files=e.files}#p(){if(null===this.#v)return;const e=[...this.files].filter(e=>e.size>this.#v);if(0===e.length)return;this.warning("maxfilesizeexceeded",this.#c(this.#v));const t=new DataTransfer;[...this.files].filter(t=>!e.includes(t)).forEach(e=>t.items.add(e)),this.files=t.files}#f(){if(null===this.#g)return;[...this.files].reduce((e,t)=>e+t.size,0)<=this.#g||(this.warning("maxtotalsizeexceeded",this.#c(this.#g)),this.files=(new DataTransfer).files)}get accept(){return this.#n}set accept(e){this._input.accept=e.join(","),this.#n=e,this.reflect(()=>{this.setAttribute("accept",this._input.accept)})}get multiple(){return this._input.multiple}set multiple(e){this._input.multiple=e,this.reflect(()=>{t.toggle(this,"multiple",e)})}get files(){return this._input.files}set files(e){this._input.files=e}get file(){return this.files[0]??null}set file(e){const t=new DataTransfer;e&&t.items.add(e),this.files=t.files}get value(){const e=Array.from(this._input.files).map(e=>e.name);return this.multiple?e:e[0]??null}set value(e){e||(this.files=(new DataTransfer).files,this.#u())}get totalsize(){return Array.from(this.files).reduce((e,t)=>e+t.size,0)}#b;get maxfiles(){return this.#b}set maxfiles(e){this.#b=e,this.reflect(()=>{t.set(this,"maxfiles",e)})}#v;get maxfilesize(){return this.#v}set maxfilesize(e){this.#v=e,this.reflect(()=>{t.set(this,"maxfilesize",e)})}#g;get maxtotalsize(){return this.#g}set maxtotalsize(e){this.#g=e,this.reflect(()=>{t.set(this,"maxtotalsize",e)})}#y;get itemlist(){return this.#y}set itemlist(e){this.#y=e,this.reflect(()=>{t.toggle(this,"itemlist",e)})}#E;get dropzone(){return this.#E}set dropzone(e){this.#E=e,this.reflect(()=>{t.toggle(this,"dropzone",e)})}}class z{#e;#t;#s;#r;#x;#w;#A;constructor({http:e,url:t,method:s,responseMapper:i,prefetch:r,revision:a}){this.#e=e,this.#t=t,this.#s=s,this.#r=i,this.#x=r,this.#w=a,this.#A=null}async prefetch(){this.#x&&await this.#q()}async exact(...e){return await this.#q(),this.#A.filter(([t,s])=>e.some(e=>e==t))}async load(e){return await this.#q(),this.#A.filter(([t,s])=>(s??"").toLowerCase().includes(e?.toLowerCase()))}async reconfigureUrl(e){this.#A=null,this.#t=e}async#q(){if(null!==this.#A)return;const e=await z.#S(this.#e,this.#s,this.#t,this.#w);this.#A=this.#r(e)}static async#S(e,t,s,i){const r=`${t}@${s}`;if(null!==i){const e=c.load(r,i);if(void 0!==e)return e}const a=await e.request(t,s).fetchJson();return null!==i&&c.save(r,i,a),a}}class L{#e;#t;#s;#r;constructor({http:e,url:t,method:s,responseMapper:i}){this.#e=e,this.#t=t,this.#s=s,this.#r=i}async exact(...e){const t=await this.#e.request(this.#s,this.#t).param("k",...e).fetchJson();return this.#r(t)}async load(e){const t=await this.#e.request(this.#s,this.#t).param("s",e).fetchJson();return this.#r(t)}}class O{#A;constructor(e){this.#A=e}update(e){this.#A=e}exact(...e){return this.#A.filter(([t,s])=>e.some(e=>e==t))}load(e){return this.#A.filter(([t,s])=>(s??"").toLowerCase().includes(e?.toLowerCase()))}}class k{static create(e,t){if(!e.hasAttribute("src")){const e=Array.from(t.options?.querySelectorAll("option")??[]).map(e=>[e.getAttribute("value")??e.innerText.trim(),e.innerText.trim()]);return new O(e)}const i=s.component("http-client"),r=k.#T(e);return"chunked"==e.getAttribute("mode")?new L({http:i,url:e.getAttribute("src"),method:e.getAttribute("method")??"POST",responseMapper:r}):new z({http:i,url:e.getAttribute("src"),method:e.getAttribute("method")??"POST",responseMapper:r,prefetch:e.hasAttribute("preload"),revision:e.getAttribute("revision")})}static#T(e){return e.hasAttribute("k-expr")&&e.hasAttribute("l-expr")?t=>s.evaluator().withOverlay(t).evaluateExpression(e.getAttribute("d-expr")??"self").map(t=>{const i=s.evaluator().withOverlay(t);return[i.evaluateExpression(e.getAttribute("k-expr")),i.evaluateExpression(e.getAttribute("l-expr")),i.evaluateExpression(e.getAttribute("m-expr")??"self")]}):e.hasAttribute("response-mapper")?s.component(e.getAttribute("response-mapper")):e=>e}}class C extends e{static slots=!0;static template='\n <ful-spinner class="centered" hidden></ful-spinner>\n <menu tabindex="-1" role="listbox" hidden></menu>\n ';static templates={options:'\n <li data-tpl-each="self" data-tpl-selected="index == 0" data-tpl-value="index" role="option" data-tpl-aria-selected="index == 0 ? \'true\' : \'false\'">\n {{ label }}\n </li>\n '};#z;#L;#O;#k=new Map;render({slots:e}){const t=this.template().render();this.#O=i.isBlank(e.default)?this.template("options"):r.fromFragment(e.default),this.#z=t.querySelector("ful-spinner"),this.#L=t.querySelector("menu"),this.#L.addEventListener("click",e=>{e.stopPropagation();const t=e.target.closest("li");t?this.#C(t):this.hide()}),this.replaceChildren(t)}acceptSelection(){const e=this.#L.querySelector("[selected]")??this.#L.firstElementChild;this.#C(e)}update(e){if(void 0===e)throw new Error("null data");this.#k=new Map(e.map((e,t)=>[String(t),e]));const t=e.map(([e,t,s],i)=>({index:i,key:e,label:t,metadata:s}));this.#O.withOverlay(t).renderTo(this.#L)}#C(e){const t=e.getAttribute("value"),s=this.#k.get(t);this.hide(),this.dispatchEvent(new CustomEvent("change",{bubbles:!0,cancelable:!1,detail:{index:t,data:s}}))}hide(){this.setAttribute("hidden","")}get shown(){return!this.hasAttribute("hidden")}async show(e){this.removeAttribute("hidden"),this.#L.setAttribute("hidden",""),this.#z.removeAttribute("hidden");try{const t=await e();this.update(t)}finally{this.#z.setAttribute("hidden",""),this.#L.removeAttribute("hidden")}}async moveOrShow(e,t){if(this.shown){const t=this.#L.querySelector("[selected]")??this.#L.firstElementChild,s=t[(e?"next":"previous")+"ElementSibling"];return void(s&&(t.removeAttribute("selected"),s.setAttribute("selected",""),s.scrollIntoView({block:"nearest",behavior:"smooth"})))}await this.show(t)}}class _ extends e{static observed=["value:csvm","readonly:presence","required:presence","itemlist:presence"];static slots=!0;static template='\n <div class="form-label">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class="input-group flex-nowrap" tabindex="-1">\n <span data-tpl-if="slots.ibefore" class="input-group-text">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <div class="ful-select-input-container">\n <div class="ful-select-input">\n <badges></badges>\n <input type="text" form="" role="combobox" aria-autocomplete="list" aria-haspopup="listbox" aria-expanded="false">\n </div>\n <ful-dropdown hidden popover="manual">{{{{ slots.dropdown }}}}</ful-dropdown>\n </div>\n {{{{ slots.after }}}}\n <span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>\n </div>\n <ful-item-list></ful-item-list>\n <ful-field-error></ful-field-error>\n ';static templates={items:'\n <ful-item data-tpl-each="entries" data-tpl-var="entry" data-tpl-data-key="entry[0]">\n <div>{{ entry[1][0] }}</div>\n <button type="button" class="btn btn-sm btn-outline-danger bi bi-x-lg"></button>\n </ful-item>\n '};static formAssociated=!0;internals;#_;#R;#I;#M;#l;#D;#N;#B=new Map;constructor(){super(),this.internals=this.attachInternals(),this.internals.role="presentation"}async render({slots:e,observed:i,disabled:r}){const a=this.getAttribute("name");this.#_=s.component(this.getAttribute("loader")??"loaders:select").create(this,{options:e.options}),this.#D=this.hasAttribute("multiple"),await(this.#_.prefetch?.());const n=this.template().withOverlay({slots:e,name:a}).render();this.#M=n.querySelector("input"),this.#l=n.querySelector("ful-item-list"),t.forward("input-",this,this.#M),this.#R=n.querySelector("badges"),this.value=i.value,this.disabled=r,this.readonly=i.readonly,this.required=i.required,this.itemlist=i.itemlist,this.#I=n.querySelector("ful-dropdown");const l=n.querySelector("label");l.addEventListener("click",()=>this.focus()),this.#N=n.querySelector("ful-field-error"),this.#M.ariaDescribedByElements=[this.#N],this.#M.ariaLabelledByElements=[l];const o=this,[d,u]=f.throttle(400,()=>{o.#M.setAttribute("aria-expanded","true"),o.#I.show(()=>o.#_.load(o.#M.value))});this.addEventListener("click",e=>{if(!e.target.matches("input")&&!this.disabled&&!this.readonly){if(this.#I.shown)return this.#M.setAttribute("aria-expanded","false"),void this.#I.hide();this.#M.focus(),d()}}),this.#l.addEventListener("click",e=>{if(e.stopPropagation(),!e.target.closest("button"))return;if(this.disabled||this.readonly)return;const t=[...this.#l.children].indexOf(e.target.closest("ful-item"));-1!==t&&(this.#B.delete(Array.from(this.#B.keys())[t]),this.#F(),this.#P())}),this.#R.addEventListener("click",e=>{if(e.stopPropagation(),this.disabled||this.readonly)return;const t=[...this.#R.children].indexOf(e.target);-1!==t&&(this.#B.delete(Array.from(this.#B.keys())[t]),this.#F(),this.#P())}),this.#M.addEventListener("change",e=>{e.stopPropagation()}),this.#M.addEventListener("blur",e=>{e.stopPropagation(),e.relatedTarget&&this.contains(e.relatedTarget)||(u(),this.#M.setAttribute("aria-expanded","false"),this.#I.hide(),this.#M.value="")}),this.#M.addEventListener("keydown",e=>{if(!this.disabled&&!this.readonly)switch(e.code){case"ArrowUp":e.preventDefault(),this.#M.setAttribute("aria-expanded","true"),this.#I.moveOrShow(!1,()=>o.#_.load(o.#M.value));break;case"ArrowDown":e.preventDefault(),this.#M.setAttribute("aria-expanded","true"),this.#I.moveOrShow(!0,()=>o.#_.load(o.#M.value));break;case"Escape":this.#M.setAttribute("aria-expanded","false"),this.#I.hide();break;case"Enter":e.preventDefault(),this.#M.setAttribute("aria-expanded","false"),this.#I.acceptSelection(),this.#M.value="";break;case"Backspace":this.#B.size&&0===this.#M.selectionStart&&0===this.#M.selectionEnd&&(this.#B.delete(Array.from(this.#B.keys()).pop()),this.#F(),this.#P());break;case"Tab":this.#M.setAttribute("aria-expanded","false"),this.#I.hide(),u()}}),this.#M.addEventListener("input",e=>{e.stopPropagation(),this.disabled||this.readonly||d()}),this.#I.addEventListener("change",e=>{e.stopPropagation(),this.#D||this.#B.clear(),this.#B.set(e.detail.data[0],e.detail.data.slice(1)),this.#F(),this.#P(),this.#M.focus(),this.#M.setAttribute("aria-expanded","false"),this.#I.hide(),this.#M.value=""}),this.replaceChildren(n)}async withLoader(e){return await e(this.#_)}#F(){const e=[...this.#B.entries()].map(e=>({key:e[0],label:e[1][0],metadata:e[1].slice(1)})),t=this.#D?e:e[0]??null;this.dispatchEvent(new CustomEvent("change",{bubbles:!0,cancelable:!1,detail:{value:t}}))}#P(){const e=Array.from(this.#B.entries()).map(([e,t])=>{const s=document.createElement("badge");return s.setAttribute("role","button"),s.setAttribute("value",e),s.innerText=t[0],s});this.#R.replaceChildren(),this.#R.append(...e),this.#l.replaceChildren(),this.template("items").withOverlay({entries:this.#B.entries()}).renderTo(this.#l)}set value(e){if(null===e)return this.#B=new Map,void this.#P();(async()=>{const t=await(this.#D?this.#_.exact(...e):this.#_.exact(e));this.#B=new Map(t.map(e=>[e[0],e.slice(1)])),this.#P()})()}get value(){return this.#D?[...this.#B.keys()]:[...this.#B.keys()][0]??null}get entry(){return this.#D?[...this.#B.entries()]:[...this.#B.entries()][0]??null}get disabled(){return this.#M.hasAttribute("disabled")}set disabled(e){t.toggle(this.#M,"disabled",e)}get readonly(){return this.#M.readOnly}set readonly(e){this.#M.readOnly=e,this.reflect(()=>{t.toggle(this,"readonly",e)})}get required(){return"true"===this.#M.getAttribute("aria-required")}set required(e){t.set(this.#M,"aria-required",e?"true":null),this.reflect(()=>{t.toggle(this,"required",e)})}#y;get itemlist(){return this.#y}set itemlist(e){this.#y=e,this.reflect(()=>{t.toggle(this,"itemlist",e)})}focus(e){this.#M.focus(e)}setCustomValidity(e){if(!e)return this.internals.setValidity({}),void(this.#N.innerText="");this.internals.setValidity({customError:!0}," "),this.#N.innerText=e}}class R extends e{static observed=["value","readonly:presence","required:presence"];static slots=!0;static template='\n <fieldset>\n <legend class="form-label">\n {{{{ slots.default }}}}\n </legend>\n <header data-tpl-if="slots.header">\n {{{{ slots.header }}}}\n </header>\n <section>\n <div class="label-wrapper" data-tpl-each="inputsAndLabels" data-tpl-var="ial">\n <label>\n {{{{ ial[0] }}}}\n <div>{{{{ ial[1] }}}}</div>\n </label>\n </div>\n </section>\n <ful-field-error></ful-field-error>\n <footer data-tpl-if="slots.footer">\n {{{{ slots.footer }}}}\n </footer>\n </fieldset>\n ';static formAssociated=!0;#H;#N;#$;#j;constructor(){super(),this.internals=this.attachInternals(),this.internals.role="radiogroup"}render({slots:e,observed:s,disabled:r}){const a=this.getAttribute("name")??t.uid("ful-radiogroup"),n=Array.from(e.default.querySelectorAll("ful-radio")),l=n.map(e=>{const s=document.createElement("input");s.setAttribute("type","radio"),t.forward("input-",this,s),t.forward("",e,s),s.setAttribute("name",`${a}-ignore`),s.setAttribute("form",""),s.addEventListener("change",e=>{e.stopPropagation(),this.dispatchEvent(new CustomEvent("change",{bubbles:!0,cancelable:!1,detail:{value:this.value}}))});return[s,i.fromChildNodes(e)]});n.forEach(e=>e.remove()),this.template().withOverlay({name:a,slots:e,inputsAndLabels:l}).renderTo(this),this.#H=this.firstElementChild,this.disabled=r,this.readonly=s.readonly,this.required=s.required,this.value=s.value,this.#N=this.querySelector("ful-field-error"),this.ariaDescribedByElements=[this.#N],this.#$=this.querySelector("input[type=radio]"),this.#j="boolean"===this.getAttribute("type")}get value(){const e=this.querySelector("input[type=radio]:checked");return e?this.#j?"true"===e.value:e.value:null}set value(e){if(null===e)return void this.querySelectorAll("input[type=radio]").forEach(e=>{e.checked=!1});const t=this.querySelector(`input[type=radio][value=${CSS.escape(String(e))}]`);t&&(t.checked=!0)}get readonly(){return this.#H.inert}set readonly(e){this.#H.inert=e,this.reflect(()=>{t.toggle(this,"readonly",e)})}get disabled(){return this.#H.hasAttribute("disabled")}set disabled(e){t.toggle(this.#H,"disabled",e)}get required(){return"true"===this.#H.getAttribute("aria-required")}set required(e){t.set(this.#H,"aria-required",e?"true":null),this.reflect(()=>{t.toggle(this,"required",e)})}focus(e){this.#$.focus(e)}setCustomValidity(e){if(!e)return this.internals.setValidity({}),void(this.#N.innerText="");this.internals.setValidity({customError:!0}," "),this.#N.innerText=e}}class I extends e{static observed=["value:bool","readonly:presence","required:presence"];static slots=!0;static template='\n <div data-tpl-class="klass">\n <div class="input-container">\n <input class="form-check-input" type="checkbox" data-tpl-role="isSwitch ? \'switch\' : false" form="" placeholder=" ">\n </div>\n <div class="form-check-label">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n </div>\n <ful-field-error></ful-field-error>\n ';#V;#M;#N;static formAssociated=!0;constructor(){super(),this.internals=this.attachInternals(),this.internals.role="presentation"}render({slots:e,observed:s,disabled:i}){const r="switch"==this.getAttribute("type"),a=r?"form-check form-switch":"form-check",n=this.template().withOverlay({slots:e,klass:a,isSwitch:r}).render();this.#V=n.firstElementChild,this.#M=n.querySelector("input"),t.forward("input-",this,this.#M),this.disabled=i,this.readonly=s.readonly,this.required=s.required,this.value=s.value,this.#M.addEventListener("change",e=>{e.stopPropagation(),this.dispatchEvent(new CustomEvent("change",{bubbles:!0,cancelable:!1,detail:{value:this.value}}))});const l=n.querySelector("label");l.addEventListener("click",()=>{this.focus(),this.disabled||this.readonly||(this.value=!this.value,this.dispatchEvent(new CustomEvent("change",{bubbles:!0,cancelable:!1,detail:{value:this.value}})))}),this.#N=n.querySelector("ful-field-error"),this.#M.ariaDescribedByElements=[this.#N],this.#M.ariaLabelledByElements=[l],this.replaceChildren(n)}get value(){return this.#M.checked}set value(e){this.#M.checked=e}get readonly(){return this.#V.inert}set readonly(e){this.#V.inert=e,this.reflect(()=>{t.toggle(this,"readonly",e)})}get disabled(){return this.#M.hasAttribute("disabled")}set disabled(e){t.toggle(this.#M,"disabled",e)}get required(){return"true"===this.#M.getAttribute("aria-required")}set required(e){t.set(this.#M,"aria-required",e?"true":null),this.reflect(()=>{t.toggle(this,"required",e)})}focus(e){this.#M.focus(e)}setCustomValidity(e){if(!e)return this.internals.setValidity({}),void(this.#N.innerText="");this.internals.setValidity({customError:!0}," "),this.#N.innerText=e}}class M extends e{static slots=!0;static template='\n <div class="ful-spinner-wrapper" role="status">\n <div class="ful-spinner-text">{{{{ slots.default }}}}</div>\n <div class="ful-spinner-icon"></div>\n </div>\n ';render({slots:e}){this.template().withOverlay({slots:e}).renderTo(this)}}class D extends e{static observed=["order"];#U;render(){const e=this.getAttribute("sorter"),t=["asc","desc",null];this.addEventListener("click",()=>{const s=t[(t.indexOf(this.order)+1)%3];this.dispatchEvent(new CustomEvent("sort-requested",{bubbles:!0,cancelable:!0,detail:{value:{sorter:e,order:s}}}))})}get order(){return this.#U||null}set order(e){this.#U=e||null,this.reflect(()=>{this.#U?this.setAttribute("order",e):this.removeAttribute("order")})}}class N extends e{static observed=["total:number","current:number"];static l10n={en:{showing:"Page {0} of {1}",navigation:"Page navigation",previous:"Previous",next:"Next"},it:{showing:"Pagina {0} di {1}",navigation:"Navigazione pagine",previous:"Precedente",next:"Successivo"},es:{showing:"Página {0} de {1}",navigation:"Navegación de páginas",previous:"Anterior",next:"Siguiente"},fr:{showing:"Page {0} sur {1}",navigation:"Navigation des pages",previous:"Précédent",next:"Suivant"}};static config={prevIcon:"bi bi-chevron-left",nextIcon:"bi bi-chevron-right",reloadIcon:"bi bi-arrow-clockwise"};static template='\n <nav data-tpl-aria-label="#l10n:t(\'navigation\')" class="user-select-none">\n <ul class="pagination">\n <li class="page-item ms-auto me-2 pagination-index"> {{ #l10n:t(\'showing\', curr.label, total) }}</li>\n <li class="page-item me-2 reload"><a role="button"><i data-tpl-class="config.reloadIcon"></i></a></li>\n <li class="page-item prev">\n <a data-tpl-class="prev.enabled?\'page-link\':\'page-link disabled\'" data-tpl-aria-label="#l10n:t(\'previous\')" role="button" data-tpl-data-page="prev.index">\n <i aria-hidden="true" data-tpl-class="config.prevIcon"></i>\n </a>\n </li>\n <li class="page-item" data-tpl-each="pages" data-tpl-var="page">\n <a data-tpl-class="curr.index != page.index ? \'page-link\': \'page-link disabled\'" role="button" data-tpl-data-page="page.index" >\n {{ page.label }}\n </a>\n </li>\n <li class="page-item next">\n <a data-tpl-class="next.enabled?\'page-link\':\'page-link disabled\'" data-tpl-aria-label="#l10n:t(\'next\')" role="button" data-tpl-data-page="next.index">\n <i aria-hidden="true" data-tpl-class="config.nextIcon"></i>\n </a>\n </li>\n </ul>\n </nav>\n ';#G=0;#W=0;render({observed:e}){this.update(e.current??0,e.total??0),this.addEventListener("click",e=>{const t=e.target.closest("a");t&&this.dispatchEvent(new CustomEvent("page-requested",{bubbles:!0,cancelable:!0,detail:{value:Number(t.dataset.page??this.#W)}}))})}update(e,t){const s=Number(this.getAttribute("pages")??"5"),i={index:Math.max(0,e-1),enabled:e>0},r={index:e,label:e+1},a={index:Math.min(t,e+1),enabled:e+1<t},n=[{index:e,label:e+1}];for(let i=e,r=1;r!==s&&n.length!=s;++r){const e=i-r;e>=0&&n.unshift({index:e,label:e+1});const s=i+r;s<t&&n.push({index:s,label:s+1})}this.template().withOverlay({total:t,prev:i,curr:r,next:a,pages:n}).renderTo(this)}get total(){return this.#G}set total(e){this.#G=e,this.reflect(()=>{this.setAttribute("total",String(e)),this.update(this.#W??0,this.#G)})}get current(){return this.#W}set current(e){this.#W=e,this.reflect(()=>{this.setAttribute("current",String(e)),this.update(this.#W,this.#G??0)})}}class B{static parse(e,t){const s=a.queryChildren(e,"schema");if(!s)throw new Error(`missing expected <schema> in ${e}`);const r=document.createElement("tr"),n=document.createElement("tr");n.setAttribute("data-tpl-each","rows");for(const e of s.getAttributeNames()){const t=s.getAttribute(e);r.setAttribute(e,t??""),n.setAttribute(e,t??"")}const l=a.queryChildrenAll(s,"column"),o=l.filter(e=>e.hasAttribute("order")).map(e=>({sorter:e.getAttribute("sorter"),order:e.getAttribute("order")}))[0]??null;for(var d of l){const e=a.queryChildren(d,"title"),t=d.getAttribute("sorter"),s=d.getAttribute("order"),i=e??document.createTextNode(d.getAttribute("title")??"");e?.remove(),d.removeAttribute("sorter"),d.removeAttribute("order"),d.removeAttribute("title");const l=t||s?(()=>{const e=document.createElement("ful-sorter");return t&&e.setAttribute("sorter",t),s&&e.setAttribute("order",s),e.append(i),e})():i,o=document.createElement("th"),u=document.createElement("td");for(const e of d.getAttributeNames()){const t=d.getAttribute(e);o.setAttribute(e,t??""),u.setAttribute(e,t??"")}o.append(l),u.append(...d.childNodes),r.append(o),n.append(u)}return{headersTemplate:t.withOverlay({inHeaders:!0,inRows:!1}).withFragment(i.from(r)),rowsTemplate:t.withOverlay({inHeaders:!1,inRows:!0}).withFragment(i.from(n)),sort:o,length:l.length}}}class F{#A;constructor(e){this.#A=e}async load(e,t,s){const i=e.page*e.size,r=i+e.size;return{data:this.#A.slice(i,r),size:this.#A.length}}update(e){this.#A=e}}class P{#e;#t;#s;constructor(e,t,s){this.#e=e,this.#t=t,this.#s=s}async load(e,t,s){const i=Object.entries(s).filter(([e,t])=>t);return await this.#e.request(this.#s,this.#t).param("page",e.page).param("size",e.size).param("sort",t?`${t.sorter},${t.order}`:null).param("filters",i.length>0?JSON.stringify(Object.fromEntries(i)):null).fetchJson()}}class H{static create(e,t){const i=e.getAttribute("src");if(i){const t=s.component("http-client"),r=e.getAttribute("method")??"GET";return new P(t,i,r)}return new F([])}}class $ extends e{static slots=!0;static l10n={en:{initial:"Start searching to see results.",error:"Error while loading data:",nodata:"No elements found."},it:{initial:"Avvia la ricerca per visualizzare i risultati.",error:"Errore nel caricamento dei dati:",nodata:"Nessun elemento trovato."},es:{initial:"Inicia la búsqueda para ver los resultados.",error:"Error al cargar los datos:",nodata:"No se encontraron elementos."},fr:{initial:"Lancez la recherche pour voir les résultats.",error:"Erreur lors du chargement des données :",nodata:"Aucun élément trouvé."}};static config={searchIcon:"bi bi-search"};static template='\n <ful-form data-tpl-if="slots.filters">\n {{{{ slots.filters }}}}\n </ful-form>\n <div class="table-wrapper">\n <table class="table">\n <caption data-tpl-if="slots.caption">{{{{ slots.caption }}}}</caption>\n <thead></thead>\n <tbody></tbody>\n <tbody data-ref="initial">\n <tr>\n <td data-tpl-colspan="schema.length">\n <div>\n <p data-tpl-if="config.searchIcon"><i data-tpl-class="config.searchIcon"></i></p>\n {{{ #l10n:t(\'initial\') }}}\n </div>\n </td>\n </tr>\n </tbody>\n <tbody data-ref="loading" hidden>\n <tr>\n <td data-tpl-colspan="schema.length">\n <ful-spinner class="big"></ful-spinner>\n </td>\n </tr>\n </tbody>\n <tbody data-ref="feedback" hidden>\n <tr>\n <td data-tpl-colspan="schema.length">\n <div class="alert alert-danger">\n <p>{{ #l10n:t(\'error\') }}</p>\n <div data-ref="feedback-error"></div>\n </div>\n </td>\n </tr>\n </tbody>\n <tfoot data-tpl-if="slots.footer">\n {{{{ slots.footer }}}}\n </tfoot>\n </table>\n </div>\n <ful-pagination current="0" total="1"></ful-pagination>\n ';static templates={row:'\n <tr data-tpl-if="pageResponse.data.length == 0">\n <td data-tpl-colspan="schema.length" class="text-center align-middle p-4">\n {{ #l10n:t(\'nodata\') }}\n </td>\n </tr>\n {{{{ schema.rowsTemplate.withOverlay({\'rows\': pageResponse.data}).render() }}}}\n '};#_;#J;#Q;#Y;#K;#X;#Z;#ee;#te;async render({slots:e,observed:i}){const r=this.template(),l=B.parse(e.schema,r),o=r.withOverlay({slots:e,schema:l}).render(),d=a.queryChildren(o,".table-wrapper").querySelector("table");t.forward("table-",this,d),this.#_=s.component(this.getAttribute("loader")??"loaders:table").create(this),this.#J=l,this.#Q=d.querySelector(":scope > tbody"),this.#Y=d.querySelector(":scope > tbody[data-ref=loading]"),this.#K=d.querySelector(":scope > tbody[data-ref=initial]"),this.#X=d.querySelector(":scope > tbody[data-ref=feedback]"),this.#Z=a.queryChildren(o,"ful-pagination"),this.#ee=d.querySelectorAll(":scope > thead ful-sorter")??[],this.replaceChildren(o),l.headersTemplate.renderTo(this.querySelector("thead")),await n.waitForChildren(this);const u=a.queryChildren(this,"ful-form");this.#te={pageRequest:{page:0,size:this.getAttribute("page-size")?Number(this.getAttribute("page-size")):10},sortRequest:l.sort,filterRequest:u?.values??{}},u?.addEventListener("submit:success",async e=>{await this.load({page:0,size:this.#te.pageRequest.size},this.#te.sortRequest,e.detail.request)}),this.addEventListener("page-requested",async e=>{await this.load({page:e.detail.value,size:this.#te.pageRequest.size},this.#te.sortRequest,this.#te.filterRequest)}),this.addEventListener("sort-requested",async e=>{const t=e.detail.value.order?e.detail.value:null;await this.load(this.#te.pageRequest,t,this.#te.filterRequest),this.#ee.forEach(e=>e.order=null),e.target.order=e.detail.value.order}),this.hasAttribute("autoload")&&await this.reload()}async reload(){return await this.load(this.#te.pageRequest,this.#te.sortRequest,this.#te.filterRequest)}async load(e,t,s){this.#Q.replaceChildren(),this.#Y.removeAttribute("hidden",""),this.#X.setAttribute("hidden",""),this.#K.setAttribute("hidden","");try{const i=await this.#_.load(e,t,s);this.#te={pageRequest:e,sortRequest:t,filterRequest:s},this.#u(e,t,s,i)}catch(e){throw this.#Y.setAttribute("hidden",""),this.#X.removeAttribute("hidden",""),e.problems?this.#X.querySelector("[data-ref=feedback-error]").textContent=e.problems.map(e=>`${e.reason}`):this.#X.querySelector("[data-ref=feedback-error]").textContent=e,e}}async withLoader(e){return await e(this.#_)}async resetWithFilter(e){return await this.load({page:0,size:this.#te.pageRequest.size},this.#te.sortRequest,e)}#u(e,t,s,i){this.#Y.setAttribute("hidden",""),this.#Q.replaceChildren(this.template("row").withOverlay({schema:this.#J,pageRequest:e,filterRequest:s,pageResponse:i}).render()),this.#Z.current=e.page,this.#Z.total=Math.ceil(i.size/e.size)}}class j extends E{static observed=["value:json","readonly:presence","required:presence"];static template='\n <div class="form-label">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class="input-group">\n <span data-tpl-if="slots.ibefore" class="input-group-text">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <button data-ref="operator" class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" value="LTE" form="">≼</button>\n <ul class="dropdown-menu">\n <li><a class="dropdown-item" role="button" value="EQ">=</a></li>\n <li><a class="dropdown-item" role="button" value="NEQ">≠</a></li>\n <li><a class="dropdown-item" role="button" value="LT">≺</a></li>\n <li><a class="dropdown-item" role="button" value="GT">≻</a></li>\n <li><a class="dropdown-item" role="button" value="LTE">≼</a></li>\n <li><a class="dropdown-item" role="button" value="GTE">≽</a></li>\n <li><a class="dropdown-item" role="button" value="BETWEEN">↔</a></li>\n </ul>\n <input data-ref="value1" type="datetime-local" class="form-control" form="">\n <input data-ref="value2" type="datetime-local" class="form-control" form="" hidden>\n {{{{ slots.after }}}}\n <span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>\n </div>\n <ful-field-error></ful-field-error>\n ';#se;#ie;#re;render(e){super.render({...e,skipObservedSetup:!0}),this.#se=this.querySelector("[data-ref=operator]"),this.#ie=this.querySelector("[data-ref=value1]"),this.#re=this.querySelector("[data-ref=value2]"),this.disabled=e.disabled,this.readonly=e.observed.readonly,this.required=e.observed.required,this.value=e.observed.value,this.addEventListener("click",e=>{const s=e.target;if(!s.matches("ul > li > a"))return;const i=s.closest("ul")?.previousElementSibling,r=s.getAttribute("value");t.toggle(this.#re,"hidden","BETWEEN"!==r),i.setAttribute("value",r),i.innerHTML=s.innerHTML})}get value(){const e=this.#se.getAttribute("value"),t="BETWEEN"===e?[this.#ie.value,this.#re.value]:[this.#ie.value];return t.some(e=>""===e)?void 0:[e,...t.map(e=>new Date(e).toISOString())]}set value(e){if(null==e)return this.#ie.value="",void(this.#re.value="");const[t,...s]=e;this.#se.setAttribute("value",t),this.#ie.value=s[0]?w.isoToLocal(s[0]):s[0],this.#re.value=s[1]?w.isoToLocal(s[1]):s[1]}set readonly(e){this.#re.readOnly=e,super.readonly=e}set disabled(e){t.toggle(this.#re,"disabled",e),super.disabled=e}}class V extends E{static observed=["value:json","readonly:presence","required:presence"];static template='\n <div class="form-label">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class="input-group">\n <span data-tpl-if="slots.ibefore" class="input-group-text">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <button data-ref="operator" class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" value="EQ" form="">=</button>\n <ul class="dropdown-menu">\n <li><a class="dropdown-item" role="button" value="EQ">=</a></li>\n <li><a class="dropdown-item" role="button" value="NEQ">≠</a></li>\n <li><a class="dropdown-item" role="button" value="LT">≺</a></li>\n <li><a class="dropdown-item" role="button" value="GT">≻</a></li>\n <li><a class="dropdown-item" role="button" value="LTE">≼</a></li>\n <li><a class="dropdown-item" role="button" value="GTE">≽</a></li>\n <li><a class="dropdown-item" role="button" value="BETWEEN">↔</a></li>\n </ul>\n <input data-ref="value1" type="date" class="form-control" form="">\n <input data-ref="value2" type="date" class="form-control" form="" hidden>\n {{{{ slots.after }}}}\n <span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>\n </div>\n <ful-field-error></ful-field-error>\n ';#se;#ie;#re;render(e){super.render({...e,skipObservedSetup:!0}),this.#se=this.querySelector("[data-ref=operator]"),this.#ie=this.querySelector("[data-ref=value1]"),this.#re=this.querySelector("[data-ref=value2]"),this.disabled=e.disabled,this.readonly=e.observed.readonly,this.required=e.observed.required,this.value=e.observed.value,this.addEventListener("click",e=>{const s=e.target;if(!s.matches("ul > li > a"))return;const i=s.closest("ul")?.previousElementSibling,r=s.getAttribute("value");t.toggle(this.#re,"hidden","BETWEEN"!==r),i.setAttribute("value",r),i.innerHTML=s.innerHTML})}get value(){const e=this.#se.getAttribute("value"),t="BETWEEN"==e?[this.#ie.value,this.#re.value]:[this.#ie.value];return t.some(e=>""===e)?void 0:[e,...t]}set value(e){if(null==e)return this.#ie.value="",void(this.#re.value="");const[t,...s]=e;this.#se.setAttribute("value",t),this.#ie.value=s[0],this.#re.value=s[1]}set readonly(e){this.#re.readOnly=e,super.readonly=e}set disabled(e){t.toggle(this.#re,"disabled",e),super.disabled=e}}class U extends E{static observed=["value:json","readonly:presence","required:presence"];static template='\n <div class="form-label">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class="input-group">\n <span data-tpl-if="slots.ibefore" class="input-group-text">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <button data-ref="operator" class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" value="CONTAINS" form="">…a…</button>\n <ul class="dropdown-menu">\n <li><a class="dropdown-item" role="button" value="CONTAINS">…a…</a></li>\n <li><a class="dropdown-item" role="button" value="STARTS_WITH">a…</a></li>\n <li><a class="dropdown-item" role="button" value="ENDS_WITH">…a</a></li>\n <li><a class="dropdown-item" role="button" value="EQ">=</a></li>\n </ul>\n <input data-ref="value" type="text" class="form-control" form="">\n {{{{ slots.after }}}}\n <span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>\n </div>\n <ful-field-error></ful-field-error>\n ';#se;#ae;render(e){super.render({...e,skipObservedSetup:!0}),this.#se=this.querySelector("[data-ref=operator]"),this.#ae=this.querySelector("[data-ref=value]"),this.disabled=e.disabled,this.readonly=e.observed.readonly,this.required=e.observed.required,this.value=e.observed.value,this.addEventListener("click",e=>{const t=e.target;if(!t.matches("ul > li > a"))return;const s=t.closest("ul")?.previousElementSibling,i=t.getAttribute("value");s.setAttribute("value",i),s.innerHTML=t.innerHTML})}get value(){const e=this.#se.getAttribute("value");return""===this.#ae.value?void 0:[e,"IGNORE_CASE",this.#ae.value]}set value(e){if(null==e)return void(this.#ae.value="");const[t,s,i]=e;this.#se.setAttribute("value",t),this.#ae.value=i}}class G{static t(e,...t){const s=this.l10n?.[this.language]?.[e]??this.l10n?.en?.[e]??e;return 0===t.length?s:s.replace(/{(\d+)}/g,(e,s)=>t[Number(s)])}static tl(e,t=[]){return G.t.apply(this,[e,...t])}}class W{configure(e){const t=o.builder().withCsrfToken().withRedirectOnUnauthorized("/").build();e.defineModule("l10n",G).defineComponent("http-client",t).defineElement("ful-spinner",M).defineElement("ful-form",y).defineElement("ful-checkbox",I).defineElement("ful-input",E).defineElement("ful-input-file",T).defineElement("ful-local-date",x).defineElement("ful-instant",w).defineElement("ful-input-local-date",A).defineElement("ful-input-local-time",q).defineElement("ful-input-instant",S).defineElement("ful-radio-group",R).defineElement("ful-table",$).defineElement("ful-pagination",N).defineElement("ful-sorter",D).defineElement("ful-filter-instant",j).defineElement("ful-filter-local-date",V).defineElement("ful-filter-text",U).defineElement("ful-select",_).defineElement("ful-dropdown",C).defineComponent("loaders:select",k).defineComponent("loaders:form",g).defineComponent("loaders:table",H).defineOverlay({language:navigator?.language?.split("-")?.[0]??"en"})}}export{p as AsyncEvents,m as Bindings,I as Checkbox,C as Dropdown,y as Form,g as FormLoader,E as Input,T as InputFile,S as InputInstant,A as InputLocalDate,q as InputLocalTime,w as Instant,j as InstantFilter,x as LocalDate,V as LocalDateFilter,d as LocalStorage,G as LocalizationModule,N as Pagination,W as Plugin,R as RadioGroup,_ as Select,k as SelectLoader,u as SessionStorage,D as SortButton,M as Spinner,$ as Table,B as TableSchemaParser,U as TextFilter,f as Timing,c as VersionedLocalStorage,h as VersionedSessionStorage};
|
|
2
|
+
//# sourceMappingURL=ful.min.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ful.min.mjs","sources":["../src/ful/storage.mjs","../src/ful/events/async.mjs","../src/ful/timing.mjs","../src/ful/elements/bindings.mjs","../src/ful/elements/form.mjs","../src/ful/elements/input.mjs","../src/ful/elements/temporals.mjs","../src/ful/elements/files.mjs","../src/ful/elements/select.mjs","../src/ful/elements/radio.mjs","../src/ful/elements/checkbox.mjs","../src/ful/elements/spinner.mjs","../src/ful/elements/table.mjs","../src/ful/elements/filters.mjs","../src/ful/elements/l10n.mjs","../src/ful/elements/plugin.mjs"],"sourcesContent":["class LocalStorage extends Storage {\n static save(k, v) {\n localStorage.setItem(k, JSON.stringify(v));\n }\n static load(k) {\n const got = localStorage.getItem(k);\n return got === null ? undefined : JSON.parse(got);\n }\n static remove(k) {\n localStorage.removeItem(k);\n }\n static pop(k) {\n const decoded = LocalStorage.load(k);\n LocalStorage.remove(k);\n return decoded;\n }\n}\n\nclass SessionStorage extends Storage {\n static save(k, v) {\n sessionStorage.setItem(k, JSON.stringify(v));\n }\n static load(k) {\n const got = sessionStorage.getItem(k);\n return got === null ? undefined : JSON.parse(got);\n }\n static remove(k) {\n sessionStorage.removeItem(k);\n }\n static pop(k) {\n const decoded = SessionStorage.load(k);\n SessionStorage.remove(k);\n return decoded;\n }\n}\n\nclass VersionedLocalStorage {\n static save(key, revision, data) {\n LocalStorage.save(key, { revision, data });\n }\n static load(key, revision) {\n const stored = LocalStorage.load(key);\n if (stored === undefined) {\n return undefined;\n }\n if (stored.revision !== revision) {\n localStorage.removeItem(key);\n return undefined;\n }\n return stored.data;\n }\n}\n\nclass VersionedSessionStorage {\n static save(key, revision, data) {\n SessionStorage.save(key, { revision, data });\n }\n static load(key, revision) {\n const stored = SessionStorage.load(key);\n if (stored === undefined) {\n return undefined;\n }\n if (stored.revision !== revision) {\n localStorage.removeItem(key);\n return undefined;\n }\n return stored.data;\n }\n}\n\nexport { LocalStorage, VersionedLocalStorage, SessionStorage, VersionedSessionStorage };\n","/**\n * @typedef {Object} AsyncExtension\n * @property {Promise<any>[]} promises\n * @typedef {Event & { async?: AsyncExtension }} AsyncEvent\n */\nclass AsyncEvents {\n /**\n * Dispatches an event and handles asynchronous resolution based on the execution mode.\n * @param {HTMLElement} el - The target element dispatching the event.\n * @param {AsyncEvent} evt - The event instance.\n * @param {{mode?: 'broadcast' | 'pipeline' | 'delegate'}} [options] - Configuration options (defaults to 'broadcast').\n * @returns {Promise<any>} Resolves with an array of values for broadcasts, a single value for pipelines/delegates, or undefined.\n */\n static async fireAsync(el, evt, options) {\n el.dispatchEvent(evt);\n const promises = evt.async?.promises ?? [];\n const mode = options?.mode ?? 'broadcast';\n if (mode === 'pipeline' && promises.length > 1) {\n throw new Error(\n `[AsyncEvents] Event \"${evt.type}\" is configured in 'pipeline' mode and expects at most one async listener, but ${promises.length} listeners were triggered on this element.`,\n );\n }\n if (mode === 'delegate' && promises.length !== 1) {\n throw new Error(\n `[AsyncEvents] Event \"${evt.type}\" is configured in 'delegate' mode and requires exactly one async listener, but ${promises.length} were registered.`,\n );\n }\n return mode === 'broadcast' ? Promise.all(promises) : Promise.resolve(promises[0]);\n }\n\n /**\n * Registers an asynchronous event listener wrapper.\n * @param {HTMLElement} el - The target element.\n * @param {string} type - The event name/type.\n * @param {Function} fn - The async listener middleware function returning the execution result.\n * @param {AddEventListenerOptions} [options] - Native addEventListener options.\n * @returns {EventListener} The underlying proxy listener function needed for cleanup via asyncOff.\n */\n static asyncOn(el, type, fn, options) {\n /** @type {(evt: Event) => Promise<void>} */\n const listener = async (event) => {\n const ae = /** @type {AsyncEvent} */ (event);\n if (!ae.async) {\n ae.async = { promises: [] };\n }\n const { promise, resolve, reject } = Promise.withResolvers();\n ae.async.promises.push(promise);\n try {\n resolve(await fn(ae));\n } catch (e) {\n reject(e);\n }\n };\n\n el.addEventListener(type, listener, options);\n return listener;\n }\n\n /**\n * Unregisters an asynchronous event listener proxy.\n * @param {HTMLElement} el - The target element.\n * @param {string} type - The event name/type.\n * @param {EventListener} listener - The proxy listener instance previously returned by asyncOn.\n * @param {EventListenerOptions} [options] - Native removeEventListener options.\n */\n static asyncOff(el, type, listener, options) {\n el.removeEventListener(type, listener, options);\n }\n\n /**\n * Mixes the asynchronous execution engine extensions into target class prototypes.\n * @param {...Function} classes - The target class constructors to decorate.\n */\n static mixInto(...classes) {\n for (const k of classes) {\n Object.assign(k.prototype, {\n /**\n * @this {HTMLElement}\n * @param {AsyncEvent} evt\n * @param {{mode?: 'broadcast' | 'pipeline' | 'delegate'}} [options]\n * @returns {Promise<any>}\n */\n async fireAsync(evt, options) {\n return await AsyncEvents.fireAsync(this, evt, options);\n },\n\n /**\n * @this {HTMLElement}\n * @param {string} type\n * @param {Function} fn\n * @param {AddEventListenerOptions} [options]\n * @returns {EventListener}\n */\n asyncOn(type, fn, options) {\n return AsyncEvents.asyncOn(this, type, fn, options);\n },\n\n /**\n * @this {HTMLElement}\n * @param {string} type\n * @param {EventListener} listener\n * @param {EventListenerOptions} [options]\n * @returns {void}\n */\n asyncOff(type, listener, options) {\n AsyncEvents.asyncOff(this, type, listener, options);\n },\n });\n }\n }\n}\n\nexport { AsyncEvents };\n","class Timing {\n static sleep(ms) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n static DEBOUNCE_DEFAULT = 0;\n static DEBOUNCE_IMMEDIATE = 1;\n /**\n * Executes only after a period of inactivity (pause in events).\n * Respond to the \"end\" of a series of events.\n * @param {*} timeoutMs\n * @param {*} func\n * @param {*} [options]\n * @returns {[function, function]}\n */\n static debounce(timeoutMs, func, options) {\n const opts = options ?? Timing.DEBOUNCE_DEFAULT;\n let tid = null;\n let args = [];\n let previousTimestamp = 0;\n\n const later = () => {\n const elapsed = performance.now() - previousTimestamp;\n if (timeoutMs > elapsed) {\n tid = setTimeout(later, timeoutMs - elapsed);\n return;\n }\n tid = null;\n if (opts !== Timing.DEBOUNCE_IMMEDIATE) {\n func(...args);\n }\n // This check is needed because `func` can recursively invoke `debounced`.\n if (tid === null) {\n args = [];\n }\n };\n\n const debounced = function () {\n args = [...arguments];\n previousTimestamp = performance.now();\n if (tid === null) {\n tid = setTimeout(later, timeoutMs);\n if (opts === Timing.DEBOUNCE_IMMEDIATE) {\n func(...args);\n }\n }\n };\n const abort = () => clearTimeout(tid);\n return [debounced, abort];\n }\n static THROTTLE_DEFAULT = 0;\n static THROTTLE_NO_LEADING = 1;\n static THROTTLE_NO_TRAILING = 2;\n /**\n * Executes at most once per specified time interval, regardless of ongoing events.\n * @param {*} timeoutMs\n * @param {*} func\n * @param {*} [options]\n * @returns {[function, function]}\n */\n static throttle(timeoutMs, func, options) {\n const opts = options ?? Timing.THROTTLE_DEFAULT;\n let tid = null;\n let args = [];\n let previousTimestamp = 0;\n\n const later = () => {\n previousTimestamp = opts & Timing.THROTTLE_NO_LEADING ? 0 : performance.now();\n tid = null;\n func(...args);\n if (tid === null) {\n args = [];\n }\n };\n const throttled = function () {\n const now = performance.now();\n if (!previousTimestamp && opts & Timing.THROTTLE_NO_LEADING) {\n previousTimestamp = now;\n }\n const remaining = previousTimestamp === 0 ? 0 : timeoutMs - (now - previousTimestamp);\n args = [...arguments];\n if (remaining <= 0 || remaining > timeoutMs) {\n if (tid !== null) {\n clearTimeout(tid);\n tid = null;\n }\n previousTimestamp = now;\n func(...args);\n if (tid === null) {\n args = [];\n }\n } else if (tid === null && !(opts & Timing.THROTTLE_NO_TRAILING)) {\n tid = setTimeout(later, remaining);\n }\n };\n const abort = () => clearTimeout(tid);\n return [throttled, abort];\n }\n}\n\nexport { Timing };\n","class Bindings {\n /**\n * @param {{ [x: string]: any; }} obj\n * @param {string} prefix\n * @param {Set<String>} stops\n * @return {{ [x: string]: any; }}\n */\n static flatten(obj, prefix, stops) {\n return Object.keys(obj).reduce((acc, k) => {\n const pre = prefix.length ? prefix + '.' + k : k;\n if (!stops.has(pre) && typeof obj[k] === 'object' && obj[k] !== null) {\n Object.assign(acc, Bindings.flatten(obj[k], pre, stops));\n } else {\n acc[pre] = obj[k];\n }\n return acc;\n }, {});\n }\n\n /**\n * @param {any} result\n * @param {string} path\n * @param {any} value\n */\n static providePath(result, path, value) {\n const keys = path.split('.').map((k) => (/^[0-9]+$/.test(k) ? +k : k));\n let current = result ?? {};\n let previous = null;\n for (let i = 0; ; ++i) {\n const ckey = keys[i];\n const pkey = keys[i - 1];\n if (Number.isInteger(ckey) && !Array.isArray(current)) {\n if (previous !== null) {\n previous[pkey] = current = [];\n } else {\n result = current = [];\n }\n }\n if (i === keys.length - 1) {\n //when value is undefined we only want to define the property if it's not defined\n current[ckey] = value !== undefined ? value : ckey in current ? current[ckey] : null;\n return result;\n }\n if (current[ckey] === undefined) {\n current[ckey] = {};\n }\n previous = current;\n current = current[ckey];\n }\n }\n /**\n *\n * @param {Element & {dataset?: any} & {checked?: boolean} & {value?: any}} el\n * @returns\n */\n static extract(el) {\n if (el.getAttribute('type') === 'radio') {\n if (!el.checked) {\n return undefined;\n }\n return el.dataset['fulBindType'] === 'boolean' ? el.value === 'true' : el.value;\n }\n if (el.getAttribute('type') === 'checkbox') {\n return el.checked;\n }\n if (el.dataset['fulBindType'] === 'boolean') {\n return !el.value ? null : el.value === 'true';\n }\n if (el.tagName === 'INPUT' || el.tagName === 'SELECT' || el.tagName === 'TEXTAREA') {\n return el.value === '' || el.value === undefined ? null : el.value;\n }\n return el.value;\n }\n\n /**\n *\n * @param {HTMLFormElement} form\n * @param {HTMLElement} [submitter]\n * @returns\n */\n static extractFrom(form, submitter) {\n let result = {};\n for (const el of form.elements) {\n // we are assuming submitters are disabled during submit.\n if (!el.hasAttribute('name') || (el.matches(':disabled') && el !== submitter)) {\n continue;\n }\n result = Bindings.providePath(\n result,\n /** @type {string} */ (el.getAttribute('name')),\n Bindings.extract(el),\n );\n }\n return result;\n }\n\n /**\n *\n * @param {Element & {checked?: boolean} & {value?: any}} el\n * @returns\n */\n static mutate(el, raw) {\n if (el.getAttribute('type') === 'radio') {\n el.checked = el.getAttribute('value') === raw;\n return;\n }\n if (el.getAttribute('type') === 'checkbox') {\n el.checked = raw;\n return;\n }\n el.value = raw;\n }\n\n static mutateIn(form, values) {\n const names = Array.from(form.elements)\n .map((el) => el.getAttribute('name'))\n .filter((n) => n);\n for (const [flattenedKey, value] of Object.entries(Bindings.flatten(values, '', new Set(names)))) {\n for (const el of form.querySelectorAll(`[name='${CSS.escape(flattenedKey)}']`)) {\n Bindings.mutate(el, value);\n }\n }\n }\n\n static errors(form, es, scrollOnError) {\n const fieldErrors = es.filter((e) => e.type === 'FIELD_ERROR' || e.type === 'INVALID_FORMAT');\n const globalErrors = es.filter((e) => e.type !== 'FIELD_ERROR' && e.type !== 'INVALID_FORMAT');\n form.querySelectorAll(`[name]`).forEach((el) => el.setCustomValidity?.(''));\n form.querySelectorAll('ful-errors').forEach((el) => {\n el.replaceChildren();\n el.setAttribute('hidden', '');\n });\n fieldErrors.forEach((e) => {\n const name = e.context.replace(/\\[/g, '.').replace(/\\]\\./g, '.').replace(/\\]/g, '')\n const parts = name.split('.');\n for (let i = parts.length; i != 0; --i) {\n const prefix = parts.slice(0, i).join('.');\n const suffix = parts.slice(i, parts.length).join('.');\n form.querySelectorAll(`[name='${CSS.escape(prefix)}']`).forEach((input) =>\n input.setCustomValidity?.(e.reason, suffix),\n );\n }\n });\n form.querySelectorAll('ful-errors').forEach((el) => {\n const hel = /** @type HTMLElement} */ (el);\n hel.innerText = globalErrors.map((e) => e.reason).join('\\n');\n if (globalErrors.length !== 0) {\n el.removeAttribute('hidden');\n }\n });\n if (es.length == 0 || !scrollOnError) {\n return;\n }\n Array.from(form.querySelectorAll(`:invalid`))\n .sort((a, b) => a.getBoundingClientRect().y - b.getBoundingClientRect().y)[0]\n ?.focus();\n }\n}\n\nexport { Bindings };\n","import { Attributes, ParsedElement, registry } from '../../ftl/index.mjs';\nimport { Failure } from '../../httpc/index.mjs';\nimport { Bindings } from './bindings.mjs';\nimport { AsyncEvents } from '../events/async.mjs';\n\nclass RemoteJsonFormLoader {\n #http;\n #url;\n #method;\n #requestMapper;\n #responseMapper;\n constructor(http, url, method, requestMapper, responseMapper) {\n this.#http = http;\n this.#url = url;\n this.#method = method;\n this.#requestMapper = requestMapper;\n this.#responseMapper = responseMapper;\n }\n prepare(values, form) {\n return this.#requestMapper(values, form);\n }\n async submit(values, form) {\n return await this.#http.request(this.#method, this.#url).json(values).fetch();\n }\n transform(response, form) {\n return this.#responseMapper(response, form);\n }\n}\n\nclass LocalFormLoader {\n #requestMapper;\n #responseMapper;\n constructor(requestMapper, responseMapper) {\n this.#requestMapper = requestMapper;\n this.#responseMapper = responseMapper;\n }\n async prepare(values, form) {\n return await this.#requestMapper(values, form);\n }\n async submit(values, form, response) {\n return response;\n }\n async transform(response, form) {\n return await this.#responseMapper(response, form);\n }\n}\n\nclass FormLoader {\n static create(el, conf) {\n const http = registry.component('http-client');\n const requestMapper = el.hasAttribute('request-mapper')\n ? registry.component(el.getAttribute('request-mapper'))\n : (v) => v;\n const responseMapper = el.hasAttribute('response-mapper')\n ? registry.component(el.getAttribute('response-mapper'))\n : (v) => v;\n const url = el.getAttribute('action');\n if (!url) {\n return new LocalFormLoader(requestMapper, responseMapper);\n }\n const method = el.getAttribute('method') ?? 'POST';\n return new RemoteJsonFormLoader(http, url, method, requestMapper, responseMapper);\n }\n}\n\nclass Form extends ParsedElement {\n form;\n render() {\n const form = (this.form = document.createElement('form'));\n form.setAttribute('novalidate', '');\n Attributes.forward('form-', this, form);\n form.replaceChildren(...this.childNodes);\n form.addEventListener('submit', async (e) => {\n e.preventDefault();\n e.stopPropagation();\n await this.submit(e.submitter ?? undefined);\n });\n if (this.hasAttribute('clear-invalid-on-change')) {\n this.addEventListener('change', (/** @type any */ evt) => {\n evt.target.setCustomValidity?.('');\n });\n }\n this.replaceChildren(form);\n }\n /**\n *\n * @param {HTMLElement} [submitter]\n * @returns\n */\n async submit(submitter) {\n this.spinner(true);\n try {\n const loader = registry.component(this.getAttribute('loader') ?? 'loaders:form').create(this);\n const values = Bindings.extractFrom(this.form, submitter);\n let request = await loader.prepare(values, this);\n try {\n const se = new CustomEvent('submit', {\n bubbles: true,\n cancelable: true,\n detail: { submitter, values, request },\n });\n if (!this.dispatchEvent(se)) {\n return;\n }\n this.errors = [];\n const sre = new CustomEvent('submit:requested', {\n bubbles: true,\n cancelable: false,\n detail: { submitter, values: se.detail.values, request: se.detail.request },\n });\n let response = await AsyncEvents.fireAsync(this, sre, { mode: 'pipeline' });\n request = sre.detail.request;\n\n response = await loader.submit(request, this, response);\n const mapped = await loader.transform(response, this);\n this.dispatchEvent(\n new CustomEvent('submit:success', {\n bubbles: true,\n cancelable: false,\n detail: { submitter, values, request, response: mapped },\n }),\n );\n } catch (e) {\n this.dispatchEvent(\n new CustomEvent('submit:failure', {\n bubbles: true,\n cancelable: false,\n detail: { submitter, values, request, exception: e },\n }),\n );\n if (e instanceof Failure) {\n this.errors = e.problems;\n }\n console.warn('failed to submit form', this, 'reason:', e);\n }\n } finally {\n this.spinner(false);\n }\n }\n reset() {\n this.form.reset();\n }\n spinner(spin) {\n this.querySelectorAll('ful-spinner').forEach((el) => {\n const hel = /** @type HTMLElement */ (el);\n hel.hidden = !spin;\n });\n this.querySelectorAll('input,button').forEach((el) => {\n const hel = /** @type HTMLButtonElement|HTMLInputElement */ (el);\n if (hel.type !== 'submit' && hel.type !== 'reset') {\n return;\n }\n if (spin) {\n hel.dataset.wd = String(hel.disabled);\n hel.disabled = true;\n } else {\n hel.disabled = hel.dataset.wd === 'true';\n delete hel.dataset.wd;\n }\n });\n }\n set values(vs) {\n Bindings.mutateIn(this.form, vs);\n }\n get values() {\n return Bindings.extractFrom(this.form);\n }\n set errors(es) {\n Bindings.errors(this.form, es, this.hasAttribute('scroll-on-error'));\n }\n}\n\nexport { FormLoader, Form };\n","import { Attributes, ParsedElement } from '../../ftl/index.mjs';\n\nclass Input extends ParsedElement {\n static observed = ['value', 'readonly:presence', 'required:presence'];\n static slots = true;\n static template = `\n <div class=\"form-label\">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class=\"input-group\">\n <span data-tpl-if=\"slots.ibefore\" class=\"input-group-text\">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <input data-tpl-if=\"type != 'textarea'\" class=\"form-control\" data-tpl-type=\"type\" placeholder=\" \" form=\"\">\n <textarea data-tpl-if=\"type == 'textarea'\" class=\"form-control\" placeholder=\" \" form=\"\"></textarea>\n {{{{ slots.after }}}}\n <span data-tpl-if=\"slots.iafter\" class=\"input-group-text\">{{{{ slots.iafter }}}}</span>\n </div>\n <ful-field-error></ful-field-error>\n `;\n static formAssociated = true;\n _input;\n _fieldError;\n constructor() {\n super();\n this.internals = this.attachInternals();\n this.internals.role = 'presentation';\n }\n _type() {\n return this.getAttribute('type') ?? 'text';\n }\n _fragment(type, slots) {\n return this.template().withOverlay({ type, slots }).render();\n }\n render({ slots, observed, disabled, skipObservedSetup }) {\n const type = this._type();\n const fragment = this._fragment(type, slots);\n this._input = fragment.querySelector('input,textarea');\n\n Attributes.forward('input-', this, this._input);\n if (!skipObservedSetup) {\n this.disabled = disabled;\n this.readonly = observed.readonly;\n this.required = observed.required;\n this.value = observed.value;\n }\n this._input.addEventListener('keydown', (evt) => {\n if (evt.key !== 'Enter' || this._type() === 'textarea') {\n return;\n }\n const form = this.internals.form;\n if (!form) {\n return;\n }\n const candidates = /** @type [HTMLButtonElement|HTMLInputElement] */ (\n Array.from(form.querySelectorAll('button:not(:disabled), input:not(:disabled)'))\n );\n const submitter = candidates.find((el) => el.type === 'submit');\n form.requestSubmit(submitter);\n });\n this._input.addEventListener('input', (evt) => {\n const re = this.getAttribute('mask');\n if (!re) {\n return;\n }\n const before = evt.target.value;\n const after = before.replace(new RegExp(re, 'g'), '');\n if (before === after) {\n return;\n }\n const start = evt.target.selectionStart;\n const offset = before.length - after.length;\n evt.target.value = after;\n evt.target.setSelectionRange(start - offset, start - offset);\n });\n this._input.addEventListener('change', (evt) => {\n evt.stopPropagation();\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n cancelable: false,\n detail: {\n value: this.value,\n },\n }),\n );\n });\n const label = fragment.querySelector('label');\n label.addEventListener('click', () => this.focus());\n this._fieldError = fragment.querySelector('ful-field-error');\n this._input.ariaDescribedByElements = [this._fieldError];\n this._input.ariaLabelledByElements = [label];\n this.replaceChildren(fragment);\n }\n get value() {\n const uppercase = this.hasAttribute('uppercase');\n const trim = this.hasAttribute('trim');\n const v = this._input.value;\n const uppercased = uppercase ? v.toUpperCase() : v;\n const trimmed = trim ? uppercased.trim() : uppercased;\n return trimmed === '' ? null : trimmed;\n }\n set value(value) {\n this._input.value = value === '' ? null : value;\n }\n get readonly() {\n return this._input.readOnly;\n }\n set readonly(v) {\n this._input.readOnly = v;\n this.reflect(() => {\n Attributes.toggle(this, 'readonly', v);\n });\n }\n get disabled() {\n return this._input.hasAttribute('disabled');\n }\n set disabled(d) {\n Attributes.toggle(this._input, 'disabled', d);\n }\n get required() {\n return this._input.getAttribute('aria-required') === 'true';\n }\n set required(d) {\n Attributes.set(this._input, 'aria-required', d ? 'true' : null);\n this.reflect(() => {\n Attributes.toggle(this, 'required', d);\n });\n }\n focus(options) {\n this._input.focus(options);\n }\n setCustomValidity(error) {\n if (!error) {\n this.internals.setValidity({});\n this._fieldError.innerText = '';\n return;\n }\n this.internals.setValidity({ customError: true }, ' ');\n this._fieldError.innerText = error;\n }\n formResetCallback() {\n this.value = this.unmarshal('value', this.getAttribute('value'));\n }\n}\n\nexport { Input };\n","import { ParsedElement } from '../../ftl/index.mjs';\nimport { Input } from './input.mjs';\n\nclass LocalDate extends ParsedElement {\n render() {\n const content = this.innerHTML.trim();\n if (content === '') {\n this.innerHTML = this.getAttribute('default') ?? '';\n return;\n }\n const locale = this.getAttribute('locale') ?? Intl.DateTimeFormat().resolvedOptions().locale;\n const formatter = new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'numeric', day: 'numeric' });\n const [y, m, d] = content.split('-').map(Number);\n this.innerHTML = formatter.format(new Date(y, m - 1, d));\n }\n}\n\nclass Instant extends ParsedElement {\n render() {\n const content = this.innerHTML.trim();\n if (content === '') {\n this.innerHTML = this.getAttribute('default') ?? '';\n return;\n }\n const locale = this.getAttribute('locale') ?? Intl.DateTimeFormat().resolvedOptions().locale;\n const format = new Intl.DateTimeFormat(locale, {\n year: 'numeric',\n month: 'numeric',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n second: 'numeric',\n hour12: false,\n });\n this.innerHTML = format.format(new Date(Instant.isoToLocal(content)));\n }\n static isoToLocal(iso) {\n //this is so sad\n const d = new Date(iso);\n const pad = (n, v) => String(v).padStart(n, '0');\n const date = `${d.getFullYear()}-${pad(2, d.getMonth() + 1)}-${pad(2, d.getDate())}`;\n const time = `${pad(2, d.getHours())}:${pad(2, d.getMinutes())}:${pad(2, d.getSeconds())}.${pad(3, d.getMilliseconds())}`;\n return `${date}T${time}`;\n }\n}\n\nclass InputLocalDate extends Input {\n static observed = ['value', 'readonly:presence', 'required:presence', 'min', 'max', 'step'];\n _type() {\n return 'date';\n }\n render(conf) {\n const { observed } = conf;\n super.render(conf);\n this.min = observed.min;\n this.max = observed.max;\n this.step = observed.step;\n }\n get min() {\n const v = this._input.min;\n return v === '' ? null : v;\n }\n set min(v) {\n this._input.min = InputLocalDate.#fromIsoOrOffset(v);\n }\n get max() {\n const v = this._input.max;\n return v === '' ? null : v;\n }\n set max(v) {\n this._input.max = InputLocalDate.#fromIsoOrOffset(v);\n }\n get step() {\n const v = this._input.step;\n return v === '' ? null : v;\n }\n set step(v) {\n this._input.step = v ?? '';\n }\n static #fromIsoOrOffset(v) {\n if (!v) {\n return '';\n }\n //this could be date.toLocaleDateString('en-CA')\n const formatLocalDate = (date) =>\n new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString().split('T')[0];\n if (v === 'now') {\n return formatLocalDate(new Date());\n }\n const re = /^([+-])(\\d+)([dmy])$/;\n const match = re.exec(v);\n if (!match) {\n return v;\n }\n const sign = match[1] === '-' ? -1 : 1;\n const offset = +match[2];\n const r = new Date();\n r.setHours(0, 0, 0, 0);\n switch (match[3]) {\n case 'd':\n r.setDate(r.getDate() + offset * sign);\n break;\n case 'm':\n const originalDay = r.getDate();\n r.setMonth(r.getMonth() + offset * sign);\n if (r.getDate() !== originalDay) {\n r.setDate(0);\n }\n break;\n case 'y':\n r.setFullYear(r.getFullYear() + offset * sign);\n break;\n }\n return formatLocalDate(r);\n }\n}\n\nclass InputLocalTime extends InputLocalDate {\n _type() {\n return 'time';\n }\n}\n\nclass InputInstant extends Input {\n static observed = ['value', 'readonly:presence', 'required:presence', 'min', 'max', 'step'];\n _type() {\n return 'datetime-local';\n }\n render(conf) {\n const { observed } = conf;\n super.render(conf);\n this.min = observed.min;\n this.max = observed.max;\n this.step = observed.step;\n }\n get value() {\n const v = this._input.value;\n return v === '' ? null : new Date(v).toISOString();\n }\n set value(v) {\n this._input.value = v ? Instant.isoToLocal(v) : '';\n }\n get min() {\n const v = this._input.min;\n return v === '' ? null : new Date(v).toISOString();\n }\n set min(v) {\n this._input.min = v ? Instant.isoToLocal(v) : '';\n }\n get max() {\n const v = this._input.max;\n return v === '' ? null : new Date(v).toISOString();\n }\n set max(v) {\n this._input.max = v ? Instant.isoToLocal(v) : '';\n }\n get step() {\n const v = this._input.step;\n return v === '' ? null : v;\n }\n set step(v) {\n this._input.step = v ?? '';\n }\n}\n\nexport { Instant, LocalDate, InputLocalDate, InputLocalTime, InputInstant };\n","import { Attributes } from '../../ftl/index.mjs';\nimport { Input } from './input.mjs';\n\nclass InputFile extends Input {\n static l10n = {\n en: {\n dropzonelabel: 'Click or drop your files here',\n unaccepptablefiletype: 'Only files of type {0} are supported',\n maxfilesizeexceeded: 'Maximum supported file size is {0}',\n maxtotalsizeexceeded: 'Maximum supported total file size is {0}',\n maxfilesexceeded: 'Maximum files count exceeded',\n },\n it: {\n dropzonelabel: 'Clicca o trascina i file qui',\n unaccepptablefiletype: 'Solo i file di tipo {0} sono supportati',\n maxfilesizeexceeded: 'La dimensione massima di un file è di {0}',\n maxtotalsizeexceeded: 'La dimensione massima complessiva dei file è di {0}',\n maxfilesexceeded: 'Numero massimo di file superato',\n },\n es: {\n dropzonelabel: 'Haz clic o arrastra tus archivos aquí',\n unaccepptablefiletype: 'Solo se admiten archivos de tipo {0}',\n maxfilesizeexceeded: 'El tamaño máximo de archivo admitido es {0}',\n maxtotalsizeexceeded: 'El tamaño total máximo admitido es {0}',\n maxfilesexceeded: 'Se ha superado el número máximo de archivos',\n },\n fr: {\n dropzonelabel: 'Cliquez ou déposez vos fichiers ici',\n unaccepptablefiletype: 'Seuls les fichiers de type {0} sont pris en charge',\n maxfilesizeexceeded: 'La taille maximale de fichier prise en charge est {0}',\n maxtotalsizeexceeded: 'La taille totale maximale prise en charge est {0}',\n maxfilesexceeded: 'Nombre maximal de fichiers dépassé',\n },\n };\n static observed = [\n 'value',\n 'readonly:presence',\n 'required:presence',\n 'accept:csv',\n 'multiple:presence',\n 'itemlist:presence',\n 'dropzone:presence',\n 'maxfiles:number',\n 'maxfilesize:number',\n 'maxtotalsize:number',\n ];\n #accept;\n #items;\n #dropzone;\n #warnings;\n _type() {\n return 'file';\n }\n static template = `\n <div class=\"form-label\">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class=\"input-group\">\n <span data-tpl-if=\"slots.ibefore\" class=\"input-group-text\">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <input class=\"form-control\" data-tpl-type=\"type\" placeholder=\" \" form=\"\">\n {{{{ slots.after }}}}\n <span data-tpl-if=\"slots.iafter\" class=\"input-group-text\">{{{{ slots.iafter }}}}</span>\n </div>\n <div data-ref=\"dropzone\" class=\"dropzone\" data-tpl-if=\"slots.dropzone\">\n {{{{ slots.dropzone }}}}\n </div>\n <div data-ref=\"dropzone\" class=\"default-dropzone\" data-tpl-if=\"!slots.dropzone\">\n {{ #l10n:t('dropzonelabel') }}\n </div>\n <ful-item-list></ful-item-list>\n <ful-field-warnings></ful-field-warnings>\n <ful-field-error></ful-field-error>\n `;\n static templates = {\n items: `\n <ful-item data-tpl-each=\"files\" data-tpl-var=\"file\" data-tpl-data-name=\"file.name\">\n <div>{{ file.name }}</div>\n <div>{{ #bytes:format(file.size) }}</div>\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger bi bi-x-lg\" alt=\"Rimuovi\"></button>\n </ful-item>\n `,\n warning: `<ful-field-warning>{{ #l10n:t(key, args) }}</ful-field-warning>`,\n };\n render(conf) {\n const { observed } = conf;\n super.render(conf);\n this.#items = this.querySelector('ful-item-list');\n this.#dropzone = this.querySelector('[data-ref=dropzone]');\n this.#warnings = this.querySelector('ful-field-warnings');\n this.accept = observed.accept;\n this.multiple = observed.multiple;\n this.itemlist = observed.itemlist;\n this.dropzone = observed.dropzone;\n this.maxfiles = observed.maxfiles;\n this.maxfilesize = observed.maxfilesize;\n this.maxtotalsize = observed.maxtotalsize;\n this.#warnings.addEventListener('animationend', (e) => {\n e.target.remove();\n });\n this.#items.addEventListener('click', (e) => {\n if (!e.target.closest('button')) {\n return;\n }\n const fileName = e.target.closest('ful-item').dataset.name;\n const dt = new DataTransfer();\n [...this.files].filter((f) => f.name !== fileName).forEach((f) => dt.items.add(f));\n this.files = dt.files;\n this.#update();\n });\n this.#dropzone.addEventListener('click', (e) => {\n this.querySelector('input')?.click();\n });\n\n this.#dropzone.addEventListener('dragover', (e) => {\n e.preventDefault();\n });\n this.#dropzone.addEventListener('drop', (e) => {\n e.preventDefault();\n const dt = new DataTransfer();\n [...e.dataTransfer.items].filter((i) => i.kind === 'file').forEach((i) => dt.items.add(i.getAsFile()));\n this.files = dt.files;\n this.#update();\n });\n this._input.addEventListener('change', (e) => {\n this.#update();\n });\n }\n #formatByteSize(v) {\n return v > 1024 * 1024\n ? `${Math.round((v / 1024 / 1024) * 100) / 100}MiB`\n : v > 1024\n ? `${Math.round((v / 1024) * 100) / 100}KiB`\n : `${v}B`;\n }\n #update() {\n this.setCustomValidity();\n this.#ensureAcceptable();\n this.#ensureFileSizes();\n this.#ensureTotalSize();\n this.#ensureFilesCount();\n this.template('items')\n .withOverlay({ files: this.files })\n .withModule('bytes', { format: this.#formatByteSize })\n .renderTo(this.#items);\n }\n warning(key, args) {\n this.template('warning').withOverlay({ key, args }).renderTo(this.#warnings);\n }\n #ensureAcceptable() {\n if (!this.#accept.length) {\n return;\n }\n const unacceptable = [...this.files].filter(\n (file) => !this.#accept.some((type) => file.name.toLowerCase().endsWith(type.toLowerCase())),\n );\n\n if (unacceptable.length === 0) {\n return;\n }\n this.warning('unaccepptablefiletype', this.#accept.join(', '));\n const dt = new DataTransfer();\n [...this.files].filter((f) => !unacceptable.includes(f)).forEach((f) => dt.items.add(f));\n this.files = dt.files;\n }\n #ensureFilesCount() {\n if (this.#maxfiles === null) {\n return;\n }\n if (this.files.length <= this.#maxfiles) {\n return;\n }\n this.warning('maxfilesexceeded');\n const dt = new DataTransfer();\n this.files = dt.files;\n }\n\n #ensureFileSizes() {\n if (this.#maxfilesize === null) {\n return;\n }\n const oversized = [...this.files].filter((file) => file.size > this.#maxfilesize);\n if (oversized.length === 0) {\n return;\n }\n this.warning('maxfilesizeexceeded', this.#formatByteSize(this.#maxfilesize));\n const dt = new DataTransfer();\n [...this.files].filter((f) => !oversized.includes(f)).forEach((f) => dt.items.add(f));\n this.files = dt.files;\n }\n #ensureTotalSize() {\n if (this.#maxtotalsize === null) {\n return;\n }\n const totalSize = [...this.files].reduce((acc, file) => acc + file.size, 0);\n if (totalSize <= this.#maxtotalsize) {\n return;\n }\n this.warning('maxtotalsizeexceeded', this.#formatByteSize(this.#maxtotalsize));\n this.files = new DataTransfer().files;\n }\n get accept() {\n return this.#accept;\n }\n set accept(vs) {\n this._input.accept = vs.join(',');\n this.#accept = vs;\n this.reflect(() => {\n this.setAttribute('accept', this._input.accept);\n });\n }\n get multiple() {\n return this._input.multiple;\n }\n set multiple(v) {\n this._input.multiple = v;\n this.reflect(() => {\n Attributes.toggle(this, 'multiple', v);\n });\n }\n get files() {\n return this._input.files;\n }\n set files(vs) {\n this._input.files = vs;\n }\n get file() {\n return this.files[0] ?? null;\n }\n set file(v) {\n const dt = new DataTransfer();\n if (v) {\n dt.items.add(v);\n }\n this.files = dt.files;\n }\n get value() {\n const names = Array.from(this._input.files).map((f) => f.name);\n return this.multiple ? names : (names[0] ?? null);\n }\n set value(v) {\n if (v) {\n return;\n }\n this.files = new DataTransfer().files;\n this.#update();\n }\n get totalsize() {\n return Array.from(this.files).reduce((a, f) => a + f.size, 0);\n }\n #maxfiles;\n get maxfiles() {\n return this.#maxfiles;\n }\n set maxfiles(v) {\n this.#maxfiles = v;\n this.reflect(() => {\n Attributes.set(this, 'maxfiles', v);\n });\n }\n #maxfilesize;\n get maxfilesize() {\n return this.#maxfilesize;\n }\n set maxfilesize(v) {\n this.#maxfilesize = v;\n this.reflect(() => {\n Attributes.set(this, 'maxfilesize', v);\n });\n }\n #maxtotalsize;\n get maxtotalsize() {\n return this.#maxtotalsize;\n }\n set maxtotalsize(v) {\n this.#maxtotalsize = v;\n this.reflect(() => {\n Attributes.set(this, 'maxtotalsize', v);\n });\n }\n #useItemlist;\n get itemlist() {\n return this.#useItemlist;\n }\n set itemlist(v) {\n this.#useItemlist = v;\n this.reflect(() => {\n Attributes.toggle(this, 'itemlist', v);\n });\n }\n #useDropzone;\n get dropzone() {\n return this.#useDropzone;\n }\n set dropzone(v) {\n this.#useDropzone = v;\n this.reflect(() => {\n Attributes.toggle(this, 'dropzone', v);\n });\n }\n}\n\nexport { InputFile };\n","import { Attributes, Fragments, ParsedElement, registry, Templates } from '../../ftl/index.mjs';\nimport { VersionedLocalStorage } from '../storage.mjs';\nimport { Timing } from '../timing.mjs';\n\nclass RemoteLoader {\n #http;\n #url;\n #method;\n #responseMapper;\n #prefetch;\n #revision;\n #data;\n constructor({ http, url, method, responseMapper, prefetch, revision }) {\n this.#http = http;\n this.#url = url;\n this.#method = method;\n this.#responseMapper = responseMapper;\n this.#prefetch = prefetch;\n this.#revision = revision;\n this.#data = null;\n }\n async prefetch() {\n if (!this.#prefetch) {\n return;\n }\n await this.#ensureFetched();\n }\n async exact(...keys) {\n await this.#ensureFetched();\n return this.#data.filter(([k, v]) => keys.some((r) => r == k));\n }\n async load(needle) {\n await this.#ensureFetched();\n return this.#data.filter(([k, v]) => (v ?? '').toLowerCase().includes(needle?.toLowerCase()));\n }\n async reconfigureUrl(url) {\n this.#data = null;\n this.#url = url;\n }\n async #ensureFetched() {\n if (this.#data !== null) {\n return;\n }\n const raw = await RemoteLoader.#revisionedData(this.#http, this.#method, this.#url, this.#revision);\n this.#data = this.#responseMapper(raw);\n }\n static async #revisionedData(http, method, url, revision) {\n const storageKey = `${method}@${url}`;\n if (revision !== null) {\n const data = VersionedLocalStorage.load(storageKey, revision);\n if (data !== undefined) {\n return data;\n }\n }\n const data = await http.request(method, url).fetchJson();\n if (revision !== null) {\n VersionedLocalStorage.save(storageKey, revision, data);\n }\n return data;\n }\n}\n\nclass PartialRemoteLoader {\n #http;\n #url;\n #method;\n #responseMapper;\n constructor({ http, url, method, responseMapper }) {\n this.#http = http;\n this.#url = url;\n this.#method = method;\n this.#responseMapper = responseMapper;\n }\n async exact(...keys) {\n const response = await this.#http\n .request(this.#method, this.#url)\n .param('k', ...keys)\n .fetchJson();\n return this.#responseMapper(response);\n }\n async load(needle) {\n const response = await this.#http.request(this.#method, this.#url).param('s', needle).fetchJson();\n return this.#responseMapper(response);\n }\n}\n\nclass InMemoryLoader {\n #data;\n constructor(data) {\n this.#data = data;\n }\n update(data) {\n this.#data = data;\n }\n exact(...keys) {\n return this.#data.filter(([k, v]) => keys.some((r) => r == k));\n }\n load(needle) {\n return this.#data.filter(([k, v]) => (v ?? '').toLowerCase().includes(needle?.toLowerCase()));\n }\n}\n\nclass SelectLoader {\n static create(el, conf) {\n if (!el.hasAttribute('src')) {\n const els = Array.from(conf.options?.querySelectorAll('option') ?? []);\n const data = els.map((e) => {\n return [e.getAttribute('value') ?? e.innerText.trim(), e.innerText.trim()];\n });\n return new InMemoryLoader(data);\n }\n const http = registry.component('http-client');\n const responseMapper = SelectLoader.#responseMapperFrom(el);\n\n if ('chunked' == el.getAttribute('mode')) {\n return new PartialRemoteLoader({\n http,\n url: el.getAttribute('src'),\n method: el.getAttribute('method') ?? 'POST',\n responseMapper,\n });\n }\n return new RemoteLoader({\n http,\n url: el.getAttribute('src'),\n method: el.getAttribute('method') ?? 'POST',\n responseMapper,\n prefetch: el.hasAttribute('preload'),\n revision: el.getAttribute('revision'),\n });\n }\n static #responseMapperFrom(el) {\n if (el.hasAttribute('k-expr') && el.hasAttribute('l-expr')) {\n return (response) => {\n const rows = registry\n .evaluator()\n .withOverlay(response)\n .evaluateExpression(el.getAttribute('d-expr') ?? 'self');\n return rows.map((row) => {\n const evaluator = registry.evaluator().withOverlay(row);\n return [\n evaluator.evaluateExpression(el.getAttribute('k-expr')),\n evaluator.evaluateExpression(el.getAttribute('l-expr')),\n evaluator.evaluateExpression(el.getAttribute('m-expr') ?? 'self'),\n ];\n });\n };\n }\n if (el.hasAttribute('response-mapper')) {\n return registry.component(el.getAttribute('response-mapper'));\n }\n return (response) => response;\n }\n}\n\nclass Dropdown extends ParsedElement {\n static slots = true;\n static template = `\n <ful-spinner class=\"centered\" hidden></ful-spinner>\n <menu tabindex=\"-1\" role=\"listbox\" hidden></menu>\n `;\n static templates = {\n options: `\n <li data-tpl-each=\"self\" data-tpl-selected=\"index == 0\" data-tpl-value=\"index\" role=\"option\" data-tpl-aria-selected=\"index == 0 ? 'true' : 'false'\">\n {{ label }}\n </li>\n `,\n };\n #spinner;\n #menu;\n #optionstemplate;\n #options = new Map();\n render({ slots }) {\n const fragment = this.template().render();\n this.#optionstemplate = Fragments.isBlank(slots.default)\n ? this.template('options')\n : Templates.fromFragment(slots.default);\n this.#spinner = fragment.querySelector('ful-spinner');\n this.#menu = fragment.querySelector('menu');\n this.#menu.addEventListener('click', (evt) => {\n evt.stopPropagation();\n const li = evt.target.closest('li');\n if (!li) {\n this.hide();\n return;\n }\n this.#change(li);\n });\n this.replaceChildren(fragment);\n }\n acceptSelection() {\n const selected = this.#menu.querySelector('[selected]') ?? this.#menu.firstElementChild;\n this.#change(selected);\n }\n update(values) {\n if (values === undefined) {\n throw new Error('null data');\n }\n this.#options = new Map(values.map((v, i) => [String(i), v]));\n const data = values.map(([key, label, metadata], index) => ({ index, key, label, metadata }));\n this.#optionstemplate.withOverlay(data).renderTo(this.#menu);\n }\n #change(target) {\n const index = target.getAttribute('value');\n const data = this.#options.get(index);\n this.hide();\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n cancelable: false,\n detail: { index, data },\n }),\n );\n }\n hide() {\n this.setAttribute('hidden', '');\n }\n get shown() {\n return !this.hasAttribute('hidden');\n }\n async show(loader) {\n this.removeAttribute('hidden');\n this.#menu.setAttribute('hidden', '');\n this.#spinner.removeAttribute('hidden');\n try {\n const data = await loader();\n this.update(data);\n } finally {\n this.#spinner.setAttribute('hidden', '');\n this.#menu.removeAttribute('hidden');\n }\n }\n async moveOrShow(forward, loader) {\n if (this.shown) {\n const selected = this.#menu.querySelector('[selected]') ?? this.#menu.firstElementChild;\n const candidate = selected[`${forward ? 'next' : 'previous'}ElementSibling`];\n if (candidate) {\n selected.removeAttribute('selected');\n candidate.setAttribute('selected', '');\n candidate.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n }\n return;\n }\n await this.show(loader);\n }\n}\n\nclass Select extends ParsedElement {\n static observed = ['value:csvm', 'readonly:presence', 'required:presence', 'itemlist:presence'];\n static slots = true;\n static template = `\n <div class=\"form-label\">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class=\"input-group flex-nowrap\" tabindex=\"-1\">\n <span data-tpl-if=\"slots.ibefore\" class=\"input-group-text\">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <div class=\"ful-select-input-container\">\n <div class=\"ful-select-input\">\n <badges></badges>\n <input type=\"text\" form=\"\" role=\"combobox\" aria-autocomplete=\"list\" aria-haspopup=\"listbox\" aria-expanded=\"false\">\n </div>\n <ful-dropdown hidden popover=\"manual\">{{{{ slots.dropdown }}}}</ful-dropdown>\n </div>\n {{{{ slots.after }}}}\n <span data-tpl-if=\"slots.iafter\" class=\"input-group-text\">{{{{ slots.iafter }}}}</span>\n </div>\n <ful-item-list></ful-item-list>\n <ful-field-error></ful-field-error>\n `;\n static templates = {\n items: `\n <ful-item data-tpl-each=\"entries\" data-tpl-var=\"entry\" data-tpl-data-key=\"entry[0]\">\n <div>{{ entry[1][0] }}</div>\n <button type=\"button\" class=\"btn btn-sm btn-outline-danger bi bi-x-lg\"></button>\n </ful-item>\n `,\n };\n static formAssociated = true;\n internals;\n #loader;\n #badges;\n #ddmenu;\n #input;\n #items;\n #multiple;\n #fieldError;\n #values = new Map();\n constructor() {\n super();\n this.internals = this.attachInternals();\n this.internals.role = 'presentation';\n }\n async render({ slots, observed, disabled }) {\n const name = this.getAttribute('name');\n this.#loader = registry\n .component(this.getAttribute('loader') ?? 'loaders:select')\n .create(this, { options: slots.options });\n\n this.#multiple = this.hasAttribute('multiple');\n await this.#loader.prefetch?.();\n const fragment = this.template().withOverlay({ slots, name }).render();\n this.#input = fragment.querySelector('input');\n this.#items = fragment.querySelector('ful-item-list');\n Attributes.forward('input-', this, this.#input);\n this.#badges = fragment.querySelector('badges');\n\n this.value = observed.value;\n this.disabled = disabled;\n this.readonly = observed.readonly;\n this.required = observed.required;\n this.itemlist = observed.itemlist;\n\n this.#ddmenu = fragment.querySelector('ful-dropdown');\n const label = fragment.querySelector('label');\n label.addEventListener('click', () => this.focus());\n this.#fieldError = fragment.querySelector('ful-field-error');\n this.#input.ariaDescribedByElements = [this.#fieldError];\n this.#input.ariaLabelledByElements = [label];\n\n const self = this;\n const [dload, abortdload] = Timing.throttle(400, () => {\n self.#input.setAttribute('aria-expanded', 'true');\n self.#ddmenu.show(() => self.#loader.load(self.#input.value));\n });\n this.addEventListener('click', (/** @type any */ e) => {\n if (e.target.matches('input')) {\n return;\n }\n if (this.disabled || this.readonly) {\n return;\n }\n if (this.#ddmenu.shown) {\n this.#input.setAttribute('aria-expanded', 'false');\n this.#ddmenu.hide();\n return;\n }\n this.#input.focus();\n dload();\n });\n this.#items.addEventListener('click', (e) => {\n e.stopPropagation();\n if (!e.target.closest('button')) {\n return;\n }\n if (this.disabled || this.readonly) {\n return;\n }\n const idx = [...this.#items.children].indexOf(e.target.closest('ful-item'));\n if (idx === -1) {\n return;\n }\n this.#values.delete(Array.from(this.#values.keys())[idx]);\n this.#changed();\n this.#syncBadges();\n });\n this.#badges.addEventListener('click', (e) => {\n e.stopPropagation();\n if (this.disabled || this.readonly) {\n return;\n }\n const idx = [...this.#badges.children].indexOf(e.target);\n if (idx === -1) {\n return;\n }\n this.#values.delete(Array.from(this.#values.keys())[idx]);\n this.#changed();\n this.#syncBadges();\n });\n this.#input.addEventListener('change', (e) => {\n e.stopPropagation();\n });\n this.#input.addEventListener('blur', (e) => {\n e.stopPropagation();\n if (e.relatedTarget && this.contains(e.relatedTarget)) {\n return;\n }\n abortdload();\n this.#input.setAttribute('aria-expanded', 'false');\n this.#ddmenu.hide();\n this.#input.value = '';\n });\n this.#input.addEventListener('keydown', (e) => {\n if (this.disabled || this.readonly) {\n return;\n }\n switch (e.code) {\n case 'ArrowUp': {\n e.preventDefault();\n this.#input.setAttribute('aria-expanded', 'true');\n this.#ddmenu.moveOrShow(false, () => self.#loader.load(self.#input.value));\n break;\n }\n case 'ArrowDown': {\n e.preventDefault();\n this.#input.setAttribute('aria-expanded', 'true');\n this.#ddmenu.moveOrShow(true, () => self.#loader.load(self.#input.value));\n break;\n }\n case 'Escape': {\n this.#input.setAttribute('aria-expanded', 'false'); \n this.#ddmenu.hide();\n break;\n }\n case 'Enter': {\n e.preventDefault();\n this.#input.setAttribute('aria-expanded', 'false');\n this.#ddmenu.acceptSelection();\n this.#input.value = '';\n break;\n }\n case 'Backspace': {\n //remove last if caret at position 0\n if (this.#values.size && this.#input.selectionStart === 0 && this.#input.selectionEnd === 0) {\n this.#values.delete(Array.from(this.#values.keys()).pop());\n this.#changed();\n this.#syncBadges();\n }\n break;\n }\n case 'Tab': {\n this.#input.setAttribute('aria-expanded', 'false');\n this.#ddmenu.hide();\n abortdload();\n break;\n }\n }\n });\n this.#input.addEventListener('input', (e) => {\n e.stopPropagation();\n if (this.disabled || this.readonly) {\n return;\n }\n dload();\n });\n this.#ddmenu.addEventListener('change', (e) => {\n e.stopPropagation();\n if (!this.#multiple) {\n this.#values.clear();\n }\n this.#values.set(e.detail.data[0], e.detail.data.slice(1));\n this.#changed();\n this.#syncBadges();\n this.#input.focus();\n this.#input.setAttribute('aria-expanded', 'false');\n this.#ddmenu.hide();\n this.#input.value = '';\n });\n this.replaceChildren(fragment);\n }\n async withLoader(fn) {\n return await fn(this.#loader);\n }\n #changed() {\n const selection = [...this.#values.entries()].map((e) => ({\n key: e[0],\n label: e[1][0],\n metadata: e[1].slice(1),\n }));\n const value = this.#multiple ? selection : (selection[0] ?? null);\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n cancelable: false,\n detail: { value },\n }),\n );\n }\n #syncBadges() {\n const badges = Array.from(this.#values.entries()).map(([k, v]) => {\n const b = document.createElement('badge');\n b.setAttribute('role', 'button');\n b.setAttribute('value', k);\n b.innerText = v[0];\n return b;\n });\n this.#badges.replaceChildren();\n this.#badges.append(...badges);\n this.#items.replaceChildren();\n this.template('items').withOverlay({ entries: this.#values.entries() }).renderTo(this.#items);\n }\n set value(vs) {\n if (vs === null) {\n this.#values = new Map();\n this.#syncBadges();\n return;\n }\n (async () => {\n const entries = await (this.#multiple ? this.#loader.exact(...vs) : this.#loader.exact(vs));\n this.#values = new Map(entries.map((e) => [e[0], e.slice(1)]));\n this.#syncBadges();\n })();\n }\n get value() {\n if (this.#multiple) {\n return [...this.#values.keys()];\n }\n return [...this.#values.keys()][0] ?? null;\n }\n get entry() {\n if (this.#multiple) {\n return [...this.#values.entries()];\n }\n return [...this.#values.entries()][0] ?? null;\n }\n get disabled() {\n return this.#input.hasAttribute('disabled');\n }\n set disabled(d) {\n Attributes.toggle(this.#input, 'disabled', d);\n }\n get readonly() {\n return this.#input.readOnly;\n }\n set readonly(v) {\n this.#input.readOnly = v;\n this.reflect(() => {\n Attributes.toggle(this, 'readonly', v);\n });\n }\n get required() {\n return this.#input.getAttribute('aria-required') === 'true';\n }\n set required(d) {\n Attributes.set(this.#input, 'aria-required', d ? 'true' : null);\n this.reflect(() => {\n Attributes.toggle(this, 'required', d);\n });\n }\n #useItemlist;\n get itemlist() {\n return this.#useItemlist;\n }\n set itemlist(v) {\n this.#useItemlist = v;\n this.reflect(() => {\n Attributes.toggle(this, 'itemlist', v);\n });\n }\n focus(options) {\n this.#input.focus(options);\n }\n setCustomValidity(error) {\n if (!error) {\n this.internals.setValidity({});\n this.#fieldError.innerText = '';\n return;\n }\n this.internals.setValidity({ customError: true }, ' ');\n this.#fieldError.innerText = error;\n }\n}\n\nexport { Dropdown, Select, SelectLoader };\n","import { Attributes, Fragments, ParsedElement } from '../../ftl/index.mjs';\n\nclass RadioGroup extends ParsedElement {\n static observed = ['value', 'readonly:presence', 'required:presence'];\n static slots = true;\n static template = `\n <fieldset>\n <legend class=\"form-label\">\n {{{{ slots.default }}}}\n </legend>\n <header data-tpl-if=\"slots.header\">\n {{{{ slots.header }}}}\n </header>\n <section>\n <div class=\"label-wrapper\" data-tpl-each=\"inputsAndLabels\" data-tpl-var=\"ial\">\n <label>\n {{{{ ial[0] }}}}\n <div>{{{{ ial[1] }}}}</div>\n </label>\n </div>\n </section>\n <ful-field-error></ful-field-error>\n <footer data-tpl-if=\"slots.footer\">\n {{{{ slots.footer }}}}\n </footer>\n </fieldset>\n `;\n static formAssociated = true;\n #fieldset;\n #fieldError;\n #firstRadio;\n #booleanType;\n constructor() {\n super();\n this.internals = this.attachInternals();\n this.internals.role = 'radiogroup';\n }\n render({ slots, observed, disabled }) {\n const name = this.getAttribute('name') ?? Attributes.uid('ful-radiogroup');\n const radioEls = Array.from(slots.default.querySelectorAll('ful-radio'));\n const inputsAndLabels = radioEls.map((el) => {\n const input = document.createElement('input');\n input.setAttribute('type', 'radio');\n Attributes.forward('input-', this, input);\n Attributes.forward('', el, input);\n input.setAttribute('name', `${name}-ignore`);\n input.setAttribute('form', ``);\n input.addEventListener('change', (evt) => {\n evt.stopPropagation();\n //change is not cancelable\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n cancelable: false,\n detail: {\n value: this.value,\n },\n }),\n );\n });\n const label = Fragments.fromChildNodes(el);\n return [input, label];\n });\n\n radioEls.forEach((el) => el.remove());\n this.template().withOverlay({ name, slots, inputsAndLabels }).renderTo(this);\n this.#fieldset = this.firstElementChild;\n this.disabled = disabled;\n this.readonly = observed.readonly;\n this.required = observed.required;\n this.value = observed.value;\n this.#fieldError = this.querySelector('ful-field-error');\n this.ariaDescribedByElements = [this.#fieldError];\n this.#firstRadio = this.querySelector('input[type=radio]');\n this.#booleanType = this.getAttribute('type') === 'boolean';\n }\n get value() {\n /** @type {HTMLInputElement|null} */\n const checked = this.querySelector('input[type=radio]:checked');\n return checked ? (this.#booleanType ? checked.value === 'true' : checked.value) : null;\n }\n set value(value) {\n if (value === null) {\n this.querySelectorAll(`input[type=radio]`).forEach((el) => {\n /** @type {HTMLInputElement} */ (el).checked = false;\n });\n return;\n }\n /** @type {HTMLInputElement|null} */\n const el = this.querySelector(`input[type=radio][value=${CSS.escape(String(value))}]`);\n if (el) {\n el.checked = true;\n }\n }\n get readonly() {\n return this.#fieldset.inert;\n }\n set readonly(v) {\n this.#fieldset.inert = v;\n this.reflect(() => {\n Attributes.toggle(this, 'readonly', v);\n });\n }\n get disabled() {\n return this.#fieldset.hasAttribute('disabled');\n }\n set disabled(d) {\n Attributes.toggle(this.#fieldset, 'disabled', d);\n }\n get required() {\n return this.#fieldset.getAttribute('aria-required') === 'true';\n }\n set required(d) {\n Attributes.set(this.#fieldset, 'aria-required', d ? 'true' : null);\n this.reflect(() => {\n Attributes.toggle(this, 'required', d);\n });\n }\n focus(options) {\n this.#firstRadio.focus(options);\n }\n setCustomValidity(error) {\n if (!error) {\n this.internals.setValidity({});\n this.#fieldError.innerText = '';\n return;\n }\n this.internals.setValidity({ customError: true }, ' ');\n this.#fieldError.innerText = error;\n }\n}\n\nexport { RadioGroup };\n","import { Attributes, ParsedElement } from '../../ftl/index.mjs';\n\nclass Checkbox extends ParsedElement {\n static observed = ['value:bool', 'readonly:presence', 'required:presence'];\n static slots = true;\n static template = `\n <div data-tpl-class=\"klass\">\n <div class=\"input-container\">\n <input class=\"form-check-input\" type=\"checkbox\" data-tpl-role=\"isSwitch ? 'switch' : false\" form=\"\" placeholder=\" \">\n </div>\n <div class=\"form-check-label\">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n </div>\n <ful-field-error></ful-field-error>\n `;\n #container;\n #input;\n #fieldError;\n static formAssociated = true;\n constructor() {\n super();\n this.internals = this.attachInternals();\n this.internals.role = 'presentation';\n }\n render({ slots, observed, disabled }) {\n const isSwitch = this.getAttribute('type') == 'switch';\n const klass = isSwitch ? 'form-check form-switch' : 'form-check';\n const fragment = this.template().withOverlay({ slots, klass, isSwitch }).render();\n this.#container = fragment.firstElementChild;\n this.#input = fragment.querySelector('input');\n Attributes.forward('input-', this, this.#input);\n this.disabled = disabled;\n this.readonly = observed.readonly;\n this.required = observed.required;\n this.value = observed.value;\n this.#input.addEventListener('change', (evt) => {\n evt.stopPropagation();\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n cancelable: false,\n detail: {\n value: this.value,\n },\n }),\n );\n });\n const label = fragment.querySelector('label');\n label.addEventListener('click', () => {\n this.focus();\n if (this.disabled || this.readonly) {\n return;\n }\n this.value = !this.value;\n this.dispatchEvent(\n new CustomEvent('change', {\n bubbles: true,\n cancelable: false,\n detail: {\n value: this.value,\n },\n }),\n );\n });\n this.#fieldError = fragment.querySelector('ful-field-error');\n this.#input.ariaDescribedByElements = [this.#fieldError];\n this.#input.ariaLabelledByElements = [label];\n this.replaceChildren(fragment);\n }\n get value() {\n return this.#input.checked;\n }\n set value(value) {\n this.#input.checked = value;\n }\n get readonly() {\n return this.#container.inert;\n }\n set readonly(v) {\n this.#container.inert = v;\n this.reflect(() => {\n Attributes.toggle(this, 'readonly', v);\n });\n }\n get disabled() {\n return this.#input.hasAttribute('disabled');\n }\n set disabled(d) {\n Attributes.toggle(this.#input, 'disabled', d);\n }\n get required() {\n return this.#input.getAttribute('aria-required') === 'true';\n }\n set required(d) {\n Attributes.set(this.#input, 'aria-required', d ? 'true' : null);\n this.reflect(() => {\n Attributes.toggle(this, 'required', d);\n });\n }\n focus(options) {\n this.#input.focus(options);\n }\n setCustomValidity(error) {\n if (!error) {\n this.internals.setValidity({});\n this.#fieldError.innerText = '';\n return;\n }\n this.internals.setValidity({ customError: true }, ' ');\n this.#fieldError.innerText = error;\n }\n}\n\nexport { Checkbox };\n","import { ParsedElement } from '../../ftl/index.mjs';\n\nclass Spinner extends ParsedElement {\n static slots = true;\n static template = `\n <div class=\"ful-spinner-wrapper\" role=\"status\">\n <div class=\"ful-spinner-text\">{{{{ slots.default }}}}</div>\n <div class=\"ful-spinner-icon\"></div>\n </div>\n `;\n render({ slots }) {\n this.template().withOverlay({ slots }).renderTo(this);\n }\n}\n\nexport { Spinner };\n","import { Attributes, Fragments, Nodes, ParsedElement, registry, Rendering } from '../../ftl/index.mjs';\n\nclass SortButton extends ParsedElement {\n static observed = ['order'];\n #order;\n render() {\n const sorter = this.getAttribute('sorter');\n const orders = ['asc', 'desc', null];\n this.addEventListener('click', () => {\n const nextOrder = orders[(orders.indexOf(this.order) + 1) % 3];\n this.dispatchEvent(\n new CustomEvent('sort-requested', {\n bubbles: true,\n cancelable: true,\n detail: {\n value: { sorter, order: nextOrder },\n },\n }),\n );\n });\n }\n\n get order() {\n return this.#order || null;\n }\n\n set order(value) {\n this.#order = value || null;\n this.reflect(() => {\n if (this.#order) {\n this.setAttribute('order', value);\n } else {\n this.removeAttribute('order');\n }\n });\n }\n}\n\nclass Pagination extends ParsedElement {\n static observed = ['total:number', 'current:number'];\n static l10n = {\n en: {\n showing: 'Page {0} of {1}',\n navigation: 'Page navigation',\n previous: 'Previous',\n next: 'Next',\n },\n it: {\n showing: 'Pagina {0} di {1}',\n navigation: 'Navigazione pagine',\n previous: 'Precedente',\n next: 'Successivo',\n },\n es: {\n showing: 'Página {0} de {1}',\n navigation: 'Navegación de páginas',\n previous: 'Anterior',\n next: 'Siguiente',\n },\n fr: {\n showing: 'Page {0} sur {1}',\n navigation: 'Navigation des pages',\n previous: 'Précédent',\n next: 'Suivant',\n },\n };\n static config = {\n prevIcon: 'bi bi-chevron-left',\n nextIcon: 'bi bi-chevron-right',\n reloadIcon: 'bi bi-arrow-clockwise',\n };\n static template = `\n <nav data-tpl-aria-label=\"#l10n:t('navigation')\" class=\"user-select-none\">\n <ul class=\"pagination\">\n <li class=\"page-item ms-auto me-2 pagination-index\"> {{ #l10n:t('showing', curr.label, total) }}</li>\n <li class=\"page-item me-2 reload\"><a role=\"button\"><i data-tpl-class=\"config.reloadIcon\"></i></a></li>\n <li class=\"page-item prev\">\n <a data-tpl-class=\"prev.enabled?'page-link':'page-link disabled'\" data-tpl-aria-label=\"#l10n:t('previous')\" role=\"button\" data-tpl-data-page=\"prev.index\">\n <i aria-hidden=\"true\" data-tpl-class=\"config.prevIcon\"></i>\n </a>\n </li>\n <li class=\"page-item\" data-tpl-each=\"pages\" data-tpl-var=\"page\">\n <a data-tpl-class=\"curr.index != page.index ? 'page-link': 'page-link disabled'\" role=\"button\" data-tpl-data-page=\"page.index\" >\n {{ page.label }}\n </a>\n </li>\n <li class=\"page-item next\">\n <a data-tpl-class=\"next.enabled?'page-link':'page-link disabled'\" data-tpl-aria-label=\"#l10n:t('next')\" role=\"button\" data-tpl-data-page=\"next.index\">\n <i aria-hidden=\"true\" data-tpl-class=\"config.nextIcon\"></i>\n </a>\n </li>\n </ul>\n </nav>\n `;\n #total = 0;\n #current = 0;\n render({ observed }) {\n this.update(observed.current ?? 0, observed.total ?? 0);\n this.addEventListener('click', (/** @type any */ evt) => {\n const el = evt.target.closest('a');\n if (!el) {\n return;\n }\n this.dispatchEvent(\n new CustomEvent('page-requested', {\n bubbles: true,\n cancelable: true,\n detail: {\n value: Number(el.dataset.page ?? this.#current),\n },\n }),\n );\n });\n }\n update(current, total) {\n const maxRender = Number(this.getAttribute('pages') ?? '5');\n const prev = { index: Math.max(0, current - 1), enabled: current > 0 };\n const curr = { index: current, label: current + 1 };\n const next = { index: Math.min(total, current + 1), enabled: current + 1 < total };\n const pages = [\n {\n index: current,\n label: current + 1,\n },\n ];\n for (let mid = current, offset = 1; offset !== maxRender && pages.length != maxRender; ++offset) {\n const p = mid - offset;\n if (p >= 0) {\n pages.unshift({ index: p, label: p + 1 });\n }\n const n = mid + offset;\n if (n < total) {\n pages.push({ index: n, label: n + 1 });\n }\n }\n this.template().withOverlay({ total, prev, curr, next, pages }).renderTo(this);\n }\n get total() {\n return this.#total;\n }\n set total(value) {\n this.#total = value;\n this.reflect(() => {\n this.setAttribute('total', String(value));\n this.update(this.#current ?? 0, this.#total);\n });\n }\n get current() {\n return this.#current;\n }\n set current(value) {\n this.#current = value;\n this.reflect(() => {\n this.setAttribute('current', String(value));\n this.update(this.#current, this.#total ?? 0);\n });\n }\n}\n\nclass TableSchemaParser {\n static parse(nodeOrFragment, template) {\n const schema = Nodes.queryChildren(nodeOrFragment, 'schema');\n if (!schema) {\n throw new Error(`missing expected <schema> in ${nodeOrFragment}`);\n }\n const headersTr = document.createElement('tr');\n const rowsTr = document.createElement('tr');\n rowsTr.setAttribute('data-tpl-each', 'rows');\n for (const attr of schema.getAttributeNames()) {\n const value = schema.getAttribute(attr);\n headersTr.setAttribute(attr, value ?? '');\n rowsTr.setAttribute(attr, value ?? '');\n }\n const columns = Nodes.queryChildrenAll(schema, 'column');\n const sort =\n columns\n .filter((v) => v.hasAttribute('order'))\n .map((v) => ({ sorter: v.getAttribute('sorter'), order: v.getAttribute('order') }))[0] ?? null;\n for (var column of columns) {\n const maybeTitleTag = Nodes.queryChildren(column, 'title');\n const sorter = column.getAttribute('sorter');\n const order = column.getAttribute('order');\n const titleNode = maybeTitleTag ?? document.createTextNode(column.getAttribute('title') ?? '');\n maybeTitleTag?.remove();\n column.removeAttribute('sorter');\n column.removeAttribute('order');\n column.removeAttribute('title');\n const wrappedTitleNode =\n !sorter && !order\n ? titleNode\n : (() => {\n const fulSorter = document.createElement('ful-sorter');\n if (sorter) {\n fulSorter.setAttribute('sorter', sorter);\n }\n if (order) {\n fulSorter.setAttribute('order', order);\n }\n fulSorter.append(titleNode);\n return fulSorter;\n })();\n const th = document.createElement('th');\n const td = document.createElement('td');\n for (const attr of column.getAttributeNames()) {\n const value = column.getAttribute(attr);\n th.setAttribute(attr, value ?? '');\n td.setAttribute(attr, value ?? '');\n }\n th.append(wrappedTitleNode);\n td.append(...column.childNodes);\n headersTr.append(th);\n rowsTr.append(td);\n }\n\n return {\n headersTemplate: template\n .withOverlay({ inHeaders: true, inRows: false })\n .withFragment(Fragments.from(headersTr)),\n rowsTemplate: template.withOverlay({ inHeaders: false, inRows: true }).withFragment(Fragments.from(rowsTr)),\n sort: sort,\n length: columns.length,\n };\n }\n}\n\nclass InMemoryTableLoader {\n #data;\n constructor(data) {\n this.#data = data;\n }\n async load(pageRequest, sortRequest, filterRequest) {\n const begin = pageRequest.page * pageRequest.size;\n const end = begin + pageRequest.size;\n const page = this.#data.slice(begin, end);\n const totalElements = this.#data.length;\n return {\n data: page,\n size: totalElements\n };\n }\n update(data) {\n this.#data = data;\n }\n}\n\nclass RemoteTableLoader {\n #http;\n #url;\n #method;\n constructor(http, url, method) {\n this.#http = http;\n this.#url = url;\n this.#method = method;\n }\n async load(pageRequest, sortRequest, filterRequest) {\n const filters = Object.entries(filterRequest).filter(([k, v]) => v);\n return await this.#http\n .request(this.#method, this.#url)\n .param('page', pageRequest.page)\n .param('size', pageRequest.size)\n .param('sort', sortRequest ? `${sortRequest.sorter},${sortRequest.order}` : null)\n .param('filters', filters.length > 0 ? JSON.stringify(Object.fromEntries(filters)) : null)\n .fetchJson();\n }\n}\n\nclass TableLoader {\n static create(el, conf) {\n const url = el.getAttribute('src');\n if (url) {\n const http = registry.component('http-client');\n const method = el.getAttribute('method') ?? 'GET';\n return new RemoteTableLoader(http, url, method);\n }\n return new InMemoryTableLoader([]);\n }\n}\n\nclass Table extends ParsedElement {\n static slots = true;\n static l10n = {\n en: {\n initial: 'Start searching to see results.',\n error: 'Error while loading data:',\n nodata: 'No elements found.',\n },\n it: {\n initial: 'Avvia la ricerca per visualizzare i risultati.',\n error: 'Errore nel caricamento dei dati:',\n nodata: 'Nessun elemento trovato.',\n },\n es: {\n initial: 'Inicia la búsqueda para ver los resultados.',\n error: 'Error al cargar los datos:',\n nodata: 'No se encontraron elementos.',\n },\n fr: {\n initial: 'Lancez la recherche pour voir les résultats.',\n error: 'Erreur lors du chargement des données :',\n nodata: 'Aucun élément trouvé.',\n },\n };\n static config = {\n searchIcon: 'bi bi-search',\n };\n static template = `\n <ful-form data-tpl-if=\"slots.filters\">\n {{{{ slots.filters }}}}\n </ful-form>\n <div class=\"table-wrapper\">\n <table class=\"table\">\n <caption data-tpl-if=\"slots.caption\">{{{{ slots.caption }}}}</caption>\n <thead></thead>\n <tbody></tbody>\n <tbody data-ref=\"initial\">\n <tr>\n <td data-tpl-colspan=\"schema.length\">\n <div>\n <p data-tpl-if=\"config.searchIcon\"><i data-tpl-class=\"config.searchIcon\"></i></p>\n {{{ #l10n:t('initial') }}}\n </div>\n </td>\n </tr>\n </tbody>\n <tbody data-ref=\"loading\" hidden>\n <tr>\n <td data-tpl-colspan=\"schema.length\">\n <ful-spinner class=\"big\"></ful-spinner>\n </td>\n </tr>\n </tbody>\n <tbody data-ref=\"feedback\" hidden>\n <tr>\n <td data-tpl-colspan=\"schema.length\">\n <div class=\"alert alert-danger\">\n <p>{{ #l10n:t('error') }}</p>\n <div data-ref=\"feedback-error\"></div>\n </div>\n </td>\n </tr>\n </tbody>\n <tfoot data-tpl-if=\"slots.footer\">\n {{{{ slots.footer }}}}\n </tfoot>\n </table>\n </div>\n <ful-pagination current=\"0\" total=\"1\"></ful-pagination>\n `;\n static templates = {\n row: `\n <tr data-tpl-if=\"pageResponse.data.length == 0\">\n <td data-tpl-colspan=\"schema.length\" class=\"text-center align-middle p-4\">\n {{ #l10n:t('nodata') }}\n </td>\n </tr>\n {{{{ schema.rowsTemplate.withOverlay({'rows': pageResponse.data}).render() }}}}\n `,\n };\n #loader;\n #schema;\n #body;\n #loading;\n #noAutoload;\n #feedback;\n #paginator;\n #sorters;\n #latestRequest;\n async render({ slots, observed }) {\n const template = this.template();\n const schema = TableSchemaParser.parse(slots.schema, template);\n const fragment = template.withOverlay({ slots, schema }).render();\n const tableWrapper = /** @type HTMLTableElement */ (Nodes.queryChildren(fragment, '.table-wrapper'));\n const table = /** @type HTMLTableElement */ (tableWrapper.querySelector('table'));\n Attributes.forward('table-', this, table);\n this.#loader = registry.component(this.getAttribute('loader') ?? 'loaders:table').create(this);\n\n this.#schema = schema;\n this.#body = table.querySelector(':scope > tbody');\n this.#loading = table.querySelector(':scope > tbody[data-ref=loading]');\n this.#noAutoload = table.querySelector(':scope > tbody[data-ref=initial]');\n this.#feedback = table.querySelector(':scope > tbody[data-ref=feedback]');\n this.#paginator = Nodes.queryChildren(fragment, 'ful-pagination');\n this.#sorters = table.querySelectorAll(':scope > thead ful-sorter') ?? [];\n this.replaceChildren(fragment);\n schema.headersTemplate.renderTo(this.querySelector('thead'));\n await Rendering.waitForChildren(this);\n\n const maybeForm = /** @type any */ (Nodes.queryChildren(this, 'ful-form'));\n this.#latestRequest = {\n pageRequest: {\n page: 0,\n size: this.getAttribute('page-size') ? Number(this.getAttribute('page-size')) : 10,\n },\n sortRequest: schema.sort,\n filterRequest: maybeForm?.values ?? {},\n };\n maybeForm?.addEventListener('submit:success', async (evt) => {\n await this.load(\n {\n page: 0,\n size: this.#latestRequest.pageRequest.size,\n },\n this.#latestRequest.sortRequest,\n evt.detail.request,\n );\n });\n this.addEventListener('page-requested', async (/** @type any */ e) => {\n await this.load(\n {\n page: e.detail.value,\n size: this.#latestRequest.pageRequest.size,\n },\n this.#latestRequest.sortRequest,\n this.#latestRequest.filterRequest,\n );\n });\n this.addEventListener('sort-requested', async (/** @type any */ e) => {\n const sortRequest = e.detail.value.order ? e.detail.value : null;\n await this.load(this.#latestRequest.pageRequest, sortRequest, this.#latestRequest.filterRequest);\n this.#sorters.forEach((s) => (s.order = null));\n e.target.order = e.detail.value.order;\n });\n if (this.hasAttribute('autoload')) {\n await this.reload();\n }\n }\n\n async reload() {\n return await this.load(\n this.#latestRequest.pageRequest,\n this.#latestRequest.sortRequest,\n this.#latestRequest.filterRequest,\n );\n }\n async load(pageRequest, sortRequest, filterRequest) {\n this.#body.replaceChildren();\n this.#loading.removeAttribute('hidden', '');\n this.#feedback.setAttribute('hidden', '');\n this.#noAutoload.setAttribute('hidden', '');\n try {\n const pageResponse = await this.#loader.load(pageRequest, sortRequest, filterRequest);\n this.#latestRequest = { pageRequest, sortRequest, filterRequest };\n this.#update(pageRequest, sortRequest, filterRequest, pageResponse);\n } catch (/** @type any */ error) {\n this.#loading.setAttribute('hidden', '');\n this.#feedback.removeAttribute('hidden', '');\n if (!error.problems) {\n this.#feedback.querySelector('[data-ref=feedback-error]').textContent = error;\n } else {\n this.#feedback.querySelector('[data-ref=feedback-error]').textContent = error.problems.map(\n (p) => `${p.reason}`,\n );\n }\n throw error;\n }\n }\n async withLoader(fn) {\n return await fn(this.#loader);\n }\n async resetWithFilter(filterRequest) {\n return await this.load(\n {\n page: 0,\n size: this.#latestRequest.pageRequest.size,\n },\n this.#latestRequest.sortRequest,\n filterRequest,\n );\n }\n #update(pageRequest, sortRequest, filterRequest, pageResponse) {\n this.#loading.setAttribute('hidden', '');\n this.#body.replaceChildren(\n this.template('row')\n .withOverlay({\n schema: this.#schema,\n pageRequest,\n filterRequest,\n pageResponse,\n })\n .render(),\n );\n this.#paginator.current = pageRequest.page;\n this.#paginator.total = Math.ceil(pageResponse.size / pageRequest.size);\n }\n}\n\nexport { TableLoader, SortButton, Table, TableSchemaParser, Pagination };\n","import { Attributes } from '../../ftl/index.mjs';\nimport { Instant } from './temporals.mjs';\nimport { Input } from './input.mjs';\n\nclass InstantFilter extends Input {\n static observed = ['value:json', 'readonly:presence', 'required:presence'];\n static template = `\n <div class=\"form-label\">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class=\"input-group\">\n <span data-tpl-if=\"slots.ibefore\" class=\"input-group-text\">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <button data-ref=\"operator\" class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" value=\"LTE\" form=\"\">≼</button>\n <ul class=\"dropdown-menu\">\n <li><a class=\"dropdown-item\" role=\"button\" value=\"EQ\">=</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"NEQ\">≠</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"LT\">≺</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"GT\">≻</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"LTE\">≼</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"GTE\">≽</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"BETWEEN\">↔</a></li>\n </ul>\n <input data-ref=\"value1\" type=\"datetime-local\" class=\"form-control\" form=\"\">\n <input data-ref=\"value2\" type=\"datetime-local\" class=\"form-control\" form=\"\" hidden>\n {{{{ slots.after }}}}\n <span data-tpl-if=\"slots.iafter\" class=\"input-group-text\">{{{{ slots.iafter }}}}</span>\n </div>\n <ful-field-error></ful-field-error>\n `;\n #operator;\n #value1;\n #value2;\n render(conf) {\n super.render({ ...conf, skipObservedSetup: true });\n this.#operator = this.querySelector('[data-ref=operator]');\n this.#value1 = this.querySelector('[data-ref=value1]');\n this.#value2 = this.querySelector('[data-ref=value2]');\n\n this.disabled = conf.disabled;\n this.readonly = conf.observed.readonly;\n this.required = conf.observed.required;\n this.value = conf.observed.value;\n\n this.addEventListener('click', (evt) => {\n const target = /** @type HTMLElement */ (evt.target);\n if (!target.matches('ul > li > a')) {\n return;\n }\n const btn = /** @type HTMLButtonElement */ (target.closest('ul')?.previousElementSibling);\n const value = /** @type String */ (target.getAttribute('value'));\n Attributes.toggle(this.#value2, 'hidden', value !== 'BETWEEN');\n btn.setAttribute('value', value);\n btn.innerHTML = target.innerHTML;\n });\n }\n\n get value() {\n const operator = this.#operator.getAttribute('value');\n const values = operator === 'BETWEEN' ? [this.#value1.value, this.#value2.value] : [this.#value1.value];\n return values.some((v) => v === '') ? undefined : [operator, ...values.map((v) => new Date(v).toISOString())];\n }\n set value(v) {\n if (v == null) {\n this.#value1.value = '';\n this.#value2.value = '';\n return;\n }\n const [operator, ...values] = v;\n this.#operator.setAttribute('value', operator);\n this.#value1.value = values[0] ? Instant.isoToLocal(values[0]) : values[0];\n this.#value2.value = values[1] ? Instant.isoToLocal(values[1]) : values[1];\n }\n set readonly(v) {\n this.#value2.readOnly = v;\n super.readonly = v;\n }\n set disabled(d) {\n Attributes.toggle(this.#value2, 'disabled', d);\n super.disabled = d;\n }\n}\n\nclass LocalDateFilter extends Input {\n static observed = ['value:json', 'readonly:presence', 'required:presence'];\n static template = `\n <div class=\"form-label\">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class=\"input-group\">\n <span data-tpl-if=\"slots.ibefore\" class=\"input-group-text\">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <button data-ref=\"operator\" class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" value=\"EQ\" form=\"\">=</button>\n <ul class=\"dropdown-menu\">\n <li><a class=\"dropdown-item\" role=\"button\" value=\"EQ\">=</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"NEQ\">≠</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"LT\">≺</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"GT\">≻</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"LTE\">≼</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"GTE\">≽</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"BETWEEN\">↔</a></li>\n </ul>\n <input data-ref=\"value1\" type=\"date\" class=\"form-control\" form=\"\">\n <input data-ref=\"value2\" type=\"date\" class=\"form-control\" form=\"\" hidden>\n {{{{ slots.after }}}}\n <span data-tpl-if=\"slots.iafter\" class=\"input-group-text\">{{{{ slots.iafter }}}}</span>\n </div>\n <ful-field-error></ful-field-error>\n `;\n #operator;\n #value1;\n #value2;\n render(conf) {\n super.render({ ...conf, skipObservedSetup: true });\n\n this.#operator = this.querySelector('[data-ref=operator]');\n this.#value1 = this.querySelector('[data-ref=value1]');\n this.#value2 = this.querySelector('[data-ref=value2]');\n\n this.disabled = conf.disabled;\n this.readonly = conf.observed.readonly;\n this.required = conf.observed.required;\n this.value = conf.observed.value;\n\n this.addEventListener('click', (evt) => {\n const target = /** @type HTMLElement */ (evt.target);\n if (!target.matches('ul > li > a')) {\n return;\n }\n const btn = /** @type HTMLButtonElement */ (target.closest('ul')?.previousElementSibling);\n const value = /** @type String */ (target.getAttribute('value'));\n Attributes.toggle(this.#value2, 'hidden', value !== 'BETWEEN');\n btn.setAttribute('value', value);\n btn.innerHTML = target.innerHTML;\n });\n }\n get value() {\n const operator = this.#operator.getAttribute('value');\n const values = operator == 'BETWEEN' ? [this.#value1.value, this.#value2.value] : [this.#value1.value];\n return values.some((v) => v === '') ? undefined : [operator, ...values];\n }\n set value(v) {\n if (v == null) {\n this.#value1.value = '';\n this.#value2.value = '';\n return;\n }\n const [operator, ...values] = v;\n this.#operator.setAttribute('value', operator);\n this.#value1.value = values[0];\n this.#value2.value = values[1];\n }\n set readonly(v) {\n this.#value2.readOnly = v;\n super.readonly = v;\n }\n set disabled(d) {\n Attributes.toggle(this.#value2, 'disabled', d);\n super.disabled = d;\n }\n}\n\nclass TextFilter extends Input {\n static observed = ['value:json', 'readonly:presence', 'required:presence'];\n static template = `\n <div class=\"form-label\">\n <label>{{{{ slots.default }}}}</label>\n {{{{ slots.info }}}}\n </div>\n <div class=\"input-group\">\n <span data-tpl-if=\"slots.ibefore\" class=\"input-group-text\">{{{{ slots.ibefore }}}}</span>\n {{{{ slots.before }}}}\n <button data-ref=\"operator\" class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" data-bs-toggle=\"dropdown\" aria-expanded=\"false\" value=\"CONTAINS\" form=\"\">…a…</button>\n <ul class=\"dropdown-menu\">\n <li><a class=\"dropdown-item\" role=\"button\" value=\"CONTAINS\">…a…</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"STARTS_WITH\">a…</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"ENDS_WITH\">…a</a></li>\n <li><a class=\"dropdown-item\" role=\"button\" value=\"EQ\">=</a></li>\n </ul>\n <input data-ref=\"value\" type=\"text\" class=\"form-control\" form=\"\">\n {{{{ slots.after }}}}\n <span data-tpl-if=\"slots.iafter\" class=\"input-group-text\">{{{{ slots.iafter }}}}</span>\n </div>\n <ful-field-error></ful-field-error>\n `;\n #operator;\n #value;\n render(conf) {\n super.render({ ...conf, skipObservedSetup: true });\n\n this.#operator = this.querySelector('[data-ref=operator]');\n this.#value = this.querySelector('[data-ref=value]');\n\n this.disabled = conf.disabled;\n this.readonly = conf.observed.readonly;\n this.required = conf.observed.required;\n this.value = conf.observed.value;\n\n this.addEventListener('click', (evt) => {\n const target = /** @type HTMLElement */ (evt.target);\n if (!target.matches('ul > li > a')) {\n return;\n }\n const btn = /** @type HTMLButtonElement */ (target.closest('ul')?.previousElementSibling);\n const value = /** @type String */ (target.getAttribute('value'));\n btn.setAttribute('value', value);\n btn.innerHTML = target.innerHTML;\n });\n }\n get value() {\n const operator = this.#operator.getAttribute('value');\n return this.#value.value === '' ? undefined : [operator, 'IGNORE_CASE', this.#value.value];\n }\n set value(v) {\n if (v == null) {\n this.#value.value = '';\n return;\n }\n const [operator, sensitivity, value] = v;\n this.#operator.setAttribute('value', operator);\n this.#value.value = value;\n }\n}\n\nexport { InstantFilter, LocalDateFilter, TextFilter };\n","class LocalizationModule {\n static t(k, ...args) {\n //@ts-ignore\n const format = this.l10n?.[this.language]?.[k] ?? this.l10n?.['en']?.[k] ?? k;\n if (args.length === 0) {\n return format;\n }\n return format.replace(/{(\\d+)}/g, (m, is) => {\n return args[Number(is)];\n });\n }\n static tl(k, args = []) {\n return LocalizationModule.t.apply(this, [k, ...args]);\n }\n}\n\nexport { LocalizationModule };\n","import { HttpClient } from '../../httpc/index.mjs';\nimport { Checkbox } from './checkbox.mjs';\nimport { LocalDate, Instant, InputLocalDate, InputLocalTime, InputInstant } from './temporals.mjs';\nimport { InstantFilter, LocalDateFilter, TextFilter } from './filters.mjs';\nimport { FormLoader, Form } from './form.mjs';\nimport { Input } from './input.mjs';\nimport { InputFile } from './files.mjs';\nimport { RadioGroup } from './radio.mjs';\nimport { SelectLoader, Dropdown, Select } from './select.mjs';\nimport { Spinner } from './spinner.mjs';\nimport { TableLoader, Table, Pagination, SortButton } from './table.mjs';\nimport { LocalizationModule } from './l10n.mjs';\n\nclass Plugin {\n configure(registry) {\n const httpClient = HttpClient.builder().withCsrfToken().withRedirectOnUnauthorized('/').build();\n registry\n .defineModule('l10n', LocalizationModule)\n .defineComponent('http-client', httpClient)\n .defineElement('ful-spinner', Spinner)\n .defineElement('ful-form', Form)\n .defineElement('ful-checkbox', Checkbox)\n .defineElement('ful-input', Input)\n .defineElement('ful-input-file', InputFile)\n .defineElement('ful-local-date', LocalDate)\n .defineElement('ful-instant', Instant)\n .defineElement('ful-input-local-date', InputLocalDate)\n .defineElement('ful-input-local-time', InputLocalTime)\n .defineElement('ful-input-instant', InputInstant)\n .defineElement('ful-radio-group', RadioGroup)\n .defineElement('ful-table', Table)\n .defineElement('ful-pagination', Pagination)\n .defineElement('ful-sorter', SortButton)\n .defineElement('ful-filter-instant', InstantFilter)\n .defineElement('ful-filter-local-date', LocalDateFilter)\n .defineElement('ful-filter-text', TextFilter)\n .defineElement('ful-select', Select)\n .defineElement('ful-dropdown', Dropdown)\n .defineComponent('loaders:select', SelectLoader)\n .defineComponent('loaders:form', FormLoader)\n .defineComponent('loaders:table', TableLoader)\n .defineOverlay({\n language: navigator?.language?.split('-')?.[0] ?? 'en',\n });\n }\n}\n\nexport { Plugin };\n"],"names":["LocalStorage","Storage","save","k","v","localStorage","setItem","JSON","stringify","load","got","getItem","undefined","parse","remove","removeItem","pop","decoded","SessionStorage","sessionStorage","VersionedLocalStorage","key","revision","data","stored","VersionedSessionStorage","AsyncEvents","fireAsync","el","evt","options","dispatchEvent","promises","async","mode","length","Error","type","Promise","all","resolve","asyncOn","fn","listener","event","ae","promise","reject","withResolvers","push","e","addEventListener","asyncOff","removeEventListener","mixInto","classes","Object","assign","prototype","this","Timing","sleep","ms","setTimeout","static","debounce","timeoutMs","func","opts","DEBOUNCE_DEFAULT","tid","args","previousTimestamp","later","elapsed","performance","now","DEBOUNCE_IMMEDIATE","arguments","clearTimeout","throttle","THROTTLE_DEFAULT","THROTTLE_NO_LEADING","remaining","THROTTLE_NO_TRAILING","Bindings","flatten","obj","prefix","stops","keys","reduce","acc","pre","has","providePath","result","path","value","split","map","test","current","previous","i","ckey","pkey","Number","isInteger","Array","isArray","extract","getAttribute","checked","dataset","tagName","extractFrom","form","submitter","elements","hasAttribute","matches","mutate","raw","mutateIn","values","names","from","filter","n","flattenedKey","entries","Set","querySelectorAll","CSS","escape","errors","es","scrollOnError","fieldErrors","globalErrors","forEach","setCustomValidity","replaceChildren","setAttribute","parts","context","replace","slice","join","suffix","input","reason","innerText","removeAttribute","sort","a","b","getBoundingClientRect","y","focus","RemoteJsonFormLoader","http","url","method","requestMapper","responseMapper","constructor","prepare","submit","request","json","fetch","transform","response","LocalFormLoader","FormLoader","create","conf","registry","component","Form","ParsedElement","render","document","createElement","Attributes","forward","childNodes","preventDefault","stopPropagation","target","spinner","loader","se","CustomEvent","bubbles","cancelable","detail","sre","mapped","exception","Failure","problems","console","warn","reset","spin","hidden","hel","wd","String","disabled","vs","Input","_input","_fieldError","super","internals","attachInternals","role","_type","_fragment","slots","template","withOverlay","observed","skipObservedSetup","fragment","querySelector","readonly","required","find","requestSubmit","re","before","after","RegExp","start","selectionStart","offset","setSelectionRange","label","ariaDescribedByElements","ariaLabelledByElements","uppercase","trim","uppercased","toUpperCase","trimmed","readOnly","reflect","toggle","d","set","error","setValidity","customError","formResetCallback","unmarshal","LocalDate","content","innerHTML","locale","Intl","DateTimeFormat","resolvedOptions","formatter","year","month","day","m","format","Date","Instant","hour","minute","second","hour12","isoToLocal","iso","pad","padStart","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","getMilliseconds","InputLocalDate","min","max","step","fromIsoOrOffset","formatLocalDate","date","getTime","getTimezoneOffset","toISOString","match","exec","sign","r","setHours","setDate","originalDay","setMonth","setFullYear","InputLocalTime","InputInstant","InputFile","en","dropzonelabel","unaccepptablefiletype","maxfilesizeexceeded","maxtotalsizeexceeded","maxfilesexceeded","it","fr","accept","items","dropzone","warnings","warning","multiple","itemlist","maxfiles","maxfilesize","maxtotalsize","closest","fileName","name","dt","DataTransfer","files","f","add","update","click","dataTransfer","kind","getAsFile","formatByteSize","Math","round","ensureAcceptable","ensureFileSizes","ensureTotalSize","ensureFilesCount","withModule","renderTo","unacceptable","file","some","toLowerCase","endsWith","includes","oversized","size","totalsize","useItemlist","useDropzone","RemoteLoader","prefetch","ensureFetched","exact","needle","reconfigureUrl","revisionedData","storageKey","fetchJson","PartialRemoteLoader","param","InMemoryLoader","SelectLoader","responseMapperFrom","evaluator","evaluateExpression","row","Dropdown","menu","optionstemplate","Map","Fragments","isBlank","default","Templates","fromFragment","li","change","hide","acceptSelection","selected","firstElementChild","metadata","index","get","shown","show","moveOrShow","candidate","scrollIntoView","block","behavior","Select","badges","ddmenu","fieldError","self","dload","abortdload","idx","children","indexOf","delete","changed","syncBadges","relatedTarget","contains","code","selectionEnd","clear","withLoader","selection","append","entry","RadioGroup","fieldset","firstRadio","booleanType","uid","radioEls","inputsAndLabels","fromChildNodes","inert","Checkbox","container","isSwitch","klass","Spinner","SortButton","order","sorter","orders","nextOrder","Pagination","showing","navigation","next","prevIcon","nextIcon","reloadIcon","total","page","maxRender","prev","enabled","curr","pages","mid","p","unshift","TableSchemaParser","nodeOrFragment","schema","Nodes","queryChildren","headersTr","rowsTr","attr","getAttributeNames","columns","queryChildrenAll","column","maybeTitleTag","titleNode","createTextNode","wrappedTitleNode","fulSorter","th","td","headersTemplate","inHeaders","inRows","withFragment","rowsTemplate","InMemoryTableLoader","pageRequest","sortRequest","filterRequest","begin","end","RemoteTableLoader","filters","fromEntries","TableLoader","Table","initial","nodata","searchIcon","body","loading","noAutoload","feedback","paginator","sorters","latestRequest","table","Rendering","waitForChildren","maybeForm","s","reload","pageResponse","textContent","resetWithFilter","ceil","InstantFilter","operator","value1","value2","btn","previousElementSibling","LocalDateFilter","TextFilter","sensitivity","LocalizationModule","t","l10n","language","is","tl","apply","Plugin","configure","httpClient","HttpClient","builder","withCsrfToken","withRedirectOnUnauthorized","build","defineModule","defineComponent","defineElement","defineOverlay","navigator"],"mappings":"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"}
|