@jhits/plugin-blog 0.0.9 → 0.0.11

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 (276) hide show
  1. package/package.json +58 -59
  2. package/src/api/categories.ts +0 -43
  3. package/src/api/check-title.ts +0 -60
  4. package/src/api/config-handler.ts +0 -76
  5. package/src/api/handler.ts +0 -418
  6. package/src/api/index.ts +0 -33
  7. package/src/api/route.ts +0 -116
  8. package/src/api/router.ts +0 -128
  9. package/src/api-server.ts +0 -11
  10. package/src/config.ts +0 -161
  11. package/src/hooks/index.d.ts +0 -8
  12. package/src/hooks/index.d.ts.map +0 -1
  13. package/src/hooks/index.js +0 -7
  14. package/src/hooks/index.ts +0 -9
  15. package/src/hooks/useBlog.d.ts +0 -31
  16. package/src/hooks/useBlog.d.ts.map +0 -1
  17. package/src/hooks/useBlog.js +0 -57
  18. package/src/hooks/useBlog.ts +0 -85
  19. package/src/hooks/useBlogs.d.ts +0 -39
  20. package/src/hooks/useBlogs.d.ts.map +0 -1
  21. package/src/hooks/useBlogs.js +0 -82
  22. package/src/hooks/useBlogs.ts +0 -123
  23. package/src/hooks/useCategories.d.ts +0 -9
  24. package/src/hooks/useCategories.d.ts.map +0 -1
  25. package/src/hooks/useCategories.js +0 -70
  26. package/src/hooks/useCategories.ts +0 -76
  27. package/src/index.d.ts +0 -55
  28. package/src/index.d.ts.map +0 -1
  29. package/src/index.js +0 -228
  30. package/src/index.server.ts +0 -14
  31. package/src/index.tsx +0 -335
  32. package/src/init.d.ts +0 -40
  33. package/src/init.d.ts.map +0 -1
  34. package/src/init.js +0 -41
  35. package/src/init.tsx +0 -63
  36. package/src/lib/blocks/BlockRenderer.d.ts +0 -54
  37. package/src/lib/blocks/BlockRenderer.d.ts.map +0 -1
  38. package/src/lib/blocks/BlockRenderer.js +0 -54
  39. package/src/lib/blocks/BlockRenderer.tsx +0 -141
  40. package/src/lib/blocks/index.ts +0 -6
  41. package/src/lib/config-storage.d.ts +0 -30
  42. package/src/lib/config-storage.d.ts.map +0 -1
  43. package/src/lib/config-storage.js +0 -31
  44. package/src/lib/config-storage.ts +0 -65
  45. package/src/lib/index.ts +0 -9
  46. package/src/lib/layouts/blocks/ColumnsBlock.d.ts +0 -25
  47. package/src/lib/layouts/blocks/ColumnsBlock.d.ts.map +0 -1
  48. package/src/lib/layouts/blocks/ColumnsBlock.js +0 -182
  49. package/src/lib/layouts/blocks/ColumnsBlock.tsx +0 -298
  50. package/src/lib/layouts/blocks/ColumnsBlock.tsx.tmp +0 -81
  51. package/src/lib/layouts/blocks/SectionBlock.d.ts +0 -25
  52. package/src/lib/layouts/blocks/SectionBlock.d.ts.map +0 -1
  53. package/src/lib/layouts/blocks/SectionBlock.js +0 -44
  54. package/src/lib/layouts/blocks/SectionBlock.tsx +0 -104
  55. package/src/lib/layouts/blocks/index.ts +0 -8
  56. package/src/lib/layouts/index.d.ts +0 -23
  57. package/src/lib/layouts/index.d.ts.map +0 -1
  58. package/src/lib/layouts/index.js +0 -45
  59. package/src/lib/layouts/index.ts +0 -52
  60. package/src/lib/layouts/registerLayoutBlocks.d.ts +0 -9
  61. package/src/lib/layouts/registerLayoutBlocks.d.ts.map +0 -1
  62. package/src/lib/layouts/registerLayoutBlocks.js +0 -60
  63. package/src/lib/layouts/registerLayoutBlocks.ts +0 -64
  64. package/src/lib/mappers/apiMapper.d.ts +0 -66
  65. package/src/lib/mappers/apiMapper.d.ts.map +0 -1
  66. package/src/lib/mappers/apiMapper.js +0 -191
  67. package/src/lib/mappers/apiMapper.ts +0 -254
  68. package/src/lib/migration/index.ts +0 -6
  69. package/src/lib/migration/mapper.ts +0 -140
  70. package/src/lib/rich-text/RichTextEditor.d.ts +0 -45
  71. package/src/lib/rich-text/RichTextEditor.d.ts.map +0 -1
  72. package/src/lib/rich-text/RichTextEditor.js +0 -564
  73. package/src/lib/rich-text/RichTextEditor.tsx +0 -826
  74. package/src/lib/rich-text/RichTextPreview.d.ts +0 -16
  75. package/src/lib/rich-text/RichTextPreview.d.ts.map +0 -1
  76. package/src/lib/rich-text/RichTextPreview.js +0 -144
  77. package/src/lib/rich-text/RichTextPreview.tsx +0 -210
  78. package/src/lib/rich-text/index.d.ts +0 -9
  79. package/src/lib/rich-text/index.d.ts.map +0 -1
  80. package/src/lib/rich-text/index.js +0 -6
  81. package/src/lib/rich-text/index.ts +0 -10
  82. package/src/lib/utils/blockHelpers.d.ts +0 -23
  83. package/src/lib/utils/blockHelpers.d.ts.map +0 -1
  84. package/src/lib/utils/blockHelpers.js +0 -65
  85. package/src/lib/utils/blockHelpers.ts +0 -72
  86. package/src/lib/utils/configValidation.d.ts +0 -23
  87. package/src/lib/utils/configValidation.d.ts.map +0 -1
  88. package/src/lib/utils/configValidation.js +0 -113
  89. package/src/lib/utils/configValidation.ts +0 -137
  90. package/src/lib/utils/index.ts +0 -8
  91. package/src/lib/utils/slugify.ts +0 -79
  92. package/src/registry/BlockRegistry.d.ts +0 -62
  93. package/src/registry/BlockRegistry.d.ts.map +0 -1
  94. package/src/registry/BlockRegistry.js +0 -112
  95. package/src/registry/BlockRegistry.ts +0 -139
  96. package/src/registry/index.d.ts +0 -6
  97. package/src/registry/index.d.ts.map +0 -1
  98. package/src/registry/index.js +0 -4
  99. package/src/registry/index.ts +0 -11
  100. package/src/state/EditorContext.d.ts +0 -45
  101. package/src/state/EditorContext.d.ts.map +0 -1
  102. package/src/state/EditorContext.js +0 -215
  103. package/src/state/EditorContext.tsx +0 -283
  104. package/src/state/index.d.ts +0 -7
  105. package/src/state/index.d.ts.map +0 -1
  106. package/src/state/index.js +0 -6
  107. package/src/state/index.ts +0 -8
  108. package/src/state/reducer.d.ts +0 -11
  109. package/src/state/reducer.d.ts.map +0 -1
  110. package/src/state/reducer.js +0 -443
  111. package/src/state/reducer.ts +0 -694
  112. package/src/state/types.d.ts +0 -162
  113. package/src/state/types.d.ts.map +0 -1
  114. package/src/state/types.js +0 -27
  115. package/src/state/types.ts +0 -160
  116. package/src/types/block.d.ts +0 -221
  117. package/src/types/block.d.ts.map +0 -1
  118. package/src/types/block.js +0 -6
  119. package/src/types/block.ts +0 -269
  120. package/src/types/index.d.ts +0 -8
  121. package/src/types/index.d.ts.map +0 -1
  122. package/src/types/index.js +0 -5
  123. package/src/types/index.ts +0 -17
  124. package/src/types/post.d.ts +0 -136
  125. package/src/types/post.d.ts.map +0 -1
  126. package/src/types/post.js +0 -5
  127. package/src/types/post.ts +0 -169
  128. package/src/utils/client.d.ts +0 -48
  129. package/src/utils/client.d.ts.map +0 -1
  130. package/src/utils/client.js +0 -77
  131. package/src/utils/client.ts +0 -122
  132. package/src/utils/index.ts +0 -7
  133. package/src/views/CanvasEditor/BlockWrapper.d.ts +0 -16
  134. package/src/views/CanvasEditor/BlockWrapper.d.ts.map +0 -1
  135. package/src/views/CanvasEditor/BlockWrapper.js +0 -276
  136. package/src/views/CanvasEditor/BlockWrapper.tsx +0 -522
  137. package/src/views/CanvasEditor/CanvasEditorView.d.ts +0 -14
  138. package/src/views/CanvasEditor/CanvasEditorView.d.ts.map +0 -1
  139. package/src/views/CanvasEditor/CanvasEditorView.js +0 -209
  140. package/src/views/CanvasEditor/CanvasEditorView.tsx +0 -337
  141. package/src/views/CanvasEditor/EditorBody.d.ts +0 -22
  142. package/src/views/CanvasEditor/EditorBody.d.ts.map +0 -1
  143. package/src/views/CanvasEditor/EditorBody.js +0 -505
  144. package/src/views/CanvasEditor/EditorBody.tsx +0 -665
  145. package/src/views/CanvasEditor/EditorHeader.d.ts +0 -18
  146. package/src/views/CanvasEditor/EditorHeader.d.ts.map +0 -1
  147. package/src/views/CanvasEditor/EditorHeader.js +0 -101
  148. package/src/views/CanvasEditor/EditorHeader.tsx +0 -268
  149. package/src/views/CanvasEditor/LayoutContainer.d.ts +0 -17
  150. package/src/views/CanvasEditor/LayoutContainer.d.ts.map +0 -1
  151. package/src/views/CanvasEditor/LayoutContainer.js +0 -222
  152. package/src/views/CanvasEditor/LayoutContainer.tsx +0 -322
  153. package/src/views/CanvasEditor/SaveConfirmationModal.d.ts +0 -13
  154. package/src/views/CanvasEditor/SaveConfirmationModal.d.ts.map +0 -1
  155. package/src/views/CanvasEditor/SaveConfirmationModal.js +0 -78
  156. package/src/views/CanvasEditor/SaveConfirmationModal.tsx +0 -233
  157. package/src/views/CanvasEditor/components/CustomBlockItem.d.ts +0 -14
  158. package/src/views/CanvasEditor/components/CustomBlockItem.d.ts.map +0 -1
  159. package/src/views/CanvasEditor/components/CustomBlockItem.js +0 -44
  160. package/src/views/CanvasEditor/components/CustomBlockItem.tsx +0 -92
  161. package/src/views/CanvasEditor/components/EditorCanvas.d.ts +0 -29
  162. package/src/views/CanvasEditor/components/EditorCanvas.d.ts.map +0 -1
  163. package/src/views/CanvasEditor/components/EditorCanvas.js +0 -32
  164. package/src/views/CanvasEditor/components/EditorCanvas.tsx +0 -160
  165. package/src/views/CanvasEditor/components/EditorLibrary.d.ts +0 -7
  166. package/src/views/CanvasEditor/components/EditorLibrary.d.ts.map +0 -1
  167. package/src/views/CanvasEditor/components/EditorLibrary.js +0 -25
  168. package/src/views/CanvasEditor/components/EditorLibrary.tsx +0 -122
  169. package/src/views/CanvasEditor/components/EditorSidebar.d.ts +0 -13
  170. package/src/views/CanvasEditor/components/EditorSidebar.d.ts.map +0 -1
  171. package/src/views/CanvasEditor/components/EditorSidebar.js +0 -20
  172. package/src/views/CanvasEditor/components/EditorSidebar.tsx +0 -181
  173. package/src/views/CanvasEditor/components/ErrorBanner.d.ts +0 -6
  174. package/src/views/CanvasEditor/components/ErrorBanner.d.ts.map +0 -1
  175. package/src/views/CanvasEditor/components/ErrorBanner.js +0 -8
  176. package/src/views/CanvasEditor/components/ErrorBanner.tsx +0 -31
  177. package/src/views/CanvasEditor/components/FeaturedMediaSection.d.ts +0 -25
  178. package/src/views/CanvasEditor/components/FeaturedMediaSection.d.ts.map +0 -1
  179. package/src/views/CanvasEditor/components/FeaturedMediaSection.js +0 -182
  180. package/src/views/CanvasEditor/components/FeaturedMediaSection.tsx +0 -341
  181. package/src/views/CanvasEditor/components/LibraryItem.d.ts +0 -14
  182. package/src/views/CanvasEditor/components/LibraryItem.d.ts.map +0 -1
  183. package/src/views/CanvasEditor/components/LibraryItem.js +0 -43
  184. package/src/views/CanvasEditor/components/LibraryItem.tsx +0 -80
  185. package/src/views/CanvasEditor/components/PrivacySettingsSection.d.ts +0 -15
  186. package/src/views/CanvasEditor/components/PrivacySettingsSection.d.ts.map +0 -1
  187. package/src/views/CanvasEditor/components/PrivacySettingsSection.js +0 -63
  188. package/src/views/CanvasEditor/components/PrivacySettingsSection.tsx +0 -212
  189. package/src/views/CanvasEditor/components/index.d.ts +0 -21
  190. package/src/views/CanvasEditor/components/index.d.ts.map +0 -1
  191. package/src/views/CanvasEditor/components/index.js +0 -12
  192. package/src/views/CanvasEditor/components/index.ts +0 -28
  193. package/src/views/CanvasEditor/hooks/index.d.ts +0 -10
  194. package/src/views/CanvasEditor/hooks/index.d.ts.map +0 -1
  195. package/src/views/CanvasEditor/hooks/index.js +0 -9
  196. package/src/views/CanvasEditor/hooks/index.ts +0 -10
  197. package/src/views/CanvasEditor/hooks/useHeroBlock.d.ts +0 -8
  198. package/src/views/CanvasEditor/hooks/useHeroBlock.d.ts.map +0 -1
  199. package/src/views/CanvasEditor/hooks/useHeroBlock.js +0 -79
  200. package/src/views/CanvasEditor/hooks/useHeroBlock.ts +0 -103
  201. package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts +0 -3
  202. package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts.map +0 -1
  203. package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.js +0 -114
  204. package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.ts +0 -142
  205. package/src/views/CanvasEditor/hooks/usePostLoader.d.ts +0 -5
  206. package/src/views/CanvasEditor/hooks/usePostLoader.d.ts.map +0 -1
  207. package/src/views/CanvasEditor/hooks/usePostLoader.js +0 -32
  208. package/src/views/CanvasEditor/hooks/usePostLoader.ts +0 -39
  209. package/src/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts +0 -2
  210. package/src/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts.map +0 -1
  211. package/src/views/CanvasEditor/hooks/useRegisteredBlocks.js +0 -47
  212. package/src/views/CanvasEditor/hooks/useRegisteredBlocks.ts +0 -55
  213. package/src/views/CanvasEditor/hooks/useUnsavedChanges.d.ts +0 -25
  214. package/src/views/CanvasEditor/hooks/useUnsavedChanges.d.ts.map +0 -1
  215. package/src/views/CanvasEditor/hooks/useUnsavedChanges.js +0 -285
  216. package/src/views/CanvasEditor/hooks/useUnsavedChanges.ts +0 -339
  217. package/src/views/CanvasEditor/index.d.ts +0 -16
  218. package/src/views/CanvasEditor/index.d.ts.map +0 -1
  219. package/src/views/CanvasEditor/index.js +0 -9
  220. package/src/views/CanvasEditor/index.ts +0 -16
  221. package/src/views/PostManager/EmptyState.d.ts +0 -10
  222. package/src/views/PostManager/EmptyState.d.ts.map +0 -1
  223. package/src/views/PostManager/EmptyState.js +0 -12
  224. package/src/views/PostManager/EmptyState.tsx +0 -42
  225. package/src/views/PostManager/PostActionsMenu.d.ts +0 -12
  226. package/src/views/PostManager/PostActionsMenu.d.ts.map +0 -1
  227. package/src/views/PostManager/PostActionsMenu.js +0 -58
  228. package/src/views/PostManager/PostActionsMenu.tsx +0 -112
  229. package/src/views/PostManager/PostCards.d.ts +0 -15
  230. package/src/views/PostManager/PostCards.d.ts.map +0 -1
  231. package/src/views/PostManager/PostCards.js +0 -79
  232. package/src/views/PostManager/PostCards.tsx +0 -197
  233. package/src/views/PostManager/PostFilters.d.ts +0 -16
  234. package/src/views/PostManager/PostFilters.d.ts.map +0 -1
  235. package/src/views/PostManager/PostFilters.js +0 -10
  236. package/src/views/PostManager/PostFilters.tsx +0 -95
  237. package/src/views/PostManager/PostManagerView.d.ts +0 -11
  238. package/src/views/PostManager/PostManagerView.d.ts.map +0 -1
  239. package/src/views/PostManager/PostManagerView.js +0 -174
  240. package/src/views/PostManager/PostManagerView.tsx +0 -289
  241. package/src/views/PostManager/PostStats.d.ts +0 -11
  242. package/src/views/PostManager/PostStats.d.ts.map +0 -1
  243. package/src/views/PostManager/PostStats.js +0 -46
  244. package/src/views/PostManager/PostStats.tsx +0 -81
  245. package/src/views/PostManager/PostTable.d.ts +0 -15
  246. package/src/views/PostManager/PostTable.d.ts.map +0 -1
  247. package/src/views/PostManager/PostTable.js +0 -79
  248. package/src/views/PostManager/PostTable.tsx +0 -230
  249. package/src/views/PostManager/index.d.ts +0 -12
  250. package/src/views/PostManager/index.d.ts.map +0 -1
  251. package/src/views/PostManager/index.js +0 -11
  252. package/src/views/PostManager/index.ts +0 -15
  253. package/src/views/Preview/PreviewBridgeView.d.ts +0 -12
  254. package/src/views/Preview/PreviewBridgeView.d.ts.map +0 -1
  255. package/src/views/Preview/PreviewBridgeView.js +0 -11
  256. package/src/views/Preview/PreviewBridgeView.tsx +0 -64
  257. package/src/views/Preview/index.d.ts +0 -6
  258. package/src/views/Preview/index.d.ts.map +0 -1
  259. package/src/views/Preview/index.js +0 -4
  260. package/src/views/Preview/index.ts +0 -7
  261. package/src/views/Settings/SettingsView.d.ts +0 -10
  262. package/src/views/Settings/SettingsView.d.ts.map +0 -1
  263. package/src/views/Settings/SettingsView.js +0 -111
  264. package/src/views/Settings/SettingsView.tsx +0 -298
  265. package/src/views/Settings/index.d.ts +0 -6
  266. package/src/views/Settings/index.d.ts.map +0 -1
  267. package/src/views/Settings/index.js +0 -4
  268. package/src/views/Settings/index.ts +0 -7
  269. package/src/views/SlugSEO/SlugSEOManagerView.d.ts +0 -12
  270. package/src/views/SlugSEO/SlugSEOManagerView.d.ts.map +0 -1
  271. package/src/views/SlugSEO/SlugSEOManagerView.js +0 -11
  272. package/src/views/SlugSEO/SlugSEOManagerView.tsx +0 -94
  273. package/src/views/SlugSEO/index.d.ts +0 -6
  274. package/src/views/SlugSEO/index.d.ts.map +0 -1
  275. package/src/views/SlugSEO/index.js +0 -4
  276. package/src/views/SlugSEO/index.ts +0 -7
