zmp-vue
Version:
Build full featured iOS & Android apps using ZMP & Vue
480 lines (424 loc) • 16.9 kB
JavaScript
;
exports.__esModule = true;
exports.default = void 0;
var _vue = require("vue");
var _utils = require("../shared/utils");
var _mixins = require("../shared/mixins");
var _zmp = require("../shared/zmp");
var _textEditor = _interopRequireDefault(require("./text-editor"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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); }
var _default = {
name: 'zmp-list-input',
props: _extends({
sortable: {
type: Boolean,
default: undefined
},
media: String,
dropdown: {
type: [String, Boolean],
default: 'auto'
},
wrap: {
type: Boolean,
default: true
},
// Inputs
input: {
type: Boolean,
default: true
},
type: {
type: String,
default: 'text'
},
name: String,
value: {
type: [String, Number, Array, Date, Object],
default: undefined
},
inputmode: String,
readonly: Boolean,
required: Boolean,
disabled: Boolean,
placeholder: String,
inputId: [String, Number],
size: [String, Number],
accept: [String, Number],
autocomplete: [String],
autocorrect: [String],
autocapitalize: [String],
spellcheck: [String],
autofocus: Boolean,
autosave: String,
max: [String, Number],
min: [String, Number],
step: [String, Number],
maxlength: [String, Number],
minlength: [String, Number],
multiple: 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,
// Label
label: [String, Number],
inlineLabel: Boolean,
floatingLabel: Boolean,
// Datepicker
calendarParams: Object,
// Colorpicker
colorPickerParams: Object,
// Text editor
textEditorParams: Object
}, _mixins.colorProps),
emits: ['textarea:resize', 'input:notempty', 'input:empty', 'input:clear', 'texteditor:change', 'calendar:change', 'colorpicker:change', 'change', 'focus', 'blur', 'input', 'update:value'],
setup: function setup(props, _ref) {
var emit = _ref.emit,
slots = _ref.slots;
var inputInvalid = (0, _vue.ref)(false);
var inputFocused = (0, _vue.ref)(false);
var ListContext = (0, _vue.inject)('ListContext', {
value: {
listIsMedia: false,
listIsSortable: false,
listIsSortableOpposite: false,
listIsSimple: false
}
});
var zmpCalendar = null;
var zmpColorPicker = null;
var elRef = (0, _vue.ref)(null);
var inputElRef = (0, _vue.ref)(null);
var itemContentElRef = (0, _vue.ref)(null);
var updateInputOnDidUpdate = false;
var getDomValue = function getDomValue() {
if (!inputElRef.value) return undefined;
return inputElRef.value.value;
};
var domValue = (0, _vue.ref)(getDomValue());
var inputHasValue = (0, _vue.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.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(inputElRef.value);
}
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(inputElRef.value);
}
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[0]);
emit('update:value', args[0]);
}
};
(0, _vue.onMounted)(function () {
if (!elRef.value && !itemContentElRef.value) return;
(0, _zmp.zmpready)(function () {
if (!inputElRef.value) return;
inputElRef.value.addEventListener('input:notempty', onInputNotEmpty, false);
inputElRef.value.addEventListener('textarea:resize', onTextareaResize, false);
inputElRef.value.addEventListener('input:empty', onInputEmpty, false);
inputElRef.value.addEventListener('input:clear', onInputClear, false);
if (props.type === 'datepicker') {
zmpCalendar = _zmp.zmp.calendar.create(_extends({
inputEl: inputElRef.value,
value: props.value,
on: {
change: function change(calendar, calendarValue) {
emit('update:value', calendarValue);
emit('calendar:change', calendarValue);
}
}
}, props.calendarParams || {}));
}
if (props.type === 'colorpicker') {
zmpColorPicker = _zmp.zmp.colorPicker.create(_extends({
inputEl: inputElRef.value,
value: props.value,
on: {
change: function change(colorPicker, colorPickerValue) {
emit('update:value', colorPickerValue);
emit('colorpicker:change', colorPickerValue);
}
}
}, props.colorPickerParams || {}));
}
if (!(props.validateOnBlur || props.validateOnBlur === '') && (props.validate || props.validate === '') && typeof props.value !== 'undefined' && props.value !== null && props.value !== '') {
setTimeout(function () {
validateInput();
}, 0);
}
if (props.type === 'textarea' && props.resizable) {
_zmp.zmp.input.resizeTextarea(inputElRef.value);
}
});
});
(0, _vue.onBeforeUnmount)(function () {
if (inputElRef.value) {
inputElRef.value.removeEventListener('input:notempty', onInputNotEmpty, false);
inputElRef.value.removeEventListener('textarea:resize', onTextareaResize, false);
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;
}
});
(0, _vue.onUpdated)(function () {
if (!_zmp.zmp) return;
if (updateInputOnDidUpdate) {
if (!inputElRef.value) return;
updateInputOnDidUpdate = false;
if (props.validate && !props.validateOnBlur) {
validateInput();
}
if (props.type === 'textarea' && props.resizable) {
_zmp.zmp.input.resizeTextarea(inputElRef.value);
}
}
});
(0, _vue.watch)(function () {
return props.colorPickerParams;
}, function (newValue) {
if (!_zmp.zmp || !zmpColorPicker) return;
(0, _utils.extend)(zmpColorPicker.params, newValue || {});
});
(0, _vue.watch)(function () {
return props.calendarParams;
}, function (newValue) {
if (!_zmp.zmp || !zmpCalendar) return;
(0, _utils.extend)(zmpCalendar.params, newValue || {});
});
(0, _vue.watch)(function () {
return props.value;
}, function (newValue) {
if (!_zmp.zmp) return;
updateInputOnDidUpdate = true;
if (zmpCalendar) {
zmpCalendar.setValue(newValue);
}
if (zmpColorPicker) {
zmpColorPicker.setValue(newValue);
}
});
var isSortableComputed = (0, _vue.computed)(function () {
return props.sortable || ListContext.value.listIsSortable || false;
});
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 = (0, _utils.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 = (0, _utils.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,
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 (0, _vue.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.input) {
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 (props.type === 'texteditor') {
inputEl = (0, _vue.h)(_textEditor.default, _extends({
value: props.value,
resizable: props.resizable,
placeholder: props.placeholder,
onTextEditorFocus: onFocus,
onTextEditorBlur: onBlur,
onTextEditorInput: onInput,
onTextEditorChange: onChange
}, props.textEditorParams || {}));
} else {
inputEl = createInput('input');
}
}
var hasErrorMessage = !!props.errorMessage || slots['error-message'];
var ItemContent = (0, _vue.h)('div', {
ref: itemContentElRef,
class: (0, _utils.classNames)('item-content item-input', !props.wrap && {
disabled: props.disabled
}, !props.wrap && (0, _mixins.colorClasses)(props), {
'inline-label': props.inlineLabel,
'item-input-outline': props.outline,
'item-input-focused': inputFocused.value,
'item-input-with-info': !!props.info || slots.info,
'item-input-with-value': inputHasValue.value,
'item-input-with-error-message': hasErrorMessage && props.errorMessageForce || inputInvalid.value,
'item-input-invalid': hasErrorMessage && props.errorMessageForce || inputInvalid.value
})
}, [slots['content-start'] && slots['content-start'](), (props.media || slots.media) && (0, _vue.h)('div', {
class: 'item-media'
}, [props.media && (0, _vue.h)('img', {
src: props.media
}), slots.media && slots.media()]), (0, _vue.h)('div', {
class: 'item-inner'
}, [slots['inner-start'] && slots['inner-start'](), (props.label || slots.label) && (0, _vue.h)('div', {
class: (0, _utils.classNames)('item-title item-label', {
'item-floating-label': props.floatingLabel
})
}, [props.label, slots.label && slots.label()]), (0, _vue.h)('div', {
class: (0, _utils.classNames)('item-input-wrap', {
'input-dropdown': props.dropdown === 'auto' ? props.type === 'select' : props.dropdown
})
}, [inputEl, slots.input && slots.input(), hasErrorMessage && props.errorMessageForce && (0, _vue.h)('div', {
class: 'item-input-error-message'
}, [props.errorMessage, slots['error-message'] && slots['error-message']()]), props.clearButton && (0, _vue.h)('span', {
class: 'input-clear-button'
}), (props.info || slots.info) && (0, _vue.h)('div', {
class: 'item-input-info'
}, [props.info, slots.info && slots.info()])]), slots.inner && slots.inner(), slots['inner-end'] && slots['inner-end']()]), slots.content && slots.content(), slots['content-end'] && slots['content-end']()]);
if (!props.wrap) return ItemContent;
return (0, _vue.h)('li', {
ref: elRef,
class: (0, _utils.classNames)({
disabled: props.disabled
}, (0, _mixins.colorClasses)(props))
}, [slots['root-start'] && slots['root-start'](), ItemContent, isSortableComputed.value && (0, _vue.h)('div', {
class: 'sortable-handler'
}), slots.root && slots.root(), slots['root-end'] && slots['root-end']()]);
};
}
};
exports.default = _default;