@coreui/vue-pro
Version:
UI Components Library for Vue.js
594 lines (590 loc) • 21.6 kB
JavaScript
var vue = require('vue');
var CButton = require('../button/CButton.js');
var CFormControlWrapper = require('../form/CFormControlWrapper.js');
var CPicker = require('../picker/CPicker.js');
var CTimePickerRollCol = require('./CTimePickerRollCol.js');
var utils = require('./utils.js');
var useDebouncedCallback = require('../../composables/useDebouncedCallback.js');
require('@popperjs/core');
var props = require('../props.js');
const CTimePicker = vue.defineComponent({
name: 'CTimePicker',
props: {
/**
* Set if the component should use the 12/24 hour format. If `true` forces the interface to a 12-hour format. If `false` forces the interface into a 24-hour format. If `auto` the current locale will determine the 12 or 24-hour interface by default locales.
*
* @since 4.7.0
*/
ampm: {
type: [Boolean, String],
default: 'auto',
validator: (value) => {
if (typeof value == 'string') {
return ['auto'].includes(value);
}
if (typeof value == 'boolean') {
return true;
}
return false;
},
},
/**
* Toggle visibility or set the content of cancel button.
*/
cancelButton: {
type: [Boolean, String],
default: 'Cancel',
},
/**
* Sets the color context of the cancel button to one of CoreUI’s themed colors.
*
* @values 'primary', 'secondary', 'success', 'danger', 'warning', 'info', 'dark', 'light'
*/
cancelButtonColor: {
...props.Color,
default: 'primary',
},
/**
* Size the cancel button small or large.
*
* @values 'sm', 'lg'
*/
cancelButtonSize: {
type: String,
default: 'sm',
validator: (value) => {
return ['sm', 'lg'].includes(value);
},
},
/**
* Set the cancel button variant to an outlined button or a ghost button.
*
* @values 'ghost', 'outline'
*/
cancelButtonVariant: {
type: String,
default: 'ghost',
validator: (value) => {
return ['ghost', 'outline'].includes(value);
},
},
/**
* Toggle visibility of the cleaner button.
*/
cleaner: {
type: Boolean,
default: true,
},
/**
* Toggle visibility or set the content of confirm button.
*/
confirmButton: {
type: [Boolean, String],
default: 'OK',
},
/**
* Sets the color context of the confirm button to one of CoreUI’s themed colors.
*
* @values 'primary', 'secondary', 'success', 'danger', 'warning', 'info', 'dark', 'light'
*/
confirmButtonColor: {
...props.Color,
default: 'primary',
},
/**
* Size the confirm button small or large.
*
* @values 'sm', 'lg'
*/
confirmButtonSize: {
type: String,
default: 'sm',
validator: (value) => {
return ['sm', 'lg'].includes(value);
},
},
/**
* Set the confirm button variant to an outlined button or a ghost button.
*
* @values 'ghost', 'outline'
*/
confirmButtonVariant: {
type: String,
validator: (value) => {
return ['ghost', 'outline'].includes(value);
},
},
/**
* Set container type for the component.
*/
container: {
type: String,
default: 'dropdown',
},
/**
* Toggle the disabled state for the component.
*/
disabled: Boolean,
/**
* Provide valuable, actionable feedback.
*
* @since 4.6.0
*/
feedback: String,
/**
* Provide valuable, actionable feedback.
*
* @since 4.6.0
*/
feedbackInvalid: String,
/**
* Provide valuable, actionable invalid feedback when using standard HTML form validation which applied two CSS pseudo-classes, `:invalid` and `:valid`.
*
* @since 4.6.0
*/
feedbackValid: String,
/**
* Specify a list of available hours using an array, or customize the filtering of hours through a function.
*
* @since 5.0.0
*/
hours: {
type: [Array, Function],
},
/**
* The id global attribute defines an identifier (ID) that must be unique in the whole document.
*/
id: String,
/**
* Toggle visibility or set the content of the input indicator.
*/
indicator: {
type: Boolean,
default: true,
},
/**
* Defines the delay (in milliseconds) for the input field's onChange event.
*
* @since 5.0.0
*/
inputOnChangeDelay: {
type: Number,
default: 750,
},
/**
* Toggle the readonly state for the component.
*/
inputReadOnly: Boolean,
/**
* Set component validation state to invalid.
*
* @since 4.6.0
*/
invalid: {
type: Boolean,
default: undefined,
},
/**
* Add a caption for a component.
*
* @since 4.6.0
*/
label: String,
/**
* Sets the default locale for components. If not set, it is inherited from the navigator.language.
*/
locale: {
type: String,
default: 'default',
},
/**
* Toggle the display of minutes, specify a list of available minutes using an array, or customize the filtering of minutes through a function.
*
* @since 5.0.0
*/
minutes: {
type: [Array, Boolean, Function],
default: true,
},
/**
* Set the name attribute for the input element.
*
* @since 5.3.0
*/
name: String,
/**
* Specifies a short hint that is visible in the input.
*/
placeholder: {
type: String,
default: 'Select time',
},
/**
* When present, it specifies that must be filled out before submitting the form.
*
* @since 4.9.0
*/
required: Boolean,
/**
* Toggle the display of seconds, specify a list of available seconds using an array, or customize the filtering of seconds through a function.
*
* @since 4.7.0
*/
seconds: {
type: [Array, Boolean, Function],
default: true,
},
/**
* Size the component small or large.
*
* @values 'sm', 'lg'
*/
size: {
type: String,
default: undefined,
validator: (value) => {
return ['sm', 'lg'].includes(value);
},
},
/**
* Add helper text to the component.
*
* @since 4.6.0
*/
text: String,
/**
* Initial selected time.
*/
time: [Date, String],
/**
* Display validation feedback in a styled tooltip.
*
* @since 4.6.0
*/
tooltipFeedback: Boolean,
/**
* Set component validation state to valid.
*
* @since 4.6.0
*/
valid: {
type: Boolean,
default: undefined,
},
/**
* Set the time picker variant to a roll or select.
*
* @values 'roll', 'select'
*/
variant: {
type: String,
default: 'roll',
validator: (value) => {
return ['roll', 'select'].includes(value);
},
},
/**
* Toggle the visibility of the component.
*/
visible: Boolean,
},
emits: [
/**
* Callback fired when the time changed.
*/
'change',
/**
* Callback fired when the component requests to be hidden.
*/
'hide',
/**
* Callback fired when the component requests to be shown.
*/
'show',
/**
* Callback fired when the time changed.
*
* @since 4.7.0
*/
'update:time',
],
setup(props, { emit, attrs, slots }) {
const formRef = vue.ref();
const inputRef = vue.ref();
const date = vue.ref(utils.convertTimeToDate(props.time));
const ampm = vue.ref(date.value ? utils.getAmPm(new Date(date.value), props.locale) : 'am');
const initialDate = vue.ref(null);
const visible = vue.ref(props.visible);
const localizedTimePartials = vue.ref({
listOfHours: [],
listOfMinutes: [],
listOfSeconds: [],
hour12: false,
});
const isValid = vue.ref(props.valid ?? (props.invalid === true ? false : undefined));
vue.watch(() => props.time, () => {
date.value = utils.convertTimeToDate(props.time);
});
vue.watch(() => [props.valid, props.invalid], () => {
isValid.value = props.valid ?? (props.invalid === true ? false : undefined);
});
vue.watch(date, () => {
localizedTimePartials.value = utils.getLocalizedTimePartials(props.locale, props.ampm, props.hours, props.minutes, props.seconds);
if (date.value) {
ampm.value = utils.getAmPm(new Date(date.value), props.locale);
}
}, { immediate: true });
vue.watch(inputRef, () => {
if (inputRef.value && inputRef.value.form) {
formRef.value = inputRef.value.form;
}
});
vue.watch([formRef, date], () => {
if (formRef.value) {
formRef.value.addEventListener('submit', (event) => {
setTimeout(() => handleFormValidation(event.target));
});
handleFormValidation(formRef.value);
}
});
const handleClear = (event) => {
event.stopPropagation();
date.value = null;
emit('change', null);
emit('update:time', null);
};
const handleFormValidation = (form) => {
if (!form.classList.contains('was-validated')) {
return;
}
if (date.value) {
isValid.value = true;
return;
}
isValid.value = false;
};
const handleTimeChange = (set, value) => {
const _date = date.value || new Date('1970-01-01');
if (set === 'toggle') {
if (value === 'am') {
_date.setHours(_date.getHours() - 12);
}
if (value === 'pm') {
_date.setHours(_date.getHours() + 12);
}
}
if (set === 'hours') {
if (localizedTimePartials.value && localizedTimePartials.value.hour12) {
_date.setHours(utils.convert12hTo24h(ampm.value, Number.parseInt(value)));
}
else {
_date.setHours(Number.parseInt(value));
}
}
if (set === 'minutes') {
_date.setMinutes(Number.parseInt(value));
}
if (set === 'seconds') {
_date.setSeconds(Number.parseInt(value));
}
date.value = new Date(_date);
emit('change', _date.toTimeString(), _date.toLocaleTimeString(props.locale), _date);
emit('update:time', _date.toLocaleTimeString(props.locale));
};
const InputGroup = () => vue.h('div', { class: 'time-picker-input-group' }, [
vue.h('input', {
autocomplete: 'off',
class: 'time-picker-input',
disabled: props.disabled,
id: props.id,
name: props.name,
onInput: (event) => useDebouncedCallback.useDebouncedCallback(() => {
if (utils.isValidTime(event.target.value)) {
date.value = utils.convertTimeToDate(event.target.value);
}
}, props.inputOnChangeDelay),
placeholder: props.placeholder,
readonly: props.inputReadOnly,
ref: inputRef,
required: props.required,
value: date.value
? date.value.toLocaleTimeString(props.locale, {
hour12: localizedTimePartials.value && localizedTimePartials.value.hour12,
hour: 'numeric',
...(props.minutes && { minute: 'numeric' }),
...(props.seconds && { second: 'numeric' }),
})
: '',
}),
props.indicator && vue.h('div', { class: 'time-picker-indicator' }),
props.cleaner &&
date.value &&
vue.h('div', {
class: 'time-picker-cleaner',
onClick: (event) => handleClear(event),
}),
]);
const TimePickerSelect = () => [
vue.h('span', { class: 'time-picker-inline-icon' }),
vue.h('select', {
class: 'time-picker-inline-select',
disabled: props.disabled,
onChange: (event) => handleTimeChange('hours', event.target.value),
...(date.value && { value: utils.getSelectedHour(date.value, props.locale) }),
}, localizedTimePartials.value &&
localizedTimePartials.value.listOfHours.map((option) => vue.h('option', {
value: option.value.toString(),
}, option.label))),
props.minutes && ':',
props.minutes &&
vue.h('select', {
class: 'time-picker-inline-select',
disabled: props.disabled,
onChange: (event) => handleTimeChange('minutes', event.target.value),
...(date.value && { value: utils.getSelectedMinutes(date.value) }),
}, localizedTimePartials.value &&
localizedTimePartials.value.listOfMinutes?.map((option) => vue.h('option', {
value: option.value.toString(),
}, option.label))),
props.seconds && ':',
props.seconds &&
vue.h('select', {
class: 'time-picker-inline-select',
disabled: props.disabled,
onChange: (event) => handleTimeChange('seconds', event.target.value),
...(date.value && { value: utils.getSelectedSeconds(date.value) }),
}, localizedTimePartials.value &&
localizedTimePartials.value.listOfSeconds?.map((option) => vue.h('option', {
value: option.value.toString(),
}, option.label))),
localizedTimePartials.value &&
localizedTimePartials.value.hour12 &&
vue.h('select', {
class: 'time-picker-inline-select',
disabled: props.disabled,
onChange: (event) => handleTimeChange('toggle', event.target.value),
value: ampm.value,
}, [
vue.h('option', {
value: 'am',
}, 'AM'),
vue.h('option', {
value: 'pm',
}, 'PM'),
]),
];
const TimePickerRoll = () => [
vue.h(CTimePickerRollCol.CTimePickerRollCol, {
elements: localizedTimePartials.value && localizedTimePartials.value.listOfHours,
onClick: (index) => handleTimeChange('hours', index.toString()),
selected: utils.getSelectedHour(date.value, props.locale, props.ampm),
}),
props.minutes &&
vue.h(CTimePickerRollCol.CTimePickerRollCol, {
elements: localizedTimePartials.value && localizedTimePartials.value.listOfMinutes,
onClick: (index) => handleTimeChange('minutes', index.toString()),
selected: utils.getSelectedMinutes(date.value),
}),
props.seconds &&
vue.h(CTimePickerRollCol.CTimePickerRollCol, {
elements: localizedTimePartials.value && localizedTimePartials.value.listOfSeconds,
onClick: (index) => handleTimeChange('seconds', index.toString()),
selected: utils.getSelectedSeconds(date.value),
}),
localizedTimePartials.value &&
localizedTimePartials.value.hour12 &&
vue.h(CTimePickerRollCol.CTimePickerRollCol, {
elements: [
{ value: 'am', label: 'AM' },
{ value: 'pm', label: 'PM' },
],
onClick: (value) => handleTimeChange('toggle', value),
selected: ampm.value,
}),
];
return () => vue.h(CFormControlWrapper.CFormControlWrapper, {
...(typeof attrs['aria-describedby'] === 'string' && {
describedby: attrs['aria-describedby'],
}),
feedback: props.feedback,
feedbackInvalid: props.feedbackInvalid,
feedbackValid: props.feedbackValid,
id: props.id,
invalid: isValid.value === false ? true : false,
label: props.label,
text: props.text,
tooltipFeedback: props.tooltipFeedback,
valid: isValid.value,
}, {
default: () => vue.h(CPicker.CPicker, {
class: [
'time-picker',
{
[`time-picker-${props.size}`]: props.size,
disabled: props.disabled,
'is-invalid': isValid.value === false ? true : false,
'is-valid': isValid.value,
},
],
container: props.container,
disabled: props.disabled,
dropdownClassNames: 'time-picker-dropdown',
footer: true,
onHide: () => {
visible.value = false;
emit('hide');
},
onShow: () => {
if (date.value) {
initialDate.value = new Date(date.value);
}
visible.value = true;
emit('show');
},
visible: visible.value,
}, {
...(slots.cancelButton && {
cancelButton: () => slots.cancelButton && slots.cancelButton(),
}),
...(slots.confirmButton && {
confirmButton: () => slots.confirmButton && slots.confirmButton(),
}),
toggler: () => InputGroup(),
default: () => vue.h('div', {
class: [
'time-picker-body',
{
['time-picker-roll']: props.variant === 'roll',
},
],
}, props.variant === 'select' ? TimePickerSelect() : TimePickerRoll()),
footer: () => vue.h('div', { class: 'time-picker-footer' }, [
props.cancelButton &&
vue.h(CButton.CButton, {
color: props.cancelButtonColor,
onClick: () => {
if (initialDate.value) {
date.value = new Date(initialDate.value);
}
visible.value = false;
},
size: props.cancelButtonSize,
variant: props.cancelButtonVariant,
}, () => props.cancelButton),
props.confirmButton &&
vue.h(CButton.CButton, {
color: props.confirmButtonColor,
onClick: () => {
visible.value = false;
},
size: props.confirmButtonSize,
variant: props.confirmButtonVariant,
}, () => props.confirmButton),
]),
}),
});
},
});
exports.CTimePicker = CTimePicker;
//# sourceMappingURL=CTimePicker.js.map
;