UNPKG

@ishitatsuyuki/oruga-next

Version:

UI components for Vue.js and CSS framework agnostic

337 lines (331 loc) 11.8 kB
import { defineComponent, resolveComponent, openBlock, createBlock, mergeProps, createVNode, createCommentVNode, toDisplayString } from 'vue'; import { getValueByPath } from './helpers.mjs'; import { getOptions } from './config.mjs'; import { B as BaseComponentMixin } from './BaseComponentMixin-d78ed3dc.mjs'; import { s as script$1 } from './Icon-2e1c404c.mjs'; import { F as FormElementMixin } from './FormElementMixin-386fdfd0.mjs'; /** * Get user Input. Use with Field to access all functionalities * @displayName Input * @style _input.scss */ var script = defineComponent({ name: 'OInput', components: { [script$1.name]: script$1 }, mixins: [BaseComponentMixin, FormElementMixin], configField: 'input', inheritAttrs: false, emits: ['update:modelValue', 'icon-click', 'icon-right-click'], props: { /** @model */ modelValue: [Number, String], /** Native options to use in HTML5 validation */ autocomplete: String, /** * Input type, like native * @values Any native input type, and textarea */ type: { type: String, default: 'text' }, /** * Vertical size of input, optional * @values small, medium, large */ size: String, /** * Color of the control, optional * @values primary, info, success, warning, danger, and any other custom color */ variant: String, /** * Adds the reveal password functionality */ passwordReveal: Boolean, /** * Makes the icon clickable */ iconClickable: Boolean, /** * Show character counter when maxlength prop is passed */ hasCounter: { type: Boolean, default: () => { return getValueByPath(getOptions(), 'input.counter', false); } }, /** * Automatically adjust height in textarea */ autosize: { type: Boolean, default: false }, /** * Icon name to be added on the right side */ iconRight: String, /** * Make the icon right clickable */ iconRightClickable: Boolean, /** Variant of right icon */ iconRightVariant: String, /** Add a button/icon to clear the inputed text */ clearable: { type: Boolean, default: () => { return getValueByPath(getOptions(), 'input.clearable', false); } }, rootClass: [String, Function, Array], expandedClass: [String, Function, Array], iconLeftSpaceClass: [String, Function, Array], iconRightSpaceClass: [String, Function, Array], inputClass: [String, Function, Array], roundedClass: [String, Function, Array], iconLeftClass: [String, Function, Array], iconRightClass: [String, Function, Array], counterClass: [String, Function, Array], sizeClass: [String, Function, Array], variantClass: [String, Function, Array] }, data() { return { newValue: this.modelValue, newType: this.type, // from mixin (ts workaround) newAutocomplete: this.autocomplete || getValueByPath(getOptions(), 'input.autocompletete', 'off'), isPasswordVisible: false, height: 'auto' }; }, computed: { rootClasses() { return [ this.computedClass('rootClass', 'o-ctrl-input'), { [this.computedClass('expandedClass', 'o-ctrl-input--expanded')]: this.expanded } ]; }, inputClasses() { return [ this.computedClass('inputClass', 'o-input'), { [this.computedClass('roundedClass', 'o-input--rounded')]: this.rounded }, { [this.computedClass('sizeClass', 'o-input--', this.size)]: this.size }, { [this.computedClass('variantClass', 'o-input--', (this.statusVariant || this.variant))]: (this.statusVariant || this.variant) }, { [this.computedClass('textareaClass', 'o-input__textarea')]: this.type === 'textarea' }, { [this.computedClass('iconLeftSpaceClass', 'o-input-iconspace-left')]: this.icon }, { [this.computedClass('iconRightSpaceClass', 'o-input-iconspace-right')]: this.hasIconRight } ]; }, iconLeftClasses() { return [ this.computedClass('iconLeftClass', 'o-input__icon-left') ]; }, iconRightClasses() { return [ this.computedClass('iconRightClass', 'o-input__icon-right') ]; }, counterClasses() { return [ this.computedClass('counterClass', 'o-input__counter') ]; }, computedValue: { get() { return this.newValue; }, set(value) { this.newValue = value; this.$emit('update:modelValue', this.newValue); this.syncFilled(this.newValue); !this.isValid && this.checkHtml5Validity(); } }, hasIconRight() { return this.passwordReveal || (this.statusIcon && this.statusVariantIcon) || (this.clearable && this.newValue) || this.iconRight; }, rightIcon() { if (this.passwordReveal) { return this.passwordVisibleIcon; } else if (this.clearable && this.newValue) { return 'close-circle'; } else if (this.iconRight) { return this.iconRight; } return this.statusVariantIcon; }, rightIconVariant() { if (this.passwordReveal || this.iconRight) { return this.iconRightVariant || this.variant || null; } return this.statusVariant; }, /** * Check if have any message prop from parent if it's a Field. */ hasMessage() { return !!this.statusMessage; }, /** * Current password-reveal icon name. */ passwordVisibleIcon() { return !this.isPasswordVisible ? 'eye' : 'eye-off'; }, /** * Get value length */ valueLength() { if (typeof this.computedValue === 'string') { return this.computedValue.length; } else if (typeof this.computedValue === 'number') { return this.computedValue.toString().length; } return 0; }, /** * Computed inline styles for autoresize */ computedStyles() { if (!this.autosize) return {}; return { resize: 'none', height: this.height, overflow: 'hidden' }; }, $elementRef() { return this.type === 'textarea' ? 'textarea' : 'input'; } }, watch: { /** * When v-model is changed: * 1. Set internal value. */ modelValue: { immediate: true, handler(value) { this.newValue = value; this.syncFilled(this.newValue); if (this.autosize) { this.resize(); } } } }, methods: { /** * Toggle the visibility of a password-reveal input * by changing the type and focus the input right away. */ togglePasswordVisibility() { this.isPasswordVisible = !this.isPasswordVisible; this.newType = this.isPasswordVisible ? 'text' : 'password'; this.$nextTick(() => { this.focus(); }); }, iconClick(emit, event) { this.$emit(emit, event); this.$nextTick(() => { this.focus(); }); }, rightIconClick(event) { if (this.passwordReveal) { this.togglePasswordVisibility(); } else if (this.clearable) { this.computedValue = ''; } else if (this.iconRightClickable) { this.iconClick('icon-right-click', event); } }, resize() { this.height = 'auto'; this.$nextTick(() => { let scrollHeight = this.$refs.textarea.scrollHeight; this.height = scrollHeight + 'px'; }); } } }); function render(_ctx, _cache, $props, $setup, $data, $options) { const _component_o_icon = resolveComponent("o-icon"); return openBlock(), createBlock("div", { class: _ctx.rootClasses }, [_ctx.type !== 'textarea' ? (openBlock(), createBlock("input", mergeProps({ key: 0 }, _ctx.$attrs, { ref: "input", class: _ctx.inputClasses, type: _ctx.newType, autocomplete: _ctx.newAutocomplete, maxlength: _ctx.maxlength, value: _ctx.computedValue, onInput: _cache[1] || (_cache[1] = $event => _ctx.computedValue = $event.target.value), onBlur: _cache[2] || (_cache[2] = (...args) => _ctx.onBlur(...args)), onFocus: _cache[3] || (_cache[3] = (...args) => _ctx.onFocus(...args)) }), null, 16 /* FULL_PROPS */ , ["type", "autocomplete", "maxlength", "value"])) : (openBlock(), createBlock("textarea", mergeProps({ key: 1 }, _ctx.$attrs, { ref: "textarea", class: _ctx.inputClasses, maxlength: _ctx.maxlength, value: _ctx.computedValue, onInput: _cache[4] || (_cache[4] = $event => _ctx.computedValue = $event.target.value), onBlur: _cache[5] || (_cache[5] = (...args) => _ctx.onBlur(...args)), onFocus: _cache[6] || (_cache[6] = (...args) => _ctx.onFocus(...args)), style: _ctx.computedStyles }), null, 16 /* FULL_PROPS */ , ["maxlength", "value"])), _ctx.icon ? createVNode(_component_o_icon, { key: 2, class: _ctx.iconLeftClasses, clickable: _ctx.iconClickable, icon: _ctx.icon, pack: _ctx.iconPack, size: _ctx.size, onClick: _cache[7] || (_cache[7] = $event => _ctx.iconClick('icon-click', $event)) }, null, 8 /* PROPS */ , ["class", "clickable", "icon", "pack", "size"]) : createCommentVNode("v-if", true), _ctx.hasIconRight ? createVNode(_component_o_icon, { key: 3, class: _ctx.iconRightClasses, clickable: _ctx.passwordReveal || _ctx.clearable || _ctx.iconRightClickable, icon: _ctx.rightIcon, pack: _ctx.iconPack, size: _ctx.size, variant: _ctx.rightIconVariant, both: "", onClick: _ctx.rightIconClick }, null, 8 /* PROPS */ , ["class", "clickable", "icon", "pack", "size", "variant", "onClick"]) : createCommentVNode("v-if", true), _ctx.maxlength && _ctx.hasCounter && _ctx.isFocused && _ctx.type !== 'number' ? (openBlock(), createBlock("small", { key: 4, class: _ctx.counterClasses }, toDisplayString(_ctx.valueLength) + " / " + toDisplayString(_ctx.maxlength), 3 /* TEXT, CLASS */ )) : createCommentVNode("v-if", true)], 2 /* CLASS */ ); } script.render = render; script.__file = "src/components/input/Input.vue"; export { script as s };