| <!-- |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| --> |
| <template> |
| <div :class="computedClasses" class="material-input__component"> |
| <div :class="{iconClass:icon}"> |
| <i v-if="icon" :class="['el-icon-' + icon]" class="el-input__icon material-input__icon" /> |
| <input |
| v-if="type === 'email'" |
| v-model="currentValue" |
| :name="name" |
| :placeholder="fillPlaceHolder" |
| :readonly="readonly" |
| :disabled="disabled" |
| :autocomplete="autoComplete" |
| :required="required" |
| type="email" |
| class="material-input" |
| @focus="handleMdFocus" |
| @blur="handleMdBlur" |
| @input="handleModelInput" |
| > |
| <input |
| v-if="type === 'url'" |
| v-model="currentValue" |
| :name="name" |
| :placeholder="fillPlaceHolder" |
| :readonly="readonly" |
| :disabled="disabled" |
| :autocomplete="autoComplete" |
| :required="required" |
| type="url" |
| class="material-input" |
| @focus="handleMdFocus" |
| @blur="handleMdBlur" |
| @input="handleModelInput" |
| > |
| <input |
| v-if="type === 'number'" |
| v-model="currentValue" |
| :name="name" |
| :placeholder="fillPlaceHolder" |
| :step="step" |
| :readonly="readonly" |
| :disabled="disabled" |
| :autocomplete="autoComplete" |
| :max="max" |
| :min="min" |
| :minlength="minlength" |
| :maxlength="maxlength" |
| :required="required" |
| type="number" |
| class="material-input" |
| @focus="handleMdFocus" |
| @blur="handleMdBlur" |
| @input="handleModelInput" |
| > |
| <input |
| v-if="type === 'password'" |
| v-model="currentValue" |
| :name="name" |
| :placeholder="fillPlaceHolder" |
| :readonly="readonly" |
| :disabled="disabled" |
| :autocomplete="autoComplete" |
| :max="max" |
| :min="min" |
| :required="required" |
| type="password" |
| class="material-input" |
| @focus="handleMdFocus" |
| @blur="handleMdBlur" |
| @input="handleModelInput" |
| > |
| <input |
| v-if="type === 'tel'" |
| v-model="currentValue" |
| :name="name" |
| :placeholder="fillPlaceHolder" |
| :readonly="readonly" |
| :disabled="disabled" |
| :autocomplete="autoComplete" |
| :required="required" |
| type="tel" |
| class="material-input" |
| @focus="handleMdFocus" |
| @blur="handleMdBlur" |
| @input="handleModelInput" |
| > |
| <input |
| v-if="type === 'text'" |
| v-model="currentValue" |
| :name="name" |
| :placeholder="fillPlaceHolder" |
| :readonly="readonly" |
| :disabled="disabled" |
| :autocomplete="autoComplete" |
| :minlength="minlength" |
| :maxlength="maxlength" |
| :required="required" |
| type="text" |
| class="material-input" |
| @focus="handleMdFocus" |
| @blur="handleMdBlur" |
| @input="handleModelInput" |
| > |
| <span class="material-input-bar" /> |
| <label class="material-label"> |
| <slot /> |
| </label> |
| </div> |
| </div> |
| </template> |
| |
| <script> |
| // source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue |
| export default { |
| name: 'MdInput', |
| props: { |
| /* eslint-disable */ |
| icon: String, |
| name: String, |
| type: { |
| type: String, |
| default: 'text' |
| }, |
| value: [String, Number], |
| placeholder: String, |
| readonly: Boolean, |
| disabled: Boolean, |
| min: String, |
| max: String, |
| step: String, |
| minlength: Number, |
| maxlength: Number, |
| required: { |
| type: Boolean, |
| default: true |
| }, |
| autoComplete: { |
| type: String, |
| default: 'off' |
| }, |
| validateEvent: { |
| type: Boolean, |
| default: true |
| } |
| }, |
| data() { |
| return { |
| currentValue: this.value, |
| focus: false, |
| fillPlaceHolder: null |
| } |
| }, |
| computed: { |
| computedClasses() { |
| return { |
| 'material--active': this.focus, |
| 'material--disabled': this.disabled, |
| 'material--raised': Boolean(this.focus || this.currentValue) // has value |
| } |
| } |
| }, |
| watch: { |
| value(newValue) { |
| this.currentValue = newValue |
| } |
| }, |
| methods: { |
| handleModelInput(event) { |
| const value = event.target.value |
| this.$emit('input', value) |
| if (this.$parent.$options.componentName === 'ElFormItem') { |
| if (this.validateEvent) { |
| this.$parent.$emit('el.form.change', [value]) |
| } |
| } |
| this.$emit('change', value) |
| }, |
| handleMdFocus(event) { |
| this.focus = true |
| this.$emit('focus', event) |
| if (this.placeholder && this.placeholder !== '') { |
| this.fillPlaceHolder = this.placeholder |
| } |
| }, |
| handleMdBlur(event) { |
| this.focus = false |
| this.$emit('blur', event) |
| this.fillPlaceHolder = null |
| if (this.$parent.$options.componentName === 'ElFormItem') { |
| if (this.validateEvent) { |
| this.$parent.$emit('el.form.blur', [this.currentValue]) |
| } |
| } |
| } |
| } |
| } |
| </script> |
| |
| <style lang="scss" scoped> |
| // Fonts: |
| $font-size-base: 16px; |
| $font-size-small: 18px; |
| $font-size-smallest: 12px; |
| $font-weight-normal: normal; |
| $font-weight-bold: bold; |
| $apixel: 1px; |
| // Utils |
| $spacer: 12px; |
| $transition: 0.2s ease all; |
| $index: 0px; |
| $index-has-icon: 30px; |
| // Theme: |
| $color-white: white; |
| $color-grey: #9E9E9E; |
| $color-grey-light: #E0E0E0; |
| $color-blue: #2196F3; |
| $color-red: #F44336; |
| $color-black: black; |
| // Base clases: |
| %base-bar-pseudo { |
| content: ''; |
| height: 1px; |
| width: 0; |
| bottom: 0; |
| position: absolute; |
| transition: $transition; |
| } |
| // Mixins: |
| @mixin slided-top() { |
| top: - ($font-size-base + $spacer); |
| left: 0; |
| font-size: $font-size-base; |
| font-weight: $font-weight-bold; |
| } |
| // Component: |
| .material-input__component { |
| margin-top: 36px; |
| position: relative; |
| * { |
| box-sizing: border-box; |
| } |
| .iconClass { |
| .material-input__icon { |
| position: absolute; |
| left: 0; |
| line-height: $font-size-base; |
| color: $color-blue; |
| top: $spacer; |
| width: $index-has-icon; |
| height: $font-size-base; |
| font-size: $font-size-base; |
| font-weight: $font-weight-normal; |
| pointer-events: none; |
| } |
| .material-label { |
| left: $index-has-icon; |
| } |
| .material-input { |
| text-indent: $index-has-icon; |
| } |
| } |
| .material-input { |
| font-size: $font-size-base; |
| padding: $spacer $spacer $spacer - $apixel * 10 $spacer / 2; |
| display: block; |
| width: 100%; |
| border: none; |
| line-height: 1; |
| border-radius: 0; |
| &:focus { |
| outline: none; |
| border: none; |
| border-bottom: 1px solid transparent; // fixes the height issue |
| } |
| } |
| .material-label { |
| font-weight: $font-weight-normal; |
| position: absolute; |
| pointer-events: none; |
| left: $index; |
| top: 0; |
| transition: $transition; |
| font-size: $font-size-small; |
| } |
| .material-input-bar { |
| position: relative; |
| display: block; |
| width: 100%; |
| &:before { |
| @extend %base-bar-pseudo; |
| left: 50%; |
| } |
| &:after { |
| @extend %base-bar-pseudo; |
| right: 50%; |
| } |
| } |
| // Disabled state: |
| &.material--disabled { |
| .material-input { |
| border-bottom-style: dashed; |
| } |
| } |
| // Raised state: |
| &.material--raised { |
| .material-label { |
| @include slided-top(); |
| } |
| } |
| // Active state: |
| &.material--active { |
| .material-input-bar { |
| &:before, |
| &:after { |
| width: 50%; |
| } |
| } |
| } |
| } |
| .material-input__component { |
| background: $color-white; |
| .material-input { |
| background: none; |
| color: $color-black; |
| text-indent: $index; |
| border-bottom: 1px solid $color-grey-light; |
| } |
| .material-label { |
| color: $color-grey; |
| } |
| .material-input-bar { |
| &:before, |
| &:after { |
| background: $color-blue; |
| } |
| } |
| // Active state: |
| &.material--active { |
| .material-label { |
| color: $color-blue; |
| } |
| } |
| // Errors: |
| &.material--has-errors { |
| &.material--active .material-label { |
| color: $color-red; |
| } |
| .material-input-bar { |
| &:before, |
| &:after { |
| background: transparent; |
| } |
| } |
| } |
| } |
| </style> |