190 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			190 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <div class="form-group" :class="[
 | |
|        {'has-error': error},
 | |
|        formClasses
 | |
|        ]">
 | |
|     <slot name="label">
 | |
|       <label v-if="label" :class="labelClasses">
 | |
|         {{label}}
 | |
|         <span v-if="!notRequired" class="text-red ltr:ml-1 rtl:mr-1">*</span>
 | |
|       </label>
 | |
|     </slot>
 | |
|     <div class="relative" :class="[
 | |
|        {'input-group input-group-merge': hasIcon},
 | |
|        {'focused': focused},
 | |
|        {'input-group-alternative': alternative},
 | |
|        {'has-label': label || $slots.label},
 | |
|        {'prepend-input-icon': prependIcon},
 | |
|        inputGroupClasses
 | |
|        ]">
 | |
|       <div v-if="prependIcon || $slots.prepend" class="input-group-prepend absolute left-2 bottom-3 text-light-gray">
 | |
|         <span class="input-group-text">
 | |
|           <slot name="prepend">
 | |
|             <span class="material-icons w-4 h-5 text-sm">{{ prependIcon }}</span>
 | |
|           </slot>
 | |
|         </span>
 | |
|       </div>
 | |
|       <slot v-bind="slotData">
 | |
|         <input
 | |
|           :value="value"
 | |
|           :type="type"
 | |
|           v-on="listeners"
 | |
|           v-bind="$attrs"
 | |
|           :valid="!error"
 | |
|           :required="required"
 | |
|           class="w-full text-sm px-3 py-2.5 mt-1 rounded-lg border border-light-gray text-black placeholder-light-gray bg-white disabled:bg-gray-200 focus:outline-none focus:ring-transparent focus:border-purple"
 | |
|           :class="[{'is-valid': valid === true}, {'is-invalid': error}, inputClasses]">
 | |
|       </slot>
 | |
|       <div v-if="appendIcon || $slots.append" class="input-group-append absolute ltr:right-2 rtl:left-2 bottom-2 text-light-gray">
 | |
|           <span class="input-group-text">
 | |
|               <slot name="append">
 | |
|                 <span class="material-icons w-4 h-5 text-sm">{{ appendIcon }}</span>
 | |
|               </slot>
 | |
|           </span>
 | |
|       </div>
 | |
|       <slot name="infoBlock"></slot>
 | |
|       <slot name="error">
 | |
|         <div v-if="error" class="text-red text-sm mt-1 block"
 | |
|             v-html="error">
 | |
|         </div>
 | |
|       </slot>
 | |
|       <slot name="success">
 | |
|         <div class="text-green text-sm mt-1" v-if="!error && valid">
 | |
|           {{successMessage}}
 | |
|         </div>
 | |
|       </slot>
 | |
|     </div>
 | |
|     <slot name="error">
 | |
|       <div v-if="footerError" class="text-red text-sm mt-1 block"
 | |
|           v-html="footerError">
 | |
|       </div>
 | |
|     </slot>
 | |
|   </div>
 | |
| </template>
 | |
| <script>
 | |
|   export default {
 | |
|     inheritAttrs: false,
 | |
|     name: "base-input",
 | |
|     props: {
 | |
|       required: {
 | |
|         type: Boolean,
 | |
|         description: "Whether input is required (adds an asterix *)"
 | |
|       },
 | |
|       group: {
 | |
|         type: Boolean,
 | |
|         description: "Whether input is an input group (manual override in special cases)"
 | |
|       },
 | |
|       valid: {
 | |
|         type: Boolean,
 | |
|         description: "Whether is valid",
 | |
|         default: undefined
 | |
|       },
 | |
|       alternative: {
 | |
|         type: Boolean,
 | |
|         description: "Whether input is of alternative layout"
 | |
|       },
 | |
|       label: {
 | |
|         type: String,
 | |
|         description: "Input label (text before input)"
 | |
|       },
 | |
|       error: {
 | |
|         type: String,
 | |
|         description: "Input error (below input)"
 | |
|       },
 | |
|       footerError: {
 | |
|         type: String,
 | |
|         description: "Input error (below input)"
 | |
|       },
 | |
|       successMessage: {
 | |
|         type: String,
 | |
|         description: "Input success message",
 | |
|         default: 'Looks good!'
 | |
|       },
 | |
|       formClasses: {
 | |
|         type: String,
 | |
|         description: "Input form css classes"
 | |
|       },
 | |
|       labelClasses: {
 | |
|         type: String,
 | |
|         description: "Input label css classes",
 | |
|         default: "text-black text-sm font-medium"
 | |
|       },
 | |
|       inputClasses: {
 | |
|         type: String,
 | |
|         description: "Input css classes"
 | |
|       },
 | |
|       inputGroupClasses: {
 | |
|         type: String,
 | |
|         description: "Input group css classes"
 | |
|       },
 | |
|       value: {
 | |
|         type: [String, Number],
 | |
|         description: "Input value"
 | |
|       },
 | |
|       type: {
 | |
|         type: String,
 | |
|         description: "Input type",
 | |
|         default: "text"
 | |
|       },
 | |
|       appendIcon: {
 | |
|         type: String,
 | |
|         description: "Append icon (right)"
 | |
|       },
 | |
|       prependIcon: {
 | |
|         type: String,
 | |
|         description: "Prepend icon (left)"
 | |
|       },
 | |
|       notRequired: {
 | |
|         type: Boolean,
 | |
|         default: false
 | |
|       }
 | |
|     },
 | |
|     data() {
 | |
|       return {
 | |
|         focused: false
 | |
|       };
 | |
|     },
 | |
|     computed: {
 | |
|       listeners() {
 | |
|         return {
 | |
|           ...this.$listeners,
 | |
|           input: this.updateValue,
 | |
|           focus: this.onFocus,
 | |
|           blur: this.onBlur
 | |
|         };
 | |
|       },
 | |
|       slotData() {
 | |
|         return {
 | |
|           focused: this.focused,
 | |
|           error: this.error,
 | |
|           ...this.listeners
 | |
|         };
 | |
|       },
 | |
|       hasIcon() {
 | |
|         const { append, prepend } = this.$slots;
 | |
|         return (
 | |
|           append !== undefined ||
 | |
|           prepend !== undefined ||
 | |
|           this.appendIcon !== undefined ||
 | |
|           this.prependIcon !== undefined ||
 | |
|           this.group
 | |
|         );
 | |
|       }
 | |
|     },
 | |
|     methods: {
 | |
|       updateValue(evt) {
 | |
|         let value = evt.target.value;
 | |
|         this.$emit("input", value);
 | |
|       },
 | |
|       onFocus(evt) {
 | |
|         this.focused = true;
 | |
|         this.$emit("focus", evt);
 | |
|       },
 | |
|       onBlur(evt) {
 | |
|         this.focused = false;
 | |
|         this.$emit("blur", evt);
 | |
|       }
 | |
|     }
 | |
|   };
 | |
| </script>
 |