mirror of
https://github.com/pheralb/svgl.git
synced 2024-11-13 08:46:56 +08:00
⚙️ Add support for download light & dark svgs.
This commit is contained in:
parent
ffff743283
commit
6a0520e2f8
@ -1,14 +1,20 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { iSVG } from '../types/svg';
|
import type { iSVG } from '../types/svg';
|
||||||
|
|
||||||
import download from 'downloadjs';
|
import download from 'downloadjs';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import { MIMETYPE, getSvgContent } from '../utils/getSvgContent';
|
import jszip from 'jszip';
|
||||||
|
|
||||||
|
// Utils:
|
||||||
|
import { MIMETYPE, getSvgContent } from '@/utils/getSvgContent';
|
||||||
|
import { flyAndScale } from '@/utils/flyAndScale';
|
||||||
|
|
||||||
// Icons:
|
// Icons:
|
||||||
import { CopyIcon, DownloadIcon, LinkIcon } from 'lucide-svelte';
|
import { CopyIcon, DownloadIcon, LinkIcon, PackageIcon, PaintBucket } from 'lucide-svelte';
|
||||||
|
|
||||||
// Main Card:
|
// Main Card:
|
||||||
import CardSpotlight from './cardSpotlight.svelte';
|
import CardSpotlight from './cardSpotlight.svelte';
|
||||||
|
import { DropdownMenu } from 'bits-ui';
|
||||||
|
|
||||||
// Props:
|
// Props:
|
||||||
export let svgInfo: iSVG;
|
export let svgInfo: iSVG;
|
||||||
@ -16,7 +22,33 @@
|
|||||||
// Download SVG:
|
// Download SVG:
|
||||||
const downloadSvg = (url?: string) => {
|
const downloadSvg = (url?: string) => {
|
||||||
download(url || '');
|
download(url || '');
|
||||||
toast.success('Downloading...');
|
toast.success(`Downloading...`, {
|
||||||
|
description: `${svgInfo.title} - ${svgInfo.category}`
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Download all variants:
|
||||||
|
const downloadAllVariants = async ({ route }: iSVG) => {
|
||||||
|
const zip = new jszip();
|
||||||
|
|
||||||
|
if (typeof route === 'string') {
|
||||||
|
downloadSvg(route);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const lightSvg = await getSvgContent(route.light, false);
|
||||||
|
const darkSvg = await getSvgContent(route.dark, false);
|
||||||
|
|
||||||
|
zip.file(`${svgInfo.title}.svg`, lightSvg);
|
||||||
|
zip.file(`${svgInfo.title}.dark.svg`, darkSvg);
|
||||||
|
|
||||||
|
zip.generateAsync({ type: 'blob' }).then((content) => {
|
||||||
|
download(content, `${svgInfo.title}.zip`, 'application/zip');
|
||||||
|
});
|
||||||
|
|
||||||
|
toast.success('Downloading light & dark variants...', {
|
||||||
|
description: `${svgInfo.title} - ${svgInfo.category}`
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Copy SVG to clipboard:
|
// Copy SVG to clipboard:
|
||||||
@ -43,6 +75,7 @@
|
|||||||
|
|
||||||
<CardSpotlight>
|
<CardSpotlight>
|
||||||
<div class="flex flex-col items-center justify-center rounded-md p-4">
|
<div class="flex flex-col items-center justify-center rounded-md p-4">
|
||||||
|
<!-- Image -->
|
||||||
<img
|
<img
|
||||||
class="hidden dark:block mb-4 mt-2 h-10"
|
class="hidden dark:block mb-4 mt-2 h-10"
|
||||||
src={typeof svgInfo.route !== 'string' ? svgInfo.route.dark : svgInfo.route}
|
src={typeof svgInfo.route !== 'string' ? svgInfo.route.dark : svgInfo.route}
|
||||||
@ -57,6 +90,7 @@
|
|||||||
title={svgInfo.title}
|
title={svgInfo.title}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
|
<!-- Title -->
|
||||||
<div class="mb-3 flex flex-col items-center justify-center">
|
<div class="mb-3 flex flex-col items-center justify-center">
|
||||||
<p class="truncate text-[15px] font-medium text-balance text-center select-all">
|
<p class="truncate text-[15px] font-medium text-balance text-center select-all">
|
||||||
{svgInfo.title}
|
{svgInfo.title}
|
||||||
@ -66,6 +100,7 @@
|
|||||||
class="text-sm lowercase text-neutral-500 hover:underline font-mono">{svgInfo.category}</a
|
class="text-sm lowercase text-neutral-500 hover:underline font-mono">{svgInfo.category}</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Actions -->
|
||||||
<div class="flex items-center space-x-1">
|
<div class="flex items-center space-x-1">
|
||||||
<button
|
<button
|
||||||
title="Copy to clipboard"
|
title="Copy to clipboard"
|
||||||
@ -95,8 +130,30 @@
|
|||||||
>
|
>
|
||||||
<CopyIcon size={iconSize} strokeWidth={iconStroke} />
|
<CopyIcon size={iconSize} strokeWidth={iconStroke} />
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
title="Download"
|
{#if typeof svgInfo.route !== 'string'}
|
||||||
|
<DropdownMenu.Root>
|
||||||
|
<DropdownMenu.Trigger
|
||||||
|
class="flex items-center space-x-2 rounded-md p-2 duration-100 hover:bg-neutral-200 dark:hover:bg-neutral-700/40"
|
||||||
|
>
|
||||||
|
<DownloadIcon size={iconSize} strokeWidth={iconStroke} />
|
||||||
|
</DropdownMenu.Trigger>
|
||||||
|
<DropdownMenu.Content
|
||||||
|
class="w-full shadow-md max-w-[229px] rounded-md border border-neutral-100 dark:border-neutral-800 bg-white dark:bg-neutral-900 px-1 py-1.5 shadow-popover"
|
||||||
|
transition={flyAndScale}
|
||||||
|
sideOffset={3}
|
||||||
|
>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
class="flex h-10 select-none items-center rounded-md py-3 pl-3 pr-1.5 text-sm font-medium hover:bg-neutral-100 dark:hover:bg-neutral-700/40"
|
||||||
|
on:click={() => {
|
||||||
|
downloadAllVariants(svgInfo);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PackageIcon class="mr-2" size={18} />
|
||||||
|
<p>Light & Dark variants</p>
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
<DropdownMenu.Item
|
||||||
|
class="flex h-10 select-none items-center rounded-md py-3 pl-3 pr-1.5 text-sm font-medium hover:bg-neutral-100 dark:hover:bg-neutral-700/40"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
const svgHasTheme = typeof svgInfo.route !== 'string';
|
const svgHasTheme = typeof svgInfo.route !== 'string';
|
||||||
|
|
||||||
@ -119,10 +176,23 @@
|
|||||||
: svgInfo.route
|
: svgInfo.route
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
>
|
||||||
|
<PaintBucket class="mr-2" size={18} />
|
||||||
|
Only {document.documentElement.classList.contains('dark') ? 'dark' : 'light'} variant
|
||||||
|
</DropdownMenu.Item>
|
||||||
|
</DropdownMenu.Content>
|
||||||
|
</DropdownMenu.Root>
|
||||||
|
{:else}
|
||||||
|
<button
|
||||||
|
title="Download SVG"
|
||||||
|
on:click={() => {
|
||||||
|
if (typeof svgInfo.route === 'string') downloadSvg(svgInfo.route);
|
||||||
|
}}
|
||||||
class="flex items-center space-x-2 rounded-md p-2 duration-100 hover:bg-neutral-200 dark:hover:bg-neutral-700/40"
|
class="flex items-center space-x-2 rounded-md p-2 duration-100 hover:bg-neutral-200 dark:hover:bg-neutral-700/40"
|
||||||
>
|
>
|
||||||
<DownloadIcon size={iconSize} strokeWidth={iconStroke} />
|
<DownloadIcon size={iconSize} strokeWidth={iconStroke} />
|
||||||
</button>
|
</button>
|
||||||
|
{/if}
|
||||||
<a
|
<a
|
||||||
href={svgInfo.url}
|
href={svgInfo.url}
|
||||||
title="Website"
|
title="Website"
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
let filteredSvgs: iSVG[] = [];
|
let filteredSvgs: iSVG[] = [];
|
||||||
|
|
||||||
// Order by last added:
|
// Order by last added:
|
||||||
|
|
||||||
if (searchTerm.length === 0) {
|
if (searchTerm.length === 0) {
|
||||||
filteredSvgs = allSvgs.sort((a: iSVG, b: iSVG) => {
|
filteredSvgs = allSvgs.sort((a: iSVG, b: iSVG) => {
|
||||||
return b.id! - a.id!;
|
return b.id! - a.id!;
|
||||||
|
Loading…
Reference in New Issue
Block a user