svelora 3.0.0 → 3.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 (109) hide show
  1. package/dist/Accordion/Accordion.svelte +66 -97
  2. package/dist/Alert/Alert.svelte +39 -64
  3. package/dist/Alert/Alert.svelte.d.ts +1 -1
  4. package/dist/Avatar/Avatar.svelte +35 -75
  5. package/dist/AvatarGroup/AvatarGroup.svelte +38 -55
  6. package/dist/Badge/Badge.svelte +28 -50
  7. package/dist/Banner/Banner.svelte +46 -41
  8. package/dist/Banner/Banner.svelte.d.ts +1 -1
  9. package/dist/Breadcrumb/Breadcrumb.svelte +32 -26
  10. package/dist/Button/Button.svelte +70 -138
  11. package/dist/Calendar/Calendar.svelte +94 -157
  12. package/dist/Calendar/Calendar.svelte.d.ts +1 -1
  13. package/dist/Card/Card.svelte +18 -31
  14. package/dist/Carousel/Carousel.svelte +118 -173
  15. package/dist/Checkbox/Checkbox.svelte +52 -97
  16. package/dist/CheckboxGroup/CheckboxGroup.svelte +62 -107
  17. package/dist/CheckboxGroup/CheckboxGroup.svelte.d.ts +1 -1
  18. package/dist/Chip/Chip.svelte +22 -34
  19. package/dist/CodeBlock/CodeBlock.svelte +42 -59
  20. package/dist/Collapsible/Collapsible.svelte +22 -38
  21. package/dist/Collapsible/Collapsible.svelte.d.ts +1 -1
  22. package/dist/Collapsible/CollapsibleTestWrapper.svelte +2 -5
  23. package/dist/Collapsible/CollapsibleTestWrapper.svelte.d.ts +1 -1
  24. package/dist/Command/Command.svelte +40 -77
  25. package/dist/Command/Command.svelte.d.ts +1 -1
  26. package/dist/Command/CommandTestWrapper.svelte +2 -10
  27. package/dist/Command/CommandTestWrapper.svelte.d.ts +1 -1
  28. package/dist/Container/Container.svelte +11 -14
  29. package/dist/ContextMenu/ContextMenu.svelte +51 -114
  30. package/dist/ContextMenu/ContextMenu.svelte.d.ts +1 -1
  31. package/dist/Drawer/Drawer.svelte +72 -110
  32. package/dist/Drawer/DrawerTriggerTestWrapper.svelte +1 -2
  33. package/dist/DropdownMenu/DropdownMenu.svelte +63 -124
  34. package/dist/DropdownMenu/DropdownMenu.svelte.d.ts +1 -1
  35. package/dist/DropdownMenu/DropdownMenuTriggerTestWrapper.svelte +2 -5
  36. package/dist/Editor/Editor.svelte +441 -576
  37. package/dist/Editor/Editor.svelte.d.ts +1 -1
  38. package/dist/Editor/EditorUrlPrompt.svelte +40 -53
  39. package/dist/Editor/SlashPopup.svelte +12 -24
  40. package/dist/Empty/Empty.svelte +32 -63
  41. package/dist/FieldGroup/FieldGroup.svelte +23 -38
  42. package/dist/FileUpload/FileUpload.svelte +242 -320
  43. package/dist/FileUpload/FileUpload.svelte.d.ts +1 -1
  44. package/dist/Fonts/Fonts.svelte +15 -37
  45. package/dist/Form/Form.svelte +112 -170
  46. package/dist/FormField/FormField.svelte +102 -135
  47. package/dist/Icon/Icon.svelte +7 -32
  48. package/dist/Input/Input.svelte +71 -141
  49. package/dist/Input/Input.svelte.d.ts +2 -2
  50. package/dist/Kbd/Kbd.svelte +18 -34
  51. package/dist/Link/Link.svelte +129 -196
  52. package/dist/LocaleButton/LocaleButton.svelte +165 -0
  53. package/dist/LocaleButton/LocaleButton.svelte.d.ts +5 -0
  54. package/dist/LocaleButton/index.d.ts +2 -0
  55. package/dist/LocaleButton/index.js +1 -0
  56. package/dist/LocaleButton/locale-button.types.d.ts +182 -0
  57. package/dist/LocaleButton/locale-button.types.js +1 -0
  58. package/dist/LocaleButton/locale-button.variants.d.ts +61 -0
  59. package/dist/LocaleButton/locale-button.variants.js +34 -0
  60. package/dist/Modal/Modal.svelte +52 -106
  61. package/dist/Modal/ModalTriggerTestWrapper.svelte +1 -2
  62. package/dist/Pagination/Pagination.svelte +48 -92
  63. package/dist/Pagination/pagination.variants.d.ts +1 -1
  64. package/dist/PinInput/PinInput.svelte +57 -111
  65. package/dist/PinInput/PinInput.svelte.d.ts +1 -1
  66. package/dist/Popover/Popover.svelte +28 -61
  67. package/dist/Popover/Popover.svelte.d.ts +1 -1
  68. package/dist/Progress/Progress.svelte +75 -94
  69. package/dist/RadioGroup/RadioGroup.svelte +54 -99
  70. package/dist/RadioGroup/RadioGroup.svelte.d.ts +1 -1
  71. package/dist/Select/Select.svelte +112 -269
  72. package/dist/Select/Select.svelte.d.ts +1 -1
  73. package/dist/SelectMenu/SelectMenu.svelte +211 -409
  74. package/dist/SelectMenu/SelectMenu.svelte.d.ts +1 -1
  75. package/dist/SelectMenu/SelectMenuFormFieldTestWrapper.svelte +3 -6
  76. package/dist/Separator/Separator.svelte +29 -44
  77. package/dist/Skeleton/Skeleton.svelte +11 -23
  78. package/dist/Slideover/Slideover.svelte +52 -106
  79. package/dist/Slideover/SlideoverTriggerTestWrapper.svelte +1 -2
  80. package/dist/Slider/Slider.svelte +48 -84
  81. package/dist/Slider/Slider.svelte.d.ts +1 -1
  82. package/dist/Stepper/Stepper.svelte +139 -132
  83. package/dist/Stepper/Stepper.svelte.d.ts +1 -1
  84. package/dist/Switch/Switch.svelte +62 -98
  85. package/dist/Table/Table.svelte +232 -283
  86. package/dist/Table/table.variants.d.ts +1 -1
  87. package/dist/Tabs/Tabs.svelte +96 -129
  88. package/dist/Tabs/Tabs.svelte.d.ts +1 -1
  89. package/dist/Textarea/Textarea.svelte +90 -173
  90. package/dist/Textarea/Textarea.svelte.d.ts +1 -1
  91. package/dist/ThemeModeButton/ThemeModeButton.svelte +16 -38
  92. package/dist/Timeline/Timeline.svelte +75 -54
  93. package/dist/Toast/Toaster.svelte +8 -25
  94. package/dist/Tooltip/Tooltip.svelte +34 -66
  95. package/dist/Tooltip/Tooltip.svelte.d.ts +1 -1
  96. package/dist/Tooltip/TooltipTestWrapper.svelte +2 -5
  97. package/dist/User/User.svelte +33 -49
  98. package/dist/docs/navigation.d.ts +1 -1
  99. package/dist/docs/navigation.js +8 -1
  100. package/dist/hooks/HookContextProbe.svelte +2 -4
  101. package/dist/hooks/HookContextProvider.svelte +8 -6
  102. package/dist/hooks/HookEmitProbe.svelte +8 -11
  103. package/dist/i18n.d.ts +2 -0
  104. package/dist/i18n.js +19 -0
  105. package/dist/index.d.ts +1 -0
  106. package/dist/index.js +1 -0
  107. package/dist/mcp/svelora-docs.data.json +4 -2
  108. package/dist/theme.css +1 -1
  109. package/package.json +16 -8
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": 1,
3
3
  "packageName": "svelora",
