@ewanc26/ui 0.1.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 (154) hide show
  1. package/README.md +65 -0
  2. package/dist/components/layout/ThemeToggle.svelte +50 -0
  3. package/dist/components/layout/ThemeToggle.svelte.d.ts +4 -0
  4. package/dist/components/layout/ThemeToggle.svelte.d.ts.map +1 -0
  5. package/dist/components/layout/WolfToggle.svelte +19 -0
  6. package/dist/components/layout/WolfToggle.svelte.d.ts +4 -0
  7. package/dist/components/layout/WolfToggle.svelte.d.ts.map +1 -0
  8. package/dist/components/layout/index.d.ts +5 -0
  9. package/dist/components/layout/index.d.ts.map +1 -0
  10. package/dist/components/layout/index.js +4 -0
  11. package/dist/components/layout/main/DynamicLinks.svelte +63 -0
  12. package/dist/components/layout/main/DynamicLinks.svelte.d.ts +7 -0
  13. package/dist/components/layout/main/DynamicLinks.svelte.d.ts.map +1 -0
  14. package/dist/components/layout/main/ScrollToTop.svelte +36 -0
  15. package/dist/components/layout/main/ScrollToTop.svelte.d.ts +4 -0
  16. package/dist/components/layout/main/ScrollToTop.svelte.d.ts.map +1 -0
  17. package/dist/components/layout/main/card/BlueskyPostCard.svelte +261 -0
  18. package/dist/components/layout/main/card/BlueskyPostCard.svelte.d.ts +9 -0
  19. package/dist/components/layout/main/card/BlueskyPostCard.svelte.d.ts.map +1 -0
  20. package/dist/components/layout/main/card/KibunStatusCard.svelte +48 -0
  21. package/dist/components/layout/main/card/KibunStatusCard.svelte.d.ts +8 -0
  22. package/dist/components/layout/main/card/KibunStatusCard.svelte.d.ts.map +1 -0
  23. package/dist/components/layout/main/card/LinkCard.svelte +63 -0
  24. package/dist/components/layout/main/card/LinkCard.svelte.d.ts +17 -0
  25. package/dist/components/layout/main/card/LinkCard.svelte.d.ts.map +1 -0
  26. package/dist/components/layout/main/card/MusicStatusCard.svelte +101 -0
  27. package/dist/components/layout/main/card/MusicStatusCard.svelte.d.ts +8 -0
  28. package/dist/components/layout/main/card/MusicStatusCard.svelte.d.ts.map +1 -0
  29. package/dist/components/layout/main/card/PostCard.svelte +46 -0
  30. package/dist/components/layout/main/card/PostCard.svelte.d.ts +8 -0
  31. package/dist/components/layout/main/card/PostCard.svelte.d.ts.map +1 -0
  32. package/dist/components/layout/main/card/ProfileCard.svelte +70 -0
  33. package/dist/components/layout/main/card/ProfileCard.svelte.d.ts +8 -0
  34. package/dist/components/layout/main/card/ProfileCard.svelte.d.ts.map +1 -0
  35. package/dist/components/layout/main/card/TangledRepoCard.svelte +80 -0
  36. package/dist/components/layout/main/card/TangledRepoCard.svelte.d.ts +11 -0
  37. package/dist/components/layout/main/card/TangledRepoCard.svelte.d.ts.map +1 -0
  38. package/dist/components/layout/main/card/index.d.ts +8 -0
  39. package/dist/components/layout/main/card/index.d.ts.map +1 -0
  40. package/dist/components/layout/main/card/index.js +7 -0
  41. package/dist/components/layout/main/index.d.ts +4 -0
  42. package/dist/components/layout/main/index.d.ts.map +1 -0
  43. package/dist/components/layout/main/index.js +3 -0
  44. package/dist/components/seo/MetaTags.svelte +39 -0
  45. package/dist/components/seo/MetaTags.svelte.d.ts +9 -0
  46. package/dist/components/seo/MetaTags.svelte.d.ts.map +1 -0
  47. package/dist/components/seo/index.d.ts +2 -0
  48. package/dist/components/seo/index.d.ts.map +1 -0
  49. package/dist/components/seo/index.js +1 -0
  50. package/dist/components/ui/BlogPostCard.svelte +44 -0
  51. package/dist/components/ui/BlogPostCard.svelte.d.ts +9 -0
  52. package/dist/components/ui/BlogPostCard.svelte.d.ts.map +1 -0
  53. package/dist/components/ui/Card.svelte +144 -0
  54. package/dist/components/ui/Card.svelte.d.ts +27 -0
  55. package/dist/components/ui/Card.svelte.d.ts.map +1 -0
  56. package/dist/components/ui/DocumentCard.svelte +42 -0
  57. package/dist/components/ui/DocumentCard.svelte.d.ts +9 -0
  58. package/dist/components/ui/DocumentCard.svelte.d.ts.map +1 -0
  59. package/dist/components/ui/Dropdown.svelte +36 -0
  60. package/dist/components/ui/Dropdown.svelte.d.ts +15 -0
  61. package/dist/components/ui/Dropdown.svelte.d.ts.map +1 -0
  62. package/dist/components/ui/InternalCard.svelte +41 -0
  63. package/dist/components/ui/InternalCard.svelte.d.ts +14 -0
  64. package/dist/components/ui/InternalCard.svelte.d.ts.map +1 -0
  65. package/dist/components/ui/Pagination.svelte +74 -0
  66. package/dist/components/ui/Pagination.svelte.d.ts +11 -0
  67. package/dist/components/ui/Pagination.svelte.d.ts.map +1 -0
  68. package/dist/components/ui/PostsGroupedView.svelte +40 -0
  69. package/dist/components/ui/PostsGroupedView.svelte.d.ts +10 -0
  70. package/dist/components/ui/PostsGroupedView.svelte.d.ts.map +1 -0
  71. package/dist/components/ui/SearchBar.svelte +26 -0
  72. package/dist/components/ui/SearchBar.svelte.d.ts +9 -0
  73. package/dist/components/ui/SearchBar.svelte.d.ts.map +1 -0
  74. package/dist/components/ui/Tabs.svelte +25 -0
  75. package/dist/components/ui/Tabs.svelte.d.ts +13 -0
  76. package/dist/components/ui/Tabs.svelte.d.ts.map +1 -0
  77. package/dist/components/ui/index.d.ts +11 -0
  78. package/dist/components/ui/index.d.ts.map +1 -0
  79. package/dist/components/ui/index.js +10 -0
  80. package/dist/config/themes.config.d.ts +23 -0
  81. package/dist/config/themes.config.d.ts.map +1 -0
  82. package/dist/config/themes.config.js +116 -0
  83. package/dist/helper/badges.d.ts +9 -0
  84. package/dist/helper/badges.d.ts.map +1 -0
  85. package/dist/helper/badges.js +28 -0
  86. package/dist/helper/posts.d.ts +14 -0
  87. package/dist/helper/posts.d.ts.map +1 -0
  88. package/dist/helper/posts.js +47 -0
  89. package/dist/index.d.ts +16 -0
  90. package/dist/index.d.ts.map +1 -0
  91. package/dist/index.js +18 -0
  92. package/dist/stores/colorTheme.d.ts +12 -0
  93. package/dist/stores/colorTheme.d.ts.map +1 -0
  94. package/dist/stores/colorTheme.js +36 -0
  95. package/dist/stores/dropdownState.d.ts +2 -0
  96. package/dist/stores/dropdownState.d.ts.map +1 -0
  97. package/dist/stores/dropdownState.js +2 -0
  98. package/dist/stores/happyMac.d.ts +11 -0
  99. package/dist/stores/happyMac.d.ts.map +1 -0
  100. package/dist/stores/happyMac.js +19 -0
  101. package/dist/stores/index.d.ts +6 -0
  102. package/dist/stores/index.d.ts.map +1 -0
  103. package/dist/stores/index.js +4 -0
  104. package/dist/stores/wolfMode.d.ts +7 -0
  105. package/dist/stores/wolfMode.d.ts.map +1 -0
  106. package/dist/stores/wolfMode.js +130 -0
  107. package/dist/types/index.d.ts +19 -0
  108. package/dist/types/index.d.ts.map +1 -0
  109. package/dist/types/index.js +1 -0
  110. package/dist/utils/formatNumber.d.ts +3 -0
  111. package/dist/utils/formatNumber.d.ts.map +1 -0
  112. package/dist/utils/formatNumber.js +26 -0
  113. package/dist/utils/locale.d.ts +4 -0
  114. package/dist/utils/locale.d.ts.map +1 -0
  115. package/dist/utils/locale.js +32 -0
  116. package/package.json +45 -0
  117. package/src/lib/components/layout/ThemeToggle.svelte +50 -0
  118. package/src/lib/components/layout/WolfToggle.svelte +19 -0
  119. package/src/lib/components/layout/index.ts +4 -0
  120. package/src/lib/components/layout/main/DynamicLinks.svelte +63 -0
  121. package/src/lib/components/layout/main/ScrollToTop.svelte +36 -0
  122. package/src/lib/components/layout/main/card/BlueskyPostCard.svelte +261 -0
  123. package/src/lib/components/layout/main/card/KibunStatusCard.svelte +48 -0
  124. package/src/lib/components/layout/main/card/LinkCard.svelte +63 -0
  125. package/src/lib/components/layout/main/card/MusicStatusCard.svelte +101 -0
  126. package/src/lib/components/layout/main/card/PostCard.svelte +46 -0
  127. package/src/lib/components/layout/main/card/ProfileCard.svelte +70 -0
  128. package/src/lib/components/layout/main/card/TangledRepoCard.svelte +80 -0
  129. package/src/lib/components/layout/main/card/index.ts +7 -0
  130. package/src/lib/components/layout/main/index.ts +3 -0
  131. package/src/lib/components/seo/MetaTags.svelte +39 -0
  132. package/src/lib/components/seo/index.ts +1 -0
  133. package/src/lib/components/ui/BlogPostCard.svelte +44 -0
  134. package/src/lib/components/ui/Card.svelte +144 -0
  135. package/src/lib/components/ui/DocumentCard.svelte +42 -0
  136. package/src/lib/components/ui/Dropdown.svelte +36 -0
  137. package/src/lib/components/ui/InternalCard.svelte +41 -0
  138. package/src/lib/components/ui/Pagination.svelte +74 -0
  139. package/src/lib/components/ui/PostsGroupedView.svelte +40 -0
  140. package/src/lib/components/ui/SearchBar.svelte +26 -0
  141. package/src/lib/components/ui/Tabs.svelte +25 -0
  142. package/src/lib/components/ui/index.ts +10 -0
  143. package/src/lib/config/themes.config.ts +130 -0
  144. package/src/lib/helper/badges.ts +44 -0
  145. package/src/lib/helper/posts.ts +63 -0
  146. package/src/lib/index.ts +32 -0
  147. package/src/lib/stores/colorTheme.ts +44 -0
  148. package/src/lib/stores/dropdownState.ts +3 -0
  149. package/src/lib/stores/happyMac.ts +28 -0
  150. package/src/lib/stores/index.ts +5 -0
  151. package/src/lib/stores/wolfMode.ts +127 -0
  152. package/src/lib/types/index.ts +19 -0
  153. package/src/lib/utils/formatNumber.ts +27 -0
  154. package/src/lib/utils/locale.ts +29 -0
