// #region Imports
// #endregion
// Slot Query decorators are similar to the query decorator in lit.
// Instead of querying the component template they query the content slot of the component.
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const legacyQuery = (descriptor, proto, name) => {
    Object.defineProperty(proto, name, descriptor);
};
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
const standardQuery = (descriptor, element) => ({
    kind: 'method',
    placement: 'prototype',
    key: element.key,
    descriptor
});
/**
 * A property decorator that converts a class property into a getter that
 * executes a querySelector on the element's light DOM Slot.
 */
export function QuerySlotAsync(selector, config) {
    return (protoOrDescriptor, name) => {
        const targetFirstUpdated = protoOrDescriptor.firstUpdated;
        function firstUpdated() {
            const ref = this.querySelector(selector);
            const shouldExempt = config?.exemptOn?.(this);
            if (!ref && config?.required && !shouldExempt) {
                const message = config.requiredMessage ?? `The <${selector}> element is required to use <${this.tagName.toLocaleLowerCase()}>`;
                if (config.required === 'error') {
                    throw new Error(message);
                }
            }
            if (config?.assign && ref?.hasAttribute('slot') === false) {
                ref.setAttribute('slot', config.assign);
            }
            if (targetFirstUpdated) {
                targetFirstUpdated.apply(this);
            }
        }
        protoOrDescriptor.firstUpdated = firstUpdated;
        const descriptor = {
            // eslint-disable-next-line @typescript-eslint/tslint/config
            async get() {
                await this.updateComplete;
                return this.querySelector(selector);
            },
            enumerable: true,
            configurable: true
        };
        return name !== undefined
            ? legacyQuery(descriptor, protoOrDescriptor, name)
            : standardQuery(descriptor, protoOrDescriptor);
    };
}
/**
 * A property decorator that converts a class property into a getter
 * that executes a querySelectorAll on the element's light DOM Slot.
 */
export function QuerySlotAllAsync(selector, config) {
    return (protoOrDescriptor, name) => {
        const targetFirstUpdated = protoOrDescriptor.firstUpdated;
        function firstUpdated(props) {
            if (config?.assign) {
                Array.from(this.querySelectorAll(selector))
                    .filter((i) => !i.hasAttribute('slot'))
                    .forEach((i) => i.setAttribute('slot', config.assign));
            }
            if (targetFirstUpdated) {
                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                // @ts-ignore
                targetFirstUpdated.apply(this, [props]);
            }
        }
        protoOrDescriptor.firstUpdated = firstUpdated;
        const descriptor = {
            // eslint-disable-next-line @typescript-eslint/tslint/config
            async get() {
                await this.updateComplete;
                return Array.from(this.querySelectorAll(selector));
            },
            enumerable: true,
            configurable: true
        };
        return name !== undefined
            ? legacyQuery(descriptor, protoOrDescriptor, name)
            : standardQuery(descriptor, protoOrDescriptor);
    };
}
//# sourceMappingURL=QuerySlotAsyncDecorator.js.map