Slow work on creating a textarea element thing.

This commit is contained in:
Scott Idem
2024-10-14 19:02:56 -04:00
parent 115751bcd7
commit e2a510ceaa
5 changed files with 1806 additions and 201 deletions

View File

@@ -0,0 +1,102 @@
/* Basic editor styles */
.tiptap {
:first-child {
margin-top: 0;
}
/* List styles */
ul {
list-style-type: disc;
margin-left: 1.5rem;
// border: solid thin red;
}
ol {
list-style-type: decimal;
margin-left: 1.5rem;
// border: solid thin red;
}
ul,
ol {
padding: 0 1rem;
margin: 1.25rem 1rem 1.25rem 0.4rem;
li p {
margin-top: 0.25em;
margin-bottom: 0.25em;
}
}
/* Heading styles */
h1,
h2,
h3,
h4,
h5,
h6 {
line-height: 1.1;
margin-top: 2.5rem;
text-wrap: pretty;
}
h1,
h2 {
margin-top: 3.5rem;
margin-bottom: 1.5rem;
}
h1 {
font-size: 1.4rem;
}
h2 {
font-size: 1.2rem;
}
h3 {
font-size: 1.1rem;
}
h4,
h5,
h6 {
font-size: 1rem;
}
/* Code and preformatted text styles */
code {
background-color: var(--purple-light);
border-radius: 0.4rem;
color: var(--black);
font-size: 0.85rem;
padding: 0.25em 0.3em;
}
pre {
background: var(--black);
border-radius: 0.5rem;
color: var(--white);
font-family: 'JetBrainsMono', monospace;
margin: 1.5rem 0;
padding: 0.75rem 1rem;
code {
background: none;
color: inherit;
font-size: 0.8rem;
padding: 0;
}
}
blockquote {
border-left: 3px solid var(--gray-3);
margin: 1.5rem 0;
padding-left: 1rem;
}
hr {
border: none;
border-top: 1px solid var(--gray-2);
margin: 2rem 0;
}
}

View File

@@ -0,0 +1,372 @@
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import { Color } from '@tiptap/extension-color'
import ListItem from '@tiptap/extension-list-item'
import TextStyle from '@tiptap/extension-text-style'
import StarterKit from "@tiptap/starter-kit";
import { Editor } from "@tiptap/core";
import "./element_tiptap_editor.scss";
export let html_text: string = '';
// export let html_text: string = `
// <h2>
// Hi there,
// </h2>
// <p>
// this is a <em>basic</em> example of <strong>Tiptap</strong>. Sure, there are all kind of basic text styles youd probably expect from a text editor. But wait until you see the lists:
// </p>
// <ul>
// <li>
// Thats a bullet list with one …
// </li>
// <li>
// … or two list items.
// </li>
// </ul>
// <p>
// Isnt that great? And all of that is editable. But wait, theres more. Lets try a code block:
// </p>
// <pre><code class="language-css">body {
// display: none;
// }</code></pre>
// <p>
// I know, I know, this is impressive. Its only the tip of the iceberg though. Give it a try and click a little bit around. Dont forget to check the other examples too.
// </p>
// <blockquote>
// Wow, thats amazing. Good work, boy! 👏
// <br />
// — Mom
// </blockquote>
// `;
let element: HTMLDivElement;
let editor: any;
let show_button_kv_defaults: any = {
bold: true,
italic: true,
strike: true,
code: true,
paragraph: true,
heading__h1: true,
heading__h2: true,
heading__h3: true,
unsetAllMarks: true,
bulletList: true,
orderedList: true,
hardBreak: true,
undo: true,
redo: true,
};
export let show_button_kv: any;
if (show_button_kv) {
show_button_kv = { ...show_button_kv_defaults, ...show_button_kv };
} else {
show_button_kv = show_button_kv_defaults;
}
onMount(() => {
editor = new Editor({
element: element,
extensions: [
Color.configure({ types: [TextStyle.name, ListItem.name] }),
TextStyle.configure({ types: [ListItem.name] }),
StarterKit,
],
content: html_text,
onTransaction: () => {
// force re-render so `editor.isActive` works as expected
editor = editor;
},
});
});
onDestroy(() => {
if (editor) {
editor.destroy();
}
});
</script>
<div
class="editor border border-gray-300 rounded p-1 pb-2 bg-gray-200"
>
{#if editor}
<div class="control-group bg-gray-200 border-b border-gray-400 p-1">
<div class="button-group flex flex-row flex-wrap gap-4 items-center justify-between">
<span>
<button
type="button"
on:click={() => console.log && 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-secondary={editor.isActive("bold") ?? false}
class:hidden={!show_button_kv.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-secondary={editor.isActive("italic") ?? false}
class:hidden={!show_button_kv.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-secondary={editor.isActive("strike") ?? false}
class:hidden={!show_button_kv.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-secondary={editor.isActive("code") ?? false}
class:hidden={!show_button_kv.code}
>
<span class="fas fa-code mx-1"></span>
<!-- Code -->
</button>
<button
type="button"
on:click={() => editor.chain().focus().unsetAllMarks().run()}
class="btn btn-sm variant-glass-secondary hover:variant-filled-secondary rounded-md"
class:hidden={!show_button_kv.unsetAllMarks}
>
<!-- <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-secondary rounded-md"
class:hidden={!show_button_kv.clearNodes}
>
<!-- <span class="fas fa-broom mx-1"></span> -->
<span class="fas fa-remove-format mx-1"></span>
Clear nodes
</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-secondary={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-secondary={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-secondary={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-secondary={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-secondary={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-secondary={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-secondary={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-secondary={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-secondary={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-secondary={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-secondary={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
class="justify-self-end"
>
<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-secondary rounded-md"
class:hidden={!show_button_kv.undo}
title="Undo"
>
<span class="fas fa-undo mx-1"></span>
<!-- Undo -->
</button>
<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-secondary rounded-md"
class:hidden={!show_button_kv.redo}
title="Redo"
>
<span class="fas fa-redo mx-1"></span>
<!-- Redo -->
</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-secondary={editor.isActive('textStyle', { color: '#958DF1' }) ? 'is-active' : ''}
class:hidden={!show_button_kv.color__purple}
>
Purple
</button>
</span> -->
</div>
</div>
{/if}
<div
bind:this={element}
class="tiptap bg-slate-100 px-1 py-2"
/>
</div>
<style lang="scss">
</style>