{
  "version": 3,
  "sources": ["../src/i18n/locales/sv/r-common.json", "../src/i18n/locales/sv/r-pipes.json", "../src/i18n/locales/sv/r-validation.json", "../src/errors.ts", "../src/collections/LinkedList.ts", "../src/collections/Pager.ts", "../src/forms/FormValidator.ts", "../src/i18n/icu.ts", "../src/i18n/catalogue.ts", "../src/i18n/locales/en/r-common.json", "../src/i18n/locales/en/r-pipes.json", "../src/i18n/locales/en/r-validation.json", "../src/i18n/builtins.ts", "../src/i18n/i18n.ts", "../src/forms/FormReader.ts", "../src/forms/ValidationRules.ts", "../src/forms/setFormData.ts", "../src/pipes.ts", "../src/html/html.ts", "../src/html/template.ts", "../src/templates/accessorParser.ts", "../src/templates/tokenizer.ts", "../src/templates/parseTemplate.ts", "../src/templates/NodeTemplate.ts", "../src/html/TableRenderer.ts", "../src/routing/types.ts", "../src/routing/NavigateRouteEvent.ts", "../src/routing/NavigationHistory.ts", "../src/routing/routeTargetRegistry.ts", "../src/routing/routeMatching.ts", "../src/routing/RouteLink.ts", "../src/routing/RoutingTarget.ts", "../src/routing/navigation.ts", "../src/DependencyInjection.ts", "../src/getParentComponent.ts", "../src/SequentialId.ts", "../src/http/http.ts", "../src/http/SseFrameParser.ts", "../src/http/ServerSentEvents.ts", "../src/tools.ts"],
  "sourcesContent": ["{\r\n    \"greeting\": \"Hej, {name}!\",\r\n    \"items\": \"{count, plural, one {# sak} other {# saker}}\"\r\n}\r\n", "{\r\n    \"today\": \"idag\",\r\n    \"yesterday\": \"ig\u00E5r\",\r\n    \"daysAgo\": \"{count, plural, one {# dag sedan} other {# dagar sedan}}\",\r\n    \"pieces\": \"{count, plural, =0 {inga} one {en} other {# st}}\"\r\n}\r\n", "{\r\n    \"required\": \"Detta f\u00E4lt \u00E4r obligatoriskt.\",\r\n    \"range\": \"Talet m\u00E5ste vara mellan {min} och {max}, var {actual}.\",\r\n    \"digits\": \"Ange endast siffror.\"\r\n}\r\n", "/**\r\n * Global error handling for Relaxjs.\r\n * Register a handler with `onError()` to intercept errors before they throw.\r\n * Call `ctx.suppress()` in the handler to prevent the error from being thrown.\r\n *\r\n * @example\r\n * import { onError } from 'relaxjs';\r\n *\r\n * onError((error, ctx) => {\r\n *     logToService(error.message, error.context);\r\n *     showToast(error.message);\r\n *     ctx.suppress();\r\n * });\r\n */\r\n\r\n/**\r\n * Passed to error handlers to control error behavior.\r\n * Call `suppress()` to prevent the error from being thrown.\r\n */\r\nexport interface ErrorContext {\r\n    suppress(): void;\r\n}\r\n\r\n/**\r\n * Error with structured context for debugging.\r\n * The `context` record contains details like route name, component tag, route data.\r\n *\r\n * @example\r\n * onError((error, ctx) => {\r\n *     console.log(error.context.route);\r\n *     console.log(error.context.componentTagName);\r\n * });\r\n */\r\nexport class RelaxError extends Error {\r\n    constructor(\r\n        message: string,\r\n        public context: Record<string, unknown>,\r\n    ) {\r\n        super(message);\r\n    }\r\n}\r\n\r\n/** @internal */\r\ntype ErrorHandler = (error: RelaxError, ctx: ErrorContext) => void;\r\n\r\nlet handler: ErrorHandler | null = null;\r\n\r\n/**\r\n * Registers a global error handler for Relaxjs errors.\r\n * The handler receives the error and an `ErrorContext`.\r\n * Call `ctx.suppress()` to prevent the error from being thrown.\r\n * Only one handler can be active at a time; subsequent calls replace the previous handler.\r\n *\r\n * @example\r\n * onError((error, ctx) => {\r\n *     if (error.context.route === 'optional-panel') {\r\n *         ctx.suppress();\r\n *         return;\r\n *     }\r\n *     showErrorDialog(error.message);\r\n * });\r\n */\r\nexport function onError(fn: ErrorHandler) {\r\n    handler = fn;\r\n}\r\n\r\n/**\r\n * Reports an error through the global handler.\r\n * Returns the `RelaxError` if it should be thrown, or `null` if the handler suppressed it.\r\n * The caller is responsible for throwing the returned error.\r\n *\r\n * @param message - Human-readable error description\r\n * @param context - Structured data for debugging (route, component, params, cause, etc.)\r\n * @returns The error to throw, or `null` if suppressed\r\n *\r\n * @example\r\n * const error = reportError('Failed to load route component', {\r\n *     route: 'user',\r\n *     componentTagName: 'user-profile',\r\n *     routeData: { id: 123 },\r\n * });\r\n * if (error) throw error;\r\n */\r\nexport function reportError(message: string, context: Record<string, unknown>): RelaxError | null {\r\n    const error = new RelaxError(message, context);\r\n    if (handler) {\r\n        let suppressed = false;\r\n        const ctx: ErrorContext = {\r\n            suppress() { suppressed = true; },\r\n        };\r\n        handler(error, ctx);\r\n        if (suppressed) {\r\n            return null;\r\n        }\r\n    }\r\n    return error;\r\n}\r\n\r\n/**\r\n * Wraps an async function into a synchronous callback suitable for addEventListener.\r\n * Catches promise rejections and reports them through the global error handler.\r\n *\r\n * @param fn - Async function to wrap\r\n * @returns Synchronous function that can be passed to addEventListener\r\n *\r\n * @example\r\n * button.addEventListener('click', asyncHandler(async (e) => {\r\n *     await saveData();\r\n * }));\r\n *\r\n * @example\r\n * form.addEventListener('submit', asyncHandler(async (e) => {\r\n *     e.preventDefault();\r\n *     await submitForm();\r\n * }));\r\n */\r\nexport function asyncHandler<TArgs extends unknown[]>(\r\n    fn: (...args: TArgs) => Promise<void>,\r\n): (...args: TArgs) => void {\r\n    return function (this: any, ...args: TArgs) {\r\n        fn.call(this, ...args).catch((cause: unknown) => {\r\n            const error = reportError('Async callback failed', { cause });\r\n            if (error) throw error;\r\n        });\r\n    };\r\n}\r\n", "/**\r\n * A node in the @see LinkedList.\r\n */\r\nexport class Node<T> {\r\n    /**\r\n     * Next node unless last one.\r\n     */\r\n    public next: Node<T> | null = null;\r\n    /**\r\n     * Previous node unless first one.\r\n     */\r\n    public prev: Node<T> | null = null;\r\n\r\n    /**\r\n     * Constructor.\r\n     * @param value Value contained in the node.\r\n     */\r\n    constructor(public value: T, private removeCallback: () => void) {}\r\n\r\n    /**\r\n     * Remove this node.\r\n     * Will notify the list of the update to ensure correct element count.\r\n     */\r\n    remove() {\r\n        if (this.prev) this.prev.next = this.next;\r\n        if (this.next) this.next.prev = this.prev;\r\n        this.removeCallback();\r\n    }\r\n}\r\n\r\n/**\r\n * A trivial linked list implementation.\r\n */\r\nexport class LinkedList<T> {\r\n    private _first: Node<T> | null = null;\r\n    private _last: Node<T> | null = null;\r\n    private _length = 0;\r\n\r\n    /**\r\n     * Add a value to the beginning of the list.\r\n     * @param value Value that should be contained in the node.\r\n     */\r\n    addFirst(value: T) {\r\n        const newNode = this.createNode(value);\r\n        if (!this._first) {\r\n            this._first = newNode;\r\n            this._last = this._first;\r\n        } else {\r\n            newNode.next = this._first;\r\n            this._first.prev = newNode;\r\n            this._first = newNode;\r\n        }\r\n\r\n        this._length++;\r\n    }\r\n\r\n    /**\r\n     * Add a value to the end of the list.\r\n     * @param value Value that should be contained in a node.\r\n     */\r\n    addLast(value: T) {\r\n        const newNode = this.createNode(value);\r\n        if (!this._last) {\r\n            this._first = newNode;\r\n            this._last = newNode;\r\n        } else {\r\n            newNode.prev = this._last;\r\n            this._last.next = newNode;\r\n            this._last = newNode;\r\n        }\r\n\r\n        this._length++;\r\n    }\r\n\r\n    private createNode(value: T): Node<T> {\r\n        let node: Node<T>;\r\n        node = new Node(value, () => {\r\n            if (this._first === node) this._first = node.next;\r\n            if (this._last === node) this._last = node.prev;\r\n            this._length--;\r\n        });\r\n        return node;\r\n    }\r\n\r\n    /**\r\n     * Remove a node from the beginning of the list.\r\n     * @returns Value contained in the first node.\r\n     */\r\n    removeFirst(): T {\r\n        if (!this._first) {\r\n            throw new Error('The list is empty.');\r\n        }\r\n\r\n        const value = this._first.value;\r\n        this._first = this._first.next;\r\n        if (!this._first) this._last = null;\r\n        this._length--;\r\n        return value;\r\n    }\r\n\r\n    /**\r\n     * Remove a node from the end of the list.\r\n     * @returns Value contained in the last node.\r\n     */\r\n    removeLast(): T {\r\n        if (!this._last) {\r\n            throw new Error('The list is empty.');\r\n        }\r\n\r\n        const value = this._last.value;\r\n        this._last = this._last.prev;\r\n        if (!this._last) this._first = null;\r\n        this._length--;\r\n        return value;\r\n    }\r\n\r\n    /**\r\n     * Number of nodes in the list.\r\n     *\r\n     * The count works as long as you do not manually remove nodes (by assigning next/prev to the neighbors).\r\n     */\r\n    get length(): number {\r\n        return this._length;\r\n    }\r\n\r\n    /**\r\n     * First node, or `null` if the list is empty.\r\n     */\r\n    get first(): Node<T> | null {\r\n        return this._first;\r\n    }\r\n\r\n    /**\r\n     * Contained value of the first node, or `undefined` if the list is empty.\r\n     */\r\n    get firstValue(): T | undefined {\r\n        return this._first?.value;\r\n    }\r\n\r\n    /**\r\n     * Last node, or `null` if the list is empty.\r\n     */\r\n    get last(): Node<T> | null {\r\n        return this._last;\r\n    }\r\n\r\n    /**\r\n     * Contained value of the last node, or `undefined` if the list is empty.\r\n     */\r\n    get lastValue(): T | undefined {\r\n        return this._last?.value;\r\n    }\r\n}\r\n", "export class PageSelectedEvent extends Event {\r\n  constructor(public page: number) {\r\n    super('pageselected', {\r\n      bubbles: true,\r\n      composed: true,\r\n    });\r\n  }\r\n}\r\n\r\ndeclare global {\r\n  interface HTMLElementEventMap {\r\n    'pageselected': PageSelectedEvent;\r\n  }\r\n}\r\n\r\nexport class Pager {\r\n  private container: HTMLElement;\r\n  private totalCount: number;\r\n  private pageSize: number;\r\n  private currentPage: number = 1;\r\n\r\n  constructor(container: HTMLElement, totalCount: number, pageSize: number) {\r\n    this.container = container;\r\n    this.totalCount = totalCount;\r\n    this.pageSize = pageSize;\r\n\r\n    this.render();\r\n  }\r\n\r\n  private render() {\r\n    this.container.innerHTML = '';\r\n\r\n    const pageCount = Math.max(1, Math.ceil(this.totalCount / this.pageSize));\r\n\r\n    const createButton = (label: string, page: number, disabled: boolean = false) => {\r\n      const btn = document.createElement('button');\r\n      btn.textContent = label;\r\n      btn.disabled = disabled;\r\n      btn.addEventListener('click', () => this.selectPage(page));\r\n      return btn;\r\n    };\r\n\r\n    this.container.appendChild(\r\n      createButton('Previous', this.currentPage - 1, this.currentPage === 1)\r\n    );\r\n\r\n    for (let i = 1; i <= pageCount; i++) {\r\n      const btn = createButton(i.toString(), i);\r\n      if (i === this.currentPage) {\r\n        btn.classList.add('selected');\r\n      }\r\n      this.container.appendChild(btn);\r\n    }\r\n\r\n    this.container.appendChild(\r\n      createButton('Next', this.currentPage + 1, this.currentPage === pageCount)\r\n    );\r\n  }\r\n\r\n  private selectPage(page: number) {\r\n    const pageCount = Math.max(1, Math.ceil(this.totalCount / this.pageSize));\r\n    if (page < 1 || page > pageCount || page === this.currentPage) return;\r\n\r\n    this.currentPage = page;\r\n    this.render();\r\n\r\n    this.container.dispatchEvent(new PageSelectedEvent(this.currentPage));\r\n  }\r\n\r\n  public update(totalCount: number) {\r\n    this.totalCount = totalCount;\r\n    const pageCount = Math.max(1, Math.ceil(this.totalCount / this.pageSize));\r\n    if (this.currentPage > pageCount) {\r\n      this.currentPage = pageCount;\r\n    }\r\n    this.render();\r\n  }\r\n\r\n  public getCurrentPage(): number {\r\n    return this.currentPage;\r\n  }\r\n}\r\n", "import { reportError } from '../errors';\r\n\r\n/**\r\n * @module FormValidator\r\n * Form validation with support for native HTML5 validation and error summaries.\r\n * Provides automatic validation on submit with customizable behavior.\r\n *\r\n * @example\r\n * // Basic usage with submit callback\r\n * const form = document.querySelector('form');\r\n * const validator = new FormValidator(form, {\r\n *     submitCallback: () => saveData()\r\n * });\r\n *\r\n * @example\r\n * // With auto-validation on input\r\n * const validator = new FormValidator(form, {\r\n *     autoValidate: true,\r\n *     useSummary: true\r\n * });\r\n */\r\n\r\n/**\r\n * Gets the human-readable field name from its associated label.\r\n */\r\nfunction getFieldName(element: HTMLElement): string | null {\r\n    const id = element.getAttribute('id');\r\n    if (id) {\r\n        const form = element.closest('form');\r\n        if (form) {\r\n            const label = form.querySelector(`label[for=\"${id}\"]`) as HTMLLabelElement | null;\r\n            if (label) {\r\n                return label.textContent?.trim() || null;\r\n            }\r\n        }\r\n    }\r\n\r\n    return null;\r\n}\r\n\r\n/**\r\n * Configuration options for FormValidator.\r\n */\r\nexport interface ValidatorOptions {\r\n    /** Validate on every input event, not just submit */\r\n    autoValidate?: boolean;\r\n    /** Show errors in a summary element instead of browser tooltips */\r\n    useSummary?: boolean;\r\n    /** Custom validation function called before native validation */\r\n    customChecks?: (form: HTMLFormElement) => void;\r\n    /** Always prevent default form submission */\r\n    preventDefault?: boolean;\r\n    /** Prevent default on validation failure (default: true) */\r\n    preventDefaultOnFailed?: boolean;\r\n    /** Callback invoked when form passes validation */\r\n    submitCallback?: () => void | Promise<void>;\r\n}\r\n\r\n/**\r\n * Form validation helper that integrates with HTML5 validation.\r\n * Supports error summaries, auto-validation, and custom submit handling.\r\n *\r\n * @example\r\n * // Prevent submission and handle manually\r\n * class MyComponent extends HTMLElement {\r\n *     private validator: FormValidator;\r\n *\r\n *     connectedCallback() {\r\n *         const form = this.querySelector('form');\r\n *         this.validator = new FormValidator(form, {\r\n *             submitCallback: () => this.handleSubmit()\r\n *         });\r\n *     }\r\n *\r\n *     private async handleSubmit() {\r\n *         const data = readData(this.form);\r\n *         await fetch('/api/save', { method: 'POST', body: JSON.stringify(data) });\r\n *     }\r\n * }\r\n *\r\n * @example\r\n * // With error summary display\r\n * const validator = new FormValidator(form, {\r\n *     useSummary: true,\r\n *     autoValidate: true\r\n * });\r\n */\r\nexport class FormValidator {\r\n    private errorSummary?: HTMLDivElement;\r\n\r\n    constructor(\r\n        private form: HTMLFormElement,\r\n        private options?: ValidatorOptions\r\n    ) {\r\n        if (!this.form) {\r\n            throw new Error('Form must be specified.');\r\n        }\r\n\r\n        this.form.addEventListener('submit', (event) => {\r\n            if (\r\n                options?.preventDefault ||\r\n                this.options?.submitCallback != null\r\n            ) {\r\n                event.preventDefault();\r\n            }\r\n            if (this.options?.customChecks) {\r\n                this.options.customChecks(form);\r\n            }\r\n\r\n            if (this.validateForm()) {\r\n                try {\r\n                    const result = this.options?.submitCallback?.call(this);\r\n                    if (result instanceof Promise) {\r\n                        result.catch((cause) => {\r\n                            const error = reportError('submitCallback failed', { cause });\r\n                            if (error) throw error;\r\n                        });\r\n                    }\r\n                } catch (cause) {\r\n                    const error = reportError('submitCallback failed', { cause });\r\n                    if (error) throw error;\r\n                }\r\n            } else {\r\n                if (options?.preventDefaultOnFailed !== false) {\r\n                    event.preventDefault();\r\n                }\r\n            }\r\n        });\r\n\r\n        if (options?.autoValidate) {\r\n            form.addEventListener('input', (/*e: InputEvent*/) => {\r\n                this.validateForm();\r\n            });\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Validates all form fields.\r\n     * Uses native HTML5 validation and optionally displays an error summary.\r\n     *\r\n     * @returns true if form is valid, false otherwise\r\n     */\r\n    public validateForm(): boolean {\r\n        const formElements = Array.from(\r\n            this.form.querySelectorAll('input,textarea,select')\r\n        ) as (HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement)[];\r\n        let isFormValid = true;\r\n\r\n        if (this.options?.useSummary !== true) {\r\n            if (this.form.checkValidity()) {\r\n                return true;\r\n            }\r\n\r\n            this.form.reportValidity();\r\n            this.focusFirstErrorElement();\r\n            return false;\r\n        }\r\n\r\n        const errorMessages: string[] = [];\r\n\r\n        formElements.forEach((element) => {\r\n            if (!element.checkValidity()) {\r\n                isFormValid = false;\r\n                const fieldName =\r\n                    getFieldName.call(this, element) ||\r\n                    element.name ||\r\n                    'Unnamed Field';\r\n                errorMessages.push(\r\n                    `${fieldName}: ${element.validationMessage}`\r\n                );\r\n            }\r\n        });\r\n\r\n        if (!isFormValid) {\r\n            this.displayErrorSummary(errorMessages);\r\n            this.focusFirstErrorElement();\r\n        } else {\r\n            this.clearErrorSummary();\r\n        }\r\n\r\n        return isFormValid;\r\n    }\r\n\r\n    /**\r\n     * Displays a list of error messages in the summary element.\r\n     *\r\n     * @param messages - Array of error messages to display\r\n     */\r\n    public displayErrorSummary(messages: string[]) {\r\n        this.clearErrorSummary();\r\n        if (!this.errorSummary){\r\n            this.createErrorSummary();\r\n        }\r\n\r\n        const errorList = this.errorSummary!.querySelector('ul')!;\r\n        messages.forEach((message) => {\r\n            const listItem = document.createElement('li');\r\n            listItem.textContent = message;\r\n            errorList.appendChild(listItem);\r\n        });\r\n    }\r\n\r\n    private createErrorSummary() {\r\n        const errorSummary = document.createElement('div');\r\n        errorSummary.className = 'error-summary';\r\n        errorSummary.style.color = 'red';\r\n        errorSummary.setAttribute('role', 'alert');\r\n        errorSummary.setAttribute('aria-live', 'assertive');\r\n        errorSummary.setAttribute('aria-atomic', 'true');\r\n        this.errorSummary = errorSummary;\r\n\r\n        const errorList = document.createElement('ul');\r\n        this.errorSummary.appendChild(errorList);\r\n\r\n        this.form.prepend(errorSummary);\r\n    }\r\n    /**\r\n     * Adds a single error to the summary display.\r\n     *\r\n     * @param fieldName - The name of the field with the error\r\n     * @param message - The error message\r\n     */\r\n    public addErrorToSummary(fieldName: string, message: string) {\r\n        if (!this.errorSummary){\r\n            this.createErrorSummary();\r\n        }\r\n        const errorList = this.errorSummary!.querySelector('ul')!;\r\n        const listItem = document.createElement('li');\r\n        listItem.textContent = `${fieldName}: ${message}`;\r\n        errorList.appendChild(listItem);\r\n    }\r\n\r\n    /**\r\n     * Clears all errors from the summary display.\r\n     */\r\n    public clearErrorSummary() {\r\n        if (this.errorSummary){\r\n            const ul = this.errorSummary.querySelector('ul');\r\n            if (ul) ul.innerHTML = '';\r\n        }\r\n    }\r\n\r\n    private focusFirstErrorElement() {\r\n        const firstInvalidElement = this.form.querySelector(':invalid');\r\n        if (\r\n            firstInvalidElement instanceof HTMLElement &&\r\n            document.activeElement !== firstInvalidElement\r\n        ) {\r\n            firstInvalidElement.focus();\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Finds a form element relative to the given element.\r\n     * Searches parent first, then direct children.\r\n     *\r\n     * @param element - The element to search from\r\n     * @returns The found form element\r\n     * @throws Error if no form is found\r\n     *\r\n     * @example\r\n     * class MyComponent extends HTMLElement {\r\n     *     connectedCallback() {\r\n     *         const form = FormValidator.FindForm(this);\r\n     *         new FormValidator(form);\r\n     *     }\r\n     * }\r\n     */\r\n    public static FindForm(element: HTMLElement): HTMLFormElement {\r\n        if (element.parentElement?.tagName == 'FORM') {\r\n            return <HTMLFormElement>element.parentElement;\r\n        } else {\r\n            for (let i = 0; i < element.children.length; i++) {\r\n                const child = element.children[i];\r\n                if (child.tagName == 'FORM') {\r\n                    return <HTMLFormElement>child;\r\n                }\r\n            }\r\n        }\r\n\r\n        throw new Error(\r\n            'Parent or a direct child must be a FORM for class ' +\r\n                element.constructor.name\r\n        );\r\n    }\r\n}\r\n", "/**\r\n * @module icu\r\n * ICU message format support for internationalization.\r\n * Provides pluralization, select, and value interpolation.\r\n *\r\n * @example\r\n * // Simple interpolation\r\n * formatICU('Hello, {name}!', { name: 'World' });\r\n * // Returns: 'Hello, World!'\r\n *\r\n * @example\r\n * // Pluralization\r\n * formatICU('{count, plural, one {# item} other {# items}}', { count: 5 });\r\n * // Returns: '5 items'\r\n *\r\n * @example\r\n * // Select\r\n * formatICU('{gender, select, male {He} female {She} other {They}}', { gender: 'female' });\r\n * // Returns: 'She'\r\n */\r\n\r\nconst pluralRulesCache = new Map<string, Intl.PluralRules>();\r\n\r\n/**\r\n * Function type for message formatters.\r\n * Implement this to provide custom message formatting.\r\n */\r\nexport type MessageFormatter = (\r\n    message: string,\r\n    values?: Record<string, any>,\r\n    locale?: string\r\n) => string;\r\n\r\n\r\nfunction getPluralRule(locale: string): Intl.PluralRules {\r\n    if (!pluralRulesCache.has(locale)) {\r\n        pluralRulesCache.set(locale, new Intl.PluralRules(locale));\r\n    }\r\n    return pluralRulesCache.get(locale)!;\r\n}\r\n\r\nfunction escapeRegex(s: string): string {\r\n    return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n}\r\n\r\n/**\r\n * Default ICU message formatter implementation.\r\n * Supports simple interpolation, pluralization with exact matches, and select.\r\n *\r\n * @param message - ICU format message string\r\n * @param values - Values to interpolate\r\n * @param locale - Locale for plural rules (default: 'en')\r\n * @returns Formatted message string\r\n *\r\n * @example\r\n * defaultFormatICU('{n, plural, =0 {none} one {# item} other {# items}}', { n: 0 }, 'en');\r\n * // Returns: 'none'\r\n *\r\n * @example\r\n * defaultFormatICU('{role, select, admin {Full access} other {Limited access}}', { role: 'admin' });\r\n * // Returns: 'Full access'\r\n */\r\nexport function defaultFormatICU(\r\n    message: string,\r\n    values?: Record<string, any>,\r\n    locale: string = 'en'\r\n): string {\r\n    return message.replace(\r\n        /\\{(\\w+)(?:, (plural|select),((?:[^{}]*\\{[^{}]*\\})+))?\\}/g,\r\n        (_, key, type, categoriesPart) => {\r\n            const value = values?.[key];\r\n\r\n            if (type === 'plural') {\r\n                const exact = new RegExp(\r\n                    `=${escapeRegex(String(value))}\\\\s*\\\\{([^{}]*)\\\\}`\r\n                ).exec(categoriesPart);\r\n                if (exact) {\r\n                    return exact[1]\r\n                        .replace(`{${key}}`, String(value))\r\n                        .replace('#', String(value));\r\n                }\r\n\r\n                const rules = getPluralRule(locale);\r\n                const category = rules.select(value);\r\n                const match =\r\n                    new RegExp(`${category}\\\\s*\\\\{([^{}]*)\\\\}`).exec(categoriesPart) ||\r\n                    new RegExp(`other\\\\s*\\\\{([^{}]*)\\\\}`).exec(categoriesPart);\r\n                if (match) {\r\n                    return match[1]\r\n                        .replace(`{${key}}`, String(value))\r\n                        .replace('#', String(value));\r\n                }\r\n                return String(value);\r\n            }\r\n\r\n            if (type === 'select') {\r\n                const escaped = escapeRegex(String(value));\r\n                const match =\r\n                    new RegExp(`\\\\b${escaped}\\\\s*\\\\{([^{}]*)\\\\}`).exec(categoriesPart) ||\r\n                    new RegExp(`\\\\bother\\\\s*\\\\{([^{}]*)\\\\}`).exec(categoriesPart);\r\n                return match ? match[1] : String(value);\r\n            }\r\n\r\n            return value !== undefined ? String(value) : `{${key}}`;\r\n        },\r\n    );\r\n}\r\n\r\n/**\r\n * The active message formatter. Defaults to `defaultFormatICU`.\r\n * Can be replaced with `setMessageFormatter` for custom formatting.\r\n */\r\nexport let formatICU: MessageFormatter = defaultFormatICU;\r\n\r\n/**\r\n * Replaces the default message formatter with a custom implementation.\r\n * Use this to integrate with external i18n libraries like FormatJS.\r\n *\r\n * @param formatter - The custom formatter function\r\n *\r\n * @example\r\n * // Use FormatJS IntlMessageFormat\r\n * import { IntlMessageFormat } from 'intl-messageformat';\r\n *\r\n * setMessageFormatter((message, values, locale) => {\r\n *     const fmt = new IntlMessageFormat(message, locale);\r\n *     return fmt.format(values);\r\n * });\r\n */\r\nexport function setMessageFormatter(formatter: MessageFormatter) {\r\n    formatICU = formatter;\r\n}", "/**\n * @module i18n/catalogue\n * Registry of translation files, filled by the application at startup.\n *\n * A bundler resolves import paths relative to the file that contains them, so a\n * library can never discover translation files that live in an application. The\n * application therefore hands its files to the library instead.\n *\n * @example\n * // Vite\n * import { registerCatalogue } from '@relax.js/core/i18n';\n * registerCatalogue(import.meta.glob('./locales/*\\/*.json', { eager: true }));\n *\n * @example\n * // Any bundler, or no bundler at all\n * import { registerNamespace } from '@relax.js/core/i18n';\n * import shellEn from './locales/en/shell.json';\n * registerNamespace('en', 'shell', shellEn);\n */\n\nexport type TranslationMap = Record<string, string>;\n\n/**\n * Loads a namespace the first time it is used, so translations for locales\n * nobody selects stay out of the initial download.\n */\nexport type NamespaceLoader = () => Promise<TranslationMap | { default: TranslationMap }>;\n\n/**\n * A namespace given either as ready messages or as a loader that fetches them.\n */\nexport type NamespaceSource = TranslationMap | NamespaceLoader;\n\nconst catalogue: Record<string, Record<string, NamespaceSource>> = {};\n\n/**\n * Reduces `en-US` to `en`, so a browser language matches a translation folder.\n */\nexport function normalizeLocale(locale: string): string {\n    return locale.toLowerCase().split('-')[0];\n}\n\nfunction unwrapModule(value: TranslationMap | { default: TranslationMap }): TranslationMap {\n    const candidate = (value as { default?: TranslationMap }).default;\n    return candidate && typeof candidate === 'object' ? candidate : (value as TranslationMap);\n}\n\n/**\n * Adds a single namespace to the catalogue.\n *\n * Registering the same locale and namespace twice replaces the previous entry,\n * which lets an application override a built-in namespace such as `r-validation`.\n *\n * @param locale - Locale code, normalized the same way as `setLocale()`\n * @param namespace - Namespace name used in front of the colon in `t('shell:title')`\n * @param source - The messages, or a function that loads them on first use\n *\n * @example\n * import shellEn from './locales/en/shell.json';\n * registerNamespace('en', 'shell', shellEn);\n *\n * @example\n * registerNamespace('sv', 'shell', () => import('./locales/sv/shell.json'));\n */\nexport function registerNamespace(\n    locale: string,\n    namespace: string,\n    source: NamespaceSource,\n): void {\n    const normalized = normalizeLocale(locale);\n    if (!catalogue[normalized]) catalogue[normalized] = {};\n    catalogue[normalized][namespace] = source;\n}\n\n/**\n * Adds every namespace in a path-keyed record, so a whole `locales/` folder is\n * registered in one call.\n *\n * The locale and namespace are read from the last two segments of each key, so\n * `./locales/en/shell.json` becomes locale `en` and namespace `shell`. Values may\n * be the messages, a module with the messages as its default export, or a\n * function returning either. That covers Vite's eager and lazy `import.meta.glob`,\n * webpack's `require.context`, and a plain object written by hand.\n *\n * @param modules - Record keyed by file path\n *\n * @example\n * // Vite, everything in the first download\n * registerCatalogue(import.meta.glob('./locales/*\\/*.json', { eager: true }));\n *\n * @example\n * // Vite, each locale downloaded when it is first selected\n * registerCatalogue(import.meta.glob('./locales/*\\/*.json'));\n *\n * @example\n * // No bundler\n * registerCatalogue({\n *     './locales/en/shell.json': { title: 'Dashboard' },\n *     './locales/sv/shell.json': { title: 'Instrumentpanel' },\n * });\n */\nexport function registerCatalogue(modules: Record<string, unknown>): void {\n    for (const path of Object.keys(modules)) {\n        const segments = path.replace(/\\.json$/i, '').split('/').filter(Boolean);\n        if (segments.length < 2) {\n            console.warn(\n                `i18n: skipped catalogue entry '${path}' because it has no {locale}/{namespace} part.`,\n            );\n            continue;\n        }\n        const namespace = segments[segments.length - 1];\n        const locale = segments[segments.length - 2];\n        registerNamespace(locale, namespace, modules[path] as NamespaceSource);\n    }\n}\n\n/**\n * Returns the messages for a namespace, or `undefined` when it was never registered.\n *\n * Rejects when a registered loader fails, so a network error is reported rather\n * than mistaken for a namespace nobody registered.\n */\nexport async function resolveNamespace(\n    locale: string,\n    namespace: string,\n): Promise<TranslationMap | undefined> {\n    const source = catalogue[normalizeLocale(locale)]?.[namespace];\n    if (!source) return undefined;\n    if (typeof source === 'function') return unwrapModule(await source());\n    return unwrapModule(source);\n}\n", "{\r\n    \"greeting\": \"Hello, {name}!\",\r\n    \"items\": \"{count, plural, one {# item} other {# items}}\"\r\n}\r\n", "{\r\n    \"today\": \"today\",\r\n    \"yesterday\": \"yesterday\",\r\n    \"daysAgo\": \"{count, plural, one {# day ago} other {# days ago}}\",\r\n    \"pieces\": \"{count, plural, =0 {none} one {one} other {# pcs}}\"\r\n}\r\n", "{\r\n    \"required\": \"This field is required.\",\r\n    \"range\": \"Number must be between {min} and {max}, was {actual}.\",\r\n    \"digits\": \"Please enter only digits.\"\r\n}\r\n", "/**\n * @module i18n/builtins\n * Registers the namespaces that ship with Relaxjs.\n *\n * English is imported directly so it is always present in the bundle and can act\n * as the fallback for every other locale. The remaining locales are loaded the\n * first time they are selected.\n */\n\nimport { registerNamespace } from './catalogue';\nimport enCommon from './locales/en/r-common.json';\nimport enPipes from './locales/en/r-pipes.json';\nimport enValidation from './locales/en/r-validation.json';\n\n/**\n * Fills the catalogue with `r-common`, `r-pipes`, and `r-validation`.\n *\n * Called once when the i18n module loads. An application may replace any of these\n * afterwards by registering the same locale and namespace again.\n */\nexport function registerBuiltinNamespaces(): void {\n    registerNamespace('en', 'r-common', enCommon);\n    registerNamespace('en', 'r-pipes', enPipes);\n    registerNamespace('en', 'r-validation', enValidation);\n\n    registerNamespace('sv', 'r-common', () => import('./locales/sv/r-common.json'));\n    registerNamespace('sv', 'r-pipes', () => import('./locales/sv/r-pipes.json'));\n    registerNamespace('sv', 'r-validation', () => import('./locales/sv/r-validation.json'));\n}\n", "/**\r\n * @module i18n\r\n * Internationalization support with namespace-based translations.\r\n * Uses ICU message format for pluralization, select, and formatting.\r\n *\r\n * @example\r\n * // Initialize locale\r\n * await setLocale('sv');\r\n *\r\n * // Use translations\r\n * const greeting = t('r-common:greeting', { name: 'John' });\r\n * const items = t('shop:items', { count: 5 });\r\n */\r\n\r\nimport { formatICU } from './icu';\r\nimport { registerBuiltinNamespaces } from './builtins';\r\nimport { normalizeLocale, resolveNamespace, TranslationMap } from './catalogue';\r\n\r\ntype Locale = string;\r\ntype Namespace = string;\r\ntype Translations = Record<Namespace, TranslationMap>;\r\n\r\n/**\r\n * Extra behaviour for a single `t()` call.\r\n */\r\nexport interface TranslateOptions {\r\n    /**\r\n     * Text to show when the key is missing, instead of the key itself.\r\n     *\r\n     * Use it for wording that must never be absent, such as a legally required\r\n     * notice. The fallback goes through the same formatter, so it can contain\r\n     * placeholders.\r\n     */\r\n    fallback?: string;\r\n}\r\n\r\nexport type MissingTranslationHandler = (\r\n    key: string,\r\n    namespace: string,\r\n    locale: string,\r\n) => void;\r\n\r\n/**\r\n * Dispatched on `document` after `setLocale()` completes.\r\n * The `locale` property contains the new normalized locale code.\r\n *\r\n * @example\r\n * document.addEventListener('localechange', (e) => {\r\n *     console.log(`Locale changed to ${e.locale}`);\r\n *     this.render();\r\n * });\r\n */\r\nexport class LocaleChangeEvent extends Event {\r\n    readonly locale: string;\r\n    constructor(locale: string) {\r\n        super('localechange', { bubbles: false });\r\n        this.locale = locale;\r\n    }\r\n}\r\n\r\ndeclare global {\r\n    interface DocumentEventMap {\r\n        localechange: LocaleChangeEvent;\r\n    }\r\n}\r\n\r\nconst fallbackLocale: Locale = 'en';\r\nlet currentLocale: Locale = fallbackLocale;\r\nconst loadedNamespaces = new Set<Namespace>();\r\nconst translations: Translations = {};\r\nlet missingHandler: MissingTranslationHandler | null = null;\r\n\r\nregisterBuiltinNamespaces();\r\n\r\n/**\r\n * Sets the current locale and loads the common namespace.\r\n * Clears previously loaded translations and dispatches a `localechange` event.\r\n *\r\n * @param locale - The locale code (e.g., 'en', 'sv', 'en-US')\r\n *\r\n * @example\r\n * await setLocale('sv');\r\n */\r\nexport async function setLocale(locale: string): Promise<void> {\r\n    const normalized = normalizeLocale(locale);\r\n    currentLocale = normalized;\r\n    loadedNamespaces.clear();\r\n    Object.keys(translations).forEach(ns => delete translations[ns]);\r\n    await loadNamespace('r-common');\r\n    if (typeof document !== 'undefined') {\r\n        document.dispatchEvent(new LocaleChangeEvent(normalized));\r\n    }\r\n}\r\n\r\nasync function tryResolve(\r\n    locale: Locale,\r\n    namespace: Namespace,\r\n): Promise<TranslationMap | undefined> {\r\n    try {\r\n        return await resolveNamespace(locale, namespace);\r\n    } catch (err) {\r\n        console.warn(\r\n            `i18n: could not load namespace '${namespace}' for locale '${locale}'.`,\r\n            err,\r\n        );\r\n        return undefined;\r\n    }\r\n}\r\n\r\n/**\r\n * Loads a translation namespace from the catalogue.\r\n * Falls back to the default locale when the namespace is not translated yet.\r\n *\r\n * Never rejects. A namespace nobody registered is reported as a warning so that\r\n * one forgotten file cannot stop the application from starting.\r\n *\r\n * @param namespace - The namespace to load (e.g., 'shop', 'errors')\r\n *\r\n * @example\r\n * await loadNamespace('shop');\r\n * const price = t('shop:priceLabel');\r\n */\r\nexport async function loadNamespace(namespace: Namespace): Promise<void> {\r\n    if (loadedNamespaces.has(namespace)) return;\r\n\r\n    let messages = await tryResolve(currentLocale, namespace);\r\n    if (!messages && currentLocale !== fallbackLocale) {\r\n        messages = await tryResolve(fallbackLocale, namespace);\r\n    }\r\n\r\n    if (!messages) {\r\n        console.warn(\r\n            `i18n: namespace '${namespace}' is not registered for locale '${currentLocale}'. ` +\r\n            `Register it during startup with registerCatalogue() or registerNamespace().`,\r\n        );\r\n        return;\r\n    }\r\n\r\n    translations[namespace] = messages;\r\n    loadedNamespaces.add(namespace);\r\n}\r\n\r\n/**\r\n * Loads multiple translation namespaces in parallel.\r\n *\r\n * @param namespaces - Array of namespace names to load\r\n *\r\n * @example\r\n * await loadNamespaces(['r-pipes', 'r-validation']);\r\n */\r\nexport async function loadNamespaces(namespaces: Namespace[]): Promise<void> {\r\n    await Promise.all(namespaces.map(ns => loadNamespace(ns)));\r\n}\r\n\r\n/**\r\n * Translates a key with optional value interpolation.\r\n * Supports ICU message format for pluralization and select.\r\n *\r\n * @param fullKey - Translation key in format 'namespace:key' or just 'key' (uses 'r-common')\r\n * @param values - Values to interpolate into the message\r\n * @param options - Set `fallback` for text that must never be missing\r\n * @returns The translated string, the fallback, or the key if neither is available\r\n *\r\n * @example\r\n * // Simple translation\r\n * t('greeting'); // Uses r-common:greeting\r\n *\r\n * // With namespace\r\n * t('errors:notFound');\r\n *\r\n * // With interpolation\r\n * t('welcome', { name: 'John' }); // \"Welcome, John!\"\r\n *\r\n * // With pluralization (ICU format)\r\n * t('items', { count: 5 }); // \"5 items\" or \"5 f\u00F6rem\u00E5l\"\r\n *\r\n * // Wording that must never render as a raw key\r\n * t('shell:aiDisclosure', undefined, {\r\n *     fallback: 'You are interacting with an AI system.',\r\n * });\r\n */\r\nexport function t(\r\n    fullKey: string,\r\n    values?: Record<string, any>,\r\n    options?: TranslateOptions,\r\n): string {\r\n    const [namespace, key] = fullKey.includes(':')\r\n        ? fullKey.split(':')\r\n        : ['r-common', fullKey];\r\n    const message = translations[namespace]?.[key];\r\n\r\n    if (!message) {\r\n        if (missingHandler) missingHandler(key, namespace, currentLocale);\r\n        if (options?.fallback === undefined) return fullKey;\r\n        return format(options.fallback, values, options.fallback);\r\n    }\r\n\r\n    return format(message, values, options?.fallback ?? fullKey);\r\n}\r\n\r\nfunction format(message: string, values: Record<string, any> | undefined, onError: string): string {\r\n    try {\r\n        return formatICU(message, values, currentLocale) as string;\r\n    } catch {\r\n        return onError;\r\n    }\r\n}\r\n\r\n/**\r\n * Returns the current locale code.\r\n *\r\n * @returns The normalized locale code (e.g., 'en', 'sv')\r\n */\r\nexport function getCurrentLocale(): string {\r\n    return currentLocale;\r\n}\r\n\r\n/**\r\n * Registers a handler called when `t()` encounters a missing translation key.\r\n * Pass `null` to remove the handler.\r\n *\r\n * @param handler - Callback receiving the key, namespace, and locale\r\n *\r\n * @example\r\n * onMissingTranslation((key, ns, locale) => {\r\n *     console.warn(`Missing: ${ns}:${key} [${locale}]`);\r\n * });\r\n */\r\nexport function onMissingTranslation(handler: MissingTranslationHandler | null): void {\r\n    missingHandler = handler;\r\n}\r\n", "/**\r\n * @module FormReader\r\n * Utilities for reading form data into typed objects.\r\n * Handles type conversion based on input types and data-type attributes.\r\n *\r\n * @example\r\n * // Basic form reading\r\n * const form = document.querySelector('form');\r\n * const data = readData(form);\r\n *\r\n * // Type-safe mapping to a class instance\r\n * const user = mapFormToClass(form, new UserDTO());\r\n */\r\n\r\nimport { getCurrentLocale } from '../i18n/i18n';\r\n\r\n/**\r\n * Maps form field values to a class instance's properties.\r\n * Automatically converts values based on input types (checkbox, number, date).\r\n *\r\n * Form field names must match property names on the target instance.\r\n *\r\n * @template T - The type of the class instance\r\n * @param form - The HTML form element to read from\r\n * @param instance - The class instance to populate\r\n * @param options - Configuration options\r\n * @param options.throwOnMissingProperty - Throw if form field has no matching property\r\n * @param options.throwOnMissingField - Throw if class property has no matching form field\r\n * @returns The populated instance\r\n *\r\n * @example\r\n * class UserDTO {\r\n *     name: string = '';\r\n *     email: string = '';\r\n *     age: number = 0;\r\n *     newsletter: boolean = false;\r\n * }\r\n *\r\n * const form = document.querySelector('form');\r\n * const user = mapFormToClass(form, new UserDTO());\r\n * console.log(user.name, user.age, user.newsletter);\r\n *\r\n * @example\r\n * // With validation\r\n * const user = mapFormToClass(form, new UserDTO(), {\r\n *     throwOnMissingProperty: true,  // Catch typos in form field names\r\n *     throwOnMissingField: true      // Ensure all DTO fields are in form\r\n * });\r\n */\r\nexport function mapFormToClass<T extends object>(\r\n    form: HTMLFormElement,\r\n    instance: T,\r\n    options: {\r\n        throwOnMissingProperty?: boolean;\r\n        throwOnMissingField?: boolean;\r\n    } = {}\r\n): T {\r\n    const formElements = form.querySelectorAll('input, select, textarea');\r\n\r\n    formElements.forEach((element) => {\r\n        if (!element.hasAttribute('name')) return;\r\n        if (booleanAttr(element, 'disabled')) return;\r\n\r\n        const propertyName = element.getAttribute('name')!;\r\n\r\n        if (!(propertyName in instance)) {\r\n            if (options.throwOnMissingProperty) {\r\n                throw new Error(\r\n                    `Form field \"${propertyName}\" has no matching property in class instance`\r\n                );\r\n            }\r\n            return;\r\n        }\r\n\r\n        const value = readElementValue(element);\r\n        if (value === SKIP) return;\r\n\r\n        (instance as Record<string, unknown>)[propertyName] = value;\r\n    });\r\n\r\n    if (options.throwOnMissingField) {\r\n        const formFieldNames = new Set<string>();\r\n        formElements.forEach((element) => {\r\n            if (element.hasAttribute('name')) {\r\n                formFieldNames.add(element.getAttribute('name')!);\r\n            }\r\n        });\r\n\r\n        for (const prop in instance) {\r\n            if (\r\n                typeof instance[prop] !== 'function' &&\r\n                Object.prototype.hasOwnProperty.call(instance, prop) &&\r\n                !formFieldNames.has(prop)\r\n            ) {\r\n                throw new Error(\r\n                    `Class property \"${prop}\" has no matching form field`\r\n                );\r\n            }\r\n        }\r\n    }\r\n\r\n    return instance;\r\n}\r\n\r\n/**\r\n * Configuration options for form reading operations.\r\n */\r\nexport interface FormReaderOptions {\r\n    /** Prefix to strip from field names when mapping to properties */\r\n    prefix?: string;\r\n    /** If true, checkboxes return their value instead of true/false */\r\n    disableBinaryCheckbox?: boolean;\r\n    /** If true, radio buttons return their value instead of true/false */\r\n    disableBinaryRadioButton?: boolean;\r\n}\r\n\r\n/**\r\n * Gets the appropriate type converter function for a form element.\r\n * Uses the `data-type` attribute if present, otherwise infers from input type.\r\n *\r\n * @param element - The form element to get a converter for\r\n * @returns A function that converts string values to the appropriate type\r\n *\r\n * @example\r\n * // With data-type attribute\r\n * <input name=\"age\" data-type=\"number\" />\r\n * const converter = getDataConverter(input);\r\n * converter('42'); // Returns: 42 (number)\r\n *\r\n * @example\r\n * // Inferred from input type\r\n * <input type=\"checkbox\" name=\"active\" />\r\n * const converter = getDataConverter(checkbox);\r\n * converter('true'); // Returns: true (boolean)\r\n */\r\nexport function getDataConverter(element: HTMLElement): ConverterFunc {\r\n    const dataType = element.getAttribute('data-type') as DataType | null;\r\n    if (dataType) {\r\n        return createConverterFromDataType(dataType);\r\n    }\r\n\r\n    if (element instanceof HTMLInputElement) {\r\n        return createConverterFromInputType(element.type as InputType);\r\n    }\r\n\r\n    // Handle custom form-associated elements with checked property (boolean values)\r\n    if ('checked' in element && typeof (element as any).checked === 'boolean') {\r\n        return BooleanConverter as ConverterFunc;\r\n    }\r\n\r\n    return (str) => str;\r\n}\r\n\r\n\r\n/**\r\n * Reads all form data into a plain object with automatic type conversion.\r\n * Handles multiple values (e.g., multi-select) and custom form-associated elements.\r\n *\r\n * Type conversion is based on:\r\n * 1. `data-type` attribute if present (number, boolean, string, Date)\r\n * 2. Input type (checkbox, number, date, etc.)\r\n * 3. Falls back to string\r\n *\r\n * @param form - The HTML form element to read\r\n * @returns Object with property names matching field names\r\n *\r\n * @example\r\n * // HTML form\r\n * <form>\r\n *     <input name=\"username\" value=\"john\" />\r\n *     <input name=\"age\" type=\"number\" value=\"25\" />\r\n *     <input name=\"active\" type=\"checkbox\" checked />\r\n *     <select name=\"colors\" multiple>\r\n *         <option value=\"red\" selected>Red</option>\r\n *         <option value=\"blue\" selected>Blue</option>\r\n *     </select>\r\n * </form>\r\n *\r\n * // Reading the form\r\n * const data = readData(form);\r\n * // Returns: { username: 'john', age: 25, active: true, colors: ['red', 'blue'] }\r\n *\r\n * @example\r\n * // With custom form elements\r\n * <form>\r\n *     <r-input name=\"email\" value=\"test@example.com\" />\r\n *     <r-checkbox name=\"terms\" checked />\r\n * </form>\r\n * const data = readData(form);\r\n 1*/\r\nexport function readData<T = Record<string, unknown>>(form: HTMLFormElement): T{\r\n    const data: Record<string, unknown> = {};\r\n    const formData = new FormData(form);\r\n    const seen = new Set<string>();\r\n\r\n    formData.forEach((_, name) => {\r\n        if (seen.has(name)) return;\r\n        seen.add(name);\r\n\r\n        const values = formData.getAll(name);\r\n        const element = form.elements.namedItem(name);\r\n        const converter = element ? getDataConverter(element as HTMLElement) : (v: string) => v;\r\n\r\n        if (values.length === 1) {\r\n            const v = values[0];\r\n            data[name] = typeof v === 'string' ? converter(v) : v;\r\n        } else {\r\n            data[name] = values.map(v => typeof v === 'string' ? converter(v) : v);\r\n        }\r\n    });\r\n\r\n    for (let i = 0; i < form.elements.length; i++) {\r\n        const el = form.elements[i] as HTMLInputElement;\r\n        if (el.type === 'checkbox' && el.name && !seen.has(el.name)) {\r\n            seen.add(el.name);\r\n            data[el.name] = false;\r\n        }\r\n    }\r\n\r\n    return data as T;\r\n}\r\n\r\n/**\r\n * Function type for converting string form values to typed values.\r\n */\r\nexport type ConverterFunc = (value: string) => unknown;\r\n\r\n/**\r\n * Supported data-type attribute values for explicit type conversion.\r\n */\r\nexport type DataType = 'number' | 'boolean' | 'string' | 'Date';\r\n\r\n/**\r\n * Supported HTML input types for automatic type inference.\r\n */\r\nexport type InputType =\r\n    | 'tel'\r\n    | 'text'\r\n    | 'checkbox'\r\n    | 'radio'\r\n    | 'number'\r\n    | 'color'\r\n    | 'date'\r\n    | 'datetime-local'\r\n    | 'month'\r\n    | 'week'\r\n    | 'time';\r\n\r\n/**\r\n * Converts string values to booleans.\r\n * Handles 'true'/'false' strings and numeric values (>0 is true).\r\n *\r\n * @param value - String value to convert\r\n * @returns Boolean value or undefined if empty\r\n * @throws Error if value cannot be interpreted as boolean\r\n */\r\nexport function BooleanConverter(value?: string): boolean | undefined {\r\n    if (!value || value == '') {\r\n        return undefined;\r\n    }\r\n\r\n    const lower = value.toLowerCase();\r\n\r\n    if (lower === 'true' || lower === 'on' || Number(value) > 0) {\r\n        return true;\r\n    }\r\n\r\n    if (lower === 'false' || lower === 'off' || Number(value) <= 0) {\r\n        return false;\r\n    }\r\n\r\n    throw new Error(\"Could not convert value '\" + value + \"' to boolean.\");\r\n}\r\n\r\n/**\r\n * Converts string values to numbers.\r\n *\r\n * @param value - String value to convert\r\n * @returns Number value or undefined if empty\r\n * @throws Error if value is not a valid number\r\n */\r\nexport function NumberConverter(value?: string): number | undefined {\r\n    if (!value || value == '') {\r\n        return undefined;\r\n    }\r\n    const nr = Number(value);\r\n    if (!isNaN(nr)) {\r\n        return nr;\r\n    }\r\n    throw new Error(\"Could not convert value '\" + value + \"' to number.\");\r\n}\r\n\r\n/**\r\n * Detects the order of day/month/year parts for a given locale\r\n * using `Intl.DateTimeFormat.formatToParts`.\r\n *\r\n * @example\r\n * getLocaleDateOrder('en-US')  // ['month', 'day', 'year']\r\n * getLocaleDateOrder('sv')     // ['year', 'month', 'day']\r\n * getLocaleDateOrder('de')     // ['day', 'month', 'year']\r\n */\r\nfunction getLocaleDateOrder(locale: string): ('day' | 'month' | 'year')[] {\r\n    const parts = new Intl.DateTimeFormat(locale).formatToParts(new Date(2024, 0, 15));\r\n    return parts\r\n        .filter((p): p is Intl.DateTimeFormatPart & { type: 'day' | 'month' | 'year' } =>\r\n            p.type === 'day' || p.type === 'month' || p.type === 'year')\r\n        .map(p => p.type);\r\n}\r\n\r\n/**\r\n * Converts string values to Date objects.\r\n * Supports both ISO format (`2024-01-15`) and locale-specific formats\r\n * (`01/15/2024` for en-US, `15.01.2024` for de, etc.) based on the\r\n * current i18n locale.\r\n *\r\n * @param value - Date string in ISO or locale format\r\n * @returns Date object\r\n * @throws Error if value is not a valid date\r\n *\r\n * @example\r\n * // ISO format (from <input type=\"date\">)\r\n * DateConverter('2024-01-15')   // Date(2024, 0, 15)\r\n *\r\n * // Locale format (from <input type=\"text\" data-type=\"Date\">)\r\n * // with locale set to 'sv': 2024-01-15\r\n * // with locale set to 'en-US': 01/15/2024\r\n * // with locale set to 'de': 15.01.2024\r\n */\r\nexport function DateConverter(value: string): Date | undefined {\r\n    if (!value || value === '') return undefined;\r\n\r\n    if (/^\\d{4}-\\d{2}-\\d{2}(T|$)/.test(value)) {\r\n        const date = new Date(value);\r\n        if (!isNaN(date.getTime())) return date;\r\n    }\r\n\r\n    const numericParts = value.split(/[\\/.\\-\\s]/);\r\n    if (numericParts.length >= 3 && numericParts.every(p => /^\\d+$/.test(p))) {\r\n        const locale = getCurrentLocale();\r\n        const order = getLocaleDateOrder(locale);\r\n        const mapped: Record<string, number> = {};\r\n        order.forEach((type, i) => {\r\n            mapped[type] = parseInt(numericParts[i], 10);\r\n        });\r\n\r\n        if (mapped.year !== undefined && mapped.month !== undefined && mapped.day !== undefined) {\r\n            if (mapped.year < 100) mapped.year += 2000;\r\n            const date = new Date(mapped.year, mapped.month - 1, mapped.day);\r\n            if (!isNaN(date.getTime())) return date;\r\n        }\r\n    }\r\n\r\n    const date = new Date(value);\r\n    if (isNaN(date.getTime())) {\r\n        throw new Error('Invalid date format');\r\n    }\r\n    return date;\r\n}\r\n\r\n/**\r\n * Creates a converter function based on the data-type attribute value.\r\n *\r\n * @param dataType - The data-type attribute value\r\n * @returns Appropriate converter function for the type\r\n */\r\nexport function createConverterFromDataType(dataType: DataType): ConverterFunc {\r\n    switch (dataType) {\r\n        case 'boolean':\r\n            return BooleanConverter as ConverterFunc;\r\n        case 'number':\r\n            return NumberConverter as ConverterFunc;\r\n        case 'Date':\r\n            return DateConverter;\r\n        case 'string':\r\n            return (value) => (!value || value == '' ? undefined : value);\r\n        default:\r\n            throw new Error(`Unknown data-type \"${dataType}\".`);\r\n    }\r\n}\r\n\r\n/**\r\n * Creates a converter function based on HTML input type.\r\n * Handles special types like checkbox, date, time, week, and month.\r\n *\r\n * @param inputType - The HTML input type attribute value\r\n * @returns Appropriate converter function for the type\r\n */\r\nexport function createConverterFromInputType(inputType: InputType): ConverterFunc {\r\n    switch (inputType) {\r\n        case 'checkbox':\r\n            return BooleanConverter as ConverterFunc;\r\n\r\n        case 'number':\r\n            return NumberConverter as ConverterFunc;\r\n\r\n        case 'date':\r\n        case 'datetime-local':\r\n            return DateConverter;\r\n\r\n        case 'month':\r\n            return (value) => {\r\n                const [year, month] = value.split('-').map(Number);\r\n                return new Date(year, month - 1);\r\n            };\r\n\r\n        case 'week':\r\n            return (value) => {\r\n                const [year, week] = value.split('-W').map(Number);\r\n                return { year, week };\r\n            };\r\n\r\n        case 'time':\r\n            return (value) => {\r\n                const [hours, minutes, seconds = 0] = value.split(':').map(Number);\r\n                return { hours, minutes, seconds };\r\n            };\r\n\r\n        default:\r\n            return (value) => (!value || value == '' ? undefined : value);\r\n    }\r\n}\r\n\r\nfunction booleanAttr(element: Element, name: string): boolean {\r\n    const el = element as Record<string, any>;\r\n    if (name in el && typeof el[name] === 'boolean') return el[name];\r\n    const attr = element.getAttribute(name);\r\n    if (attr === null) return false;\r\n    if (attr === '' || attr.toLowerCase() === 'true' || attr.toLowerCase() === name) return true;\r\n    return false;\r\n}\r\n\r\nconst SKIP = Symbol('skip');\r\n\r\nfunction readElementValue(element: Element): unknown {\r\n    const el = element as Record<string, any>;\r\n    const type = el.type || element.getAttribute('type') || '';\r\n\r\n    if (type === 'checkbox') {\r\n        return booleanAttr(element, 'checked');\r\n    }\r\n\r\n    if (type === 'radio') {\r\n        if (!booleanAttr(element, 'checked')) return SKIP;\r\n        return el.value;\r\n    }\r\n\r\n    if (type === 'number') {\r\n        return el.value ? Number(el.value) : null;\r\n    }\r\n\r\n    if (type === 'date') {\r\n        return el.value ? new Date(el.value) : null;\r\n    }\r\n\r\n    if ('selectedOptions' in el && booleanAttr(element, 'multiple')) {\r\n        return Array.from(el.selectedOptions as NodeListOf<HTMLOptionElement>)\r\n            .map((o: HTMLOptionElement) => o.value);\r\n    }\r\n\r\n    if ('value' in el) {\r\n        return el.value;\r\n    }\r\n\r\n    return undefined;\r\n}", "/**\r\n * @module ValidationRules\r\n * Form validation rules for use with FormValidator.\r\n * Provides declarative validation through decorators.\r\n *\r\n * Validation messages use the i18n system. Load the 'r-validation' namespace\r\n * for localized error messages:\r\n *\r\n * @example\r\n * await loadNamespace('r-validation');\r\n *\r\n * @example\r\n * // In HTML, use validation attributes\r\n * <input name=\"age\" data-validate=\"required range(0-120)\" />\r\n */\r\n\r\nimport { t } from '../i18n/i18n';\r\n\r\n/**\r\n * Context provided to validators during validation.\r\n */\r\nexport interface ValidationContext {\r\n    /** The HTML input type (text, number, email, etc.) */\r\n    inputType: string;\r\n    /** The data-type attribute value if present */\r\n    dataType?: string;\r\n    /** Adds an error message to the validation result */\r\n    addError(message: string): void;\r\n}\r\n\r\n/**\r\n * Interface for custom validators.\r\n * @internal\r\n */\r\ninterface Validator {\r\n    /**\r\n     * Validates the given value.\r\n     * @param value - The string value to validate\r\n     * @param context - Validation context with type info and error reporting\r\n     */\r\n    validate(value: string, context: ValidationContext): void;\r\n}\r\n\r\n/** @internal */\r\ninterface ValidatorRegistryEntry {\r\n    validator: new (...args: any[]) => Validator;\r\n    validInputTypes: string[];\r\n}\r\n\r\nconst validators: Map<string, ValidatorRegistryEntry> = new Map();\r\n\r\n/**\r\n * Decorator to register a validator class for a specific validation name.\r\n *\r\n * @param validationName - The name used in data-validate attribute\r\n * @param validInputTypes - Optional list of input types this validator applies to\r\n *\r\n * @example\r\n * @RegisterValidator('email')\r\n * class EmailValidation implements Validator {\r\n *     validate(value: string, context: ValidationContext) {\r\n *         if (!value.includes('@')) {\r\n *             context.addError('Invalid email address');\r\n *         }\r\n *     }\r\n * }\r\n */\r\nexport function RegisterValidator(validationName: string, validInputTypes: string[] = []) {\r\n    return function (target: new (...args: any[]) => Validator) {\r\n        validators.set(validationName, { validator: target, validInputTypes });\r\n    };\r\n}\r\n\r\n/**\r\n * Looks up a registered validator by name.\r\n *\r\n * @param name - The validator name used in `data-validate`\r\n * @returns The registry entry, or `undefined` if not found\r\n */\r\nexport function getValidator(name: string): ValidatorRegistryEntry | undefined {\r\n    return validators.get(name);\r\n}\r\n\r\n/**\r\n * Validates that a field has a non-empty value.\r\n * Use with `data-validate=\"required\"`.\r\n */\r\n@RegisterValidator('required')\r\nexport class RequiredValidation implements Validator {\r\n    static create(rule: string): RequiredValidation | null {\r\n        return rule === 'required' ? new RequiredValidation() : null;\r\n    }\r\n\r\n    validate(value: string, context: ValidationContext) {\r\n        if (value.trim() !== ''){\r\n            return;\r\n        }\r\n\r\n        context.addError(this.getMessage());\r\n    }\r\n\r\n    getMessage(): string {\r\n        return t('r-validation:required');\r\n    }\r\n}\r\n\r\n/**\r\n * Validates that a numeric value falls within a specified range.\r\n * Use with `data-validate=\"range(min-max)\"`.\r\n *\r\n * @example\r\n * <input name=\"age\" type=\"number\" data-validate=\"range(0-120)\" />\r\n */\r\n@RegisterValidator('range', ['number'])\r\nexport class RangeValidation implements Validator {\r\n    min: number;\r\n    max: number;\r\n\r\n    constructor(min: number, max: number) {\r\n        this.min = min;\r\n        this.max = max;\r\n    }\r\n\r\n    static create(rule: string): RangeValidation | null {\r\n        const rangeMatch = rule.match(/^range\\((-?\\d+(?:\\.\\d+)?)-(-?\\d+(?:\\.\\d+)?)\\)$/);\r\n        if (rangeMatch) {\r\n            const [, min, max] = rangeMatch;\r\n            return new RangeValidation(parseFloat(min), parseFloat(max));\r\n        }\r\n        return null;\r\n    }\r\n\r\n    validate(value: string, context: ValidationContext) {\r\n        if (value.trim() === '') return;\r\n\r\n        const num = parseFloat(value);\r\n        if (!isNaN(num) && num >= this.min && num <= this.max){\r\n            return;\r\n        }\r\n\r\n        context.addError(this.getMessage(value));\r\n    }\r\n\r\n    getMessage(actual: string): string {\r\n        return t('r-validation:range', { min: this.min, max: this.max, actual });\r\n    }\r\n}\r\n\r\n/**\r\n * Validates that a value contains only numeric digits (0-9).\r\n * Use with `data-validate=\"digits\"`.\r\n */\r\n@RegisterValidator('digits', ['number'])\r\nexport class DigitsValidation implements Validator {\r\n    static create(rule: string): DigitsValidation | null {\r\n        return rule === 'digits' ? new DigitsValidation() : null;\r\n    }\r\n\r\n    validate(value: string, context: ValidationContext) {\r\n        if (/^\\d+$/.test(value)){\r\n            return;\r\n        }\r\n\r\n        context.addError(this.getMessage());\r\n    }\r\n\r\n    getMessage(): string {\r\n        return t('r-validation:digits');\r\n    }\r\n}\r\n", "/**\r\n * Sets form field values from a data object using the name attribute.\r\n * Supports dot notation for accessing nested properties and array handling.\r\n *\r\n * When `context` is provided, `<select>` elements are populated with options\r\n * before their value is set. The option source is resolved from either the\r\n * `data-source` attribute or, as a fallback, the select's `name` attribute.\r\n * The resolved property on `context` can be an array or a method returning\r\n * an array. The `data-source` attribute may also declare which item\r\n * properties to use as value and text.\r\n *\r\n * @param form - The HTML form element to populate\r\n * @param data - The data object containing values to set in the form\r\n * @param context - Optional sources used to populate `<select>` options\r\n *\r\n * @example\r\n * // Basic usage with flat object\r\n * const form = document.querySelector('form');\r\n * const data = { name: 'John', email: 'john@example.com' };\r\n * setFormData(form, data);\r\n *\r\n * @example\r\n * // Using with nested objects via dot notation\r\n * const form = document.querySelector('form');\r\n * const data = {\r\n *   user: {\r\n *     name: 'John',\r\n *     contact: {\r\n *       email: 'john@example.com'\r\n *     }\r\n *   }\r\n * };\r\n * // Form has fields with names like \"user.name\" and \"user.contact.email\"\r\n * setFormData(form, data);\r\n *\r\n * @example\r\n * // Using with simple arrays using [] notation\r\n * const form = document.querySelector('form');\r\n * const data = {\r\n *   hobbies: ['Reading', 'Cycling', 'Cooking']\r\n * };\r\n * // Form has multiple fields with names like \"hobbies[]\"\r\n * setFormData(form, data);\r\n *\r\n * @example\r\n * // Using with array of objects using numeric indexers\r\n * const form = document.querySelector('form');\r\n * const data = {\r\n *   users: [\r\n *     { name: 'John', email: 'john@example.com' },\r\n *     { name: 'Jane', email: 'jane@example.com' }\r\n *   ]\r\n * };\r\n * // Form has fields with names like \"users[0].name\", \"users[1].email\", etc.\r\n * setFormData(form, data);\r\n *\r\n * @example\r\n * // Populating a <select> from context using the name convention\r\n * // <select name=\"country\"></select>\r\n * setFormData(form, { country: 'se' }, {\r\n *   country: [\r\n *     { value: 'se', text: 'Sweden' },\r\n *     { value: 'us', text: 'United States' }\r\n *   ]\r\n * });\r\n *\r\n * @example\r\n * // Using data-source with custom value/text properties\r\n * // <select name=\"country\" data-source=\"countries(id, name)\"></select>\r\n * setFormData(form, { country: 2 }, {\r\n *   countries: [\r\n *     { id: 1, name: 'Sweden' },\r\n *     { id: 2, name: 'United States' }\r\n *   ]\r\n * });\r\n *\r\n * @example\r\n * // data-source as a method on context\r\n * // <select name=\"country\" data-source=\"getCountries\"></select>\r\n * setFormData(form, { country: 'se' }, {\r\n *   getCountries: () => [\r\n *     { value: 'se', text: 'Sweden' },\r\n *     { value: 'us', text: 'United States' }\r\n *   ]\r\n * });\r\n *\r\n * @example\r\n * // Grouping options into <optgroup> using a third field in data-source\r\n * // <select name=\"country\" data-source=\"countries(id, name, region)\"></select>\r\n * setFormData(form, { country: 2 }, {\r\n *   countries: [\r\n *     { id: 1, name: 'Sweden', region: 'Europe' },\r\n *     { id: 2, name: 'United States', region: 'Americas' },\r\n *     { id: 3, name: 'Germany', region: 'Europe' }\r\n *   ]\r\n * });\r\n * // Produces two <optgroup> elements, \"Europe\" and \"Americas\", in the\r\n * // order each group first appears in the items array.\r\n */\r\nexport function setFormData(form: HTMLFormElement, data: object, context?: object): void {\r\n    if (context) {\r\n        const selects = form.querySelectorAll('select[name]');\r\n        selects.forEach(select => {\r\n            populateSelectOptions(select as HTMLSelectElement, context as Record<string, any>);\r\n        });\r\n    }\r\n\r\n    const formElements = form.querySelectorAll('[name]');\r\n\r\n    formElements.forEach(element => {\r\n\r\n      const name = element.getAttribute('name');\r\n      if (!name) return;\r\n\r\n      // Handle simple array notation (e.g., hobbies[])\r\n      if (name.endsWith('[]')) {\r\n        const arrayName = name.slice(0, -2);\r\n        const arrayValue = getValueByComplexPath(data, arrayName);\r\n\r\n        if (Array.isArray(arrayValue)) {\r\n          const el = element as Record<string, any>;\r\n          const type = el.type || element.getAttribute('type') || '';\r\n\r\n          if (type === 'checkbox' || type === 'radio') {\r\n            el.checked = arrayValue.includes(el.value);\r\n          } else if ('options' in el && boolAttr(element, 'multiple')) {\r\n            arrayValue.forEach(val => {\r\n              const option = Array.from(el.options as HTMLOptionElement[])\r\n                .find((opt: HTMLOptionElement) => opt.value === String(val));\r\n              if (option) (option as HTMLOptionElement).selected = true;\r\n            });\r\n          } else if ('value' in el) {\r\n            const allWithName = form.querySelectorAll(`[name=\"${name}\"]`);\r\n            const idx = Array.from(allWithName).indexOf(element);\r\n            if (idx >= 0 && idx < arrayValue.length) {\r\n              el.value = String(arrayValue[idx]);\r\n            }\r\n          }\r\n        }\r\n        return;\r\n      }\r\n\r\n      // Handle complex paths with array indexers and dot notation\r\n      const value = getValueByComplexPath(data, name);\r\n      if (value === undefined || value === null) return;\r\n\r\n      setElementValue(element, value);\r\n    });\r\n  }\r\n  \r\n  function getValueByComplexPath(obj: object, path: string): any {\r\n    // Handle array indexers like users[0].name\r\n    const segments = [];\r\n    let currentSegment = '';\r\n    let inBrackets = false;\r\n    \r\n    for (let i = 0; i < path.length; i++) {\r\n      const char = path[i];\r\n      \r\n      if (char === '[' && !inBrackets) {\r\n        if (currentSegment) {\r\n          segments.push(currentSegment);\r\n          currentSegment = '';\r\n        }\r\n        inBrackets = true;\r\n        currentSegment += char;\r\n      } else if (char === ']' && inBrackets) {\r\n        currentSegment += char;\r\n        segments.push(currentSegment);\r\n        currentSegment = '';\r\n        inBrackets = false;\r\n      } else if (char === '.' && !inBrackets) {\r\n        if (currentSegment) {\r\n          segments.push(currentSegment);\r\n          currentSegment = '';\r\n        }\r\n      } else {\r\n        currentSegment += char;\r\n      }\r\n    }\r\n    \r\n    if (currentSegment) {\r\n      segments.push(currentSegment);\r\n    }\r\n    \r\n    return segments.reduce<any>((result, segment) => {\r\n      if (!result || typeof result !== 'object') return undefined;\r\n\r\n      // Handle array indexer segments like [0]\r\n      if (segment.startsWith('[') && segment.endsWith(']')) {\r\n        const index = segment.slice(1, -1);\r\n        return result[index];\r\n      }\r\n\r\n      return result[segment];\r\n    }, obj);\r\n  }\r\n\r\n  function setElementValue(element: Element, value: any): void {\r\n    const el = element as Record<string, any>;\r\n    const type = el.type || element.getAttribute('type') || '';\r\n\r\n    if (type === 'checkbox') {\r\n      el.checked = Boolean(value);\r\n    } else if (type === 'radio') {\r\n      el.checked = el.value === String(value);\r\n    } else if (type === 'date' && value instanceof Date) {\r\n      el.value = value.toISOString().split('T')[0];\r\n    } else if (type === 'datetime-local' && value instanceof Date) {\r\n      const pad = (n: number) => String(n).padStart(2, '0');\r\n      el.value = `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(value.getDate())}T${pad(value.getHours())}:${pad(value.getMinutes())}`;\r\n    } else if ('options' in el && boolAttr(element, 'multiple') && Array.isArray(value)) {\r\n      const options = Array.from(el.options as HTMLOptionElement[]);\r\n      const vals = value.map(String);\r\n      options.forEach((opt: HTMLOptionElement) => {\r\n        opt.selected = vals.includes(opt.value);\r\n      });\r\n    } else if ('value' in el) {\r\n      el.value = String(value);\r\n    }\r\n  }\r\n\r\n  function populateSelectOptions(select: HTMLSelectElement, context: Record<string, any>): void {\r\n    const dataSource = select.getAttribute('data-source');\r\n    const name = select.getAttribute('name') || '';\r\n\r\n    let sourceKey: string;\r\n    let valueField = 'value';\r\n    let textField = 'text';\r\n    let groupField: string | null = null;\r\n\r\n    if (dataSource) {\r\n      const match = dataSource.match(/^\\s*(\\w+)\\s*(?:\\(\\s*(\\w+)\\s*,\\s*(\\w+)\\s*(?:,\\s*(\\w+)\\s*)?\\))?\\s*$/);\r\n      if (!match) return;\r\n      sourceKey = match[1];\r\n      if (match[2] && match[3]) {\r\n        valueField = match[2];\r\n        textField = match[3];\r\n      }\r\n      if (match[4]) {\r\n        groupField = match[4];\r\n      }\r\n    } else {\r\n      sourceKey = name.endsWith('[]') ? name.slice(0, -2) : name;\r\n      if (!sourceKey) return;\r\n    }\r\n\r\n    const source = context[sourceKey];\r\n    if (source === undefined) return;\r\n\r\n    const items = typeof source === 'function' ? source.call(context) : source;\r\n    if (!Array.isArray(items)) return;\r\n\r\n    const placeholders = Array.from(select.options).filter(opt => opt.value === '');\r\n    select.innerHTML = '';\r\n    placeholders.forEach(opt => select.add(opt));\r\n\r\n    const groups = new Map<string, HTMLOptGroupElement>();\r\n\r\n    for (const item of items) {\r\n      if (item === null || item === undefined) continue;\r\n\r\n      let value: string;\r\n      let text: string;\r\n      let groupLabel = '';\r\n\r\n      if (typeof item === 'object') {\r\n        value = String(item[valueField]);\r\n        text = String(item[textField]);\r\n        if (groupField) {\r\n          const raw = item[groupField];\r\n          if (raw !== null && raw !== undefined && String(raw) !== '') {\r\n            groupLabel = String(raw);\r\n          }\r\n        }\r\n      } else {\r\n        const str = String(item);\r\n        value = str;\r\n        text = str;\r\n      }\r\n\r\n      const option = new Option(text, value);\r\n      if (groupLabel) {\r\n        let optgroup = groups.get(groupLabel);\r\n        if (!optgroup) {\r\n          optgroup = document.createElement('optgroup');\r\n          optgroup.label = groupLabel;\r\n          groups.set(groupLabel, optgroup);\r\n          select.appendChild(optgroup);\r\n        }\r\n        optgroup.appendChild(option);\r\n      } else {\r\n        select.add(option);\r\n      }\r\n    }\r\n  }\r\n\r\n  function boolAttr(element: Element, name: string): boolean {\r\n    const el = element as Record<string, any>;\r\n    if (name in el && typeof el[name] === 'boolean') return el[name];\r\n    const attr = element.getAttribute(name);\r\n    if (attr === null) return false;\r\n    if (attr === '' || attr.toLowerCase() === 'true' || attr.toLowerCase() === name) return true;\r\n    return false;\r\n  }", "/**\r\n * @module pipes\r\n * Data transformation functions (pipes) for use in template expressions.\r\n * Pipes transform values for display, like formatting dates, currencies, or text.\r\n *\r\n * Locale-aware pipes (currency, date, daysAgo, pieces) use the i18n system\r\n * for formatting and translations. Call `setLocale()` before using these pipes.\r\n *\r\n * Pipes can be chained in templates: `{{value | uppercase | shorten:20}}`\r\n *\r\n * @example\r\n * // In templates\r\n * <span>{{user.name | uppercase}}</span>\r\n * <span>{{price | currency}}</span>\r\n * <span>{{createdAt | daysAgo}}</span>\r\n *\r\n * @example\r\n * // Programmatic usage\r\n * import { applyPipes, defaultPipes } from 'relaxjs';\r\n * const result = applyPipes('hello world', ['uppercase', 'shorten:8']);\r\n * // Returns: 'HELLO...'\r\n */\r\n\r\nimport { getCurrentLocale, t } from './i18n/i18n';\r\n\r\n/**\r\n * Type definition for pipe transformation functions.\r\n * Pipes take a value and optional arguments, returning a transformed value.\r\n *\r\n * @example\r\n * // Define a custom pipe\r\n * const reversePipe: PipeFunction = (value: string) => {\r\n *     return value.split('').reverse().join('');\r\n * };\r\n */\r\nexport type PipeFunction = (value: any, ...args: any[]) => any;\r\n\r\n\r\n//  =============================== Text manipulation pipes  ===========================\r\n\r\n\r\n\r\n/**\r\n * Converts a string to uppercase\r\n * @param value The string to convert\r\n * @returns The uppercase string\r\n */\r\nexport function uppercasePipe(value: string): string {\r\n    return String(value).toUpperCase();\r\n}\r\n\r\n/**\r\n * Converts a string to uppercase\r\n * @param value The string to convert\r\n * @returns The uppercase string\r\n */\r\nexport function trimPipe(value: string): string {\r\n    return String(value).trimEnd().trimStart();\r\n}\r\n\r\n\r\n/**\r\n * Converts a string to lowercase\r\n * @param value The string to convert\r\n * @returns The lowercase string\r\n */\r\nexport function lowercasePipe(value: string): string {\r\n    return String(value).toLowerCase();\r\n}\r\n\r\n/**\r\n * Capitalizes the first character of a string\r\n * @param value The string to capitalize\r\n * @returns The capitalized string\r\n */\r\nexport function capitalizePipe(value: string): string {\r\n    const str = String(value);\r\n    return str.charAt(0).toUpperCase() + str.slice(1);\r\n}\r\n\r\n/**\r\n * Shortens a string to a specified length and adds ellipsis.\r\n * @param value The string to shorten\r\n * @param length Maximum length including ellipsis\r\n * @returns The shortened string with ellipsis if needed\r\n */\r\nexport function shortenPipe(value: string, length: string): string {\r\n    const str = String(value);\r\n    const maxLength = parseInt(length, 10);\r\n    return str.length > maxLength\r\n        ? str.substring(0, maxLength - 3) + '...'\r\n        : str;\r\n}\r\n\r\n// Formatting pipes\r\n/**\r\n * Formats a number as currency using the current locale.\r\n * Uses the i18n system's current locale for formatting.\r\n *\r\n * @param value The number to format\r\n * @param currency Currency code (defaults to USD)\r\n * @returns Formatted currency string\r\n *\r\n * @example\r\n * // In template: {{price | currency}} or {{price | currency:EUR}}\r\n * currencyPipe(1234.56);        // \"$1,234.56\" (en) or \"1 234,56 $\" (sv)\r\n * currencyPipe(1234.56, 'SEK'); // \"SEK 1,234.56\" (en) or \"1 234,56 kr\" (sv)\r\n */\r\nexport function currencyPipe(value: number, currency: string = 'USD'): string {\r\n    const locale = getCurrentLocale();\r\n    return new Intl.NumberFormat(locale, {\r\n        style: 'currency',\r\n        currency\r\n    }).format(value);\r\n}\r\n\r\n/**\r\n * Formats a date value according to the specified format.\r\n * Uses the i18n system's current locale for formatting.\r\n *\r\n * @param value Date value (string, number, or Date object)\r\n * @param format Format type: 'short', 'long', or default (ISO)\r\n * @returns Formatted date string\r\n *\r\n * @example\r\n * // In template: {{date | date:short}} or {{date | date:long}}\r\n * datePipe(new Date(), 'short'); // \"1/15/2024\" (en) or \"2024-01-15\" (sv)\r\n * datePipe(new Date(), 'long');  // \"Monday, January 15, 2024\" (en) or \"m\u00E5ndag 15 januari 2024\" (sv)\r\n */\r\nexport function datePipe(value: string | number | Date, format?: string): string {\r\n    const date = new Date(value);\r\n    const locale = getCurrentLocale();\r\n    if (format === 'short') {\r\n        return date.toLocaleDateString(locale);\r\n    } else if (format === 'long') {\r\n        return date.toLocaleDateString(locale, {\r\n            weekday: 'long',\r\n            year: 'numeric',\r\n            month: 'long',\r\n            day: 'numeric'\r\n        });\r\n    }\r\n    return date.toISOString();\r\n}\r\n\r\n/**\r\n * Prints today, yesterday or X days ago.\r\n * Uses the i18n system for translations (requires pipes namespace loaded).\r\n *\r\n * @param value Date value (string, number, or Date object)\r\n * @returns Formatted relative date string\r\n *\r\n * @example\r\n * // In template: {{createdAt | daysAgo}}\r\n * // English: \"today\", \"yesterday\", \"3 days ago\"\r\n * // Swedish: \"idag\", \"ig\u00E5r\", \"3 dagar sedan\"\r\n */\r\nexport function daysAgoPipe(value: string | number | Date): string {\r\n    if (!value) {\r\n        return 'n/a';\r\n    }\r\n\r\n    const inputDate = new Date(value);\r\n    const today = new Date();\r\n\r\n    // Normalize times to midnight to compare only dates\r\n    inputDate.setHours(0, 0, 0, 0);\r\n    today.setHours(0, 0, 0, 0);\r\n\r\n    const diffTime = today.getTime() - inputDate.getTime();\r\n    const diffDays = Math.round(diffTime / (1000 * 60 * 60 * 24));\r\n\r\n    if (diffDays === 0) return t('r-pipes:today');\r\n    if (diffDays === 1) return t('r-pipes:yesterday');\r\n    return t('r-pipes:daysAgo', { count: diffDays });\r\n}\r\n\r\n/**\r\n * Formats a count as pieces/items.\r\n * Uses the i18n system for translations (requires pipes namespace loaded).\r\n *\r\n * @param value Count value\r\n * @returns Formatted piece count string\r\n *\r\n * @example\r\n * // In template: {{quantity | pieces}}\r\n * // English: \"none\", \"one\", \"3 pcs\"\r\n * // Swedish: \"inga\", \"en\", \"3 st\"\r\n */\r\nexport function piecesPipe(value: string | number): string {\r\n    if (value === null || value === undefined) {\r\n        return 'n/a';\r\n    }\r\n\r\n    const count = Number(value);\r\n    return t('r-pipes:pieces', { count });\r\n}\r\n\r\n\r\n\r\n//  =============================== Array operation pipes  ===========================\r\n\r\n\r\n\r\n/**\r\n * Joins array elements with the specified separator\r\n * @param value Array to join\r\n * @param separator Character(s) to use between elements (defaults to comma)\r\n * @returns Joined string or original value if not an array\r\n */\r\nexport function joinPipe(value: any[], separator: string = ','): string | any {\r\n    if (!Array.isArray(value)) return value;\r\n    return value.join(separator);\r\n}\r\n\r\n/**\r\n * Returns the first element of an array\r\n * @param value Array to extract from\r\n * @returns First element or empty string if array is empty/invalid\r\n */\r\nexport function firstPipe(value: any[]): any {\r\n    if (!Array.isArray(value) || value.length === 0) return '';\r\n    return value[0];\r\n}\r\n\r\n/**\r\n * Returns the last element of an array\r\n * @param value Array to extract from\r\n * @returns Last element or empty string if array is empty/invalid\r\n */\r\nexport function lastPipe(value: any[]): any {\r\n    if (!Array.isArray(value) || value.length === 0) return '';\r\n    return value[value.length - 1];\r\n}\r\n\r\n// Object operation pipes\r\n/**\r\n * Returns the keys of an object\r\n * @param value Object to extract keys from\r\n * @returns Array of object keys or empty array if not an object\r\n */\r\nexport function keysPipe(value: object): string[] {\r\n    if (typeof value !== 'object' || value === null) return [];\r\n    return Object.keys(value);\r\n}\r\n\r\n// Conditional pipes\r\n/**\r\n * Returns a default value if the input is falsy\r\n * @param value Input value to check\r\n * @param defaultValue Value to return if input is falsy\r\n * @returns Original value or default value\r\n */\r\nexport function defaultPipe(value: any, defaultValue: string): any {\r\n    return value || defaultValue;\r\n}\r\n\r\n/**\r\n * Implements ternary operator as a pipe\r\n * @param value Condition to evaluate\r\n * @param trueValue Value to return if condition is truthy\r\n * @param falseValue Value to return if condition is falsy\r\n * @returns Selected value based on condition\r\n */\r\nexport function ternaryPipe(value: any, trueValue: string, falseValue: string): string {\r\n    return value ? trueValue : falseValue;\r\n}\r\n\r\n\r\n\r\n//  =============================== Pipe registry and application  ===========================\r\n\r\n\r\n/**\r\n * Interface for a collection of pipe functions.\r\n * Use this to look up pipes by name for template processing.\r\n *\r\n * @example\r\n * // Check if a pipe exists before using\r\n * if (registry.has('currency')) {\r\n *     const formatted = registry.get('currency')(price);\r\n * }\r\n */\r\nexport interface PipeRegistry {\r\n    /**\r\n     * Looks up a pipe by name, returning null if not found.\r\n     */\r\n    lookup(name: string): PipeFunction | null;\r\n\r\n    /**\r\n     * Gets a pipe by name, throwing if not found.\r\n     */\r\n    get(name: string): PipeFunction;\r\n\r\n    /**\r\n     * Checks if a pipe with the given name exists.\r\n     */\r\n    has(name: string): boolean;\r\n}\r\n\r\n\r\n/**\r\n * Creates a new pipe registry with all built-in pipes registered.\r\n * Built-in pipes include:\r\n *\r\n * **Text:** uppercase, lowercase, capitalize, trim, shorten\r\n * **Formatting:** currency, date, daysAgo, pieces\r\n * **Arrays:** join, first, last\r\n * **Objects:** keys\r\n * **Conditionals:** default, ternary\r\n *\r\n * @returns A new pipe registry instance\r\n *\r\n * @example\r\n * const registry = createPipeRegistry();\r\n * const upperPipe = registry.get('uppercase');\r\n * console.log(upperPipe('hello')); // 'HELLO'\r\n */\r\nexport function createPipeRegistry(): PipeRegistry {\r\n    const pipes = new Map<string, PipeFunction>();\r\n\r\n    // Text manipulation\r\n    pipes.set('uppercase', uppercasePipe);\r\n    pipes.set('lowercase', lowercasePipe);\r\n    pipes.set('capitalize', capitalizePipe);\r\n    pipes.set('trim', trimPipe);\r\n    pipes.set('shorten', shortenPipe);\r\n\r\n    // Formatting\r\n    pipes.set('currency', currencyPipe);\r\n    pipes.set('date', datePipe);\r\n    pipes.set('daysAgo', daysAgoPipe);\r\n    pipes.set('pieces', piecesPipe);\r\n\r\n    // Array operations\r\n    pipes.set('join', joinPipe);\r\n    pipes.set('first', firstPipe);\r\n    pipes.set('last', lastPipe);\r\n\r\n    // Object operations\r\n    pipes.set('keys', keysPipe);\r\n\r\n    // Conditional formatting\r\n    pipes.set('default', defaultPipe);\r\n    pipes.set('ternary', ternaryPipe);\r\n\r\n    return {\r\n        lookup(name) {\r\n            return pipes.get(name) ?? null;\r\n        },\r\n        get(name) {\r\n            var pipe = pipes.get(name);\r\n            if (!pipe) {\r\n                throw Error(\"Pipe '\" + name + \"' not found.\");\r\n            }\r\n            return pipe;\r\n        },\r\n        has(name) {\r\n            return pipes.has(name);\r\n        },\r\n    };\r\n}\r\n\r\n/**\r\n * Default pipe registry instance with all built-in pipes.\r\n * Used by template engines unless a custom registry is provided.\r\n *\r\n * @example\r\n * import { defaultPipes } from 'relaxjs';\r\n *\r\n * if (defaultPipes.has('uppercase')) {\r\n *     const result = defaultPipes.get('uppercase')('hello');\r\n * }\r\n */\r\nexport const defaultPipes = createPipeRegistry();\r\n\r\n/**\r\n * Applies a series of pipes to a value sequentially.\r\n * Each pipe transforms the output of the previous pipe.\r\n *\r\n * Pipe arguments are specified after a colon: `shorten:20`\r\n *\r\n * @param value - Initial value to transform\r\n * @param pipes - Array of pipe strings (name and optional arguments separated by ':')\r\n * @param registry - Optional custom pipe registry (uses defaultPipes if not provided)\r\n * @returns The transformed value after applying all pipes\r\n *\r\n * @example\r\n * // Apply single pipe\r\n * applyPipes('hello', ['uppercase']); // 'HELLO'\r\n *\r\n * @example\r\n * // Chain multiple pipes\r\n * applyPipes('hello world', ['uppercase', 'shorten:8']); // 'HELLO...'\r\n *\r\n * @example\r\n * // With pipe arguments\r\n * applyPipes(1234.56, ['currency']); // '$1,234.56'\r\n */\r\nexport function applyPipes(\r\n    value: any,\r\n    pipes: string[],\r\n    registry: PipeRegistry = defaultPipes\r\n): any {\r\n\r\n    return pipes.reduce((currentValue, pipe) => {\r\n        const [pipeName, ...args] = pipe.split(':').map((p) => p.trim());\r\n\r\n        if (!registry.has(pipeName)) {\r\n            return `[Pipe ${pipeName} not found]`;\r\n        }\r\n\r\n        try {\r\n            return registry.get(pipeName)(currentValue, ...args);\r\n        } catch (error) {\r\n            return `[Pipe ${pipeName}, value: ${value}, error: ${error}]`;\r\n        }\r\n    }, value);\r\n}", "/**\r\n * @module html\r\n * HTML template engine with update capabilities.\r\n * Creates templates that can be re-rendered with new data without recreating DOM nodes.\r\n */\r\n\r\nimport { defaultPipes } from \"../pipes\";\r\n\r\nconst pipes = defaultPipes;\r\n\r\ninterface Binding {\r\n  originalValue?: unknown;\r\n  setter: (instance: unknown) => void;\r\n}\r\n\r\n/**\r\n * Result of rendering a template.\r\n * Provides the DOM fragment and an update function for re-rendering.\r\n */\r\nexport interface RenderTemplate {\r\n  /** The rendered DOM fragment */\r\n  fragment: DocumentFragment;\r\n  /** Updates the DOM with new data without recreating elements */\r\n  update(context: any): void;\r\n}\r\n\r\n/**\r\n * Creates an updateable HTML template using tagged template literals.\r\n * Returns an object with the fragment and an update method for efficient re-rendering.\r\n *\r\n * Supports:\r\n * - Template literal substitutions (`${}`)\r\n * - Mustache-style bindings (`{{property}}`)\r\n * - Pipe transformations (`{{value|uppercase}}`)\r\n * - Event handler binding\r\n *\r\n * @param templateStrings - The static parts of the template literal\r\n * @param substitutions - The dynamic values interpolated into the template\r\n * @returns A function that takes context and returns a RenderTemplate\r\n *\r\n * @example\r\n * // Create and render a template\r\n * const template = html`\r\n *     <div class=\"user\">\r\n *         <h2>{{name}}</h2>\r\n *         <p>{{email}}</p>\r\n *         <span>{{createdAt|daysAgo}}</span>\r\n *     </div>\r\n * `;\r\n *\r\n * const result = template({ name: 'John', email: 'john@example.com', createdAt: new Date() });\r\n * container.appendChild(result.fragment);\r\n *\r\n * // Later, update with new data\r\n * result.update({ name: 'Jane', email: 'jane@example.com', createdAt: new Date() });\r\n *\r\n * @example\r\n * // With event handlers\r\n * const row = html`\r\n *     <tr>\r\n *         <td>{{name}}</td>\r\n *         <td><button onclick=${function() { this.edit(this.id) }}>Edit</button></td>\r\n *     </tr>\r\n * `;\r\n */\r\nexport function html(\r\n  templateStrings: TemplateStringsArray,\r\n  ...substitutions: any[]\r\n): (context: any) => RenderTemplate {\r\n  // Preprocess template strings\r\n  const template = document.createElement(\"template\");\r\n  const resolvedTemplate = resolveTemplate(templateStrings);\r\n  template.innerHTML = resolvedTemplate;\r\n  const bindings: Binding[] = [];\r\n\r\n  const walker = document.createTreeWalker(\r\n    template.content,\r\n    NodeFilter.SHOW_ALL\r\n  );\r\n  let node: Node | null;\r\n\r\n  while ((node = walker.nextNode())) {\r\n    if (node.nodeType === Node.ELEMENT_NODE) {\r\n      const element = node as HTMLElement;\r\n      processElement(element, substitutions, bindings);\r\n      if (customElements.get(element.tagName.toLowerCase())) {\r\n        customElements.upgrade(element);\r\n      }\r\n    } else if (node.nodeType === Node.TEXT_NODE) {\r\n      const myNode = node;\r\n      const text = myNode.textContent!;\r\n      const result = parseTemplate(text, substitutions);\r\n      if (result) {\r\n        const hasSubstitutions = /\u20AC\u20AC\\d+\u20AC\u20AC/.test(text);\r\n        if (hasSubstitutions) {\r\n          let startMarker: Comment | null = null;\r\n          let endMarker: Comment | null = null;\r\n          let insertedNodes: Node[] = [];\r\n          bindings.push({\r\n            originalValue: text,\r\n            setter(instance) {\r\n              var value = result(instance);\r\n              if (!startMarker) {\r\n                startMarker = document.createComment('');\r\n                endMarker = document.createComment('');\r\n                myNode.parentNode?.replaceChild(endMarker, myNode);\r\n                endMarker.parentNode?.insertBefore(startMarker, endMarker);\r\n              }\r\n              insertedNodes.forEach(n => n.parentNode?.removeChild(n));\r\n              insertedNodes = [];\r\n              const temp = document.createElement('template');\r\n              temp.innerHTML = value;\r\n              const nodes = Array.from(temp.content.childNodes);\r\n              const parent = endMarker!.parentNode!;\r\n              nodes.forEach(n => {\r\n                parent.insertBefore(n, endMarker);\r\n                insertedNodes.push(n);\r\n              });\r\n            },\r\n          });\r\n        } else {\r\n          bindings.push({\r\n            originalValue: text,\r\n            setter(instance) {\r\n              var value = result(instance);\r\n              myNode.textContent = value;\r\n            },\r\n          });\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  // Return a function for binding\r\n  return function bind(context: any): RenderTemplate {\r\n    bindings.forEach((x) => {\r\n      x.setter(context);\r\n    });\r\n\r\n    return {\r\n      fragment: template.content,\r\n      update(context: any) {\r\n        bindings.forEach((x) => {\r\n          x.setter(context);\r\n        });\r\n      },\r\n    };\r\n  };\r\n}\r\n\r\nfunction resolveTemplate(templateStrings: TemplateStringsArray): string {\r\n  return templateStrings.raw\r\n    .map((str, i) =>\r\n      i < templateStrings.raw.length - 1 ? `${str}\u20AC\u20AC${i}\u20AC\u20AC` : str\r\n    )\r\n    .join(\"\");\r\n}\r\n\r\nfunction processElement(\r\n  element: HTMLElement,\r\n  substitutions: any[],\r\n  bindings: Binding[]\r\n) {\r\n  const attrBindings: Binding[] = [];\r\n\r\n  for (const attr of Array.from(element.attributes)) {\r\n    var attrValue = attr.value;\r\n    if (attrValue == \"\") {\r\n      continue;\r\n    }\r\n\r\n    const regex = /\u20AC\u20AC(\\d+)\u20AC\u20AC/;\r\n    const match = attrValue.match(regex);\r\n    if (match) {\r\n      const index = parseInt(match[1], 10);\r\n      const func = substitutions[index];\r\n      if (typeof func === \"function\") {\r\n        attrBindings.push({\r\n          setter(instance) {\r\n            const boundFunction = func.bind(instance);\r\n            element.removeAttribute(attr.name);\r\n            (element as any)[attr.name] = boundFunction;\r\n          },\r\n        });\r\n\r\n        continue;\r\n      }\r\n    }\r\n\r\n    var attributeCallback = parseTemplate(attrValue, substitutions);\r\n    if (attributeCallback == null) {\r\n      continue;\r\n    }\r\n\r\n    attrBindings.push({\r\n      originalValue: attrValue,\r\n      setter(instance) {\r\n        const value = attributeCallback!(instance) ?? attrValue;\r\n        if (attr.name in element) {\r\n          (element as any)[attr.name] = value;\r\n        } else {\r\n          attr.value = value;\r\n        }\r\n      },\r\n    });\r\n  }\r\n\r\n  if (attrBindings.length > 0) {\r\n    bindings.push({\r\n      originalValue: element.tagName,\r\n      setter(instance) {\r\n        attrBindings.forEach((attrBinding) => attrBinding.setter(instance));\r\n      },\r\n    });\r\n  }\r\n}\r\n\r\ntype TemplateCallback = (instance: any) => string;\r\n\r\n\r\n/**\r\n * Parse arguments for function calls in mustache expressions\r\n * Handles dot notation like row.id and nested properties\r\n */\r\nfunction parseArguments(argsStr: string, instance: any): any[] {\r\n  return argsStr.split(',').map(arg => {\r\n    arg = arg.trim();\r\n\r\n    if ((arg.startsWith('\"') && arg.endsWith('\"')) ||\r\n        (arg.startsWith(\"'\") && arg.endsWith(\"'\"))) {\r\n      return arg.slice(1, -1);\r\n    }\r\n\r\n    if (!isNaN(Number(arg))) {\r\n      return Number(arg);\r\n    }\r\n\r\n    if (arg.includes('.')) {\r\n      const parts = arg.split('.');\r\n      let value = instance;\r\n      for (const part of parts) {\r\n        if (value === undefined || value === null) return undefined;\r\n        value = value[part];\r\n      }\r\n      return value;\r\n    }\r\n\r\n    // Handle simple variable references\r\n    return instance[arg];\r\n  });\r\n}\r\n\r\n\r\nfunction parseTemplate(\r\n  template: string,\r\n  substitutions: any[]\r\n): TemplateCallback | null {\r\n  const regex = /\u20AC\u20AC(\\d+)\u20AC\u20AC|{{\\s*([^|]+?)(?:\\|([\\w|]+))?\\s*}}/g;\r\n  let lastIndex = 0;\r\n  let match;\r\n\r\n  const textBindings: TemplateCallback[] = [];\r\n  while ((match = regex.exec(template)) !== null) {\r\n    var value = template.slice(lastIndex, match.index);\r\n    if (value.length > 0) {\r\n      textBindings.push((_instance) => {\r\n        return value;\r\n      });\r\n    }\r\n\r\n    // ${}\r\n    if (match[1]) {\r\n      const index = parseInt(match[1], 10);\r\n      const sub = substitutions[index];\r\n      if (!sub) {\r\n        continue;\r\n      }\r\n\r\n      if (typeof sub === \"function\") {\r\n        const func = sub as Function;\r\n        textBindings.push((instance) => {\r\n          var result = func.apply(instance);\r\n          return result;\r\n        });\r\n      } else {\r\n        if (sub && sub.length > 0) {\r\n          textBindings.push((instance) => {\r\n            return sub;\r\n          });\r\n        }\r\n      }\r\n    } else if (match[2]) {\r\n      // {{mustache|pipes}} case\r\n      const mustacheName = match[2].trim();\r\n      const argsStr = match[3] ? match[3].trim() : null;\r\n      const matchingPipes = match[4]\r\n        ? match[4].split(\"|\").map((pipe) => pipe.trim())\r\n        : [];\r\n\r\n      textBindings.push((instance) => {\r\n        var value = instance[mustacheName];\r\n\r\n        if (typeof value === \"function\") {\r\n          if (argsStr) {\r\n            const args = parseArguments(argsStr, instance);\r\n            value = value.apply(instance, args);\r\n          } else {\r\n            value = value.call(instance);\r\n          }\r\n        }\r\n\r\n        matchingPipes.forEach((pipe) => {\r\n          value = pipes.get(pipe)(value);\r\n        });\r\n        return value;\r\n      });\r\n    }\r\n\r\n    lastIndex = regex.lastIndex;\r\n  }\r\n\r\n  if (textBindings.length == 0) {\r\n    return null;\r\n  }\r\n\r\n  var val = template.slice(lastIndex);\r\n  if (val.length > 0) {\r\n    textBindings.push((_) => {\r\n      return val;\r\n    });\r\n  }\r\n  return (instance) => {\r\n    var result = \"\";\r\n    textBindings.forEach((binding) => {\r\n      var value = binding(instance);\r\n      result += value;\r\n    });\r\n\r\n    return result;\r\n  };\r\n}\r\n", "/**\r\n * @module template\r\n * DOM-based template engine with reactive rendering capabilities.\r\n *\r\n * Compiles HTML templates with mustache-style expressions into efficient\r\n * render functions that update the DOM when data changes.\r\n *\r\n * **Features:**\r\n * - Text interpolation: `{{name}}`, `{{user.profile.email}}`\r\n * - Attribute binding: `<div class=\"{{className}}\">`\r\n * - Pipes: `{{price | currency}}`, `{{name | uppercase | shorten:20}}`\r\n * - Function calls: `{{formatDate(createdAt)}}`, `{{add(5, 3)}}`\r\n * - Array indexing: `{{items[0]}}`, `{{users[1].name}}`\r\n * - Conditionals: `<div if=\"isVisible\">`, `<div unless=\"isHidden\">`\r\n * - Loops: `<li loop=\"item in items\">{{item.name}}</li>`\r\n *\r\n * @example\r\n * // Basic usage\r\n * import { compileTemplate } from './m';\r\n *\r\n * const { content, render } = compileTemplate(`\r\n *     <div class=\"card\">\r\n *         <h2>{{title}}</h2>\r\n *         <p>{{description}}</p>\r\n *     </div>\r\n * `);\r\n *\r\n * render({ title: 'Hello', description: 'World' });\r\n * document.body.appendChild(content);\r\n *\r\n * @example\r\n * // With pipes and functions\r\n * import { createPipeRegistry } from '../pipes';\r\n *\r\n * const pipeRegistry = createPipeRegistry();\r\n * const { content, render } = compileTemplate(`\r\n *     <span>{{user.name | uppercase}}</span>\r\n *     <span>{{formatDate(user.createdAt)}}</span>\r\n * `, { strict: false, pipeRegistry });\r\n *\r\n * render(\r\n *     { user: { name: 'john', createdAt: new Date() } },\r\n *     { formatDate: (d) => d.toLocaleDateString() }\r\n * );\r\n *\r\n * @example\r\n * // With loops and conditionals\r\n * const { content, render } = compileTemplate(`\r\n *     <ul>\r\n *         <li loop=\"item in items\" if=\"item.visible\">\r\n *             {{item.name}}: {{item.price | currency}}\r\n *         </li>\r\n *     </ul>\r\n * `);\r\n *\r\n * render({ items: [\r\n *     { name: 'Apple', price: 1.5, visible: true },\r\n *     { name: 'Hidden', price: 0, visible: false }\r\n * ]});\r\n */\r\n\r\nimport { PipeRegistry, defaultPipes, applyPipes } from '../pipes';\r\n\r\n/**\r\n * Configuration options for the template engine.\r\n *\r\n * @example\r\n * const config: EngineConfig = {\r\n *     strict: true,\r\n *     onError: (msg) => console.error(msg),\r\n *     pipeRegistry: createPipeRegistry()\r\n * };\r\n */\r\nexport interface EngineConfig {\r\n    /** When true, throws errors for missing paths/functions. When false, returns empty string. */\r\n    strict: boolean;\r\n    /** Optional callback invoked when errors occur, receives formatted error message. */\r\n    onError?: (msg: string) => void;\r\n    /** Custom pipe registry for transformations. Defaults to built-in pipes. */\r\n    pipeRegistry?: PipeRegistry;\r\n}\r\n\r\nexport type Path = string;\r\nexport type TemplateValue = string | number | boolean | null | undefined;\r\n\r\n/**\r\n * Data context object passed to render function.\r\n * Contains the data values that expressions resolve against.\r\n *\r\n * @example\r\n * const ctx: Context = {\r\n *     user: { name: 'John', age: 30 },\r\n *     items: ['a', 'b', 'c'],\r\n *     isActive: true\r\n * };\r\n *\r\n * @internal\r\n */\r\nexport interface Context {\r\n    [key: string]: ContextValue;\r\n}\r\n\r\n/**\r\n * Functions context object passed as second argument to render.\r\n * Contains callable functions that can be invoked from templates.\r\n *\r\n * @example\r\n * const fns: FunctionsContext = {\r\n *     formatDate: (d) => d.toLocaleDateString(),\r\n *     add: (a, b) => a + b,\r\n *     greet: (name) => `Hello, ${name}!`\r\n * };\r\n *\r\n * @internal\r\n */\r\nexport interface FunctionsContext {\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    [key: string]: (...args: any[]) => any;\r\n}\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport type ContextValue = TemplateValue | any[] | Context | ((...args: any[]) => any);\r\n\r\nexport type Getter = (ctx: Context, path: Path, debugInfo?: string) => TemplateValue;\r\nexport type Setter = (ctx: Context, fns?: FunctionsContext) => void;\r\nexport type Patcher = (node: Node, get: Getter, config: EngineConfig) => Setter | void;\r\nexport type ExpressionFn = (ctx: Context, fns?: FunctionsContext) => TemplateValue;\r\n\r\ninterface ParsedExpression {\r\n    type: 'path' | 'function';\r\n    path?: string;\r\n    fnName?: string;\r\n    fnArgs?: string[];\r\n    pipes: string[];\r\n}\r\n\r\nfunction parseExpression(expr: string): ParsedExpression {\r\n    const pipesSplit = expr.split('|').map(s => s.trim());\r\n    const mainExpr = pipesSplit[0];\r\n    const pipes = pipesSplit.slice(1);\r\n\r\n    // Check if it's a function call: functionName(args)\r\n    const fnMatch = mainExpr.match(/^(\\w+)\\s*\\((.*)\\)$/);\r\n    if (fnMatch) {\r\n        const [, fnName, argsStr] = fnMatch;\r\n        const fnArgs = argsStr\r\n            ? argsStr.split(',').map(a => a.trim())\r\n            : [];\r\n        return { type: 'function', fnName, fnArgs, pipes };\r\n    }\r\n\r\n    return { type: 'path', path: mainExpr, pipes };\r\n}\r\n\r\n// Resolve a path with support for array indexing: items[0].name\r\nfunction resolvePath(ctx: ContextValue, path: string): ContextValue {\r\n    // Handle array indexing by converting items[0] to items.0\r\n    const normalizedPath = path.replace(/\\[(\\d+)\\]/g, '.$1');\r\n    const segments = normalizedPath.split('.');\r\n    let current = ctx;\r\n\r\n    for (const key of segments) {\r\n        if (current && typeof current === 'object' && key in current) {\r\n            current = (current as Record<string, ContextValue>)[key];\r\n        } else {\r\n            return undefined;\r\n        }\r\n    }\r\n\r\n    return current;\r\n}\r\n  \r\n  function handleError(config: EngineConfig, message: string, context: string, shouldThrow = false): void {\r\n    const formattedMessage = `[template error] ${message} (at ${context})`;\r\n\r\n    if (window.relaxDebug?.templates) console.warn(formattedMessage);\r\n    if (config.onError) config.onError(formattedMessage);\r\n    if (config.strict || shouldThrow) throw new Error(formattedMessage);\r\n  }\r\n  \r\nfunction createGetter(config: EngineConfig): Getter {\r\n    return function get(ctx: ContextValue, path: Path, debugInfo = ''): TemplateValue {\r\n        try {\r\n            const current = resolvePath(ctx, path);\r\n\r\n            if (current === undefined) {\r\n                handleError(config, `Cannot resolve \"${path}\"`, debugInfo);\r\n                return '';\r\n            }\r\n\r\n            // Return primitive values as-is for conditional checks\r\n            if (current === null) {\r\n                return '';\r\n            } else if (Array.isArray(current)) {\r\n                return current.length > 0 ? JSON.stringify(current) : '';\r\n            } else if (typeof current === 'object') {\r\n                return JSON.stringify(current);\r\n            } else {\r\n                return current as TemplateValue;\r\n            }\r\n        } catch (err) {\r\n            const errorMessage = err instanceof Error ? err.message : String(err);\r\n            handleError(config, `Exception resolving \"${path}\": ${errorMessage}`, debugInfo, true);\r\n            return '';\r\n        }\r\n    };\r\n}\r\n\r\nfunction evaluateExpression(\r\n    parsed: ParsedExpression,\r\n    ctx: Context,\r\n    fns: FunctionsContext | undefined,\r\n    config: EngineConfig,\r\n    debugInfo: string\r\n): TemplateValue {\r\n    let value: TemplateValue;\r\n    const registry = config.pipeRegistry ?? defaultPipes;\r\n\r\n    if (parsed.type === 'function') {\r\n        const fn = fns?.[parsed.fnName!];\r\n        if (typeof fn !== 'function') {\r\n            handleError(config, `Function \"${parsed.fnName}\" not found`, debugInfo);\r\n            return '';\r\n        }\r\n\r\n        // Resolve function arguments - could be literals or paths\r\n        const resolvedArgs = (parsed.fnArgs ?? []).map(arg => {\r\n            // String literal\r\n            if ((arg.startsWith('\"') && arg.endsWith('\"')) ||\r\n                (arg.startsWith(\"'\") && arg.endsWith(\"'\"))) {\r\n                return arg.slice(1, -1);\r\n            }\r\n            // Number literal\r\n            if (!isNaN(Number(arg))) {\r\n                return Number(arg);\r\n            }\r\n            // Path reference - resolve from context\r\n            const resolved = resolvePath(ctx, arg);\r\n            return resolved;\r\n        });\r\n\r\n        try {\r\n            value = fn(...resolvedArgs) as TemplateValue;\r\n        } catch (err) {\r\n            const errorMessage = err instanceof Error ? err.message : String(err);\r\n            handleError(config, `Error calling \"${parsed.fnName}\": ${errorMessage}`, debugInfo);\r\n            return '';\r\n        }\r\n    } else {\r\n        // Path resolution\r\n        const resolved = resolvePath(ctx, parsed.path!);\r\n        if (resolved === undefined) {\r\n            handleError(config, `Cannot resolve \"${parsed.path}\"`, debugInfo);\r\n            return '';\r\n        }\r\n        if (resolved === null) {\r\n            value = '';\r\n        } else if (typeof resolved === 'object') {\r\n            value = JSON.stringify(resolved);\r\n        } else {\r\n            value = resolved as TemplateValue;\r\n        }\r\n    }\r\n\r\n    // Apply pipes if any\r\n    if (parsed.pipes.length > 0) {\r\n        value = applyPipes(value, parsed.pipes, registry);\r\n    }\r\n\r\n    return value;\r\n}\r\n  \r\ninterface InterpolationPart {\r\n    /** Set for a `{{expr}}` segment, null for surrounding literal text. */\r\n    parsed: ParsedExpression | null;\r\n    literal: string;\r\n}\r\n\r\nconst expressionCache = new Map<string, InterpolationPart[]>();\r\n\r\n/**\r\n * Splits interpolated text into the literal and `{{expr}}` segments it is made\r\n * of, so both can be re-joined on every render. Text and attributes share the\r\n * parse result, which is memoized because loops recompile a clone per item.\r\n */\r\nfunction splitInterpolation(raw: string): InterpolationPart[] {\r\n    let parts = expressionCache.get(raw);\r\n    if (!parts) {\r\n        parts = raw\r\n            .split(/(\\{\\{.*?\\}\\})/)\r\n            .filter(part => part !== '')\r\n            .map(part => part.startsWith('{{') && part.endsWith('}}')\r\n                ? { parsed: parseExpression(part.slice(2, -2).trim()), literal: '' }\r\n                : { parsed: null, literal: part });\r\n        expressionCache.set(raw, parts);\r\n    }\r\n    return parts;\r\n}\r\n\r\nfunction composeParts(\r\n    parts: InterpolationPart[],\r\n    ctx: Context,\r\n    fns: FunctionsContext | undefined,\r\n    config: EngineConfig,\r\n    debugInfo: string\r\n): string {\r\n    return parts\r\n        .map(({ parsed, literal }) => parsed\r\n            ? String(evaluateExpression(parsed, ctx, fns, config, debugInfo))\r\n            : literal)\r\n        .join('');\r\n}\r\n\r\nfunction textNodePatcher(node: Node, _get: Getter, config: EngineConfig): Setter | void {\r\n    if (node.nodeType !== Node.TEXT_NODE || !node.textContent?.includes('{{')) return;\r\n\r\n    const raw = node.textContent;\r\n    const parts = splitInterpolation(raw);\r\n    const debugInfo = `TextNode: \"${raw}\"`;\r\n\r\n    return (ctx: Context, fns?: FunctionsContext) => {\r\n        (node as Text).textContent = composeParts(parts, ctx, fns, config, debugInfo);\r\n    };\r\n}\r\n  \r\n/**\r\n * Attributes whose content attribute does not stay in sync with the live\r\n * property the user actually sees. Setting `value`/`checked`/`selected` via\r\n * `setAttribute` only writes the *default* (`defaultValue`/`defaultChecked`),\r\n * so a form control that is cleared and repopulated programmatically would\r\n * keep showing stale data. For these we write the property directly.\r\n */\r\nconst liveValueAttributes = ['value', 'checked', 'selected'];\r\n\r\n/**\r\n * Resolves `{{expr}}` inside element attributes and keeps them updated on\r\n * every render. An attribute may mix literal text with any number of\r\n * expressions, as in `class=\"finding {{severity}}\"`.\r\n *\r\n * Three binding modes, chosen by the attribute and the resolved value:\r\n * - `value`/`checked`/`selected` are written to the matching DOM *property*,\r\n *   because the content attribute only seeds the default and would not\r\n *   reflect a programmatic clear-and-repopulate.\r\n * - A boolean value is applied with `toggleAttribute`, so `disabled=\"{{busy}}\"`\r\n *   adds the attribute when `true` and removes it when `false` (a plain\r\n *   `setAttribute` would leave `disabled=\"false\"`, which is still disabled).\r\n * - Everything else is a normal string `setAttribute`.\r\n *\r\n * @example\r\n * // Property binding keeps the input in sync after a reset\r\n * compileTemplate('<input value=\"{{name}}\">');\r\n *\r\n * @example\r\n * // Boolean binding toggles the attribute on and off. Only a whole-value\r\n * // expression can do this; \"busy {{flag}}\" is always a string.\r\n * compileTemplate('<button disabled=\"{{busy}}\">Save</button>');\r\n *\r\n * @example\r\n * // Literals and expressions compose into one string\r\n * compileTemplate('<img src=\"/avatars/{{user.id}}.png\">');\r\n */\r\nfunction attributeInterpolationPatcher(node: Node, _get: Getter, config: EngineConfig): Setter | void {\r\n    if (node.nodeType !== Node.ELEMENT_NODE) return;\r\n\r\n    const element = node as Element;\r\n    const setters: Setter[] = [];\r\n\r\n    // Use Array.from to safely iterate over NamedNodeMap\r\n    const attributes = Array.from(element.attributes);\r\n    for (const attr of attributes) {\r\n        if (!attr.value.includes('{{')) continue;\r\n\r\n        const parts = splitInterpolation(attr.value);\r\n        if (!parts.some(part => part.parsed)) continue;\r\n\r\n        const name = attr.name;\r\n        const wholeValue = parts.length === 1 ? parts[0].parsed : null;\r\n        const debugInfo = `Attribute: ${name} on <${element.tagName.toLowerCase()}>`;\r\n\r\n        setters.push((ctx: Context, fns?: FunctionsContext) => {\r\n            const value = wholeValue\r\n                ? evaluateExpression(wholeValue, ctx, fns, config, debugInfo)\r\n                : composeParts(parts, ctx, fns, config, debugInfo);\r\n\r\n            if (liveValueAttributes.includes(name) && name in element) {\r\n                (element as unknown as Record<string, unknown>)[name] = value;\r\n            } else if (typeof value === 'boolean') {\r\n                element.toggleAttribute(name, value);\r\n            } else {\r\n                element.setAttribute(name, String(value));\r\n            }\r\n        });\r\n    }\r\n\r\n    if (setters.length > 0) {\r\n        return (ctx: Context, fns?: FunctionsContext) => setters.forEach(fn => fn(ctx, fns));\r\n    }\r\n}\r\n\r\n/**\r\n * Binds event handlers declared with `r-<event>=\"handler(args)\"`, for example\r\n * `r-click`, `r-change`, or `r-keypress`. The part after `r-` is treated as a\r\n * DOM event name and is only wired when the element actually supports it\r\n * (checked via the matching `on<event>` property); an unrecognised name is\r\n * reported as an error.\r\n *\r\n * The handler name is resolved from the functions context passed to `render`.\r\n * Arguments are resolved against the current data context, so inside a loop\r\n * the iteration alias (`row`) and its nested values can be passed straight to\r\n * the handler. The literal `event` resolves to the native DOM event.\r\n *\r\n * Listeners are attached once per element. Each render only refreshes the data\r\n * the listeners close over, so handlers keep working as loops reuse, add, or\r\n * remove rows.\r\n */\r\nfunction eventPatcher(node: Node, _get: Getter, config: EngineConfig): Setter | void {\r\n    if (node.nodeType !== Node.ELEMENT_NODE) return;\r\n\r\n    const element = node as Element;\r\n    const tag = element.tagName.toLowerCase();\r\n    const rAttributes = Array.from(element.attributes).filter(attr => attr.name.startsWith('r-'));\r\n    if (rAttributes.length === 0) return;\r\n\r\n    const updaters: Setter[] = [];\r\n\r\n    for (const attr of rAttributes) {\r\n        const eventName = attr.name.slice(2);\r\n        const expr = attr.value;\r\n        const debugInfo = `${attr.name}=\"${expr}\" on <${tag}>`;\r\n        element.removeAttribute(attr.name);\r\n\r\n        if (!(`on${eventName}` in element)) {\r\n            handleError(config, `\"${attr.name}\" is not a known event for <${tag}>`, debugInfo);\r\n            continue;\r\n        }\r\n\r\n        const parsed = parseExpression(expr);\r\n        if (parsed.type !== 'function') {\r\n            handleError(config, `${attr.name} must be a function call, got \"${expr}\"`, debugInfo);\r\n            continue;\r\n        }\r\n\r\n        let currentCtx: Context | null = null;\r\n        let currentFns: FunctionsContext | undefined = undefined;\r\n\r\n        element.addEventListener(eventName, (event) => {\r\n            if (!currentCtx) return;\r\n            const ctxWithEvent = { ...currentCtx, event } as unknown as Context;\r\n            evaluateExpression(parsed, ctxWithEvent, currentFns, config, debugInfo);\r\n        });\r\n\r\n        updaters.push((ctx: Context, fns?: FunctionsContext) => {\r\n            currentCtx = ctx;\r\n            currentFns = fns;\r\n        });\r\n    }\r\n\r\n    if (updaters.length > 0) {\r\n        return (ctx: Context, fns?: FunctionsContext) => updaters.forEach(fn => fn(ctx, fns));\r\n    }\r\n}\r\n\r\nconst structuralAttributes = ['loop', 'if', 'unless'];\r\n\r\n/** One rendered copy of a structural element, kept so the next render can re-use it. */\r\ninterface Instance {\r\n    element: Element;\r\n    render: (ctx: Context, fns?: FunctionsContext) => void;\r\n}\r\n\r\n/**\r\n * Takes full ownership of any element carrying `loop`, `if` or `unless`,\r\n * including an element carrying several of them at once. The element is\r\n * replaced by a comment placeholder, and every render decides which copies\r\n * belong after that placeholder. Content patchers and child traversal are\r\n * skipped for such an element; its copies are compiled on their own.\r\n *\r\n * `if` and `unless` combine: the element renders when the `if` holds and the\r\n * `unless` does not. On a looping element the condition is evaluated per item\r\n * against that item's context, so an item that fails it produces no element.\r\n *\r\n * Rendering order for a new copy:\r\n *\r\n * 1. Clone from template (detached, attributes still contain mustache)\r\n * 2. Compile the clone, creating setters for mustache in attributes/text\r\n * 3. Render, resolving mustache against the iteration context\r\n * 4. Insert into DOM. Custom elements upgrade with final attribute values\r\n *\r\n * Steps 2-3 MUST happen before step 4. If we insert first, the browser\r\n * upgrades custom elements immediately (connectedCallback fires) while\r\n * attributes still contain raw \"{{expr}}\" strings.\r\n *\r\n * Copies already in the DOM are re-rendered in place. The most recently\r\n * removed copy is kept, so hiding and re-showing an element, or a list that\r\n * shrinks and grows again, skips the clone + compile.\r\n */\r\nfunction structuralPatcher(node: Node, get: Getter, config: EngineConfig): Setter | void {\r\n    if (node.nodeType !== Node.ELEMENT_NODE) return;\r\n\r\n    const element = node as Element;\r\n    const loopDef = element.getAttribute('loop');\r\n    const ifExpr = element.getAttribute('if');\r\n    const unlessExpr = element.getAttribute('unless');\r\n    if (loopDef === null && ifExpr === null && unlessExpr === null) return;\r\n\r\n    const tag = element.tagName.toLowerCase();\r\n    let alias = '';\r\n    let source = '';\r\n\r\n    if (loopDef !== null) {\r\n        const match = loopDef.match(/(\\w+)\\s+in\\s+(.+)/);\r\n        if (!match) {\r\n            handleError(config, `Invalid loop syntax: \"${loopDef}\"`, `Element: <${tag}>`);\r\n            return;\r\n        }\r\n        [, alias, source] = match;\r\n    }\r\n\r\n    const template = element.cloneNode(true) as Element;\r\n    structuralAttributes.forEach(name => template.removeAttribute(name));\r\n\r\n    const placeholder = document.createComment(\r\n        loopDef !== null\r\n            ? `loop: ${loopDef}`\r\n            : ifExpr !== null\r\n                ? `if: ${ifExpr}`\r\n                : `unless: ${unlessExpr}`\r\n    );\r\n    const parent = element.parentNode!;\r\n    parent.insertBefore(placeholder, element);\r\n    element.remove();\r\n\r\n    const isVisible = (candidate: Context): boolean => {\r\n        if (ifExpr !== null && !get(candidate, ifExpr, `if=\"${ifExpr}\"`)) return false;\r\n        if (unlessExpr !== null && get(candidate, unlessExpr, `unless=\"${unlessExpr}\"`)) return false;\r\n        return true;\r\n    };\r\n\r\n    /** The contexts to render one copy for, or null when the loop source is unusable. */\r\n    const contextsToRender = (ctx: Context): Context[] | null => {\r\n        if (loopDef === null) return isVisible(ctx) ? [ctx] : [];\r\n\r\n        const items = resolvePath(ctx, source);\r\n\r\n        if (items === undefined) {\r\n            handleError(config, `Cannot resolve \"${source}\"`, `Loop source: \"${loopDef}\"`);\r\n            return null;\r\n        }\r\n\r\n        if (!Array.isArray(items)) {\r\n            handleError(config, `\"${source}\" is not an array in loop: \"${loopDef}\"`, `Element: <${tag}>`);\r\n            return null;\r\n        }\r\n\r\n        return items\r\n            .map(item => ({ ...ctx, [alias]: item }) as Context)\r\n            .filter(isVisible);\r\n    };\r\n\r\n    let instances: Instance[] = [];\r\n    let spare: Instance | null = null;\r\n\r\n    return (ctx: Context, fns?: FunctionsContext) => {\r\n        const contexts = contextsToRender(ctx);\r\n        if (!contexts) return;\r\n\r\n        const reuseCount = Math.min(instances.length, contexts.length);\r\n\r\n        // Re-render copies that are already in the DOM\r\n        for (let i = 0; i < reuseCount; i++) {\r\n            instances[i].render(contexts[i], fns);\r\n        }\r\n\r\n        // Remove excess copies, keeping the last one for re-use\r\n        for (let i = instances.length - 1; i >= contexts.length; i--) {\r\n            instances[i].element.remove();\r\n            spare = instances[i];\r\n        }\r\n\r\n        // Create missing copies via DocumentFragment for batch insertion\r\n        if (contexts.length > reuseCount) {\r\n            const fragment = document.createDocumentFragment();\r\n            const added: Instance[] = [];\r\n\r\n            for (let i = reuseCount; i < contexts.length; i++) {\r\n                let instance = spare;\r\n                spare = null;\r\n                if (!instance) {\r\n                    // 1-2. Clone (detached, no connectedCallback yet) and compile\r\n                    const clone = template.cloneNode(true) as Element;\r\n                    instance = { element: clone, render: compileDOM(clone, config) };\r\n                }\r\n\r\n                // 3. Render while detached; resolves mustache\r\n                instance.render(contexts[i], fns);\r\n\r\n                fragment.appendChild(instance.element);\r\n                added.push(instance);\r\n            }\r\n\r\n            // 4. Batch-insert into live DOM. Custom elements upgrade with final values\r\n            const insertAfter = reuseCount > 0 ? instances[reuseCount - 1].element : placeholder;\r\n            parent.insertBefore(fragment, insertAfter.nextSibling);\r\n\r\n            instances = instances.slice(0, reuseCount).concat(added);\r\n        } else {\r\n            instances.length = contexts.length;\r\n        }\r\n    };\r\n}\r\n\r\n/** Content patchers resolve mustache expressions and bind `r-<event>` handlers. */\r\nconst contentPatchers: Patcher[] = [\r\n    textNodePatcher,\r\n    attributeInterpolationPatcher,\r\n    eventPatcher,\r\n];\r\n\r\n/**\r\n * Walks the DOM tree and collects setters from patchers.\r\n *\r\n * Processing order per node:\r\n * 1. Try the structural patcher. If it matches, it owns the node (skip steps 2-3)\r\n * 2. Run content patchers (text interpolation, attribute interpolation)\r\n * 3. Recurse into child nodes\r\n */\r\nfunction compileDOM(root: Node, config: EngineConfig): (ctx: Context, fns?: FunctionsContext) => void {\r\n    const setters: Setter[] = [];\r\n    const get = createGetter(config);\r\n\r\n    function processNode(node: Node) {\r\n        // Structural directives own the node; they clone + compileDOM internally\r\n        const structural = structuralPatcher(node, get, config);\r\n        if (structural) {\r\n            setters.push(structural);\r\n            return;\r\n        }\r\n\r\n        // Content patchers: resolve {{expr}} in text and attributes\r\n        for (const patch of contentPatchers) {\r\n            const setter = patch(node, get, config);\r\n            if (setter) setters.push(setter);\r\n        }\r\n\r\n        for (const child of Array.from(node.childNodes)) {\r\n            processNode(child);\r\n        }\r\n    }\r\n\r\n    processNode(root);\r\n\r\n    // Return memoized render function\r\n    let lastCtx: Context | null = null;\r\n    let lastFns: FunctionsContext | undefined = undefined;\r\n    return (ctx: Context, fns?: FunctionsContext) => {\r\n        // Only re-render if context has changed\r\n        if (lastCtx !== ctx || lastFns !== fns) {\r\n            setters.forEach(fn => fn(ctx, fns));\r\n            lastCtx = ctx;\r\n            lastFns = fns;\r\n        }\r\n    };\r\n}\r\n\r\n/**\r\n * Result of compiling a template.\r\n * Contains the DOM content and a render function for updating it with data.\r\n */\r\nexport interface CompiledTemplate {\r\n    /** The compiled DOM element containing the template structure. */\r\n    content: DocumentFragment | HTMLElement;\r\n    /**\r\n     * Updates the DOM with the provided data context.\r\n     * Memoized: only re-renders when context object reference changes.\r\n     * @param ctx - Data context with values for template expressions\r\n     * @param fns - Optional functions context for callable expressions\r\n     */\r\n    render: (ctx: Context, fns?: FunctionsContext) => void;\r\n}\r\n\r\n/**\r\n * Compiles an HTML template string into a reusable render function.\r\n *\r\n * The template supports mustache-style expressions `{{expression}}` for:\r\n * - Path resolution: `{{user.name}}`, `{{items[0].title}}`\r\n * - Pipes: `{{value | uppercase}}`, `{{price | currency}}`\r\n * - Function calls: `{{formatDate(createdAt)}}`, `{{add(a, b)}}`\r\n *\r\n * Directive attributes for control flow:\r\n * - `if=\"condition\"` - Renders element only when condition is truthy\r\n * - `unless=\"condition\"` - Renders element only when condition is falsy\r\n * - `loop=\"item in items\"` - Repeats element for each array item\r\n * - `r-<event>=\"handler(args)\"` - Calls a function from the functions context\r\n *   on the named DOM event (`r-click`, `r-change`, `r-keypress`, ...);\r\n *   arguments resolve against the current data context\r\n *\r\n * @param templateStr - HTML template string with mustache expressions\r\n * @param config - Optional engine configuration\r\n * @returns Compiled template with content and render function\r\n *\r\n * @example\r\n * // Simple data binding\r\n * const { content, render } = compileTemplate('<h1>{{title}}</h1>');\r\n * render({ title: 'Hello World' });\r\n * document.body.appendChild(content);\r\n *\r\n * @example\r\n * // Re-rendering with new data\r\n * const { content, render } = compileTemplate('<span>Count: {{count}}</span>');\r\n * render({ count: 0 });\r\n * render({ count: 1 }); // DOM updates automatically\r\n *\r\n * @example\r\n * // With strict mode and error handling\r\n * const { render } = compileTemplate('{{missing}}', {\r\n *     strict: true,\r\n *     onError: (msg) => console.error(msg)\r\n * });\r\n * render({}); // Throws error for missing path\r\n *\r\n * @example\r\n * // Event handling in loops with r-<event>\r\n * const tpl = compileTemplate(`\r\n *     <ul>\r\n *         <li loop=\"row in rows\">\r\n *             {{row.name}}\r\n *             <button r-click=\"removeRow(row)\">x</button>\r\n *         </li>\r\n *     </ul>\r\n * `);\r\n *\r\n * // The handler is looked up in the functions context passed to render.\r\n * tpl.render(\r\n *     { rows: [{ id: 1, name: 'Apple' }] },\r\n *     { removeRow: (row) => console.log('remove', row.id) }\r\n * );\r\n * document.body.appendChild(tpl.content);\r\n */\r\nexport function compileTemplate(templateStr: string, config: EngineConfig = { strict: false }): CompiledTemplate {\r\n    const parser = new DOMParser();\r\n    const doc = parser.parseFromString(`<template><div>${templateStr}</div></template>`, 'text/html');\r\n    const content = doc.querySelector('template')!.content.firstElementChild as HTMLElement;\r\n    const render = compileDOM(content, config);\r\n\r\n    return { content, render };\r\n}", "/**\r\n * Represents a single step in a property access path\r\n * Can be either a property name or an array index access\r\n * @example { type: \"property\", key: \"user\" }\r\n * @example { type: \"index\", key: \"0\" }\r\n */\r\ntype PathSegment = {\r\n  type: \"property\" | \"index\";\r\n  key: string;\r\n};\r\n\r\n/**\r\n * Represents the result of parsing a dot-notation string into path segments\r\n * Used internally by the parser to break down property access chains including arrays\r\n * @example [{ type: \"property\", key: \"users\" }, { type: \"index\", key: \"0\" }, { type: \"property\", key: \"name\" }] for \"users[0].name\"\r\n */\r\ntype PropertyPath = PathSegment[];\r\n\r\n/**\r\n * Function type that accesses nested properties safely from a record\r\n * Returns undefined if any property in the chain is missing or null/undefined\r\n * @example\r\n * const accessor = createAccessor(\"user.name\");\r\n * const result = accessor(data); // string | undefined\r\n */\r\ntype PropertyAccessor<T = unknown> = (\r\n  record: Record<string, any>\r\n) => T | undefined;\r\n\r\n/**\r\n * Parser configuration options for customizing dot-notation parsing behavior\r\n * Used to modify how the parser handles property paths and edge cases\r\n * @example { delimiter: \".\", escapeChar: \"\\\\\" }\r\n */\r\ninterface ParserOptions {\r\n  delimiter?: string;\r\n  escapeChar?: string;\r\n}\r\n\r\n/**\r\n * Parses a dot-notation string with array support into path segments\r\n * Handles escaped delimiters, array indices, and validates input format\r\n * @param notation - Notation string with dots and brackets (e.g., \"users[0].profile.name\")\r\n * @param options - Parser configuration options\r\n * @returns Array of path segments for property and array access\r\n * @example\r\n * parsePath(\"user.profile.name\") // [{ type: \"property\", key: \"user\" }, { type: \"property\", key: \"profile\" }, { type: \"property\", key: \"name\" }]\r\n * parsePath(\"users[0].name\") // [{ type: \"property\", key: \"users\" }, { type: \"index\", key: \"0\" }, { type: \"property\", key: \"name\" }]\r\n * parsePath(\"data\\\\.file[1]\", { escapeChar: \"\\\\\" }) // [{ type: \"property\", key: \"data.file\" }, { type: \"index\", key: \"1\" }]\r\n */\r\nfunction parsePath(\r\n  notation: string,\r\n  options: ParserOptions = {}\r\n): PropertyPath {\r\n  const { delimiter = \".\", escapeChar = \"\\\\\" } = options;\r\n\r\n  if (!notation || typeof notation !== \"string\") {\r\n    throw new Error(\"Notation must be a non-empty string\");\r\n  }\r\n\r\n  const segments: PathSegment[] = [];\r\n  let current = \"\";\r\n  let i = 0;\r\n  let inBrackets = false;\r\n  let bracketContent = \"\";\r\n\r\n  while (i < notation.length) {\r\n    const char = notation[i];\r\n    const currentInDelimLength = notation.substring(i, delimiter.length + i);\r\n    const nextChar = notation[i + 1];\r\n    const nextInDelimLength = notation.substring(i + 1, delimiter.length + i + 1);\r\n\r\n    if (\r\n      char === escapeChar &&\r\n      (nextInDelimLength === delimiter || nextChar === \"[\" || nextChar === \"]\")\r\n    ) {\r\n      if (inBrackets) {\r\n        bracketContent += nextChar;\r\n      } else {\r\n        current += nextChar;\r\n      }\r\n      i += 2;\r\n    } else if (char === \"[\" && !inBrackets) {\r\n      if (current) {\r\n        segments.push({ type: \"property\", key: current });\r\n        current = \"\";\r\n      }\r\n      inBrackets = true;\r\n      bracketContent = \"\";\r\n      i++;\r\n    } else if (char === \"]\" && inBrackets) {\r\n      if (!/^\\d+$/.test(bracketContent.trim())) {\r\n        throw new Error(\r\n          `Invalid array index: [${bracketContent}]. Only numeric indices are supported.`\r\n        );\r\n      }\r\n      segments.push({ type: \"index\", key: bracketContent.trim() });\r\n      inBrackets = false;\r\n      bracketContent = \"\";\r\n      i++;\r\n    } else if (currentInDelimLength === delimiter && !inBrackets) {\r\n      if (current) {\r\n        segments.push({ type: \"property\", key: current });\r\n        current = \"\";\r\n      }\r\n      i += delimiter.length;\r\n    } else if (inBrackets) {\r\n      bracketContent += char;\r\n      i++;\r\n    } else {\r\n      current += char;\r\n      i++;\r\n    }\r\n  }\r\n\r\n  if (inBrackets) {\r\n    throw new Error(\"Unclosed bracket in notation\");\r\n  }\r\n\r\n  if (current) {\r\n    segments.push({ type: \"property\", key: current });\r\n  }\r\n\r\n  if (segments.length === 0) {\r\n    throw new Error(\r\n      \"Invalid notation: must contain at least one property or index\"\r\n    );\r\n  }\r\n\r\n  return segments;\r\n}\r\n\r\n/**\r\n * Creates an accessor function from a parsed property path with array support\r\n * The returned function safely navigates nested objects and arrays using the parsed path\r\n * @param path - Array of path segments to access in sequence\r\n * @returns Function that takes a record and returns the nested value or undefined\r\n * @example\r\n * const path = [{ type: \"property\", key: \"users\" }, { type: \"index\", key: \"0\" }, { type: \"property\", key: \"name\" }];\r\n * const accessor = createAccessorFromPath(path);\r\n * accessor({ users: [{ name: \"John\" }] }) // \"John\"\r\n */\r\nfunction createAccessorFromPath<T = unknown>(\r\n  path: PropertyPath\r\n): PropertyAccessor<T> {\r\n  return (record: Record<string, any>): T | undefined => {\r\n    let current: any = record;\r\n\r\n    for (const segment of path) {\r\n      if (current == null) {\r\n        return undefined;\r\n      }\r\n\r\n      if (segment.type === \"property\") {\r\n        if (typeof current !== \"object\") {\r\n          return undefined;\r\n        }\r\n        current = current[segment.key];\r\n      } else if (segment.type === \"index\") {\r\n        if (!Array.isArray(current)) {\r\n          return undefined;\r\n        }\r\n        const index = parseInt(segment.key, 10);\r\n        if (index < 0 || index >= current.length) {\r\n          return undefined;\r\n        }\r\n        current = current[index];\r\n      }\r\n    }\r\n\r\n    return current as T;\r\n  };\r\n}\r\n\r\n/**\r\n * Main parser function that creates an accessor from notation string with array support\r\n * Combines path parsing and accessor creation into a single operation\r\n * @param notation - Notation string with dots and brackets (e.g., \"users[0].profile.name\")\r\n * @param options - Parser configuration options\r\n * @returns Accessor function for the specified property path\r\n * @example\r\n * const accessor = createAccessor(\"user.profile.name\");\r\n * const name = accessor(userData); // safely gets nested property\r\n *\r\n * const arrayAccessor = createAccessor(\"users[0].name\");\r\n * const userName = arrayAccessor(data); // safely accesses array elements\r\n *\r\n * const complexAccessor = createAccessor(\"items[2].meta\\\\.data.values[1]\", { escapeChar: \"\\\\\" });\r\n * const value = complexAccessor(response); // handles escaped dots and nested arrays\r\n */\r\nfunction createAccessor<T = unknown>(\r\n  notation: string,\r\n  options: ParserOptions = {}\r\n): PropertyAccessor<T> {\r\n  const path = parsePath(notation, options);\r\n  return createAccessorFromPath<T>(path);\r\n}\r\n\r\n/**\r\n * Utility function to test if a property path exists in a record (with array support)\r\n * Useful for validation before attempting to access nested properties or array elements\r\n * @param notation - Notation string with dots and brackets to test\r\n * @param record - Record to test against\r\n * @param options - Parser configuration options\r\n * @returns Boolean indicating if the complete path exists\r\n * @example\r\n * hasProperty(\"user.name\", data) // true if data.user.name exists\r\n * hasProperty(\"users[0].name\", data) // true if data.users[0].name exists\r\n * hasProperty(\"missing.path\", data) // false if any part is undefined\r\n */\r\nfunction hasProperty(\r\n  notation: string,\r\n  record: Record<string, any>,\r\n  options: ParserOptions = {}\r\n): boolean {\r\n  const accessor = createAccessor(notation, options);\r\n  return accessor(record) !== undefined;\r\n}\r\n\r\nexport {\r\n  createAccessor,\r\n  createAccessorFromPath,\r\n  parsePath,\r\n  hasProperty,\r\n  type PropertyAccessor,\r\n  type PropertyPath,\r\n  type PathSegment,\r\n  type ParserOptions,\r\n};\r\n", "/**\r\n * Represents different token types that can be identified by the tokenizer\r\n * @example\r\n * // Use to classify what kind of syntax element was found\r\n * const tokenType = TokenType.Constant;\r\n */\r\nexport enum TokenType {\r\n  Constant = 0,\r\n  FunctionCall = 1,\r\n  Variable = 2,\r\n  Pipe = 3,\r\n}\r\n\r\n/**\r\n * Represents a token with its type and value\r\n * @example\r\n * // Creating a token for a number constant\r\n * const token: Token = { type: TokenType.Constant, value: '42' };\r\n */\r\nexport interface Token {\r\n  type: TokenType;\r\n  value: string;\r\n}\r\n\r\n/**\r\n * Tokenizes an input string into constants, function calls, and variables\r\n * @example\r\n * // Basic usage\r\n * const tokens = tokenize('myVar.property + func(42)');\r\n * \r\n * @example\r\n * // Handling complex expressions\r\n * const tokens = tokenize('math.sin(angle) + \"hello\".length');\r\n * \r\n * @example\r\n * // Handling pipes\r\n * const tokens = tokenize('input | transform | display');\r\n */\r\nexport function tokenize(input: string): Token[] {\r\n  const tokens: Token[] = [];\r\n  let i = 0;\r\n\r\n  while (i < input.length) {\r\n    let char = input[i];\r\n\r\n    // Skip whitespace\r\n    if (/\\s/.test(char)) {\r\n      i++;\r\n      continue;\r\n    }\r\n\r\n    // Handle pipe operator (\"|\")\r\n    if (char === '|') {\r\n      i++;\r\n\r\n      // Skip whitespace after pipe\r\n      while (i < input.length && /\\s/.test(input[i])) {\r\n        i++;\r\n      }\r\n\r\n      // Capture the pipe target (everything up to the next whitespace or special character)\r\n      let pipeTarget = '';\r\n      while (i < input.length && !/[\\s\\(\\)\\[\\]\\{\\}\\|\\+\\-\\*\\/\\=\\;\\,\\.]/.test(input[i])) {\r\n        pipeTarget += input[i];\r\n        i++;\r\n      }\r\n\r\n      tokens.push({ type: TokenType.Pipe, value: pipeTarget });\r\n      continue;\r\n    }\r\n\r\n    // Handle string constants\r\n    if (char === '\"' || char === \"'\") {\r\n      const quote = char;\r\n      let value = quote;\r\n      i++;\r\n\r\n      while (i < input.length && input[i] !== quote) {\r\n        // Handle escaped quotes\r\n        if (input[i] === '\\\\' && i + 1 < input.length && input[i + 1] === quote) {\r\n          value += '\\\\' + quote;\r\n          i += 2;\r\n        } else {\r\n          value += input[i];\r\n          i++;\r\n        }\r\n      }\r\n\r\n      if (i < input.length) {\r\n        value += quote;\r\n        i++;\r\n      }\r\n\r\n      tokens.push({ type: TokenType.Constant, value });\r\n      continue;\r\n    }\r\n\r\n    // Handle numeric constants\r\n    if (/[0-9]/.test(char)) {\r\n      let value = '';\r\n      let hasDecimal = false;\r\n\r\n      while (i < input.length && (/[0-9]/.test(input[i]) || (input[i] === '.' && !hasDecimal))) {\r\n        if (input[i] === '.') {\r\n          hasDecimal = true;\r\n        }\r\n        value += input[i];\r\n        i++;\r\n      }\r\n\r\n      tokens.push({ type: TokenType.Constant, value });\r\n      continue;\r\n    }\r\n\r\n    // Handle identifiers (variables and function calls with property/array access)\r\n    if (/[a-zA-Z_$]/.test(char)) {\r\n      let value = '';\r\n      let isFunctionCall = false;\r\n\r\n      // Capture identifier, including dots and bracket access\r\n      while (i < input.length) {\r\n        if (/[a-zA-Z0-9_$.]/.test(input[i])) {\r\n          value += input[i];\r\n          i++;\r\n        } else if (input[i] === '[') {\r\n          // Include array index expression like [0] or ['key']\r\n          let bracketCount = 1;\r\n          value += input[i++];\r\n          while (i < input.length && bracketCount > 0) {\r\n            if (input[i] === '[') bracketCount++;\r\n            if (input[i] === ']') bracketCount--;\r\n            value += input[i++];\r\n          }\r\n        } else {\r\n          break;\r\n        }\r\n      }\r\n\r\n      // Skip whitespace to check for function call\r\n      let wsCount = 0;\r\n      while (i < input.length && /\\s/.test(input[i])) {\r\n        wsCount++;\r\n        i++;\r\n      }\r\n\r\n      // Check if this is a function call\r\n      if (i < input.length && input[i] === '(') {\r\n        isFunctionCall = true;\r\n\r\n        value += '(';\r\n        i++;\r\n\r\n        let parenCount = 1;\r\n        while (i < input.length && parenCount > 0) {\r\n          if (input[i] === '(') parenCount++;\r\n          if (input[i] === ')') parenCount--;\r\n          value += input[i++];\r\n        }\r\n      } else {\r\n        // Restore skipped whitespace\r\n        i -= wsCount;\r\n      }\r\n\r\n      const lastToken = tokens[tokens.length - 1];\r\n      const isDotAfterConstant = input[i - value.length - 1] === '.' && lastToken?.type === TokenType.Constant;\r\n\r\n      tokens.push({\r\n        type: isFunctionCall || isDotAfterConstant ? TokenType.FunctionCall : TokenType.Variable,\r\n        value\r\n      });\r\n      continue;\r\n    }\r\n\r\n    // Handle operators and other characters\r\n    i++;\r\n  }\r\n\r\n  return tokens;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n/** Functions */\r\n\r\nexport type ArgToken =\r\n  | { type: 'number'; value: number }\r\n  | { type: 'string'; value: string }\r\n  | { type: 'identifier'; value: string };\r\n\r\nexport function tokenizeArgs(input: string): ArgToken[] {\r\n  const tokens: ArgToken[] = [];\r\n\r\n  const start = input.indexOf('(');\r\n  const end = input.lastIndexOf(')');\r\n  if (start === -1 || end === -1 || end <= start) {\r\n    throw new Error('Invalid function call syntax');\r\n  }\r\n\r\n  const argsStr = input.slice(start + 1, end);\r\n  let i = 0;\r\n\r\n  while (i < argsStr.length) {\r\n    const char = argsStr[i];\r\n\r\n    if (/\\s/.test(char)) {\r\n      i++;\r\n      continue;\r\n    }\r\n\r\n    if (char === '\"' || char === \"'\") {\r\n      const quoteType = char;\r\n      let value = '';\r\n      i++;\r\n      while (i < argsStr.length && argsStr[i] !== quoteType) {\r\n        if (argsStr[i] === '\\\\') {\r\n          i++;\r\n          if (i < argsStr.length) {\r\n            value += argsStr[i];\r\n          }\r\n        } else {\r\n          value += argsStr[i];\r\n        }\r\n        i++;\r\n      }\r\n      if (i >= argsStr.length) {\r\n        throw new Error('Unterminated string in arguments');\r\n      }\r\n\r\n      i++; // skip closing quote\r\n      tokens.push({ type: 'string', value });\r\n      continue;\r\n    }\r\n\r\n\r\n    if (/[0-9]/.test(char)) {\r\n      let numStr = '';\r\n      while (i < argsStr.length && /[0-9.]/.test(argsStr[i])) {\r\n        numStr += argsStr[i];\r\n        i++;\r\n      }\r\n      tokens.push({ type: 'number', value: parseFloat(numStr) });\r\n      continue;\r\n    }\r\n\r\n    if (/[a-zA-Z_]/.test(char)) {\r\n      let ident = '';\r\n      while (i < argsStr.length && /[a-zA-Z0-9_\\.]/.test(argsStr[i])) {\r\n        ident += argsStr[i];\r\n        i++;\r\n      }\r\n      tokens.push({ type: 'identifier', value: ident });\r\n      continue;\r\n    }\r\n\r\n    if (char === ',') {\r\n      i++;\r\n      continue;\r\n    }\r\n\r\n    throw new Error(`Unexpected character in arguments: ${char}`);\r\n  }\r\n\r\n  return tokens;\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n/** For STRING/MUSTACHE */\r\n\r\nexport type MustacheTokenType = 'string' | 'mustache';\r\n\r\n/**\r\n * Represents a token extracted from a template string\r\n * @typedef {Object} MustahceToken\r\n * @property {MustacheTokenType} type - Either 'string' for plain text or 'mustache' for mustache expressions\r\n * @property {string} value - The actual content of the token\r\n */\r\nexport interface MustacheToken {\r\n  type: MustacheTokenType;\r\n  value: string;\r\n}\r\n\r\n/**\r\n * Tokenizes a template string into an array of string and mustache tokens\r\n * @param {string} template - The template string containing text and mustache expressions\r\n * @returns {MustacheToken[]} An array of tokens representing the parsed template\r\n *\r\n * @example\r\n * // Returns tokens for a simple greeting template\r\n * tokenizeTemplate(\"Hello, {{name}}!\");\r\n * // [\r\n * //   { type: 'string', value: 'Hello, ' },\r\n * //   { type: 'mustache', value: '{{name}}' },\r\n * //   { type: 'string', value: '!' }\r\n * // ]\r\n */\r\nexport function tokenizeMustache(template: string): MustacheToken[] {\r\n  const tokens: MustacheToken[] = [];\r\n  let currentIndex = 0;\r\n\r\n  while (currentIndex < template.length) {\r\n    const openTagIndex = template.indexOf('{{', currentIndex);\r\n\r\n    if (openTagIndex === -1) {\r\n      tokens.push(createStringToken(template.slice(currentIndex)));\r\n      break;\r\n    }\r\n\r\n    if (openTagIndex > currentIndex) {\r\n      tokens.push(createStringToken(template.slice(currentIndex, openTagIndex)));\r\n    }\r\n\r\n    const { value: mustache, endIndex, balanced } = extractMustache(template, openTagIndex);\r\n    if (!balanced) {\r\n      throw new Error(`Unclosed mustache tag starting at index ${openTagIndex}, template: ${template}`);\r\n    }\r\n    tokens.push(createMustacheToken(mustache));\r\n    currentIndex = endIndex;\r\n  }\r\n\r\n  return tokens;\r\n}\r\n\r\nfunction createStringToken(value: string): MustacheToken {\r\n  return { type: 'string', value };\r\n}\r\n\r\nfunction createMustacheToken(value: string): MustacheToken {\r\n  return { type: 'mustache', value };\r\n}\r\n\r\nfunction extractMustache(template: string, startIndex: number): {\r\n  value: string;\r\n  endIndex: number;\r\n  balanced: boolean;\r\n} {\r\n  const open = '{{';\r\n  const close = '}}';\r\n  let i = startIndex + open.length;\r\n  let depth = 1;\r\n\r\n  while (i < template.length && depth > 0) {\r\n    if (template.slice(i, i + open.length) === open) {\r\n      depth++;\r\n      i += open.length;\r\n    } else if (template.slice(i, i + close.length) === close) {\r\n      depth--;\r\n      i += close.length;\r\n    } else {\r\n      i++;\r\n    }\r\n  }\r\n\r\n  const balanced = depth === 0;\r\n  const endIndex = balanced ? i : template.length;\r\n  const value = template.slice(startIndex, endIndex);\r\n\r\n  return { value, endIndex, balanced };\r\n}\r\n", "import { defaultPipes, PipeFunction, PipeRegistry } from \"../pipes\";\r\nimport { createAccessor } from \"./accessorParser\";\r\nimport {\r\n  MustacheToken,\r\n  Token,\r\n  tokenize,\r\n  tokenizeArgs,\r\n  tokenizeMustache,\r\n  TokenType,\r\n} from \"./tokenizer\";\r\n\r\nexport type RenderTemplate = (data: Record<string, any>, component?: any) => string;\r\ntype ResolveValue = (data: Record<string, any>, component?: any) => any;\r\ntype ResolveFunctionValue = (data: Record<string, any>, component: any) => any;\r\ntype RenderPart = (data: Record<string, any>, component: any) => string;\r\n\r\nexport interface TemplateParserOptions {\r\n  pipeRegistry?: PipeRegistry;\r\n}\r\n\r\ninterface ExpressionChain {\r\n  source: ResolveValue;\r\n  pipes: PipeFunction[];\r\n}\r\n\r\nexport function compileMustard(template: string, options?: TemplateParserOptions): RenderTemplate {\r\n  const segments: RenderPart[] = tokenizeMustache(template).map(token =>\r\n    token.type === \"string\"\r\n      ? (_data, _component) => token.value\r\n      : compileExpression(token, options)\r\n  );\r\n\r\n  return (data, component) => segments.map(fn => fn(data, component)).join(\"\");\r\n}\r\n\r\nfunction compileExpression(token: MustacheToken, options?: TemplateParserOptions): RenderPart {\r\n  const tokens = tokenize(token.value);\r\n  const chain = buildExpressionChain(tokens, token.value, options?.pipeRegistry);\r\n  return renderFromChain(chain);\r\n}\r\n\r\nfunction buildExpressionChain(\r\n  tokens: Token[],\r\n  sourceText: string,\r\n  pipeRegistry?: PipeRegistry\r\n): ExpressionChain {\r\n  let chain: ExpressionChain | null = null;\r\n  if (!pipeRegistry){\r\n    pipeRegistry = defaultPipes;\r\n  }\r\n\r\n  for (const token of tokens) {\r\n    switch (token.type) {\r\n      case TokenType.Constant:\r\n        throw Error(`Constants not supported: ${token.value}`);\r\n\r\n      case TokenType.Variable: {\r\n        const accessor = createAccessor(token.value);\r\n        chain = { source: accessor, pipes: [] };\r\n        break;\r\n      }\r\n\r\n      case TokenType.FunctionCall: {\r\n        const func = resolveFunction(token.value);\r\n        chain = {\r\n          source: func,\r\n          pipes: []\r\n        };\r\n        break;\r\n      }\r\n\r\n      case TokenType.Pipe: {\r\n        if (!chain) throw Error(`Pipe '${token.value}' has no input expression in: ${sourceText}`);\r\n        if (!token.value || token.value === ''){\r\n          throw Error('Pipe symbol was provided, but no pipes. Template: ' + sourceText);\r\n        }\r\n\r\n        const [pipeName, ...args] = token.value.split(':').map((p) => p.trim());\r\n        const pipe = pipeRegistry.lookup(pipeName);\r\n        if (!pipe) throw Error(`Pipe not found: ${pipeName}`);\r\n        chain.pipes.push(value => pipe(value, args));\r\n        break;\r\n      }\r\n    }\r\n  }\r\n\r\n  if (!chain) throw Error(`Invalid expression: ${sourceText}`);\r\n  return chain;\r\n}\r\n\r\nfunction renderFromChain(chain: ExpressionChain): RenderPart {\r\n  return (data, component) => {\r\n    const initial = chain.source(data, component);\r\n    const result = chain.pipes.reduce((acc, fn) => fn(acc), initial);\r\n    return result != null ? result.toString() : \"\";\r\n  };\r\n}\r\n\r\nfunction resolveFunction(expression: string): ResolveFunctionValue {\r\n  const pos = expression.indexOf(\"(\");\r\n  if (pos === -1) throw Error(`Invalid function: ${expression}`);\r\n\r\n  const args = tokenizeArgs(expression);\r\n  const resolvedArgs: ((data: Record<string, any>) => any)[] = args.map(arg => {\r\n    if (arg.type === \"number\" || arg.type === \"string\") return () => arg.value;\r\n    if (arg.type === \"identifier\") return data => createAccessor(arg.value)(data);\r\n    throw Error(`Unsupported argument type: ${(arg as any).type}`);\r\n  });\r\n\r\n  const name = expression.substring(0, pos);\r\n  const fnAccessor = createAccessor(name);\r\n\r\n  return (data, component) => {\r\n    if (!component) throw Error(`Component context is required for calling '${name}'`);\r\n    const fn = fnAccessor(component);\r\n    if (typeof fn !== \"function\") throw Error(`Resolved '${name}' is not a function`);\r\n    const evaluatedArgs = resolvedArgs.map(argFn => argFn(data));\r\n    return fn.apply(component, evaluatedArgs);\r\n  };\r\n}\r\n", "import { compileMustard } from \"./parseTemplate\";\r\nimport { ArgToken, tokenizeArgs } from \"./tokenizer\";\r\n\r\ntype RawBinding =\r\n  | {\r\n    type: 'text';\r\n    path: number[];\r\n    func: (context: Record<string, any>, component: Record<string, any>, node: Node) => void;\r\n  }\r\n  | {\r\n    type: 'attribute';\r\n    path: number[];\r\n    name: string;\r\n    func: (context: Record<string, any>, component: Record<string, any>, element: HTMLElement) => void;\r\n  };\r\n\r\n/** @internal */\r\ntype ClickBinding = {\r\n  path: number[];\r\n  methodName: string;\r\n  argTokens: ArgToken[];\r\n};\r\n\r\n/** @internal */\r\ntype BoundBinding =\r\n  | {\r\n    type: 'text';\r\n    node: Node;\r\n    func: (context: Record<string, any>, node: Node) => void;\r\n  }\r\n  | {\r\n    type: 'attribute';\r\n    element: HTMLElement;\r\n    name: string;\r\n    func: (context: Record<string, any>, element: HTMLElement) => void;\r\n  };\r\n\r\nexport class BoundNode {\r\n  constructor(\r\n    private readonly root: HTMLElement,\r\n    private readonly bindings: BoundBinding[],\r\n    private readonly clickBindings: ClickBinding[],\r\n    private readonly component?: Record<string, any>\r\n  ) { }\r\n\r\n  render(data: Record<string, any>): HTMLElement {\r\n    for (const binding of this.bindings) {\r\n      if (binding.type === 'text') {\r\n        binding.func(data, binding.node);\r\n      } else {\r\n        binding.func(data, binding.element);\r\n      }\r\n    }\r\n\r\n    for (const click of this.clickBindings) {\r\n      const node = this.getNodeAtPath(this.root, click.path);\r\n      const method = this.component?.[click.methodName];\r\n\r\n      if (node instanceof HTMLElement && typeof method === 'function') {\r\n        node.onclick = (evt: Event) => {\r\n          const args = click.argTokens.map(token => {\r\n            if (token.type === 'number' || token.type === 'string') {\r\n              return token.value;\r\n            }\r\n            if (token.type === 'identifier') {\r\n              if (token.value === 'event') {\r\n                return evt;\r\n              }\r\n\r\n              const parts = token.value.split('.');\r\n              return parts.reduce((obj, key) => obj?.[key], data);\r\n            }\r\n          });\r\n          method.apply(this.component, args);\r\n        };\r\n      }\r\n    }\r\n\r\n    return this.root;\r\n  }\r\n\r\n  private getNodeAtPath(root: Node, path: number[]): Node {\r\n    return path.reduce((node, index) => node.childNodes[index], root);\r\n  }\r\n}\r\n\r\nexport function createBluePrint(html: string): Blueprint {\r\n  var bp = new Blueprint(html);\r\n  return bp;\r\n}\r\n\r\nexport class Blueprint {\r\n  private readonly template: HTMLTemplateElement;\r\n  private readonly bindings: RawBinding[];\r\n  private readonly clickBindings: ClickBinding[];\r\n\r\n  constructor(htmlOrTemplate: string | HTMLTemplateElement) {\r\n    if (typeof htmlOrTemplate === 'string') {\r\n      const trimmed = htmlOrTemplate.trim();\r\n      if (trimmed.startsWith('<template')) {\r\n        const wrapper = document.createElement('div');\r\n        wrapper.innerHTML = trimmed;\r\n        const found = wrapper.querySelector('template');\r\n        if (!found) throw new Error('Could not find <template> in input string');\r\n        this.template = found;\r\n      } else {\r\n        this.template = document.createElement('template');\r\n        this.template.innerHTML = trimmed;\r\n      }\r\n    } else {\r\n      this.template = htmlOrTemplate;\r\n    }\r\n\r\n    const rootElement = this.getRootElement();\r\n    this.bindings = this.collectBindings(rootElement);\r\n    this.clickBindings = this.collectClickBindings(rootElement);\r\n  }\r\n\r\n  createInstance(component?: Record<string, any>): BoundNode {\r\n    const rootClone = this.getRootElement().cloneNode(true) as HTMLElement;\r\n    const componentOrEmpty = component ?? {};\r\n\r\n    const boundBindings: BoundBinding[] = this.bindings.map(binding => {\r\n      const node = this.getNodeAtPath(rootClone, binding.path);\r\n      if (binding.type === 'text') {\r\n        return {\r\n          type: 'text',\r\n          node,\r\n          func: (data, node) => binding.func(data, componentOrEmpty, node)\r\n        };\r\n      } else {\r\n        return {\r\n          type: 'attribute',\r\n          element: node as HTMLElement,\r\n          name: binding.name,\r\n          func: (data, node) => binding.func(data, componentOrEmpty, node)\r\n        };\r\n      }\r\n    });\r\n\r\n    return new BoundNode(rootClone, boundBindings, this.clickBindings, component);\r\n  }\r\n\r\n  private getRootElement(): HTMLElement {\r\n    const el = Array.from(this.template.content.childNodes).find(\r\n      node => node.nodeType === Node.ELEMENT_NODE\r\n    );\r\n    if (!(el instanceof HTMLElement)) {\r\n      throw new Error('Template must contain a single root element');\r\n    }\r\n    return el;\r\n  }\r\n\r\n  private collectBindings(root: HTMLElement): RawBinding[] {\r\n    const bindings: RawBinding[] = [];\r\n\r\n    const walk = (node: Node, path: number[] = []) => {\r\n      if (node.nodeType === Node.TEXT_NODE && node.textContent) {\r\n        if (node.textContent.match(/\\{\\{\\s*(.*?)\\s*\\}\\}/g)) {\r\n          const func = compileMustard(node.textContent);\r\n          bindings.push({\r\n            type: 'text',\r\n            path: [...path],\r\n            func: (data, component, targetNode) => {\r\n              targetNode.textContent = func(data, component);\r\n            }\r\n          });\r\n        }\r\n      }\r\n\r\n      if (node.nodeType === Node.ELEMENT_NODE) {\r\n        const element = node as HTMLElement;\r\n\r\n        if (element.tagName === 'TEMPLATE') return;\r\n\r\n        for (let i = 0; i < element.attributes.length; i++) {\r\n          const attr = element.attributes[i];\r\n          if (attr.value.match(/\\{\\{\\s*(.*?)\\s*\\}\\}/g)) {\r\n            const func = compileMustard(attr.value);\r\n            bindings.push({\r\n              type: 'attribute',\r\n              path: [...path],\r\n              name: attr.name,\r\n              func: (data, component, el) => {\r\n                el.setAttribute(attr.name, func(data, component));\r\n              }\r\n            });\r\n          }\r\n        }\r\n\r\n        Array.from(node.childNodes).forEach((child, index) => {\r\n          walk(child, [...path, index]);\r\n        });\r\n      }\r\n    };\r\n\r\n    walk(root);\r\n    return bindings;\r\n  }\r\n\r\n  private collectClickBindings(root: Node): ClickBinding[] {\r\n    const bindings: ClickBinding[] = [];\r\n\r\n    const walk = (node: Node, path: number[] = []) => {\r\n      if (node.nodeType === Node.ELEMENT_NODE) {\r\n        const element = node as HTMLElement;\r\n        const clickAttr = element.getAttribute('click');\r\n        if (clickAttr?.trim()) {\r\n          const trimmed = clickAttr.trim();\r\n\r\n          const match = trimmed.match(/^([a-zA-Z_$][\\w$]*)\\s*\\((.*)\\)$/);\r\n          if (match) {\r\n            const methodName = match[1];\r\n            const argTokens = tokenizeArgs(trimmed);\r\n            bindings.push({ path: [...path], methodName, argTokens });\r\n          } else {\r\n            // No parentheses, treat as method with no args\r\n            bindings.push({ path: [...path], methodName: trimmed, argTokens: [] });\r\n          }\r\n        }\r\n\r\n        Array.from(node.childNodes).forEach((child, index) => {\r\n          walk(child, [...path, index]);\r\n        });\r\n      }\r\n    };\r\n\r\n    walk(root);\r\n    return bindings;\r\n  }\r\n\r\n  private getNodeAtPath(root: Node, path: number[]): Node {\r\n    return path.reduce((node, index) => node.childNodes[index], root);\r\n  }\r\n}\r\n", "export class TableRenderer {\r\n  private table: HTMLTableElement;\r\n  private template: HTMLTemplateElement;\r\n  private component: HTMLElement;\r\n  private dataMap = new Map<string, Record<string, any>>();\r\n  private rowMap = new Map<string, HTMLTableRowElement>();\r\n\r\n  public IdColumn: string;\r\n\r\n  constructor(\r\n    table: HTMLTableElement,\r\n    template: HTMLTemplateElement,\r\n    idColumn: string,\r\n    component: HTMLElement\r\n  ) {\r\n    this.table = table;\r\n    this.template = template;\r\n    this.IdColumn = idColumn;\r\n    this.component = component;\r\n  }\r\n\r\n  public render(data: Record<string, any>[]) {\r\n    this.clearRows();\r\n    for (const item of data) {\r\n      this.renderRow(item);\r\n    }\r\n  }\r\n\r\n  private clearRows(): void {\r\n    this.table.tBodies[0].innerHTML = '';\r\n    this.dataMap.clear();\r\n    this.rowMap.clear();\r\n  }\r\n\r\n  private renderRow(data: Record<string, any>): void {\r\n    const id = data[this.IdColumn];\r\n    if (id === undefined || id === null) {\r\n      throw new Error(`Missing IdColumn '${this.IdColumn}' in data`);\r\n    }\r\n\r\n    const row = this.template.content.firstElementChild?.cloneNode(true) as HTMLTableRowElement;\r\n    if (!row) throw new Error(\"Template must have a <tr> as its first child\");\r\n\r\n    this.populateRow(row, data);\r\n    this.attachEventHandlers(row, data);\r\n\r\n    this.table.tBodies[0].appendChild(row);\r\n    this.dataMap.set(id, data);\r\n    this.rowMap.set(id, row);\r\n  }\r\n\r\n  private populateRow(row: HTMLTableRowElement, data: Record<string, any>): void {\r\n    const cells = row.querySelectorAll('[data-field]');\r\n    cells.forEach((cell) => {\r\n      const field = (cell as HTMLElement).dataset.field;\r\n      if (field && field in data) {\r\n        cell.textContent = String(data[field]);\r\n      }\r\n    });\r\n  }\r\n\r\n  private attachEventHandlers(row: HTMLElement, data: Record<string, any>): void {\r\n    const interactiveElements = row.querySelectorAll('[onclick]');\r\n    interactiveElements.forEach((el) => {\r\n      const element = el as HTMLElement;\r\n      const handlerAttr = element.getAttribute('onclick');\r\n      if (!handlerAttr) return;\r\n\r\n      const match = handlerAttr.match(/^(\\w+)(\\(([^)]*)\\))?$/);\r\n      if (!match) return;\r\n\r\n      const [, methodName, , argStr] = match;\r\n      const args = argStr ? argStr.split(',').map(s => s.trim().replace(/^['\"]|['\"]$/g, '')) : [];\r\n\r\n      if (typeof (this.component as any)[methodName] === 'function') {\r\n        element.removeAttribute('onclick');\r\n        element.addEventListener('click', (event) => {\r\n          (this.component as any)[methodName](...args, data, event);\r\n        });\r\n      }\r\n    });\r\n  }\r\n\r\n  public update(data: Record<string, any>) {\r\n    const id = data[this.IdColumn];\r\n    if (id === undefined || id === null) {\r\n      throw new Error(`Missing IdColumn '${this.IdColumn}' in update data`);\r\n    }\r\n\r\n    const row = this.rowMap.get(id);\r\n    if (!row) {\r\n      this.renderRow(data);\r\n    } else {\r\n      this.populateRow(row, data);\r\n      this.attachEventHandlers(row, data);\r\n      this.dataMap.set(id, data);\r\n    }\r\n  }\r\n}\r\n\r\nexport class SortChangeEvent extends CustomEvent<SortColumn[]> {\r\n  constructor(sortColumns: SortColumn[]) {\r\n    super('sortchange', {\r\n      detail: sortColumns,\r\n      bubbles: true,\r\n      composed: true,\r\n    });\r\n  }\r\n}\r\n\r\n\r\n/** @internal */\r\ntype SortDirection = 'asc' | 'desc';\r\nexport type SortColumn = { column: string; direction: SortDirection };\r\n\r\nexport class TableSorter {\r\n  private table: HTMLTableElement;\r\n  private sortColumns: SortColumn[] = [];\r\n  private component: HTMLElement;\r\n\r\n  constructor(table: HTMLTableElement, component: HTMLElement) {\r\n    this.table = table;\r\n    this.component = component;\r\n    this.setupListeners();\r\n  }\r\n\r\n  private setupListeners() {\r\n    const headers = this.table.tHead?.querySelectorAll('th[name]');\r\n    headers?.forEach((th) => {\r\n      th.addEventListener('click', () => {\r\n        const column = th.getAttribute('name')!;\r\n        this.toggle(column);\r\n        this.updateSortIndicators();\r\n        this.emit();\r\n      });\r\n    });\r\n  }\r\n\r\n  private toggle(column: string) {\r\n    const index = this.sortColumns.findIndex(c => c.column === column);\r\n\r\n    if (index === -1) {\r\n      this.sortColumns.push({ column, direction: 'asc' });\r\n    } else if (this.sortColumns[index].direction === 'asc') {\r\n      this.sortColumns[index].direction = 'desc';\r\n    } else {\r\n      this.sortColumns.splice(index, 1);\r\n    }\r\n  }\r\n\r\n  private emit() {\r\n    const event = new SortChangeEvent(this.sortColumns);\r\n        this.component.dispatchEvent(event);\r\n  }\r\n\r\n   private updateSortIndicators() {\r\n    const headers = this.table.tHead?.querySelectorAll('th[name]');\r\n    headers?.forEach((el) => {\r\n      const th = el as HTMLElement;\r\n      // Remove existing indicators\r\n      const existingIndicator = th.querySelector('.sort-indicator') as HTMLElement;\r\n      if (existingIndicator) {\r\n        th.removeChild(existingIndicator);\r\n      }\r\n\r\n      // Get column name and find if it's sorted\r\n      const column = th.getAttribute('name')!;\r\n      const sortInfo = this.sortColumns.find(c => c.column === column);\r\n      \r\n      if (sortInfo) {\r\n        // Create indicator element\r\n        const indicator = document.createElement('span');\r\n        indicator.className = 'sort-indicator';\r\n        indicator.textContent = sortInfo.direction === 'asc' ? '\u2191' : '\u2193';\r\n        \r\n        // Style for right alignment\r\n        indicator.style.float = 'right';\r\n        indicator.style.marginLeft = '5px';\r\n        \r\n        // Append to header\r\n        th.appendChild(indicator);\r\n      }\r\n      \r\n      // Ensure header is positioned relatively for absolute positioning if needed\r\n      if (!th.style.position) {\r\n        th.style.position = 'relative';\r\n      }\r\n    });\r\n  }\r\n\r\n  public getSortColumns(): SortColumn[] {\r\n    return [...this.sortColumns];\r\n  }\r\n\r\n  public clear() {\r\n    this.sortColumns = [];\r\n    this.updateSortIndicators();\r\n    this.emit();\r\n  }\r\n}\r\n\r\ndeclare global {\r\n  interface HTMLTableElementEventMap extends HTMLElementEventMap {\r\n    'sortchange': SortChangeEvent;\r\n  }\r\n\r\n  interface HTMLTableElement {\r\n    addEventListener<K extends keyof HTMLTableElementEventMap>(\r\n      type: K,\r\n      listener: (this: HTMLTableElement, ev: HTMLTableElementEventMap[K]) => any,\r\n      options?: boolean | AddEventListenerOptions\r\n    ): void;\r\n  }\r\n}", "/** @internal */\r\ntype WebComponentConstructor = new (...args: any[]) => HTMLElement;\r\n\r\nexport enum GuardResult {\r\n    /**\r\n     * Handle route without checking more guards.\r\n     */\r\n    Allow,\r\n\r\n    /**\r\n     * Throw a RouteGuardError.\r\n     */\r\n    Deny,\r\n\r\n    /**\r\n     * Resume and check other guards.\r\n     */\r\n    Continue,\r\n\r\n    /**\r\n     * Do not invoke the rooute nor other guards.\r\n     */\r\n    Stop\r\n}\r\n\r\nexport interface RouteGuard {\r\n    check(route: RouteMatchResult): GuardResult;\r\n}\r\n\r\nexport interface Route {\r\n    name?: string;\r\n    target?: string;\r\n    path: string;\r\n\r\n    /**\r\n     * HTML file name (without extension).\r\n     *\r\n     * Define for instance if you have a route that requires a more limited layout. The library\r\n     * will automatically load that HTML file and rewrite URL history so that the correct url is displayed.\r\n     */\r\n    layout?: string;\r\n\r\n    /**\r\n     * Name of the tag for your web component.\r\n     */\r\n    componentTagName?: string;\r\n\r\n    /**\r\n     * Guards used to check if this route can be visited.\r\n     */\r\n    guards?: RouteGuard[];\r\n\r\n    component?: WebComponentConstructor;\r\n}\r\n\r\nexport type RouteParamType = string | number;\r\nexport type RouteData = Record<string, RouteParamType>;\r\n\r\n/**\r\n * Implement to receive typed route parameters via a `routeData` property.\r\n * RouteTarget assigns `routeData` after element creation but before DOM insertion.\r\n * Optional since it's not available at construction time.\r\n *\r\n * For convention-based usage without undefined checks, skip the interface\r\n * and declare `routeData` directly on your component.\r\n *\r\n * @example\r\n * class UserProfile extends HTMLElement implements Routable<{ userName: string }> {\r\n *     routeData?: { userName: string };\r\n * }\r\n */\r\nexport interface Routable<T extends RouteData = RouteData> {\r\n    routeData?: T;\r\n}\r\n\r\n/**\r\n * Implement to run async initialization before the component is added to the DOM.\r\n * RouteTarget calls `loadRoute()` and awaits it before inserting the element.\r\n *\r\n * @example\r\n * class OrderDetail extends HTMLElement implements LoadRoute<{ orderId: number }> {\r\n *     async loadRoute(data: { orderId: number }) {\r\n *         this.order = await fetchOrder(data.orderId);\r\n *     }\r\n * }\r\n */\r\nexport interface LoadRoute<T extends RouteData = RouteData> {\r\n    loadRoute(data: T): void | Promise<void>;\r\n}\r\n\r\n/**\r\n * Result from route matching operations.\r\n * Contains all information needed for navigation and rendering.\r\n */\r\nexport type RouteMatchResult = {\r\n    /**\r\n     * Matched route configuration\r\n     */\r\n    route: Route;\r\n\r\n    /**\r\n     * URL segments used for history state\r\n     */\r\n    urlSegments: string[];\r\n\r\n    /**\r\n     * Extracted and type-converted parameters\r\n     */\r\n    params: RouteData;\r\n\r\n    /**\r\n     * URL fragment without the leading `#`, or `undefined` when the URL had none.\r\n     *\r\n     * Kept separate from `params` because a fragment is an opaque string with no\r\n     * name. Unlike the query string it is never sent to the server, which is why\r\n     * activation and password reset links sometimes carry their token here.\r\n     */\r\n    fragment?: string;\r\n};\r\n\r\n/**\r\n * Supported types of route segments\r\n */\r\nexport type RouteSegmentType = 'string' | 'number' | 'path' | 'regex';\r\n\r\n/**\r\n * Strongly typed route segment value\r\n */\r\nexport interface RouteValue {\r\n    /**\r\n     * Type of parameter for validation\r\n     */\r\n    type: RouteSegmentType;\r\n\r\n    /**\r\n     * Actual parameter value\r\n     */\r\n    value: any;\r\n}\r\n\r\nexport class RouteError extends Error {}\r\nexport class RouteGuardError extends RouteError {\r\n    isGuard = true;\r\n}\r\n\r\nexport interface NavigateOptions {\r\n    /**\r\n     * Optional parameters when using route name\r\n     */\r\n    params?: Record<string, string | number>;\r\n\r\n    /**\r\n     * override for route's default target\r\n     */\r\n    target?: string;\r\n\r\n    /**\r\n     * When you want to override routes from the globally registered ones.\r\n     */\r\n    routes?: Route[];\r\n\r\n    /**\r\n     * URL fragment (without `#`) to hand to the component.\r\n     *\r\n     * Rarely set by hand. The router fills it in when it replays a navigation\r\n     * that crossed a layout switch.\r\n     */\r\n    fragment?: string;\r\n}\r\n", "import type { Route, RouteData } from './types';\r\n\r\n/**\r\n * Event sent to routing targets when a new route should be displayed.\r\n */\r\nexport class NavigateRouteEvent extends Event {\r\n    static NAME: string = 'rlx.navigateRoute';\r\n\r\n    /**\r\n     * Identifies the entry in the target's NavigationHistory and in\r\n     * `history.state.entryId`. Set by `navigate()` for every navigation.\r\n     * Optional only so old call-sites that constructed events manually keep\r\n     * compiling.\r\n     */\r\n    entryId?: number;\r\n\r\n    /**\r\n     * `true` when the event is a replay of a previously recorded navigation\r\n     * (e.g. triggered by browser back/forward or `navigateBack`/`navigateForward`).\r\n     * Tells the target registry to move its index instead of recording a new entry.\r\n     */\r\n    isReplay: boolean = false;\r\n\r\n    /**\r\n     * URL fragment without the leading `#`, or `undefined` when the URL had none.\r\n     *\r\n     * Survives a layout switch, so a component can rely on it even when the\r\n     * route loaded a different HTML file on the way in.\r\n     *\r\n     * @example\r\n     * document.addEventListener('rlx.navigateRoute', (e) => {\r\n     *     const resetToken = e.fragment;\r\n     * });\r\n     */\r\n    fragment?: string;\r\n\r\n    constructor(\r\n        /**\r\n         * Matched route.\r\n         */\r\n        public route: Route,\r\n\r\n        /**\r\n         * The generated url sements which can be used to push the url into the browser history.\r\n         */\r\n        public urlSegments: string[],\r\n\r\n        /**\r\n         * Data supplied to the route.\r\n         */\r\n        public routeData?: RouteData,\r\n\r\n        /**\r\n         * The target can differ from the default target that is defined in the route.\r\n         *\r\n         * undefined means that the default (unnamed) target should be used.\r\n         */\r\n        public routeTarget?: string,\r\n\r\n        eventInit?: EventInit\r\n    ) {\r\n        super(NavigateRouteEvent.NAME, eventInit);\r\n    }\r\n}\r\n\r\ndeclare global {\r\n    interface HTMLElementEventMap {\r\n        'rlx.navigateRoute': NavigateRouteEvent;\r\n    }\r\n    interface DocumentEventMap {\r\n        'rlx.navigateRoute': NavigateRouteEvent;\r\n    }\r\n}\r\n", "import type { RouteData } from './types';\n\n/**\n * Single recorded navigation. Each `<r-route-target>` stores a stack of these\n * so it can replay previously rendered routes when the user navigates back\n * or forward.\n *\n * `entryId` correlates the entry with `history.state.entryId`, so the popstate\n * handler can find the right entry when the user clicks the browser's\n * back/forward buttons.\n */\nexport interface NavigationEntry {\n    routeName: string;\n    params: RouteData;\n    target?: string;\n    urlSegments: string[];\n    entryId: number;\n    fragment?: string;\n}\n\n/**\n * Encapsulated back/forward history for a single route target.\n * Behaves like the browser's own history stack: pushing a new entry while\n * the index sits in the middle of the stack truncates the forward entries.\n *\n * @example\n * const history = new NavigationHistory();\n * history.record({ routeName: 'home', params: {}, urlSegments: [''], entryId: 1 });\n * history.record({ routeName: 'user', params: { id: 'a' }, urlSegments: ['users', 'a'], entryId: 2 });\n * history.canGoBack();        // true\n * history.back();             // returns the 'home' entry\n * history.canGoForward();     // true\n */\nexport class NavigationHistory {\n    private entries: NavigationEntry[] = [];\n    private currentIndex = -1;\n\n    record(entry: NavigationEntry): void {\n        if (this.currentIndex < this.entries.length - 1) {\n            this.entries.length = this.currentIndex + 1;\n        }\n        this.entries.push(entry);\n        this.currentIndex = this.entries.length - 1;\n    }\n\n    canGoBack(): boolean {\n        return this.currentIndex > 0;\n    }\n\n    canGoForward(): boolean {\n        return this.currentIndex >= 0 && this.currentIndex < this.entries.length - 1;\n    }\n\n    back(): NavigationEntry | undefined {\n        if (!this.canGoBack()) return undefined;\n        this.currentIndex--;\n        return this.entries[this.currentIndex];\n    }\n\n    forward(): NavigationEntry | undefined {\n        if (!this.canGoForward()) return undefined;\n        this.currentIndex++;\n        return this.entries[this.currentIndex];\n    }\n\n    /**\n     * Move the index to the entry with the given `entryId`. Used by the\n     * popstate handler to keep the per-target index in sync with the\n     * browser's global history position.\n     */\n    setIndexById(entryId: number): NavigationEntry | undefined {\n        const found = this.entries.findIndex((e) => e.entryId === entryId);\n        if (found < 0) return undefined;\n        this.currentIndex = found;\n        return this.entries[found];\n    }\n\n    current(): NavigationEntry | undefined {\n        if (this.currentIndex < 0) return undefined;\n        return this.entries[this.currentIndex];\n    }\n\n    /** @internal Used by tests. */\n    size(): number {\n        return this.entries.length;\n    }\n}\n", "import { reportError } from '../errors';\nimport { NavigateRouteEvent } from './NavigateRouteEvent';\nimport { NavigationHistory, type NavigationEntry } from './NavigationHistory';\n\n/** @internal */\ntype RouteTargetHandler = (evt: NavigateRouteEvent) => void;\n\n/** @internal */\ninterface TargetRegistration {\n    handler: RouteTargetHandler;\n    history: NavigationHistory;\n}\n\nconst targets = new Map<string | undefined, TargetRegistration>();\nconst pendingEvents = new Map<string | undefined, NavigateRouteEvent>();\nconst detachedHistories = new Map<string | undefined, NavigationHistory>();\n\n/**\n * Registers a route target handler.\n * When a navigation event targets this name, the handler is called directly.\n * If a pending event exists for this target, it is replayed immediately.\n *\n * Each target owns a NavigationHistory that records every navigation it\n * handles. When a target reconnects after being removed (e.g. layout change),\n * its previous history is restored so back/forward keep working.\n *\n * @param name - Target name, or `undefined` for the default (unnamed) target\n * @param handler - Callback that receives the `NavigateRouteEvent`\n *\n * @example\n * registerRouteTarget('sidebar', (evt) => renderComponent(evt));\n */\nexport function registerRouteTarget(\n    name: string | undefined,\n    handler: RouteTargetHandler,\n) {\n    initRouteTargetListener();\n    if (targets.has(name)) {\n        const error = reportError('Duplicate route target', {\n            target: name ?? 'default',\n        });\n        if (error) throw error;\n        return;\n    }\n\n    const restoredHistory = detachedHistories.get(name);\n    const history = restoredHistory ?? new NavigationHistory();\n    detachedHistories.delete(name);\n    targets.set(name, { handler, history });\n\n    if (window.relaxDebug?.routing) {\n        console.log('[relaxjs:routing] target registered', name ?? 'default', {\n            historyRestored: restoredHistory !== undefined,\n        });\n    }\n\n    const pending = pendingEvents.get(name);\n    if (pending) {\n        pendingEvents.delete(name);\n        if (window.relaxDebug?.routing) {\n            console.log(\n                '[relaxjs:routing] replaying parked navigation into target',\n                name ?? 'default',\n                pending.route.name\n            );\n        }\n        dispatchToTarget(pending);\n    }\n}\n\n/**\n * Unregisters a previously registered route target handler.\n * The target's history is kept aside so it can be restored if a new target\n * with the same name reconnects later.\n *\n * @param name - Target name that was passed to `registerRouteTarget`\n */\nexport function unregisterRouteTarget(name: string | undefined) {\n    const reg = targets.get(name);\n    if (reg) {\n        detachedHistories.set(name, reg.history);\n    }\n    targets.delete(name);\n}\n\n/**\n * Returns the NavigationHistory for a named target, or `undefined` if no\n * target with that name is currently registered.\n *\n * Used by `navigateBack` / `navigateForward` / `canGoBack` / `canGoForward`\n * to read or walk a target's encapsulated stack.\n */\nexport function getTargetHistory(name?: string): NavigationHistory | undefined {\n    return targets.get(name)?.history;\n}\n\nexport function clearPendingNavigations() {\n    pendingEvents.clear();\n    targets.clear();\n    detachedHistories.clear();\n}\n\nfunction entryFromEvent(evt: NavigateRouteEvent): NavigationEntry | undefined {\n    if (evt.entryId === undefined) return undefined;\n    if (!evt.route.name) return undefined;\n    return {\n        routeName: evt.route.name,\n        params: evt.routeData ?? {},\n        target: evt.routeTarget,\n        urlSegments: evt.urlSegments,\n        entryId: evt.entryId,\n        fragment: evt.fragment,\n    };\n}\n\nfunction dispatchToTarget(evt: NavigateRouteEvent) {\n    const reg = targets.get(evt.routeTarget);\n    if (!reg) {\n        if (window.relaxDebug?.routing) {\n            console.log(\n                '[relaxjs:routing] no target registered, navigation parked',\n                evt.routeTarget ?? 'default',\n                evt.route.name,\n                {\n                    replacedParkedNavigation: pendingEvents.has(evt.routeTarget),\n                    registeredTargets: Array.from(targets.keys(), (name) => name ?? 'default'),\n                }\n            );\n        }\n        pendingEvents.set(evt.routeTarget, evt);\n        return;\n    }\n\n    if (evt.isReplay) {\n        if (evt.entryId !== undefined) {\n            reg.history.setIndexById(evt.entryId);\n        }\n    } else {\n        const entry = entryFromEvent(evt);\n        if (entry) {\n            reg.history.record(entry);\n        }\n    }\n\n    reg.handler(evt);\n}\n\nlet listenerAttached = false;\n\nexport function initRouteTargetListener() {\n    if (listenerAttached) return;\n    listenerAttached = true;\n    document.addEventListener(NavigateRouteEvent.NAME, (evt) => {\n        dispatchToTarget(evt as NavigateRouteEvent);\n    });\n}\n", "import type { Route, RouteData, RouteParamType, RouteMatchResult } from './types';\r\n\r\n/**\r\n * Route segment matcher interface.\r\n * Each segment type (string, number, path) implements this\r\n * for parameter extraction and validation.\r\n */\r\ninterface RouteSegment {\r\n    /**\r\n     * Parameter name when segment is dynamic (:name or ;id)\r\n     */\r\n    paramName?: string;\r\n\r\n    /**\r\n     * Validates if URL segment matches pattern\r\n     * @param value Segment from URL to validate\r\n     */\r\n    isMatch(value: string): boolean;\r\n\r\n    /**\r\n     * Converts URL segment to typed parameter\r\n     * @param pathValue Raw value from URL\r\n     */\r\n    getValue(pathValue: string): RouteParamType;\r\n}\r\n\r\n/**\r\n * Number parameter segment matcher.\r\n * Used for ;id style parameters that must be numbers.\r\n */\r\nclass NumberRouteSegment implements RouteSegment {\r\n    constructor(public paramName: string) {}\r\n    isMatch(value: string): boolean {\r\n        if (/^\\d+$/.test(value)) {\r\n            return true;\r\n        }\r\n        return false;\r\n    }\r\n\r\n    getValue(pathValue: string): RouteParamType {\r\n        if (/^\\d+$/.test(pathValue) === false) {\r\n            throw new Error(\r\n                `Path is not a number, parameter name '${this.paramName}', value: '${pathValue}'.`\r\n            );\r\n        }\r\n        return parseInt(pathValue);\r\n    }\r\n}\r\n\r\n/**\r\n * String parameter segment matcher.\r\n * Used for :name style parameters.\r\n */\r\nclass StringRouteSegment implements RouteSegment {\r\n    constructor(public paramName: string) {}\r\n    isMatch(_value: string): boolean {\r\n        return true;\r\n    }\r\n\r\n    /**\r\n     *\r\n     * @param pathValue the route data (for route by name) or segment extracted from the url (for url routing).\r\n     * @returns\r\n     */\r\n    getValue(pathValue: string): RouteParamType {\r\n        return pathValue;\r\n    }\r\n}\r\n\r\n/**\r\n * Static path segment matcher.\r\n * Used for fixed URL parts like 'users' in /users/:id\r\n */\r\nclass PathRouteSegment implements RouteSegment {\r\n    constructor(public value: string) {}\r\n    isMatch(value: string): boolean {\r\n        return value == this.value;\r\n    }\r\n\r\n    getValue(_pathValue: string): RouteParamType {\r\n        return this.value;\r\n    }\r\n}\r\n\r\n/**\r\n * Internal route implementation that handles segment matching\r\n * and parameter extraction.\r\n */\r\nclass RouteImp {\r\n    constructor(public route: Route, private segments: RouteSegment[]) {}\r\n\r\n    /**\r\n     * Attempts to match URL segments against route pattern\r\n     * @param segments URL parts to match\r\n     * @returns Match result with parameters if successful\r\n     */\r\n    match(segments: string[]): RouteMatchResult | null {\r\n        if (segments.length != this.segments.length) {\r\n            return null;\r\n        }\r\n\r\n        const generatedSegments: string[] = [];\r\n        var params: RouteData = {};\r\n        for (let index = 0; index < segments.length; index++) {\r\n            const urlSegment = segments[index];\r\n            const ourSegment = this.segments[index];\r\n\r\n            if (!ourSegment.isMatch(urlSegment)) {\r\n                return null;\r\n            }\r\n\r\n            if (ourSegment.paramName) {\r\n                const value = ourSegment.getValue(urlSegment);\r\n                params[ourSegment.paramName] = value;\r\n                generatedSegments.push(value.toString());\r\n            } else {\r\n                generatedSegments.push(urlSegment);\r\n            }\r\n        }\r\n\r\n        return { route: this.route, params, urlSegments: generatedSegments };\r\n    }\r\n\r\n    /**\r\n     * Routing by name and route data, so generate the url segments.\r\n     * @param routeData Data to use in the URL.\r\n     * @returns Match result with parameters if successful\r\n     */\r\n    buildUrl(routeData: RouteData): RouteMatchResult | null {\r\n        const urlSegments: string[] = [];\r\n        const params: RouteData = {};\r\n\r\n        const lowerIndex: Record<string, string> = {};\r\n        for (const key of Object.keys(routeData)) {\r\n            lowerIndex[key.toLowerCase()] = key;\r\n        }\r\n\r\n        for (let index = 0; index < this.segments.length; index++) {\r\n            const ourSegment = this.segments[index];\r\n            if (ourSegment.paramName) {\r\n                let value = routeData[ourSegment.paramName];\r\n                if (value === undefined) {\r\n                    const matched = lowerIndex[ourSegment.paramName.toLowerCase()];\r\n                    if (matched !== undefined) {\r\n                        value = routeData[matched];\r\n                    }\r\n                }\r\n                if (!value) {\r\n                    throw new Error(\r\n                        `Route \"${\r\n                            this.route.name\r\n                        }\" did not get value for parameter \"${\r\n                            ourSegment.paramName\r\n                        }\" from the provided routeData: \"${JSON.stringify(\r\n                            routeData\r\n                        )}\".`\r\n                    );\r\n                }\r\n\r\n                params[ourSegment.paramName] = value;\r\n                urlSegments.push(value.toString());\r\n            } else {\r\n                urlSegments.push(ourSegment.getValue('').toString());\r\n            }\r\n        }\r\n\r\n        return { route: this.route, params, urlSegments };\r\n    }\r\n\r\n}\r\n\r\n/**\r\n * Match route by either name or URL pattern\r\n * @param routes Available routes\r\n * @param routeNameOrUrl Route name or URL to match\r\n * @param routeData Optional parameters for named routes\r\n */\r\nexport function matchRoute(\r\n    routes: Route[],\r\n    routeNameOrUrl: string,\r\n    routeData?: Record<string, string | any>\r\n): RouteMatchResult | null {\r\n    if (routeNameOrUrl === '' || routeNameOrUrl.indexOf('/') >= 0) {\r\n        return findRouteByUrl(routes, routeNameOrUrl || '/');\r\n    } else {\r\n        return findRouteByName(routes, routeNameOrUrl, routeData!);\r\n    }\r\n}\r\n\r\n/**\r\n * Find route by name and apply parameters\r\n * @param routes Available routes\r\n * @param name Route name to find\r\n * @param routeData Parameters to apply\r\n */\r\nexport function findRouteByName(\r\n    routes: Route[],\r\n    name: string,\r\n    routeData?: Record<string, string | any>\r\n): RouteMatchResult | null {\r\n    var route = routes.find((x) => x.name === name);\r\n    if (!route) {\r\n        return null;\r\n    }\r\n\r\n    var imp = generateRouteImp(route);\r\n    var result = imp.buildUrl(routeData ?? {});\r\n    return result;\r\n}\r\n\r\n/**\r\n * Find route matching URL pattern\r\n * @param routes Available routes\r\n * @param path URL to match\r\n */\r\nexport function findRouteByUrl(\r\n    routes: Route[],\r\n    path: string\r\n): RouteMatchResult | null {\r\n    const urlSegments = path.replace(/^\\/|\\/$/g, '').split('/');\r\n    const routeImps = generateRouteImps(routes);\r\n\r\n    for (let index = 0; index < routeImps.length; index++) {\r\n        const element = routeImps[index];\r\n        const m = element.match(urlSegments);\r\n        if (m) {\r\n            return m;\r\n        }\r\n    }\r\n\r\n    if (window.relaxDebug?.routing) {\r\n        console.log('[relaxjs:routing] no route matched url', path, {\r\n            urlSegments,\r\n            tried: routes.map((route) => ({\r\n                name: route.name,\r\n                path: route.path,\r\n                segmentCount: route.path.replace(/^\\/|\\/$/g, '').split('/').length,\r\n            })),\r\n        });\r\n    }\r\n\r\n    return null;\r\n}\r\n\r\n/**\r\n * Generate implementations for all routes\r\n */\r\nfunction generateRouteImps(routes: Route[]) {\r\n    const routeImps: RouteImp[] = [];\r\n    routes.forEach((route) => {\r\n        var imp = generateRouteImp(route);\r\n        routeImps.push(imp);\r\n    });\r\n\r\n    return routeImps;\r\n}\r\n\r\n/**\r\n * Generate implementation for single route\r\n * Parses URL pattern into segment matchers\r\n */\r\nfunction generateRouteImp(route: Route): RouteImp {\r\n    var impSegments: RouteSegment[] = [];\r\n    const segments = route.path.replace(/^\\/|\\/$/g, '').split('/');\r\n    segments.forEach((segment) => {\r\n        if (segment.substring(0, 1) == ':') {\r\n            impSegments.push(new StringRouteSegment(segment.substring(1)));\r\n        } else if (segment.substring(0, 1) === ';') {\r\n            impSegments.push(new NumberRouteSegment(segment.substring(1)));\r\n        } else {\r\n            impSegments.push(new PathRouteSegment(segment));\r\n        }\r\n    });\r\n\r\n    var imp = new RouteImp(route, impSegments);\r\n    return imp;\r\n}\r\n", "import {\n    navigate,\n    navigateBack,\n    navigateForward,\n    canGoBack,\n    canGoForward,\n} from './navigation';\nimport { RelaxError, reportError } from '../errors';\n\n/**\n * Direction values accepted by the `direction` attribute on `<r-link>`.\n * When set, the link triggers back/forward in the named target's history\n * instead of navigating to a route by name.\n */\nexport type RouteLinkDirection = 'back' | 'forward';\n\nexport class RouteLink extends HTMLElement {\n    static get observedAttributes() {\n        return ['name', 'target', 'params', 'direction'];\n    }\n\n    constructor() {\n        super();\n        this.addEventListener('click', e => this.handleClick(e));\n    }\n\n    private handleClick(e: MouseEvent)  {\n        e.preventDefault();\n\n        const direction = this.getAttribute('direction') as RouteLinkDirection | null;\n        if (direction === 'back' || direction === 'forward') {\n            this.handleDirectionClick(direction);\n            return;\n        }\n\n        const name = this.getAttribute('name');\n        if (!name) return;\n\n        const params: Record<string, string> = {};\n        for (const attr of Array.from(this.attributes)) {\n            if (attr.name.startsWith('param-')) {\n                const raw = attr.name.substring(6);\n                const paramName = raw.replace(/-([a-z0-9])/g, (_, c) => c.toUpperCase());\n                params[paramName] = attr.value;\n            }\n        }\n\n        const paramsAttr = this.getAttribute('params');\n        let additionalParams: Record<string, string | number> | undefined;\n        if (paramsAttr) {\n            try {\n                const parsed = JSON.parse(paramsAttr);\n                additionalParams = parsed as Record<string, string | number>;\n            } catch (error) {\n                const err = reportError('Failed to parse route params', {\n                    element: 'r-link',\n                    params: paramsAttr,\n                    cause: error,\n                });\n                if (err) throw err;\n            }\n        }\n\n        const target = this.getAttribute('target');\n        if (additionalParams){\n            Object.assign(params, additionalParams);\n        }\n\n        try {\n            navigate(name, { params, target: target || undefined });\n        } catch (error) {\n            if (error instanceof RelaxError) throw error;\n            const reported = reportError('Navigation failed', {\n                element: 'r-link',\n                route: name,\n                params,\n                target,\n                cause: error,\n            });\n            if (reported) throw reported;\n        }\n    }\n\n    private handleDirectionClick(direction: RouteLinkDirection) {\n        const target = this.getAttribute('target') || undefined;\n        if (direction === 'back') {\n            if (!canGoBack(target)) return;\n            navigateBack(target);\n        } else {\n            if (!canGoForward(target)) return;\n            navigateForward(target);\n        }\n    }\n\n    connectedCallback() {\n        if (!this.hasAttribute('tabindex')) {\n            this.setAttribute('tabindex', '0');\n        }\n\n        this.style.cursor = 'pointer';\n        this.role = 'link';\n        this.updateDirectionState();\n    }\n\n    attributeChangedCallback(name: string) {\n        if (name === 'direction' || name === 'target') {\n            this.updateDirectionState();\n        }\n    }\n\n    /**\n     * Keeps `aria-disabled` in sync with whether the linked target has\n     * history to walk. Lets CSS react via `[aria-disabled=\"true\"]`.\n     */\n    private updateDirectionState() {\n        const direction = this.getAttribute('direction') as RouteLinkDirection | null;\n        if (direction !== 'back' && direction !== 'forward') {\n            this.removeAttribute('aria-disabled');\n            return;\n        }\n        const target = this.getAttribute('target') || undefined;\n        const available = direction === 'back' ? canGoBack(target) : canGoForward(target);\n        if (available) {\n            this.removeAttribute('aria-disabled');\n        } else {\n            this.setAttribute('aria-disabled', 'true');\n        }\n    }\n\n    disconnectedCallback() {\n        this.removeEventListener('click', this.handleClick);\n    }\n}\n", "import { registerRouteTarget, unregisterRouteTarget } from './routeTargetRegistry';\r\nimport type { NavigateRouteEvent } from './NavigateRouteEvent';\r\nimport type { RouteData, LoadRoute } from './types';\r\nimport { RelaxError, reportError } from '../errors';\r\n\r\n/**\r\n * How long a route waits for its component to appear in `customElements`\r\n * before saying so.\r\n *\r\n * A component behind a dynamic import may legitimately take a moment, so the\r\n * route keeps waiting after the warning rather than failing the navigation.\r\n */\r\nconst COMPONENT_REGISTRATION_WARNING_MS = 5000;\r\n\r\n/**\r\n * WebComponent that listens on the `NavigateRouteEvent` event to be able to switch route.\r\n *\r\n * Use the \"name\" attribute to make this non-default target.\r\n * Use the \"dialog\" attribute to render routes inside a native `<dialog>` element\r\n * with built-in focus trapping, backdrop, and Escape-to-close.\r\n *\r\n * @example\r\n * <r-route-target></r-route-target>\r\n * <r-route-target name=\"modal\" dialog></r-route-target>\r\n */\r\nexport class RouteTarget extends HTMLElement {\r\n    name?: string = undefined;\r\n    private dialog?: HTMLDialogElement;\r\n\r\n    connectedCallback() {\r\n        this.name = this.getAttribute('name') ?? undefined;\r\n\r\n        if (this.hasAttribute('dialog')) {\r\n            this.dialog = document.createElement('dialog');\r\n            this.dialog.addEventListener('close', () => {\r\n                this.dialog!.replaceChildren();\r\n            });\r\n            this.appendChild(this.dialog);\r\n        }\r\n\r\n        registerRouteTarget(this.name, (evt) => this.onNavigate(evt));\r\n    }\r\n\r\n    disconnectedCallback() {\r\n        unregisterRouteTarget(this.name);\r\n    }\r\n\r\n    private onNavigate(evt: NavigateRouteEvent) {\r\n        this.loadComponent(evt).catch((error) => {\r\n            if (!(error instanceof RelaxError)) {\r\n                error = reportError('Route navigation failed', {\r\n                    route: evt.route.name,\r\n                    routeTarget: evt.routeTarget,\r\n                    cause: error,\r\n                });\r\n            }\r\n            if (error) {\r\n                console.error(error);\r\n            }\r\n        });\r\n    }\r\n\r\n    private async loadComponent(evt: NavigateRouteEvent) {\r\n        const tagName = evt.route.componentTagName\r\n            ?? (evt.route.component ? customElements.getName(evt.route.component) : null);\r\n\r\n        if (!tagName) {\r\n            const error = reportError('Failed to find component for route', {\r\n                route: evt.route.name,\r\n                componentTagName: evt.route.componentTagName,\r\n                component: evt.route.component?.name,\r\n                routeData: evt.routeData,\r\n            });\r\n            if (error) throw error;\r\n            return;\r\n        }\r\n\r\n        await this.whenComponentRegistered(tagName, evt);\r\n        const element = document.createElement(tagName);\r\n\r\n        await this.applyRouteData(element, evt.routeData);\r\n\r\n        if (this.dialog) {\r\n            this.dialog.replaceChildren(element);\r\n            if (!this.dialog.open) {\r\n                this.dialog.showModal();\r\n            }\r\n            return;\r\n        }\r\n\r\n        await this.showPage(element);\r\n    }\r\n\r\n    /**\r\n     * Waits for the route's component to be registered.\r\n     *\r\n     * `customElements.whenDefined` never rejects, so a tag name that is never\r\n     * registered leaves the route waiting with nothing on screen and nothing in\r\n     * the console. The warning breaks that silence without giving up on a\r\n     * component that is merely slow to arrive.\r\n     */\r\n    private async whenComponentRegistered(tagName: string, evt: NavigateRouteEvent) {\r\n        if (customElements.get(tagName)) {\r\n            return;\r\n        }\r\n\r\n        const stillWaiting = setTimeout(() => {\r\n            console.warn(\r\n                `[relaxjs:routing] Route '${evt.route.name}' is waiting for <${tagName}> to be registered with customElements, and cannot render until it is. Check the tag name for typos, and that the module defining the component is imported.`\r\n            );\r\n        }, COMPONENT_REGISTRATION_WARNING_MS);\r\n\r\n        try {\r\n            await customElements.whenDefined(tagName);\r\n        } finally {\r\n            clearTimeout(stillWaiting);\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Puts the page on screen, animated with a view transition when the browser supports one.\r\n     *\r\n     * The browser drops the animation when the tab is hidden or when the visitor navigates again\r\n     * before it has finished. That is normal browsing, not a failed navigation, so the dropped\r\n     * animation is not reported. The visitor must still get the new page, so the swap is done\r\n     * directly when the browser gave up before running it.\r\n     */\r\n    private async showPage(element: Element) {\r\n        if (!document.startViewTransition) {\r\n            this.replaceChildren(element);\r\n            return;\r\n        }\r\n\r\n        const transition = document.startViewTransition(() => this.replaceChildren(element));\r\n        transition.ready.catch(() => undefined);\r\n        transition.finished.catch(() => undefined);\r\n\r\n        try {\r\n            await transition.updateCallbackDone;\r\n        } catch {\r\n            this.replaceChildren(element);\r\n        }\r\n    }\r\n\r\n    /** Closes the dialog (only applies to dialog targets). */\r\n    close() {\r\n        this.dialog?.close();\r\n    }\r\n\r\n    private async applyRouteData(element: Element, data?: RouteData) {\r\n        if ('loadRoute' in element) {\r\n            if (!data) {\r\n                console.warn(\r\n                    `[relaxjs:routing] <${element.tagName.toLowerCase()}> has loadRoute(), but the route carries no parameters to hand it. Add parameters to the route path, or drop loadRoute() from the component.`\r\n                );\r\n            }\r\n            const routeData = data\r\n                ?? { r_error: 'loadRoute function without mapped route data in the routes' };\r\n            await (element as unknown as LoadRoute).loadRoute(routeData);\r\n        }\r\n\r\n        if (data) {\r\n            (element as any).routeData = data;\r\n        }\r\n    }\r\n}\r\n", "/**\r\n * Single Page Application routing system with multiple target support.\r\n * Designed for scenarios where you need:\r\n * - Multiple navigation targets (main content, modals, sidebars)\r\n * - Strongly typed route parameters\r\n * - History management with back/forward support\r\n *\r\n * @example\r\n * // Configure routes\r\n * const routes = [\r\n *   { name: 'user', path: '/users/:id' },          // String parameter\r\n *   { name: 'order', path: '/orders/;orderId' },   // Number parameter\r\n *   { name: 'modal', path: '/detail/:id', target: 'modal' }  // Custom target\r\n * ];\r\n */\r\n\r\nimport { reportError } from '../errors';\r\nimport {\r\n    GuardResult,\r\n    RouteError,\r\n    RouteGuardError,\r\n    type Route,\r\n    type RouteData,\r\n    type RouteParamType,\r\n    type RouteMatchResult,\r\n    type NavigateOptions,\r\n} from './types';\r\nimport { NavigateRouteEvent } from './NavigateRouteEvent';\r\nimport { matchRoute, findRouteByName, findRouteByUrl } from './routeMatching';\r\nimport { initRouteTargetListener, getTargetHistory } from './routeTargetRegistry';\r\nimport { RouteLink } from './RouteLink';\r\nimport { RouteTarget } from './RoutingTarget';\r\nimport type { NavigationEntry } from './NavigationHistory';\r\n\r\n/**\r\n * State stored in `history.pushState` / `history.replaceState`.\r\n * Contains everything the popstate handler needs to replay a navigation\r\n * into the correct route target.\r\n */\r\ninterface NavigationState {\r\n    target?: string;\r\n    routeName?: string;\r\n    params: RouteData;\r\n    urlSegments: string[];\r\n    entryId: number;\r\n    fragment?: string;\r\n}\r\n\r\n/**\r\n * Fragment the router puts on the URL when it reloads the page to switch layout.\r\n *\r\n * It is namespaced so the router can tell its own marker apart from a fragment\r\n * that belongs to the application. Everything not matching this is left alone.\r\n */\r\nconst LAYOUT_SENTINEL = '#rlx-layout';\r\n\r\nlet nextEntryId = 1;\r\nlet popstateAttached = false;\r\n\r\n/**\r\n * Application fragment of the current URL, without the leading `#`.\r\n *\r\n * Returns `undefined` for the router's own layout marker, so an app never sees\r\n * an internal value it did not put there.\r\n */\r\nfunction readAppFragment(): string | undefined {\r\n    const hash = window.location.hash;\r\n    if (!hash || hash === LAYOUT_SENTINEL) {\r\n        return undefined;\r\n    }\r\n\r\n    return hash.slice(1);\r\n}\r\n\r\nfunction allocEntryId(): number {\r\n    return nextEntryId++;\r\n}\r\n\r\n/**\r\n * Used to keep track of current main HTML file,\r\n * used when different layouts are supported.\r\n *\r\n * The default page is ALWAYS loaded initially,\r\n * which means that we need to switch layout page\r\n * if someone else is configured for the route.\r\n */\r\nvar currentLayout: string | undefined;\r\n\r\nfunction getCurrentLayout(): string {\r\n    if (currentLayout === undefined) {\r\n        currentLayout = getLayout() ?? 'default';\r\n    }\r\n    return currentLayout;\r\n}\r\n\r\nfunction getLayout() {\r\n    const path = window.location.pathname;\r\n    if (path == '/index.html') {\r\n        return 'default';\r\n    }\r\n\r\n    return path.endsWith('.html') ? path.slice(1, -5) : null;\r\n}\r\n\r\nexport const internalRoutes: Route[] = [];\r\n\r\nexport const MyData = {\r\n    routes: []\r\n};\r\n\r\n/**\r\n * Debug helper to print all registered routes to console.\r\n */\r\nexport function printRoutes() {\r\n    console.log(internalRoutes);\r\n}\r\n\r\n/**\r\n * Registers application routes with the router.\r\n * Call this at application startup before routing begins.\r\n *\r\n * @param appRoutes - Array of route configurations\r\n * @throws Error if referenced components are not registered\r\n *\r\n * @example\r\n * const routes: Route[] = [\r\n *     { name: 'home', path: '/', componentTagName: 'app-home' },\r\n *     { name: 'user', path: '/users/:id', componentTagName: 'user-profile' },\r\n *     { name: 'login', path: '/auth/', componentTagName: 'login-form', layout: 'noauth' }\r\n * ];\r\n * defineRoutes(routes);\r\n */\r\nexport function defineRoutes(appRoutes: Route[]) {\r\n    initRouteTargetListener();\r\n    if (!customElements.get('r-route-target')) {\r\n        customElements.define('r-route-target', RouteTarget);\r\n    }\r\n    if (!customElements.get('r-link')) {\r\n        customElements.define('r-link', RouteLink);\r\n    }\r\n    internalRoutes.length = 0;\r\n    internalRoutes.push(...appRoutes);\r\n\r\n    if (window.relaxDebug?.routing) {\r\n        console.log('[relaxjs:routing] routes defined', appRoutes);\r\n    }\r\n\r\n    var errs: string[] = [];\r\n    appRoutes.forEach((route) => {\r\n        if (\r\n            route.componentTagName &&\r\n            !customElements.get(route.componentTagName)\r\n        ) {\r\n            errs.push(\r\n                `Component with tagName '${route.componentTagName}' is not defined in customElements.`\r\n            );\r\n        }\r\n        if (route.component && !customElements.getName(route.component)) {\r\n            errs.push(\r\n                `Component '${route.component.name}' is not defined in customElements. Used in route '${JSON.stringify(route)}'.`\r\n            );\r\n        }\r\n        const bracedSegments = route.path\r\n            .replace(/^\\/|\\/$/g, '')\r\n            .split('/')\r\n            .filter((segment) => segment.startsWith('{'));\r\n        if (bracedSegments.length > 0) {\r\n            errs.push(\r\n                `Route '${route.name}' uses ${bracedSegments.join(', ')} in path '${route.path}'. Relaxjs writes parameters as ':name' for text and ';name' for a number.`\r\n            );\r\n        }\r\n        if (route.layout === '') {\r\n            console.warn(\r\n                `[relaxjs:routing] Route '${route.name}' has an empty layout name, which is being treated as \"no layout\". Leave layout undefined instead.`,\r\n                route\r\n            );\r\n            route.layout = undefined;\r\n        }\r\n    });\r\n\r\n    if (errs.length > 0) {\r\n        throw new Error(errs.join('\\n'));\r\n    }\r\n}\r\n\r\n/**\r\n * Initializes routing and navigates to the current URL.\r\n * Call this after DOM is ready and routes are defined.\r\n *\r\n * @example\r\n * // In your main application component\r\n * connectedCallback() {\r\n *     defineRoutes(routes);\r\n *     startRouting();\r\n * }\r\n */\r\nexport function startRouting() {\r\n    if (getCurrentLayout() == '') {\r\n        const path = window.location.pathname;\r\n        const match = path.match(/\\/([^\\/]+)\\.html$/);\r\n        if (match && match[1] !== '') {\r\n            if (window.relaxDebug?.routing) {\r\n                console.log('[relaxjs:routing] current layout taken from URL', match[1], path);\r\n            }\r\n            currentLayout = match[1];\r\n        } else {\r\n            if (window.relaxDebug?.routing) {\r\n                console.log('[relaxjs:routing] current layout defaulted to \"default\"', path);\r\n            }\r\n            currentLayout = 'default';\r\n        }\r\n    }\r\n\r\n    if (tryLoadRouteFromLayoutNavigation()) {\r\n        return;\r\n    }\r\n\r\n    const currentUrl = window.location.pathname || '/';\r\n    const routeResult = findRoute(currentUrl, {});\r\n\r\n    const searchParams = new URLSearchParams(window.location.search);\r\n    if (searchParams.size > 0) {\r\n        routeResult.params ??= {};\r\n        searchParams.forEach((value, key) => {\r\n            routeResult.params[key] = value;\r\n        });\r\n    }\r\n\r\n    routeResult.fragment = readAppFragment();\r\n\r\n    if (navigateToLayout(routeResult)) {\r\n        return;\r\n    }\r\n\r\n    attachPopstateListener();\r\n\r\n    const target = routeResult.route.target;\r\n    const entryId = allocEntryId();\r\n    const state: NavigationState = {\r\n        target,\r\n        routeName: routeResult.route.name,\r\n        params: routeResult.params,\r\n        urlSegments: routeResult.urlSegments,\r\n        entryId,\r\n        fragment: routeResult.fragment,\r\n    };\r\n    history.replaceState(state, '', '/' + routeResult.urlSegments.join('/'));\r\n\r\n    const e = new NavigateRouteEvent(\r\n        routeResult.route,\r\n        routeResult.urlSegments,\r\n        routeResult.params,\r\n        target\r\n    );\r\n    e.entryId = entryId;\r\n    e.fragment = routeResult.fragment;\r\n    document.dispatchEvent(e);\r\n}\r\n\r\n/**\r\n * Navigates to a route by name or URL.\r\n * Updates browser history and dispatches navigation events.\r\n *\r\n * @param routeNameOrUrl - Route name or URL path to navigate to\r\n * @param options - Navigation options including params and target\r\n *\r\n * @example\r\n * // Navigate by route name\r\n * navigate('user', { params: { id: '123' } });\r\n *\r\n * // Navigate by URL\r\n * navigate('/users/123');\r\n *\r\n * // Navigate to specific target\r\n * navigate('detail', { params: { id: '42' }, target: 'modal' });\r\n */\r\nexport function navigate(routeNameOrUrl: string, options?: NavigateOptions) {\r\n    if (window.relaxDebug?.routing) {\r\n        console.log('[relaxjs:routing] navigate', routeNameOrUrl, options);\r\n    }\r\n    const routeResult = findRoute(routeNameOrUrl, options);\r\n    routeResult.fragment = options?.fragment;\r\n    if (navigateToLayout(routeResult)) {\r\n        return;\r\n    }\r\n\r\n    attachPopstateListener();\r\n\r\n    const target = options?.target ?? routeResult.route.target;\r\n    const entryId = allocEntryId();\r\n    const ourUrl = routeResult.urlSegments.join('/');\r\n    const currentUrl = window.location.pathname.replace(/^\\/|\\/$/g, '');\r\n    const state: NavigationState = {\r\n        target,\r\n        routeName: routeResult.route.name,\r\n        params: routeResult.params,\r\n        urlSegments: routeResult.urlSegments,\r\n        entryId,\r\n        fragment: routeResult.fragment,\r\n    };\r\n    if (currentUrl != ourUrl) {\r\n        history.pushState(state, '', '/' + routeResult.urlSegments.join('/'));\r\n    }\r\n    const e = new NavigateRouteEvent(\r\n        routeResult.route,\r\n        routeResult.urlSegments,\r\n        routeResult.params,\r\n        target\r\n    );\r\n    e.entryId = entryId;\r\n    e.fragment = routeResult.fragment;\r\n    document.dispatchEvent(e);\r\n}\r\n\r\n/**\r\n * Returns `true` when the named target has a previous navigation it can\r\n * step back to. Pass `undefined` (or omit) for the default unnamed target.\r\n *\r\n * @example\r\n * if (canGoBack()) navigateBack();\r\n */\r\nexport function canGoBack(target?: string): boolean {\r\n    return getTargetHistory(target)?.canGoBack() ?? false;\r\n}\r\n\r\n/**\r\n * Returns `true` when the named target was stepped back and can be stepped\r\n * forward again. Pass `undefined` for the default unnamed target.\r\n */\r\nexport function canGoForward(target?: string): boolean {\r\n    return getTargetHistory(target)?.canGoForward() ?? false;\r\n}\r\n\r\n/**\r\n * Replays the previous navigation in the named target's history.\r\n * Updates the browser URL bar via `pushState`. Does nothing if the target\r\n * has no prior entry.\r\n *\r\n * @param target - Target name. Omit for the default unnamed target.\r\n *\r\n * @example\r\n * navigateBack();          // step the default target back\r\n * navigateBack('modal');   // step the modal target back independently\r\n */\r\nexport function navigateBack(target?: string): void {\r\n    const history = getTargetHistory(target);\r\n    const entry = history?.back();\r\n    if (entry) replayEntry(entry);\r\n}\r\n\r\n/**\r\n * Replays the next navigation in the named target's history (after a back).\r\n * Does nothing if the target has no forward entry.\r\n */\r\nexport function navigateForward(target?: string): void {\r\n    const history = getTargetHistory(target);\r\n    const entry = history?.forward();\r\n    if (entry) replayEntry(entry);\r\n}\r\n\r\nfunction replayEntry(entry: NavigationEntry): void {\r\n    const routeResult = findRouteByName(internalRoutes, entry.routeName, entry.params);\r\n    if (!routeResult) {\r\n        const error = reportError('Cannot replay navigation entry', {\r\n            routeName: entry.routeName,\r\n            target: entry.target,\r\n        });\r\n        if (error) throw error;\r\n        return;\r\n    }\r\n    const state: NavigationState = {\r\n        target: entry.target,\r\n        routeName: entry.routeName,\r\n        params: entry.params,\r\n        urlSegments: entry.urlSegments,\r\n        entryId: entry.entryId,\r\n    };\r\n    window.history.pushState(state, '', '/' + entry.urlSegments.join('/'));\r\n    dispatchReplay(routeResult.route, entry);\r\n}\r\n\r\nfunction dispatchReplay(route: Route, entry: NavigationEntry): void {\r\n    const evt = new NavigateRouteEvent(\r\n        route,\r\n        entry.urlSegments,\r\n        entry.params,\r\n        entry.target\r\n    );\r\n    evt.isReplay = true;\r\n    evt.entryId = entry.entryId;\r\n    evt.fragment = entry.fragment;\r\n    document.dispatchEvent(evt);\r\n}\r\n\r\nfunction attachPopstateListener(): void {\r\n    if (popstateAttached) return;\r\n    popstateAttached = true;\r\n    window.addEventListener('popstate', onPopState);\r\n}\r\n\r\nfunction onPopState(e: PopStateEvent): void {\r\n    const state = e.state as NavigationState | null;\r\n    if (!state || typeof state !== 'object' || !('entryId' in state)) return;\r\n\r\n    let routeResult: RouteMatchResult | null = null;\r\n    if (state.routeName) {\r\n        routeResult = findRouteByName(internalRoutes, state.routeName, state.params);\r\n    }\r\n    if (!routeResult) {\r\n        routeResult = findRouteByUrl(internalRoutes, '/' + state.urlSegments.join('/'));\r\n    }\r\n    if (!routeResult) return;\r\n\r\n    const entry: NavigationEntry = {\r\n        routeName: state.routeName ?? routeResult.route.name ?? '',\r\n        params: state.params,\r\n        target: state.target,\r\n        urlSegments: state.urlSegments,\r\n        entryId: state.entryId,\r\n        fragment: state.fragment,\r\n    };\r\n    dispatchReplay(routeResult.route, entry);\r\n}\r\n\r\nfunction findRoute(routeNameOrUrl: string, options?: NavigateOptions) {\r\n    const theRoutes = options?.routes ?? internalRoutes;\r\n    const params = options?.params;\r\n\r\n    const routeResult = matchRoute(theRoutes, routeNameOrUrl, params);\r\n    if (!routeResult) {\r\n        const errorMsg = generateErrorMessage(\r\n            routeNameOrUrl,\r\n            params,\r\n            theRoutes\r\n        );\r\n        console.error(errorMsg);\r\n        throw new RouteError(errorMsg);\r\n    }\r\n\r\n    if (!checkRouteGuards(routeResult)) {\r\n        throw new RouteGuardError('Route guards stopped navigation for route ' + routeNameOrUrl);\r\n    }\r\n\r\n    return routeResult;\r\n}\r\n\r\nfunction navigateToLayout(routeResult: RouteMatchResult): boolean {\r\n    if (!routeResult) {\r\n        console.error('Route result is null, cannot navigate to layout.');\r\n    }\r\n\r\n    const wantedLayout = (routeResult.route.layout ?? 'default').replace(\r\n        /\\.html?$/,\r\n        ''\r\n    );\r\n    if (wantedLayout === getCurrentLayout()) {\r\n        return false;\r\n    }\r\n\r\n    // Our own marker means that we attempted to redirect to the same layout once,\r\n    // so if it's there and another redirect is requsted, something is wrong.\r\n    //\r\n    // Because the push history should remove it if everything worked out.\r\n    // Only our namespaced marker counts, any other fragment belongs to the app.\r\n    if (window.location.hash === LAYOUT_SENTINEL) {\r\n        throw Error(\r\n            `A redirect failed. Wanted layout '${wantedLayout}' for route '${routeResult.route.name}', but after reloading ${window.location.pathname} the current layout is still '${getCurrentLayout()}'. Does the layout page exist?`\r\n        );\r\n    }\r\n\r\n    if (window.relaxDebug?.routing) {\r\n        console.log(\r\n            `[relaxjs:routing] layout switch required, from '${getCurrentLayout()}' to '${wantedLayout}'`,\r\n            routeResult.route.name\r\n        );\r\n    }\r\n    // The fragment travels in session storage instead of on the new URL, so a\r\n    // token carried there is not repeated in the address bar of the layout page.\r\n    const navigationState = {\r\n        routeName: routeResult.route.name,\r\n        params: routeResult.params || {},\r\n        fragment: routeResult.fragment\r\n    };\r\n\r\n    sessionStorage.setItem('layoutNavigation', JSON.stringify(navigationState));\r\n    const layoutUrl =\r\n        wantedLayout.indexOf('.htm') > -1\r\n            ? `/${wantedLayout}${LAYOUT_SENTINEL}`\r\n            : `/${wantedLayout}.html${LAYOUT_SENTINEL}`;\r\n    if (window.relaxDebug?.routing) {\r\n        console.log('[relaxjs:routing] reloading page to switch layout', layoutUrl, navigationState);\r\n    }\r\n    window.location.href = layoutUrl;\r\n    return true;\r\n}\r\n/**\r\n * Checks session storage for route information and initiates proper navigation\r\n * Should be called when page loads to handle layout transitions\r\n *\r\n * @returns Whether navigation was initiated from session storage\r\n *\r\n * @example\r\n * // Call on page load\r\n * document.addEventListener('DOMContentLoaded', () => {\r\n *   if (handleLayoutNavigation()) {\r\n *     console.log('Navigation handled from session storage');\r\n *   }\r\n * });\r\n */\r\nfunction tryLoadRouteFromLayoutNavigation(): boolean {\r\n    try {\r\n        const navigationStateJson = sessionStorage.getItem('layoutNavigation');\r\n        if (!navigationStateJson) {\r\n            return false;\r\n        }\r\n\r\n        const navigationState = JSON.parse(navigationStateJson);\r\n        sessionStorage.removeItem('layoutNavigation');\r\n        if (window.relaxDebug?.routing) {\r\n            console.log('[relaxjs:routing] resuming navigation after layout switch', navigationState);\r\n        }\r\n        navigate(navigationState.routeName, {\r\n            params: navigationState.params,\r\n            fragment: navigationState.fragment\r\n        });\r\n\r\n        return true;\r\n    } catch (error) {\r\n        sessionStorage.removeItem('layoutNavigation');\r\n        reportError('Failed to navigate from session storage', {\r\n            cause: error,\r\n        });\r\n        return false;\r\n    }\r\n}\r\n\r\nfunction generateErrorMessage(\r\n    routeNameOrUrl: string,\r\n    routeParams: Record<string, RouteParamType> | undefined,\r\n    allRoutes: Route[]\r\n): string {\r\n    var routeData = '';\r\n    if (routeParams) {\r\n        routeData += Object.entries(routeParams)\r\n            .map(([key, value]) => `${key}=${value}`)\r\n            .join(', ');\r\n    } else {\r\n        routeData = '.';\r\n    }\r\n\r\n    var routesStr = allRoutes.map(\r\n        (x) =>\r\n            ` * Name: '${x.name}', path: '${x.path}', target: ${\r\n                x.target ?? 'default'\r\n            }\\n`\r\n    );\r\n    return `No route matched '${routeNameOrUrl}${routeData}'. Available routes:\\n${routesStr}`;\r\n}\r\n\r\nfunction checkRouteGuards(routeResult: RouteMatchResult): boolean {\r\n    if (\r\n        !routeResult ||\r\n        !routeResult.route.guards ||\r\n        routeResult.route.guards.length == 0\r\n    ) {\r\n        return true;\r\n    }\r\n\r\n    for (let index = 0; index < routeResult.route.guards.length; index++) {\r\n        const element = routeResult.route.guards[index];\r\n        var result = element.check(routeResult);\r\n        if (result == GuardResult.Allow) {\r\n            return true;\r\n        }\r\n\r\n        if (result == GuardResult.Stop) {\r\n            return false;\r\n        }\r\n\r\n        if (result == GuardResult.Deny) {\r\n            throw new RouteGuardError(\r\n                `Guard ${element.constructor.name} said 'Deny' for ${routeResult.route.name}`\r\n            );\r\n        }\r\n    }\r\n\r\n    return true;\r\n}\r\n", "import { reportError } from './errors';\r\n\r\n/**\r\n * Generic constructor type used for dependency registration and injection.\r\n * Represents any class constructor that can be used with the DI container.\r\n *\r\n * @template T - The type of object the constructor creates\r\n *\r\n * @example\r\n * // Use with service registration\r\n * class UserService {}\r\n * const ctor: Constructor<UserService> = UserService;\r\n * serviceCollection.registerByType(ctor, { inject: [] });\r\n */\r\nexport type Constructor<T extends object = object> = new (...args: any[]) => T;\r\n\r\n/**\r\n * Controls how service instances are shared across the container hierarchy.\r\n * Used when registering services to define their lifetime behavior.\r\n *\r\n * - `global`: Single instance shared everywhere (singleton pattern)\r\n * - `closest`: New instance per container scope (scoped lifetime)\r\n *\r\n * @example\r\n * // Singleton service - same instance everywhere\r\n * serviceCollection.register(LoggerService, { scope: 'global', inject: [] });\r\n *\r\n * // Scoped service - new instance per scope\r\n * serviceCollection.register(RequestContext, { scope: 'closest', inject: [] });\r\n */\r\nexport type ServiceScope = 'global' | 'closest';\r\n\r\n/**\r\n * Configuration options for registering a service in the DI container.\r\n * Controls identification, lifetime, and dependency resolution.\r\n *\r\n * @example\r\n * // Register with constructor injection\r\n * const options: RegistrationOptions = {\r\n *     scope: 'global',\r\n *     inject: [DatabaseConnection, ConfigService]\r\n * };\r\n * serviceCollection.register(UserRepository, options);\r\n *\r\n * @example\r\n * // Register with property injection\r\n * const options: RegistrationOptions = {\r\n *     inject: [],\r\n *     properties: { logger: Logger, config: 'appConfig' }\r\n * };\r\n *\r\n * @example\r\n * // Register with a pre-created instance\r\n * const options: RegistrationOptions = {\r\n *     inject: [],\r\n *     instance: existingService\r\n * };\r\n */\r\nexport interface RegistrationOptions {\r\n    /** Service lifetime - 'global' for singleton, 'closest' for scoped */\r\n    scope?: ServiceScope;\r\n    /** Optional string key for resolving by name instead of type */\r\n    key?: string;\r\n    /** Pre-existing instance to use instead of creating new one */\r\n    instance?: unknown;\r\n    /** Types or keys for constructor parameters, in order */\r\n    inject: (string | Constructor)[];\r\n    /** Map of property names to their injection types/keys */\r\n    properties?: Record<string, string | Constructor>;\r\n}\r\n\r\n/**\r\n * Field decorator that injects a service from the global DI container.\r\n * The service is resolved when the class instance is created (not at class definition time),\r\n * so services must be registered before the first instance is created.\r\n *\r\n * Works with web components regardless of how they are created:\r\n * - By the browser (HTML parsing): services are resolved during construction\r\n * - By application code (`document.createElement` or `new`): same behavior\r\n * - Injected fields are available in `connectedCallback` and all lifecycle methods\r\n *\r\n * @example\r\n * // Using `@Inject` in a web component\r\n * class UserPanel extends HTMLElement {\r\n *     @Inject(UserService)\r\n *     private userService!: UserService;\r\n *\r\n *     connectedCallback() {\r\n *         // userService is already resolved and ready to use\r\n *         const user = this.userService.getCurrentUser();\r\n *         this.render(user);\r\n *     }\r\n * }\r\n *\r\n * @example\r\n * // Services must be registered before components are created.\r\n * // In your app entry point (e.g. main.ts):\r\n * serviceCollection.registerByType(UserService, { inject: [ApiClient] });\r\n * serviceCollection.registerByType(ApiClient, { inject: [] });\r\n *\r\n * // Now components can be created (by browser or code)\r\n * customElements.define('user-panel', UserPanel);\r\n */\r\nexport function Inject<T extends object>(typeOrKey: Constructor<T> | string) {\r\n    return (_: undefined, context: ClassFieldDecoratorContext) => {\r\n        return function(this: any) {\r\n            return container.resolve(typeOrKey);\r\n        };\r\n    };\r\n}\r\n\r\n// Temporary collector of property injections - cleared after registration\r\n//const propertyCollector = new WeakMap<object, Record<string, string>>();\r\n\r\n/**\r\n * Class decorator that registers a service in the global DI container.\r\n * Registration happens at class definition time (when the module loads),\r\n * so import the module before creating instances that depend on this service.\r\n *\r\n * For web components: use `@ContainerService` on services, not on the\r\n * components themselves. Components use `@Inject` to consume services.\r\n *\r\n * @param options - Registration configuration including scope and dependencies\r\n *\r\n * @example\r\n * // Register a service that components can inject\r\n * @ContainerService({ inject: [ApiClient] })\r\n * class UserService {\r\n *     constructor(private api: ApiClient) {}\r\n *     getCurrentUser() { return this.api.get('/user'); }\r\n * }\r\n *\r\n * // Component consumes the service\r\n * class UserPanel extends HTMLElement {\r\n *     @Inject(UserService)\r\n *     private userService!: UserService;\r\n * }\r\n *\r\n * @example\r\n * // Service with custom key for named resolution\r\n * @ContainerService({ key: 'primaryCache', scope: 'global', inject: [] })\r\n * class CacheService {}\r\n *\r\n * // Later resolve by key\r\n * const cache = container.resolve('primaryCache');\r\n */\r\nexport function ContainerService<T extends object>(\r\n    options?: RegistrationOptions\r\n) {\r\n    return (target: Constructor<T>) => {\r\n        const opts = options ?? {inject: []};\r\n\r\n        if (opts.key) {\r\n            serviceCollection.register(target, opts);\r\n        } else {\r\n            serviceCollection.registerByType(target, opts);\r\n        }\r\n    };\r\n}\r\n\r\n/**\r\n * Internal class representing a registered service's metadata.\r\n * Holds all information needed to create and configure service instances.\r\n *\r\n * @internal This is an implementation detail and should not be used directly.\r\n */\r\nclass Registration {\r\n    /**\r\n     * Creates a new registration record.\r\n     *\r\n     * @param classConstructor - The class constructor function\r\n     * @param scope - Instance sharing behavior\r\n     * @param inject - Constructor parameter dependencies\r\n     * @param properties - Property injection mappings\r\n     * @param key - Optional string identifier\r\n     * @param instance - Optional pre-created instance\r\n     */\r\n    constructor(\r\n        public classConstructor: Constructor,\r\n        public scope: ServiceScope,\r\n        public inject: (string | Constructor)[],\r\n        public properties: Record<string, string | Constructor> = {},\r\n        public key?: string,\r\n        public instance?: unknown\r\n    ) {}\r\n}\r\n\r\n/**\r\n * Registry that stores service registration metadata.\r\n * Use this to register services before they can be resolved by a ServiceContainer.\r\n *\r\n * Typically you'll use the global `serviceCollection` instance rather than creating your own.\r\n *\r\n * @example\r\n * // Register a service by type\r\n * serviceCollection.registerByType(LoggerService, { inject: [] });\r\n *\r\n * // Register with a string key\r\n * serviceCollection.register(CacheService, { key: 'cache', inject: [] });\r\n *\r\n * // Check if service is registered\r\n * const reg = serviceCollection.tryGet(LoggerService);\r\n * if (reg) {\r\n *     console.log('Logger is registered');\r\n * }\r\n */\r\nexport class ServiceCollection {\r\n    private servicesByKey = new Map<string, Registration>();\r\n    private servicesByType = new Map<Constructor, Registration>();\r\n\r\n    /**\r\n     * Registers a service with full configuration options.\r\n     * The service will be resolvable by both its class name and optional key.\r\n     *\r\n     * @param constructor - The service class constructor\r\n     * @param options - Registration configuration\r\n     */\r\n    register<T extends object>(constructor: Constructor<T>, options: RegistrationOptions): void {\r\n        this.validateRegistration(constructor, options);\r\n\r\n        const reg = new Registration(\r\n            constructor,\r\n            options.scope ?? 'global',\r\n            options.inject,\r\n            options.properties ?? {},\r\n            options.key,\r\n            options.instance\r\n        );\r\n\r\n        if (options.key) {\r\n            this.servicesByKey.set(options.key, reg);\r\n        }\r\n        this.servicesByType.set(constructor, reg);\r\n    }\r\n\r\n    /**\r\n     * Registers a service by its class type.\r\n     * The service will be resolvable by its class constructor.\r\n     *\r\n     * @param constructor - The service class constructor\r\n     * @param options - Optional registration configuration\r\n     */\r\n    registerByType<T extends object>(\r\n        constructor: Constructor<T>,\r\n        options?: RegistrationOptions\r\n    ): void {\r\n        if (options) this.validateRegistration(constructor, options);\r\n\r\n        const reg = new Registration(constructor, options?.scope ?? 'global', options?.inject ?? [], options?.properties, options?.key, options?.instance);\r\n        if (options?.key) {\r\n            this.servicesByKey.set(options.key, reg);\r\n        }\r\n        this.servicesByType.set(constructor, reg);\r\n    }\r\n\r\n    private validateRegistration<T extends object>(constructor: Constructor<T>, options: RegistrationOptions): void {\r\n        if (options.key) {\r\n            const existingByKey = this.servicesByKey.get(options.key);\r\n            if (existingByKey && existingByKey.classConstructor !== constructor) {\r\n                const error = reportError('Service key already registered to a different class', {\r\n                    key: options.key,\r\n                    existingClass: existingByKey.classConstructor.name,\r\n                    newClass: constructor.name,\r\n                });\r\n                if (error) throw error;\r\n            }\r\n        }\r\n\r\n        if (options.instance && options.inject.length > 0) {\r\n            const error = reportError('Service has both instance and inject (inject will be ignored)', {\r\n                service: constructor.name,\r\n            });\r\n            if (error) throw error;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Attempts to retrieve a service registration.\r\n     * Returns undefined if the service is not registered.\r\n     *\r\n     * @param key - Either a string key or class constructor\r\n     * @returns The registration or undefined\r\n     */\r\n    tryGet<T extends object>(key: string | Constructor<T>): Registration | undefined {\r\n        if (typeof key === 'string') {\r\n            return this.servicesByKey.get(key);\r\n        }\r\n        return this.servicesByType.get(key);\r\n    }\r\n\r\n    /**\r\n     * Retrieves a service registration or throws if not found.\r\n     *\r\n     * @param key - Either a string key or class constructor\r\n     * @returns The registration\r\n     * @throws Error if the service is not registered\r\n     */\r\n    get<T extends object>(key: string | Constructor<T>): Registration {\r\n        const reg = this.tryGet(key);\r\n        if (!reg) {\r\n            const service = typeof key === 'string' ? key : key.name;\r\n            const error = reportError(`Failed to resolve service '${service}'`, {\r\n                service,\r\n                registeredTypes: Array.from(this.servicesByType.keys()).map(c => c.name),\r\n                registeredKeys: Array.from(this.servicesByKey.keys()),\r\n            });\r\n            if (error) throw error;\r\n        }\r\n        return reg!;\r\n    }\r\n}\r\n\r\n/**\r\n * Internal storage for tracking injected fields during service resolution.\r\n * @internal\r\n */\r\nconst injectedFields = new WeakMap<object, Map<string, string>>();\r\n\r\n/**\r\n * IoC container that resolves and manages service instances.\r\n * Creates instances based on registrations in a ServiceCollection,\r\n * handling constructor injection, property injection, and lifetime management.\r\n *\r\n * Typically you'll use the global `container` instance rather than creating your own.\r\n *\r\n * @example\r\n * // Resolve a service by class\r\n * const logger = container.resolve(LoggerService);\r\n *\r\n * // Resolve by string key\r\n * const cache = container.resolve<CacheService>('primaryCache');\r\n *\r\n * @example\r\n * // Full setup workflow\r\n * serviceCollection.register(UserService, {\r\n *     inject: [DatabaseConnection],\r\n *     scope: 'global'\r\n * });\r\n *\r\n * const userService = container.resolve(UserService);\r\n */\r\nexport class ServiceContainer {\r\n    private instances = new Map<string | Constructor, any>();\r\n\r\n    /**\r\n     * Creates a new container backed by the given service collection.\r\n     *\r\n     * @param serviceCollection - The registry containing service registrations\r\n     */\r\n    constructor(private serviceCollection: ServiceCollection) {}\r\n\r\n    /**\r\n     * Resolves a service instance by class type or string key.\r\n     * Creates the instance if not already cached (for global scope).\r\n     * Handles constructor and property injection automatically.\r\n     *\r\n     * @param keyOrType - Either a string key or class constructor\r\n     * @returns The resolved service instance\r\n     * @throws Error if the service is not registered\r\n     *\r\n     * @example\r\n     * const service = container.resolve(MyService);\r\n     */\r\n    resolve<T extends object>(keyOrType: string | Constructor<T>): T {\r\n        if (this.instances.has(keyOrType)) {\r\n            return this.instances.get(keyOrType);\r\n        }\r\n\r\n        const registration = this.serviceCollection.get(keyOrType);\r\n        if (!registration) {\r\n            const name = typeof keyOrType === 'string' ? keyOrType : keyOrType.name;\r\n            const error = reportError(`Failed to resolve service '${name}'`, { service: name });\r\n            if (error) throw error;\r\n            return undefined as unknown as T;\r\n        }\r\n\r\n        if (registration.instance) {\r\n            const inst = registration.instance as T;\r\n            this.injectFields(inst, registration);\r\n            this.instances.set(keyOrType, inst);\r\n            return inst;\r\n        }\r\n\r\n        const instance = this.createInstance<T>(registration);\r\n        if (registration.scope === 'global') {\r\n            this.instances.set(keyOrType, instance);\r\n        }\r\n        this.injectFields(instance, registration);\r\n\r\n        return instance;\r\n    }\r\n\r\n    /**\r\n     * Creates a new instance of a service, resolving all constructor dependencies.\r\n     */\r\n    private createInstance<T extends object>(registration: Registration): T {\r\n        const constructor = registration.classConstructor as Constructor<T>;\r\n\r\n        const dependencies = registration.inject.map(dep => this.resolve(dep));\r\n        return new constructor(...dependencies);\r\n    }\r\n\r\n    /**\r\n     * Injects dependencies into instance properties based on registration config.\r\n     */\r\n    private injectFields<T extends object>(instance: T, registration: Registration): void {\r\n        for (const [fieldName, keyOrType] of Object.entries(registration.properties)) {\r\n            (instance as any)[fieldName] = this.resolve(keyOrType);\r\n        }\r\n    }\r\n}\r\n\r\n/**\r\n * Global service collection instance for registering services.\r\n * Use this to register services that can later be resolved by the container.\r\n *\r\n * @example\r\n * import { serviceCollection } from 'relaxjs';\r\n *\r\n * serviceCollection.register(MyService, { inject: [Dependency] });\r\n */\r\nexport const serviceCollection = new ServiceCollection();\r\n\r\n/**\r\n * Global service container instance for resolving dependencies.\r\n * Use this to obtain service instances with all dependencies injected.\r\n *\r\n * @example\r\n * import { container } from 'relaxjs';\r\n *\r\n * const service = container.resolve(MyService);\r\n */\r\nexport const container = new ServiceContainer(serviceCollection);", "/**\r\n * Finds the closest parent element of a specific Web Component type.\r\n * Traverses up the DOM tree looking for an ancestor matching the constructor.\r\n *\r\n * Useful for child components that need to communicate with or access\r\n * their parent container component, common in composite component patterns.\r\n *\r\n * @template T - The type of HTMLElement to find\r\n * @param node - The starting node to search from\r\n * @param constructor - The class constructor of the desired element type\r\n * @returns The matching parent element or null if not found\r\n *\r\n * @example\r\n * // Inside a child component, find the parent container\r\n * class ListItem extends HTMLElement {\r\n *     connectedCallback() {\r\n *         const list = getParentComponent(this, ListContainer);\r\n *         if (list) {\r\n *             list.registerItem(this);\r\n *         }\r\n *     }\r\n * }\r\n *\r\n * @example\r\n * // Access parent component's methods\r\n * class TabPanel extends HTMLElement {\r\n *     activate() {\r\n *         const tabs = getParentComponent(this, TabContainer);\r\n *         tabs?.selectPanel(this);\r\n *     }\r\n * }\r\n *\r\n * @example\r\n * // Handle case where parent might not exist\r\n * const form = getParentComponent(input, FormContainer);\r\n * if (!form) {\r\n *     console.warn('Input must be inside a FormContainer');\r\n *     return;\r\n * }\r\n */\r\nexport function getParentComponent<T extends HTMLElement>(\r\n    node: Node,\r\n    constructor: { new (...args: any[]): T }\r\n): T | null {\r\n    let current = node.parentElement;\r\n\r\n    while (current) {\r\n        if (current instanceof constructor) {\r\n            return current;\r\n        }\r\n        current = current.parentElement;\r\n    }\r\n\r\n    return null;\r\n}   ", "/**\r\n * @module SequentialId\r\n * Generates compact, time-ordered unique identifiers suitable for distributed systems.\r\n *\r\n * IDs are structured to be:\r\n * - Unique across multiple clients (via baseId)\r\n * - Time-sortable (timestamp is the most significant bits)\r\n * - Compact (Base36 encoding produces short strings)\r\n *\r\n * Bit allocation (58 bits total):\r\n * - 30 bits for timestamp (seconds since January 1, 2025)\r\n * - 8 bits for per-second counter (supports 256 IDs/second)\r\n * - 20 bits for client/endpoint identifier (supports ~1M unique sources)\r\n */\r\n\r\nconst TIMESTAMP_BITS = 30;\r\nconst COUNTER_BITS = 8;\r\nconst BASEID_BITS = 20;\r\n\r\nconst MAX_TIMESTAMP = (1 << TIMESTAMP_BITS) - 1;\r\nconst MAX_COUNTER = (1 << COUNTER_BITS) - 1;\r\nconst MAX_BASEID = (1 << BASEID_BITS) - 1;\r\n\r\nconst EPOCH = Math.floor(new Date('2025-01-01T00:00:00Z').getTime() / 1000);\r\n\r\nlet lastTimestamp = 0;\r\nlet counter = 0;\r\n\r\n/**\r\n * Generates a unique, time-ordered sequential ID.\r\n *\r\n * The ID combines a timestamp, per-second counter, and client identifier\r\n * into a compact Base36 string. IDs generated later will sort after earlier IDs,\r\n * making them suitable for ordered collections.\r\n *\r\n * @param baseId - Unique identifier for the client/endpoint (0 to 1,048,575).\r\n *                 Use different baseIds for different servers or processes to\r\n *                 avoid collisions.\r\n * @returns Base36 encoded string representing the unique ID\r\n * @throws Error if baseId is out of valid range\r\n * @throws Error if more than 256 IDs are generated in a single second\r\n * @throws Error if timestamp exceeds range (after year 2045)\r\n *\r\n * @example\r\n * // Generate ID for server instance 1\r\n * const id1 = generateSequentialId(1);\r\n * // Returns something like: 'k2j8m3n5p'\r\n *\r\n * @example\r\n * // Different servers use different baseIds\r\n * const SERVER_ID = parseInt(process.env.SERVER_ID || '0');\r\n * const orderId = generateSequentialId(SERVER_ID);\r\n *\r\n * @example\r\n * // IDs are time-sortable\r\n * const id1 = generateSequentialId(0);\r\n * await delay(1000);\r\n * const id2 = generateSequentialId(0);\r\n * console.log(id1 < id2); // true (lexicographic comparison works)\r\n */\r\nexport function generateSequentialId(baseId: number): string {\r\n    if (baseId < 0 || baseId > MAX_BASEID) {\r\n        throw new Error(`baseId must be between 0 and ${MAX_BASEID}`);\r\n    }\r\n\r\n    const now = Math.floor(Date.now() / 1000);\r\n    if (now === lastTimestamp) {\r\n        counter++;\r\n        if (counter > MAX_COUNTER) {\r\n            throw new Error('Too many IDs generated in one second');\r\n        }\r\n    } else {\r\n        lastTimestamp = now;\r\n        counter = 0;\r\n    }\r\n\r\n    const timestamp = now - EPOCH;\r\n    if (timestamp > MAX_TIMESTAMP) {\r\n        throw new Error('Timestamp exceeds allowed range (beyond 2045-01-01)');\r\n    }\r\n\r\n    const ts = BigInt(timestamp);\r\n    const cnt = BigInt(counter);\r\n    const uid = BigInt(baseId);\r\n\r\n    // [ timestamp (30 bits) | counter (8 bits) | baseId (20 bits) ]\r\n    const id =\r\n        (ts << BigInt(COUNTER_BITS + BASEID_BITS)) |\r\n        (cnt << BigInt(BASEID_BITS)) |\r\n        uid;\r\n\r\n    return id.toString(36).toLowerCase();\r\n}\r\n", "/**\r\n * @module http\r\n * Type-safe HTTP module built on fetch() with automatic JWT handling.\r\n *\r\n * @example\r\n * import { configure, get, post } from './http';\r\n *\r\n * configure({ baseUrl: '/api' });\r\n * const response = await get('/users');\r\n * const users = response.as<User[]>();\r\n */\r\n\r\n/**\r\n * Configuration options for the http module.\r\n */\r\nexport interface HttpOptions {\r\n    /**\r\n     * Root URL to remote endpoint. Used so that each method only has to specify path in requests.\r\n     */\r\n    baseUrl?: string;\r\n\r\n    /**\r\n     * Default content type to use if none is specified in the request method.\r\n     */\r\n    contentType?: string;\r\n\r\n    /**\r\n     * Checks for a JWT token in localStorage to automatically include it in requests.\r\n     *\r\n     * Undefined = use \"jwt\", null = disable.\r\n     */\r\n    bearerTokenName?: string | null;\r\n\r\n    /**\r\n     * Default request timeout in milliseconds.\r\n     * Uses `AbortSignal.timeout()` to automatically abort requests that take too long.\r\n     * Can be overridden per-request by passing a `signal` in `RequestInit`.\r\n     *\r\n     * @example\r\n     * configure({ baseUrl: '/api', timeout: 10000 }); // 10 second timeout\r\n     */\r\n    timeout?: number;\r\n}\r\n\r\n/**\r\n * Response for request methods.\r\n */\r\nexport interface HttpResponse {\r\n    /**\r\n     * Http status code.\r\n     */\r\n    statusCode: number;\r\n\r\n    /**\r\n     * Reason to why the status code was used.\r\n     */\r\n    statusReason: string;\r\n\r\n    /**\r\n     * True if this is a 2xx response.\r\n     */\r\n    success: boolean;\r\n\r\n    /**\r\n     * Content type of response body.\r\n     */\r\n    contentType: string | null;\r\n\r\n    /**\r\n     * Body returned.\r\n     *\r\n     * Body has been read and deserialized from json (if the request content type was 'application/json' which is the default).\r\n     */\r\n    body: unknown;\r\n\r\n    /**\r\n     * Charset used in body.\r\n     */\r\n    charset: string | null;\r\n\r\n    /**\r\n     * Cast body to a type.\r\n     */\r\n    as<T>(): T;\r\n}\r\n\r\n/**\r\n * Error thrown when a request fails.\r\n */\r\nexport class HttpError extends Error {\r\n    message: string;\r\n    response: HttpResponse;\r\n\r\n    constructor(response: HttpResponse) {\r\n        super(response.statusReason);\r\n        this.message = response.statusReason;\r\n        this.response = response;\r\n    }\r\n}\r\n\r\n/**\r\n * HTTP request options.\r\n */\r\nexport interface RequestOptions {\r\n    method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\r\n    mode?: 'cors' | 'no-cors' | '*cors' | 'same-origin';\r\n    cache:\r\n        | 'default'\r\n        | 'no-store'\r\n        | 'reload'\r\n        | 'no-cache'\r\n        | 'force-cache'\r\n        | 'only-if-cached';\r\n    credentials: 'omit' | 'same-origin' | 'include';\r\n    headers: Map<string, string>;\r\n    redirect: 'follow' | 'manual' | '*follow' | 'error';\r\n    referrerPolicy:\r\n        | 'no-referrer'\r\n        | '*no-referrer-when-downgrade'\r\n        | 'origin'\r\n        | 'origin-when-cross-origin'\r\n        | 'same-origin'\r\n        | 'strict-origin'\r\n        | 'strict-origin-when-cross-origin'\r\n        | 'unsafe-url';\r\n\r\n    /**\r\n     * Will be serialized if the content type is json (and the body is an object).\r\n     */\r\n    body: unknown;\r\n}\r\n\r\n/** @internal */\r\ndeclare type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;\r\n\r\nlet config: HttpOptions = {\r\n    bearerTokenName: 'jwt'\r\n};\r\n\r\nlet fetchImpl: FetchFn = fetch;\r\n\r\n/**\r\n * Replace the fetch implementation for testing purposes.\r\n *\r\n * @param fn - Custom fetch function, or undefined to restore the default.\r\n *\r\n * @example\r\n * setFetch(async (url, options) => {\r\n *     return new Response(JSON.stringify({ id: 1 }), { status: 200 });\r\n * });\r\n */\r\nexport function setFetch(fn?: FetchFn): void {\r\n    fetchImpl = fn ?? fetch;\r\n}\r\n\r\n/**\r\n * Configure the http module.\r\n *\r\n * @example\r\n * configure({ baseUrl: '/api/v1', bearerTokenName: 'auth_token' });\r\n */\r\nexport function configure(options: HttpOptions): void {\r\n    config = {\r\n        ...config,\r\n        ...options\r\n    };\r\n    if (options.bearerTokenName === undefined) {\r\n        config.bearerTokenName = 'jwt';\r\n    }\r\n}\r\n\r\n/**\r\n * The fetch implementation currently in use, so that `setFetch()` also controls other modules\r\n * in this package that talk to the network.\r\n *\r\n * @internal\r\n */\r\nexport function currentFetch(): FetchFn {\r\n    return fetchImpl;\r\n}\r\n\r\n/**\r\n * Prefixes a url with the configured base url.\r\n *\r\n * @internal\r\n */\r\nexport function resolveUrl(url: string): string {\r\n    if (!config.baseUrl) {\r\n        return url;\r\n    }\r\n\r\n    if (url[0] !== '/' && config.baseUrl[config.baseUrl.length - 1] !== '/') {\r\n        return `${config.baseUrl}/${url}`;\r\n    }\r\n\r\n    return config.baseUrl + url;\r\n}\r\n\r\n/**\r\n * The JWT token from localStorage, or null when token handling is disabled or no token is stored.\r\n *\r\n * @internal\r\n */\r\nexport function bearerToken(): string | null {\r\n    if (!config.bearerTokenName) {\r\n        return null;\r\n    }\r\n\r\n    return localStorage.getItem(config.bearerTokenName);\r\n}\r\n\r\n/**\r\n * Make an HTTP request.\r\n *\r\n * @param url - URL to make the request against.\r\n * @param options - Request options.\r\n * @returns Response from server.\r\n *\r\n * @example\r\n * const response = await request('/users', { method: 'GET' });\r\n */\r\nexport async function request(url: string, options?: RequestInit): Promise<HttpResponse> {\r\n    const token = bearerToken();\r\n    if (token && options) {\r\n        const headers = options?.headers\r\n            ? new Headers(options.headers)\r\n            : new Headers();\r\n\r\n        if (!headers.get('Authorization')) {\r\n            headers.set('Authorization', 'Bearer ' + token);\r\n        }\r\n\r\n        options.headers = headers;\r\n    }\r\n\r\n    if (config.timeout && !options?.signal) {\r\n        options ??= {};\r\n        options.signal = AbortSignal.timeout(config.timeout);\r\n    }\r\n\r\n    const response = await fetchImpl(resolveUrl(url), options);\r\n\r\n    if (!response.ok) {\r\n        return {\r\n            statusCode: response.status,\r\n            statusReason: response.statusText,\r\n            success: false,\r\n            contentType: response.headers.get('content-type'),\r\n            body: await response.text(),\r\n            charset: response.headers.get('charset'),\r\n\r\n            as() {\r\n                throw new Error('No response received');\r\n            }\r\n        };\r\n    }\r\n\r\n    let body: unknown | null = null;\r\n    if (response.status !== 204) {\r\n        body = await response.json();\r\n    }\r\n\r\n    return {\r\n        success: true,\r\n        statusCode: response.status,\r\n        statusReason: response.statusText,\r\n        contentType: response.headers.get('content-type'),\r\n        body: body,\r\n        charset: response.headers.get('charset'),\r\n        as<T>() {\r\n            return <T>body;\r\n        }\r\n    };\r\n}\r\n\r\n/**\r\n * GET a resource.\r\n *\r\n * @param url - URL to get resource from.\r\n * @param queryString - Optional query string parameters.\r\n * @param options - Request options.\r\n * @returns HTTP response.\r\n *\r\n * @example\r\n * const response = await get('/users', { page: '1', limit: '10' });\r\n * const users = response.as<User[]>();\r\n */\r\nexport async function get(\r\n    url: string,\r\n    queryString?: Record<string, string>,\r\n    options?: RequestInit\r\n): Promise<HttpResponse> {\r\n    if (!options) {\r\n        options = {\r\n            method: 'GET',\r\n            headers: {\r\n                'content-type': config.contentType ?? 'application/json'\r\n            }\r\n        };\r\n    } else {\r\n        options.method = 'GET';\r\n    }\r\n\r\n    if (queryString) {\r\n        let prefix = '&';\r\n        if (url.indexOf('?') === -1) {\r\n            prefix = '?';\r\n        }\r\n\r\n        for (const key in queryString) {\r\n            const value = queryString[key];\r\n            url += `${prefix}${key}=${value}`;\r\n            prefix = '&';\r\n        }\r\n    }\r\n\r\n    return request(url, options);\r\n}\r\n\r\n/**\r\n * POST a resource.\r\n *\r\n * @param url - URL to post to.\r\n * @param data - Data to post.\r\n * @param options - Request options.\r\n * @returns HTTP response.\r\n *\r\n * @example\r\n * const response = await post('/users', JSON.stringify({ name: 'John' }));\r\n */\r\nexport async function post(\r\n    url: string,\r\n    data: BodyInit,\r\n    options?: RequestInit\r\n): Promise<HttpResponse> {\r\n    if (!options) {\r\n        options = {\r\n            method: 'POST',\r\n            body: data,\r\n            headers: {\r\n                'content-type': config.contentType ?? 'application/json'\r\n            }\r\n        };\r\n    } else {\r\n        options.method = 'POST';\r\n        options.body = data;\r\n    }\r\n\r\n    return request(url, options);\r\n}\r\n\r\n/**\r\n * PUT a resource.\r\n *\r\n * @param url - URL to resource.\r\n * @param data - Data to put.\r\n * @param options - Request options.\r\n * @returns HTTP response.\r\n *\r\n * @example\r\n * const response = await put('/users/1', JSON.stringify({ name: 'Jane' }));\r\n */\r\nexport async function put(\r\n    url: string,\r\n    data: BodyInit,\r\n    options?: RequestInit\r\n): Promise<HttpResponse> {\r\n    if (!options) {\r\n        options = {\r\n            method: 'PUT',\r\n            body: data,\r\n            headers: {\r\n                'content-type': config.contentType ?? 'application/json'\r\n            }\r\n        };\r\n    } else {\r\n        options.method = 'PUT';\r\n        options.body = data;\r\n    }\r\n\r\n    return request(url, options);\r\n}\r\n\r\n/**\r\n * DELETE a resource.\r\n *\r\n * @param url - URL to resource.\r\n * @param options - Request options.\r\n * @returns HTTP response.\r\n *\r\n * @example\r\n * const response = await del('/users/1');\r\n */\r\nexport async function del(url: string, options?: RequestInit): Promise<HttpResponse> {\r\n    if (!options) {\r\n        options = {\r\n            method: 'DELETE',\r\n            headers: {\r\n                'content-type': config.contentType ?? 'application/json'\r\n            }\r\n        };\r\n    } else {\r\n        options.method = 'DELETE';\r\n    }\r\n\r\n    return request(url, options);\r\n}\r\n", "/**\n * @module SseFrameParser\n * Turns the raw text of a `text/event-stream` response into complete SSE frames.\n *\n * A streamed response arrives in arbitrary chunks. A single frame is regularly split across two\n * chunks, and two frames regularly arrive in one chunk. The parser buffers whatever is incomplete\n * so the caller only ever sees whole frames.\n *\n * Internal to the http module. Not part of the public API.\n *\n * @example\n * const parser = new SseFrameParser();\n * parser.push('event: token\\ndata: {\"te');  // []\n * parser.push('xt\":\"hi\"}\\n\\n');             // [{ event: 'token', data: '{\"text\":\"hi\"}' }]\n */\n\n/**\n * One complete event received from the server.\n */\nexport interface SseFrame {\n    /**\n     * Name from the `event:` field, or `message` when the server did not send one.\n     */\n    event: string;\n\n    /**\n     * Payload from the `data:` field. Several `data:` lines are joined with a newline.\n     */\n    data: string;\n\n    /**\n     * Value of the `id:` field, when the server sent one for this frame.\n     */\n    id?: string;\n\n    /**\n     * Reconnection delay in milliseconds from the `retry:` field.\n     */\n    retry?: number;\n}\n\n/**\n * Parses `text/event-stream` text into frames.\n *\n * A frame that is still incomplete when the stream ends is discarded, as the event stream\n * specification requires. Half a JSON payload is worse than no payload.\n */\nexport class SseFrameParser {\n    private buffer = '';\n    private eventName = '';\n    private data: string[] = [];\n    private id?: string;\n    private retry?: number;\n\n    /**\n     * Feed the next piece of the response body in.\n     *\n     * @param chunk - Decoded text, of any length and split at any position.\n     * @returns Every frame that became complete with this chunk, in arrival order.\n     */\n    push(chunk: string): SseFrame[] {\n        this.buffer += chunk;\n\n        const frames: SseFrame[] = [];\n        let position = 0;\n        let lineBreak = this.findLineBreak(position);\n\n        while (lineBreak) {\n            const line = this.buffer.slice(position, lineBreak.start);\n            position = lineBreak.end;\n\n            if (line.length === 0) {\n                const frame = this.takeFrame();\n                if (frame) {\n                    frames.push(frame);\n                }\n            } else {\n                this.readField(line);\n            }\n\n            lineBreak = this.findLineBreak(position);\n        }\n\n        this.buffer = this.buffer.slice(position);\n        return frames;\n    }\n\n    /**\n     * Locates the next line terminator, which may be LF, CRLF or a lone CR.\n     *\n     * A CR at the very end of the buffer is left unresolved: the next chunk decides whether it was\n     * a lone CR or the first half of a CRLF.\n     */\n    private findLineBreak(from: number): { start: number; end: number } | null {\n        for (let i = from; i < this.buffer.length; i++) {\n            const character = this.buffer[i];\n\n            if (character === '\\n') {\n                return { start: i, end: i + 1 };\n            }\n\n            if (character === '\\r') {\n                if (i + 1 >= this.buffer.length) {\n                    return null;\n                }\n                return this.buffer[i + 1] === '\\n'\n                    ? { start: i, end: i + 2 }\n                    : { start: i, end: i + 1 };\n            }\n        }\n\n        return null;\n    }\n\n    private readField(line: string): void {\n        if (line[0] === ':') {\n            return;\n        }\n\n        const colon = line.indexOf(':');\n        const name = colon === -1 ? line : line.slice(0, colon);\n        let value = colon === -1 ? '' : line.slice(colon + 1);\n\n        if (value[0] === ' ') {\n            value = value.slice(1);\n        }\n\n        switch (name) {\n            case 'event':\n                this.eventName = value;\n                break;\n            case 'data':\n                this.data.push(value);\n                break;\n            case 'id':\n                this.id = value;\n                break;\n            case 'retry':\n                if (/^\\d+$/.test(value)) {\n                    this.retry = Number(value);\n                }\n                break;\n        }\n    }\n\n    private takeFrame(): SseFrame | null {\n        if (this.data.length === 0) {\n            this.reset();\n            return null;\n        }\n\n        const frame: SseFrame = {\n            event: this.eventName.length > 0 ? this.eventName : 'message',\n            data: this.data.join('\\n')\n        };\n\n        if (this.id !== undefined) {\n            frame.id = this.id;\n        }\n        if (this.retry !== undefined) {\n            frame.retry = this.retry;\n        }\n\n        this.reset();\n        return frame;\n    }\n\n    private reset(): void {\n        this.eventName = '';\n        this.data = [];\n        this.id = undefined;\n        this.retry = undefined;\n    }\n}\n", "/**\n * @module ServerSentEvents\n * SSE client that dispatches received events as DOM events.\n *\n * By default it uses the browser's built-in EventSource, which reconnects on its own.\n * Set a request option like `method`, `body`, `headers` or `signal`, or `autoReconnect: false`,\n * and it switches to a fetch based transport that can send data to the server and can tell you\n * why the stream ended.\n *\n * @example\n * const sse = new SSEClient('/api/events', {\n *     eventTypes: ['user-updated', 'order-created']\n * });\n * sse.connect();\n *\n * document.addEventListener('user-updated', (e: SSEDataEvent) => {\n *     console.log('User updated:', e.data);\n * });\n */\n\nimport { reportError } from '../errors';\nimport { HttpError, HttpResponse, bearerToken, currentFetch, resolveUrl } from './http';\nimport { SseFrameParser } from './SseFrameParser';\n\n/**\n * Event dispatched when an SSE message is received.\n * The event name matches the SSE event type.\n */\nexport class SSEDataEvent extends Event {\n    constructor(\n        eventName: string,\n        public data: unknown,\n        eventInit?: EventInit\n    ) {\n        super(eventName, { bubbles: true, ...eventInit });\n    }\n}\n\n/**\n * Factory function for creating custom event instances.\n *\n * @example\n * const factory: SSEEventFactory = (eventName, data) => {\n *     switch (eventName) {\n *         case 'user-updated':\n *             return new UserUpdatedEvent(data as User);\n *         default:\n *             return new SSEDataEvent(eventName, data);\n *     }\n * };\n */\nexport type SSEEventFactory = (eventName: string, data: unknown) => Event;\n\n/**\n * Why a stream stopped.\n *\n * `completed` = the server sent one of your `terminalEvents` and then closed.\n * `truncated` = the server closed cleanly but never sent a terminal event, so the result is\n * incomplete and you may want to offer a retry.\n * `aborted` = you stopped it yourself, through `disconnect()` or an `AbortSignal`.\n * `failed` = the request never started or died. `error` and `response` say why.\n */\nexport type SSECloseReason = 'completed' | 'truncated' | 'aborted' | 'failed';\n\n/**\n * Details about a stream that has stopped.\n */\nexport interface SSECloseResult {\n    /**\n     * Why the stream stopped.\n     */\n    reason: SSECloseReason;\n\n    /**\n     * Name of the last event received before the stream stopped.\n     */\n    lastEventName?: string;\n\n    /**\n     * Set when the reason is `failed`.\n     */\n    error?: Error;\n\n    /**\n     * Set when the server answered with a non 2xx status. `body` holds the raw response text.\n     */\n    response?: HttpResponse;\n}\n\n/**\n * Passed to `onError` when the fetch transport fails.\n *\n * It extends Event so that the `onError` signature is the same for both transports.\n */\nexport class SSEErrorEvent extends Event {\n    constructor(\n        public error: Error,\n        public response?: HttpResponse\n    ) {\n        super('error');\n    }\n}\n\n/**\n * Configuration options for SSEClient.\n */\nexport interface SSEOptions {\n    /**\n     * Target element or CSS selector for event dispatching.\n     * Defaults to document.\n     */\n    target?: string | Element;\n\n    /**\n     * Whether to send credentials with the request (default: false).\n     */\n    withCredentials?: boolean;\n\n    /**\n     * Specific SSE event types to listen for.\n     * If not specified, listens to the default 'message' event.\n     *\n     * @example\n     * eventTypes: ['user-updated', 'order-created']\n     */\n    eventTypes?: string[];\n\n    /**\n     * Factory function for creating custom event instances.\n     * If not provided, SSEDataEvent is used.\n     *\n     * @example\n     * eventFactory: (name, data) => new MyCustomEvent(name, data)\n     */\n    eventFactory?: SSEEventFactory;\n\n    /**\n     * HTTP method for the request (default: 'GET').\n     * Setting it selects the fetch transport.\n     */\n    method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\n\n    /**\n     * Data to send to the server.\n     * Setting it selects the fetch transport, since EventSource cannot send a body.\n     *\n     * @example\n     * body: JSON.stringify({ matchId: 42 })\n     */\n    body?: BodyInit;\n\n    /**\n     * Extra request headers.\n     * Setting them selects the fetch transport, since EventSource cannot send headers.\n     */\n    headers?: Record<string, string>;\n\n    /**\n     * Signal used to cancel the stream. Closes with reason `aborted`.\n     * Setting it selects the fetch transport.\n     */\n    signal?: AbortSignal;\n\n    /**\n     * Whether the browser should reconnect when the stream drops (default: true).\n     *\n     * Set to false to select the fetch transport, which never reconnects. A request that sends\n     * data is not always safe to repeat, so reconnection is not available there.\n     */\n    autoReconnect?: boolean;\n\n    /**\n     * Names of the events the server sends last. Receiving one of them means the result is\n     * complete, so the stream closes with reason `completed` instead of `truncated`.\n     *\n     * @example\n     * terminalEvents: ['verdict']\n     */\n    terminalEvents?: string[];\n\n    /**\n     * Callback when the stream stops, for any reason. Called once per `connect()`.\n     *\n     * On the EventSource transport it is only called for `disconnect()`, because EventSource\n     * cannot tell a finished server from a broken one.\n     */\n    onClose?: (client: SSEClient, result: SSECloseResult) => void;\n\n    /**\n     * Callback when connection is established.\n     */\n    onConnect?: (client: SSEClient) => void;\n\n    /**\n     * Callback when an error occurs.\n     * On the EventSource transport the browser reconnects afterwards.\n     * On the fetch transport the argument is an SSEErrorEvent and there is no reconnect.\n     */\n    onError?: (client: SSEClient, error: Event) => void;\n}\n\n/**\n * Server-Sent Events client that dispatches received events as DOM events.\n *\n * @example\n * const sse = new SSEClient('/api/events', {\n *     target: '#notifications',\n *     eventTypes: ['notification', 'alert']\n * });\n *\n * sse.connect();\n *\n * document.querySelector('#notifications')\n *     .addEventListener('notification', (e: SSEDataEvent) => {\n *         showNotification(e.data);\n *     });\n *\n * sse.disconnect();\n *\n * @example\n * const sse = new SSEClient('/api/verdict', {\n *     method: 'POST',\n *     body: JSON.stringify({ matchId: 42 }),\n *     eventTypes: ['token', 'verdict'],\n *     terminalEvents: ['verdict'],\n *     onClose: (client, result) => {\n *         if (result.reason === 'truncated') {\n *             showRetryButton();\n *         }\n *     }\n * });\n *\n * sse.connect();\n */\nexport class SSEClient {\n    private eventSource?: EventSource;\n    private abortController?: AbortController;\n    private streaming = false;\n    private target: Element | Document;\n\n    /**\n     * Whether the client is currently connected.\n     */\n    get connected(): boolean {\n        if (this.eventSource) {\n            return this.eventSource.readyState === EventSource.OPEN;\n        }\n\n        return this.streaming;\n    }\n\n    constructor(\n        private url: string,\n        private options?: SSEOptions\n    ) {\n        this.target = this.resolveTarget(options?.target);\n    }\n\n    /**\n     * Establish connection to the SSE endpoint.\n     *\n     * Can be called again after the stream has closed, which is how you retry a truncated result.\n     */\n    connect(): void {\n        if (this.eventSource || this.abortController) {\n            return;\n        }\n\n        if (!this.usesFetchTransport()) {\n            this.connectViaEventSource();\n            return;\n        }\n\n        if (this.options?.autoReconnect === true) {\n            const error = reportError(\n                'SSEClient: autoReconnect is not available when you set method, body, headers or signal, because a request that sends data is not always safe to repeat.',\n                { url: this.url }\n            );\n            if (error) {\n                throw error;\n            }\n        }\n\n        this.connectViaFetch();\n    }\n\n    /**\n     * Close the connection. Closes with reason `aborted`.\n     */\n    disconnect(): void {\n        if (this.abortController) {\n            this.abortController.abort();\n            return;\n        }\n\n        if (this.eventSource) {\n            this.eventSource.close();\n            this.eventSource = undefined;\n            this.options?.onClose?.(this, { reason: 'aborted' });\n        }\n    }\n\n    private usesFetchTransport(): boolean {\n        const options = this.options;\n        if (!options) {\n            return false;\n        }\n\n        return (\n            options.method !== undefined ||\n            options.body !== undefined ||\n            options.headers !== undefined ||\n            options.signal !== undefined ||\n            options.autoReconnect === false\n        );\n    }\n\n    private connectViaEventSource(): void {\n        const eventSource = new EventSource(this.url, {\n            withCredentials: this.options?.withCredentials ?? false\n        });\n\n        this.eventSource = eventSource;\n\n        eventSource.onopen = () => {\n            this.options?.onConnect?.(this);\n        };\n\n        eventSource.onerror = (error) => {\n            this.options?.onError?.(this, error);\n        };\n\n        if (this.options?.eventTypes && this.options.eventTypes.length > 0) {\n            for (const eventType of this.options.eventTypes) {\n                eventSource.addEventListener(eventType, (e: MessageEvent) => {\n                    this.dispatchEvent(eventType, e.data);\n                });\n            }\n        } else {\n            eventSource.onmessage = (e: MessageEvent) => {\n                this.dispatchEvent('message', e.data);\n            };\n        }\n    }\n\n    private connectViaFetch(): void {\n        const controller = new AbortController();\n        this.abortController = controller;\n\n        this.streamResponse(controller).catch((error) => {\n            this.streaming = false;\n            this.abortController = undefined;\n            reportError('SSEClient: unhandled failure while reading the event stream.', {\n                url: this.url,\n                error\n            });\n        });\n    }\n\n    private async streamResponse(controller: AbortController): Promise<void> {\n        const options = this.options ?? {};\n        this.bridgeSignal(options.signal, controller);\n\n        let response: Response;\n        try {\n            response = await currentFetch()(resolveUrl(this.url), {\n                method: options.method ?? 'GET',\n                body: options.body,\n                headers: this.buildHeaders(options.headers),\n                signal: controller.signal,\n                credentials: options.withCredentials ? 'include' : 'same-origin'\n            });\n        } catch (error) {\n            this.reportFailure(error, controller);\n            return;\n        }\n\n        if (!response.ok) {\n            const httpResponse = await this.readErrorResponse(response);\n            const error = new HttpError(httpResponse);\n            options.onError?.(this, new SSEErrorEvent(error, httpResponse));\n            this.finish({ reason: 'failed', error, response: httpResponse });\n            return;\n        }\n\n        this.streaming = true;\n        options.onConnect?.(this);\n\n        let lastEventName: string | undefined;\n        let sawTerminalEvent = false;\n\n        try {\n            const parser = new SseFrameParser();\n            const decoder = new TextDecoder();\n            const reader = response.body?.getReader();\n\n            while (reader) {\n                const { done, value } = await reader.read();\n                if (done) {\n                    break;\n                }\n\n                for (const frame of parser.push(decoder.decode(value, { stream: true }))) {\n                    lastEventName = frame.event;\n\n                    if (options.terminalEvents?.includes(frame.event)) {\n                        sawTerminalEvent = true;\n                    }\n\n                    if (this.acceptsEvent(frame.event)) {\n                        this.dispatchEvent(frame.event, frame.data);\n                    }\n                }\n            }\n        } catch (error) {\n            this.reportFailure(error, controller, lastEventName);\n            return;\n        }\n\n        if (controller.signal.aborted) {\n            this.finish({ reason: 'aborted', lastEventName });\n            return;\n        }\n\n        const expectsTerminalEvent = (options.terminalEvents?.length ?? 0) > 0;\n        this.finish({\n            reason: expectsTerminalEvent && !sawTerminalEvent ? 'truncated' : 'completed',\n            lastEventName\n        });\n    }\n\n    private bridgeSignal(signal: AbortSignal | undefined, controller: AbortController): void {\n        if (!signal) {\n            return;\n        }\n\n        if (signal.aborted) {\n            controller.abort();\n            return;\n        }\n\n        signal.addEventListener('abort', () => controller.abort(), { once: true });\n    }\n\n    private buildHeaders(custom?: Record<string, string>): Headers {\n        const headers = new Headers({ Accept: 'text/event-stream' });\n\n        for (const name in custom) {\n            headers.set(name, custom[name]);\n        }\n\n        const token = bearerToken();\n        if (token && !headers.get('Authorization')) {\n            headers.set('Authorization', 'Bearer ' + token);\n        }\n\n        return headers;\n    }\n\n    private async readErrorResponse(response: Response): Promise<HttpResponse> {\n        return {\n            statusCode: response.status,\n            statusReason: response.statusText,\n            success: false,\n            contentType: response.headers.get('content-type'),\n            body: await response.text(),\n            charset: response.headers.get('charset'),\n\n            as() {\n                throw new Error('No response received');\n            }\n        };\n    }\n\n    private reportFailure(\n        error: unknown,\n        controller: AbortController,\n        lastEventName?: string\n    ): void {\n        if (controller.signal.aborted) {\n            this.finish({ reason: 'aborted', lastEventName });\n            return;\n        }\n\n        const failure = error instanceof Error ? error : new Error(String(error));\n        this.options?.onError?.(this, new SSEErrorEvent(failure));\n        this.finish({ reason: 'failed', error: failure, lastEventName });\n    }\n\n    private finish(result: SSECloseResult): void {\n        this.streaming = false;\n        this.abortController = undefined;\n        this.options?.onClose?.(this, result);\n    }\n\n    private acceptsEvent(eventName: string): boolean {\n        const eventTypes = this.options?.eventTypes;\n        if (eventTypes && eventTypes.length > 0) {\n            return eventTypes.includes(eventName);\n        }\n\n        return eventName === 'message';\n    }\n\n    private resolveTarget(target?: string | Element): Element | Document {\n        if (!target) {\n            return document;\n        }\n        if (typeof target === 'string') {\n            const element = document.querySelector(target);\n            if (!element) {\n                throw new Error(`SSEClient: Target element not found: ${target}`);\n            }\n            return element;\n        }\n        return target;\n    }\n\n    private dispatchEvent(eventName: string, rawData: string): void {\n        let data: unknown;\n\n        if (rawData.length > 0 && (rawData[0] === '{' || rawData[0] === '[' || rawData[0] === '\"')) {\n            try {\n                data = JSON.parse(rawData);\n            } catch {\n                data = rawData;\n            }\n        } else {\n            data = rawData;\n        }\n\n        const event = this.options?.eventFactory\n            ? this.options.eventFactory(eventName, data)\n            : new SSEDataEvent(eventName, data);\n\n        this.target.dispatchEvent(event);\n    }\n}\n", "/**\r\n * Resolves a deeply nested value from an object using a path array.\r\n * Safely navigates through the object tree, returning undefined if any\r\n * segment in the path is null or undefined.\r\n *\r\n * Used internally by template engines to access data properties,\r\n * but also useful for general-purpose deep property access.\r\n *\r\n * @param path - Array of property names forming the path to the value\r\n * @param context - The object to resolve the value from\r\n * @returns The resolved value, or undefined if path cannot be resolved\r\n *\r\n * @example\r\n * // Access nested property\r\n * const user = { address: { city: 'Stockholm' } };\r\n * const city = resolveValue(['address', 'city'], user);\r\n * // Returns: 'Stockholm'\r\n *\r\n * @example\r\n * // Safe access with missing properties\r\n * const data = { user: null };\r\n * const name = resolveValue(['user', 'name'], data);\r\n * // Returns: undefined (doesn't throw)\r\n *\r\n * @example\r\n * // Use with template expression paths\r\n * const path = 'user.profile.avatar'.split('.');\r\n * const avatar = resolveValue(path, context);\r\n */\r\nexport function resolveValue(\r\n    path: string[],\r\n    context: Record<string, any>\r\n): any | undefined {\r\n    let value = context;\r\n\r\n    for (const key of path) {\r\n        if (value === undefined || value === null) {\r\n            return undefined;\r\n        }\r\n\r\n        value = value[key];\r\n    }\r\n\r\n    return value !== undefined && value !== null ? value : undefined;\r\n}\r\n  "],
  "mappings": "4yEAAA,IAAAA,GAAAC,GAAA,CAAAC,GAAAC,KAAA,CAAAA,GAAA,SACI,SAAY,eACZ,MAAS,8CACb,ICHA,IAAAC,GAAAC,GAAA,CAAAC,GAAAC,KAAA,CAAAA,GAAA,SACI,MAAS,OACT,UAAa,UACb,QAAW,2DACX,OAAU,kDACd,ICLA,IAAAC,GAAAC,GAAA,CAAAC,GAAAC,KAAA,CAAAA,GAAA,SACI,SAAY,qCACZ,MAAS,4DACT,OAAU,sBACd,IC6BO,IAAMC,EAAN,cAAyB,KAAM,CAClC,YACIC,EACOC,EACT,CACE,MAAMD,CAAO,EAFN,aAAAC,CAGX,CACJ,EAKIC,GAA+B,KAiB5B,SAASC,GAAQC,EAAkB,CACtCF,GAAUE,CACd,CAmBO,SAASC,EAAYL,EAAiBC,EAAqD,CAC9F,IAAMK,EAAQ,IAAIP,EAAWC,EAASC,CAAO,EAC7C,GAAIC,GAAS,CACT,IAAIK,EAAa,GAKjB,GADAL,GAAQI,EAHkB,CACtB,UAAW,CAAEC,EAAa,EAAM,CACpC,CACkB,EACdA,EACA,OAAO,IAEf,CACA,OAAOD,CACX,CAoBO,SAASE,GACZJ,EACwB,CACxB,OAAO,YAAwBK,EAAa,CACxCL,EAAG,KAAK,KAAM,GAAGK,CAAI,EAAE,MAAOC,GAAmB,CAC7C,IAAMJ,EAAQD,EAAY,wBAAyB,CAAE,MAAAK,CAAM,CAAC,EAC5D,GAAIJ,EAAO,MAAMA,CACrB,CAAC,CACL,CACJ,CC1HO,IAAMK,GAAN,KAAc,CAcjB,YAAmBC,EAAkBC,EAA4B,CAA9C,WAAAD,EAAkB,oBAAAC,EAVrC,KAAO,KAAuB,KAI9B,KAAO,KAAuB,IAMoC,CAMlE,QAAS,CACD,KAAK,OAAM,KAAK,KAAK,KAAO,KAAK,MACjC,KAAK,OAAM,KAAK,KAAK,KAAO,KAAK,MACrC,KAAK,eAAe,CACxB,CACJ,EAKaC,GAAN,KAAoB,CAApB,cACH,KAAQ,OAAyB,KACjC,KAAQ,MAAwB,KAChC,KAAQ,QAAU,EAMlB,SAASF,EAAU,CACf,IAAMG,EAAU,KAAK,WAAWH,CAAK,EAChC,KAAK,QAING,EAAQ,KAAO,KAAK,OACpB,KAAK,OAAO,KAAOA,EACnB,KAAK,OAASA,IALd,KAAK,OAASA,EACd,KAAK,MAAQ,KAAK,QAOtB,KAAK,SACT,CAMA,QAAQH,EAAU,CACd,IAAMG,EAAU,KAAK,WAAWH,CAAK,EAChC,KAAK,OAING,EAAQ,KAAO,KAAK,MACpB,KAAK,MAAM,KAAOA,EAClB,KAAK,MAAQA,IALb,KAAK,OAASA,EACd,KAAK,MAAQA,GAOjB,KAAK,SACT,CAEQ,WAAWH,EAAmB,CAClC,IAAII,EACJ,OAAAA,EAAO,IAAIL,GAAKC,EAAO,IAAM,CACrB,KAAK,SAAWI,IAAM,KAAK,OAASA,EAAK,MACzC,KAAK,QAAUA,IAAM,KAAK,MAAQA,EAAK,MAC3C,KAAK,SACT,CAAC,EACMA,CACX,CAMA,aAAiB,CACb,GAAI,CAAC,KAAK,OACN,MAAM,IAAI,MAAM,oBAAoB,EAGxC,IAAMJ,EAAQ,KAAK,OAAO,MAC1B,YAAK,OAAS,KAAK,OAAO,KACrB,KAAK,SAAQ,KAAK,MAAQ,MAC/B,KAAK,UACEA,CACX,CAMA,YAAgB,CACZ,GAAI,CAAC,KAAK,MACN,MAAM,IAAI,MAAM,oBAAoB,EAGxC,IAAMA,EAAQ,KAAK,MAAM,MACzB,YAAK,MAAQ,KAAK,MAAM,KACnB,KAAK,QAAO,KAAK,OAAS,MAC/B,KAAK,UACEA,CACX,CAOA,IAAI,QAAiB,CACjB,OAAO,KAAK,OAChB,CAKA,IAAI,OAAwB,CACxB,OAAO,KAAK,MAChB,CAKA,IAAI,YAA4B,CAC5B,OAAO,KAAK,QAAQ,KACxB,CAKA,IAAI,MAAuB,CACvB,OAAO,KAAK,KAChB,CAKA,IAAI,WAA2B,CAC3B,OAAO,KAAK,OAAO,KACvB,CACJ,ECxJO,IAAMK,GAAN,cAAgC,KAAM,CAC3C,YAAmBC,EAAc,CAC/B,MAAM,eAAgB,CACpB,QAAS,GACT,SAAU,EACZ,CAAC,EAJgB,UAAAA,CAKnB,CACF,EAQaC,GAAN,KAAY,CAMjB,YAAYC,EAAwBC,EAAoBC,EAAkB,CAF1E,KAAQ,YAAsB,EAG5B,KAAK,UAAYF,EACjB,KAAK,WAAaC,EAClB,KAAK,SAAWC,EAEhB,KAAK,OAAO,CACd,CAEQ,QAAS,CACf,KAAK,UAAU,UAAY,GAE3B,IAAMC,EAAY,KAAK,IAAI,EAAG,KAAK,KAAK,KAAK,WAAa,KAAK,QAAQ,CAAC,EAElEC,EAAe,CAACC,EAAeP,EAAcQ,EAAoB,KAAU,CAC/E,IAAMC,EAAM,SAAS,cAAc,QAAQ,EAC3C,OAAAA,EAAI,YAAcF,EAClBE,EAAI,SAAWD,EACfC,EAAI,iBAAiB,QAAS,IAAM,KAAK,WAAWT,CAAI,CAAC,EAClDS,CACT,EAEA,KAAK,UAAU,YACbH,EAAa,WAAY,KAAK,YAAc,EAAG,KAAK,cAAgB,CAAC,CACvE,EAEA,QAASI,EAAI,EAAGA,GAAKL,EAAWK,IAAK,CACnC,IAAMD,EAAMH,EAAaI,EAAE,SAAS,EAAGA,CAAC,EACpCA,IAAM,KAAK,aACbD,EAAI,UAAU,IAAI,UAAU,EAE9B,KAAK,UAAU,YAAYA,CAAG,CAChC,CAEA,KAAK,UAAU,YACbH,EAAa,OAAQ,KAAK,YAAc,EAAG,KAAK,cAAgBD,CAAS,CAC3E,CACF,CAEQ,WAAWL,EAAc,CAC/B,IAAMK,EAAY,KAAK,IAAI,EAAG,KAAK,KAAK,KAAK,WAAa,KAAK,QAAQ,CAAC,EACpEL,EAAO,GAAKA,EAAOK,GAAaL,IAAS,KAAK,cAElD,KAAK,YAAcA,EACnB,KAAK,OAAO,EAEZ,KAAK,UAAU,cAAc,IAAID,GAAkB,KAAK,WAAW,CAAC,EACtE,CAEO,OAAOI,EAAoB,CAChC,KAAK,WAAaA,EAClB,IAAME,EAAY,KAAK,IAAI,EAAG,KAAK,KAAK,KAAK,WAAa,KAAK,QAAQ,CAAC,EACpE,KAAK,YAAcA,IACrB,KAAK,YAAcA,GAErB,KAAK,OAAO,CACd,CAEO,gBAAyB,CAC9B,OAAO,KAAK,WACd,CACF,ECxDA,SAASM,GAAaC,EAAqC,CACvD,IAAMC,EAAKD,EAAQ,aAAa,IAAI,EACpC,GAAIC,EAAI,CACJ,IAAMC,EAAOF,EAAQ,QAAQ,MAAM,EACnC,GAAIE,EAAM,CACN,IAAMC,EAAQD,EAAK,cAAc,cAAcD,CAAE,IAAI,EACrD,GAAIE,EACA,OAAOA,EAAM,aAAa,KAAK,GAAK,IAE5C,CACJ,CAEA,OAAO,IACX,CAiDO,IAAMC,GAAN,KAAoB,CAGvB,YACYF,EACAG,EACV,CAFU,UAAAH,EACA,aAAAG,EAER,GAAI,CAAC,KAAK,KACN,MAAM,IAAI,MAAM,yBAAyB,EAG7C,KAAK,KAAK,iBAAiB,SAAWC,GAAU,CAW5C,IATID,GAAS,gBACT,KAAK,SAAS,gBAAkB,OAEhCC,EAAM,eAAe,EAErB,KAAK,SAAS,cACd,KAAK,QAAQ,aAAaJ,CAAI,EAG9B,KAAK,aAAa,EAClB,GAAI,CACA,IAAMK,EAAS,KAAK,SAAS,gBAAgB,KAAK,IAAI,EAClDA,aAAkB,SAClBA,EAAO,MAAOC,GAAU,CACpB,IAAMC,EAAQC,EAAY,wBAAyB,CAAE,MAAAF,CAAM,CAAC,EAC5D,GAAIC,EAAO,MAAMA,CACrB,CAAC,CAET,OAASD,EAAO,CACZ,IAAMC,EAAQC,EAAY,wBAAyB,CAAE,MAAAF,CAAM,CAAC,EAC5D,GAAIC,EAAO,MAAMA,CACrB,MAEIJ,GAAS,yBAA2B,IACpCC,EAAM,eAAe,CAGjC,CAAC,EAEGD,GAAS,cACTH,EAAK,iBAAiB,QAAS,IAAuB,CAClD,KAAK,aAAa,CACtB,CAAC,CAET,CAQO,cAAwB,CAC3B,IAAMS,EAAe,MAAM,KACvB,KAAK,KAAK,iBAAiB,uBAAuB,CACtD,EACIC,EAAc,GAElB,GAAI,KAAK,SAAS,aAAe,GAC7B,OAAI,KAAK,KAAK,cAAc,EACjB,IAGX,KAAK,KAAK,eAAe,EACzB,KAAK,uBAAuB,EACrB,IAGX,IAAMC,EAA0B,CAAC,EAEjC,OAAAF,EAAa,QAASX,GAAY,CAC9B,GAAI,CAACA,EAAQ,cAAc,EAAG,CAC1BY,EAAc,GACd,IAAME,EACFf,GAAa,KAAK,KAAMC,CAAO,GAC/BA,EAAQ,MACR,gBACJa,EAAc,KACV,GAAGC,CAAS,KAAKd,EAAQ,iBAAiB,EAC9C,CACJ,CACJ,CAAC,EAEIY,EAID,KAAK,kBAAkB,GAHvB,KAAK,oBAAoBC,CAAa,EACtC,KAAK,uBAAuB,GAKzBD,CACX,CAOO,oBAAoBG,EAAoB,CAC3C,KAAK,kBAAkB,EAClB,KAAK,cACN,KAAK,mBAAmB,EAG5B,IAAMC,EAAY,KAAK,aAAc,cAAc,IAAI,EACvDD,EAAS,QAASE,GAAY,CAC1B,IAAMC,EAAW,SAAS,cAAc,IAAI,EAC5CA,EAAS,YAAcD,EACvBD,EAAU,YAAYE,CAAQ,CAClC,CAAC,CACL,CAEQ,oBAAqB,CACzB,IAAMC,EAAe,SAAS,cAAc,KAAK,EACjDA,EAAa,UAAY,gBACzBA,EAAa,MAAM,MAAQ,MAC3BA,EAAa,aAAa,OAAQ,OAAO,EACzCA,EAAa,aAAa,YAAa,WAAW,EAClDA,EAAa,aAAa,cAAe,MAAM,EAC/C,KAAK,aAAeA,EAEpB,IAAMH,EAAY,SAAS,cAAc,IAAI,EAC7C,KAAK,aAAa,YAAYA,CAAS,EAEvC,KAAK,KAAK,QAAQG,CAAY,CAClC,CAOO,kBAAkBL,EAAmBG,EAAiB,CACpD,KAAK,cACN,KAAK,mBAAmB,EAE5B,IAAMD,EAAY,KAAK,aAAc,cAAc,IAAI,EACjDE,EAAW,SAAS,cAAc,IAAI,EAC5CA,EAAS,YAAc,GAAGJ,CAAS,KAAKG,CAAO,GAC/CD,EAAU,YAAYE,CAAQ,CAClC,CAKO,mBAAoB,CACvB,GAAI,KAAK,aAAa,CAClB,IAAME,EAAK,KAAK,aAAa,cAAc,IAAI,EAC3CA,IAAIA,EAAG,UAAY,GAC3B,CACJ,CAEQ,wBAAyB,CAC7B,IAAMC,EAAsB,KAAK,KAAK,cAAc,UAAU,EAE1DA,aAA+B,aAC/B,SAAS,gBAAkBA,GAE3BA,EAAoB,MAAM,CAElC,CAkBA,OAAc,SAASrB,EAAuC,CAC1D,GAAIA,EAAQ,eAAe,SAAW,OAClC,OAAwBA,EAAQ,cAEhC,QAASsB,EAAI,EAAGA,EAAItB,EAAQ,SAAS,OAAQsB,IAAK,CAC9C,IAAMC,EAAQvB,EAAQ,SAASsB,CAAC,EAChC,GAAIC,EAAM,SAAW,OACjB,OAAwBA,CAEhC,CAGJ,MAAM,IAAI,MACN,qDACIvB,EAAQ,YAAY,IAC5B,CACJ,CACJ,ECxQA,IAAMwB,GAAmB,IAAI,IAa7B,SAASC,GAAcC,EAAkC,CACrD,OAAKF,GAAiB,IAAIE,CAAM,GAC5BF,GAAiB,IAAIE,EAAQ,IAAI,KAAK,YAAYA,CAAM,CAAC,EAEtDF,GAAiB,IAAIE,CAAM,CACtC,CAEA,SAASC,GAAYC,EAAmB,CACpC,OAAOA,EAAE,QAAQ,sBAAuB,MAAM,CAClD,CAmBO,SAASC,GACZC,EACAC,EACAL,EAAiB,KACX,CACN,OAAOI,EAAQ,QACX,2DACA,CAACE,EAAGC,EAAKC,EAAMC,IAAmB,CAC9B,IAAMC,EAAQL,IAASE,CAAG,EAE1B,GAAIC,IAAS,SAAU,CACnB,IAAMG,EAAQ,IAAI,OACd,IAAIV,GAAY,OAAOS,CAAK,CAAC,CAAC,oBAClC,EAAE,KAAKD,CAAc,EACrB,GAAIE,EACA,OAAOA,EAAM,CAAC,EACT,QAAQ,IAAIJ,CAAG,IAAK,OAAOG,CAAK,CAAC,EACjC,QAAQ,IAAK,OAAOA,CAAK,CAAC,EAInC,IAAME,EADQb,GAAcC,CAAM,EACX,OAAOU,CAAK,EAC7BG,EACF,IAAI,OAAO,GAAGD,CAAQ,oBAAoB,EAAE,KAAKH,CAAc,GAC/D,IAAI,OAAO,yBAAyB,EAAE,KAAKA,CAAc,EAC7D,OAAII,EACOA,EAAM,CAAC,EACT,QAAQ,IAAIN,CAAG,IAAK,OAAOG,CAAK,CAAC,EACjC,QAAQ,IAAK,OAAOA,CAAK,CAAC,EAE5B,OAAOA,CAAK,CACvB,CAEA,GAAIF,IAAS,SAAU,CACnB,IAAMM,EAAUb,GAAY,OAAOS,CAAK,CAAC,EACnCG,EACF,IAAI,OAAO,MAAMC,CAAO,oBAAoB,EAAE,KAAKL,CAAc,GACjE,IAAI,OAAO,4BAA4B,EAAE,KAAKA,CAAc,EAChE,OAAOI,EAAQA,EAAM,CAAC,EAAI,OAAOH,CAAK,CAC1C,CAEA,OAAOA,IAAU,OAAY,OAAOA,CAAK,EAAI,IAAIH,CAAG,GACxD,CACJ,CACJ,CAMO,IAAIQ,GAA8BZ,GC/EzC,IAAMa,GAA6D,CAAC,EAK7D,SAASC,GAAgBC,EAAwB,CACpD,OAAOA,EAAO,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC,CAC5C,CAwBO,SAASC,EACZC,EACAC,EACAC,EACI,CACJ,IAAMC,EAAaC,GAAgBJ,CAAM,EACpCK,GAAUF,CAAU,IAAGE,GAAUF,CAAU,EAAI,CAAC,GACrDE,GAAUF,CAAU,EAAEF,CAAS,EAAIC,CACvC,CCxEA,IAAAI,GAAA,CACI,SAAY,iBACZ,MAAS,+CACb,ECHA,IAAAC,GAAA,CACI,MAAS,QACT,UAAa,YACb,QAAW,sDACX,OAAU,oDACd,ECLA,IAAAC,GAAA,CACI,SAAY,0BACZ,MAAS,wDACT,OAAU,2BACd,ECgBO,SAASC,IAAkC,CAC9CC,EAAkB,KAAM,WAAYC,EAAQ,EAC5CD,EAAkB,KAAM,UAAWE,EAAO,EAC1CF,EAAkB,KAAM,eAAgBG,EAAY,EAEpDH,EAAkB,KAAM,WAAY,IAAM,oCAAoC,EAC9EA,EAAkB,KAAM,UAAW,IAAM,oCAAmC,EAC5EA,EAAkB,KAAM,eAAgB,IAAM,oCAAwC,CAC1F,CCsCA,IAAMI,GAAyB,KAC3BC,GAAwBD,GAE5B,IAAME,GAA6B,CAAC,EAChCC,GAAmD,KAEvDC,GAA0B,EA6GnB,SAASC,EACZC,EACAC,EACAC,EACM,CACN,GAAM,CAACC,EAAWC,CAAG,EAAIJ,EAAQ,SAAS,GAAG,EACvCA,EAAQ,MAAM,GAAG,EACjB,CAAC,WAAYA,CAAO,EACpBK,EAAUC,GAAaH,CAAS,IAAIC,CAAG,EAE7C,OAAKC,EAMEE,GAAOF,EAASJ,EAAQC,GAAS,UAAYF,CAAO,GALnDQ,IAAgBA,GAAeJ,EAAKD,EAAWM,EAAa,EAC5DP,GAAS,WAAa,OAAkBF,EACrCO,GAAOL,EAAQ,SAAUD,EAAQC,EAAQ,QAAQ,EAIhE,CAEA,SAASK,GAAOF,EAAiBJ,EAAyCS,EAAyB,CAC/F,GAAI,CACA,OAAOC,GAAUN,EAASJ,EAAQQ,EAAa,CACnD,MAAQ,CACJ,OAAOC,CACX,CACJ,CAOO,SAASE,GAA2B,CACvC,OAAOH,EACX,CCtKO,SAASI,GACZC,EACAC,EACAC,EAGI,CAAC,EACJ,CACD,IAAMC,EAAeH,EAAK,iBAAiB,yBAAyB,EAuBpE,GArBAG,EAAa,QAASC,GAAY,CAE9B,GADI,CAACA,EAAQ,aAAa,MAAM,GAC5BC,GAAYD,EAAS,UAAU,EAAG,OAEtC,IAAME,EAAeF,EAAQ,aAAa,MAAM,EAEhD,GAAI,EAAEE,KAAgBL,GAAW,CAC7B,GAAIC,EAAQ,uBACR,MAAM,IAAI,MACN,eAAeI,CAAY,8CAC/B,EAEJ,MACJ,CAEA,IAAMC,EAAQC,GAAiBJ,CAAO,EAClCG,IAAUE,KAEbR,EAAqCK,CAAY,EAAIC,EAC1D,CAAC,EAEGL,EAAQ,oBAAqB,CAC7B,IAAMQ,EAAiB,IAAI,IAC3BP,EAAa,QAASC,GAAY,CAC1BA,EAAQ,aAAa,MAAM,GAC3BM,EAAe,IAAIN,EAAQ,aAAa,MAAM,CAAE,CAExD,CAAC,EAED,QAAWO,KAAQV,EACf,GACI,OAAOA,EAASU,CAAI,GAAM,YAC1B,OAAO,UAAU,eAAe,KAAKV,EAAUU,CAAI,GACnD,CAACD,EAAe,IAAIC,CAAI,EAExB,MAAM,IAAI,MACN,mBAAmBA,CAAI,8BAC3B,CAGZ,CAEA,OAAOV,CACX,CAiCO,SAASW,GAAiBR,EAAqC,CAClE,IAAMS,EAAWT,EAAQ,aAAa,WAAW,EACjD,OAAIS,EACOC,GAA4BD,CAAQ,EAG3CT,aAAmB,iBACZW,GAA6BX,EAAQ,IAAiB,EAI7D,YAAaA,GAAW,OAAQA,EAAgB,SAAY,UACrDY,GAGHC,GAAQA,CACpB,CAuCO,SAASC,GAAsClB,EAAyB,CAC3E,IAAMmB,EAAgC,CAAC,EACjCC,EAAW,IAAI,SAASpB,CAAI,EAC5BqB,EAAO,IAAI,IAEjBD,EAAS,QAAQ,CAACE,EAAGC,IAAS,CAC1B,GAAIF,EAAK,IAAIE,CAAI,EAAG,OACpBF,EAAK,IAAIE,CAAI,EAEb,IAAMC,EAASJ,EAAS,OAAOG,CAAI,EAC7BnB,EAAUJ,EAAK,SAAS,UAAUuB,CAAI,EACtCE,EAAYrB,EAAUQ,GAAiBR,CAAsB,EAAKsB,GAAcA,EAEtF,GAAIF,EAAO,SAAW,EAAG,CACrB,IAAME,EAAIF,EAAO,CAAC,EAClBL,EAAKI,CAAI,EAAI,OAAOG,GAAM,SAAWD,EAAUC,CAAC,EAAIA,CACxD,MACIP,EAAKI,CAAI,EAAIC,EAAO,IAAIE,GAAK,OAAOA,GAAM,SAAWD,EAAUC,CAAC,EAAIA,CAAC,CAE7E,CAAC,EAED,QAASC,EAAI,EAAGA,EAAI3B,EAAK,SAAS,OAAQ2B,IAAK,CAC3C,IAAMC,EAAK5B,EAAK,SAAS2B,CAAC,EACtBC,EAAG,OAAS,YAAcA,EAAG,MAAQ,CAACP,EAAK,IAAIO,EAAG,IAAI,IACtDP,EAAK,IAAIO,EAAG,IAAI,EAChBT,EAAKS,EAAG,IAAI,EAAI,GAExB,CAEA,OAAOT,CACX,CAoCO,SAASH,GAAiBT,EAAqC,CAClE,GAAI,CAACA,GAASA,GAAS,GACnB,OAGJ,IAAMsB,EAAQtB,EAAM,YAAY,EAEhC,GAAIsB,IAAU,QAAUA,IAAU,MAAQ,OAAOtB,CAAK,EAAI,EACtD,MAAO,GAGX,GAAIsB,IAAU,SAAWA,IAAU,OAAS,OAAOtB,CAAK,GAAK,EACzD,MAAO,GAGX,MAAM,IAAI,MAAM,4BAA8BA,EAAQ,eAAe,CACzE,CASO,SAASuB,GAAgBvB,EAAoC,CAChE,GAAI,CAACA,GAASA,GAAS,GACnB,OAEJ,IAAMwB,EAAK,OAAOxB,CAAK,EACvB,GAAI,CAAC,MAAMwB,CAAE,EACT,OAAOA,EAEX,MAAM,IAAI,MAAM,4BAA8BxB,EAAQ,cAAc,CACxE,CAWA,SAASyB,GAAmBC,EAA8C,CAEtE,OADc,IAAI,KAAK,eAAeA,CAAM,EAAE,cAAc,IAAI,KAAK,KAAM,EAAG,EAAE,CAAC,EAE5E,OAAQC,GACLA,EAAE,OAAS,OAASA,EAAE,OAAS,SAAWA,EAAE,OAAS,MAAM,EAC9D,IAAIA,GAAKA,EAAE,IAAI,CACxB,CAqBO,SAASC,GAAc5B,EAAiC,CAC3D,GAAI,CAACA,GAASA,IAAU,GAAI,OAE5B,GAAI,0BAA0B,KAAKA,CAAK,EAAG,CACvC,IAAM6B,EAAO,IAAI,KAAK7B,CAAK,EAC3B,GAAI,CAAC,MAAM6B,EAAK,QAAQ,CAAC,EAAG,OAAOA,CACvC,CAEA,IAAMC,EAAe9B,EAAM,MAAM,WAAW,EAC5C,GAAI8B,EAAa,QAAU,GAAKA,EAAa,MAAMH,GAAK,QAAQ,KAAKA,CAAC,CAAC,EAAG,CACtE,IAAMD,EAASK,EAAiB,EAC1BC,EAAQP,GAAmBC,CAAM,EACjCO,EAAiC,CAAC,EAKxC,GAJAD,EAAM,QAAQ,CAACE,EAAMd,IAAM,CACvBa,EAAOC,CAAI,EAAI,SAASJ,EAAaV,CAAC,EAAG,EAAE,CAC/C,CAAC,EAEGa,EAAO,OAAS,QAAaA,EAAO,QAAU,QAAaA,EAAO,MAAQ,OAAW,CACjFA,EAAO,KAAO,MAAKA,EAAO,MAAQ,KACtC,IAAMJ,EAAO,IAAI,KAAKI,EAAO,KAAMA,EAAO,MAAQ,EAAGA,EAAO,GAAG,EAC/D,GAAI,CAAC,MAAMJ,EAAK,QAAQ,CAAC,EAAG,OAAOA,CACvC,CACJ,CAEA,IAAMA,EAAO,IAAI,KAAK7B,CAAK,EAC3B,GAAI,MAAM6B,EAAK,QAAQ,CAAC,EACpB,MAAM,IAAI,MAAM,qBAAqB,EAEzC,OAAOA,CACX,CAQO,SAAStB,GAA4BD,EAAmC,CAC3E,OAAQA,EAAU,CACd,IAAK,UACD,OAAOG,GACX,IAAK,SACD,OAAOc,GACX,IAAK,OACD,OAAOK,GACX,IAAK,SACD,OAAQ5B,GAAW,CAACA,GAASA,GAAS,GAAK,OAAYA,EAC3D,QACI,MAAM,IAAI,MAAM,sBAAsBM,CAAQ,IAAI,CAC1D,CACJ,CASO,SAASE,GAA6B2B,EAAqC,CAC9E,OAAQA,EAAW,CACf,IAAK,WACD,OAAO1B,GAEX,IAAK,SACD,OAAOc,GAEX,IAAK,OACL,IAAK,iBACD,OAAOK,GAEX,IAAK,QACD,OAAQ5B,GAAU,CACd,GAAM,CAACoC,EAAMC,CAAK,EAAIrC,EAAM,MAAM,GAAG,EAAE,IAAI,MAAM,EACjD,OAAO,IAAI,KAAKoC,EAAMC,EAAQ,CAAC,CACnC,EAEJ,IAAK,OACD,OAAQrC,GAAU,CACd,GAAM,CAACoC,EAAME,CAAI,EAAItC,EAAM,MAAM,IAAI,EAAE,IAAI,MAAM,EACjD,MAAO,CAAE,KAAAoC,EAAM,KAAAE,CAAK,CACxB,EAEJ,IAAK,OACD,OAAQtC,GAAU,CACd,GAAM,CAACuC,EAAOC,EAASC,EAAU,CAAC,EAAIzC,EAAM,MAAM,GAAG,EAAE,IAAI,MAAM,EACjE,MAAO,CAAE,MAAAuC,EAAO,QAAAC,EAAS,QAAAC,CAAQ,CACrC,EAEJ,QACI,OAAQzC,GAAW,CAACA,GAASA,GAAS,GAAK,OAAYA,CAC/D,CACJ,CAEA,SAASF,GAAYD,EAAkBmB,EAAuB,CAC1D,IAAMK,EAAKxB,EACX,GAAImB,KAAQK,GAAM,OAAOA,EAAGL,CAAI,GAAM,UAAW,OAAOK,EAAGL,CAAI,EAC/D,IAAM0B,EAAO7C,EAAQ,aAAamB,CAAI,EACtC,OAAI0B,IAAS,KAAa,GACtBA,IAAS,IAAMA,EAAK,YAAY,IAAM,QAAUA,EAAK,YAAY,IAAM1B,CAE/E,CAEA,IAAMd,GAAO,OAAO,MAAM,EAE1B,SAASD,GAAiBJ,EAA2B,CACjD,IAAMwB,EAAKxB,EACLqC,EAAOb,EAAG,MAAQxB,EAAQ,aAAa,MAAM,GAAK,GAExD,GAAIqC,IAAS,WACT,OAAOpC,GAAYD,EAAS,SAAS,EAGzC,GAAIqC,IAAS,QACT,OAAKpC,GAAYD,EAAS,SAAS,EAC5BwB,EAAG,MADmCnB,GAIjD,GAAIgC,IAAS,SACT,OAAOb,EAAG,MAAQ,OAAOA,EAAG,KAAK,EAAI,KAGzC,GAAIa,IAAS,OACT,OAAOb,EAAG,MAAQ,IAAI,KAAKA,EAAG,KAAK,EAAI,KAG3C,GAAI,oBAAqBA,GAAMvB,GAAYD,EAAS,UAAU,EAC1D,OAAO,MAAM,KAAKwB,EAAG,eAAgD,EAChE,IAAKsB,GAAyBA,EAAE,KAAK,EAG9C,GAAI,UAAWtB,EACX,OAAOA,EAAG,KAIlB,CC/ZA,IAAMuB,GAAkD,IAAI,IAkBrD,SAASC,GAAkBC,EAAwBC,EAA4B,CAAC,EAAG,CACtF,OAAO,SAAUC,EAA2C,CACxDJ,GAAW,IAAIE,EAAgB,CAAE,UAAWE,EAAQ,gBAAAD,CAAgB,CAAC,CACzE,CACJ,CAQO,SAASE,GAAaC,EAAkD,CAC3E,OAAON,GAAW,IAAIM,CAAI,CAC9B,CAjFA,IAAAC,GAAAC,GAuFAD,GAAA,CAACN,GAAkB,UAAU,GACtB,IAAMQ,EAAN,MAAMA,CAAwC,CACjD,OAAO,OAAOC,EAAyC,CACnD,OAAOA,IAAS,WAAa,IAAID,EAAuB,IAC5D,CAEA,SAASE,EAAeC,EAA4B,CAC5CD,EAAM,KAAK,IAAM,IAIrBC,EAAQ,SAAS,KAAK,WAAW,CAAC,CACtC,CAEA,YAAqB,CACjB,OAAOC,EAAE,uBAAuB,CACpC,CACJ,EAhBOL,GAAAM,EAAA,MAAML,EAANM,EAAAP,GAAA,uBADPD,GACaE,GAANO,EAAAR,GAAA,EAAMC,GAAN,IAAMQ,GAANR,EAxFPS,GAAAV,GAiHAU,GAAA,CAACjB,GAAkB,QAAS,CAAC,QAAQ,CAAC,GAC/B,IAAMkB,EAAN,MAAMA,CAAqC,CAI9C,YAAYC,EAAaC,EAAa,CAHtC,gBACA,gBAGI,KAAK,IAAMD,EACX,KAAK,IAAMC,CACf,CAEA,OAAO,OAAOX,EAAsC,CAChD,IAAMY,EAAaZ,EAAK,MAAM,gDAAgD,EAC9E,GAAIY,EAAY,CACZ,GAAM,CAAC,CAAEF,EAAKC,CAAG,EAAIC,EACrB,OAAO,IAAIH,EAAgB,WAAWC,CAAG,EAAG,WAAWC,CAAG,CAAC,CAC/D,CACA,OAAO,IACX,CAEA,SAASV,EAAeC,EAA4B,CAChD,GAAID,EAAM,KAAK,IAAM,GAAI,OAEzB,IAAMY,EAAM,WAAWZ,CAAK,EACxB,CAAC,MAAMY,CAAG,GAAKA,GAAO,KAAK,KAAOA,GAAO,KAAK,KAIlDX,EAAQ,SAAS,KAAK,WAAWD,CAAK,CAAC,CAC3C,CAEA,WAAWa,EAAwB,CAC/B,OAAOX,EAAE,qBAAsB,CAAE,IAAK,KAAK,IAAK,IAAK,KAAK,IAAK,OAAAW,CAAO,CAAC,CAC3E,CACJ,EAhCOhB,GAAAM,EAAA,MAAMK,EAANJ,EAAAP,GAAA,oBADPU,GACaC,GAANH,EAAAR,GAAA,EAAMW,GAAN,IAAMM,GAANN,EAlHPO,GAAAlB,GAwJAkB,GAAA,CAACzB,GAAkB,SAAU,CAAC,QAAQ,CAAC,GAChC,IAAM0B,EAAN,MAAMA,CAAsC,CAC/C,OAAO,OAAOjB,EAAuC,CACjD,OAAOA,IAAS,SAAW,IAAIiB,EAAqB,IACxD,CAEA,SAAShB,EAAeC,EAA4B,CAC5C,QAAQ,KAAKD,CAAK,GAItBC,EAAQ,SAAS,KAAK,WAAW,CAAC,CACtC,CAEA,YAAqB,CACjB,OAAOC,EAAE,qBAAqB,CAClC,CACJ,EAhBOL,GAAAM,EAAA,MAAMa,EAANZ,EAAAP,GAAA,qBADPkB,GACaC,GAANX,EAAAR,GAAA,EAAMmB,GAAN,IAAMC,GAAND,ECtDA,SAASE,GAAYC,EAAuBC,EAAcC,EAAwB,CACjFA,GACgBF,EAAK,iBAAiB,cAAc,EAC5C,QAAQG,GAAU,CACtBC,GAAsBD,EAA6BD,CAA8B,CACrF,CAAC,EAGgBF,EAAK,iBAAiB,QAAQ,EAEtC,QAAQK,GAAW,CAE9B,IAAMC,EAAOD,EAAQ,aAAa,MAAM,EACxC,GAAI,CAACC,EAAM,OAGX,GAAIA,EAAK,SAAS,IAAI,EAAG,CACvB,IAAMC,EAAYD,EAAK,MAAM,EAAG,EAAE,EAC5BE,EAAaC,GAAsBR,EAAMM,CAAS,EAExD,GAAI,MAAM,QAAQC,CAAU,EAAG,CAC7B,IAAME,EAAKL,EACLM,EAAOD,EAAG,MAAQL,EAAQ,aAAa,MAAM,GAAK,GAExD,GAAIM,IAAS,YAAcA,IAAS,QAClCD,EAAG,QAAUF,EAAW,SAASE,EAAG,KAAK,UAChC,YAAaA,GAAME,GAASP,EAAS,UAAU,EACxDG,EAAW,QAAQK,GAAO,CACxB,IAAMC,EAAS,MAAM,KAAKJ,EAAG,OAA8B,EACxD,KAAMK,GAA2BA,EAAI,QAAU,OAAOF,CAAG,CAAC,EACzDC,IAASA,EAA6B,SAAW,GACvD,CAAC,UACQ,UAAWJ,EAAI,CACxB,IAAMM,EAAchB,EAAK,iBAAiB,UAAUM,CAAI,IAAI,EACtDW,EAAM,MAAM,KAAKD,CAAW,EAAE,QAAQX,CAAO,EAC/CY,GAAO,GAAKA,EAAMT,EAAW,SAC/BE,EAAG,MAAQ,OAAOF,EAAWS,CAAG,CAAC,EAErC,CACF,CACA,MACF,CAGA,IAAMC,EAAQT,GAAsBR,EAAMK,CAAI,EACnBY,GAAU,MAErCC,GAAgBd,EAASa,CAAK,CAChC,CAAC,CACH,CAEA,SAAST,GAAsBW,EAAaC,EAAmB,CAE7D,IAAMC,EAAW,CAAC,EACdC,EAAiB,GACjBC,EAAa,GAEjB,QAAS,EAAI,EAAG,EAAIH,EAAK,OAAQ,IAAK,CACpC,IAAMI,EAAOJ,EAAK,CAAC,EAEfI,IAAS,KAAO,CAACD,GACfD,IACFD,EAAS,KAAKC,CAAc,EAC5BA,EAAiB,IAEnBC,EAAa,GACbD,GAAkBE,GACTA,IAAS,KAAOD,GACzBD,GAAkBE,EAClBH,EAAS,KAAKC,CAAc,EAC5BA,EAAiB,GACjBC,EAAa,IACJC,IAAS,KAAO,CAACD,EACtBD,IACFD,EAAS,KAAKC,CAAc,EAC5BA,EAAiB,IAGnBA,GAAkBE,CAEtB,CAEA,OAAIF,GACFD,EAAS,KAAKC,CAAc,EAGvBD,EAAS,OAAY,CAACI,EAAQC,IAAY,CAC/C,GAAI,GAACD,GAAU,OAAOA,GAAW,UAGjC,IAAIC,EAAQ,WAAW,GAAG,GAAKA,EAAQ,SAAS,GAAG,EAAG,CACpD,IAAMC,EAAQD,EAAQ,MAAM,EAAG,EAAE,EACjC,OAAOD,EAAOE,CAAK,CACrB,CAEA,OAAOF,EAAOC,CAAO,EACvB,EAAGP,CAAG,CACR,CAEA,SAASD,GAAgBd,EAAkBa,EAAkB,CAC3D,IAAMR,EAAKL,EACLM,EAAOD,EAAG,MAAQL,EAAQ,aAAa,MAAM,GAAK,GAExD,GAAIM,IAAS,WACXD,EAAG,QAAU,EAAQQ,UACZP,IAAS,QAClBD,EAAG,QAAUA,EAAG,QAAU,OAAOQ,CAAK,UAC7BP,IAAS,QAAUO,aAAiB,KAC7CR,EAAG,MAAQQ,EAAM,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC,UAClCP,IAAS,kBAAoBO,aAAiB,KAAM,CAC7D,IAAMW,EAAOC,GAAc,OAAOA,CAAC,EAAE,SAAS,EAAG,GAAG,EACpDpB,EAAG,MAAQ,GAAGQ,EAAM,YAAY,CAAC,IAAIW,EAAIX,EAAM,SAAS,EAAI,CAAC,CAAC,IAAIW,EAAIX,EAAM,QAAQ,CAAC,CAAC,IAAIW,EAAIX,EAAM,SAAS,CAAC,CAAC,IAAIW,EAAIX,EAAM,WAAW,CAAC,CAAC,EAC5I,SAAW,YAAaR,GAAME,GAASP,EAAS,UAAU,GAAK,MAAM,QAAQa,CAAK,EAAG,CACnF,IAAMa,EAAU,MAAM,KAAKrB,EAAG,OAA8B,EACtDsB,EAAOd,EAAM,IAAI,MAAM,EAC7Ba,EAAQ,QAAShB,GAA2B,CAC1CA,EAAI,SAAWiB,EAAK,SAASjB,EAAI,KAAK,CACxC,CAAC,CACH,KAAW,UAAWL,IACpBA,EAAG,MAAQ,OAAOQ,CAAK,EAE3B,CAEA,SAASd,GAAsBD,EAA2BD,EAAoC,CAC5F,IAAM+B,EAAa9B,EAAO,aAAa,aAAa,EAC9CG,EAAOH,EAAO,aAAa,MAAM,GAAK,GAExC+B,EACAC,EAAa,QACbC,EAAY,OACZC,EAA4B,KAEhC,GAAIJ,EAAY,CACd,IAAMK,EAAQL,EAAW,MAAM,mEAAmE,EAClG,GAAI,CAACK,EAAO,OACZJ,EAAYI,EAAM,CAAC,EACfA,EAAM,CAAC,GAAKA,EAAM,CAAC,IACrBH,EAAaG,EAAM,CAAC,EACpBF,EAAYE,EAAM,CAAC,GAEjBA,EAAM,CAAC,IACTD,EAAaC,EAAM,CAAC,EAExB,SACEJ,EAAY5B,EAAK,SAAS,IAAI,EAAIA,EAAK,MAAM,EAAG,EAAE,EAAIA,EAClD,CAAC4B,EAAW,OAGlB,IAAMK,EAASrC,EAAQgC,CAAS,EAChC,GAAIK,IAAW,OAAW,OAE1B,IAAMC,EAAQ,OAAOD,GAAW,WAAaA,EAAO,KAAKrC,CAAO,EAAIqC,EACpE,GAAI,CAAC,MAAM,QAAQC,CAAK,EAAG,OAE3B,IAAMC,EAAe,MAAM,KAAKtC,EAAO,OAAO,EAAE,OAAOY,GAAOA,EAAI,QAAU,EAAE,EAC9EZ,EAAO,UAAY,GACnBsC,EAAa,QAAQ1B,GAAOZ,EAAO,IAAIY,CAAG,CAAC,EAE3C,IAAM2B,EAAS,IAAI,IAEnB,QAAWC,KAAQH,EAAO,CACxB,GAAIG,GAAS,KAA4B,SAEzC,IAAIzB,EACA0B,EACAC,EAAa,GAEjB,GAAI,OAAOF,GAAS,UAGlB,GAFAzB,EAAQ,OAAOyB,EAAKR,CAAU,CAAC,EAC/BS,EAAO,OAAOD,EAAKP,CAAS,CAAC,EACzBC,EAAY,CACd,IAAMS,EAAMH,EAAKN,CAAU,EACvBS,GAAQ,MAA6B,OAAOA,CAAG,IAAM,KACvDD,EAAa,OAAOC,CAAG,EAE3B,MACK,CACL,IAAMC,EAAM,OAAOJ,CAAI,EACvBzB,EAAQ6B,EACRH,EAAOG,CACT,CAEA,IAAMjC,EAAS,IAAI,OAAO8B,EAAM1B,CAAK,EACrC,GAAI2B,EAAY,CACd,IAAIG,EAAWN,EAAO,IAAIG,CAAU,EAC/BG,IACHA,EAAW,SAAS,cAAc,UAAU,EAC5CA,EAAS,MAAQH,EACjBH,EAAO,IAAIG,EAAYG,CAAQ,EAC/B7C,EAAO,YAAY6C,CAAQ,GAE7BA,EAAS,YAAYlC,CAAM,CAC7B,MACEX,EAAO,IAAIW,CAAM,CAErB,CACF,CAEA,SAASF,GAASP,EAAkBC,EAAuB,CACzD,IAAMI,EAAKL,EACX,GAAIC,KAAQI,GAAM,OAAOA,EAAGJ,CAAI,GAAM,UAAW,OAAOI,EAAGJ,CAAI,EAC/D,IAAM2C,EAAO5C,EAAQ,aAAaC,CAAI,EACtC,OAAI2C,IAAS,KAAa,GACtBA,IAAS,IAAMA,EAAK,YAAY,IAAM,QAAUA,EAAK,YAAY,IAAM3C,CAE7E,CCjQK,SAAS4C,GAAcC,EAAuB,CACjD,OAAO,OAAOA,CAAK,EAAE,YAAY,CACrC,CAOO,SAASC,GAASD,EAAuB,CAC5C,OAAO,OAAOA,CAAK,EAAE,QAAQ,EAAE,UAAU,CAC7C,CAQO,SAASE,GAAcF,EAAuB,CACjD,OAAO,OAAOA,CAAK,EAAE,YAAY,CACrC,CAOO,SAASG,GAAeH,EAAuB,CAClD,IAAMI,EAAM,OAAOJ,CAAK,EACxB,OAAOI,EAAI,OAAO,CAAC,EAAE,YAAY,EAAIA,EAAI,MAAM,CAAC,CACpD,CAQO,SAASC,GAAYL,EAAeM,EAAwB,CAC/D,IAAMF,EAAM,OAAOJ,CAAK,EAClBO,EAAY,SAASD,EAAQ,EAAE,EACrC,OAAOF,EAAI,OAASG,EACdH,EAAI,UAAU,EAAGG,EAAY,CAAC,EAAI,MAClCH,CACV,CAgBO,SAASI,GAAaR,EAAeS,EAAmB,MAAe,CAC1E,IAAMC,EAASC,EAAiB,EAChC,OAAO,IAAI,KAAK,aAAaD,EAAQ,CACjC,MAAO,WACP,SAAAD,CACJ,CAAC,EAAE,OAAOT,CAAK,CACnB,CAeO,SAASY,GAASZ,EAA+Ba,EAAyB,CAC7E,IAAMC,EAAO,IAAI,KAAKd,CAAK,EACrBU,EAASC,EAAiB,EAChC,OAAIE,IAAW,QACJC,EAAK,mBAAmBJ,CAAM,EAC9BG,IAAW,OACXC,EAAK,mBAAmBJ,EAAQ,CACnC,QAAS,OACT,KAAM,UACN,MAAO,OACP,IAAK,SACT,CAAC,EAEEI,EAAK,YAAY,CAC5B,CAcO,SAASC,GAAYf,EAAuC,CAC/D,GAAI,CAACA,EACD,MAAO,MAGX,IAAMgB,EAAY,IAAI,KAAKhB,CAAK,EAC1BiB,EAAQ,IAAI,KAGlBD,EAAU,SAAS,EAAG,EAAG,EAAG,CAAC,EAC7BC,EAAM,SAAS,EAAG,EAAG,EAAG,CAAC,EAEzB,IAAMC,EAAWD,EAAM,QAAQ,EAAID,EAAU,QAAQ,EAC/CG,EAAW,KAAK,MAAMD,GAAY,IAAO,GAAK,GAAK,GAAG,EAE5D,OAAIC,IAAa,EAAUC,EAAE,eAAe,EACxCD,IAAa,EAAUC,EAAE,mBAAmB,EACzCA,EAAE,kBAAmB,CAAE,MAAOD,CAAS,CAAC,CACnD,CAcO,SAASE,GAAWrB,EAAgC,CACvD,GAAIA,GAAU,KACV,MAAO,MAGX,IAAMsB,EAAQ,OAAOtB,CAAK,EAC1B,OAAOoB,EAAE,iBAAkB,CAAE,MAAAE,CAAM,CAAC,CACxC,CAcO,SAASC,GAASvB,EAAcwB,EAAoB,IAAmB,CAC1E,OAAK,MAAM,QAAQxB,CAAK,EACjBA,EAAM,KAAKwB,CAAS,EADOxB,CAEtC,CAOO,SAASyB,GAAUzB,EAAmB,CACzC,MAAI,CAAC,MAAM,QAAQA,CAAK,GAAKA,EAAM,SAAW,EAAU,GACjDA,EAAM,CAAC,CAClB,CAOO,SAAS0B,GAAS1B,EAAmB,CACxC,MAAI,CAAC,MAAM,QAAQA,CAAK,GAAKA,EAAM,SAAW,EAAU,GACjDA,EAAMA,EAAM,OAAS,CAAC,CACjC,CAQO,SAAS2B,GAAS3B,EAAyB,CAC9C,OAAI,OAAOA,GAAU,UAAYA,IAAU,KAAa,CAAC,EAClD,OAAO,KAAKA,CAAK,CAC5B,CASO,SAAS4B,GAAY5B,EAAY6B,EAA2B,CAC/D,OAAO7B,GAAS6B,CACpB,CASO,SAASC,GAAY9B,EAAY+B,EAAmBC,EAA4B,CACnF,OAAOhC,EAAQ+B,EAAYC,CAC/B,CAoDO,SAASC,IAAmC,CAC/C,IAAMC,EAAQ,IAAI,IAGlB,OAAAA,EAAM,IAAI,YAAanC,EAAa,EACpCmC,EAAM,IAAI,YAAahC,EAAa,EACpCgC,EAAM,IAAI,aAAc/B,EAAc,EACtC+B,EAAM,IAAI,OAAQjC,EAAQ,EAC1BiC,EAAM,IAAI,UAAW7B,EAAW,EAGhC6B,EAAM,IAAI,WAAY1B,EAAY,EAClC0B,EAAM,IAAI,OAAQtB,EAAQ,EAC1BsB,EAAM,IAAI,UAAWnB,EAAW,EAChCmB,EAAM,IAAI,SAAUb,EAAU,EAG9Ba,EAAM,IAAI,OAAQX,EAAQ,EAC1BW,EAAM,IAAI,QAAST,EAAS,EAC5BS,EAAM,IAAI,OAAQR,EAAQ,EAG1BQ,EAAM,IAAI,OAAQP,EAAQ,EAG1BO,EAAM,IAAI,UAAWN,EAAW,EAChCM,EAAM,IAAI,UAAWJ,EAAW,EAEzB,CACH,OAAOK,EAAM,CACT,OAAOD,EAAM,IAAIC,CAAI,GAAK,IAC9B,EACA,IAAIA,EAAM,CACN,IAAIC,EAAOF,EAAM,IAAIC,CAAI,EACzB,GAAI,CAACC,EACD,MAAM,MAAM,SAAWD,EAAO,cAAc,EAEhD,OAAOC,CACX,EACA,IAAID,EAAM,CACN,OAAOD,EAAM,IAAIC,CAAI,CACzB,CACJ,CACJ,CAaO,IAAME,EAAeJ,GAAmB,EAyBxC,SAASK,GACZtC,EACAkC,EACAK,EAAyBF,EACtB,CAEH,OAAOH,EAAM,OAAO,CAACM,EAAcJ,IAAS,CACxC,GAAM,CAACK,EAAU,GAAGC,CAAI,EAAIN,EAAK,MAAM,GAAG,EAAE,IAAKO,GAAMA,EAAE,KAAK,CAAC,EAE/D,GAAI,CAACJ,EAAS,IAAIE,CAAQ,EACtB,MAAO,SAASA,CAAQ,cAG5B,GAAI,CACA,OAAOF,EAAS,IAAIE,CAAQ,EAAED,EAAc,GAAGE,CAAI,CACvD,OAASE,EAAO,CACZ,MAAO,SAASH,CAAQ,YAAYzC,CAAK,YAAY4C,CAAK,GAC9D,CACJ,EAAG5C,CAAK,CACZ,CC1ZA,IAAM6C,GAAQC,EAyDP,SAASC,GACdC,KACGC,EAC+B,CAElC,IAAMC,EAAW,SAAS,cAAc,UAAU,EAC5CC,EAAmBC,GAAgBJ,CAAe,EACxDE,EAAS,UAAYC,EACrB,IAAME,EAAsB,CAAC,EAEvBC,EAAS,SAAS,iBACtBJ,EAAS,QACT,WAAW,QACb,EACIK,EAEJ,KAAQA,EAAOD,EAAO,SAAS,GAC7B,GAAIC,EAAK,WAAa,KAAK,aAAc,CACvC,IAAMC,EAAUD,EAChBE,GAAeD,EAASP,EAAeI,CAAQ,EAC3C,eAAe,IAAIG,EAAQ,QAAQ,YAAY,CAAC,GAClD,eAAe,QAAQA,CAAO,CAElC,SAAWD,EAAK,WAAa,KAAK,UAAW,CAC3C,IAAMG,EAASH,EACTI,EAAOD,EAAO,YACdE,EAASC,GAAcF,EAAMV,CAAa,EAChD,GAAIW,EAEF,GADyB,UAAU,KAAKD,CAAI,EACtB,CACpB,IAAIG,EAA8B,KAC9BC,EAA4B,KAC5BC,EAAwB,CAAC,EAC7BX,EAAS,KAAK,CACZ,cAAeM,EACf,OAAOM,EAAU,CACf,IAAIC,EAAQN,EAAOK,CAAQ,EACtBH,IACHA,EAAc,SAAS,cAAc,EAAE,EACvCC,EAAY,SAAS,cAAc,EAAE,EACrCL,EAAO,YAAY,aAAaK,EAAWL,CAAM,EACjDK,EAAU,YAAY,aAAaD,EAAaC,CAAS,GAE3DC,EAAc,QAAQG,GAAKA,EAAE,YAAY,YAAYA,CAAC,CAAC,EACvDH,EAAgB,CAAC,EACjB,IAAMI,EAAO,SAAS,cAAc,UAAU,EAC9CA,EAAK,UAAYF,EACjB,IAAMG,EAAQ,MAAM,KAAKD,EAAK,QAAQ,UAAU,EAC1CE,EAASP,EAAW,WAC1BM,EAAM,QAAQF,GAAK,CACjBG,EAAO,aAAaH,EAAGJ,CAAS,EAChCC,EAAc,KAAKG,CAAC,CACtB,CAAC,CACH,CACF,CAAC,CACH,MACEd,EAAS,KAAK,CACZ,cAAeM,EACf,OAAOM,EAAU,CACf,IAAIC,EAAQN,EAAOK,CAAQ,EAC3BP,EAAO,YAAcQ,CACvB,CACF,CAAC,CAGP,CAIF,OAAO,SAAcK,EAA8B,CACjD,OAAAlB,EAAS,QAASmB,GAAM,CACtBA,EAAE,OAAOD,CAAO,CAClB,CAAC,EAEM,CACL,SAAUrB,EAAS,QACnB,OAAOqB,EAAc,CACnBlB,EAAS,QAASmB,GAAM,CACtBA,EAAE,OAAOD,CAAO,CAClB,CAAC,CACH,CACF,CACF,CACF,CAEA,SAASnB,GAAgBJ,EAA+C,CACtE,OAAOA,EAAgB,IACpB,IAAI,CAACyB,EAAKC,IACTA,EAAI1B,EAAgB,IAAI,OAAS,EAAI,GAAGyB,CAAG,eAAKC,CAAC,eAAOD,CAC1D,EACC,KAAK,EAAE,CACZ,CAEA,SAAShB,GACPD,EACAP,EACAI,EACA,CACA,IAAMsB,EAA0B,CAAC,EAEjC,QAAWC,KAAQ,MAAM,KAAKpB,EAAQ,UAAU,EAAG,CACjD,IAAIqB,EAAYD,EAAK,MACrB,GAAIC,GAAa,GACf,SAGF,IAAMC,EAAQ,YACRC,EAAQF,EAAU,MAAMC,CAAK,EACnC,GAAIC,EAAO,CACT,IAAMC,EAAQ,SAASD,EAAM,CAAC,EAAG,EAAE,EAC7BE,EAAOhC,EAAc+B,CAAK,EAChC,GAAI,OAAOC,GAAS,WAAY,CAC9BN,EAAa,KAAK,CAChB,OAAOV,EAAU,CACf,IAAMiB,EAAgBD,EAAK,KAAKhB,CAAQ,EACxCT,EAAQ,gBAAgBoB,EAAK,IAAI,EAChCpB,EAAgBoB,EAAK,IAAI,EAAIM,CAChC,CACF,CAAC,EAED,QACF,CACF,CAEA,IAAIC,EAAoBtB,GAAcgB,EAAW5B,CAAa,EAC1DkC,GAAqB,MAIzBR,EAAa,KAAK,CAChB,cAAeE,EACf,OAAOZ,EAAU,CACf,IAAMC,EAAQiB,EAAmBlB,CAAQ,GAAKY,EAC1CD,EAAK,QAAQpB,EACdA,EAAgBoB,EAAK,IAAI,EAAIV,EAE9BU,EAAK,MAAQV,CAEjB,CACF,CAAC,CACH,CAEIS,EAAa,OAAS,GACxBtB,EAAS,KAAK,CACZ,cAAeG,EAAQ,QACvB,OAAOS,EAAU,CACfU,EAAa,QAASS,GAAgBA,EAAY,OAAOnB,CAAQ,CAAC,CACpE,CACF,CAAC,CAEL,CASA,SAASoB,GAAeC,EAAiBrB,EAAsB,CAC7D,OAAOqB,EAAQ,MAAM,GAAG,EAAE,IAAIC,GAAO,CAGnC,GAFAA,EAAMA,EAAI,KAAK,EAEVA,EAAI,WAAW,GAAG,GAAKA,EAAI,SAAS,GAAG,GACvCA,EAAI,WAAW,GAAG,GAAKA,EAAI,SAAS,GAAG,EAC1C,OAAOA,EAAI,MAAM,EAAG,EAAE,EAGxB,GAAI,CAAC,MAAM,OAAOA,CAAG,CAAC,EACpB,OAAO,OAAOA,CAAG,EAGnB,GAAIA,EAAI,SAAS,GAAG,EAAG,CACrB,IAAMC,EAAQD,EAAI,MAAM,GAAG,EACvBrB,EAAQD,EACZ,QAAWwB,KAAQD,EAAO,CACxB,GAA2BtB,GAAU,KAAM,OAC3CA,EAAQA,EAAMuB,CAAI,CACpB,CACA,OAAOvB,CACT,CAGA,OAAOD,EAASsB,CAAG,CACrB,CAAC,CACH,CAGA,SAAS1B,GACPX,EACAD,EACyB,CACzB,IAAM6B,EAAQ,+CACVY,EAAY,EACZX,EAEEY,EAAmC,CAAC,EAC1C,MAAQZ,EAAQD,EAAM,KAAK5B,CAAQ,KAAO,MAAM,CAC9C,IAAIgB,EAAQhB,EAAS,MAAMwC,EAAWX,EAAM,KAAK,EAQjD,GAPIb,EAAM,OAAS,GACjByB,EAAa,KAAMC,GACV1B,CACR,EAICa,EAAM,CAAC,EAAG,CACZ,IAAMC,EAAQ,SAASD,EAAM,CAAC,EAAG,EAAE,EAC7Bc,EAAM5C,EAAc+B,CAAK,EAC/B,GAAI,CAACa,EACH,SAGF,GAAI,OAAOA,GAAQ,WAAY,CAC7B,IAAMZ,EAAOY,EACbF,EAAa,KAAM1B,GAAa,CAC9B,IAAIL,EAASqB,EAAK,MAAMhB,CAAQ,EAChC,OAAOL,CACT,CAAC,CACH,MACMiC,GAAOA,EAAI,OAAS,GACtBF,EAAa,KAAM1B,GACV4B,CACR,CAGP,SAAWd,EAAM,CAAC,EAAG,CAEnB,IAAMe,EAAef,EAAM,CAAC,EAAE,KAAK,EAC7BO,EAAUP,EAAM,CAAC,EAAIA,EAAM,CAAC,EAAE,KAAK,EAAI,KACvCgB,EAAgBhB,EAAM,CAAC,EACzBA,EAAM,CAAC,EAAE,MAAM,GAAG,EAAE,IAAKiB,GAASA,EAAK,KAAK,CAAC,EAC7C,CAAC,EAELL,EAAa,KAAM1B,GAAa,CAC9B,IAAIC,EAAQD,EAAS6B,CAAY,EAEjC,GAAI,OAAO5B,GAAU,WACnB,GAAIoB,EAAS,CACX,IAAMW,EAAOZ,GAAeC,EAASrB,CAAQ,EAC7CC,EAAQA,EAAM,MAAMD,EAAUgC,CAAI,CACpC,MACE/B,EAAQA,EAAM,KAAKD,CAAQ,EAI/B,OAAA8B,EAAc,QAASC,GAAS,CAC9B9B,EAAQrB,GAAM,IAAImD,CAAI,EAAE9B,CAAK,CAC/B,CAAC,EACMA,CACT,CAAC,CACH,CAEAwB,EAAYZ,EAAM,SACpB,CAEA,GAAIa,EAAa,QAAU,EACzB,OAAO,KAGT,IAAIO,EAAMhD,EAAS,MAAMwC,CAAS,EAClC,OAAIQ,EAAI,OAAS,GACfP,EAAa,KAAMQ,GACVD,CACR,EAEKjC,GAAa,CACnB,IAAIL,EAAS,GACb,OAAA+B,EAAa,QAASS,GAAY,CAChC,IAAIlC,EAAQkC,EAAQnC,CAAQ,EAC5BL,GAAUM,CACZ,CAAC,EAEMN,CACT,CACF,CC5MA,SAASyC,GAAgBC,EAAgC,CACrD,IAAMC,EAAaD,EAAK,MAAM,GAAG,EAAE,IAAIE,GAAKA,EAAE,KAAK,CAAC,EAC9CC,EAAWF,EAAW,CAAC,EACvBG,EAAQH,EAAW,MAAM,CAAC,EAG1BI,EAAUF,EAAS,MAAM,oBAAoB,EACnD,GAAIE,EAAS,CACT,GAAM,CAAC,CAAEC,EAAQC,CAAO,EAAIF,EACtBG,EAASD,EACTA,EAAQ,MAAM,GAAG,EAAE,IAAIE,GAAKA,EAAE,KAAK,CAAC,EACpC,CAAC,EACP,MAAO,CAAE,KAAM,WAAY,OAAAH,EAAQ,OAAAE,EAAQ,MAAAJ,CAAM,CACrD,CAEA,MAAO,CAAE,KAAM,OAAQ,KAAMD,EAAU,MAAAC,CAAM,CACjD,CAGA,SAASM,GAAYC,EAAmBC,EAA4B,CAGhE,IAAMC,EADiBD,EAAK,QAAQ,aAAc,KAAK,EACvB,MAAM,GAAG,EACrCE,EAAUH,EAEd,QAAWI,KAAOF,EACd,GAAIC,GAAW,OAAOA,GAAY,UAAYC,KAAOD,EACjDA,EAAWA,EAAyCC,CAAG,MAEvD,QAIR,OAAOD,CACX,CAEE,SAASE,EAAYC,EAAsBC,EAAiBC,EAAiBC,EAAc,GAAa,CACtG,IAAMC,EAAmB,oBAAoBH,CAAO,QAAQC,CAAO,IAInE,GAFI,OAAO,YAAY,WAAW,QAAQ,KAAKE,CAAgB,EAC3DJ,EAAO,SAASA,EAAO,QAAQI,CAAgB,EAC/CJ,EAAO,QAAUG,EAAa,MAAM,IAAI,MAAMC,CAAgB,CACpE,CAEF,SAASC,GAAaL,EAA8B,CAChD,OAAO,SAAaN,EAAmBC,EAAYW,EAAY,GAAmB,CAC9E,GAAI,CACA,IAAMT,EAAUJ,GAAYC,EAAKC,CAAI,EAErC,OAAIE,IAAY,QACZE,EAAYC,EAAQ,mBAAmBL,CAAI,IAAKW,CAAS,EAClD,IAIPT,IAAY,KACL,GACA,MAAM,QAAQA,CAAO,EACrBA,EAAQ,OAAS,EAAI,KAAK,UAAUA,CAAO,EAAI,GAC/C,OAAOA,GAAY,SACnB,KAAK,UAAUA,CAAO,EAEtBA,CAEf,OAASU,EAAK,CACV,IAAMC,EAAeD,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,EACpE,OAAAR,EAAYC,EAAQ,wBAAwBL,CAAI,MAAMa,CAAY,GAAIF,EAAW,EAAI,EAC9E,EACX,CACJ,CACJ,CAEA,SAASG,GACLC,EACAhB,EACAiB,EACAX,EACAM,EACa,CACb,IAAIM,EACEC,EAAWb,EAAO,cAAgBc,EAExC,GAAIJ,EAAO,OAAS,WAAY,CAC5B,IAAMK,EAAKJ,IAAMD,EAAO,MAAO,EAC/B,GAAI,OAAOK,GAAO,WACd,OAAAhB,EAAYC,EAAQ,aAAaU,EAAO,MAAM,cAAeJ,CAAS,EAC/D,GAIX,IAAMU,GAAgBN,EAAO,QAAU,CAAC,GAAG,IAAIO,GAEtCA,EAAI,WAAW,GAAG,GAAKA,EAAI,SAAS,GAAG,GACvCA,EAAI,WAAW,GAAG,GAAKA,EAAI,SAAS,GAAG,EACjCA,EAAI,MAAM,EAAG,EAAE,EAGrB,MAAM,OAAOA,CAAG,CAAC,EAILxB,GAAYC,EAAKuB,CAAG,EAH1B,OAAOA,CAAG,CAKxB,EAED,GAAI,CACAL,EAAQG,EAAG,GAAGC,CAAY,CAC9B,OAAST,EAAK,CACV,IAAMC,EAAeD,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,EACpE,OAAAR,EAAYC,EAAQ,kBAAkBU,EAAO,MAAM,MAAMF,CAAY,GAAIF,CAAS,EAC3E,EACX,CACJ,KAAO,CAEH,IAAMY,EAAWzB,GAAYC,EAAKgB,EAAO,IAAK,EAC9C,GAAIQ,IAAa,OACb,OAAAnB,EAAYC,EAAQ,mBAAmBU,EAAO,IAAI,IAAKJ,CAAS,EACzD,GAEPY,IAAa,KACbN,EAAQ,GACD,OAAOM,GAAa,SAC3BN,EAAQ,KAAK,UAAUM,CAAQ,EAE/BN,EAAQM,CAEhB,CAGA,OAAIR,EAAO,MAAM,OAAS,IACtBE,EAAQO,GAAWP,EAAOF,EAAO,MAAOG,CAAQ,GAG7CD,CACX,CAQA,IAAMQ,GAAkB,IAAI,IAO5B,SAASC,GAAmBC,EAAkC,CAC1D,IAAIC,EAAQH,GAAgB,IAAIE,CAAG,EACnC,OAAKC,IACDA,EAAQD,EACH,MAAM,eAAe,EACrB,OAAOE,GAAQA,IAAS,EAAE,EAC1B,IAAIA,GAAQA,EAAK,WAAW,IAAI,GAAKA,EAAK,SAAS,IAAI,EAClD,CAAE,OAAQ1C,GAAgB0C,EAAK,MAAM,EAAG,EAAE,EAAE,KAAK,CAAC,EAAG,QAAS,EAAG,EACjE,CAAE,OAAQ,KAAM,QAASA,CAAK,CAAC,EACzCJ,GAAgB,IAAIE,EAAKC,CAAK,GAE3BA,CACX,CAEA,SAASE,GACLF,EACA7B,EACAiB,EACAX,EACAM,EACM,CACN,OAAOiB,EACF,IAAI,CAAC,CAAE,OAAAb,EAAQ,QAAAgB,CAAQ,IAAMhB,EACxB,OAAOD,GAAmBC,EAAQhB,EAAKiB,EAAKX,EAAQM,CAAS,CAAC,EAC9DoB,CAAO,EACZ,KAAK,EAAE,CAChB,CAEA,SAASC,GAAgBC,EAAYC,EAAc7B,EAAqC,CACpF,GAAI4B,EAAK,WAAa,KAAK,WAAa,CAACA,EAAK,aAAa,SAAS,IAAI,EAAG,OAE3E,IAAMN,EAAMM,EAAK,YACXL,EAAQF,GAAmBC,CAAG,EAC9BhB,EAAY,cAAcgB,CAAG,IAEnC,MAAO,CAAC5B,EAAciB,IAA2B,CAC5CiB,EAAc,YAAcH,GAAaF,EAAO7B,EAAKiB,EAAKX,EAAQM,CAAS,CAChF,CACJ,CASA,IAAMwB,GAAsB,CAAC,QAAS,UAAW,UAAU,EA6B3D,SAASC,GAA8BH,EAAYC,EAAc7B,EAAqC,CAClG,GAAI4B,EAAK,WAAa,KAAK,aAAc,OAEzC,IAAMI,EAAUJ,EACVK,EAAoB,CAAC,EAGrBC,EAAa,MAAM,KAAKF,EAAQ,UAAU,EAChD,QAAWG,KAAQD,EAAY,CAC3B,GAAI,CAACC,EAAK,MAAM,SAAS,IAAI,EAAG,SAEhC,IAAMZ,EAAQF,GAAmBc,EAAK,KAAK,EAC3C,GAAI,CAACZ,EAAM,KAAKC,GAAQA,EAAK,MAAM,EAAG,SAEtC,IAAMY,EAAOD,EAAK,KACZE,EAAad,EAAM,SAAW,EAAIA,EAAM,CAAC,EAAE,OAAS,KACpDjB,EAAY,cAAc8B,CAAI,QAAQJ,EAAQ,QAAQ,YAAY,CAAC,IAEzEC,EAAQ,KAAK,CAACvC,EAAciB,IAA2B,CACnD,IAAMC,EAAQyB,EACR5B,GAAmB4B,EAAY3C,EAAKiB,EAAKX,EAAQM,CAAS,EAC1DmB,GAAaF,EAAO7B,EAAKiB,EAAKX,EAAQM,CAAS,EAEjDwB,GAAoB,SAASM,CAAI,GAAKA,KAAQJ,EAC7CA,EAA+CI,CAAI,EAAIxB,EACjD,OAAOA,GAAU,UACxBoB,EAAQ,gBAAgBI,EAAMxB,CAAK,EAEnCoB,EAAQ,aAAaI,EAAM,OAAOxB,CAAK,CAAC,CAEhD,CAAC,CACL,CAEA,GAAIqB,EAAQ,OAAS,EACjB,MAAO,CAACvC,EAAciB,IAA2BsB,EAAQ,QAAQlB,GAAMA,EAAGrB,EAAKiB,CAAG,CAAC,CAE3F,CAkBA,SAAS2B,GAAaV,EAAYC,EAAc7B,EAAqC,CACjF,GAAI4B,EAAK,WAAa,KAAK,aAAc,OAEzC,IAAMI,EAAUJ,EACVW,EAAMP,EAAQ,QAAQ,YAAY,EAClCQ,EAAc,MAAM,KAAKR,EAAQ,UAAU,EAAE,OAAOG,GAAQA,EAAK,KAAK,WAAW,IAAI,CAAC,EAC5F,GAAIK,EAAY,SAAW,EAAG,OAE9B,IAAMC,EAAqB,CAAC,EAE5B,QAAWN,KAAQK,EAAa,CAC5B,IAAME,EAAYP,EAAK,KAAK,MAAM,CAAC,EAC7BpD,EAAOoD,EAAK,MACZ7B,EAAY,GAAG6B,EAAK,IAAI,KAAKpD,CAAI,SAASwD,CAAG,IAGnD,GAFAP,EAAQ,gBAAgBG,EAAK,IAAI,EAE7B,EAAE,KAAKO,CAAS,KAAMV,GAAU,CAChCjC,EAAYC,EAAQ,IAAImC,EAAK,IAAI,+BAA+BI,CAAG,IAAKjC,CAAS,EACjF,QACJ,CAEA,IAAMI,EAAS5B,GAAgBC,CAAI,EACnC,GAAI2B,EAAO,OAAS,WAAY,CAC5BX,EAAYC,EAAQ,GAAGmC,EAAK,IAAI,kCAAkCpD,CAAI,IAAKuB,CAAS,EACpF,QACJ,CAEA,IAAIqC,EAA6B,KAC7BC,EAEJZ,EAAQ,iBAAiBU,EAAYG,GAAU,CAC3C,GAAI,CAACF,EAAY,OACjB,IAAMG,EAAe,CAAE,GAAGH,EAAY,MAAAE,CAAM,EAC5CpC,GAAmBC,EAAQoC,EAAcF,EAAY5C,EAAQM,CAAS,CAC1E,CAAC,EAEDmC,EAAS,KAAK,CAAC/C,EAAciB,IAA2B,CACpDgC,EAAajD,EACbkD,EAAajC,CACjB,CAAC,CACL,CAEA,GAAI8B,EAAS,OAAS,EAClB,MAAO,CAAC/C,EAAciB,IAA2B8B,EAAS,QAAQ1B,GAAMA,EAAGrB,EAAKiB,CAAG,CAAC,CAE5F,CAEA,IAAMoC,GAAuB,CAAC,OAAQ,KAAM,QAAQ,EAkCpD,SAASC,GAAkBpB,EAAYqB,EAAajD,EAAqC,CACrF,GAAI4B,EAAK,WAAa,KAAK,aAAc,OAEzC,IAAMI,EAAUJ,EACVsB,EAAUlB,EAAQ,aAAa,MAAM,EACrCmB,EAASnB,EAAQ,aAAa,IAAI,EAClCoB,EAAapB,EAAQ,aAAa,QAAQ,EAChD,GAAIkB,IAAY,MAAQC,IAAW,MAAQC,IAAe,KAAM,OAEhE,IAAMb,EAAMP,EAAQ,QAAQ,YAAY,EACpCqB,EAAQ,GACRC,EAAS,GAEb,GAAIJ,IAAY,KAAM,CAClB,IAAMK,EAAQL,EAAQ,MAAM,mBAAmB,EAC/C,GAAI,CAACK,EAAO,CACRxD,EAAYC,EAAQ,yBAAyBkD,CAAO,IAAK,aAAaX,CAAG,GAAG,EAC5E,MACJ,CACA,CAAC,CAAEc,EAAOC,CAAM,EAAIC,CACxB,CAEA,IAAMC,EAAWxB,EAAQ,UAAU,EAAI,EACvCe,GAAqB,QAAQX,GAAQoB,EAAS,gBAAgBpB,CAAI,CAAC,EAEnE,IAAMqB,EAAc,SAAS,cACzBP,IAAY,KACN,SAASA,CAAO,GAChBC,IAAW,KACP,OAAOA,CAAM,GACb,WAAWC,CAAU,EACnC,EACMM,EAAS1B,EAAQ,WACvB0B,EAAO,aAAaD,EAAazB,CAAO,EACxCA,EAAQ,OAAO,EAEf,IAAM2B,EAAaC,GACX,EAAAT,IAAW,MAAQ,CAACF,EAAIW,EAAWT,EAAQ,OAAOA,CAAM,GAAG,GAC3DC,IAAe,MAAQH,EAAIW,EAAWR,EAAY,WAAWA,CAAU,GAAG,GAK5ES,EAAoBnE,GAAmC,CACzD,GAAIwD,IAAY,KAAM,OAAOS,EAAUjE,CAAG,EAAI,CAACA,CAAG,EAAI,CAAC,EAEvD,IAAMoE,EAAQrE,GAAYC,EAAK4D,CAAM,EAErC,OAAIQ,IAAU,QACV/D,EAAYC,EAAQ,mBAAmBsD,CAAM,IAAK,iBAAiBJ,CAAO,GAAG,EACtE,MAGN,MAAM,QAAQY,CAAK,EAKjBA,EACF,IAAIC,IAAS,CAAE,GAAGrE,EAAK,CAAC2D,CAAK,EAAGU,CAAK,EAAa,EAClD,OAAOJ,CAAS,GANjB5D,EAAYC,EAAQ,IAAIsD,CAAM,+BAA+BJ,CAAO,IAAK,aAAaX,CAAG,GAAG,EACrF,KAMf,EAEIyB,EAAwB,CAAC,EACzBC,EAAyB,KAE7B,MAAO,CAACvE,EAAciB,IAA2B,CAC7C,IAAMuD,EAAWL,EAAiBnE,CAAG,EACrC,GAAI,CAACwE,EAAU,OAEf,IAAMC,EAAa,KAAK,IAAIH,EAAU,OAAQE,EAAS,MAAM,EAG7D,QAASE,EAAI,EAAGA,EAAID,EAAYC,IAC5BJ,EAAUI,CAAC,EAAE,OAAOF,EAASE,CAAC,EAAGzD,CAAG,EAIxC,QAASyD,EAAIJ,EAAU,OAAS,EAAGI,GAAKF,EAAS,OAAQE,IACrDJ,EAAUI,CAAC,EAAE,QAAQ,OAAO,EAC5BH,EAAQD,EAAUI,CAAC,EAIvB,GAAIF,EAAS,OAASC,EAAY,CAC9B,IAAME,EAAW,SAAS,uBAAuB,EAC3CC,GAAoB,CAAC,EAE3B,QAASF,GAAID,EAAYC,GAAIF,EAAS,OAAQE,KAAK,CAC/C,IAAIG,EAAWN,EAEf,GADAA,EAAQ,KACJ,CAACM,EAAU,CAEX,IAAMC,GAAQhB,EAAS,UAAU,EAAI,EACrCe,EAAW,CAAE,QAASC,GAAO,OAAQC,GAAWD,GAAOxE,CAAM,CAAE,CACnE,CAGAuE,EAAS,OAAOL,EAASE,EAAC,EAAGzD,CAAG,EAEhC0D,EAAS,YAAYE,EAAS,OAAO,EACrCD,GAAM,KAAKC,CAAQ,CACvB,CAGA,IAAMG,GAAcP,EAAa,EAAIH,EAAUG,EAAa,CAAC,EAAE,QAAUV,EACzEC,EAAO,aAAaW,EAAUK,GAAY,WAAW,EAErDV,EAAYA,EAAU,MAAM,EAAGG,CAAU,EAAE,OAAOG,EAAK,CAC3D,MACIN,EAAU,OAASE,EAAS,MAEpC,CACJ,CAGA,IAAMS,GAA6B,CAC/BhD,GACAI,GACAO,EACJ,EAUA,SAASmC,GAAWG,EAAY5E,EAAsE,CAClG,IAAMiC,EAAoB,CAAC,EACrBgB,EAAM5C,GAAaL,CAAM,EAE/B,SAAS6E,EAAYjD,EAAY,CAE7B,IAAMkD,EAAa9B,GAAkBpB,EAAMqB,EAAKjD,CAAM,EACtD,GAAI8E,EAAY,CACZ7C,EAAQ,KAAK6C,CAAU,EACvB,MACJ,CAGA,QAAWC,KAASJ,GAAiB,CACjC,IAAMK,EAASD,EAAMnD,EAAMqB,EAAKjD,CAAM,EAClCgF,GAAQ/C,EAAQ,KAAK+C,CAAM,CACnC,CAEA,QAAWC,KAAS,MAAM,KAAKrD,EAAK,UAAU,EAC1CiD,EAAYI,CAAK,CAEzB,CAEAJ,EAAYD,CAAI,EAGhB,IAAIM,EAA0B,KAC1BC,EACJ,MAAO,CAACzF,EAAciB,IAA2B,EAEzCuE,IAAYxF,GAAOyF,IAAYxE,KAC/BsB,EAAQ,QAAQlB,GAAMA,EAAGrB,EAAKiB,CAAG,CAAC,EAClCuE,EAAUxF,EACVyF,EAAUxE,EAElB,CACJ,CA4EO,SAASyE,GAAgBC,EAAqBrF,EAAuB,CAAE,OAAQ,EAAM,EAAqB,CAG7G,IAAMsF,EAFS,IAAI,UAAU,EACV,gBAAgB,kBAAkBD,CAAW,oBAAqB,WAAW,EAC5E,cAAc,UAAU,EAAG,QAAQ,kBACjDE,EAASd,GAAWa,EAAStF,CAAM,EAEzC,MAAO,CAAE,QAAAsF,EAAS,OAAAC,CAAO,CAC7B,CCvrBA,SAASC,GACPC,EACAC,EAAyB,CAAC,EACZ,CACd,GAAM,CAAE,UAAAC,EAAY,IAAK,WAAAC,EAAa,IAAK,EAAIF,EAE/C,GAAI,CAACD,GAAY,OAAOA,GAAa,SACnC,MAAM,IAAI,MAAM,qCAAqC,EAGvD,IAAMI,EAA0B,CAAC,EAC7BC,EAAU,GACVC,EAAI,EACJC,EAAa,GACbC,EAAiB,GAErB,KAAOF,EAAIN,EAAS,QAAQ,CAC1B,IAAMS,EAAOT,EAASM,CAAC,EACjBI,EAAuBV,EAAS,UAAUM,EAAGJ,EAAU,OAASI,CAAC,EACjEK,EAAWX,EAASM,EAAI,CAAC,EACzBM,EAAoBZ,EAAS,UAAUM,EAAI,EAAGJ,EAAU,OAASI,EAAI,CAAC,EAE5E,GACEG,IAASN,IACRS,IAAsBV,GAAaS,IAAa,KAAOA,IAAa,KAEjEJ,EACFC,GAAkBG,EAElBN,GAAWM,EAEbL,GAAK,UACIG,IAAS,KAAO,CAACF,EACtBF,IACFD,EAAS,KAAK,CAAE,KAAM,WAAY,IAAKC,CAAQ,CAAC,EAChDA,EAAU,IAEZE,EAAa,GACbC,EAAiB,GACjBF,YACSG,IAAS,KAAOF,EAAY,CACrC,GAAI,CAAC,QAAQ,KAAKC,EAAe,KAAK,CAAC,EACrC,MAAM,IAAI,MACR,yBAAyBA,CAAc,wCACzC,EAEFJ,EAAS,KAAK,CAAE,KAAM,QAAS,IAAKI,EAAe,KAAK,CAAE,CAAC,EAC3DD,EAAa,GACbC,EAAiB,GACjBF,GACF,MAAWI,IAAyBR,GAAa,CAACK,GAC5CF,IACFD,EAAS,KAAK,CAAE,KAAM,WAAY,IAAKC,CAAQ,CAAC,EAChDA,EAAU,IAEZC,GAAKJ,EAAU,QACNK,GACTC,GAAkBC,EAClBH,MAEAD,GAAWI,EACXH,IAEJ,CAEA,GAAIC,EACF,MAAM,IAAI,MAAM,8BAA8B,EAOhD,GAJIF,GACFD,EAAS,KAAK,CAAE,KAAM,WAAY,IAAKC,CAAQ,CAAC,EAG9CD,EAAS,SAAW,EACtB,MAAM,IAAI,MACR,+DACF,EAGF,OAAOA,CACT,CAYA,SAASS,GACPC,EACqB,CACrB,OAAQC,GAA+C,CACrD,IAAIV,EAAeU,EAEnB,QAAWC,KAAWF,EAAM,CAC1B,GAAIT,GAAW,KACb,OAGF,GAAIW,EAAQ,OAAS,WAAY,CAC/B,GAAI,OAAOX,GAAY,SACrB,OAEFA,EAAUA,EAAQW,EAAQ,GAAG,CAC/B,SAAWA,EAAQ,OAAS,QAAS,CACnC,GAAI,CAAC,MAAM,QAAQX,CAAO,EACxB,OAEF,IAAMY,EAAQ,SAASD,EAAQ,IAAK,EAAE,EACtC,GAAIC,EAAQ,GAAKA,GAASZ,EAAQ,OAChC,OAEFA,EAAUA,EAAQY,CAAK,CACzB,CACF,CAEA,OAAOZ,CACT,CACF,CAkBA,SAASa,GACPlB,EACAC,EAAyB,CAAC,EACL,CACrB,IAAMa,EAAOf,GAAUC,EAAUC,CAAO,EACxC,OAAOY,GAA0BC,CAAI,CACvC,CC9JO,SAASK,GAASC,EAAwB,CAC/C,IAAMC,EAAkB,CAAC,EACrBC,EAAI,EAER,KAAOA,EAAIF,EAAM,QAAQ,CACvB,IAAIG,EAAOH,EAAME,CAAC,EAGlB,GAAI,KAAK,KAAKC,CAAI,EAAG,CACnBD,IACA,QACF,CAGA,GAAIC,IAAS,IAAK,CAIhB,IAHAD,IAGOA,EAAIF,EAAM,QAAU,KAAK,KAAKA,EAAME,CAAC,CAAC,GAC3CA,IAIF,IAAIE,EAAa,GACjB,KAAOF,EAAIF,EAAM,QAAU,CAAC,qCAAqC,KAAKA,EAAME,CAAC,CAAC,GAC5EE,GAAcJ,EAAME,CAAC,EACrBA,IAGFD,EAAO,KAAK,CAAE,KAAM,EAAgB,MAAOG,CAAW,CAAC,EACvD,QACF,CAGA,GAAID,IAAS,KAAOA,IAAS,IAAK,CAChC,IAAME,EAAQF,EACVG,EAAQD,EAGZ,IAFAH,IAEOA,EAAIF,EAAM,QAAUA,EAAME,CAAC,IAAMG,GAElCL,EAAME,CAAC,IAAM,MAAQA,EAAI,EAAIF,EAAM,QAAUA,EAAME,EAAI,CAAC,IAAMG,GAChEC,GAAS,KAAOD,EAChBH,GAAK,IAELI,GAASN,EAAME,CAAC,EAChBA,KAIAA,EAAIF,EAAM,SACZM,GAASD,EACTH,KAGFD,EAAO,KAAK,CAAE,KAAM,EAAoB,MAAAK,CAAM,CAAC,EAC/C,QACF,CAGA,GAAI,QAAQ,KAAKH,CAAI,EAAG,CACtB,IAAIG,EAAQ,GACRC,EAAa,GAEjB,KAAOL,EAAIF,EAAM,SAAW,QAAQ,KAAKA,EAAME,CAAC,CAAC,GAAMF,EAAME,CAAC,IAAM,KAAO,CAACK,IACtEP,EAAME,CAAC,IAAM,MACfK,EAAa,IAEfD,GAASN,EAAME,CAAC,EAChBA,IAGFD,EAAO,KAAK,CAAE,KAAM,EAAoB,MAAAK,CAAM,CAAC,EAC/C,QACF,CAGA,GAAI,aAAa,KAAKH,CAAI,EAAG,CAC3B,IAAIG,EAAQ,GACRE,EAAiB,GAGrB,KAAON,EAAIF,EAAM,QACf,GAAI,iBAAiB,KAAKA,EAAME,CAAC,CAAC,EAChCI,GAASN,EAAME,CAAC,EAChBA,YACSF,EAAME,CAAC,IAAM,IAAK,CAE3B,IAAIO,EAAe,EAEnB,IADAH,GAASN,EAAME,GAAG,EACXA,EAAIF,EAAM,QAAUS,EAAe,GACpCT,EAAME,CAAC,IAAM,KAAKO,IAClBT,EAAME,CAAC,IAAM,KAAKO,IACtBH,GAASN,EAAME,GAAG,CAEtB,KACE,OAKJ,IAAIQ,EAAU,EACd,KAAOR,EAAIF,EAAM,QAAU,KAAK,KAAKA,EAAME,CAAC,CAAC,GAC3CQ,IACAR,IAIF,GAAIA,EAAIF,EAAM,QAAUA,EAAME,CAAC,IAAM,IAAK,CACxCM,EAAiB,GAEjBF,GAAS,IACTJ,IAEA,IAAIS,EAAa,EACjB,KAAOT,EAAIF,EAAM,QAAUW,EAAa,GAClCX,EAAME,CAAC,IAAM,KAAKS,IAClBX,EAAME,CAAC,IAAM,KAAKS,IACtBL,GAASN,EAAME,GAAG,CAEtB,MAEEA,GAAKQ,EAGP,IAAME,EAAYX,EAAOA,EAAO,OAAS,CAAC,EACpCY,EAAqBb,EAAME,EAAII,EAAM,OAAS,CAAC,IAAM,KAAOM,GAAW,OAAS,EAEtFX,EAAO,KAAK,CACV,KAAMO,GAAkBK,EAAqB,EAAyB,EACtE,MAAAP,CACF,CAAC,EACD,QACF,CAGAJ,GACF,CAEA,OAAOD,CACT,CAaO,SAASa,GAAad,EAA2B,CACtD,IAAMC,EAAqB,CAAC,EAEtBc,EAAQf,EAAM,QAAQ,GAAG,EACzBgB,EAAMhB,EAAM,YAAY,GAAG,EACjC,GAAIe,IAAU,IAAMC,IAAQ,IAAMA,GAAOD,EACvC,MAAM,IAAI,MAAM,8BAA8B,EAGhD,IAAME,EAAUjB,EAAM,MAAMe,EAAQ,EAAGC,CAAG,EACtC,EAAI,EAER,KAAO,EAAIC,EAAQ,QAAQ,CACzB,IAAMd,EAAOc,EAAQ,CAAC,EAEtB,GAAI,KAAK,KAAKd,CAAI,EAAG,CACnB,IACA,QACF,CAEA,GAAIA,IAAS,KAAOA,IAAS,IAAK,CAChC,IAAMe,EAAYf,EACdG,EAAQ,GAEZ,IADA,IACO,EAAIW,EAAQ,QAAUA,EAAQ,CAAC,IAAMC,GACtCD,EAAQ,CAAC,IAAM,MACjB,IACI,EAAIA,EAAQ,SACdX,GAASW,EAAQ,CAAC,IAGpBX,GAASW,EAAQ,CAAC,EAEpB,IAEF,GAAI,GAAKA,EAAQ,OACf,MAAM,IAAI,MAAM,kCAAkC,EAGpD,IACAhB,EAAO,KAAK,CAAE,KAAM,SAAU,MAAAK,CAAM,CAAC,EACrC,QACF,CAGA,GAAI,QAAQ,KAAKH,CAAI,EAAG,CACtB,IAAIgB,EAAS,GACb,KAAO,EAAIF,EAAQ,QAAU,SAAS,KAAKA,EAAQ,CAAC,CAAC,GACnDE,GAAUF,EAAQ,CAAC,EACnB,IAEFhB,EAAO,KAAK,CAAE,KAAM,SAAU,MAAO,WAAWkB,CAAM,CAAE,CAAC,EACzD,QACF,CAEA,GAAI,YAAY,KAAKhB,CAAI,EAAG,CAC1B,IAAIiB,EAAQ,GACZ,KAAO,EAAIH,EAAQ,QAAU,iBAAiB,KAAKA,EAAQ,CAAC,CAAC,GAC3DG,GAASH,EAAQ,CAAC,EAClB,IAEFhB,EAAO,KAAK,CAAE,KAAM,aAAc,MAAOmB,CAAM,CAAC,EAChD,QACF,CAEA,GAAIjB,IAAS,IAAK,CAChB,IACA,QACF,CAEA,MAAM,IAAI,MAAM,sCAAsCA,CAAI,EAAE,CAC9D,CAEA,OAAOF,CACT,CAoCO,SAASoB,GAAiBC,EAAmC,CAClE,IAAMrB,EAA0B,CAAC,EAC7BsB,EAAe,EAEnB,KAAOA,EAAeD,EAAS,QAAQ,CACrC,IAAME,EAAeF,EAAS,QAAQ,KAAMC,CAAY,EAExD,GAAIC,IAAiB,GAAI,CACvBvB,EAAO,KAAKwB,GAAkBH,EAAS,MAAMC,CAAY,CAAC,CAAC,EAC3D,KACF,CAEIC,EAAeD,GACjBtB,EAAO,KAAKwB,GAAkBH,EAAS,MAAMC,EAAcC,CAAY,CAAC,CAAC,EAG3E,GAAM,CAAE,MAAOE,EAAU,SAAAC,EAAU,SAAAC,CAAS,EAAIC,GAAgBP,EAAUE,CAAY,EACtF,GAAI,CAACI,EACH,MAAM,IAAI,MAAM,2CAA2CJ,CAAY,eAAeF,CAAQ,EAAE,EAElGrB,EAAO,KAAK6B,GAAoBJ,CAAQ,CAAC,EACzCH,EAAeI,CACjB,CAEA,OAAO1B,CACT,CAEA,SAASwB,GAAkBnB,EAA8B,CACvD,MAAO,CAAE,KAAM,SAAU,MAAAA,CAAM,CACjC,CAEA,SAASwB,GAAoBxB,EAA8B,CACzD,MAAO,CAAE,KAAM,WAAY,MAAAA,CAAM,CACnC,CAEA,SAASuB,GAAgBP,EAAkBS,EAIzC,CACA,IAAMC,EAAO,KACPC,EAAQ,KACV/B,EAAI6B,EAAaC,EAAK,OACtBE,EAAQ,EAEZ,KAAOhC,EAAIoB,EAAS,QAAUY,EAAQ,GAChCZ,EAAS,MAAMpB,EAAGA,EAAI8B,EAAK,MAAM,IAAMA,GACzCE,IACAhC,GAAK8B,EAAK,QACDV,EAAS,MAAMpB,EAAGA,EAAI+B,EAAM,MAAM,IAAMA,GACjDC,IACAhC,GAAK+B,EAAM,QAEX/B,IAIJ,IAAM0B,EAAWM,IAAU,EACrBP,EAAWC,EAAW1B,EAAIoB,EAAS,OAGzC,MAAO,CAAE,MAFKA,EAAS,MAAMS,EAAYJ,CAAQ,EAEjC,SAAAA,EAAU,SAAAC,CAAS,CACrC,CClVO,SAASO,GAAeC,EAAkBC,EAAiD,CAChG,IAAMC,EAAyBC,GAAiBH,CAAQ,EAAE,IAAII,GAC5DA,EAAM,OAAS,SACX,CAACC,EAAOC,IAAeF,EAAM,MAC7BG,GAAkBH,EAAOH,CAAO,CACtC,EAEA,MAAO,CAACO,EAAMC,IAAcP,EAAS,IAAIQ,GAAMA,EAAGF,EAAMC,CAAS,CAAC,EAAE,KAAK,EAAE,CAC7E,CAEA,SAASF,GAAkBH,EAAsBH,EAA6C,CAC5F,IAAMU,EAASC,GAASR,EAAM,KAAK,EAC7BS,EAAQC,GAAqBH,EAAQP,EAAM,MAAOH,GAAS,YAAY,EAC7E,OAAOc,GAAgBF,CAAK,CAC9B,CAEA,SAASC,GACPH,EACAK,EACAC,EACiB,CACjB,IAAIJ,EAAgC,KAC/BI,IACHA,EAAeC,GAGjB,QAAWd,KAASO,EAClB,OAAQP,EAAM,KAAM,CAClB,OACE,MAAM,MAAM,4BAA4BA,EAAM,KAAK,EAAE,EAEvD,OAAyB,CAEvBS,EAAQ,CAAE,OADOM,GAAef,EAAM,KAAK,EACf,MAAO,CAAC,CAAE,EACtC,KACF,CAEA,OAA6B,CAE3BS,EAAQ,CACN,OAFWO,GAAgBhB,EAAM,KAAK,EAGtC,MAAO,CAAC,CACV,EACA,KACF,CAEA,OAAqB,CACnB,GAAI,CAACS,EAAO,MAAM,MAAM,SAAST,EAAM,KAAK,iCAAiCY,CAAU,EAAE,EACzF,GAAI,CAACZ,EAAM,OAASA,EAAM,QAAU,GAClC,MAAM,MAAM,qDAAuDY,CAAU,EAG/E,GAAM,CAACK,EAAU,GAAGC,CAAI,EAAIlB,EAAM,MAAM,MAAM,GAAG,EAAE,IAAKmB,GAAMA,EAAE,KAAK,CAAC,EAChEC,EAAOP,EAAa,OAAOI,CAAQ,EACzC,GAAI,CAACG,EAAM,MAAM,MAAM,mBAAmBH,CAAQ,EAAE,EACpDR,EAAM,MAAM,KAAKY,GAASD,EAAKC,EAAOH,CAAI,CAAC,EAC3C,KACF,CACF,CAGF,GAAI,CAACT,EAAO,MAAM,MAAM,uBAAuBG,CAAU,EAAE,EAC3D,OAAOH,CACT,CAEA,SAASE,GAAgBF,EAAoC,CAC3D,MAAO,CAACL,EAAMC,IAAc,CAC1B,IAAMiB,EAAUb,EAAM,OAAOL,EAAMC,CAAS,EACtCkB,EAASd,EAAM,MAAM,OAAO,CAACe,EAAKlB,IAAOA,EAAGkB,CAAG,EAAGF,CAAO,EAC/D,OAAOC,GAAU,KAAOA,EAAO,SAAS,EAAI,EAC9C,CACF,CAEA,SAASP,GAAgBS,EAA0C,CACjE,IAAMC,EAAMD,EAAW,QAAQ,GAAG,EAClC,GAAIC,IAAQ,GAAI,MAAM,MAAM,qBAAqBD,CAAU,EAAE,EAG7D,IAAME,EADOC,GAAaH,CAAU,EAC8B,IAAII,GAAO,CAC3E,GAAIA,EAAI,OAAS,UAAYA,EAAI,OAAS,SAAU,MAAO,IAAMA,EAAI,MACrE,GAAIA,EAAI,OAAS,aAAc,OAAOzB,GAAQW,GAAec,EAAI,KAAK,EAAEzB,CAAI,EAC5E,MAAM,MAAM,8BAA+ByB,EAAY,IAAI,EAAE,CAC/D,CAAC,EAEKC,EAAOL,EAAW,UAAU,EAAGC,CAAG,EAClCK,EAAahB,GAAee,CAAI,EAEtC,MAAO,CAAC1B,EAAMC,IAAc,CAC1B,GAAI,CAACA,EAAW,MAAM,MAAM,8CAA8CyB,CAAI,GAAG,EACjF,IAAMxB,EAAKyB,EAAW1B,CAAS,EAC/B,GAAI,OAAOC,GAAO,WAAY,MAAM,MAAM,aAAawB,CAAI,qBAAqB,EAChF,IAAME,EAAgBL,EAAa,IAAIM,GAASA,EAAM7B,CAAI,CAAC,EAC3D,OAAOE,EAAG,MAAMD,EAAW2B,CAAa,CAC1C,CACF,CClFO,IAAME,GAAN,KAAgB,CACrB,YACmBC,EACAC,EACAC,EACAC,EACjB,CAJiB,UAAAH,EACA,cAAAC,EACA,mBAAAC,EACA,eAAAC,CACf,CAEJ,OAAOC,EAAwC,CAC7C,QAAWC,KAAW,KAAK,SACrBA,EAAQ,OAAS,OACnBA,EAAQ,KAAKD,EAAMC,EAAQ,IAAI,EAE/BA,EAAQ,KAAKD,EAAMC,EAAQ,OAAO,EAItC,QAAWC,KAAS,KAAK,cAAe,CACtC,IAAMC,EAAO,KAAK,cAAc,KAAK,KAAMD,EAAM,IAAI,EAC/CE,EAAS,KAAK,YAAYF,EAAM,UAAU,EAE5CC,aAAgB,aAAe,OAAOC,GAAW,aACnDD,EAAK,QAAWE,GAAe,CAC7B,IAAMC,EAAOJ,EAAM,UAAU,IAAIK,GAAS,CACxC,GAAIA,EAAM,OAAS,UAAYA,EAAM,OAAS,SAC5C,OAAOA,EAAM,MAEf,GAAIA,EAAM,OAAS,aACjB,OAAIA,EAAM,QAAU,QACXF,EAGKE,EAAM,MAAM,MAAM,GAAG,EACtB,OAAO,CAACC,EAAKC,IAAQD,IAAMC,CAAG,EAAGT,CAAI,CAEtD,CAAC,EACDI,EAAO,MAAM,KAAK,UAAWE,CAAI,CACnC,EAEJ,CAEA,OAAO,KAAK,IACd,CAEQ,cAAcV,EAAYc,EAAsB,CACtD,OAAOA,EAAK,OAAO,CAACP,EAAMQ,IAAUR,EAAK,WAAWQ,CAAK,EAAGf,CAAI,CAClE,CACF,EAEO,SAASgB,GAAgBC,EAAyB,CACvD,IAAIC,EAAK,IAAIC,GAAUF,CAAI,EAC3B,OAAOC,CACT,CAEO,IAAMC,GAAN,KAAgB,CAKrB,YAAYC,EAA8C,CACxD,GAAI,OAAOA,GAAmB,SAAU,CACtC,IAAMC,EAAUD,EAAe,KAAK,EACpC,GAAIC,EAAQ,WAAW,WAAW,EAAG,CACnC,IAAMC,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAYD,EACpB,IAAME,EAAQD,EAAQ,cAAc,UAAU,EAC9C,GAAI,CAACC,EAAO,MAAM,IAAI,MAAM,2CAA2C,EACvE,KAAK,SAAWA,CAClB,MACE,KAAK,SAAW,SAAS,cAAc,UAAU,EACjD,KAAK,SAAS,UAAYF,CAE9B,MACE,KAAK,SAAWD,EAGlB,IAAMI,EAAc,KAAK,eAAe,EACxC,KAAK,SAAW,KAAK,gBAAgBA,CAAW,EAChD,KAAK,cAAgB,KAAK,qBAAqBA,CAAW,CAC5D,CAEA,eAAerB,EAA4C,CACzD,IAAMsB,EAAY,KAAK,eAAe,EAAE,UAAU,EAAI,EAChDC,EAAmBvB,GAAa,CAAC,EAEjCwB,EAAgC,KAAK,SAAS,IAAItB,GAAW,CACjE,IAAME,EAAO,KAAK,cAAckB,EAAWpB,EAAQ,IAAI,EACvD,OAAIA,EAAQ,OAAS,OACZ,CACL,KAAM,OACN,KAAAE,EACA,KAAM,CAACH,EAAMG,IAASF,EAAQ,KAAKD,EAAMsB,EAAkBnB,CAAI,CACjE,EAEO,CACL,KAAM,YACN,QAASA,EACT,KAAMF,EAAQ,KACd,KAAM,CAACD,EAAMG,IAASF,EAAQ,KAAKD,EAAMsB,EAAkBnB,CAAI,CACjE,CAEJ,CAAC,EAED,OAAO,IAAIR,GAAU0B,EAAWE,EAAe,KAAK,cAAexB,CAAS,CAC9E,CAEQ,gBAA8B,CACpC,IAAMyB,EAAK,MAAM,KAAK,KAAK,SAAS,QAAQ,UAAU,EAAE,KACtDrB,GAAQA,EAAK,WAAa,KAAK,YACjC,EACA,GAAI,EAAEqB,aAAc,aAClB,MAAM,IAAI,MAAM,6CAA6C,EAE/D,OAAOA,CACT,CAEQ,gBAAgB5B,EAAiC,CACvD,IAAMC,EAAyB,CAAC,EAE1B4B,EAAO,CAACtB,EAAYO,EAAiB,CAAC,IAAM,CAChD,GAAIP,EAAK,WAAa,KAAK,WAAaA,EAAK,aACvCA,EAAK,YAAY,MAAM,sBAAsB,EAAG,CAClD,IAAMuB,EAAOC,GAAexB,EAAK,WAAW,EAC5CN,EAAS,KAAK,CACZ,KAAM,OACN,KAAM,CAAC,GAAGa,CAAI,EACd,KAAM,CAACV,EAAMD,EAAW6B,IAAe,CACrCA,EAAW,YAAcF,EAAK1B,EAAMD,CAAS,CAC/C,CACF,CAAC,CACH,CAGF,GAAII,EAAK,WAAa,KAAK,aAAc,CACvC,IAAM0B,EAAU1B,EAEhB,GAAI0B,EAAQ,UAAY,WAAY,OAEpC,QAASC,EAAI,EAAGA,EAAID,EAAQ,WAAW,OAAQC,IAAK,CAClD,IAAMC,EAAOF,EAAQ,WAAWC,CAAC,EACjC,GAAIC,EAAK,MAAM,MAAM,sBAAsB,EAAG,CAC5C,IAAML,EAAOC,GAAeI,EAAK,KAAK,EACtClC,EAAS,KAAK,CACZ,KAAM,YACN,KAAM,CAAC,GAAGa,CAAI,EACd,KAAMqB,EAAK,KACX,KAAM,CAAC/B,EAAMD,EAAWyB,IAAO,CAC7BA,EAAG,aAAaO,EAAK,KAAML,EAAK1B,EAAMD,CAAS,CAAC,CAClD,CACF,CAAC,CACH,CACF,CAEA,MAAM,KAAKI,EAAK,UAAU,EAAE,QAAQ,CAAC6B,EAAOrB,IAAU,CACpDc,EAAKO,EAAO,CAAC,GAAGtB,EAAMC,CAAK,CAAC,CAC9B,CAAC,CACH,CACF,EAEA,OAAAc,EAAK7B,CAAI,EACFC,CACT,CAEQ,qBAAqBD,EAA4B,CACvD,IAAMC,EAA2B,CAAC,EAE5B4B,EAAO,CAACtB,EAAYO,EAAiB,CAAC,IAAM,CAChD,GAAIP,EAAK,WAAa,KAAK,aAAc,CAEvC,IAAM8B,EADU9B,EACU,aAAa,OAAO,EAC9C,GAAI8B,GAAW,KAAK,EAAG,CACrB,IAAMhB,EAAUgB,EAAU,KAAK,EAEzBC,EAAQjB,EAAQ,MAAM,iCAAiC,EAC7D,GAAIiB,EAAO,CACT,IAAMC,EAAaD,EAAM,CAAC,EACpBE,EAAYC,GAAapB,CAAO,EACtCpB,EAAS,KAAK,CAAE,KAAM,CAAC,GAAGa,CAAI,EAAG,WAAAyB,EAAY,UAAAC,CAAU,CAAC,CAC1D,MAEEvC,EAAS,KAAK,CAAE,KAAM,CAAC,GAAGa,CAAI,EAAG,WAAYO,EAAS,UAAW,CAAC,CAAE,CAAC,CAEzE,CAEA,MAAM,KAAKd,EAAK,UAAU,EAAE,QAAQ,CAAC6B,EAAOrB,IAAU,CACpDc,EAAKO,EAAO,CAAC,GAAGtB,EAAMC,CAAK,CAAC,CAC9B,CAAC,CACH,CACF,EAEA,OAAAc,EAAK7B,CAAI,EACFC,CACT,CAEQ,cAAcD,EAAYc,EAAsB,CACtD,OAAOA,EAAK,OAAO,CAACP,EAAMQ,IAAUR,EAAK,WAAWQ,CAAK,EAAGf,CAAI,CAClE,CACF,EC1OO,IAAM0C,GAAN,KAAoB,CASzB,YACEC,EACAC,EACAC,EACAC,EACA,CAVF,KAAQ,QAAU,IAAI,IACtB,KAAQ,OAAS,IAAI,IAUnB,KAAK,MAAQH,EACb,KAAK,SAAWC,EAChB,KAAK,SAAWC,EAChB,KAAK,UAAYC,CACnB,CAEO,OAAOC,EAA6B,CACzC,KAAK,UAAU,EACf,QAAWC,KAAQD,EACjB,KAAK,UAAUC,CAAI,CAEvB,CAEQ,WAAkB,CACxB,KAAK,MAAM,QAAQ,CAAC,EAAE,UAAY,GAClC,KAAK,QAAQ,MAAM,EACnB,KAAK,OAAO,MAAM,CACpB,CAEQ,UAAUD,EAAiC,CACjD,IAAME,EAAKF,EAAK,KAAK,QAAQ,EAC7B,GAAwBE,GAAO,KAC7B,MAAM,IAAI,MAAM,qBAAqB,KAAK,QAAQ,WAAW,EAG/D,IAAMC,EAAM,KAAK,SAAS,QAAQ,mBAAmB,UAAU,EAAI,EACnE,GAAI,CAACA,EAAK,MAAM,IAAI,MAAM,8CAA8C,EAExE,KAAK,YAAYA,EAAKH,CAAI,EAC1B,KAAK,oBAAoBG,EAAKH,CAAI,EAElC,KAAK,MAAM,QAAQ,CAAC,EAAE,YAAYG,CAAG,EACrC,KAAK,QAAQ,IAAID,EAAIF,CAAI,EACzB,KAAK,OAAO,IAAIE,EAAIC,CAAG,CACzB,CAEQ,YAAYA,EAA0BH,EAAiC,CAC/DG,EAAI,iBAAiB,cAAc,EAC3C,QAASC,GAAS,CACtB,IAAMC,EAASD,EAAqB,QAAQ,MACxCC,GAASA,KAASL,IACpBI,EAAK,YAAc,OAAOJ,EAAKK,CAAK,CAAC,EAEzC,CAAC,CACH,CAEQ,oBAAoBF,EAAkBH,EAAiC,CACjDG,EAAI,iBAAiB,WAAW,EACxC,QAASG,GAAO,CAClC,IAAMC,EAAUD,EACVE,EAAcD,EAAQ,aAAa,SAAS,EAClD,GAAI,CAACC,EAAa,OAElB,IAAMC,EAAQD,EAAY,MAAM,uBAAuB,EACvD,GAAI,CAACC,EAAO,OAEZ,GAAM,CAAC,CAAEC,EAAY,CAAEC,CAAM,EAAIF,EAC3BG,EAAOD,EAASA,EAAO,MAAM,GAAG,EAAE,IAAIE,GAAKA,EAAE,KAAK,EAAE,QAAQ,eAAgB,EAAE,CAAC,EAAI,CAAC,EAEtF,OAAQ,KAAK,UAAkBH,CAAU,GAAM,aACjDH,EAAQ,gBAAgB,SAAS,EACjCA,EAAQ,iBAAiB,QAAUO,GAAU,CAC1C,KAAK,UAAkBJ,CAAU,EAAE,GAAGE,EAAMZ,EAAMc,CAAK,CAC1D,CAAC,EAEL,CAAC,CACH,CAEO,OAAOd,EAA2B,CACvC,IAAME,EAAKF,EAAK,KAAK,QAAQ,EAC7B,GAAwBE,GAAO,KAC7B,MAAM,IAAI,MAAM,qBAAqB,KAAK,QAAQ,kBAAkB,EAGtE,IAAMC,EAAM,KAAK,OAAO,IAAID,CAAE,EACzBC,GAGH,KAAK,YAAYA,EAAKH,CAAI,EAC1B,KAAK,oBAAoBG,EAAKH,CAAI,EAClC,KAAK,QAAQ,IAAIE,EAAIF,CAAI,GAJzB,KAAK,UAAUA,CAAI,CAMvB,CACF,EAEae,GAAN,cAA8B,WAA0B,CAC7D,YAAYC,EAA2B,CACrC,MAAM,aAAc,CAClB,OAAQA,EACR,QAAS,GACT,SAAU,EACZ,CAAC,CACH,CACF,EAOaC,GAAN,KAAkB,CAKvB,YAAYrB,EAAyBG,EAAwB,CAH7D,KAAQ,YAA4B,CAAC,EAInC,KAAK,MAAQH,EACb,KAAK,UAAYG,EACjB,KAAK,eAAe,CACtB,CAEQ,gBAAiB,CACP,KAAK,MAAM,OAAO,iBAAiB,UAAU,GACpD,QAASmB,GAAO,CACvBA,EAAG,iBAAiB,QAAS,IAAM,CACjC,IAAMC,EAASD,EAAG,aAAa,MAAM,EACrC,KAAK,OAAOC,CAAM,EAClB,KAAK,qBAAqB,EAC1B,KAAK,KAAK,CACZ,CAAC,CACH,CAAC,CACH,CAEQ,OAAOA,EAAgB,CAC7B,IAAMC,EAAQ,KAAK,YAAY,UAAUC,GAAKA,EAAE,SAAWF,CAAM,EAE7DC,IAAU,GACZ,KAAK,YAAY,KAAK,CAAE,OAAAD,EAAQ,UAAW,KAAM,CAAC,EACzC,KAAK,YAAYC,CAAK,EAAE,YAAc,MAC/C,KAAK,YAAYA,CAAK,EAAE,UAAY,OAEpC,KAAK,YAAY,OAAOA,EAAO,CAAC,CAEpC,CAEQ,MAAO,CACb,IAAMN,EAAQ,IAAIC,GAAgB,KAAK,WAAW,EAC9C,KAAK,UAAU,cAAcD,CAAK,CACxC,CAES,sBAAuB,CACd,KAAK,MAAM,OAAO,iBAAiB,UAAU,GACpD,QAASR,GAAO,CACvB,IAAMY,EAAKZ,EAELgB,EAAoBJ,EAAG,cAAc,iBAAiB,EACxDI,GACFJ,EAAG,YAAYI,CAAiB,EAIlC,IAAMH,EAASD,EAAG,aAAa,MAAM,EAC/BK,EAAW,KAAK,YAAY,KAAKF,GAAKA,EAAE,SAAWF,CAAM,EAE/D,GAAII,EAAU,CAEZ,IAAMC,EAAY,SAAS,cAAc,MAAM,EAC/CA,EAAU,UAAY,iBACtBA,EAAU,YAAcD,EAAS,YAAc,MAAQ,SAAM,SAG7DC,EAAU,MAAM,MAAQ,QACxBA,EAAU,MAAM,WAAa,MAG7BN,EAAG,YAAYM,CAAS,CAC1B,CAGKN,EAAG,MAAM,WACZA,EAAG,MAAM,SAAW,WAExB,CAAC,CACH,CAEO,gBAA+B,CACpC,MAAO,CAAC,GAAG,KAAK,WAAW,CAC7B,CAEO,OAAQ,CACb,KAAK,YAAc,CAAC,EACpB,KAAK,qBAAqB,EAC1B,KAAK,KAAK,CACZ,CACF,ECpMO,IAAKO,QAIRA,IAAA,iBAKAA,IAAA,eAKAA,IAAA,uBAKAA,IAAA,eAnBQA,QAAA,IAyICC,EAAN,cAAyB,KAAM,CAAC,EAC1BC,EAAN,cAA8BD,CAAW,CAAzC,kCACH,aAAU,GACd,EC1IO,IAAME,EAAN,MAAMC,UAA2B,KAAM,CA+B1C,YAIWC,EAKAC,EAKAC,EAOAC,EAEPC,EACF,CACE,MAAML,EAAmB,KAAMK,CAAS,EArBjC,WAAAJ,EAKA,iBAAAC,EAKA,eAAAC,EAOA,iBAAAC,EApCX,cAAoB,EAyCpB,CAxDA,YAAO,KAAe,oBAyD1B,EC9BO,IAAME,EAAN,KAAwB,CAAxB,cACH,KAAQ,QAA6B,CAAC,EACtC,KAAQ,aAAe,GAEvB,OAAOC,EAA8B,CAC7B,KAAK,aAAe,KAAK,QAAQ,OAAS,IAC1C,KAAK,QAAQ,OAAS,KAAK,aAAe,GAE9C,KAAK,QAAQ,KAAKA,CAAK,EACvB,KAAK,aAAe,KAAK,QAAQ,OAAS,CAC9C,CAEA,WAAqB,CACjB,OAAO,KAAK,aAAe,CAC/B,CAEA,cAAwB,CACpB,OAAO,KAAK,cAAgB,GAAK,KAAK,aAAe,KAAK,QAAQ,OAAS,CAC/E,CAEA,MAAoC,CAChC,GAAK,KAAK,UAAU,EACpB,YAAK,eACE,KAAK,QAAQ,KAAK,YAAY,CACzC,CAEA,SAAuC,CACnC,GAAK,KAAK,aAAa,EACvB,YAAK,eACE,KAAK,QAAQ,KAAK,YAAY,CACzC,CAOA,aAAaC,EAA8C,CACvD,IAAMC,EAAQ,KAAK,QAAQ,UAAWC,GAAMA,EAAE,UAAYF,CAAO,EACjE,GAAI,EAAAC,EAAQ,GACZ,YAAK,aAAeA,EACb,KAAK,QAAQA,CAAK,CAC7B,CAEA,SAAuC,CACnC,GAAI,OAAK,aAAe,GACxB,OAAO,KAAK,QAAQ,KAAK,YAAY,CACzC,CAGA,MAAe,CACX,OAAO,KAAK,QAAQ,MACxB,CACJ,ECzEA,IAAME,EAAU,IAAI,IACdC,EAAgB,IAAI,IACpBC,GAAoB,IAAI,IAiBvB,SAASC,GACZC,EACAC,EACF,CAEE,GADAC,GAAwB,EACpBN,EAAQ,IAAII,CAAI,EAAG,CACnB,IAAMG,EAAQC,EAAY,yBAA0B,CAChD,OAAQJ,GAAQ,SACpB,CAAC,EACD,GAAIG,EAAO,MAAMA,EACjB,MACJ,CAEA,IAAME,EAAkBP,GAAkB,IAAIE,CAAI,EAC5CM,EAAUD,GAAmB,IAAIE,EACvCT,GAAkB,OAAOE,CAAI,EAC7BJ,EAAQ,IAAII,EAAM,CAAE,QAAAC,EAAS,QAAAK,CAAQ,CAAC,EAElC,OAAO,YAAY,SACnB,QAAQ,IAAI,sCAAuCN,GAAQ,UAAW,CAClE,gBAAiBK,IAAoB,MACzC,CAAC,EAGL,IAAMG,EAAUX,EAAc,IAAIG,CAAI,EAClCQ,IACAX,EAAc,OAAOG,CAAI,EACrB,OAAO,YAAY,SACnB,QAAQ,IACJ,4DACAA,GAAQ,UACRQ,EAAQ,MAAM,IAClB,EAEJC,GAAiBD,CAAO,EAEhC,CASO,SAASE,GAAsBV,EAA0B,CAC5D,IAAMW,EAAMf,EAAQ,IAAII,CAAI,EACxBW,GACAb,GAAkB,IAAIE,EAAMW,EAAI,OAAO,EAE3Cf,EAAQ,OAAOI,CAAI,CACvB,CASO,SAASY,EAAiBZ,EAA8C,CAC3E,OAAOJ,EAAQ,IAAII,CAAI,GAAG,OAC9B,CAEO,SAASa,IAA0B,CACtChB,EAAc,MAAM,EACpBD,EAAQ,MAAM,EACdE,GAAkB,MAAM,CAC5B,CAEA,SAASgB,GAAeC,EAAsD,CAC1E,GAAIA,EAAI,UAAY,QACfA,EAAI,MAAM,KACf,MAAO,CACH,UAAWA,EAAI,MAAM,KACrB,OAAQA,EAAI,WAAa,CAAC,EAC1B,OAAQA,EAAI,YACZ,YAAaA,EAAI,YACjB,QAASA,EAAI,QACb,SAAUA,EAAI,QAClB,CACJ,CAEA,SAASN,GAAiBM,EAAyB,CAC/C,IAAMJ,EAAMf,EAAQ,IAAImB,EAAI,WAAW,EACvC,GAAI,CAACJ,EAAK,CACF,OAAO,YAAY,SACnB,QAAQ,IACJ,4DACAI,EAAI,aAAe,UACnBA,EAAI,MAAM,KACV,CACI,yBAA0BlB,EAAc,IAAIkB,EAAI,WAAW,EAC3D,kBAAmB,MAAM,KAAKnB,EAAQ,KAAK,EAAII,GAASA,GAAQ,SAAS,CAC7E,CACJ,EAEJH,EAAc,IAAIkB,EAAI,YAAaA,CAAG,EACtC,MACJ,CAEA,GAAIA,EAAI,SACAA,EAAI,UAAY,QAChBJ,EAAI,QAAQ,aAAaI,EAAI,OAAO,MAErC,CACH,IAAMC,EAAQF,GAAeC,CAAG,EAC5BC,GACAL,EAAI,QAAQ,OAAOK,CAAK,CAEhC,CAEAL,EAAI,QAAQI,CAAG,CACnB,CAEA,IAAIE,GAAmB,GAEhB,SAASf,IAA0B,CAClCe,KACJA,GAAmB,GACnB,SAAS,iBAAiBC,EAAmB,KAAOH,GAAQ,CACxDN,GAAiBM,CAAyB,CAC9C,CAAC,EACL,CC7HA,IAAMI,GAAN,KAAiD,CAC7C,YAAmBC,EAAmB,CAAnB,eAAAA,CAAoB,CACvC,QAAQC,EAAwB,CAC5B,MAAI,UAAQ,KAAKA,CAAK,CAI1B,CAEA,SAASC,EAAmC,CACxC,GAAI,QAAQ,KAAKA,CAAS,IAAM,GAC5B,MAAM,IAAI,MACN,yCAAyC,KAAK,SAAS,cAAcA,CAAS,IAClF,EAEJ,OAAO,SAASA,CAAS,CAC7B,CACJ,EAMMC,GAAN,KAAiD,CAC7C,YAAmBH,EAAmB,CAAnB,eAAAA,CAAoB,CACvC,QAAQI,EAAyB,CAC7B,MAAO,EACX,CAOA,SAASF,EAAmC,CACxC,OAAOA,CACX,CACJ,EAMMG,GAAN,KAA+C,CAC3C,YAAmBJ,EAAe,CAAf,WAAAA,CAAgB,CACnC,QAAQA,EAAwB,CAC5B,OAAOA,GAAS,KAAK,KACzB,CAEA,SAASK,EAAoC,CACzC,OAAO,KAAK,KAChB,CACJ,EAMMC,GAAN,KAAe,CACX,YAAmBC,EAAsBC,EAA0B,CAAhD,WAAAD,EAAsB,cAAAC,CAA2B,CAOpE,MAAMA,EAA6C,CAC/C,GAAIA,EAAS,QAAU,KAAK,SAAS,OACjC,OAAO,KAGX,IAAMC,EAA8B,CAAC,EACrC,IAAIC,EAAoB,CAAC,EACzB,QAASC,EAAQ,EAAGA,EAAQH,EAAS,OAAQG,IAAS,CAClD,IAAMC,EAAaJ,EAASG,CAAK,EAC3BE,EAAa,KAAK,SAASF,CAAK,EAEtC,GAAI,CAACE,EAAW,QAAQD,CAAU,EAC9B,OAAO,KAGX,GAAIC,EAAW,UAAW,CACtB,IAAMb,EAAQa,EAAW,SAASD,CAAU,EAC5CF,EAAOG,EAAW,SAAS,EAAIb,EAC/BS,EAAkB,KAAKT,EAAM,SAAS,CAAC,CAC3C,MACIS,EAAkB,KAAKG,CAAU,CAEzC,CAEA,MAAO,CAAE,MAAO,KAAK,MAAO,OAAAF,EAAQ,YAAaD,CAAkB,CACvE,CAOA,SAASK,EAA+C,CACpD,IAAMC,EAAwB,CAAC,EACzBL,EAAoB,CAAC,EAErBM,EAAqC,CAAC,EAC5C,QAAWC,KAAO,OAAO,KAAKH,CAAS,EACnCE,EAAWC,EAAI,YAAY,CAAC,EAAIA,EAGpC,QAASN,EAAQ,EAAGA,EAAQ,KAAK,SAAS,OAAQA,IAAS,CACvD,IAAME,EAAa,KAAK,SAASF,CAAK,EACtC,GAAIE,EAAW,UAAW,CACtB,IAAIb,EAAQc,EAAUD,EAAW,SAAS,EAC1C,GAAIb,IAAU,OAAW,CACrB,IAAMkB,EAAUF,EAAWH,EAAW,UAAU,YAAY,CAAC,EACzDK,IAAY,SACZlB,EAAQc,EAAUI,CAAO,EAEjC,CACA,GAAI,CAAClB,EACD,MAAM,IAAI,MACN,UACI,KAAK,MAAM,IACf,sCACIa,EAAW,SACf,mCAAmC,KAAK,UACpCC,CACJ,CAAC,IACL,EAGJJ,EAAOG,EAAW,SAAS,EAAIb,EAC/Be,EAAY,KAAKf,EAAM,SAAS,CAAC,CACrC,MACIe,EAAY,KAAKF,EAAW,SAAS,EAAE,EAAE,SAAS,CAAC,CAE3D,CAEA,MAAO,CAAE,MAAO,KAAK,MAAO,OAAAH,EAAQ,YAAAK,CAAY,CACpD,CAEJ,EAQO,SAASI,GACZC,EACAC,EACAP,EACuB,CACvB,OAAIO,IAAmB,IAAMA,EAAe,QAAQ,GAAG,GAAK,EACjDC,GAAeF,EAAQC,GAAkB,GAAG,EAE5CE,EAAgBH,EAAQC,EAAgBP,CAAU,CAEjE,CAQO,SAASS,EACZH,EACAI,EACAV,EACuB,CACvB,IAAIP,EAAQa,EAAO,KAAMK,GAAMA,EAAE,OAASD,CAAI,EAC9C,GAAI,CAACjB,EACD,OAAO,KAGX,IAAImB,EAAMC,GAAiBpB,CAAK,EAC5BqB,EAASF,EAAI,SAASZ,GAAa,CAAC,CAAC,EACzC,OAAOc,CACX,CAOO,SAASN,GACZF,EACAS,EACuB,CACvB,IAAMd,EAAcc,EAAK,QAAQ,WAAY,EAAE,EAAE,MAAM,GAAG,EACpDC,EAAYC,GAAkBX,CAAM,EAE1C,QAAST,EAAQ,EAAGA,EAAQmB,EAAU,OAAQnB,IAAS,CAEnD,IAAMqB,EADUF,EAAUnB,CAAK,EACb,MAAMI,CAAW,EACnC,GAAIiB,EACA,OAAOA,CAEf,CAEA,OAAI,OAAO,YAAY,SACnB,QAAQ,IAAI,yCAA0CH,EAAM,CACxD,YAAAd,EACA,MAAOK,EAAO,IAAKb,IAAW,CAC1B,KAAMA,EAAM,KACZ,KAAMA,EAAM,KACZ,aAAcA,EAAM,KAAK,QAAQ,WAAY,EAAE,EAAE,MAAM,GAAG,EAAE,MAChE,EAAE,CACN,CAAC,EAGE,IACX,CAKA,SAASwB,GAAkBX,EAAiB,CACxC,IAAMU,EAAwB,CAAC,EAC/B,OAAAV,EAAO,QAASb,GAAU,CACtB,IAAImB,EAAMC,GAAiBpB,CAAK,EAChCuB,EAAU,KAAKJ,CAAG,CACtB,CAAC,EAEMI,CACX,CAMA,SAASH,GAAiBpB,EAAwB,CAC9C,IAAI0B,EAA8B,CAAC,EAClB1B,EAAM,KAAK,QAAQ,WAAY,EAAE,EAAE,MAAM,GAAG,EACpD,QAAS2B,GAAY,CACtBA,EAAQ,UAAU,EAAG,CAAC,GAAK,IAC3BD,EAAY,KAAK,IAAI/B,GAAmBgC,EAAQ,UAAU,CAAC,CAAC,CAAC,EACtDA,EAAQ,UAAU,EAAG,CAAC,IAAM,IACnCD,EAAY,KAAK,IAAInC,GAAmBoC,EAAQ,UAAU,CAAC,CAAC,CAAC,EAE7DD,EAAY,KAAK,IAAI7B,GAAiB8B,CAAO,CAAC,CAEtD,CAAC,EAED,IAAIR,EAAM,IAAIpB,GAASC,EAAO0B,CAAW,EACzC,OAAOP,CACX,CCpQO,IAAMS,EAAN,cAAwB,WAAY,CACvC,WAAW,oBAAqB,CAC5B,MAAO,CAAC,OAAQ,SAAU,SAAU,WAAW,CACnD,CAEA,aAAc,CACV,MAAM,EACN,KAAK,iBAAiB,QAASC,GAAK,KAAK,YAAYA,CAAC,CAAC,CAC3D,CAEQ,YAAYA,EAAgB,CAChCA,EAAE,eAAe,EAEjB,IAAMC,EAAY,KAAK,aAAa,WAAW,EAC/C,GAAIA,IAAc,QAAUA,IAAc,UAAW,CACjD,KAAK,qBAAqBA,CAAS,EACnC,MACJ,CAEA,IAAMC,EAAO,KAAK,aAAa,MAAM,EACrC,GAAI,CAACA,EAAM,OAEX,IAAMC,EAAiC,CAAC,EACxC,QAAWC,KAAQ,MAAM,KAAK,KAAK,UAAU,EACzC,GAAIA,EAAK,KAAK,WAAW,QAAQ,EAAG,CAEhC,IAAMC,EADMD,EAAK,KAAK,UAAU,CAAC,EACX,QAAQ,eAAgB,CAACE,EAAGC,IAAMA,EAAE,YAAY,CAAC,EACvEJ,EAAOE,CAAS,EAAID,EAAK,KAC7B,CAGJ,IAAMI,EAAa,KAAK,aAAa,QAAQ,EACzCC,EACJ,GAAID,EACA,GAAI,CAEAC,EADe,KAAK,MAAMD,CAAU,CAExC,OAASE,EAAO,CACZ,IAAMC,EAAMC,EAAY,+BAAgC,CACpD,QAAS,SACT,OAAQJ,EACR,MAAOE,CACX,CAAC,EACD,GAAIC,EAAK,MAAMA,CACnB,CAGJ,IAAME,EAAS,KAAK,aAAa,QAAQ,EACrCJ,GACA,OAAO,OAAON,EAAQM,CAAgB,EAG1C,GAAI,CACAK,GAASZ,EAAM,CAAE,OAAAC,EAAQ,OAAQU,GAAU,MAAU,CAAC,CAC1D,OAASH,EAAO,CACZ,GAAIA,aAAiBK,EAAY,MAAML,EACvC,IAAMM,EAAWJ,EAAY,oBAAqB,CAC9C,QAAS,SACT,MAAOV,EACP,OAAAC,EACA,OAAAU,EACA,MAAOH,CACX,CAAC,EACD,GAAIM,EAAU,MAAMA,CACxB,CACJ,CAEQ,qBAAqBf,EAA+B,CACxD,IAAMY,EAAS,KAAK,aAAa,QAAQ,GAAK,OAC9C,GAAIZ,IAAc,OAAQ,CACtB,GAAI,CAACgB,GAAUJ,CAAM,EAAG,OACxBK,GAAaL,CAAM,CACvB,KAAO,CACH,GAAI,CAACM,GAAaN,CAAM,EAAG,OAC3BO,GAAgBP,CAAM,CAC1B,CACJ,CAEA,mBAAoB,CACX,KAAK,aAAa,UAAU,GAC7B,KAAK,aAAa,WAAY,GAAG,EAGrC,KAAK,MAAM,OAAS,UACpB,KAAK,KAAO,OACZ,KAAK,qBAAqB,CAC9B,CAEA,yBAAyBX,EAAc,EAC/BA,IAAS,aAAeA,IAAS,WACjC,KAAK,qBAAqB,CAElC,CAMQ,sBAAuB,CAC3B,IAAMD,EAAY,KAAK,aAAa,WAAW,EAC/C,GAAIA,IAAc,QAAUA,IAAc,UAAW,CACjD,KAAK,gBAAgB,eAAe,EACpC,MACJ,CACA,IAAMY,EAAS,KAAK,aAAa,QAAQ,GAAK,QAC5BZ,IAAc,OAASgB,GAAUJ,CAAM,EAAIM,GAAaN,CAAM,GAE5E,KAAK,gBAAgB,eAAe,EAEpC,KAAK,aAAa,gBAAiB,MAAM,CAEjD,CAEA,sBAAuB,CACnB,KAAK,oBAAoB,QAAS,KAAK,WAAW,CACtD,CACJ,ECxHA,IAAMQ,GAAoC,IAa7BC,EAAN,cAA0B,WAAY,CAAtC,kCACH,UAAgB,OAGhB,mBAAoB,CAChB,KAAK,KAAO,KAAK,aAAa,MAAM,GAAK,OAErC,KAAK,aAAa,QAAQ,IAC1B,KAAK,OAAS,SAAS,cAAc,QAAQ,EAC7C,KAAK,OAAO,iBAAiB,QAAS,IAAM,CACxC,KAAK,OAAQ,gBAAgB,CACjC,CAAC,EACD,KAAK,YAAY,KAAK,MAAM,GAGhCC,GAAoB,KAAK,KAAOC,GAAQ,KAAK,WAAWA,CAAG,CAAC,CAChE,CAEA,sBAAuB,CACnBC,GAAsB,KAAK,IAAI,CACnC,CAEQ,WAAWD,EAAyB,CACxC,KAAK,cAAcA,CAAG,EAAE,MAAOE,GAAU,CAC/BA,aAAiBC,IACnBD,EAAQE,EAAY,0BAA2B,CAC3C,MAAOJ,EAAI,MAAM,KACjB,YAAaA,EAAI,YACjB,MAAOE,CACX,CAAC,GAEDA,GACA,QAAQ,MAAMA,CAAK,CAE3B,CAAC,CACL,CAEA,MAAc,cAAcF,EAAyB,CACjD,IAAMK,EAAUL,EAAI,MAAM,mBAClBA,EAAI,MAAM,UAAY,eAAe,QAAQA,EAAI,MAAM,SAAS,EAAI,MAE5E,GAAI,CAACK,EAAS,CACV,IAAMH,EAAQE,EAAY,qCAAsC,CAC5D,MAAOJ,EAAI,MAAM,KACjB,iBAAkBA,EAAI,MAAM,iBAC5B,UAAWA,EAAI,MAAM,WAAW,KAChC,UAAWA,EAAI,SACnB,CAAC,EACD,GAAIE,EAAO,MAAMA,EACjB,MACJ,CAEA,MAAM,KAAK,wBAAwBG,EAASL,CAAG,EAC/C,IAAMM,EAAU,SAAS,cAAcD,CAAO,EAI9C,GAFA,MAAM,KAAK,eAAeC,EAASN,EAAI,SAAS,EAE5C,KAAK,OAAQ,CACb,KAAK,OAAO,gBAAgBM,CAAO,EAC9B,KAAK,OAAO,MACb,KAAK,OAAO,UAAU,EAE1B,MACJ,CAEA,MAAM,KAAK,SAASA,CAAO,CAC/B,CAUA,MAAc,wBAAwBD,EAAiBL,EAAyB,CAC5E,GAAI,eAAe,IAAIK,CAAO,EAC1B,OAGJ,IAAME,EAAe,WAAW,IAAM,CAClC,QAAQ,KACJ,4BAA4BP,EAAI,MAAM,IAAI,qBAAqBK,CAAO,8JAC1E,CACJ,EAAGR,EAAiC,EAEpC,GAAI,CACA,MAAM,eAAe,YAAYQ,CAAO,CAC5C,QAAE,CACE,aAAaE,CAAY,CAC7B,CACJ,CAUA,MAAc,SAASD,EAAkB,CACrC,GAAI,CAAC,SAAS,oBAAqB,CAC/B,KAAK,gBAAgBA,CAAO,EAC5B,MACJ,CAEA,IAAME,EAAa,SAAS,oBAAoB,IAAM,KAAK,gBAAgBF,CAAO,CAAC,EACnFE,EAAW,MAAM,MAAM,IAAG,EAAY,EACtCA,EAAW,SAAS,MAAM,IAAG,EAAY,EAEzC,GAAI,CACA,MAAMA,EAAW,kBACrB,MAAQ,CACJ,KAAK,gBAAgBF,CAAO,CAChC,CACJ,CAGA,OAAQ,CACJ,KAAK,QAAQ,MAAM,CACvB,CAEA,MAAc,eAAeA,EAAkBG,EAAkB,CAC7D,GAAI,cAAeH,EAAS,CACnBG,GACD,QAAQ,KACJ,sBAAsBH,EAAQ,QAAQ,YAAY,CAAC,8IACvD,EAEJ,IAAMI,EAAYD,GACX,CAAE,QAAS,4DAA6D,EAC/E,MAAOH,EAAiC,UAAUI,CAAS,CAC/D,CAEID,IACCH,EAAgB,UAAYG,EAErC,CACJ,EC/GA,IAAME,GAAkB,cAEpBC,GAAc,EACdC,GAAmB,GAQvB,SAASC,IAAsC,CAC3C,IAAMC,EAAO,OAAO,SAAS,KAC7B,GAAI,GAACA,GAAQA,IAASJ,IAItB,OAAOI,EAAK,MAAM,CAAC,CACvB,CAEA,SAASC,IAAuB,CAC5B,OAAOJ,IACX,CAUA,IAAIK,EAEJ,SAASC,IAA2B,CAChC,OAAID,IAAkB,SAClBA,EAAgBE,GAAU,GAAK,WAE5BF,CACX,CAEA,SAASE,IAAY,CACjB,IAAMC,EAAO,OAAO,SAAS,SAC7B,OAAIA,GAAQ,cACD,UAGJA,EAAK,SAAS,OAAO,EAAIA,EAAK,MAAM,EAAG,EAAE,EAAI,IACxD,CAEO,IAAMC,EAA0B,CAAC,EASjC,SAASC,IAAc,CAC1B,QAAQ,IAAIC,CAAc,CAC9B,CAiBO,SAASC,GAAaC,EAAoB,CAC7CC,GAAwB,EACnB,eAAe,IAAI,gBAAgB,GACpC,eAAe,OAAO,iBAAkBC,CAAW,EAElD,eAAe,IAAI,QAAQ,GAC5B,eAAe,OAAO,SAAUC,CAAS,EAE7CL,EAAe,OAAS,EACxBA,EAAe,KAAK,GAAGE,CAAS,EAE5B,OAAO,YAAY,SACnB,QAAQ,IAAI,mCAAoCA,CAAS,EAG7D,IAAII,EAAiB,CAAC,EAiCtB,GAhCAJ,EAAU,QAASK,GAAU,CAErBA,EAAM,kBACN,CAAC,eAAe,IAAIA,EAAM,gBAAgB,GAE1CD,EAAK,KACD,2BAA2BC,EAAM,gBAAgB,qCACrD,EAEAA,EAAM,WAAa,CAAC,eAAe,QAAQA,EAAM,SAAS,GAC1DD,EAAK,KACD,cAAcC,EAAM,UAAU,IAAI,sDAAsD,KAAK,UAAUA,CAAK,CAAC,IACjH,EAEJ,IAAMC,EAAiBD,EAAM,KACxB,QAAQ,WAAY,EAAE,EACtB,MAAM,GAAG,EACT,OAAQE,GAAYA,EAAQ,WAAW,GAAG,CAAC,EAC5CD,EAAe,OAAS,GACxBF,EAAK,KACD,UAAUC,EAAM,IAAI,UAAUC,EAAe,KAAK,IAAI,CAAC,aAAaD,EAAM,IAAI,4EAClF,EAEAA,EAAM,SAAW,KACjB,QAAQ,KACJ,4BAA4BA,EAAM,IAAI,qGACtCA,CACJ,EACAA,EAAM,OAAS,OAEvB,CAAC,EAEGD,EAAK,OAAS,EACd,MAAM,IAAI,MAAMA,EAAK,KAAK;AAAA,CAAI,CAAC,CAEvC,CAaO,SAASI,IAAe,CAC3B,GAAIC,GAAiB,GAAK,GAAI,CAC1B,IAAMC,EAAO,OAAO,SAAS,SACvBC,EAAQD,EAAK,MAAM,mBAAmB,EACxCC,GAASA,EAAM,CAAC,IAAM,IAClB,OAAO,YAAY,SACnB,QAAQ,IAAI,kDAAmDA,EAAM,CAAC,EAAGD,CAAI,EAEjFE,EAAgBD,EAAM,CAAC,IAEnB,OAAO,YAAY,SACnB,QAAQ,IAAI,0DAA2DD,CAAI,EAE/EE,EAAgB,UAExB,CAEA,GAAIC,GAAiC,EACjC,OAGJ,IAAMC,EAAa,OAAO,SAAS,UAAY,IACzCC,EAAcC,GAAUF,EAAY,CAAC,CAAC,EAEtCG,EAAe,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAU/D,GATIA,EAAa,KAAO,IACpBF,EAAY,SAAW,CAAC,EACxBE,EAAa,QAAQ,CAACC,EAAOC,IAAQ,CACjCJ,EAAY,OAAOI,CAAG,EAAID,CAC9B,CAAC,GAGLH,EAAY,SAAWK,GAAgB,EAEnCC,GAAiBN,CAAW,EAC5B,OAGJO,GAAuB,EAEvB,IAAMC,EAASR,EAAY,MAAM,OAC3BS,EAAUC,GAAa,EACvBC,EAAyB,CAC3B,OAAAH,EACA,UAAWR,EAAY,MAAM,KAC7B,OAAQA,EAAY,OACpB,YAAaA,EAAY,YACzB,QAAAS,EACA,SAAUT,EAAY,QAC1B,EACA,QAAQ,aAAaW,EAAO,GAAI,IAAMX,EAAY,YAAY,KAAK,GAAG,CAAC,EAEvE,IAAMY,EAAI,IAAIC,EACVb,EAAY,MACZA,EAAY,YACZA,EAAY,OACZQ,CACJ,EACAI,EAAE,QAAUH,EACZG,EAAE,SAAWZ,EAAY,SACzB,SAAS,cAAcY,CAAC,CAC5B,CAmBO,SAASE,GAASC,EAAwBC,EAA2B,CACpE,OAAO,YAAY,SACnB,QAAQ,IAAI,6BAA8BD,EAAgBC,CAAO,EAErE,IAAMhB,EAAcC,GAAUc,EAAgBC,CAAO,EAErD,GADAhB,EAAY,SAAWgB,GAAS,SAC5BV,GAAiBN,CAAW,EAC5B,OAGJO,GAAuB,EAEvB,IAAMC,EAASQ,GAAS,QAAUhB,EAAY,MAAM,OAC9CS,EAAUC,GAAa,EACvBO,EAASjB,EAAY,YAAY,KAAK,GAAG,EACzCD,EAAa,OAAO,SAAS,SAAS,QAAQ,WAAY,EAAE,EAC5DY,EAAyB,CAC3B,OAAAH,EACA,UAAWR,EAAY,MAAM,KAC7B,OAAQA,EAAY,OACpB,YAAaA,EAAY,YACzB,QAAAS,EACA,SAAUT,EAAY,QAC1B,EACID,GAAckB,GACd,QAAQ,UAAUN,EAAO,GAAI,IAAMX,EAAY,YAAY,KAAK,GAAG,CAAC,EAExE,IAAMY,EAAI,IAAIC,EACVb,EAAY,MACZA,EAAY,YACZA,EAAY,OACZQ,CACJ,EACAI,EAAE,QAAUH,EACZG,EAAE,SAAWZ,EAAY,SACzB,SAAS,cAAcY,CAAC,CAC5B,CASO,SAASM,GAAUV,EAA0B,CAChD,OAAOW,EAAiBX,CAAM,GAAG,UAAU,GAAK,EACpD,CAMO,SAASY,GAAaZ,EAA0B,CACnD,OAAOW,EAAiBX,CAAM,GAAG,aAAa,GAAK,EACvD,CAaO,SAASa,GAAab,EAAuB,CAEhD,IAAMc,EADUH,EAAiBX,CAAM,GAChB,KAAK,EACxBc,GAAOC,GAAYD,CAAK,CAChC,CAMO,SAASE,GAAgBhB,EAAuB,CAEnD,IAAMc,EADUH,EAAiBX,CAAM,GAChB,QAAQ,EAC3Bc,GAAOC,GAAYD,CAAK,CAChC,CAEA,SAASC,GAAYD,EAA8B,CAC/C,IAAMtB,EAAcyB,EAAgB1C,EAAgBuC,EAAM,UAAWA,EAAM,MAAM,EACjF,GAAI,CAACtB,EAAa,CACd,IAAM0B,EAAQC,EAAY,iCAAkC,CACxD,UAAWL,EAAM,UACjB,OAAQA,EAAM,MAClB,CAAC,EACD,GAAII,EAAO,MAAMA,EACjB,MACJ,CACA,IAAMf,EAAyB,CAC3B,OAAQW,EAAM,OACd,UAAWA,EAAM,UACjB,OAAQA,EAAM,OACd,YAAaA,EAAM,YACnB,QAASA,EAAM,OACnB,EACA,OAAO,QAAQ,UAAUX,EAAO,GAAI,IAAMW,EAAM,YAAY,KAAK,GAAG,CAAC,EACrEM,GAAe5B,EAAY,MAAOsB,CAAK,CAC3C,CAEA,SAASM,GAAetC,EAAcgC,EAA8B,CAChE,IAAMO,EAAM,IAAIhB,EACZvB,EACAgC,EAAM,YACNA,EAAM,OACNA,EAAM,MACV,EACAO,EAAI,SAAW,GACfA,EAAI,QAAUP,EAAM,QACpBO,EAAI,SAAWP,EAAM,SACrB,SAAS,cAAcO,CAAG,CAC9B,CAEA,SAAStB,IAA+B,CAChCuB,KACJA,GAAmB,GACnB,OAAO,iBAAiB,WAAYC,EAAU,EAClD,CAEA,SAASA,GAAWnB,EAAwB,CACxC,IAAMD,EAAQC,EAAE,MAChB,GAAI,CAACD,GAAS,OAAOA,GAAU,UAAY,EAAE,YAAaA,GAAQ,OAElE,IAAIX,EAAuC,KAO3C,GANIW,EAAM,YACNX,EAAcyB,EAAgB1C,EAAgB4B,EAAM,UAAWA,EAAM,MAAM,GAE1EX,IACDA,EAAcgC,GAAejD,EAAgB,IAAM4B,EAAM,YAAY,KAAK,GAAG,CAAC,GAE9E,CAACX,EAAa,OAElB,IAAMsB,EAAyB,CAC3B,UAAWX,EAAM,WAAaX,EAAY,MAAM,MAAQ,GACxD,OAAQW,EAAM,OACd,OAAQA,EAAM,OACd,YAAaA,EAAM,YACnB,QAASA,EAAM,QACf,SAAUA,EAAM,QACpB,EACAiB,GAAe5B,EAAY,MAAOsB,CAAK,CAC3C,CAEA,SAASrB,GAAUc,EAAwBC,EAA2B,CAClE,IAAMiB,EAAYjB,GAAS,QAAUjC,EAC/BmD,EAASlB,GAAS,OAElBhB,EAAcmC,GAAWF,EAAWlB,EAAgBmB,CAAM,EAChE,GAAI,CAAClC,EAAa,CACd,IAAMoC,EAAWC,GACbtB,EACAmB,EACAD,CACJ,EACA,cAAQ,MAAMG,CAAQ,EAChB,IAAIE,EAAWF,CAAQ,CACjC,CAEA,GAAI,CAACG,GAAiBvC,CAAW,EAC7B,MAAM,IAAIwC,EAAgB,6CAA+CzB,CAAc,EAG3F,OAAOf,CACX,CAEA,SAASM,GAAiBN,EAAwC,CACzDA,GACD,QAAQ,MAAM,kDAAkD,EAGpE,IAAMyC,GAAgBzC,EAAY,MAAM,QAAU,WAAW,QACzD,WACA,EACJ,EACA,GAAIyC,IAAiB/C,GAAiB,EAClC,MAAO,GAQX,GAAI,OAAO,SAAS,OAASgD,GACzB,MAAM,MACF,qCAAqCD,CAAY,gBAAgBzC,EAAY,MAAM,IAAI,0BAA0B,OAAO,SAAS,QAAQ,iCAAiCN,GAAiB,CAAC,gCAChM,EAGA,OAAO,YAAY,SACnB,QAAQ,IACJ,mDAAmDA,GAAiB,CAAC,SAAS+C,CAAY,IAC1FzC,EAAY,MAAM,IACtB,EAIJ,IAAM2C,EAAkB,CACpB,UAAW3C,EAAY,MAAM,KAC7B,OAAQA,EAAY,QAAU,CAAC,EAC/B,SAAUA,EAAY,QAC1B,EAEA,eAAe,QAAQ,mBAAoB,KAAK,UAAU2C,CAAe,CAAC,EAC1E,IAAMC,EACFH,EAAa,QAAQ,MAAM,EAAI,GACzB,IAAIA,CAAY,GAAGC,EAAe,GAClC,IAAID,CAAY,QAAQC,EAAe,GACjD,OAAI,OAAO,YAAY,SACnB,QAAQ,IAAI,oDAAqDE,EAAWD,CAAe,EAE/F,OAAO,SAAS,KAAOC,EAChB,EACX,CAeA,SAAS9C,IAA4C,CACjD,GAAI,CACA,IAAM+C,EAAsB,eAAe,QAAQ,kBAAkB,EACrE,GAAI,CAACA,EACD,MAAO,GAGX,IAAMF,EAAkB,KAAK,MAAME,CAAmB,EACtD,sBAAe,WAAW,kBAAkB,EACxC,OAAO,YAAY,SACnB,QAAQ,IAAI,4DAA6DF,CAAe,EAE5F7B,GAAS6B,EAAgB,UAAW,CAChC,OAAQA,EAAgB,OACxB,SAAUA,EAAgB,QAC9B,CAAC,EAEM,EACX,OAASjB,EAAO,CACZ,sBAAe,WAAW,kBAAkB,EAC5CC,EAAY,0CAA2C,CACnD,MAAOD,CACX,CAAC,EACM,EACX,CACJ,CAEA,SAASW,GACLtB,EACA+B,EACAC,EACM,CACN,IAAIC,EAAY,GACZF,EACAE,GAAa,OAAO,QAAQF,CAAW,EAClC,IAAI,CAAC,CAAC1C,EAAKD,CAAK,IAAM,GAAGC,CAAG,IAAID,CAAK,EAAE,EACvC,KAAK,IAAI,EAEd6C,EAAY,IAGhB,IAAIC,EAAYF,EAAU,IACrBG,GACG,aAAaA,EAAE,IAAI,aAAaA,EAAE,IAAI,cAClCA,EAAE,QAAU,SAChB;AAAA,CACR,EACA,MAAO,qBAAqBnC,CAAc,GAAGiC,CAAS;AAAA,EAAyBC,CAAS,EAC5F,CAEA,SAASV,GAAiBvC,EAAwC,CAC9D,GACI,CAACA,GACD,CAACA,EAAY,MAAM,QACnBA,EAAY,MAAM,OAAO,QAAU,EAEnC,MAAO,GAGX,QAASmD,EAAQ,EAAGA,EAAQnD,EAAY,MAAM,OAAO,OAAQmD,IAAS,CAClE,IAAMC,EAAUpD,EAAY,MAAM,OAAOmD,CAAK,EAC9C,IAAIE,EAASD,EAAQ,MAAMpD,CAAW,EACtC,GAAIqD,GAAU,EACV,MAAO,GAGX,GAAIA,GAAU,EACV,MAAO,GAGX,GAAIA,GAAU,EACV,MAAM,IAAIb,EACN,SAASY,EAAQ,YAAY,IAAI,oBAAoBpD,EAAY,MAAM,IAAI,EAC/E,CAER,CAEA,MAAO,EACX,CCpeO,SAASsD,GAAyBC,EAAoC,CACzE,MAAO,CAACC,EAAcC,IACX,UAAoB,CACvB,OAAOC,GAAU,QAAQH,CAAS,CACtC,CAER,CAqCO,SAASI,GACZC,EACF,CACE,OAAQC,GAA2B,CAC/B,IAAMC,EAAOF,GAAW,CAAC,OAAQ,CAAC,CAAC,EAE/BE,EAAK,IACLC,GAAkB,SAASF,EAAQC,CAAI,EAEvCC,GAAkB,eAAeF,EAAQC,CAAI,CAErD,CACJ,CAQA,IAAME,GAAN,KAAmB,CAWf,YACWC,EACAC,EACAC,EACAC,EAAmD,CAAC,EACpDC,EACAC,EACT,CANS,sBAAAL,EACA,WAAAC,EACA,YAAAC,EACA,gBAAAC,EACA,SAAAC,EACA,cAAAC,CACR,CACP,EAqBaC,GAAN,KAAwB,CAAxB,cACH,KAAQ,cAAgB,IAAI,IAC5B,KAAQ,eAAiB,IAAI,IAS7B,SAA2BC,EAA6BZ,EAAoC,CACxF,KAAK,qBAAqBY,EAAaZ,CAAO,EAE9C,IAAMa,EAAM,IAAIT,GACZQ,EACAZ,EAAQ,OAAS,SACjBA,EAAQ,OACRA,EAAQ,YAAc,CAAC,EACvBA,EAAQ,IACRA,EAAQ,QACZ,EAEIA,EAAQ,KACR,KAAK,cAAc,IAAIA,EAAQ,IAAKa,CAAG,EAE3C,KAAK,eAAe,IAAID,EAAaC,CAAG,CAC5C,CASA,eACID,EACAZ,EACI,CACAA,GAAS,KAAK,qBAAqBY,EAAaZ,CAAO,EAE3D,IAAMa,EAAM,IAAIT,GAAaQ,EAAaZ,GAAS,OAAS,SAAUA,GAAS,QAAU,CAAC,EAAGA,GAAS,WAAYA,GAAS,IAAKA,GAAS,QAAQ,EAC7IA,GAAS,KACT,KAAK,cAAc,IAAIA,EAAQ,IAAKa,CAAG,EAE3C,KAAK,eAAe,IAAID,EAAaC,CAAG,CAC5C,CAEQ,qBAAuCD,EAA6BZ,EAAoC,CAC5G,GAAIA,EAAQ,IAAK,CACb,IAAMc,EAAgB,KAAK,cAAc,IAAId,EAAQ,GAAG,EACxD,GAAIc,GAAiBA,EAAc,mBAAqBF,EAAa,CACjE,IAAMG,EAAQC,EAAY,sDAAuD,CAC7E,IAAKhB,EAAQ,IACb,cAAec,EAAc,iBAAiB,KAC9C,SAAUF,EAAY,IAC1B,CAAC,EACD,GAAIG,EAAO,MAAMA,CACrB,CACJ,CAEA,GAAIf,EAAQ,UAAYA,EAAQ,OAAO,OAAS,EAAG,CAC/C,IAAMe,EAAQC,EAAY,gEAAiE,CACvF,QAASJ,EAAY,IACzB,CAAC,EACD,GAAIG,EAAO,MAAMA,CACrB,CACJ,CASA,OAAyBN,EAAwD,CAC7E,OAAI,OAAOA,GAAQ,SACR,KAAK,cAAc,IAAIA,CAAG,EAE9B,KAAK,eAAe,IAAIA,CAAG,CACtC,CASA,IAAsBA,EAA4C,CAC9D,IAAMI,EAAM,KAAK,OAAOJ,CAAG,EAC3B,GAAI,CAACI,EAAK,CACN,IAAMI,EAAU,OAAOR,GAAQ,SAAWA,EAAMA,EAAI,KAC9CM,EAAQC,EAAY,8BAA8BC,CAAO,IAAK,CAChE,QAAAA,EACA,gBAAiB,MAAM,KAAK,KAAK,eAAe,KAAK,CAAC,EAAE,IAAIC,GAAKA,EAAE,IAAI,EACvE,eAAgB,MAAM,KAAK,KAAK,cAAc,KAAK,CAAC,CACxD,CAAC,EACD,GAAIH,EAAO,MAAMA,CACrB,CACA,OAAOF,CACX,CACJ,EA+BO,IAAMM,GAAN,KAAuB,CAQ1B,YAAoBC,EAAsC,CAAtC,uBAAAA,EAPpB,KAAQ,UAAY,IAAI,GAOmC,CAc3D,QAA0BC,EAAuC,CAC7D,GAAI,KAAK,UAAU,IAAIA,CAAS,EAC5B,OAAO,KAAK,UAAU,IAAIA,CAAS,EAGvC,IAAMC,EAAe,KAAK,kBAAkB,IAAID,CAAS,EACzD,GAAI,CAACC,EAAc,CACf,IAAMC,EAAO,OAAOF,GAAc,SAAWA,EAAYA,EAAU,KAC7DG,EAAQC,EAAY,8BAA8BF,CAAI,IAAK,CAAE,QAASA,CAAK,CAAC,EAClF,GAAIC,EAAO,MAAMA,EACjB,MACJ,CAEA,GAAIF,EAAa,SAAU,CACvB,IAAMI,EAAOJ,EAAa,SAC1B,YAAK,aAAaI,EAAMJ,CAAY,EACpC,KAAK,UAAU,IAAID,EAAWK,CAAI,EAC3BA,CACX,CAEA,IAAMC,EAAW,KAAK,eAAkBL,CAAY,EACpD,OAAIA,EAAa,QAAU,UACvB,KAAK,UAAU,IAAID,EAAWM,CAAQ,EAE1C,KAAK,aAAaA,EAAUL,CAAY,EAEjCK,CACX,CAKQ,eAAiCL,EAA+B,CACpE,IAAMM,EAAcN,EAAa,iBAE3BO,EAAeP,EAAa,OAAO,IAAIQ,GAAO,KAAK,QAAQA,CAAG,CAAC,EACrE,OAAO,IAAIF,EAAY,GAAGC,CAAY,CAC1C,CAKQ,aAA+BF,EAAaL,EAAkC,CAClF,OAAW,CAACS,EAAWV,CAAS,IAAK,OAAO,QAAQC,EAAa,UAAU,EACtEK,EAAiBI,CAAS,EAAI,KAAK,QAAQV,CAAS,CAE7D,CACJ,EAWaD,GAAoB,IAAIY,GAWxBC,GAAY,IAAId,GAAiBC,EAAiB,ECxYxD,SAASc,GACZC,EACAC,EACQ,CACR,IAAIC,EAAUF,EAAK,cAEnB,KAAOE,GAAS,CACZ,GAAIA,aAAmBD,EACnB,OAAOC,EAEXA,EAAUA,EAAQ,aACtB,CAEA,OAAO,IACX,CC/BA,IAAMC,GAAQ,KAAK,MAAM,IAAI,KAAK,sBAAsB,EAAE,QAAQ,EAAI,GAAI,EAEtEC,GAAgB,EAChBC,GAAU,EAkCP,SAASC,GAAqBC,EAAwB,CACzD,GAAIA,EAAS,GAAKA,EAAS,QACvB,MAAM,IAAI,MAAM,sCAA4C,EAGhE,IAAMC,EAAM,KAAK,MAAM,KAAK,IAAI,EAAI,GAAI,EACxC,GAAIA,IAAQJ,IAER,GADAC,KACIA,GAAU,IACV,MAAM,IAAI,MAAM,sCAAsC,OAG1DD,GAAgBI,EAChBH,GAAU,EAGd,IAAMI,EAAYD,EAAML,GACxB,GAAIM,EAAY,WACZ,MAAM,IAAI,MAAM,qDAAqD,EAGzE,IAAMC,EAAK,OAAOD,CAAS,EACrBE,EAAM,OAAON,EAAO,EACpBO,EAAM,OAAOL,CAAM,EAQzB,OAJKG,GAAM,OAAO,EAA0B,EACvCC,GAAO,OAAO,EAAW,EAC1BC,GAEM,SAAS,EAAE,EAAE,YAAY,CACvC,CCHO,IAAMC,EAAN,cAAwB,KAAM,CAIjC,YAAYC,EAAwB,CAChC,MAAMA,EAAS,YAAY,EAC3B,KAAK,QAAUA,EAAS,aACxB,KAAK,SAAWA,CACpB,CACJ,EAqCIC,EAAsB,CACtB,gBAAiB,KACrB,EAEIC,GAAqB,MAYlB,SAASC,GAASC,EAAoB,CACzCF,GAAYE,GAAM,KACtB,CAQO,SAASC,GAAUC,EAA4B,CAClDL,EAAS,CACL,GAAGA,EACH,GAAGK,CACP,EACIA,EAAQ,kBAAoB,SAC5BL,EAAO,gBAAkB,MAEjC,CAQO,SAASM,IAAwB,CACpC,OAAOL,EACX,CAOO,SAASM,GAAWC,EAAqB,CAC5C,OAAKR,EAAO,QAIRQ,EAAI,CAAC,IAAM,KAAOR,EAAO,QAAQA,EAAO,QAAQ,OAAS,CAAC,IAAM,IACzD,GAAGA,EAAO,OAAO,IAAIQ,CAAG,GAG5BR,EAAO,QAAUQ,EAPbA,CAQf,CAOO,SAASC,IAA6B,CACzC,OAAKT,EAAO,gBAIL,aAAa,QAAQA,EAAO,eAAe,EAHvC,IAIf,CAYA,eAAsBU,EAAQF,EAAaH,EAA8C,CACrF,IAAMM,EAAQF,GAAY,EAC1B,GAAIE,GAASN,EAAS,CAClB,IAAMO,EAAUP,GAAS,QACnB,IAAI,QAAQA,EAAQ,OAAO,EAC3B,IAAI,QAELO,EAAQ,IAAI,eAAe,GAC5BA,EAAQ,IAAI,gBAAiB,UAAYD,CAAK,EAGlDN,EAAQ,QAAUO,CACtB,CAEIZ,EAAO,SAAW,CAACK,GAAS,SAC5BA,IAAY,CAAC,EACbA,EAAQ,OAAS,YAAY,QAAQL,EAAO,OAAO,GAGvD,IAAMD,EAAW,MAAME,GAAUM,GAAWC,CAAG,EAAGH,CAAO,EAEzD,GAAI,CAACN,EAAS,GACV,MAAO,CACH,WAAYA,EAAS,OACrB,aAAcA,EAAS,WACvB,QAAS,GACT,YAAaA,EAAS,QAAQ,IAAI,cAAc,EAChD,KAAM,MAAMA,EAAS,KAAK,EAC1B,QAASA,EAAS,QAAQ,IAAI,SAAS,EAEvC,IAAK,CACD,MAAM,IAAI,MAAM,sBAAsB,CAC1C,CACJ,EAGJ,IAAIc,EAAuB,KAC3B,OAAId,EAAS,SAAW,MACpBc,EAAO,MAAMd,EAAS,KAAK,GAGxB,CACH,QAAS,GACT,WAAYA,EAAS,OACrB,aAAcA,EAAS,WACvB,YAAaA,EAAS,QAAQ,IAAI,cAAc,EAChD,KAAMc,EACN,QAASd,EAAS,QAAQ,IAAI,SAAS,EACvC,IAAQ,CACJ,OAAUc,CACd,CACJ,CACJ,CAcA,eAAsBC,GAClBN,EACAO,EACAV,EACqB,CAYrB,GAXKA,EAQDA,EAAQ,OAAS,MAPjBA,EAAU,CACN,OAAQ,MACR,QAAS,CACL,eAAgBL,EAAO,aAAe,kBAC1C,CACJ,EAKAe,EAAa,CACb,IAAIC,EAAS,IACTR,EAAI,QAAQ,GAAG,IAAM,KACrBQ,EAAS,KAGb,QAAWC,KAAOF,EAAa,CAC3B,IAAMG,EAAQH,EAAYE,CAAG,EAC7BT,GAAO,GAAGQ,CAAM,GAAGC,CAAG,IAAIC,CAAK,GAC/BF,EAAS,GACb,CACJ,CAEA,OAAON,EAAQF,EAAKH,CAAO,CAC/B,CAaA,eAAsBc,GAClBX,EACAY,EACAf,EACqB,CACrB,OAAKA,GASDA,EAAQ,OAAS,OACjBA,EAAQ,KAAOe,GATff,EAAU,CACN,OAAQ,OACR,KAAMe,EACN,QAAS,CACL,eAAgBpB,EAAO,aAAe,kBAC1C,CACJ,EAMGU,EAAQF,EAAKH,CAAO,CAC/B,CAaA,eAAsBgB,GAClBb,EACAY,EACAf,EACqB,CACrB,OAAKA,GASDA,EAAQ,OAAS,MACjBA,EAAQ,KAAOe,GATff,EAAU,CACN,OAAQ,MACR,KAAMe,EACN,QAAS,CACL,eAAgBpB,EAAO,aAAe,kBAC1C,CACJ,EAMGU,EAAQF,EAAKH,CAAO,CAC/B,CAYA,eAAsBiB,GAAId,EAAaH,EAA8C,CACjF,OAAKA,EAQDA,EAAQ,OAAS,SAPjBA,EAAU,CACN,OAAQ,SACR,QAAS,CACL,eAAgBL,EAAO,aAAe,kBAC1C,CACJ,EAKGU,EAAQF,EAAKH,CAAO,CAC/B,CCvWO,IAAMkB,GAAN,KAAqB,CAArB,cACH,KAAQ,OAAS,GACjB,KAAQ,UAAY,GACpB,KAAQ,KAAiB,CAAC,EAU1B,KAAKC,EAA2B,CAC5B,KAAK,QAAUA,EAEf,IAAMC,EAAqB,CAAC,EACxBC,EAAW,EACXC,EAAY,KAAK,cAAcD,CAAQ,EAE3C,KAAOC,GAAW,CACd,IAAMC,EAAO,KAAK,OAAO,MAAMF,EAAUC,EAAU,KAAK,EAGxD,GAFAD,EAAWC,EAAU,IAEjBC,EAAK,SAAW,EAAG,CACnB,IAAMC,EAAQ,KAAK,UAAU,EACzBA,GACAJ,EAAO,KAAKI,CAAK,CAEzB,MACI,KAAK,UAAUD,CAAI,EAGvBD,EAAY,KAAK,cAAcD,CAAQ,CAC3C,CAEA,YAAK,OAAS,KAAK,OAAO,MAAMA,CAAQ,EACjCD,CACX,CAQQ,cAAcK,EAAqD,CACvE,QAASC,EAAID,EAAMC,EAAI,KAAK,OAAO,OAAQA,IAAK,CAC5C,IAAMC,EAAY,KAAK,OAAOD,CAAC,EAE/B,GAAIC,IAAc;AAAA,EACd,MAAO,CAAE,MAAOD,EAAG,IAAKA,EAAI,CAAE,EAGlC,GAAIC,IAAc,KACd,OAAID,EAAI,GAAK,KAAK,OAAO,OACd,KAEJ,KAAK,OAAOA,EAAI,CAAC,IAAM;AAAA,EACxB,CAAE,MAAOA,EAAG,IAAKA,EAAI,CAAE,EACvB,CAAE,MAAOA,EAAG,IAAKA,EAAI,CAAE,CAErC,CAEA,OAAO,IACX,CAEQ,UAAUH,EAAoB,CAClC,GAAIA,EAAK,CAAC,IAAM,IACZ,OAGJ,IAAMK,EAAQL,EAAK,QAAQ,GAAG,EACxBM,EAAOD,IAAU,GAAKL,EAAOA,EAAK,MAAM,EAAGK,CAAK,EAClDE,EAAQF,IAAU,GAAK,GAAKL,EAAK,MAAMK,EAAQ,CAAC,EAMpD,OAJIE,EAAM,CAAC,IAAM,MACbA,EAAQA,EAAM,MAAM,CAAC,GAGjBD,EAAM,CACV,IAAK,QACD,KAAK,UAAYC,EACjB,MACJ,IAAK,OACD,KAAK,KAAK,KAAKA,CAAK,EACpB,MACJ,IAAK,KACD,KAAK,GAAKA,EACV,MACJ,IAAK,QACG,QAAQ,KAAKA,CAAK,IAClB,KAAK,MAAQ,OAAOA,CAAK,GAE7B,KACR,CACJ,CAEQ,WAA6B,CACjC,GAAI,KAAK,KAAK,SAAW,EACrB,YAAK,MAAM,EACJ,KAGX,IAAMN,EAAkB,CACpB,MAAO,KAAK,UAAU,OAAS,EAAI,KAAK,UAAY,UACpD,KAAM,KAAK,KAAK,KAAK;AAAA,CAAI,CAC7B,EAEA,OAAI,KAAK,KAAO,SACZA,EAAM,GAAK,KAAK,IAEhB,KAAK,QAAU,SACfA,EAAM,MAAQ,KAAK,OAGvB,KAAK,MAAM,EACJA,CACX,CAEQ,OAAc,CAClB,KAAK,UAAY,GACjB,KAAK,KAAO,CAAC,EACb,KAAK,GAAK,OACV,KAAK,MAAQ,MACjB,CACJ,ECjJO,IAAMO,GAAN,cAA2B,KAAM,CACpC,YACIC,EACOC,EACPC,EACF,CACE,MAAMF,EAAW,CAAE,QAAS,GAAM,GAAGE,CAAU,CAAC,EAHzC,UAAAD,CAIX,CACJ,EA0DaE,GAAN,cAA4B,KAAM,CACrC,YACWC,EACAC,EACT,CACE,MAAM,OAAO,EAHN,WAAAD,EACA,cAAAC,CAGX,CACJ,EAqIaC,GAAN,KAAgB,CAiBnB,YACYC,EACAC,EACV,CAFU,SAAAD,EACA,aAAAC,EAhBZ,KAAQ,UAAY,GAkBhB,KAAK,OAAS,KAAK,cAAcA,GAAS,MAAM,CACpD,CAbA,IAAI,WAAqB,CACrB,OAAI,KAAK,YACE,KAAK,YAAY,aAAe,YAAY,KAGhD,KAAK,SAChB,CAcA,SAAgB,CACZ,GAAI,OAAK,aAAe,KAAK,iBAI7B,IAAI,CAAC,KAAK,mBAAmB,EAAG,CAC5B,KAAK,sBAAsB,EAC3B,MACJ,CAEA,GAAI,KAAK,SAAS,gBAAkB,GAAM,CACtC,IAAMJ,EAAQK,EACV,0JACA,CAAE,IAAK,KAAK,GAAI,CACpB,EACA,GAAIL,EACA,MAAMA,CAEd,CAEA,KAAK,gBAAgB,EACzB,CAKA,YAAmB,CACf,GAAI,KAAK,gBAAiB,CACtB,KAAK,gBAAgB,MAAM,EAC3B,MACJ,CAEI,KAAK,cACL,KAAK,YAAY,MAAM,EACvB,KAAK,YAAc,OACnB,KAAK,SAAS,UAAU,KAAM,CAAE,OAAQ,SAAU,CAAC,EAE3D,CAEQ,oBAA8B,CAClC,IAAMI,EAAU,KAAK,QACrB,OAAKA,EAKDA,EAAQ,SAAW,QACnBA,EAAQ,OAAS,QACjBA,EAAQ,UAAY,QACpBA,EAAQ,SAAW,QACnBA,EAAQ,gBAAkB,GARnB,EAUf,CAEQ,uBAA8B,CAClC,IAAME,EAAc,IAAI,YAAY,KAAK,IAAK,CAC1C,gBAAiB,KAAK,SAAS,iBAAmB,EACtD,CAAC,EAYD,GAVA,KAAK,YAAcA,EAEnBA,EAAY,OAAS,IAAM,CACvB,KAAK,SAAS,YAAY,IAAI,CAClC,EAEAA,EAAY,QAAWN,GAAU,CAC7B,KAAK,SAAS,UAAU,KAAMA,CAAK,CACvC,EAEI,KAAK,SAAS,YAAc,KAAK,QAAQ,WAAW,OAAS,EAC7D,QAAWO,KAAa,KAAK,QAAQ,WACjCD,EAAY,iBAAiBC,EAAYC,GAAoB,CACzD,KAAK,cAAcD,EAAWC,EAAE,IAAI,CACxC,CAAC,OAGLF,EAAY,UAAa,GAAoB,CACzC,KAAK,cAAc,UAAW,EAAE,IAAI,CACxC,CAER,CAEQ,iBAAwB,CAC5B,IAAMG,EAAa,IAAI,gBACvB,KAAK,gBAAkBA,EAEvB,KAAK,eAAeA,CAAU,EAAE,MAAOT,GAAU,CAC7C,KAAK,UAAY,GACjB,KAAK,gBAAkB,OACvBK,EAAY,+DAAgE,CACxE,IAAK,KAAK,IACV,MAAAL,CACJ,CAAC,CACL,CAAC,CACL,CAEA,MAAc,eAAeS,EAA4C,CACrE,IAAML,EAAU,KAAK,SAAW,CAAC,EACjC,KAAK,aAAaA,EAAQ,OAAQK,CAAU,EAE5C,IAAIR,EACJ,GAAI,CACAA,EAAW,MAAMS,GAAa,EAAEC,GAAW,KAAK,GAAG,EAAG,CAClD,OAAQP,EAAQ,QAAU,MAC1B,KAAMA,EAAQ,KACd,QAAS,KAAK,aAAaA,EAAQ,OAAO,EAC1C,OAAQK,EAAW,OACnB,YAAaL,EAAQ,gBAAkB,UAAY,aACvD,CAAC,CACL,OAASJ,EAAO,CACZ,KAAK,cAAcA,EAAOS,CAAU,EACpC,MACJ,CAEA,GAAI,CAACR,EAAS,GAAI,CACd,IAAMW,EAAe,MAAM,KAAK,kBAAkBX,CAAQ,EACpDD,EAAQ,IAAIa,EAAUD,CAAY,EACxCR,EAAQ,UAAU,KAAM,IAAIL,GAAcC,EAAOY,CAAY,CAAC,EAC9D,KAAK,OAAO,CAAE,OAAQ,SAAU,MAAAZ,EAAO,SAAUY,CAAa,CAAC,EAC/D,MACJ,CAEA,KAAK,UAAY,GACjBR,EAAQ,YAAY,IAAI,EAExB,IAAIU,EACAC,EAAmB,GAEvB,GAAI,CACA,IAAMC,EAAS,IAAIC,GACbC,EAAU,IAAI,YACdC,EAASlB,EAAS,MAAM,UAAU,EAExC,KAAOkB,GAAQ,CACX,GAAM,CAAE,KAAAC,EAAM,MAAAC,CAAM,EAAI,MAAMF,EAAO,KAAK,EAC1C,GAAIC,EACA,MAGJ,QAAWE,KAASN,EAAO,KAAKE,EAAQ,OAAOG,EAAO,CAAE,OAAQ,EAAK,CAAC,CAAC,EACnEP,EAAgBQ,EAAM,MAElBlB,EAAQ,gBAAgB,SAASkB,EAAM,KAAK,IAC5CP,EAAmB,IAGnB,KAAK,aAAaO,EAAM,KAAK,GAC7B,KAAK,cAAcA,EAAM,MAAOA,EAAM,IAAI,CAGtD,CACJ,OAAStB,EAAO,CACZ,KAAK,cAAcA,EAAOS,EAAYK,CAAa,EACnD,MACJ,CAEA,GAAIL,EAAW,OAAO,QAAS,CAC3B,KAAK,OAAO,CAAE,OAAQ,UAAW,cAAAK,CAAc,CAAC,EAChD,MACJ,CAEA,IAAMS,GAAwBnB,EAAQ,gBAAgB,QAAU,GAAK,EACrE,KAAK,OAAO,CACR,OAAQmB,GAAwB,CAACR,EAAmB,YAAc,YAClE,cAAAD,CACJ,CAAC,CACL,CAEQ,aAAaU,EAAiCf,EAAmC,CACrF,GAAKe,EAIL,IAAIA,EAAO,QAAS,CAChBf,EAAW,MAAM,EACjB,MACJ,CAEAe,EAAO,iBAAiB,QAAS,IAAMf,EAAW,MAAM,EAAG,CAAE,KAAM,EAAK,CAAC,EAC7E,CAEQ,aAAagB,EAA0C,CAC3D,IAAMC,EAAU,IAAI,QAAQ,CAAE,OAAQ,mBAAoB,CAAC,EAE3D,QAAWC,KAAQF,EACfC,EAAQ,IAAIC,EAAMF,EAAOE,CAAI,CAAC,EAGlC,IAAMC,EAAQC,GAAY,EAC1B,OAAID,GAAS,CAACF,EAAQ,IAAI,eAAe,GACrCA,EAAQ,IAAI,gBAAiB,UAAYE,CAAK,EAG3CF,CACX,CAEA,MAAc,kBAAkBzB,EAA2C,CACvE,MAAO,CACH,WAAYA,EAAS,OACrB,aAAcA,EAAS,WACvB,QAAS,GACT,YAAaA,EAAS,QAAQ,IAAI,cAAc,EAChD,KAAM,MAAMA,EAAS,KAAK,EAC1B,QAASA,EAAS,QAAQ,IAAI,SAAS,EAEvC,IAAK,CACD,MAAM,IAAI,MAAM,sBAAsB,CAC1C,CACJ,CACJ,CAEQ,cACJD,EACAS,EACAK,EACI,CACJ,GAAIL,EAAW,OAAO,QAAS,CAC3B,KAAK,OAAO,CAAE,OAAQ,UAAW,cAAAK,CAAc,CAAC,EAChD,MACJ,CAEA,IAAMgB,EAAU9B,aAAiB,MAAQA,EAAQ,IAAI,MAAM,OAAOA,CAAK,CAAC,EACxE,KAAK,SAAS,UAAU,KAAM,IAAID,GAAc+B,CAAO,CAAC,EACxD,KAAK,OAAO,CAAE,OAAQ,SAAU,MAAOA,EAAS,cAAAhB,CAAc,CAAC,CACnE,CAEQ,OAAOiB,EAA8B,CACzC,KAAK,UAAY,GACjB,KAAK,gBAAkB,OACvB,KAAK,SAAS,UAAU,KAAMA,CAAM,CACxC,CAEQ,aAAanC,EAA4B,CAC7C,IAAMoC,EAAa,KAAK,SAAS,WACjC,OAAIA,GAAcA,EAAW,OAAS,EAC3BA,EAAW,SAASpC,CAAS,EAGjCA,IAAc,SACzB,CAEQ,cAAcqC,EAA+C,CACjE,GAAI,CAACA,EACD,OAAO,SAEX,GAAI,OAAOA,GAAW,SAAU,CAC5B,IAAMC,EAAU,SAAS,cAAcD,CAAM,EAC7C,GAAI,CAACC,EACD,MAAM,IAAI,MAAM,wCAAwCD,CAAM,EAAE,EAEpE,OAAOC,CACX,CACA,OAAOD,CACX,CAEQ,cAAcrC,EAAmBuC,EAAuB,CAC5D,IAAItC,EAEJ,GAAIsC,EAAQ,OAAS,IAAMA,EAAQ,CAAC,IAAM,KAAOA,EAAQ,CAAC,IAAM,KAAOA,EAAQ,CAAC,IAAM,KAClF,GAAI,CACAtC,EAAO,KAAK,MAAMsC,CAAO,CAC7B,MAAQ,CACJtC,EAAOsC,CACX,MAEAtC,EAAOsC,EAGX,IAAMC,EAAQ,KAAK,SAAS,aACtB,KAAK,QAAQ,aAAaxC,EAAWC,CAAI,EACzC,IAAIF,GAAaC,EAAWC,CAAI,EAEtC,KAAK,OAAO,cAAcuC,CAAK,CACnC,CACJ,EC5fO,SAASC,GACZC,EACAC,EACe,CACf,IAAIC,EAAQD,EAEZ,QAAWE,KAAOH,EAAM,CACpB,GAA2BE,GAAU,KACjC,OAGJA,EAAQA,EAAMC,CAAG,CACrB,CAEA,OAA8BD,GAAyB,MAC3D",
  "names": ["require_r_common", "__commonJSMin", "exports", "module", "require_r_pipes", "__commonJSMin", "exports", "module", "require_r_validation", "__commonJSMin", "exports", "module", "RelaxError", "message", "context", "handler", "onError", "fn", "reportError", "error", "suppressed", "asyncHandler", "args", "cause", "Node", "value", "removeCallback", "LinkedList", "newNode", "node", "PageSelectedEvent", "page", "Pager", "container", "totalCount", "pageSize", "pageCount", "createButton", "label", "disabled", "btn", "i", "getFieldName", "element", "id", "form", "label", "FormValidator", "options", "event", "result", "cause", "error", "reportError", "formElements", "isFormValid", "errorMessages", "fieldName", "messages", "errorList", "message", "listItem", "errorSummary", "ul", "firstInvalidElement", "i", "child", "pluralRulesCache", "getPluralRule", "locale", "escapeRegex", "s", "defaultFormatICU", "message", "values", "_", "key", "type", "categoriesPart", "value", "exact", "category", "match", "escaped", "formatICU", "catalogue", "normalizeLocale", "locale", "registerNamespace", "locale", "namespace", "source", "normalized", "normalizeLocale", "catalogue", "r_common_default", "r_pipes_default", "r_validation_default", "registerBuiltinNamespaces", "registerNamespace", "r_common_default", "r_pipes_default", "r_validation_default", "fallbackLocale", "currentLocale", "translations", "missingHandler", "registerBuiltinNamespaces", "t", "fullKey", "values", "options", "namespace", "key", "message", "translations", "format", "missingHandler", "currentLocale", "onError", "formatICU", "getCurrentLocale", "mapFormToClass", "form", "instance", "options", "formElements", "element", "booleanAttr", "propertyName", "value", "readElementValue", "SKIP", "formFieldNames", "prop", "getDataConverter", "dataType", "createConverterFromDataType", "createConverterFromInputType", "BooleanConverter", "str", "readData", "data", "formData", "seen", "_", "name", "values", "converter", "v", "i", "el", "lower", "NumberConverter", "nr", "getLocaleDateOrder", "locale", "p", "DateConverter", "date", "numericParts", "getCurrentLocale", "order", "mapped", "type", "inputType", "year", "month", "week", "hours", "minutes", "seconds", "attr", "o", "validators", "RegisterValidator", "validationName", "validInputTypes", "target", "getValidator", "name", "_RequiredValidation_decorators", "_init", "_RequiredValidation", "rule", "value", "context", "t", "__decoratorStart", "__decorateElement", "__runInitializers", "RequiredValidation", "_RangeValidation_decorators", "_RangeValidation", "min", "max", "rangeMatch", "num", "actual", "RangeValidation", "_DigitsValidation_decorators", "_DigitsValidation", "DigitsValidation", "setFormData", "form", "data", "context", "select", "populateSelectOptions", "element", "name", "arrayName", "arrayValue", "getValueByComplexPath", "el", "type", "boolAttr", "val", "option", "opt", "allWithName", "idx", "value", "setElementValue", "obj", "path", "segments", "currentSegment", "inBrackets", "char", "result", "segment", "index", "pad", "n", "options", "vals", "dataSource", "sourceKey", "valueField", "textField", "groupField", "match", "source", "items", "placeholders", "groups", "item", "text", "groupLabel", "raw", "str", "optgroup", "attr", "uppercasePipe", "value", "trimPipe", "lowercasePipe", "capitalizePipe", "str", "shortenPipe", "length", "maxLength", "currencyPipe", "currency", "locale", "getCurrentLocale", "datePipe", "format", "date", "daysAgoPipe", "inputDate", "today", "diffTime", "diffDays", "t", "piecesPipe", "count", "joinPipe", "separator", "firstPipe", "lastPipe", "keysPipe", "defaultPipe", "defaultValue", "ternaryPipe", "trueValue", "falseValue", "createPipeRegistry", "pipes", "name", "pipe", "defaultPipes", "applyPipes", "registry", "currentValue", "pipeName", "args", "p", "error", "pipes", "defaultPipes", "html", "templateStrings", "substitutions", "template", "resolvedTemplate", "resolveTemplate", "bindings", "walker", "node", "element", "processElement", "myNode", "text", "result", "parseTemplate", "startMarker", "endMarker", "insertedNodes", "instance", "value", "n", "temp", "nodes", "parent", "context", "x", "str", "i", "attrBindings", "attr", "attrValue", "regex", "match", "index", "func", "boundFunction", "attributeCallback", "attrBinding", "parseArguments", "argsStr", "arg", "parts", "part", "lastIndex", "textBindings", "_instance", "sub", "mustacheName", "matchingPipes", "pipe", "args", "val", "_", "binding", "parseExpression", "expr", "pipesSplit", "s", "mainExpr", "pipes", "fnMatch", "fnName", "argsStr", "fnArgs", "a", "resolvePath", "ctx", "path", "segments", "current", "key", "handleError", "config", "message", "context", "shouldThrow", "formattedMessage", "createGetter", "debugInfo", "err", "errorMessage", "evaluateExpression", "parsed", "fns", "value", "registry", "defaultPipes", "fn", "resolvedArgs", "arg", "resolved", "applyPipes", "expressionCache", "splitInterpolation", "raw", "parts", "part", "composeParts", "literal", "textNodePatcher", "node", "_get", "liveValueAttributes", "attributeInterpolationPatcher", "element", "setters", "attributes", "attr", "name", "wholeValue", "eventPatcher", "tag", "rAttributes", "updaters", "eventName", "currentCtx", "currentFns", "event", "ctxWithEvent", "structuralAttributes", "structuralPatcher", "get", "loopDef", "ifExpr", "unlessExpr", "alias", "source", "match", "template", "placeholder", "parent", "isVisible", "candidate", "contextsToRender", "items", "item", "instances", "spare", "contexts", "reuseCount", "i", "fragment", "added", "instance", "clone", "compileDOM", "insertAfter", "contentPatchers", "root", "processNode", "structural", "patch", "setter", "child", "lastCtx", "lastFns", "compileTemplate", "templateStr", "content", "render", "parsePath", "notation", "options", "delimiter", "escapeChar", "segments", "current", "i", "inBrackets", "bracketContent", "char", "currentInDelimLength", "nextChar", "nextInDelimLength", "createAccessorFromPath", "path", "record", "segment", "index", "createAccessor", "tokenize", "input", "tokens", "i", "char", "pipeTarget", "quote", "value", "hasDecimal", "isFunctionCall", "bracketCount", "wsCount", "parenCount", "lastToken", "isDotAfterConstant", "tokenizeArgs", "start", "end", "argsStr", "quoteType", "numStr", "ident", "tokenizeMustache", "template", "currentIndex", "openTagIndex", "createStringToken", "mustache", "endIndex", "balanced", "extractMustache", "createMustacheToken", "startIndex", "open", "close", "depth", "compileMustard", "template", "options", "segments", "tokenizeMustache", "token", "_data", "_component", "compileExpression", "data", "component", "fn", "tokens", "tokenize", "chain", "buildExpressionChain", "renderFromChain", "sourceText", "pipeRegistry", "defaultPipes", "createAccessor", "resolveFunction", "pipeName", "args", "p", "pipe", "value", "initial", "result", "acc", "expression", "pos", "resolvedArgs", "tokenizeArgs", "arg", "name", "fnAccessor", "evaluatedArgs", "argFn", "BoundNode", "root", "bindings", "clickBindings", "component", "data", "binding", "click", "node", "method", "evt", "args", "token", "obj", "key", "path", "index", "createBluePrint", "html", "bp", "Blueprint", "htmlOrTemplate", "trimmed", "wrapper", "found", "rootElement", "rootClone", "componentOrEmpty", "boundBindings", "el", "walk", "func", "compileMustard", "targetNode", "element", "i", "attr", "child", "clickAttr", "match", "methodName", "argTokens", "tokenizeArgs", "TableRenderer", "table", "template", "idColumn", "component", "data", "item", "id", "row", "cell", "field", "el", "element", "handlerAttr", "match", "methodName", "argStr", "args", "s", "event", "SortChangeEvent", "sortColumns", "TableSorter", "th", "column", "index", "c", "existingIndicator", "sortInfo", "indicator", "GuardResult", "RouteError", "RouteGuardError", "NavigateRouteEvent", "_NavigateRouteEvent", "route", "urlSegments", "routeData", "routeTarget", "eventInit", "NavigationHistory", "entry", "entryId", "found", "e", "targets", "pendingEvents", "detachedHistories", "registerRouteTarget", "name", "handler", "initRouteTargetListener", "error", "reportError", "restoredHistory", "history", "NavigationHistory", "pending", "dispatchToTarget", "unregisterRouteTarget", "reg", "getTargetHistory", "clearPendingNavigations", "entryFromEvent", "evt", "entry", "listenerAttached", "NavigateRouteEvent", "NumberRouteSegment", "paramName", "value", "pathValue", "StringRouteSegment", "_value", "PathRouteSegment", "_pathValue", "RouteImp", "route", "segments", "generatedSegments", "params", "index", "urlSegment", "ourSegment", "routeData", "urlSegments", "lowerIndex", "key", "matched", "matchRoute", "routes", "routeNameOrUrl", "findRouteByUrl", "findRouteByName", "name", "x", "imp", "generateRouteImp", "result", "path", "routeImps", "generateRouteImps", "m", "impSegments", "segment", "RouteLink", "e", "direction", "name", "params", "attr", "paramName", "_", "c", "paramsAttr", "additionalParams", "error", "err", "reportError", "target", "navigate", "RelaxError", "reported", "canGoBack", "navigateBack", "canGoForward", "navigateForward", "COMPONENT_REGISTRATION_WARNING_MS", "RouteTarget", "registerRouteTarget", "evt", "unregisterRouteTarget", "error", "RelaxError", "reportError", "tagName", "element", "stillWaiting", "transition", "data", "routeData", "LAYOUT_SENTINEL", "nextEntryId", "popstateAttached", "readAppFragment", "hash", "allocEntryId", "currentLayout", "getCurrentLayout", "getLayout", "path", "internalRoutes", "printRoutes", "internalRoutes", "defineRoutes", "appRoutes", "initRouteTargetListener", "RouteTarget", "RouteLink", "errs", "route", "bracedSegments", "segment", "startRouting", "getCurrentLayout", "path", "match", "currentLayout", "tryLoadRouteFromLayoutNavigation", "currentUrl", "routeResult", "findRoute", "searchParams", "value", "key", "readAppFragment", "navigateToLayout", "attachPopstateListener", "target", "entryId", "allocEntryId", "state", "e", "NavigateRouteEvent", "navigate", "routeNameOrUrl", "options", "ourUrl", "canGoBack", "getTargetHistory", "canGoForward", "navigateBack", "entry", "replayEntry", "navigateForward", "findRouteByName", "error", "reportError", "dispatchReplay", "evt", "popstateAttached", "onPopState", "findRouteByUrl", "theRoutes", "params", "matchRoute", "errorMsg", "generateErrorMessage", "RouteError", "checkRouteGuards", "RouteGuardError", "wantedLayout", "LAYOUT_SENTINEL", "navigationState", "layoutUrl", "navigationStateJson", "routeParams", "allRoutes", "routeData", "routesStr", "x", "index", "element", "result", "Inject", "typeOrKey", "_", "context", "container", "ContainerService", "options", "target", "opts", "serviceCollection", "Registration", "classConstructor", "scope", "inject", "properties", "key", "instance", "ServiceCollection", "constructor", "reg", "existingByKey", "error", "reportError", "service", "c", "ServiceContainer", "serviceCollection", "keyOrType", "registration", "name", "error", "reportError", "inst", "instance", "constructor", "dependencies", "dep", "fieldName", "ServiceCollection", "container", "getParentComponent", "node", "constructor", "current", "EPOCH", "lastTimestamp", "counter", "generateSequentialId", "baseId", "now", "timestamp", "ts", "cnt", "uid", "HttpError", "response", "config", "fetchImpl", "setFetch", "fn", "configure", "options", "currentFetch", "resolveUrl", "url", "bearerToken", "request", "token", "headers", "body", "get", "queryString", "prefix", "key", "value", "post", "data", "put", "del", "SseFrameParser", "chunk", "frames", "position", "lineBreak", "line", "frame", "from", "i", "character", "colon", "name", "value", "SSEDataEvent", "eventName", "data", "eventInit", "SSEErrorEvent", "error", "response", "SSEClient", "url", "options", "reportError", "eventSource", "eventType", "e", "controller", "currentFetch", "resolveUrl", "httpResponse", "HttpError", "lastEventName", "sawTerminalEvent", "parser", "SseFrameParser", "decoder", "reader", "done", "value", "frame", "expectsTerminalEvent", "signal", "custom", "headers", "name", "token", "bearerToken", "failure", "result", "eventTypes", "target", "element", "rawData", "event", "resolveValue", "path", "context", "value", "key"]
}
