UNPKG

bootstrap-vue

Version:

BootstrapVue provides one of the most comprehensive implementations of Bootstrap 4 components and grid system for Vue.js and with extensive and automated WAI-ARIA accessibility markup.

229 lines (201 loc) 6.38 kB
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; import { assign, keys } from '../../utils/object'; import { arrayIncludes, concat } from '../../utils/array'; import { mergeData } from 'vue-functional-data-merge'; /** * The Link component is used in many other BV components. * As such, sharing its props makes supporting all its features easier. * However, some components need to modify the defaults for their own purpose. * Prefer sharing a fresh copy of the props to ensure mutations * do not affect other component references to the props. * * https://github.com/vuejs/vue-router/blob/dev/src/components/link.js * @return {{}} */ export function propsFactory() { return { href: { type: String, default: null }, rel: { type: String, default: null }, target: { type: String, default: '_self' }, active: { type: Boolean, default: false }, activeClass: { type: String, default: 'active' }, append: { type: Boolean, default: false }, disabled: { type: Boolean, default: false }, event: { type: [String, Array], default: 'click' }, exact: { type: Boolean, default: false }, exactActiveClass: { type: String, default: 'active' }, replace: { type: Boolean, default: false }, routerTag: { type: String, default: 'a' }, to: { type: [String, Object], default: null } }; } export var props = propsFactory(); export function pickLinkProps(propsToPick) { var freshLinkProps = propsFactory(); // Normalize everything to array. propsToPick = concat(propsToPick); return keys(freshLinkProps).reduce(function (memo, prop) { if (arrayIncludes(propsToPick, prop)) { memo[prop] = freshLinkProps[prop]; } return memo; }, {}); } export function omitLinkProps(propsToOmit) { var freshLinkProps = propsFactory(); // Normalize everything to array. propsToOmit = concat(propsToOmit); return keys(props).reduce(function (memo, prop) { if (!arrayIncludes(propsToOmit, prop)) { memo[prop] = freshLinkProps[prop]; } return memo; }, {}); } export var computed = { linkProps: function linkProps() { var linkProps = {}; var propKeys = keys(props); for (var i = 0; i < propKeys.length; i++) { var prop = propKeys[i]; // Computed Vue getters are bound to the instance. linkProps[prop] = this[prop]; } return linkProps; } }; function computeTag(props, parent) { return Boolean(parent.$router) && props.to && !props.disabled ? 'router-link' : 'a'; } function computeHref(_ref, tag) { var disabled = _ref.disabled, href = _ref.href, to = _ref.to; // We've already checked the parent.$router in computeTag, // so router-link means live router. // When deferring to Vue Router's router-link, // don't use the href attr at all. // Must return undefined for router-link to populate href. if (tag === 'router-link') return void 0; // If href explicitly provided if (href) return href; // Reconstruct href when `to` used, but no router if (to) { // Fallback to `to` prop (if `to` is a string) if (typeof to === 'string') return to; // Fallback to `to.path` prop (if `to` is an object) if ((typeof to === 'undefined' ? 'undefined' : _typeof(to)) === 'object' && typeof to.path === 'string') return to.path; } // If nothing is provided use '#' return '#'; } function computeRel(_ref2) { var target = _ref2.target, rel = _ref2.rel; if (target === '_blank' && rel === null) { return 'noopener'; } return rel || null; } function clickHandlerFactory(_ref3) { var disabled = _ref3.disabled, tag = _ref3.tag, href = _ref3.href, suppliedHandler = _ref3.suppliedHandler, parent = _ref3.parent; var isRouterLink = tag === 'router-link'; return function onClick(e) { if (disabled && e instanceof Event) { // Stop event from bubbling up. e.stopPropagation(); // Kill the event loop attached to this specific EventTarget. e.stopImmediatePropagation(); } else { parent.$root.$emit('clicked::link', e); if (isRouterLink && e.target.__vue__) { e.target.__vue__.$emit('click', e); } if (typeof suppliedHandler === 'function') { suppliedHandler.apply(undefined, arguments); } } if (!isRouterLink && href === '#' || disabled) { // Stop scroll-to-top behavior or navigation. e.preventDefault(); } }; } export default { functional: true, props: propsFactory(), render: function render(h, _ref4) { var props = _ref4.props, data = _ref4.data, parent = _ref4.parent, children = _ref4.children; var tag = computeTag(props, parent); var rel = computeRel(props); var href = computeHref(props, tag); var eventType = tag === 'router-link' ? 'nativeOn' : 'on'; var suppliedHandler = (data[eventType] || {}).click; var handlers = { click: clickHandlerFactory({ tag: tag, href: href, disabled: props.disabled, suppliedHandler: suppliedHandler, parent: parent }) }; var componentData = mergeData(data, { class: [props.active ? props.exact ? props.exactActiveClass : props.activeClass : null, { disabled: props.disabled }], attrs: { rel: rel, href: href, target: props.target, tabindex: props.disabled ? '-1' : data.attrs ? data.attrs.tabindex : null, 'aria-disabled': tag === 'a' && props.disabled ? 'true' : null }, props: assign(props, { tag: props.routerTag }) }); // If href prop exists on router-link (even undefined or null) it fails working on SSR if (!componentData.attrs.href) { delete componentData.attrs.href; } // We want to overwrite any click handler since our callback // will invoke the supplied handler if !props.disabled componentData[eventType] = assign(componentData[eventType] || {}, handlers); return h(tag, componentData, children); } };