// #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 { on } from '@breadstone/mosaik-elements';
import { RendererServiceLocator } from '../../../../Dom/Renderer';
import { Slottable } from '../../../Behaviors/Slottable';
import { Themeable } from '../../../Behaviors/Themeable';
import { ResizeContainerController } from '../../../Controllers/ResizeContainerController';
import { Attribute } from '../../../Decorators/AttributeDecorator';
import { Component } from '../../../Decorators/ComponentDecorator';
import { Property } from '../../../Decorators/PropertyDecorator';
import { ContainerResizeMode } from '../../../Types/ContainerResizeMode';
import { ResizeDirection } from '../../../Types/ResizeDirection';
import { CustomElement } from '../../Abstracts/CustomElement';
import { resizeElementTemplate } from './ResizeElementTemplate';
import { resizeElementJoyStyle } from './Themes/ResizeElement.Joy';
// #endregion
/**
 * Resize - a container that allows its content to be resized via drag handles.
 *
 * @name ResizeElement
 * @element mosaik-resize
 * @category Layouts
 *
 * @slot - The default slot for the content to be resized.
 *
 * @csspart thumb ${ResizeDirection.East} - The thumb ${ResizeDirection.East} part.
 * @csspart thumb ${ResizeDirection.North} - The thumb ${ResizeDirection.North} part.
 * @csspart thumb ${ResizeDirection.NorthEast} - The thumb ${ResizeDirection.NorthEast} part.
 * @csspart thumb ${ResizeDirection.NorthWest} - The thumb ${ResizeDirection.NorthWest} part.
 * @csspart thumb ${ResizeDirection.South} - The thumb ${ResizeDirection.South} part.
 * @csspart thumb ${ResizeDirection.SouthEast} - The thumb ${ResizeDirection.SouthEast} part.
 * @csspart thumb ${ResizeDirection.SouthWest} - The thumb ${ResizeDirection.SouthWest} part.
 * @csspart thumb ${ResizeDirection.West} - The thumb ${ResizeDirection.West} part.
 *
 * @cssprop {String} --resize-font-family - The font family CSS custom property.
 * @cssprop {String} --resize-font-letter-spacing - The font letter spacing CSS custom property.
 * @cssprop {String} --resize-font-line-height - The font line height CSS custom property.
 * @cssprop {String} --resize-font-size - The font size CSS custom property.
 * @cssprop {String} --resize-font-text-decoration - The font text decoration CSS custom property.
 * @cssprop {String} --resize-font-text-transform - The font text transform CSS custom property.
 * @cssprop {String} --resize-font-weight - The font weight CSS custom property.
 * @cssprop {String} --resize-gap - The gap CSS custom property.
 * @cssprop {String} --resize-padding-bottom - The padding bottom CSS custom property.
 * @cssprop {String} --resize-padding-left - The padding left CSS custom property.
 * @cssprop {String} --resize-padding-right - The padding right CSS custom property.
 * @cssprop {String} --resize-padding-top - The padding top CSS custom property.
 * @cssprop {String} --resize-shadow - The shadow CSS custom property.
 * @cssprop {String} --resize-shadow-blur - The shadow blur CSS custom property.
 * @cssprop {String} --resize-shadow-color - The shadow color CSS custom property.
 * @cssprop {String} --resize-shadow-offset-x - The shadow offset x CSS custom property.
 * @cssprop {String} --resize-shadow-offset-y - The shadow offset y CSS custom property.
 * @cssprop {String} --resize-shadow-spread - The shadow spread CSS custom property.
 * @cssprop {String} --resize-transition-duration - The transition duration CSS custom property.
 * @cssprop {String} --resize-transition-mode - The transition mode CSS custom property.
 * @cssprop {String} --resize-transition-property - The transition property CSS custom property.
 * @cssprop {String} --resize-translate - The translate CSS custom property.
 *
 * @fires resizeResizeStarted {ResizeStartEvent} - Fired when a resize operation is started.
 * @fires resizeResized {ResizingEvent} - Fired when a resize operation is in progress.
 * @fires resizeResizeEnded {ResizeEndEvent} - Fired when a resize operation is ended.
 * @fires resizeResizeCanceled {ResizeCancelEvent} - Fired when a resize operation is canceled.
 *
 * @dependency mosaik-thumb - The Thumb element.
 *
 * @example
 * ```html
 * <mosaik-resize mode="immediate">
 *   <div style="width: 200px; height: 150px; background-color: lightgray;">
 *     Resizable Content
 *   </div>
 * </mosaik-resize>
 * ```
 */
