@jhits/plugin-blog 0.0.18 → 0.0.20
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.
- package/dist/api/categories.d.ts.map +1 -1
- package/dist/api/categories.js +42 -38
- package/dist/api/handler.d.ts +1 -26
- package/dist/api/handler.d.ts.map +1 -1
- package/dist/api/handler.js +81 -500
- package/dist/api/router.d.ts +0 -5
- package/dist/api/router.d.ts.map +1 -1
- package/dist/api/router.js +8 -35
- package/dist/api/service.d.ts +80 -0
- package/dist/api/service.d.ts.map +1 -0
- package/dist/api/service.js +219 -0
- package/dist/hooks/useAutoSave.d.ts +10 -0
- package/dist/hooks/useAutoSave.d.ts.map +1 -0
- package/dist/hooks/useAutoSave.js +57 -0
- package/dist/hooks/useCategories.d.ts +1 -1
- package/dist/hooks/useCategories.d.ts.map +1 -1
- package/dist/hooks/useCategories.js +15 -46
- package/dist/index.d.ts +24 -31
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -201
- package/dist/init.d.ts +20 -7
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +8 -7
- package/dist/lib/blocks/BlockRenderer.d.ts.map +1 -1
- package/dist/lib/layouts/blocks/ColumnsBlock.d.ts.map +1 -1
- package/dist/lib/layouts/blocks/ColumnsBlock.js +30 -113
- package/dist/lib/layouts/blocks/SectionBlock.d.ts.map +1 -1
- package/dist/lib/layouts/blocks/SectionBlock.js +9 -21
- package/dist/lib/layouts/index.d.ts +3 -3
- package/dist/lib/layouts/index.js +4 -4
- package/dist/lib/mappers/apiMapper.d.ts +10 -0
- package/dist/lib/mappers/apiMapper.d.ts.map +1 -1
- package/dist/lib/mappers/apiMapper.js +47 -32
- package/dist/lib/rich-text/RichTextEditor.d.ts +4 -2
- package/dist/lib/rich-text/RichTextEditor.d.ts.map +1 -1
- package/dist/lib/rich-text/RichTextEditor.js +12 -9
- package/dist/lib/utils/config-resolver.d.ts +28 -0
- package/dist/lib/utils/config-resolver.d.ts.map +1 -0
- package/dist/lib/utils/config-resolver.js +46 -0
- package/dist/lib/utils/tree.d.ts +29 -0
- package/dist/lib/utils/tree.d.ts.map +1 -0
- package/dist/lib/utils/tree.js +129 -0
- package/dist/state/EditorContext.d.ts +3 -25
- package/dist/state/EditorContext.d.ts.map +1 -1
- package/dist/state/EditorContext.js +124 -174
- package/dist/state/reducer.d.ts +1 -5
- package/dist/state/reducer.d.ts.map +1 -1
- package/dist/state/reducer.js +128 -521
- package/dist/state/types.d.ts +12 -1
- package/dist/state/types.d.ts.map +1 -1
- package/dist/types/block.d.ts +9 -0
- package/dist/types/block.d.ts.map +1 -1
- package/dist/types/post.d.ts +17 -1
- package/dist/types/post.d.ts.map +1 -1
- package/dist/views/CanvasEditor/BlockWrapper.d.ts +5 -6
- package/dist/views/CanvasEditor/BlockWrapper.d.ts.map +1 -1
- package/dist/views/CanvasEditor/BlockWrapper.js +56 -264
- package/dist/views/CanvasEditor/CanvasEditorView.d.ts +5 -3
- package/dist/views/CanvasEditor/CanvasEditorView.d.ts.map +1 -1
- package/dist/views/CanvasEditor/CanvasEditorView.js +55 -315
- package/dist/views/CanvasEditor/EditorBody.d.ts +6 -8
- package/dist/views/CanvasEditor/EditorBody.d.ts.map +1 -1
- package/dist/views/CanvasEditor/EditorBody.js +34 -482
- package/dist/views/CanvasEditor/EditorHeader.d.ts.map +1 -1
- package/dist/views/CanvasEditor/EditorHeader.js +27 -63
- package/dist/views/CanvasEditor/LayoutContainer.d.ts.map +1 -1
- package/dist/views/CanvasEditor/LayoutContainer.js +49 -70
- package/dist/views/CanvasEditor/components/CustomBlockItem.js +1 -1
- package/dist/views/CanvasEditor/components/EditorCanvas.d.ts +15 -3
- package/dist/views/CanvasEditor/components/EditorCanvas.d.ts.map +1 -1
- package/dist/views/CanvasEditor/components/EditorCanvas.js +40 -18
- package/dist/views/CanvasEditor/components/EditorLibrary.d.ts +5 -1
- package/dist/views/CanvasEditor/components/EditorLibrary.d.ts.map +1 -1
- package/dist/views/CanvasEditor/components/EditorLibrary.js +11 -7
- package/dist/views/CanvasEditor/components/EditorSidebar.d.ts.map +1 -1
- package/dist/views/CanvasEditor/components/EditorSidebar.js +32 -14
- package/dist/views/CanvasEditor/components/FeaturedMediaSection.d.ts +0 -6
- package/dist/views/CanvasEditor/components/FeaturedMediaSection.d.ts.map +1 -1
- package/dist/views/CanvasEditor/components/FeaturedMediaSection.js +17 -128
- package/dist/views/CanvasEditor/components/JSONInspector.d.ts +9 -0
- package/dist/views/CanvasEditor/components/JSONInspector.d.ts.map +1 -0
- package/dist/views/CanvasEditor/components/JSONInspector.js +56 -0
- package/dist/views/CanvasEditor/components/LibraryItem.js +2 -2
- package/dist/views/CanvasEditor/components/PrivacySettingsSection.d.ts +0 -4
- package/dist/views/CanvasEditor/components/PrivacySettingsSection.d.ts.map +1 -1
- package/dist/views/CanvasEditor/components/PrivacySettingsSection.js +6 -28
- package/dist/views/CanvasEditor/components/index.d.ts +2 -0
- package/dist/views/CanvasEditor/components/index.d.ts.map +1 -1
- package/dist/views/CanvasEditor/components/index.js +1 -0
- package/dist/views/CanvasEditor/hooks/useHeroBlock.d.ts.map +1 -1
- package/dist/views/CanvasEditor/hooks/useHeroBlock.js +15 -18
- package/dist/views/CanvasEditor/hooks/usePostLoader.d.ts +3 -0
- package/dist/views/CanvasEditor/hooks/usePostLoader.d.ts.map +1 -1
- package/dist/views/CanvasEditor/hooks/usePostLoader.js +12 -13
- package/dist/views/CanvasEditor/hooks/useUnsavedChanges.js +0 -4
- package/dist/views/PostManager/EmptyState.d.ts +1 -1
- package/dist/views/PostManager/EmptyState.js +4 -4
- package/dist/views/PostManager/FilterDropdown.d.ts +21 -0
- package/dist/views/PostManager/FilterDropdown.d.ts.map +1 -0
- package/dist/views/PostManager/FilterDropdown.js +28 -0
- package/dist/views/PostManager/LanguageFlags.d.ts.map +1 -1
- package/dist/views/PostManager/LanguageFlags.js +4 -1
- package/dist/views/PostManager/PostCards.d.ts.map +1 -1
- package/dist/views/PostManager/PostCards.js +23 -40
- package/dist/views/PostManager/PostFilters.d.ts.map +1 -1
- package/dist/views/PostManager/PostFilters.js +34 -3
- package/dist/views/PostManager/PostManagerView.d.ts +1 -2
- package/dist/views/PostManager/PostManagerView.d.ts.map +1 -1
- package/dist/views/PostManager/PostManagerView.js +30 -96
- package/dist/views/PostManager/PostStats.d.ts.map +1 -1
- package/dist/views/PostManager/PostStats.js +10 -10
- package/dist/views/PostManager/PostTable.d.ts.map +1 -1
- package/dist/views/PostManager/PostTable.js +23 -40
- package/dist/views/Settings/SettingsView.d.ts +1 -1
- package/dist/views/Settings/SettingsView.d.ts.map +1 -1
- package/dist/views/Settings/SettingsView.js +12 -39
- package/dist/views/SlugSEO/SlugSEOManagerView.d.ts.map +1 -1
- package/dist/views/SlugSEO/SlugSEOManagerView.js +2 -2
- package/package.json +42 -6
- package/src/api/categories.ts +48 -52
- package/src/api/handler.ts +87 -604
- package/src/api/router.ts +15 -65
- package/src/api/service.ts +241 -0
- package/src/hooks/useAutoSave.ts +64 -0
- package/src/hooks/useCategories.ts +19 -47
- package/src/index.tsx +79 -293
- package/src/init.tsx +24 -11
- package/src/lib/blocks/BlockRenderer.tsx +1 -0
- package/src/lib/layouts/blocks/ColumnsBlock.tsx +60 -173
- package/src/lib/layouts/blocks/SectionBlock.tsx +22 -26
- package/src/lib/layouts/index.ts +4 -4
- package/src/lib/mappers/apiMapper.ts +63 -32
- package/src/lib/rich-text/RichTextEditor.tsx +16 -9
- package/src/lib/utils/config-resolver.ts +64 -0
- package/src/lib/utils/tree.ts +150 -0
- package/src/state/EditorContext.tsx +153 -232
- package/src/state/reducer.ts +141 -606
- package/src/state/types.ts +14 -1
- package/src/types/block.ts +10 -0
- package/src/types/post.ts +19 -1
- package/src/views/CanvasEditor/BlockWrapper.tsx +130 -460
- package/src/views/CanvasEditor/CanvasEditorView.tsx +145 -420
- package/src/views/CanvasEditor/EditorBody.tsx +98 -610
- package/src/views/CanvasEditor/EditorHeader.tsx +176 -196
- package/src/views/CanvasEditor/LayoutContainer.tsx +74 -89
- package/src/views/CanvasEditor/components/CustomBlockItem.tsx +7 -8
- package/src/views/CanvasEditor/components/EditorCanvas.tsx +139 -84
- package/src/views/CanvasEditor/components/EditorLibrary.tsx +25 -10
- package/src/views/CanvasEditor/components/EditorSidebar.tsx +196 -127
- package/src/views/CanvasEditor/components/FeaturedMediaSection.tsx +78 -210
- package/src/views/CanvasEditor/components/JSONInspector.tsx +125 -0
- package/src/views/CanvasEditor/components/LibraryItem.tsx +5 -6
- package/src/views/CanvasEditor/components/PrivacySettingsSection.tsx +73 -124
- package/src/views/CanvasEditor/components/index.ts +2 -1
- package/src/views/CanvasEditor/hooks/useHeroBlock.ts +15 -18
- package/src/views/CanvasEditor/hooks/usePostLoader.ts +21 -13
- package/src/views/CanvasEditor/hooks/useUnsavedChanges.ts +4 -4
- package/src/views/PostManager/EmptyState.tsx +9 -10
- package/src/views/PostManager/FilterDropdown.tsx +95 -0
- package/src/views/PostManager/LanguageFlags.tsx +6 -2
- package/src/views/PostManager/PostCards.tsx +127 -133
- package/src/views/PostManager/PostFilters.tsx +73 -68
- package/src/views/PostManager/PostManagerView.tsx +132 -179
- package/src/views/PostManager/PostStats.tsx +21 -20
- package/src/views/PostManager/PostTable.tsx +137 -165
- package/src/views/Settings/SettingsView.tsx +64 -180
- package/src/views/SlugSEO/SlugSEOManagerView.tsx +59 -44
- package/src/hooks/index.d.ts +0 -8
- package/src/hooks/index.d.ts.map +0 -1
- package/src/hooks/useBlog.d.ts +0 -31
- package/src/hooks/useBlog.d.ts.map +0 -1
- package/src/hooks/useBlogs.d.ts +0 -39
- package/src/hooks/useBlogs.d.ts.map +0 -1
- package/src/hooks/useCategories.d.ts +0 -9
- package/src/hooks/useCategories.d.ts.map +0 -1
- package/src/lib/blocks/BlockRenderer.d.ts +0 -54
- package/src/lib/blocks/BlockRenderer.d.ts.map +0 -1
- package/src/lib/config-storage.d.ts +0 -30
- package/src/lib/config-storage.d.ts.map +0 -1
- package/src/lib/layouts/blocks/ColumnsBlock.d.ts +0 -25
- package/src/lib/layouts/blocks/ColumnsBlock.d.ts.map +0 -1
- package/src/lib/layouts/blocks/SectionBlock.d.ts +0 -25
- package/src/lib/layouts/blocks/SectionBlock.d.ts.map +0 -1
- package/src/lib/layouts/index.d.ts +0 -23
- package/src/lib/layouts/index.d.ts.map +0 -1
- package/src/lib/layouts/registerLayoutBlocks.d.ts +0 -9
- package/src/lib/layouts/registerLayoutBlocks.d.ts.map +0 -1
- package/src/lib/mappers/apiMapper.d.ts +0 -66
- package/src/lib/mappers/apiMapper.d.ts.map +0 -1
- package/src/lib/rich-text/RichTextEditor.d.ts +0 -45
- package/src/lib/rich-text/RichTextEditor.d.ts.map +0 -1
- package/src/lib/rich-text/RichTextPreview.d.ts +0 -16
- package/src/lib/rich-text/RichTextPreview.d.ts.map +0 -1
- package/src/lib/rich-text/index.d.ts +0 -9
- package/src/lib/rich-text/index.d.ts.map +0 -1
- package/src/lib/utils/blockHelpers.d.ts +0 -23
- package/src/lib/utils/blockHelpers.d.ts.map +0 -1
- package/src/lib/utils/configValidation.d.ts +0 -23
- package/src/lib/utils/configValidation.d.ts.map +0 -1
- package/src/registry/BlockRegistry.d.ts +0 -62
- package/src/registry/BlockRegistry.d.ts.map +0 -1
- package/src/registry/index.d.ts +0 -6
- package/src/registry/index.d.ts.map +0 -1
- package/src/state/EditorContext.d.ts +0 -45
- package/src/state/EditorContext.d.ts.map +0 -1
- package/src/state/index.d.ts +0 -7
- package/src/state/index.d.ts.map +0 -1
- package/src/state/reducer.d.ts +0 -11
- package/src/state/reducer.d.ts.map +0 -1
- package/src/state/types.d.ts +0 -162
- package/src/state/types.d.ts.map +0 -1
- package/src/types/block.d.ts +0 -221
- package/src/types/block.d.ts.map +0 -1
- package/src/types/index.d.ts +0 -8
- package/src/types/index.d.ts.map +0 -1
- package/src/types/post.d.ts +0 -136
- package/src/types/post.d.ts.map +0 -1
- package/src/utils/client.d.ts +0 -48
- package/src/utils/client.d.ts.map +0 -1
- package/src/views/CanvasEditor/BlockWrapper.d.ts +0 -16
- package/src/views/CanvasEditor/BlockWrapper.d.ts.map +0 -1
- package/src/views/CanvasEditor/CanvasEditorView.d.ts +0 -14
- package/src/views/CanvasEditor/CanvasEditorView.d.ts.map +0 -1
- package/src/views/CanvasEditor/EditorBody.d.ts +0 -22
- package/src/views/CanvasEditor/EditorBody.d.ts.map +0 -1
- package/src/views/CanvasEditor/EditorHeader.d.ts +0 -18
- package/src/views/CanvasEditor/EditorHeader.d.ts.map +0 -1
- package/src/views/CanvasEditor/LayoutContainer.d.ts +0 -17
- package/src/views/CanvasEditor/LayoutContainer.d.ts.map +0 -1
- package/src/views/CanvasEditor/SaveConfirmationModal.d.ts +0 -13
- package/src/views/CanvasEditor/SaveConfirmationModal.d.ts.map +0 -1
- package/src/views/CanvasEditor/components/CustomBlockItem.d.ts +0 -14
- package/src/views/CanvasEditor/components/CustomBlockItem.d.ts.map +0 -1
- package/src/views/CanvasEditor/components/EditorCanvas.d.ts +0 -29
- package/src/views/CanvasEditor/components/EditorCanvas.d.ts.map +0 -1
- package/src/views/CanvasEditor/components/EditorLibrary.d.ts +0 -7
- package/src/views/CanvasEditor/components/EditorLibrary.d.ts.map +0 -1
- package/src/views/CanvasEditor/components/EditorSidebar.d.ts +0 -13
- package/src/views/CanvasEditor/components/EditorSidebar.d.ts.map +0 -1
- package/src/views/CanvasEditor/components/ErrorBanner.d.ts +0 -6
- package/src/views/CanvasEditor/components/ErrorBanner.d.ts.map +0 -1
- package/src/views/CanvasEditor/components/FeaturedMediaSection.d.ts +0 -25
- package/src/views/CanvasEditor/components/FeaturedMediaSection.d.ts.map +0 -1
- package/src/views/CanvasEditor/components/LibraryItem.d.ts +0 -14
- package/src/views/CanvasEditor/components/LibraryItem.d.ts.map +0 -1
- package/src/views/CanvasEditor/components/PrivacySettingsSection.d.ts +0 -15
- package/src/views/CanvasEditor/components/PrivacySettingsSection.d.ts.map +0 -1
- package/src/views/CanvasEditor/components/index.d.ts +0 -21
- package/src/views/CanvasEditor/components/index.d.ts.map +0 -1
- package/src/views/CanvasEditor/hooks/index.d.ts +0 -10
- package/src/views/CanvasEditor/hooks/index.d.ts.map +0 -1
- package/src/views/CanvasEditor/hooks/useHeroBlock.d.ts +0 -8
- package/src/views/CanvasEditor/hooks/useHeroBlock.d.ts.map +0 -1
- package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts +0 -3
- package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts.map +0 -1
- package/src/views/CanvasEditor/hooks/usePostLoader.d.ts +0 -5
- package/src/views/CanvasEditor/hooks/usePostLoader.d.ts.map +0 -1
- package/src/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts +0 -2
- package/src/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts.map +0 -1
- package/src/views/CanvasEditor/hooks/useUnsavedChanges.d.ts +0 -25
- package/src/views/CanvasEditor/hooks/useUnsavedChanges.d.ts.map +0 -1
- package/src/views/CanvasEditor/index.d.ts +0 -16
- package/src/views/CanvasEditor/index.d.ts.map +0 -1
- package/src/views/PostManager/EmptyState.d.ts +0 -10
- package/src/views/PostManager/EmptyState.d.ts.map +0 -1
- package/src/views/PostManager/PostActionsMenu.d.ts +0 -12
- package/src/views/PostManager/PostActionsMenu.d.ts.map +0 -1
- package/src/views/PostManager/PostCards.d.ts +0 -15
- package/src/views/PostManager/PostCards.d.ts.map +0 -1
- package/src/views/PostManager/PostFilters.d.ts +0 -16
- package/src/views/PostManager/PostFilters.d.ts.map +0 -1
- package/src/views/PostManager/PostManagerView.d.ts +0 -11
- package/src/views/PostManager/PostManagerView.d.ts.map +0 -1
- package/src/views/PostManager/PostStats.d.ts +0 -11
- package/src/views/PostManager/PostStats.d.ts.map +0 -1
- package/src/views/PostManager/PostTable.d.ts +0 -15
- package/src/views/PostManager/PostTable.d.ts.map +0 -1
- package/src/views/PostManager/index.d.ts +0 -12
- package/src/views/PostManager/index.d.ts.map +0 -1
- package/src/views/Preview/PreviewBridgeView.d.ts +0 -12
- package/src/views/Preview/PreviewBridgeView.d.ts.map +0 -1
- package/src/views/Preview/index.d.ts +0 -6
- package/src/views/Preview/index.d.ts.map +0 -1
- package/src/views/Settings/SettingsView.d.ts +0 -10
- package/src/views/Settings/SettingsView.d.ts.map +0 -1
- package/src/views/Settings/index.d.ts +0 -6
- package/src/views/Settings/index.d.ts.map +0 -1
- package/src/views/SlugSEO/SlugSEOManagerView.d.ts +0 -12
- package/src/views/SlugSEO/SlugSEOManagerView.d.ts.map +0 -1
- package/src/views/SlugSEO/index.d.ts +0 -6
- package/src/views/SlugSEO/index.d.ts.map +0 -1
package/src/index.tsx
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Plugin Blog - Main Entry Point
|
|
3
|
-
*
|
|
4
|
-
* Multi-Tenant Architecture: Accepts custom blocks from client applications
|
|
3
|
+
* Simplified with Configuration Resolver
|
|
5
4
|
*/
|
|
6
5
|
|
|
7
6
|
'use client';
|
|
8
7
|
|
|
9
8
|
import React, { useMemo, useEffect } from 'react';
|
|
10
9
|
import { EditorProvider } from './state/EditorContext';
|
|
11
|
-
import { ClientBlockDefinition } from './types/block';
|
|
12
10
|
import { PostManagerView } from './views/PostManager';
|
|
13
11
|
import { CanvasEditorView } from './views/CanvasEditor';
|
|
14
12
|
import { editorStateToAPI } from './lib/mappers/apiMapper';
|
|
@@ -16,324 +14,112 @@ import { SlugSEOManagerView } from './views/SlugSEO';
|
|
|
16
14
|
import { PreviewBridgeView } from './views/Preview';
|
|
17
15
|
import { SettingsView } from './views/Settings';
|
|
18
16
|
import { useHeroBlockValidation, findHeroBlock } from './lib/utils/configValidation';
|
|
17
|
+
import { resolvePluginConfig } from './lib/utils/config-resolver';
|
|
18
|
+
import { ClientBlockDefinition } from './types/block';
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
* Plugin Props Interface
|
|
22
|
-
* Matches the PluginProps from @jhits/jhits-dashboard
|
|
23
|
-
*/
|
|
24
20
|
export interface PluginProps {
|
|
25
21
|
subPath: string[];
|
|
26
22
|
siteId: string;
|
|
27
23
|
locale: string;
|
|
28
|
-
/** Custom blocks from client application (optional, can also come from window.__JHITS_PLUGIN_PROPS__) */
|
|
29
24
|
customBlocks?: ClientBlockDefinition[];
|
|
30
|
-
/** Enable dark mode for content area and wrappers (default: true) */
|
|
31
25
|
darkMode?: boolean;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
light: string;
|
|
36
|
-
/** Background color for dark mode (optional) */
|
|
37
|
-
dark?: string;
|
|
38
|
-
};
|
|
26
|
+
backgroundColors?: { light: string; dark?: string };
|
|
27
|
+
LayoutWrapper?: React.ComponentType<any>;
|
|
28
|
+
translations?: Record<string, any>;
|
|
39
29
|
}
|
|
40
30
|
|
|
41
31
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* Client Handshake:
|
|
46
|
-
* - Client apps can pass customBlocks via props
|
|
47
|
-
* - Or via window.__JHITS_PLUGIN_PROPS__['plugin-blog'].customBlocks
|
|
48
|
-
* - The EditorProvider will automatically register these blocks
|
|
32
|
+
* Client-facing configuration type
|
|
33
|
+
* Allows partial overrides of plugin behavior
|
|
49
34
|
*/
|
|
35
|
+
export type BlogPluginConfig = Partial<Omit<PluginProps, 'subPath' | 'siteId' | 'locale'>> & {
|
|
36
|
+
customBlocks?: ClientBlockDefinition[];
|
|
37
|
+
darkMode?: boolean;
|
|
38
|
+
backgroundColors?: { light: string; dark?: string };
|
|
39
|
+
LayoutWrapper?: React.ComponentType<any>;
|
|
40
|
+
translations?: Record<string, any>;
|
|
41
|
+
};
|
|
42
|
+
|
|
50
43
|
export default function BlogPlugin(props: PluginProps) {
|
|
51
|
-
const { subPath, siteId, locale
|
|
52
|
-
|
|
53
|
-
// Get custom blocks from props or window global (client app injection point)
|
|
54
|
-
const customBlocks = useMemo(() => {
|
|
55
|
-
// First, try props
|
|
56
|
-
if (propsCustomBlocks && propsCustomBlocks.length > 0) {
|
|
57
|
-
return propsCustomBlocks;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Fallback to window global (for client app injection)
|
|
61
|
-
if (typeof window !== 'undefined' && (window as any).__JHITS_PLUGIN_PROPS__) {
|
|
62
|
-
const pluginProps = (window as any).__JHITS_PLUGIN_PROPS__['plugin-blog'];
|
|
63
|
-
if (pluginProps?.customBlocks) {
|
|
64
|
-
return pluginProps.customBlocks as ClientBlockDefinition[];
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return [];
|
|
69
|
-
}, [propsCustomBlocks]);
|
|
70
|
-
|
|
71
|
-
// Get dark mode setting from props, localStorage (dev settings), or window global
|
|
72
|
-
// Priority: localStorage (dev) > props > window global > default
|
|
73
|
-
const darkMode = useMemo(() => {
|
|
74
|
-
// First, check localStorage for dev settings (highest priority for dev)
|
|
75
|
-
if (typeof window !== 'undefined') {
|
|
76
|
-
try {
|
|
77
|
-
const saved = localStorage.getItem('__JHITS_PLUGIN_BLOG_CONFIG__');
|
|
78
|
-
if (saved) {
|
|
79
|
-
const config = JSON.parse(saved);
|
|
80
|
-
if (config.darkMode !== undefined) {
|
|
81
|
-
return config.darkMode as boolean;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
} catch (e) {
|
|
85
|
-
// Ignore localStorage errors
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Then try props
|
|
90
|
-
if (propsDarkMode !== undefined) {
|
|
91
|
-
return propsDarkMode;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Fallback to window global if prop not provided
|
|
95
|
-
if (typeof window !== 'undefined' && (window as any).__JHITS_PLUGIN_PROPS__) {
|
|
96
|
-
const pluginProps = (window as any).__JHITS_PLUGIN_PROPS__['plugin-blog'];
|
|
97
|
-
if (pluginProps?.darkMode !== undefined) {
|
|
98
|
-
return pluginProps.darkMode as boolean;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return true; // Default to dark mode enabled
|
|
103
|
-
}, [propsDarkMode]);
|
|
104
|
-
|
|
105
|
-
// Get background colors from props, localStorage (dev settings), or window global
|
|
106
|
-
// Priority: localStorage (dev) > props > window global
|
|
107
|
-
const backgroundColors = useMemo(() => {
|
|
108
|
-
// First, check localStorage for dev settings (highest priority for dev)
|
|
109
|
-
if (typeof window !== 'undefined') {
|
|
110
|
-
try {
|
|
111
|
-
const saved = localStorage.getItem('__JHITS_PLUGIN_BLOG_CONFIG__');
|
|
112
|
-
if (saved) {
|
|
113
|
-
const config = JSON.parse(saved);
|
|
114
|
-
if (config.backgroundColors) {
|
|
115
|
-
return config.backgroundColors;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
} catch (e) {
|
|
119
|
-
// Ignore localStorage errors
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Then try props
|
|
124
|
-
if (propsBackgroundColors) {
|
|
125
|
-
return propsBackgroundColors;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Fallback to window global
|
|
129
|
-
if (typeof window !== 'undefined' && (window as any).__JHITS_PLUGIN_PROPS__) {
|
|
130
|
-
const pluginProps = (window as any).__JHITS_PLUGIN_PROPS__['plugin-blog'];
|
|
131
|
-
if (pluginProps?.backgroundColors) {
|
|
132
|
-
return pluginProps.backgroundColors as { light: string; dark?: string };
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return undefined;
|
|
137
|
-
}, [propsBackgroundColors]);
|
|
44
|
+
const { subPath, siteId, locale } = props;
|
|
138
45
|
|
|
46
|
+
// Resolve configuration from multiple sources (Props, Window, Storage)
|
|
47
|
+
const config = useMemo(() => resolvePluginConfig(props), [props]);
|
|
139
48
|
const route = subPath[0] || 'posts';
|
|
140
49
|
|
|
141
|
-
// Validate hero block configuration
|
|
142
|
-
useHeroBlockValidation(route, customBlocks,
|
|
50
|
+
// Validate hero block configuration
|
|
51
|
+
useHeroBlockValidation(route, config.customBlocks, props.customBlocks);
|
|
143
52
|
|
|
144
|
-
//
|
|
145
|
-
const heroBlockDefinition = useMemo(() => {
|
|
146
|
-
const needsHeroBlock = route === 'editor' || route === 'new' || route === 'preview';
|
|
147
|
-
return needsHeroBlock ? findHeroBlock(customBlocks) : undefined;
|
|
148
|
-
}, [customBlocks, route]);
|
|
149
|
-
|
|
150
|
-
// Listen for config updates from settings screen
|
|
53
|
+
// Listen for config updates from settings
|
|
151
54
|
useEffect(() => {
|
|
152
55
|
if (typeof window === 'undefined') return;
|
|
153
|
-
|
|
154
|
-
const handleConfigUpdate = () => {
|
|
155
|
-
// Reload page to apply changes (simplest way to ensure all components pick up new values)
|
|
156
|
-
window.location.reload();
|
|
157
|
-
};
|
|
158
|
-
|
|
56
|
+
const handleConfigUpdate = () => window.location.reload();
|
|
159
57
|
window.addEventListener('blog-plugin-config-updated', handleConfigUpdate as EventListener);
|
|
160
|
-
return () =>
|
|
161
|
-
window.removeEventListener('blog-plugin-config-updated', handleConfigUpdate as EventListener);
|
|
162
|
-
};
|
|
58
|
+
return () => window.removeEventListener('blog-plugin-config-updated', handleConfigUpdate as EventListener);
|
|
163
59
|
}, []);
|
|
164
|
-
|
|
165
|
-
if (heroBlockDefinition !== undefined) {
|
|
166
|
-
console.log('[BlogPlugin] Hero block definition:', heroBlockDefinition ? 'found' : 'not found (REQUIRED)');
|
|
167
|
-
}
|
|
168
60
|
|
|
169
|
-
//
|
|
61
|
+
// Helper to render editor with provider
|
|
62
|
+
const renderEditor = (postId?: string) => (
|
|
63
|
+
<EditorProvider
|
|
64
|
+
customBlocks={config.customBlocks}
|
|
65
|
+
darkMode={config.darkMode}
|
|
66
|
+
backgroundColors={config.backgroundColors}
|
|
67
|
+
translations={config.translations}
|
|
68
|
+
onSave={async (state, heroBlock) => {
|
|
69
|
+
const originalSlug = postId || state.slug || state.postId;
|
|
70
|
+
if (!originalSlug && route !== 'new') throw new Error('No post identifier');
|
|
71
|
+
|
|
72
|
+
const apiData = editorStateToAPI(state, undefined, heroBlock);
|
|
73
|
+
const isNew = route === 'new';
|
|
74
|
+
const url = isNew ? '/api/plugin-blog/new' : `/api/plugin-blog/${originalSlug}`;
|
|
75
|
+
|
|
76
|
+
const response = await fetch(`${url}?language=${state.currentLanguage || locale}`, {
|
|
77
|
+
method: isNew ? 'POST' : 'PUT',
|
|
78
|
+
headers: { 'Content-Type': 'application/json' },
|
|
79
|
+
credentials: 'include',
|
|
80
|
+
body: JSON.stringify(apiData),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (!response.ok) throw new Error('Save failed');
|
|
84
|
+
const result = await response.json();
|
|
85
|
+
if (result.slug && result.slug !== originalSlug) {
|
|
86
|
+
window.history.replaceState(null, '', `/dashboard/blog/editor/${result.slug}`);
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
<CanvasEditorView
|
|
92
|
+
postId={postId || undefined}
|
|
93
|
+
siteId={siteId}
|
|
94
|
+
locale={locale}
|
|
95
|
+
LayoutWrapper={config.LayoutWrapper}
|
|
96
|
+
/>
|
|
97
|
+
</EditorProvider>
|
|
98
|
+
);
|
|
99
|
+
|
|
170
100
|
switch (route) {
|
|
171
|
-
case 'posts':
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
case '
|
|
175
|
-
|
|
176
|
-
return (
|
|
177
|
-
<EditorProvider
|
|
178
|
-
customBlocks={customBlocks}
|
|
179
|
-
darkMode={darkMode}
|
|
180
|
-
backgroundColors={backgroundColors}
|
|
181
|
-
onSave={async (state, heroBlock) => {
|
|
182
|
-
// Save to API - update existing post
|
|
183
|
-
// Use the route postId (original slug) to identify which blog to update
|
|
184
|
-
// If route postId is missing, use state.slug or state.postId as fallback
|
|
185
|
-
const originalSlug = postId || state.slug || state.postId;
|
|
186
|
-
if (!originalSlug) {
|
|
187
|
-
throw new Error('Cannot save: no post identifier available. Please reload the page.');
|
|
188
|
-
}
|
|
189
|
-
const language = state.currentLanguage || locale;
|
|
190
|
-
console.log('[BlogPlugin] Saving post with slug:', originalSlug, 'language:', language);
|
|
191
|
-
const apiData = editorStateToAPI(state, undefined, heroBlock);
|
|
192
|
-
const response = await fetch(`/api/plugin-blog/${originalSlug}?language=${language}`, {
|
|
193
|
-
method: 'PUT',
|
|
194
|
-
headers: { 'Content-Type': 'application/json' },
|
|
195
|
-
credentials: 'include', // Include cookies for authentication
|
|
196
|
-
body: JSON.stringify(apiData),
|
|
197
|
-
});
|
|
198
|
-
if (!response.ok) {
|
|
199
|
-
const error = await response.json();
|
|
200
|
-
console.error('[BlogPlugin] Save failed:', {
|
|
201
|
-
status: response.status,
|
|
202
|
-
statusText: response.statusText,
|
|
203
|
-
error,
|
|
204
|
-
missingFields: error.missingFields,
|
|
205
|
-
});
|
|
206
|
-
// Provide more detailed error message if available
|
|
207
|
-
const errorMessage = error.message || error.error || 'Failed to save post';
|
|
208
|
-
const missingFieldsMsg = error.missingFields && error.missingFields.length > 0
|
|
209
|
-
? ` Missing: ${error.missingFields.join(', ')}`
|
|
210
|
-
: '';
|
|
211
|
-
throw new Error(errorMessage + missingFieldsMsg);
|
|
212
|
-
}
|
|
213
|
-
const result = await response.json();
|
|
214
|
-
// If the slug changed, update the URL
|
|
215
|
-
if (result.slug && result.slug !== originalSlug) {
|
|
216
|
-
window.history.replaceState(null, '', `/dashboard/blog/editor/${result.slug}`);
|
|
217
|
-
}
|
|
218
|
-
return result;
|
|
219
|
-
}}
|
|
220
|
-
>
|
|
221
|
-
<CanvasEditorView postId={postId} siteId={siteId} locale={locale} darkMode={darkMode} backgroundColors={backgroundColors} />
|
|
222
|
-
</EditorProvider>
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
case 'new':
|
|
226
|
-
return (
|
|
227
|
-
<EditorProvider
|
|
228
|
-
customBlocks={customBlocks}
|
|
229
|
-
darkMode={darkMode}
|
|
230
|
-
backgroundColors={backgroundColors}
|
|
231
|
-
onSave={async (state) => {
|
|
232
|
-
// Save to API - create new post
|
|
233
|
-
const language = state.currentLanguage || locale;
|
|
234
|
-
const apiData = editorStateToAPI(state);
|
|
235
|
-
const response = await fetch(`/api/plugin-blog/new?language=${language}`, {
|
|
236
|
-
method: 'POST',
|
|
237
|
-
headers: { 'Content-Type': 'application/json' },
|
|
238
|
-
credentials: 'include', // Include cookies for authentication
|
|
239
|
-
body: JSON.stringify(apiData),
|
|
240
|
-
});
|
|
241
|
-
if (!response.ok) {
|
|
242
|
-
const error = await response.json();
|
|
243
|
-
throw new Error(error.message || 'Failed to create post');
|
|
244
|
-
}
|
|
245
|
-
const result = await response.json();
|
|
246
|
-
// Update the URL to the new post's slug
|
|
247
|
-
if (result.slug) {
|
|
248
|
-
window.history.replaceState(null, '', `/dashboard/blog/editor/${result.slug}`);
|
|
249
|
-
}
|
|
250
|
-
return result;
|
|
251
|
-
}}
|
|
252
|
-
>
|
|
253
|
-
<CanvasEditorView siteId={siteId} locale={locale} darkMode={darkMode} backgroundColors={backgroundColors} />
|
|
254
|
-
</EditorProvider>
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
case 'seo':
|
|
258
|
-
const seoPostId = subPath[1];
|
|
259
|
-
return <SlugSEOManagerView postId={seoPostId} siteId={siteId} locale={locale} />;
|
|
260
|
-
|
|
261
|
-
case 'preview':
|
|
262
|
-
const previewPostId = subPath[1];
|
|
263
|
-
return <PreviewBridgeView postId={previewPostId} siteId={siteId} locale={locale} />;
|
|
264
|
-
|
|
101
|
+
case 'posts': return <PostManagerView siteId={siteId} locale={locale} />;
|
|
102
|
+
case 'editor': return renderEditor(subPath[1]);
|
|
103
|
+
case 'new': return renderEditor();
|
|
104
|
+
case 'seo': return <SlugSEOManagerView postId={subPath[1]} siteId={siteId} locale={locale} />;
|
|
105
|
+
case 'preview': return <PreviewBridgeView postId={subPath[1]} siteId={siteId} locale={locale} />;
|
|
265
106
|
case 'settings':
|
|
266
|
-
case 'install':
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
default:
|
|
270
|
-
return <PostManagerView siteId={siteId} locale={locale} />;
|
|
107
|
+
case 'install': return <SettingsView siteId={siteId} locale={locale} />;
|
|
108
|
+
default: return <PostManagerView siteId={siteId} locale={locale} />;
|
|
271
109
|
}
|
|
272
110
|
}
|
|
273
111
|
|
|
274
|
-
|
|
275
|
-
// Export for use as default
|
|
276
112
|
export { BlogPlugin as Index };
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
export type {
|
|
280
|
-
Block,
|
|
281
|
-
BlockTypeDefinition,
|
|
282
|
-
ClientBlockDefinition,
|
|
283
|
-
RichTextFormattingConfig,
|
|
284
|
-
BlockEditProps,
|
|
285
|
-
BlockPreviewProps,
|
|
286
|
-
IBlockComponent,
|
|
287
|
-
} from './types';
|
|
288
|
-
|
|
289
|
-
// Export post types
|
|
290
|
-
export type {
|
|
291
|
-
SEOMetadata,
|
|
292
|
-
PublicationData,
|
|
293
|
-
PostStatus,
|
|
294
|
-
PostMetadata,
|
|
295
|
-
BlogPost,
|
|
296
|
-
PostListItem,
|
|
297
|
-
PostFilterOptions,
|
|
298
|
-
BlogPostLanguageContent,
|
|
299
|
-
BlogPostLanguages,
|
|
300
|
-
} from './types/post';
|
|
301
|
-
|
|
302
|
-
// Export initialization utility for easy setup
|
|
113
|
+
// ... Re-export other symbols as needed (keeping existing exports from original file)
|
|
114
|
+
export type { Block, ClientBlockDefinition, BlockEditProps, BlockPreviewProps, BlockTypeDefinition, IBlockComponent } from './types';
|
|
115
|
+
export type { SEOMetadata, PublicationData, BlogPost, PostListItem, PostStatus } from './types';
|
|
303
116
|
export { initBlogPlugin } from './init';
|
|
304
|
-
export type { BlogPluginConfig } from './init';
|
|
305
|
-
|
|
306
|
-
// Export rich text components for client applications
|
|
307
117
|
export { RichTextEditor, RichTextPreview } from './lib/rich-text';
|
|
308
|
-
export
|
|
309
|
-
|
|
310
|
-
// Export hooks for client applications
|
|
311
|
-
export { useBlogs, useBlog } from './hooks';
|
|
312
|
-
export type { UseBlogsOptions, UseBlogsResult, UseBlogOptions, UseBlogResult } from './hooks';
|
|
313
|
-
|
|
314
|
-
// Export client utilities
|
|
315
|
-
export { fetchBlogs, fetchBlog } from './utils/client';
|
|
316
|
-
export type { FetchBlogsOptions, FetchBlogsResult, FetchBlogOptions } from './utils/client';
|
|
317
|
-
|
|
318
|
-
// Export block rendering components
|
|
319
|
-
export { BlockRenderer, BlocksRenderer } from './lib/blocks/BlockRenderer';
|
|
320
|
-
|
|
321
|
-
// Export block registry
|
|
118
|
+
export { useBlogs, useBlog, useCategories } from './hooks';
|
|
322
119
|
export { blockRegistry } from './registry';
|
|
323
|
-
|
|
324
|
-
// Export layout block registration
|
|
325
|
-
export { registerLayoutBlocks } from './lib/layouts/registerLayoutBlocks';
|
|
326
|
-
|
|
327
|
-
// Export config storage utilities
|
|
328
|
-
export { getPluginConfig, savePluginConfig } from './lib/config-storage';
|
|
329
|
-
|
|
330
|
-
// Export editor state management
|
|
331
120
|
export { EditorProvider, useEditor } from './state/EditorContext';
|
|
332
|
-
export type { EditorProviderProps
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
export {
|
|
336
|
-
|
|
337
|
-
// Note: API handlers are server-only and exported from ./index.ts (server entry point)
|
|
338
|
-
// They are NOT exported here to prevent client/server context mixing
|
|
339
|
-
|
|
121
|
+
export type { EditorProviderProps } from './state/EditorContext';
|
|
122
|
+
export type { EditorState, EditorContextValue } from './state/types';
|
|
123
|
+
export { BlockRenderer, BlocksRenderer } from './lib/blocks/BlockRenderer';
|
|
124
|
+
export { ColumnsPreview } from './lib/layouts/blocks/ColumnsBlock';
|
|
125
|
+
export { registerLayoutBlocks } from './lib/layouts/registerLayoutBlocks';
|
package/src/init.tsx
CHANGED
|
@@ -32,17 +32,29 @@ export interface BlogPluginConfig {
|
|
|
32
32
|
/** Background color for dark mode (optional) - CSS color value (hex, rgb, or named color) */
|
|
33
33
|
dark?: string;
|
|
34
34
|
};
|
|
35
|
-
|
|
35
|
+
/** Optional layout wrapper for 1:1 preview (injected by client app) */
|
|
36
|
+
LayoutWrapper?: React.ComponentType<{
|
|
37
|
+
children: React.ReactNode;
|
|
38
|
+
header?: React.ReactNode;
|
|
39
|
+
footer?: React.ReactNode;
|
|
40
|
+
title?: string;
|
|
41
|
+
excerpt?: string;
|
|
42
|
+
category?: string;
|
|
43
|
+
date?: string;
|
|
44
|
+
thumbnail?: string;
|
|
45
|
+
isPreview?: boolean;
|
|
46
|
+
}>;
|
|
47
|
+
}
|
|
36
48
|
|
|
37
|
-
/**
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
export function initBlogPlugin(config: BlogPluginConfig): void {
|
|
49
|
+
/**
|
|
50
|
+
* Initialize the blog plugin with client configuration
|
|
51
|
+
*
|
|
52
|
+
* This function sets up the window global that the plugin reads from automatically.
|
|
53
|
+
* Call this once when your app loads, before the plugin is rendered.
|
|
54
|
+
*
|
|
55
|
+
* @param config - Blog plugin configuration (customBlocks, darkMode, etc.)
|
|
56
|
+
*/
|
|
57
|
+
export function initBlogPlugin(config: BlogPluginConfig): void {
|
|
46
58
|
if (typeof window === 'undefined') {
|
|
47
59
|
// Server-side: no-op
|
|
48
60
|
return;
|
|
@@ -58,6 +70,7 @@ export function initBlogPlugin(config: BlogPluginConfig): void {
|
|
|
58
70
|
customBlocks: config.customBlocks || [],
|
|
59
71
|
darkMode: config.darkMode !== undefined ? config.darkMode : true, // Default to true
|
|
60
72
|
backgroundColors: config.backgroundColors || undefined,
|
|
73
|
+
LayoutWrapper: config.LayoutWrapper || undefined,
|
|
61
74
|
};
|
|
62
|
-
}
|
|
75
|
+
}
|
|
63
76
|
|