UNPKG

bootstrap-vue

Version:

With more than 85 components, over 45 available plugins, several directives, and 1000+ icons, BootstrapVue provides one of the most comprehensive implementations of the Bootstrap v4 component and grid system available for Vue.js v2.6, complete with extens

186 lines (157 loc) 8.18 kB
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } import { extend, mergeData } from '../../vue'; import { NAME_BUTTON } from '../../constants/components'; import { CODE_ENTER, CODE_SPACE } from '../../constants/key-codes'; import { PROP_TYPE_BOOLEAN, PROP_TYPE_STRING } from '../../constants/props'; import { concat } from '../../utils/array'; import { addClass, isTag, removeClass } from '../../utils/dom'; import { stopEvent } from '../../utils/events'; import { isBoolean, isEvent, isFunction } from '../../utils/inspect'; import { omit, sortKeys } from '../../utils/object'; import { makeProp, makePropsConfigurable, pluckProps } from '../../utils/props'; import { isLink as isLinkStrict } from '../../utils/router'; import { BLink, props as BLinkProps } from '../link/link'; // --- Props --- var linkProps = omit(BLinkProps, ['event', 'routerTag']); delete linkProps.href.default; delete linkProps.to.default; export var props = makePropsConfigurable(sortKeys(_objectSpread(_objectSpread({}, linkProps), {}, { block: makeProp(PROP_TYPE_BOOLEAN, false), disabled: makeProp(PROP_TYPE_BOOLEAN, false), pill: makeProp(PROP_TYPE_BOOLEAN, false), // Tri-state: `true`, `false` or `null` // => On, off, not a toggle pressed: makeProp(PROP_TYPE_BOOLEAN, null), size: makeProp(PROP_TYPE_STRING), squared: makeProp(PROP_TYPE_BOOLEAN, false), tag: makeProp(PROP_TYPE_STRING, 'button'), type: makeProp(PROP_TYPE_STRING, 'button'), variant: makeProp(PROP_TYPE_STRING, 'secondary') })), NAME_BUTTON); // --- Helper methods --- // Focus handler for toggle buttons // Needs class of 'focus' when focused var handleFocus = function handleFocus(event) { if (event.type === 'focusin') { addClass(event.target, 'focus'); } else if (event.type === 'focusout') { removeClass(event.target, 'focus'); } }; // Is the requested button a link? // If tag prop is set to `a`, we use a <b-link> to get proper disabled handling var isLink = function isLink(props) { return isLinkStrict(props) || isTag(props.tag, 'a'); }; // Is the button to be a toggle button? var isToggle = function isToggle(props) { return isBoolean(props.pressed); }; // Is the button "really" a button? var isButton = function isButton(props) { return !(isLink(props) || props.tag && !isTag(props.tag, 'button')); }; // Is the requested tag not a button or link? var isNonStandardTag = function isNonStandardTag(props) { return !isLink(props) && !isButton(props); }; // Compute required classes (non static classes) var computeClass = function computeClass(props) { var _ref; return ["btn-".concat(props.variant || 'secondary'), (_ref = {}, _defineProperty(_ref, "btn-".concat(props.size), props.size), _defineProperty(_ref, 'btn-block', props.block), _defineProperty(_ref, 'rounded-pill', props.pill), _defineProperty(_ref, 'rounded-0', props.squared && !props.pill), _defineProperty(_ref, "disabled", props.disabled), _defineProperty(_ref, "active", props.pressed), _ref)]; }; // Compute the link props to pass to b-link (if required) var computeLinkProps = function computeLinkProps(props) { return isLink(props) ? pluckProps(linkProps, props) : {}; }; // Compute the attributes for a button var computeAttrs = function computeAttrs(props, data) { var button = isButton(props); var link = isLink(props); var toggle = isToggle(props); var nonStandardTag = isNonStandardTag(props); var hashLink = link && props.href === '#'; var role = data.attrs && data.attrs.role ? data.attrs.role : null; var tabindex = data.attrs ? data.attrs.tabindex : null; if (nonStandardTag || hashLink) { tabindex = '0'; } return { // Type only used for "real" buttons type: button && !link ? props.type : null, // Disabled only set on "real" buttons disabled: button ? props.disabled : null, // We add a role of button when the tag is not a link or button for ARIA // Don't bork any role provided in `data.attrs` when `isLink` or `isButton` // Except when link has `href` of `#` role: nonStandardTag || hashLink ? 'button' : role, // We set the `aria-disabled` state for non-standard tags 'aria-disabled': nonStandardTag ? String(props.disabled) : null, // For toggles, we need to set the pressed state for ARIA 'aria-pressed': toggle ? String(props.pressed) : null, // `autocomplete="off"` is needed in toggle mode to prevent some browsers // from remembering the previous setting when using the back button autocomplete: toggle ? 'off' : null, // `tabindex` is used when the component is not a button // Links are tabbable, but don't allow disabled, while non buttons or links // are not tabbable, so we mimic that functionality by disabling tabbing // when disabled, and adding a `tabindex="0"` to non buttons or non links tabindex: props.disabled && !button ? '-1' : tabindex }; }; // --- Main component --- // @vue/component export var BButton = /*#__PURE__*/extend({ name: NAME_BUTTON, functional: true, props: props, render: function render(h, _ref2) { var props = _ref2.props, data = _ref2.data, listeners = _ref2.listeners, children = _ref2.children; var toggle = isToggle(props); var link = isLink(props); var nonStandardTag = isNonStandardTag(props); var hashLink = link && props.href === '#'; var on = { keydown: function keydown(event) { // When the link is a `href="#"` or a non-standard tag (has `role="button"`), // we add a keydown handlers for CODE_SPACE/CODE_ENTER /* istanbul ignore next */ if (props.disabled || !(nonStandardTag || hashLink)) { return; } var keyCode = event.keyCode; // Add CODE_SPACE handler for `href="#"` and CODE_ENTER handler for non-standard tags if (keyCode === CODE_SPACE || keyCode === CODE_ENTER && nonStandardTag) { var target = event.currentTarget || event.target; stopEvent(event, { propagation: false }); target.click(); } }, click: function click(event) { /* istanbul ignore if: blink/button disabled should handle this */ if (props.disabled && isEvent(event)) { stopEvent(event); } else if (toggle && listeners && listeners['update:pressed']) { // Send `.sync` updates to any "pressed" prop (if `.sync` listeners) // `concat()` will normalize the value to an array without // double wrapping an array value in an array concat(listeners['update:pressed']).forEach(function (fn) { if (isFunction(fn)) { fn(!props.pressed); } }); } } }; if (toggle) { on.focusin = handleFocus; on.focusout = handleFocus; } var componentData = { staticClass: 'btn', class: computeClass(props), props: computeLinkProps(props), attrs: computeAttrs(props, data), on: on }; return h(link ? BLink : props.tag, mergeData(_objectSpread(_objectSpread({}, data), {}, { props: undefined }), componentData), children); } });