@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,129 @@
1
+ <script>
2
+ /**
3
+ * LOCBar - Lines of Code visualization
4
+ * Shows additions and deletions as a horizontal stacked bar
5
+ */
6
+
7
+ let {
8
+ additions = 0,
9
+ deletions = 0,
10
+ maxWidth = 100,
11
+ height = 8,
12
+ showLabels = false,
13
+ compact = false
14
+ } = $props();
15
+
16
+ const total = $derived(additions + deletions || 1);
17
+ const addPercent = $derived((additions / total) * 100);
18
+ const delPercent = $derived((deletions / total) * 100);
19
+
20
+ // Scale based on a reasonable max (e.g., 1000 lines)
21
+ const maxLines = 2000;
22
+ const scaledTotal = $derived(Math.min(total / maxLines, 1) * 100);
23
+ </script>
24
+
25
+ {#if compact}
26
+ <div class="loc-bar-compact" style="width: {maxWidth}px;">
27
+ <div class="bar-track">
28
+ <div
29
+ class="bar-add"
30
+ style="width: {(additions / maxLines) * 100}%;"
31
+ title="+{additions.toLocaleString()} additions"
32
+ ></div>
33
+ <div
34
+ class="bar-del"
35
+ style="width: {(deletions / maxLines) * 100}%;"
36
+ title="-{deletions.toLocaleString()} deletions"
37
+ ></div>
38
+ </div>
39
+ </div>
40
+ {:else}
41
+ <div class="loc-bar" style="width: {maxWidth}px;">
42
+ {#if showLabels}
43
+ <div class="loc-labels">
44
+ <span class="label-add">+{additions.toLocaleString()}</span>
45
+ <span class="label-del">-{deletions.toLocaleString()}</span>
46
+ </div>
47
+ {/if}
48
+ <div class="bar-container" style="height: {height}px;">
49
+ <div
50
+ class="bar-segment bar-add"
51
+ style="width: {addPercent}%;"
52
+ title="+{additions.toLocaleString()} additions"
53
+ ></div>
54
+ <div
55
+ class="bar-segment bar-del"
56
+ style="width: {delPercent}%;"
57
+ title="-{deletions.toLocaleString()} deletions"
58
+ ></div>
59
+ </div>
60
+ </div>
61
+ {/if}
62
+
63
+ <style>
64
+ .loc-bar {
65
+ display: flex;
66
+ flex-direction: column;
67
+ gap: 0.25rem;
68
+ }
69
+ .loc-labels {
70
+ display: flex;
71
+ justify-content: space-between;
72
+ font-size: 0.7rem;
73
+ font-weight: 500;
74
+ }
75
+ .label-add {
76
+ color: var(--accent-success);
77
+ }
78
+ .label-del {
79
+ color: var(--accent-danger);
80
+ }
81
+ :global(.dark) .label-add {
82
+ color: var(--accent-success);
83
+ }
84
+ :global(.dark) .label-del {
85
+ color: #e57373;
86
+ }
87
+ .bar-container {
88
+ display: flex;
89
+ background: #e9ecef;
90
+ border-radius: 4px;
91
+ overflow: hidden;
92
+ }
93
+ :global(.dark) .bar-container {
94
+ background: var(--light-border-secondary);
95
+ }
96
+ .bar-segment {
97
+ height: 100%;
98
+ transition: width 0.3s ease;
99
+ }
100
+ .bar-add {
101
+ background: linear-gradient(90deg, var(--accent-success) 0%, #34d058 100%);
102
+ }
103
+ .bar-del {
104
+ background: linear-gradient(90deg, var(--accent-danger) 0%, #e57373 100%);
105
+ }
106
+ /* Compact style */
107
+ .loc-bar-compact {
108
+ display: flex;
109
+ align-items: center;
110
+ gap: 0.25rem;
111
+ }
112
+ .loc-bar-compact .bar-track {
113
+ flex: 1;
114
+ height: 4px;
115
+ background: #e9ecef;
116
+ border-radius: 2px;
117
+ display: flex;
118
+ overflow: hidden;
119
+ }
120
+ :global(.dark) .loc-bar-compact .bar-track {
121
+ background: var(--light-border-secondary);
122
+ }
123
+ .loc-bar-compact .bar-add,
124
+ .loc-bar-compact .bar-del {
125
+ height: 100%;
126
+ max-width: 50%;
127
+ transition: width 0.3s ease;
128
+ }
129
+ </style>
@@ -0,0 +1,21 @@
1
+ export default LOCBar;
2
+ type LOCBar = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<$$ComponentProps>): void;
5
+ };
6
+ declare const LOCBar: import("svelte").Component<{
7
+ additions?: number;
8
+ deletions?: number;
9
+ maxWidth?: number;
10
+ height?: number;
11
+ showLabels?: boolean;
12
+ compact?: boolean;
13
+ }, {}, "">;
14
+ type $$ComponentProps = {
15
+ additions?: number;
16
+ deletions?: number;
17
+ maxWidth?: number;
18
+ height?: number;
19
+ showLabels?: boolean;
20
+ compact?: boolean;
21
+ };
@@ -0,0 +1,136 @@
1
+ <script>
2
+ /**
3
+ * RepoBreakdown - Shows which repositories had activity
4
+ * A simple horizontal stacked bar or pill visualization
5
+ */
6
+
7
+ /**
8
+ * @type {{ name: string, commits?: number, additions?: number, deletions?: number }[]}
9
+ */
10
+ let {
11
+ repos = [],
12
+ mode = 'commits', // 'commits' or 'loc'
13
+ maxWidth = 150,
14
+ showLegend = true
15
+ } = $props();
16
+
17
+ // Color palette for repos
18
+ const colors = [
19
+ '#5cb85f', // green
20
+ '#5bc0de', // cyan
21
+ '#f0ad4e', // orange
22
+ '#d9534f', // red
23
+ '#9b59b6', // purple
24
+ '#3498db', // blue
25
+ '#1abc9c', // teal
26
+ '#e67e22', // dark orange
27
+ ];
28
+
29
+ function getTotal() {
30
+ if (mode === 'commits') {
31
+ return repos.reduce((sum, r) => sum + (r.commits || 1), 0) || 1;
32
+ }
33
+ return repos.reduce((sum, r) => sum + (r.additions || 0) + (r.deletions || 0), 0) || 1;
34
+ }
35
+
36
+ function getValue(repo) {
37
+ if (mode === 'commits') {
38
+ return repo.commits || 1;
39
+ }
40
+ return (repo.additions || 0) + (repo.deletions || 0);
41
+ }
42
+
43
+ const total = $derived(getTotal());
44
+ const segments = $derived(
45
+ repos.map((repo, i) => ({
46
+ name: repo.name,
47
+ value: getValue(repo),
48
+ percent: (getValue(repo) / total) * 100,
49
+ color: colors[i % colors.length]
50
+ }))
51
+ );
52
+ </script>
53
+
54
+ {#if repos.length > 0}
55
+ <div class="repo-breakdown" style="max-width: {maxWidth}px;">
56
+ <div class="breakdown-bar">
57
+ {#each segments as segment, i}
58
+ <div
59
+ class="breakdown-segment"
60
+ style="width: {segment.percent}%; background-color: {segment.color};"
61
+ title="{segment.name}: {segment.value} {mode === 'commits' ? 'commits' : 'lines'}"
62
+ ></div>
63
+ {/each}
64
+ </div>
65
+
66
+ {#if showLegend && repos.length <= 4}
67
+ <div class="breakdown-legend">
68
+ {#each segments as segment}
69
+ <div class="legend-item">
70
+ <span class="legend-dot" style="background-color: {segment.color};"></span>
71
+ <span class="legend-name">{segment.name}</span>
72
+ </div>
73
+ {/each}
74
+ </div>
75
+ {/if}
76
+ </div>
77
+ {/if}
78
+
79
+ <style>
80
+ .repo-breakdown {
81
+ display: flex;
82
+ flex-direction: column;
83
+ gap: 0.35rem;
84
+ }
85
+ .breakdown-bar {
86
+ display: flex;
87
+ height: 6px;
88
+ background: #e9ecef;
89
+ border-radius: 3px;
90
+ overflow: hidden;
91
+ }
92
+ :global(.dark) .breakdown-bar {
93
+ background: var(--light-border-secondary);
94
+ }
95
+ .breakdown-segment {
96
+ height: 100%;
97
+ min-width: 2px;
98
+ transition: width 0.3s ease;
99
+ }
100
+ .breakdown-segment:first-child {
101
+ border-radius: 3px 0 0 3px;
102
+ }
103
+ .breakdown-segment:last-child {
104
+ border-radius: 0 3px 3px 0;
105
+ }
106
+ .breakdown-segment:only-child {
107
+ border-radius: 3px;
108
+ }
109
+ .breakdown-legend {
110
+ display: flex;
111
+ flex-wrap: wrap;
112
+ gap: 0.5rem;
113
+ }
114
+ .legend-item {
115
+ display: flex;
116
+ align-items: center;
117
+ gap: 0.25rem;
118
+ font-size: 0.65rem;
119
+ color: #666;
120
+ }
121
+ :global(.dark) .legend-item {
122
+ color: var(--light-text-muted);
123
+ }
124
+ .legend-dot {
125
+ width: 6px;
126
+ height: 6px;
127
+ border-radius: 50%;
128
+ flex-shrink: 0;
129
+ }
130
+ .legend-name {
131
+ white-space: nowrap;
132
+ overflow: hidden;
133
+ text-overflow: ellipsis;
134
+ max-width: 60px;
135
+ }
136
+ </style>
@@ -0,0 +1,16 @@
1
+ export default RepoBreakdown;
2
+ type RepoBreakdown = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: ({
5
+ name: string;
6
+ commits?: number | undefined;
7
+ additions?: number | undefined;
8
+ deletions?: number | undefined;
9
+ } | undefined)[]): void;
10
+ };
11
+ declare const RepoBreakdown: import("svelte").Component<{
12
+ name: string;
13
+ commits?: number;
14
+ additions?: number;
15
+ deletions?: number;
16
+ }[], {}, "">;
@@ -0,0 +1,139 @@
1
+ <script>
2
+ /**
3
+ * Sparkline - A simple SVG sparkline chart
4
+ * Shows activity trend over time (commits, LOC, etc.)
5
+ */
6
+
7
+ /** @type {number[]} */
8
+ let {
9
+ data = [],
10
+ width = 120,
11
+ height = 24,
12
+ strokeColor = '#5cb85f',
13
+ fillColor = 'rgba(92, 184, 95, 0.1)',
14
+ strokeWidth = 1.5,
15
+ showDots = false,
16
+ showArea = true
17
+ } = $props();
18
+
19
+ // Calculate the path for the sparkline
20
+ function getPath() {
21
+ if (!data || data.length < 2) return '';
22
+
23
+ const max = Math.max(...data, 1); // Ensure at least 1 to avoid division by zero
24
+ const min = Math.min(...data, 0);
25
+ const range = max - min || 1;
26
+
27
+ const points = data.map((value, i) => {
28
+ const x = (i / (data.length - 1)) * width;
29
+ const y = height - ((value - min) / range) * (height - 4) - 2; // 2px padding
30
+ return { x, y };
31
+ });
32
+
33
+ // Create line path
34
+ const linePath = points.map((p, i) =>
35
+ `${i === 0 ? 'M' : 'L'} ${p.x.toFixed(1)} ${p.y.toFixed(1)}`
36
+ ).join(' ');
37
+
38
+ return linePath;
39
+ }
40
+
41
+ function getAreaPath() {
42
+ if (!data || data.length < 2) return '';
43
+
44
+ const max = Math.max(...data, 1);
45
+ const min = Math.min(...data, 0);
46
+ const range = max - min || 1;
47
+
48
+ const points = data.map((value, i) => {
49
+ const x = (i / (data.length - 1)) * width;
50
+ const y = height - ((value - min) / range) * (height - 4) - 2;
51
+ return { x, y };
52
+ });
53
+
54
+ // Create closed area path
55
+ const linePath = points.map((p, i) =>
56
+ `${i === 0 ? 'M' : 'L'} ${p.x.toFixed(1)} ${p.y.toFixed(1)}`
57
+ ).join(' ');
58
+
59
+ return `${linePath} L ${width} ${height} L 0 ${height} Z`;
60
+ }
61
+
62
+ function getDots() {
63
+ if (!data || data.length < 2) return [];
64
+
65
+ const max = Math.max(...data, 1);
66
+ const min = Math.min(...data, 0);
67
+ const range = max - min || 1;
68
+
69
+ return data.map((value, i) => ({
70
+ x: (i / (data.length - 1)) * width,
71
+ y: height - ((value - min) / range) * (height - 4) - 2,
72
+ value
73
+ }));
74
+ }
75
+
76
+ const linePath = $derived(getPath());
77
+ const areaPath = $derived(getAreaPath());
78
+ const dots = $derived(getDots());
79
+ </script>
80
+
81
+ <svg
82
+ class="sparkline"
83
+ viewBox="0 0 {width} {height}"
84
+ width={width}
85
+ height={height}
86
+ role="img"
87
+ aria-label="Sparkline chart"
88
+ >
89
+ {#if showArea && areaPath}
90
+ <path
91
+ d={areaPath}
92
+ fill={fillColor}
93
+ class="sparkline-area"
94
+ />
95
+ {/if}
96
+
97
+ {#if linePath}
98
+ <path
99
+ d={linePath}
100
+ fill="none"
101
+ stroke={strokeColor}
102
+ stroke-width={strokeWidth}
103
+ stroke-linecap="round"
104
+ stroke-linejoin="round"
105
+ class="sparkline-line"
106
+ />
107
+ {/if}
108
+
109
+ {#if showDots && dots.length > 0}
110
+ {#each dots as dot}
111
+ <circle
112
+ cx={dot.x}
113
+ cy={dot.y}
114
+ r={2}
115
+ fill={strokeColor}
116
+ class="sparkline-dot"
117
+ />
118
+ {/each}
119
+ {/if}
120
+ </svg>
121
+
122
+ <style>
123
+ .sparkline {
124
+ display: inline-block;
125
+ vertical-align: middle;
126
+ }
127
+
128
+ .sparkline-line {
129
+ transition: stroke 0.2s ease;
130
+ }
131
+
132
+ .sparkline-area {
133
+ transition: fill 0.2s ease;
134
+ }
135
+
136
+ .sparkline-dot {
137
+ transition: fill 0.2s ease;
138
+ }
139
+ </style>
@@ -0,0 +1,6 @@
1
+ export default Sparkline;
2
+ type Sparkline = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: (number | undefined)[]): void;
5
+ };
6
+ declare const Sparkline: import("svelte").Component<number[], {}, "">;
@@ -0,0 +1,5 @@
1
+ export { default as ActivityOverview } from './ActivityOverview.svelte';
2
+ export { default as LOCBar } from './LOCBar.svelte';
3
+ export { default as RepoBreakdown } from './RepoBreakdown.svelte';
4
+ export { default as Sparkline } from './Sparkline.svelte';
5
+ export declare const CHARTS_VERSION = "0.2.0";
@@ -0,0 +1,11 @@
1
+ // GroveUI - Chart Components
2
+ //
3
+ // This module exports data visualization and chart components
4
+ //
5
+ // Usage:
6
+ // import { ActivityOverview, LOCBar, RepoBreakdown, Sparkline } from '@groveengine/ui/charts';
7
+ export { default as ActivityOverview } from './ActivityOverview.svelte';
8
+ export { default as LOCBar } from './LOCBar.svelte';
9
+ export { default as RepoBreakdown } from './RepoBreakdown.svelte';
10
+ export { default as Sparkline } from './Sparkline.svelte';
11
+ export const CHARTS_VERSION = '0.2.0';
@@ -0,0 +1,91 @@
1
+ <script lang="ts">
2
+ import Icons from '../icons/Icons.svelte';
3
+
4
+ interface Props {
5
+ name: string;
6
+ price: number;
7
+ searches: number;
8
+ features: string[];
9
+ popular?: boolean;
10
+ current?: boolean;
11
+ priceId?: string;
12
+ onselect?: (priceId: string) => void;
13
+ }
14
+
15
+ let {
16
+ name,
17
+ price,
18
+ searches,
19
+ features,
20
+ popular = false,
21
+ current = false,
22
+ priceId = '',
23
+ onselect
24
+ }: Props = $props();
25
+
26
+ const pricePerSearch = $derived((price / searches).toFixed(2));
27
+
28
+ function handleSelect() {
29
+ if (onselect && priceId) {
30
+ onselect(priceId);
31
+ }
32
+ }
33
+ </script>
34
+
35
+ <div
36
+ class="scout-card relative flex flex-col h-full {popular ? 'ring-2 ring-grove-500 shadow-grove-lg' : ''}"
37
+ >
38
+ <!-- Popular badge -->
39
+ {#if popular}
40
+ <div class="absolute -top-3 left-1/2 -translate-x-1/2">
41
+ <span class="bg-grove-500 text-white text-xs font-bold px-3 py-1 rounded-full">
42
+ MOST POPULAR
43
+ </span>
44
+ </div>
45
+ {/if}
46
+
47
+ <div class="p-6 flex-1 flex flex-col">
48
+ <!-- Header -->
49
+ <div class="text-center mb-6">
50
+ <h3 class="text-xl font-bold text-bark dark:text-cream mb-2">{name}</h3>
51
+ <div class="flex items-baseline justify-center gap-1">
52
+ <span class="text-4xl font-bold text-bark dark:text-cream">${price}</span>
53
+ <span class="text-bark-400 dark:text-cream-500">/month</span>
54
+ </div>
55
+ <p class="text-sm text-bark-400 dark:text-cream-500 mt-2">
56
+ {searches} searches • ${pricePerSearch}/search
57
+ </p>
58
+ </div>
59
+
60
+ <!-- Features -->
61
+ <ul class="space-y-3 mb-6 flex-1">
62
+ {#each features as feature}
63
+ <li class="flex items-start gap-2 text-sm text-bark-600 dark:text-cream-400">
64
+ <Icons name="check" size="sm" class="text-grove-500 mt-0.5 flex-shrink-0" />
65
+ <span>{feature}</span>
66
+ </li>
67
+ {/each}
68
+ </ul>
69
+
70
+ <!-- CTA -->
71
+ {#if current}
72
+ <button
73
+ disabled
74
+ class="scout-btn-secondary w-full opacity-75 cursor-not-allowed"
75
+ >
76
+ Current Plan
77
+ </button>
78
+ {:else}
79
+ <button
80
+ onclick={handleSelect}
81
+ class="{popular ? 'scout-btn-primary' : 'scout-btn-secondary'} w-full"
82
+ >
83
+ {#if popular}
84
+ Get Started
85
+ {:else}
86
+ Choose {name}
87
+ {/if}
88
+ </button>
89
+ {/if}
90
+ </div>
91
+ </div>
@@ -0,0 +1,13 @@
1
+ interface Props {
2
+ name: string;
3
+ price: number;
4
+ searches: number;
5
+ features: string[];
6
+ popular?: boolean;
7
+ current?: boolean;
8
+ priceId?: string;
9
+ onselect?: (priceId: string) => void;
10
+ }
11
+ declare const PlanCard: import("svelte").Component<Props, {}, "">;
12
+ type PlanCard = ReturnType<typeof PlanCard>;
13
+ export default PlanCard;
@@ -0,0 +1,125 @@
1
+ <script lang="ts">
2
+ import Icons from '../icons/Icons.svelte';
3
+ import ScoreBar from '../indicators/ScoreBar.svelte';
4
+
5
+ interface Props {
6
+ name: string;
7
+ price: number;
8
+ originalPrice?: number;
9
+ retailer: string;
10
+ url: string;
11
+ imageUrl?: string;
12
+ matchScore?: number;
13
+ matchReason?: string;
14
+ index?: number;
15
+ }
16
+
17
+ let {
18
+ name,
19
+ price,
20
+ originalPrice,
21
+ retailer,
22
+ url,
23
+ imageUrl,
24
+ matchScore = 0,
25
+ matchReason,
26
+ index = 0
27
+ }: Props = $props();
28
+
29
+ const discount = $derived(
30
+ originalPrice && originalPrice > price
31
+ ? Math.round(((originalPrice - price) / originalPrice) * 100)
32
+ : 0
33
+ );
34
+
35
+ const formatPrice = (cents: number) => {
36
+ return new Intl.NumberFormat('en-US', {
37
+ style: 'currency',
38
+ currency: 'USD'
39
+ }).format(cents / 100);
40
+ };
41
+
42
+ // Stagger animation delay based on index
43
+ const animationDelay = $derived(`${index * 100}ms`);
44
+ </script>
45
+
46
+ <article
47
+ class="scout-product-card animate-deal-pop"
48
+ style="animation-delay: {animationDelay}"
49
+ >
50
+ <!-- Image Section -->
51
+ <div class="scout-product-image relative">
52
+ {#if imageUrl}
53
+ <img src={imageUrl} alt={name} class="w-full h-full object-cover" loading="lazy" />
54
+ {:else}
55
+ <div class="flex flex-col items-center justify-center text-bark-300 dark:text-bark-600">
56
+ <Icons name="shopping-bag" size="xl" />
57
+ <span class="text-xs mt-2">No image</span>
58
+ </div>
59
+ {/if}
60
+
61
+ <!-- Discount Badge -->
62
+ {#if discount > 0}
63
+ <div class="absolute top-3 left-3 scout-badge-deal text-sm font-bold px-2.5 py-1">
64
+ {discount}% OFF
65
+ </div>
66
+ {/if}
67
+
68
+ <!-- Retailer Badge -->
69
+ <div class="absolute bottom-3 right-3 bg-white/90 dark:bg-bark-800/90 backdrop-blur-sm px-2 py-1 rounded text-xs font-medium text-bark dark:text-cream">
70
+ {retailer}
71
+ </div>
72
+ </div>
73
+
74
+ <!-- Content Section -->
75
+ <div class="scout-product-body">
76
+ <h3 class="font-medium text-bark dark:text-cream mb-2 line-clamp-2 leading-snug">
77
+ {name}
78
+ </h3>
79
+
80
+ <!-- Price -->
81
+ <div class="flex items-baseline gap-2 mb-3">
82
+ <span class="scout-price">{formatPrice(price)}</span>
83
+ {#if originalPrice && originalPrice > price}
84
+ <span class="scout-price-original">{formatPrice(originalPrice)}</span>
85
+ {/if}
86
+ </div>
87
+
88
+ <!-- Match Score -->
89
+ {#if matchScore > 0}
90
+ <div class="mb-3">
91
+ <ScoreBar score={matchScore} size="sm" />
92
+ </div>
93
+ {/if}
94
+
95
+ <!-- Match Reason -->
96
+ {#if matchReason}
97
+ <p class="text-sm text-bark-500 dark:text-cream-500 mb-4 line-clamp-2">
98
+ {matchReason}
99
+ </p>
100
+ {/if}
101
+
102
+ <!-- Action Button -->
103
+ <div class="mt-auto">
104
+ <a
105
+ href={url}
106
+ target="_blank"
107
+ rel="noopener noreferrer"
108
+ class="scout-btn-primary w-full text-sm"
109
+ >
110
+ View Deal
111
+ <Icons name="external" size="sm" />
112
+ </a>
113
+ </div>
114
+ </div>
115
+ </article>
116
+
117
+ <style>
118
+ .line-clamp-2 {
119
+ display: -webkit-box;
120
+ -webkit-line-clamp: 2;
121
+ line-clamp: 2;
122
+ -webkit-box-orient: vertical;
123
+ overflow: hidden;
124
+ }
125
+ </style>