import { Component, Element, Event, h, Prop, Watch } from '@stencil/core';
import { __ } from '@wordpress/i18n';
import { animateTo, stopAnimations } from '../../../functions/animate';
import { getAnimation, setDefaultAnimation } from '../../../functions/animation-registry';
export class ScDrawer {
  constructor() {
    /** Indicates whether or not the drawer is open. You can use this in lieu of the show/hide methods. */
    this.open = false;
    /**
     * The drawer's label as displayed in the header. You should always include a relevant label even when using
     * `no-header`, as it is required for proper accessibility.
     */
    this.label = '';
    /** The direction from which the drawer will open. */
    this.placement = 'end';
    /**
     * By default, the drawer slides out of its containing block (usually the viewport). To make the drawer slide out of
     * its parent element, set this prop and add `position: relative` to the parent.
     */
    this.contained = false;
    /**
     * Removes the header. This will also remove the default close button, so please ensure you provide an easy,
     * accessible way for users to dismiss the drawer.
     */
    this.noHeader = false;
  }
  componentDidLoad() {
    this.drawer.hidden = !this.open;
    if (this.open && !this.contained) {
      this.lockBodyScrolling();
    }
  }
  disconnectedCallback() {
    this.unLockBodyScrolling();
  }
  lockBodyScrolling() {
    document.body.classList.add('sc-scroll-lock');
  }
  unLockBodyScrolling() {
    document.body.classList.remove('sc-scroll-lock');
  }
  /** Shows the drawer. */
  async show() {
    if (this.open) {
      return undefined;
    }
    this.open = true;
  }
  /** Hides the drawer */
  async hide() {
    if (!this.open) {
      return undefined;
    }
    this.open = false;
  }
  requestClose(source) {
    const slRequestClose = this.scRequestClose.emit(source);
    if (slRequestClose.defaultPrevented) {
      const animation = getAnimation(this.el, 'drawer.denyClose');
      animateTo(this.panel, animation.keyframes, animation.options);
      return;
    }
    this.hide();
  }
  handleKeyDown(event) {
    if (event.key === 'Escape') {
      event.stopPropagation();
      this.requestClose('keyboard');
    }
  }
  async handleOpenChange() {
    if (this.open) {
      this.scShow.emit();
      this.originalTrigger = document.activeElement;
      // Lock body scrolling only if the drawer isn't contained
      if (!this.contained) {
        this.lockBodyScrolling();
      }
      // When the drawer is shown, Safari will attempt to set focus on whatever element has autofocus. This causes the
      // drawer's animation to jitter, so we'll temporarily remove the attribute, call `focus({ preventScroll: true })`
      // ourselves, and add the attribute back afterwards.
      //
      // Related: https://github.com/shoelace-style/shoelace/issues/693
      //
      const autoFocusTarget = this.el.querySelector('[autofocus]');
      if (autoFocusTarget) {
        autoFocusTarget.removeAttribute('autofocus');
      }
      await Promise.all([stopAnimations(this.drawer), stopAnimations(this.overlay)]);
      this.drawer.hidden = false;
      // Set initial focus
      requestAnimationFrame(() => {
        const slInitialFocus = this.scInitialFocus.emit();
        if (!slInitialFocus.defaultPrevented) {
          // Set focus to the autofocus target and restore the attribute
          if (autoFocusTarget) {
            autoFocusTarget.focus({ preventScroll: true });
          }
          else {
            this.panel.focus({ preventScroll: true });
          }
        }
        // Restore the autofocus attribute
        if (autoFocusTarget) {
          autoFocusTarget.setAttribute('autofocus', '');
        }
      });
      const panelAnimation = getAnimation(this.el, `drawer.show${this.placement.charAt(0).toUpperCase() + this.placement.slice(1)}`);
      const overlayAnimation = getAnimation(this.el, 'drawer.overlay.show');
      await Promise.all([animateTo(this.panel, panelAnimation.keyframes, panelAnimation.options), animateTo(this.overlay, overlayAnimation.keyframes, overlayAnimation.options)]);
      this.scAfterShow.emit();
    }
    else {
      // Hide
      this.scHide.emit();
      this.unLockBodyScrolling();
      await Promise.all([stopAnimations(this.drawer), stopAnimations(this.overlay)]);
      const panelAnimation = getAnimation(this.el, `drawer.hide${this.placement.charAt(0).toUpperCase() + this.placement.slice(1)}`);
      const overlayAnimation = getAnimation(this.el, 'drawer.overlay.hide');
      await Promise.all([animateTo(this.panel, panelAnimation.keyframes, panelAnimation.options), animateTo(this.overlay, overlayAnimation.keyframes, overlayAnimation.options)]);
      this.drawer.hidden = true;
      // Restore focus to the original trigger
      const trigger = this.originalTrigger;
      if (typeof (trigger === null || trigger === void 0 ? void 0 : trigger.focus) === 'function') {
        setTimeout(() => trigger.focus());
      }
      this.scAfterHide.emit();
    }
  }
  render() {
    return (h("div", { part: "base", class: {
        'drawer': true,
        'drawer--open': this.open,
        'drawer--top': this.placement === 'top',
        'drawer--end': this.placement === 'end',
        'drawer--bottom': this.placement === 'bottom',
        'drawer--start': this.placement === 'start',
        'drawer--contained': this.contained,
        'drawer--fixed': !this.contained,
        'drawer--has-footer': this.el.querySelector('[slot="footer"]') !== null,
      }, ref: el => (this.drawer = el), onKeyDown: (e) => this.handleKeyDown(e) },
      h("div", { part: "overlay", class: "drawer__overlay", onClick: () => this.requestClose('overlay'), tabindex: "-1", ref: el => (this.overlay = el) }),
      h("div", { part: "panel", class: "drawer__panel", role: "dialog", "aria-modal": "true", "aria-hidden": this.open ? 'false' : 'true', "aria-label": this.noHeader ? this.label : undefined, "aria-labelledby": !this.noHeader ? 'title' : undefined, tabindex: "0", ref: el => (this.panel = el) },
        !this.noHeader && (h("header", { part: "header" },
          h("slot", { name: "header" },
            h("div", { class: "drawer__header" },
              h("h2", { part: "title", class: "drawer__title", id: "title" },
                h("slot", { name: "label" },
                  this.label.length > 0 ? this.label : ' ',
                  " ")),
              h("sc-icon", { part: "close-button", exportparts: "base:close-button__base", class: "drawer__close", name: "x", label: 
                /** translators: Close this modal window. */
                __('Close', 'surecart'), onClick: () => this.requestClose('close-button') }))))),
        h("footer", { part: "header-suffix", class: "drawer__header-suffix" },
          h("slot", { name: "header-suffix" })),
        h("div", { part: "body", class: "drawer__body" },
          h("slot", null)),
        h("footer", { part: "footer", class: "drawer__footer" },
          h("slot", { name: "footer" })))));
  }
  static get is() { return "sc-drawer"; }
  static get encapsulation() { return "shadow"; }
  static get originalStyleUrls() { return {
    "$": ["sc-drawer.css"]
  }; }
  static get styleUrls() { return {
    "$": ["sc-drawer.css"]
  }; }
  static get properties() { return {
    "open": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Indicates whether or not the drawer is open. You can use this in lieu of the show/hide methods."
      },
      "attribute": "open",
      "reflect": true,
      "defaultValue": "false"
    },
    "label": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "string",
        "resolved": "string",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "The drawer's label as displayed in the header. You should always include a relevant label even when using\n`no-header`, as it is required for proper accessibility."
      },
      "attribute": "label",
      "reflect": true,
      "defaultValue": "''"
    },
    "placement": {
      "type": "string",
      "mutable": false,
      "complexType": {
        "original": "'top' | 'end' | 'bottom' | 'start'",
        "resolved": "\"bottom\" | \"end\" | \"start\" | \"top\"",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "The direction from which the drawer will open."
      },
      "attribute": "placement",
      "reflect": true,
      "defaultValue": "'end'"
    },
    "contained": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "By default, the drawer slides out of its containing block (usually the viewport). To make the drawer slide out of\nits parent element, set this prop and add `position: relative` to the parent."
      },
      "attribute": "contained",
      "reflect": true,
      "defaultValue": "false"
    },
    "noHeader": {
      "type": "boolean",
      "mutable": false,
      "complexType": {
        "original": "boolean",
        "resolved": "boolean",
        "references": {}
      },
      "required": false,
      "optional": false,
      "docs": {
        "tags": [],
        "text": "Removes the header. This will also remove the default close button, so please ensure you provide an easy,\naccessible way for users to dismiss the drawer."
      },
      "attribute": "no-header",
      "reflect": true,
      "defaultValue": "false"
    }
  }; }
  static get events() { return [{
      "method": "scInitialFocus",
      "name": "scInitialFocus",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }, {
      "method": "scRequestClose",
      "name": "scRequestClose",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "'close-button' | 'keyboard' | 'overlay'",
        "resolved": "\"close-button\" | \"keyboard\" | \"overlay\"",
        "references": {}
      }
    }, {
      "method": "scShow",
      "name": "scShow",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }, {
      "method": "scHide",
      "name": "scHide",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }, {
      "method": "scAfterShow",
      "name": "scAfterShow",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }, {
      "method": "scAfterHide",
      "name": "scAfterHide",
      "bubbles": true,
      "cancelable": true,
      "composed": true,
      "docs": {
        "tags": [],
        "text": ""
      },
      "complexType": {
        "original": "void",
        "resolved": "void",
        "references": {}
      }
    }]; }
  static get elementRef() { return "el"; }
  static get watchers() { return [{
      "propName": "open",
      "methodName": "handleOpenChange"
    }]; }
}
// Top
setDefaultAnimation('drawer.showTop', {
  keyframes: [
    { opacity: 0, transform: 'translateY(-100%)' },
    { opacity: 1, transform: 'translateY(0)' },
  ],
  options: { duration: 250, easing: 'ease' },
});
setDefaultAnimation('drawer.hideTop', {
  keyframes: [
    { opacity: 1, transform: 'translateY(0)' },
    { opacity: 0, transform: 'translateY(-100%)' },
  ],
  options: { duration: 250, easing: 'ease' },
});
// End
setDefaultAnimation('drawer.showEnd', {
  keyframes: [
    { opacity: 0, transform: 'translateX(100%)' },
    { opacity: 1, transform: 'translateX(0)' },
  ],
  options: { duration: 250, easing: 'ease' },
});
setDefaultAnimation('drawer.hideEnd', {
  keyframes: [
    { opacity: 1, transform: 'translateX(0)' },
    { opacity: 0, transform: 'translateX(100%)' },
  ],
  options: { duration: 250, easing: 'ease' },
});
// Bottom
setDefaultAnimation('drawer.showBottom', {
  keyframes: [
    { opacity: 0, transform: 'translateY(100%)' },
    { opacity: 1, transform: 'translateY(0)' },
  ],
  options: { duration: 250, easing: 'ease' },
});
setDefaultAnimation('drawer.hideBottom', {
  keyframes: [
    { opacity: 1, transform: 'translateY(0)' },
    { opacity: 0, transform: 'translateY(100%)' },
  ],
  options: { duration: 250, easing: 'ease' },
});
// Start
setDefaultAnimation('drawer.showStart', {
  keyframes: [
    { opacity: 0, transform: 'translateX(-100%)' },
    { opacity: 1, transform: 'translateX(0)' },
  ],
  options: { duration: 250, easing: 'ease' },
});
setDefaultAnimation('drawer.hideStart', {
  keyframes: [
    { opacity: 1, transform: 'translateX(0)' },
    { opacity: 0, transform: 'translateX(-100%)' },
  ],
  options: { duration: 250, easing: 'ease' },
});
// Deny close
setDefaultAnimation('drawer.denyClose', {
  keyframes: [{ transform: 'scale(1)' }, { transform: 'scale(1.01)' }, { transform: 'scale(1)' }],
  options: { duration: 250 },
});
// Overlay
setDefaultAnimation('drawer.overlay.show', {
  keyframes: [{ opacity: 0 }, { opacity: 1 }],
  options: { duration: 250, easing: 'ease' },
});
setDefaultAnimation('drawer.overlay.hide', {
  keyframes: [{ opacity: 1 }, { opacity: 0 }],
  options: { duration: 250, easing: 'ease' },
});
