feat: base implementation of panel preview
This commit is contained in:
@@ -1,25 +0,0 @@
|
||||
<script lang="ts">
|
||||
import Card from "$components/layout/Card.svelte";
|
||||
import Badge from "$components/ui/Badge.svelte";
|
||||
import IconArrowLeft from "$components/ui/Icons/IconArrowLeft.svelte";
|
||||
import IconArrowRight from "$components/ui/Icons/IconArrowRight.svelte";
|
||||
</script>
|
||||
|
||||
{#snippet panelTitle()}
|
||||
Панели <Badge text="0" />
|
||||
{/snippet}
|
||||
|
||||
{#snippet panelControls()}
|
||||
<button id="prevPanel" class="nav-btn" disabled>
|
||||
<IconArrowLeft />
|
||||
</button>
|
||||
<span id="panelIndicator" class="panel-indicator">0 / 0</span>
|
||||
<button id="nextPanel" class="nav-btn" disabled>
|
||||
<IconArrowRight />
|
||||
</button>
|
||||
{/snippet}
|
||||
|
||||
<Card title={panelTitle} titleSnippet={panelControls}>Панели</Card>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
@@ -0,0 +1,17 @@
|
||||
<script lang="ts">
|
||||
import type { SlideDirection } from "$lib/types/utils";
|
||||
import { fly } from "svelte/transition";
|
||||
|
||||
interface Props {
|
||||
text: string;
|
||||
direction: SlideDirection;
|
||||
}
|
||||
|
||||
let { text, direction }: Props = $props();
|
||||
|
||||
let xDirection = $derived(direction == "next" ? 320 : -320);
|
||||
</script>
|
||||
|
||||
<div in:fly={{ x: xDirection, duration: 300 }} out:fly={{ x: -xDirection, duration: 300 }}>
|
||||
{text}
|
||||
</div>
|
||||
@@ -0,0 +1,41 @@
|
||||
<script lang="ts">
|
||||
import Button from "$components/ui/Button.svelte";
|
||||
import IconArrowLeft from "$components/ui/Icons/IconArrowLeft.svelte";
|
||||
import IconArrowRight from "$components/ui/Icons/IconArrowRight.svelte";
|
||||
import type { SlideDirection } from "$lib/types/utils";
|
||||
|
||||
interface Props {
|
||||
current: number;
|
||||
direction: SlideDirection;
|
||||
max: number;
|
||||
}
|
||||
|
||||
let { current = $bindable(), direction = $bindable("next"), max }: Props = $props();
|
||||
|
||||
let isFirst = $derived(current === 0);
|
||||
let isLast = $derived(current === max - 1);
|
||||
|
||||
function prev() {
|
||||
if (current > 0) current--;
|
||||
direction = "prev";
|
||||
}
|
||||
|
||||
function next() {
|
||||
if (current < max - 1) current++;
|
||||
direction = "next";
|
||||
}
|
||||
</script>
|
||||
|
||||
<Button icon={IconArrowLeft} type="mini" onclick={prev} disabled={isFirst} />
|
||||
<span class="panel-indicator">{current + 1} / {max}</span>
|
||||
<Button icon={IconArrowRight} type="mini" onclick={next} disabled={isLast} />
|
||||
|
||||
<style>
|
||||
.panel-indicator {
|
||||
font-size: 13px;
|
||||
color: var(--text-secondary);
|
||||
font-weight: 500;
|
||||
min-width: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,90 @@
|
||||
<script lang="ts">
|
||||
import Card from "$components/layout/Card.svelte";
|
||||
import Badge from "$components/ui/Badge.svelte";
|
||||
import Button from "$components/ui/Button.svelte";
|
||||
import IconDownload from "$components/ui/Icons/IconDownload.svelte";
|
||||
import IconEmpty from "$components/ui/Icons/IconEmpty.svelte";
|
||||
import type { SlideDirection } from "$lib/types/utils";
|
||||
import { textsState } from "$states/texts.svelte";
|
||||
import Preview from "./Preview.svelte";
|
||||
import PreviewControls from "./PreviewControls.svelte";
|
||||
|
||||
let current: number = $state(0);
|
||||
let direction: SlideDirection = $state("next");
|
||||
|
||||
$effect(() => {
|
||||
$inspect(current, textsState.texts);
|
||||
if (current > textsState.texts.length - 1) current = textsState.texts.length - 1;
|
||||
});
|
||||
</script>
|
||||
|
||||
{#snippet panelTitle()}
|
||||
Панели <Badge text={textsState.texts.length} />
|
||||
{/snippet}
|
||||
|
||||
{#snippet panelControls()}
|
||||
<PreviewControls bind:current bind:direction max={textsState.texts.length} />
|
||||
{/snippet}
|
||||
|
||||
<Card title={panelTitle} titleSnippet={panelControls}>
|
||||
<div class="panel-viewer">
|
||||
<div class="panel-display">
|
||||
{#if textsState.texts.length}
|
||||
<!-- {@const text = } -->
|
||||
{#key current}
|
||||
<Preview text={textsState.texts[current].text} {direction} />
|
||||
{/key}
|
||||
{:else}
|
||||
<div class="empty-state">
|
||||
<IconEmpty />
|
||||
<p>Добавьте тексты для создания панелей</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="panel-actions">
|
||||
<Button label="Скачать всё" icon={IconDownload} />
|
||||
<Button label="Скачать" type="outline" icon={IconDownload} />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<style>
|
||||
.panel-viewer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.panel-display {
|
||||
background: var(--bg-secondary);
|
||||
border-radius: var(--radius);
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
.panel-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 32px 16px;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
.empty-state :global(svg) {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
margin: 0 auto 12px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.empty-state p {
|
||||
font-size: 14px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user