UNPKG

zmp-vue

Version:

Build full featured iOS & Android apps using ZMP & Vue

459 lines (406 loc) 15.3 kB
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } import { computed, ref, onMounted, onBeforeUnmount, h, watch, onUpdated } from 'vue'; import { classNames, extend, noUndefinedProps } from '../shared/utils'; import { colorClasses, colorProps } from '../shared/mixins'; import { zmpready, zmp } from '../shared/zmp'; import zmpToggle from './toggle'; import zmpRange from './range'; import zmpTextEditor from './text-editor'; export default { name: 'zmp-input', props: _extends({ type: String, name: String, value: { type: [String, Number, Array, Date, Object], default: undefined }, inputmode: String, placeholder: String, inputId: [String, Number], size: [String, Number], accept: [String, Number], autocomplete: [String], autocorrect: [String], autocapitalize: [String], spellcheck: [String], autofocus: Boolean, autosave: String, checked: Boolean, disabled: Boolean, max: [String, Number], min: [String, Number], step: [String, Number], maxlength: [String, Number], minlength: [String, Number], multiple: Boolean, readonly: Boolean, required: Boolean, inputStyle: [String, Object], pattern: String, validate: [Boolean, String], validateOnBlur: Boolean, onValidate: Function, tabindex: [String, Number], resizable: Boolean, clearButton: Boolean, // Form noFormStoreData: Boolean, noStoreData: Boolean, ignoreStoreData: Boolean, // Error, Info errorMessage: String, errorMessageForce: Boolean, info: String, // Outline outline: Boolean, // Components wrap: { type: Boolean, default: true }, dropdown: { type: [String, Boolean], default: 'auto' }, // Datepicker calendarParams: Object, // Colorpciker colorPickerParams: Object, // Text editor textEditorParams: Object }, colorProps), emits: ['input', 'focus', 'blur', 'change', 'textarea:resize', 'input:notempty', 'input:empty', 'input:clear', 'texteditor:change', 'calendar:change', 'colorpicker:change', 'update:value'], setup: function setup(props, _ref) { var emit = _ref.emit, slots = _ref.slots; var zmpCalendar = null; var zmpColorPicker = null; var inputInvalid = ref(false); var inputFocused = ref(false); var elRef = ref(null); var inputElRef = ref(null); var updateInputOnDidUpdate = false; var getDomValue = function getDomValue() { if (!inputElRef.value) return undefined; return inputElRef.value.value; }; var domValue = ref(getDomValue()); var inputHasValue = computed(function () { if (props.type === 'datepicker' && Array.isArray(props.value) && props.value.length === 0) { return false; } return typeof props.value === 'undefined' ? domValue.value || domValue.value === 0 : props.value || props.value === 0; }); var validateInput = function validateInput() { if (!zmp || !inputElRef.value) return; var validity = inputElRef.value.validity; if (!validity) return; if (!validity.valid) { if (props.onValidate) props.onValidate(false); if (inputInvalid.value !== true) { inputInvalid.value = true; } } else { if (props.onValidate) props.onValidate(true); if (inputInvalid.value !== false) { inputInvalid.value = false; } } }; var onTextareaResize = function onTextareaResize(event) { emit('textarea:resize', event); }; var onInputNotEmpty = function onInputNotEmpty(event) { emit('input:notempty', event); }; var onInputEmpty = function onInputEmpty(event) { emit('input:empty', event); }; var onInputClear = function onInputClear(event) { emit('input:clear', event); }; var onInput = function onInput() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } emit.apply(void 0, ['input'].concat(args)); if (inputElRef.value) { domValue.value = inputElRef.value.value; } if (!(props.validateOnBlur || props.validateOnBlur === '') && (props.validate || props.validate === '') && inputElRef.value) { validateInput(); } if (inputElRef.value && props.type !== 'texteditor' && props.type !== 'colorpicker' && props.type !== 'datepicker') { emit('update:value', inputElRef.value.value); } }; var onFocus = function onFocus() { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } emit.apply(void 0, ['focus'].concat(args)); inputFocused.value = true; }; var onBlur = function onBlur() { for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } emit.apply(void 0, ['blur'].concat(args)); if ((props.validate || props.validate === '' || props.validateOnBlur || props.validateOnBlur === '') && inputElRef.value) { validateInput(); } inputFocused.value = false; }; var onChange = function onChange() { for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } emit.apply(void 0, ['change'].concat(args)); if (props.type === 'texteditor') { emit('texteditor:change', args[1]); emit('update:value', args[1]); } }; onMounted(function () { var type = props.type, resizable = props.resizable, clearButton = props.clearButton, value = props.value, calendarParams = props.calendarParams, colorPickerParams = props.colorPickerParams, validate = props.validate, validateOnBlur = props.validateOnBlur; zmpready(function () { if (type === 'range' || type === 'toggle') return; if (!inputElRef.value) return; inputElRef.value.addEventListener('input:notempty', onInputNotEmpty, false); if (type === 'textarea' && resizable) { inputElRef.value.addEventListener('textarea:resize', onTextareaResize, false); } if (clearButton) { inputElRef.value.addEventListener('input:empty', onInputEmpty, false); inputElRef.value.addEventListener('input:clear', onInputClear, false); } if (type === 'datepicker') { zmpCalendar = zmp.calendar.create(_extends({ inputEl: inputElRef.value, value: value, on: { change: function change(calendar, calendarValue) { emit('calendar:change', calendarValue); emit('update:value', calendarValue); } } }, calendarParams || {})); } if (type === 'colorpicker') { zmpColorPicker = zmp.colorPicker.create(_extends({ inputEl: inputElRef.value, value: value, on: { change: function change(colorPicker, colorPickerValue) { emit('colorpicker:change', colorPickerValue); emit('update:value', colorPickerValue); } } }, colorPickerParams || {})); } zmp.input.checkEmptyState(inputElRef.value); if (!(validateOnBlur || validateOnBlur === '') && (validate || validate === '') && typeof value !== 'undefined' && value !== null && value !== '') { setTimeout(function () { validateInput(); }, 0); } if (resizable) { zmp.input.resizeTextarea(inputElRef.value); } }); }); onBeforeUnmount(function () { if (props.type === 'range' || props.type === 'toggle') return; if (!inputElRef.value) return; inputElRef.value.removeEventListener('input:notempty', onInputNotEmpty, false); if (props.type === 'textarea' && props.resizable) { inputElRef.value.removeEventListener('textarea:resize', onTextareaResize, false); } if (props.clearButton) { inputElRef.value.removeEventListener('input:empty', onInputEmpty, false); inputElRef.value.removeEventListener('input:clear', onInputClear, false); } if (zmpCalendar && zmpCalendar.destroy) { zmpCalendar.destroy(); zmpCalendar = null; } if (zmpColorPicker && zmpColorPicker.destroy) { zmpColorPicker.destroy(); zmpColorPicker = null; } }); onUpdated(function () { if (!zmp) return; if (updateInputOnDidUpdate) { if (!inputElRef.value) return; updateInputOnDidUpdate = false; zmp.input.checkEmptyState(inputElRef.value); if (props.validate && !props.validateOnBlur) { validateInput(); } if (props.resizable) { zmp.input.resizeTextarea(inputElRef.value); } } }); watch(function () { return props.colorPickerParams; }, function (newValue) { if (!zmp || !zmpColorPicker) return; extend(zmpColorPicker.params, newValue || {}); }); watch(function () { return props.calendarParams; }, function (newValue) { if (!zmp || !zmpCalendar) return; extend(zmpCalendar.params, newValue || {}); }); watch(function () { return props.value; }, function (newValue) { if (props.type === 'range' || props.type === 'toggle' || !zmp) return; updateInputOnDidUpdate = true; if (zmpCalendar) { zmpCalendar.setValue(newValue); } if (zmpColorPicker) { zmpColorPicker.setValue(newValue); } }); var createInput = function createInput(InputTag, children) { var needsValue = props.type !== 'file' && props.type !== 'datepicker' && props.type !== 'colorpicker'; var needsType = InputTag === 'input'; var inputType = props.type; if (inputType === 'datepicker' || inputType === 'colorpicker') { inputType = 'text'; } var inputClassName = classNames({ resizable: inputType === 'textarea' && props.resizable, 'no-store-data': props.noFormStoreData || props.noStoreData || props.ignoreStoreData, 'input-invalid': props.errorMessage && props.errorMessageForce || inputInvalid.value, 'input-with-value': inputHasValue.value, 'input-focused': inputFocused.value }); var inputValue; if (needsValue) { if (typeof props.value !== 'undefined') inputValue = props.value;else inputValue = domValue.value; } var valueProps = {}; if (props.type !== 'datepicker' && props.type !== 'colorpicker') { if ('value' in props) valueProps.value = inputValue; } var inputProps = noUndefinedProps({ name: props.name, type: needsType ? inputType : undefined, placeholder: props.placeholder, inputmode: props.inputmode, id: props.inputId, size: props.size, accept: props.accept, autocomplete: props.autocomplete, autoCorrect: props.autocorrect, autocapitalize: props.autocapitalize, spellcheck: props.spellcheck, autofocus: props.autofocus, autoSave: props.autosave, checked: props.checked, disabled: props.disabled, max: props.max, maxlength: props.maxlength, min: props.min, minlength: props.minlength, step: props.step, multiple: props.multiple, readonly: props.readonly, required: props.required, pattern: props.pattern, validate: typeof props.validate === 'string' && props.validate.length ? props.validate : undefined, tabindex: props.tabindex }); return h(InputTag, _extends({ ref: inputElRef, style: props.inputStyle }, inputProps, { 'data-validate': props.validate === true || props.validate === '' || props.validateOnBlur === true || props.validateOnBlur === '' ? true : undefined, 'data-validate-on-blur': props.validateOnBlur === true || props.validateOnBlur === '' ? true : undefined, 'data-error-message': props.errorMessageForce ? undefined : props.errorMessage, class: inputClassName, onFocus: onFocus, onBlur: onBlur, onInput: onInput, onChange: onChange }, valueProps), [children]); }; return function () { var inputEl; if (props.type === 'select' || props.type === 'textarea' || props.type === 'file') { if (props.type === 'select') { inputEl = createInput('select', slots.default && slots.default()); } else if (props.type === 'file') { inputEl = createInput('input'); } else { inputEl = createInput('textarea'); } } else if (slots.default || !props.type) { inputEl = slots.default(); } else if (props.type === 'toggle') { inputEl = h(zmpToggle, { checked: props.checked, readonly: props.readonly, name: props.name, value: props.value, disabled: props.disabled, id: props.inputId, onChange: onChange }); } else if (props.type === 'range') { inputEl = h(zmpRange, { value: props.value, disabled: props.disabled, min: props.min, max: props.max, step: props.step, name: props.name, id: props.inputId, input: true, onRangeChange: onChange }); } else if (props.type === 'texteditor') { inputEl = h(zmpTextEditor, _extends({ value: props.value, resizable: props.resizable, placeholder: props.placeholder, onTextEditorFocus: onFocus, onTextEditorBlur: onBlur, onTextEditorInput: onInput, onTextEditorChange: onChange }, props.textEditorParams || {})); } else { inputEl = createInput('input'); } if (!props.wrap) return inputEl; var wrapClasses = classNames('input', { 'input-outline': props.outline, 'input-dropdown': props.dropdown === 'auto' ? props.type === 'select' : props.dropdown }, colorClasses(props)); return h('div', { class: wrapClasses, ref: elRef }, [inputEl, (props.errorMessage || slots['error-message']) && props.errorMessageForce && h('div', { class: 'input-error-message' }, [props.errorMessage, slots['error-message'] && slots['error-message']()]), props.clearButton && h('span', { class: 'input-clear-button' }), (props.info || slots.info) && h('div', { class: 'input-info' }, [props.info, slots.info && slots.info()])]); }; } };