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 || '');
|
||
|
},
|
||
|
},
|
||
|
);
|
||
|
},
|
||
|
});
|