mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-07-25 15:59:38 +02:00
Add Markdown editor component and integrate it into AdventureModal
This commit is contained in:
parent
7d609d01ea
commit
dd08a6fe24
14 changed files with 131 additions and 20 deletions
|
@ -32,6 +32,7 @@
|
|||
import { appVersion } from '$lib/config';
|
||||
import CategoryDropdown from './CategoryDropdown.svelte';
|
||||
import { findFirstValue } from '$lib';
|
||||
import MarkdownEditor from './MarkdownEditor.svelte';
|
||||
|
||||
let wikiError: string = '';
|
||||
|
||||
|
@ -577,15 +578,10 @@
|
|||
</div>
|
||||
<div>
|
||||
<label for="description">{$t('adventures.description')}</label><br />
|
||||
<textarea
|
||||
id="description"
|
||||
name="description"
|
||||
bind:value={adventure.description}
|
||||
class="textarea textarea-bordered w-full h-32"
|
||||
></textarea>
|
||||
<MarkdownEditor bind:text={adventure.description} />
|
||||
<div class="mt-2">
|
||||
<div class="tooltip tooltip-right" data-tip={$t('adventures.wiki_desc')}>
|
||||
<button type="button" class="btn btn-neutral" on:click={generateDesc}
|
||||
<button type="button" class="btn btn-neutral mt-2" on:click={generateDesc}
|
||||
>{$t('adventures.generate_desc')}</button
|
||||
>
|
||||
</div>
|
||||
|
|
80
frontend/src/lib/components/MarkdownEditor.svelte
Normal file
80
frontend/src/lib/components/MarkdownEditor.svelte
Normal file
|
@ -0,0 +1,80 @@
|
|||
<script lang="ts">
|
||||
import { marked } from 'marked'; // Import the markdown parser
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
export let text: string | null | undefined = ''; // Markdown text
|
||||
let is_preview: boolean = false; // Toggle between Edit and Preview mode
|
||||
|
||||
// Function to parse markdown to HTML
|
||||
const renderMarkdown = (markdown: string) => {
|
||||
return marked(markdown);
|
||||
};
|
||||
|
||||
// References for scroll syncing
|
||||
let editorRef: HTMLTextAreaElement | null = null;
|
||||
let previewRef: HTMLElement | null = null;
|
||||
|
||||
// Sync scrolling between editor and preview
|
||||
const syncScroll = () => {
|
||||
if (editorRef && previewRef) {
|
||||
const ratio = editorRef.scrollTop / (editorRef.scrollHeight - editorRef.clientHeight);
|
||||
previewRef.scrollTop = ratio * (previewRef.scrollHeight - previewRef.clientHeight);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="join justify-center mt-2">
|
||||
<button
|
||||
type="button"
|
||||
class="join-item btn btn-sm btn-outline"
|
||||
on:click={() => (is_preview = false)}
|
||||
class:btn-active={!is_preview}
|
||||
>
|
||||
{$t('transportation.edit')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="join-item btn btn-sm btn-outline"
|
||||
on:click={() => (is_preview = true)}
|
||||
class:btn-active={is_preview}
|
||||
>
|
||||
{$t('adventures.preview')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col mt-4 gap-4">
|
||||
<!-- Markdown Editor -->
|
||||
{#if !is_preview}
|
||||
<textarea
|
||||
class="textarea textarea-bordered resize-none h-64 w-full"
|
||||
bind:this={editorRef}
|
||||
bind:value={text}
|
||||
placeholder={$t('adventures.md_instructions')}
|
||||
on:scroll={syncScroll}
|
||||
></textarea>
|
||||
{/if}
|
||||
|
||||
<!-- Markdown Preview -->
|
||||
{#if is_preview}
|
||||
<article
|
||||
class="prose overflow-auto h-96 max-w-full w-full p-4 border border-base-300 rounded-lg bg-base-300"
|
||||
bind:this={previewRef}
|
||||
>
|
||||
{@html renderMarkdown(text || '')}
|
||||
</article>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* Optional: Smooth scrolling for synced scroll effect */
|
||||
textarea,
|
||||
article {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* Force both editor and preview to have equal width */
|
||||
textarea,
|
||||
article {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
Loading…
Add table
Add a link
Reference in a new issue