/* eslint-disable @typescript-eslint/no-empty-object-type */
/* eslint-disable @typescript-eslint/naming-convention */
// #region Imports
import { SlotController } from '../Controllers/SlotController';
/**
 * Slottable - A behavior that adds slottable capabilities to a control.
 *
 * @public
 */
export const Slottable = (base) => {
    class SlottableElement extends base {
        // #region Fields
        _slotController;
        // #endregion
        // #region Ctor
        /**
         * Constructs a new instance of the `SlottableElement` class.
         *
         * @public
         */
        constructor(...args) {
            super(args);
            this._slotController = new SlotController(this, {
                callback: (slotName) => {
                    this.onSlotChanges(slotName);
                }
            });
        }
        // #endregion
        // #region Methods
        /**
         * Assigns nodes to a dedicated slot.
         *
         * @public
         * @hidden
         * @param slotName - The slot name (For default slot, pass an empty string).
         * @param node - The nodes to assign to the slot.
         * @returns void
         */
        assignToSlot(slotName, node) {
            const slotSelector = slotName ? `slot[name="${slotName}"]` : 'slot:not([name])';
            const slot = this.shadowRoot?.querySelector(slotSelector);
            if (!slot) {
                const exceptionMessage = slotName
                    ? `The slot "${slotName}" was not found.`
                    : 'The default slot was not found.';
                throw new Error(exceptionMessage);
            }
            slot.assign(node);
        }
        /**
         * Returns the assigned elements of a slot.
         *
         * @public
         * @hidden
         * @param slotName - The slot name (For default slot, pass an empty string).
         * @param filter - The optional filter function.
         * @returns The assigned elements of a slot.
         */
        getSlotAssignments(slotName, filter) {
            const elements = this._slotController.getAssignedElements(slotName);
            if (filter) {
                return elements.filter((x) => filter(x));
            }
            return elements;
        }
        /**
         * Returns the assigned elements of a slot.
         *
         * @public
         * @hidden
         * @param slotName - The slot name (For default slot, pass an empty string).
         * @param element - The element to filter.
         * @returns The assigned elements of a slot.
         */
        getSlotAssignmentsOf(slotName, element) {
            return this.getSlotAssignments(slotName).filter((x) => x instanceof element);
        }
        /**
         * Returns a boolean that indicates if a slot has content.
         *
         * @public
         * @hidden
         * @param slotName - The slot name (For default slot, pass an empty string).
         * @returns A boolean that indicates if a slot has content.
         */
        hasSlotContent(slotName) {
            const hasAssignedContent = this._slotController.hasAssignedContent(slotName);
            const hasContent = this._slotController.hasContent(slotName);
            return hasAssignedContent || hasContent;
        }
        /**
         * Returns a boolean that indicates if a slot exists.
         *
         * @public
         * @hidden
         * @param slotName - The slot name (For default slot, pass an empty string).
         * @returns A boolean that indicates if a slot exists.
         */
        hasSlot(slotName) {
            return this._slotController.hasSlot(slotName);
        }
        /**
         * Called when the slot changes.
         *
         * @public
         * @hidden
         * @param slotName - The optional slot name (For default slot, passes undefined).
         * @returns void
         */
        onSlotChanges(_slotName) {
            // Override
        }
    }
    return SlottableElement;
};
//# sourceMappingURL=Slottable.js.map