UNPKG

bootstrap-vue

Version:

Quickly integrate Bootstrap 4 components with Vue.js

228 lines (200 loc) 6.97 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 "../../utils"; /** * 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 = {}, 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), rel = computeRel(props), href = computeHref(props, tag), eventType = tag === "router-link" ? "nativeOn" : "on", suppliedHandler = (data[eventType] || {}).click, 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, "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); } };