More work on the new rich text editor. It may have a few bugs still.
This commit is contained in:
@@ -20,7 +20,7 @@
|
|||||||
import Align from './icons/textalign.svelte';
|
import Align from './icons/textalign.svelte';
|
||||||
import Quickcolor from './icons/quickcolor.svelte';
|
import Quickcolor from './icons/quickcolor.svelte';
|
||||||
import Table from './icons/table.svelte';
|
import Table from './icons/table.svelte';
|
||||||
import Image from './icons/image.svelte';
|
// import Image from './icons/image.svelte';
|
||||||
import Text from './icons/text.svelte';
|
import Text from './icons/text.svelte';
|
||||||
import SearchReplace from './icons/search-replace.svelte';
|
import SearchReplace from './icons/search-replace.svelte';
|
||||||
|
|
||||||
@@ -35,15 +35,15 @@ let { editor, show_button_kv }: Props = $props();
|
|||||||
|
|
||||||
let show_button_kv_defaults: any = {
|
let show_button_kv_defaults: any = {
|
||||||
undo: true,
|
undo: true,
|
||||||
redo: false,
|
redo: true,
|
||||||
|
|
||||||
text: true,
|
text: true,
|
||||||
|
|
||||||
bold: true,
|
bold: true,
|
||||||
italic: true,
|
italic: true,
|
||||||
underline: true,
|
underline: true,
|
||||||
strikethrough: true,
|
strikethrough: false,
|
||||||
align: true,
|
align: false,
|
||||||
link: true,
|
link: true,
|
||||||
code: false,
|
code: false,
|
||||||
blockquote: false,
|
blockquote: false,
|
||||||
@@ -57,7 +57,7 @@ let show_button_kv_defaults: any = {
|
|||||||
text_color: true,
|
text_color: true,
|
||||||
highlighter: true,
|
highlighter: true,
|
||||||
quick_color: true,
|
quick_color: true,
|
||||||
search_replace: true,
|
search_replace: false,
|
||||||
};
|
};
|
||||||
if (show_button_kv) {
|
if (show_button_kv) {
|
||||||
show_button_kv = {...show_button_kv_defaults, ...show_button_kv};
|
show_button_kv = {...show_button_kv_defaults, ...show_button_kv};
|
||||||
@@ -116,9 +116,9 @@ if (show_button_kv) {
|
|||||||
{#if show_button_kv.task_list}
|
{#if show_button_kv.task_list}
|
||||||
<TaskList {editor} />
|
<TaskList {editor} />
|
||||||
{/if}
|
{/if}
|
||||||
{#if show_button_kv.image}
|
<!-- {#if show_button_kv.image}
|
||||||
<Image {editor} />
|
<Image {editor} />
|
||||||
{/if}
|
{/if} -->
|
||||||
{#if show_button_kv.table}
|
{#if show_button_kv.table}
|
||||||
<Table {editor} />
|
<Table {editor} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
showToolbar?: boolean;
|
showToolbar?: boolean;
|
||||||
// html_text?: string;
|
// html_text?: string;
|
||||||
new_html?: string;
|
new_html?: string;
|
||||||
|
placeholder?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { class:
|
let { class:
|
||||||
@@ -52,6 +53,7 @@
|
|||||||
showToolbar = true,
|
showToolbar = true,
|
||||||
// html_text = '',
|
// html_text = '',
|
||||||
new_html = $bindable(''),
|
new_html = $bindable(''),
|
||||||
|
placeholder = $bindable('Start typing...')
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
let editor = $state<Editor>();
|
let editor = $state<Editor>();
|
||||||
@@ -141,11 +143,12 @@
|
|||||||
editor = transaction.editor;
|
editor = transaction.editor;
|
||||||
console.log(editor.isActive('bold'));
|
console.log(editor.isActive('bold'));
|
||||||
content = editor.getHTML();
|
content = editor.getHTML();
|
||||||
console.log(content);
|
// console.log(content);
|
||||||
if (content == '<p></p>') {
|
let html = editor.getHTML();
|
||||||
|
if (html == '<p></p>') {
|
||||||
new_html = '';
|
new_html = '';
|
||||||
} else {
|
} else {
|
||||||
new_html = content ?? '';
|
new_html = html ?? '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -160,5 +163,14 @@
|
|||||||
{#if editor && showToolbar}
|
{#if editor && showToolbar}
|
||||||
<EditorToolbar {editor} />
|
<EditorToolbar {editor} />
|
||||||
{/if}
|
{/if}
|
||||||
<div bind:this={element} spellcheck="false" class="h-full w-full flex-1 overflow-auto"></div>
|
<div
|
||||||
|
bind:this={element}
|
||||||
|
spellcheck="false"
|
||||||
|
class="tiptap h-full w-full overflow-auto relative">
|
||||||
|
<span
|
||||||
|
class="placeholder text-sm text-gray-400 italic absolute p-3"
|
||||||
|
contenteditable="false"
|
||||||
|
hidden={editor?.getHTML() !== '<p></p>'}
|
||||||
|
>{placeholder}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ let mouse_leave_wait: number = 2000;
|
|||||||
// show_menu = true;
|
// show_menu = true;
|
||||||
// }
|
// }
|
||||||
}}
|
}}
|
||||||
class="editor textarea p-1 transition-all duration-1000"
|
class="xxxeditor textarea p-1 transition-all duration-1000"
|
||||||
class:hidden={true}
|
class:hidden={true}
|
||||||
>
|
>
|
||||||
|
|
||||||
@@ -308,304 +308,7 @@ let mouse_leave_wait: number = 2000;
|
|||||||
items-center justify-between
|
items-center justify-between
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
|
<!-- Nothing Here Anymore -->
|
||||||
<!-- <div class="button-group flex flex-row flex-wrap gap-4 items-center justify-between"> -->
|
|
||||||
|
|
||||||
<span>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().toggleBold().run()}
|
|
||||||
disabled={!editor.can().chain().focus().toggleBold().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md font-bold"
|
|
||||||
class:variant-ghost-success={editor.isActive("bold") ?? false}
|
|
||||||
class:hidden={!show_button_kv.bold}
|
|
||||||
title="Bold"
|
|
||||||
>
|
|
||||||
<span class="fas fa-bold mx-1"></span>
|
|
||||||
<!-- Bold -->
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleItalic().run()}
|
|
||||||
disabled={!editor.can().chain().focus().toggleItalic().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md italic"
|
|
||||||
class:variant-ghost-success={editor.isActive("italic") ?? false}
|
|
||||||
class:hidden={!show_button_kv.italic}
|
|
||||||
title="Italic"
|
|
||||||
>
|
|
||||||
<span class="fas fa-italic mx-1"></span>
|
|
||||||
<!-- Italic -->
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleStrike().run()}
|
|
||||||
disabled={!editor.can().chain().focus().toggleStrike().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md line-through"
|
|
||||||
class:variant-ghost-success={editor.isActive("strike") ?? false}
|
|
||||||
class:hidden={!show_button_kv.strike}
|
|
||||||
title="Strike"
|
|
||||||
>
|
|
||||||
<span class="fas fa-strikethrough mx-1"></span>
|
|
||||||
<!-- Strike -->
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
|
|
||||||
<span>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleCode().run()}
|
|
||||||
disabled={!editor.can().chain().focus().toggleCode().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:variant-ghost-success={editor.isActive("code") ?? false}
|
|
||||||
class:hidden={!show_button_kv.code}
|
|
||||||
title="Code <code>"
|
|
||||||
>
|
|
||||||
<span class="fas fa-code mx-1"></span>
|
|
||||||
<!-- Code -->
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().setParagraph().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:variant-ghost-success={editor.isActive("paragraph") ? "is-active" : ""}
|
|
||||||
class:hidden={!show_button_kv.paragraph}
|
|
||||||
title="Paragraph"
|
|
||||||
>
|
|
||||||
<span class="fas fa-paragraph mx-1"></span>
|
|
||||||
<!-- Paragraph -->
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md text-xs"
|
|
||||||
class:variant-ghost-success={editor.isActive("heading", { level: 1 }) ? "is-active" : ""}
|
|
||||||
class:hidden={!show_button_kv.heading__h1}
|
|
||||||
title="Heading 1 <h1>"
|
|
||||||
>
|
|
||||||
<span class="fas fa-heading mx-1"></span>1
|
|
||||||
<!-- H1 -->
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md text-xs"
|
|
||||||
class:variant-ghost-success={editor.isActive("heading", { level: 2 }) ? "is-active" : ""}
|
|
||||||
class:hidden={!show_button_kv.heading__h2}
|
|
||||||
title="Heading 2 <h2>"
|
|
||||||
>
|
|
||||||
<span class="fas fa-heading mx-1"></span>2
|
|
||||||
<!-- <span class="text-xs">2</span> -->
|
|
||||||
<!-- 2 -->
|
|
||||||
<!-- H2 -->
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md text-xs"
|
|
||||||
class:variant-ghost-success={editor.isActive("heading", { level: 3 }) ? "is-active" : ""}
|
|
||||||
class:hidden={!show_button_kv.heading__h3}
|
|
||||||
title="Heading 3 <h3>"
|
|
||||||
>
|
|
||||||
<span class="fas fa-heading mx-1"></span>3
|
|
||||||
<!-- H3 -->
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:variant-ghost-success={editor.isActive("heading", { level: 4 }) ? "is-active" : ""}
|
|
||||||
class:hidden={!show_button_kv.heading__h4}
|
|
||||||
title="Heading 4 <h4>"
|
|
||||||
>
|
|
||||||
H4
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:variant-ghost-success={editor.isActive("heading", { level: 5 }) ? "is-active" : ""}
|
|
||||||
class:hidden={!show_button_kv.heading__h5}
|
|
||||||
title="Heading 5 <h5>"
|
|
||||||
>
|
|
||||||
H5
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:variant-ghost-success={editor.isActive("heading", { level: 6 }) ? "is-active" : ""}
|
|
||||||
class:hidden={!show_button_kv.heading__h6}
|
|
||||||
title="Heading 6 <h6>"
|
|
||||||
>
|
|
||||||
H6
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
|
|
||||||
<span>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleBulletList().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:variant-ghost-success={editor.isActive("bulletList") ? "is-active" : ""}
|
|
||||||
class:hidden={!show_button_kv.bulletList}
|
|
||||||
title="Bullet list"
|
|
||||||
>
|
|
||||||
<span class="fas fa-list-ul mx-1"></span>
|
|
||||||
<!-- Bullet -->
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleOrderedList().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:variant-ghost-success={editor.isActive("orderedList") ? "is-active" : ""}
|
|
||||||
class:hidden={!show_button_kv.orderedList}
|
|
||||||
title="Ordered list"
|
|
||||||
>
|
|
||||||
<span class="fas fa-list-ol mx-1"></span>
|
|
||||||
<!-- Ordered -->
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleCodeBlock().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:variant-ghost-success={editor.isActive("codeBlock") ? "is-active" : ""}
|
|
||||||
class:hidden={!show_button_kv.codeBlock}
|
|
||||||
title="Code block"
|
|
||||||
>
|
|
||||||
Code block
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleBlockquote().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:variant-ghost-success={editor.isActive("blockquote") ? "is-active" : ""}
|
|
||||||
class:hidden={!show_button_kv.blockquote}
|
|
||||||
title="Blockquote"
|
|
||||||
>
|
|
||||||
Blockquote
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().setHorizontalRule().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:hidden={!show_button_kv.horizontalRule}
|
|
||||||
title="Horizontal rule"
|
|
||||||
>
|
|
||||||
Horizontal rule
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().setHardBreak().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:hidden={!show_button_kv.hardBreak}
|
|
||||||
title="Hard break"
|
|
||||||
>
|
|
||||||
<span class="fas fa-level-down-alt mx-1"></span>
|
|
||||||
<!-- Hard break -->
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
|
|
||||||
<span>
|
|
||||||
<!-- Links: -->
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().toggleLink({ href: 'https://example.com' }).run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:variant-ghost-success={editor.isActive('link') ? 'is-active' : ''}
|
|
||||||
class:hidden={!show_button_kv.link}
|
|
||||||
title="Link"
|
|
||||||
>
|
|
||||||
<span class="fas fa-link mx-1"></span>
|
|
||||||
<!-- Link -->
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().unsetLink().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-warning rounded-md"
|
|
||||||
class:hidden={!show_button_kv.unsetLink}
|
|
||||||
title="Unset link"
|
|
||||||
>
|
|
||||||
<span class="fas fa-unlink mx-1"></span>
|
|
||||||
<!-- Unset link -->
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
|
|
||||||
<span
|
|
||||||
class="justify-self-end"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().unsetAllMarks().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-warning rounded-md"
|
|
||||||
class:hidden={!show_button_kv.unsetAllMarks}
|
|
||||||
title="Clear marks"
|
|
||||||
>
|
|
||||||
<!-- <span class="fas fa-broom mx-1"></span> -->
|
|
||||||
<span class="fas fa-remove-format mx-1"></span>
|
|
||||||
<!-- Clear marks -->
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().clearNodes().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-warning rounded-md"
|
|
||||||
class:hidden={!show_button_kv.clearNodes}
|
|
||||||
title="Clear nodes"
|
|
||||||
>
|
|
||||||
<!-- <span class="fas fa-broom mx-1"></span> -->
|
|
||||||
<span class="fas fa-remove-format mx-1"></span>
|
|
||||||
Clear nodes
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Undo (only once???) -->
|
|
||||||
<!-- Seems to forget the history after the first undo? -->
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().undo().run()}
|
|
||||||
disabled={!editor.can().chain().focus().undo().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-warning rounded-md"
|
|
||||||
class:hidden={!show_button_kv.undo}
|
|
||||||
title="Undo"
|
|
||||||
>
|
|
||||||
<span class="fas fa-undo mx-1"></span>
|
|
||||||
<span class="hidden">Undo</span>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Redo (not working???) -->
|
|
||||||
<!-- <button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().redo().run()}
|
|
||||||
disabled={!editor.can().chain().focus().redo().run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-warning rounded-md"
|
|
||||||
class:hidden={!show_button_kv.redo}
|
|
||||||
title="Redo"
|
|
||||||
>
|
|
||||||
<span class="fas fa-redo mx-1"></span>
|
|
||||||
</button> -->
|
|
||||||
</span>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- <span>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click={() => editor.chain().focus().setColor('#958DF1').run()}
|
|
||||||
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
|
|
||||||
class:variant-ghost-success={editor.isActive('textStyle', { color: '#958DF1' }) ? 'is-active' : ''}
|
|
||||||
class:hidden={!show_button_kv.color__purple}
|
|
||||||
>
|
|
||||||
Purple
|
|
||||||
</button>
|
|
||||||
</span> -->
|
|
||||||
|
|
||||||
<!-- </div> -->
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{/if} <!-- show_menu -->
|
{/if} <!-- show_menu -->
|
||||||
|
|
||||||
@@ -630,6 +333,7 @@ let mouse_leave_wait: number = 2000;
|
|||||||
class="editor textarea p-1 transition-all duration-1000"
|
class="editor textarea p-1 transition-all duration-1000"
|
||||||
bind:content={html_text}
|
bind:content={html_text}
|
||||||
bind:new_html={new_html}
|
bind:new_html={new_html}
|
||||||
|
placeholder={placeholder}
|
||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user