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

View file

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