Add settings management with package manager and SVG optimization options

This commit is contained in:
pheralb
2025-09-21 19:15:11 +01:00
parent 0c78255847
commit 3e507cf7c8
10 changed files with 227 additions and 44 deletions
+2
View File
@@ -13,6 +13,7 @@
import SvglVersion from "@/components/svglVersion.svelte";
import SendIcon from "@/components/ui/moving-icons/send-icon.svelte";
import SidebarMobileMenu from "@/components/layout/sidebarMobileMenu.svelte";
import SettingsMenu from "../settings/settingsMenu.svelte";
interface HeaderProps {
githubStars?: number;
@@ -55,6 +56,7 @@
"hover:bg-neutral-200 dark:hover:bg-neutral-800",
)}
/>
<SettingsMenu />
</div>
<div class="hidden h-5 items-center space-x-2 md:flex">
<Separator orientation="vertical" />
@@ -0,0 +1,19 @@
<script lang="ts">
import { Switch } from "@/components/ui/switch";
import { settingsStore } from "@/stores/settings.store";
let optimize = $derived($settingsStore.optimizeSvgs);
const handleOptimizeChange = (checked: boolean) => {
settingsStore.setOptimizeSvgs(checked);
};
</script>
<div class="flex items-center gap-3">
<Switch
id="optimize"
checked={optimize}
onCheckedChange={handleOptimizeChange}
/>
<label for="optimize">Optimize SVGs</label>
</div>
@@ -1,16 +1,18 @@
<script lang="ts">
import type { Component } from "svelte";
import * as Select from "@/components/ui/select";
import { pkgManager, type PackageManager } from "@/stores/pkgManager.store";
import { buttonVariants } from "@/components/ui/button";
import { settingsStore, type PackageManager } from "@/stores/settings.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);
let pkg = $derived($settingsStore.packageManager);
const managers = {
const managers: Record<PackageManager, { label: string; Icon: Component }> = {
npm: { label: "npm", Icon: Npm },
pnpm: { label: "pnpm", Icon: Pnpm },
yarn: { label: "yarn", Icon: Yarn },
@@ -19,18 +21,22 @@
</script>
<Select.Root type="single" bind:value={pkg}>
<Select.Trigger class={buttonVariants({ variant: "outline", size: "sm" })}>
<Select.Trigger
class={buttonVariants({ variant: "outline", class: "justify-between" })}
>
{#if managers[pkg]}
{@const { Icon, label } = managers[pkg]}
<Icon size={14} />
<span>{label}</span>
<div class="flex items-center space-x-2.5">
<Icon size={16} />
<span>{label}</span>
</div>
{/if}
</Select.Trigger>
<Select.Content sideOffset={1.5}>
{#each Object.entries(managers) as [value, { Icon, label }] (value)}
<Select.Item
{value}
onclick={() => pkgManager.set(value as PackageManager)}
onclick={() => settingsStore.setPackageManager(value as PackageManager)}
>
<Icon size={16} />
<span>{label}</span>
@@ -0,0 +1,19 @@
<script lang="ts">
import type { Snippet } from "svelte";
interface SettingsCardProps {
title: string;
description: string;
children: Snippet;
}
let { title, description, children }: SettingsCardProps = $props();
</script>
<div class="flex flex-col">
<h3 class="mb-0.5 font-medium">{title}</h3>
<p class="mb-3 text-sm text-neutral-600 dark:text-neutral-400">
{description}
</p>
{@render children?.()}
</div>
@@ -0,0 +1,60 @@
<script lang="ts">
import { cn } from "@/utils/cn";
import { toast } from "svelte-sonner";
import { settingsStore } from "@/stores/settings.store";
import SettingsCard from "@/components/settings/settingsCard.svelte";
import SettingsIcon from "@lucide/svelte/icons/settings";
import * as Dialog from "@/components/ui/dialog";
import { Button, buttonVariants } from "@/components/ui/button";
import Separator from "@/components/ui/separator/separator.svelte";
import OptimizeSvgs from "@/components/settings/options/optimizeSvgs.svelte";
import SelectPkgManager from "@/components/settings/options/selectPkgManager.svelte";
const handleResetSettings = () => {
settingsStore.reset();
toast.success("Settings have been reset to default");
};
</script>
<Dialog.Root>
<Dialog.Trigger
class={cn(
buttonVariants({ variant: "ghost", size: "icon" }),
"hover:bg-neutral-200 dark:hover:bg-neutral-800",
)}
>
<SettingsIcon size={20} strokeWidth={1.5} />
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Settings</Dialog.Title>
<Dialog.Description>Customize your preferences.</Dialog.Description>
</Dialog.Header>
<Separator />
<div class="my-3 flex flex-col space-y-8">
<SettingsCard
title="Package Manager"
description="Select your preferred package manager for all installations commands"
>
<SelectPkgManager />
</SettingsCard>
<SettingsCard
title="Copy SVGs"
description="Use SVGO to optimize your SVGs when you copy source code (including all frameworks)"
>
<OptimizeSvgs />
</SettingsCard>
</div>
<Dialog.Footer>
<Button variant="outline" onclick={handleResetSettings}>
<span>Reset</span>
</Button>
<Dialog.Close class={buttonVariants({ variant: "default" })}>
<span>Save</span>
</Dialog.Close>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>
+2 -4
View File
@@ -1,9 +1,8 @@
<script lang="ts">
import { buttonVariants } from "@/components/ui/button";
import Shadcn from "@/components/logos/shadcn.svelte";
import SelectPkgManager from "@/components/selectPkgManager.svelte";
import { pkgManager, type PackageManager } from "@/stores/pkgManager.store";
import { settingsStore, type PackageManager } from "@/stores/settings.store";
import CodeBlock from "@/components/codeBlock.svelte";
import ArrowUpRightIcon from "@lucide/svelte/icons/arrow-up-right";
@@ -20,7 +19,7 @@
bun: "bunx shadcn@latest add",
};
let pkg = $derived($pkgManager);
let pkg = $derived($settingsStore.packageManager);
let shadcnCommand = $derived(shadcnCommands[pkg]);
const svgFormatTitle = svgTitle
.toLowerCase()
@@ -40,6 +39,5 @@
class="text-neutral-500 dark:text-neutral-400"
/>
</a>
<SelectPkgManager />
</div>
<CodeBlock code={`${shadcnCommand} @svgl/${svgFormatTitle}`} Icon={Shadcn} />
+9
View File
@@ -6,6 +6,7 @@
import { clipboard } from "@/utils/clipboard";
import { getPrefixFromSvgUrl, prefixSvgIds } from "@/utils/prefixSvgIds";
import { copyToClipboard as figmaCopyToClipboard } from "@/figma/copy-to-clipboard";
import { settingsStore } from "@/stores/settings.store";
// Icons:
import XIcon from "@lucide/svelte/icons/x";
@@ -59,6 +60,7 @@
// States:
let optionsOpen = $state<boolean>(false);
let isLoading = $state<boolean>(false);
let optimize = $derived($settingsStore.optimizeSvgs);
const getSvgUrl = () => {
let svgUrlToCopy;
@@ -105,6 +107,7 @@
let content = await getSource({
url: svgUrlToCopy,
optimize,
});
if (svgUrlToCopy) {
@@ -150,6 +153,7 @@
const title = svgInfo.title.split(" ").join("");
let content = await getSource({
url: svgUrlToCopy,
optimize,
});
if (svgUrlToCopy) {
@@ -186,6 +190,7 @@
let content = await getSource({
url: svgUrlToCopy,
optimize,
});
if (svgUrlToCopy) {
@@ -223,6 +228,7 @@
let content = await getSource({
url: svgUrlToCopy,
optimize,
});
if (svgUrlToCopy) {
@@ -260,6 +266,7 @@
const svgUrlToCopy = getSvgUrl();
let content = await getSource({
url: svgUrlToCopy,
optimize,
});
if (svgUrlToCopy) {
@@ -297,6 +304,7 @@
const svgUrlToCopy = getSvgUrl();
let content = await getSource({
url: svgUrlToCopy,
optimize,
});
if (svgUrlToCopy) {
@@ -333,6 +341,7 @@
const svgUrlToCopy = getSvgUrl();
let content = await getSource({
url: svgUrlToCopy,
optimize,
});
if (svgUrlToCopy) {