mirror of
https://github.com/Blah-IM/Weblah.git
synced 2025-05-01 00:31:08 +00:00
84 lines
2.5 KiB
Svelte
84 lines
2.5 KiB
Svelte
<script lang="ts">
|
|
import { Delta, Editor, asRoot, h } from 'typewriter-editor';
|
|
import { keyboardSubmit } from './keyboardSubmitModule';
|
|
|
|
interface Props {
|
|
delta?: Delta;
|
|
plainText?: string | undefined;
|
|
placeholder?: string;
|
|
keyboardSubmitMethod?: 'enter' | 'shiftEnter' | undefined;
|
|
onKeyboardSubmit?: () => void;
|
|
children?: import('svelte').Snippet;
|
|
}
|
|
|
|
let {
|
|
delta = $bindable(new Delta()),
|
|
plainText = $bindable(undefined),
|
|
placeholder = '',
|
|
keyboardSubmitMethod = undefined,
|
|
onKeyboardSubmit,
|
|
children
|
|
}: Props = $props();
|
|
|
|
let editor: Editor = $state(initEditor());
|
|
|
|
function initEditor() {
|
|
const modules = keyboardSubmitMethod
|
|
? {
|
|
keyboardSubmit: keyboardSubmit(
|
|
() => onKeyboardSubmit && onKeyboardSubmit(),
|
|
keyboardSubmitMethod
|
|
)
|
|
}
|
|
: undefined;
|
|
const editor = new Editor({ modules });
|
|
editor.typeset.formats.add({
|
|
name: 'underline',
|
|
selector: 'span[data-weblah-brt=underline]',
|
|
styleSelector: '[style*="text-decoration:underline"], [style*="text-decoration: underline"]',
|
|
commands: (editor) => () => editor.toggleTextFormat({ underline: true }),
|
|
shortcuts: 'Mod+U',
|
|
render: (attributes, children) => h('span', { 'data-weblah-brt': 'underline' }, children)
|
|
});
|
|
editor.typeset.formats.add({
|
|
name: 'strikethrough',
|
|
selector: 's',
|
|
styleSelector:
|
|
'[style*="text-decoration:line-through"], [style*="text-decoration: line-through"]',
|
|
commands: (editor) => () => editor.toggleTextFormat({ strikethrough: true }),
|
|
shortcuts: 'Mod+Shift+X',
|
|
render: (attributes, children) => h('s', null, children)
|
|
});
|
|
|
|
editor.on('change', () => {
|
|
delta = editor.getDelta();
|
|
if (typeof plainText === 'string') plainText = editor.getText();
|
|
});
|
|
|
|
return editor;
|
|
}
|
|
|
|
$effect.pre(() => {
|
|
if (keyboardSubmitMethod || typeof keyboardSubmitMethod === 'undefined') editor = initEditor();
|
|
});
|
|
|
|
$effect.pre(() => {
|
|
editor.setDelta(delta ?? new Delta());
|
|
});
|
|
$effect.pre(() => {
|
|
if (typeof plainText === 'string' && plainText !== editor.getText()) editor.setText(plainText);
|
|
});
|
|
</script>
|
|
|
|
<div
|
|
class="rich-text relative w-full outline-hidden before:absolute before:hidden before:leading-tight before:opacity-50 before:content-[attr(data-weblah-placeholder)] data-weblah-is-empty:before:block"
|
|
use:asRoot={editor}
|
|
data-weblah-is-empty={!delta || (delta.ops.length === 1 && delta.ops[0].insert === '\n')
|
|
? 'true'
|
|
: undefined}
|
|
data-weblah-placeholder={placeholder}
|
|
role="textbox"
|
|
tabindex="0"
|
|
>
|
|
{@render children?.()}
|
|
</div>
|