yaxa-svelte 1.0.1 → 1.2.0

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 (39) hide show
  1. package/README.md +7 -8
  2. package/dist/components/elements/Badge.svelte +2 -1
  3. package/dist/components/elements/Badge.svelte.d.ts +2 -1
  4. package/dist/components/elements/Button.svelte +3 -2
  5. package/dist/components/elements/Button.svelte.d.ts +3 -2
  6. package/dist/components/elements/Icon.svelte +41 -7
  7. package/dist/components/elements/Icon.svelte.d.ts +11 -4
  8. package/dist/components/forms/Input.svelte +3 -2
  9. package/dist/components/forms/Input.svelte.d.ts +3 -2
  10. package/dist/components/forms/Select.svelte +3 -2
  11. package/dist/components/forms/Select.svelte.d.ts +3 -2
  12. package/dist/components/layout/Divider.svelte +9 -5
  13. package/dist/components/layout/Divider.svelte.d.ts +4 -3
  14. package/dist/components/layout/Footer.svelte +98 -5
  15. package/dist/components/legal/LegalDocument.svelte +341 -0
  16. package/dist/components/legal/LegalDocument.svelte.d.ts +21 -0
  17. package/dist/components/navigation/Breadcrumb.svelte +4 -2
  18. package/dist/components/navigation/Breadcrumb.svelte.d.ts +3 -2
  19. package/dist/components/navigation/CommandPalette.svelte +3 -1
  20. package/dist/components/navigation/CommandPalette.svelte.d.ts +2 -1
  21. package/dist/components/navigation/DropdownMenu.svelte +3 -1
  22. package/dist/components/navigation/DropdownMenu.svelte.d.ts +2 -1
  23. package/dist/components/navigation/Pagination.svelte +15 -7
  24. package/dist/components/navigation/Pagination.svelte.d.ts +5 -2
  25. package/dist/components/navigation/Tabs.svelte +3 -1
  26. package/dist/components/navigation/Tabs.svelte.d.ts +2 -1
  27. package/dist/components/overlays/Accordion.svelte +10 -8
  28. package/dist/components/overlays/Accordion.svelte.d.ts +5 -4
  29. package/dist/components/overlays/Alert.svelte +2 -1
  30. package/dist/components/overlays/Alert.svelte.d.ts +2 -1
  31. package/dist/components/overlays/ContextMenu.svelte +2 -2
  32. package/dist/components/overlays/ContextMenu.svelte.d.ts +2 -1
  33. package/dist/index.d.ts +18 -2
  34. package/dist/index.js +2 -1
  35. package/dist/site/config.d.ts +29 -0
  36. package/dist/site/config.js +35 -0
  37. package/dist/site/schema.d.ts +11 -0
  38. package/dist/site/schema.js +23 -0
  39. package/package.json +8 -1
package/README.md CHANGED
@@ -35,14 +35,14 @@ _Nuxt UI v4 & Nuxt UI Pro Equivalent for SvelteKit 2.7+ & Svelte 5 with Built-in
35
35
 
36
36
  ### 1. Install Dependencies
37
37
 
38
- Install `yaxa-svelte` along with Tailwind CSS v4 and icon tooling:
38
+ Install `yaxa-svelte` along with Tailwind CSS v4 and `@lucide/svelte`:
39
39
 
40
40
  ```bash
41
- # Core package
42
- pnpm add yaxa-svelte
41
+ # Core package & icons
42
+ pnpm add yaxa-svelte @lucide/svelte
43
43
 
44
- # Tailwind CSS v4 & Icon tooling (Dev Dependencies)
45
- pnpm add -D tailwindcss @tailwindcss/vite @tailwindcss/typography unplugin-icons @iconify/json
44
+ # Tailwind CSS v4 (Dev Dependencies)
45
+ pnpm add -D tailwindcss @tailwindcss/vite @tailwindcss/typography
46
46
  ```
47
47
 