4
- "packageVersion": "3.0.0",
5
- "generatedAt": "2026-06-23T07:37:57.185Z",
4
+ "packageVersion": "3.0.2",
5
+ "generatedAt": "2026-06-23T16:34:19.080Z",
6
6
  "slugs": {
7
7
  "components": [
8
8
  "button",
@@ -11,6 +11,7 @@
11
11
  "fonts",
12
12
  "icon",
13
13
  "link",
14
+ "locale-button",
14
15
  "kbd",
15
16
  "theme-mode-button",
16
17
  "card",
@@ -78,6 +79,7 @@
78
79
  "fonts": "<script lang=\"ts\">\n import { Card, CodeBlock, Fonts, defaultFontFamilies, fontsDefaults } from '$lib/index.js'\n import { renderHighlightedCode } from '$lib/docs/code-block.js'\n import type { FontDefinition } from '$lib/index.js'\n\n const googleFamilies: FontDefinition[] = [\n {\n name: 'Inter',\n variable: '--font-sans-family',\n weights: [400, 500, 600, 700]\n },\n {\n name: 'Poppins',\n variable: '--font-heading-family',\n weights: [600, 700]\n },\n {\n name: 'JetBrains Mono',\n variable: '--font-mono-family',\n weights: [400, 500, 700]\n }\n ]\n\n const defaultPresetCode = `<Fonts />`\n\n const defaultPresetItems = [\n {\n variable: '--font-sans-family',\n family: 'Inter',\n weights: '400, 500, 600, 700',\n utility: 'font-sans'\n },\n {\n variable: '--font-heading-family',\n family: 'Inter',\n weights: '400, 500, 600, 700',\n utility: 'font-heading'\n },\n {\n variable: '--font-mono-family',\n family: 'JetBrains Mono',\n weights: '400, 500, 700',\n utility: 'font-mono'\n }\n ] as const\n\n const localSetupSteps = [\n 'Add your files under `static/fonts/*` so they are served from the app root.',\n 'Map each file with `provider: \"local\"` and `sources` entries for the weights/styles you need.',\n 'Bind the family to a CSS variable such as `--font-sarabun-family`.',\n 'Use the mapped variable through utility classes like `font-sarabun`, `font-heading`, or `font-mono`.'\n ] as const\n\n const localLayoutCode = `<script lang=\"ts\">\n import 'svelora/theme.css';\n import { Fonts } from 'svelora';\n\n let { children } = $props();\n<` + `/script>\n\n<Fonts\n families={[\n {\n provider: 'local',\n name: 'Sarabun',\n variable: '--font-sarabun-family',\n sources: [\n { src: '/fonts/Sarabun-Regular.woff2', format: 'woff2', weight: 400 },\n { src: '/fonts/Sarabun-Medium.woff2', format: 'woff2', weight: 500 },\n { src: '/fonts/Sarabun-Bold.woff2', format: 'woff2', weight: 700 }\n ]\n }\n ]}\n/>\n\n<main class=\"font-sarabun\">\n {@render children?.()}\n</main>`\n\n const familyReference = [\n {\n name: 'provider',\n type: `'google' | 'local'`,\n description: 'Selects whether the family loads from Google Fonts or local assets.'\n },\n {\n name: 'name',\n type: 'string',\n description: 'Font family name used in the request or `@font-face` declaration.'\n },\n {\n name: 'variable',\n type: '`--${string}`',\n description: 'CSS custom property that stores the generated font-family stack.'\n },\n {\n name: 'fallback',\n type: 'string',\n description: 'Optional fallback stack appended after the primary font family.'\n },\n {\n name: 'weights',\n type: 'number[]',\n description: 'Google-only list of weights to request.'\n },\n {\n name: 'styles',\n type: `('normal' | 'italic')[]`,\n description: 'Google-only styles to request.'\n },\n {\n name: 'sources',\n type: 'LocalFontSource[]',\n description: 'Local-only file definitions used to build `@font-face` rules.'\n }\n ] as const\n\n const optionsReference = [\n {\n name: 'families',\n type: 'FontDefinition[]',\n description: 'Complete list of families managed by the provider.'\n },\n {\n name: 'display',\n type: `'auto' | 'block' | 'swap' | 'fallback' | 'optional'`,\n description: 'Controls `font-display` for Google requests and local `@font-face` output.'\n },\n {\n name: 'preconnect',\n type: 'boolean',\n description: 'Adds preconnect links for Google Fonts when enabled.'\n }\n ] as const\n\n const localSourceReference = [\n {\n name: 'src',\n type: 'string',\n description: 'Public URL to the local font file, for example `/fonts/Sarabun-Regular.woff2`.'\n },\n {\n name: 'format',\n type: `'woff2' | 'woff' | 'truetype' | 'opentype' | 'embedded-opentype' | 'svg'`,\n description: 'Optional format hint used in `@font-face`.'\n },\n {\n name: 'weight',\n type: 'number | `${number} ${number}`',\n description: 'Single weight or variable font range.'\n },\n {\n name: 'style',\n type: `'normal' | 'italic'`,\n description: 'Font style for the source entry.'\n },\n {\n name: 'unicodeRange',\n type: 'string',\n description: 'Optional unicode-range for partial subsets.'\n }\n ] as const\n\n const localProviderCode = `<Fonts\n families={[\n {\n provider: 'local',\n name: 'Sarabun',\n variable: '--font-sarabun-family',\n sources: [\n { src: '/fonts/Sarabun-Regular.woff2', format: 'woff2', weight: 400 },\n { src: '/fonts/Sarabun-Bold.woff2', format: 'woff2', weight: 700 }\n ]\n }\n ]}\n/>`\n\n const mixedProviderCode = `<Fonts\n families={[\n { name: 'Inter', variable: '--font-sans-family', weights: [400, 500, 600, 700] },\n { name: 'Poppins', variable: '--font-heading-family', weights: [600, 700] },\n {\n provider: 'local',\n name: 'Sarabun',\n variable: '--font-sarabun-family',\n sources: [{ src: '/fonts/Sarabun-Regular.woff2', format: 'woff2', weight: 400 }]\n }\n ]}\n/>`\n\n const configCode = `import { defineConfig } from 'svelora';\n\ndefineConfig({\n fonts: {\n families: [\n { name: 'Inter', variable: '--font-sans-family', weights: [400, 500, 600, 700] },\n { name: 'Poppins', variable: '--font-heading-family', weights: [600, 700] },\n {\n provider: 'local',\n name: 'Sarabun',\n variable: '--font-sarabun-family',\n sources: [\n { src: '/fonts/Sarabun-Regular.woff2', format: 'woff2', weight: 400 },\n { src: '/fonts/Sarabun-Bold.woff2', format: 'woff2', weight: 700 }\n ]\n }\n ]\n }\n});`\n\n const layoutCode = `<script lang=\"ts\">\n import 'svelora/theme.css';\n import { Fonts, ModeWatcher } from 'svelora';\n\n let { children } = $props();\n<` + `/script>\n\n<Fonts />\n<ModeWatcher />\n{@render children?.()}`\n\n const disableDefaultsCode = `import { defineConfig } from 'svelora';\n\ndefineConfig({\n fonts: false\n});`\n\n let isDarkMode = $state(true)\n let defaultPresetHtml = $state('')\n let localProviderHtml = $state('')\n let localLayoutHtml = $state('')\n let mixedProviderHtml = $state('')\n let configHtml = $state('')\n let layoutHtml = $state('')\n let disableDefaultsHtml = $state('')\n\n $effect(() => {\n if (typeof document === 'undefined') return\n\n const root = document.documentElement\n const updateMode = () => {\n isDarkMode = root.classList.contains('dark')\n }\n\n updateMode()\n\n const observer = new MutationObserver(() => {\n updateMode()\n })\n\n observer.observe(root, { attributes: true, attributeFilter: ['class'] })\n return () => observer.disconnect()\n })\n\n $effect(() => {\n const darkMode = isDarkMode\n let cancelled = false\n\n const tasks = [\n renderHighlightedCode(defaultPresetCode, darkMode).then((html) => {\n if (!cancelled) defaultPresetHtml = html\n }),\n renderHighlightedCode(localProviderCode, darkMode).then((html) => {\n if (!cancelled) localProviderHtml = html\n }),\n renderHighlightedCode(localLayoutCode, darkMode).then((html) => {\n if (!cancelled) localLayoutHtml = html\n }),\n renderHighlightedCode(mixedProviderCode, darkMode).then((html) => {\n if (!cancelled) mixedProviderHtml = html\n }),\n renderHighlightedCode(configCode, darkMode).then((html) => {\n if (!cancelled) configHtml = html\n }),\n renderHighlightedCode(layoutCode, darkMode).then((html) => {\n if (!cancelled) layoutHtml = html\n }),\n renderHighlightedCode(disableDefaultsCode, darkMode).then((html) => {\n if (!cancelled) disableDefaultsHtml = html\n })\n ]\n\n void Promise.all(tasks)\n\n return () => {\n cancelled = true\n }\n })\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Fonts</h1>\n <p class=\"text-on-surface-variant\">\n A unified font provider for Svelora that supports both Google Fonts and local font files\n through the same `fonts.families` API.\n </p>\n </div>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Default Preset</h2>\n <p class=\"text-sm text-on-surface-variant\">\n If you render `<Fonts />` without props or custom config, Svelora uses the built-in preset\n below. The current default display is `{fontsDefaults.display}` with preconnect set to\n `{fontsDefaults.preconnect ? 'true' : 'false'}`.\n </p>\n <CodeBlock title=\"Default Preset\" code={defaultPresetCode} html={defaultPresetHtml} />\n <div class=\"grid gap-4 md:grid-cols-3\">\n {#each defaultPresetItems as item (item.variable)}\n <Card class=\"border border-outline-variant/70\">\n <div class=\"space-y-2\">\n <p class=\"font-mono text-xs text-on-surface-variant\">{item.variable}</p>\n <h3 class=\"text-base font-semibold\">{item.family}</h3>\n <p class=\"text-sm text-on-surface-variant\">Weights: {item.weights}</p>\n <p class=\"text-sm text-on-surface-variant\">Utility: `{item.utility}`</p>\n </div>\n </Card>\n {/each}\n </div>\n <p class=\"text-sm text-on-surface-variant\">\n The preset is sourced from `defaultFontFamilies` and currently includes\n `{defaultFontFamilies.length}` families.\n </p>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Google Provider</h2>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <Fonts families={googleFamilies} />\n <h3 class=\"font-heading text-2xl font-semibold\">Poppins heading</h3>\n <p>Inter body copy is mapped to `--font-sans-family`.</p>\n <p class=\"font-mono mt-2 text-sm\">const provider = 'google';</p>\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Local Provider</h2>\n <CodeBlock title=\"Local Provider\" code={localProviderCode} html={localProviderHtml} />\n <p class=\"text-sm text-on-surface-variant\">\n Put your font files under `static/fonts/*`, map them to a CSS variable, then use utility\n classes like `font-sarabun` across the project.\n </p>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Local Font Setup</h2>\n <div class=\"grid gap-3 md:grid-cols-2\">\n {#each localSetupSteps as step, index (`${index}-${step}`)}\n <Card class=\"border border-outline-variant/70\">\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-primary\">Step {index + 1}</p>\n <p class=\"text-sm text-on-surface-variant\">{step}</p>\n </div>\n </Card>\n {/each}\n </div>\n <CodeBlock title=\"Local Font Setup\" code={localLayoutCode} html={localLayoutHtml} />\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Mixed Providers</h2>\n <CodeBlock title=\"Mixed Providers\" code={mixedProviderCode} html={mixedProviderHtml} />\n <p class=\"text-sm text-on-surface-variant\">\n Mix Google fonts for global typography with local assets for brand or language-specific\n families in the same provider.\n </p>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Using Global Config</h2>\n <CodeBlock title=\"defineConfig()\" code={configCode} html={configHtml} />\n <CodeBlock title=\"+layout.svelte\" code={layoutCode} html={layoutHtml} />\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disable Defaults</h2>\n <CodeBlock title=\"Disable Defaults\" code={disableDefaultsCode} html={disableDefaultsHtml} />\n <p class=\"text-sm text-on-surface-variant\">\n Set `fonts: false` when you want to fully manage font loading yourself.\n </p>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">API Reference</h2>\n <div class=\"grid gap-4 lg:grid-cols-2\">\n <Card class=\"border border-outline-variant/70\">\n <div class=\"space-y-4\">\n <h3 class=\"text-base font-semibold\">Fonts Options</h3>\n <div class=\"space-y-3\">\n {#each optionsReference as item (item.name)}\n <div class=\"border-b border-outline-variant/60 pb-3 last:border-b-0 last:pb-0\">\n <p class=\"font-mono text-xs text-on-surface-variant\">{item.name}</p>\n <p class=\"mt-1 text-sm font-medium\">{item.type}</p>\n <p class=\"mt-1 text-sm text-on-surface-variant\">{item.description}</p>\n </div>\n {/each}\n </div>\n </div>\n </Card>\n <Card class=\"border border-outline-variant/70\">\n <div class=\"space-y-4\">\n <h3 class=\"text-base font-semibold\">Font Definition</h3>\n <div class=\"space-y-3\">\n {#each familyReference as item (item.name)}\n <div class=\"border-b border-outline-variant/60 pb-3 last:border-b-0 last:pb-0\">\n <p class=\"font-mono text-xs text-on-surface-variant\">{item.name}</p>\n <p class=\"mt-1 text-sm font-medium\">{item.type}</p>\n <p class=\"mt-1 text-sm text-on-surface-variant\">{item.description}</p>\n </div>\n {/each}\n </div>\n </div>\n </Card>\n </div>\n <Card class=\"border border-outline-variant/70\">\n <div class=\"space-y-4\">\n <h3 class=\"text-base font-semibold\">Local Font Source</h3>\n <div class=\"grid gap-3 md:grid-cols-2\">\n {#each localSourceReference as item (item.name)}\n <div class=\"rounded-xl border border-outline-variant/60 p-4\">\n <p class=\"font-mono text-xs text-on-surface-variant\">{item.name}</p>\n <p class=\"mt-1 text-sm font-medium\">{item.type}</p>\n <p class=\"mt-1 text-sm text-on-surface-variant\">{item.description}</p>\n </div>\n {/each}\n </div>\n </div>\n </Card>\n </section>\n</div>\n",
79
80
  "icon": "<script lang=\"ts\">\n import { Icon } from '$lib/index.js'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Icon</h1>\n <p class=\"text-on-surface-variant\">\n Use the Icon component to display any icon from the\n <a\n href=\"https://icon-sets.iconify.design/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"text-primary hover:underline\">Iconify</a\n >\n library. Renders as an inline SVG with\n <code class=\"rounded bg-surface-container-highest px-1\">aria-hidden=\"true\"</code> by default.\n </p>\n </div>\n\n <!-- Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">name</code> prop with\n the Iconify format\n <code class=\"rounded bg-surface-container-highest px-1\">collection:icon-name</code>.\n </p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <Icon name=\"lucide:home\" />\n <Icon name=\"lucide:settings\" />\n <Icon name=\"lucide:user\" />\n <Icon name=\"lucide:mail\" />\n <Icon name=\"lucide:bell\" />\n <Icon name=\"lucide:search\" />\n <Icon name=\"lucide:heart\" />\n <Icon name=\"lucide:star\" />\n </div>\n </section>\n\n <!-- Size -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Size</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">size</code> prop to set\n both width and height. Accepts a number (pixels) or CSS string value. Defaults to\n <code class=\"rounded bg-surface-container-highest px-1\">24</code>.\n </p>\n <div class=\"flex flex-wrap items-end gap-6 rounded-lg bg-surface-container-high p-4\">\n {#each [16, 20, 24, 32, 48] as size (size)}\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:rocket\" {size} />\n <span class=\"text-xs text-on-surface-variant\">{size}px</span>\n </div>\n {/each}\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:rocket\" size=\"2rem\" />\n <span class=\"text-xs text-on-surface-variant\">2rem</span>\n </div>\n </div>\n </section>\n\n <!-- Color -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Color</h2>\n <p class=\"text-sm text-on-surface-variant\">\n The icon inherits <code class=\"rounded bg-surface-container-highest px-1\"\n >currentColor</code\n >\n from its parent by default. Use the\n <code class=\"rounded bg-surface-container-highest px-1\">color</code> prop for a CSS\n color value, or Tailwind\n <code class=\"rounded bg-surface-container-highest px-1\">text-*</code> classes via\n <code class=\"rounded bg-surface-container-highest px-1\">class</code>.\n </p>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">With Tailwind classes</p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <Icon name=\"lucide:circle\" class=\"text-primary\" />\n <Icon name=\"lucide:circle\" class=\"text-secondary\" />\n <Icon name=\"lucide:circle\" class=\"text-tertiary\" />\n <Icon name=\"lucide:circle\" class=\"text-success\" />\n <Icon name=\"lucide:circle\" class=\"text-warning\" />\n <Icon name=\"lucide:circle\" class=\"text-error\" />\n <Icon name=\"lucide:circle\" class=\"text-info\" />\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">With color prop</p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <Icon name=\"lucide:circle\" color=\"red\" />\n <Icon name=\"lucide:circle\" color=\"#22c55e\" />\n <Icon name=\"lucide:circle\" color=\"rgb(59, 130, 246)\" />\n <Icon name=\"lucide:circle\" color=\"orange\" />\n </div>\n\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Inheriting parent color</p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <span class=\"flex items-center gap-1 text-primary\">\n <Icon name=\"lucide:info\" size={16} />\n Inherits primary\n </span>\n <span class=\"flex items-center gap-1 text-error\">\n <Icon name=\"lucide:alert-triangle\" size={16} />\n Inherits error\n </span>\n <span class=\"flex items-center gap-1 text-success\">\n <Icon name=\"lucide:check-circle\" size={16} />\n Inherits success\n </span>\n </div>\n </section>\n\n <!-- Flip -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Flip</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use <code class=\"rounded bg-surface-container-highest px-1\">flipH</code> and\n <code class=\"rounded bg-surface-container-highest px-1\">flipV</code> to mirror the icon horizontally\n or vertically. Combining both is optimized into a 180&deg; rotation.\n </p>\n <div class=\"flex flex-wrap items-center gap-8 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:arrow-right\" />\n <span class=\"text-xs text-on-surface-variant\">Normal</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:arrow-right\" flipH />\n <span class=\"text-xs text-on-surface-variant\">flipH</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:arrow-right\" flipV />\n <span class=\"text-xs text-on-surface-variant\">flipV</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:arrow-right\" flipH flipV />\n <span class=\"text-xs text-on-surface-variant\">flipH + flipV</span>\n </div>\n </div>\n </section>\n\n <!-- Rotate -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Rotate</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">rotate</code> prop for\n quarter-turn rotation (<code class=\"rounded bg-surface-container-highest px-1\">0</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">90</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">180</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">270</code>). For arbitrary\n angles, use a Tailwind class like\n <code class=\"rounded bg-surface-container-highest px-1\">rotate-45</code>.\n </p>\n <div class=\"flex flex-wrap items-center gap-8 rounded-lg bg-surface-container-high p-4\">\n {#each [0, 90, 180, 270] as deg (deg)}\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:arrow-up\" rotate={deg as 0 | 90 | 180 | 270} />\n <span class=\"text-xs text-on-surface-variant\">{deg}&deg;</span>\n </div>\n {/each}\n <span class=\"mx-2 text-on-surface-variant\">|</span>\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:arrow-up\" class=\"rotate-45\" />\n <span class=\"text-xs text-on-surface-variant\">CSS 45&deg;</span>\n </div>\n </div>\n </section>\n\n <!-- Class -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Class</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">class</code> prop to add\n Tailwind utilities. Classes are merged with\n <code class=\"rounded bg-surface-container-highest px-1\">tailwind-merge</code>, so\n conflicting utilities like\n <code class=\"rounded bg-surface-container-highest px-1\">shrink</code> correctly override\n the default\n <code class=\"rounded bg-surface-container-highest px-1\">shrink-0</code>.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:star\" class=\"text-warning\" />\n <span class=\"text-xs text-on-surface-variant\">text-warning</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:heart\" class=\"animate-pulse text-error\" />\n <span class=\"text-xs text-on-surface-variant\">animate-pulse</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:loader\" class=\"animate-spin text-primary\" />\n <span class=\"text-xs text-on-surface-variant\">animate-spin</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:zap\" class=\"text-warning drop-shadow-lg\" />\n <span class=\"text-xs text-on-surface-variant\">drop-shadow</span>\n </div>\n </div>\n </section>\n\n <!-- Icon Sets -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Icon Sets</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Supports any collection from the Iconify library. Use the format\n <code class=\"rounded bg-surface-container-highest px-1\">collection:icon-name</code>.\n </p>\n <div class=\"overflow-x-auto\">\n <table class=\"w-full text-sm\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-3 py-2 text-left font-medium text-on-surface-variant\"\n >Collection</th\n >\n <th class=\"px-3 py-2 text-left font-medium text-on-surface-variant\">Icon</th\n >\n <th class=\"px-3 py-2 text-left font-medium text-on-surface-variant\">Name</th\n >\n </tr>\n </thead>\n <tbody>\n {#each [{ name: 'lucide:github', label: 'Lucide' }, { name: 'mdi:github', label: 'Material Design Icons' }, { name: 'ph:github-logo', label: 'Phosphor' }, { name: 'tabler:brand-github', label: 'Tabler' }, { name: 'heroicons:code-bracket', label: 'Heroicons' }, { name: 'ri:github-fill', label: 'Remix Icon' }, { name: 'solar:star-bold', label: 'Solar' }] as icon (icon.name)}\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-2 text-on-surface-variant\">{icon.label}</td>\n <td class=\"px-3 py-2\">\n <Icon name={icon.name} />\n </td>\n <td class=\"px-3 py-2 font-mono text-xs\">{icon.name}</td>\n </tr>\n {/each}\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Examples</h2>\n\n <!-- Inline with text -->\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Inline with text</p>\n <div class=\"flex flex-col gap-2\">\n <p class=\"flex items-center gap-1.5 text-sm\">\n <Icon name=\"lucide:check-circle\" size={16} class=\"text-success\" />\n Payment successful\n </p>\n <p class=\"flex items-center gap-1.5 text-sm\">\n <Icon name=\"lucide:alert-triangle\" size={16} class=\"text-warning\" />\n Storage almost full\n </p>\n <p class=\"flex items-center gap-1.5 text-sm\">\n <Icon name=\"lucide:x-circle\" size={16} class=\"text-error\" />\n Connection failed\n </p>\n </div>\n </div>\n\n <!-- Icon grid -->\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Feature grid</p>\n <div class=\"grid grid-cols-4 gap-4\">\n {#each [{ name: 'lucide:shield-check', label: 'Secure', color: 'text-success' }, { name: 'lucide:zap', label: 'Fast', color: 'text-warning' }, { name: 'lucide:globe', label: 'Global', color: 'text-info' }, { name: 'lucide:heart', label: 'Loved', color: 'text-error' }] as item (item.name)}\n <div\n class=\"flex flex-col items-center gap-2 rounded-lg bg-surface-container p-3\"\n >\n <Icon name={item.name} size={32} class={item.color} />\n <span class=\"text-xs font-medium\">{item.label}</span>\n </div>\n {/each}\n </div>\n </div>\n\n <!-- Loading states -->\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Loading states</p>\n <div class=\"flex items-center gap-6\">\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"lucide:loader-2\" class=\"animate-spin text-primary\" />\n <span class=\"text-xs text-on-surface-variant\">Spinner</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"svg-spinners:ring-resize\" class=\"text-secondary\" />\n <span class=\"text-xs text-on-surface-variant\">SVG Spinner</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"svg-spinners:3-dots-bounce\" class=\"text-tertiary\" />\n <span class=\"text-xs text-on-surface-variant\">Dots</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <Icon name=\"svg-spinners:pulse-3\" class=\"text-info\" />\n <span class=\"text-xs text-on-surface-variant\">Pulse</span>\n </div>\n </div>\n </div>\n </section>\n</div>\n",
80
81
  "link": "<script lang=\"ts\">\n import { Link, Icon } from '$lib/index.js'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Link</h1>\n <p class=\"text-on-surface-variant\">\n Use the Link component to create hyperlinks with automatic active state detection.\n Renders as an anchor tag when <code class=\"rounded bg-surface-container-highest px-1\"\n >href</code\n >\n is provided, otherwise renders as a button.\n </p>\n </div>\n\n <!-- Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Usage</h2>\n <p class=\"text-sm text-on-surface-variant\">\n The Link component is styled by default with <code\n class=\"rounded bg-surface-container-highest px-1\">text-on-surface-variant</code\n >\n when inactive and\n <code class=\"rounded bg-surface-container-highest px-1\">text-primary</code>\n when active, with a\n <code class=\"rounded bg-surface-container-highest px-1\">hover:text-on-surface</code> transition.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\">Link</Link>\n </div>\n </section>\n\n <!-- InactiveClass -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">InactiveClass</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">inactiveClass</code> prop\n to apply additional classes when the link is inactive.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/non-existent\" inactiveClass=\"opacity-50\">Dimmed when inactive</Link>\n <Link href=\"/non-existent\" inactiveClass=\"italic\">Italic when inactive</Link>\n </div>\n </section>\n\n <!-- ActiveClass -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">ActiveClass</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">activeClass</code> prop to\n apply additional classes when the link is active.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\" activeClass=\"font-bold\">Bold when active</Link>\n <Link href=\"/link\" activeClass=\"underline underline-offset-4\"\n >Underlined when active</Link\n >\n <Link href=\"/link\" activeClass=\"font-bold underline underline-offset-4\"\n >Bold + underline</Link\n >\n </div>\n </section>\n\n <!-- Active -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Active</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">active</code> prop to force\n the active state, overriding auto-detection from the current route.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\" active={true}>Active (forced)</Link>\n <Link href=\"/link\" active={false}>Inactive (forced)</Link>\n <Link href=\"/link\">Auto-detected</Link>\n </div>\n </section>\n\n <!-- Matching Modes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Matching Modes</h2>\n <p class=\"text-sm text-on-surface-variant\">\n By default, a link is active when the current URL starts with the <code\n class=\"rounded bg-surface-container-highest px-1\">href</code\n >. Use <code class=\"rounded bg-surface-container-highest px-1\">exact</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">exactQuery</code>, and\n <code class=\"rounded bg-surface-container-highest px-1\">exactHash</code> to control this behavior.\n </p>\n <div class=\"overflow-x-auto\">\n <table class=\"w-full text-sm\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-3 py-2 text-left font-medium text-on-surface-variant\">Prop</th\n >\n <th class=\"px-3 py-2 text-left font-medium text-on-surface-variant\">Href</th\n >\n <th class=\"px-3 py-2 text-left font-medium text-on-surface-variant\"\n >Preview</th\n >\n <th class=\"px-3 py-2 text-left font-medium text-on-surface-variant\"\n >Description</th\n >\n </tr>\n </thead>\n <tbody>\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-2 font-mono text-xs text-on-surface-variant\">default</td>\n <td class=\"px-3 py-2 font-mono text-xs\">/link</td>\n <td class=\"px-3 py-2\">\n <Link href=\"/link\" activeClass=\"font-semibold\">Link</Link>\n </td>\n <td class=\"px-3 py-2 text-on-surface-variant\"\n >Prefix match — active if URL starts with href</td\n >\n </tr>\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-2 font-mono text-xs text-on-surface-variant\">exact</td>\n <td class=\"px-3 py-2 font-mono text-xs\">/link</td>\n <td class=\"px-3 py-2\">\n <Link href=\"/link\" exact activeClass=\"font-semibold\">Link (exact)</Link>\n </td>\n <td class=\"px-3 py-2 text-on-surface-variant\"\n >Only active when pathname is exactly \"/link\"</td\n >\n </tr>\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-2 font-mono text-xs text-on-surface-variant\"\n >exactHash</td\n >\n <td class=\"px-3 py-2 font-mono text-xs\">/link#section</td>\n <td class=\"px-3 py-2\">\n <Link href=\"/link#section\" exactHash activeClass=\"font-semibold\"\n >#section</Link\n >\n </td>\n <td class=\"px-3 py-2 text-on-surface-variant\"\n >Hash must also match for active state</td\n >\n </tr>\n <tr>\n <td class=\"px-3 py-2 font-mono text-xs text-on-surface-variant\"\n >exactQuery</td\n >\n <td class=\"px-3 py-2 font-mono text-xs\">/link?tab=1</td>\n <td class=\"px-3 py-2\">\n <Link href=\"/link?tab=1\" exactQuery activeClass=\"font-semibold\"\n >?tab=1</Link\n >\n </td>\n <td class=\"px-3 py-2 text-on-surface-variant\"\n >Query params must exactly match</td\n >\n </tr>\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- disabled -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disabled</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">disabled</code> prop to\n disable the link. On anchors, it removes\n <code class=\"rounded bg-surface-container-highest px-1\">href</code>, sets\n <code class=\"rounded bg-surface-container-highest px-1\">aria-disabled</code>\n and\n <code class=\"rounded bg-surface-container-highest px-1\">role=\"link\"</code>. On buttons,\n it uses the native disabled attribute.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\" disabled>Disabled anchor</Link>\n <Link disabled>Disabled button</Link>\n </div>\n </section>\n\n <!-- Raw -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Raw</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">raw</code> prop to strip\n all default styling. Only\n <code class=\"rounded bg-surface-container-highest px-1\">class</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">activeClass</code>, and\n <code class=\"rounded bg-surface-container-highest px-1\">inactiveClass</code> are applied.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link\n href=\"/link\"\n raw\n class=\"text-on-surface underline decoration-primary underline-offset-4 hover:decoration-2\"\n >\n Custom styled\n </Link>\n <Link\n href=\"/link\"\n raw\n class=\"rounded-md bg-primary-container px-3 py-1 text-on-primary-container hover:bg-primary-container/80\"\n >\n Chip style\n </Link>\n <Link\n href=\"/link\"\n raw\n active={true}\n activeClass=\"bg-primary text-on-primary\"\n inactiveClass=\"bg-surface-container-highest text-on-surface-variant hover:bg-surface-container-high\"\n class=\"rounded-full px-4 py-1.5 text-sm font-medium transition-colors\"\n >\n Pill style\n </Link>\n </div>\n </section>\n\n <!-- External -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">External</h2>\n <p class=\"text-sm text-on-surface-variant\">\n External URLs (<code class=\"rounded bg-surface-container-highest px-1\">http://</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">https://</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">//</code>) are auto-detected.\n The component adds\n <code class=\"rounded bg-surface-container-highest px-1\">target=\"_blank\"</code> and\n <code class=\"rounded bg-surface-container-highest px-1\">rel=\"noopener noreferrer\"</code>\n automatically. Use the\n <code class=\"rounded bg-surface-container-highest px-1\">external</code> prop to force this\n behavior on internal paths.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"https://svelte.dev\">\n <Icon name=\"lucide:external-link\" size=\"14\" class=\"mr-1\" />\n Svelte (auto)\n </Link>\n <Link href=\"https://tailwindcss.com\">\n <Icon name=\"lucide:external-link\" size=\"14\" class=\"mr-1\" />\n Tailwind CSS (auto)\n </Link>\n <Link href=\"/api/docs\" external>\n <Icon name=\"lucide:external-link\" size=\"14\" class=\"mr-1\" />\n API Docs (forced)\n </Link>\n </div>\n </section>\n\n <!-- Prefetch -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Prefetch</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Since the Link component extends native HTML anchor attributes, you can use SvelteKit's\n <code class=\"rounded bg-surface-container-highest px-1\"\n >data-sveltekit-preload-data</code\n >\n and\n <code class=\"rounded bg-surface-container-highest px-1\"\n >data-sveltekit-preload-code</code\n >\n attributes to control prefetching behavior.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\" data-sveltekit-preload-data=\"hover\">Preload on hover</Link>\n <Link href=\"/link\" data-sveltekit-preload-data=\"tap\">Preload on tap</Link>\n <Link href=\"/link\" data-sveltekit-preload-data=\"off\">No preload</Link>\n <Link href=\"/link\" data-sveltekit-preload-code=\"eager\">Preload code eagerly</Link>\n </div>\n </section>\n\n <!-- As Button -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">As Button</h2>\n <p class=\"text-sm text-on-surface-variant\">\n When no <code class=\"rounded bg-surface-container-highest px-1\">href</code> is provided,\n the component renders a button element with\n <code class=\"rounded bg-surface-container-highest px-1\">type=\"button\"</code> by default.\n Use the <code class=\"rounded bg-surface-container-highest px-1\">type</code> prop to change\n the button type.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link onclick={() => alert('Clicked!')}>Click action</Link>\n <Link type=\"submit\">Submit type</Link>\n <Link type=\"reset\">Reset type</Link>\n </div>\n </section>\n\n <!-- UI Slot Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">ui</code> prop to override\n styles on specific slots.\n </p>\n <div class=\"flex flex-wrap items-center gap-6 rounded-lg bg-surface-container-high p-4\">\n <Link href=\"/link\" ui={{ base: 'underline underline-offset-4 decoration-2' }}>\n Underlined\n </Link>\n <Link href=\"/link\" ui={{ base: 'font-bold text-lg' }}>Bold & Large</Link>\n <Link href=\"/link\" ui={{ base: 'uppercase tracking-wider text-xs font-semibold' }}>\n Uppercase\n </Link>\n </div>\n </section>\n\n <!-- States Overview -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">States</h2>\n <div class=\"overflow-x-auto\">\n <table class=\"w-full\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-3 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >State</th\n >\n <th class=\"px-3 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >&lt;a&gt;</th\n >\n <th class=\"px-3 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >&lt;button&gt;</th\n >\n </tr>\n </thead>\n <tbody>\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-3 text-sm font-medium text-on-surface-variant\"\n >Default</td\n >\n <td class=\"px-3 py-3\">\n <Link href=\"/demo\">Link text</Link>\n </td>\n <td class=\"px-3 py-3\">\n <Link>Button text</Link>\n </td>\n </tr>\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-3 text-sm font-medium text-on-surface-variant\">Active</td\n >\n <td class=\"px-3 py-3\">\n <Link href=\"/link\" active={true}>Link text</Link>\n </td>\n <td class=\"px-3 py-3\">\n <Link active={true}>Button text</Link>\n </td>\n </tr>\n <tr>\n <td class=\"px-3 py-3 text-sm font-medium text-on-surface-variant\"\n >Disabled</td\n >\n <td class=\"px-3 py-3\">\n <Link href=\"/link\" disabled>Link text</Link>\n </td>\n <td class=\"px-3 py-3\">\n <Link disabled>Button text</Link>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Examples</h2>\n\n <!-- Navigation Bar -->\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Navigation bar</p>\n <nav class=\"flex items-center gap-6\">\n <Link href=\"/\" exact activeClass=\"font-semibold\">Home</Link>\n <Link href=\"/about\" activeClass=\"font-semibold\">About</Link>\n <Link href=\"/link\" activeClass=\"font-semibold\" active={true}>Docs</Link>\n <Link href=\"/pricing\" activeClass=\"font-semibold\">Pricing</Link>\n </nav>\n </div>\n\n <!-- Sidebar Menu -->\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Sidebar menu</p>\n <div class=\"flex w-56 flex-col gap-0.5\">\n <Link\n href=\"/link\"\n raw\n active={true}\n activeClass=\"bg-primary-container text-on-primary-container font-medium\"\n inactiveClass=\"text-on-surface-variant hover:bg-surface-container-highest\"\n class=\"flex items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors\"\n >\n <Icon name=\"lucide:layout-dashboard\" size=\"16\" />\n Dashboard\n </Link>\n <Link\n href=\"/settings\"\n raw\n activeClass=\"bg-primary-container text-on-primary-container font-medium\"\n inactiveClass=\"text-on-surface-variant hover:bg-surface-container-highest\"\n class=\"flex items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors\"\n >\n <Icon name=\"lucide:settings\" size=\"16\" />\n Settings\n </Link>\n <Link\n href=\"/profile\"\n raw\n activeClass=\"bg-primary-container text-on-primary-container font-medium\"\n inactiveClass=\"text-on-surface-variant hover:bg-surface-container-highest\"\n class=\"flex items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors\"\n >\n <Icon name=\"lucide:user\" size=\"16\" />\n Profile\n </Link>\n </div>\n </div>\n\n <!-- Breadcrumb -->\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Breadcrumb</p>\n <nav class=\"flex items-center gap-1 text-sm\">\n <Link href=\"/\">Home</Link>\n <Icon name=\"lucide:chevron-right\" size=\"14\" class=\"text-on-surface-variant/50\" />\n <Link href=\"/link\">Components</Link>\n <Icon name=\"lucide:chevron-right\" size=\"14\" class=\"text-on-surface-variant/50\" />\n <span class=\"text-on-surface\">Link</span>\n </nav>\n </div>\n\n <!-- Footer Links -->\n <div class=\"space-y-2 rounded-lg bg-surface-container-high p-4\">\n <p class=\"text-xs font-medium text-on-surface-variant uppercase\">Footer links</p>\n <div class=\"flex items-center gap-4 text-sm\">\n <Link href=\"https://github.com\">\n <Icon name=\"lucide:github\" size=\"14\" class=\"mr-1\" />\n GitHub\n </Link>\n <span class=\"text-outline-variant\">|</span>\n <Link href=\"https://svelte.dev\">\n <Icon name=\"lucide:external-link\" size=\"14\" class=\"mr-1\" />\n Svelte\n </Link>\n <span class=\"text-outline-variant\">|</span>\n <Link\n href=\"/link\"\n raw\n class=\"text-on-surface-variant underline hover:text-on-surface\"\n >Privacy Policy</Link\n >\n </div>\n </div>\n </section>\n</div>\n",
82
+ "locale-button": "<script lang=\"ts\">\n import { CodeBlock, LocaleButton } from '$lib/index.js'\n import type { LocaleButtonLocale } from '$lib/index.js'\n\n const locales: LocaleButtonLocale[] = [\n {\n code: 'en',\n label: 'English',\n shortLabel: 'EN',\n description: 'Default content language'\n },\n {\n code: 'th',\n label: 'Thai',\n shortLabel: 'TH',\n description: 'Thai translation'\n },\n {\n code: 'ja',\n label: 'Japanese',\n shortLabel: 'JA',\n description: 'Japanese translation'\n }\n ]\n\n const variants = ['solid', 'outline', 'soft', 'subtle', 'ghost', 'link'] as const\n const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const\n const integrationStrategies = [\n {\n title: 'Callback Strategy',\n badge: 'Recommended',\n description:\n 'Use onLocaleChange when your app controls locale changes in code. This works well with Paraglide cookie-based setups and custom i18n stores.',\n bullets: [\n 'Keeps the current pathname unchanged',\n 'Works with setLocale(..., { reload: false })',\n 'Best default for consumer apps'\n ]\n },\n {\n title: 'Href Strategy',\n badge: 'Optional',\n description:\n 'Use getLocaleHref when your app intentionally exposes locale-specific URLs such as /th/docs or /en/docs.',\n bullets: [\n 'Generates per-locale links',\n 'Useful for URL-prefix routing',\n 'Navigation happens through hrefs instead of imperative state'\n ]\n },\n {\n title: 'Custom I18n',\n badge: 'Flexible',\n description:\n 'You can use LocaleButton without Paraglide at all. Pass your own locale state, persistence, and translation runtime.',\n bullets: [\n 'No hard dependency on Paraglide',\n 'Works with stores, cookies, or API-backed preferences',\n 'Good for non-SvelteKit or mixed stacks'\n ]\n }\n ] as const\n\n const localeItemFields = [\n {\n field: 'code',\n required: 'Yes',\n description: 'The locale identifier used by your i18n layer, such as en or th.'\n },\n {\n field: 'label',\n required: 'Yes',\n description: 'The full label rendered in the dropdown menu.'\n },\n {\n field: 'shortLabel',\n required: 'No',\n description: 'Compact text for the trigger or badge, such as EN or TH.'\n },\n {\n field: 'description',\n required: 'No',\n description: 'Secondary helper text shown inside the menu.'\n },\n {\n field: 'href',\n required: 'No',\n description: 'A precomputed locale-specific link if your app uses href navigation.'\n },\n {\n field: 'hreflang',\n required: 'No',\n description: 'Optional hreflang value forwarded to anchor items.'\n },\n {\n field: 'disabled',\n required: 'No',\n description: 'Disables a specific locale item.'\n }\n ] as const\n\n const integrationChecklist = [\n 'Use onLocaleChange when you do not want locale prefixes in the URL.',\n 'Use getLocaleHref only when your routing strategy intentionally includes locale-specific paths.',\n 'Pass locale from your own source of truth so the trigger always reflects the current language.',\n 'Provide shortLabel values when you want compact trigger text such as EN, TH, or JA.',\n 'Use the children snippet when your product needs a fully custom trigger design.'\n ] as const\n\n let locale = $state('en')\n let customLocale = $state('th')\n\n const paraglideSetLocaleExample =\n `<script lang=\"ts\">\n import { LocaleButton, type LocaleButtonLocale } from 'svelora'\n import { setLocale, toLocale } from '$lib/paraglide/runtime'\n \n const locales: LocaleButtonLocale[] = [\n { code: 'en', label: 'English', shortLabel: 'EN' },\n { code: 'th', label: 'Thai', shortLabel: 'TH' }\n ]\n \n let locale = 'en'\n<` +\n `/script>\n\n<LocaleButton\n {locale}\n {locales}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n const target = toLocale(nextLocale)\n if (target) {\n return setLocale(target)\n }\n }}\n/>`\n\n const paraglideCookieExample =\n `<script lang=\"ts\">\n import { LocaleButton, type LocaleButtonLocale } from 'svelora'\n import { setLocale, toLocale } from '$lib/paraglide/runtime'\n \n const locales: LocaleButtonLocale[] = [\n { code: 'en', label: 'English', shortLabel: 'EN' },\n { code: 'th', label: 'Thai', shortLabel: 'TH' }\n ]\n \n let locale = 'en'\n<` +\n `/script>\n\n<LocaleButton\n {locale}\n {locales}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n const target = toLocale(nextLocale)\n if (target) {\n return setLocale(target, { reload: false })\n }\n }}\n/>`\n\n const consumerAppExample =\n `<script lang=\"ts\">\n import { LocaleButton, type LocaleButtonLocale } from 'svelora'\n import { setLocale, toLocale } from '$lib/paraglide/runtime'\n \n const locales: LocaleButtonLocale[] = [\n { code: 'en', label: 'English', shortLabel: 'EN' },\n { code: 'th', label: 'Thai', shortLabel: 'TH' }\n ]\n \n let locale = 'en'\n<` +\n `/script>\n\n<LocaleButton\n {locales}\n {locale}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n const target = toLocale(nextLocale)\n if (target) {\n return setLocale(target, { reload: false })\n }\n }}\n/>`\n\n const hrefStrategyExample =\n `<script lang=\"ts\">\n import { LocaleButton, type LocaleButtonLocale } from 'svelora'\n import { localizeHref } from '$lib/paraglide/runtime'\n \n const locales: LocaleButtonLocale[] = [\n { code: 'en', label: 'English', shortLabel: 'EN' },\n { code: 'th', label: 'Thai', shortLabel: 'TH' }\n ]\n \n let locale = 'en'\n const pathname = '/docs/components/locale-button'\n<` +\n `/script>\n\n<LocaleButton\n {locales}\n {locale}\n getLocaleHref={(nextLocale) => localizeHref(pathname, { locale: nextLocale })}\n/>`\n\n const customI18nExample =\n `<script lang=\"ts\">\n import { LocaleButton, type LocaleButtonLocale } from 'svelora'\n \n const locales: LocaleButtonLocale[] = [\n { code: 'en', label: 'English', shortLabel: 'EN' },\n { code: 'th', label: 'Thai', shortLabel: 'TH' }\n ]\n \n let locale = 'en'\n \n function applyLocale(nextLocale: string) {\n locale = nextLocale\n localStorage.setItem('preferred-locale', nextLocale)\n }\n<` +\n `/script>\n\n<LocaleButton\n {locales}\n {locale}\n onLocaleChange={(nextLocale) => {\n applyLocale(nextLocale)\n }}\n/>`\n\n const localeShapeExample = `import type { LocaleButtonLocale } from 'svelora'\n\nconst locales: LocaleButtonLocale[] = [\n {\n code: 'en',\n label: 'English',\n shortLabel: 'EN',\n description: 'Default content language'\n },\n {\n code: 'th',\n label: 'Thai',\n shortLabel: 'TH',\n description: 'Thai translation',\n href: '/th/docs',\n hreflang: 'th'\n }\n]`\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">LocaleButton</h1>\n <p class=\"text-on-surface-variant\">\n A language switcher button designed to work nicely with Paraglide. Use\n <code class=\"rounded bg-surface-container-highest px-1\">onLocaleChange</code> for\n <code class=\"rounded bg-surface-container-highest px-1\">setLocale()</code> flows\n while keeping the current path unchanged.\n </p>\n </div>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic Usage</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <LocaleButton\n {locales}\n {locale}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n }}\n />\n <span class=\"text-sm text-on-surface-variant\">Current locale: {locale}</span>\n </div>\n </section>\n\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold\">Choose Your Strategy</h2>\n <p class=\"text-sm text-on-surface-variant\">\n <code class=\"rounded bg-surface-container-highest px-1\">LocaleButton</code> is only\n the UI layer. Your app decides how locale changes are applied.\n </p>\n <div class=\"grid gap-4 lg:grid-cols-3\">\n {#each integrationStrategies as strategy (strategy.title)}\n <div class=\"space-y-3 rounded-2xl border border-outline-variant bg-surface-container/40 p-5\">\n <div class=\"flex items-center justify-between gap-3\">\n <h3 class=\"text-base font-semibold\">{strategy.title}</h3>\n <span class=\"rounded-full bg-primary/10 px-2.5 py-1 text-xs font-medium text-primary\">\n {strategy.badge}\n </span>\n </div>\n <p class=\"text-sm text-on-surface-variant\">{strategy.description}</p>\n <ul class=\"space-y-2 text-sm text-on-surface-variant\">\n {#each strategy.bullets as bullet (bullet)}\n <li>{bullet}</li>\n {/each}\n </ul>\n </div>\n {/each}\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Paraglide with setLocale</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the selection callback when your app already manages locale changes in code.\n </p>\n <CodeBlock title=\"Paraglide setLocale()\" code={paraglideSetLocaleExample} />\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <LocaleButton\n {locales}\n {locale}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n }}\n />\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Use In Consumer Apps</h2>\n <p class=\"text-sm text-on-surface-variant\">\n <code class=\"rounded bg-surface-container-highest px-1\">LocaleButton</code> is\n exported from the\n <code class=\"rounded bg-surface-container-highest px-1\">svelora</code> package and can\n be used in any app that installs this library.\n </p>\n <p class=\"text-sm text-on-surface-variant\">\n The component does not depend on Paraglide internally. Your app provides\n <code class=\"rounded bg-surface-container-highest px-1\">locale</code>,\n <code class=\"rounded bg-surface-container-highest px-1\">locales</code>, and the\n locale-change logic through\n <code class=\"rounded bg-surface-container-highest px-1\">onLocaleChange</code> or\n <code class=\"rounded bg-surface-container-highest px-1\">getLocaleHref</code>.\n </p>\n <CodeBlock title=\"Consumer app example\" code={consumerAppExample} />\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Keep The Same Path</h2>\n <p class=\"text-sm text-on-surface-variant\">\n With cookie-based Paraglide strategy, you can switch locale without adding\n <code class=\"rounded bg-surface-container-highest px-1\">/th</code> or other locale\n prefixes to the URL.\n </p>\n <CodeBlock title=\"Paraglide without locale prefix\" code={paraglideCookieExample} />\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <LocaleButton\n {locales}\n {locale}\n disableCurrentLocale={false}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n }}\n />\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Use Locale Prefix URLs</h2>\n <p class=\"text-sm text-on-surface-variant\">\n If your product intentionally uses locale-prefixed routes such as\n <code class=\"rounded bg-surface-container-highest px-1\">/th/docs</code>, provide\n <code class=\"rounded bg-surface-container-highest px-1\">getLocaleHref</code>. This\n keeps navigation declarative and lets the button render locale-specific links.\n </p>\n <CodeBlock title=\"Href strategy with localizeHref()\" code={hrefStrategyExample} />\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Use Without Paraglide</h2>\n <p class=\"text-sm text-on-surface-variant\">\n The component works with any locale source of truth. You can connect it to a Svelte\n store, cookies, localStorage, an API-backed user preference, or another i18n runtime.\n </p>\n <CodeBlock title=\"Custom i18n integration\" code={customI18nExample} />\n </section>\n\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold\">Locale Item Shape</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Each locale entry is just data. Start with\n <code class=\"rounded bg-surface-container-highest px-1\">code</code> and\n <code class=\"rounded bg-surface-container-highest px-1\">label</code>, then add\n optional fields only when your app needs them.\n </p>\n <CodeBlock title=\"LocaleButtonLocale[]\" code={localeShapeExample} />\n <div class=\"overflow-hidden rounded-2xl border border-outline-variant\">\n <table class=\"w-full text-left text-sm\">\n <thead class=\"bg-surface-container\">\n <tr>\n <th class=\"px-4 py-3 font-semibold\">Field</th>\n <th class=\"px-4 py-3 font-semibold\">Required</th>\n <th class=\"px-4 py-3 font-semibold\">Purpose</th>\n </tr>\n </thead>\n <tbody>\n {#each localeItemFields as field (field.field)}\n <tr class=\"border-t border-outline-variant/70\">\n <td class=\"px-4 py-3 font-mono text-xs\">{field.field}</td>\n <td class=\"px-4 py-3 text-on-surface-variant\">{field.required}</td>\n <td class=\"px-4 py-3 text-on-surface-variant\">{field.description}</td>\n </tr>\n {/each}\n </tbody>\n </table>\n </div>\n </section>\n\n <section class=\"space-y-4\">\n <h2 class=\"text-lg font-semibold\">Integration Checklist</h2>\n <div class=\"rounded-2xl border border-outline-variant bg-surface-container/40 p-5\">\n <ul class=\"space-y-3 text-sm text-on-surface-variant\">\n {#each integrationChecklist as item (item)}\n <li>{item}</li>\n {/each}\n </ul>\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants</h2>\n <div class=\"flex flex-wrap items-center gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each variants as variant (variant)}\n <LocaleButton\n {locales}\n {locale}\n {variant}\n size=\"sm\"\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n }}\n />\n {/each}\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"flex flex-wrap items-end gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <LocaleButton\n {locales}\n {locale}\n {size}\n onLocaleChange={(nextLocale) => {\n locale = nextLocale\n }}\n />\n {/each}\n </div>\n </section>\n\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Trigger</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the\n <code class=\"rounded bg-surface-container-highest px-1\">children</code> snippet to\n fully control the trigger content while keeping the dropdown behavior.\n </p>\n <div class=\"rounded-lg bg-surface-container-high p-4\">\n <LocaleButton\n {locales}\n locale={customLocale}\n square={false}\n variant=\"soft\"\n color=\"primary\"\n onLocaleChange={(nextLocale) => {\n customLocale = nextLocale\n }}\n >\n {#snippet children({ currentLocale, open })}\n <span class=\"flex items-center gap-2\">\n <span>{currentLocale?.label ?? 'Language'}</span>\n <span class=\"text-xs text-on-surface-variant\">\n {open ? 'Open' : currentLocale?.code.toUpperCase()}\n </span>\n </span>\n {/snippet}\n </LocaleButton>\n </div>\n </section>\n</div>\n",
81
83
  "kbd": "<script lang=\"ts\">\n import { Kbd, useKbd } from '$lib/index.js'\n\n const colors = [\n 'primary',\n 'secondary',\n 'success',\n 'warning',\n 'error',\n 'info',\n 'surface'\n ] as const\n const variants = ['solid', 'outline', 'soft', 'subtle'] as const\n const sizes = ['sm', 'md', 'lg'] as const\n\n let shortcutLog = $state<string[]>([])\n let searchOpen = $state(false)\n\n const kbd = useKbd({\n shortcuts: {\n 'ctrl+k': () => {\n searchOpen = !searchOpen\n shortcutLog = [...shortcutLog, 'Ctrl+K → Toggle search'].slice(-5)\n },\n 'ctrl+shift+p': () => {\n shortcutLog = [...shortcutLog, 'Ctrl+Shift+P → Command palette'].slice(-5)\n },\n escape: () => {\n searchOpen = false\n shortcutLog = [...shortcutLog, 'Escape → Close'].slice(-5)\n }\n },\n captureModifiers: true\n })\n\n const modifierKeys = ['meta', 'ctrl', 'alt', 'shift'] as const\n const specialKeys = [\n 'enter',\n 'escape',\n 'tab',\n 'backspace',\n 'delete',\n 'space',\n 'capslock'\n ] as const\n const arrowKeys = ['arrowup', 'arrowdown', 'arrowleft', 'arrowright'] as const\n const navKeys = ['pageup', 'pagedown', 'home', 'end'] as const\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Kbd</h1>\n <p class=\"text-on-surface-variant\">\n Keyboard key indicator for displaying shortcuts and key combinations.\n </p>\n </div>\n\n <!-- Basic -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic</h2>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n <Kbd value=\"K\" />\n <Kbd value=\"Enter\" />\n <Kbd value=\"Escape\" />\n <Kbd value=\"Tab\" />\n </div>\n </section>\n\n <!-- Modifier Keys -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Modifier Keys</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Platform-aware: Mac shows symbols, others show text labels.\n </p>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n {#each modifierKeys as key (key)}\n <Kbd value={key} />\n {/each}\n </div>\n </section>\n\n <!-- Special Keys -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Special Keys</h2>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n {#each specialKeys as key (key)}\n <Kbd value={key} />\n {/each}\n </div>\n </section>\n\n <!-- Arrow & Navigation Keys -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Arrow & Navigation Keys</h2>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n {#each arrowKeys as key (key)}\n <Kbd value={key} />\n {/each}\n <span class=\"mx-1 text-on-surface-variant\">|</span>\n {#each navKeys as key (key)}\n <Kbd value={key} />\n {/each}\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"flex flex-wrap items-center gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <div class=\"flex items-center gap-1\">\n <span class=\"text-sm text-on-surface-variant\">{size}:</span>\n <Kbd value=\"K\" {size} />\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Variants -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants</h2>\n <div class=\"space-y-3 rounded-lg bg-surface-container-high p-4\">\n {#each variants as variant (variant)}\n <div class=\"flex flex-wrap items-center gap-2\">\n <span class=\"w-16 text-sm text-on-surface-variant\">{variant}</span>\n {#each colors as color (color)}\n <Kbd value=\"K\" {variant} {color} />\n {/each}\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Children Slot -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Children Slot</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the default snippet for custom key labels.\n </p>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n <Kbd>F1</Kbd>\n <Kbd>F12</Kbd>\n <Kbd>PgUp</Kbd>\n <Kbd>PgDn</Kbd>\n <Kbd>Ins</Kbd>\n <Kbd>Fn</Kbd>\n </div>\n </section>\n\n <!-- Keyboard Shortcuts -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Keyboard Shortcuts</h2>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n {#each [{ label: 'Copy', keys: ['meta', 'C'] }, { label: 'Paste', keys: ['meta', 'V'] }, { label: 'Save', keys: ['meta', 'S'] }, { label: 'Search', keys: ['meta', 'K'] }, { label: 'Undo', keys: ['meta', 'Z'] }, { label: 'Redo', keys: ['meta', 'shift', 'Z'] }] as shortcut (shortcut.label)}\n <div class=\"flex items-center justify-between\">\n <span class=\"text-sm\">{shortcut.label}</span>\n <div class=\"flex items-center gap-1\">\n {#each shortcut.keys as key, i (i)}\n {#if i > 0}\n <span class=\"text-on-surface-variant\">+</span>\n {/if}\n <Kbd value={key} />\n {/each}\n </div>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- UI Slot Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Slot Overrides</h2>\n <div class=\"flex flex-wrap items-center gap-2 rounded-lg bg-surface-container-high p-4\">\n <Kbd value=\"K\" ui={{ base: 'rounded-md' }} />\n <Kbd value=\"meta\" ui={{ base: 'rounded-full px-2' }} />\n <Kbd value=\"Enter\" ui={{ base: 'rounded-lg px-2 shadow-sm' }} variant=\"soft\" />\n </div>\n </section>\n\n <!-- Real World Examples -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Real World Examples</h2>\n <div class=\"space-y-6 rounded-lg bg-surface-container-high p-4\">\n <!-- Command Palette -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Command Palette Trigger</p>\n <div\n class=\"flex items-center gap-2 rounded-lg border border-outline-variant bg-surface-container p-3\"\n >\n <span class=\"flex-1 text-sm text-on-surface-variant\">Search commands...</span>\n <div class=\"flex items-center gap-1\">\n <Kbd value=\"meta\" size=\"sm\" />\n <Kbd value=\"K\" size=\"sm\" />\n </div>\n </div>\n </div>\n\n <!-- Menu Item -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Menu Item with Shortcut</p>\n <div class=\"max-w-xs rounded-lg border border-outline-variant bg-surface-container\">\n {#each [{ label: 'New File', keys: ['meta', 'N'] }, { label: 'Open File', keys: ['meta', 'O'] }, { label: 'Save', keys: ['meta', 'S'] }] as item (item.label)}\n <div\n class=\"flex items-center justify-between px-3 py-2 hover:bg-surface-container-high\"\n >\n <span class=\"text-sm\">{item.label}</span>\n <div class=\"flex items-center gap-0.5\">\n {#each item.keys as key (key)}\n <Kbd value={key} size=\"sm\" variant=\"soft\" />\n {/each}\n </div>\n </div>\n {/each}\n </div>\n </div>\n\n <!-- Inline Help -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Inline Help Text</p>\n <p class=\"text-sm text-on-surface-variant\">\n Press <Kbd value=\"escape\" size=\"sm\" class=\"mx-0.5\" /> to close the modal, or\n <Kbd value=\"enter\" size=\"sm\" class=\"mx-0.5\" /> to confirm.\n </p>\n </div>\n\n <!-- Navigation Hint -->\n <div class=\"space-y-2\">\n <p class=\"text-sm font-medium text-on-surface-variant\">Navigation Hint</p>\n <div class=\"flex items-center gap-4 text-sm text-on-surface-variant\">\n <span class=\"flex items-center gap-1\">\n <Kbd value=\"arrowup\" size=\"sm\" />\n <Kbd value=\"arrowdown\" size=\"sm\" />\n to navigate\n </span>\n <span class=\"flex items-center gap-1\">\n <Kbd value=\"enter\" size=\"sm\" />\n to select\n </span>\n </div>\n </div>\n </div>\n </section>\n\n <!-- useKbd: Shortcut Listener -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">useKbd — Shortcut Listener</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Try pressing the shortcuts below. The hook listens for keyboard events and fires\n callbacks.\n </p>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-wrap gap-4 text-sm\">\n <span class=\"flex items-center gap-1\">\n <Kbd value=\"ctrl\" size=\"sm\" /> + <Kbd value=\"K\" size=\"sm\" /> Toggle search\n </span>\n <span class=\"flex items-center gap-1\">\n <Kbd value=\"ctrl\" size=\"sm\" /> + <Kbd value=\"shift\" size=\"sm\" /> +\n <Kbd value=\"P\" size=\"sm\" /> Command palette\n </span>\n <span class=\"flex items-center gap-1\">\n <Kbd value=\"escape\" size=\"sm\" /> Close\n </span>\n </div>\n\n {#if searchOpen}\n <div\n class=\"flex items-center gap-2 rounded-lg border border-primary/50 bg-surface-container p-3\"\n >\n <span class=\"flex-1 text-sm text-on-surface-variant\">\n Search is open! Press <Kbd value=\"escape\" size=\"sm\" class=\"mx-0.5\" /> to close.\n </span>\n </div>\n {/if}\n\n {#if shortcutLog.length > 0}\n <div class=\"space-y-1 rounded-md bg-surface-container p-3\">\n <p class=\"text-xs font-medium text-on-surface-variant\">Recent shortcuts:</p>\n {#each shortcutLog as entry, i (i)}\n <p class=\"font-mono text-xs text-on-surface\">{entry}</p>\n {/each}\n </div>\n {/if}\n </div>\n </section>\n\n <!-- useKbd: Reactive Key State -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">useKbd — Reactive Key State</h2>\n <p class=\"text-sm text-on-surface-variant\">Hold any key to see it tracked in real-time.</p>\n <div class=\"space-y-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-wrap gap-2\">\n {#each ['shift', 'ctrl', 'alt', 'meta'] as key (key)}\n <div\n class=\"rounded-lg border px-3 py-2 text-sm transition-colors {kbd.isPressed(\n key\n )\n ? 'border-primary bg-primary-container text-on-primary-container'\n : 'border-outline-variant bg-surface-container text-on-surface-variant'}\"\n >\n <Kbd\n value={key}\n size=\"sm\"\n variant={kbd.isPressed(key) ? 'solid' : 'outline'}\n color={kbd.isPressed(key) ? 'primary' : 'surface'}\n />\n <span class=\"ml-1\">{kbd.isPressed(key) ? 'Pressed' : 'Released'}</span>\n </div>\n {/each}\n </div>\n\n <div class=\"rounded-md bg-surface-container p-3\">\n <p class=\"text-xs font-medium text-on-surface-variant\">Currently pressed keys:</p>\n <p class=\"mt-1 font-mono text-sm text-on-surface\">\n {#if kbd.pressedKeys.size > 0}\n {[...kbd.pressedKeys].join(' + ')}\n {:else}\n <span class=\"text-on-surface-variant\">None</span>\n {/if}\n </p>\n </div>\n </div>\n </section>\n\n <!-- Variants x Colors Matrix -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants x Colors</h2>\n <div class=\"overflow-x-auto rounded-lg bg-surface-container-high p-4\">\n <table class=\"w-full\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-3 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >Variant</th\n >\n {#each colors as color (color)}\n <th\n class=\"px-3 py-3 text-center text-sm font-medium text-on-surface-variant capitalize\"\n >{color}</th\n >\n {/each}\n </tr>\n </thead>\n <tbody>\n {#each variants as variant (variant)}\n <tr class=\"border-b border-outline-variant/50\">\n <td class=\"px-3 py-3 text-sm font-medium text-on-surface-variant\"\n >{variant}</td\n >\n {#each colors as color (color)}\n <td class=\"px-3 py-3 text-center\">\n <Kbd value=\"K\" {variant} {color} />\n </td>\n {/each}\n </tr>\n {/each}\n </tbody>\n </table>\n </div>\n </section>\n</div>\n",
82
84
  "theme-mode-button": "<script lang=\"ts\">\n import { ThemeModeButton, mode } from '$lib/index.js'\n\n const variants = ['solid', 'outline', 'soft', 'subtle', 'ghost', 'link'] as const\n const colors = [\n 'primary',\n 'secondary',\n 'tertiary',\n 'success',\n 'warning',\n 'error',\n 'info',\n 'surface'\n ] as const\n const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">ThemeModeButton</h1>\n <p class=\"text-on-surface-variant\">\n A button to switch between light and dark mode. Built on top of the Button component\n and Svelora theme utilities.\n </p>\n </div>\n\n <!-- Basic Usage -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Basic Usage</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <ThemeModeButton />\n <span class=\"text-sm text-on-surface-variant capitalize\">\n Current mode: {mode.current}\n </span>\n </div>\n </section>\n\n <!-- Variants -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants</h2>\n <div class=\"flex flex-wrap items-center gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each variants as variant (variant)}\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton {variant} color=\"primary\" />\n <span class=\"text-xs text-on-surface-variant capitalize\">{variant}</span>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Colors -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Colors</h2>\n <div class=\"overflow-x-auto\">\n <table class=\"w-full\">\n <thead>\n <tr class=\"border-b border-outline-variant\">\n <th class=\"px-2 py-3 text-left text-sm font-medium text-on-surface-variant\"\n >Variant</th\n >\n {#each colors as color (color)}\n <th\n class=\"px-2 py-3 text-center text-sm font-medium text-on-surface-variant capitalize\"\n >{color}</th\n >\n {/each}\n </tr>\n </thead>\n <tbody>\n {#each variants as variant (variant)}\n <tr class=\"border-b border-outline-variant/50\">\n <td\n class=\"px-2 py-3 text-sm font-medium text-on-surface-variant capitalize\"\n >{variant}</td\n >\n {#each colors as color (color)}\n <td class=\"px-2 py-3 text-center\">\n <ThemeModeButton {variant} {color} />\n </td>\n {/each}\n </tr>\n {/each}\n </tbody>\n </table>\n </div>\n </section>\n\n <!-- Sizes -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Sizes</h2>\n <div class=\"flex flex-wrap items-end gap-3 rounded-lg bg-surface-container-high p-4\">\n {#each sizes as size (size)}\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton {size} />\n <span class=\"text-xs text-on-surface-variant\">{size}</span>\n </div>\n {/each}\n </div>\n </section>\n\n <!-- Custom Icons -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Icons</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Override the default light/dark icons using the\n <code class=\"rounded bg-surface-container-highest px-1\">lightIcon</code> and\n <code class=\"rounded bg-surface-container-highest px-1\">darkIcon</code> props.\n </p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton lightIcon=\"lucide:sun-medium\" darkIcon=\"lucide:moon-star\" />\n <span class=\"text-xs text-on-surface-variant\">sun-medium / moon-star</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton lightIcon=\"lucide:sun-dim\" darkIcon=\"lucide:cloud-moon\" />\n <span class=\"text-xs text-on-surface-variant\">sun-dim / cloud-moon</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton lightIcon=\"lucide:sunrise\" darkIcon=\"lucide:sunset\" />\n <span class=\"text-xs text-on-surface-variant\">sunrise / sunset</span>\n </div>\n </div>\n </section>\n\n <!-- Non-square (with label via children) -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Content (Children Snippet)</h2>\n <p class=\"text-sm text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">children</code> snippet\n with\n <code class=\"rounded bg-surface-container-highest px-1\">{'{ isDark }'}</code> to render custom\n content.\n </p>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <ThemeModeButton square={false} variant=\"outline\" color=\"secondary\">\n {#snippet children({ isDark })}\n {isDark ? 'Light Mode' : 'Dark Mode'}\n {/snippet}\n </ThemeModeButton>\n\n <ThemeModeButton square={false} variant=\"soft\" color=\"primary\">\n {#snippet children({ isDark })}\n <span class=\"flex items-center gap-2\">\n {#if isDark}\n ☀️ Switch to Light\n {:else}\n 🌙 Switch to Dark\n {/if}\n </span>\n {/snippet}\n </ThemeModeButton>\n </div>\n </section>\n\n <!-- Disabled & Loading -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Disabled & Loading</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton disabled />\n <span class=\"text-xs text-on-surface-variant\">Disabled</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton loading />\n <span class=\"text-xs text-on-surface-variant\">Loading</span>\n </div>\n </div>\n </section>\n\n <!-- UI Overrides -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">UI Prop (Class Overrides)</h2>\n <div class=\"flex flex-wrap items-center gap-4 rounded-lg bg-surface-container-high p-4\">\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton class=\"rounded-full\" variant=\"outline\" color=\"primary\" />\n <span class=\"text-xs text-on-surface-variant\">Pill shape</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton\n variant=\"solid\"\n color=\"tertiary\"\n class=\"shadow-lg shadow-tertiary/30\"\n />\n <span class=\"text-xs text-on-surface-variant\">With shadow</span>\n </div>\n <div class=\"flex flex-col items-center gap-2\">\n <ThemeModeButton\n variant=\"solid\"\n color=\"primary\"\n class=\"bg-linear-to-r from-primary to-tertiary hover:from-primary/90 hover:to-tertiary/90\"\n />\n <span class=\"text-xs text-on-surface-variant\">Gradient</span>\n </div>\n </div>\n </section>\n</div>\n",
83
85
  "card": "<script lang=\"ts\">\n import { Card, Button, Icon, Avatar } from '$lib/index.js'\n</script>\n\n<div class=\"space-y-8\">\n <div class=\"space-y-2\">\n <h1 class=\"text-2xl font-bold\">Card</h1>\n <p class=\"text-on-surface-variant\">\n Container component for grouping related content with optional header and footer.\n </p>\n </div>\n\n <!-- Variants -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Variants</h2>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <Card variant=\"outline\">\n {#snippet header()}\n <h3 class=\"font-semibold\">Outline (Default)</h3>\n {/snippet}\n <p class=\"text-on-surface-variant\">Card with border and background.</p>\n </Card>\n\n <Card variant=\"soft\">\n {#snippet header()}\n <h3 class=\"font-semibold\">Soft</h3>\n {/snippet}\n <p class=\"text-on-surface-variant\">Card with subtle background.</p>\n </Card>\n\n <Card variant=\"subtle\">\n {#snippet header()}\n <h3 class=\"font-semibold\">Subtle</h3>\n {/snippet}\n <p class=\"text-on-surface-variant\">Card with background and border.</p>\n </Card>\n\n <Card variant=\"solid\">\n {#snippet header()}\n <h3 class=\"font-semibold\">Solid</h3>\n {/snippet}\n <p class=\"opacity-90\">Card with inverted colors.</p>\n </Card>\n </div>\n </section>\n\n <!-- With Header and Footer -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">With Header & Footer</h2>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <Card>\n {#snippet header()}\n <div class=\"flex items-center justify-between\">\n <h3 class=\"font-semibold\">Card Title</h3>\n <Button\n variant=\"ghost\"\n color=\"secondary\"\n icon=\"lucide:more-horizontal\"\n square\n size=\"sm\"\n />\n </div>\n {/snippet}\n <p class=\"text-on-surface-variant\">\n This is the card body content. You can put any content here.\n </p>\n {#snippet footer()}\n <div class=\"flex justify-end gap-2\">\n <Button variant=\"ghost\" color=\"secondary\" label=\"Cancel\" size=\"sm\" />\n <Button variant=\"solid\" color=\"primary\" label=\"Save\" size=\"sm\" />\n </div>\n {/snippet}\n </Card>\n\n <Card variant=\"soft\">\n {#snippet header()}\n <div class=\"flex items-center gap-3\">\n <Avatar src=\"https://i.pravatar.cc/150?img=5\" alt=\"John Doe\" size=\"md\" />\n <div>\n <h3 class=\"font-semibold\">John Doe</h3>\n <p class=\"text-sm text-on-surface-variant\">Software Engineer</p>\n </div>\n </div>\n {/snippet}\n <p class=\"text-on-surface-variant\">\n Building awesome things with Svelte and TypeScript.\n </p>\n {#snippet footer()}\n <div class=\"flex gap-2\">\n <Button\n variant=\"soft\"\n color=\"primary\"\n leadingIcon=\"lucide:mail\"\n label=\"Contact\"\n size=\"sm\"\n />\n <Button\n variant=\"ghost\"\n color=\"secondary\"\n leadingIcon=\"lucide:user-plus\"\n label=\"Follow\"\n size=\"sm\"\n />\n </div>\n {/snippet}\n </Card>\n </div>\n </section>\n\n <!-- Body Only -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Body Only</h2>\n <div class=\"grid gap-4 md:grid-cols-3\">\n <Card>\n <div class=\"text-center\">\n <Icon name=\"lucide:folder\" size=\"32\" class=\"mx-auto text-primary\" />\n <h4 class=\"mt-2 font-medium\">Documents</h4>\n <p class=\"text-sm text-on-surface-variant\">24 files</p>\n </div>\n </Card>\n\n <Card variant=\"soft\">\n <div class=\"text-center\">\n <Icon name=\"lucide:image\" size=\"32\" class=\"mx-auto text-success\" />\n <h4 class=\"mt-2 font-medium\">Images</h4>\n <p class=\"text-sm text-on-surface-variant\">128 files</p>\n </div>\n </Card>\n\n <Card variant=\"subtle\">\n <div class=\"text-center\">\n <Icon name=\"lucide:music\" size=\"32\" class=\"mx-auto text-tertiary\" />\n <h4 class=\"mt-2 font-medium\">Music</h4>\n <p class=\"text-sm text-on-surface-variant\">56 files</p>\n </div>\n </Card>\n </div>\n </section>\n\n <!-- Custom Styling -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">Custom Styling</h2>\n <div class=\"grid gap-4 md:grid-cols-2\">\n <Card class=\"border-l-4 border-l-primary\">\n {#snippet header()}\n <h3 class=\"font-semibold text-primary\">Accent Border</h3>\n {/snippet}\n <p class=\"text-on-surface-variant\">Card with left accent border.</p>\n </Card>\n\n <Card\n class=\"shadow-lg\"\n ui={{ header: 'bg-primary text-on-primary', body: 'bg-primary-container' }}\n >\n {#snippet header()}\n <h3 class=\"font-semibold\">Custom Slots</h3>\n {/snippet}\n <p class=\"text-on-primary-container\">\n Card with custom header and body styles via ui prop.\n </p>\n </Card>\n </div>\n </section>\n\n <!-- As Different Element -->\n <section class=\"space-y-3\">\n <h2 class=\"text-lg font-semibold\">As Different Element</h2>\n <Card as=\"article\" variant=\"soft\">\n {#snippet header()}\n <h3 class=\"font-semibold\">Article Card</h3>\n <p class=\"text-sm text-on-surface-variant\">Rendered as &lt;article&gt; element</p>\n {/snippet}\n <p class=\"text-on-surface-variant\">\n Use the <code class=\"rounded bg-surface-container-highest px-1\">as</code> prop to render\n as different HTML elements for better semantics.\n </p>\n </Card>\n </section>\n</div>\n",
package/dist/theme.css CHANGED
@@ -280,7 +280,7 @@
280
280
  }
281
281
 
282
282
  body {
283
- @apply bg-surface text-on-surface;
283
+ @apply bg-surface text-on-surface cursor-default;
284
284
  font-family: var(--font-sans-family);
285
285
  }
286
286
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelora",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "Modern primitive-based UI component library for Svelte 5",
5
5
  "packageManager": "bun@1.3.14",
6
6
  "author": "asphum",
@@ -18,18 +18,24 @@
18
18
  },
19
19
  "scripts": {
20
20
  "dev": "vite dev --port 3000",
21
+ "predev": "bun run paraglide:compile",
21
22
  "dev:docs": "vite dev --host 0.0.0.0 --port 4173",
23
+ "predev:docs": "bun run paraglide:compile",
22
24
  "build": "vite build && bun run prepack",
25
+ "prebuild": "bun run paraglide:compile",
23
26
  "preview": "vite preview",
24
- "prepare": "svelte-kit sync || echo ''",
27
+ "prepare": "bun run paraglide:compile && svelte-kit sync || echo ''",
25
28
  "prepack": "svelte-kit sync && svelte-package && bun run package:mcp && publint",
26
29
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
30
+ "precheck": "bun run paraglide:compile",
27
31
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
28
32
  "lint": "biome check .",
29
33
  "format": "biome format --write .",
30
34
  "lint:fix": "biome check --write .",
31
35
  "test:unit": "vitest",
36
+ "pretest:unit": "bun run paraglide:compile",
32
37
  "test": "bun run test:unit -- --run",
38
+ "paraglide:compile": "paraglide-js compile --project ./project.inlang --outdir ./src/lib/paraglide --emit-ts-declarations --strategy cookie globalVariable baseLocale",
33
39
  "package:mcp": "node ./scripts/package-mcp.mjs",
34
40
  "mcp:svelora-docs": "node ./mcp/svelora-docs/server.mjs",
35
41
  "changelog:template": "node ./scripts/changelog-template.mjs",
@@ -191,9 +197,10 @@
191
197
  }
192
198
  },
