70 lines
1.4 KiB
TypeScript
70 lines
1.4 KiB
TypeScript
import {
|
|
ref,
|
|
Ref,
|
|
h,
|
|
defineComponent,
|
|
onMounted,
|
|
onBeforeUnmount,
|
|
PropType,
|
|
computed,
|
|
watchEffect,
|
|
} from 'vue';
|
|
import { useFormattingToolbar } from './use-formatting-toolbar';
|
|
|
|
export const SbRichText = defineComponent({
|
|
name: 'sb-rich-text',
|
|
|
|
props: {
|
|
inputRef: {
|
|
type: (null as unknown) as PropType<Ref<HTMLElement|null>>,
|
|
default: ref(null),
|
|
},
|
|
tag: { type: String, default: 'p' },
|
|
|
|
value: { type: String, default: '' },
|
|
|
|
onValueChange: {
|
|
type: (null as unknown) as PropType<(value: string) => void>,
|
|
default: (_:string) => {},
|
|
},
|
|
},
|
|
|
|
setup(props) {
|
|
const {
|
|
registerClient,
|
|
unregisterClient,
|
|
} = useFormattingToolbar();
|
|
|
|
const onKeydown = (event: KeyboardEvent) => {
|
|
if (['Delete', 'Backspace'].indexOf(event.key) < 0) {
|
|
return;
|
|
}
|
|
|
|
if (props.inputRef.value?.textContent === '') {
|
|
props.inputRef.value.innerHTML = '';
|
|
}
|
|
};
|
|
|
|
onMounted(() => {
|
|
registerClient(props.inputRef.value!);
|
|
});
|
|
|
|
onBeforeUnmount(() => {
|
|
unregisterClient(props.inputRef.value!);
|
|
});
|
|
|
|
return () => h(
|
|
props.tag,
|
|
{
|
|
class: 'sb-contenteditable',
|
|
contenteditable: 'true',
|
|
ref: props.inputRef,
|
|
onKeydown,
|
|
onInput: () => {
|
|
props.onValueChange(props.inputRef.value?.innerHTML || '');
|
|
},
|
|
},
|
|
);
|
|
},
|
|
});
|