@@ -0,0 +1,144 @@
1
+ <script lang="ts">
2
+ import { ExternalLink } from '@lucide/svelte';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ export interface Badge {
6
+ text: string;
7
+ color?: 'mint' | 'sage' | 'jade' | 'ink';
8
+ variant?: 'solid' | 'soft';
9
+ }
10
+
11
+ interface Props {
12
+ variant?: 'default' | 'elevated' | 'flat' | 'button' | 'outline';
13
+ padding?: 'sm' | 'md' | 'lg' | 'none';
14
+ interactive?: boolean;
15
+ href?: string;
16
+ target?: string;
17
+ rel?: string;
18
+ showExternalIcon?: boolean;
19
+ badges?: Badge[];
20
+ loading?: boolean;
21
+ error?: boolean;
22
+ errorMessage?: string;
23
+ class?: string;
24
+ ariaLabel?: string;
25
+ children?: Snippet;
26
+ skeleton?: Snippet;
27
+ }
28
+
29
+ let {
30
+ variant = 'default',
31
+ padding = 'md',
32
+ interactive = false,
33
+ href,
34
+ target = '_blank',
35
+ rel = 'noopener noreferrer',
36
+ showExternalIcon = false,
37
+ badges = [],
38
+ loading = false,
39
+ error = false,
40
+ errorMessage = 'Something went wrong',
41
+ class: customClass = '',
42
+ ariaLabel,
43
+ children,
44
+ skeleton
45
+ }: Props = $props();
46
+
47
+ let isLink = $derived(!!href);
48
+ const baseClasses = 'rounded-xl transition-all duration-300';
49
+ const variantClasses = {
50
+ default: 'bg-canvas-100 dark:bg-canvas-900 shadow-md',
51
+ elevated: 'bg-canvas-100 dark:bg-canvas-900 shadow-lg hover:shadow-xl',
52
+ flat: 'bg-canvas-200 dark:bg-canvas-800',
53
+ button:
54
+ 'bg-canvas-200 dark:bg-canvas-800 hover:bg-canvas-300 dark:hover:bg-canvas-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600',
55
+ outline:
56
+ 'bg-transparent border-2 border-canvas-300 dark:border-canvas-700 hover:border-primary-400 dark:hover:border-primary-600'
57
+ };
58
+ const paddingClasses = { none: '', sm: 'p-4', md: 'p-6', lg: 'p-8' };
59
+ let interactiveClasses = $derived(interactive || isLink ? 'cursor-pointer' : '');
60
+ let cardClasses = $derived(
61
+ `${baseClasses} ${variantClasses[variant]} ${paddingClasses[padding]} ${interactiveClasses} ${customClass}`
62
+ );
63
+
64
+ function getBadgeClasses(badge: Badge): string {
65
+ const baseStyle =
66
+ badge.variant === 'soft'
67
+ ? 'px-2 py-0.5 text-xs font-medium rounded'
68
+ : 'px-2 py-0.5 text-xs font-semibold uppercase rounded';
69
+ const colorClasses = {
70
+ mint:
71
+ badge.variant === 'soft'
72
+ ? 'bg-secondary-100 text-secondary-800 dark:bg-secondary-900 dark:text-secondary-200'
73
+ : 'bg-secondary-500 text-white dark:bg-secondary-600',
74
+ sage:
75
+ badge.variant === 'soft'
76
+ ? 'bg-primary-100 text-primary-800 dark:bg-primary-900 dark:text-primary-200'
77
+ : 'bg-primary-500 text-white dark:bg-primary-600',
78
+ jade:
79
+ badge.variant === 'soft'
80
+ ? 'bg-accent-100 text-accent-800 dark:bg-accent-900 dark:text-accent-200'
81
+ : 'bg-accent-500 text-white dark:bg-accent-600',
82
+ ink:
83
+ badge.variant === 'soft'
84
+ ? 'bg-ink-100 text-ink-800 dark:bg-ink-800 dark:text-ink-100'
85
+ : 'bg-ink-700 text-white dark:bg-ink-300 dark:text-ink-900'
86
+ };
87
+ return `${baseStyle} ${colorClasses[badge.color || 'ink']}`;
88
+ }
89
+ </script>
90
+
91
+ {#if loading}
92
+ <div class="{cardClasses} animate-pulse" aria-label="Loading content" role="status">
93
+ {#if skeleton}
94
+ {@render skeleton()}
95
+ {:else}
96
+ <div class="space-y-3">
97
+ <div class="h-4 w-3/4 rounded bg-canvas-300 dark:bg-canvas-700"></div>
98
+ <div class="h-4 w-full rounded bg-canvas-300 dark:bg-canvas-700"></div>
99
+ <div class="h-4 w-5/6 rounded bg-canvas-300 dark:bg-canvas-700"></div>
100
+ </div>
101
+ {/if}
102
+ <span class="sr-only">Loading...</span>
103
+ </div>
104
+ {:else if error}
105
+ <div
106
+ class="{cardClasses} border-2 border-red-300 bg-red-50 dark:border-red-700 dark:bg-red-900/20"
107
+ role="alert"
108
+ aria-live="polite"
109
+ >
110
+ <p class="text-red-600 dark:text-red-400">{errorMessage}</p>
111
+ </div>
112
+ {:else if isLink}
113
+ <a {href} {target} {rel} class={cardClasses} aria-label={ariaLabel || `Link to ${href}`}>
114
+ {#if badges.length > 0}
115
+ <div class="mb-3 flex flex-wrap items-center gap-2">
116
+ {#each badges as badge}
117
+ <span class={getBadgeClasses(badge)}>{badge.text}</span>
118
+ {/each}
119
+ </div>
120
+ {/if}
121
+ <div class="flex items-start justify-between gap-3">
122
+ <div class="flex-1">
123
+ {#if children}{@render children()}{/if}
124
+ </div>
125
+ {#if showExternalIcon}
126
+ <ExternalLink
127
+ class="h-4 w-4 shrink-0 text-ink-700 transition-colors group-hover:text-primary-600 dark:text-ink-200 dark:group-hover:text-primary-400"
128
+ aria-hidden="true"
129
+ />
130
+ {/if}
131
+ </div>
132
+ </a>
133
+ {:else}
134
+ <div class={cardClasses} role={ariaLabel ? 'region' : undefined} aria-label={ariaLabel}>
135
+ {#if badges.length > 0}
136
+ <div class="mb-3 flex flex-wrap items-center gap-2">
137
+ {#each badges as badge}
138
+ <span class={getBadgeClasses(badge)}>{badge.text}</span>
139
+ {/each}
140
+ </div>
141
+ {/if}
142
+ {#if children}{@render children()}{/if}
143
+ </div>
144
+ {/if}
@@ -0,0 +1,27 @@
1
+ import type { Snippet } from 'svelte';
2
+ export interface Badge {
3
+ text: string;
4
+ color?: 'mint' | 'sage' | 'jade' | 'ink';
5
+ variant?: 'solid' | 'soft';
6
+ }
7
+ interface Props {
8
+ variant?: 'default' | 'elevated' | 'flat' | 'button' | 'outline';
9
+ padding?: 'sm' | 'md' | 'lg' | 'none';
10
+ interactive?: boolean;
11
+ href?: string;
12
+ target?: string;
13
+ rel?: string;
14
+ showExternalIcon?: boolean;
15
+ badges?: Badge[];
16
+ loading?: boolean;
17
+ error?: boolean;
18
+ errorMessage?: string;
19
+ class?: string;
20
+ ariaLabel?: string;
21
+ children?: Snippet;
22
+ skeleton?: Snippet;
23
+ }
24
+ declare const Card: import("svelte").Component<Props, {}, "">;
25
+ type Card = ReturnType<typeof Card>;
26
+ export default Card;
27
+ //# sourceMappingURL=Card.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Card.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/ui/Card.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGrC,MAAM,WAAW,KAAK;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IACzC,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC3B;AAED,UAAU,KAAK;IACd,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;IACjE,OAAO,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;IACtC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAuHF,QAAA,MAAM,IAAI,2CAAwC,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
@@ -0,0 +1,42 @@
1
+ <script lang="ts">
2
+ import { ExternalLink, Tag } from '@lucide/svelte';
3
+ import type { StandardSiteDocument } from '@ewanc26/atproto';
4
+ import InternalCard from './InternalCard.svelte';
5
+ import { formatLocalizedDate } from '../../utils/locale.js';
6
+
7
+ interface Props { document: StandardSiteDocument; locale?: string; }
8
+ let { document, locale }: Props = $props();
9
+ </script>
10
+
11
+ <InternalCard href={document.url}>
12
+ {#snippet children()}
13
+ {#if document.coverImage}
14
+ <div class="mb-3 overflow-hidden rounded-lg">
15
+ <img src={document.coverImage} alt={document.title} class="h-48 w-full object-cover transition-transform duration-300 hover:scale-105" />
16
+ </div>
17
+ {/if}
18
+ <div class="relative min-w-0 flex-1 space-y-2">
19
+ {#if document.publicationName}
20
+ <div class="flex flex-wrap items-center gap-2">
21
+ <span class="rounded bg-accent-500 px-2 py-0.5 text-xs font-semibold text-white uppercase dark:bg-accent-600">{document.publicationName}</span>
22
+ </div>
23
+ {/if}
24
+ <h4 class="overflow-wrap-anywhere font-semibold wrap-break-word text-ink-900 dark:text-ink-50">{document.title}</h4>
25
+ {#if document.description}
26
+ <p class="overflow-wrap-anywhere line-clamp-2 text-sm wrap-break-word text-ink-700 dark:text-ink-200">{document.description}</p>
27
+ {/if}
28
+ <div class="pt-1">
29
+ <p class="text-xs font-medium text-ink-800 dark:text-ink-100">{formatLocalizedDate(document.publishedAt, locale)}</p>
30
+ </div>
31
+ </div>
32
+ <div class="flex shrink-0 flex-col items-end justify-between gap-2 self-stretch">
33
+ <ExternalLink class="h-4 w-4 text-ink-700 transition-colors dark:text-ink-200" aria-hidden="true" />
34
+ {#if document.tags && document.tags.length > 0}
35
+ <div class="flex items-center gap-1.5 rounded bg-ink-100 px-2 py-0.5 dark:bg-ink-800">
36
+ <Tag class="h-3 w-3 text-ink-700 dark:text-ink-200" aria-hidden="true" />
37
+ <span class="text-xs font-medium text-ink-800 dark:text-ink-100">{document.tags.length}</span>
38
+ </div>
39
+ {/if}
40
+ </div>
41
+ {/snippet}
42
+ </InternalCard>
@@ -0,0 +1,9 @@
1
+ import type { StandardSiteDocument } from '@ewanc26/atproto';
2
+ interface Props {
3
+ document: StandardSiteDocument;
4
+ locale?: string;
5
+ }
6
+ declare const DocumentCard: import("svelte").Component<Props, {}, "">;
7
+ type DocumentCard = ReturnType<typeof DocumentCard>;
8
+ export default DocumentCard;
9
+ //# sourceMappingURL=DocumentCard.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocumentCard.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/ui/DocumentCard.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAK5D,UAAU,KAAK;IAAG,QAAQ,EAAE,oBAAoB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAAE;AA6CrE,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -0,0 +1,36 @@
1
+ <script lang="ts">
2
+ import { ChevronDown } from '@lucide/svelte';
3
+
4
+ interface Option { value: string; label: string; }
5
+ interface Props {
6
+ options: Option[];
7
+ value: string;
8
+ label?: string;
9
+ placeholder?: string;
10
+ id?: string;
11
+ }
12
+
13
+ let { options, value = $bindable(), label, placeholder = 'Select...', id = 'dropdown' }: Props = $props();
14
+ </script>
15
+
16
+ <div class="relative">
17
+ {#if label}
18
+ <label for={id} class="mb-2 block text-sm font-medium text-ink-700 dark:text-ink-200">{label}</label>
19
+ {/if}
20
+ <div class="relative">
21
+ <select
22
+ {id}
23
+ bind:value
24
+ class="w-full appearance-none rounded-lg border-2 border-canvas-300 bg-canvas-100 py-2 pr-10 pl-3 text-ink-900 transition-colors focus:border-primary-500 focus:ring-2 focus:ring-primary-500/20 focus:outline-none dark:border-canvas-700 dark:bg-canvas-900 dark:text-ink-50 dark:focus:border-primary-400"
25
+ aria-label={label || 'Select an option'}
26
+ >
27
+ <option value="" disabled>{placeholder}</option>
28
+ {#each options as option}
29
+ <option value={option.value}>{option.label}</option>
30
+ {/each}
31
+ </select>
32
+ <div class="pointer-events-none absolute top-1/2 right-3 -translate-y-1/2 text-ink-500 dark:text-ink-400" aria-hidden="true">
33
+ <ChevronDown class="h-5 w-5" />
34
+ </div>
35
+ </div>
36
+ </div>
@@ -0,0 +1,15 @@
1
+ interface Option {
2
+ value: string;
3
+ label: string;
4
+ }
5
+ interface Props {
6
+ options: Option[];
7
+ value: string;
8
+ label?: string;
9
+ placeholder?: string;
10
+ id?: string;
11
+ }
12
+ declare const Dropdown: import("svelte").Component<Props, {}, "value">;
13
+ type Dropdown = ReturnType<typeof Dropdown>;
14
+ export default Dropdown;
15
+ //# sourceMappingURL=Dropdown.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dropdown.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/ui/Dropdown.svelte.ts"],"names":[],"mappings":"AAMC,UAAU,MAAM;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;CAAE;AAClD,UAAU,KAAK;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;CACZ;AA4BF,QAAA,MAAM,QAAQ,gDAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,41 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ href?: string;
6
+ target?: string;
7
+ rel?: string;
8
+ onclick?: () => void;
9
+ class?: string;
10
+ ariaLabel?: string;
11
+ children?: Snippet;
12
+ }
13
+
14
+ let {
15
+ href,
16
+ target = '_blank',
17
+ rel = 'noopener noreferrer',
18
+ onclick,
19
+ class: customClass = '',
20
+ ariaLabel,
21
+ children
22
+ }: Props = $props();
23
+
24
+ const baseClasses =
25
+ 'flex items-start gap-3 rounded-lg bg-canvas-200 p-4 transition-colors hover:bg-canvas-300 dark:bg-canvas-800 dark:hover:bg-canvas-700 self-start';
26
+ let combinedClasses = $derived(`${baseClasses} ${customClass}`);
27
+ </script>
28
+
29
+ {#if href}
30
+ <a {href} {target} {rel} class={combinedClasses} aria-label={ariaLabel}>
31
+ {#if children}{@render children()}{/if}
32
+ </a>
33
+ {:else if onclick}
34
+ <button type="button" {onclick} class={combinedClasses} aria-label={ariaLabel}>
35
+ {#if children}{@render children()}{/if}
36
+ </button>
37
+ {:else}
38
+ <div class={combinedClasses} role={ariaLabel ? 'region' : undefined} aria-label={ariaLabel}>
39
+ {#if children}{@render children()}{/if}
40
+ </div>
41
+ {/if}
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ href?: string;
4
+ target?: string;
5
+ rel?: string;
6
+ onclick?: () => void;
7
+ class?: string;
8
+ ariaLabel?: string;
9
+ children?: Snippet;
10
+ }
11
+ declare const InternalCard: import("svelte").Component<Props, {}, "">;
12
+ type InternalCard = ReturnType<typeof InternalCard>;
13
+ export default InternalCard;
14
+ //# sourceMappingURL=InternalCard.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"InternalCard.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/ui/InternalCard.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGrC,UAAU,KAAK;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAoCF,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -0,0 +1,74 @@
1
+ <script lang="ts">
2
+ import { ChevronLeft, ChevronRight } from '@lucide/svelte';
3
+
4
+ interface Props {
5
+ currentPage: number;
6
+ totalPages: number;
7
+ totalItems: number;
8
+ itemsPerPage: number;
9
+ onPageChange: (page: number) => void;
10
+ }
11
+
12
+ let { currentPage, totalPages, totalItems, itemsPerPage, onPageChange }: Props = $props();
13
+
14
+ function getPageNumbers(current: number, total: number): (number | string)[] {
15
+ if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1);
16
+ const pages: (number | string)[] = [1];
17
+ if (current > 3) pages.push('...');
18
+ const start = Math.max(2, current - 1);
19
+ const end = Math.min(total - 1, current + 1);
20
+ for (let i = start; i <= end; i++) pages.push(i);
21
+ if (current < total - 2) pages.push('...');
22
+ if (total > 1) pages.push(total);
23
+ return pages;
24
+ }
25
+
26
+ const pageNumbers = $derived(getPageNumbers(currentPage, totalPages));
27
+ const startItem = $derived((currentPage - 1) * itemsPerPage + 1);
28
+ const endItem = $derived(Math.min(currentPage * itemsPerPage, totalItems));
29
+ </script>
30
+
31
+ {#if totalPages > 1}
32
+ <nav class="mt-12" aria-label="Pagination navigation">
33
+ <div class="flex items-center justify-center gap-2" role="navigation">
34
+ <button
35
+ onclick={() => currentPage > 1 && onPageChange(currentPage - 1)}
36
+ disabled={currentPage === 1}
37
+ class="flex h-10 w-10 items-center justify-center rounded-lg border-2 border-canvas-300 bg-canvas-100 text-ink-700 transition-colors hover:bg-canvas-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 disabled:cursor-not-allowed disabled:opacity-50 dark:border-canvas-700 dark:bg-canvas-900 dark:text-ink-200 dark:hover:bg-canvas-800"
38
+ aria-label="Go to previous page"
39
+ >
40
+ <ChevronLeft class="h-5 w-5" aria-hidden="true" />
41
+ </button>
42
+
43
+ {#each pageNumbers as page}
44
+ {#if page === '...'}
45
+ <span class="px-2 text-ink-500 dark:text-ink-400" aria-hidden="true">...</span>
46
+ {:else}
47
+ <button
48
+ onclick={() => onPageChange(page as number)}
49
+ class="flex h-10 min-w-[2.5rem] items-center justify-center rounded-lg border-2 px-3 font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 {currentPage === page
50
+ ? 'border-primary-500 bg-primary-500 text-white dark:border-primary-400 dark:bg-primary-400'
51
+ : 'border-canvas-300 bg-canvas-100 text-ink-700 hover:bg-canvas-200 dark:border-canvas-700 dark:bg-canvas-900 dark:text-ink-200 dark:hover:bg-canvas-800'}"
52
+ aria-label="Go to page {page}"
53
+ aria-current={currentPage === page ? 'page' : undefined}
54
+ >
55
+ {page}
56
+ </button>
57
+ {/if}
58
+ {/each}
59
+
60
+ <button
61
+ onclick={() => currentPage < totalPages && onPageChange(currentPage + 1)}
62
+ disabled={currentPage === totalPages}
63
+ class="flex h-10 w-10 items-center justify-center rounded-lg border-2 border-canvas-300 bg-canvas-100 text-ink-700 transition-colors hover:bg-canvas-200 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 disabled:cursor-not-allowed disabled:opacity-50 dark:border-canvas-700 dark:bg-canvas-900 dark:text-ink-200 dark:hover:bg-canvas-800"
64
+ aria-label="Go to next page"
65
+ >
66
+ <ChevronRight class="h-5 w-5" aria-hidden="true" />
67
+ </button>
68
+ </div>
69
+ <p class="mt-4 text-center text-sm text-ink-600 dark:text-ink-300" role="status" aria-live="polite" aria-atomic="true">
70
+ Page {currentPage} of {totalPages} &middot; Showing {startItem}–{endItem} of {totalItems}
71
+ {totalItems === 1 ? 'item' : 'items'}
72
+ </p>
73
+ </nav>
74
+ {/if}
@@ -0,0 +1,11 @@
1
+ interface Props {
2
+ currentPage: number;
3
+ totalPages: number;
4
+ totalItems: number;
5
+ itemsPerPage: number;
6
+ onPageChange: (page: number) => void;
7
+ }
8
+ declare const Pagination: import("svelte").Component<Props, {}, "">;
9
+ type Pagination = ReturnType<typeof Pagination>;
10
+ export default Pagination;
11
+ //# sourceMappingURL=Pagination.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Pagination.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/ui/Pagination.svelte.ts"],"names":[],"mappings":"AAMC,UAAU,KAAK;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAwDF,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -0,0 +1,40 @@
1
+ <script lang="ts">
2
+ import type { BlogPost } from '@ewanc26/atproto';
3
+ import BlogPostCard from './BlogPostCard.svelte';
4
+ import { getUserLocale } from '../../utils/locale.js';
5
+ import { groupPostsByDate, getSortedMonths, getSortedYears } from '../../helper/posts.js';
6
+
7
+ interface Props { posts: BlogPost[]; locale?: string; filterYear?: string | null; }
8
+ let { posts, locale, filterYear }: Props = $props();
9
+ let userLocale = $derived(locale || getUserLocale());
10
+ const groupedPosts = $derived(groupPostsByDate(posts, userLocale));
11
+ const sortedYears = $derived(
12
+ filterYear && filterYear !== 'all'
13
+ ? [parseInt(filterYear)].filter((year) => groupedPosts.has(year))
14
+ : getSortedYears(groupedPosts)
15
+ );
16
+ </script>
17
+
18
+ <div class="space-y-12">
19
+ {#each sortedYears as year}
20
+ {@const yearGroup = groupedPosts.get(year)}
21
+ {#if yearGroup}
22
+ {@const sortedMonths = getSortedMonths(yearGroup)}
23
+ <section>
24
+ <h2 class="mb-6 text-3xl font-bold text-ink-900 dark:text-ink-50">{year}</h2>
25
+ <div class="space-y-8">
26
+ {#each sortedMonths as [_, monthData]}
27
+ <div>
28
+ <h3 class="mb-4 text-xl font-semibold text-ink-800 dark:text-ink-100">{monthData.monthName}</h3>
29
+ <div class="space-y-3">
30
+ {#each monthData.posts as post}
31
+ <BlogPostCard {post} locale={userLocale} />
32
+ {/each}
33
+ </div>
34
+ </div>
35
+ {/each}
36
+ </div>
37
+ </section>
38
+ {/if}
39
+ {/each}
40
+ </div>
@@ -0,0 +1,10 @@
1
+ import type { BlogPost } from '@ewanc26/atproto';
2
+ interface Props {
3
+ posts: BlogPost[];
4
+ locale?: string;
5
+ filterYear?: string | null;
6
+ }
7
+ declare const PostsGroupedView: import("svelte").Component<Props, {}, "">;
8
+ type PostsGroupedView = ReturnType<typeof PostsGroupedView>;
9
+ export default PostsGroupedView;
10
+ //# sourceMappingURL=PostsGroupedView.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostsGroupedView.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/ui/PostsGroupedView.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAMhD,UAAU,KAAK;IAAG,KAAK,EAAE,QAAQ,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAAE;AA2CpF,QAAA,MAAM,gBAAgB,2CAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,26 @@
1
+ <script lang="ts">
2
+ import { Search } from '@lucide/svelte';
3
+ interface Props { value: string; placeholder?: string; resultCount?: number; }
4
+ let { value = $bindable(), placeholder = 'Search...', resultCount }: Props = $props();
5
+ </script>
6
+
7
+ <div role="search">
8
+ <label for="search-input" class="sr-only">Search</label>
9
+ <div class="relative">
10
+ <Search class="absolute top-1/2 left-3 h-5 w-5 -translate-y-1/2 text-ink-500 dark:text-ink-400" aria-hidden="true" />
11
+ <input
12
+ id="search-input"
13
+ type="search"
14
+ {placeholder}
15
+ bind:value
16
+ class="w-full rounded-lg border-2 border-canvas-300 bg-canvas-100 py-3 pr-4 pl-11 text-ink-900 placeholder-ink-500 transition-colors focus:border-primary-500 focus:ring-2 focus:ring-primary-500/20 focus:outline-none dark:border-canvas-700 dark:bg-canvas-900 dark:text-ink-50 dark:placeholder-ink-400 dark:focus:border-primary-400"
17
+ aria-label="Search"
18
+ autocomplete="off"
19
+ />
20
+ </div>
21
+ {#if value && resultCount !== undefined}
22
+ <p class="mt-2 text-sm text-ink-600 dark:text-ink-300" role="status" aria-live="polite">
23
+ Found {resultCount} {resultCount === 1 ? 'result' : 'results'}
24
+ </p>
25
+ {/if}
26
+ </div>
@@ -0,0 +1,9 @@
1
+ interface Props {
2
+ value: string;
3
+ placeholder?: string;
4
+ resultCount?: number;
5
+ }
6
+ declare const SearchBar: import("svelte").Component<Props, {}, "value">;
7
+ type SearchBar = ReturnType<typeof SearchBar>;
8
+ export default SearchBar;
9
+ //# sourceMappingURL=SearchBar.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchBar.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/ui/SearchBar.svelte.ts"],"names":[],"mappings":"AAKC,UAAU,KAAK;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAAE;AAsB/E,QAAA,MAAM,SAAS,gDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -0,0 +1,25 @@
1
+ <script lang="ts">
2
+ interface Tab { id: string; label: string; }
3
+ interface Props { tabs: Tab[]; activeTab: string; onTabChange: (tabId: string) => void; }
4
+ let { tabs, activeTab, onTabChange }: Props = $props();
5
+ </script>
6
+
7
+ <div class="mb-8" role="tablist" aria-label="Content tabs">
8
+ <div class="flex flex-wrap gap-2">
9
+ {#each tabs as tab}
10
+ <button
11
+ onclick={() => onTabChange(tab.id)}
12
+ role="tab"
13
+ aria-selected={activeTab === tab.id}
14
+ aria-controls="{tab.id}-panel"
15
+ id="{tab.id}-tab"
16
+ tabindex={activeTab === tab.id ? 0 : -1}
17
+ class="rounded-full px-4 py-2 text-sm font-medium transition-all focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 {activeTab === tab.id
18
+ ? 'bg-primary-500 text-white shadow-md dark:bg-primary-400'
19
+ : 'bg-canvas-200 text-ink-700 hover:bg-canvas-300 dark:bg-canvas-800 dark:text-ink-200 dark:hover:bg-canvas-700'}"
20
+ >
21
+ {tab.label}
22
+ </button>
23
+ {/each}
24
+ </div>
25
+ </div>
@@ -0,0 +1,13 @@
1
+ interface Tab {
2
+ id: string;
3
+ label: string;
4
+ }
5
+ interface Props {
6
+ tabs: Tab[];
7
+ activeTab: string;
8
+ onTabChange: (tabId: string) => void;
9
+ }
10
+ declare const Tabs: import("svelte").Component<Props, {}, "">;
11
+ type Tabs = ReturnType<typeof Tabs>;
12
+ export default Tabs;
13
+ //# sourceMappingURL=Tabs.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tabs.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/ui/Tabs.svelte.ts"],"names":[],"mappings":"AAGC,UAAU,GAAG;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;CAAE;AAC5C,UAAU,KAAK;IAAG,IAAI,EAAE,GAAG,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAAE;AAqB1F,QAAA,MAAM,IAAI,2CAAwC,CAAC;AACnD,KAAK,IAAI,GAAG,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC;AACpC,eAAe,IAAI,CAAC"}
@@ -0,0 +1,11 @@
1
+ export { default as Card } from './Card.svelte';
2
+ export { default as InternalCard } from './InternalCard.svelte';
3
+ export { default as Dropdown } from './Dropdown.svelte';
4
+ export { default as Pagination } from './Pagination.svelte';
5
+ export { default as SearchBar } from './SearchBar.svelte';
6
+ export { default as Tabs } from './Tabs.svelte';
7
+ export { default as PostsGroupedView } from './PostsGroupedView.svelte';
8
+ export { default as DocumentCard } from './DocumentCard.svelte';
9
+ /** @deprecated Use DocumentCard instead */
10
+ export { default as BlogPostCard } from './BlogPostCard.svelte';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/components/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,2CAA2C;AAC3C,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { default as Card } from './Card.svelte';
2
+ export { default as InternalCard } from './InternalCard.svelte';
3
+ export { default as Dropdown } from './Dropdown.svelte';
4
+ export { default as Pagination } from './Pagination.svelte';
5
+ export { default as SearchBar } from './SearchBar.svelte';
6
+ export { default as Tabs } from './Tabs.svelte';
7
+ export { default as PostsGroupedView } from './PostsGroupedView.svelte';
8
+ export { default as DocumentCard } from './DocumentCard.svelte';
9
+ /** @deprecated Use DocumentCard instead */
10
+ export { default as BlogPostCard } from './BlogPostCard.svelte';
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Central theme configuration
3
+ * Add new themes here and they'll automatically appear in the dropdown and type system
4
+ */
5
+ export interface ThemeDefinition {
6
+ value: string;
7
+ label: string;
8
+ description: string;
9
+ color: string;
10
+ category: 'neutral' | 'warm' | 'cool' | 'vibrant';
11
+ }
12
+ export declare const THEMES: readonly ThemeDefinition[];
13
+ export type ColorTheme = (typeof THEMES)[number]['value'];
14
+ export declare const DEFAULT_THEME: ColorTheme;
15
+ export declare const CATEGORY_LABELS: {
16
+ readonly neutral: "Neutral";
17
+ readonly warm: "Warm";
18
+ readonly cool: "Cool";
19
+ readonly vibrant: "Vibrant";
20
+ };
21
+ export declare const getThemesByCategory: () => Record<"neutral" | "warm" | "cool" | "vibrant", ThemeDefinition[]>;
22
+ export declare const getTheme: (value: string) => ThemeDefinition | undefined;
23
+ //# sourceMappingURL=themes.config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themes.config.d.ts","sourceRoot":"","sources":["../../src/lib/config/themes.config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAClD;AAED,eAAO,MAAM,MAAM,EAAE,SAAS,eAAe,EAyFnC,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC;AAC1D,eAAO,MAAM,aAAa,EAAE,UAAoB,CAAC;AAEjD,eAAO,MAAM,eAAe;;;;;CAKlB,CAAC;AAEX,eAAO,MAAM,mBAAmB,0EAW/B,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,OAAO,MAAM,KAAG,eAAe,GAAG,SAE1D,CAAC"}