refactor(editor): Migrate InlineNameEdit & InlineTextEdit components to Vue 3 syntax (no-changelog) (#9755)

Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
This commit is contained in:
oleg 2024-06-20 10:38:08 +02:00 committed by GitHub
parent b7aea957b8
commit c0a6acaef6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 110 additions and 146 deletions

View file

@ -5,7 +5,6 @@
</span> </span>
<div <div
v-else v-else
v-on-click-outside="disableNameEdit"
:class="[$style.headline, $style['headline-editable']]" :class="[$style.headline, $style['headline-editable']]"
@keydown.stop @keydown.stop
@click="enableNameEdit" @click="enableNameEdit"
@ -31,66 +30,53 @@
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue'; import { nextTick, ref } from 'vue';
import { useToast } from '@/composables/useToast'; import { useToast } from '@/composables/useToast';
import { onClickOutside } from '@vueuse/core';
export default defineComponent({ interface Props {
name: 'InlineNameEdit', modelValue: string;
props: { subtitle: string;
modelValue: { type: string;
type: String, readonly: boolean;
},
subtitle: {
type: String,
},
type: {
type: String,
},
readonly: {
type: Boolean,
default: false,
},
},
setup() {
return {
...useToast(),
};
},
data() {
return {
isNameEdit: false,
};
},
methods: {
onNameEdit(value: string) {
this.$emit('update:modelValue', value);
},
enableNameEdit() {
this.isNameEdit = true;
setTimeout(() => {
const inputRef = this.$refs.nameInput as HTMLInputElement | undefined;
if (inputRef) {
inputRef.focus();
} }
}, 0); const props = defineProps<Props>();
},
disableNameEdit() {
if (!this.modelValue) {
this.$emit('update:modelValue', `Untitled ${this.type}`);
this.showToast({ const emit = defineEmits<{
(event: 'update:modelValue', value: string): void;
}>();
const isNameEdit = ref(false);
const nameInput = ref<HTMLInputElement | null>(null);
const { showToast } = useToast();
const onNameEdit = (value: string) => {
emit('update:modelValue', value);
};
const enableNameEdit = () => {
isNameEdit.value = true;
void nextTick(() => {
if (nameInput.value) {
nameInput.value.focus();
}
});
};
const disableNameEdit = () => {
if (!props.modelValue) {
emit('update:modelValue', `Untitled ${props.type}`);
showToast({
title: 'Error', title: 'Error',
message: `${this.type} name cannot be empty`, message: `${props.type} name cannot be empty`,
type: 'warning', type: 'warning',
}); });
} }
isNameEdit.value = false;
};
this.isNameEdit = false; onClickOutside(nameInput, disableNameEdit);
},
},
});
</script> </script>
<style module lang="scss"> <style module lang="scss">

View file

@ -2,8 +2,8 @@
<span class="inline-edit" @keydown.stop> <span class="inline-edit" @keydown.stop>
<span v-if="isEditEnabled && !isDisabled"> <span v-if="isEditEnabled && !isDisabled">
<ExpandableInputEdit <ExpandableInputEdit
v-model="newValue"
:placeholder="placeholder" :placeholder="placeholder"
:model-value="newValue"
:maxlength="maxLength" :maxlength="maxLength"
:autofocus="true" :autofocus="true"
:event-bus="inputBus" :event-bus="inputBus"
@ -20,106 +20,84 @@
</span> </span>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue'; import { ref, watch, defineProps, defineEmits } from 'vue';
import ExpandableInputEdit from '@/components/ExpandableInput/ExpandableInputEdit.vue'; import ExpandableInputEdit from '@/components/ExpandableInput/ExpandableInputEdit.vue';
import ExpandableInputPreview from '@/components/ExpandableInput/ExpandableInputPreview.vue'; import ExpandableInputPreview from '@/components/ExpandableInput/ExpandableInputPreview.vue';
import { createEventBus } from 'n8n-design-system/utils'; import { createEventBus } from 'n8n-design-system/utils';
export default defineComponent({ const props = withDefaults(
name: 'InlineTextEdit', defineProps<{
components: { ExpandableInputEdit, ExpandableInputPreview }, isEditEnabled: boolean;
props: { modelValue: string;
isEditEnabled: { placeholder: string;
type: Boolean, maxLength: number;
default: false, previewValue: string;
disabled: boolean;
}>(),
{
isEditEnabled: false,
modelValue: '',
placeholder: '',
maxLength: 0,
previewValue: '',
disabled: false,
}, },
modelValue: { );
type: String,
default: '', const emit = defineEmits<{
(event: 'toggle'): void;
(event: 'submit', payload: { name: string; onSubmit: (updated: boolean) => void }): void;
}>();
const isDisabled = ref(props.disabled);
const newValue = ref('');
const escPressed = ref(false);
const inputBus = ref(createEventBus());
watch(
() => props.disabled,
(value) => {
isDisabled.value = value;
}, },
placeholder: { );
type: String,
default: '', function onInput(val: string) {
}, if (isDisabled.value) return;
maxLength: { newValue.value = val;
type: Number,
default: 0,
},
previewValue: {
type: String,
default: '',
},
disabled: {
type: Boolean,
default: false,
},
},
data() {
return {
isDisabled: this.disabled,
newValue: '',
escPressed: false,
inputBus: createEventBus(),
};
},
watch: {
disabled(value) {
this.isDisabled = value;
},
},
methods: {
onInput(newValue: string) {
if (this.disabled) {
return;
} }
this.newValue = newValue; function onClick() {
}, if (isDisabled.value) return;
onClick() { newValue.value = props.modelValue;
if (this.disabled) { emit('toggle');
return;
} }
this.newValue = this.modelValue; function onBlur() {
this.$emit('toggle'); if (isDisabled.value) return;
}, if (!escPressed.value) {
onBlur() { submit();
if (this.disabled) { }
return; escPressed.value = false;
}
if (!this.escPressed) {
this.submit();
}
this.escPressed = false;
},
submit() {
if (this.disabled) {
return;
} }
function submit() {
if (isDisabled.value) return;
const onSubmit = (updated: boolean) => { const onSubmit = (updated: boolean) => {
this.isDisabled = false; isDisabled.value = false;
if (!updated) { if (!updated) {
this.inputBus.emit('focus'); inputBus.value.emit('focus');
} }
}; };
isDisabled.value = true;
this.isDisabled = true; emit('submit', { name: newValue.value, onSubmit });
this.$emit('submit', { name: this.newValue, onSubmit });
},
onEscape() {
if (this.disabled) {
return;
} }
this.escPressed = true; function onEscape() {
this.$emit('toggle'); if (isDisabled.value) return;
}, escPressed.value = true;
}, emit('toggle');
}); }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>