schlechtenburg/packages/core/lib/components/Contenteditable.tsx

77 lines
1.6 KiB
TypeScript

import {
ref,
Ref,
h,
defineComponent,
onMounted,
onBeforeUnmount,
PropType,
watchEffect,
} from 'vue';
import { useInline } from '../inline';
export const SbContenteditable = defineComponent({
name: 'sb-contenteditable',
props: {
inputRef: {
type: (null as unknown) as PropType<Ref<HTMLElement|null>>,
default: ref(null),
},
tag: { type: String, default: 'div' },
value: { type: String, default: '' },
onValueChange: {
type: (null as unknown) as PropType<(value: string) => void>,
default: (_:string) => {},
},
},
setup(props) {
const {
registerClient,
unregisterClient,
} = useInline();
const onKeyup = (event: KeyboardEvent) => {
if (event.code !== 'Backspace' && event.code !== 'Delete') {
return;
}
if (!props.inputRef.value) {
return;
}
const textContent = props.inputRef.value.textContent;
if (textContent === '') {
props.inputRef.value.innerHTML = '';
}
};
onMounted(() => {
props.inputRef.value?.focus();
registerClient(props.inputRef.value!);
});
watchEffect(() => {
if (props.inputRef.value && props.inputRef.value.innerHTML != props.value) {
props.inputRef.value.innerHTML = props.value;
}
});
onBeforeUnmount(() => {
unregisterClient(props.inputRef.value!);
});
return () => h(props.tag, {
class: 'sb-contenteditable',
contenteditable: 'true',
ref: props.inputRef,
onKeyup,
onInput: () => {
props.onValueChange(props.inputRef.value?.innerHTML || '');
},
});
},
});