let ResizeElement = class ResizeElement extends Themeable(Slottable(CustomElement)) {
    // #region Fields
    _resizeContainerController;
    _ghostFactory;
    _mode;
    _active;
    _hasPointer;
    _pointerenterSubscription;
    _pointerleaveSubscription;
    _containerElement;
    _sideThumbElement;
    _cornerThumbElement;
    _bottomThumbElement;
    // #endregion
    // #region Ctor
    /**
     * Constructs a new instance of the `ResizeElement` class.
     *
     * @public
     */
    constructor() {
        super();
        this._ghostFactory = undefined;
        this._mode = 'immediate';
        this._active = false;
        this._hasPointer = false;
        this._containerElement = undefined;
        this._sideThumbElement = undefined;
        this._cornerThumbElement = undefined;
        this._bottomThumbElement = undefined;
        this._resizeContainerController = new ResizeContainerController(this, {
            mode: this._mode,
            deferredFactory: this._ghostFactory,
            start: (x) => this.handleResizeStart(x),
            resize: (x) => this.handleResize(x),
            end: (x) => this.handleResizeEnd(x),
            cancel: (x) => this.handleResizeCancel(x),
            resizeTarget: () => this._containerElement
        });
    }
    // #endregion
    // #region Properties
    /**
     * Returns the `is` property.
     * The `is` property represents natural name of this element.
     *
     * @public
     * @static
     * @readonly
     */
    static get is() {
        return 'mosaik-resize';
    }
    /**
     * Gets or sets the `mode` property.
     *
     * @public
     * @attr
     */
    get mode() {
        return this._mode;
    }
    set mode(value) {
        if (this._mode !== value) {
            this._mode = value;
            this._resizeContainerController.set({ mode: this._mode });
            this.requestUpdate('mode');
        }
    }
    /**
     * Gets or sets the `active` property.
     *
     * @public
     * @attr
     */
    get active() {
        return this._active;
    }
    set active(value) {
        if (this._active !== value) {
            this._active = value;
            this.requestUpdate('active');
        }
    }
    /**
     * Gets or sets the `ghostFactory` property.
     *
     * @public
     */
    get ghostFactory() {
        return this._ghostFactory;
    }
    set ghostFactory(value) {
        if (this._ghostFactory !== value) {
            this._ghostFactory = value;
            this._resizeContainerController.set({ deferredFactory: this._ghostFactory });
            this.requestUpdate('ghostFactory');
        }
    }
    /**
     * Gets the `hasPointer` property.
     *
     * @private
     * @readonly
     */
    get hasPointer() {
        return this._hasPointer;
    }
    // #endregion
    // #region Methods
    /**
     * @public
     * @override
     */
    disconnectedCallback() {
        super.disconnectedCallback();
        this._pointerenterSubscription?.dispose();
        this._pointerleaveSubscription?.dispose();
    }
    /**
     * @protected
     * @override
     */
    onApplyTemplate() {
        super.onApplyTemplate();
        this._containerElement = this.getTemplatePart('root', 'token');
        this._pointerenterSubscription = on(this._containerElement, 'pointerenter', () => {
            this._hasPointer = true;
            this.requestUpdate('hasPointer');
        });
        this._pointerleaveSubscription = on(this._containerElement, 'pointerleave', () => {
            this._hasPointer = false;
            this.requestUpdate('hasPointer');
        });
        this._resizeContainerController.set({
            thumbs: {
                [ResizeDirection.North]: this.getTemplatePart(`thumb ${ResizeDirection.North}`),
                [ResizeDirection.East]: this.getTemplatePart(`thumb ${ResizeDirection.East}`),
                [ResizeDirection.South]: this.getTemplatePart(`thumb ${ResizeDirection.South}`),
                [ResizeDirection.West]: this.getTemplatePart(`thumb ${ResizeDirection.West}`),
                [ResizeDirection.NorthEast]: this.getTemplatePart(`thumb ${ResizeDirection.NorthEast}`),
                [ResizeDirection.SouthEast]: this.getTemplatePart(`thumb ${ResizeDirection.SouthEast}`),
                [ResizeDirection.SouthWest]: this.getTemplatePart(`thumb ${ResizeDirection.SouthWest}`),
                [ResizeDirection.NorthWest]: this.getTemplatePart(`thumb ${ResizeDirection.NorthWest}`)
            }
        });
    }
    /**
     * @protected
     * @override
     */
    createRenderRoot() {
        const root = super.createRenderRoot();
        root.addEventListener('slotchange', () => this.requestUpdate());
        return root;
    }
    /**
     * @private
     */
    updateResizingState(params) {
        if (params.state.trigger === this._sideThumbElement) {
            params.state.current.height = params.state.initial.height;
        }
        else if (params.state.trigger === this._bottomThumbElement) {
            params.state.current.width = params.state.initial.width;
        }
    }
    /**
     * @private
     */
    handleResizeStart(params) {
        params.event.preventDefault();
        return this.emit('resizeResizeStarted', {
            bubbles: false,
            cancelable: true,
            detail: params
        });
    }
    /**
     * @private
     */
    handleResize(params) {
        this.updateResizingState(params);
        this.emit('resizeResized', {
            bubbles: false,
            detail: params
        });
    }
    /**
     * @private
     */
    handleResizeEnd(params) {
        this.emit('resizeResizeEnded', {
            bubbles: false,
            detail: params
        });
    }
    /**
     * @private
     */
    handleResizeCancel({ initial }) {
        this._resizeContainerController.dispose();
        if (this.mode !== 'deferred') {
            if (this._containerElement) {
                RendererServiceLocator.current.setStyle(this._containerElement, 'width', `${initial.width}px`);
                RendererServiceLocator.current.setStyle(this._containerElement, 'height', `${initial.height}px`);
            }
        }
        this.emit('resizeResizeCanceled', {
            bubbles: false,
            cancelable: false
        });
    }
};
__decorate([
    Attribute({ type: ContainerResizeMode }),
    __metadata("design:type", String),
    __metadata("design:paramtypes", [String])
], ResizeElement.prototype, "mode", null);
__decorate([
    Attribute({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [Boolean])
], ResizeElement.prototype, "active", null);
__decorate([
    Property({ type: Function }),
    __metadata("design:type", Object),
    __metadata("design:paramtypes", [Object])
], ResizeElement.prototype, "ghostFactory", null);
__decorate([
    Property({
        type: Boolean,
        useDefault: true
    }),
    __metadata("design:type", Boolean),
    __metadata("design:paramtypes", [])
], ResizeElement.prototype, "hasPointer", null);
ResizeElement = __decorate([
    Component({
        selector: 'mosaik-resize',
        template: resizeElementTemplate,
        themes: {
            joy: resizeElementJoyStyle
            //     memphis: splitElementMemphisStyle,
            //     cosmopolitan: splitElementCosmopolitanStyle
        },
        imports: []
    }),
    __metadata("design:paramtypes", [])
], ResizeElement);
export { ResizeElement };
//# sourceMappingURL=ResizeElement.js.map