@@ -4,70 +4,82 @@ import ValidationError from '@/components/ValidationError.vue'
44import { required } from ' @vuelidate/validators'
55import useVuelidate from ' @vuelidate/core'
66import { CheckIcon , PencilIcon , XIcon } from ' @heroicons/vue/outline'
7- import { computed , defineEmits , defineProps , reactive , ref } from ' vue'
7+ import { computed , defineEmits , defineProps , effect , ref , watchEffect } from ' vue'
88
99const emit = defineEmits ([' change' ])
1010
1111const props = defineProps ({
1212 busy: Boolean ,
1313 disabled: Boolean ,
1414 placeholder: String ,
15+ validate: [Function , Object ],
1516 value: String
1617})
1718
18- const formState = reactive ({
19- newValue: props .value || ' '
20- })
19+ const newValue = ref (' ' )
2120
22- const v$ = useVuelidate ({ newValue: [ required] }, formState )
21+ const v$ = useVuelidate ({ newValue: props . validate || { required } }, { newValue } )
2322
24- const canSave = computed (() => ! v$ .value .$invalid )
23+ const canSave = computed (() => ! props . disabled && ! v$ .value .$invalid )
2524const editing = ref (false )
26- const inputRef = ref ()
25+ const inputRef = ref (null )
26+
27+ function reset () {
28+ editing .value = false
29+ v$ .value .newValue .$model = props .value || ' '
30+ v$ .value .$reset ()
31+ }
2732
2833function startEdit () {
2934 editing .value = true
30- inputRef .value .focus ()
3135}
3236
33- function stopEdit (change = true ) {
37+ async function stopEdit () {
38+ if (! await v$ .value .$validate ()) return
39+
40+ emit (' change' , newValue .value )
41+
3442 editing .value = false
35- if (change) {
36- emit (' change' , formState .newValue )
37- }
3843}
44+
45+ effect (() => {
46+ reset ()
47+ })
48+
49+ watchEffect (() => {
50+ if (inputRef .value ) inputRef .value .focus ()
51+ })
3952 </script >
4053
4154<template >
4255 <div class =" editable-title__container flex" >
4356 <div v-if =" editing" >
4457 <input
4558 v-model =" v$.newValue.$model"
46- @keypress.enter =" stopEdit"
59+ @keypress.enter.prevent =" stopEdit"
4760 class =" editable-title__value"
48- :placeholder =" value || placeholder"
49- : ref =" inputRef"
61+ :placeholder =" placeholder"
62+ ref =" inputRef"
5063 type =" text"
5164 />
5265 <ValidationError :errors =" v$ .newValue .$errors " />
5366 </div >
5467 <h1 v-else class =" w-max mb-0" >{{ value }}</h1 >
5568
56- <div v-if = editing class =" mt-3" >
69+ <div class =" mt-3" >
5770 <button v-if =" busy" class =" ml-2" disabled >
5871 <LoadingSpinner v-if =" busy " />
5972 </button >
60- <button v-else class =" ml-2" @click =" stopEdit" :disabled =" !canSave" >
73+ <button v-else-if = " editing " class =" ml-2" @click =" stopEdit" :disabled =" !canSave" >
6174 <CheckIcon class="button__icon text-green hover:text-green-600 " />
6275 </button >
63- <button v-if =" !busy" @click =" stopEdit(false)" class =" ml-2" >
64- <XIcon class="button__icon text-red hover:text-red-600 " />
65- </button >
66- </div >
67- <div v-else-if =" !disabled" class =" mt-3" >
68- <button class =" ml-2" @click =" startEdit" >
76+ <button v-else class =" ml-2" @click =" startEdit" :disabled =" disabled" >
6977 <PencilIcon class="button__icon text-gray-400 hover:text-green " />
7078 </button >
79+
80+ <button v-if =" !busy && editing" @click =" reset" class =" ml-2" >
81+ <XIcon class="button__icon text-red hover:text-red-600 " />
82+ </button >
7183 </div >
7284 </div >
7385</template >
0 commit comments