svforge 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +7 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11,12 +11,13 @@ const baseFiles = {
11
11
  "/lib/styles/index.css": "@import './tokens.css';\n@import './svelteforge-theme.css';\n",
12
12
  "/lib/styles/svelteforge-theme.css": "/* === SvelteForge Theme === */\n[data-theme='svelteForge'] {\n --text-scaling: 1.067;\n --base-font-color: var(--color-surface-950);\n --base-font-color-dark: var(--color-surface-50);\n --base-font-family: 'Inter Variable', sans-serif;\n --heading-font-family: 'Space Grotesk Variable', sans-serif;\n --heading-font-weight: bold;\n --anchor-font-color: var(--color-primary-700);\n --anchor-font-color-dark: var(--color-primary-200);\n --anchor-text-decoration: none;\n --anchor-text-decoration-hover: underline;\n --body-background-color: var(--color-surface-50);\n --body-background-color-dark: var(--color-surface-950);\n --spacing: 0.25rem;\n --radius-base: 0.375rem;\n --radius-container: 0.75rem;\n\n /* Primary: Steel blue */\n --color-primary-50: oklch(94.82% 0.04 216.84deg);\n --color-primary-100: oklch(88.84% 0.07 215.45deg);\n --color-primary-200: oklch(83.12% 0.09 215.47deg);\n --color-primary-300: oklch(78.03% 0.11 216.31deg);\n --color-primary-400: oklch(73.14% 0.12 218.53deg);\n --color-primary-500: oklch(68.74% 0.13 222.38deg);\n --color-primary-600: oklch(63.96% 0.12 222.67deg);\n --color-primary-700: oklch(59.05% 0.11 222.32deg);\n --color-primary-800: oklch(53.82% 0.1 223.63deg);\n --color-primary-900: oklch(48.67% 0.09 223.32deg);\n --color-primary-950: oklch(43.44% 0.08 223.92deg);\n --color-primary-contrast-dark: oklch(20.02% 0 none);\n --color-primary-contrast-light: oklch(97.91% 0 none);\n --color-primary-contrast-50: var(--color-primary-contrast-dark);\n --color-primary-contrast-100: var(--color-primary-contrast-dark);\n --color-primary-contrast-200: var(--color-primary-contrast-dark);\n --color-primary-contrast-300: var(--color-primary-contrast-dark);\n --color-primary-contrast-400: var(--color-primary-contrast-dark);\n --color-primary-contrast-500: var(--color-primary-contrast-dark);\n --color-primary-contrast-600: var(--color-primary-contrast-dark);\n --color-primary-contrast-700: var(--color-primary-contrast-dark);\n --color-primary-contrast-800: var(--color-primary-contrast-light);\n --color-primary-contrast-900: var(--color-primary-contrast-light);\n --color-primary-contrast-950: var(--color-primary-contrast-light);\n\n /* Secondary: Burnt orange */\n --color-secondary-50: oklch(93.05% 0.05 71.66deg);\n --color-secondary-100: oklch(86.31% 0.07 50.93deg);\n --color-secondary-200: oklch(79.78% 0.1 39.88deg);\n --color-secondary-300: oklch(73.56% 0.12 32.86deg);\n --color-secondary-400: oklch(67.93% 0.14 30.33deg);\n --color-secondary-500: oklch(63.07% 0.17 29.44deg);\n --color-secondary-600: oklch(58.47% 0.15 27.5deg);\n --color-secondary-700: oklch(53.83% 0.13 24.55deg);\n --color-secondary-800: oklch(49.31% 0.11 20.41deg);\n --color-secondary-900: oklch(44.67% 0.09 12.99deg);\n --color-secondary-950: oklch(40.1% 0.07 0.14deg);\n --color-secondary-contrast-dark: oklch(97.91% 0 none);\n --color-secondary-contrast-light: oklch(20.02% 0 none);\n --color-secondary-contrast-50: var(--color-secondary-contrast-light);\n --color-secondary-contrast-100: var(--color-secondary-contrast-light);\n --color-secondary-contrast-200: var(--color-secondary-contrast-light);\n --color-secondary-contrast-300: var(--color-secondary-contrast-light);\n --color-secondary-contrast-400: var(--color-secondary-contrast-light);\n --color-secondary-contrast-500: var(--color-secondary-contrast-light);\n --color-secondary-contrast-600: var(--color-secondary-contrast-dark);\n --color-secondary-contrast-700: var(--color-secondary-contrast-dark);\n --color-secondary-contrast-800: var(--color-secondary-contrast-dark);\n --color-secondary-contrast-900: var(--color-secondary-contrast-dark);\n --color-secondary-contrast-950: var(--color-secondary-contrast-dark);\n\n /* Tertiary: Soft teal */\n --color-tertiary-50: oklch(98.31% 0.02 196.74deg);\n --color-tertiary-100: oklch(90.4% 0.03 193.59deg);\n --color-tertiary-200: oklch(82.32% 0.03 191.41deg);\n --color-tertiary-300: oklch(74.29% 0.04 187.78deg);\n --color-tertiary-400: oklch(65.86% 0.04 186.58deg);\n --color-tertiary-500: oklch(57.22% 0.05 185.36deg);\n --color-tertiary-600: oklch(52.72% 0.05 190.1deg);\n --color-tertiary-700: oklch(48.14% 0.04 195.76deg);\n --color-tertiary-800: oklch(43.13% 0.04 204.75deg);\n --color-tertiary-900: oklch(38.31% 0.04 212.77deg);\n --color-tertiary-950: oklch(33.36% 0.04 221.8deg);\n --color-tertiary-contrast-dark: var(--color-tertiary-950);\n --color-tertiary-contrast-light: var(--color-tertiary-50);\n --color-tertiary-contrast-50: var(--color-tertiary-contrast-dark);\n --color-tertiary-contrast-100: var(--color-tertiary-contrast-dark);\n --color-tertiary-contrast-200: var(--color-tertiary-contrast-dark);\n --color-tertiary-contrast-300: var(--color-tertiary-contrast-dark);\n --color-tertiary-contrast-400: var(--color-tertiary-contrast-dark);\n --color-tertiary-contrast-500: var(--color-tertiary-contrast-light);\n --color-tertiary-contrast-600: var(--color-tertiary-contrast-light);\n --color-tertiary-contrast-700: var(--color-tertiary-contrast-light);\n --color-tertiary-contrast-800: var(--color-tertiary-contrast-light);\n --color-tertiary-contrast-900: var(--color-tertiary-contrast-light);\n --color-tertiary-contrast-950: var(--color-tertiary-contrast-light);\n\n /* Success */\n --color-success-50: oklch(93.9% 0.09 179.09deg);\n --color-success-100: oklch(91.57% 0.1 178.72deg);\n --color-success-200: oklch(89.48% 0.11 177.05deg);\n --color-success-300: oklch(87.2% 0.12 176.72deg);\n --color-success-400: oklch(85.21% 0.12 175.14deg);\n --color-success-500: oklch(83.08% 0.13 174.56deg);\n --color-success-600: oklch(72.99% 0.11 174.61deg);\n --color-success-700: oklch(62.32% 0.1 176.14deg);\n --color-success-800: oklch(51.37% 0.08 176.77deg);\n --color-success-900: oklch(39.58% 0.06 180.47deg);\n --color-success-950: oklch(27.1% 0.04 184.49deg);\n --color-success-contrast-dark: var(--color-success-950);\n --color-success-contrast-light: var(--color-success-50);\n --color-success-contrast-50: var(--color-success-contrast-dark);\n --color-success-contrast-100: var(--color-success-contrast-dark);\n --color-success-contrast-200: var(--color-success-contrast-dark);\n --color-success-contrast-300: var(--color-success-contrast-dark);\n --color-success-contrast-400: var(--color-success-contrast-dark);\n --color-success-contrast-500: var(--color-success-contrast-dark);\n --color-success-contrast-600: var(--color-success-contrast-dark);\n --color-success-contrast-700: var(--color-success-contrast-dark);\n --color-success-contrast-800: var(--color-success-contrast-light);\n --color-success-contrast-900: var(--color-success-contrast-light);\n --color-success-contrast-950: var(--color-success-contrast-light);\n\n /* Warning */\n --color-warning-50: oklch(95.79% 0.05 88.07deg);\n --color-warning-100: oklch(92.94% 0.07 85.27deg);\n --color-warning-200: oklch(90.05% 0.09 81.8deg);\n --color-warning-300: oklch(87.31% 0.11 80.89deg);\n --color-warning-400: oklch(84.57% 0.13 78.29deg);\n --color-warning-500: oklch(82.02% 0.14 76.71deg);\n --color-warning-600: oklch(76.11% 0.14 72.37deg);\n --color-warning-700: oklch(70.14% 0.13 67.8deg);\n --color-warning-800: oklch(64% 0.13 62.98deg);\n --color-warning-900: oklch(57.93% 0.13 57.46deg);\n --color-warning-950: oklch(51.87% 0.13 51.28deg);\n --color-warning-contrast-dark: var(--color-warning-950);\n --color-warning-contrast-light: var(--color-warning-50);\n --color-warning-contrast-50: var(--color-warning-contrast-dark);\n --color-warning-contrast-100: var(--color-warning-contrast-dark);\n --color-warning-contrast-200: var(--color-warning-contrast-dark);\n --color-warning-contrast-300: var(--color-warning-contrast-dark);\n --color-warning-contrast-400: var(--color-warning-contrast-dark);\n --color-warning-contrast-500: var(--color-warning-contrast-dark);\n --color-warning-contrast-600: var(--color-warning-contrast-dark);\n --color-warning-contrast-700: var(--color-warning-contrast-light);\n --color-warning-contrast-800: var(--color-warning-contrast-light);\n --color-warning-contrast-900: var(--color-warning-contrast-light);\n --color-warning-contrast-950: var(--color-warning-contrast-light);\n\n /* Error */\n --color-error-50: oklch(89.99% 0.04 14.04deg);\n --color-error-100: oklch(83.6% 0.08 19.82deg);\n --color-error-200: oklch(77.52% 0.11 21.99deg);\n --color-error-300: oklch(72.26% 0.15 24.9deg);\n --color-error-400: oklch(67.55% 0.19 26.72deg);\n --color-error-500: oklch(64.06% 0.22 28.71deg);\n --color-error-600: oklch(59.71% 0.21 28.7deg);\n --color-error-700: oklch(55.17% 0.2 28.73deg);\n --color-error-800: oklch(50.88% 0.19 28.77deg);\n --color-error-900: oklch(46.35% 0.18 28.89deg);\n --color-error-950: oklch(42.03% 0.17 29.27deg);\n --color-error-contrast-dark: var(--color-error-950);\n --color-error-contrast-light: var(--color-error-50);\n --color-error-contrast-50: var(--color-error-contrast-dark);\n --color-error-contrast-100: var(--color-error-contrast-dark);\n --color-error-contrast-200: var(--color-error-contrast-dark);\n --color-error-contrast-300: var(--color-error-contrast-dark);\n --color-error-contrast-400: var(--color-error-contrast-dark);\n --color-error-contrast-500: var(--color-error-contrast-light);\n --color-error-contrast-600: var(--color-error-contrast-light);\n --color-error-contrast-700: var(--color-error-contrast-light);\n --color-error-contrast-800: var(--color-error-contrast-light);\n --color-error-contrast-900: var(--color-error-contrast-light);\n --color-error-contrast-950: var(--color-error-contrast-light);\n\n /* Surface: Subtle blue tint */\n --color-surface-50: oklch(96% 0.01 260deg);\n --color-surface-100: oklch(90% 0.01 260deg);\n --color-surface-200: oklch(78.47% 0.02 264.48deg);\n --color-surface-300: oklch(68.53% 0.03 265.52deg);\n --color-surface-400: oklch(58.21% 0.04 265.04deg);\n --color-surface-500: oklch(47.47% 0.05 264.53deg);\n --color-surface-600: oklch(42.05% 0.05 264.5deg);\n --color-surface-700: oklch(36.45% 0.05 264.44deg);\n --color-surface-800: oklch(30.96% 0.04 263.65deg);\n --color-surface-900: oklch(24.88% 0.04 263.42deg);\n --color-surface-950: oklch(18.45% 0.04 262.95deg);\n --color-surface-contrast-dark: var(--color-surface-950);\n --color-surface-contrast-light: var(--color-surface-50);\n --color-surface-contrast-50: var(--color-surface-contrast-dark);\n --color-surface-contrast-100: var(--color-surface-contrast-dark);\n --color-surface-contrast-200: var(--color-surface-contrast-dark);\n --color-surface-contrast-300: var(--color-surface-contrast-dark);\n --color-surface-contrast-400: var(--color-surface-contrast-dark);\n --color-surface-contrast-500: var(--color-surface-contrast-light);\n --color-surface-contrast-600: var(--color-surface-contrast-light);\n --color-surface-contrast-700: var(--color-surface-contrast-light);\n --color-surface-contrast-800: var(--color-surface-contrast-light);\n --color-surface-contrast-900: var(--color-surface-contrast-light);\n --color-surface-contrast-950: var(--color-surface-contrast-light);\n}\n",
13
13
  "/lib/components/ui/ThemeToggle.svelte": "<script lang=\"ts\">\n import Sun from 'phosphor-svelte/lib/Sun';\n import Moon from 'phosphor-svelte/lib/Moon';\n import { onMount } from 'svelte';\n\n interface Props {\n class?: string;\n }\n\n let { class: className = '' }: Props = $props();\n\n let isDark = $state(true);\n\n function applyMode(dark: boolean) {\n const mode = dark ? 'dark' : 'light';\n document.documentElement.setAttribute('data-mode', mode);\n document.documentElement.style.colorScheme = mode;\n }\n\n onMount(() => {\n const stored = localStorage.getItem('theme-mode');\n if (stored) {\n // User has a manual preference\n isDark = stored === 'dark';\n } else {\n // Follow system\n isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n applyMode(isDark);\n });\n\n function toggle() {\n isDark = !isDark;\n applyMode(isDark);\n localStorage.setItem('theme-mode', isDark ? 'dark' : 'light');\n }\n<\/script>\n\n<button\n onclick={toggle}\n class=\"btn hover:preset-tonal-surface p-2 rounded-full {className}\"\n aria-label=\"Toggle theme\"\n>\n {#if isDark}\n <Moon size={18} />\n {:else}\n <Sun size={18} />\n {/if}\n</button>\n",
14
- "/lib/components/ui/index.ts": "export { default as Accordion } from './Accordion.svelte';\nexport { default as Alert } from './Alert.svelte';\nexport { default as Avatar } from './Avatar.svelte';\nexport { default as Badge } from './Badge.svelte';\nexport { default as Breadcrumb } from './Breadcrumb.svelte';\nexport { default as Button } from './Button.svelte';\nexport { default as Card } from './Card.svelte';\nexport { default as Checkbox } from './Checkbox.svelte';\nexport { default as Input } from './Input.svelte';\nexport { default as Select } from './Select.svelte';\nexport { default as Table } from './Table.svelte';\nexport { default as Tabs } from './Tabs.svelte';\nexport { default as Textarea } from './Textarea.svelte';\nexport { default as ThemeToggle } from './ThemeToggle.svelte';\nexport { default as Toggle } from './Toggle.svelte';\n",
14
+ "/lib/components/ui/index.ts": "export { default as Accordion } from './Accordion.svelte';\nexport { default as Alert } from './Alert.svelte';\nexport { default as Avatar } from './Avatar.svelte';\nexport { default as Badge } from './Badge.svelte';\nexport { default as Breadcrumb } from './Breadcrumb.svelte';\nexport { default as Button } from './Button.svelte';\nexport { default as Card } from './Card.svelte';\nexport { default as Checkbox } from './Checkbox.svelte';\nexport { default as Input } from './Input.svelte';\nexport { default as Select } from './Select.svelte';\nexport { default as Table } from './Table.svelte';\nexport { default as Tabs } from './Tabs.svelte';\nexport { default as Textarea } from './Textarea.svelte';\nexport { default as ThemeToggle } from './ThemeToggle.svelte';\nexport { default as Toggle } from './Toggle.svelte';\nexport { default as Logo } from './Logo.svelte';\n",
15
15
  "/lib/components/ui/Breadcrumb.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import CaretRight from 'phosphor-svelte/lib/CaretRight';\n\n interface Crumb {\n href?: string;\n label: string;\n }\n\n interface Props {\n items: Crumb[];\n class?: string;\n }\n\n let { items, class: className = '' }: Props = $props();\n<\/script>\n\n<nav aria-label=\"Breadcrumb\" class={className}>\n <ol class=\"flex items-center gap-1 text-sm\">\n {#each items as item, i}\n <li class=\"flex items-center gap-1\">\n {#if i > 0}\n <CaretRight size={14} class=\"text-surface-400\" />\n {/if}\n {#if item.href}\n <a href={item.href} class=\"hover:text-primary-500 transition-colors\">\n {item.label}\n </a>\n {:else}\n <span class=\"text-surface-500\">{item.label}</span>\n {/if}\n </li>\n {/each}\n </ol>\n</nav>\n",
16
16
  "/lib/components/ui/Accordion.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import CaretDown from 'phosphor-svelte/lib/CaretDown';\n\n interface AccordionItem {\n title: string;\n content: string;\n }\n\n interface Props {\n items: AccordionItem[];\n class?: string;\n }\n\n let { items, class: className = '' }: Props = $props();\n let openIndex = $state<number | null>(null);\n\n function toggle(i: number) {\n openIndex = openIndex === i ? null : i;\n }\n<\/script>\n\n<div class={cn('divide-y divide-surface-200-800 rounded-card border border-surface-200-800', className)}>\n {#each items as item, i}\n <div>\n <button\n class=\"w-full flex items-center justify-between p-element hover:bg-surface-100-800 transition-colors\"\n onclick={() => toggle(i)}\n >\n <span class=\"font-medium\">{item.title}</span>\n <CaretDown\n size={18}\n class={cn('transition-transform', openIndex === i && 'rotate-180')}\n />\n </button>\n {#if openIndex === i}\n <div class=\"px-element pb-element text-surface-500-400\">\n {item.content}\n </div>\n {/if}\n </div>\n {/each}\n</div>\n",
17
17
  "/lib/components/ui/Badge.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n type Variant = 'filled' | 'outlined' | 'tonal';\n type Color = 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'error' | 'surface';\n type Size = 'sm' | 'md' | 'lg';\n\n interface Props extends HTMLAttributes<HTMLSpanElement> {\n variant?: Variant;\n color?: Color;\n size?: Size;\n class?: string;\n children: Snippet;\n }\n\n let {\n variant = 'filled',\n color = 'primary',\n size = 'md',\n class: className = '',\n children,\n ...rest\n }: Props = $props();\n\n const presets = {\n filled: {\n primary: 'preset-filled-primary-400-600',\n secondary: 'preset-filled-secondary-400-600',\n tertiary: 'preset-filled-tertiary-400-600',\n success: 'preset-filled-success-400-600',\n warning: 'preset-filled-warning-400-600',\n error: 'preset-filled-error-400-600',\n surface: 'preset-filled-surface-400-600'\n },\n outlined: {\n primary: 'preset-outlined-primary-400-600',\n secondary: 'preset-outlined-secondary-400-600',\n tertiary: 'preset-outlined-tertiary-400-600',\n success: 'preset-outlined-success-400-600',\n warning: 'preset-outlined-warning-400-600',\n error: 'preset-outlined-error-400-600',\n surface: 'preset-outlined-surface-400-600'\n },\n tonal: {\n primary: 'preset-tonal-primary',\n secondary: 'preset-tonal-secondary',\n tertiary: 'preset-tonal-tertiary',\n success: 'preset-tonal-success',\n warning: 'preset-tonal-warning',\n error: 'preset-tonal-error',\n surface: 'preset-tonal-surface'\n }\n } as const;\n\n let sizeClass = $derived(\n size === 'sm' ? 'badge-sm' : size === 'lg' ? 'badge-lg' : 'badge-md'\n );\n\n let presetClass = $derived(presets[variant][color]);\n\n let classes = $derived(cn('badge', presetClass, sizeClass, className));\n<\/script>\n\n<span class={classes} {...rest}>\n {@render children()}\n</span>\n",
18
18
  "/lib/components/ui/Input.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLInputElement> {\n label?: string;\n error?: string;\n type?: string;\n placeholder?: string;\n value?: string;\n required?: boolean;\n name?: string;\n class?: string;\n }\n let { label, error, class: className, value = $bindable(''), ...rest }: Props = $props();\n let inputId = $derived(rest.id ?? `input-${Math.random().toString(36).slice(2, 9)}`);\n<\/script>\n\n<div class=\"w-full\">\n {#if label}\n <label class=\"label\" for={inputId}>\n {label}\n </label>\n {/if}\n <input\n id={inputId}\n class={cn('input', error && 'input-error', className)}\n bind:value\n {...rest}\n />\n {#if error}\n <p class=\"text-error-500 text-sm mt-1\">{error}</p>\n {/if}\n</div>\n",
19
19
  "/lib/components/ui/Checkbox.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLInputElement> {\n label?: string;\n checked?: boolean;\n class?: string;\n }\n\n let { label, class: className, checked = $bindable(false), ...rest }: Props = $props();\n<\/script>\n\n<label class={cn('flex items-center gap-2 cursor-pointer', className)}>\n <input type=\"checkbox\" class=\"checkbox\" bind:checked {...rest} />\n {#if label}\n <span>{label}</span>\n {/if}\n</label>\n",
20
+ "/lib/components/ui/Logo.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n\n interface Props {\n class?: string;\n }\n\n let { class: className = '' }: Props = $props();\n<\/script>\n\n<span class={cn('logo text-xl font-extrabold', className)}>SVForge</span>\n\n<style>\n @keyframes metalFlow {\n 0% {\n background-position: 0% 50%;\n }\n 50% {\n background-position: 100% 50%;\n }\n 100% {\n background-position: 0% 50%;\n }\n }\n .logo {\n font-family: 'Space Grotesk Variable', sans-serif;\n color: transparent;\n background: linear-gradient(\n 45deg,\n var(--color-secondary-200-800),\n var(--color-secondary-500),\n var(--color-secondary-600-400),\n var(--color-secondary-200-800)\n );\n background-size: 200% 200%;\n -webkit-background-clip: text;\n background-clip: text;\n letter-spacing: 0.05em;\n animation: metalFlow 5s ease-in-out infinite;\n filter: drop-shadow(0 0 2px var(--color-secondary-200-800));\n }\n</style>\n",
20
21
  "/lib/components/ui/Select.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLSelectElement> {\n label?: string;\n error?: string;\n options: { value: string; label: string }[];\n value?: string;\n class?: string;\n }\n\n let { label, error, options, class: className, value = $bindable(''), ...rest }: Props = $props();\n<\/script>\n\n<div class=\"w-full\">\n {#if label}\n <label class=\"label\" for={rest.id}>\n {label}\n </label>\n {/if}\n <select class={cn('select', error && 'select-error', className)} bind:value {...rest}>\n {#each options as opt}\n <option value={opt.value}>{opt.label}</option>\n {/each}\n </select>\n {#if error}\n <p class=\"text-error-500 text-sm mt-1\">{error}</p>\n {/if}\n</div>\n",
21
22
  "/lib/components/ui/Alert.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n type Variant = 'info' | 'success' | 'warning' | 'error';\n\n interface Props extends HTMLAttributes<HTMLDivElement> {\n variant?: Variant;\n class?: string;\n children: Snippet;\n }\n\n let { variant = 'info', class: className = '', children, ...rest }: Props = $props();\n\n const presets: Record<Variant, string> = {\n info: 'preset-tonal-info',\n success: 'preset-tonal-success',\n warning: 'preset-tonal-warning',\n error: 'preset-tonal-error'\n };\n\n let classes = $derived(cn('alert', presets[variant], className));\n<\/script>\n\n<div class={classes} {...rest}>\n {@render children()}\n</div>\n",
22
23
  "/lib/components/ui/Tabs.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n\n interface Tab {\n label: string;\n content: string;\n }\n\n interface Props {\n tabs: Tab[];\n class?: string;\n }\n\n let { tabs, class: className = '' }: Props = $props();\n let activeTab = $state(0);\n<\/script>\n\n<div class={className}>\n <div class=\"flex border-b border-surface-200-800 gap-1\">\n {#each tabs as tab, i}\n <button\n class={cn(\n 'px-4 py-2 font-medium transition-colors rounded-t-card',\n activeTab === i\n ? 'text-primary-500 border-b-2 border-primary-500'\n : 'text-surface-500 hover:text-surface-900-100'\n )}\n onclick={() => (activeTab = i)}\n >\n {tab.label}\n </button>\n {/each}\n </div>\n <div class=\"p-element\">\n {tabs[activeTab].content}\n </div>\n</div>\n",
@@ -26,8 +27,8 @@ const baseFiles = {
26
27
  "/lib/components/ui/Textarea.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLTextAreaElement> {\n label?: string;\n error?: string;\n placeholder?: string;\n rows?: number;\n value?: string;\n class?: string;\n }\n\n let { label, error, class: className, value = $bindable(''), ...rest }: Props = $props();\n let inputId = $derived(rest.id ?? `textarea-${Math.random().toString(36).slice(2, 9)}`);\n<\/script>\n\n<div class=\"w-full\">\n {#if label}\n <label class=\"label\" for={inputId}>\n {label}\n </label>\n {/if}\n <textarea\n id={inputId}\n class={cn('textarea', error && 'textarea-error', className)}\n bind:value\n {...rest}\n ></textarea>\n {#if error}\n <p class=\"text-error-500 text-sm mt-1\">{error}</p>\n {/if}\n</div>\n",
27
28
  "/lib/components/ui/Avatar.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n\n interface Props {\n src: string;\n alt?: string;\n size?: 'sm' | 'md' | 'lg';\n class?: string;\n }\n\n let { size = 'md', class: className = '', src, alt = '' }: Props = $props();\n\n const sizes: Record<string, string> = {\n sm: 'w-8 h-8',\n md: 'w-10 h-10',\n lg: 'w-14 h-14'\n };\n<\/script>\n\n<img\n {src}\n {alt}\n class={cn('rounded-full object-cover ring-2 ring-surface-200-800', sizes[size], className)}\n/>\n",
28
29
  "/lib/components/ui/Button.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n type Variant = 'filled' | 'outlined' | 'tonal' | 'ghost';\n type Color = 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'error' | 'surface';\n type Size = 'sm' | 'md' | 'lg';\n\n interface Props extends HTMLAttributes<HTMLButtonElement> {\n variant?: Variant;\n color?: Color;\n size?: Size;\n href?: string;\n loading?: boolean;\n disabled?: boolean;\n type?: 'button' | 'submit' | 'reset';\n class?: string;\n children: Snippet;\n }\n\n let {\n variant = 'filled',\n color = 'primary',\n size = 'md',\n href,\n loading = false,\n disabled = false,\n type = 'button',\n class: className = '',\n children,\n ...rest\n }: Props = $props();\n\n const presets = {\n filled: {\n primary: 'preset-filled-primary-400-600',\n secondary: 'preset-filled-secondary-400-600',\n tertiary: 'preset-filled-tertiary-400-600',\n success: 'preset-filled-success-400-600',\n warning: 'preset-filled-warning-400-600',\n error: 'preset-filled-error-400-600',\n surface: 'preset-filled-surface-400-600'\n },\n outlined: {\n primary: 'preset-outlined-primary-400-600',\n secondary: 'preset-outlined-secondary-400-600',\n tertiary: 'preset-outlined-tertiary-400-600',\n success: 'preset-outlined-success-400-600',\n warning: 'preset-outlined-warning-400-600',\n error: 'preset-outlined-error-400-600',\n surface: 'preset-outlined-surface-400-600'\n },\n tonal: {\n primary: 'preset-tonal-primary',\n secondary: 'preset-tonal-secondary',\n tertiary: 'preset-tonal-tertiary',\n success: 'preset-tonal-success',\n warning: 'preset-tonal-warning',\n error: 'preset-tonal-error',\n surface: 'preset-tonal-surface'\n },\n ghost: {\n primary: 'hover:preset-tonal-primary',\n secondary: 'hover:preset-tonal-secondary',\n tertiary: 'hover:preset-tonal-tertiary',\n success: 'hover:preset-tonal-success',\n warning: 'hover:preset-tonal-warning',\n error: 'hover:preset-tonal-error',\n surface: 'hover:preset-tonal-surface'\n }\n } as const;\n\n let sizeClass = $derived(\n size === 'sm' ? 'btn-sm' : size === 'lg' ? 'btn-lg' : 'btn-md'\n );\n\n let presetClass = $derived(\n presets[variant]?.[color] ?? ''\n );\n\n let classes = $derived(cn('btn', presetClass, sizeClass, className));\n<\/script>\n\n{#if href}\n <a {href} class={classes}>\n {#if loading}\n <span\n class=\"mr-2 inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\"\n ></span>\n {/if}\n {@render children()}\n </a>\n{:else}\n <button class={classes} disabled={disabled || loading} type={type} {...rest} aria-busy={loading}>\n {#if loading}\n <span\n class=\"mr-2 inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\"\n ></span>\n {/if}\n {@render children()}\n </button>\n{/if}\n",
29
- "/lib/components/layout/Navbar.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n import ThemeToggle from '$lib/components/ui/ThemeToggle.svelte';\n import Menu from 'phosphor-svelte/lib/List';\n import X from 'phosphor-svelte/lib/X';\n\n interface Props extends HTMLAttributes<HTMLElement> {\n brand?: Snippet;\n links?: { href: string; label: string }[];\n class?: string;\n }\n\n let { brand, links = [], class: className, ...rest }: Props = $props();\n let mobileOpen = $state(false);\n<\/script>\n\n<nav class={cn('sticky top-0 z-50 bg-surface-50-950/80 backdrop-blur-md border-b border-surface-200-800', className)} {...rest}>\n <div class=\"max-w-container mx-auto flex items-center justify-between px-element py-3\">\n <!-- Brand -->\n <a href=\"/\" class=\"text-xl font-heading font-bold text-primary-500\">\n {#if brand}\n {@render brand()}\n {:else}\n SvelteForge\n {/if}\n </a>\n\n <!-- Desktop links -->\n <div class=\"hidden md:flex items-center gap-4\">\n {#each links as link}\n <a href={link.href} class=\"hover:text-primary-500 transition-colors\">\n {link.label}\n </a>\n {/each}\n <ThemeToggle />\n </div>\n\n <!-- Mobile toggle -->\n <button\n class=\"md:hidden btn hover:preset-tonal-surface p-2 rounded-full\"\n onclick={() => (mobileOpen = !mobileOpen)}\n aria-label=\"Toggle menu\"\n >\n {#if mobileOpen}\n <X size={20} />\n {:else}\n <Menu size={20} />\n {/if}\n </button>\n </div>\n\n <!-- Mobile menu -->\n {#if mobileOpen}\n <div class=\"md:hidden border-t border-surface-200-800 px-element py-3 flex flex-col gap-3\">\n {#each links as link}\n <a href={link.href} class=\"hover:text-primary-500 transition-colors\" onclick={() => (mobileOpen = false)}>\n {link.label}\n </a>\n {/each}\n <ThemeToggle />\n </div>\n {/if}\n</nav>\n",
30
- "/lib/components/layout/Footer.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLElement> {\n links?: { href: string; label: string }[];\n class?: string;\n children?: Snippet;\n }\n\n let { links = [], class: className, children, ...rest }: Props = $props();\n<\/script>\n\n<footer class={cn('border-t border-surface-200-800 bg-surface-100-900', className)} {...rest}>\n <div class=\"max-w-container mx-auto px-element py-section\">\n <div class=\"flex flex-col md:flex-row justify-between gap-group\">\n {#if children}\n {@render children()}\n {/if}\n\n {#if links.length}\n <div class=\"flex flex-col gap-2\">\n {#each links as link}\n <a href={link.href} class=\"text-sm hover:text-primary-500 transition-colors\">\n {link.label}\n </a>\n {/each}\n </div>\n {/if}\n </div>\n\n <div class=\"mt-section pt-3 border-t border-surface-200-800 text-sm text-surface-500\">\n &copy; {new Date().getFullYear()} SvelteForge. All rights reserved.\n </div>\n </div>\n</footer>\n",
30
+ "/lib/components/layout/Navbar.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n import ThemeToggle from '$lib/components/ui/ThemeToggle.svelte';\n import Logo from '$lib/components/ui/Logo.svelte';\n import Menu from 'phosphor-svelte/lib/List';\n import X from 'phosphor-svelte/lib/X';\n\n interface Props extends HTMLAttributes<HTMLElement> {\n brand?: Snippet;\n links?: { href: string; label: string }[];\n class?: string;\n }\n\n let { brand, links = [], class: className, ...rest }: Props = $props();\n let mobileOpen = $state(false);\n<\/script>\n\n<nav class={cn('sticky top-0 z-50 bg-surface-50-950/80 backdrop-blur-md border-b border-surface-200-800', className)} {...rest}>\n <div class=\"max-w-container mx-auto flex items-center justify-between px-element py-3\">\n <!-- Brand -->\n <a href=\"/\" class=\"text-xl font-bold\">\n {#if brand}\n {@render brand()}\n {:else}\n <Logo />\n {/if}\n </a>\n\n <!-- Desktop links -->\n <div class=\"hidden md:flex items-center gap-4\">\n {#each links as link}\n <a href={link.href} class=\"hover:text-primary-500 transition-colors\">\n {link.label}\n </a>\n {/each}\n <ThemeToggle />\n </div>\n\n <!-- Mobile toggle -->\n <button\n class=\"md:hidden btn hover:preset-tonal-surface p-2 rounded-full\"\n onclick={() => (mobileOpen = !mobileOpen)}\n aria-label=\"Toggle menu\"\n >\n {#if mobileOpen}\n <X size={20} />\n {:else}\n <Menu size={20} />\n {/if}\n </button>\n </div>\n\n <!-- Mobile menu -->\n {#if mobileOpen}\n <div class=\"md:hidden border-t border-surface-200-800 px-element py-3 flex flex-col gap-3\">\n {#each links as link}\n <a href={link.href} class=\"hover:text-primary-500 transition-colors\" onclick={() => (mobileOpen = false)}>\n {link.label}\n </a>\n {/each}\n <ThemeToggle />\n </div>\n {/if}\n</nav>\n",
31
+ "/lib/components/layout/Footer.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLElement> {\n links?: { href: string; label: string }[];\n class?: string;\n children?: Snippet;\n }\n\n let { links = [], class: className, children, ...rest }: Props = $props();\n<\/script>\n\n<footer class={cn('border-t border-surface-200-800 bg-surface-100-900', className)} {...rest}>\n <div class=\"max-w-container mx-auto px-element py-section\">\n <div class=\"flex flex-col md:flex-row justify-between gap-group\">\n {#if children}\n {@render children()}\n {/if}\n\n {#if links.length}\n <div class=\"flex flex-col gap-2\">\n {#each links as link}\n <a href={link.href} class=\"text-sm hover:text-primary-500 transition-colors\">\n {link.label}\n </a>\n {/each}\n </div>\n {/if}\n </div>\n\n <div class=\"mt-section pt-3 border-t border-surface-200-800 text-sm text-surface-500\">\n &copy; {new Date().getFullYear()} SVForge. All rights reserved.\n </div>\n </div>\n</footer>\n",
31
32
  "/lib/components/layout/index.ts": "export { default as Footer } from './Footer.svelte';\nexport { default as Navbar } from './Navbar.svelte';\n",
32
33
  "/app.html": "<!doctype html>\n<html lang=\"en\" data-theme=\"svelteForge\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta name=\"text-scale\" content=\"scale\" />\n <link rel=\"icon\" href=\"%sveltekit.assets%/favicon.ico\" />\n %sveltekit.head%\n </head>\n <body data-sveltekit-preload-data=\"hover\">\n <div style=\"display: contents\">%sveltekit.body%</div>\n </body>\n</html>\n",
33
34
  "/app.d.ts": "// See https://svelte.dev/docs/kit/types#app.d.ts\n// for information about these interfaces\ndeclare global {\n namespace App {\n // interface Error {}\n // interface Locals {}\n // interface PageData {}\n // interface PageState {}\n // interface Platform {}\n }\n}\n\nexport {};\n"
@@ -49,6 +50,7 @@ const fullstackFiles = {
49
50
  "/lib/components/ui/Badge.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n type Variant = 'filled' | 'outlined' | 'tonal';\n type Color = 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'error' | 'surface';\n type Size = 'sm' | 'md' | 'lg';\n\n interface Props extends HTMLAttributes<HTMLSpanElement> {\n variant?: Variant;\n color?: Color;\n size?: Size;\n class?: string;\n children: Snippet;\n }\n\n let {\n variant = 'filled',\n color = 'primary',\n size = 'md',\n class: className = '',\n children,\n ...rest\n }: Props = $props();\n\n const presets = {\n filled: {\n primary: 'preset-filled-primary-400-600',\n secondary: 'preset-filled-secondary-400-600',\n tertiary: 'preset-filled-tertiary-400-600',\n success: 'preset-filled-success-400-600',\n warning: 'preset-filled-warning-400-600',\n error: 'preset-filled-error-400-600',\n surface: 'preset-filled-surface-400-600'\n },\n outlined: {\n primary: 'preset-outlined-primary-400-600',\n secondary: 'preset-outlined-secondary-400-600',\n tertiary: 'preset-outlined-tertiary-400-600',\n success: 'preset-outlined-success-400-600',\n warning: 'preset-outlined-warning-400-600',\n error: 'preset-outlined-error-400-600',\n surface: 'preset-outlined-surface-400-600'\n },\n tonal: {\n primary: 'preset-tonal-primary',\n secondary: 'preset-tonal-secondary',\n tertiary: 'preset-tonal-tertiary',\n success: 'preset-tonal-success',\n warning: 'preset-tonal-warning',\n error: 'preset-tonal-error',\n surface: 'preset-tonal-surface'\n }\n } as const;\n\n let sizeClass = $derived(\n size === 'sm' ? 'badge-sm' : size === 'lg' ? 'badge-lg' : 'badge-md'\n );\n\n let presetClass = $derived(presets[variant][color]);\n\n let classes = $derived(cn('badge', presetClass, sizeClass, className));\n<\/script>\n\n<span class={classes} {...rest}>\n {@render children()}\n</span>\n",
50
51
  "/lib/components/ui/Input.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLInputElement> {\n label?: string;\n error?: string;\n type?: string;\n placeholder?: string;\n value?: string;\n required?: boolean;\n name?: string;\n class?: string;\n }\n let { label, error, class: className, value = $bindable(''), ...rest }: Props = $props();\n let inputId = $derived(rest.id ?? `input-${Math.random().toString(36).slice(2, 9)}`);\n<\/script>\n\n<div class=\"w-full\">\n {#if label}\n <label class=\"label\" for={inputId}>\n {label}\n </label>\n {/if}\n <input\n id={inputId}\n class={cn('input', error && 'input-error', className)}\n bind:value\n {...rest}\n />\n {#if error}\n <p class=\"text-error-500 text-sm mt-1\">{error}</p>\n {/if}\n</div>\n",
51
52
  "/lib/components/ui/Checkbox.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLInputElement> {\n label?: string;\n checked?: boolean;\n class?: string;\n }\n\n let { label, class: className, checked = $bindable(false), ...rest }: Props = $props();\n<\/script>\n\n<label class={cn('flex items-center gap-2 cursor-pointer', className)}>\n <input type=\"checkbox\" class=\"checkbox\" bind:checked {...rest} />\n {#if label}\n <span>{label}</span>\n {/if}\n</label>\n",
53
+ "/lib/components/ui/Logo.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n\n interface Props {\n class?: string;\n }\n\n let { class: className = '' }: Props = $props();\n<\/script>\n\n<span class={cn('logo text-xl font-extrabold', className)}>SVForge</span>\n\n<style>\n @keyframes metalFlow {\n 0% {\n background-position: 0% 50%;\n }\n 50% {\n background-position: 100% 50%;\n }\n 100% {\n background-position: 0% 50%;\n }\n }\n .logo {\n font-family: 'Space Grotesk Variable', sans-serif;\n color: transparent;\n background: linear-gradient(\n 45deg,\n var(--color-secondary-200-800),\n var(--color-secondary-500),\n var(--color-secondary-600-400),\n var(--color-secondary-200-800)\n );\n background-size: 200% 200%;\n -webkit-background-clip: text;\n background-clip: text;\n letter-spacing: 0.05em;\n animation: metalFlow 5s ease-in-out infinite;\n filter: drop-shadow(0 0 2px var(--color-secondary-200-800));\n }\n</style>\n",
52
54
  "/lib/components/ui/Select.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLSelectElement> {\n label?: string;\n error?: string;\n options: { value: string; label: string }[];\n value?: string;\n class?: string;\n }\n\n let { label, error, options, class: className, value = $bindable(''), ...rest }: Props = $props();\n<\/script>\n\n<div class=\"w-full\">\n {#if label}\n <label class=\"label\" for={rest.id}>\n {label}\n </label>\n {/if}\n <select class={cn('select', error && 'select-error', className)} bind:value {...rest}>\n {#each options as opt}\n <option value={opt.value}>{opt.label}</option>\n {/each}\n </select>\n {#if error}\n <p class=\"text-error-500 text-sm mt-1\">{error}</p>\n {/if}\n</div>\n",
53
55
  "/lib/components/ui/Alert.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n type Variant = 'info' | 'success' | 'warning' | 'error';\n\n interface Props extends HTMLAttributes<HTMLDivElement> {\n variant?: Variant;\n class?: string;\n children: Snippet;\n }\n\n let { variant = 'info', class: className = '', children, ...rest }: Props = $props();\n\n const presets: Record<Variant, string> = {\n info: 'preset-tonal-info',\n success: 'preset-tonal-success',\n warning: 'preset-tonal-warning',\n error: 'preset-tonal-error'\n };\n\n let classes = $derived(cn('alert', presets[variant], className));\n<\/script>\n\n<div class={classes} {...rest}>\n {@render children()}\n</div>\n",
54
56
  "/lib/components/ui/Tabs.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n\n interface Tab {\n label: string;\n content: string;\n }\n\n interface Props {\n tabs: Tab[];\n class?: string;\n }\n\n let { tabs, class: className = '' }: Props = $props();\n let activeTab = $state(0);\n<\/script>\n\n<div class={className}>\n <div class=\"flex border-b border-surface-200-800 gap-1\">\n {#each tabs as tab, i}\n <button\n class={cn(\n 'px-4 py-2 font-medium transition-colors rounded-t-card',\n activeTab === i\n ? 'text-primary-500 border-b-2 border-primary-500'\n : 'text-surface-500 hover:text-surface-900-100'\n )}\n onclick={() => (activeTab = i)}\n >\n {tab.label}\n </button>\n {/each}\n </div>\n <div class=\"p-element\">\n {tabs[activeTab].content}\n </div>\n</div>\n",
@@ -58,8 +60,8 @@ const fullstackFiles = {
58
60
  "/lib/components/ui/Textarea.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLTextAreaElement> {\n label?: string;\n error?: string;\n placeholder?: string;\n rows?: number;\n value?: string;\n class?: string;\n }\n\n let { label, error, class: className, value = $bindable(''), ...rest }: Props = $props();\n let inputId = $derived(rest.id ?? `textarea-${Math.random().toString(36).slice(2, 9)}`);\n<\/script>\n\n<div class=\"w-full\">\n {#if label}\n <label class=\"label\" for={inputId}>\n {label}\n </label>\n {/if}\n <textarea\n id={inputId}\n class={cn('textarea', error && 'textarea-error', className)}\n bind:value\n {...rest}\n ></textarea>\n {#if error}\n <p class=\"text-error-500 text-sm mt-1\">{error}</p>\n {/if}\n</div>\n",
59
61
  "/lib/components/ui/Avatar.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n\n interface Props {\n src: string;\n alt?: string;\n size?: 'sm' | 'md' | 'lg';\n class?: string;\n }\n\n let { size = 'md', class: className = '', src, alt = '' }: Props = $props();\n\n const sizes: Record<string, string> = {\n sm: 'w-8 h-8',\n md: 'w-10 h-10',\n lg: 'w-14 h-14'\n };\n<\/script>\n\n<img\n {src}\n {alt}\n class={cn('rounded-full object-cover ring-2 ring-surface-200-800', sizes[size], className)}\n/>\n",
60
62
  "/lib/components/ui/Button.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n type Variant = 'filled' | 'outlined' | 'tonal' | 'ghost';\n type Color = 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'error' | 'surface';\n type Size = 'sm' | 'md' | 'lg';\n\n interface Props extends HTMLAttributes<HTMLButtonElement> {\n variant?: Variant;\n color?: Color;\n size?: Size;\n href?: string;\n loading?: boolean;\n disabled?: boolean;\n type?: 'button' | 'submit' | 'reset';\n class?: string;\n children: Snippet;\n }\n\n let {\n variant = 'filled',\n color = 'primary',\n size = 'md',\n href,\n loading = false,\n disabled = false,\n type = 'button',\n class: className = '',\n children,\n ...rest\n }: Props = $props();\n\n const presets = {\n filled: {\n primary: 'preset-filled-primary-400-600',\n secondary: 'preset-filled-secondary-400-600',\n tertiary: 'preset-filled-tertiary-400-600',\n success: 'preset-filled-success-400-600',\n warning: 'preset-filled-warning-400-600',\n error: 'preset-filled-error-400-600',\n surface: 'preset-filled-surface-400-600'\n },\n outlined: {\n primary: 'preset-outlined-primary-400-600',\n secondary: 'preset-outlined-secondary-400-600',\n tertiary: 'preset-outlined-tertiary-400-600',\n success: 'preset-outlined-success-400-600',\n warning: 'preset-outlined-warning-400-600',\n error: 'preset-outlined-error-400-600',\n surface: 'preset-outlined-surface-400-600'\n },\n tonal: {\n primary: 'preset-tonal-primary',\n secondary: 'preset-tonal-secondary',\n tertiary: 'preset-tonal-tertiary',\n success: 'preset-tonal-success',\n warning: 'preset-tonal-warning',\n error: 'preset-tonal-error',\n surface: 'preset-tonal-surface'\n },\n ghost: {\n primary: 'hover:preset-tonal-primary',\n secondary: 'hover:preset-tonal-secondary',\n tertiary: 'hover:preset-tonal-tertiary',\n success: 'hover:preset-tonal-success',\n warning: 'hover:preset-tonal-warning',\n error: 'hover:preset-tonal-error',\n surface: 'hover:preset-tonal-surface'\n }\n } as const;\n\n let sizeClass = $derived(\n size === 'sm' ? 'btn-sm' : size === 'lg' ? 'btn-lg' : 'btn-md'\n );\n\n let presetClass = $derived(\n presets[variant]?.[color] ?? ''\n );\n\n let classes = $derived(cn('btn', presetClass, sizeClass, className));\n<\/script>\n\n{#if href}\n <a {href} class={classes}>\n {#if loading}\n <span\n class=\"mr-2 inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\"\n ></span>\n {/if}\n {@render children()}\n </a>\n{:else}\n <button class={classes} disabled={disabled || loading} type={type} {...rest} aria-busy={loading}>\n {#if loading}\n <span\n class=\"mr-2 inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\"\n ></span>\n {/if}\n {@render children()}\n </button>\n{/if}\n",
61
- "/lib/components/layout/Navbar.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n import ThemeToggle from '$lib/components/ui/ThemeToggle.svelte';\n import Menu from 'phosphor-svelte/lib/List';\n import X from 'phosphor-svelte/lib/X';\n\n interface Props extends HTMLAttributes<HTMLElement> {\n brand?: Snippet;\n links?: { href: string; label: string }[];\n class?: string;\n }\n\n let { brand, links = [], class: className, ...rest }: Props = $props();\n let mobileOpen = $state(false);\n<\/script>\n\n<nav class={cn('sticky top-0 z-50 bg-surface-50-950/80 backdrop-blur-md border-b border-surface-200-800', className)} {...rest}>\n <div class=\"max-w-container mx-auto flex items-center justify-between px-element py-3\">\n <!-- Brand -->\n <a href=\"/\" class=\"text-xl font-heading font-bold text-primary-500\">\n {#if brand}\n {@render brand()}\n {:else}\n SvelteForge\n {/if}\n </a>\n\n <!-- Desktop links -->\n <div class=\"hidden md:flex items-center gap-4\">\n {#each links as link}\n <a href={link.href} class=\"hover:text-primary-500 transition-colors\">\n {link.label}\n </a>\n {/each}\n <ThemeToggle />\n </div>\n\n <!-- Mobile toggle -->\n <button\n class=\"md:hidden btn hover:preset-tonal-surface p-2 rounded-full\"\n onclick={() => (mobileOpen = !mobileOpen)}\n aria-label=\"Toggle menu\"\n >\n {#if mobileOpen}\n <X size={20} />\n {:else}\n <Menu size={20} />\n {/if}\n </button>\n </div>\n\n <!-- Mobile menu -->\n {#if mobileOpen}\n <div class=\"md:hidden border-t border-surface-200-800 px-element py-3 flex flex-col gap-3\">\n {#each links as link}\n <a href={link.href} class=\"hover:text-primary-500 transition-colors\" onclick={() => (mobileOpen = false)}>\n {link.label}\n </a>\n {/each}\n <ThemeToggle />\n </div>\n {/if}\n</nav>\n",
62
- "/lib/components/layout/Footer.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLElement> {\n links?: { href: string; label: string }[];\n class?: string;\n children?: Snippet;\n }\n\n let { links = [], class: className, children, ...rest }: Props = $props();\n<\/script>\n\n<footer class={cn('border-t border-surface-200-800 bg-surface-100-900', className)} {...rest}>\n <div class=\"max-w-container mx-auto px-element py-section\">\n <div class=\"flex flex-col md:flex-row justify-between gap-group\">\n {#if children}\n {@render children()}\n {/if}\n\n {#if links.length}\n <div class=\"flex flex-col gap-2\">\n {#each links as link}\n <a href={link.href} class=\"text-sm hover:text-primary-500 transition-colors\">\n {link.label}\n </a>\n {/each}\n </div>\n {/if}\n </div>\n\n <div class=\"mt-section pt-3 border-t border-surface-200-800 text-sm text-surface-500\">\n &copy; {new Date().getFullYear()} SvelteForge. All rights reserved.\n </div>\n </div>\n</footer>\n",
63
+ "/lib/components/layout/Navbar.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n import ThemeToggle from '$lib/components/ui/ThemeToggle.svelte';\n import Logo from '$lib/components/ui/Logo.svelte';\n import Menu from 'phosphor-svelte/lib/List';\n import X from 'phosphor-svelte/lib/X';\n\n interface Props extends HTMLAttributes<HTMLElement> {\n brand?: Snippet;\n links?: { href: string; label: string }[];\n class?: string;\n }\n\n let { brand, links = [], class: className, ...rest }: Props = $props();\n let mobileOpen = $state(false);\n<\/script>\n\n<nav class={cn('sticky top-0 z-50 bg-surface-50-950/80 backdrop-blur-md border-b border-surface-200-800', className)} {...rest}>\n <div class=\"max-w-container mx-auto flex items-center justify-between px-element py-3\">\n <!-- Brand -->\n <a href=\"/\" class=\"text-xl font-bold\">\n {#if brand}\n {@render brand()}\n {:else}\n <Logo />\n {/if}\n </a>\n\n <!-- Desktop links -->\n <div class=\"hidden md:flex items-center gap-4\">\n {#each links as link}\n <a href={link.href} class=\"hover:text-primary-500 transition-colors\">\n {link.label}\n </a>\n {/each}\n <ThemeToggle />\n </div>\n\n <!-- Mobile toggle -->\n <button\n class=\"md:hidden btn hover:preset-tonal-surface p-2 rounded-full\"\n onclick={() => (mobileOpen = !mobileOpen)}\n aria-label=\"Toggle menu\"\n >\n {#if mobileOpen}\n <X size={20} />\n {:else}\n <Menu size={20} />\n {/if}\n </button>\n </div>\n\n <!-- Mobile menu -->\n {#if mobileOpen}\n <div class=\"md:hidden border-t border-surface-200-800 px-element py-3 flex flex-col gap-3\">\n {#each links as link}\n <a href={link.href} class=\"hover:text-primary-500 transition-colors\" onclick={() => (mobileOpen = false)}>\n {link.label}\n </a>\n {/each}\n <ThemeToggle />\n </div>\n {/if}\n</nav>\n",
64
+ "/lib/components/layout/Footer.svelte": "<script lang=\"ts\">\n import { cn } from '$lib/utils/cn';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n interface Props extends HTMLAttributes<HTMLElement> {\n links?: { href: string; label: string }[];\n class?: string;\n children?: Snippet;\n }\n\n let { links = [], class: className, children, ...rest }: Props = $props();\n<\/script>\n\n<footer class={cn('border-t border-surface-200-800 bg-surface-100-900', className)} {...rest}>\n <div class=\"max-w-container mx-auto px-element py-section\">\n <div class=\"flex flex-col md:flex-row justify-between gap-group\">\n {#if children}\n {@render children()}\n {/if}\n\n {#if links.length}\n <div class=\"flex flex-col gap-2\">\n {#each links as link}\n <a href={link.href} class=\"text-sm hover:text-primary-500 transition-colors\">\n {link.label}\n </a>\n {/each}\n </div>\n {/if}\n </div>\n\n <div class=\"mt-section pt-3 border-t border-surface-200-800 text-sm text-surface-500\">\n &copy; {new Date().getFullYear()} SVForge. All rights reserved.\n </div>\n </div>\n</footer>\n",
63
65
  "/lib/components/layout/index.ts": "export { default as AdminLayout } from './AdminLayout.svelte';\nexport { default as Footer } from './Footer.svelte';\nexport { default as Navbar } from './Navbar.svelte';\n",
64
66
  "/app.html": "<!doctype html>\n<html lang=\"en\" data-theme=\"svelteForge\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta name=\"text-scale\" content=\"scale\" />\n <link rel=\"icon\" href=\"%sveltekit.assets%/favicon.ico\" />\n %sveltekit.head%\n </head>\n <body data-sveltekit-preload-data=\"hover\">\n <div style=\"display: contents\">%sveltekit.body%</div>\n </body>\n</html>\n",
65
67
  "/app.d.ts": "import type { User, Session } from 'better-auth/minimal';\n\n// See https://svelte.dev/docs/kit/types#app.d.ts\n// for information about these interfaces\ndeclare global {\n namespace App {\n interface Locals { user?: User; session?: Session }\n\n // interface Error {}\n // interface PageData {}\n // interface PageState {}\n // interface Platform {}\n }\n}\n\nexport {};\n",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svforge",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "description": "sv community addon — SvelteKit starter templates with Skeleton UI, Tailwind CSS, Better Auth, and Drizzle ORM",
6
6
  "author": "Ludo (https://lelab.dev)",