All files / lib/components button.vue

71.05% Statements 27/38
76.09% Branches 35/46
94.12% Functions 16/17
71.05% Lines 27/38
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 13418x 18x 18x   18x 18x                     18x       18x     18x                 18x                                       18x         1285x     1280x     1280x     1280x     1280x     1280x     1280x     1285x     1285x     1285x   5x     1280x     1280x                                                                 8x       8x 8x   2x  
<template>
    <button v-bind="conditionalLinkProps"
    I        :is="componentType"
            :class="classList"
           E :data-toggle="isToggle ? 'button' : null"
            :aria-pressed="ariaPressed"
            :type="btnType"
            :disabled="disabled"
            :tabindex="(disabled && componentType !== 'button') ? '-1' : null"
            @focusin.native="handleFocus"
            @focusout.native="handleFocus"
            @click="onClick">
        <slot></slot>
    </button>
</template>
 
<script>
import bLink from './link.vue';
import { omitLinkProps, props as originalLinkProps, computed } from '../mixins/link';
import { assign } from '../utils/object';
 
// Grab a fresh object of link props (omitLinkProps does this)
// less the 'href' and 'to' props
// that we will reconstruct without any defaults
// so our computed 'componentType' functions properly
const linkProps = assign(omitLinkProps('href', 'to'), {
    href: { type: originalLinkProps.href.type },
    to: { type: originalLinkProps.to.type }
});
 
export default {
    components: { bLink },
    computed: {
        linkProps: computed.linkProps,
        classList() {
            return [
                'btn',
                this.btnVariant,
                this.btnSize,
                this.btnBlock,
                this.btnDisabled,
                this.btnPressed
            ];
        },
        componentType() {
            return (this.href || this.to) ? 'b-link' : 'button';
        },
        btnBlock() {
            return this.block ? 'btn-block' : '';
        },
        btnVariant() {
            return this.variant ? `btn-${this.variant}` : `btn-secondary`;
        },
        btnSize() {
            return this.size ? `btn-${this.size}` : '';
        },
        btnDisabled() {
            return this.disabled ? 'disabled' : '';
        },
        btnType() {
            return (this.href || this.to) ? null : this.type;
        },
        isToggle() {
            return this.pressed === true || this.pressed === false;
        },
        btnPressed() {
            return this.pressed ? 'active' : '';
        },
        ariaPressed() {
            if (this.isToggle) {
                // Add aria-pressed state
                return this.pressed ? 'true' : 'false';
            }
            // Remove aria-pressed attribute
            return null;
        },
        conditionalLinkProps() {
            return this.componentType === 'button' ? {} : this.linkProps;
        }
    },
    // merge our prepared link props with button props
    props: assign(linkProps, {
        block: {
            type: Boolean,
            default: false
        },
        disabled: {
            type: Boolean,
            default: false
        },
        size: {
            type: String,
            default: null
        },
        variant: {
            type: String,
            default: null
        },
        type: {
            type: String,
            default: 'button'
        },
        pressed: {
            // tri-state prop: true, false or null
            type: Boolean,
            default: null
        }
    }),
    methods: {
        onClick(e) {
            if (this.disabled) {
                e.stopPropagation();
                e.preventDefault();
            } else {
                this.$emit('click', e);
                if (this.isToggle) {
                    // Emit .sync notification about pressed prop state changing
                    this.$emit('update:pressed', !this.pressed);
                }
            }
        },
        handleFocus(evt) {
            if (this.isToggle) {
                if (evt.type === 'focusin') {
                    evt.target.classList.add('focus');
                I} else if (evt.type === 'focusout') {
                    evt.target.classList.remove('focus');
                }
            }
        }
    }
};
</script>