193
199
  "devDependencies": {
194
- "@biomejs/biome": "2.5.0",
200
+ "@biomejs/biome": "2.5.1",
201
+ "@inlang/paraglide-js": "^2.20.1",
195
202
  "@sveltejs/adapter-vercel": "^6.3.4",
196
- "@sveltejs/kit": "^2.66.0",
203
+ "@sveltejs/kit": "^2.67.0",
197
204
  "@sveltejs/package": "^2.5.8",
198
205
  "@sveltejs/vite-plugin-svelte": "^7.1.2",
199
206
  "@tailwindcss/vite": "^4.3.1",
@@ -220,12 +227,12 @@
220
227
  "playwright": "^1.61.0",
221
228
  "publint": "^0.3.21",
222
229
  "svelte": "^5.56.3",
223
- "svelte-check": "^4.6.0",
230
+ "svelte-check": "^4.7.0",
224
231
  "tailwindcss": "^4.3.1",
225
232
  "tiptap-markdown": "^0.9.0",
226
233
  "typescript": "^6.0.3",
227
234
  "valibot": "^1.4.1",
228
- "vite": "^8.0.16",
235
+ "vite": "^8.1.0",
229
236
  "vitest": "^4.1.9",
230
237
  "vitest-browser-svelte": "^2.1.1",
231
238
  "yup": "^1.7.1"
@@ -247,10 +254,10 @@
247
254
  "accessible"
248
255
  ],
249
256
  "dependencies": {
250
- "@modelcontextprotocol/sdk": "^1.0.0",
251
257
  "@floating-ui/dom": "^1.7.6",
252
258
  "@iconify/svelte": "^5.2.2",
253
259
  "@internationalized/date": "^3.12.2",
260
+ "@modelcontextprotocol/sdk": "^1.29.0",
254
261
  "@standard-schema/spec": "^1.1.0",
255
262
  "bits-ui": "^2.18.1",
256
263
  "embla-carousel": "9.0.0-rc02",
@@ -271,6 +278,7 @@
271
278
  "embla-carousel": "9.0.0-rc02",
272
279
  "embla-carousel-autoplay": "9.0.0-rc02",
273
280
  "embla-carousel-class-names": "9.0.0-rc02",
274
- "embla-carousel-fade": "9.0.0-rc02"
281
+ "embla-carousel-fade": "9.0.0-rc02",
282
+ "embla-carousel-svelte": "9.0.0-rc02"
275
283
  }
276
284
  }