@@ -1,77 +0,0 @@
1
- /**
2
- * Client Utilities
3
- * Helper functions for fetching blog data in client applications
4
- */
5
- import { apiToBlogPost } from '../lib/mappers/apiMapper';
6
- /**
7
- * Fetch blog posts from the API
8
- *
9
- * @example
10
- * ```ts
11
- * const { blogs, total } = await fetchBlogs({ limit: 5 });
12
- * ```
13
- */
14
- export async function fetchBlogs(options = {}) {
15
- const { limit = 10, skip = 0, status, admin = false, apiBaseUrl = '/api/plugin-blog', } = options;
16
- const params = new URLSearchParams();
17
- if (limit)
18
- params.set('limit', limit.toString());
19
- if (skip)
20
- params.set('skip', skip.toString());
21
- if (status)
22
- params.set('status', status);
23
- if (admin)
24
- params.set('admin', 'true');
25
- const url = `${apiBaseUrl}?${params.toString()}`;
26
- const response = await fetch(url);
27
- if (!response.ok) {
28
- throw new Error(`Failed to fetch blogs: ${response.status}`);
29
- }
30
- const data = await response.json();
31
- // Handle error response
32
- if (data.error) {
33
- throw new Error(data.error || 'Failed to fetch blogs');
34
- }
35
- // Convert API format to PostListItem format
36
- const blogsArray = Array.isArray(data.blogs) ? data.blogs : [];
37
- const convertedBlogs = blogsArray.map((apiDoc) => {
38
- const blogPost = apiToBlogPost(apiDoc);
39
- return {
40
- id: blogPost.id,
41
- title: blogPost.title,
42
- slug: blogPost.slug,
43
- excerpt: blogPost.metadata.excerpt || '',
44
- status: blogPost.publication.status,
45
- authorId: blogPost.publication.authorId || '',
46
- updatedAt: blogPost.updatedAt,
47
- featuredImage: blogPost.metadata.featuredImage,
48
- };
49
- });
50
- return {
51
- blogs: convertedBlogs,
52
- total: data.total || convertedBlogs.length,
53
- };
54
- }
55
- /**
56
- * Fetch a single blog post by slug
57
- *
58
- * @example
59
- * ```ts
60
- * const blog = await fetchBlog({ slug: 'my-blog-post' });
61
- * ```
62
- */
63
- export async function fetchBlog(options) {
64
- const { slug, apiBaseUrl = '/api/plugin-blog' } = options;
65
- if (!slug) {
66
- throw new Error('Slug is required');
67
- }
68
- const response = await fetch(`${apiBaseUrl}/${slug}`);
69
- if (!response.ok) {
70
- if (response.status === 404) {
71
- throw new Error('Blog post not found');
72
- }
73
- throw new Error(`Failed to fetch blog: ${response.status}`);
74
- }
75
- const apiDoc = await response.json();
76
- return apiToBlogPost(apiDoc);
77
- }
@@ -1,122 +0,0 @@
1
- /**
2
- * Client Utilities
3
- * Helper functions for fetching blog data in client applications
4
- */
5
-
6
- import { apiToBlogPost, type APIBlogDocument } from '../lib/mappers/apiMapper';
7
- import { PostListItem, BlogPost } from '../types/post';
8
-
9
- export interface FetchBlogsOptions {
10
- /** Maximum number of posts to fetch (default: 10) */
11
- limit?: number;
12
- /** Number of posts to skip (default: 0) */
13
- skip?: number;
14
- /** Filter by status (published, draft, concept) */
15
- status?: string;
16
- /** Whether to fetch all posts for admin (includes drafts) */
17
- admin?: boolean;
18
- /** API base URL (default: '/api/blogs') */
19
- apiBaseUrl?: string;
20
- }
21
-
22
- export interface FetchBlogsResult {
23
- /** Array of blog posts */
24
- blogs: PostListItem[];
25
- /** Total number of posts available */
26
- total: number;
27
- }
28
-
29
- /**
30
- * Fetch blog posts from the API
31
- *
32
- * @example
33
- * ```ts
34
- * const { blogs, total } = await fetchBlogs({ limit: 5 });
35
- * ```
36
- */
37
- export async function fetchBlogs(options: FetchBlogsOptions = {}): Promise<FetchBlogsResult> {
38
- const {
39
- limit = 10,
40
- skip = 0,
41
- status,
42
- admin = false,
43
- apiBaseUrl = '/api/plugin-blog',
44
- } = options;
45
-
46
- const params = new URLSearchParams();
47
- if (limit) params.set('limit', limit.toString());
48
- if (skip) params.set('skip', skip.toString());
49
- if (status) params.set('status', status);
50
- if (admin) params.set('admin', 'true');
51
-
52
- const url = `${apiBaseUrl}?${params.toString()}`;
53
- const response = await fetch(url);
54
-
55
- if (!response.ok) {
56
- throw new Error(`Failed to fetch blogs: ${response.status}`);
57
- }
58
-
59
- const data = await response.json();
60
-
61
- // Handle error response
62
- if (data.error) {
63
- throw new Error(data.error || 'Failed to fetch blogs');
64
- }
65
-
66
- // Convert API format to PostListItem format
67
- const blogsArray = Array.isArray(data.blogs) ? data.blogs : [];
68
- const convertedBlogs: PostListItem[] = blogsArray.map((apiDoc: APIBlogDocument) => {
69
- const blogPost = apiToBlogPost(apiDoc);
70
- return {
71
- id: blogPost.id,
72
- title: blogPost.title,
73
- slug: blogPost.slug,
74
- excerpt: blogPost.metadata.excerpt || '',
75
- status: blogPost.publication.status,
76
- authorId: blogPost.publication.authorId || '',
77
- updatedAt: blogPost.updatedAt,
78
- featuredImage: blogPost.metadata.featuredImage,
79
- };
80
- });
81
-
82
- return {
83
- blogs: convertedBlogs,
84
- total: data.total || convertedBlogs.length,
85
- };
86
- }
87
-
88
- export interface FetchBlogOptions {
89
- /** Blog post slug */
90
- slug: string;
91
- /** API base URL (default: '/api/blogs') */
92
- apiBaseUrl?: string;
93
- }
94
-
95
- /**
96
- * Fetch a single blog post by slug
97
- *
98
- * @example
99
- * ```ts
100
- * const blog = await fetchBlog({ slug: 'my-blog-post' });
101
- * ```
102
- */
103
- export async function fetchBlog(options: FetchBlogOptions): Promise<BlogPost> {
104
- const { slug, apiBaseUrl = '/api/plugin-blog' } = options;
105
-
106
- if (!slug) {
107
- throw new Error('Slug is required');
108
- }
109
-
110
- const response = await fetch(`${apiBaseUrl}/${slug}`);
111
-
112
- if (!response.ok) {
113
- if (response.status === 404) {
114
- throw new Error('Blog post not found');
115
- }
116
- throw new Error(`Failed to fetch blog: ${response.status}`);
117
- }
118
-
119
- const apiDoc: APIBlogDocument = await response.json();
120
- return apiToBlogPost(apiDoc);
121
- }
122
-
@@ -1,7 +0,0 @@
1
- /**
2
- * Utilities
3
- * Helper functions and utilities for the blog plugin
4
- */
5
-
6
- export * from './client';
7
-
@@ -1,16 +0,0 @@
1
- /**
2
- * Block Wrapper Component
3
- * Provides hover controls (Delete, Move, Settings) for each block
4
- */
5
- import { Block } from '../../types/block';
6
- export interface BlockWrapperProps {
7
- block: Block;
8
- onUpdate: (data: Partial<Block['data']>) => void;
9
- onDelete: () => void;
10
- onMoveUp?: () => void;
11
- onMoveDown?: () => void;
12
- /** All blocks in the editor (for resolving child block IDs) */
13
- allBlocks?: Block[];
14
- }
15
- export declare function BlockWrapper({ block, onUpdate, onDelete, onMoveUp, onMoveDown, allBlocks, }: BlockWrapperProps): import("react/jsx-runtime").JSX.Element;
16
- //# sourceMappingURL=BlockWrapper.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BlockWrapper.d.ts","sourceRoot":"","sources":["BlockWrapper.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAK1C,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,CAAC;IACjD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;CACvB;AAED,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,SAAc,GACjB,EAAE,iBAAiB,2CAyenB"}
@@ -1,276 +0,0 @@
1
- /**
2
- * Block Wrapper Component
3
- * Provides hover controls (Delete, Move, Settings) for each block
4
- */
5
- 'use client';
6
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
7
- import { useState, useEffect, useRef } from 'react';
8
- import { Plus, Trash2, ChevronUp, ChevronDown, Settings2, GripVertical, Copy } from 'lucide-react';
9
- import { blockRegistry } from '../../registry/BlockRegistry';
10
- import { getChildBlocks, isContainerBlock } from '../../lib/utils/blockHelpers';
11
- import { useEditor } from '../../state/EditorContext';
12
- export function BlockWrapper({ block, onUpdate, onDelete, onMoveUp, onMoveDown, allBlocks = [], }) {
13
- const [isHovered, setIsHovered] = useState(false);
14
- const [isControlsHovered, setIsControlsHovered] = useState(false);
15
- const [showControls, setShowControls] = useState(false);
16
- const [isSelectingText, setIsSelectingText] = useState(false);
17
- const [showSettingsMenu, setShowSettingsMenu] = useState(false);
18
- const hideTimeoutRef = useRef(null);
19
- const settingsMenuRef = useRef(null);
20
- const { helpers, state, dispatch } = useEditor();
21
- const blockDefinition = blockRegistry.get(block.type);
22
- // Check if this is a container block
23
- const isContainer = isContainerBlock(block, blockRegistry);
24
- // Get child blocks - if children are Block objects, use them directly
25
- const childBlocks = isContainer && block.children && Array.isArray(block.children) && block.children.length > 0
26
- ? (typeof block.children[0] === 'object'
27
- ? block.children
28
- : getChildBlocks(block, state.blocks))
29
- : [];
30
- // Handle delayed hide with timeout
31
- useEffect(() => {
32
- const shouldShow = isHovered || isControlsHovered;
33
- if (shouldShow) {
34
- // Clear any pending hide timeout
35
- if (hideTimeoutRef.current) {
36
- clearTimeout(hideTimeoutRef.current);
37
- hideTimeoutRef.current = null;
38
- }
39
- // Show immediately
40
- setShowControls(true);
41
- }
42
- else {
43
- // Delay hiding by 500ms
44
- hideTimeoutRef.current = setTimeout(() => {
45
- setShowControls(false);
46
- }, 500);
47
- }
48
- return () => {
49
- if (hideTimeoutRef.current) {
50
- clearTimeout(hideTimeoutRef.current);
51
- }
52
- };
53
- }, [isHovered, isControlsHovered]);
54
- if (!blockDefinition) {
55
- return (_jsx("div", { className: "p-4 border border-red-300 dark:border-red-700 rounded-2xl bg-red-50 dark:bg-red-900/20", children: _jsxs("p", { className: "text-sm text-red-600 dark:text-red-400", children: ["Unknown block type: ", block.type] }) }));
56
- }
57
- const EditComponent = blockDefinition.components.Edit;
58
- const handleDragStart = (e) => {
59
- // Check if user is selecting text - if so, prevent dragging
60
- const selection = window.getSelection();
61
- if (selection && selection.toString().length > 0) {
62
- e.preventDefault();
63
- return;
64
- }
65
- // Prevent dragging if user was selecting text
66
- if (isSelectingText) {
67
- e.preventDefault();
68
- return;
69
- }
70
- // Only allow dragging when the block is focused/selected (hovered)
71
- if (!isHovered && !showControls) {
72
- e.preventDefault();
73
- return;
74
- }
75
- // Stop propagation to prevent parent containers from also handling the drag
76
- e.stopPropagation();
77
- console.log('[BlockWrapper] Drag Start:', {
78
- blockId: block.id,
79
- blockType: block.type,
80
- blockData: block.data,
81
- isContainer,
82
- hasChildren: isContainer && childBlocks.length > 0,
83
- });
84
- e.dataTransfer.setData('block-id', block.id);
85
- e.dataTransfer.setData('block-type', block.type);
86
- e.dataTransfer.effectAllowed = 'move';
87
- e.dataTransfer.setData('text/plain', ''); // Required for Firefox
88
- // Store in a way that persists across components
89
- if (typeof window !== 'undefined') {
90
- window.__DRAGGED_BLOCK_ID__ = block.id;
91
- console.log('[BlockWrapper] Stored global dragged block ID:', block.id);
92
- }
93
- };
94
- // Track text selection
95
- const handleMouseDown = (e) => {
96
- // Check if clicking on an input, textarea, or contentEditable element
97
- const target = e.target;
98
- const isEditableElement = target.tagName === 'INPUT' ||
99
- target.tagName === 'TEXTAREA' ||
100
- target.isContentEditable ||
101
- target.closest('input, textarea, [contenteditable="true"]');
102
- if (isEditableElement) {
103
- setIsSelectingText(true);
104
- // Reset after mouse up
105
- const handleMouseUp = () => {
106
- setTimeout(() => {
107
- const selection = window.getSelection();
108
- if (!selection || selection.toString().length === 0) {
109
- setIsSelectingText(false);
110
- }
111
- }, 100);
112
- document.removeEventListener('mouseup', handleMouseUp);
113
- };
114
- document.addEventListener('mouseup', handleMouseUp);
115
- }
116
- };
117
- // For hero blocks, only show controls when hovering over the image container
118
- const isHeroBlock = block.type === 'hero';
119
- const wrapperRef = useRef(null);
120
- const handleMouseMove = (e) => {
121
- if (isHeroBlock) {
122
- // For hero blocks, check if mouse is actually over the image container element
123
- const target = e.target;
124
- // Check if we're over the image container (using data attribute for more reliable detection)
125
- const imageContainer = target.closest('[data-hero-image-container]');
126
- // Check if we're over an Image component (from plugin-images)
127
- const imageElement = target.closest('[data-image-id]');
128
- // Check if we're directly over an img tag
129
- const isImgTag = target.tagName === 'IMG';
130
- const isOverImage = !!(imageContainer || imageElement || isImgTag);
131
- setIsHovered(isOverImage);
132
- }
133
- else if (!isHeroBlock) {
134
- setIsHovered(true);
135
- }
136
- };
137
- const handleMouseEnter = (e) => {
138
- if (!isHeroBlock) {
139
- setIsHovered(true);
140
- }
141
- else {
142
- // For hero blocks, check position on enter
143
- handleMouseMove(e);
144
- }
145
- };
146
- const handleMouseLeave = () => {
147
- setIsHovered(false);
148
- };
149
- // Close settings menu when clicking outside
150
- useEffect(() => {
151
- function handleClickOutside(event) {
152
- if (settingsMenuRef.current && !settingsMenuRef.current.contains(event.target)) {
153
- setShowSettingsMenu(false);
154
- }
155
- }
156
- if (showSettingsMenu) {
157
- document.addEventListener('mousedown', handleClickOutside);
158
- }
159
- return () => {
160
- document.removeEventListener('mousedown', handleClickOutside);
161
- };
162
- }, [showSettingsMenu]);
163
- // Generate a unique block ID
164
- const generateBlockId = () => {
165
- if (typeof crypto !== 'undefined' && crypto.randomUUID) {
166
- return crypto.randomUUID();
167
- }
168
- return `block-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
169
- };
170
- // Clone a block with new IDs (recursive for nested blocks)
171
- const cloneBlock = (blockToClone) => {
172
- const cloned = Object.assign(Object.assign({}, blockToClone), { id: generateBlockId(), data: Object.assign({}, blockToClone.data), meta: blockToClone.meta ? Object.assign({}, blockToClone.meta) : undefined });
173
- // Handle children if they exist
174
- if (blockToClone.children) {
175
- if (Array.isArray(blockToClone.children) && blockToClone.children.length > 0) {
176
- // Check if children are Block objects or IDs
177
- if (typeof blockToClone.children[0] === 'object') {
178
- cloned.children = blockToClone.children.map(cloneBlock);
179
- }
180
- else {
181
- // If children are IDs, we need to find and clone the actual blocks
182
- const childBlocks = getChildBlocks(blockToClone, allBlocks.length > 0 ? allBlocks : state.blocks);
183
- cloned.children = childBlocks.map(cloneBlock);
184
- }
185
- }
186
- }
187
- return cloned;
188
- };
189
- const handleCopy = () => {
190
- const clonedBlock = cloneBlock(block);
191
- // Store in localStorage for persistence across components
192
- if (typeof window !== 'undefined') {
193
- localStorage.setItem('__BLOG_EDITOR_COPIED_BLOCK__', JSON.stringify(clonedBlock));
194
- }
195
- setShowSettingsMenu(false);
196
- };
197
- // Store block ID when hovering for paste context
198
- useEffect(() => {
199
- if (isHovered || showControls) {
200
- if (typeof window !== 'undefined') {
201
- window.__BLOG_EDITOR_HOVERED_BLOCK_ID__ = block.id;
202
- }
203
- }
204
- }, [isHovered, showControls, block.id]);
205
- return (_jsxs("div", { ref: wrapperRef, className: "group relative", onMouseEnter: handleMouseEnter, onMouseMove: isHeroBlock ? handleMouseMove : undefined, onMouseLeave: handleMouseLeave, onMouseDown: handleMouseDown, draggable: isHovered || showControls, onDragStart: handleDragStart, "data-block-wrapper": true, "data-block-id": block.id, children: [_jsxs("div", { className: `absolute -left-16 top-1/2 -translate-y-1/2 flex flex-col gap-2 transition-all duration-200 ${showControls ? 'opacity-100' : 'opacity-0 pointer-events-none'}`, onMouseEnter: () => setIsControlsHovered(true), onMouseLeave: () => setIsControlsHovered(false), children: [_jsx("button", { className: "p-2 text-neutral-500 dark:text-neutral-400 hover:text-primary dark:hover:text-primary bg-white dark:bg-neutral-800 rounded-lg shadow-sm border border-neutral-200 dark:border-neutral-700 hover:border-primary dark:hover:border-primary/50 transition-colors", title: "Add block above", children: _jsx(Plus, { size: 14 }) }), onMoveUp && (_jsx("button", { onClick: onMoveUp, className: "p-2 text-neutral-500 dark:text-neutral-400 hover:text-neutral-950 dark:hover:text-white bg-white dark:bg-neutral-800 rounded-lg shadow-sm border border-neutral-200 dark:border-neutral-700 hover:border-neutral-300 dark:hover:border-neutral-600 transition-colors", title: "Move up", children: _jsx(ChevronUp, { size: 14 }) })), onMoveDown && (_jsx("button", { onClick: onMoveDown, className: "p-2 text-neutral-500 dark:text-neutral-400 hover:text-neutral-950 dark:hover:text-white bg-white dark:bg-neutral-800 rounded-lg shadow-sm border border-neutral-200 dark:border-neutral-700 hover:border-neutral-300 dark:hover:border-neutral-600 transition-colors", title: "Move down", children: _jsx(ChevronDown, { size: 14 }) })), _jsx("button", { onClick: onDelete, className: "p-2 text-neutral-500 dark:text-neutral-400 hover:text-red-500 dark:hover:text-red-400 bg-white dark:bg-neutral-800 rounded-lg shadow-sm border border-neutral-200 dark:border-neutral-700 hover:border-red-500 dark:hover:border-red-500/50 transition-colors", title: "Delete block", children: _jsx(Trash2, { size: 14 }) })] }), _jsx("div", { className: `mb-2 transition-all relative ${isHovered || showControls || showSettingsMenu
206
- ? 'opacity-100 translate-y-0'
207
- : 'opacity-0 -translate-y-2 pointer-events-none'}`, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: _jsxs("div", { className: "flex items-center justify-between px-2 py-1.5 rounded-lg backdrop-blur-sm border bg-neutral-50/95 dark:bg-neutral-800/95 border-neutral-200 dark:border-neutral-800", children: [_jsxs("div", { className: "flex items-center gap-2 flex-1 min-w-0", children: [_jsx(GripVertical, { size: 12, className: "cursor-grab active:cursor-grabbing shrink-0 text-neutral-400 dark:text-neutral-500" }), _jsx("span", { className: "text-[10px] font-black uppercase tracking-wider shrink-0 text-neutral-500 dark:text-neutral-400", children: blockDefinition.name }), block.type === 'columns' && (() => {
208
- const columnCount = block.data.columnCount;
209
- const layout = block.data.layout;
210
- // Determine number of columns
211
- let numColumns;
212
- if (columnCount !== undefined && columnCount > 0) {
213
- numColumns = columnCount;
214
- }
215
- else if (layout) {
216
- // Legacy layout system
217
- const layoutMap = {
218
- '50-50': 2,
219
- '33-66': 2,
220
- '66-33': 2,
221
- '25-25-25-25': 4,
222
- '25-75': 2,
223
- '75-25': 2,
224
- };
225
- numColumns = layoutMap[layout] || 2;
226
- }
227
- else {
228
- numColumns = 2;
229
- }
230
- // Get column widths
231
- const storedWidths = block.data.columnWidths;
232
- const columnWidths = storedWidths && storedWidths.length === numColumns
233
- ? storedWidths
234
- : Array(numColumns).fill(Math.floor(100 / numColumns));
235
- return (_jsx("div", { className: "flex items-center gap-1.5 ml-4 flex-1 min-w-0", children: Array.from({ length: numColumns }).map((_, colIndex) => (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx("input", { type: "number", min: "10", max: "90", step: "1", value: columnWidths[colIndex] || 50, onChange: (e) => {
236
- const newWidth = parseInt(e.target.value) || 50;
237
- const newWidths = [...columnWidths];
238
- newWidths[colIndex] = Math.max(10, Math.min(90, newWidth));
239
- // Normalize remaining columns to sum to 100
240
- const remainingTotal = newWidths.reduce((sum, w, i) => i === colIndex ? sum : sum + w, 0);
241
- const remainingTarget = 100 - newWidths[colIndex];
242
- if (remainingTotal > 0 && remainingTarget > 0) {
243
- const scale = remainingTarget / remainingTotal;
244
- newWidths.forEach((w, i) => {
245
- if (i !== colIndex) {
246
- newWidths[i] = Math.round(w * scale);
247
- }
248
- });
249
- }
250
- // Ensure sum is exactly 100
251
- const finalTotal = newWidths.reduce((sum, w) => sum + w, 0);
252
- if (finalTotal !== 100) {
253
- const diff = 100 - finalTotal;
254
- const lastIndex = newWidths.length - 1;
255
- newWidths[lastIndex] = Math.max(10, newWidths[lastIndex] + diff);
256
- }
257
- onUpdate(Object.assign(Object.assign({}, block.data), { columnWidths: newWidths, layout: undefined }));
258
- }, onClick: (e) => e.stopPropagation(), className: "w-12 text-[10px] font-bold bg-white dark:bg-neutral-900/50 border border-neutral-300 dark:border-neutral-700 px-1.5 py-0.5 rounded outline-none focus:border-primary transition-all dark:text-neutral-100 text-center" }), _jsx("span", { className: "text-[9px] text-neutral-400 dark:text-neutral-500", children: "%" })] }, colIndex))) }));
259
- })()] }), _jsxs("div", { className: "relative shrink-0 z-20", ref: settingsMenuRef, children: [_jsx("button", { onClick: (e) => {
260
- e.stopPropagation();
261
- setShowSettingsMenu(!showSettingsMenu);
262
- }, className: "p-1 rounded transition-colors text-neutral-400 dark:text-neutral-500 hover:text-neutral-950 dark:hover:text-white hover:bg-neutral-100 dark:hover:bg-neutral-800 relative z-20", title: "Block settings", children: _jsx(Settings2, { size: 12 }) }), showSettingsMenu && (_jsx("div", { className: "absolute right-0 top-full mt-1 w-40 bg-white dark:bg-neutral-900 border border-neutral-300 dark:border-neutral-700 rounded-lg shadow-xl z-20 overflow-hidden", children: _jsxs("button", { onClick: (e) => {
263
- e.stopPropagation();
264
- handleCopy();
265
- }, className: "w-full flex items-center gap-2 px-3 py-2 text-xs font-bold text-neutral-600 dark:text-neutral-400 hover:bg-neutral-100 dark:hover:bg-neutral-800 transition-colors", children: [_jsx(Copy, { size: 14 }), _jsx("span", { children: "Copy" })] }) }))] })] }) }), _jsx("div", { className: `relative rounded-xl border-2 transition-all ${showControls
266
- ? 'border-primary/60 dark:border-primary/40 bg-primary/5 dark:bg-primary/10'
267
- : 'border-neutral-200 dark:border-neutral-700 bg-transparent'}`, children: _jsx("div", { className: "relative", style: { userSelect: 'text' }, children: isContainer && (block.type === 'section' || block.type === 'columns') ? (_jsx(EditComponent, { block: block, onUpdate: onUpdate, onDelete: onDelete, isSelected: isHovered, childBlocks: childBlocks, onChildBlockAdd: (type, index, containerId) => {
268
- helpers.addBlock(type, index, containerId || block.id);
269
- }, onChildBlockUpdate: (id, data, containerId) => {
270
- helpers.updateBlock(id, data);
271
- }, onChildBlockDelete: (id, containerId) => {
272
- helpers.deleteBlock(id);
273
- }, onChildBlockMove: (id, newIndex, containerId) => {
274
- helpers.moveBlock(id, newIndex, containerId || block.id);
275
- } })) : (_jsx(EditComponent, { block: block, onUpdate: onUpdate, onDelete: onDelete, isSelected: isHovered })) }) })] }));
276
- }