import { Host, h } from '@stencil/core';
/**
 * This component has been built for abstracting simple CSS transitions with
 * dynamically rendered elements (e.g. `v-if` in Vue). This is primarily used
 * internally within BSDS. Some implementation notes:
 * - By default the transition plays on mount.
 * - The immediate child element of this component will get the class and/or
 *   attribute added to it.
 * - If desired, leave transition may be played prior to removing from the DOM
 *   by setting the `leaveTrigger` prop to `true` and then wait for `leaveend`
 *   to emit before removing.
 * - Optionally, `enterControlled` may be set to `true` to prevent the enter
 *   on mount. Useful when the enter transition needs to be triggered manually
 *   (e.g. `v-show` in Vue). Set `enterTrigger` to `true` when ready to play.
 * - To function properly, there should only be one container child
 *   element of this component.
 */
export class BsTransition {
  constructor() {
    this.timers = {
      enterMountTimer: undefined,
      enterDurationTimer: undefined,
      leaveMountTimer: undefined,
      leaveDurationTimer: undefined
    };
    this.enterClass = undefined;
    this.enterAttribute = undefined;
    this.enterDuration = undefined;
    this.leaveClass = undefined;
    this.leaveAttribute = undefined;
    this.leaveDuration = undefined;
    this.enterControlled = false;
    this.enterTrigger = false;
    this.leaveTrigger = false;
  }
  /** Lazy-load the child element if it's available. */
  get childEl() {
    if (!this._childEl && this.hostEl.children.length > 0) {
      this._childEl = this.hostEl.children[0];
    }
    return this._childEl;
  }
  componentDidLoad() {
    if (!this.enterControlled) {
      this.handleEnterTransition();
    }
  }
  handleEnterTrigger(newValue) {
    if (this.enterControlled && newValue) {
      this.handleEnterTransition();
    }
  }
  handleLeaveTrigger(newValue) {
    if (newValue) {
      this.handleLeaveTransition();
    }
  }
  handleEnterTransition() {
    // Wait a few milliseconds to allow for the element to be rendered
    this.timers.enterMountTimer = setTimeout(() => {
      this.addEnterClassAndAttribute();
      this.timers.enterDurationTimer = setTimeout(() => {
        this.enterend.emit();
      }, this.enterDuration);
    }, 10);
  }
  /** Adds the "enter" class and/or attribute */
  addEnterClassAndAttribute() {
    if (this.enterClass) {
      this.childEl.classList.add(this.enterClass);
    }
    if (this.enterAttribute) {
      this.childEl.setAttribute(this.enterAttribute, '');
    }
  }
  handleLeaveTransition() {
    var _a;
    // Add/Remove the classes
    this.removeEnterClassAndAttribute();
    this.addLeaveClassAndAttribute();
    this.timers.leaveDurationTimer = setTimeout(() => {
      this.leaveend.emit();
    }, (_a = this.leaveDuration) !== null && _a !== void 0 ? _a : this.enterDuration);
  }
  /** Adds the "leave" class and/or attribute */
  addLeaveClassAndAttribute() {
    if (this.leaveClass) {
      this.childEl.classList.add(this.leaveClass);
    }
    if (this.leaveAttribute) {
      this.childEl.setAttribute(this.leaveAttribute, '');
    }
  }
  /** Removes the "enter" class and/or attribute */
  removeEnterClassAndAttribute() {
    if (this.enterClass) {
      this.childEl.classList.remove(this.enterClass);
    }
    if (this.enterAttribute) {
      this.childEl.removeAttribute(this.enterAttribute);
    }
  }
  disconnectedCallback() {
    // Cleanup timers
    Object.keys(this.timers).forEach(timer => {
      if (this.timers[timer]) {
        clearTimeout(this.timers[timer]);
        this.timers[timer] = undefined;
      }
    });
  }
  render() {
    return (h(Host, null, h("slot", null)));
  }
  static get is() { return "bs-transition"; }
  static get properties() {
    return {
      "enterClass": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Transition class name to be added when entering."
        },
        "attribute": "enter-class",
        "reflect": false,
        "defaultValue": "undefined"
      },
      "enterAttribute": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Transition attribute to be added when entering."
        },
        "attribute": "enter-attribute",
        "reflect": false,
        "defaultValue": "undefined"
      },
      "enterDuration": {
        "type": "number",
        "mutable": false,
        "complexType": {
          "original": "number",
          "resolved": "number",
          "references": {}
        },
        "required": true,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Duration of the enter transition in milliseconds."
        },
        "attribute": "enter-duration",
        "reflect": false
      },
      "leaveClass": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Transition class name to be added when leaving."
        },
        "attribute": "leave-class",
        "reflect": false,
        "defaultValue": "undefined"
      },
      "leaveAttribute": {
        "type": "string",
        "mutable": false,
        "complexType": {
          "original": "string",
          "resolved": "string",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Transition attribute to be added when leaving."
        },
        "attribute": "leave-attribute",
        "reflect": false,
        "defaultValue": "undefined"
      },
      "leaveDuration": {
        "type": "number",
        "mutable": false,
        "complexType": {
          "original": "number",
          "resolved": "number",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Duration of the leave transition. If not given, will default to\n`enterDuration` in milliseconds."
        },
        "attribute": "leave-duration",
        "reflect": false,
        "defaultValue": "undefined"
      },
      "enterControlled": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Whether or not the enter transition should be controlled manually. Useful\nwhen the enter transition needs to be triggered manually (e.g. \\`v-show\\`\nin Vue)."
        },
        "attribute": "enter-controlled",
        "reflect": false,
        "defaultValue": "false"
      },
      "enterTrigger": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "Only used when \\`enterControlled\\` is \\`true\\`. When ready to play the\nenter transition, set this to \\`true\\`."
        },
        "attribute": "enter-trigger",
        "reflect": false,
        "defaultValue": "false"
      },
      "leaveTrigger": {
        "type": "boolean",
        "mutable": false,
        "complexType": {
          "original": "boolean",
          "resolved": "boolean",
          "references": {}
        },
        "required": false,
        "optional": false,
        "docs": {
          "tags": [],
          "text": "If desired, leave transition needs to be triggered manually. Set this to\n\\`true\\` when ready to fire leave transition."
        },
        "attribute": "leave-trigger",
        "reflect": false,
        "defaultValue": "false"
      }
    };
  }
  static get events() {
    return [{
        "method": "enterend",
        "name": "enterend",
        "bubbles": false,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": "Emits when the enter transition has ended. The element should be fully\nrendered by now and may be manipulated (e.g. setting focus)."
        },
        "complexType": {
          "original": "any",
          "resolved": "any",
          "references": {}
        }
      }, {
        "method": "leaveend",
        "name": "leaveend",
        "bubbles": false,
        "cancelable": true,
        "composed": true,
        "docs": {
          "tags": [],
          "text": "Only emits when \\`leaveTrigger\\` is toggled and the leave transition has\nended. The element can be fully removed from the DOM now."
        },
        "complexType": {
          "original": "any",
          "resolved": "any",
          "references": {}
        }
      }];
  }
  static get elementRef() { return "hostEl"; }
  static get watchers() {
    return [{
        "propName": "enterTrigger",
        "methodName": "handleEnterTrigger"
      }, {
        "propName": "leaveTrigger",
        "methodName": "handleLeaveTrigger"
      }];
  }
}
//# sourceMappingURL=bs-transition.js.map
