@btst/stack 1.0.1 → 1.1.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 (282) hide show
  1. package/README.md +156 -709
  2. package/dist/api/index.cjs +2 -1
  3. package/dist/api/index.d.cts +4 -3
  4. package/dist/api/index.d.mts +4 -3
  5. package/dist/api/index.d.ts +4 -3
  6. package/dist/api/index.mjs +1 -1
  7. package/dist/client/components/compose.cjs +68 -0
  8. package/dist/client/components/compose.mjs +65 -0
  9. package/dist/client/components/error-boundary.cjs +24 -0
  10. package/dist/client/components/error-boundary.mjs +22 -0
  11. package/dist/client/components/index.cjs +10 -0
  12. package/dist/client/components/index.d.cts +52 -0
  13. package/dist/client/components/index.d.mts +52 -0
  14. package/dist/client/components/index.d.ts +52 -0
  15. package/dist/client/components/index.mjs +2 -0
  16. package/dist/client/index.cjs +24 -5
  17. package/dist/client/index.d.cts +125 -8
  18. package/dist/client/index.d.mts +125 -8
  19. package/dist/client/index.d.ts +125 -8
  20. package/dist/client/index.mjs +21 -4
  21. package/dist/client/meta-utils.cjs +162 -0
  22. package/dist/client/meta-utils.mjs +160 -0
  23. package/dist/client/path-utils.cjs +15 -0
  24. package/dist/client/path-utils.mjs +13 -0
  25. package/dist/client/sitemap-utils.cjs +14 -0
  26. package/dist/client/sitemap-utils.mjs +12 -0
  27. package/dist/context/index.cjs +6 -63
  28. package/dist/context/index.d.cts +21 -24
  29. package/dist/context/index.d.mts +21 -24
  30. package/dist/context/index.d.ts +21 -24
  31. package/dist/context/index.mjs +1 -61
  32. package/dist/context/provider.cjs +51 -0
  33. package/dist/context/provider.mjs +46 -0
  34. package/dist/index.cjs +2 -3
  35. package/dist/index.d.cts +3 -2
  36. package/dist/index.d.mts +3 -2
  37. package/dist/index.d.ts +3 -2
  38. package/dist/index.mjs +1 -2
  39. package/dist/plugins/api/index.cjs +13 -0
  40. package/dist/plugins/api/index.d.cts +40 -0
  41. package/dist/plugins/api/index.d.mts +40 -0
  42. package/dist/plugins/api/index.d.ts +40 -0
  43. package/dist/plugins/api/index.mjs +8 -0
  44. package/dist/plugins/blog/api/index.cjs +11 -0
  45. package/dist/plugins/blog/api/index.d.cts +7 -0
  46. package/dist/plugins/blog/api/index.d.mts +7 -0
  47. package/dist/plugins/blog/api/index.d.ts +7 -0
  48. package/dist/plugins/blog/api/index.mjs +2 -0
  49. package/dist/plugins/blog/api/plugin.cjs +569 -0
  50. package/dist/plugins/blog/api/plugin.mjs +565 -0
  51. package/dist/plugins/blog/client/components/forms/image-field.cjs +133 -0
  52. package/dist/plugins/blog/client/components/forms/image-field.mjs +131 -0
  53. package/dist/plugins/blog/client/components/forms/markdown-editor-styles.css +30 -0
  54. package/dist/plugins/blog/client/components/forms/markdown-editor.cjs +106 -0
  55. package/dist/plugins/blog/client/components/forms/markdown-editor.mjs +104 -0
  56. package/dist/plugins/blog/client/components/forms/post-forms.cjs +401 -0
  57. package/dist/plugins/blog/client/components/forms/post-forms.mjs +398 -0
  58. package/dist/plugins/blog/client/components/forms/tags-multiselect.cjs +71 -0
  59. package/dist/plugins/blog/client/components/forms/tags-multiselect.mjs +65 -0
  60. package/dist/plugins/blog/client/components/index.cjs +17 -0
  61. package/dist/plugins/blog/client/components/index.d.cts +22 -0
  62. package/dist/plugins/blog/client/components/index.d.mts +22 -0
  63. package/dist/plugins/blog/client/components/index.d.ts +22 -0
  64. package/dist/plugins/blog/client/components/index.mjs +12 -0
  65. package/dist/plugins/blog/client/components/loading/form-page-skeleton.cjs +62 -0
  66. package/dist/plugins/blog/client/components/loading/form-page-skeleton.mjs +60 -0
  67. package/dist/plugins/blog/client/components/loading/index.cjs +20 -0
  68. package/dist/plugins/blog/client/components/loading/index.mjs +16 -0
  69. package/dist/plugins/blog/client/components/loading/list-page-skeleton.cjs +26 -0
  70. package/dist/plugins/blog/client/components/loading/list-page-skeleton.mjs +24 -0
  71. package/dist/plugins/blog/client/components/loading/page-header-skeleton.cjs +13 -0
  72. package/dist/plugins/blog/client/components/loading/page-header-skeleton.mjs +11 -0
  73. package/dist/plugins/blog/client/components/loading/post-card-skeleton.cjs +22 -0
  74. package/dist/plugins/blog/client/components/loading/post-card-skeleton.mjs +20 -0
  75. package/dist/plugins/blog/client/components/loading/post-page-skeleton.cjs +56 -0
  76. package/dist/plugins/blog/client/components/loading/post-page-skeleton.mjs +54 -0
  77. package/dist/plugins/blog/client/components/pages/404-page.cjs +19 -0
  78. package/dist/plugins/blog/client/components/pages/404-page.mjs +17 -0
  79. package/dist/plugins/blog/client/components/pages/edit-post-page.cjs +41 -0
  80. package/dist/plugins/blog/client/components/pages/edit-post-page.internal.cjs +57 -0
  81. package/dist/plugins/blog/client/components/pages/edit-post-page.internal.mjs +55 -0
  82. package/dist/plugins/blog/client/components/pages/edit-post-page.mjs +39 -0
  83. package/dist/plugins/blog/client/components/pages/home-page.cjs +41 -0
  84. package/dist/plugins/blog/client/components/pages/home-page.internal.cjs +61 -0
  85. package/dist/plugins/blog/client/components/pages/home-page.internal.mjs +59 -0
  86. package/dist/plugins/blog/client/components/pages/home-page.mjs +39 -0
  87. package/dist/plugins/blog/client/components/pages/new-post-page.cjs +37 -0
  88. package/dist/plugins/blog/client/components/pages/new-post-page.internal.cjs +53 -0
  89. package/dist/plugins/blog/client/components/pages/new-post-page.internal.mjs +51 -0
  90. package/dist/plugins/blog/client/components/pages/new-post-page.mjs +35 -0
  91. package/dist/plugins/blog/client/components/pages/post-page.cjs +39 -0
  92. package/dist/plugins/blog/client/components/pages/post-page.internal.cjs +101 -0
  93. package/dist/plugins/blog/client/components/pages/post-page.internal.mjs +99 -0
  94. package/dist/plugins/blog/client/components/pages/post-page.mjs +37 -0
  95. package/dist/plugins/blog/client/components/pages/tag-page.cjs +39 -0
  96. package/dist/plugins/blog/client/components/pages/tag-page.internal.cjs +61 -0
  97. package/dist/plugins/blog/client/components/pages/tag-page.internal.mjs +59 -0
  98. package/dist/plugins/blog/client/components/pages/tag-page.mjs +37 -0
  99. package/dist/plugins/blog/client/components/shared/better-blog-attribution.cjs +24 -0
  100. package/dist/plugins/blog/client/components/shared/better-blog-attribution.mjs +22 -0
  101. package/dist/plugins/blog/client/components/shared/default-error.cjs +18 -0
  102. package/dist/plugins/blog/client/components/shared/default-error.mjs +16 -0
  103. package/dist/plugins/blog/client/components/shared/defaults.cjs +13 -0
  104. package/dist/plugins/blog/client/components/shared/defaults.mjs +10 -0
  105. package/dist/plugins/blog/client/components/shared/empty-list.cjs +21 -0
  106. package/dist/plugins/blog/client/components/shared/empty-list.mjs +19 -0
  107. package/dist/plugins/blog/client/components/shared/error-placeholder.cjs +24 -0
  108. package/dist/plugins/blog/client/components/shared/error-placeholder.mjs +22 -0
  109. package/dist/plugins/blog/client/components/shared/highlight-text.cjs +53 -0
  110. package/dist/plugins/blog/client/components/shared/highlight-text.mjs +51 -0
  111. package/dist/plugins/blog/client/components/shared/markdown-content-styles.css +328 -0
  112. package/dist/plugins/blog/client/components/shared/markdown-content.cjs +324 -0
  113. package/dist/plugins/blog/client/components/shared/markdown-content.mjs +315 -0
  114. package/dist/plugins/blog/client/components/shared/on-this-page.cjs +161 -0
  115. package/dist/plugins/blog/client/components/shared/on-this-page.mjs +158 -0
  116. package/dist/plugins/blog/client/components/shared/page-header.cjs +40 -0
  117. package/dist/plugins/blog/client/components/shared/page-header.mjs +38 -0
  118. package/dist/plugins/blog/client/components/shared/page-layout.cjs +24 -0
  119. package/dist/plugins/blog/client/components/shared/page-layout.mjs +22 -0
  120. package/dist/plugins/blog/client/components/shared/page-wrapper.cjs +23 -0
  121. package/dist/plugins/blog/client/components/shared/page-wrapper.mjs +21 -0
  122. package/dist/plugins/blog/client/components/shared/post-card.cjs +279 -0
  123. package/dist/plugins/blog/client/components/shared/post-card.mjs +277 -0
  124. package/dist/plugins/blog/client/components/shared/post-navigation.cjs +74 -0
  125. package/dist/plugins/blog/client/components/shared/post-navigation.mjs +72 -0
  126. package/dist/plugins/blog/client/components/shared/posts-list.cjs +48 -0
  127. package/dist/plugins/blog/client/components/shared/posts-list.mjs +46 -0
  128. package/dist/plugins/blog/client/components/shared/recent-posts-carousel.cjs +59 -0
  129. package/dist/plugins/blog/client/components/shared/recent-posts-carousel.mjs +57 -0
  130. package/dist/plugins/blog/client/components/shared/search-input.cjs +136 -0
  131. package/dist/plugins/blog/client/components/shared/search-input.mjs +117 -0
  132. package/dist/plugins/blog/client/components/shared/search-modal.cjs +135 -0
  133. package/dist/plugins/blog/client/components/shared/search-modal.mjs +116 -0
  134. package/dist/plugins/blog/client/components/shared/tags-list.cjs +22 -0
  135. package/dist/plugins/blog/client/components/shared/tags-list.mjs +20 -0
  136. package/dist/plugins/blog/client/components/shared/use-route-lifecycle.cjs +50 -0
  137. package/dist/plugins/blog/client/components/shared/use-route-lifecycle.mjs +48 -0
  138. package/dist/plugins/blog/client/hooks/blog-hooks.cjs +380 -0
  139. package/dist/plugins/blog/client/hooks/blog-hooks.mjs +368 -0
  140. package/dist/plugins/blog/client/hooks/index.cjs +17 -0
  141. package/dist/plugins/blog/client/hooks/index.d.cts +150 -0
  142. package/dist/plugins/blog/client/hooks/index.d.mts +150 -0
  143. package/dist/plugins/blog/client/hooks/index.d.ts +150 -0
  144. package/dist/plugins/blog/client/hooks/index.mjs +1 -0
  145. package/dist/plugins/blog/client/hooks/use-debounce.cjs +16 -0
  146. package/dist/plugins/blog/client/hooks/use-debounce.mjs +14 -0
  147. package/dist/plugins/blog/client/index.cjs +7 -0
  148. package/dist/plugins/blog/client/index.d.cts +414 -0
  149. package/dist/plugins/blog/client/index.d.mts +414 -0
  150. package/dist/plugins/blog/client/index.d.ts +414 -0
  151. package/dist/plugins/blog/client/index.mjs +1 -0
  152. package/dist/plugins/blog/client/localization/blog-card.cjs +7 -0
  153. package/dist/plugins/blog/client/localization/blog-card.mjs +5 -0
  154. package/dist/plugins/blog/client/localization/blog-common.cjs +10 -0
  155. package/dist/plugins/blog/client/localization/blog-common.mjs +8 -0
  156. package/dist/plugins/blog/client/localization/blog-forms.cjs +40 -0
  157. package/dist/plugins/blog/client/localization/blog-forms.mjs +38 -0
  158. package/dist/plugins/blog/client/localization/blog-list.cjs +18 -0
  159. package/dist/plugins/blog/client/localization/blog-list.mjs +16 -0
  160. package/dist/plugins/blog/client/localization/blog-post.cjs +13 -0
  161. package/dist/plugins/blog/client/localization/blog-post.mjs +11 -0
  162. package/dist/plugins/blog/client/localization/index.cjs +17 -0
  163. package/dist/plugins/blog/client/localization/index.mjs +15 -0
  164. package/dist/plugins/blog/client/plugin.cjs +462 -0
  165. package/dist/plugins/blog/client/plugin.mjs +460 -0
  166. package/dist/plugins/blog/client.css +3 -0
  167. package/dist/plugins/blog/db.cjs +90 -0
  168. package/dist/plugins/blog/db.mjs +88 -0
  169. package/dist/plugins/blog/query-keys.cjs +181 -0
  170. package/dist/plugins/blog/query-keys.d.cts +530 -0
  171. package/dist/plugins/blog/query-keys.d.mts +530 -0
  172. package/dist/plugins/blog/query-keys.d.ts +530 -0
  173. package/dist/plugins/blog/query-keys.mjs +179 -0
  174. package/dist/plugins/blog/schemas.cjs +39 -0
  175. package/dist/plugins/blog/schemas.mjs +35 -0
  176. package/dist/plugins/blog/style.css +22 -0
  177. package/dist/plugins/blog/utils.cjs +97 -0
  178. package/dist/plugins/blog/utils.mjs +87 -0
  179. package/dist/plugins/client/index.cjs +15 -0
  180. package/dist/plugins/client/index.d.cts +57 -0
  181. package/dist/plugins/client/index.d.mts +57 -0
  182. package/dist/plugins/client/index.d.ts +57 -0
  183. package/dist/plugins/client/index.mjs +9 -0
  184. package/dist/{shared/stack.3OUyGp_E.mjs → plugins/utils.mjs} +1 -1
  185. package/dist/shared/{stack.DORw_1ps.d.cts → stack.ByOugz9d.d.cts} +17 -1
  186. package/dist/shared/{stack.DORw_1ps.d.mts → stack.ByOugz9d.d.mts} +17 -1
  187. package/dist/shared/{stack.DORw_1ps.d.ts → stack.ByOugz9d.d.ts} +17 -1
  188. package/dist/shared/stack.CoPoHVfV.d.cts +76 -0
  189. package/dist/shared/stack.CoPoHVfV.d.mts +76 -0
  190. package/dist/shared/stack.CoPoHVfV.d.ts +76 -0
  191. package/package.json +102 -14
  192. package/src/__tests__/plugins.test.tsx +539 -0
  193. package/src/__tests__/sitemap.test.ts +60 -0
  194. package/src/api/index.ts +75 -0
  195. package/src/client/components/compose.tsx +116 -0
  196. package/src/client/components/error-boundary.tsx +30 -0
  197. package/src/client/components/index.tsx +2 -0
  198. package/src/client/index.ts +109 -0
  199. package/src/client/meta-utils.ts +228 -0
  200. package/src/client/path-utils.ts +38 -0
  201. package/src/client/sitemap-utils.ts +46 -0
  202. package/src/context/index.ts +1 -0
  203. package/src/context/provider.tsx +157 -0
  204. package/src/index.ts +1 -0
  205. package/src/plugins/api/index.ts +50 -0
  206. package/src/plugins/blog/api/index.ts +2 -0
  207. package/src/plugins/blog/api/plugin.ts +759 -0
  208. package/src/plugins/blog/client/components/forms/image-field.tsx +165 -0
  209. package/src/plugins/blog/client/components/forms/markdown-editor-styles.css +30 -0
  210. package/src/plugins/blog/client/components/forms/markdown-editor.tsx +136 -0
  211. package/src/plugins/blog/client/components/forms/post-forms.tsx +531 -0
  212. package/src/plugins/blog/client/components/forms/tags-multiselect.tsx +79 -0
  213. package/src/plugins/blog/client/components/index.tsx +11 -0
  214. package/src/plugins/blog/client/components/loading/form-page-skeleton.tsx +75 -0
  215. package/src/plugins/blog/client/components/loading/index.tsx +27 -0
  216. package/src/plugins/blog/client/components/loading/list-page-skeleton.tsx +38 -0
  217. package/src/plugins/blog/client/components/loading/page-header-skeleton.tsx +10 -0
  218. package/src/plugins/blog/client/components/loading/post-card-skeleton.tsx +30 -0
  219. package/src/plugins/blog/client/components/loading/post-page-skeleton.tsx +75 -0
  220. package/src/plugins/blog/client/components/pages/404-page.tsx +23 -0
  221. package/src/plugins/blog/client/components/pages/edit-post-page.internal.tsx +60 -0
  222. package/src/plugins/blog/client/components/pages/edit-post-page.tsx +40 -0
  223. package/src/plugins/blog/client/components/pages/home-page.internal.tsx +71 -0
  224. package/src/plugins/blog/client/components/pages/home-page.tsx +42 -0
  225. package/src/plugins/blog/client/components/pages/new-post-page.internal.tsx +59 -0
  226. package/src/plugins/blog/client/components/pages/new-post-page.tsx +36 -0
  227. package/src/plugins/blog/client/components/pages/post-page.internal.tsx +142 -0
  228. package/src/plugins/blog/client/components/pages/post-page.tsx +38 -0
  229. package/src/plugins/blog/client/components/pages/tag-page.internal.tsx +74 -0
  230. package/src/plugins/blog/client/components/pages/tag-page.tsx +38 -0
  231. package/src/plugins/blog/client/components/shared/better-blog-attribution.tsx +19 -0
  232. package/src/plugins/blog/client/components/shared/default-error.tsx +20 -0
  233. package/src/plugins/blog/client/components/shared/defaults.tsx +9 -0
  234. package/src/plugins/blog/client/components/shared/empty-list.tsx +25 -0
  235. package/src/plugins/blog/client/components/shared/error-placeholder.tsx +20 -0
  236. package/src/plugins/blog/client/components/shared/highlight-text.tsx +80 -0
  237. package/src/plugins/blog/client/components/shared/markdown-content-styles.css +328 -0
  238. package/src/plugins/blog/client/components/shared/markdown-content.tsx +448 -0
  239. package/src/plugins/blog/client/components/shared/on-this-page.tsx +234 -0
  240. package/src/plugins/blog/client/components/shared/page-header.tsx +35 -0
  241. package/src/plugins/blog/client/components/shared/page-layout.tsx +23 -0
  242. package/src/plugins/blog/client/components/shared/page-wrapper.tsx +32 -0
  243. package/src/plugins/blog/client/components/shared/post-card.tsx +308 -0
  244. package/src/plugins/blog/client/components/shared/post-navigation.tsx +98 -0
  245. package/src/plugins/blog/client/components/shared/posts-list.tsx +67 -0
  246. package/src/plugins/blog/client/components/shared/recent-posts-carousel.tsx +79 -0
  247. package/src/plugins/blog/client/components/shared/search-input.tsx +146 -0
  248. package/src/plugins/blog/client/components/shared/search-modal.tsx +162 -0
  249. package/src/plugins/blog/client/components/shared/tags-list.tsx +34 -0
  250. package/src/plugins/blog/client/components/shared/use-route-lifecycle.tsx +68 -0
  251. package/src/plugins/blog/client/hooks/blog-hooks.tsx +623 -0
  252. package/src/plugins/blog/client/hooks/index.tsx +1 -0
  253. package/src/plugins/blog/client/hooks/use-debounce.ts +43 -0
  254. package/src/plugins/blog/client/index.ts +9 -0
  255. package/src/plugins/blog/client/localization/blog-card.ts +3 -0
  256. package/src/plugins/blog/client/localization/blog-common.ts +7 -0
  257. package/src/plugins/blog/client/localization/blog-forms.ts +45 -0
  258. package/src/plugins/blog/client/localization/blog-list.ts +14 -0
  259. package/src/plugins/blog/client/localization/blog-post.ts +9 -0
  260. package/src/plugins/blog/client/localization/index.ts +15 -0
  261. package/src/plugins/blog/client/overrides.ts +123 -0
  262. package/src/plugins/blog/client/plugin.tsx +672 -0
  263. package/src/plugins/blog/client.css +3 -0
  264. package/src/plugins/blog/db.ts +90 -0
  265. package/src/plugins/blog/query-keys.ts +267 -0
  266. package/src/plugins/blog/schemas.ts +39 -0
  267. package/src/plugins/blog/style.css +22 -0
  268. package/src/plugins/blog/types.ts +37 -0
  269. package/src/plugins/blog/utils.ts +144 -0
  270. package/src/plugins/client/index.ts +53 -0
  271. package/src/plugins/index.ts +0 -0
  272. package/src/plugins/utils.ts +35 -0
  273. package/src/types.ts +209 -0
  274. package/dist/plugins/index.cjs +0 -15
  275. package/dist/plugins/index.d.cts +0 -64
  276. package/dist/plugins/index.d.mts +0 -64
  277. package/dist/plugins/index.d.ts +0 -64
  278. package/dist/plugins/index.mjs +0 -11
  279. package/dist/shared/stack.DrUAVfIH.d.cts +0 -17
  280. package/dist/shared/stack.DrUAVfIH.d.mts +0 -17
  281. package/dist/shared/stack.DrUAVfIH.d.ts +0 -17
  282. /package/dist/{shared/stack.CktCg4PJ.cjs → plugins/utils.cjs} +0 -0
