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

478 lines (453 loc) 13.5 kB
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (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 = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { 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 Vue from '../../vue'; import { NAME_FORM_SPINBUTTON, NAME_FORM_TIMEPICKER, NAME_TIME } from '../../constants/components'; import { BVFormBtnLabelControl, dropdownProps } from '../../utils/bv-form-btn-label-control'; import { getComponentConfig } from '../../utils/config'; import { attemptBlur, attemptFocus } from '../../utils/dom'; import { isUndefinedOrNull } from '../../utils/inspect'; import idMixin from '../../mixins/id'; import { BButton } from '../button/button'; import { BTime } from '../time/time'; import { BIconClock, BIconClockFill } from '../../icons/icons'; // Fallback to BTime/BFormSpinbutton prop if no value found var getConfigFallback = function getConfigFallback(prop) { return getComponentConfig(NAME_FORM_TIMEPICKER, prop) || getComponentConfig(NAME_TIME, prop) || getComponentConfig(NAME_FORM_SPINBUTTON, prop); }; // We create our props as a mixin so that we can control // where they appear in the props listing reference section var propsMixin = { props: _objectSpread({ value: { type: String, default: '' }, resetValue: { type: String, default: '' }, placeholder: { type: String // Defaults to `labelNoTime` from BTime context // default: null }, size: { type: String // default: null }, disabled: { type: Boolean, default: false }, readonly: { type: Boolean, default: false }, required: { // If true adds the `aria-required` attribute type: Boolean, default: false }, name: { type: String // default: null }, form: { type: String // default: null }, state: { // Tri-state prop: `true`, `false` or `null` type: Boolean, default: null }, hour12: { // Tri-state prop: `true` => 12 hour, `false` => 24 hour, `null` => auto type: Boolean, default: null }, locale: { type: [String, Array] // default: null }, showSeconds: { type: Boolean, default: false }, hideHeader: { type: Boolean, default: false }, secondsStep: { type: [Number, String], default: 1 }, minutesStep: { type: [Number, String], default: 1 }, buttonOnly: { type: Boolean, default: false }, buttonVariant: { // Applicable in button only mode type: String, default: 'secondary' }, nowButton: { type: Boolean, default: false }, labelNowButton: { type: String, default: function _default() { return getComponentConfig(NAME_FORM_TIMEPICKER, 'labelNowButton'); } }, nowButtonVariant: { type: String, default: 'outline-primary' }, resetButton: { type: Boolean, default: false }, labelResetButton: { type: String, default: function _default() { return getComponentConfig(NAME_FORM_TIMEPICKER, 'labelResetButton'); } }, resetButtonVariant: { type: String, default: 'outline-danger' }, noCloseButton: { type: Boolean, default: false }, labelCloseButton: { type: String, default: function _default() { return getComponentConfig(NAME_FORM_TIMEPICKER, 'labelCloseButton'); } }, closeButtonVariant: { type: String, default: 'outline-secondary' }, // Labels // These fallback to BTime values labelSelected: { type: String, default: function _default() { return getConfigFallback('labelSelected'); } }, labelNoTimeSelected: { type: String, default: function _default() { return getConfigFallback('labelNoTimeSelected'); } }, labelHours: { type: String, default: function _default() { return getConfigFallback('labelHours'); } }, labelMinutes: { type: String, default: function _default() { return getConfigFallback('labelMinutes'); } }, labelSeconds: { type: String, default: function _default() { return getConfigFallback('labelSeconds'); } }, labelAmpm: { type: String, default: function _default() { return getConfigFallback('labelAmpm'); } }, labelAm: { type: String, default: function _default() { return getConfigFallback('labelAm'); } }, labelPm: { type: String, default: function _default() { return getConfigFallback('labelPm'); } }, // These pick BTime or BFormSpinbutton global config if no BFormTimepicker global config labelIncrement: { type: String, default: function _default() { return getConfigFallback('labelIncrement'); } }, labelDecrement: { type: String, default: function _default() { return getConfigFallback('labelDecrement'); } }, // extra dropdown stuff menuClass: { type: [String, Array, Object] // default: null } }, dropdownProps) }; // --- BFormDate component --- // @vue/component export var BFormTimepicker = /*#__PURE__*/Vue.extend({ name: NAME_FORM_TIMEPICKER, // The mixins order determines the order of appearance in the props reference section mixins: [idMixin, propsMixin], model: { prop: 'value', event: 'input' }, data: function data() { return { // We always use `HH:mm:ss` value internally localHMS: this.value || '', // Context data from BTime localLocale: null, isRTL: false, formattedValue: '', // If the menu is opened isVisible: false }; }, computed: { computedLang: function computedLang() { return (this.localLocale || '').replace(/-u-.*$/i, '') || null; }, timeProps: function timeProps() { // Props we pass to BTime // Use self for better minification, as `this` won't // minimize and we reference it many times below var self = this; return { hidden: !self.isVisible, value: self.localHMS, // Passthrough props readonly: self.readonly, disabled: self.disabled, locale: self.locale, hour12: self.hour12, hideHeader: self.hideHeader, showSeconds: self.showSeconds, secondsStep: self.secondsStep, minutesStep: self.minutesStep, labelNoTimeSelected: self.labelNoTimeSelected, labelSelected: self.labelSelected, labelHours: self.labelHours, labelMinutes: self.labelMinutes, labelSeconds: self.labelSeconds, labelAmpm: self.labelAmpm, labelAm: self.labelAm, labelPm: self.labelPm, labelIncrement: self.labelIncrement, labelDecrement: self.labelDecrement }; } }, watch: { value: function value(newVal) { this.localHMS = newVal || ''; }, localHMS: function localHMS(newVal) { // We only update the v-model value when the timepicker // is open, to prevent cursor jumps when bound to a // text input in button only mode if (this.isVisible) { this.$emit('input', newVal || ''); } } }, methods: { // Public methods focus: function focus() { if (!this.disabled) { attemptFocus(this.$refs.control); } }, blur: function blur() { if (!this.disabled) { attemptBlur(this.$refs.control); } }, // Private methods setAndClose: function setAndClose(value) { var _this = this; this.localHMS = value; this.$nextTick(function () { _this.$refs.control.hide(true); }); }, onInput: function onInput(hms) { if (this.localHMS !== hms) { this.localHMS = hms; } }, onContext: function onContext(ctx) { var isRTL = ctx.isRTL, locale = ctx.locale, value = ctx.value, formatted = ctx.formatted; this.isRTL = isRTL; this.localLocale = locale; this.formattedValue = formatted; this.localHMS = value || ''; // Re-emit the context event this.$emit('context', ctx); }, onNowButton: function onNowButton() { var now = new Date(); var hours = now.getHours(); var minutes = now.getMinutes(); var seconds = this.showSeconds ? now.getSeconds() : 0; var value = [hours, minutes, seconds].map(function (v) { return "00".concat(v || '').slice(-2); }).join(':'); this.setAndClose(value); }, onResetButton: function onResetButton() { this.setAndClose(this.resetValue); }, onCloseButton: function onCloseButton() { this.$refs.control.hide(true); }, onShow: function onShow() { this.isVisible = true; }, onShown: function onShown() { var _this2 = this; this.$nextTick(function () { attemptFocus(_this2.$refs.time); _this2.$emit('shown'); }); }, onHidden: function onHidden() { this.isVisible = false; this.$emit('hidden'); }, // Render function helpers defaultButtonFn: function defaultButtonFn(_ref) { var isHovered = _ref.isHovered, hasFocus = _ref.hasFocus; return this.$createElement(isHovered || hasFocus ? BIconClockFill : BIconClock, { attrs: { 'aria-hidden': 'true' } }); } }, render: function render(h) { var localHMS = this.localHMS, disabled = this.disabled, readonly = this.readonly; var placeholder = isUndefinedOrNull(this.placeholder) ? this.labelNoTimeSelected : this.placeholder; // Footer buttons var $footer = []; if (this.nowButton) { var label = this.labelNowButton; $footer.push(h(BButton, { key: 'now-btn', props: { size: 'sm', disabled: disabled || readonly, variant: this.nowButtonVariant }, attrs: { 'aria-label': label || null }, on: { click: this.onNowButton } }, label)); } if (this.resetButton) { if ($footer.length > 0) { // Add a "spacer" between buttons ('&nbsp;') $footer.push(h('span', "\xA0")); } var _label = this.labelResetButton; $footer.push(h(BButton, { key: 'reset-btn', props: { size: 'sm', disabled: disabled || readonly, variant: this.resetButtonVariant }, attrs: { 'aria-label': _label || null }, on: { click: this.onResetButton } }, _label)); } if (!this.noCloseButton) { if ($footer.length > 0) { // Add a "spacer" between buttons ('&nbsp;') $footer.push(h('span', "\xA0")); } var _label2 = this.labelCloseButton; $footer.push(h(BButton, { key: 'close-btn', props: { size: 'sm', disabled: disabled, variant: this.closeButtonVariant }, attrs: { 'aria-label': _label2 || null }, on: { click: this.onCloseButton } }, _label2)); } if ($footer.length > 0) { $footer = [h('div', { staticClass: 'b-form-date-controls d-flex flex-wrap', class: { 'justify-content-between': $footer.length > 1, 'justify-content-end': $footer.length < 2 } }, $footer)]; } var $time = h(BTime, { ref: 'time', staticClass: 'b-form-time-control', props: this.timeProps, on: { input: this.onInput, context: this.onContext } }, $footer); return h(BVFormBtnLabelControl, { ref: 'control', staticClass: 'b-form-timepicker', props: _objectSpread(_objectSpread({}, this.$props), {}, { // Overridden / computed props id: this.safeId(), rtl: this.isRTL, lang: this.computedLang, value: localHMS || '', formattedValue: localHMS ? this.formattedValue : '', placeholder: placeholder || '' }), on: { show: this.onShow, shown: this.onShown, hidden: this.onHidden }, scopedSlots: { 'button-content': this.$scopedSlots['button-content'] || this.defaultButtonFn } }, [$time]); } });