bootstrap-vue
Version:
BootstrapVue, with more than 85 custom components, over 45 plugins, several custom directives, and over 300 icons, provides one of the most comprehensive implementations of Bootstrap v4 components and grid system for Vue.js. With extensive and automated W
483 lines (458 loc) • 13.4 kB
JavaScript
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 '../../utils/vue';
import { BVFormBtnLabelControl, dropdownProps } from '../../utils/bv-form-btn-label-control';
import { getComponentConfig } from '../../utils/config';
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';
var NAME = 'BFormTimepicker'; // Fallback to BTime/BFormSpinbutton prop if no value found
var getConfigFallback = function getConfigFallback(prop) {
return getComponentConfig(NAME, prop) || getComponentConfig('BTime', prop) || getComponentConfig('BFormSpinbutton', 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, 'labelNowButton');
}
},
nowButtonVariant: {
type: String,
default: 'outline-primary'
},
resetButton: {
type: Boolean,
default: false
},
labelResetButton: {
type: String,
default: function _default() {
return getComponentConfig(NAME, 'labelResetButton');
}
},
resetButtonVariant: {
type: String,
default: 'outline-danger'
},
noCloseButton: {
type: Boolean,
default: false
},
labelCloseButton: {
type: String,
default: function _default() {
return getComponentConfig(NAME, '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,
// 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) {
try {
this.$refs.control.focus();
} catch (_unused) {}
}
},
blur: function blur() {
if (!this.disabled) {
try {
this.$refs.control.blur();
} catch (_unused2) {}
}
},
// 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 () {
try {
_this2.$refs.time.focus();
} catch (_unused3) {}
_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 (' ')
$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 (' ')
$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]);
}
});