@jhits/plugin-blog 0.0.8 → 0.0.10
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 +8 -0
- package/dist/api/categories.d.ts.map +1 -0
- package/dist/api/categories.js +30 -0
- package/dist/api/check-title.d.ts +8 -0
- package/dist/api/check-title.d.ts.map +1 -0
- package/dist/api/check-title.js +47 -0
- package/dist/api/config-handler.d.ts +21 -0
- package/dist/api/config-handler.d.ts.map +1 -0
- package/dist/api/config-handler.js +46 -0
- package/dist/api/handler.d.ts +42 -0
- package/dist/api/handler.d.ts.map +1 -0
- package/dist/api/handler.js +331 -0
- package/dist/api/index.d.ts +12 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +12 -0
- package/dist/api/route.d.ts +50 -0
- package/dist/api/route.d.ts.map +1 -0
- package/dist/api/route.js +69 -0
- package/dist/api/router.d.ts +27 -0
- package/dist/api/router.d.ts.map +1 -0
- package/dist/api/router.js +98 -0
- package/dist/api-server.d.ts +9 -0
- package/dist/api-server.d.ts.map +1 -0
- package/dist/api-server.js +9 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +156 -0
- package/dist/hooks/index.d.ts +8 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/useBlog.d.ts +31 -0
- package/dist/hooks/useBlog.d.ts.map +1 -0
- package/dist/hooks/useBlog.js +57 -0
- package/dist/hooks/useBlogs.d.ts +39 -0
- package/dist/hooks/useBlogs.d.ts.map +1 -0
- package/dist/hooks/useBlogs.js +82 -0
- package/dist/hooks/useCategories.d.ts +9 -0
- package/dist/hooks/useCategories.d.ts.map +1 -0
- package/dist/hooks/useCategories.js +70 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +228 -0
- package/dist/index.server.d.ts +12 -0
- package/dist/index.server.d.ts.map +1 -0
- package/dist/index.server.js +10 -0
- package/dist/init.d.ts +40 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +41 -0
- package/dist/lib/blocks/BlockRenderer.d.ts +54 -0
- package/dist/lib/blocks/BlockRenderer.d.ts.map +1 -0
- package/dist/lib/blocks/BlockRenderer.js +54 -0
- package/dist/lib/blocks/index.d.ts +5 -0
- package/dist/lib/blocks/index.d.ts.map +1 -0
- package/dist/lib/blocks/index.js +4 -0
- package/dist/lib/config-storage.d.ts +30 -0
- package/dist/lib/config-storage.d.ts.map +1 -0
- package/dist/lib/config-storage.js +31 -0
- package/dist/lib/index.d.ts +8 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +7 -0
- package/dist/lib/layouts/blocks/ColumnsBlock.d.ts +25 -0
- package/dist/lib/layouts/blocks/ColumnsBlock.d.ts.map +1 -0
- package/dist/lib/layouts/blocks/ColumnsBlock.js +186 -0
- package/dist/lib/layouts/blocks/SectionBlock.d.ts +25 -0
- package/dist/lib/layouts/blocks/SectionBlock.d.ts.map +1 -0
- package/dist/lib/layouts/blocks/SectionBlock.js +44 -0
- package/dist/lib/layouts/blocks/index.d.ts +7 -0
- package/dist/lib/layouts/blocks/index.d.ts.map +1 -0
- package/dist/lib/layouts/blocks/index.js +6 -0
- package/dist/lib/layouts/index.d.ts +23 -0
- package/dist/lib/layouts/index.d.ts.map +1 -0
- package/dist/lib/layouts/index.js +45 -0
- package/dist/lib/layouts/registerLayoutBlocks.d.ts +9 -0
- package/dist/lib/layouts/registerLayoutBlocks.d.ts.map +1 -0
- package/dist/lib/layouts/registerLayoutBlocks.js +60 -0
- package/dist/lib/mappers/apiMapper.d.ts +66 -0
- package/dist/lib/mappers/apiMapper.d.ts.map +1 -0
- package/dist/lib/mappers/apiMapper.js +188 -0
- package/dist/lib/migration/index.d.ts +5 -0
- package/dist/lib/migration/index.d.ts.map +1 -0
- package/dist/lib/migration/index.js +4 -0
- package/dist/lib/migration/mapper.d.ts +37 -0
- package/dist/lib/migration/mapper.d.ts.map +1 -0
- package/dist/lib/migration/mapper.js +98 -0
- package/dist/lib/rich-text/RichTextEditor.d.ts +45 -0
- package/dist/lib/rich-text/RichTextEditor.d.ts.map +1 -0
- package/dist/lib/rich-text/RichTextEditor.js +556 -0
- package/dist/lib/rich-text/RichTextPreview.d.ts +16 -0
- package/dist/lib/rich-text/RichTextPreview.d.ts.map +1 -0
- package/dist/lib/rich-text/RichTextPreview.js +144 -0
- package/dist/lib/rich-text/index.d.ts +9 -0
- package/dist/lib/rich-text/index.d.ts.map +1 -0
- package/dist/lib/rich-text/index.js +6 -0
- package/dist/lib/utils/blockHelpers.d.ts +23 -0
- package/dist/lib/utils/blockHelpers.d.ts.map +1 -0
- package/dist/lib/utils/blockHelpers.js +65 -0
- package/dist/lib/utils/configValidation.d.ts +23 -0
- package/dist/lib/utils/configValidation.d.ts.map +1 -0
- package/dist/lib/utils/configValidation.js +111 -0
- package/dist/lib/utils/index.d.ts +7 -0
- package/dist/lib/utils/index.d.ts.map +1 -0
- package/dist/lib/utils/index.js +6 -0
- package/dist/lib/utils/slugify.d.ts +25 -0
- package/dist/lib/utils/slugify.d.ts.map +1 -0
- package/dist/lib/utils/slugify.js +65 -0
- package/dist/registry/BlockRegistry.d.ts +62 -0
- package/dist/registry/BlockRegistry.d.ts.map +1 -0
- package/dist/registry/BlockRegistry.js +112 -0
- package/dist/registry/index.d.ts +6 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +4 -0
- package/dist/state/EditorContext.d.ts +45 -0
- package/dist/state/EditorContext.d.ts.map +1 -0
- package/dist/state/EditorContext.js +215 -0
- package/dist/state/index.d.ts +7 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +6 -0
- package/dist/state/reducer.d.ts +11 -0
- package/dist/state/reducer.d.ts.map +1 -0
- package/dist/state/reducer.js +599 -0
- package/dist/state/types.d.ts +162 -0
- package/dist/state/types.d.ts.map +1 -0
- package/dist/state/types.js +27 -0
- package/dist/types/block.d.ts +221 -0
- package/dist/types/block.d.ts.map +1 -0
- package/dist/types/block.js +6 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/post.d.ts +136 -0
- package/dist/types/post.d.ts.map +1 -0
- package/dist/types/post.js +5 -0
- package/dist/utils/client.d.ts +48 -0
- package/dist/utils/client.d.ts.map +1 -0
- package/dist/utils/client.js +77 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +5 -0
- package/dist/views/CanvasEditor/BlockWrapper.d.ts +16 -0
- package/dist/views/CanvasEditor/BlockWrapper.d.ts.map +1 -0
- package/dist/views/CanvasEditor/BlockWrapper.js +285 -0
- package/dist/views/CanvasEditor/CanvasEditorView.d.ts +14 -0
- package/dist/views/CanvasEditor/CanvasEditorView.d.ts.map +1 -0
- package/dist/views/CanvasEditor/CanvasEditorView.js +215 -0
- package/dist/views/CanvasEditor/EditorBody.d.ts +22 -0
- package/dist/views/CanvasEditor/EditorBody.d.ts.map +1 -0
- package/dist/views/CanvasEditor/EditorBody.js +505 -0
- package/dist/views/CanvasEditor/EditorHeader.d.ts +18 -0
- package/dist/views/CanvasEditor/EditorHeader.d.ts.map +1 -0
- package/dist/views/CanvasEditor/EditorHeader.js +101 -0
- package/dist/views/CanvasEditor/LayoutContainer.d.ts +17 -0
- package/dist/views/CanvasEditor/LayoutContainer.d.ts.map +1 -0
- package/dist/views/CanvasEditor/LayoutContainer.js +222 -0
- package/dist/views/CanvasEditor/SaveConfirmationModal.d.ts +13 -0
- package/dist/views/CanvasEditor/SaveConfirmationModal.d.ts.map +1 -0
- package/dist/views/CanvasEditor/SaveConfirmationModal.js +78 -0
- package/dist/views/CanvasEditor/components/CustomBlockItem.d.ts +14 -0
- package/dist/views/CanvasEditor/components/CustomBlockItem.d.ts.map +1 -0
- package/dist/views/CanvasEditor/components/CustomBlockItem.js +44 -0
- package/dist/views/CanvasEditor/components/EditorCanvas.d.ts +29 -0
- package/dist/views/CanvasEditor/components/EditorCanvas.d.ts.map +1 -0
- package/dist/views/CanvasEditor/components/EditorCanvas.js +32 -0
- package/dist/views/CanvasEditor/components/EditorLibrary.d.ts +7 -0
- package/dist/views/CanvasEditor/components/EditorLibrary.d.ts.map +1 -0
- package/dist/views/CanvasEditor/components/EditorLibrary.js +25 -0
- package/dist/views/CanvasEditor/components/EditorSidebar.d.ts +13 -0
- package/dist/views/CanvasEditor/components/EditorSidebar.d.ts.map +1 -0
- package/dist/views/CanvasEditor/components/EditorSidebar.js +19 -0
- package/dist/views/CanvasEditor/components/ErrorBanner.d.ts +6 -0
- package/dist/views/CanvasEditor/components/ErrorBanner.d.ts.map +1 -0
- package/dist/views/CanvasEditor/components/ErrorBanner.js +8 -0
- package/dist/views/CanvasEditor/components/FeaturedMediaSection.d.ts +25 -0
- package/dist/views/CanvasEditor/components/FeaturedMediaSection.d.ts.map +1 -0
- package/dist/views/CanvasEditor/components/FeaturedMediaSection.js +199 -0
- package/dist/views/CanvasEditor/components/LibraryItem.d.ts +14 -0
- package/dist/views/CanvasEditor/components/LibraryItem.d.ts.map +1 -0
- package/dist/views/CanvasEditor/components/LibraryItem.js +43 -0
- package/dist/views/CanvasEditor/components/PrivacySettingsSection.d.ts +15 -0
- package/dist/views/CanvasEditor/components/PrivacySettingsSection.d.ts.map +1 -0
- package/dist/views/CanvasEditor/components/PrivacySettingsSection.js +70 -0
- package/dist/views/CanvasEditor/components/index.d.ts +21 -0
- package/dist/views/CanvasEditor/components/index.d.ts.map +1 -0
- package/dist/views/CanvasEditor/components/index.js +12 -0
- package/dist/views/CanvasEditor/hooks/index.d.ts +10 -0
- package/dist/views/CanvasEditor/hooks/index.d.ts.map +1 -0
- package/dist/views/CanvasEditor/hooks/index.js +9 -0
- package/dist/views/CanvasEditor/hooks/useHeroBlock.d.ts +8 -0
- package/dist/views/CanvasEditor/hooks/useHeroBlock.d.ts.map +1 -0
- package/dist/views/CanvasEditor/hooks/useHeroBlock.js +90 -0
- package/dist/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts +3 -0
- package/dist/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts.map +1 -0
- package/dist/views/CanvasEditor/hooks/useKeyboardShortcuts.js +119 -0
- package/dist/views/CanvasEditor/hooks/usePostLoader.d.ts +5 -0
- package/dist/views/CanvasEditor/hooks/usePostLoader.d.ts.map +1 -0
- package/dist/views/CanvasEditor/hooks/usePostLoader.js +32 -0
- package/dist/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts +2 -0
- package/dist/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts.map +1 -0
- package/dist/views/CanvasEditor/hooks/useRegisteredBlocks.js +47 -0
- package/dist/views/CanvasEditor/hooks/useUnsavedChanges.d.ts +25 -0
- package/dist/views/CanvasEditor/hooks/useUnsavedChanges.d.ts.map +1 -0
- package/dist/views/CanvasEditor/hooks/useUnsavedChanges.js +285 -0
- package/dist/views/CanvasEditor/index.d.ts +16 -0
- package/dist/views/CanvasEditor/index.d.ts.map +1 -0
- package/dist/views/CanvasEditor/index.js +9 -0
- package/dist/views/PostManager/EmptyState.d.ts +10 -0
- package/dist/views/PostManager/EmptyState.d.ts.map +1 -0
- package/dist/views/PostManager/EmptyState.js +12 -0
- package/dist/views/PostManager/PostActionsMenu.d.ts +12 -0
- package/dist/views/PostManager/PostActionsMenu.d.ts.map +1 -0
- package/dist/views/PostManager/PostActionsMenu.js +58 -0
- package/dist/views/PostManager/PostCards.d.ts +15 -0
- package/dist/views/PostManager/PostCards.d.ts.map +1 -0
- package/dist/views/PostManager/PostCards.js +77 -0
- package/dist/views/PostManager/PostFilters.d.ts +16 -0
- package/dist/views/PostManager/PostFilters.d.ts.map +1 -0
- package/dist/views/PostManager/PostFilters.js +10 -0
- package/dist/views/PostManager/PostManagerView.d.ts +11 -0
- package/dist/views/PostManager/PostManagerView.d.ts.map +1 -0
- package/dist/views/PostManager/PostManagerView.js +179 -0
- package/dist/views/PostManager/PostStats.d.ts +11 -0
- package/dist/views/PostManager/PostStats.d.ts.map +1 -0
- package/dist/views/PostManager/PostStats.js +46 -0
- package/dist/views/PostManager/PostTable.d.ts +15 -0
- package/dist/views/PostManager/PostTable.d.ts.map +1 -0
- package/dist/views/PostManager/PostTable.js +77 -0
- package/dist/views/PostManager/index.d.ts +12 -0
- package/dist/views/PostManager/index.d.ts.map +1 -0
- package/dist/views/PostManager/index.js +11 -0
- package/dist/views/Preview/PreviewBridgeView.d.ts +12 -0
- package/dist/views/Preview/PreviewBridgeView.d.ts.map +1 -0
- package/dist/views/Preview/PreviewBridgeView.js +11 -0
- package/dist/views/Preview/index.d.ts +6 -0
- package/dist/views/Preview/index.d.ts.map +1 -0
- package/dist/views/Preview/index.js +4 -0
- package/dist/views/Settings/SettingsView.d.ts +10 -0
- package/dist/views/Settings/SettingsView.d.ts.map +1 -0
- package/dist/views/Settings/SettingsView.js +113 -0
- package/dist/views/Settings/index.d.ts +6 -0
- package/dist/views/Settings/index.d.ts.map +1 -0
- package/dist/views/Settings/index.js +4 -0
- package/dist/views/SlugSEO/SlugSEOManagerView.d.ts +12 -0
- package/dist/views/SlugSEO/SlugSEOManagerView.d.ts.map +1 -0
- package/dist/views/SlugSEO/SlugSEOManagerView.js +11 -0
- package/dist/views/SlugSEO/index.d.ts +6 -0
- package/dist/views/SlugSEO/index.d.ts.map +1 -0
- package/dist/views/SlugSEO/index.js +4 -0
- package/package.json +4 -4
- package/src/hooks/index.d.ts +8 -0
- package/src/hooks/index.d.ts.map +1 -0
- package/src/hooks/index.js +7 -0
- package/src/hooks/useBlog.d.ts +31 -0
- package/src/hooks/useBlog.d.ts.map +1 -0
- package/src/hooks/useBlog.js +57 -0
- package/src/hooks/useBlogs.d.ts +39 -0
- package/src/hooks/useBlogs.d.ts.map +1 -0
- package/src/hooks/useBlogs.js +82 -0
- package/src/hooks/useCategories.d.ts +9 -0
- package/src/hooks/useCategories.d.ts.map +1 -0
- package/src/hooks/useCategories.js +70 -0
- package/src/index.d.ts +55 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.js +228 -0
- package/src/init.d.ts +40 -0
- package/src/init.d.ts.map +1 -0
- package/src/init.js +41 -0
- package/src/lib/blocks/BlockRenderer.d.ts +54 -0
- package/src/lib/blocks/BlockRenderer.d.ts.map +1 -0
- package/src/lib/blocks/BlockRenderer.js +54 -0
- package/src/lib/config-storage.d.ts +30 -0
- package/src/lib/config-storage.d.ts.map +1 -0
- package/src/lib/config-storage.js +31 -0
- package/src/lib/layouts/blocks/ColumnsBlock.d.ts +25 -0
- package/src/lib/layouts/blocks/ColumnsBlock.d.ts.map +1 -0
- package/src/lib/layouts/blocks/ColumnsBlock.js +182 -0
- package/src/lib/layouts/blocks/SectionBlock.d.ts +25 -0
- package/src/lib/layouts/blocks/SectionBlock.d.ts.map +1 -0
- package/src/lib/layouts/blocks/SectionBlock.js +44 -0
- package/src/lib/layouts/index.d.ts +23 -0
- package/src/lib/layouts/index.d.ts.map +1 -0
- package/src/lib/layouts/index.js +45 -0
- package/src/lib/layouts/registerLayoutBlocks.d.ts +9 -0
- package/src/lib/layouts/registerLayoutBlocks.d.ts.map +1 -0
- package/src/lib/layouts/registerLayoutBlocks.js +60 -0
- package/src/lib/mappers/apiMapper.d.ts +66 -0
- package/src/lib/mappers/apiMapper.d.ts.map +1 -0
- package/src/lib/mappers/apiMapper.js +191 -0
- package/src/lib/rich-text/RichTextEditor.d.ts +45 -0
- package/src/lib/rich-text/RichTextEditor.d.ts.map +1 -0
- package/src/lib/rich-text/RichTextEditor.js +564 -0
- package/src/lib/rich-text/RichTextPreview.d.ts +16 -0
- package/src/lib/rich-text/RichTextPreview.d.ts.map +1 -0
- package/src/lib/rich-text/RichTextPreview.js +144 -0
- package/src/lib/rich-text/index.d.ts +9 -0
- package/src/lib/rich-text/index.d.ts.map +1 -0
- package/src/lib/rich-text/index.js +6 -0
- package/src/lib/utils/blockHelpers.d.ts +23 -0
- package/src/lib/utils/blockHelpers.d.ts.map +1 -0
- package/src/lib/utils/blockHelpers.js +65 -0
- package/src/lib/utils/configValidation.d.ts +23 -0
- package/src/lib/utils/configValidation.d.ts.map +1 -0
- package/src/lib/utils/configValidation.js +113 -0
- package/src/registry/BlockRegistry.d.ts +62 -0
- package/src/registry/BlockRegistry.d.ts.map +1 -0
- package/src/registry/BlockRegistry.js +112 -0
- package/src/registry/index.d.ts +6 -0
- package/src/registry/index.d.ts.map +1 -0
- package/src/registry/index.js +4 -0
- package/src/state/EditorContext.d.ts +45 -0
- package/src/state/EditorContext.d.ts.map +1 -0
- package/src/state/EditorContext.js +215 -0
- package/src/state/index.d.ts +7 -0
- package/src/state/index.d.ts.map +1 -0
- package/src/state/index.js +6 -0
- package/src/state/reducer.d.ts +11 -0
- package/src/state/reducer.d.ts.map +1 -0
- package/src/state/reducer.js +443 -0
- package/src/state/types.d.ts +162 -0
- package/src/state/types.d.ts.map +1 -0
- package/src/state/types.js +27 -0
- package/src/types/block.d.ts +221 -0
- package/src/types/block.d.ts.map +1 -0
- package/src/types/block.js +6 -0
- package/src/types/index.d.ts +8 -0
- package/src/types/index.d.ts.map +1 -0
- package/src/types/index.js +5 -0
- package/src/types/post.d.ts +136 -0
- package/src/types/post.d.ts.map +1 -0
- package/src/types/post.js +5 -0
- package/src/utils/client.d.ts +48 -0
- package/src/utils/client.d.ts.map +1 -0
- package/src/utils/client.js +77 -0
- package/src/views/CanvasEditor/BlockWrapper.d.ts +16 -0
- package/src/views/CanvasEditor/BlockWrapper.d.ts.map +1 -0
- package/src/views/CanvasEditor/BlockWrapper.js +276 -0
- package/src/views/CanvasEditor/CanvasEditorView.d.ts +14 -0
- package/src/views/CanvasEditor/CanvasEditorView.d.ts.map +1 -0
- package/src/views/CanvasEditor/CanvasEditorView.js +209 -0
- package/src/views/CanvasEditor/EditorBody.d.ts +22 -0
- package/src/views/CanvasEditor/EditorBody.d.ts.map +1 -0
- package/src/views/CanvasEditor/EditorBody.js +505 -0
- package/src/views/CanvasEditor/EditorHeader.d.ts +18 -0
- package/src/views/CanvasEditor/EditorHeader.d.ts.map +1 -0
- package/src/views/CanvasEditor/EditorHeader.js +101 -0
- package/src/views/CanvasEditor/LayoutContainer.d.ts +17 -0
- package/src/views/CanvasEditor/LayoutContainer.d.ts.map +1 -0
- package/src/views/CanvasEditor/LayoutContainer.js +222 -0
- package/src/views/CanvasEditor/SaveConfirmationModal.d.ts +13 -0
- package/src/views/CanvasEditor/SaveConfirmationModal.d.ts.map +1 -0
- package/src/views/CanvasEditor/SaveConfirmationModal.js +78 -0
- package/src/views/CanvasEditor/components/CustomBlockItem.d.ts +14 -0
- package/src/views/CanvasEditor/components/CustomBlockItem.d.ts.map +1 -0
- package/src/views/CanvasEditor/components/CustomBlockItem.js +44 -0
- package/src/views/CanvasEditor/components/EditorCanvas.d.ts +29 -0
- package/src/views/CanvasEditor/components/EditorCanvas.d.ts.map +1 -0
- package/src/views/CanvasEditor/components/EditorCanvas.js +32 -0
- package/src/views/CanvasEditor/components/EditorLibrary.d.ts +7 -0
- package/src/views/CanvasEditor/components/EditorLibrary.d.ts.map +1 -0
- package/src/views/CanvasEditor/components/EditorLibrary.js +25 -0
- package/src/views/CanvasEditor/components/EditorSidebar.d.ts +13 -0
- package/src/views/CanvasEditor/components/EditorSidebar.d.ts.map +1 -0
- package/src/views/CanvasEditor/components/EditorSidebar.js +20 -0
- package/src/views/CanvasEditor/components/ErrorBanner.d.ts +6 -0
- package/src/views/CanvasEditor/components/ErrorBanner.d.ts.map +1 -0
- package/src/views/CanvasEditor/components/ErrorBanner.js +8 -0
- package/src/views/CanvasEditor/components/FeaturedMediaSection.d.ts +25 -0
- package/src/views/CanvasEditor/components/FeaturedMediaSection.d.ts.map +1 -0
- package/src/views/CanvasEditor/components/FeaturedMediaSection.js +182 -0
- package/src/views/CanvasEditor/components/LibraryItem.d.ts +14 -0
- package/src/views/CanvasEditor/components/LibraryItem.d.ts.map +1 -0
- package/src/views/CanvasEditor/components/LibraryItem.js +43 -0
- package/src/views/CanvasEditor/components/PrivacySettingsSection.d.ts +15 -0
- package/src/views/CanvasEditor/components/PrivacySettingsSection.d.ts.map +1 -0
- package/src/views/CanvasEditor/components/PrivacySettingsSection.js +63 -0
- package/src/views/CanvasEditor/components/index.d.ts +21 -0
- package/src/views/CanvasEditor/components/index.d.ts.map +1 -0
- package/src/views/CanvasEditor/components/index.js +12 -0
- package/src/views/CanvasEditor/hooks/index.d.ts +10 -0
- package/src/views/CanvasEditor/hooks/index.d.ts.map +1 -0
- package/src/views/CanvasEditor/hooks/index.js +9 -0
- package/src/views/CanvasEditor/hooks/useHeroBlock.d.ts +8 -0
- package/src/views/CanvasEditor/hooks/useHeroBlock.d.ts.map +1 -0
- package/src/views/CanvasEditor/hooks/useHeroBlock.js +79 -0
- package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts +3 -0
- package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts.map +1 -0
- package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.js +114 -0
- package/src/views/CanvasEditor/hooks/usePostLoader.d.ts +5 -0
- package/src/views/CanvasEditor/hooks/usePostLoader.d.ts.map +1 -0
- package/src/views/CanvasEditor/hooks/usePostLoader.js +32 -0
- package/src/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts +2 -0
- package/src/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts.map +1 -0
- package/src/views/CanvasEditor/hooks/useRegisteredBlocks.js +47 -0
- package/src/views/CanvasEditor/hooks/useUnsavedChanges.d.ts +25 -0
- package/src/views/CanvasEditor/hooks/useUnsavedChanges.d.ts.map +1 -0
- package/src/views/CanvasEditor/hooks/useUnsavedChanges.js +285 -0
- package/src/views/CanvasEditor/index.d.ts +16 -0
- package/src/views/CanvasEditor/index.d.ts.map +1 -0
- package/src/views/CanvasEditor/index.js +9 -0
- package/src/views/PostManager/EmptyState.d.ts +10 -0
- package/src/views/PostManager/EmptyState.d.ts.map +1 -0
- package/src/views/PostManager/EmptyState.js +12 -0
- package/src/views/PostManager/PostActionsMenu.d.ts +12 -0
- package/src/views/PostManager/PostActionsMenu.d.ts.map +1 -0
- package/src/views/PostManager/PostActionsMenu.js +58 -0
- package/src/views/PostManager/PostCards.d.ts +15 -0
- package/src/views/PostManager/PostCards.d.ts.map +1 -0
- package/src/views/PostManager/PostCards.js +79 -0
- package/src/views/PostManager/PostFilters.d.ts +16 -0
- package/src/views/PostManager/PostFilters.d.ts.map +1 -0
- package/src/views/PostManager/PostFilters.js +10 -0
- package/src/views/PostManager/PostManagerView.d.ts +11 -0
- package/src/views/PostManager/PostManagerView.d.ts.map +1 -0
- package/src/views/PostManager/PostManagerView.js +174 -0
- package/src/views/PostManager/PostStats.d.ts +11 -0
- package/src/views/PostManager/PostStats.d.ts.map +1 -0
- package/src/views/PostManager/PostStats.js +46 -0
- package/src/views/PostManager/PostTable.d.ts +15 -0
- package/src/views/PostManager/PostTable.d.ts.map +1 -0
- package/src/views/PostManager/PostTable.js +79 -0
- package/src/views/PostManager/index.d.ts +12 -0
- package/src/views/PostManager/index.d.ts.map +1 -0
- package/src/views/PostManager/index.js +11 -0
- package/src/views/Preview/PreviewBridgeView.d.ts +12 -0
- package/src/views/Preview/PreviewBridgeView.d.ts.map +1 -0
- package/src/views/Preview/PreviewBridgeView.js +11 -0
- package/src/views/Preview/index.d.ts +6 -0
- package/src/views/Preview/index.d.ts.map +1 -0
- package/src/views/Preview/index.js +4 -0
- package/src/views/Settings/SettingsView.d.ts +10 -0
- package/src/views/Settings/SettingsView.d.ts.map +1 -0
- package/src/views/Settings/SettingsView.js +111 -0
- package/src/views/Settings/index.d.ts +6 -0
- package/src/views/Settings/index.d.ts.map +1 -0
- package/src/views/Settings/index.js +4 -0
- package/src/views/SlugSEO/SlugSEOManagerView.d.ts +12 -0
- package/src/views/SlugSEO/SlugSEOManagerView.d.ts.map +1 -0
- package/src/views/SlugSEO/SlugSEOManagerView.js +11 -0
- package/src/views/SlugSEO/index.d.ts +6 -0
- package/src/views/SlugSEO/index.d.ts.map +1 -0
- package/src/views/SlugSEO/index.js +4 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post Manager View Exports
|
|
3
|
+
*/
|
|
4
|
+
export { PostManagerView } from './PostManagerView';
|
|
5
|
+
// Sub-components (for potential reuse)
|
|
6
|
+
export { PostStats } from './PostStats';
|
|
7
|
+
export { PostFilters } from './PostFilters';
|
|
8
|
+
export { PostTable } from './PostTable';
|
|
9
|
+
export { PostCards } from './PostCards';
|
|
10
|
+
export { EmptyState } from './EmptyState';
|
|
11
|
+
export { PostActionsMenu } from './PostActionsMenu';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preview Bridge View
|
|
3
|
+
* Live preview of blog post
|
|
4
|
+
* Follows dashboard earth-tone design system
|
|
5
|
+
*/
|
|
6
|
+
export interface PreviewBridgeViewProps {
|
|
7
|
+
postId?: string;
|
|
8
|
+
siteId: string;
|
|
9
|
+
locale: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function PreviewBridgeView({ postId, siteId, locale }: PreviewBridgeViewProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=PreviewBridgeView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PreviewBridgeView.d.ts","sourceRoot":"","sources":["../../../src/views/Preview/PreviewBridgeView.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,sBAAsB;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,sBAAsB,2CA6CnF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preview Bridge View
|
|
3
|
+
* Live preview of blog post
|
|
4
|
+
* Follows dashboard earth-tone design system
|
|
5
|
+
*/
|
|
6
|
+
'use client';
|
|
7
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { ExternalLink, RefreshCw } from 'lucide-react';
|
|
9
|
+
export function PreviewBridgeView({ postId, siteId, locale }) {
|
|
10
|
+
return (_jsxs("div", { className: "h-full w-full bg-white dark:bg-neutral-900 flex flex-col", children: [_jsxs("div", { className: "flex items-center justify-between p-6 border-b border-neutral-300 dark:border-neutral-700 bg-neutral-100 dark:bg-neutral-800/50", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-xl font-black text-neutral-950 dark:text-white uppercase tracking-tighter", children: "Preview" }), _jsx("p", { className: "text-xs text-neutral-500 dark:text-neutral-400", children: postId ? `Previewing post: ${postId}` : 'Live preview of your post' })] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsxs("button", { className: "inline-flex items-center gap-2 px-4 py-2 bg-neutral-200 dark:bg-neutral-700 text-neutral-700 dark:text-neutral-300 rounded-full text-[10px] font-black uppercase tracking-widest hover:bg-neutral-300 dark:hover:bg-neutral-600 transition-all", children: [_jsx(RefreshCw, { size: 14 }), "Refresh"] }), _jsxs("button", { className: "inline-flex items-center gap-2 px-4 py-2 bg-neutral-200 dark:bg-neutral-700 text-neutral-700 dark:text-neutral-300 rounded-full text-[10px] font-black uppercase tracking-widest hover:bg-neutral-300 dark:hover:bg-neutral-600 transition-all", children: [_jsx(ExternalLink, { size: 14 }), "Open in New Tab"] })] })] }), _jsx("div", { className: "flex-1 overflow-hidden bg-neutral-100 dark:bg-neutral-800/30", children: _jsx("div", { className: "h-full w-full p-8", children: _jsx("div", { className: "h-full w-full bg-white dark:bg-neutral-900 rounded-[2.5rem] border border-neutral-300 dark:border-neutral-700 overflow-hidden", children: _jsx("div", { className: "h-full w-full flex items-center justify-center", children: _jsxs("div", { className: "text-center", children: [_jsx("p", { className: "text-sm text-neutral-500 dark:text-neutral-400 mb-2", children: "Preview will be rendered here" }), _jsx("p", { className: "text-xs text-neutral-400", children: "Using iframe or side-by-side panel" })] }) }) }) }) })] }));
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/views/Preview/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings View - Development/Installation Screen
|
|
3
|
+
* Allows manual configuration of plugin settings (darkMode, backgroundColors)
|
|
4
|
+
*/
|
|
5
|
+
export interface SettingsViewProps {
|
|
6
|
+
siteId: string;
|
|
7
|
+
locale: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function SettingsView({ siteId, locale }: SettingsViewProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=SettingsView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsView.d.ts","sourceRoot":"","sources":["../../../src/views/Settings/SettingsView.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,iBAAiB,2CAyRjE"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings View - Development/Installation Screen
|
|
3
|
+
* Allows manual configuration of plugin settings (darkMode, backgroundColors)
|
|
4
|
+
*/
|
|
5
|
+
'use client';
|
|
6
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { useState, useEffect } from 'react';
|
|
8
|
+
import { Save, RotateCcw, Palette, Moon, Sun } from 'lucide-react';
|
|
9
|
+
export function SettingsView({ siteId, locale }) {
|
|
10
|
+
// Get current config from window global
|
|
11
|
+
const getCurrentConfig = () => {
|
|
12
|
+
if (typeof window !== 'undefined' && window.__JHITS_PLUGIN_PROPS__) {
|
|
13
|
+
const pluginProps = window.__JHITS_PLUGIN_PROPS__['plugin-blog'];
|
|
14
|
+
return {
|
|
15
|
+
darkMode: pluginProps?.darkMode ?? true,
|
|
16
|
+
backgroundColors: pluginProps?.backgroundColors ?? {
|
|
17
|
+
light: '#ffffff',
|
|
18
|
+
dark: '#171717',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
darkMode: true,
|
|
24
|
+
backgroundColors: {
|
|
25
|
+
light: '#ffffff',
|
|
26
|
+
dark: '#171717',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
const [darkMode, setDarkMode] = useState(getCurrentConfig().darkMode);
|
|
31
|
+
const [lightBg, setLightBg] = useState(getCurrentConfig().backgroundColors.light);
|
|
32
|
+
const [darkBg, setDarkBg] = useState(getCurrentConfig().backgroundColors.dark || '#171717');
|
|
33
|
+
const [hasChanges, setHasChanges] = useState(false);
|
|
34
|
+
const [saved, setSaved] = useState(false);
|
|
35
|
+
// Check for changes
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const current = getCurrentConfig();
|
|
38
|
+
const hasChanges = darkMode !== current.darkMode ||
|
|
39
|
+
lightBg !== current.backgroundColors.light ||
|
|
40
|
+
darkBg !== (current.backgroundColors.dark || '#171717');
|
|
41
|
+
setHasChanges(hasChanges);
|
|
42
|
+
setSaved(false);
|
|
43
|
+
}, [darkMode, lightBg, darkBg]);
|
|
44
|
+
// Save configuration
|
|
45
|
+
const handleSave = () => {
|
|
46
|
+
if (typeof window === 'undefined')
|
|
47
|
+
return;
|
|
48
|
+
// Initialize window global if needed
|
|
49
|
+
if (!window.__JHITS_PLUGIN_PROPS__) {
|
|
50
|
+
window.__JHITS_PLUGIN_PROPS__ = {};
|
|
51
|
+
}
|
|
52
|
+
// Update configuration
|
|
53
|
+
window.__JHITS_PLUGIN_PROPS__['plugin-blog'] = {
|
|
54
|
+
...(window.__JHITS_PLUGIN_PROPS__['plugin-blog'] || {}),
|
|
55
|
+
darkMode,
|
|
56
|
+
backgroundColors: {
|
|
57
|
+
light: lightBg,
|
|
58
|
+
dark: darkBg,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
// Also save to localStorage for persistence
|
|
62
|
+
try {
|
|
63
|
+
localStorage.setItem('__JHITS_PLUGIN_BLOG_CONFIG__', JSON.stringify({
|
|
64
|
+
darkMode,
|
|
65
|
+
backgroundColors: {
|
|
66
|
+
light: lightBg,
|
|
67
|
+
dark: darkBg,
|
|
68
|
+
},
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
console.warn('[SettingsView] Failed to save to localStorage:', e);
|
|
73
|
+
}
|
|
74
|
+
setSaved(true);
|
|
75
|
+
setTimeout(() => setSaved(false), 2000);
|
|
76
|
+
// Trigger a custom event to notify other components
|
|
77
|
+
window.dispatchEvent(new CustomEvent('blog-plugin-config-updated', {
|
|
78
|
+
detail: { darkMode, backgroundColors: { light: lightBg, dark: darkBg } }
|
|
79
|
+
}));
|
|
80
|
+
console.log('[SettingsView] Configuration saved:', {
|
|
81
|
+
darkMode,
|
|
82
|
+
backgroundColors: { light: lightBg, dark: darkBg },
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
// Reset to defaults
|
|
86
|
+
const handleReset = () => {
|
|
87
|
+
setDarkMode(true);
|
|
88
|
+
setLightBg('#ffffff');
|
|
89
|
+
setDarkBg('#171717');
|
|
90
|
+
};
|
|
91
|
+
// Load from localStorage on mount
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
try {
|
|
94
|
+
const saved = localStorage.getItem('__JHITS_PLUGIN_BLOG_CONFIG__');
|
|
95
|
+
if (saved) {
|
|
96
|
+
const config = JSON.parse(saved);
|
|
97
|
+
setDarkMode(config.darkMode ?? true);
|
|
98
|
+
setLightBg(config.backgroundColors?.light ?? '#ffffff');
|
|
99
|
+
setDarkBg(config.backgroundColors?.dark ?? '#171717');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
console.warn('[SettingsView] Failed to load from localStorage:', e);
|
|
104
|
+
}
|
|
105
|
+
}, []);
|
|
106
|
+
return (_jsx("div", { className: "min-h-screen bg-neutral-50 dark:bg-neutral-900 p-8", children: _jsxs("div", { className: "max-w-4xl mx-auto", children: [_jsxs("div", { className: "mb-8", children: [_jsx("h1", { className: "text-4xl font-black uppercase tracking-tighter text-neutral-950 dark:text-white mb-2", children: "Blog Plugin Settings" }), _jsx("p", { className: "text-sm text-neutral-600 dark:text-neutral-400", children: "Configure editor appearance and behavior. Changes are applied immediately." })] }), _jsxs("div", { className: "bg-white dark:bg-neutral-800 rounded-[2.5rem] border border-neutral-200 dark:border-neutral-700 shadow-lg p-8", children: [_jsx("div", { className: "mb-8 pb-8 border-b border-neutral-200 dark:border-neutral-700", children: _jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [darkMode ? (_jsx(Moon, { className: "size-5 text-neutral-600 dark:text-neutral-400" })) : (_jsx(Sun, { className: "size-5 text-neutral-600 dark:text-neutral-400" })), _jsxs("div", { children: [_jsx("label", { className: "text-sm font-black uppercase tracking-widest text-neutral-600 dark:text-neutral-400", children: "Dark Mode" }), _jsx("p", { className: "text-xs text-neutral-500 dark:text-neutral-500 mt-1", children: "Enable dark mode for editor content area and wrappers" })] })] }), _jsx("button", { onClick: () => setDarkMode(!darkMode), className: `relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${darkMode
|
|
107
|
+
? 'bg-primary'
|
|
108
|
+
: 'bg-neutral-300 dark:bg-neutral-600'}`, children: _jsx("span", { className: `inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${darkMode ? 'translate-x-6' : 'translate-x-1'}` }) })] }) }), _jsxs("div", { className: "mb-8", children: [_jsxs("div", { className: "flex items-center gap-3 mb-6", children: [_jsx(Palette, { className: "size-5 text-neutral-600 dark:text-neutral-400" }), _jsxs("div", { children: [_jsx("label", { className: "text-sm font-black uppercase tracking-widest text-neutral-600 dark:text-neutral-400", children: "Background Colors" }), _jsx("p", { className: "text-xs text-neutral-500 dark:text-neutral-500 mt-1", children: "Set custom background colors for the editor canvas" })] })] }), _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsxs("label", { className: "block text-[10px] font-black uppercase tracking-widest text-neutral-500 dark:text-neutral-500 mb-2", children: ["Light Mode Background ", _jsx("span", { className: "text-red-500", children: "*" })] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("input", { type: "text", value: lightBg, onChange: (e) => setLightBg(e.target.value), placeholder: "#ffffff", className: "flex-1 bg-dashboard-card border border-dashboard-border p-4 rounded-2xl text-sm font-bold outline-none focus:border-primary transition-all text-dashboard-text" }), _jsx("div", { className: "w-16 h-16 rounded-xl border-2 border-neutral-200 dark:border-neutral-700", style: { backgroundColor: lightBg } })] }), _jsx("p", { className: "text-xs text-neutral-400 dark:text-neutral-600 mt-1", children: "CSS color value (hex, rgb, or named color)" })] }), _jsxs("div", { children: [_jsxs("label", { className: "block text-[10px] font-black uppercase tracking-widest text-neutral-500 dark:text-neutral-500 mb-2", children: ["Dark Mode Background ", _jsx("span", { className: "text-neutral-400", children: "(Optional)" })] }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("input", { type: "text", value: darkBg, onChange: (e) => setDarkBg(e.target.value), placeholder: "#171717", disabled: !darkMode, className: `flex-1 bg-white dark:bg-neutral-900/50 border border-neutral-300 dark:border-neutral-700 p-4 rounded-2xl text-sm font-bold outline-none focus:border-primary transition-all dark:text-neutral-100 ${!darkMode ? 'opacity-50 cursor-not-allowed' : ''}` }), _jsx("div", { className: `w-16 h-16 rounded-xl border-2 border-neutral-200 dark:border-neutral-700 ${!darkMode ? 'opacity-50' : ''}`, style: { backgroundColor: darkBg } })] }), _jsx("p", { className: "text-xs text-neutral-400 dark:text-neutral-600 mt-1", children: "Only used when dark mode is enabled" })] })] })] }), _jsxs("div", { className: "mb-8 p-6 bg-neutral-50 dark:bg-neutral-900/50 rounded-2xl border border-neutral-200 dark:border-neutral-700", children: [_jsx("label", { className: "block text-[10px] font-black uppercase tracking-widest text-neutral-500 dark:text-neutral-500 mb-3", children: "Preview" }), _jsx("div", { className: "h-32 rounded-xl border-2 border-dashed border-neutral-300 dark:border-neutral-700 flex items-center justify-center", style: {
|
|
109
|
+
backgroundColor: darkMode ? darkBg : lightBg,
|
|
110
|
+
}, children: _jsx("span", { className: "text-xs font-bold uppercase tracking-widest text-neutral-600 dark:text-neutral-400", children: "Editor Canvas Preview" }) })] }), _jsxs("div", { className: "flex items-center justify-between pt-6 border-t border-neutral-200 dark:border-neutral-700", children: [_jsxs("button", { onClick: handleReset, className: "px-6 py-3 rounded-full border border-neutral-300 dark:border-neutral-700 bg-white dark:bg-neutral-900/50 text-sm font-black uppercase tracking-widest text-neutral-600 dark:text-neutral-400 hover:bg-neutral-50 dark:hover:bg-neutral-800 transition-colors flex items-center gap-2", children: [_jsx(RotateCcw, { className: "size-4" }), "Reset"] }), _jsxs("button", { onClick: handleSave, disabled: !hasChanges, className: `px-6 py-3 rounded-full text-sm font-black uppercase tracking-widest transition-all flex items-center gap-2 ${hasChanges
|
|
111
|
+
? 'bg-primary text-white hover:bg-primary/90 shadow-lg shadow-primary/20'
|
|
112
|
+
: 'bg-neutral-200 dark:bg-neutral-700 text-neutral-400 dark:text-neutral-600 cursor-not-allowed'}`, children: [_jsx(Save, { className: "size-4" }), saved ? 'Saved!' : 'Save Changes'] })] })] }), _jsxs("div", { className: "mt-6 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-2xl p-6", children: [_jsx("h3", { className: "text-sm font-black uppercase tracking-widest text-blue-900 dark:text-blue-300 mb-2", children: "How It Works" }), _jsxs("ul", { className: "text-xs text-blue-800 dark:text-blue-400 space-y-1 list-disc list-inside", children: [_jsxs("li", { children: ["Changes are saved to ", _jsx("code", { className: "bg-blue-100 dark:bg-blue-900/50 px-1 rounded", children: "window.__JHITS_PLUGIN_PROPS__" }), " and localStorage"] }), _jsx("li", { children: "Configuration persists across page refreshes" }), _jsx("li", { children: "To apply changes in the editor, navigate to a post editor page" }), _jsx("li", { children: "For production, configure these settings in your client app's blog config file" })] })] })] }) }));
|
|
113
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/views/Settings/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slug & SEO Manager View
|
|
3
|
+
* URL and SEO metadata management
|
|
4
|
+
* Follows dashboard earth-tone design system
|
|
5
|
+
*/
|
|
6
|
+
export interface SlugSEOManagerViewProps {
|
|
7
|
+
postId?: string;
|
|
8
|
+
siteId: string;
|
|
9
|
+
locale: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function SlugSEOManagerView({ postId, siteId, locale }: SlugSEOManagerViewProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=SlugSEOManagerView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SlugSEOManagerView.d.ts","sourceRoot":"","sources":["../../../src/views/SlugSEO/SlugSEOManagerView.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,uBAAuB;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,uBAAuB,2CA2ErF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slug & SEO Manager View
|
|
3
|
+
* URL and SEO metadata management
|
|
4
|
+
* Follows dashboard earth-tone design system
|
|
5
|
+
*/
|
|
6
|
+
'use client';
|
|
7
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { Search, Link2, FileText } from 'lucide-react';
|
|
9
|
+
export function SlugSEOManagerView({ postId, siteId, locale }) {
|
|
10
|
+
return (_jsx("div", { className: "h-full w-full bg-white dark:bg-neutral-900 p-8 overflow-y-auto", children: _jsxs("div", { className: "max-w-4xl mx-auto", children: [_jsx("h1", { className: "text-3xl font-black text-neutral-950 dark:text-white uppercase tracking-tighter mb-2", children: "Slug & SEO Manager" }), _jsx("p", { className: "text-sm text-neutral-500 dark:text-neutral-400 mb-8", children: postId ? `Managing SEO for post: ${postId}` : 'Manage URL slugs and SEO metadata' }), _jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "p-6 bg-neutral-100 dark:bg-neutral-800/50 rounded-[2.5rem] border border-neutral-300 dark:border-neutral-700", children: [_jsx("label", { className: "block text-sm font-black text-neutral-950 dark:text-white uppercase tracking-tight mb-3", children: "URL Slug" }), _jsxs("div", { className: "flex items-center gap-3", children: [_jsx(Link2, { className: "text-neutral-400 size-5" }), _jsx("input", { type: "text", placeholder: "post-url-slug", className: "flex-1 px-4 py-3 bg-white dark:bg-neutral-900 border border-neutral-300 dark:border-neutral-700 rounded-2xl text-sm focus:ring-2 focus:ring-primary/20 focus:border-primary outline-none" })] }), _jsx("p", { className: "text-xs text-neutral-500 dark:text-neutral-400 mt-2", children: "Collision detection will appear here" })] }), _jsxs("div", { className: "p-6 bg-neutral-100 dark:bg-neutral-800/50 rounded-[2.5rem] border border-neutral-300 dark:border-neutral-700", children: [_jsx("label", { className: "block text-sm font-black text-neutral-950 dark:text-white uppercase tracking-tight mb-3", children: "Search Result Preview" }), _jsxs("div", { className: "bg-white dark:bg-neutral-900 rounded-2xl p-4 border border-neutral-300 dark:border-neutral-700", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(Search, { size: 16, className: "text-neutral-400" }), _jsx("span", { className: "text-xs text-neutral-500", children: "Google Search Result" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("h3", { className: "text-lg text-blue-600 dark:text-blue-400 hover:underline cursor-pointer", children: "Post Title Will Appear Here" }), _jsx("p", { className: "text-sm text-green-700 dark:text-green-400", children: "https://example.com/blog/post-url-slug" }), _jsx("p", { className: "text-sm text-neutral-600 dark:text-neutral-400", children: "Meta description will appear here. This is what users see in search results." })] })] })] }), _jsxs("div", { className: "p-6 bg-neutral-100 dark:bg-neutral-800/50 rounded-[2.5rem] border border-neutral-300 dark:border-neutral-700", children: [_jsx("label", { className: "block text-sm font-black text-neutral-950 dark:text-white uppercase tracking-tight mb-3", children: "Meta Description" }), _jsxs("div", { className: "flex items-start gap-3", children: [_jsx(FileText, { className: "text-neutral-400 size-5 mt-1" }), _jsx("textarea", { placeholder: "Enter meta description for search engines...", rows: 4, className: "flex-1 px-4 py-3 bg-white dark:bg-neutral-900 border border-neutral-300 dark:border-neutral-700 rounded-2xl text-sm focus:ring-2 focus:ring-primary/20 focus:border-primary outline-none resize-none" })] }), _jsx("p", { className: "text-xs text-neutral-500 dark:text-neutral-400 mt-2", children: "0 / 160 characters" })] })] })] }) }));
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/views/SlugSEO/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jhits/plugin-blog",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "Professional blog management system for the JHITS ecosystem",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"lucide-react": "^0.564.0",
|
|
24
24
|
"mongodb": "^7.1.0",
|
|
25
25
|
"next-auth": "^4.24.13",
|
|
26
|
-
"@jhits/plugin-content": "0.0.
|
|
27
|
-
"@jhits/plugin-core": "0.0.
|
|
28
|
-
"@jhits/plugin-images": "0.0.
|
|
26
|
+
"@jhits/plugin-content": "0.0.7",
|
|
27
|
+
"@jhits/plugin-core": "0.0.4",
|
|
28
|
+
"@jhits/plugin-images": "0.0.8"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
31
|
"next": ">=15.0.0",
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Blog Hooks
|
|
3
|
+
* React hooks for fetching blog data in client applications
|
|
4
|
+
*/
|
|
5
|
+
export { useBlogs, type UseBlogsOptions, type UseBlogsResult } from './useBlogs';
|
|
6
|
+
export { useBlog, type UseBlogOptions, type UseBlogResult } from './useBlog';
|
|
7
|
+
export { useCategories } from './useCategories';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useBlog Hook
|
|
3
|
+
* React hook for fetching a single blog post by slug
|
|
4
|
+
*/
|
|
5
|
+
import { BlogPost } from '../types/post';
|
|
6
|
+
export interface UseBlogOptions {
|
|
7
|
+
/** Blog post slug */
|
|
8
|
+
slug: string;
|
|
9
|
+
/** API base URL (default: '/api/blogs') */
|
|
10
|
+
apiBaseUrl?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface UseBlogResult {
|
|
13
|
+
/** Blog post data */
|
|
14
|
+
blog: BlogPost | null;
|
|
15
|
+
/** Whether data is currently loading */
|
|
16
|
+
loading: boolean;
|
|
17
|
+
/** Error message if fetch failed */
|
|
18
|
+
error: string | null;
|
|
19
|
+
/** Function to refetch the blog post */
|
|
20
|
+
refetch: () => Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* React hook to fetch a single blog post by slug
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* const { blog, loading, error } = useBlog({ slug: 'my-blog-post' });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function useBlog(options: UseBlogOptions): UseBlogResult;
|
|
31
|
+
//# sourceMappingURL=useBlog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBlog.d.ts","sourceRoot":"","sources":["useBlog.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,MAAM,WAAW,cAAc;IAC3B,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC1B,qBAAqB;IACrB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,wCAAwC;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,wCAAwC;IACxC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa,CAgD9D"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useBlog Hook
|
|
3
|
+
* React hook for fetching a single blog post by slug
|
|
4
|
+
*/
|
|
5
|
+
import { useState, useEffect } from 'react';
|
|
6
|
+
import { apiToBlogPost } from '../lib/mappers/apiMapper';
|
|
7
|
+
/**
|
|
8
|
+
* React hook to fetch a single blog post by slug
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const { blog, loading, error } = useBlog({ slug: 'my-blog-post' });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function useBlog(options) {
|
|
16
|
+
const { slug, apiBaseUrl = '/api/plugin-blog' } = options;
|
|
17
|
+
const [blog, setBlog] = useState(null);
|
|
18
|
+
const [loading, setLoading] = useState(true);
|
|
19
|
+
const [error, setError] = useState(null);
|
|
20
|
+
const fetchBlog = async () => {
|
|
21
|
+
if (!slug) {
|
|
22
|
+
setLoading(false);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
setLoading(true);
|
|
27
|
+
setError(null);
|
|
28
|
+
const response = await fetch(`${apiBaseUrl}/${slug}`);
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
if (response.status === 404) {
|
|
31
|
+
throw new Error('Blog post not found');
|
|
32
|
+
}
|
|
33
|
+
throw new Error(`Failed to fetch blog: ${response.status}`);
|
|
34
|
+
}
|
|
35
|
+
const apiDoc = await response.json();
|
|
36
|
+
const blogPost = apiToBlogPost(apiDoc);
|
|
37
|
+
setBlog(blogPost);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
console.error('[useBlog] Error fetching blog:', err);
|
|
41
|
+
setError(err.message || 'Failed to fetch blog');
|
|
42
|
+
setBlog(null);
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
setLoading(false);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
fetchBlog();
|
|
50
|
+
}, [slug, apiBaseUrl]);
|
|
51
|
+
return {
|
|
52
|
+
blog,
|
|
53
|
+
loading,
|
|
54
|
+
error,
|
|
55
|
+
refetch: fetchBlog,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useBlogs Hook
|
|
3
|
+
* React hook for fetching blog posts in client applications
|
|
4
|
+
*/
|
|
5
|
+
import { PostListItem } from '../types/post';
|
|
6
|
+
export interface UseBlogsOptions {
|
|
7
|
+
/** Maximum number of posts to fetch (default: 10) */
|
|
8
|
+
limit?: number;
|
|
9
|
+
/** Number of posts to skip (default: 0) */
|
|
10
|
+
skip?: number;
|
|
11
|
+
/** Filter by status (published, draft, concept) */
|
|
12
|
+
status?: string;
|
|
13
|
+
/** Whether to fetch all posts for admin (includes drafts) */
|
|
14
|
+
admin?: boolean;
|
|
15
|
+
/** API base URL (default: '/api/blogs') */
|
|
16
|
+
apiBaseUrl?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface UseBlogsResult {
|
|
19
|
+
/** Array of blog posts */
|
|
20
|
+
blogs: PostListItem[];
|
|
21
|
+
/** Whether data is currently loading */
|
|
22
|
+
loading: boolean;
|
|
23
|
+
/** Error message if fetch failed */
|
|
24
|
+
error: string | null;
|
|
25
|
+
/** Total number of posts available */
|
|
26
|
+
total: number;
|
|
27
|
+
/** Function to refetch blogs */
|
|
28
|
+
refetch: () => Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* React hook to fetch blog posts
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* const { blogs, loading, error } = useBlogs({ limit: 5 });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function useBlogs(options?: UseBlogsOptions): UseBlogsResult;
|
|
39
|
+
//# sourceMappingURL=useBlogs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBlogs.d.ts","sourceRoot":"","sources":["useBlogs.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC5B,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC3B,0BAA0B;IAC1B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,wCAAwC;IACxC,OAAO,EAAE,OAAO,CAAC;IACjB,oCAAoC;IACpC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,eAAoB,GAAG,cAAc,CA8EtE"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useBlogs Hook
|
|
3
|
+
* React hook for fetching blog posts in client applications
|
|
4
|
+
*/
|
|
5
|
+
import { useState, useEffect } from 'react';
|
|
6
|
+
import { apiToBlogPost } from '../lib/mappers/apiMapper';
|
|
7
|
+
/**
|
|
8
|
+
* React hook to fetch blog posts
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const { blogs, loading, error } = useBlogs({ limit: 5 });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function useBlogs(options = {}) {
|
|
16
|
+
const { limit = 10, skip = 0, status, admin = false, apiBaseUrl = '/api/plugin-blog', } = options;
|
|
17
|
+
const [blogs, setBlogs] = useState([]);
|
|
18
|
+
const [loading, setLoading] = useState(true);
|
|
19
|
+
const [error, setError] = useState(null);
|
|
20
|
+
const [total, setTotal] = useState(0);
|
|
21
|
+
const fetchBlogs = async () => {
|
|
22
|
+
try {
|
|
23
|
+
setLoading(true);
|
|
24
|
+
setError(null);
|
|
25
|
+
const params = new URLSearchParams();
|
|
26
|
+
if (limit)
|
|
27
|
+
params.set('limit', limit.toString());
|
|
28
|
+
if (skip)
|
|
29
|
+
params.set('skip', skip.toString());
|
|
30
|
+
if (status)
|
|
31
|
+
params.set('status', status);
|
|
32
|
+
if (admin)
|
|
33
|
+
params.set('admin', 'true');
|
|
34
|
+
const url = `${apiBaseUrl}?${params.toString()}`;
|
|
35
|
+
const response = await fetch(url);
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
throw new Error(`Failed to fetch blogs: ${response.status}`);
|
|
38
|
+
}
|
|
39
|
+
const data = await response.json();
|
|
40
|
+
// Handle error response
|
|
41
|
+
if (data.error) {
|
|
42
|
+
throw new Error(data.error || 'Failed to fetch blogs');
|
|
43
|
+
}
|
|
44
|
+
// Convert API format to PostListItem format
|
|
45
|
+
const blogsArray = Array.isArray(data.blogs) ? data.blogs : [];
|
|
46
|
+
const convertedBlogs = blogsArray.map((apiDoc) => {
|
|
47
|
+
const blogPost = apiToBlogPost(apiDoc);
|
|
48
|
+
return {
|
|
49
|
+
id: blogPost.id,
|
|
50
|
+
title: blogPost.title,
|
|
51
|
+
slug: blogPost.slug,
|
|
52
|
+
excerpt: blogPost.metadata.excerpt || '',
|
|
53
|
+
status: blogPost.publication.status,
|
|
54
|
+
authorId: blogPost.publication.authorId || '',
|
|
55
|
+
updatedAt: blogPost.updatedAt,
|
|
56
|
+
featuredImage: blogPost.metadata.featuredImage,
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
setBlogs(convertedBlogs);
|
|
60
|
+
setTotal(data.total || convertedBlogs.length);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
console.error('[useBlogs] Error fetching blogs:', err);
|
|
64
|
+
setError(err.message || 'Failed to fetch blogs');
|
|
65
|
+
setBlogs([]);
|
|
66
|
+
setTotal(0);
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
setLoading(false);
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
fetchBlogs();
|
|
74
|
+
}, [limit, skip, status, admin, apiBaseUrl]);
|
|
75
|
+
return {
|
|
76
|
+
blogs,
|
|
77
|
+
loading,
|
|
78
|
+
error,
|
|
79
|
+
total,
|
|
80
|
+
refetch: fetchBlogs,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCategories.d.ts","sourceRoot":"","sources":["useCategories.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,wBAAgB,aAAa;;;EAkE5B"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook to fetch categories from existing blog posts
|
|
3
|
+
* Extracts categories from Hero blocks in all posts
|
|
4
|
+
*/
|
|
5
|
+
'use client';
|
|
6
|
+
import { useState, useEffect } from 'react';
|
|
7
|
+
export function useCategories() {
|
|
8
|
+
const [categories, setCategories] = useState([]);
|
|
9
|
+
const [loading, setLoading] = useState(true);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const fetchCategories = async () => {
|
|
12
|
+
try {
|
|
13
|
+
const categorySet = new Set();
|
|
14
|
+
// 1. Fetch from categories endpoint (legacy categoryTags.category)
|
|
15
|
+
try {
|
|
16
|
+
const categoriesResponse = await fetch('/api/plugin-blog/categories');
|
|
17
|
+
if (categoriesResponse.ok) {
|
|
18
|
+
const categoriesData = await categoriesResponse.json();
|
|
19
|
+
if (Array.isArray(categoriesData.categories)) {
|
|
20
|
+
categoriesData.categories.forEach((cat) => {
|
|
21
|
+
if (cat && cat.trim()) {
|
|
22
|
+
categorySet.add(cat.trim());
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
// Categories endpoint not available, continue
|
|
30
|
+
}
|
|
31
|
+
// 2. Fetch all blog posts and extract categories from Hero blocks
|
|
32
|
+
try {
|
|
33
|
+
const response = await fetch('/api/plugin-blog?admin=true&limit=1000');
|
|
34
|
+
if (response.ok) {
|
|
35
|
+
const data = await response.json();
|
|
36
|
+
const posts = Array.isArray(data.blogs) ? data.blogs : (Array.isArray(data) ? data : []);
|
|
37
|
+
posts.forEach((post) => {
|
|
38
|
+
if (post.blocks && Array.isArray(post.blocks)) {
|
|
39
|
+
// Find Hero block
|
|
40
|
+
const heroBlock = post.blocks.find((block) => block.type === 'hero');
|
|
41
|
+
if (heroBlock && heroBlock.data && heroBlock.data.category) {
|
|
42
|
+
const category = heroBlock.data.category.trim();
|
|
43
|
+
if (category) {
|
|
44
|
+
categorySet.add(category);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
console.error('Failed to fetch posts for categories:', e);
|
|
53
|
+
}
|
|
54
|
+
// Convert to sorted array
|
|
55
|
+
const sortedCategories = Array.from(categorySet).sort();
|
|
56
|
+
setCategories(sortedCategories);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
console.error('Failed to fetch categories:', error);
|
|
60
|
+
// Fallback to empty array
|
|
61
|
+
setCategories([]);
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
setLoading(false);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
fetchCategories();
|
|
68
|
+
}, []);
|
|
69
|
+
return { categories, loading };
|
|
70
|
+
}
|