{"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        if (got === null) {\n            return undefined;\n        }\n        try {\n            return JSON.parse(got);\n        } catch {\n            //not what save wrote: drop it, otherwise every later read fails the same way\n            localStorage.removeItem(k);\n            return undefined;\n        }\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        if (got === null) {\n            return undefined;\n        }\n        try {\n            return JSON.parse(got);\n        } catch {\n            //not what save wrote: drop it, otherwise every later read fails the same way\n            sessionStorage.removeItem(k);\n            return undefined;\n        }\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.remove(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            SessionStorage.remove(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 = /** @type {number | null} */ (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 = (...called) => {\n            args = called;\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 = () => {\n            clearTimeout(tid ?? undefined);\n            tid = null;\n            args = [];\n        };\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 = /** @type {number | null} */ (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 = (...called) => {\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 = called;\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 = () => {\n            clearTimeout(tid ?? undefined);\n            tid = null;\n            args = [];\n        };\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 = /** @type {any} */ (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 & {dataset?: any} & {checked?: boolean} & {value?: any}} el\n     * @returns\n     */\n    static mutate(el, raw) {\n        if (el.getAttribute('type') === 'radio') {\n            //values are matched as strings, as ful-radio-group does: extract decodes\n            //boolean radios, and payloads carry numbers where the attribute is text\n            el.checked = raw != null && el.getAttribute('value') === String(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) => {\n            el.setCustomValidity?.('');\n        });\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 = document.createElement('form');\n        this.form = 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        //one try: building the loader and preparing the request are as much part of a\n        //submit as sending it, and a mapper that throws is how a caller reports a\n        //problem with the values\n        let values;\n        let request;\n        try {\n            const loader = registry.component(this.getAttribute('loader') ?? 'loaders:form').create(this);\n            values = Bindings.extractFrom(this.form, submitter);\n            request = await loader.prepare(values, this);\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        } finally {\n            this.spinner(false);\n        }\n    }\n    reset() {\n        this.form.reset();\n    }\n    #spinning = 0;\n    spinner(spin) {\n        //submits can overlap: only the outermost one saves and restores the button states\n        if (spin) {\n            ++this.#spinning;\n            if (this.#spinning !== 1) {\n                return;\n            }\n        } else {\n            this.#spinning = Math.max(0, this.#spinning - 1);\n            if (this.#spinning !== 0) {\n                return;\n            }\n        }\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', 'placeholder'];\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        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 mask = this.getAttribute('mask');\n            if (!mask) {\n                return;\n            }\n            const strip = (v) => v.replace(new RegExp(mask, 'g'), '');\n            const before = evt.target.value;\n            const after = strip(before);\n            if (before === after) {\n                return;\n            }\n            const start = evt.target.selectionStart;\n            evt.target.value = after;\n            if (start === null) {\n                //email, number and the date types have no selection to restore\n                return;\n            }\n            //the caret keeps its place among the characters that survived, so only the\n            //ones stripped before it count\n            const caret = strip(before.slice(0, start)).length;\n            evt.target.setSelectionRange(caret, caret);\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        if (!skipObservedSetup) {\n            // biome-ignore lint/complexity/noUselessThisAlias: keeps checkJs from seeing these as class fields\n            const el = this;\n            el.disabled = disabled;\n            el.readonly = observed.readonly;\n            el.required = observed.required;\n            el.placeholder = observed.placeholder;\n            el.value = observed.value;\n        }\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        //the claim only, like a native input: the effective state, claim or disabled\n        //ancestry, is what :disabled matches\n        return this.hasAttribute('disabled');\n    }\n    set disabled(d) {\n        //the claim belongs to the author alone, nothing else ever writes it\n        Attributes.toggle(this, 'disabled', d);\n        //the inner control carries the claim as a native input would: a disabled\n        //fieldset ancestry is left to the browser, which reaches the inner control\n        //as a descendant of the fieldset and re-enables it on its own\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    get placeholder() {\n        const v = this._input.getAttribute('placeholder');\n        return v === ' ' ? null : v;\n    }\n    set placeholder(d) {\n        //without a placeholder :placeholder-shown never matches, and floating labels\n        //rely on it, so a blank one stands in for none\n        Attributes.set(this._input, 'placeholder', d ?? ' ');\n        this.reflect(() => {\n            Attributes.set(this, 'placeholder', 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.textContent.trim();\n        if (content === '') {\n            this.replaceChildren(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.replaceChildren(formatter.format(new Date(y, m - 1, d)));\n    }\n}\n\nclass Instant extends ParsedElement {\n    render() {\n        const content = this.textContent.trim();\n        if (content === '') {\n            this.replaceChildren(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.replaceChildren(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', 'placeholder', 'min', 'max', 'step'];\n    _type() {\n        return 'date';\n    }\n    render(conf) {\n        const { observed } = conf;\n        super.render(conf);\n        //step first: on a time input min and max are snapped to its grid\n        this.step = observed.step;\n        this.min = observed.min;\n        this.max = observed.max;\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            }\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    get min() {\n        const v = this._input.min;\n        return v === '' ? null : v;\n    }\n    set min(v) {\n        this._input.min = this.#fromNowOrOffset(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 = this.#fromNowOrOffset(v);\n    }\n    /**\n     * Resolves `now` and hour or minute offsets against the current time, wrapping\n     * around midnight. `m` is minutes here, unlike the date offsets of the parent where\n     * it is months: months mean nothing on a time. Anything else is passed through.\n     */\n    #fromNowOrOffset(v) {\n        if (!v) {\n            return '';\n        }\n        const resolved = new Date();\n        if (v !== 'now') {\n            const re = /^([+-])(\\d+)([hm])$/;\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] * sign;\n            if (match[3] === 'h') {\n                resolved.setHours(resolved.getHours() + offset);\n            } else {\n                resolved.setMinutes(resolved.getMinutes() + offset);\n            }\n        }\n        return InputLocalTime.#snapped(resolved, Number(this._input.step) || 60);\n    }\n    /**\n     * Truncates a time to the step grid: min anchors that grid, so a bound that is not\n     * on it makes every value on it invalid.\n     */\n    static #snapped(date, stepSeconds) {\n        const pad = (n) => String(n).padStart(2, '0');\n        const seconds = date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds();\n        const snapped = Math.floor(seconds / stepSeconds) * stepSeconds;\n        const hh = pad(Math.floor(snapped / 3600));\n        const mm = pad(Math.floor((snapped % 3600) / 60));\n        return stepSeconds % 60 === 0 ? `${hh}:${mm}` : `${hh}:${mm}:${pad(snapped % 60)}`;\n    }\n}\n\nclass InputInstant extends Input {\n    static observed = ['value', 'readonly:presence', 'required:presence', 'placeholder', '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            unacceptablefiletype: '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            unacceptablefiletype: '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            unacceptablefiletype: '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            unacceptablefiletype: '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        'placeholder',\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, skipObservedSetup: true });\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\n        this.disabled = conf.disabled;\n        this.readonly = observed.readonly;\n        this.required = observed.required;\n        this.placeholder = observed.placeholder;\n        this.value = observed.value;\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 idx = [...this.#items.children].indexOf(e.target.closest('ful-item'));\n            if (idx === -1) {\n                return;\n            }\n            const dt = new DataTransfer();\n            [...this.files]\n                .filter((f, i) => i !== idx)\n                .forEach((f) => {\n                    dt.items.add(f);\n                });\n            this.files = dt.files;\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 dropped = [...e.dataTransfer.items].filter((i) => i.kind === 'file');\n            if (dropped.length === 0) {\n                return;\n            }\n            const dt = new DataTransfer();\n            dropped.forEach((i) => {\n                dt.items.add(i.getAsFile());\n            });\n            this.files = dt.files;\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.#warnings.replaceChildren();\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 }).appendTo(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('unacceptablefiletype', this.#accept.join(', '));\n        const dt = new DataTransfer();\n        [...this.files]\n            .filter((f) => !unacceptable.includes(f))\n            .forEach((f) => {\n                dt.items.add(f);\n            });\n        this._input.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        this._input.files = new DataTransfer().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]\n            .filter((f) => !oversized.includes(f))\n            .forEach((f) => {\n                dt.items.add(f);\n            });\n        this._input.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._input.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        this.#update();\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    }\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    #selected() {\n        return this.#menu?.querySelector('[selected]') ?? this.#menu?.firstElementChild ?? null;\n    }\n    acceptSelection() {\n        const selected = this.#selected();\n        if (!selected) {\n            return;\n        }\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        } catch (e) {\n            this.hide();\n            throw e;\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.#selected();\n            const candidate = selected?.[`${forward ? 'next' : 'previous'}ElementSibling`];\n            if (selected && 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    #token = 0;\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        try {\n            await this.#loader.prefetch?.();\n        } catch (/** @type any */ e) {\n            console.warn('failed to prefetch select options', this, 'reason:', e);\n        }\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        const [dload, abortdload] = Timing.throttle(400, () => {\n            this.#input.setAttribute('aria-expanded', 'true');\n            this.#ddmenu.show(() => this.#loader.load(this.#input.value));\n        });\n        this.addEventListener('click', (/** @type any */ e) => {\n            if (e.target.matches('input')) {\n                return;\n            }\n            //badges and other chrome are not form controls, the guard must ask the\n            //effective state\n            if (this.matches(':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.matches(':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.matches(':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.matches(':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, () => this.#loader.load(this.#input.value));\n                    break;\n                }\n                case 'ArrowDown': {\n                    e.preventDefault();\n                    this.#input.setAttribute('aria-expanded', 'true');\n                    this.#ddmenu.moveOrShow(true, () => this.#loader.load(this.#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                    if (!this.#ddmenu.shown) {\n                        //nothing to accept: submit the form as ful-input does. the inner\n                        //input carries form=\"\" so it never submits one on its own\n                        this.#requestSubmit();\n                        return;\n                    }\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.matches(':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(this.#coerceKey(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    #requestSubmit() {\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        form.requestSubmit(candidates.find((el) => el.type === 'submit'));\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    /**\n     * Coerces a key to the type declared by `k-type`. Keys reach the element from\n     * both worlds: the `value` attribute is text, a loader returns whatever its\n     * endpoint carries. One canonical type keeps the internal Map, which compares\n     * keys strictly, consistent. A key that does not decode is left as it is.\n     */\n    #coerceKey(k) {\n        switch (this.getAttribute('k-type')) {\n            case 'number': {\n                const n = k === '' ? Number.NaN : Number(k);\n                return Number.isNaN(n) ? k : n;\n            }\n            case 'boolean': {\n                if (k === true || k === 'true') {\n                    return true;\n                }\n                if (k === false || k === 'false') {\n                    return false;\n                }\n                return k;\n            }\n            default:\n                return String(k);\n        }\n    }\n\n    set value(vs) {\n        //the csvm mapper yields [] for a missing multiple value, an empty string is\n        //left alone: it is a usable key for an <option value=\"\">\n        const keys = (vs == null ? [] : Array.isArray(vs) ? vs : [vs]).map((k) => this.#coerceKey(k));\n        //the keys are known synchronously and are all `value` reads, so they are applied\n        //now: only the labels need the loader, until then a key stands in for its own\n        this.#values = new Map(keys.map((k) => [k, [k]]));\n        this.#syncBadges();\n        const token = ++this.#token;\n        if (keys.length === 0) {\n            return;\n        }\n        this.#resolve(keys, token);\n    }\n    /**\n     * Resolves the labels of the assigned keys. A failed lookup is left to reject so\n     * that it is reported like any other failure: the keys stay applied either way.\n     */\n    async #resolve(keys, token) {\n        const entries = await this.#loader.exact(...keys);\n        if (token !== this.#token) {\n            //a newer assignment has been made in the meantime\n            return;\n        }\n        //label the keys that are still selected: a removal made while the lookup was in\n        //flight must not be undone by it, and a key the loader does not know is dropped\n        //the loader keys are coerced too, so they line up with the assigned ones\n        const resolved = new Map(entries.map((e) => [this.#coerceKey(e[0]), e.slice(1)]));\n        for (const key of keys) {\n            if (!this.#values.has(key)) {\n                continue;\n            }\n            if (resolved.has(key)) {\n                this.#values.set(key, resolved.get(key));\n            } else {\n                this.#values.delete(key);\n            }\n        }\n        this.#syncBadges();\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        //the claim only, like a native input: the effective state, claim or disabled\n        //ancestry, is what :disabled matches\n        return this.hasAttribute('disabled');\n    }\n    set disabled(d) {\n        //the claim belongs to the author alone, nothing else ever writes it\n        Attributes.toggle(this, 'disabled', d);\n        //the inner control carries the claim as a native input would: a disabled\n        //fieldset ancestry is left to the browser, which reaches the inner control\n        //as a descendant of the fieldset and re-enables it on its own\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) => {\n            el.remove();\n        });\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        //the claim only, like a native input: the effective state, claim or disabled\n        //ancestry, is what :disabled matches\n        return this.hasAttribute('disabled');\n    }\n    set disabled(d) {\n        //the claim belongs to the author alone, nothing else ever writes it\n        Attributes.toggle(this, 'disabled', d);\n        //the group disables through its own fieldset, which carries the claim like\n        //a native input would: a disabled outer ancestry is left to the browser,\n        //which reaches the radios as descendants and re-enables them on its own\n        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            //a label is not a form control, the guard must ask the effective state\n            if (this.matches(':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        //the claim only, like a native input: the effective state, claim or disabled\n        //ancestry, is what :disabled matches\n        return this.hasAttribute('disabled');\n    }\n    set disabled(d) {\n        //the claim belongs to the author alone, nothing else ever writes it\n        Attributes.toggle(this, 'disabled', d);\n        //the inner control carries the claim as a native input would: a disabled\n        //fieldset ancestry is left to the browser, which reaches the inner control\n        //as a descendant of the fieldset and re-enables it on its own\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({ observed }) {\n        const sorter = this.getAttribute('sorter');\n        const orders = ['asc', 'desc', null];\n        this.order = observed.order;\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.total = observed.total ?? 0;\n        this.current = observed.current ?? 0;\n        this.addEventListener('click', (/** @type any */ evt) => {\n            const el = evt.target.closest('a');\n            if (!el || el.classList.contains('disabled')) {\n                //a disabled link leads nowhere: the page it would ask for does not exist\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 hasPrev = current > 0;\n        const hasNext = current + 1 < total;\n        //a disabled arrow carries no page: there is nothing valid for it to point at\n        const prev = { index: hasPrev ? current - 1 : null, enabled: hasPrev };\n        const curr = { index: current, label: current + 1 };\n        const next = { index: hasNext ? current + 1 : null, enabled: hasNext };\n        //the window holds at most maxRender pages, centered on the current one and slid\n        //back towards the end so it stays full on the last pages\n        const rendered = Math.max(1, Math.min(maxRender, total));\n        const first = Math.max(0, Math.min(current - Math.floor((rendered - 1) / 2), total - rendered));\n        const pages = Array.from({ length: rendered }, (_, offset) => ({\n            index: first + offset,\n            label: first + offset + 1,\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        //nodeOrFragment is undefined when the slot is missing altogether\n        const schema = nodeOrFragment ? Nodes.queryChildren(nodeOrFragment, 'schema') : null;\n        if (!schema) {\n            throw new Error('missing expected <schema>: ful-table needs a <template slot=\"schema\"> holding one');\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.replaceChildren(fragment);\n        const thead = /** @type HTMLTableSectionElement */ (this.querySelector('thead'));\n        schema.headersTemplate.renderTo(thead);\n        this.#sorters = thead.querySelectorAll('ful-sorter');\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) => {\n                s.order = null;\n            });\n            e.target.order = e.detail.value.order;\n        });\n        if (this.hasAttribute('autoload')) {\n            //not awaited: the first load must not hold up the upgrade, and a loader that\n            //fails or never answers must not keep ftl:ready from firing for the page.\n            //load renders its own error state and lets the failure reject, so it is reported\n            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', 'placeholder'];\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=\"\">&PrecedesSlantEqual;</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\">&ne;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"LT\">&prec;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"GT\">&succ;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"LTE\">&PrecedesSlantEqual;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"GTE\">&SucceedsSlantEqual;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"BETWEEN\">&LeftRightArrow;</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        //Input.render only re-dispatches changes coming from the first operand\n        this.#value2.addEventListener('change', (evt) => {\n            evt.stopPropagation();\n            this.#notifyChange();\n        });\n\n        this.disabled = conf.disabled;\n        this.readonly = conf.observed.readonly;\n        this.required = conf.observed.required;\n        this.placeholder = conf.observed.placeholder;\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            const previous = btn.getAttribute('value');\n            Attributes.toggle(this.#value2, 'hidden', value !== 'BETWEEN');\n            btn.setAttribute('value', value);\n            btn.innerHTML = target.innerHTML;\n            if (previous !== value) {\n                this.#notifyChange();\n            }\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.#showOperator(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    #showOperator(operator) {\n        this.#operator.setAttribute('value', operator);\n        const items = Array.from(this.#operator.nextElementSibling?.querySelectorAll('li > a[value]') ?? []);\n        const item = items.find((a) => a.getAttribute('value') === operator);\n        if (item) {\n            this.#operator.innerHTML = item.innerHTML;\n        }\n        Attributes.toggle(this.#value2, 'hidden', operator !== 'BETWEEN');\n    }\n    #notifyChange() {\n        this.dispatchEvent(\n            new CustomEvent('change', {\n                bubbles: true,\n                cancelable: false,\n                detail: {\n                    value: this.value,\n                },\n            }),\n        );\n    }\n    get readonly() {\n        return super.readonly;\n    }\n    set readonly(v) {\n        this.#value2.readOnly = v;\n        super.readonly = v;\n    }\n    get disabled() {\n        return super.disabled;\n    }\n    set disabled(d) {\n        //the claim and the first operand are the base's, the second operand mirrors\n        //the claim like the first one does\n        super.disabled = d;\n        Attributes.toggle(this.#value2, 'disabled', d);\n    }\n}\n\nclass LocalDateFilter extends Input {\n    static observed = ['value:json', 'readonly:presence', 'required:presence', 'placeholder'];\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\">&ne;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"LT\">&prec;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"GT\">&succ;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"LTE\">&PrecedesSlantEqual;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"GTE\">&SucceedsSlantEqual;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"BETWEEN\">&LeftRightArrow;</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        //Input.render only re-dispatches changes coming from the first operand\n        this.#value2.addEventListener('change', (evt) => {\n            evt.stopPropagation();\n            this.#notifyChange();\n        });\n\n        this.disabled = conf.disabled;\n        this.readonly = conf.observed.readonly;\n        this.required = conf.observed.required;\n        this.placeholder = conf.observed.placeholder;\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            const previous = btn.getAttribute('value');\n            Attributes.toggle(this.#value2, 'hidden', value !== 'BETWEEN');\n            btn.setAttribute('value', value);\n            btn.innerHTML = target.innerHTML;\n            if (previous !== value) {\n                this.#notifyChange();\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];\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.#showOperator(operator);\n        this.#value1.value = values[0];\n        this.#value2.value = values[1];\n    }\n    #showOperator(operator) {\n        this.#operator.setAttribute('value', operator);\n        const items = Array.from(this.#operator.nextElementSibling?.querySelectorAll('li > a[value]') ?? []);\n        const item = items.find((a) => a.getAttribute('value') === operator);\n        if (item) {\n            this.#operator.innerHTML = item.innerHTML;\n        }\n        Attributes.toggle(this.#value2, 'hidden', operator !== 'BETWEEN');\n    }\n    #notifyChange() {\n        this.dispatchEvent(\n            new CustomEvent('change', {\n                bubbles: true,\n                cancelable: false,\n                detail: {\n                    value: this.value,\n                },\n            }),\n        );\n    }\n    get readonly() {\n        return super.readonly;\n    }\n    set readonly(v) {\n        this.#value2.readOnly = v;\n        super.readonly = v;\n    }\n    get disabled() {\n        return super.disabled;\n    }\n    set disabled(d) {\n        //the claim and the first operand are the base's, the second operand mirrors\n        //the claim like the first one does\n        super.disabled = d;\n        Attributes.toggle(this.#value2, 'disabled', d);\n    }\n}\n\nclass TextFilter extends Input {\n    static observed = ['value:json', 'readonly:presence', 'required:presence', 'placeholder'];\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=\"\">&mldr;a&mldr;</button>\n            <ul class=\"dropdown-menu\">\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"CONTAINS\">&mldr;a&mldr;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"STARTS_WITH\">a&mldr;</a></li>\n                <li><a class=\"dropdown-item\" role=\"button\" value=\"ENDS_WITH\">&mldr;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    //the sensitivity has no control of its own: it is carried through from whoever set the value\n    #sensitivity = 'IGNORE_CASE';\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.placeholder = conf.observed.placeholder;\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            const previous = btn.getAttribute('value');\n            btn.setAttribute('value', value);\n            btn.innerHTML = target.innerHTML;\n            if (previous !== value) {\n                this.#notifyChange();\n            }\n        });\n    }\n    get value() {\n        const operator = this.#operator.getAttribute('value');\n        return this.#value.value === '' ? undefined : [operator, this.#sensitivity, 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.#showOperator(operator);\n        this.#sensitivity = sensitivity ?? 'IGNORE_CASE';\n        this.#value.value = value;\n    }\n    #showOperator(operator) {\n        this.#operator.setAttribute('value', operator);\n        const items = Array.from(this.#operator.nextElementSibling?.querySelectorAll('li > a[value]') ?? []);\n        const item = items.find((a) => a.getAttribute('value') === operator);\n        if (item) {\n            this.#operator.innerHTML = item.innerHTML;\n        }\n    }\n    #notifyChange() {\n        this.dispatchEvent(\n            new CustomEvent('change', {\n                bubbles: true,\n                cancelable: false,\n                detail: {\n                    value: this.value,\n                },\n            }),\n        );\n    }\n}\n\nexport { InstantFilter, LocalDateFilter, TextFilter };\n","class LocalizationModule {\n    static t(k, ...args) {\n        //@ts-expect-error l10n and language come from the element class and the data stack\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","parse","removeItem","remove","pop","decoded","SessionStorage","sessionStorage","VersionedLocalStorage","key","revision","data","stored","undefined","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","called","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","fulBindType","tagName","extractFrom","form","submitter","elements","hasAttribute","matches","mutate","raw","String","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","spinning","spin","Math","max","hidden","hel","wd","disabled","vs","Input","_input","_fieldError","super","internals","attachInternals","role","_type","_fragment","slots","template","withOverlay","observed","skipObservedSetup","fragment","querySelector","find","requestSubmit","mask","strip","RegExp","before","after","start","selectionStart","caret","setSelectionRange","label","ariaDescribedByElements","ariaLabelledByElements","readonly","required","placeholder","uppercase","trim","uppercased","toUpperCase","trimmed","readOnly","reflect","toggle","d","set","error","setValidity","customError","formResetCallback","unmarshal","LocalDate","content","textContent","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","step","min","fromIsoOrOffset","formatLocalDate","date","getTime","getTimezoneOffset","toISOString","match","exec","sign","offset","r","setHours","setDate","originalDay","setMonth","setFullYear","InputLocalTime","fromNowOrOffset","resolved","setMinutes","snapped","stepSeconds","seconds","floor","hh","mm","InputInstant","InputFile","en","dropzonelabel","unacceptablefiletype","maxfilesizeexceeded","maxtotalsizeexceeded","maxfilesexceeded","it","fr","accept","items","dropzone","warnings","warning","multiple","itemlist","maxfiles","maxfilesize","maxtotalsize","closest","idx","children","indexOf","dt","DataTransfer","files","f","add","click","dropped","dataTransfer","kind","getAsFile","update","formatByteSize","round","ensureAcceptable","ensureFileSizes","ensureTotalSize","ensureFilesCount","withModule","renderTo","appendTo","unacceptable","file","some","name","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","selected","firstElementChild","acceptSelection","metadata","index","get","shown","show","moveOrShow","candidate","scrollIntoView","block","behavior","Select","badges","ddmenu","fieldError","token","dload","abortdload","delete","changed","syncBadges","relatedTarget","contains","code","selectionEnd","clear","coerceKey","withLoader","candidates","selection","append","NaN","isNaN","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","classList","page","maxRender","hasPrev","hasNext","prev","enabled","curr","rendered","first","pages","_","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","thead","Rendering","waitForChildren","maybeForm","s","reload","pageResponse","p","resetWithFilter","ceil","InstantFilter","operator","value1","value2","notifyChange","btn","previousElementSibling","innerHTML","showOperator","item","nextElementSibling","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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"}