adds shadcn, removes skeleton, implements button after styleguide
This commit is contained in:
+44
-25
@@ -1,11 +1,16 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte";
|
||||
import Card from "$lib/components/Card.svelte";
|
||||
import ProcessedZipArchiveEditor from "$lib/components/ProcessedZipArchiveEditor.svelte";
|
||||
import ZipDropzone from "$lib/components/ZipDropzone.svelte";
|
||||
import {extractZipArchives, mergeProcessedZipArchive, type ProcessedZipArchive} from "$lib/zip-processing";
|
||||
import {onMount} from 'svelte';
|
||||
import Button from '$lib/components/ui/button.svelte';
|
||||
import ProcessedZipArchiveEditor from '$lib/components/ProcessedZipArchiveEditor.svelte';
|
||||
import ZipDropzone from '$lib/components/ZipDropzone.svelte';
|
||||
import {
|
||||
extractZipArchives,
|
||||
mergeProcessedZipArchive,
|
||||
type ProcessedZipArchive
|
||||
} from '$lib/zip-processing';
|
||||
import * as Card from "$lib/components/ui/card/index";
|
||||
|
||||
const THUMBNAIL_WIDTH_STORAGE_KEY = "thumbnailWidth";
|
||||
const THUMBNAIL_WIDTH_STORAGE_KEY = 'thumbnailWidth';
|
||||
|
||||
let selectedZipFiles: File[] = $state([]);
|
||||
let processedZipFiles: ProcessedZipArchive[] = $state([]);
|
||||
@@ -45,13 +50,13 @@
|
||||
};
|
||||
|
||||
const downloadPdfBytes = (bytes: Uint8Array, fileName: string) => {
|
||||
const pdfBlob = new Blob([toArrayBuffer(bytes)], {type: "application/pdf"});
|
||||
const pdfBlob = new Blob([toArrayBuffer(bytes)], {type: 'application/pdf'});
|
||||
const objectUrl = URL.createObjectURL(pdfBlob);
|
||||
const downloadLink = document.createElement("a");
|
||||
const downloadLink = document.createElement('a');
|
||||
|
||||
downloadLink.href = objectUrl;
|
||||
downloadLink.download = fileName.toLowerCase().endsWith(".pdf") ? fileName : `${fileName}.pdf`;
|
||||
downloadLink.rel = "noopener";
|
||||
downloadLink.download = fileName.toLowerCase().endsWith('.pdf') ? fileName : `${fileName}.pdf`;
|
||||
downloadLink.rel = 'noopener';
|
||||
downloadLink.click();
|
||||
window.setTimeout(() => URL.revokeObjectURL(objectUrl), 1000);
|
||||
};
|
||||
@@ -86,7 +91,7 @@
|
||||
|
||||
const updateProcessedZipFile = (index: number, archive: ProcessedZipArchive) => {
|
||||
processedZipFiles = processedZipFiles.map((existingArchive, existingIndex) =>
|
||||
existingIndex === index ? archive : existingArchive,
|
||||
existingIndex === index ? archive : existingArchive
|
||||
);
|
||||
};
|
||||
|
||||
@@ -111,39 +116,49 @@
|
||||
|
||||
{#snippet content()}
|
||||
{#if selectedZipFiles.length === 0}
|
||||
<ZipDropzone onFilesSelected={handleFilesSelected}/>
|
||||
<Card.Root>
|
||||
<Card.Content>
|
||||
<ZipDropzone onFilesSelected={handleFilesSelected}/>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
{:else}
|
||||
<details class="fixed bottom-4 right-4 z-20">
|
||||
<summary
|
||||
class="flex h-12 w-12 cursor-pointer list-none items-center justify-center rounded-full border border-primary-200 bg-white text-lg font-semibold text-primary-800 shadow-lg transition hover:border-primary-300 hover:bg-primary-50">
|
||||
class="flex h-12 w-12 cursor-pointer list-none items-center justify-center rounded-full border border-primary-200 bg-white text-lg font-semibold text-primary-800 shadow-lg transition hover:border-primary-300 hover:bg-primary-50"
|
||||
>
|
||||
<span class="sr-only">Settings</span>
|
||||
<span>⚙️</span>
|
||||
</summary>
|
||||
|
||||
<div class="absolute bottom-14 right-0 w-72 rounded-xl border border-primary-100 bg-white p-4 shadow-lg">
|
||||
<div
|
||||
class="absolute bottom-14 right-0 w-72 rounded-xl border border-primary-100 bg-white p-4 shadow-lg"
|
||||
>
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex gap-2">
|
||||
<button
|
||||
class="flex-1 rounded-container bg-primary-900 px-3 py-2 text-[13px] font-bold leading-5 text-white shadow-sm transition hover:bg-primary-800 disabled:cursor-not-allowed disabled:bg-primary-300"
|
||||
<Button
|
||||
class="flex-1"
|
||||
type="button"
|
||||
disabled={processedZipFiles.length === 0}
|
||||
onclick={exportAllZipArchivesAsPdf}
|
||||
>
|
||||
Alle ZIP-Archive als PDF exportieren
|
||||
</button>
|
||||
</Button>
|
||||
|
||||
<button
|
||||
class="flex-1 rounded-container bg-red-600 px-3 py-2 text-[13px] font-bold leading-5 text-white shadow-sm transition hover:bg-red-500 disabled:cursor-not-allowed disabled:bg-red-300"
|
||||
<Button
|
||||
class="flex-1"
|
||||
type="button"
|
||||
disabled={selectedZipFiles.length === 0}
|
||||
variant="secondary"
|
||||
onclick={deleteAllZipArchives}
|
||||
>
|
||||
Alle ZIP-Archive löschen
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<label class="flex flex-col gap-2">
|
||||
<div class="flex items-center justify-between gap-3 text-sm font-medium text-primary-900">
|
||||
<div
|
||||
class="flex items-center justify-between gap-3 text-sm font-medium text-primary-900"
|
||||
>
|
||||
<span>Thumbnail Breite</span>
|
||||
<span class="tabular-nums text-primary-700">{thumbnailWidth}px</span>
|
||||
</div>
|
||||
@@ -160,11 +175,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
<div class="flex min-h-[calc(-180px+100vh)] w-full grow flex-col justify-center gap-4 px-4 py-6">
|
||||
<div
|
||||
class="flex min-h-[calc(-180px+100vh)] w-full grow flex-col justify-center gap-4 px-4 py-6"
|
||||
>
|
||||
<div class="mx-auto flex w-full flex-col gap-3">
|
||||
{#if pendingZipCount > 0}
|
||||
<div class="rounded-container bg-primary-50 px-4 py-3 text-[14px] font-medium text-primary-900">
|
||||
Noch {pendingZipCount} ZIP-Datei{pendingZipCount === 1 ? "" : "en"} in Bearbeitung.
|
||||
<div
|
||||
class="rounded-container bg-primary-50 px-4 py-3 text-[14px] font-medium text-primary-900"
|
||||
>
|
||||
Noch {pendingZipCount} ZIP-Datei{pendingZipCount === 1 ? '' : 'en'} in Bearbeitung.
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -188,5 +207,5 @@
|
||||
<div class="flex flex-wrap items-center justify-between gap-3 py-6">
|
||||
<h1 class="h1 text-[20px] font-bold text-primary-900">beA-Edit</h1>
|
||||
</div>
|
||||
<Card {content} class="h-full"/>
|
||||
{@render content()}
|
||||
</section>
|
||||
|
||||
+155
-7
@@ -1,13 +1,161 @@
|
||||
@import 'tailwindcss';
|
||||
@import '../lib/nom-theme.css';
|
||||
/*@import '../globals.css';*/
|
||||
@import "tw-animate-css";
|
||||
@import "shadcn-svelte/tailwind.css";
|
||||
@import "@fontsource-variable/geist";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@plugin '@tailwindcss/forms';
|
||||
@plugin '@tailwindcss/typography';
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nunito';
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
src: url('$lib/assets/Nunito-VariableFont_wght.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face{
|
||||
font-family: 'Nunito';
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
src: url('$lib/assets/Nunito-VariableFont_wght.ttf') format("truetype");
|
||||
}
|
||||
:root {
|
||||
--background: #EEF4F6;
|
||||
--foreground: #122F62;
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: #122f62;
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: #EA544B;
|
||||
--secondary-end: #FF6F6D;
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--accent: #d6dce5;
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: #ff0027;
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
--chart-1: oklch(0.87 0 0);
|
||||
--chart-2: oklch(0.556 0 0);
|
||||
--chart-3: oklch(0.439 0 0);
|
||||
--chart-4: oklch(0.371 0 0);
|
||||
--chart-5: oklch(0.269 0 0);
|
||||
--radius: 16px;
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.708 0 0);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: #212121;
|
||||
--foreground: #FFFFFF;
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: #92b2eb;
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: linear-gradient(90deg, #EA544B 0%, #FF6F6D 100%);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: #ff0027;
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
--chart-1: oklch(0.87 0 0);
|
||||
--chart-2: oklch(0.556 0 0);
|
||||
--chart-3: oklch(0.439 0 0);
|
||||
--chart-4: oklch(0.371 0 0);
|
||||
--chart-5: oklch(0.269 0 0);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.556 0 0);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--font-sans: 'Nunito', sans-serif;
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-ring: var(--ring);
|
||||
--color-input: var(--input);
|
||||
--color-border: var(--border);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-card: var(--card);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-background: var(--background);
|
||||
--radius-sm: calc(var(--radius) * 0.6);
|
||||
--radius-md: calc(var(--radius) * 0.8);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) * 1.4);
|
||||
--radius-2xl: calc(var(--radius) * 1.8);
|
||||
--radius-3xl: calc(var(--radius) * 2.2);
|
||||
--radius-4xl: calc(var(--radius) * 2.6);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
html {
|
||||
@apply font-sans;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ripple */
|
||||
|
||||
@keyframes ripple {
|
||||
from {
|
||||
transform: scale(0);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: scale(4);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-ripple {
|
||||
animation: ripple 600ms ease-out;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user