{"version":3,"file":"button.vue.cjs","sources":["../../../components/button/button.vue"],"sourcesContent":["<template>\n  <button\n    :class=\"[\n      'base-button__button',\n      buttonClasses(),\n    ]\"\n    data-qa=\"dt-button\"\n    :type=\"type\"\n    :disabled=\"disabled\"\n    :style=\"{ width: width }\"\n    :aria-live=\"computedAriaLive\"\n    :aria-label=\"loading ? 'loading' : $attrs['aria-label']\"\n    v-on=\"buttonListeners\"\n  >\n    <!-- NOTE(cormac): This span is needed since we can't apply styles to slots. -->\n    <span\n      v-if=\"shouldRenderIcon()\"\n      data-qa=\"dt-button-icon\"\n      :class=\"[\n        'base-button__icon',\n        'd-btn__icon',\n        ICON_POSITION_MODIFIERS[iconPosition],\n      ]\"\n    >\n      <!-- @slot Button icon -->\n      <slot\n        name=\"icon\"\n        :icon-size=\"iconSize\"\n      />\n    </span>\n    <span\n      v-if=\"$slots.default\"\n      data-qa=\"dt-button-label\"\n      :class=\"['d-btn__label', 'base-button__label', labelClass]\"\n    >\n      <!-- @slot Content within button -->\n      <slot />\n    </span>\n  </button>\n</template>\n\n<script>\nimport Vue from 'vue';\n\nimport {\n  BUTTON_SIZE_MODIFIERS,\n  BUTTON_KIND_MODIFIERS,\n  BUTTON_IMPORTANCE_MODIFIERS,\n  BUTTON_ICON_SIZES,\n  BUTTON_TYPES,\n  ICON_POSITION_MODIFIERS,\n  INVALID_COMBINATION,\n} from './button_constants';\n\nimport { LINK_KIND_MODIFIERS, getLinkKindModifier } from '@/components/link';\n\n/**\n * A button is a UI element which allows users to take an action throughout the app.\n * It is important a button is identifiable, consistent, and communicates its actions clearly,\n * and is appropriately sized to its action.\n * @see https://dialtone.dialpad.com/components/button.html\n */\nexport default {\n  name: 'DtButton',\n\n  props: {\n    /**\n     * Whether the button is a circle or not.\n     * @values true, false\n     */\n    circle: {\n      type: Boolean,\n      default: false,\n    },\n\n    /**\n     * The position of the icon slot within the button.\n     * @values left, right, top, bottom\n     */\n    iconPosition: {\n      type: String,\n      default: 'left',\n      validator: (position) => Object.keys(ICON_POSITION_MODIFIERS).includes(position),\n    },\n\n    /**\n     * The fill and outline of the button associated with its visual importance.\n     * @values clear, outlined, primary\n     */\n    importance: {\n      type: String,\n      default: 'primary',\n      validator: (i) => Object.keys(BUTTON_IMPORTANCE_MODIFIERS).includes(i),\n    },\n\n    /**\n     * Whether the button should be styled as a link or not.\n     * @values true, false\n     * @see DtLink\n     */\n    link: {\n      type: Boolean,\n      default: false,\n    },\n\n    /**\n     * The color of the link and button if the button is styled as a link.\n     * @values default, warning, danger, success, muted\n     * @see DtLink\n     */\n    linkKind: {\n      type: String,\n      default: 'default',\n      validator: (lk) => Object.keys(LINK_KIND_MODIFIERS).includes(lk),\n    },\n\n    /**\n     * Determines whether the link should have inverted styling if the button is styled as a link.\n     * @values true, false\n     * @see DtLink\n     */\n    linkInverted: {\n      type: Boolean,\n      default: false,\n    },\n\n    /**\n     * HTML button disabled attribute\n     * <a class=\"d-link\" href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#disabled\" target=\"_blank\"> (Reference) </a>\n     * @values true, false\n     */\n    disabled: {\n      type: Boolean,\n      default: false,\n    },\n\n    /**\n     * HTML button type attribute\n     * <a\n     *   class=\"d-link\"\n     *   href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type\"\n     *   target=\"_blank\"\n     * >\n     *   (Reference)\n     * </a>\n     * @values button, submit, reset\n     */\n    type: {\n      type: String,\n      default: 'button',\n      validator: (t) => BUTTON_TYPES.includes(t),\n    },\n\n    /**\n     * Button width, accepts\n     * <a class=\"d-link\" href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/width\" target=\"_blank\">\n     *   CSS width attribute\n     * </a>\n     * values\n     */\n    width: {\n      type: String,\n      default: null,\n    },\n\n    /**\n     * The size of the button.\n     * @values xs, sm, md, lg, xl\n     */\n    size: {\n      type: String,\n      default: 'md',\n      validator: (s) => Object.keys(BUTTON_SIZE_MODIFIERS).includes(s),\n    },\n\n    /**\n     * Used to customize the label container\n     */\n    labelClass: {\n      type: [String, Array, Object],\n      default: '',\n    },\n\n    /**\n     * Whether the button should display a loading animation or not.\n     * @values true, false\n     */\n    loading: {\n      type: Boolean,\n      default: false,\n    },\n\n    /**\n     * The color of the button.\n     * @values default, muted, danger, inverted\n     */\n    kind: {\n      type: String,\n      default: 'default',\n      validator: (k) => Object.keys(BUTTON_KIND_MODIFIERS).includes(k),\n    },\n\n    /**\n     * Determines whether a screenreader reads live updates of\n     * the button content to the user while the button\n     * is in focus. default is to not.\n     * @values true, false\n     */\n    assertiveOnFocus: {\n      type: Boolean,\n      default: false,\n    },\n\n    /**\n     * Determines whether the button should have active styling\n     * default is false.\n     * @values true, false\n     */\n    active: {\n      type: Boolean,\n      default: false,\n    },\n  },\n\n  emits: [\n    /**\n     * Native button click event\n     *\n     * @event click\n     * @type {PointerEvent | KeyboardEvent}\n     */\n    'click',\n\n    /**\n     * Native button focus in event\n     *\n     * @event focusin\n     * @type {FocusEvent}\n     */\n    'focusin',\n\n    /**\n     * Native button focus out event\n     *\n     * @event focusout\n     * @type {FocusEvent}\n     */\n    'focusout',\n  ],\n\n  data () {\n    return {\n      ICON_POSITION_MODIFIERS,\n      // whether the button is currently in focus\n      isInFocus: false,\n    };\n  },\n\n  computed: {\n\n    buttonListeners () {\n      if (!this.assertiveOnFocus) {\n        return this.$listeners;\n      }\n      return {\n        ...this.$listeners,\n        focusin: (e) => {\n          this.isInFocus = true;\n        },\n\n        focusout: (e) => {\n          this.isInFocus = false;\n        },\n      };\n    },\n\n    computedAriaLive () {\n      return this.assertiveOnFocus && this.isInFocus ? 'assertive' : this.$attrs.ariaLive;\n    },\n\n    iconSize () {\n      return BUTTON_ICON_SIZES[this.size];\n    },\n  },\n\n  watch: {\n    $props: {\n      deep: true,\n      immediate: true,\n      handler () {\n        if (process.env.NODE_ENV === 'production') return;\n\n        if (this.circle && this.link) {\n          Vue.util.warn('You cannot enable circle and link at the same time', this);\n        }\n\n        this.isInvalidPropCombination(this.circle, this.kind, this.importance);\n      },\n    },\n  },\n\n  methods: {\n    buttonClasses () {\n      if (this.link) {\n        return [\n          'd-link',\n          getLinkKindModifier(this.linkKind, this.linkInverted),\n          BUTTON_SIZE_MODIFIERS[this.size],\n        ];\n      }\n      return [\n        'd-btn',\n        BUTTON_IMPORTANCE_MODIFIERS[this.importance],\n        BUTTON_KIND_MODIFIERS[this.kind],\n        BUTTON_SIZE_MODIFIERS[this.size],\n        {\n          'd-btn--circle': this.circle,\n          'd-btn--loading': this.loading,\n          'd-btn--icon-only': this.isIconOnly(),\n          'd-btn--vertical': this.isVerticalIconLayout(),\n          'd-btn--active': this.active,\n        },\n      ];\n    },\n\n    isInvalidPropCombination (circle, kind, importance) {\n      for (const row of INVALID_COMBINATION) {\n        if (circle === row.circle && kind === row.kind && importance === row.importance) {\n          console.warn(row.message);\n          return false;\n        }\n      }\n      return true;\n    },\n\n    shouldRenderIcon () {\n      return this.$scopedSlots.icon && this.$scopedSlots.icon() && !this.link;\n    },\n\n    isIconOnly () {\n      return this.shouldRenderIcon() && !this.$slots.default;\n    },\n\n    isVerticalIconLayout () {\n      return !this.isIconOnly() && ['top', 'bottom'].includes(this.iconPosition);\n    },\n  },\n};\n</script>\n"],"names":["ICON_POSITION_MODIFIERS","BUTTON_IMPORTANCE_MODIFIERS","LINK_KIND_MODIFIERS","BUTTON_TYPES","BUTTON_SIZE_MODIFIERS","BUTTON_KIND_MODIFIERS","BUTTON_ICON_SIZES","getLinkKindModifier","INVALID_COMBINATION"],"mappings":"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"}