48
48
  _(Optional full-stack SaaS features: `pnpm add better-auth drizzle-orm @polar-sh/sdk resend`)_
@@ -51,17 +51,16 @@ _(Optional full-stack SaaS features: `pnpm add better-auth drizzle-orm @polar-sh
51
51
 
52
52
  ### 2. Configure `vite.config.ts`
53
53
 
54
- Add Tailwind CSS and Unplugin Icons to your Vite plugins:
54
+ Add Tailwind CSS to your Vite plugins:
55
55
 
56
56
  ```ts
57
57
  // vite.config.ts
58
58
  import { sveltekit } from '@sveltejs/kit/vite';
59
59
  import tailwindcss from '@tailwindcss/vite';
60
- import Icons from 'unplugin-icons/vite';
61
60
  import { defineConfig } from 'vite';
62
61
 
63
62
  export default defineConfig({
64
- plugins: [tailwindcss(), Icons({ compiler: 'svelte', autoInstall: false }), sveltekit()]
63
+ plugins: [tailwindcss(), sveltekit()]
65
64
  });
66
65
  ```
67
66
 
@@ -1,6 +1,7 @@
1
1
  <script module lang="ts">
2
2
  import { tv, type VariantProps } from '../../utils/cn';
3
3
  import type { Snippet } from 'svelte';
4
+ import type { IconSource } from './Icon.svelte';
4
5
 
5
6
  export const badgeVariants = tv({
6
7
  base: 'inline-flex items-center font-medium select-none transition-colors duration-150',
@@ -150,7 +151,7 @@
150
151
 
151
152
  export type BadgeProps = VariantProps<typeof badgeVariants> & {
152
153
  dot?: boolean;
153
- icon?: string;
154
+ icon?: IconSource;
154
155
  class?: string;
155
156
  children?: Snippet;
156
157
  };
@@ -1,5 +1,6 @@
1
1
  import { type VariantProps } from '../../utils/cn';
2
2
  import type { Snippet } from 'svelte';
3
+ import type { IconSource } from './Icon.svelte';
3
4
  export declare const badgeVariants: import("tailwind-variants").TVReturnType<{
4
5
  variant: {
5
6
  solid: "text-white";
@@ -66,7 +67,7 @@ export declare const badgeVariants: import("tailwind-variants").TVReturnType<{
66
67
  }, undefined>>;
67
68
  export type BadgeProps = VariantProps<typeof badgeVariants> & {
68
69
  dot?: boolean;
69
- icon?: string;
70
+ icon?: IconSource;
70
71
  class?: string;
71
72
  children?: Snippet;
72
73
  };
@@ -2,6 +2,7 @@
2
2
  import { tv, type VariantProps } from '../../utils/cn';
3
3
  import type { Snippet } from 'svelte';
4
4
  import type { HTMLButtonAttributes, HTMLAnchorAttributes } from 'svelte/elements';
5
+ import type { IconSource } from './Icon.svelte';
5
6
 
6
7
  export const buttonVariants = tv({
7
8
  base: 'inline-flex items-center justify-center font-medium transition-all duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 select-none active:scale-[0.98]',
@@ -195,8 +196,8 @@
195
196
  href?: string;
196
197
  loading?: boolean;
197
198
  disabled?: boolean;
198
- icon?: string;
199
- trailingIcon?: string;
199
+ icon?: IconSource;
200
+ trailingIcon?: IconSource;
200
201
  type?: 'button' | 'submit' | 'reset';
201
202
  class?: string;
202
203
  leading?: Snippet;
@@ -1,5 +1,6 @@
1
1
  import { type VariantProps } from '../../utils/cn';
2
2
  import type { Snippet } from 'svelte';
3
+ import type { IconSource } from './Icon.svelte';
3
4
  export declare const buttonVariants: import("tailwind-variants").TVReturnType<{
4
5
  variant: {
5
6
  solid: "shadow-xs text-white";
@@ -92,8 +93,8 @@ export type ButtonProps = VariantProps<typeof buttonVariants> & {
92
93
  href?: string;
93
94
  loading?: boolean;
94
95
  disabled?: boolean;
95
- icon?: string;
96
- trailingIcon?: string;
96
+ icon?: IconSource;
97
+ trailingIcon?: IconSource;
97
98
  type?: 'button' | 'submit' | 'reset';
98
99
  class?: string;
99
100
  leading?: Snippet;
@@ -1,14 +1,28 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte';
1
+ <script module lang="ts">
2
+ import type { Component, Snippet } from 'svelte';
3
+
4
+ export type IconSource =
5
+ string | Component<{ class?: string; size?: string | number; [key: string]: any }>;
3
6
 
4
- interface Props {
5
- name?: string;
7
+ export interface IconProps {
8
+ name?: IconSource;
9
+ icon?: IconSource;
6
10
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number;
7
11
  class?: string;
8
12
  children?: Snippet;
13
+ [key: string]: unknown;
9
14
  }
15
+ </script>
10
16
 
11
- let { name, size = 'md', class: className = '', children }: Props = $props();
17
+ <script lang="ts">
18
+ let {
19
+ name,
20
+ icon,
21
+ size = 'md',
22
+ class: className = '',
23
+ children,
24
+ ...restProps
25
+ }: IconProps = $props();
12
26
 
13
27
  let sizeClass = $derived.by(() => {
14
28
  if (typeof size === 'number') return `w-[${size}px] h-[${size}px]`;
@@ -27,6 +41,18 @@
27
41
  }
28
42
  });
29
43
 
44
+ let IconComponent = $derived.by(() => {
45
+ if (icon && typeof icon !== 'string') return icon;
46
+ if (name && typeof name !== 'string') return name;
47
+ return null;
48
+ });
49
+
50
+ let stringIconName = $derived.by(() => {
51
+ if (typeof icon === 'string') return icon;
52
+ if (typeof name === 'string') return name;
53
+ return null;
54
+ });
55
+
30
56
  // Common built-in SVGs for immediate zero-config use
31
57
  const builtInIcons: Record<string, string> = {
32
58
  check:
@@ -66,14 +92,21 @@
66
92
  <span class="inline-flex shrink-0 items-center justify-center {sizeClass} {className}">
67
93
  {@render children()}
68
94
  </span>
69
- {:else if name && builtInIcons[name]}
95
+ {:else if IconComponent}
96
+ {@const RenderIcon = IconComponent}
97
+ <RenderIcon
98
+ class="inline-flex shrink-0 items-center justify-center {sizeClass} {className}"
99
+ {...restProps}
100
+ />
101
+ {:else if stringIconName && builtInIcons[stringIconName]}
70
102
  <svg
71
103
  class="inline-flex shrink-0 items-center justify-center {sizeClass} {className}"
72
104
  viewBox="0 0 24 24"
73
105
  fill="none"
74
106
  aria-hidden="true"
107
+ {...restProps}
75
108
  >
76
- {@html builtInIcons[name]}
109
+ {@html builtInIcons[stringIconName]}
77
110
  </svg>
78
111
  {:else}
79
112
  <svg
@@ -81,6 +114,7 @@
81
114
  viewBox="0 0 24 24"
82
115
  fill="none"
83
116
  aria-hidden="true"
117
+ {...restProps}
84
118
  >
85
119
  <circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2" stroke-dasharray="4 4" />
86
120
  </svg>
@@ -1,10 +1,17 @@
1
- import type { Snippet } from 'svelte';
2
- interface Props {
3
- name?: string;
1
+ import type { Component, Snippet } from 'svelte';
2
+ export type IconSource = string | Component<{
3
+ class?: string;
4
+ size?: string | number;
5
+ [key: string]: any;
6
+ }>;
7
+ export interface IconProps {
8
+ name?: IconSource;
9
+ icon?: IconSource;
4
10
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number;
5
11
  class?: string;
6
12
  children?: Snippet;
13
+ [key: string]: unknown;
7
14
  }
8
- declare const Icon: import("svelte").Component<Props, {}, "">;
15
+ declare const Icon: Component<IconProps, {}, "">;
9
16
  type Icon = ReturnType<typeof Icon>;
10
17
  export default Icon;
@@ -2,6 +2,7 @@
2
2
  import { tv, type VariantProps } from '../../utils/cn';
3
3
  import type { Snippet } from 'svelte';
4
4
  import type { HTMLInputAttributes } from 'svelte/elements';
5
+ import type { IconSource } from '../elements/Icon.svelte';
5
6
 
6
7
  export const inputVariants = tv({
7
8
  base: 'w-full rounded-lg border bg-white dark:bg-neutral-900 text-neutral-900 dark:text-neutral-100 placeholder:text-neutral-400 dark:placeholder:text-neutral-500 focus:outline-none focus:ring-2 transition-all duration-150 disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-neutral-50 dark:disabled:bg-neutral-950',
@@ -30,8 +31,8 @@
30
31
  export type InputProps = Omit<HTMLInputAttributes, 'size'> &
31
32
  VariantProps<typeof inputVariants> & {
32
33
  value?: string | number;
33
- icon?: string;
34
- trailingIcon?: string;
34
+ icon?: IconSource;
35
+ trailingIcon?: IconSource;
35
36
  loading?: boolean;
36
37
  clearable?: boolean;
37
38
  prefix?: string;
@@ -1,6 +1,7 @@
1
1
  import { type VariantProps } from '../../utils/cn';
2
2
  import type { Snippet } from 'svelte';
3
3
  import type { HTMLInputAttributes } from 'svelte/elements';
4
+ import type { IconSource } from '../elements/Icon.svelte';
4
5
  export declare const inputVariants: import("tailwind-variants").TVReturnType<{
5
6
  size: {
6
7
  xs: "text-xs py-1 px-2";
@@ -43,8 +44,8 @@ export declare const inputVariants: import("tailwind-variants").TVReturnType<{
43
44
  }, undefined>>;
44
45
  export type InputProps = Omit<HTMLInputAttributes, 'size'> & VariantProps<typeof inputVariants> & {
45
46
  value?: string | number;
46
- icon?: string;
47
- trailingIcon?: string;
47
+ icon?: IconSource;
48
+ trailingIcon?: IconSource;
48
49
  loading?: boolean;
49
50
  clearable?: boolean;
50
51
  prefix?: string;
@@ -1,10 +1,11 @@
1
1
  <script module lang="ts">
2
2
  import { tv, type VariantProps } from '../../utils/cn';
3
+ import type { IconSource } from '../elements/Icon.svelte';
3
4
 
4
5
  export interface SelectOption {
5
6
  value: string;
6
7
  label: string;
7
- icon?: string;
8
+ icon?: IconSource;
8
9
  disabled?: boolean;
9
10
  }
10
11
 
@@ -33,7 +34,7 @@
33
34
  value?: string;
34
35
  options?: SelectOption[];
35
36
  placeholder?: string;
36
- icon?: string;
37
+ icon?: IconSource;
37
38
  disabled?: boolean;
38
39
  name?: string;
39
40
  class?: string;
@@ -1,8 +1,9 @@
1
1
  import { type VariantProps } from '../../utils/cn';
2
+ import type { IconSource } from '../elements/Icon.svelte';
2
3
  export interface SelectOption {
3
4
  value: string;
4
5
  label: string;
5
- icon?: string;
6
+ icon?: IconSource;
6
7
  disabled?: boolean;
7
8
  }
8
9
  export declare const selectVariants: import("tailwind-variants").TVReturnType<{
@@ -40,7 +41,7 @@ export type SelectProps = VariantProps<typeof selectVariants> & {
40
41
  value?: string;
41
42
  options?: SelectOption[];
42
43
  placeholder?: string;
43
- icon?: string;
44
+ icon?: IconSource;
44
45
  disabled?: boolean;
45
46
  name?: string;
46
47
  class?: string;
@@ -1,14 +1,18 @@
1
- <script lang="ts">
1
+ <script module lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
- import Icon from '../elements/Icon.svelte';
3
+ import type { IconSource } from '../elements/Icon.svelte';
4
4
 
5
- interface Props {
5
+ export interface DividerProps {
6
6
  label?: string;
7
- icon?: string;
7
+ icon?: IconSource;
8
8
  orientation?: 'horizontal' | 'vertical';
9
9
  class?: string;
10
10
  children?: Snippet;
11
11
  }
12
+ </script>
13
+
14
+ <script lang="ts">
15
+ import Icon from '../elements/Icon.svelte';
12
16
 
13
17
  let {
14
18
  label,
@@ -16,7 +20,7 @@
16
20
  orientation = 'horizontal',
17
21
  class: className = '',
18
22
  children
19
- }: Props = $props();
23
+ }: DividerProps = $props();
20
24
  </script>
21
25
 
22
26
  {#if orientation === 'vertical'}
@@ -1,11 +1,12 @@
1
1
  import type { Snippet } from 'svelte';
2
- interface Props {
2
+ import type { IconSource } from '../elements/Icon.svelte';
3
+ export interface DividerProps {
3
4
  label?: string;
4
- icon?: string;
5
+ icon?: IconSource;
5
6
  orientation?: 'horizontal' | 'vertical';
6
7
  class?: string;
7
8
  children?: Snippet;
8
9
  }
9
- declare const Divider: import("svelte").Component<Props, {}, "">;
10
+ declare const Divider: import("svelte").Component<DividerProps, {}, "">;
10
11
  type Divider = ReturnType<typeof Divider>;
11
12
  export default Divider;
@@ -16,21 +16,37 @@
16
16
 
17
17
  let currentConfig = $derived(config || getSiteConfig());
18
18
  let currentYear = new Date().getFullYear();
19
+
20
+ let company = $derived(currentConfig.company);
21
+ let legal = $derived(currentConfig.legal);
22
+ let legalLinks = $derived(legal?.links);
23
+ let entityName = $derived(company?.legalName || currentConfig.name);
24
+
25
+ let hasLegalLinks = $derived(
26
+ Boolean(
27
+ legalLinks?.privacy || legalLinks?.terms || legalLinks?.refunds || legalLinks?.impressum
28
+ )
29
+ );
19
30
  </script>
20
31
 
21
32
  <footer
22
33
  class="border-t border-neutral-200 bg-white dark:border-neutral-800 dark:bg-neutral-950 {className}"
23
34
  >
24
35
  <Container size="lg" class="py-12 md:py-16">
25
- <div class="grid grid-cols-1 gap-8 md:grid-cols-4">
36
+ <div class="grid grid-cols-1 gap-8 md:grid-cols-4 lg:grid-cols-5">
26
37
  <!-- Brand Info -->
27
- <div class="space-y-4 md:col-span-2">
38
+ <div class="space-y-4 md:col-span-2 lg:col-span-2">
28
39
  <a href="/" class="inline-flex items-center gap-2.5 font-bold tracking-tight">
29
40
  <Logo size="sm" showText text={currentConfig.name} />
30
41
  </a>
31
42
  <p class="max-w-sm text-base text-neutral-600 dark:text-neutral-400">
32
43
  {currentConfig.description}
33
44
  </p>
45
+ {#if legal?.morNotice}
46
+ <p class="text-xs text-neutral-500 dark:text-neutral-500">
47
+ {legal.morNotice}
48
+ </p>
49
+ {/if}
34
50
  </div>
35
51
 
36
52
  <!-- Quick Links -->
@@ -50,6 +66,57 @@
50
66
  </ul>
51
67
  </div>
52
68
 
69
+ <!-- Legal Links -->
70
+ {#if hasLegalLinks}
71
+ <div>
72
+ <h3 class="text-base font-semibold text-neutral-900 dark:text-white">
73
+ Legal & Compliance
74
+ </h3>
75
+ <ul class="mt-4 space-y-2.5 text-sm text-neutral-600 dark:text-neutral-400">
76
+ {#if legalLinks?.privacy}
77
+ <li>
78
+ <a
79
+ href={legalLinks.privacy}
80
+ class="transition-colors hover:text-primary-600 dark:hover:text-primary-400"
81
+ >
82
+ Privacy Policy
83
+ </a>
84
+ </li>
85
+ {/if}
86
+ {#if legalLinks?.terms}
87
+ <li>
88
+ <a
89
+ href={legalLinks.terms}
90
+ class="transition-colors hover:text-primary-600 dark:hover:text-primary-400"
91
+ >
92
+ Terms of Service
93
+ </a>
94
+ </li>
95
+ {/if}
96
+ {#if legalLinks?.refunds}
97
+ <li>
98
+ <a
99
+ href={legalLinks.refunds}
100
+ class="transition-colors hover:text-primary-600 dark:hover:text-primary-400"
101
+ >
102
+ Cancellation & Refunds
103
+ </a>
104
+ </li>
105
+ {/if}
106
+ {#if legalLinks?.impressum}
107
+ <li>
108
+ <a
109
+ href={legalLinks.impressum}
110
+ class="transition-colors hover:text-primary-600 dark:hover:text-primary-400"
111
+ >
112
+ Impressum
113
+ </a>
114
+ </li>
115
+ {/if}
116
+ </ul>
117
+ </div>
118
+ {/if}
119
+
53
120
  <!-- Socials & Newsletter -->
54
121
  <div>
55
122
  <h3 class="text-base font-semibold text-neutral-900 dark:text-white">Community</h3>
@@ -86,11 +153,37 @@
86
153
  </div>
87
154
  </div>
88
155
 
156
+ <!-- Footer Bottom Identification Bar -->
89
157
  <div
90
- class="mt-12 flex flex-col items-center justify-between border-t border-neutral-200 pt-8 text-sm text-neutral-500 sm:flex-row dark:border-neutral-800 dark:text-neutral-400"
158
+ class="mt-12 flex flex-col items-center justify-between gap-4 border-t border-neutral-200 pt-8 text-xs text-neutral-500 sm:flex-row dark:border-neutral-800 dark:text-neutral-400"
91
159
  >
92
- <p>© {currentYear} {currentConfig.name}. Built for SvelteKit 2.7 & Svelte 5.</p>
93
- <p class="mt-2 sm:mt-0">Designed for solo developers · 100% DRY.</p>
160
+ <div class="flex flex-wrap items-center justify-center gap-x-3 gap-y-1 sm:justify-start">
161
+ <span>© {currentYear} {entityName}.</span>
162
+ {#if company?.address}
163
+ <span>· {company.address}</span>
164
+ {/if}
165
+ {#if company?.vatNumber}
166
+ <span>· VAT: {company.vatNumber}</span>
167
+ {/if}
168
+ {#if company?.registrationCourt}
169
+ <span>· {company.registrationCourt}</span>
170
+ {/if}
171
+ </div>
172
+
173
+ <div class="flex flex-wrap items-center justify-center gap-4">
174
+ {#if legalLinks?.privacy}
175
+ <a href={legalLinks.privacy} class="hover:underline">Privacy</a>
176
+ {/if}
177
+ {#if legalLinks?.terms}
178
+ <a href={legalLinks.terms} class="hover:underline">Terms</a>
179
+ {/if}
180
+ {#if legalLinks?.refunds}
181
+ <a href={legalLinks.refunds} class="hover:underline">Refunds</a>
182
+ {/if}
183
+ {#if legalLinks?.impressum}
184
+ <a href={legalLinks.impressum} class="hover:underline">Impressum</a>
185
+ {/if}
186
+ </div>
94
187
  </div>
95
188
  </Container>
96
189
  </footer>