{"version":3,"file":"button.cjs","names":[],"sources":["../../../components/button/button.vue"],"sourcesContent":["<template>\n  <component\n    :is=\"computedTag\"\n    :class=\"[\n      'base-button__button',\n      buttonClasses(),\n    ]\"\n    data-qa=\"dt-button\"\n    :style=\"{ width: width }\"\n    :aria-live=\"computedAriaLive\"\n    :aria-label=\"loading ? i18n.$t('DIALTONE_LOADING') : $attrs['aria-label']\"\n    v-bind=\"computedAttrs\"\n    v-on=\"computedListeners\"\n  >\n    <dt-loader\n      v-if=\"loading && kind !== 'unstyled'\"\n      class=\"d-btn__loader\"\n      :size=\"loaderSize\"\n      aria-hidden=\"true\"\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        {\n          'd-btn__icon': kind !== 'unstyled',\n          [ICON_POSITION_MODIFIERS[iconPosition]]: kind !== 'unstyled',\n        },\n      ]\"\n    >\n      <!-- @slot Button icon -->\n      <slot\n        name=\"icon\"\n        :icon-size=\"iconSize\"\n      />\n    </span>\n    <span\n      v-if=\"hasSlotContent($slots.default)\"\n      data-qa=\"dt-button-label\"\n      :class=\"[\n        'base-button__label',\n        { 'd-btn__label': kind !== 'unstyled' },\n        labelClass,\n      ]\"\n    >\n      <!-- @slot Content within button -->\n      <slot />\n    </span>\n  </component>\n</template>\n\n<script>\nimport { warn, resolveComponent } from 'vue';\nimport { hasSlotContent } from '@/common/utils';\nimport DtLoader from '@/components/loader/loader.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';\nimport { DialtoneLocalization } from '@/localization';\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  compatConfig: { MODE: 3 },\n  name: 'DtButton',\n\n  components: { DtLoader },\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 class=\"d-link\" href=\"https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type\" target=\"_blank\">(Reference)</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\">CSS width attribute</a> 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, unstyled, muted, danger, positive, 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     * vue-router `to` prop. When provided, renders a `<router-link>`\n     * for client-side SPA navigation.\n     * @see https://router.vuejs.org/api/interfaces/RouterLinkProps.html#to\n     */\n    to: {\n      type: [String, Object],\n      default: null,\n    },\n\n    /**\n     * When provided, renders an `<a>` element for standard browser navigation.\n     */\n    href: {\n      type: String,\n      default: null,\n    },\n\n    /**\n     * HTML anchor target attribute. Only applied when using the `href` prop.\n     * @values _self, _blank, _parent, _top\n     */\n    target: {\n      type: String,\n      default: null,\n    },\n\n    /**\n     * HTML anchor rel attribute. Only applied when using the `href` prop.\n     */\n    rel: {\n      type: String,\n      default: null,\n    },\n\n    /**\n     * vue-router `replace` prop. When true, navigation will not leave a\n     * history entry. Only applied when using the `to` prop.\n     * @values true, false\n     */\n    replace: {\n      type: Boolean,\n      default: false,\n    },\n  },\n\n  emits: [\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      hasSlotContent,\n      i18n: new DialtoneLocalization(),\n    };\n  },\n\n  computed: {\n    computedTag () {\n      if (this.to) return this.resolveRouterLink();\n      if (this.href) return 'a';\n      return 'button';\n    },\n\n    isNativeButton () {\n      return !this.to && !this.href;\n    },\n\n    computedAttrs () {\n      if (this.to) {\n        return {\n          to: this.to,\n          replace: this.replace,\n          ...(this.disabled && { 'aria-disabled': 'true', tabindex: '-1' }),\n        };\n      }\n      if (this.href) {\n        return {\n          href: this.disabled ? null : this.href,\n          target: this.target,\n          rel: this.rel,\n          ...(this.disabled && { 'aria-disabled': 'true', tabindex: '-1' }),\n        };\n      }\n      return {\n        type: this.type,\n        disabled: this.disabled,\n      };\n    },\n\n    computedListeners () {\n      const listeners = {\n        focusin: (e) => {\n          this.isInFocus = this.assertiveOnFocus;\n          this.$emit('focusin', e);\n        },\n\n        focusout: (e) => {\n          this.isInFocus = false;\n          this.$emit('focusout', e);\n        },\n      };\n\n      if (!this.isNativeButton) {\n        // Prevent click when disabled for link elements.\n        // stopImmediatePropagation prevents parent onClick attrs from firing.\n        if (this.disabled) {\n          listeners.click = (e) => {\n            e.preventDefault();\n            e.stopImmediatePropagation();\n          };\n        }\n\n        // Space key handler: <a> only responds to Enter natively,\n        // but buttons respond to both Enter and Space.\n        listeners.keydown = (e) => {\n          if (e.key === ' ' || e.code === 'Space') {\n            e.preventDefault();\n            if (!this.disabled) {\n              e.target.click();\n            }\n          }\n        };\n      }\n\n      return listeners;\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    loaderSize () {\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          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    resolveRouterLink () {\n      try {\n        return resolveComponent('RouterLink');\n      } catch {\n        warn('DtButton: \"to\" prop requires vue-router. Falling back to <a>.');\n        return 'a';\n      }\n    },\n\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      if (this.kind === 'unstyled') {\n        return ['d-btn--unstyled'];\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      // Skip validation if unstyled is true\n      if (this.kind === 'unstyled') {\n        return true;\n      }\n\n      for (const row of INVALID_COMBINATION) {\n        if (circle === row.circle && kind === row.kind && importance === row.importance) {\n          warn(row.message);\n          return false;\n        }\n      }\n      return true;\n    },\n\n    shouldRenderIcon () {\n      return hasSlotContent(this.$slots.icon) && !this.link;\n    },\n\n    isIconOnly () {\n      return this.shouldRenderIcon() && !hasSlotContent(this.$slots.default);\n    },\n\n    isVerticalIconLayout () {\n      return !this.isIconOnly() && ['top', 'bottom'].includes(this.iconPosition);\n    },\n  },\n};\n</script>\n"],"mappings":"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"}