// #region Imports
import { ControllerBase } from './Abstracts/ControllerBase';
/**
 * ResizeController is a ReactiveController that integrates a ResizeObserver
 * with a ReactiveControllerHost's reactive update lifecycle. This is typically
 * a ReactiveElement or LitElement. ResizeObservers can be used to detect
 * size changes to DOM elements.
 *
 * The controller can specify a `target` element to observe and the
 * configuration options to pass to the ResizeObserver. The `observe`
 * method can be called to observe additional elements.
 *
 * When a change is detected, the controller's given `callback` function is
 * used to process the result into a value which is stored on the controller.
 * The controller's `value` is usable during the host's update cycle.
 *
 * @public
 */
export class ResizeController extends ControllerBase {
    // #region Fields
    _targets = new Set();
    _config;
    _observer;
    _skipInitial;
    /**
         * Flag used to help manage calling the `callback` when observe is called
         * in addition to when a mutation occurs. This is done to help setup initial
         * state and is performed async by requesting a host update and calling
         * `handleChanges` once by checking and then resetting this flag.
         */
    _unobservedUpdate = false;
    // #endregion
    // #region Ctor
    constructor(host, config) {
        super(host);
        // Target defaults to `host` unless explicitly `null`.
        if (config?.target !== null) {
            this._targets.add(config?.target ?? host);
        }
        this._config = config?.config;
        this._skipInitial = config?.skipInitial ?? false;
        this.callback = config?.callback;
        this._observer = new ResizeObserver((entries) => {
            this.handleChanges(entries);
            this.host.requestUpdate();
        });
    }
    // #endregion
    // #region Properties
    /**
    * The result of processing the observer's changes via the `callback`
    * function.
    */
    value;
    /**
         * Function that returns a value processed from the observer's changes.
         * The result is stored in the `value` property.
         */
    callback;
    // #endregion
    // #region Methods
    /**
     * @public
     * @override
     */
    hostConnected() {
        for (const target of this._targets) {
            target.setAttribute('resize-observed', '');
            this.observe(target);
        }
    }
    /**
     * @public
     * @override
     */
    hostDisconnected() {
        for (const target of this._targets) {
            target.removeAttribute('resize-observed');
        }
        this.disconnect();
    }
    /**
     * @public
     * @override
     */
    hostUpdated() {
        // Handle initial state as a set of 0 changes. This helps setup initial
        // state and promotes UI = f(state) since ideally the callback does not
        // rely on changes.
        if (!this._skipInitial && this._unobservedUpdate) {
            this.handleChanges([]);
        }
        this._unobservedUpdate = false;
    }
    /**
     * Observe the target element. The controller's `target` is automatically
     * observed when the host connects.
     *
     * @public
     * @param target Element to observe
     */
    observe(target) {
        this._targets.add(target);
        this._observer.observe(target, this._config);
        this._unobservedUpdate = true;
        this.host.requestUpdate();
    }
    /**
     * Unobserve the target element.
     *
     * @public
     * @param target Element to unobserve
     */
    unobserve(target) {
        this._targets.delete(target);
        this._observer.unobserve(target);
    }
    /**
     * Disconnects the observer. This is done automatically when the host
     * disconnects.
     */
    disconnect() {
        this._observer.disconnect();
    }
    /**
     * Process the observer's changes with the controller's `callback`
     * function to produce a result stored in the `value` property.
     */
    handleChanges(entries) {
        this.value = this.callback?.(entries, this._observer);
    }
}
//# sourceMappingURL=ResizeController.js.map