@autumnsgrove/groveengine 0.3.2 → 0.4.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 (270) hide show
  1. package/dist/auth/index.d.ts +2 -0
  2. package/dist/auth/index.js +5 -0
  3. package/dist/components/admin/GutterManager.svelte +4 -4
  4. package/dist/components/admin/MarkdownEditor.svelte +381 -1311
  5. package/dist/components/admin/MarkdownEditor.svelte.d.ts +2 -8
  6. package/dist/components/admin/composables/index.d.ts +7 -0
  7. package/dist/components/admin/composables/index.js +12 -0
  8. package/dist/components/admin/composables/useAmbientSounds.svelte.d.ts +53 -0
  9. package/dist/components/admin/composables/useAmbientSounds.svelte.js +192 -0
  10. package/dist/components/admin/composables/useCommandPalette.svelte.d.ts +17 -0
  11. package/dist/components/admin/composables/useCommandPalette.svelte.js +118 -0
  12. package/dist/components/admin/composables/useDraftManager.svelte.d.ts +17 -0
  13. package/dist/components/admin/composables/useDraftManager.svelte.js +154 -0
  14. package/dist/components/admin/composables/useEditorTheme.svelte.d.ts +195 -0
  15. package/dist/components/admin/composables/useEditorTheme.svelte.js +182 -0
  16. package/dist/components/admin/composables/useSlashCommands.svelte.d.ts +32 -0
  17. package/dist/components/admin/composables/useSlashCommands.svelte.js +166 -0
  18. package/dist/components/admin/composables/useSnippets.svelte.d.ts +5 -0
  19. package/dist/components/admin/composables/useSnippets.svelte.js +122 -0
  20. package/dist/components/admin/composables/useWritingSession.svelte.d.ts +13 -0
  21. package/dist/components/admin/composables/useWritingSession.svelte.js +100 -0
  22. package/dist/components/custom/ContentWithGutter.svelte +1 -1
  23. package/dist/components/custom/GutterItem.svelte +2 -2
  24. package/dist/config/ai-models.d.ts +25 -0
  25. package/dist/config/ai-models.js +50 -0
  26. package/dist/config/index.d.ts +1 -0
  27. package/dist/config/index.js +4 -0
  28. package/dist/index.d.ts +5 -5
  29. package/dist/index.js +6 -6
  30. package/dist/server/index.d.ts +1 -0
  31. package/dist/server/index.js +4 -0
  32. package/dist/ui/components/charts/ActivityOverview.svelte +293 -0
  33. package/dist/ui/components/charts/ActivityOverview.svelte.d.ts +12 -0
  34. package/dist/ui/components/charts/LOCBar.svelte +129 -0
  35. package/dist/ui/components/charts/LOCBar.svelte.d.ts +21 -0
  36. package/dist/ui/components/charts/RepoBreakdown.svelte +136 -0
  37. package/dist/ui/components/charts/RepoBreakdown.svelte.d.ts +16 -0
  38. package/dist/ui/components/charts/Sparkline.svelte +139 -0
  39. package/dist/ui/components/charts/Sparkline.svelte.d.ts +6 -0
  40. package/dist/ui/components/charts/index.d.ts +5 -0
  41. package/dist/ui/components/charts/index.js +11 -0
  42. package/dist/ui/components/content/PlanCard.svelte +91 -0
  43. package/dist/ui/components/content/PlanCard.svelte.d.ts +13 -0
  44. package/dist/ui/components/content/ProductCard.svelte +125 -0
  45. package/dist/ui/components/content/ProductCard.svelte.d.ts +14 -0
  46. package/dist/ui/components/content/SearchCard.svelte +60 -0
  47. package/dist/ui/components/content/SearchCard.svelte.d.ts +10 -0
  48. package/dist/ui/components/content/index.d.ts +4 -0
  49. package/dist/ui/components/content/index.js +10 -0
  50. package/dist/ui/components/forms/SearchInput.svelte +89 -0
  51. package/dist/ui/components/forms/SearchInput.svelte.d.ts +11 -0
  52. package/dist/ui/components/forms/index.d.ts +2 -0
  53. package/dist/ui/components/forms/index.js +8 -0
  54. package/dist/ui/components/gallery/index.d.ts +5 -0
  55. package/dist/ui/components/gallery/index.js +13 -0
  56. package/dist/ui/components/icons/IconLegend.svelte +83 -0
  57. package/dist/ui/components/icons/IconLegend.svelte.d.ts +11 -0
  58. package/dist/ui/components/icons/Icons.svelte +115 -0
  59. package/dist/ui/components/icons/Icons.svelte.d.ts +8 -0
  60. package/dist/ui/components/icons/index.d.ts +3 -0
  61. package/dist/ui/components/icons/index.js +9 -0
  62. package/dist/ui/components/indicators/CreditBalance.svelte +67 -0
  63. package/dist/ui/components/indicators/CreditBalance.svelte.d.ts +9 -0
  64. package/dist/ui/components/indicators/ScoreBar.svelte +63 -0
  65. package/dist/ui/components/indicators/ScoreBar.svelte.d.ts +9 -0
  66. package/dist/ui/components/indicators/StatusBadge.svelte +46 -0
  67. package/dist/ui/components/indicators/StatusBadge.svelte.d.ts +7 -0
  68. package/dist/ui/components/indicators/index.d.ts +4 -0
  69. package/dist/ui/components/indicators/index.js +10 -0
  70. package/dist/{components/ui → ui/components/primitives}/accordion/accordion-content.svelte +1 -1
  71. package/dist/{components/ui → ui/components/primitives}/accordion/accordion-item.svelte +1 -1
  72. package/dist/{components/ui → ui/components/primitives}/accordion/accordion-trigger.svelte +1 -1
  73. package/dist/ui/components/primitives/badge/badge.svelte +50 -0
  74. package/dist/ui/components/primitives/badge/badge.svelte.d.ts +60 -0
  75. package/dist/ui/components/primitives/badge/index.d.ts +2 -0
  76. package/dist/ui/components/primitives/badge/index.js +2 -0
  77. package/dist/ui/components/primitives/button/button.svelte +82 -0
  78. package/dist/ui/components/primitives/button/button.svelte.d.ts +132 -0
  79. package/dist/ui/components/primitives/button/index.d.ts +2 -0
  80. package/dist/ui/components/primitives/button/index.js +4 -0
  81. package/dist/ui/components/primitives/card/card-content.svelte +16 -0
  82. package/dist/ui/components/primitives/card/card-content.svelte.d.ts +5 -0
  83. package/dist/ui/components/primitives/card/card-description.svelte +16 -0
  84. package/dist/ui/components/primitives/card/card-description.svelte.d.ts +5 -0
  85. package/dist/ui/components/primitives/card/card-footer.svelte +16 -0
  86. package/dist/ui/components/primitives/card/card-footer.svelte.d.ts +5 -0
  87. package/dist/ui/components/primitives/card/card-header.svelte +16 -0
  88. package/dist/ui/components/primitives/card/card-header.svelte.d.ts +5 -0
  89. package/dist/ui/components/primitives/card/card-title.svelte +25 -0
  90. package/dist/ui/components/primitives/card/card-title.svelte.d.ts +8 -0
  91. package/dist/ui/components/primitives/card/card.svelte +20 -0
  92. package/dist/ui/components/primitives/card/card.svelte.d.ts +5 -0
  93. package/dist/ui/components/primitives/card/index.d.ts +7 -0
  94. package/dist/ui/components/primitives/card/index.js +9 -0
  95. package/dist/{components/ui → ui/components/primitives}/dialog/dialog-content.svelte +1 -1
  96. package/dist/{components/ui → ui/components/primitives}/dialog/dialog-description.svelte +1 -1
  97. package/dist/{components/ui → ui/components/primitives}/dialog/dialog-footer.svelte +1 -1
  98. package/dist/{components/ui → ui/components/primitives}/dialog/dialog-header.svelte +1 -1
  99. package/dist/{components/ui → ui/components/primitives}/dialog/dialog-overlay.svelte +1 -1
  100. package/dist/{components/ui → ui/components/primitives}/dialog/dialog-title.svelte +1 -1
  101. package/dist/ui/components/primitives/input/index.d.ts +2 -0
  102. package/dist/ui/components/primitives/input/index.js +4 -0
  103. package/dist/ui/components/primitives/input/input.svelte +46 -0
  104. package/dist/ui/components/primitives/input/input.svelte.d.ts +13 -0
  105. package/dist/{components/ui → ui/components/primitives}/select/select-content.svelte +1 -1
  106. package/dist/{components/ui → ui/components/primitives}/select/select-group-heading.svelte +1 -1
  107. package/dist/{components/ui → ui/components/primitives}/select/select-item.svelte +1 -1
  108. package/dist/{components/ui → ui/components/primitives}/select/select-scroll-down-button.svelte +1 -1
  109. package/dist/{components/ui → ui/components/primitives}/select/select-scroll-up-button.svelte +1 -1
  110. package/dist/{components/ui → ui/components/primitives}/select/select-separator.svelte +1 -1
  111. package/dist/{components/ui → ui/components/primitives}/select/select-trigger.svelte +1 -1
  112. package/dist/ui/components/primitives/separator/index.d.ts +2 -0
  113. package/dist/ui/components/primitives/separator/index.js +4 -0
  114. package/dist/ui/components/primitives/separator/separator.svelte +22 -0
  115. package/dist/ui/components/primitives/separator/separator.svelte.d.ts +4 -0
  116. package/dist/{components/ui → ui/components/primitives}/sheet/sheet-content.svelte +1 -1
  117. package/dist/{components/ui → ui/components/primitives}/sheet/sheet-description.svelte +1 -1
  118. package/dist/{components/ui → ui/components/primitives}/sheet/sheet-footer.svelte +1 -1
  119. package/dist/{components/ui → ui/components/primitives}/sheet/sheet-header.svelte +1 -1
  120. package/dist/{components/ui → ui/components/primitives}/sheet/sheet-overlay.svelte +1 -1
  121. package/dist/{components/ui → ui/components/primitives}/sheet/sheet-title.svelte +1 -1
  122. package/dist/ui/components/primitives/skeleton/index.d.ts +2 -0
  123. package/dist/ui/components/primitives/skeleton/index.js +4 -0
  124. package/dist/ui/components/primitives/skeleton/skeleton.svelte +17 -0
  125. package/dist/ui/components/primitives/skeleton/skeleton.svelte.d.ts +5 -0
  126. package/dist/{components/ui → ui/components/primitives}/table/table-body.svelte +1 -1
  127. package/dist/{components/ui → ui/components/primitives}/table/table-caption.svelte +1 -1
  128. package/dist/{components/ui → ui/components/primitives}/table/table-cell.svelte +1 -1
  129. package/dist/{components/ui → ui/components/primitives}/table/table-footer.svelte +1 -1
  130. package/dist/{components/ui → ui/components/primitives}/table/table-head.svelte +1 -1
  131. package/dist/{components/ui → ui/components/primitives}/table/table-header.svelte +1 -1
  132. package/dist/{components/ui → ui/components/primitives}/table/table-row.svelte +1 -1
  133. package/dist/{components/ui → ui/components/primitives}/table/table.svelte +1 -1
  134. package/dist/{components/ui → ui/components/primitives}/tabs/tabs-content.svelte +1 -1
  135. package/dist/{components/ui → ui/components/primitives}/tabs/tabs-list.svelte +1 -1
  136. package/dist/{components/ui → ui/components/primitives}/tabs/tabs-trigger.svelte +1 -1
  137. package/dist/ui/components/primitives/textarea/index.d.ts +2 -0
  138. package/dist/ui/components/primitives/textarea/index.js +4 -0
  139. package/dist/ui/components/primitives/textarea/textarea.svelte +24 -0
  140. package/dist/ui/components/primitives/textarea/textarea.svelte.d.ts +6 -0
  141. package/dist/ui/components/states/EmptyState.svelte +28 -0
  142. package/dist/ui/components/states/EmptyState.svelte.d.ts +10 -0
  143. package/dist/ui/components/states/Loading.svelte +62 -0
  144. package/dist/ui/components/states/Loading.svelte.d.ts +7 -0
  145. package/dist/ui/components/states/LoadingSkeleton.svelte +46 -0
  146. package/dist/ui/components/states/LoadingSkeleton.svelte.d.ts +8 -0
  147. package/dist/ui/components/states/ThemeToggle.svelte +138 -0
  148. package/dist/ui/components/states/ThemeToggle.svelte.d.ts +6 -0
  149. package/dist/ui/components/states/index.d.ts +5 -0
  150. package/dist/ui/components/states/index.js +11 -0
  151. package/dist/{components → ui/components}/ui/Accordion.svelte +1 -1
  152. package/dist/ui/components/ui/Badge.svelte +52 -0
  153. package/dist/ui/components/ui/Badge.svelte.d.ts +28 -0
  154. package/dist/ui/components/ui/Button.svelte +77 -0
  155. package/dist/ui/components/ui/Button.svelte.d.ts +34 -0
  156. package/dist/ui/components/ui/Card.svelte +102 -0
  157. package/dist/ui/components/ui/Card.svelte.d.ts +46 -0
  158. package/dist/ui/components/ui/CollapsibleSection.svelte +65 -0
  159. package/dist/ui/components/ui/CollapsibleSection.svelte.d.ts +10 -0
  160. package/dist/{components → ui/components}/ui/Dialog.svelte +1 -1
  161. package/dist/ui/components/ui/Input.svelte +81 -0
  162. package/dist/ui/components/ui/Input.svelte.d.ts +35 -0
  163. package/dist/{components → ui/components}/ui/Select.svelte +1 -1
  164. package/dist/{components → ui/components}/ui/Sheet.svelte +1 -1
  165. package/dist/ui/components/ui/Skeleton.svelte +31 -0
  166. package/dist/ui/components/ui/Skeleton.svelte.d.ts +26 -0
  167. package/dist/ui/components/ui/Spinner.svelte +45 -0
  168. package/dist/ui/components/ui/Spinner.svelte.d.ts +15 -0
  169. package/dist/{components → ui/components}/ui/Table.svelte +2 -2
  170. package/dist/{components → ui/components}/ui/Table.svelte.d.ts +1 -1
  171. package/dist/{components → ui/components}/ui/Tabs.svelte +2 -2
  172. package/dist/ui/components/ui/Textarea.svelte +81 -0
  173. package/dist/ui/components/ui/Textarea.svelte.d.ts +35 -0
  174. package/dist/{components → ui/components}/ui/Toast.svelte +1 -1
  175. package/dist/ui/components/ui/index.d.ts +18 -0
  176. package/dist/ui/components/ui/index.js +28 -0
  177. package/dist/{components → ui/components}/ui/toast.d.ts +1 -1
  178. package/dist/{components → ui/components}/ui/toast.js +2 -2
  179. package/dist/ui/index.d.ts +10 -0
  180. package/dist/ui/index.js +22 -0
  181. package/dist/ui/stores/theme.d.ts +12 -0
  182. package/dist/ui/stores/theme.js +52 -0
  183. package/dist/ui/styles/content.css +514 -0
  184. package/dist/ui/styles/grove.css +715 -0
  185. package/dist/ui/styles/tokens.css +429 -0
  186. package/dist/ui/tailwind.preset.d.ts +340 -0
  187. package/dist/ui/tailwind.preset.js +441 -0
  188. package/dist/ui/tokens/animation.d.ts +417 -0
  189. package/dist/ui/tokens/animation.js +139 -0
  190. package/dist/ui/tokens/colors.d.ts +183 -0
  191. package/dist/ui/tokens/colors.js +97 -0
  192. package/dist/ui/tokens/effects.d.ts +111 -0
  193. package/dist/ui/tokens/effects.js +61 -0
  194. package/dist/ui/tokens/index.d.ts +6 -0
  195. package/dist/ui/tokens/index.js +19 -0
  196. package/dist/ui/tokens/spacing.d.ts +89 -0
  197. package/dist/ui/tokens/spacing.js +49 -0
  198. package/dist/ui/tokens/typography.d.ts +85 -0
  199. package/dist/ui/tokens/typography.js +68 -0
  200. package/dist/ui/utils/cn.d.ts +13 -0
  201. package/dist/ui/utils/cn.js +24 -0
  202. package/dist/ui/utils/index.d.ts +2 -0
  203. package/dist/ui/utils/index.js +8 -0
  204. package/dist/utils/index.d.ts +11 -0
  205. package/dist/utils/index.js +14 -0
  206. package/dist/utils/markdown.d.ts +11 -0
  207. package/dist/utils/markdown.js +25 -0
  208. package/dist/utils/sanitize.js +2 -3
  209. package/package.json +73 -10
  210. package/dist/components/ui/index.d.ts +0 -14
  211. package/dist/components/ui/index.js +0 -18
  212. /package/dist/{components → ui/components}/gallery/ImageGallery.svelte +0 -0
  213. /package/dist/{components → ui/components}/gallery/ImageGallery.svelte.d.ts +0 -0
  214. /package/dist/{components → ui/components}/gallery/Lightbox.svelte +0 -0
  215. /package/dist/{components → ui/components}/gallery/Lightbox.svelte.d.ts +0 -0
  216. /package/dist/{components → ui/components}/gallery/LightboxCaption.svelte +0 -0
  217. /package/dist/{components → ui/components}/gallery/LightboxCaption.svelte.d.ts +0 -0
  218. /package/dist/{components → ui/components}/gallery/ZoomableImage.svelte +0 -0
  219. /package/dist/{components → ui/components}/gallery/ZoomableImage.svelte.d.ts +0 -0
  220. /package/dist/{components/ui → ui/components/primitives}/accordion/accordion-content.svelte.d.ts +0 -0
  221. /package/dist/{components/ui → ui/components/primitives}/accordion/accordion-item.svelte.d.ts +0 -0
  222. /package/dist/{components/ui → ui/components/primitives}/accordion/accordion-trigger.svelte.d.ts +0 -0
  223. /package/dist/{components/ui → ui/components/primitives}/accordion/index.d.ts +0 -0
  224. /package/dist/{components/ui → ui/components/primitives}/accordion/index.js +0 -0
  225. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-content.svelte.d.ts +0 -0
  226. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-description.svelte.d.ts +0 -0
  227. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-footer.svelte.d.ts +0 -0
  228. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-header.svelte.d.ts +0 -0
  229. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-overlay.svelte.d.ts +0 -0
  230. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-title.svelte.d.ts +0 -0
  231. /package/dist/{components/ui → ui/components/primitives}/dialog/index.d.ts +0 -0
  232. /package/dist/{components/ui → ui/components/primitives}/dialog/index.js +0 -0
  233. /package/dist/{components/ui → ui/components/primitives}/select/index.d.ts +0 -0
  234. /package/dist/{components/ui → ui/components/primitives}/select/index.js +0 -0
  235. /package/dist/{components/ui → ui/components/primitives}/select/select-content.svelte.d.ts +0 -0
  236. /package/dist/{components/ui → ui/components/primitives}/select/select-group-heading.svelte.d.ts +0 -0
  237. /package/dist/{components/ui → ui/components/primitives}/select/select-item.svelte.d.ts +0 -0
  238. /package/dist/{components/ui → ui/components/primitives}/select/select-scroll-down-button.svelte.d.ts +0 -0
  239. /package/dist/{components/ui → ui/components/primitives}/select/select-scroll-up-button.svelte.d.ts +0 -0
  240. /package/dist/{components/ui → ui/components/primitives}/select/select-separator.svelte.d.ts +0 -0
  241. /package/dist/{components/ui → ui/components/primitives}/select/select-trigger.svelte.d.ts +0 -0
  242. /package/dist/{components/ui → ui/components/primitives}/sheet/index.d.ts +0 -0
  243. /package/dist/{components/ui → ui/components/primitives}/sheet/index.js +0 -0
  244. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-content.svelte.d.ts +0 -0
  245. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-description.svelte.d.ts +0 -0
  246. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-footer.svelte.d.ts +0 -0
  247. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-header.svelte.d.ts +0 -0
  248. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-overlay.svelte.d.ts +0 -0
  249. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-title.svelte.d.ts +0 -0
  250. /package/dist/{components/ui → ui/components/primitives}/table/index.d.ts +0 -0
  251. /package/dist/{components/ui → ui/components/primitives}/table/index.js +0 -0
  252. /package/dist/{components/ui → ui/components/primitives}/table/table-body.svelte.d.ts +0 -0
  253. /package/dist/{components/ui → ui/components/primitives}/table/table-caption.svelte.d.ts +0 -0
  254. /package/dist/{components/ui → ui/components/primitives}/table/table-cell.svelte.d.ts +0 -0
  255. /package/dist/{components/ui → ui/components/primitives}/table/table-footer.svelte.d.ts +0 -0
  256. /package/dist/{components/ui → ui/components/primitives}/table/table-head.svelte.d.ts +0 -0
  257. /package/dist/{components/ui → ui/components/primitives}/table/table-header.svelte.d.ts +0 -0
  258. /package/dist/{components/ui → ui/components/primitives}/table/table-row.svelte.d.ts +0 -0
  259. /package/dist/{components/ui → ui/components/primitives}/table/table.svelte.d.ts +0 -0
  260. /package/dist/{components/ui → ui/components/primitives}/tabs/index.d.ts +0 -0
  261. /package/dist/{components/ui → ui/components/primitives}/tabs/index.js +0 -0
  262. /package/dist/{components/ui → ui/components/primitives}/tabs/tabs-content.svelte.d.ts +0 -0
  263. /package/dist/{components/ui → ui/components/primitives}/tabs/tabs-list.svelte.d.ts +0 -0
  264. /package/dist/{components/ui → ui/components/primitives}/tabs/tabs-trigger.svelte.d.ts +0 -0
  265. /package/dist/{components → ui/components}/ui/Accordion.svelte.d.ts +0 -0
  266. /package/dist/{components → ui/components}/ui/Dialog.svelte.d.ts +0 -0
  267. /package/dist/{components → ui/components}/ui/Select.svelte.d.ts +0 -0
  268. /package/dist/{components → ui/components}/ui/Sheet.svelte.d.ts +0 -0
  269. /package/dist/{components → ui/components}/ui/Tabs.svelte.d.ts +0 -0
  270. /package/dist/{components → ui/components}/ui/Toast.svelte.d.ts +0 -0
