mirror of
https://github.com/Blah-IM/Weblah.git
synced 2025-09-17 23:35:24 +00:00
feat: chat history ui
This commit is contained in:
parent
0582dffa1c
commit
aebe100799
16 changed files with 325 additions and 8 deletions
|
@ -23,7 +23,7 @@
|
|||
<p>{placeholder}</p>
|
||||
</div>
|
||||
{:then Input}
|
||||
<svelte:component this={Input} bind:delta class={className} {placeholder}>
|
||||
<svelte:component this={Input} bind:delta {placeholder}>
|
||||
<slot />
|
||||
</svelte:component>
|
||||
{/await}
|
||||
|
|
|
@ -1,10 +1,28 @@
|
|||
<script lang="ts">
|
||||
import { Delta, Editor, asRoot } from 'typewriter-editor';
|
||||
import { Delta, Editor, asRoot, h } from 'typewriter-editor';
|
||||
|
||||
export let delta: Delta = new Delta();
|
||||
export let placeholder: string = '';
|
||||
|
||||
const editor = new Editor();
|
||||
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)
|
||||
});
|
||||
|
||||
delta = editor.getDelta();
|
||||
editor.on('change', () => {
|
||||
delta = editor.getDelta();
|
||||
|
|
28
src/lib/components/RichTextRenderer.svelte
Normal file
28
src/lib/components/RichTextRenderer.svelte
Normal file
|
@ -0,0 +1,28 @@
|
|||
<script lang="ts">
|
||||
import type { BlahRichText } from '$lib/richText';
|
||||
import { tw } from '$lib/tw';
|
||||
import RichTextSpan from './RichTextRenderer/RichTextSpan.svelte';
|
||||
|
||||
export let content: BlahRichText;
|
||||
let className = '';
|
||||
export { className as class };
|
||||
</script>
|
||||
|
||||
<div class={tw('rich-text', className)}>
|
||||
{#each content as block}
|
||||
<p>
|
||||
{#each block as span}
|
||||
{#if typeof span === 'string'}
|
||||
{#if span === ''}
|
||||
<br />
|
||||
{:else}
|
||||
{span}
|
||||
{/if}
|
||||
{:else}
|
||||
{@const [text, attributes] = span}
|
||||
<RichTextSpan {text} {attributes} />
|
||||
{/if}
|
||||
{/each}
|
||||
</p>
|
||||
{/each}
|
||||
</div>
|
53
src/lib/components/RichTextRenderer/RichTextSpan.svelte
Normal file
53
src/lib/components/RichTextRenderer/RichTextSpan.svelte
Normal file
|
@ -0,0 +1,53 @@
|
|||
<script lang="ts">
|
||||
import type { BlahRichTextSpanAttributes } from '$lib/richText';
|
||||
|
||||
// From outside to inside, better align this with the RichTextInput
|
||||
const renderOrder: (keyof BlahRichTextSpanAttributes)[] = [
|
||||
'link',
|
||||
'hashtag',
|
||||
'b',
|
||||
'i',
|
||||
'm',
|
||||
'u',
|
||||
's'
|
||||
];
|
||||
|
||||
const tagMap: Partial<Record<keyof BlahRichTextSpanAttributes, string>> = {
|
||||
s: 's',
|
||||
b: 'strong',
|
||||
i: 'em',
|
||||
m: 'code'
|
||||
};
|
||||
|
||||
const dataAttributeBrtMap: Partial<Record<keyof BlahRichTextSpanAttributes, string>> = {
|
||||
u: 'underline'
|
||||
};
|
||||
|
||||
export let text: string;
|
||||
export let attributes: BlahRichTextSpanAttributes;
|
||||
export let attribute: keyof BlahRichTextSpanAttributes | '' = renderOrder[0];
|
||||
|
||||
const nextAttribute = attribute ? (renderOrder[renderOrder.indexOf(attribute) + 1] ?? '') : null;
|
||||
</script>
|
||||
|
||||
{#if attribute === '' || !attributes[attribute]}
|
||||
{text}
|
||||
{:else if attribute === 'link'}
|
||||
<a href={attributes.link} target="_blank">
|
||||
<svelte:self {...$$props} attribute={nextAttribute} />
|
||||
</a>
|
||||
{:else if attribute === 'hashtag'}
|
||||
<a href={`/search?q=${encodeURIComponent(text)}`}>
|
||||
<svelte:self {...$$props} attribute={nextAttribute} />
|
||||
</a>
|
||||
{:else if tagMap[attribute]}
|
||||
<svelte:element this={tagMap[attribute]}>
|
||||
<svelte:self {...$$props} attribute={nextAttribute} />
|
||||
</svelte:element>
|
||||
{:else if dataAttributeBrtMap[attribute]}
|
||||
<span data-weblah-brt={dataAttributeBrtMap[attribute]}>
|
||||
<svelte:self {...$$props} attribute={nextAttribute} />
|
||||
</span>
|
||||
{:else}
|
||||
<svelte:self {...$$props} attribute={nextAttribute} />
|
||||
{/if}
|
Loading…
Add table
Add a link
Reference in a new issue