83 lines
2.2 KiB
Svelte
83 lines
2.2 KiB
Svelte
<script lang="ts">
|
|
import { tick, type Snippet } from 'svelte';
|
|
import AppIcon from './AppIcon.svelte';
|
|
|
|
let {
|
|
labelledby,
|
|
activeSection = $bindable(),
|
|
onrequestclose,
|
|
header,
|
|
children,
|
|
footer
|
|
}: {
|
|
labelledby: string;
|
|
activeSection: 'script' | 'research' | 'presentation';
|
|
onrequestclose: () => void;
|
|
header: Snippet;
|
|
children: Snippet;
|
|
footer: Snippet;
|
|
} = $props();
|
|
|
|
let dialog: HTMLDialogElement;
|
|
let workspace: HTMLDivElement;
|
|
const scrollPositions = { script: 0, research: 0, presentation: 0 };
|
|
|
|
async function selectSection(section: typeof activeSection) {
|
|
scrollPositions[activeSection] = workspace.scrollTop;
|
|
activeSection = section;
|
|
await tick();
|
|
workspace.scrollTop = scrollPositions[section];
|
|
}
|
|
|
|
export function showModal() {
|
|
if (!dialog.open) dialog.showModal();
|
|
}
|
|
|
|
export function close() {
|
|
dialog.close();
|
|
}
|
|
</script>
|
|
|
|
<dialog
|
|
bind:this={dialog}
|
|
class="piece-editor-dialog"
|
|
aria-labelledby={labelledby}
|
|
oncancel={(event) => {
|
|
event.preventDefault();
|
|
onrequestclose();
|
|
}}
|
|
onclick={(event) => event.target === dialog && onrequestclose()}
|
|
>
|
|
<header class="piece-dialog-header">
|
|
<div class="piece-dialog-heading">{@render header()}</div>
|
|
<button
|
|
class="dialog-close"
|
|
type="button"
|
|
aria-label="Editor schließen"
|
|
onclick={onrequestclose}><AppIcon name="xmark" /></button
|
|
>
|
|
</header>
|
|
<nav class="piece-dialog-tabs" aria-label="Editorbereiche">
|
|
<button
|
|
type="button"
|
|
class:active={activeSection === 'script'}
|
|
aria-current={activeSection === 'script' ? 'page' : undefined}
|
|
onclick={() => selectSection('script')}>Sendungstext</button
|
|
>
|
|
<button
|
|
type="button"
|
|
class:active={activeSection === 'research'}
|
|
aria-current={activeSection === 'research' ? 'page' : undefined}
|
|
onclick={() => selectSection('research')}>Recherche & Quellen</button
|
|
>
|
|
<button
|
|
type="button"
|
|
class:active={activeSection === 'presentation'}
|
|
aria-current={activeSection === 'presentation' ? 'page' : undefined}
|
|
onclick={() => selectSection('presentation')}>Präsentation</button
|
|
>
|
|
</nav>
|
|
<div bind:this={workspace} class="piece-dialog-workspace">{@render children()}</div>
|
|
<footer class="piece-dialog-footer">{@render footer()}</footer>
|
|
</dialog>
|