// #region Imports
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { Attribute } from '../../../Decorators/AttributeDecorator';
import { Component } from '../../../Decorators/ComponentDecorator';
import { Size } from '../../../Types/Size';
import { CustomElement } from '../../Abstracts/CustomElement';
import { DEFAULT_SPACER_ELEMENT_PROPS } from './ISpacerElementProps';
import { spacerElementTemplate } from './SpacerElementTemplate';
import { spacerElementJoyStyle } from './Themes/SpacerElement.Joy';
import { spacerElementRetroStyle } from './Themes/SpacerElement.Retro';
import { spacerElementCosmopolitanStyle } from './Themes/SpacerElement.Cosmopolitan';
import { Themeable } from '../../../Behaviors/Themeable';
import { Property } from '../../../Decorators/PropertyDecorator';
/**
 * Spacer - A flexible spacing element for creating consistent gaps and layout control.
 *
 * Provides precise spacing control between UI elements with configurable thickness, size multipliers,
 * and directional spacing. Essential for maintaining consistent visual rhythm and alignment in layouts.
 * Supports responsive spacing based on design system tokens.
 *
 * @name SpacerElement
 * @element mosaik-spacer
 * @category Primitive
 *
 * @csspart spacer - The main spacing container element
 *
 * @cssprop --spacer-thickness - Base thickness for the spacer element
 * @cssprop --spacer-multiplier - Multiplier applied to base spacing values
 * @cssprop --spacer-size - Predefined size category (xs, sm, md, lg, xl)
 *
 * @example
 * ```html
 * <!-- Basic spacing -->
 * <div>Content Above</div>
 * <mosaik-spacer></mosaik-spacer>
 * <div>Content Below</div>
 *
 * <!-- Custom multiplier for larger gap -->
 * <mosaik-spacer multiplier="2"></mosaik-spacer>
 *
 * <!-- Size-based spacing -->
 * <mosaik-spacer size="lg"></mosaik-spacer>
 *
 * <!-- Multiple thickness values -->
 * <mosaik-spacer thickness="md lg"></mosaik-spacer>
 *
 * <!-- Flex layout spacing -->
 * <div style="display: flex; align-items: center;">
 *   <button>Button 1</button>
 *   <mosaik-spacer></mosaik-spacer>
 *   <button>Button 2</button>
 * </div>
 * ```
 *
 * @public
 */
