86 lines
2.6 KiB
Svelte
86 lines
2.6 KiB
Svelte
<!--
|
|
- This file is a part of the SteamWar software.
|
|
-
|
|
- Copyright (C) 2024 SteamWar.de-Serverteam
|
|
-
|
|
- This program is free software: you can redistribute it and/or modify
|
|
- it under the terms of the GNU Affero General Public License as published by
|
|
- the Free Software Foundation, either version 3 of the License, or
|
|
- (at your option) any later version.
|
|
-
|
|
- This program is distributed in the hope that it will be useful,
|
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- GNU Affero General Public License for more details.
|
|
-
|
|
- You should have received a copy of the GNU Affero General Public License
|
|
- along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
-->
|
|
|
|
<script lang="ts">
|
|
import {onMount} from "svelte";
|
|
import {stopPropagation} from "@components/utils.ts";
|
|
|
|
interface Props {
|
|
title: string;
|
|
open: boolean;
|
|
children?: import('svelte').Snippet;
|
|
footer?: import('svelte').Snippet;
|
|
onclose?: () => void;
|
|
onclick?: () => void;
|
|
|
|
}
|
|
|
|
let {
|
|
title,
|
|
open = $bindable(),
|
|
children,
|
|
footer,
|
|
onclose = () => {},
|
|
onclick = () => {}
|
|
}: Props = $props();
|
|
let internalOpen = $state(open);
|
|
|
|
|
|
let dialog: HTMLDialogElement = $state();
|
|
|
|
onMount(() => {
|
|
if (open) {
|
|
dialog.showModal();
|
|
internalOpen = true;
|
|
}
|
|
});
|
|
|
|
function close() {
|
|
open = false;
|
|
internalOpen = false;
|
|
onclose()
|
|
}
|
|
|
|
$effect(() => {
|
|
if (open && !internalOpen) {
|
|
dialog.showModal();
|
|
internalOpen = true;
|
|
} else if (!open && internalOpen) {
|
|
dialog.close();
|
|
internalOpen = false;
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<dialog bind:this={dialog} onclose={close} onclick={(e) => dialog.close()} aria-hidden="true" class="max-h-full min-w-md w-fit rounded-lg shadow-lg dark:bg-neutral-800 dark:text-neutral-100">
|
|
<div onclick={stopPropagation(onclick)} aria-hidden="true" class="w-fit">
|
|
<div class="p-6 border-b border-neutral-200 dark:border-neutral-700">
|
|
<h1 class="text-4xl font-bold">{title}</h1>
|
|
</div>
|
|
<div class="p-6 main border-b border-neutral-200 dark:border-neutral-700">
|
|
{@render children?.()}
|
|
</div>
|
|
<div class="mx-4 my-2 p-6">
|
|
<div class="ml-auto flex justify-end" onclick={() => dialog.close()} aria-hidden="true">
|
|
{@render footer?.()}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</dialog>
|