@autumnsgrove/groveengine 0.3.3 → 0.4.1

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 +14 -7
  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/ui/components/ui/index.d.ts +18 -0
  175. package/dist/ui/components/ui/index.js +28 -0
  176. package/dist/{components → ui/components}/ui/toast.d.ts +1 -1
  177. package/dist/{components → ui/components}/ui/toast.js +1 -1
  178. package/dist/ui/index.d.ts +10 -0
  179. package/dist/ui/index.js +22 -0
  180. package/dist/ui/stores/theme.d.ts +12 -0
  181. package/dist/ui/stores/theme.js +52 -0
  182. package/dist/ui/styles/content.css +514 -0
  183. package/dist/ui/styles/grove.css +715 -0
  184. package/dist/ui/styles/tokens.css +429 -0
  185. package/dist/ui/tailwind.preset.d.ts +340 -0
  186. package/dist/ui/tailwind.preset.js +441 -0
  187. package/dist/ui/tokens/animation.d.ts +417 -0
  188. package/dist/ui/tokens/animation.js +139 -0
  189. package/dist/ui/tokens/colors.d.ts +183 -0
  190. package/dist/ui/tokens/colors.js +97 -0
  191. package/dist/ui/tokens/effects.d.ts +111 -0
  192. package/dist/ui/tokens/effects.js +61 -0
  193. package/dist/ui/tokens/index.d.ts +6 -0
  194. package/dist/ui/tokens/index.js +19 -0
  195. package/dist/ui/tokens/spacing.d.ts +89 -0
  196. package/dist/ui/tokens/spacing.js +49 -0
  197. package/dist/ui/tokens/typography.d.ts +85 -0
  198. package/dist/ui/tokens/typography.js +68 -0
  199. package/dist/ui/utils/cn.d.ts +13 -0
  200. package/dist/ui/utils/cn.js +24 -0
  201. package/dist/ui/utils/index.d.ts +2 -0
  202. package/dist/ui/utils/index.js +8 -0
  203. package/dist/utils/index.d.ts +11 -0
  204. package/dist/utils/index.js +14 -0
  205. package/dist/utils/markdown.d.ts +11 -0
  206. package/dist/utils/markdown.js +25 -0
  207. package/dist/utils/sanitize.js +2 -3
  208. package/package.json +92 -31
  209. package/dist/components/ui/index.d.ts +0 -14
  210. package/dist/components/ui/index.js +0 -18
  211. /package/dist/{components → ui/components}/gallery/ImageGallery.svelte +0 -0
  212. /package/dist/{components → ui/components}/gallery/ImageGallery.svelte.d.ts +0 -0
  213. /package/dist/{components → ui/components}/gallery/Lightbox.svelte +0 -0
  214. /package/dist/{components → ui/components}/gallery/Lightbox.svelte.d.ts +0 -0
  215. /package/dist/{components → ui/components}/gallery/LightboxCaption.svelte +0 -0
  216. /package/dist/{components → ui/components}/gallery/LightboxCaption.svelte.d.ts +0 -0
  217. /package/dist/{components → ui/components}/gallery/ZoomableImage.svelte +0 -0
  218. /package/dist/{components → ui/components}/gallery/ZoomableImage.svelte.d.ts +0 -0
  219. /package/dist/{components/ui → ui/components/primitives}/accordion/accordion-content.svelte.d.ts +0 -0
  220. /package/dist/{components/ui → ui/components/primitives}/accordion/accordion-item.svelte.d.ts +0 -0
  221. /package/dist/{components/ui → ui/components/primitives}/accordion/accordion-trigger.svelte.d.ts +0 -0
  222. /package/dist/{components/ui → ui/components/primitives}/accordion/index.d.ts +0 -0
  223. /package/dist/{components/ui → ui/components/primitives}/accordion/index.js +0 -0
  224. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-content.svelte.d.ts +0 -0
  225. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-description.svelte.d.ts +0 -0
  226. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-footer.svelte.d.ts +0 -0
  227. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-header.svelte.d.ts +0 -0
  228. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-overlay.svelte.d.ts +0 -0
  229. /package/dist/{components/ui → ui/components/primitives}/dialog/dialog-title.svelte.d.ts +0 -0
  230. /package/dist/{components/ui → ui/components/primitives}/dialog/index.d.ts +0 -0
  231. /package/dist/{components/ui → ui/components/primitives}/dialog/index.js +0 -0
  232. /package/dist/{components/ui → ui/components/primitives}/select/index.d.ts +0 -0
  233. /package/dist/{components/ui → ui/components/primitives}/select/index.js +0 -0
  234. /package/dist/{components/ui → ui/components/primitives}/select/select-content.svelte.d.ts +0 -0
  235. /package/dist/{components/ui → ui/components/primitives}/select/select-group-heading.svelte.d.ts +0 -0
  236. /package/dist/{components/ui → ui/components/primitives}/select/select-item.svelte.d.ts +0 -0
  237. /package/dist/{components/ui → ui/components/primitives}/select/select-scroll-down-button.svelte.d.ts +0 -0
  238. /package/dist/{components/ui → ui/components/primitives}/select/select-scroll-up-button.svelte.d.ts +0 -0
  239. /package/dist/{components/ui → ui/components/primitives}/select/select-separator.svelte.d.ts +0 -0
  240. /package/dist/{components/ui → ui/components/primitives}/select/select-trigger.svelte.d.ts +0 -0
  241. /package/dist/{components/ui → ui/components/primitives}/sheet/index.d.ts +0 -0
  242. /package/dist/{components/ui → ui/components/primitives}/sheet/index.js +0 -0
  243. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-content.svelte.d.ts +0 -0
  244. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-description.svelte.d.ts +0 -0
  245. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-footer.svelte.d.ts +0 -0
  246. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-header.svelte.d.ts +0 -0
  247. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-overlay.svelte.d.ts +0 -0
  248. /package/dist/{components/ui → ui/components/primitives}/sheet/sheet-title.svelte.d.ts +0 -0
  249. /package/dist/{components/ui → ui/components/primitives}/table/index.d.ts +0 -0
  250. /package/dist/{components/ui → ui/components/primitives}/table/index.js +0 -0
  251. /package/dist/{components/ui → ui/components/primitives}/table/table-body.svelte.d.ts +0 -0
  252. /package/dist/{components/ui → ui/components/primitives}/table/table-caption.svelte.d.ts +0 -0
  253. /package/dist/{components/ui → ui/components/primitives}/table/table-cell.svelte.d.ts +0 -0
  254. /package/dist/{components/ui → ui/components/primitives}/table/table-footer.svelte.d.ts +0 -0
  255. /package/dist/{components/ui → ui/components/primitives}/table/table-head.svelte.d.ts +0 -0
  256. /package/dist/{components/ui → ui/components/primitives}/table/table-header.svelte.d.ts +0 -0
  257. /package/dist/{components/ui → ui/components/primitives}/table/table-row.svelte.d.ts +0 -0
  258. /package/dist/{components/ui → ui/components/primitives}/table/table.svelte.d.ts +0 -0
  259. /package/dist/{components/ui → ui/components/primitives}/tabs/index.d.ts +0 -0
  260. /package/dist/{components/ui → ui/components/primitives}/tabs/index.js +0 -0
  261. /package/dist/{components/ui → ui/components/primitives}/tabs/tabs-content.svelte.d.ts +0 -0
  262. /package/dist/{components/ui → ui/components/primitives}/tabs/tabs-list.svelte.d.ts +0 -0
  263. /package/dist/{components/ui → ui/components/primitives}/tabs/tabs-trigger.svelte.d.ts +0 -0
  264. /package/dist/{components → ui/components}/ui/Accordion.svelte.d.ts +0 -0
  265. /package/dist/{components → ui/components}/ui/Dialog.svelte.d.ts +0 -0
  266. /package/dist/{components → ui/components}/ui/Select.svelte.d.ts +0 -0
  267. /package/dist/{components → ui/components}/ui/Sheet.svelte.d.ts +0 -0
  268. /package/dist/{components → ui/components}/ui/Tabs.svelte.d.ts +0 -0
  269. /package/dist/{components → ui/components}/ui/Toast.svelte +0 -0
  270. /package/dist/{components → ui/components}/ui/Toast.svelte.d.ts +0 -0
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Writing Session Composable
3
+ * Manages campfire sessions and writing goals
4
+ */
5
+ /**
6
+ * Creates a writing session manager with Svelte 5 runes
7
+ * @param {object} options - Configuration options
8
+ * @param {Function} options.getWordCount - Function to get current word count
9
+ * @returns {object} Session state and controls
10
+ */
11
+ export function useWritingSession(options?: {
12
+ getWordCount: Function;
13
+ }): object;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Writing Session Composable
3
+ * Manages campfire sessions and writing goals
4
+ */
5
+
6
+ /**
7
+ * Creates a writing session manager with Svelte 5 runes
8
+ * @param {object} options - Configuration options
9
+ * @param {Function} options.getWordCount - Function to get current word count
10
+ * @returns {object} Session state and controls
11
+ */
12
+ export function useWritingSession(options = {}) {
13
+ const { getWordCount } = options;
14
+
15
+ // Campfire session state
16
+ let campfire = $state({
17
+ active: false,
18
+ startTime: null,
19
+ targetMinutes: 25,
20
+ startWordCount: 0,
21
+ });
22
+
23
+ // Writing goals state
24
+ let goal = $state({
25
+ enabled: false,
26
+ targetWords: 500,
27
+ sessionWords: 0,
28
+ });
29
+
30
+ // Campfire elapsed time (needs to be computed with current time)
31
+ function getCampfireElapsed() {
32
+ if (!campfire.active || !campfire.startTime) return "0:00";
33
+ const now = Date.now();
34
+ const elapsed = Math.floor((now - campfire.startTime) / 1000);
35
+ const mins = Math.floor(elapsed / 60);
36
+ const secs = elapsed % 60;
37
+ return `${mins}:${secs.toString().padStart(2, "0")}`;
38
+ }
39
+
40
+ // Writing goal progress
41
+ function getGoalProgress(currentWordCount) {
42
+ if (!goal.enabled) return 0;
43
+ const wordsWritten = currentWordCount - goal.sessionWords;
44
+ return Math.min(100, Math.round((wordsWritten / goal.targetWords) * 100));
45
+ }
46
+
47
+ // Words written in campfire session
48
+ function getCampfireWords(currentWordCount) {
49
+ return currentWordCount - campfire.startWordCount;
50
+ }
51
+
52
+ function startCampfire() {
53
+ const currentWords = getWordCount ? getWordCount() : 0;
54
+ campfire.active = true;
55
+ campfire.startTime = Date.now();
56
+ campfire.startWordCount = currentWords;
57
+ }
58
+
59
+ function endCampfire() {
60
+ // Could show a summary modal here in the future
61
+ campfire.active = false;
62
+ campfire.startTime = null;
63
+ }
64
+
65
+ function promptWritingGoal() {
66
+ const target = prompt("Set your word goal for this session:", "500");
67
+ if (target && !isNaN(parseInt(target))) {
68
+ const currentWords = getWordCount ? getWordCount() : 0;
69
+ goal.enabled = true;
70
+ goal.targetWords = parseInt(target);
71
+ goal.sessionWords = currentWords;
72
+ }
73
+ }
74
+
75
+ function disableGoal() {
76
+ goal.enabled = false;
77
+ }
78
+
79
+ return {
80
+ get campfire() {
81
+ return campfire;
82
+ },
83
+ get goal() {
84
+ return goal;
85
+ },
86
+ get isCampfireActive() {
87
+ return campfire.active;
88
+ },
89
+ get isGoalEnabled() {
90
+ return goal.enabled;
91
+ },
92
+ getCampfireElapsed,
93
+ getGoalProgress,
94
+ getCampfireWords,
95
+ startCampfire,
96
+ endCampfire,
97
+ promptWritingGoal,
98
+ disableGoal,
99
+ };
100
+ }
@@ -76,13 +76,16 @@
76
76
 