@@ -0,0 +1,150 @@
1
+ import * as _tanstack_react_query from '@tanstack/react-query';
2
+ import { S as SerializedPost, c as createPostSchema, u as updatePostSchema, a as SerializedTag } from '../../../../shared/stack.CoPoHVfV.js';
3
+ import { z } from 'zod';
4
+
5
+ interface UsePostsOptions {
6
+ tag?: string;
7
+ tagSlug?: string;
8
+ limit?: number;
9
+ enabled?: boolean;
10
+ query?: string;
11
+ published?: boolean;
12
+ slug?: string;
13
+ }
14
+ interface UsePostsResult {
15
+ posts: SerializedPost[];
16
+ isLoading: boolean;
17
+ error: Error | null;
18
+ loadMore: () => void;
19
+ hasMore: boolean;
20
+ isLoadingMore: boolean;
21
+ refetch: () => void;
22
+ }
23
+ interface UsePostSearchOptions {
24
+ query: string;
25
+ enabled?: boolean;
26
+ debounceMs?: number;
27
+ limit?: number;
28
+ published?: boolean;
29
+ }
30
+ interface UsePostSearchResult {
31
+ posts: SerializedPost[];
32
+ data: SerializedPost[];
33
+ isLoading: boolean;
34
+ error: Error | null;
35
+ refetch: () => void;
36
+ isSearching: boolean;
37
+ searchQuery: string;
38
+ }
39
+ interface UsePostResult {
40
+ post: SerializedPost | null;
41
+ isLoading: boolean;
42
+ error: Error | null;
43
+ refetch: () => void;
44
+ }
45
+ type PostCreateInput = z.infer<typeof createPostSchema>;
46
+ type PostUpdateInput = z.infer<typeof updatePostSchema>;
47
+ /**
48
+ * Hook for fetching paginated posts with load more functionality
49
+ */
50
+ declare function usePosts(options?: UsePostsOptions): UsePostsResult;
51
+ /** Suspense variant of usePosts */
52
+ declare function useSuspensePosts(options?: UsePostsOptions): {
53
+ posts: SerializedPost[];
54
+ loadMore: () => Promise<unknown>;
55
+ hasMore: boolean;
56
+ isLoadingMore: boolean;
57
+ refetch: () => Promise<unknown>;
58
+ };
59
+ /**
60
+ * Hook for fetching a single post by slug
61
+ */
62
+ declare function usePost(slug?: string): UsePostResult;
63
+ /** Suspense variant of usePost */
64
+ declare function useSuspensePost(slug: string): {
65
+ post: SerializedPost | null;
66
+ refetch: () => Promise<unknown>;
67
+ };
68
+ /**
69
+ * Hook for fetching all unique tags across posts
70
+ */
71
+ declare function useTags(): {
72
+ tags: SerializedTag[];
73
+ isLoading: boolean;
74
+ error: Error | null;
75
+ refetch: () => void;
76
+ };
77
+ /** Suspense variant of useTags */
78
+ declare function useSuspenseTags(): {
79
+ tags: SerializedTag[];
80
+ refetch: () => Promise<unknown>;
81
+ };
82
+ /** Create a new post */
83
+ declare function useCreatePost(): _tanstack_react_query.UseMutationResult<SerializedPost | null, Error, {
84
+ published: boolean;
85
+ title: string;
86
+ content: string;
87
+ excerpt: string;
88
+ tags: ({
89
+ name: string;
90
+ } | {
91
+ id: string;
92
+ name: string;
93
+ slug: string;
94
+ })[];
95
+ slug?: string | undefined;
96
+ createdAt?: Date | undefined;
97
+ publishedAt?: Date | undefined;
98
+ updatedAt?: Date | undefined;
99
+ image?: string | undefined;
100
+ }, unknown>;
101
+ /** Update an existing post by id */
102
+ declare function useUpdatePost(): _tanstack_react_query.UseMutationResult<SerializedPost | null, Error, {
103
+ id: string;
104
+ data: PostUpdateInput;
105
+ }, unknown>;
106
+ /**
107
+ * Hook for searching posts by a free-text query. Uses `usePosts` under the hood.
108
+ * Debounces the query and preserves last successful results to avoid flicker.
109
+ */
110
+ declare function usePostSearch({ query, enabled, debounceMs, limit, published, }: UsePostSearchOptions): UsePostSearchResult;
111
+ interface UseNextPreviousPostsOptions {
112
+ enabled?: boolean;
113
+ }
114
+ interface UseNextPreviousPostsResult {
115
+ previousPost: SerializedPost | null;
116
+ nextPost: SerializedPost | null;
117
+ isLoading: boolean;
118
+ error: Error | null;
119
+ refetch: () => void;
120
+ }
121
+ /**
122
+ * Hook for fetching previous and next posts relative to a given date
123
+ * Uses useInView to only fetch when the component is in view
124
+ */
125
+ declare function useNextPreviousPosts(createdAt: string | Date, options?: UseNextPreviousPostsOptions): UseNextPreviousPostsResult & {
126
+ ref: (node: Element | null) => void;
127
+ inView: boolean;
128
+ };
129
+ interface UseRecentPostsOptions {
130
+ limit?: number;
131
+ excludeSlug?: string;
132
+ enabled?: boolean;
133
+ }
134
+ interface UseRecentPostsResult {
135
+ recentPosts: SerializedPost[];
136
+ isLoading: boolean;
137
+ error: Error | null;
138
+ refetch: () => void;
139
+ }
140
+ /**
141
+ * Hook for fetching recent posts
142
+ * Uses useInView to only fetch when the component is in view
143
+ */
144
+ declare function useRecentPosts(options?: UseRecentPostsOptions): UseRecentPostsResult & {
145
+ ref: (node: Element | null) => void;
146
+ inView: boolean;
147
+ };
148
+
149
+ export { useCreatePost, useNextPreviousPosts, usePost, usePostSearch, usePosts, useRecentPosts, useSuspensePost, useSuspensePosts, useSuspenseTags, useTags, useUpdatePost };
150
+ export type { PostCreateInput, PostUpdateInput, UseNextPreviousPostsOptions, UseNextPreviousPostsResult, UsePostResult, UsePostSearchOptions, UsePostSearchResult, UsePostsOptions, UsePostsResult, UseRecentPostsOptions, UseRecentPostsResult };
@@ -0,0 +1 @@
1
+ export { useCreatePost, useNextPreviousPosts, usePost, usePostSearch, usePosts, useRecentPosts, useSuspensePost, useSuspensePosts, useSuspenseTags, useTags, useUpdatePost } from './blog-hooks.mjs';
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ const React = require('react');
4
+
5
+ function useDebounce(value, delay) {
6
+ const [debouncedValue, setDebouncedValue] = React.useState(value);
7
+ React.useEffect(() => {
8
+ const timer = setTimeout(() => setDebouncedValue(value), delay || 500);
9
+ return () => {
10
+ clearTimeout(timer);
11
+ };
12
+ }, [value, delay]);
13
+ return debouncedValue;
14
+ }
15
+
16
+ exports.useDebounce = useDebounce;
@@ -0,0 +1,14 @@
1
+ import { useState, useEffect } from 'react';
2
+
3
+ function useDebounce(value, delay) {
4
+ const [debouncedValue, setDebouncedValue] = useState(value);
5
+ useEffect(() => {
6
+ const timer = setTimeout(() => setDebouncedValue(value), delay || 500);
7
+ return () => {
8
+ clearTimeout(timer);
9
+ };
10
+ }, [value, delay]);
11
+ return debouncedValue;
12
+ }
13
+
14
+ export { useDebounce };
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ const plugin = require('./plugin.cjs');
4
+
5
+
6
+
7
+ exports.blogClientPlugin = plugin.blogClientPlugin;
@@ -0,0 +1,414 @@
1
+ import * as react from 'react';
2
+ import { ComponentType } from 'react';
3
+ import * as _btst_yar from '@btst/yar';
4
+ import { QueryClient } from '@tanstack/react-query';
5
+ import { P as Post, S as SerializedPost } from '../../../shared/stack.CoPoHVfV.cjs';
6
+ export { UsePostsOptions, UsePostsResult } from './hooks/index.cjs';
7
+ import 'zod';
8
+
9
+ /**
10
+ * Context passed to route hooks
11
+ */
12
+ interface RouteContext$1 {
13
+ path: string;
14
+ params?: Record<string, string>;
15
+ isSSR: boolean;
16
+ [key: string]: any;
17
+ }
18
+ /**
19
+ * Context passed to loader hooks
20
+ */
21
+ interface LoaderContext {
22
+ path: string;
23
+ params?: Record<string, string>;
24
+ isSSR: boolean;
25
+ apiBaseURL: string;
26
+ apiBasePath: string;
27
+ [key: string]: any;
28
+ }
29
+ /**
30
+ * Configuration for blog client plugin
31
+ * Note: queryClient is passed at runtime to both loader and meta (for SSR isolation)
32
+ */
33
+ interface BlogClientConfig {
34
+ apiBaseURL: string;
35
+ apiBasePath: string;
36
+ siteBaseURL: string;
37
+ siteBasePath: string;
38
+ queryClient: QueryClient;
39
+ seo?: {
40
+ siteName?: string;
41
+ author?: string;
42
+ twitterHandle?: string;
43
+ locale?: string;
44
+ defaultImage?: string;
45
+ };
46
+ hooks?: BlogClientHooks;
47
+ }
48
+ /**
49
+ * Hooks for blog client plugin
50
+ * All hooks are optional and allow consumers to customize behavior
51
+ */
52
+ interface BlogClientHooks {
53
+ beforeLoadPosts?: (filter: {
54
+ published: boolean;
55
+ }, context: LoaderContext) => Promise<boolean> | boolean;
56
+ afterLoadPosts?: (posts: Post[] | null, filter: {
57
+ published: boolean;
58
+ }, context: LoaderContext) => Promise<void> | void;
59
+ beforeLoadPost?: (slug: string, context: LoaderContext) => Promise<boolean> | boolean;
60
+ afterLoadPost?: (post: Post | null, slug: string, context: LoaderContext) => Promise<void> | void;
61
+ onLoadError?: (error: Error, context: LoaderContext) => Promise<void> | void;
62
+ }
63
+ /**
64
+ * Blog client plugin
65
+ * Provides routes, components, and React Query hooks for blog posts
66
+ *
67
+ * @param config - Configuration including queryClient, baseURL, and optional hooks
68
+ */
69
+ declare const blogClientPlugin: (config: BlogClientConfig) => {
70
+ name: string;
71
+ routes: () => {
72
+ posts: {
73
+ (inputCtx_0?: _btst_yar.InputContext<"/blog", _btst_yar.RouteOptions> | undefined): {
74
+ PageComponent?: react.ComponentType<unknown> | undefined;
75
+ LoadingComponent?: react.ComponentType<unknown> | undefined;
76
+ ErrorComponent?: react.ComponentType<unknown> | undefined;
77
+ loader?: (() => Promise<void>) | undefined;
78
+ meta?: (() => ({
79
+ title: string;
80
+ name?: undefined;
81
+ content?: undefined;
82
+ property?: undefined;
83
+ } | {
84
+ name: string;
85
+ content: string;
86
+ title?: undefined;
87
+ property?: undefined;
88
+ } | {
89
+ property: string;
90
+ content: string;
91
+ title?: undefined;
92
+ name?: undefined;
93
+ })[]) | undefined;
94
+ extra?: (() => any) | undefined;
95
+ };
96
+ options: _btst_yar.RouteOptions | undefined;
97
+ path: "/blog";
98
+ meta: _btst_yar.RouteMeta | undefined;
99
+ };
100
+ drafts: {
101
+ (inputCtx_0?: _btst_yar.InputContext<"/blog/drafts", _btst_yar.RouteOptions> | undefined): {
102
+ PageComponent?: react.ComponentType<unknown> | undefined;
103
+ LoadingComponent?: react.ComponentType<unknown> | undefined;
104
+ ErrorComponent?: react.ComponentType<unknown> | undefined;
105
+ loader?: (() => Promise<void>) | undefined;
106
+ meta?: (() => ({
107
+ title: string;
108
+ name?: undefined;
109
+ content?: undefined;
110
+ property?: undefined;
111
+ } | {
112
+ name: string;
113
+ content: string;
114
+ title?: undefined;
115
+ property?: undefined;
116
+ } | {
117
+ property: string;
118
+ content: string;
119
+ title?: undefined;
120
+ name?: undefined;
121
+ })[]) | undefined;
122
+ extra?: (() => any) | undefined;
123
+ };
124
+ options: _btst_yar.RouteOptions | undefined;
125
+ path: "/blog/drafts";
126
+ meta: _btst_yar.RouteMeta | undefined;
127
+ };
128
+ newPost: {
129
+ (inputCtx_0?: _btst_yar.InputContext<"/blog/new", _btst_yar.RouteOptions> | undefined): {
130
+ PageComponent?: react.ComponentType<unknown> | undefined;
131
+ LoadingComponent?: react.ComponentType<unknown> | undefined;
132
+ ErrorComponent?: react.ComponentType<unknown> | undefined;
133
+ loader?: (() => any) | undefined;
134
+ meta?: (() => ({
135
+ title: string;
136
+ name?: undefined;
137
+ content?: undefined;
138
+ property?: undefined;
139
+ } | {
140
+ name: string;
141
+ content: string;
142
+ title?: undefined;
143
+ property?: undefined;
144
+ } | {
145
+ property: string;
146
+ content: string;
147
+ title?: undefined;
148
+ name?: undefined;
149
+ })[]) | undefined;
150
+ extra?: (() => any) | undefined;
151
+ };
152
+ options: _btst_yar.RouteOptions | undefined;
153
+ path: "/blog/new";
154
+ meta: _btst_yar.RouteMeta | undefined;
155
+ };
156
+ editPost: {
157
+ (inputCtx_0: _btst_yar.InputContext<"/blog/:slug/edit", _btst_yar.RouteOptions>): {
158
+ PageComponent?: react.ComponentType<unknown> | undefined;
159
+ LoadingComponent?: react.ComponentType<unknown> | undefined;
160
+ ErrorComponent?: react.ComponentType<unknown> | undefined;
161
+ loader?: (() => Promise<void>) | undefined;
162
+ meta?: (() => ({
163
+ title: string;
164
+ name?: undefined;
165
+ content?: undefined;
166
+ property?: undefined;
167
+ } | {
168
+ name: string;
169
+ content: string;
170
+ title?: undefined;
171
+ property?: undefined;
172
+ } | {
173
+ property: string;
174
+ content: string;
175
+ title?: undefined;
176
+ name?: undefined;
177
+ })[]) | undefined;
178
+ extra?: (() => any) | undefined;
179
+ };
180
+ options: _btst_yar.RouteOptions | undefined;
181
+ path: "/blog/:slug/edit";
182
+ meta: _btst_yar.RouteMeta | undefined;
183
+ };
184
+ tag: {
185
+ (inputCtx_0: _btst_yar.InputContext<"/blog/tag/:tagSlug", _btst_yar.RouteOptions>): {
186
+ PageComponent?: react.ComponentType<unknown> | undefined;
187
+ LoadingComponent?: react.ComponentType<unknown> | undefined;
188
+ ErrorComponent?: react.ComponentType<unknown> | undefined;
189
+ loader?: (() => Promise<void>) | undefined;
190
+ meta?: (() => ({
191
+ title: string;
192
+ name?: undefined;
193
+ content?: undefined;
194
+ property?: undefined;
195
+ } | {
196
+ name: string;
197
+ content: string;
198
+ title?: undefined;
199
+ property?: undefined;
200
+ } | {
201
+ property: string;
202
+ content: string;
203
+ title?: undefined;
204
+ name?: undefined;
205
+ })[]) | undefined;
206
+ extra?: (() => any) | undefined;
207
+ };
208
+ options: _btst_yar.RouteOptions | undefined;
209
+ path: "/blog/tag/:tagSlug";
210
+ meta: _btst_yar.RouteMeta | undefined;
211
+ };
212
+ post: {
213
+ (inputCtx_0: _btst_yar.InputContext<"/blog/:slug", _btst_yar.RouteOptions>): {
214
+ PageComponent?: react.ComponentType<unknown> | undefined;
215
+ LoadingComponent?: react.ComponentType<unknown> | undefined;
216
+ ErrorComponent?: react.ComponentType<unknown> | undefined;
217
+ loader?: (() => Promise<void>) | undefined;
218
+ meta?: (() => ({
219
+ title: string;
220
+ name?: undefined;
221
+ content?: undefined;
222
+ property?: undefined;
223
+ } | {
224
+ name: string;
225
+ content: string | undefined;
226
+ title?: undefined;
227
+ property?: undefined;
228
+ } | {
229
+ property: string;
230
+ content: string;
231
+ title?: undefined;
232
+ name?: undefined;
233
+ })[]) | undefined;
234
+ extra?: (() => any) | undefined;
235
+ };
236
+ options: _btst_yar.RouteOptions | undefined;
237
+ path: "/blog/:slug";
238
+ meta: _btst_yar.RouteMeta | undefined;
239
+ };
240
+ };
241
+ sitemap: () => Promise<({
242
+ url: string;
243
+ lastModified: Date | undefined;
244
+ changeFrequency: "monthly";
245
+ priority: number;
246
+ } | {
247
+ url: string;
248
+ lastModified: Date | undefined;
249
+ changeFrequency: "daily";
250
+ priority: number;
251
+ })[]>;
252
+ };
253
+
254
+ declare const BLOG_LOCALIZATION: {
255
+ BLOG_FORMS_TITLE_LABEL: string;
256
+ BLOG_FORMS_REQUIRED_ASTERISK: string;
257
+ BLOG_FORMS_TITLE_PLACEHOLDER: string;
258
+ BLOG_FORMS_SLUG_LABEL: string;
259
+ BLOG_FORMS_SLUG_PLACEHOLDER: string;
260
+ BLOG_FORMS_EXCERPT_LABEL: string;
261
+ BLOG_FORMS_EXCERPT_PLACEHOLDER: string;
262
+ BLOG_FORMS_TAGS_LABEL: string;
263
+ BLOG_FORMS_TAGS_PLACEHOLDER: string;
264
+ BLOG_FORMS_CONTENT_LABEL: string;
265
+ BLOG_FORMS_PUBLISHED_LABEL: string;
266
+ BLOG_FORMS_PUBLISHED_DESCRIPTION: string;
267
+ BLOG_FORMS_SUBMIT_CREATE_IDLE: string;
268
+ BLOG_FORMS_SUBMIT_CREATE_PENDING: string;
269
+ BLOG_FORMS_SUBMIT_UPDATE_IDLE: string;
270
+ BLOG_FORMS_SUBMIT_UPDATE_PENDING: string;
271
+ BLOG_FORMS_CANCEL_BUTTON: string;
272
+ BLOG_FORMS_TOAST_CREATE_SUCCESS: string;
273
+ BLOG_FORMS_TOAST_UPDATE_SUCCESS: string;
274
+ BLOG_FORMS_LOADING_POST: string;
275
+ BLOG_FORMS_EDITOR_PLACEHOLDER: string;
276
+ BLOG_FORMS_FEATURED_IMAGE_LABEL: string;
277
+ BLOG_FORMS_FEATURED_IMAGE_REQUIRED_ASTERISK: string;
278
+ BLOG_FORMS_FEATURED_IMAGE_INPUT_PLACEHOLDER: string;
279
+ BLOG_FORMS_FEATURED_IMAGE_UPLOAD_BUTTON: string;
280
+ BLOG_FORMS_FEATURED_IMAGE_UPLOADING_BUTTON: string;
281
+ BLOG_FORMS_FEATURED_IMAGE_UPLOADING_TEXT: string;
282
+ BLOG_FORMS_FEATURED_IMAGE_PREVIEW_ALT: string;
283
+ BLOG_FORMS_FEATURED_IMAGE_ERROR_NOT_IMAGE: string;
284
+ BLOG_FORMS_FEATURED_IMAGE_ERROR_TOO_LARGE: string;
285
+ BLOG_FORMS_FEATURED_IMAGE_TOAST_SUCCESS: string;
286
+ BLOG_FORMS_FEATURED_IMAGE_TOAST_FAILURE: string;
287
+ BLOG_POST_ADD_TITLE: string;
288
+ BLOG_POST_ADD_DESCRIPTION: string;
289
+ BLOG_POST_EDIT_TITLE: string;
290
+ BLOG_POST_EDIT_DESCRIPTION: string;
291
+ BLOG_POST_ON_THIS_PAGE: string;
292
+ BLOG_POST_KEEP_READING: string;
293
+ BLOG_POST_VIEW_ALL: string;
294
+ BLOG_CARD_DRAFT_BADGE: string;
295
+ BLOG_LIST_TITLE: string;
296
+ BLOG_LIST_DRAFTS_TITLE: string;
297
+ BLOG_LIST_EMPTY: string;
298
+ BLOG_LIST_LOAD_MORE: string;
299
+ BLOG_LIST_LOADING_MORE: string;
300
+ BLOG_LIST_SEARCH_PLACEHOLDER: string;
301
+ BLOG_LIST_SEARCH_BUTTON: string;
302
+ BLOG_LIST_SEARCH_EMPTY: string;
303
+ BLOG_TAG_PAGE_TITLE: string;
304
+ BLOG_TAG_PAGE_DESCRIPTION: string;
305
+ BLOG_TAG_NOT_FOUND: string;
306
+ BLOG_TAG_NOT_FOUND_DESCRIPTION: string;
307
+ BLOG_GENERIC_ERROR_TITLE: string;
308
+ BLOG_GENERIC_ERROR_MESSAGE: string;
309
+ BLOG_PAGE_NOT_FOUND_TITLE: string;
310
+ BLOG_PAGE_NOT_FOUND_DESCRIPTION: string;
311
+ };
312
+ type BlogLocalization = typeof BLOG_LOCALIZATION;
313
+
314
+ /**
315
+ * Context passed to lifecycle hooks
316
+ */
317
+ interface RouteContext {
318
+ path: string;
319
+ params?: Record<string, string>;
320
+ isSSR: boolean;
321
+ [key: string]: any;
322
+ }
323
+ /**
324
+ * Overridable components and functions for the Blog plugin
325
+ *
326
+ * External consumers can provide their own implementations of these
327
+ * to customize the behavior for their framework (Next.js, React Router, etc.)
328
+ */
329
+ interface BlogPluginOverrides {
330
+ Link?: ComponentType<React.ComponentProps<"a"> & Record<string, any>>;
331
+ PostCard?: ComponentType<{
332
+ post: SerializedPost;
333
+ }>;
334
+ /**
335
+ * Navigation function for programmatic navigation
336
+ */
337
+ navigate: (path: string) => void | Promise<void>;
338
+ /**
339
+ * Refresh function to invalidate server-side cache (e.g., Next.js router.refresh())
340
+ */
341
+ refresh?: () => void | Promise<void>;
342
+ /**
343
+ * Image component for displaying images
344
+ */
345
+ Image?: ComponentType<React.ImgHTMLAttributes<HTMLImageElement> & Record<string, any>>;
346
+ /**
347
+ * Function used to upload an image and return its URL.
348
+ */
349
+ uploadImage: (file: File) => Promise<string>;
350
+ /**
351
+ * Localization object for the blog plugin
352
+ */
353
+ localization?: BlogLocalization;
354
+ /**
355
+ * API base URL
356
+ */
357
+ apiBaseURL: string;
358
+ /**
359
+ * API base path
360
+ */
361
+ apiBasePath: string;
362
+ /**
363
+ * Whether to show the attribution
364
+ */
365
+ showAttribution?: boolean;
366
+ /**
367
+ * Called when a route is rendered
368
+ * @param routeName - Name of the route (e.g., 'posts', 'post', 'newPost')
369
+ * @param context - Route context with path, params, etc.
370
+ */
371
+ onRouteRender?: (routeName: string, context: RouteContext) => void | Promise<void>;
372
+ /**
373
+ * Called when a route encounters an error
374
+ * @param routeName - Name of the route
375
+ * @param error - The error that occurred
376
+ * @param context - Route context
377
+ */
378
+ onRouteError?: (routeName: string, error: Error, context: RouteContext) => void | Promise<void>;
379
+ /**
380
+ * Called before the posts list page is rendered
381
+ * Return false to prevent rendering (e.g., for authorization)
382
+ * @param context - Route context
383
+ */
384
+ onBeforePostsPageRendered?: (context: RouteContext) => boolean;
385
+ /**
386
+ * Called before a single post page is rendered
387
+ * Return false to prevent rendering (e.g., for authorization)
388
+ * @param slug - The post slug
389
+ * @param context - Route context
390
+ */
391
+ onBeforePostPageRendered?: (slug: string, context: RouteContext) => boolean;
392
+ /**
393
+ * Called before the new post page is rendered
394
+ * Return false to prevent rendering (e.g., for authorization)
395
+ * @param context - Route context
396
+ */
397
+ onBeforeNewPostPageRendered?: (context: RouteContext) => boolean;
398
+ /**
399
+ * Called before the edit post page is rendered
400
+ * Return false to prevent rendering (e.g., for authorization)
401
+ * @param slug - The post slug being edited
402
+ * @param context - Route context
403
+ */
404
+ onBeforeEditPostPageRendered?: (slug: string, context: RouteContext) => boolean;
405
+ /**
406
+ * Called before the drafts page is rendered
407
+ * Return false to prevent rendering (e.g., for authorization)
408
+ * @param context - Route context
409
+ */
410
+ onBeforeDraftsPageRendered?: (context: RouteContext) => boolean;
411
+ }
412
+
413
+ export { blogClientPlugin };
414
+ export type { BlogClientConfig, BlogClientHooks, BlogPluginOverrides, LoaderContext, RouteContext$1 as RouteContext };