@@ -0,0 +1,14 @@
1
+ interface Props {
2
+ name: string;
3
+ price: number;
4
+ originalPrice?: number;
5
+ retailer: string;
6
+ url: string;
7
+ imageUrl?: string;
8
+ matchScore?: number;
9
+ matchReason?: string;
10
+ index?: number;
11
+ }
12
+ declare const ProductCard: import("svelte").Component<Props, {}, "">;
13
+ type ProductCard = ReturnType<typeof ProductCard>;
14
+ export default ProductCard;
@@ -0,0 +1,60 @@
1
+ <script lang="ts">
2
+ import Icons from '../icons/Icons.svelte';
3
+ import StatusBadge from '../indicators/StatusBadge.svelte';
4
+
5
+ interface Props {
6
+ id: string;
7
+ query: string;
8
+ status: 'pending' | 'running' | 'completed' | 'failed' | 'needs_confirmation';
9
+ createdAt: string;
10
+ resultCount?: number;
11
+ }
12
+
13
+ let { id, query, status, createdAt, resultCount = 0 }: Props = $props();
14
+
15
+ const formattedDate = $derived(
16
+ new Date(createdAt).toLocaleDateString('en-US', {
17
+ month: 'short',
18
+ day: 'numeric',
19
+ hour: 'numeric',
20
+ minute: '2-digit'
21
+ })
22
+ );
23
+
24
+ const truncatedQuery = $derived(
25
+ query.length > 80 ? query.slice(0, 80) + '...' : query
26
+ );
27
+ </script>
28
+
29
+ <a
30
+ href="/search/{id}"
31
+ class="scout-card block p-4 hover:shadow-grove-md transition-all duration-grove group"
32
+ >
33
+ <div class="flex items-start justify-between gap-4">
34
+ <div class="flex-1 min-w-0">
35
+ <p class="font-medium text-bark dark:text-cream mb-1 group-hover:text-grove-600 dark:group-hover:text-grove-400 transition-colors">
36
+ {truncatedQuery}
37
+ </p>
38
+ <div class="flex items-center gap-3 text-sm text-bark-400 dark:text-cream-500">
39
+ <span class="flex items-center gap-1">
40
+ <Icons name="clock" size="sm" />
41
+ {formattedDate}
42
+ </span>
43
+ {#if status === 'completed' && resultCount > 0}
44
+ <span class="flex items-center gap-1">
45
+ <Icons name="shopping-bag" size="sm" />
46
+ {resultCount} results
47
+ </span>
48
+ {/if}
49
+ </div>
50
+ </div>
51
+ <StatusBadge {status} size="sm" />
52
+ </div>
53
+
54
+ {#if status === 'completed'}
55
+ <div class="mt-3 pt-3 border-t border-cream-300 dark:border-bark-600 flex items-center justify-between">
56
+ <span class="text-sm text-bark-500 dark:text-cream-500">View results</span>
57
+ <Icons name="arrow-right" size="sm" class="text-grove-500 group-hover:translate-x-1 transition-transform" />
58
+ </div>
59
+ {/if}
60
+ </a>
@@ -0,0 +1,10 @@
1
+ interface Props {
2
+ id: string;
3
+ query: string;
4
+ status: 'pending' | 'running' | 'completed' | 'failed' | 'needs_confirmation';
5
+ createdAt: string;
6
+ resultCount?: number;
7
+ }
8
+ declare const SearchCard: import("svelte").Component<Props, {}, "">;
9
+ type SearchCard = ReturnType<typeof SearchCard>;
10
+ export default SearchCard;
@@ -0,0 +1,4 @@
1
+ export { default as ProductCard } from './ProductCard.svelte';
2
+ export { default as SearchCard } from './SearchCard.svelte';
3
+ export { default as PlanCard } from './PlanCard.svelte';
4
+ export declare const CONTENT_VERSION = "0.2.0";
@@ -0,0 +1,10 @@
1
+ // GroveUI - Content Card Components
2
+ //
3
+ // This module exports content display cards (products, plans, search results)
4
+ //
5
+ // Usage:
6
+ // import { ProductCard, SearchCard, PlanCard } from '@groveengine/ui/content';
7
+ export { default as ProductCard } from './ProductCard.svelte';
8
+ export { default as SearchCard } from './SearchCard.svelte';
9
+ export { default as PlanCard } from './PlanCard.svelte';
10
+ export const CONTENT_VERSION = '0.2.0';
@@ -0,0 +1,89 @@
1
+ <script lang="ts">
2
+ import Icons from '../icons/Icons.svelte';
3
+
4
+ interface Props {
5
+ value?: string;
6
+ placeholder?: string;
7
+ disabled?: boolean;
8
+ loading?: boolean;
9
+ autofocus?: boolean;
10
+ onsubmit?: (value: string) => void;
11
+ }
12
+
13
+ let {
14
+ value = $bindable(''),
15
+ placeholder = 'Describe what you\'re looking for...',
16
+ disabled = false,
17
+ loading = false,
18
+ autofocus = false,
19
+ onsubmit
20
+ }: Props = $props();
21
+
22
+ function handleSubmit(e: Event) {
23
+ e.preventDefault();
24
+ if (value.trim() && onsubmit) {
25
+ onsubmit(value.trim());
26
+ }
27
+ }
28
+
29
+ function handleKeydown(e: KeyboardEvent) {
30
+ if (e.key === 'Enter' && !e.shiftKey) {
31
+ handleSubmit(e);
32
+ }
33
+ }
34
+
35
+ const examples = [
36
+ 'Cozy sweater, earth tones, under $60',
37
+ 'Wireless earbuds for running, waterproof',
38
+ 'Birthday gift for a coffee lover, $30-50',
39
+ 'Ergonomic office chair, good lumbar support'
40
+ ];
41
+
42
+ let showExamples = $state(false);
43
+ </script>
44
+
45
+ <form onsubmit={handleSubmit} class="w-full">
46
+ <div class="scout-search">
47
+ <Icons name="search" class="scout-search-icon" />
48
+ <textarea
49
+ bind:value
50
+ {placeholder}
51
+ disabled={disabled || loading}
52
+ rows="1"
53
+ {autofocus}
54
+ onkeydown={handleKeydown}
55
+ onfocus={() => showExamples = true}
56
+ onblur={() => setTimeout(() => showExamples = false, 200)}
57
+ class="scout-search-input resize-none min-h-[60px] max-h-[200px]"
58
+ ></textarea>
59
+ <button
60
+ type="submit"
61
+ disabled={disabled || loading || !value.trim()}
62
+ class="absolute right-3 top-1/2 -translate-y-1/2 scout-btn-primary px-4 py-2"
63
+ >
64
+ {#if loading}
65
+ <Icons name="loader" size="sm" class="animate-spin" />
66
+ Searching...
67
+ {:else}
68
+ <Icons name="sparkles" size="sm" />
69
+ Search
70
+ {/if}
71
+ </button>
72
+ </div>
73
+
74
+ <!-- Example queries -->
75
+ {#if showExamples && !value}
76
+ <div class="mt-3 flex flex-wrap gap-2">
77
+ <span class="text-sm text-bark-400 dark:text-cream-500">Try:</span>
78
+ {#each examples as example}
79
+ <button
80
+ type="button"
81
+ onclick={() => value = example}
82
+ class="text-sm text-grove-600 dark:text-grove-400 hover:underline cursor-pointer"
83
+ >
84
+ "{example.slice(0, 30)}..."
85
+ </button>
86
+ {/each}
87
+ </div>
88
+ {/if}
89
+ </form>
@@ -0,0 +1,11 @@
1
+ interface Props {
2
+ value?: string;
3
+ placeholder?: string;
4
+ disabled?: boolean;
5
+ loading?: boolean;
6
+ autofocus?: boolean;
7
+ onsubmit?: (value: string) => void;
8
+ }
9
+ declare const SearchInput: import("svelte").Component<Props, {}, "value">;
10
+ type SearchInput = ReturnType<typeof SearchInput>;
11
+ export default SearchInput;
@@ -0,0 +1,2 @@
1
+ export { default as SearchInput } from './SearchInput.svelte';
2
+ export declare const FORMS_VERSION = "0.2.0";
@@ -0,0 +1,8 @@
1
+ // GroveUI - Form Components
2
+ //
3
+ // This module exports specialized form input components
4
+ //
5
+ // Usage:
6
+ // import { SearchInput } from '@groveengine/ui/forms';
7
+ export { default as SearchInput } from './SearchInput.svelte';
8
+ export const FORMS_VERSION = '0.2.0';
@@ -0,0 +1,5 @@
1
+ export { default as ImageGallery } from './ImageGallery.svelte';
2
+ export { default as Lightbox } from './Lightbox.svelte';
3
+ export { default as LightboxCaption } from './LightboxCaption.svelte';
4
+ export { default as ZoomableImage } from './ZoomableImage.svelte';
5
+ export declare const GALLERY_VERSION = "0.2.0";
@@ -0,0 +1,13 @@
1
+ // GroveUI - Gallery Components
2
+ //
3
+ // This module exports gallery and media display components:
4
+ // ImageGallery, Lightbox, LightboxCaption, ZoomableImage
5
+ //
6
+ // Usage:
7
+ // import { ImageGallery, Lightbox } from '@groveengine/ui/gallery';
8
+ // Gallery components
9
+ export { default as ImageGallery } from './ImageGallery.svelte';
10
+ export { default as Lightbox } from './Lightbox.svelte';
11
+ export { default as LightboxCaption } from './LightboxCaption.svelte';
12
+ export { default as ZoomableImage } from './ZoomableImage.svelte';
13
+ export const GALLERY_VERSION = '0.2.0';
@@ -0,0 +1,83 @@
1
+ <script>
2
+ import CollapsibleSection from '../../../components/custom/CollapsibleSection.svelte';
3
+
4
+ let { iconsUsed = [] } = $props();
5
+
6
+ // Map icon keys to their semantic meanings and display names
7
+ const iconMeanings = {
8
+ stovetop: { name: 'Stovetop', meaning: 'Cook on stove/pan' },
9
+ mix: { name: 'Mix', meaning: 'Mix/stir in bowl' },
10
+ spicy: { name: 'Spicy', meaning: 'Spicy/hot indicator' },
11
+ chop: { name: 'Chop', meaning: 'Chop/prep ingredients' },
12
+ simmer: { name: 'Simmer', meaning: 'Simmer/wait' },
13
+ chill: { name: 'Chill', meaning: 'Refrigerate/chill' },
14
+ serve: { name: 'Serve', meaning: 'Plate/serve' },
15
+ boil: { name: 'Boil', meaning: 'Boil in pot' },
16
+ bake: { name: 'Bake', meaning: 'Oven/bake' },
17
+ marinate: { name: 'Marinate', meaning: 'Marinate/rest' },
18
+ blend: { name: 'Blend', meaning: 'Blend/puree' },
19
+ season: { name: 'Season', meaning: 'Season/salt' },
20
+ grill: { name: 'Grill', meaning: 'Grill/BBQ' },
21
+ steam: { name: 'Steam', meaning: 'Steam' },
22
+ knead: { name: 'Knead', meaning: 'Knead dough' }
23
+ };
24
+ </script>
25
+
26
+ {#if iconsUsed && iconsUsed.length > 0}
27
+ <CollapsibleSection title="Icon Legend">
28
+ <div class="legend-content">
29
+ {#each iconsUsed as iconKey (iconKey)}
30
+ {#if iconMeanings[iconKey]}
31
+ <div class="legend-item">
32
+ <img
33
+ src="/icons/instruction/{iconKey}.webp"
34
+ alt={iconMeanings[iconKey].name}
35
+ class="legend-icon"
36
+ />
37
+ <div class="legend-text">
38
+ <span class="icon-name">{iconMeanings[iconKey].name}</span>
39
+ <span class="icon-meaning">{iconMeanings[iconKey].meaning}</span>
40
+ </div>
41
+ </div>
42
+ {/if}
43
+ {/each}
44
+ </div>
45
+ </CollapsibleSection>
46
+ {/if}
47
+
48
+ <style>
49
+ .legend-content {
50
+ display: grid;
51
+ grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
52
+ gap: 0.75rem;
53
+ }
54
+ .legend-item {
55
+ display: flex;
56
+ align-items: center;
57
+ gap: 0.5rem;
58
+ }
59
+ .legend-icon {
60
+ width: 24px;
61
+ height: 24px;
62
+ flex-shrink: 0;
63
+ }
64
+ .legend-text {
65
+ display: flex;
66
+ flex-direction: column;
67
+ gap: 0.1rem;
68
+ }
69
+ .icon-name {
70
+ font-weight: 500;
71
+ font-size: 0.85rem;
72
+ color: #333;
73
+ }
74
+ .icon-meaning {
75
+ font-size: 0.75rem;
76
+ color: #666;
77
+ }
78
+ @media (max-width: 640px) {
79
+ .legend-content {
80
+ grid-template-columns: 1fr;
81
+ }
82
+ }
83
+ </style>
@@ -0,0 +1,11 @@
1
+ export default IconLegend;
2
+ type IconLegend = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const IconLegend: import("svelte").Component<{
7
+ iconsUsed?: any[];
8
+ }, {}, "">;
9
+ type $$ComponentProps = {
10
+ iconsUsed?: any[];
11
+ };
@@ -0,0 +1,115 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ name: 'search' | 'credits' | 'arrow-right' | 'check' | 'x' | 'star' | 'external' | 'clock' | 'sparkles' | 'shopping-bag' | 'user' | 'settings' | 'logout' | 'menu' | 'close' | 'sun' | 'moon' | 'chevron-down' | 'loader' | 'zap' | 'heart' | 'share' | 'copy' | 'refresh';
6
+ size?: 'sm' | 'md' | 'lg' | 'xl';
7
+ class?: string;
8
+ }
9
+
10
+ let { name, size = 'md', class: className = '' }: Props = $props();
11
+
12
+ const sizes = {
13
+ sm: 'w-4 h-4',
14
+ md: 'w-5 h-5',
15
+ lg: 'w-6 h-6',
16
+ xl: 'w-8 h-8'
17
+ };
18
+ </script>
19
+
20
+ <svg
21
+ class="{sizes[size]} {className}"
22
+ viewBox="0 0 24 24"
23
+ fill="none"
24
+ stroke="currentColor"
25
+ stroke-width="2"
26
+ stroke-linecap="round"
27
+ stroke-linejoin="round"
28
+ >
29
+ {#if name === 'search'}
30
+ <circle cx="11" cy="11" r="8" />
31
+ <path d="m21 21-4.3-4.3" />
32
+ {:else if name === 'credits'}
33
+ <circle cx="12" cy="12" r="10" />
34
+ <path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8" />
35
+ <path d="M12 18V6" />
36
+ {:else if name === 'arrow-right'}
37
+ <path d="M5 12h14" />
38
+ <path d="m12 5 7 7-7 7" />
39
+ {:else if name === 'check'}
40
+ <path d="M20 6 9 17l-5-5" />
41
+ {:else if name === 'x'}
42
+ <path d="M18 6 6 18" />
43
+ <path d="m6 6 12 12" />
44
+ {:else if name === 'star'}
45
+ <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />
46
+ {:else if name === 'external'}
47
+ <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
48
+ <polyline points="15 3 21 3 21 9" />
49
+ <line x1="10" x2="21" y1="14" y2="3" />
50
+ {:else if name === 'clock'}
51
+ <circle cx="12" cy="12" r="10" />
52
+ <polyline points="12 6 12 12 16 14" />
53
+ {:else if name === 'sparkles'}
54
+ <path d="m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z" />
55
+ <path d="M5 3v4" />
56
+ <path d="M19 17v4" />
57
+ <path d="M3 5h4" />
58
+ <path d="M17 19h4" />
59
+ {:else if name === 'shopping-bag'}
60
+ <path d="M6 2 3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4Z" />
61
+ <path d="M3 6h18" />
62
+ <path d="M16 10a4 4 0 0 1-8 0" />
63
+ {:else if name === 'user'}
64
+ <path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" />
65
+ <circle cx="12" cy="7" r="4" />
66
+ {:else if name === 'settings'}
67
+ <path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" />
68
+ <circle cx="12" cy="12" r="3" />
69
+ {:else if name === 'logout'}
70
+ <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
71
+ <polyline points="16 17 21 12 16 7" />
72
+ <line x1="21" x2="9" y1="12" y2="12" />
73
+ {:else if name === 'menu'}
74
+ <line x1="4" x2="20" y1="12" y2="12" />
75
+ <line x1="4" x2="20" y1="6" y2="6" />
76
+ <line x1="4" x2="20" y1="18" y2="18" />
77
+ {:else if name === 'close'}
78
+ <path d="M18 6 6 18" />
79
+ <path d="m6 6 12 12" />
80
+ {:else if name === 'sun'}
81
+ <circle cx="12" cy="12" r="4" />
82
+ <path d="M12 2v2" />
83
+ <path d="M12 20v2" />
84
+ <path d="m4.93 4.93 1.41 1.41" />
85
+ <path d="m17.66 17.66 1.41 1.41" />
86
+ <path d="M2 12h2" />
87
+ <path d="M20 12h2" />
88
+ <path d="m6.34 17.66-1.41 1.41" />
89
+ <path d="m19.07 4.93-1.41 1.41" />
90
+ {:else if name === 'moon'}
91
+ <path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" />
92
+ {:else if name === 'chevron-down'}
93
+ <path d="m6 9 6 6 6-6" />
94
+ {:else if name === 'loader'}
95
+ <path d="M21 12a9 9 0 1 1-6.219-8.56" />
96
+ {:else if name === 'zap'}
97
+ <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
98
+ {:else if name === 'heart'}
99
+ <path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z" />
100
+ {:else if name === 'share'}
101
+ <circle cx="18" cy="5" r="3" />
102
+ <circle cx="6" cy="12" r="3" />
103
+ <circle cx="18" cy="19" r="3" />
104
+ <line x1="8.59" x2="15.42" y1="13.51" y2="17.49" />
105
+ <line x1="15.41" x2="8.59" y1="6.51" y2="10.49" />
106
+ {:else if name === 'copy'}
107
+ <rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
108
+ <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
109
+ {:else if name === 'refresh'}
110
+ <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" />
111
+ <path d="M21 3v5h-5" />
112
+ <path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" />
113
+ <path d="M3 21v-5h5" />
114
+ {/if}
115
+ </svg>
@@ -0,0 +1,8 @@
1
+ interface Props {
2
+ name: 'search' | 'credits' | 'arrow-right' | 'check' | 'x' | 'star' | 'external' | 'clock' | 'sparkles' | 'shopping-bag' | 'user' | 'settings' | 'logout' | 'menu' | 'close' | 'sun' | 'moon' | 'chevron-down' | 'loader' | 'zap' | 'heart' | 'share' | 'copy' | 'refresh';
3
+ size?: 'sm' | 'md' | 'lg' | 'xl';
4
+ class?: string;
5
+ }
6
+ declare const Icons: import("svelte").Component<Props, {}, "">;
7
+ type Icons = ReturnType<typeof Icons>;
8
+ export default Icons;
@@ -0,0 +1,3 @@
1
+ export { default as Icons } from './Icons.svelte';
2
+ export { default as IconLegend } from './IconLegend.svelte';
3
+ export declare const ICONS_VERSION = "0.2.0";
@@ -0,0 +1,9 @@
1
+ // GroveUI - Icon Components
2
+ //
3
+ // This module exports SVG icon components used across the Grove platform
4
+ //
5
+ // Usage:
6
+ // import { Icons, IconLegend } from '@groveengine/ui/icons';
7
+ export { default as Icons } from './Icons.svelte';
8
+ export { default as IconLegend } from './IconLegend.svelte';
9
+ export const ICONS_VERSION = '0.2.0';
@@ -0,0 +1,67 @@
1
+ <script lang="ts">
2
+ import Icons from '../icons/Icons.svelte';
3
+
4
+ interface Props {
5
+ credits: number;
6
+ showIcon?: boolean;
7
+ size?: 'sm' | 'md' | 'lg';
8
+ variant?: 'default' | 'compact' | 'card';
9
+ }
10
+
11
+ let { credits, showIcon = true, size = 'md', variant = 'default' }: Props = $props();
12
+
13
+ const isLow = $derived(credits <= 5);
14
+ const isEmpty = $derived(credits <= 0);
15
+
16
+ const sizeClasses = {
17
+ sm: 'text-sm px-2.5 py-1',
18
+ md: 'text-base px-3 py-1.5',
19
+ lg: 'text-lg px-4 py-2'
20
+ };
21
+ </script>
22
+
23
+ {#if variant === 'card'}
24
+ <div class="scout-card p-4 {isEmpty ? 'border-red-200 dark:border-red-800' : isLow ? 'border-amber-200 dark:border-amber-800' : ''}">
25
+ <div class="flex items-center justify-between mb-2">
26
+ <span class="text-sm text-bark-500 dark:text-cream-500">Available Credits</span>
27
+ {#if isLow && !isEmpty}
28
+ <span class="text-xs text-amber-600 dark:text-amber-400 font-medium">Low balance</span>
29
+ {:else if isEmpty}
30
+ <span class="text-xs text-red-600 dark:text-red-400 font-medium">No credits</span>
31
+ {/if}
32
+ </div>
33
+ <div class="flex items-baseline gap-1">
34
+ <span class="text-3xl font-bold text-bark dark:text-cream">{credits}</span>
35
+ <span class="text-bark-400 dark:text-cream-500">searches</span>
36
+ </div>
37
+ {#if isLow}
38
+ <a href="/pricing" class="mt-3 inline-flex items-center gap-1 text-sm text-grove-600 dark:text-grove-400 hover:underline">
39
+ Add more credits
40
+ <Icons name="arrow-right" size="sm" />
41
+ </a>
42
+ {/if}
43
+ </div>
44
+ {:else if variant === 'compact'}
45
+ <span class="scout-credits {sizeClasses[size]} {isEmpty ? 'bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-300' : isLow ? 'bg-amber-50 dark:bg-amber-900/20 text-amber-700 dark:text-amber-300' : ''}">
46
+ {#if showIcon}
47
+ <Icons name="credits" size="sm" />
48
+ {/if}
49
+ <span class="font-semibold">{credits}</span>
50
+ </span>
51
+ {:else}
52
+ <div class="flex items-center gap-2 {sizeClasses[size]}">
53
+ {#if showIcon}
54
+ <div class="p-2 rounded-full bg-grove-100 dark:bg-grove-900/30 text-grove-600 dark:text-grove-400">
55
+ <Icons name="credits" size={size === 'lg' ? 'lg' : 'md'} />
56
+ </div>
57
+ {/if}
58
+ <div>
59
+ <div class="font-bold text-bark dark:text-cream">{credits} credits</div>
60
+ {#if isLow && !isEmpty}
61
+ <div class="text-xs text-amber-600 dark:text-amber-400">Running low</div>
62
+ {:else if isEmpty}
63
+ <div class="text-xs text-red-600 dark:text-red-400">No credits left</div>
64
+ {/if}
65
+ </div>
66
+ </div>
67
+ {/if}
@@ -0,0 +1,9 @@
1
+ interface Props {
2
+ credits: number;
3
+ showIcon?: boolean;
4
+ size?: 'sm' | 'md' | 'lg';
5
+ variant?: 'default' | 'compact' | 'card';
6
+ }
7
+ declare const CreditBalance: import("svelte").Component<Props, {}, "">;
8
+ type CreditBalance = ReturnType<typeof CreditBalance>;
9
+ export default CreditBalance;
@@ -0,0 +1,63 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ score: number;
4
+ showLabel?: boolean;
5
+ size?: 'sm' | 'md';
6
+ animated?: boolean;
7
+ }
8
+
9
+ let { score, showLabel = true, size = 'md', animated = true }: Props = $props();
10
+
11
+ // Clamp score between 0-100
12
+ const clampedScore = $derived(Math.max(0, Math.min(100, score)));
13
+
14
+ // Determine color based on score
15
+ const getScoreColor = (s: number) => {
16
+ if (s >= 90) return 'from-grove-500 to-grove-400';
17
+ if (s >= 75) return 'from-grove-500 to-scout-500';
18
+ if (s >= 60) return 'from-scout-500 to-scout-400';
19
+ if (s >= 40) return 'from-amber-500 to-amber-400';
20
+ return 'from-red-500 to-red-400';
21
+ };
22
+
23
+ const getScoreLabel = (s: number) => {
24
+ if (s >= 90) return 'Excellent match';
25
+ if (s >= 75) return 'Great match';
26
+ if (s >= 60) return 'Good match';
27
+ if (s >= 40) return 'Fair match';
28
+ return 'Partial match';
29
+ };
30
+
31
+ const heightClass = $derived(size === 'sm' ? 'h-1.5' : 'h-2');
32
+ </script>
33
+
34
+ <div class="w-full">
35
+ {#if showLabel}
36
+ <div class="flex items-center justify-between mb-1.5">
37
+ <span class="text-xs text-bark-500 dark:text-cream-500">{getScoreLabel(clampedScore)}</span>
38
+ <span class="text-xs font-semibold text-bark dark:text-cream">{clampedScore}%</span>
39
+ </div>
40
+ {/if}
41
+ <div class="scout-match-score {heightClass}">
42
+ <div
43
+ class="scout-match-score-fill bg-gradient-to-r {getScoreColor(clampedScore)}"
44
+ style="width: {clampedScore}%; {animated ? '--score-width: ' + clampedScore + '%' : ''}"
45
+ class:animate-score-fill={animated}
46
+ ></div>
47
+ </div>
48
+ </div>
49
+
50
+ <style>
51
+ .animate-score-fill {
52
+ animation: score-fill 0.8s ease-out forwards;
53
+ }
54
+
55
+ @keyframes score-fill {
56
+ from {
57
+ width: 0%;
58
+ }
59
+ to {
60
+ width: var(--score-width);
61
+ }
62
+ }
63
+ </style>
@@ -0,0 +1,9 @@
1
+ interface Props {
2
+ score: number;
3
+ showLabel?: boolean;
4
+ size?: 'sm' | 'md';
5
+ animated?: boolean;
6
+ }
7
+ declare const ScoreBar: import("svelte").Component<Props, {}, "">;
8
+ type ScoreBar = ReturnType<typeof ScoreBar>;
9
+ export default ScoreBar;