<template>
<ol class="breadcrumb">
I <li v-for="normalizedItem in normalizedItems"
:class="['breadcrumb-item', normalizedItem.active ? 'active' : null]"
E @click="onClick(normalizedItem._originalItem)"
role="presentation">
<span v-if="normalizedItem.active"
:aria-current="ariaCurrent"
v-html="normalizedItem.text"></span>
<b-link v-else
v-bind="normalizedItem._linkProps"
v-html="normalizedItem.text"></b-link>
</li>
<slot></slot>
</ol>
</template>
<script>
import bLink from './link.vue';
import { props as linkProps } from '../mixins/link';
import { arrayIncludes } from '../utils/array';
import { assign, keys } from '../utils/object';
const bLinkPropKeys = keys(linkProps);
export default {
components: { bLink },
computed: {
normalizedItems() {
let userDefinedActive = false;
const originalItemsLength = this.items.length;
return this.items.map((item, index) => {
let normalizedItem = { _originalItem: item };
// if no active state is defined,
// default to the last item in the array as active
const isLast = index === originalItemsLength - 1;
// nothing defined except the text
if (typeof item === 'string') {
assign(normalizedItem, { text: item, link: '#', active: isLast });
} else {
assign(normalizedItem, item);
}
// don't default the active state if given a boolean value,
// or if a user defined value has already been given
if (normalizedItem.active !== true && normalizedItem.active !== false && !userDefinedActive) {
normalizedItem.active = isLast;
} else if (normalizedItem.active) {
// here we know we've been given an active value,
// so we won't set a default value
userDefinedActive = true;
}
if (normalizedItem.link) {
// default the link value to bLink's href prop
normalizedItem.href = normalizedItem.link;
}
// stuff all the bLink props into a single place
// so we can bind to the component
// fIor dynamic prop proxying
normalizedItem._linkProps = keys(normalizedItem).reduce((memo, itemProp) => {
if (arrayIncludes(bLinkPropKeys, itemProp)) {
memo[itemProp] = normalizedItem[itemProp];
}
return memo;
}, {});
return normalizedItem;
});
}
},
props: {
items: {
type: Array,
default: () => [],
required: true
},
ariaCurrent: {
type: String,
default: 'location'
}
},
methods: {
onClick(item) {
this.$emit('click', item);
}
}
};
</script>
|