77
77
  /**
78
78
  * Calculate positions based on anchor locations, with collision detection
79
+ * Uses getBoundingClientRect() for accurate positioning regardless of offset parent chains
79
80
  */
80
81
  async function updatePositions() {
81
82
  if (!gutterElement || !contentBodyElement) return;
82
83
 
83
84
  await tick(); // Wait for DOM to update
84
85
 
85
- const gutterTop = gutterElement.offsetTop;
86
+ // Use getBoundingClientRect for accurate relative positioning
87
+ // This works regardless of offset parent chains and CSS transforms
88
+ const gutterRect = gutterElement.getBoundingClientRect();
86
89
 
87
90
  let lastBottom = 0; // Track the bottom edge of the last positioned item
88
91
  const newOverflowingAnchors = [];
@@ -94,20 +97,24 @@
94
97
  if (!el && import.meta.env.DEV) {
95
98
  console.warn(`Anchor element not found for: ${anchor}`);
96
99
  }
100
+ // Use getBoundingClientRect for consistent positioning
101
+ const elRect = el ? el.getBoundingClientRect() : null;
97
102
  return {
98
103
  anchor,
99
104
  key: getKey(anchor),
100
105
  element: el,
101
- top: el ? el.offsetTop : Infinity
106
+ elementRect: elRect,
107
+ top: elRect ? elRect.top : Infinity
102
108
  };
103
109
  }).sort((a, b) => a.top - b.top);