let SpacerElement = class SpacerElement extends Themeable(CustomElement) {
    // #region Fields
    _multiplier;
    _size;
    _thickness;
    _invert;
    _multiplierValidator;
    // #endregion
    // #region Ctor
    /**
     * @public
     */
    constructor() {
        super();
        this._multiplier = DEFAULT_SPACER_ELEMENT_PROPS.multiplier;
        this._size = DEFAULT_SPACER_ELEMENT_PROPS.size;
        this._thickness = this.parseThickness(DEFAULT_SPACER_ELEMENT_PROPS.thickness);
        this._invert = DEFAULT_SPACER_ELEMENT_PROPS.invert;
        this._multiplierValidator = DEFAULT_SPACER_ELEMENT_PROPS.multiplierValidator;
    }
    // #endregion
    // #region Properties
    /**
     * Returns the `{@link is}` property.
     * The `{@link is}` property represents natural name of this element.
     *
     * @public
     * @static
     * @readonly
     */
    static get is() {
        return 'mosaik-spacer';
    }
    /**
     * Gets or sets the `multiplier` property.
     *
     * The multiplier factor for spacing. Adjusts the space based on a numeric value.
     *
     * @public
     * @attr
     */
    get multiplier() {
        return this._multiplier;
    }
    set multiplier(value) {
        if (this._multiplier !== value) {
            if (this._multiplierValidator(value)) {
                this._multiplier = value;
                this.requestUpdate('multiplier');
            }
        }
    }
    /**
     * Gets or sets the `density` property.
     *
     * Possible values are `tiny`, `small`, `medium`, `large` or `giant`.
     * The default is `medium`.
     *
     * @public
     * @attr
     */
    get size() {
        return this._size;
    }
    set size(value) {
        if (this._size !== value) {
            this._size = value;
            this.requestUpdate('size');
        }
    }
    /**
     * Gets or sets the `thickness` property.
     *
     * The thickness or sides for which the Spacer applies. Accepts values: `top`, `right`, `bottom`, `left`, `vertical`, `horizontal`, `all` or `none`.
     * The default is `null`.
     *
     * @public
     * @attr
     */
    get thickness() {
        return this._thickness;
    }
    set thickness(value) {
        if (this._thickness !== value) {
            this._thickness = this.parseThickness(value);
            this.requestUpdate('thickness');
        }
    }
    /**
     * Gets or sets the `invert` property.
     *
     * Inverts the spacing. This is useful for creating negative space.
     * The default is `false`.
     *
     * @public
     * @attr
     */
    get invert() {
        return this._invert;
    }
    set invert(value) {
        if (this._invert !== value) {
            this._invert = value;
            this.requestUpdate('invert');
        }
    }
    /**
     * Gets or sets the `multiplierValidator` property.
     *
     * The multiplier validator function.
     * The default is `DEFAULT_SPACER_ELEMENT_PROPS.multiplierValidator`.
     *
     * @public
     */
    get multiplierValidator() {
        return this._multiplierValidator;
    }
    set multiplierValidator(value) {
        if (this._multiplierValidator !== value) {
            this._multiplierValidator = value;
            this.requestUpdate('multiplierValidator');
        }
    }
    // #endregion
    // #region Methods
    /**
     * Tries to get the thickness.
     *
     * @private
     * @template
     */
    tryGetThickness(thicknesses) {
        let thickness = false;
        for (const t of thicknesses) {
            let size = this._multiplier * this.getSizeAsNumber(this._size);
            size = this._invert
                // isNegative
                ? Math.sign(size) <= -0
                    ? Math.abs(size) * 1
                    : Math.abs(size) * -1
                : size;
            const thicknessValue = this._thickness?.includes(t)
                ? this.parseSize(size)
                : false;
            if (thicknessValue !== false) {
                thickness = thicknessValue;
                break;
            }
        }
        return thickness;
    }
    /**
     * Parses the `thickness` property into an array of `Spacing`.
     *
     * @private
     */
    parseThickness(thickness) {
        const thicknesses = typeof thickness === 'string'
            ? thickness.split(/\s+/)
            : thickness ?? [];
        const knownThicknesses = new Array();
        this.validateThickness(thicknesses);
        thicknesses.forEach((x) => {
            if (['top', 'right', 'bottom', 'left', 'vertical', 'horizontal', 'all'].includes(x)) {
                knownThicknesses.push(x);
            }
        });
        return knownThicknesses;
    }
    /**
     * Validates the `thickness` property.
     *
     * @private
     */
    validateThickness(thickness) {
        // validate none
        if (thickness.includes('none')) {
            if (thickness.length > 1) {
                throw new Error('Error while parsing thickness.');
            }
        }
        // validate all
        if (thickness.includes('all')) {
            if (thickness.length > 1) {
                throw new Error('Error while parsing thickness.');
            }
        }
        // validate vertical
        if (thickness.includes('vertical')) {
            if (thickness.includes('top') || thickness.includes('bottom')) {
                throw new Error('Error while parsing thickness');
            }
        }
        // validate horizontal
        if (thickness.includes('horizontal')) {
            if (thickness.includes('left') || thickness.includes('right')) {
                throw new Error('Error while parsing thickness.');
            }
        }
        // validate vertical and horizontal
        if (thickness.includes('vertical') && thickness.includes('horizontal')) {
            if (thickness.length > 2) {
                throw new Error('Error while parsing thickness.');
            }
        }
    }
    /**
     * Gets the size as number.
     *
     * @private
     */
    getSizeAsNumber(size) {
        switch (size) {
            case Size.Tiny:
                return 1;
            case Size.Small:
                return 2;
            case Size.Medium:
                return 3;
            case Size.Large:
                return 4;
            case Size.Giant:
                return 5;
            default:
                throw new Error();
        }
    }
    /**
     * Parses the size.
     *
     * @private
     */
    parseSize(size) {
        if (typeof size === 'string') {
            return size;
        }
        if (typeof size === 'number') {
            return `${size}px`;
        }
        return '';
    }
};
__decorate([
    Attribute({ type: Number }),
    __metadata("design:type", Number),
    __metadata("design:paramtypes", [Number])
], SpacerElement.prototype, "multiplier", null);
__decorate([
    Attribute({ type: Size }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], SpacerElement.prototype, "size", null);
__decorate([
    Attribute({
        type: Array,
        converter: {
            fromAttribute: (value) => value.split(' ').map((p) => p.trim())
                .filter((p) => p !== ''),
            toAttribute: (value) => value.join(' ')
        }
    }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [Object])
], SpacerElement.prototype, "thickness", null);
__decorate([
    Attribute({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], SpacerElement.prototype, "invert", null);
__decorate([
    Property({ type: Function }),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Function])
], SpacerElement.prototype, "multiplierValidator", null);
SpacerElement = __decorate([
    Component({
        selector: 'mosaik-spacer',
        template: spacerElementTemplate,
        themes: {
            joy: spacerElementJoyStyle,
            retro: spacerElementRetroStyle,
            cosmopolitan: spacerElementCosmopolitanStyle
        },
        imports: []
    }),
    __metadata("design:paramtypes", [])
], SpacerElement);
export { SpacerElement };
//# sourceMappingURL=SpacerElement.js.map