@ishitatsuyuki/oruga-next
Version:
UI components for Vue.js and CSS framework agnostic
337 lines (331 loc) • 11.8 kB
JavaScript
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 };