{"version":3,"file":"ful.min.mjs","sources":["../src/encodings.mjs","../src/failure.mjs","../src/http-client.mjs","../src/storage.mjs","../src/oauth-authorization-code.mjs","../src/events/async.mjs","../src/timing.mjs","../src/elements/loaders.mjs","../src/elements/bindings.mjs","../src/elements/form.mjs","../src/elements/input.mjs","../src/elements/temporals.mjs","../src/elements/select.mjs","../src/elements/radio.mjs","../src/elements/checkbox.mjs","../src/elements/spinner.mjs","../src/elements/table.mjs","../src/elements/filters.mjs","../src/elements/plugin.mjs"],"sourcesContent":["\n\nclass Base64 {\n    static encode(arrayBuffer, dialect) {\n        const d = dialect || Base64.URL_SAFE;\n        const len = arrayBuffer.byteLength;\n        const view = new Uint8Array(arrayBuffer);\n        let res = '';\n        for (let i = 0; i < len; i += 3) {\n            const v1 = d[view[i] >> 2];\n            const v2 = d[((view[i] & 3) << 4) | (view[i + 1] >> 4)];\n            const v3 = d[((view[i + 1] & 15) << 2) | (view[i + 2] >> 6)];\n            const v4 = d[view[i + 2] & 63];\n            res += v1 + v2 + v3 + v4;\n        }\n        if (len % 3 === 2) {\n            res = res.substring(0, res.length - 1);\n        } else if (len % 3 === 1) {\n            res = res.substring(0, res.length - 2);\n        }\n        return res;\n    }\n    static decode(str, dialect) {\n        const d = dialect || Base64.URL_SAFE;\n        let nbytes = Math.floor(str.length * 0.75);\n        for (let i = 0; i !== str.length; ++i) {\n            if (str[str.length - i - 1] !== '=') {\n                break;\n            }\n            --nbytes;\n        }\n        const view = new Uint8Array(nbytes);\n\n        let vi = 0;\n        let si = 0;\n        while (vi < str.length * 0.75) {\n            const v1 = d.indexOf(str.charAt(si++));\n            const v2 = d.indexOf(str.charAt(si++));\n            const v3 = d.indexOf(str.charAt(si++));\n            const v4 = d.indexOf(str.charAt(si++));\n            view[vi++] = (v1 << 2) | (v2 >> 4);\n            view[vi++] = ((v2 & 15) << 4) | (v3 >> 2);\n            view[vi++] = ((v3 & 3) << 6) | v4;\n        }\n\n        return view.buffer;\n    }\n}\n\nBase64.STANDARD = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\nBase64.URL_SAFE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';\n\n\nclass Hex {\n    static decode(hex) {\n        if (hex.length % 2 !== 0) {\n            throw new Error(\"invalid length\");\n        }\n        const lenInBytes = hex.length / 2;\n        return new Uint8Array(lenInBytes).map((e, i) => {\n            const offset = i * 2;\n            const octet = hex.substring(offset, offset + 2);\n            return parseInt(octet, 16);\n        });\n    }\n    static encode(bytes, upper) {\n        return Array.from(bytes)\n            .map(b => b.toString(16))\n            .map(b => upper ? b.toUpperCase() : b)\n            .map(o => o.padStart(2, 0))\n            .join('');\n    }\n}\n\nexport { Base64, Hex };","\n\n/**\n * @typedef {{ type: string; context: string?; reason: string; details: any?; }} Problem\n */\nclass Failure extends Error {\n    /**\n     * \n     * @param {string} message \n     * @param {Problem[]} problems \n     * @param {*} cause\n     */\n    constructor(message, problems, cause) {\n        super(message, { cause });\n        this.name = 'Failure';\n        this.problems = problems;\n    }\n    dropping(prefix){\n        return new Failure(this.message, Failure.dropProblemsContext(this.problems, prefix), this);\n    }\n    static dropProblemsContext(problems, prefix){\n        return problems.map(({type, context, reason, details}) => {\n            const nctx = context?.startsWith(prefix) ? context.substring(prefix.length) : context;\n            return {type, context: nctx, reason, details};\n        })\n    }\n\n}\n\nexport { Failure };","import { Failure } from \"./failure.mjs\";\n\nclass MediaType {\n    #type;\n    #subtype;\n    constructor(type, subtype) {\n        this.#type = type;\n        this.#subtype = subtype;\n    }\n    get normalized() {\n        return `${this.#type}/${this.#subtype}`;\n    }\n    get type() {\n        return this.#type;\n    }\n    get subtype() {\n        return this.#subtype;\n    }\n    /**\n     * \n     * @param {string|null|undefined} v \n     * @returns \n     */\n    static parse(v) {\n        if (!v) {\n            return new MediaType(\"unknown\", \"unknown\");\n        }\n        const [prefix, _] = v.split(\";\");\n        const [ptype, psubtype] = prefix.trim().split(\"/\");\n        return new MediaType(ptype.toLowerCase(), psubtype?.toLowerCase());\n    }\n}\n\n/**\n * @typedef {Int8Array| Uint8Array| Uint8ClampedArray| Int16Array| Uint16Array| Int32Array| Uint32Array| Float32Array| Float64Array| BigInt64Array| BigUint64Array} TypedArray\n */\n/**\n * @typedef HttpInterceptor\n * @property {function(URL,RequestInit|undefined,HttpInterceptorChain):Promise<Response>} intercept  \n */\n\nclass HttpClientError extends Failure {\n    /**\n     * @param {string} message\n     * @param {number} status\n     * @param {{ type: string; context: string?; reason: string; details: any?; }[]} problems\n     * @param {Error|undefined} [cause]\n     */\n    constructor(message, status, problems, cause) {\n        super(message, problems, cause);\n        this.name = 'HttpClientError';\n        this.status = status;\n    }\n    dropping(prefix){\n        return new HttpClientError(this.message, this.status, Failure.dropProblemsContext(this.problems, prefix), this);\n    }\n    /**\n     * \n     * @param {string} type \n     * @param {any} cause \n     * @returns \n     */\n    static of(type, cause) {\n        return new HttpClientError(cause.message, 0, [{\n            type,\n            context: null,\n            reason: cause.message,\n            details: null\n        }], cause);\n    }\n    /**\n     * Creates an HttpClientError from a Response.\n     * @param {Response} response \n     * @returns an HttpClientError\n     */\n    static async fromResponse(response) {\n        switch (MediaType.parse(response.headers.get(\"Content-Type\")).normalized) {\n            case 'application/failures+json': {\n                const data = await response.json();\n                const message = `${response.status} ${response.statusText}: ${data.length} failures`;\n                return new HttpClientError(message, response.status, data);\n            }\n            case 'application/problem+json': {\n                const data = await response.json();\n                const message = `${response.status} ${response.statusText}: ${data.title} ${data.detail}`;\n                return new HttpClientError(message, response.status, data.problems || [{\n                    type: \"GENERIC_PROBLEM\",\n                    context: null,\n                    reason: message,\n                    details: null\n                }]);\n            }\n            default: {\n                const text = await response.text();\n                const message = `${response.status} ${response.statusText}: ${text}`;\n                return new HttpClientError(message, response.status, [{\n                    type: \"GENERIC_PROBLEM\",\n                    context: null,\n                    reason: message,\n                    details: null\n                }]);\n            }\n        }\n    }\n}\n\n/**\n * @implements {HttpInterceptor}\n */\nclass CsrfTokenInterceptor {\n    #k; #v;\n    constructor() {\n        this.#k = document.querySelector(\"meta[name='_csrf_header']\")?.getAttribute(\"content\");\n        this.#v = document.querySelector(\"meta[name='_csrf']\")?.getAttribute(\"content\");\n    }\n    async intercept(url, request, chain) {\n        if (this.#k && this.#v) {\n            request.headers.set(this.#k, this.#v);\n        }\n        return await chain.proceed(url, request);\n    }\n}\n/**\n * @implements {HttpInterceptor}\n */\nclass RedirectOnUnauthorizedInterceptor {\n    #redirectUri;\n    /**\n     * @param {string} redirectUri\n     */\n    constructor(redirectUri) {\n        this.#redirectUri = redirectUri;\n    }\n    async intercept(url, request, chain) {\n        const response = await chain.proceed(url, request);\n        if (response.status === 401) {\n            window.location.href = this.#redirectUri;\n        }\n        return response;\n    }\n}\n\nclass HttpClientBuilder {\n    /**\n     * @type {HttpInterceptor[]}\n     */\n    #interceptors;\n    constructor() {\n        this.#interceptors = [];\n    }\n    withCsrfToken() {\n        this.#interceptors.push(new CsrfTokenInterceptor());\n        return this;\n    }\n    withRedirectOnUnauthorized(redirectUri) {\n        this.#interceptors.push(new RedirectOnUnauthorizedInterceptor(redirectUri));\n        return this;\n    }\n    /**\n     * @param {...HttpInterceptor} interceptors\n     */\n    withInterceptors(...interceptors) {\n        this.#interceptors.push(...interceptors);\n        return this;\n    }\n    build() {\n        return new HttpClient(this.#interceptors);\n    }\n}\n\n/**\n * @implements {HttpInterceptor}\n */\nclass HttpCall {\n    async intercept(url, request, chain) {\n        return await fetch(new Request(url, request));\n    }\n}\n\nclass HttpInterceptorChain {\n    #interceptors;\n    #current;\n    /**\n     * \n     * @param {HttpInterceptor[]} interceptors \n     * @param {number} current \n     */\n    constructor(interceptors, current) {\n        this.#interceptors = interceptors;\n        this.#current = current;\n    }\n    /**\n     * \n     * @param {URL} url\n     * @param {RequestInit} request \n     * @returns {Promise<Response>} the response\n     */\n    async proceed(url, request) {\n        const interceptor = this.#interceptors[this.#current];\n        return await interceptor.intercept(url, request, new HttpInterceptorChain(this.#interceptors, this.#current + 1));\n    }\n}\n\nclass HttpClient {\n    #interceptors;\n    /**\n     * Creates a builder for an HttpClient.\n     * @returns {HttpClientBuilder} the client builder\n     */\n    static builder() {\n        return new HttpClientBuilder();\n    }\n    /**\n     * Creates an HttpClient.\n     * @param {HttpInterceptor[]|undefined} interceptors - a list of interceptors to be registered for every request performed by the created client. \n     */\n    constructor(interceptors) {\n        this.#interceptors = interceptors || [];\n    }\n    /**\n     * Performs an HTTP exchange.\n     * @async\n     * @param {string} uri - the (possibly relative) request url\n     * @param {RequestInit|undefined} options - fetch options\n     * @param {HttpInterceptor[]|undefined} interceptors - the HttpInterceptors to be registered for this exchange.\n     * @returns {Promise<Response>} the response\n     */\n    async exchange(uri, options, interceptors) {\n        const is = [...this.#interceptors, ...interceptors || [], new HttpCall()];\n        const chain = new HttpInterceptorChain(is, 0);\n        const url = new URL(new Request(uri).url);\n        return await chain.proceed(url, options ?? {});\n    }\n    /**\n     * Creates a request builder.\n     * @param {string} method - the HTTP method to be used\n     * @param {string} uri - the (possibly relative) request url\n     * @returns {HttpRequestBuilder} the request builder\n     */\n    request(method, uri) {\n        return HttpRequestBuilder.create(this, method, uri);\n    }\n    /**\n     * Creates a request builder.\n     * @param {string} uri - the (possibly relative) request url \n     * @returns {HttpRequestBuilder} the request builder\n     */\n    get(uri) {\n        return HttpRequestBuilder.create(this, 'GET', uri);\n    }\n    /**\n     * Creates a request builder.\n     * @param {string} uri - the (possibly relative) request url\n     * @returns {HttpRequestBuilder} the request builder\n     */\n    head(uri) {\n        return HttpRequestBuilder.create(this, 'HEAD', uri);\n    }\n    /**\n     * Creates a request builder.\n     * @param {string} uri - the (possibly relative) request url\n     * @returns {HttpRequestBuilder} the request builder\n     */\n    post(uri) {\n        return HttpRequestBuilder.create(this, 'POST', uri);\n    }\n    /**\n     * Creates a request builder.\n     * @param {string} uri - the (possibly relative) request url\n     * @returns {HttpRequestBuilder} the request builder\n     */\n    put(uri) {\n        return HttpRequestBuilder.create(this, 'PUT', uri);\n    }\n    /**\n     * Creates a request builder.\n     * @param {string} uri - the (possibly relative) request url\n     * @returns {HttpRequestBuilder} the request builder\n     */\n    patch(uri) {\n        return HttpRequestBuilder.create(this, 'PATCH', uri);\n    }\n    /**\n     * Creates a request builder.\n     * @param {string} uri - the (possibly relative) request url\n     * @returns {HttpRequestBuilder} the request builder\n     */\n    delete(uri) {\n        return HttpRequestBuilder.create(this, 'DELETE', uri);\n    }\n}\n\n/**\n * \n * @param {Response} response \n * @param {'text'|'json'|'blob'|'arrayBuffer'} type \n * @returns \n */\nconst unmarshal = async (response, type) => {\n    try {\n        return await response[type]();\n    } catch (ex) {\n        throw HttpClientError.of(\"UNMARSHALING_PROBLEM\", ex);\n    }\n}\n\nclass HttpRequestBuilder {\n    #client;\n    #method;\n    #uri;\n    #params;\n    #headers;\n    #body;\n    #options;\n    #interceptors;\n    /**\n     * Creates an HttpRequestBuilder.\n     * @param {HttpClient} client \n     * @param {string} method - the HTTP method to be used\n     * @param {string} uri - the (possibly relative) request url\n     * @returns {HttpRequestBuilder} the builder\n     */\n    static create(client, method, uri) {\n        return new HttpRequestBuilder(\n            client,\n            method,\n            uri,\n            new URLSearchParams(),\n            new Headers(),\n            undefined,\n            {},\n            []\n        );\n    }\n    /**\n     * Creates an HttpRequestBuilder.\n     * @param {HttpClient} client \n     * @param {string} method - the HTTP method to be used\n     * @param {string} uri - the (possibly relative) request url\n     * @param {URLSearchParams} params \n     * @param {Headers} headers \n     * @param {any} body \n     * @param {Omit<RequestInit,\"headers\"|\"method\"|\"body\">} options \n     * @param {HttpInterceptor[]} interceptors \n     */\n    constructor(client, method, uri, params, headers, body, options, interceptors) {\n        this.#client = client;\n        this.#method = method;\n        this.#uri = uri;\n        this.#params = params;\n        this.#body = body;\n        this.#headers = headers;\n        this.#options = options;\n        this.#interceptors = interceptors;\n    }\n    /**\n     * Add all passed headers to the request, overriding existing ones if that key already exists. Null and undefined values cause the key to be removed.\n     * @param {HeadersInit} hs \n     * @returns {HttpRequestBuilder} this builder\n     */\n    headers(hs) {\n        for (const [k, v] of new Headers(hs).entries()) {\n            if (v === null || v === undefined) {\n                this.#headers.delete(k);\n            } else {\n                this.#headers.set(k, v);\n            }\n        }\n        return this;\n    }\n    /**\n     * Adds an header to the request, overriding it if it already exists. Null and undefined values cause the key to be removed\n     * @param {string} k \n     * @param {string} v \n     * @returns {HttpRequestBuilder} this builder\n     */\n    header(k, v) {\n        if (v === null || v === undefined) {\n            this.#headers.delete(k);\n        } else {\n            this.#headers.set(k, v);\n        }\n        return this;\n    }\n    /**\n     * Add all query parameters to the request, overriding existing ones if that key already exists. Null and undefined values cause the key to be removed\n     * @param {URLSearchParams|Record<string,string>|string[][]|string} ps \n     * @returns {HttpRequestBuilder} this builder\n     */\n    params(ps) {\n        for (const [k, v] of new URLSearchParams(ps).entries()) {\n            if (v === null || v === undefined) {\n                this.#params.delete(k);\n            } else {\n                this.#params.set(k, v);\n            }\n        }\n        return this;\n    }\n    /**\n     * Adds a query parameter to the request, overriding it if it already exists. Empty vs, or a single null or undefined value cause the key to be removed.\n     * @param {string} k \n     * @param {...string} vs\n     * @returns {HttpRequestBuilder} this builder\n     */\n    param(k, ...vs) {\n        if (vs.length === 0 || vs[0] === null || vs[0] === undefined) {\n            this.#params.delete(k);\n            return this;\n        }\n        for (const v of vs) {\n            this.#params.append(k, v);\n        }\n        return this;\n    }\n    /**\n     * Sets the request body. \n     * `Content-Type: multipart/form-data` header is automatically added by fetch when data is a FormData instance if not explicitly set.\n     * `Content-Type: application/x-www-form-urlencoded` header is automatically added by fetch when data is an URLSearchParams instance if not explicitly set.\n     * `Content-Type: text/plain` header is automatically added by fetch when data is a string instance if not explicitly set.\n     * @param {string|ArrayBuffer|Blob|DataView|File|FormData|TypedArray|URLSearchParams|ReadableStream} data \n     * @returns {HttpRequestBuilder} this builder\n     */\n    body(data) {\n        this.#body = data;\n        return this;\n    }\n    /**\n     * Sets the request body that will be serialized as json. Calling this method adds the `Content-Type application/json` header for the request.\n     * @param {any} body - the body to be serialized as json\n     * @returns {HttpRequestBuilder} this builder\n     */\n    json(body) {\n        this.#headers.set(\"Content-Type\", \"application/json\");\n        this.#body = JSON.stringify(body);\n        return this;\n    }\n    /**\n     * Sets the request body as a FormData configured using the callback.\n     * `Content-Type: multipart/form-data` header is automatically added by fetch if not explicitly set.\n     * @param {function(HttpMultipartRequestCustomizer):void} callback\n     */\n    multipart(callback) {\n        const formData = new FormData();\n        const builder = new HttpMultipartRequestCustomizer(formData);\n        callback(builder);\n        this.#body = formData;\n        return this;\n    }\n    /**\n     * Sets a fetch options for the request.\n     * @param {Omit<RequestInit,\"headers\"|\"method\"|\"body\">} kvs\n     * @returns {HttpRequestBuilder} this builder\n     */\n    options(kvs) {\n        for (const [k, v] of Object.entries(kvs)) {\n            this.#options[k] = v;\n        }\n        return this;\n    }\n    /**\n     * Sets a fetch option for the request.\n     * @param {keyof Omit<RequestInit,\"headers\"|\"method\"|\"body\">} k \n     * @param {*} v \n     * @returns {HttpRequestBuilder} this builder\n     */\n    option(k, v) {\n        this.#options[k] = v;\n        return this;\n    }\n    /**\n     * Adds interceptors to the request.\n     * @param {[HttpInterceptor]} is - the interceptor to be regisered\n     * @returns {HttpRequestBuilder} this builder\n     */\n    interceptors(is) {\n        for (const i of is) {\n            this.#interceptors.push(i);\n        }\n        return this;\n    }\n    /**\n     * Adds an interceptor to the request.\n     * @param {HttpInterceptor} i - the interceptor to be regisered\n     * @returns {HttpRequestBuilder} this builder\n     */\n    interceptor(i) {\n        this.#interceptors.push(i);\n        return this;\n    }\n    /**\n     * Performs an HTTP exchange using the configured client, request and interceptors.\n     * @returns {Promise<Response>} the response\n     */\n    async exchange() {\n        const uri = this.#params.size ? `${this.#uri}?${this.#params}` : this.#uri;\n        const opts = {\n            ...this.#options,\n            headers: this.#headers,\n            method: this.#method,\n            body: this.#body,\n        };\n        return await this.#client.exchange(uri, opts, this.#interceptors);\n    }\n    /**\n     * Performs an HTTP exchange using the configured client request, and interceptos throwing a failure when response status is not in the 200-299 range.\n     * @returns {Promise<Response>} the response\n     */\n    async fetch() {\n        const uri = this.#params.size ? `${this.#uri}?${this.#params}` : this.#uri;\n        const opts = {\n            ...this.#options,\n            headers: this.#headers,\n            method: this.#method,\n            body: this.#body,\n        };\n        try {\n            const response = await this.#client.exchange(uri, opts, this.#interceptors);\n            if (!response.ok) {\n                throw await HttpClientError.fromResponse(response);\n            }\n            return response;\n        } catch (ex) {\n            if (ex instanceof Failure) {\n                throw ex;\n            }\n            throw HttpClientError.of(\"CONNECTION_PROBLEM\", ex);\n        }\n    }\n    /**\n     * Performs an HTTP exchange using the configured client request, and interceptos throwing a failure when response status is not in the 200-299 range.\n     * @returns {Promise<string>} the response body, as text\n     */\n    async fetchText() {\n        const response = await this.fetch();\n        return await unmarshal(response, 'text');\n    }\n    /**\n     * Performs an HTTP exchange using the configured client request, and interceptos throwing a failure when response status is not in the 200-299 range.\n     * @returns {Promise<any>} the response body, deserialized as JSON\n     */\n    async fetchJson() {\n        const response = await this.fetch();\n        return await unmarshal(response, 'json');\n    }\n    /**\n     * Performs an HTTP exchange using the configured client request, and interceptos throwing a failure when response status is not in the 200-299 range.\n     * @returns {Promise<Blob>} the response body, as a Blob\n     */\n    async fetchBlob() {\n        const response = await this.fetch();\n        return await unmarshal(response, 'blob');\n    }\n    /**\n     * Performs an HTTP exchange using the configured client request, and interceptos throwing a failure when response status is not in the 200-299 range.\n     * @returns {Promise<ArrayBuffer>} the response body, as an ArrayBuffer\n     */\n    async fetchArrayBuffer() {\n        const response = await this.fetch();\n        return await unmarshal(response, 'arrayBuffer');\n    }\n}\n\nclass HttpMultipartRequestCustomizer {\n    #formData;\n    /**\n     * \n     * @param {FormData} formData \n     */\n    constructor(formData) {\n        this.#formData = formData;\n    }\n    /**\n     * Appends a value to the FormData.\n     * @param {string} name \n     * @param {*} value \n     * @returns this builder\n     */\n    field(name, value) {\n        this.#formData.append(name, value);\n        return this;\n    }\n    /**\n     * Appends a Blob to the FormData. \n     * If `filename` is omitted, FormData defaults are applied:\n     * The default filename for Blob objects is \"blob\"; \n     * The default filename for File objects is the file's filename.\n     * @param {string} name \n     * @param {Blob} value \n     * @param {string|undefined} filename \n     * @returns this builder\n     */\n    blob(name, value, filename) {\n        this.#formData.append(name, value, filename);\n        return this;\n    }\n    /**\n     * Appends multiple Blobs to the FormData with the same name. \n     * The default filename for Blob objects is \"blob\"; \n     * The default filename for File objects is the file's filename.\n     * @param {string} name \n     * @param {Blob[]} values\n     * @returns this builder\n     */\n    blobs(name, values) {\n        for (let v of values) {\n            this.#formData.append(name, v);\n        }\n        return this;\n    }\n    /**\n     * Appends a JSON serialized blob to the FormData.\n     * @param {string} name \n     * @param {any} value \n     * @param {string|undefined} filename \n     * @returns this builder\n     */\n    json(name, value, filename) {\n        const blob = new Blob([JSON.stringify(value)], { type: 'application/json' });\n        this.#formData.append(name, blob, filename);\n        return this;\n    }\n}\n\nexport { MediaType, HttpClient, HttpClientError };\n","\nclass LocalStorage extends Storage {\n    static save(k, v) {\n        localStorage.setItem(k, JSON.stringify(v));\n    }\n    static load(k) {\n        const got = localStorage.getItem(k);\n        return got === null ? undefined : JSON.parse(got);\n    }\n    static remove(k) {\n        localStorage.removeItem(k);\n    }\n    static pop(k) {\n        const decoded = LocalStorage.load(k);\n        LocalStorage.remove(k);\n        return decoded;\n    }\n\n}\n\n\n\nclass SessionStorage extends Storage {\n    static save(k, v) {\n        sessionStorage.setItem(k, JSON.stringify(v));\n    }\n    static load(k) {\n        const got = sessionStorage.getItem(k);\n        return got === null ? undefined : JSON.parse(got);\n    }\n    static remove(k) {\n        sessionStorage.removeItem(k);\n    }\n    static pop(k) {\n        const decoded = SessionStorage.load(k);\n        SessionStorage.remove(k);\n        return decoded;\n    }\n}\n\nclass VersionedLocalStorage {\n    static save(key, revision, data){\n        LocalStorage.save(key, {revision, data});\n    }    \n    static load(key, revision){\n        const stored = LocalStorage.load(key);\n        if(stored === undefined){\n            return undefined;\n        }\n        if(stored.revision !== revision){\n            localStorage.removeItem(key);\n            return undefined;\n        }\n        return stored.data;\n    }\n}\n\nclass VersionedSessionStorage {\n    static save(key, revision, data){\n        SessionStorage.save(key, {revision, data});\n    }    \n    static load(key, revision){\n        const stored = SessionStorage.load(key);\n        if(stored === undefined){\n            return undefined;\n        }\n        if(stored.revision !== revision){\n            localStorage.removeItem(key);\n            return undefined;\n        }\n        return stored.data;\n    }\n}\n\n\nexport { LocalStorage, VersionedLocalStorage, SessionStorage, VersionedSessionStorage };","import { Base64 } from \"./encodings.mjs\";\nimport { SessionStorage } from \"./storage.mjs\";\n\n\nclass AuthorizationCodeFlow {\n    static forKeycloak(clientId, realmBaseUrl, redirectUri, maybeScope) {\n        const scope = maybeScope ?? \"openid profile\";\n        return new AuthorizationCodeFlow(clientId, scope, {\n            auth: new URL(\"protocol/openid-connect/auth\", realmBaseUrl),\n            token: new URL(\"protocol/openid-connect/token\", realmBaseUrl),\n            logout: new URL(\"protocol/openid-connect/logout\", realmBaseUrl),\n            registration: new URL(\"protocol/openid-connect/registrations\", realmBaseUrl),\n            redirect: redirectUri\n        });\n    }\n    constructor(clientId, scope, { auth, token, registration, logout, redirect }) {\n        this.clientId = clientId;\n        this.scope = scope;\n        this.uri = { auth, token, registration, logout, redirect };\n    }\n    async action(uri, additionalParams) {\n        const pkceVerifier = Base64.encode(crypto.getRandomValues(new Uint8Array(32)).buffer);\n        const pkceChallenge = Base64.encode(await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(pkceVerifier)));\n        const state = this.clientId + Base64.encode(crypto.getRandomValues(new Uint8Array(16)).buffer);\n        SessionStorage.save(`${AuthorizationCodeFlow.PKCE_AND_STATE_KEY}-${this.clientId}`, {\n            state: state,\n            verifier: pkceVerifier\n        });\n        const url = new URL(uri);\n        url.searchParams.set(\"client_id\", this.clientId);\n        url.searchParams.set(\"redirect_uri\", this.uri.redirect);\n        url.searchParams.set(\"response_type\", 'code');\n        url.searchParams.set(\"scope\", this.scope);\n        url.searchParams.set(\"state\", state);\n        url.searchParams.set(\"code_challenge\", pkceChallenge);\n        url.searchParams.set(\"code_challenge_method\", 'S256');\n        Object.entries(additionalParams || {}).forEach(kv => {\n            url.searchParams.set(kv[0], kv[1]);\n        });\n        window.location.href = url.toString();\n    }\n    async registration(additionalParams) {\n        await this.action(this.uri.registration, additionalParams);\n    }\n    async applicationInitiatedAction(kcAction, additionalParams) {\n        await this.action(this.uri.auth, {\n            ...additionalParams,\n            kc_action: kcAction,\n        });\n    }\n    async #tokenExchange(code, state) {\n        window.history.replaceState('', \"\", this.uri.redirect);\n        const stateAndVerifier = SessionStorage.pop(`${AuthorizationCodeFlow.PKCE_AND_STATE_KEY}-${this.clientId}`);\n        if (stateAndVerifier.state !== state) {\n            throw new Error(\"State mismatch\");\n        }\n        const response = await fetch(this.uri.token, {\n            method: \"POST\",\n            headers: {\n                \"Content-Type\": 'application/x-www-form-urlencoded'\n            },\n            body: new URLSearchParams([\n                [\"client_id\", this.clientId],\n                [\"code\", code],\n                [\"grant_type\", \"authorization_code\"],\n                [\"code_verifier\", stateAndVerifier.verifier],\n                [\"state\", stateAndVerifier.state],\n                [\"redirect_uri\", this.uri.redirect]\n            ])\n        });\n        if (!response.ok) {\n            const text = await response.text();\n            throw new Error(\"Error:\" + response.status + \": \" + text);\n        }\n        const token = await response.json();\n        return new AuthorizationCodeFlowSession(this.clientId, token, this.uri);\n    }\n    async ensureLoggedIn() {\n        const url = new URL(window.location.href);\n        const code = url.searchParams.get(\"code\");\n        if (code && SessionStorage.load(`${AuthorizationCodeFlow.PKCE_AND_STATE_KEY}-${this.clientId}`)) {\n            //if callback from keycloak and we have our state still stored\n            const state = url.searchParams.get(\"state\");\n            return await this.#tokenExchange(code, state);\n        }\n        //if not authorized\n        await this.action(this.uri.auth, {});\n        return null;\n    }\n}\nAuthorizationCodeFlow.PKCE_AND_STATE_KEY = \"state-and-verifier\";\n\nclass AuthorizationCodeFlowSession {\n    static parseToken(token) {\n        const [rawHeader, rawPayload, signature] = token.split(\".\");\n        const utf8decoder = new TextDecoder(\"utf-8\");\n        return {\n            header: JSON.parse(utf8decoder.decode(Base64.decode(rawHeader, Base64.STANDARD))),\n            payload: JSON.parse(utf8decoder.decode(Base64.decode(rawPayload, Base64.STANDARD))),\n            signature: signature\n        };\n    }\n    constructor(clientId, t, { token, logout, redirect }) {\n        this.clientId = clientId;\n        this.token = t;\n        this.idToken = AuthorizationCodeFlowSession.parseToken(t.id_token);\n        this.accessToken = AuthorizationCodeFlowSession.parseToken(t.access_token);\n        this.refreshToken = AuthorizationCodeFlowSession.parseToken(t.refresh_token);\n        this.uri = { token, logout, redirect }\n        this.refreshCallback = null;\n    }\n    onRefresh(callback) {\n        this.refreshCallback = callback;\n    }\n    async refresh() {\n        const response = await fetch(this.uri.token, {\n            method: \"POST\",\n            headers: {\n                \"Content-Type\": 'application/x-www-form-urlencoded'\n            },\n            body: new URLSearchParams([\n                [\"client_id\", this.clientId],\n                [\"grant_type\", \"refresh_token\"],\n                [\"refresh_token\", this.token.refresh_token]\n            ])\n        });\n        if (!response.ok) {\n            const text = await response.text();\n            throw new Error(\"Error:\" + response.status + \": \" + text);\n        }\n        const token = await response.json();\n        this.token = token;\n        this.idToken = AuthorizationCodeFlowSession.parseToken(token.id_token);\n        this.accessToken = AuthorizationCodeFlowSession.parseToken(token.access_token);\n        this.refreshToken = AuthorizationCodeFlowSession.parseToken(token.refresh_token);\n        if (this.refreshCallback) {\n            this.refreshCallback(this.token, this.accessToken, this.refreshToken);\n        }\n    }\n    shouldBeRefreshed(gracePeriod) {\n        const now = new Date().getTime();\n        const refreshTokenExpiresAt = this.refreshToken.payload.exp * 1000;\n        const expired = now > refreshTokenExpiresAt;\n        const shouldRefresh = now - gracePeriod > refreshTokenExpiresAt;\n        return !expired && shouldRefresh;\n    }\n    async refreshIf(gracePeriod) {\n        if (!this.shouldBeRefreshed(gracePeriod)) {\n            return;\n        }\n        await this.refresh();\n    }\n    logout() {\n        const url = new URL(this.uri.logout);\n        url.searchParams.set(\"post_logout_redirect_uri\", this.uri.redirect);\n        url.searchParams.set(\"id_token_hint\", this.token.id_token);\n        window.location.href = url.toString();\n    }\n\n    bearerToken() {\n        return `Bearer ${this.token.access_token}`;\n    }\n\n    interceptor(gracePeriodBefore, gracePeriodAfter) {\n        return new AuthorizationCodeFlowInterceptor(this, gracePeriodBefore, gracePeriodAfter);\n    }\n}\n\nclass AuthorizationCodeFlowInterceptor {\n    #session;\n    #gracePeriodBefore;\n    #gracePeriodAfter;\n    constructor(session, gracePeriodBefore, gracePeriodAfter) {\n        this.#session = session;\n        this.#gracePeriodBefore = gracePeriodBefore || 2000;\n        this.#gracePeriodAfter = gracePeriodAfter || 30000;\n    }\n    async intercept(url, request, chain) {\n        await this.#session.refreshIf(this.#gracePeriodBefore);\n        request.headers.set(\"Authorization\", this.#session.bearerToken());\n        const response = await chain.proceed(url, request);\n        await this.#session.refreshIf(this.#gracePeriodAfter);\n        return response;\n    }\n}\n\nexport { AuthorizationCodeFlow, AuthorizationCodeFlowSession, AuthorizationCodeFlowInterceptor };","class AsyncEvents {\n    static async fireAsync(el, evt) {\n        el.dispatchEvent(evt);\n        return await evt.async?.promise;\n    }\n    /**\n     * \n     * @param {*} el \n     * @param {*} type \n     * @param {*} fn returning the result\n     * @param {*} options \n     * @returns \n     */\n    static asyncOn(el, type, fn, options) {\n        const listener = async (event) => {\n            let resolve, reject;\n            const promise = new Promise((res, rej) => {\n                resolve = res;\n                reject = rej;\n            });\n            event.async = { promise };\n            try {\n                //@ts-ignore\n                resolve(await fn(event));\n            } catch (e) {\n                //@ts-ignore\n                reject(e);\n            }\n        };\n        el.addEventListener(type, listener, options);\n        return listener;\n    }\n    /**\n     * \n     * @param {*} el \n     * @param {*} type \n     * @param {*} listener the listener returned by asyncOn\n     * @param {*} options \n     */ \n    static asyncOff(el, type, listener, options) {\n        el.removeEventListener(type, listener, options);\n    }\n    static mixInto(...classes) {\n        for (const k of classes) {\n            Object.assign(k.prototype, {\n                async fireAsync(evt) {\n                    return await AsyncEvents.fireAsync(this, evt);\n                },\n                asyncOn(type, fn, options) {\n                    return AsyncEvents.asyncOn(this, type, fn, options);\n                },\n                asyncOff(type, listener, options) {\n                    return AsyncEvents.asyncOff(this, type, listener, options);\n                }\n            });\n        }\n    }\n}\n\nexport { AsyncEvents }","class Timing  {\n    static sleep(ms) {\n        return new Promise(resolve => setTimeout(resolve, ms));\n    }\n    static DEBOUNCE_DEFAULT = 0;\n    static DEBOUNCE_IMMEDIATE = 1;\n    /**\n     * Executes only after a period of inactivity (pause in events).\n     * Respond to the \"end\" of a series of events.\n     * @param {*} timeoutMs \n     * @param {*} func \n     * @param {*} [options]\n     * @returns {[function, function]}\n     */\n    static debounce(timeoutMs, func, options) {\n        const opts = options ?? Timing.DEBOUNCE_DEFAULT;\n        let tid = null;\n        let args = [];\n        let previousTimestamp = 0;\n\n        const later = () => {\n            const elapsed = new Date().getTime() - previousTimestamp;\n            if (timeoutMs > elapsed) {\n                tid = setTimeout(later, timeoutMs - elapsed);\n                return;\n            }\n            tid = null;\n            if (opts !== Timing.DEBOUNCE_IMMEDIATE) {\n                func(...args);\n            }\n            // This check is needed because `func` can recursively invoke `debounced`.\n            if (tid === null) {\n                args = [];\n            }\n        };\n\n        const debounced = function () {\n            args = [...arguments];\n            previousTimestamp = new Date().getTime();\n            if (tid === null) {\n                tid = setTimeout(later, timeoutMs);\n                if (opts === Timing.DEBOUNCE_IMMEDIATE) {\n                    func(...args);\n                }\n            }\n        };\n        const abort = () => clearTimeout(tid);\n        return [debounced, abort];\n    }\n    static THROTTLE_DEFAULT = 0;\n    static THROTTLE_NO_LEADING = 1;\n    static THROTTLE_NO_TRAILING = 2;\n    /**\n     * Executes at most once per specified time interval, regardless of ongoing events.\n     * @param {*} timeoutMs \n     * @param {*} func \n     * @param {*} [options]\n     * @returns {[function, function]}\n     */\n    static throttle(timeoutMs, func, options) {\n        const opts = options ?? Timing.THROTTLE_DEFAULT;\n        let tid = null;\n        let args = [];\n        let previousTimestamp = 0;\n\n        const later = () => {\n            previousTimestamp = (opts & Timing.THROTTLE_NO_LEADING) ? 0 : new Date().getTime();\n            tid = null;\n            func(...args);\n            if (tid === null) {\n                args = [];\n            }\n        };\n        const throttled = function () {\n            const now = new Date().getTime();\n            if (!previousTimestamp && (opts & Timing.THROTTLE_NO_LEADING)) {\n                previousTimestamp = now;\n            }\n            const remaining = timeoutMs - (now - previousTimestamp);\n            args = [...arguments];\n            if (remaining <= 0 || remaining > timeoutMs) {\n                if (tid !== null) {\n                    clearTimeout(tid);\n                    tid = null;\n                }\n                previousTimestamp = now;\n                func(...args);\n                if (tid === null) {\n                    args = [];\n                }\n            } else if (tid === null && !(opts & Timing.THROTTLE_NO_TRAILING)) {\n                tid = setTimeout(later, remaining);\n            }\n        };\n        const abort = () => clearTimeout(tid);\n        return [throttled, abort];\n    }\n}\n\nexport { Timing };","import { registry } from \"@optionfactory/ftl\"\n\nclass Loaders {\n    static fromAttributes(el, defaultLoader, options) {\n        const http = registry.component(\"http-client\");\n        const requestMapper = el.hasAttribute(\"request-mapper\") ? registry.component(el.getAttribute(\"request-mapper\")) : v => v;\n        const responseMapper = el.hasAttribute(\"response-mapper\") ? registry.component(el.getAttribute(\"response-mapper\")) : v => v;\n        const loaderClass = registry.component(el.getAttribute(\"loader\") ?? defaultLoader);\n        return loaderClass.create({\n            el,\n            http,\n            requestMapper,\n            responseMapper,\n            options: options ?? {}\n        });\n    }\n}\n\n\nexport { Loaders };","\nclass Bindings {\n\n    /**\n     * @param {{ [x: string]: any; }} obj\n     * @param {string} prefix\n     * @param {Set<String>} stops\n     * @return {{ [x: string]: any; }}\n     */\n    static flatten(obj, prefix, stops) {\n        return Object.keys(obj).reduce((acc, k) => {\n            const pre = prefix.length ? prefix + '.' + k : k;\n            if (!stops.has(pre) && typeof obj[k] === 'object' && obj[k] !== null) {\n                Object.assign(acc, Bindings.flatten(obj[k], pre, stops));\n            } else {\n                acc[pre] = obj[k];\n            }\n            return acc;\n        }, {});\n    }\n    \n    /**\n     * @param {any} result\n     * @param {string} path\n     * @param {any} value\n     */\n    static providePath(result, path, value) {\n        const keys = path.split(\".\").map((k) => /^[0-9]+$/.test(k) ? +k : k);\n        let current = result ?? {};\n        let previous = null;\n        for (let i = 0; ; ++i) {\n            const ckey = keys[i];\n            const pkey = keys[i - 1];\n            if (Number.isInteger(ckey) && !Array.isArray(current)) {\n                if (previous !== null) {\n                    previous[pkey] = current = [];\n                } else {\n                    result = current = [];\n                }\n            }\n            if (i === keys.length - 1) {\n                //when value is undefined we only want to define the property if it's not defined \n                current[ckey] = value !== undefined ? value : (ckey in current ? current[ckey] : null);\n                return result;\n            }\n            if (current[ckey] === undefined) {\n                current[ckey] = {};\n            }\n            previous = current;\n            current = current[ckey];\n        }\n    }\n    /**\n     * \n     * @param {Element & {dataset?: any} & {checked?: boolean} & {value?: any}} el \n     * @returns \n     */\n    static extract(el) {\n        if (el.getAttribute('type') === 'radio') {\n            if (!el.checked) {\n                return undefined;\n            }\n            return el.dataset['fulBindType'] === 'boolean' ? el.value === 'true' : el.value;\n        }\n        if (el.getAttribute('type') === 'checkbox') {\n            return el.checked;\n        }\n        if (el.dataset['fulBindType'] === 'boolean') {\n            return !el.value ? null : el.value === 'true';\n        }\n        if (el.tagName === 'INPUT' || el.tagName === 'SELECT') {\n            return el.value === '' || el.value === undefined ? null : el.value;\n        }\n        return el.value;\n    }\n\n    /**\n     * \n     * @param {HTMLFormElement} form \n     * @returns \n     */\n    static extractFrom(form){\n        let result = {};\n        for(const el of form.elements){\n            if(!el.hasAttribute(\"name\") || el.matches(\":disabled\")){\n                continue;\n            }\n            result = Bindings.providePath(result, /** @type {string} */(el.getAttribute('name')), Bindings.extract(el))\n        }\n        return result;\n    }\n   \n    /**\n     * \n     * @param {Element  & {checked?: boolean} & {value?: any}} el \n     * @returns \n     */    \n    static mutate(el, raw) {\n        if (el.getAttribute('type') === 'radio') {\n            el.checked = el.getAttribute('value') === raw;\n            return;\n        }\n        if (el.getAttribute('type') === 'checkbox') {\n            el.checked = raw;\n            return;\n        }\n        el.value = raw;\n    }\n\n    static mutateIn(form, values){\n        const names = Array.from(form.elements)\n            .map(el => el.getAttribute(\"name\"))\n            .filter(n => n);\n        for (const [flattenedKey, value] of Object.entries(Bindings.flatten(values, '', new Set(names)))) {\n            for(const el of form.querySelectorAll(`[name='${CSS.escape(flattenedKey)}']`)){\n                Bindings.mutate(el, value)\n            }\n        }\n    }\n\n\n    static errors(form, es, scrollOnError){\n        const fieldErrors = es.filter(e => e.type === 'FIELD_ERROR' || e.type === 'INVALID_FORMAT');\n        const globalErrors = es.filter(e => e.type !== 'FIELD_ERROR' && e.type !== 'INVALID_FORMAT');\n        form.querySelectorAll(`[name]`).forEach(el => el.setCustomValidity?.(\"\"));\n        form.querySelectorAll(\"ful-errors\").forEach(el => {\n            el.replaceChildren();\n            el.setAttribute('hidden', '');\n        });\n        fieldErrors.forEach(e => {\n            const name = e.context.replace(\"[\", \".\").replace(\"].\", \".\").replace(\"]\", \"\");\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 => input.setCustomValidity?.(e.reason, suffix));\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`)).sort((a,b) => a.getBoundingClientRect().y - b.getBoundingClientRect().y)[0]?.focus();\n    }\n}\n\n\nexport { Bindings }\n","import { Attributes, ParsedElement } from \"@optionfactory/ftl\"\nimport { Failure } from \"../failure.mjs\";\nimport { Bindings } from \"./bindings.mjs\"\nimport { Loaders } from \"./loaders.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)\n            .json(values)\n            .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, http, requestMapper, responseMapper }) {\n        const url = el.getAttribute(\"action\");\n        if (!url) {\n            return new LocalFormLoader(requestMapper, responseMapper);\n        }\n        const method = el.getAttribute(\"method\") ?? 'POST';\n        return new RemoteJsonFormLoader(http, url, method, requestMapper, responseMapper);\n    }\n}\n\nclass Form extends ParsedElement {\n    form;\n    render() {\n        const form = this.form = document.createElement('form');\n        form.setAttribute(\"novalidate\", \"\");\n        Attributes.forward('form-', this, form);\n        form.replaceChildren(...this.childNodes);\n        form.addEventListener('submit', async (e) => {\n            e.preventDefault();\n            e.stopPropagation();\n            await this.submit();\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    async submit() {\n        this.spinner(true)\n        try {\n            const loader = Loaders.fromAttributes(this, 'loaders:form');\n            const values = this.values;\n            let request = await loader.prepare(values, this)\n            try {\n                const se = new CustomEvent('submit', { bubbles: true, cancelable: true, detail: { values, request } });\n                if (!this.dispatchEvent(se)) {\n                    return;\n                }\n                const sre = new CustomEvent('submit:requested', { bubbles: true, cancelable: false, detail: { values: se.detail.values, request: se.detail.request} })\n                let response = await AsyncEvents.fireAsync(this, sre);\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(new CustomEvent('submit:success', { bubbles: true, cancelable: false, detail: { values, request, response: mapped } }))\n            } catch (e) {\n                this.dispatchEvent(new CustomEvent('submit:failure', { bubbles: true, cancelable: false, detail: { values, request, exception: e } }));\n                if (e instanceof Failure) {\n                    this.errors = e.problems;\n                }\n                console.warn(\"failed to submit form\", this, \"reason:\", e);\n            }\n        } finally {\n            this.spinner(false);\n        }\n    }\n    reset(){\n        this.form.reset();\n    }\n    spinner(spin) {\n        this.querySelectorAll('ful-spinner').forEach(el => {\n            const hel = /** @type HTMLElement */ (el);\n            hel.hidden = !spin;\n        })\n        this.querySelectorAll('[type=submit],[type=reset]').forEach(el => {\n            const hel = /** @type HTMLButtonElement */ (el);\n            hel.disabled = spin\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 \"@optionfactory/ftl\"\n\nclass Input extends ParsedElement {\n    static observed = ['value', 'readonly:presence'];\n    static slots = true;\n    static template = `\n        <div class=\"form-label\">\n            <label>{{{{ slots.default }}}}</label>\n            {{{{ slots.info }}}}\n        </div>\n        <div class=\"input-group\">\n            <span data-tpl-if=\"slots.ibefore\" class=\"input-group-text\">{{{{ slots.ibefore }}}}</span>\n            {{{{ slots.before }}}}\n            <input data-tpl-if=\"type != 'textarea'\" class=\"form-control\" data-tpl-type=\"type\" placeholder=\" \" form=\"\">\n            <textarea data-tpl-if=\"type == 'textarea'\" class=\"form-control\" placeholder=\" \" form=\"\"></textarea>\n            {{{{ slots.after }}}}\n            <span data-tpl-if=\"slots.iafter\" class=\"input-group-text\">{{{{ slots.iafter }}}}</span>\n        </div>\n        <ful-field-error></ful-field-error>\n    `;\n    static formAssociated = true;\n    _input;\n    _fieldError;\n    constructor() {\n        super();\n        this.internals = this.attachInternals();\n        this.internals.role = 'presentation';\n    }\n    _type() {\n        return this.getAttribute(\"type\") ?? 'text';\n    }\n    _fragment(type, slots) {\n        return this.template().withOverlay({ type, slots }).render();\n    }\n    render({ slots, observed, disabled }) {\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.disabled = disabled;\n        this.readonly = observed.readonly;\n        this.value = observed.value;\n\n        this._input.addEventListener('change', (evt) => {\n            evt.stopPropagation();\n            this.dispatchEvent(new CustomEvent('change', {\n                bubbles: true,\n                cancelable: false,\n                detail: {\n                    value: this.value\n                }\n            }));\n        });\n        const label = fragment.querySelector('label');\n        label.addEventListener('click', () => this.focus());\n        this._fieldError = fragment.querySelector('ful-field-error');\n        this._input.ariaDescribedByElements = [this._fieldError];\n        this._input.ariaLabelledByElements = [label];\n        this.replaceChildren(fragment);\n    }\n    get value() {\n        return this._input.value === '' ? null : this._input.value;\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    //@ts-ignore\n    get disabled() {\n        return this._input.hasAttribute('disabled');\n    }\n    set disabled(d) {\n        Attributes.toggle(this._input, 'disabled', d);\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.getAttribute(\"value\")\n    }\n}\n\nexport { Input };\n","import { ParsedElement } from \"@optionfactory/ftl\";\nimport { Input } from \"./input.mjs\";\n\n\n\n\nclass LocalDate extends ParsedElement {\n    render() {\n        const content = this.innerHTML.trim();\n        if (content === '') {\n            this.innerHTML = this.getAttribute('default') ?? '';\n            return;\n        }\n        const locale = this.getAttribute(\"locale\") ?? Intl.DateTimeFormat().resolvedOptions().locale;\n        const formatter = new Intl.DateTimeFormat(locale, { year: 'numeric', month: 'numeric', day: 'numeric' });\n        const [y, m, d] = content.split('-').map(Number);\n        this.innerHTML = formatter.format(new Date(y, m - 1, d));\n    }\n}\n\nclass Instant extends ParsedElement {\n    render() {\n        const content = this.innerHTML.trim();\n        if (content === '') {\n            this.innerHTML = this.getAttribute('default') ?? '';\n            return;\n        }\n        const locale = this.getAttribute(\"locale\") ?? Intl.DateTimeFormat().resolvedOptions().locale;\n        const format = new Intl.DateTimeFormat(locale, {\n            year: 'numeric',\n            month: 'numeric',\n            day: 'numeric',\n            hour: 'numeric',\n            minute: 'numeric',\n            second: 'numeric',\n            hour12: false\n        });\n        this.innerHTML = format.format(new Date(Instant.isoToLocal(content)));\n    }\n    static isoToLocal(iso) {\n        //this is so sad\n        const d = new Date(iso);\n        const pad = (n, v) => String(v).padStart(n, '0');\n        const date = `${d.getFullYear()}-${pad(2, d.getMonth() + 1)}-${pad(2, d.getDate())}`;\n        const time = `${pad(2, d.getHours())}:${pad(2, d.getMinutes())}:${pad(2, d.getSeconds())}.${pad(3, d.getMilliseconds())}`;\n        return `${date}T${time}`\n    }    \n}\n\n\nclass InputLocalDate extends Input {\n    static observed = ['value', 'readonly:presence', 'min', 'max', 'step'];\n    _type() {\n        return 'date';\n    }\n    render(conf){\n        const {observed} = conf;\n        super.render(conf);\n        this.min = observed.min;\n        this.max = observed.max;\n        this.step = observed.step;\n    }    \n    get min() {\n        const v = this._input.min;\n        return v === '' ? null : v;\n    }\n    set min(v) {\n        this._input.min = InputLocalDate.#fromIsoOrOffset(v);\n    }\n    get max() {\n        const v = this._input.max;\n        return v === '' ? null : v;\n    }\n    set max(v) {\n        this._input.max = InputLocalDate.#fromIsoOrOffset(v);\n    }\n    get step() {\n        const v = this._input.step;\n        return v === '' ? null : v;\n    }\n    set step(v) {\n        this._input.step = (v ?? '');\n    }\n    static #fromIsoOrOffset(v) {\n        if (!v) {\n            return '';\n        }\n        if (v === 'now') {\n            return new Date().toISOString().split(\"T\")[0];\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        switch (match[3]) {\n            case 'd':\n                r.setDate(r.getDate() + offset * sign);\n                break;\n            case 'm':\n                r.setMonth(r.getMonth() + offset * sign);\n                break;\n            case 'y':\n                r.setFullYear(r.getFullYear() + offset * sign);\n                break;\n        }\n        return r.toISOString().split(\"T\")[0];\n    }\n}\n\nclass InputLocalTime extends InputLocalDate {\n    _type() {\n        return 'time';\n    }\n}\n\n\nclass InputInstant extends Input {\n    static observed = ['value', 'readonly:presence', 'min', 'max', 'step'];\n    _type() {\n        return 'datetime-local';\n    }\n    render(conf){\n        const {observed} = conf;\n        super.render(conf);\n        this.min = observed.min;\n        this.max = observed.min;\n        this.step = observed.min;\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\n\n\n\nexport { Instant, LocalDate, InputLocalDate, InputLocalTime, InputInstant }","import { Attributes, ParsedElement } from \"@optionfactory/ftl\"\nimport { Loaders } from \"./loaders.mjs\";\nimport { Timing } from \"../timing.mjs\";\nimport { VersionedLocalStorage } from \"../storage.mjs\";\n\nclass RemoteLoader {\n    #http;\n    #url;\n    #method;\n    #responseMapper;\n    #prefetch;\n    #revision;\n    #data;\n    static create({ el, http, responseMapper }) {\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    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 #ensureFetched() {\n        if (this.#data !== null) {\n            return\n        }\n        const storageKey = `${this.#method}@${this.#url}`;\n        if(this.#revision !== null){\n            const data = VersionedLocalStorage.load(storageKey, this.#revision);\n            if(data !== undefined){\n                this.#data = data;\n                return;\n            }\n        }\n        const data = await this.#http.request(this.#method, this.#url)\n            .fetchJson()\n        this.#data = this.#responseMapper(data);\n        if(this.#revision !== null){\n            VersionedLocalStorage.save(storageKey, this.#revision, this.#data);\n        }\n    }\n}\n\nclass PartialRemoteLoader {\n    #http;\n    #url;\n    #method;\n    #responseMapper;\n    static create({ el, http, responseMapper }) {\n        return new PartialRemoteLoader({\n            http,\n            url: el.getAttribute(\"src\"),\n            method: el.getAttribute(\"method\") ?? 'POST',\n            responseMapper\n        });\n    }\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 data = await this.#http.request(this.#method, this.#url)\n            .param(\"k\", ...keys)\n            .fetchJson()\n        return this.#responseMapper(data);\n    }\n    async load(needle) {\n        const data = await this.#http.request(this.#method, this.#url)\n            .param(\"s\", needle)\n            .fetchJson()\n        return this.#responseMapper(data);\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\n\nclass SelectLoader {\n    static create(conf) {\n        if (!conf.el.hasAttribute(\"src\")) {\n            const els = Array.from(conf.options.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 chunked = \"chunked\" == conf.el.getAttribute(\"mode\");\n        return chunked ? PartialRemoteLoader.create(conf) : RemoteLoader.create(conf);\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\" hidden></menu>\n    `;\n    #spinner;\n    #menu;\n    #options = new Map();\n    render({ slots }) {\n        const fragment = this.template().render();\n        this.#spinner = fragment.querySelector(\"ful-spinner\");\n        this.#menu = fragment.querySelector(\"menu\");\n        this.#menu.addEventListener('click', evt => {\n            evt.stopPropagation();\n            if (!evt.target.matches('li')) {\n                this.hide();\n                return;\n            }\n            this.#change(evt.target);\n        });\n        this.replaceChildren(fragment);\n    }\n    acceptSelection() {\n        const selected = this.#menu.querySelector('[selected]') ?? this.#menu.firstElementChild;\n        this.#change(selected);\n    }\n    update(values) {\n        if (values === undefined) {\n            throw new Error(\"null data\");\n        }\n        this.#options = new Map(values.map((v,i) => [String(i), v]));\n        if (values.length === 0) {\n            const el = document.createElement('div');\n            el.classList.add('text-center', 'py-2', 'bi', 'bi-database-slash');\n            this.#menu.replaceChildren(el);\n            return;\n        }\n        this.#menu.replaceChildren(...values.map(([k, v, m], i) => {\n            const el = document.createElement('li');\n            if (i === 0) {\n                el.setAttribute(\"selected\", '');\n            }\n            el.setAttribute(\"value\", i);\n            el.innerText = v;\n            return el;\n        }));\n    }\n    #change(target) {\n        const index = target.getAttribute('value');\n        const data = this.#options.get(index)\n        this.hide();\n        this.dispatchEvent(new CustomEvent('change', {\n            bubbles: true,\n            cancelable: false,\n            detail: { index, data }\n        }));\n    }\n    hide() {\n        this.setAttribute('hidden', '')\n    }\n    get shown() {\n        return !this.hasAttribute('hidden');\n    }\n    async show(loader) {\n        this.removeAttribute('hidden');\n        this.#menu.setAttribute('hidden', '');\n        this.#spinner.removeAttribute('hidden');\n        try {\n            const data = await loader();\n            this.update(data);\n        } finally {\n            this.#spinner.setAttribute('hidden', '');\n            this.#menu.removeAttribute('hidden');\n        }\n    }\n    async moveOrShow(forward, loader) {\n        if (this.shown) {\n            const selected = this.#menu.querySelector('[selected]') ?? this.#menu.firstElementChild;\n            const candidate = selected[`${forward ? 'next' : 'previous'}ElementSibling`];\n            if (candidate) {\n                selected.removeAttribute('selected');\n                candidate.setAttribute(\"selected\", \"\");\n                candidate.scrollIntoView({block: \"nearest\", behavior: \"smooth\"});\n            }\n            return;\n        }\n        await this.show(loader);\n    }\n}\n\nclass Select extends ParsedElement {\n    static observed = ['value:csvm', 'readonly:presence']\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=\"\">\n                </div>\n                <ful-dropdown hidden popover=\"manual\"></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-field-error></ful-field-error>\n    `;\n    static mappers = {\n        \"csvm\": (v, name, el) => {\n            if (el.hasAttribute(\"multiple\")) {\n                return v === null ? [] : v.split(\",\").map(e => e.trim()).filter(e => e)\n            }\n            return v === null || v === '' ? null : v\n        }\n    };\n    static formAssociated = true\n    internals\n    #loader\n    #badges\n    #ddmenu\n    #input\n    #multiple\n    #fieldError\n    #values = new Map()\n    constructor() {\n        super();\n        this.internals = this.attachInternals();\n        this.internals.role = 'presentation';\n    }\n    async render({ slots, observed, disabled }) {\n        const name = this.getAttribute(\"name\");\n        this.#loader = Loaders.fromAttributes(this, 'loaders:select', { options: slots.options });\n        this.#multiple = this.hasAttribute(\"multiple\");\n        await this.#loader.prefetch?.();\n        const fragment = this.template().withOverlay({ slots, name }).render();\n        this.#input = fragment.querySelector('input');\n        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\n        this.#ddmenu = fragment.querySelector('ful-dropdown');\n        const label = fragment.querySelector('label');\n        label.addEventListener('click', () => this.focus());\n        this.#fieldError = fragment.querySelector('ful-field-error');\n        this.#input.ariaDescribedByElements = [this.#fieldError];\n        this.#input.ariaLabelledByElements = [label];\n\n        const self = this;\n        const [dload, abortdload] = Timing.throttle(400, () => self.#ddmenu.show(() => self.#loader.load(self.#input.value)));\n        this.addEventListener('click', (/** @type any */e) => {\n            if (e.target.matches('input')) {\n                return;\n            }\n            if(this.disabled || this.readonly){\n                return;\n            }\n            if (this.#ddmenu.shown) {\n                this.#ddmenu.hide();\n                return;\n            }\n            this.#input.focus();\n            dload();\n        })\n        this.#badges.addEventListener('click', (e) => {\n            e.stopPropagation();\n            if(this.disabled || this.readonly){\n                return;\n            }\n            const idx = [...this.#badges.children].indexOf(e.target);\n            if (idx === -1) {\n                return;\n            }\n            this.#values.delete(Array.from(this.#values.keys()).pop())\n            this.#changed();\n            this.#syncBadges();\n        })\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.#ddmenu.hide();\n            this.#input.value = '';\n        });\n        this.#input.addEventListener('keydown', e => {\n            e.stopPropagation();\n            if(this.disabled || this.readonly){\n                return;\n            }\n            switch (e.code) {\n                case 'ArrowUp': {\n                    this.#ddmenu.moveOrShow(false, () => self.#loader.load(self.#input.value));\n                    break;\n                }\n                case 'ArrowDown': {\n                    this.#ddmenu.moveOrShow(true, () => self.#loader.load(self.#input.value));\n                    break;\n                }\n                case 'Escape': {\n                    this.#ddmenu.hide();\n                    break;\n                }\n                case 'Enter': {\n                    this.#ddmenu.acceptSelection();\n                    this.#input.value = '';\n                    break;\n                }\n                case 'Backspace': {\n                    //remove last if caret a 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.#ddmenu.hide();\n                    abortdload();\n                    break;\n                }\n            }\n        });\n        this.#input.addEventListener('input', e => {\n            e.stopPropagation();\n            if(this.disabled || this.readonly){\n                return;\n            }\n            dload();\n        });\n        this.#ddmenu.addEventListener('change', (e) => {\n            e.stopPropagation();\n            if (!this.#multiple) {\n                this.#values.clear();\n            }\n            this.#values.set(e.detail.data[0], e.detail.data.slice(1));\n            this.#changed();\n            this.#syncBadges();\n            this.#input.focus();\n            this.#ddmenu.hide();\n        });\n        this.replaceChildren(fragment);\n    }\n    withLoader(fn) {\n        fn(this.#loader);\n    }\n    #changed() {\n        const selection = [...this.#values.entries()].map(e => ({key: e[0], label: e[1][0], metadata: e[1].slice(1)}))\n        const value = this.#multiple ? selection : (selection[0] ?? null);\n        this.dispatchEvent(new CustomEvent('change', {\n            bubbles: true,\n            cancelable: false,\n            detail: { value }\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.innerHTML = '';\n        this.#badges.append(...badges);\n    }\n    set value(vs) {\n        if(vs === null){\n            this.#values = new Map();\n            this.#syncBadges();\n            return;            \n        }\n        (async () => {\n            const entries = await (this.#multiple ? this.#loader.exact(...vs) : this.#loader.exact(vs));\n            this.#values = new Map(entries.map(e => [e[0], e.slice(1)]));\n            this.#syncBadges();\n        })();\n    }\n    get value() {\n        if (this.#multiple) {\n            return [...this.#values.keys()];\n        }\n        return [...this.#values.keys()][0] ?? null;\n    }\n    get entry() {\n        if (this.#multiple) {\n            return [...this.#values.entries()];\n        }\n        return [...this.#values.entries()][0] ?? null;\n    }\n    //@ts-ignore\n    get disabled(){\n        return this.#input.hasAttribute('disabled');\n    }\n    set disabled(d){\n        Attributes.toggle(this.#input, 'disabled', d);\n    }    \n    get readonly(){\n        return this.#input.readOnly;        \n    }\n    set readonly(v) {\n        this.#input.readOnly = v;\n        this.reflect(() => {\n            Attributes.toggle(this, 'readonly', v);\n        })\n    }    \n    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 { SelectLoader, Select, Dropdown };","import { Attributes, Fragments, ParsedElement } from \"@optionfactory/ftl\"\n\nclass RadioGroup extends ParsedElement {\n    static observed = ['value', 'readonly: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(new CustomEvent('change', {\n                    bubbles: true,\n                    cancelable: false,\n                    detail: {\n                        value: this.value\n                    }\n                }));\n            });\n            const label = Fragments.fromChildNodes(el);\n            return [input, label];\n        });\n\n        radioEls.forEach(el => el.remove());\n        this.template().withOverlay({ name, slots, inputsAndLabels }).renderTo(this);\n        this.#fieldset = this.firstElementChild;\n        this.disabled = disabled;\n        this.readonly = observed.readonly;\n        this.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    //@ts-ignore\n    get disabled(){\n        return this.#fieldset.hasAttribute('disabled');\n    }\n    set disabled(d){\n        Attributes.toggle(this.#fieldset, 'disabled', d);\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 };","import { Attributes, ParsedElement } from \"@optionfactory/ftl\";\n\nclass Checkbox extends ParsedElement {\n    static observed = ['value:bool', 'readonly: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\" role=\"switch\" 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 klass = this.getAttribute('type') == 'switch' ? \"form-check form-switch\" : \"form-check\";\n        const fragment = this.template().withOverlay({ slots, klass }).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.value = observed.value;\n        this.#input.addEventListener('change', (evt) => {\n            evt.stopPropagation();\n            this.dispatchEvent(new CustomEvent('change', {\n                bubbles: true,\n                cancelable: false,\n                detail: {\n                    value: this.value\n                }\n            }));\n        });\n        const label = fragment.querySelector('label');\n        label.addEventListener('click', () => {\n            this.focus();\n            if (this.disabled || this.readonly) {\n                return;\n            }\n            this.value = !this.value;\n        });\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    //@ts-ignore\n    get disabled() {\n        return this.#input.hasAttribute('disabled');\n    }\n    set disabled(d) {\n        Attributes.toggle(this.#input, 'disabled', d);\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 }","import { ParsedElement } from \"@optionfactory/ftl\"\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 };","import { Attributes, Fragments, Nodes, ParsedElement, Rendering } from \"@optionfactory/ftl\"\nimport { Loaders } from \"./loaders.mjs\";\n\nclass SortButton extends ParsedElement {\n    static observed = [\"order\"];\n    #order;\n    render() {\n        const sorter = this.getAttribute(\"sorter\");\n        const orders = [\"asc\", \"desc\", null];\n        this.addEventListener('click', () => {\n            const nextOrder = orders[(orders.indexOf(this.order) + 1) % 3];\n            this.dispatchEvent(new CustomEvent('sort-requested', {\n                bubbles: true,\n                cancelable: true,\n                detail: {\n                    value: { sorter, order: nextOrder }\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    }\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 reload me-2\"><a role=\"button\"><i data-tpl-class=\"config.reloadIcon\"></i></a></li>                \n                <li class=\"page-item prev\">\n                    <a data-tpl-class=\"prev.enabled?'page-link':'page-link disabled'\" data-tpl-aria-label=\"#l10n:t('previous')\" role=\"button\" data-tpl-data-page=\"prev.index\">\n                        <i aria-hidden=\"true\" data-tpl-class=\"config.prevIcon\"></i>\n                    </a>\n                </li>\n                <li class=\"page-item\" data-tpl-each=\"pages\" data-tpl-var=\"page\">\n                    <a data-tpl-class=\"curr.index != page.index ? 'page-link': 'page-link disabled'\" role=\"button\" data-tpl-data-page=\"page.index\" >\n                        {{ page.label }}\n                    </a>\n                </li>\n                <li class=\"page-item next\">\n                    <a data-tpl-class=\"next.enabled?'page-link':'page-link disabled'\" data-tpl-aria-label=\"#l10n:t('next')\" role=\"button\" data-tpl-data-page=\"next.index\">\n                        <i aria-hidden=\"true\" data-tpl-class=\"config.nextIcon\"></i>\n                    </a>\n                </li>\n            </ul>\n        </nav>\n    `;\n    #total = 0;\n    #current = 0;\n    render({ observed }) {\n        this.update(observed.current ?? 0, observed.total ?? 0);\n        this.addEventListener('click', (/** @type any */evt) => {\n            const el = evt.target.closest('a');\n            if (!el) {\n                return;\n            }\n            this.dispatchEvent(new CustomEvent('page-requested', {\n                bubbles: true,\n                cancelable: true,\n                detail: {\n                    value: Number(el.dataset.page ?? this.#current)\n                }\n            }));\n\n        })\n    }\n    update(current, total) {\n        const maxRender = Number(this.getAttribute('pages') ?? \"5\");\n        const prev = { index: Math.max(0, current - 1), enabled: current > 0 };\n        const curr = { index: current, label: current + 1 };\n        const next = { index: Math.min(total, current + 1), enabled: current + 1 < total };\n        const pages = [{\n            index: current,\n            label: current + 1\n        }];\n        for (let mid = current, offset = 1; offset !== maxRender && pages.length != maxRender; ++offset) {\n            const p = mid - offset;\n            if (p >= 0) {\n                pages.unshift({ index: p, label: p + 1 });\n            }\n            const n = mid + offset;\n            if (n < total) {\n                pages.push({ index: n, label: n + 1 })\n            }\n        }\n        this.template().withOverlay({ total, prev, curr, next, pages }).renderTo(this);\n    }\n    get total() {\n        return this.#total;\n    }\n    set total(value) {\n        this.#total = value;\n        this.reflect(() => {\n            this.setAttribute('total', String(value));\n            this.update(this.#current ?? 0, this.#total);\n        })\n    }\n    get current() {\n        return this.#current;\n    }\n    set current(value) {\n        this.#current = value;\n        this.reflect(() => {\n            this.setAttribute('current', String(value));\n            this.update(this.#current, this.#total ?? 0);\n        })\n    }\n}\n\nclass TableSchemaParser {\n    static parse(nodeOrFragment, template) {\n        const schema = Nodes.queryChildren(nodeOrFragment, \"schema\");\n        if (!schema) {\n            throw new Error(`missing expected <schema> in ${nodeOrFragment}`);\n        }\n        return Nodes.queryChildrenAll(schema, \"column\")\n            .map(el => {\n                return {\n                    sorter: el.getAttribute(\"sorter\"),\n                    order: el.getAttribute(\"order\"),\n                    title: TableSchemaParser.#parseTitle(el, template),\n                    content: TableSchemaParser.#parseContent(el, template)\n                }\n            });\n    }\n\n    static #parseTitle(el, template) {\n        const maybeTitleTag = Nodes.queryChildren(el, 'title');\n        if (maybeTitleTag) {\n            maybeTitleTag.remove();\n        }\n        const fragment = maybeTitleTag ? template.withFragment(Fragments.fromChildNodes(maybeTitleTag)).render() : document.createTextNode(el.getAttribute(\"title\") ?? '');\n        return {\n            classes: el.getAttribute(\"th-class\"),\n            fragment\n        };\n    }\n\n    static #parseContent(el, template) {\n        return {\n            classes: el.getAttribute(\"td-class\"),\n            template: template.withFragment(Fragments.fromChildNodes(el))\n        }\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.request(this.#method, this.#url)\n            .param(\"page\", pageRequest.page)\n            .param(\"size\", pageRequest.size)\n            .param(\"sort\", sortRequest.order ? `${sortRequest.sorter},${sortRequest.order}` : null)\n            .param(\"filters\", filters.length > 0 ? JSON.stringify(Object.fromEntries(filters)) : null)\n            .fetchJson();\n    }    \n}\n\n\nclass TableLoader{\n    static create({el, http}){\n        const url = el.getAttribute(\"src\");\n        const method = el.getAttribute(\"method\") ?? 'GET';\n        return new RemoteTableLoader(http, url, method);\n    }\n}\n\nclass Table extends ParsedElement {\n    static slots = true;\n    static l10n = {\n        en: {\n            'notloaded': 'Start searching to see results.',\n            'error': 'Error while loading data:',\n            'nodata': 'No elements found.',\n        },\n        it: {\n            'notloaded': 'Avvia la ricerca per visualizzare i risultati.',\n            'error': 'Errore nel caricamento dei dati:',\n            'nodata': 'Nessun elemento trovato.',\n        }\n    }\n    static conf = {\n        sortIcon: '',\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>\n                    <tr>\n                        <th data-tpl-each=\"schema\" scope=\"col\" data-tpl-class=\"title.classes\">\n                            {{{{ title.fragment }}}}\n                            <ful-sorter data-tpl-if=\"sorter || order\" data-tpl-sorter=\"sorter\" data-tpl-order=\"order\"></ful-sorter>\n                        </th>\n                    </tr>\n                </thead>\n                <tbody></tbody>\n                <tbody data-ref=\"no-autoload\">\n                    <tr>\n                        <td data-tpl-colspan=\"schema.length\" class=\"text-center align-middle p-4\">\n                            <i class=\"bi bi-search\" style=\"font-size: 40px; color: #BDC3CA\"></i>\n                            <p class=\"mt-3 mb-0\" style=\"color: #BDC3CA\">\n                                {{ #l10n:t('notloaded') }}\n                            </p>\n                        </td>\n                    </tr>\n                </tbody>\n                <tbody data-ref=\"loading\" hidden>\n                    <tr>\n                        <td data-tpl-colspan=\"schema.length\" class=\"text-center align-middle p-4\">\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\" class=\"text-center align-middle p-4\">\n                            <div class=\"alert alert-danger\">\n                                <p>{{ #l10n:t('error') }}</p>\n                                <p class=\"mb-0\" data-ref=\"feedback-error\"></p>\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            <tr data-tpl-each=\"pageResponse.data\" data-tpl-var=\"row\">\n                <td data-tpl-each=\"schema\" data-tpl-class=\"content.classes\">\n                    {{{{ content.template.withOverlay(row).render() }}}}\n                </td>\n            </tr>\n        `\n    };\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.default, 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.#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=no-autoload]\");\n        this.#feedback = table.querySelector(\":scope > tbody[data-ref=feedback]\");\n        this.#paginator = Nodes.queryChildren(fragment, 'ful-pagination');\n        this.#sorters = table.querySelectorAll(':scope > thead ful-sorter') ?? [];\n        this.replaceChildren(fragment);\n        await Rendering.waitForChildren(this);\n        const orderFromSchema = schema.find(v => v.order);\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: { order: orderFromSchema?.order, sorter: orderFromSchema?.sorter },\n            filterRequest: maybeForm?.values ?? {}\n        }\n        maybeForm?.addEventListener('submit:success', async (evt) => {\n            await this.load({\n                page: 0,\n                size: this.#latestRequest.pageRequest.size\n            }, this.#latestRequest.sortRequest, evt.detail.request);\n        })\n        this.addEventListener('page-requested', async (/** @type any */e) => {\n            await this.load({\n                page: e.detail.value,\n                size: this.#latestRequest.pageRequest.size\n            }, this.#latestRequest.sortRequest, this.#latestRequest.filterRequest);\n        });\n        this.addEventListener('sort-requested', async (/** @type any */e) => {\n            await this.load(this.#latestRequest.pageRequest, e.detail.value, this.#latestRequest.filterRequest);\n            this.#sorters.forEach(s => s.order = null);\n            e.target.order = e.detail.value.order;\n        })\n        if (this.hasAttribute('autoload')) {\n            await this.reload();\n        }\n    }\n\n    async reload() {\n        return await this.load(this.#latestRequest.pageRequest, this.#latestRequest.sortRequest, this.#latestRequest.filterRequest);\n    }\n    async load(pageRequest, sortRequest, filterRequest) {\n        this.#body.innerHTML = \"\";\n        this.#loading.removeAttribute(\"hidden\", \"\");\n        this.#feedback.setAttribute(\"hidden\", \"\");\n        this.#noAutoload.setAttribute(\"hidden\", \"\");\n        try {\n            const loader = Loaders.fromAttributes(this, 'loaders:table');\n            const pageResponse =await 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(p => `${p.reason}`);\n            }\n            throw error;\n        }\n    }\n\n    async resetWithFilter(filterRequest) {\n        return await this.load({\n            page: 0,\n            size: this.#latestRequest.pageRequest.size\n        }, this.#latestRequest.sortRequest, filterRequest);\n    }\n\n    #update(pageRequest, sortRequest, filterRequest, pageResponse) {\n        this.#loading.setAttribute(\"hidden\", \"\");\n        this.#body.replaceChildren(this.template('row').withOverlay({\n            schema: this.#schema,\n            pageRequest,\n            filterRequest,\n            pageResponse\n        }).render());\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 }","import { Attributes, Fragments, ParsedElement } from \"@optionfactory/ftl\";\nimport { Instant } from \"./temporals.mjs\";\n\nclass InstantFilter extends ParsedElement {\n    static observed = [\"value:json\"];\n    static slots = true;\n    static template = `\n        <div class=\"form-label\" data-tpl-if=\"label\">\n            <label>{{{{ label }}}}</label>\n            {{{{ slots.info }}}}\n        </div>\n        <div class=\"input-group\">\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            <span class=\"input-group-text\"><i class=\"bi bi-search\"></i></span>\n        </div>\n        <ful-field-error></ful-field-error>\n    `;\n    static formAssociated = true;\n    #operator;\n    #value1;\n    #value2;\n    #fieldError;\n    constructor() {\n        super();\n        this.internals = this.attachInternals();\n    }\n    render({ slots }) {\n        const label = Fragments.toHtml(slots.default.cloneNode(true)).trim().length === 0 ? null : slots.default;\n        const name = this.getAttribute(\"name\")\n        const fragment = this.template().withOverlay({ slots, label, name  }).render();\n        this.#operator = fragment.querySelector('[data-ref=operator]');\n        this.#value1 = fragment.querySelector('[data-ref=value1]');\n        this.#value2 = fragment.querySelector('[data-ref=value2]');\n        this.#fieldError = fragment.querySelector('ful-field-error');\n        const labelEl = fragment.querySelector('label')\n        labelEl?.addEventListener('click', () => this.focus());\n        this.#value1.ariaDescribedByElements = [this.#fieldError];\n        this.#value1.ariaLabelledByElements = labelEl ? [labelEl] : [];\n        this.replaceChildren(fragment);\n        this.addEventListener('click', (evt) => {\n            const target = /** @type HTMLElement */ (evt.target);\n            if (!target.matches('ul > li > a')) {\n                return;\n            }\n            const btn = /** @type HTMLButtonElement */ (target.closest('ul')?.previousElementSibling);\n            const value = /** @type String */ (target.getAttribute(\"value\"));\n            Attributes.toggle(this.#value2, 'hidden', value !== 'BETWEEN');\n            btn.setAttribute('value', value);\n            btn.innerHTML = target.innerHTML;\n        })\n    }\n\n    get value() {\n        const operator = this.#operator.getAttribute('value');\n        const values = operator === 'BETWEEN' ? [this.#value1.value, this.#value2.value] : [this.#value1.value];\n        return values.some(v => v === '') ? undefined : [operator, ...values.map(v => new Date(v).toISOString())];\n    }\n    set value(v) {\n        if (v === null || v === undefined) {\n            this.#value1.value = '';\n            this.#value2.value = '';\n            this.reflect(() => {\n                this.removeAttribute('value');\n            });\n            return;\n        }\n        const [operator, ...values] = v;\n        this.#operator.setAttribute('value', operator);\n        this.#value1.value = values[0] ? Instant.isoToLocal(values[0]) : values[0];\n        this.#value2.value = values[1] ? Instant.isoToLocal(values[1]) : values[1];\n        this.reflect(() => {\n            this.setAttribute('value', JSON.stringify(v));\n        });\n    }\n    focus(options) {\n        this.#value1.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\nclass LocalDateFilter extends ParsedElement {\n    static observed = [\"value:json\"];\n    static slots = true;\n    static template = `\n        <div class=\"form-label\" data-tpl-if=\"label\">\n            <label>{{{{ label }}}}</label>\n            {{{{ slots.info }}}}\n        </div>\n        <div class=\"input-group\">\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            <span class=\"input-group-text\"><i class=\"bi bi-search\"></i></span>\n        </div>\n        <ful-field-error></ful-field-error>\n    `;\n    static formAssociated = true;\n    #operator;\n    #value1;\n    #value2;\n    #fieldError;\n    constructor() {\n        super();\n        this.internals = this.attachInternals();\n    }\n    render({ slots }) {\n        const label = Fragments.toHtml(slots.default.cloneNode(true)).trim().length === 0 ? null : slots.default;\n        const name = this.getAttribute(\"name\")\n        const fragment = this.template().withOverlay({ slots, label, name }).render();\n        this.#operator = fragment.querySelector('[data-ref=operator]');\n        this.#value1 = fragment.querySelector('[data-ref=value1]');\n        this.#value2 = fragment.querySelector('[data-ref=value2]');\n        this.#fieldError = fragment.querySelector('ful-field-error');\n        const labelEl = fragment.querySelector('label')\n        labelEl?.addEventListener('click', () => this.focus());\n        this.#value1.ariaDescribedByElements = [this.#fieldError];\n        this.#value1.ariaLabelledByElements = labelEl ? [labelEl] : [];\n        this.replaceChildren(fragment);\n        this.addEventListener('click', (evt) => {\n            const target = /** @type HTMLElement */(evt.target);\n            if (!target.matches('ul > li > a')) {\n                return;\n            }\n            const btn = /** @type HTMLButtonElement */ (target.closest('ul')?.previousElementSibling);\n            const value = /** @type String */ (target.getAttribute(\"value\"));\n            Attributes.toggle(this.#value2, 'hidden', value !== 'BETWEEN');\n            btn.setAttribute('value', value);\n            btn.innerHTML = target.innerHTML;\n        })\n    }\n    get value() {\n        const operator = this.#operator.getAttribute('value');\n        const values = operator == 'BETWEEN' ? [this.#value1.value, this.#value2.value] : [this.#value1.value];\n        return values.some(v => v === '') ? undefined : [operator, \"ISO_8601\", ...values];\n    }\n    set value(v) {\n        if (v === null || v === undefined) {\n            this.#value1.value = '';\n            this.#value2.value = '';\n            this.reflect(() => {\n                this.removeAttribute('value');\n            });\n            return;\n        }\n        const [operator, ...values] = v;\n        this.#operator.setAttibute('value', operator);\n        this.#value1.value = values[0];\n        this.#value2.value = values[1];\n        this.reflect(() => {\n            this.setAttribute('value', JSON.stringify(v));\n        });\n    }\n    focus(options) {\n        this.#value1.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\nclass TextFilter extends ParsedElement {\n    static observed = [\"value:json\"];\n    static slots = true;\n    static template = `\n        <div class=\"form-label\" data-tpl-if=\"label\">\n            <label>{{{{ label }}}}</label>\n            {{{{ slots.info }}}}\n        </div>\n        <div class=\"input-group\">\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            <span class=\"input-group-text\"><i class=\"bi bi-search\"></i></span>\n        </div>\n        <ful-field-error></ful-field-error>\n    `;\n    static formAssociated = true;\n    #operator;\n    #value;\n    #fieldError;\n    constructor() {\n        super();\n        this.internals = this.attachInternals();\n    }\n    render({ slots }) {\n        const label = Fragments.toHtml(slots.default.cloneNode(true)).trim().length === 0 ? null : slots.default;\n        const name = this.getAttribute(\"name\")\n        const fragment = this.template().withOverlay({ slots, label, name }).render();\n        this.#operator = fragment.querySelector('[data-ref=operator]');\n        this.#value = fragment.querySelector('[data-ref=value]');\n        this.#fieldError = fragment.querySelector('ful-field-error');\n        const labelEl = fragment.querySelector('label')\n        labelEl?.addEventListener('click', () => this.focus());\n        this.#value.ariaDescribedByElements = [this.#fieldError];\n        this.#value.ariaLabelledByElements = labelEl ? [labelEl] : [];        \n        this.replaceChildren(fragment);\n        this.addEventListener('click', (evt) => {\n            const target = /** @type HTMLElement */(evt.target);\n            if (!target.matches('ul > li > a')) {\n                return;\n            }\n            const btn = /** @type HTMLButtonElement */ (target.closest('ul')?.previousElementSibling);\n            const value = /** @type String */ (target.getAttribute(\"value\"));\n            btn.setAttribute('value', value);\n            btn.innerHTML = target.innerHTML;\n        })\n    }\n\n    get value() {\n        const operator = this.#operator.getAttribute('value');\n        return this.#value.value === '' ? undefined : [operator, 'IGNORE_CASE', this.#value.value];\n    }\n\n    set value(v) {\n        if (v === null || v === undefined) {\n            this.#value.value = '';\n            this.reflect(() => {\n                this.removeAttribute('value');\n            });\n            return;\n        }\n        const [operator, sensitivity, value] = v;\n        this.#operator.setAttribute('value', operator);\n        this.#value.value = value;\n        this.reflect(() => {\n            this.setAttribute('value', JSON.stringify(v));\n        });\n    }\n    focus(options) {\n        this.#value.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 { InstantFilter, LocalDateFilter, TextFilter }","import { HttpClient } from \"../http-client.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 { RadioGroup } from \"./radio.mjs\";\nimport { SelectLoader, Dropdown, Select } from \"./select.mjs\";\nimport { Spinner } from \"./spinner.mjs\";\nimport { TableLoader, Table, Pagination, SortButton } from \"./table.mjs\";\n\n\nclass Plugin {\n    configure(registry) {\n        const httpClient = HttpClient.builder()\n            .withCsrfToken()\n            .withRedirectOnUnauthorized(\"/\")\n            .build();\n        registry\n            .defineModule(\"l10n\", {\n                t: function (k, ...args) {\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            })\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-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\n\n\nexport { Plugin }"],"names":["Base64","encode","arrayBuffer","dialect","d","URL_SAFE","len","byteLength","view","Uint8Array","res","i","substring","length","decode","str","nbytes","Math","floor","vi","si","v1","indexOf","charAt","v2","v3","v4","buffer","STANDARD","Hex","hex","Error","lenInBytes","map","e","offset","octet","parseInt","bytes","upper","Array","from","b","toString","toUpperCase","o","padStart","join","Failure","constructor","message","problems","cause","super","this","name","dropping","prefix","dropProblemsContext","type","context","reason","details","startsWith","MediaType","subtype","normalized","parse","v","_","split","ptype","psubtype","trim","toLowerCase","HttpClientError","status","of","fromResponse","response","headers","get","data","json","statusText","title","detail","text","CsrfTokenInterceptor","k","document","querySelector","getAttribute","intercept","url","request","chain","set","proceed","RedirectOnUnauthorizedInterceptor","redirectUri","window","location","href","HttpClientBuilder","interceptors","withCsrfToken","push","withRedirectOnUnauthorized","withInterceptors","build","HttpClient","HttpCall","fetch","Request","HttpInterceptorChain","current","interceptor","builder","exchange","uri","options","is","URL","method","HttpRequestBuilder","create","head","post","put","patch","unmarshal","async","ex","client","params","body","URLSearchParams","Headers","undefined","hs","entries","delete","header","ps","param","vs","append","JSON","stringify","multipart","callback","formData","FormData","HttpMultipartRequestCustomizer","kvs","Object","option","size","opts","ok","fetchText","fetchJson","fetchBlob","fetchArrayBuffer","field","value","blob","filename","blobs","values","Blob","LocalStorage","Storage","save","localStorage","setItem","load","got","getItem","remove","removeItem","pop","decoded","SessionStorage","sessionStorage","VersionedLocalStorage","key","revision","stored","VersionedSessionStorage","AuthorizationCodeFlow","forKeycloak","clientId","realmBaseUrl","maybeScope","auth","token","logout","registration","redirect","scope","action","additionalParams","pkceVerifier","crypto","getRandomValues","pkceChallenge","subtle","digest","TextEncoder","state","PKCE_AND_STATE_KEY","verifier","searchParams","forEach","kv","applicationInitiatedAction","kcAction","kc_action","tokenExchange","code","history","replaceState","stateAndVerifier","AuthorizationCodeFlowSession","ensureLoggedIn","parseToken","rawHeader","rawPayload","signature","utf8decoder","TextDecoder","payload","t","idToken","id_token","accessToken","access_token","refreshToken","refresh_token","refreshCallback","onRefresh","refresh","shouldBeRefreshed","gracePeriod","now","Date","getTime","refreshTokenExpiresAt","exp","refreshIf","bearerToken","gracePeriodBefore","gracePeriodAfter","AuthorizationCodeFlowInterceptor","session","AsyncEvents","fireAsync","el","evt","dispatchEvent","promise","asyncOn","fn","listener","event","resolve","reject","Promise","rej","addEventListener","asyncOff","removeEventListener","mixInto","classes","assign","prototype","Timing","sleep","ms","setTimeout","static","debounce","timeoutMs","func","DEBOUNCE_DEFAULT","tid","args","previousTimestamp","later","elapsed","DEBOUNCE_IMMEDIATE","arguments","clearTimeout","throttle","THROTTLE_DEFAULT","THROTTLE_NO_LEADING","remaining","THROTTLE_NO_TRAILING","Loaders","fromAttributes","defaultLoader","http","registry","component","requestMapper","hasAttribute","responseMapper","Bindings","flatten","obj","stops","keys","reduce","acc","pre","has","providePath","result","path","test","previous","ckey","pkey","Number","isInteger","isArray","extract","checked","dataset","tagName","extractFrom","form","elements","matches","mutate","raw","mutateIn","names","filter","n","flattenedKey","Set","querySelectorAll","CSS","escape","errors","es","scrollOnError","fieldErrors","globalErrors","setCustomValidity","replaceChildren","setAttribute","parts","replace","slice","suffix","input","innerText","removeAttribute","sort","a","getBoundingClientRect","y","focus","RemoteJsonFormLoader","prepare","submit","transform","LocalFormLoader","FormLoader","Form","ParsedElement","render","createElement","Attributes","forward","childNodes","preventDefault","stopPropagation","target","spinner","loader","se","CustomEvent","bubbles","cancelable","sre","mapped","exception","console","warn","reset","spin","hidden","disabled","Input","_input","_fieldError","internals","attachInternals","role","_type","_fragment","slots","template","withOverlay","observed","fragment","readonly","label","ariaDescribedByElements","ariaLabelledByElements","readOnly","reflect","toggle","error","setValidity","customError","formResetCallback","LocalDate","content","innerHTML","locale","Intl","DateTimeFormat","resolvedOptions","formatter","year","month","day","m","format","Instant","hour","minute","second","hour12","isoToLocal","iso","pad","String","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","getMilliseconds","InputLocalDate","conf","min","max","step","fromIsoOrOffset","toISOString","match","exec","sign","r","setDate","setMonth","setFullYear","InputLocalTime","InputInstant","RemoteLoader","prefetch","ensureFetched","exact","some","needle","includes","storageKey","PartialRemoteLoader","InMemoryLoader","update","SelectLoader","Dropdown","menu","Map","change","hide","acceptSelection","selected","firstElementChild","classList","add","index","shown","show","moveOrShow","candidate","scrollIntoView","block","behavior","Select","csvm","badges","ddmenu","multiple","fieldError","self","dload","abortdload","children","changed","syncBadges","relatedTarget","contains","selectionStart","selectionEnd","clear","withLoader","selection","metadata","entry","RadioGroup","fieldset","firstRadio","booleanType","uid","radioEls","default","inputsAndLabels","Fragments","fromChildNodes","renderTo","inert","Checkbox","container","klass","Spinner","SortButton","order","sorter","orders","nextOrder","Pagination","en","showing","navigation","next","it","prevIcon","nextIcon","reloadIcon","total","closest","page","maxRender","prev","enabled","curr","pages","mid","p","unshift","TableSchemaParser","nodeOrFragment","schema","Nodes","queryChildren","queryChildrenAll","parseTitle","parseContent","maybeTitleTag","withFragment","createTextNode","RemoteTableLoader","pageRequest","sortRequest","filterRequest","filters","fromEntries","TableLoader","Table","notloaded","nodata","sortIcon","row","loading","noAutoload","feedback","paginator","sorters","latestRequest","table","Rendering","waitForChildren","orderFromSchema","find","maybeForm","s","reload","pageResponse","textContent","resetWithFilter","ceil","InstantFilter","operator","value1","value2","toHtml","cloneNode","labelEl","btn","previousElementSibling","LocalDateFilter","setAttibute","TextFilter","sensitivity","Plugin","configure","httpClient","defineModule","l10n","language","defineComponent","defineElement","defineOverlay","navigator"],"mappings":"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"}