mirror of
https://github.com/pheralb/svgl.git
synced 2025-12-29 08:01:36 +08:00
✨ Initial shadcn/ui integration + improve copySvg component + move addToFavorite
This commit is contained in:
@@ -0,0 +1,40 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import * as Select from "@/components/ui/select";
|
||||||
|
import { pkgManager, type PackageManager } from "@/stores/pkgManager.store";
|
||||||
|
|
||||||
|
import Npm from "@/components/logos/npm.svelte";
|
||||||
|
import Pnpm from "@/components/logos/pnpm.svelte";
|
||||||
|
import Yarn from "@/components/logos/yarn.svelte";
|
||||||
|
import Bun from "@/components/logos/bun.svelte";
|
||||||
|
import { buttonVariants } from "./ui/button";
|
||||||
|
|
||||||
|
let pkg = $derived($pkgManager);
|
||||||
|
|
||||||
|
const managers = {
|
||||||
|
npm: { label: "npm", Icon: Npm },
|
||||||
|
pnpm: { label: "pnpm", Icon: Pnpm },
|
||||||
|
yarn: { label: "yarn", Icon: Yarn },
|
||||||
|
bun: { label: "bun", Icon: Bun },
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Select.Root type="single" bind:value={pkg}>
|
||||||
|
<Select.Trigger class={buttonVariants({ variant: "outline", size: "sm" })}>
|
||||||
|
{#if managers[pkg]}
|
||||||
|
{@const { Icon, label } = managers[pkg]}
|
||||||
|
<Icon size={14} />
|
||||||
|
<span>{label}</span>
|
||||||
|
{/if}
|
||||||
|
</Select.Trigger>
|
||||||
|
<Select.Content sideOffset={1.5}>
|
||||||
|
{#each Object.entries(managers) as [value, { Icon, label }]}
|
||||||
|
<Select.Item
|
||||||
|
{value}
|
||||||
|
onclick={() => pkgManager.set(value as PackageManager)}
|
||||||
|
>
|
||||||
|
<Icon size={16} />
|
||||||
|
<span>{label}</span>
|
||||||
|
</Select.Item>
|
||||||
|
{/each}
|
||||||
|
</Select.Content>
|
||||||
|
</Select.Root>
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { iSVG } from "@/types/svg";
|
import type { iSVG } from "@/types/svg";
|
||||||
|
|
||||||
|
import { cn } from "@/utils/cn";
|
||||||
import favoritesStore from "@/stores/favorites.store";
|
import favoritesStore from "@/stores/favorites.store";
|
||||||
import HeartIcon from "@lucide/svelte/icons/heart";
|
import HeartIcon from "@lucide/svelte/icons/heart";
|
||||||
import { cn } from "@/utils/cn";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
svg: iSVG;
|
svg: iSVG;
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { clipboard } from "@/utils/clipboard";
|
||||||
|
|
||||||
|
import CopyIcon from "@lucide/svelte/icons/copy";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import SelectPkgManager from "@/components/selectPkgManager.svelte";
|
||||||
|
import { pkgManager, type PackageManager } from "@/stores/pkgManager.store";
|
||||||
|
import Shadcn from "../logos/shadcn.svelte";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
svgTitle: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { svgTitle }: Props = $props();
|
||||||
|
|
||||||
|
const shadcnCommands: Record<PackageManager, string> = {
|
||||||
|
npm: "npx shadcn@latest add",
|
||||||
|
pnpm: "pnpm dlx shadcn@latest add",
|
||||||
|
yarn: "yarn dlx shadcn@latest add",
|
||||||
|
bun: "bunx shadcn@latest add",
|
||||||
|
};
|
||||||
|
|
||||||
|
let pkg = $derived($pkgManager);
|
||||||
|
let shadcnCommand = $derived(shadcnCommands[pkg]);
|
||||||
|
const svgFormatTitle = svgTitle
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\s+/g, "-")
|
||||||
|
.replace(/[^a-z0-9-]/g, "");
|
||||||
|
|
||||||
|
const handleCopy = () => {
|
||||||
|
clipboard(`${shadcnCommand} @svgl/${svgFormatTitle}`);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-between space-x-2">
|
||||||
|
<SelectPkgManager />
|
||||||
|
<Button variant="outline" onclick={handleCopy} size="sm">
|
||||||
|
<CopyIcon size={14} />
|
||||||
|
<span>Copy</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex items-center space-x-2 rounded-md border border-neutral-200 p-2.5 dark:border-neutral-800"
|
||||||
|
>
|
||||||
|
<Shadcn size={14} />
|
||||||
|
<code class="font-mono text-sm select-all">
|
||||||
|
{shadcnCommand} @svgl/{svgFormatTitle}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
import type { iSVG } from "@/types/svg";
|
import type { iSVG } from "@/types/svg";
|
||||||
|
|
||||||
// Utils:
|
// Utils:
|
||||||
|
import { cn } from "@/utils/cn";
|
||||||
import { clipboard } from "@/utils/clipboard";
|
import { clipboard } from "@/utils/clipboard";
|
||||||
import { getPrefixFromSvgUrl, prefixSvgIds } from "@/utils/prefixSvgIds";
|
import { getPrefixFromSvgUrl, prefixSvgIds } from "@/utils/prefixSvgIds";
|
||||||
import { copyToClipboard as figmaCopyToClipboard } from "@/figma/copy-to-clipboard";
|
import { copyToClipboard as figmaCopyToClipboard } from "@/figma/copy-to-clipboard";
|
||||||
@@ -15,9 +16,12 @@
|
|||||||
// UI Components:
|
// UI Components:
|
||||||
import { toast } from "svelte-sonner";
|
import { toast } from "svelte-sonner";
|
||||||
import * as Tabs from "@/components/ui/tabs";
|
import * as Tabs from "@/components/ui/tabs";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button, buttonVariants } from "@/components/ui/button";
|
||||||
import * as Popover from "@/components/ui/popover";
|
import * as Popover from "@/components/ui/popover";
|
||||||
|
|
||||||
|
// CLIs:
|
||||||
|
import CopyShadcnCommand from "@/components/svgs/copyShadcnCommand.svelte";
|
||||||
|
|
||||||
// Templates:
|
// Templates:
|
||||||
import { getSource } from "@/templates/getSource";
|
import { getSource } from "@/templates/getSource";
|
||||||
import { getVueCode } from "@/templates/getVueCode";
|
import { getVueCode } from "@/templates/getVueCode";
|
||||||
@@ -360,7 +364,13 @@
|
|||||||
<Popover.Root bind:open={optionsOpen}>
|
<Popover.Root bind:open={optionsOpen}>
|
||||||
<Popover.Trigger
|
<Popover.Trigger
|
||||||
title="Copy SVG element as svg file, React TSX code, or React JSX code"
|
title="Copy SVG element as svg file, React TSX code, or React JSX code"
|
||||||
class="flex items-center space-x-2 rounded-md p-2 duration-100 hover:bg-neutral-200 dark:hover:bg-neutral-700/40"
|
class={cn(
|
||||||
|
buttonVariants({
|
||||||
|
variant: "ghost",
|
||||||
|
size: "icon",
|
||||||
|
class: "hover:bg-neutral-200",
|
||||||
|
}),
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{#if optionsOpen}
|
{#if optionsOpen}
|
||||||
<XIcon {size} strokeWidth={iconStroke} />
|
<XIcon {size} strokeWidth={iconStroke} />
|
||||||
@@ -370,32 +380,37 @@
|
|||||||
<CopyIcon {size} strokeWidth={iconStroke} />
|
<CopyIcon {size} strokeWidth={iconStroke} />
|
||||||
{/if}
|
{/if}
|
||||||
</Popover.Trigger>
|
</Popover.Trigger>
|
||||||
<Popover.Content class="flex flex-col space-y-2 p-4" sideOffset={2}>
|
<Popover.Content class="flex w-fit flex-col space-y-2 p-4" sideOffset={2}>
|
||||||
<Tabs.Root value="source" class="flex w-full flex-col space-y-1">
|
<Tabs.Root value="source" class="flex w-full flex-col space-y-1">
|
||||||
<Tabs.List>
|
<Tabs.List class="w-fit border-none bg-transparent">
|
||||||
<Tabs.Trigger value="source">Source</Tabs.Trigger>
|
<Tabs.Trigger value="source">Source</Tabs.Trigger>
|
||||||
|
<Tabs.Trigger value="shadcn">shadcn/ui</Tabs.Trigger>
|
||||||
<div
|
<div
|
||||||
class="ml-3 flex flex-row space-x-0.5 border-l border-dashed border-neutral-200 pl-3 dark:border-neutral-800"
|
class="ml-3 flex flex-row space-x-1 border-l border-neutral-200 pl-3 dark:border-neutral-800"
|
||||||
>
|
>
|
||||||
<Tabs.Trigger value="web-component" title="Web Component">
|
<Tabs.Trigger
|
||||||
|
class="px-2.5"
|
||||||
|
value="web-component"
|
||||||
|
title="Web Component"
|
||||||
|
>
|
||||||
<WebComponents size={21} />
|
<WebComponents size={21} />
|
||||||
</Tabs.Trigger>
|
</Tabs.Trigger>
|
||||||
<Tabs.Trigger value="react" title="React">
|
<Tabs.Trigger class="px-2.5" value="react" title="React">
|
||||||
<React size={20} />
|
<React size={20} />
|
||||||
</Tabs.Trigger>
|
</Tabs.Trigger>
|
||||||
<Tabs.Trigger value="vue" title="Vue">
|
<Tabs.Trigger class="px-2.5" value="vue" title="Vue">
|
||||||
<Vue size={20} />
|
<Vue size={20} />
|
||||||
</Tabs.Trigger>
|
</Tabs.Trigger>
|
||||||
<Tabs.Trigger value="svelte" title="Svelte">
|
<Tabs.Trigger class="px-2.5" value="svelte" title="Svelte">
|
||||||
<Svelte size={20} />
|
<Svelte size={20} />
|
||||||
</Tabs.Trigger>
|
</Tabs.Trigger>
|
||||||
<Tabs.Trigger value="angular" title="Angular">
|
<Tabs.Trigger class="px-2.5" value="angular" title="Angular">
|
||||||
<Angular size={20} />
|
<Angular size={20} />
|
||||||
</Tabs.Trigger>
|
</Tabs.Trigger>
|
||||||
<Tabs.Trigger
|
<Tabs.Trigger
|
||||||
value="astro"
|
value="astro"
|
||||||
title="Astro"
|
title="Astro"
|
||||||
class="text-black dark:text-white"
|
class="px-2.5 text-black dark:text-white"
|
||||||
>
|
>
|
||||||
<Astro size={21} />
|
<Astro size={21} />
|
||||||
</Tabs.Trigger>
|
</Tabs.Trigger>
|
||||||
@@ -406,6 +421,7 @@
|
|||||||
<section class="flex flex-col space-y-2">
|
<section class="flex flex-col space-y-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
class="justify-start"
|
||||||
title={isWordmarkSvg
|
title={isWordmarkSvg
|
||||||
? "Copy wordmark SVG to clipboard"
|
? "Copy wordmark SVG to clipboard"
|
||||||
: "Copy SVG to clipboard"}
|
: "Copy SVG to clipboard"}
|
||||||
@@ -416,11 +432,18 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</section>
|
</section>
|
||||||
</Tabs.Content>
|
</Tabs.Content>
|
||||||
|
<!-- CLI -->
|
||||||
|
<Tabs.Content value="shadcn">
|
||||||
|
<section class="flex flex-col space-y-2">
|
||||||
|
<CopyShadcnCommand svgTitle={svgInfo.title} />
|
||||||
|
</section>
|
||||||
|
</Tabs.Content>
|
||||||
<!-- React -->
|
<!-- React -->
|
||||||
<Tabs.Content value="react">
|
<Tabs.Content value="react">
|
||||||
<section class="flex flex-col space-y-2">
|
<section class="flex flex-col space-y-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
class="justify-start"
|
||||||
title="Copy as React component"
|
title="Copy as React component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => convertSvgReactComponent(true)}
|
onclick={() => convertSvgReactComponent(true)}
|
||||||
@@ -430,6 +453,7 @@
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
class="justify-start"
|
||||||
title="Copy as React component"
|
title="Copy as React component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => convertSvgReactComponent(false)}
|
onclick={() => convertSvgReactComponent(false)}
|
||||||
@@ -444,6 +468,7 @@
|
|||||||
<section class="flex flex-col space-y-2">
|
<section class="flex flex-col space-y-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
class="justify-start"
|
||||||
title="Copy as Svelte component"
|
title="Copy as Svelte component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => convertSvgSvelteComponent(false)}
|
onclick={() => convertSvgSvelteComponent(false)}
|
||||||
@@ -454,6 +479,7 @@
|
|||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
class="justify-start"
|
||||||
title="Copy as Svelte component"
|
title="Copy as Svelte component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => convertSvgSvelteComponent(false)}
|
onclick={() => convertSvgSvelteComponent(false)}
|
||||||
@@ -464,6 +490,7 @@
|
|||||||
|
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
class="justify-start"
|
||||||
title="Copy as Svelte component"
|
title="Copy as Svelte component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => convertSvgSvelteComponent(true)}
|
onclick={() => convertSvgSvelteComponent(true)}
|
||||||
@@ -478,6 +505,7 @@
|
|||||||
<section class="flex flex-col space-y-2">
|
<section class="flex flex-col space-y-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
class="justify-start"
|
||||||
title="Copy as Vue component"
|
title="Copy as Vue component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => convertSvgVueComponent(false)}
|
onclick={() => convertSvgVueComponent(false)}
|
||||||
@@ -487,6 +515,7 @@
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
class="justify-start"
|
||||||
title="Copy as Vue component"
|
title="Copy as Vue component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => convertSvgVueComponent(true)}
|
onclick={() => convertSvgVueComponent(true)}
|
||||||
@@ -501,6 +530,7 @@
|
|||||||
<section class="flex flex-col space-y-2">
|
<section class="flex flex-col space-y-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
class="justify-start"
|
||||||
title="Copy as Standalone Component"
|
title="Copy as Standalone Component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => convertSvgAngularComponent()}
|
onclick={() => convertSvgAngularComponent()}
|
||||||
@@ -515,6 +545,7 @@
|
|||||||
<section class="flex flex-col space-y-2">
|
<section class="flex flex-col space-y-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
class="justify-start"
|
||||||
title="Copy as Web Component"
|
title="Copy as Web Component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => convertSvgWebComponent()}
|
onclick={() => convertSvgWebComponent()}
|
||||||
@@ -529,6 +560,7 @@
|
|||||||
<section class="flex flex-col space-y-2">
|
<section class="flex flex-col space-y-2">
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
class="justify-start"
|
||||||
title="Copy as Astro Component"
|
title="Copy as Astro Component"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
onclick={() => convertSvgAstroComponent()}
|
onclick={() => convertSvgAstroComponent()}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
// Components:
|
// Components:
|
||||||
import CopySvg from "@/components/svgs/copySvg.svelte";
|
import CopySvg from "@/components/svgs/copySvg.svelte";
|
||||||
import DownloadSvg from "@/components/svgs/downloadSvg.svelte";
|
import DownloadSvg from "@/components/svgs/downloadSvg.svelte";
|
||||||
import AddToFavorite from "@/components/addToFavorite.svelte";
|
import AddToFavorite from "@/components/svgs/addToFavorite.svelte";
|
||||||
|
|
||||||
// Props:
|
// Props:
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
Reference in New Issue
Block a user