UNPKG

@coreui/vue-pro

Version:

UI Components Library for Vue.js

594 lines (590 loc) 21.6 kB
'use strict'; 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