104
110
 
105
- anchorPositions.forEach(({ anchor, key, element }) => {
111
+ anchorPositions.forEach(({ anchor, key, element, elementRect }) => {
106
112
  const groupEl = anchorGroupElements[key];
107
113
 
108
- if (element && groupEl) {
109
- // Desired position (aligned with anchor element)
110
- let desiredTop = element.offsetTop - gutterTop;
114
+ if (element && elementRect && groupEl) {
115
+ // Calculate position relative to the gutter element's top
116
+ // This accounts for any content above the content-body (headers, etc.)
117
+ let desiredTop = elementRect.top - gutterRect.top;
111
118
 
112
119
  // Get the height of this gutter group
113
120
  const groupHeight = groupEl.offsetHeight;
@@ -397,7 +404,7 @@
397
404
  // Load DOMPurify only in browser
398
405
  onMount(async () => {
399
406
  if (browser) {
400
- const module = await import('dompurify');
407
+ const module = await import('isomorphic-dompurify');
401
408
  DOMPurify = module.default;
402
409
  }
403
410
  });
@@ -1,6 +1,6 @@
1
1
  <script>
2
- import Lightbox from '../gallery/Lightbox.svelte';
3
- import ImageGallery from '../gallery/ImageGallery.svelte';
2
+ import Lightbox from '../../ui/components/gallery/Lightbox.svelte';
3
+ import ImageGallery from '../../ui/components/gallery/ImageGallery.svelte';
4
4
  import { sanitizeHTML } from '../../utils/sanitize.js';
5
5
 
6
6
  let { item = {} } = $props();
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Calculate estimated cost for AI analysis
3
+ * @param {string} content - The content to analyze
4
+ * @param {string} model - The model to use ('haiku' or 'sonnet')
5
+ * @returns {{ inputTokens: number, outputTokens: number, cost: number }}
6
+ */
7
+ export function calculateCost(content: string, model?: string): {
8
+ inputTokens: number;
9
+ outputTokens: number;
10
+ cost: number;
11
+ };
12
+ /**
13
+ * Get available AI models
14
+ * @returns {Array<{ id: string, name: string, description: string }>}
15
+ */
16
+ export function getAvailableModels(): Array<{
17
+ id: string;
18
+ name: string;
19
+ description: string;
20
+ }>;
21
+ /**
22
+ * AI Model Configuration
23
+ * Constants and utilities for AI-powered features like writing assistance
24
+ */
25
+ export const MAX_CONTENT_LENGTH: 100000;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * AI Model Configuration
3
+ * Constants and utilities for AI-powered features like writing assistance
4
+ */
5
+
6
+ // Maximum content length for AI analysis (in characters)
7
+ // Based on typical API token limits (~100k tokens ≈ 400k chars, with safety margin)
8
+ export const MAX_CONTENT_LENGTH = 100000;
9
+
10
+ // Model pricing (per 1M tokens) - for cost estimation
11
+ const MODEL_PRICING = {
12
+ haiku: { input: 0.25, output: 1.25 },
13
+ sonnet: { input: 3.0, output: 15.0 }
14
+ };
15
+
16
+ // Average characters per token (rough estimate)
17
+ const CHARS_PER_TOKEN = 4;
18
+
19
+ /**
20
+ * Calculate estimated cost for AI analysis
21
+ * @param {string} content - The content to analyze
22
+ * @param {string} model - The model to use ('haiku' or 'sonnet')
23
+ * @returns {{ inputTokens: number, outputTokens: number, cost: number }}
24
+ */
25
+ export function calculateCost(content, model = 'haiku') {
26
+ const pricing = MODEL_PRICING[model] || MODEL_PRICING.haiku;
27
+ const inputTokens = Math.ceil(content.length / CHARS_PER_TOKEN);
28
+ // Estimate output tokens as ~10% of input for analysis tasks
29
+ const outputTokens = Math.ceil(inputTokens * 0.1);
30
+
31
+ const inputCost = (inputTokens / 1_000_000) * pricing.input;
32
+ const outputCost = (outputTokens / 1_000_000) * pricing.output;
33
+
34
+ return {
35
+ inputTokens,
36
+ outputTokens,
37
+ cost: inputCost + outputCost
38
+ };
39
+ }
40
+
41
+ /**
42
+ * Get available AI models
43
+ * @returns {Array<{ id: string, name: string, description: string }>}
44
+ */
45
+ export function getAvailableModels() {
46
+ return [
47
+ { id: 'haiku', name: 'Haiku', description: 'Fast and cost-effective' },
48
+ { id: 'sonnet', name: 'Sonnet', description: 'More thorough analysis' }
49
+ ];
50
+ }
@@ -0,0 +1 @@
1
+ export * from "./ai-models.js";
@@ -0,0 +1,4 @@
1
+ // Config barrel export
2
+ // Re-exports all configuration constants and utilities
3
+
4
+ export * from './ai-models.js';
package/dist/index.d.ts CHANGED
@@ -6,9 +6,9 @@ export { default as MobileTOC } from './components/custom/MobileTOC.svelte';
6
6
  export { default as CollapsibleSection } from './components/custom/CollapsibleSection.svelte';
7
7
  export { default as MarkdownEditor } from './components/admin/MarkdownEditor.svelte';
8
8
  export { default as GutterManager } from './components/admin/GutterManager.svelte';
9
- export { default as ImageGallery } from './components/gallery/ImageGallery.svelte';
10
- export { default as Lightbox } from './components/gallery/Lightbox.svelte';
11
- export { default as LightboxCaption } from './components/gallery/LightboxCaption.svelte';
12
- export { default as ZoomableImage } from './components/gallery/ZoomableImage.svelte';
13
- export * from './components/ui/index';
9
+ export { default as ImageGallery } from './ui/components/gallery/ImageGallery.svelte';
10
+ export { default as Lightbox } from './ui/components/gallery/Lightbox.svelte';
11
+ export { default as LightboxCaption } from './ui/components/gallery/LightboxCaption.svelte';
12
+ export { default as ZoomableImage } from './ui/components/gallery/ZoomableImage.svelte';
13
+ export * from './ui/index';
14
14
  export { cn } from './utils/cn';
package/dist/index.js CHANGED
@@ -9,12 +9,12 @@ export { default as CollapsibleSection } from './components/custom/CollapsibleSe
9
9
  // Admin components
10
10
  export { default as MarkdownEditor } from './components/admin/MarkdownEditor.svelte';
11
11
  export { default as GutterManager } from './components/admin/GutterManager.svelte';
12
- // Gallery components
13
- export { default as ImageGallery } from './components/gallery/ImageGallery.svelte';
14
- export { default as Lightbox } from './components/gallery/Lightbox.svelte';
15
- export { default as LightboxCaption } from './components/gallery/LightboxCaption.svelte';
16
- export { default as ZoomableImage } from './components/gallery/ZoomableImage.svelte';
12
+ // Gallery components (from UI module)
13
+ export { default as ImageGallery } from './ui/components/gallery/ImageGallery.svelte';
14
+ export { default as Lightbox } from './ui/components/gallery/Lightbox.svelte';
15
+ export { default as LightboxCaption } from './ui/components/gallery/LightboxCaption.svelte';
16
+ export { default as ZoomableImage } from './ui/components/gallery/ZoomableImage.svelte';
17
17
  // UI components - re-export all from the UI index
18
- export * from './components/ui/index';
18
+ export * from './ui/index';
19
19
  // Utilities
20
20
  export { cn } from './utils/cn';
@@ -0,0 +1 @@
1
+ export * from "./logger.js";
@@ -0,0 +1,4 @@
1
+ // Server barrel export
2
+ // Re-exports all server-side utilities
3
+
4
+ export * from './logger.js';
@@ -0,0 +1,293 @@
1
+ <script>
2
+ /**
3
+ * ActivityOverview - Weekly activity visualization
4
+ * Shows a GitHub-style contribution chart for recent days
5
+ *
6
+ * Data format: { activity_date: string, commit_count: number }[]
7
+ * (matches GitHub contributions API format)
8
+ */
9
+ import Sparkline from './Sparkline.svelte';
10
+
11
+ /**
12
+ * @type {{ activity_date: string, commit_count: number }[]}
13
+ */
14
+ let {
15
+ data = [],
16
+ locData = { additions: 0, deletions: 0 }, // LOC from separate DB fetch
17
+ days = 14
18
+ } = $props();
19
+
20
+ // Format date as YYYY-MM-DD in local timezone (not UTC!)
21
+ // This matches how GitHub attributes contributions to user's timezone
22
+ function formatDateKey(date) {
23
+ const year = date.getFullYear();
24
+ const month = String(date.getMonth() + 1).padStart(2, '0');
25
+ const day = String(date.getDate()).padStart(2, '0');
26
+ return `${year}-${month}-${day}`;
27
+ }
28
+
29
+ // Ensure we have the right number of days, using local timezone
30
+ const filledData = $derived(() => {
31
+ const result = [];
32
+ const today = new Date();
33
+
34
+ // Build activity map for quick lookup
35
+ const activityMap = {};
36
+ for (const item of data) {
37
+ activityMap[item.activity_date] = item.commit_count;
38
+ }
39
+
40
+ for (let i = days - 1; i >= 0; i--) {
41
+ const date = new Date(today);
42
+ date.setDate(date.getDate() - i);
43
+ const dateStr = formatDateKey(date); // Local timezone!
44
+
45
+ const commits = activityMap[dateStr] || 0;
46
+ result.push({
47
+ date: dateStr,
48
+ commits,
49
+ dayOfWeek: date.toLocaleDateString('en-US', { weekday: 'short' }),
50
+ isToday: i === 0
51
+ });
52
+ }
53
+
54
+ return result;
55
+ });
56
+
57
+ const commitDataArr = $derived(filledData().map(d => d.commits));
58
+
59
+ const totalCommits = $derived(filledData().reduce((sum, d) => sum + d.commits, 0));
60
+ const activeDays = $derived(filledData().filter(d => d.commits > 0).length);
61
+ const peakCommits = $derived(Math.max(...filledData().map(d => d.commits), 0));
62
+
63
+ // Get intensity level for heatmap (0-4)
64
+ function getIntensity(commits) {
65
+ if (commits === 0) return 0;
66
+ if (commits <= 2) return 1;
67
+ if (commits <= 5) return 2;
68
+ if (commits <= 10) return 3;
69
+ return 4;
70
+ }
71
+ </script>
72
+
73
+ <div class="activity-overview">
74
+ <div class="overview-header">
75
+ <h3>Recent Activity</h3>
76
+ <div class="overview-stats">
77
+ <span class="stat">
78
+ <strong>{totalCommits}</strong> commits
79
+ </span>
80
+ <span class="stat active-days">
81
+ <strong>{activeDays}</strong> of {days} days active
82
+ </span>
83
+ </div>
84
+ </div>
85
+
86
+ <div class="overview-content">
87
+ <!-- Heatmap -->
88
+ <div class="heatmap">
89
+ {#each filledData() as day}
90
+ <div
91
+ class="heatmap-cell level-{getIntensity(day.commits)}"
92
+ class:today={day.isToday}
93
+ title="{day.date}: {day.commits} commits"
94
+ >
95
+ <span class="cell-day">{day.dayOfWeek.charAt(0)}</span>
96
+ </div>
97
+ {/each}
98
+ </div>
99
+
100
+ <!-- Sparklines -->
101
+ <div class="sparklines">
102
+ <div class="sparkline-row">
103
+ <span class="sparkline-label">Commits</span>
104
+ <Sparkline
105
+ data={commitDataArr}
106
+ width={140}
107
+ height={20}
108
+ strokeColor="#5cb85f"
109
+ fillColor="rgba(92, 184, 95, 0.15)"
110
+ />
111
+ <span class="sparkline-peak" title="Peak commits in a day">↑{peakCommits}</span>
112
+ </div>
113
+ </div>
114
+ </div>
115
+
116
+ <div class="overview-footer">
117
+ <div class="loc-summary">
118
+ <span class="add">+{locData.additions.toLocaleString()}</span>
119
+ <span class="del">-{locData.deletions.toLocaleString()}</span>
120
+ </div>
121
+ </div>
122
+ </div>
123
+
124
+ <style>
125
+ .activity-overview {
126
+ background: white;
127
+ border-radius: 12px;
128
+ padding: 1rem;
129
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
130
+ margin-bottom: 1.5rem;
131
+ }
132
+ :global(.dark) .activity-overview {
133
+ background: var(--light-bg-tertiary);
134
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
135
+ }
136
+ .overview-header {
137
+ display: flex;
138
+ justify-content: space-between;
139
+ align-items: center;
140
+ margin-bottom: 0.75rem;
141
+ }
142
+ .overview-header h3 {
143
+ margin: 0;
144
+ font-size: 0.9rem;
145
+ color: #2c5f2d;
146
+ font-weight: 600;
147
+ }
148
+ :global(.dark) .overview-header h3 {
149
+ color: var(--accent-success);
150
+ }
151
+ .overview-stats {
152
+ display: flex;
153
+ gap: 0.75rem;
154
+ font-size: 0.8rem;
155
+ color: #666;
156
+ }
157
+ :global(.dark) .overview-stats {
158
+ color: var(--light-text-muted);
159
+ }
160
+ .overview-stats strong {
161
+ color: var(--light-border-secondary);
162
+ }
163
+ :global(.dark) .overview-stats strong {
164
+ color: var(--light-text-very-light);
165
+ }
166
+ .overview-content {
167
+ display: flex;
168
+ gap: 1.5rem;
169
+ align-items: flex-start;
170
+ }
171
+ @media (max-width: 500px) {
172
+ .overview-content {
173
+ flex-direction: column;
174
+ gap: 0.75rem;
175
+ }
176
+ }
177
+ /* Heatmap */
178
+ .heatmap {
179
+ display: flex;
180
+ gap: 3px;
181
+ flex-wrap: wrap;
182
+ max-width: 200px;
183
+ }
184
+ .heatmap-cell {
185
+ width: 12px;
186
+ height: 12px;
187
+ border-radius: 2px;
188
+ display: flex;
189
+ align-items: center;
190
+ justify-content: center;
191
+ font-size: 0;
192
+ transition: transform 0.15s ease;
193
+ }
194
+ .heatmap-cell:hover {
195
+ transform: scale(1.2);
196
+ }
197
+ .heatmap-cell.today {
198
+ outline: 1px solid var(--accent-success);
199
+ outline-offset: 1px;
200
+ }
201
+ .heatmap-cell.level-0 {
202
+ background: #ebedf0;
203
+ }
204
+ .heatmap-cell.level-1 {
205
+ background: #9be9a8;
206
+ }
207
+ .heatmap-cell.level-2 {
208
+ background: #40c463;
209
+ }
210
+ .heatmap-cell.level-3 {
211
+ background: #30a14e;
212
+ }
213
+ .heatmap-cell.level-4 {
214
+ background: #216e39;
215
+ }
216
+ :global(.dark) .heatmap-cell.level-0 {
217
+ background: #161b22;
218
+ }
219
+ :global(.dark) .heatmap-cell.level-1 {
220
+ background: #0e4429;
221
+ }
222
+ :global(.dark) .heatmap-cell.level-2 {
223
+ background: #006d32;
224
+ }
225
+ :global(.dark) .heatmap-cell.level-3 {
226
+ background: #26a641;
227
+ }
228
+ :global(.dark) .heatmap-cell.level-4 {
229
+ background: #39d353;
230
+ }
231
+ .cell-day {
232
+ display: none;
233
+ }
234
+ /* Sparklines */
235
+ .sparklines {
236
+ flex: 1;
237
+ display: flex;
238
+ flex-direction: column;
239
+ gap: 0.5rem;
240
+ }
241
+ .sparkline-row {
242
+ display: flex;
243
+ align-items: center;
244
+ gap: 0.5rem;
245
+ }
246
+ .sparkline-label {
247
+ font-size: 0.7rem;
248
+ color: var(--light-text-light);
249
+ width: 45px;
250
+ text-align: right;
251
+ }
252
+ :global(.dark) .sparkline-label {
253
+ color: #777;
254
+ }
255
+ .sparkline-peak {
256
+ font-size: 0.65rem;
257
+ color: var(--light-text-muted);
258
+ margin-left: 0.35rem;
259
+ font-variant-numeric: tabular-nums;
260
+ }
261
+ :global(.dark) .sparkline-peak {
262
+ color: #666;
263
+ }
264
+ /* Footer */
265
+ .overview-footer {
266
+ margin-top: 0.75rem;
267
+ padding-top: 0.5rem;
268
+ border-top: 1px solid var(--light-text-very-light);
269
+ display: flex;
270
+ justify-content: flex-end;
271
+ }
272
+ :global(.dark) .overview-footer {
273
+ border-top-color: var(--light-border-secondary);
274
+ }
275
+ .loc-summary {
276
+ display: flex;
277
+ gap: 0.75rem;
278
+ font-size: 0.8rem;
279
+ font-weight: 500;
280
+ }
281
+ .loc-summary .add {
282
+ color: var(--accent-success);
283
+ }
284
+ .loc-summary .del {
285
+ color: var(--accent-danger);
286
+ }
287
+ :global(.dark) .loc-summary .add {
288
+ color: var(--accent-success);
289
+ }
290
+ :global(.dark) .loc-summary .del {
291
+ color: #e57373;
292
+ }
293
+ </style>
@@ -0,0 +1,12 @@
1
+ export default ActivityOverview;
2
+ type ActivityOverview = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: ({
5
+ activity_date: string;
6
+ commit_count: number;
7
+ } | undefined)[]): void;
8
+ };
9
+ declare const ActivityOverview: import("svelte").Component<{
10
+ activity_date: string;
11
+ commit_count: number;
12
+ }[], {}, "">;