@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.
Files changed (291) hide show
  1. package/dist/api/categories.d.ts.map +1 -1
  2. package/dist/api/categories.js +42 -38
  3. package/dist/api/handler.d.ts +1 -26
  4. package/dist/api/handler.d.ts.map +1 -1
  5. package/dist/api/handler.js +81 -500
  6. package/dist/api/router.d.ts +0 -5
  7. package/dist/api/router.d.ts.map +1 -1
  8. package/dist/api/router.js +8 -35
  9. package/dist/api/service.d.ts +80 -0
  10. package/dist/api/service.d.ts.map +1 -0
  11. package/dist/api/service.js +219 -0
  12. package/dist/hooks/useAutoSave.d.ts +10 -0
  13. package/dist/hooks/useAutoSave.d.ts.map +1 -0
  14. package/dist/hooks/useAutoSave.js +57 -0
  15. package/dist/hooks/useCategories.d.ts +1 -1
  16. package/dist/hooks/useCategories.d.ts.map +1 -1
  17. package/dist/hooks/useCategories.js +15 -46
  18. package/dist/index.d.ts +24 -31
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +44 -201
  21. package/dist/init.d.ts +20 -7
  22. package/dist/init.d.ts.map +1 -1
  23. package/dist/init.js +8 -7
  24. package/dist/lib/blocks/BlockRenderer.d.ts.map +1 -1
  25. package/dist/lib/layouts/blocks/ColumnsBlock.d.ts.map +1 -1
  26. package/dist/lib/layouts/blocks/ColumnsBlock.js +30 -113
  27. package/dist/lib/layouts/blocks/SectionBlock.d.ts.map +1 -1
  28. package/dist/lib/layouts/blocks/SectionBlock.js +9 -21
  29. package/dist/lib/layouts/index.d.ts +3 -3
  30. package/dist/lib/layouts/index.js +4 -4
  31. package/dist/lib/mappers/apiMapper.d.ts +10 -0
  32. package/dist/lib/mappers/apiMapper.d.ts.map +1 -1
  33. package/dist/lib/mappers/apiMapper.js +47 -32
  34. package/dist/lib/rich-text/RichTextEditor.d.ts +4 -2
  35. package/dist/lib/rich-text/RichTextEditor.d.ts.map +1 -1
  36. package/dist/lib/rich-text/RichTextEditor.js +12 -9
  37. package/dist/lib/utils/config-resolver.d.ts +28 -0
  38. package/dist/lib/utils/config-resolver.d.ts.map +1 -0
  39. package/dist/lib/utils/config-resolver.js +46 -0
  40. package/dist/lib/utils/tree.d.ts +29 -0
  41. package/dist/lib/utils/tree.d.ts.map +1 -0
  42. package/dist/lib/utils/tree.js +129 -0
  43. package/dist/state/EditorContext.d.ts +3 -25
  44. package/dist/state/EditorContext.d.ts.map +1 -1
  45. package/dist/state/EditorContext.js +124 -174
  46. package/dist/state/reducer.d.ts +1 -5
  47. package/dist/state/reducer.d.ts.map +1 -1
  48. package/dist/state/reducer.js +128 -521
  49. package/dist/state/types.d.ts +12 -1
  50. package/dist/state/types.d.ts.map +1 -1
  51. package/dist/types/block.d.ts +9 -0
  52. package/dist/types/block.d.ts.map +1 -1
  53. package/dist/types/post.d.ts +17 -1
  54. package/dist/types/post.d.ts.map +1 -1
  55. package/dist/views/CanvasEditor/BlockWrapper.d.ts +5 -6
  56. package/dist/views/CanvasEditor/BlockWrapper.d.ts.map +1 -1
  57. package/dist/views/CanvasEditor/BlockWrapper.js +56 -264
  58. package/dist/views/CanvasEditor/CanvasEditorView.d.ts +5 -3
  59. package/dist/views/CanvasEditor/CanvasEditorView.d.ts.map +1 -1
  60. package/dist/views/CanvasEditor/CanvasEditorView.js +55 -315
  61. package/dist/views/CanvasEditor/EditorBody.d.ts +6 -8
  62. package/dist/views/CanvasEditor/EditorBody.d.ts.map +1 -1
  63. package/dist/views/CanvasEditor/EditorBody.js +34 -482
  64. package/dist/views/CanvasEditor/EditorHeader.d.ts.map +1 -1
  65. package/dist/views/CanvasEditor/EditorHeader.js +27 -63
  66. package/dist/views/CanvasEditor/LayoutContainer.d.ts.map +1 -1
  67. package/dist/views/CanvasEditor/LayoutContainer.js +49 -70
  68. package/dist/views/CanvasEditor/components/CustomBlockItem.js +1 -1
  69. package/dist/views/CanvasEditor/components/EditorCanvas.d.ts +15 -3
  70. package/dist/views/CanvasEditor/components/EditorCanvas.d.ts.map +1 -1
  71. package/dist/views/CanvasEditor/components/EditorCanvas.js +40 -18
  72. package/dist/views/CanvasEditor/components/EditorLibrary.d.ts +5 -1
  73. package/dist/views/CanvasEditor/components/EditorLibrary.d.ts.map +1 -1
  74. package/dist/views/CanvasEditor/components/EditorLibrary.js +11 -7
  75. package/dist/views/CanvasEditor/components/EditorSidebar.d.ts.map +1 -1
  76. package/dist/views/CanvasEditor/components/EditorSidebar.js +32 -14
  77. package/dist/views/CanvasEditor/components/FeaturedMediaSection.d.ts +0 -6
  78. package/dist/views/CanvasEditor/components/FeaturedMediaSection.d.ts.map +1 -1
  79. package/dist/views/CanvasEditor/components/FeaturedMediaSection.js +17 -128
  80. package/dist/views/CanvasEditor/components/JSONInspector.d.ts +9 -0
  81. package/dist/views/CanvasEditor/components/JSONInspector.d.ts.map +1 -0
  82. package/dist/views/CanvasEditor/components/JSONInspector.js +56 -0
  83. package/dist/views/CanvasEditor/components/LibraryItem.js +2 -2
  84. package/dist/views/CanvasEditor/components/PrivacySettingsSection.d.ts +0 -4
  85. package/dist/views/CanvasEditor/components/PrivacySettingsSection.d.ts.map +1 -1
  86. package/dist/views/CanvasEditor/components/PrivacySettingsSection.js +6 -28
  87. package/dist/views/CanvasEditor/components/index.d.ts +2 -0
  88. package/dist/views/CanvasEditor/components/index.d.ts.map +1 -1
  89. package/dist/views/CanvasEditor/components/index.js +1 -0
  90. package/dist/views/CanvasEditor/hooks/useHeroBlock.d.ts.map +1 -1
  91. package/dist/views/CanvasEditor/hooks/useHeroBlock.js +15 -18
  92. package/dist/views/CanvasEditor/hooks/usePostLoader.d.ts +3 -0
  93. package/dist/views/CanvasEditor/hooks/usePostLoader.d.ts.map +1 -1
  94. package/dist/views/CanvasEditor/hooks/usePostLoader.js +12 -13
  95. package/dist/views/CanvasEditor/hooks/useUnsavedChanges.js +0 -4
  96. package/dist/views/PostManager/EmptyState.d.ts +1 -1
  97. package/dist/views/PostManager/EmptyState.js +4 -4
  98. package/dist/views/PostManager/FilterDropdown.d.ts +21 -0
  99. package/dist/views/PostManager/FilterDropdown.d.ts.map +1 -0
  100. package/dist/views/PostManager/FilterDropdown.js +28 -0
  101. package/dist/views/PostManager/LanguageFlags.d.ts.map +1 -1
  102. package/dist/views/PostManager/LanguageFlags.js +4 -1
  103. package/dist/views/PostManager/PostCards.d.ts.map +1 -1
  104. package/dist/views/PostManager/PostCards.js +23 -40
  105. package/dist/views/PostManager/PostFilters.d.ts.map +1 -1
  106. package/dist/views/PostManager/PostFilters.js +34 -3
  107. package/dist/views/PostManager/PostManagerView.d.ts +1 -2
  108. package/dist/views/PostManager/PostManagerView.d.ts.map +1 -1
  109. package/dist/views/PostManager/PostManagerView.js +30 -96
  110. package/dist/views/PostManager/PostStats.d.ts.map +1 -1
  111. package/dist/views/PostManager/PostStats.js +10 -10
  112. package/dist/views/PostManager/PostTable.d.ts.map +1 -1
  113. package/dist/views/PostManager/PostTable.js +23 -40
  114. package/dist/views/Settings/SettingsView.d.ts +1 -1
  115. package/dist/views/Settings/SettingsView.d.ts.map +1 -1
  116. package/dist/views/Settings/SettingsView.js +12 -39
  117. package/dist/views/SlugSEO/SlugSEOManagerView.d.ts.map +1 -1
  118. package/dist/views/SlugSEO/SlugSEOManagerView.js +2 -2
  119. package/package.json +42 -6
  120. package/src/api/categories.ts +48 -52
  121. package/src/api/handler.ts +87 -604
  122. package/src/api/router.ts +15 -65
  123. package/src/api/service.ts +241 -0
  124. package/src/hooks/useAutoSave.ts +64 -0
  125. package/src/hooks/useCategories.ts +19 -47
  126. package/src/index.tsx +79 -293
  127. package/src/init.tsx +24 -11
  128. package/src/lib/blocks/BlockRenderer.tsx +1 -0
  129. package/src/lib/layouts/blocks/ColumnsBlock.tsx +60 -173
  130. package/src/lib/layouts/blocks/SectionBlock.tsx +22 -26
  131. package/src/lib/layouts/index.ts +4 -4
  132. package/src/lib/mappers/apiMapper.ts +63 -32
  133. package/src/lib/rich-text/RichTextEditor.tsx +16 -9
  134. package/src/lib/utils/config-resolver.ts +64 -0
  135. package/src/lib/utils/tree.ts +150 -0
  136. package/src/state/EditorContext.tsx +153 -232
  137. package/src/state/reducer.ts +141 -606
  138. package/src/state/types.ts +14 -1
  139. package/src/types/block.ts +10 -0
  140. package/src/types/post.ts +19 -1
  141. package/src/views/CanvasEditor/BlockWrapper.tsx +130 -460
  142. package/src/views/CanvasEditor/CanvasEditorView.tsx +145 -420
  143. package/src/views/CanvasEditor/EditorBody.tsx +98 -610
  144. package/src/views/CanvasEditor/EditorHeader.tsx +176 -196
  145. package/src/views/CanvasEditor/LayoutContainer.tsx +74 -89
  146. package/src/views/CanvasEditor/components/CustomBlockItem.tsx +7 -8
  147. package/src/views/CanvasEditor/components/EditorCanvas.tsx +139 -84
  148. package/src/views/CanvasEditor/components/EditorLibrary.tsx +25 -10
  149. package/src/views/CanvasEditor/components/EditorSidebar.tsx +196 -127
  150. package/src/views/CanvasEditor/components/FeaturedMediaSection.tsx +78 -210
  151. package/src/views/CanvasEditor/components/JSONInspector.tsx +125 -0
  152. package/src/views/CanvasEditor/components/LibraryItem.tsx +5 -6
  153. package/src/views/CanvasEditor/components/PrivacySettingsSection.tsx +73 -124
  154. package/src/views/CanvasEditor/components/index.ts +2 -1
  155. package/src/views/CanvasEditor/hooks/useHeroBlock.ts +15 -18
  156. package/src/views/CanvasEditor/hooks/usePostLoader.ts +21 -13
  157. package/src/views/CanvasEditor/hooks/useUnsavedChanges.ts +4 -4
  158. package/src/views/PostManager/EmptyState.tsx +9 -10
  159. package/src/views/PostManager/FilterDropdown.tsx +95 -0
  160. package/src/views/PostManager/LanguageFlags.tsx +6 -2
  161. package/src/views/PostManager/PostCards.tsx +127 -133
  162. package/src/views/PostManager/PostFilters.tsx +73 -68
  163. package/src/views/PostManager/PostManagerView.tsx +132 -179
  164. package/src/views/PostManager/PostStats.tsx +21 -20
  165. package/src/views/PostManager/PostTable.tsx +137 -165
  166. package/src/views/Settings/SettingsView.tsx +64 -180
  167. package/src/views/SlugSEO/SlugSEOManagerView.tsx +59 -44
  168. package/src/hooks/index.d.ts +0 -8
  169. package/src/hooks/index.d.ts.map +0 -1
  170. package/src/hooks/useBlog.d.ts +0 -31
  171. package/src/hooks/useBlog.d.ts.map +0 -1
  172. package/src/hooks/useBlogs.d.ts +0 -39
  173. package/src/hooks/useBlogs.d.ts.map +0 -1
  174. package/src/hooks/useCategories.d.ts +0 -9
  175. package/src/hooks/useCategories.d.ts.map +0 -1
  176. package/src/lib/blocks/BlockRenderer.d.ts +0 -54
  177. package/src/lib/blocks/BlockRenderer.d.ts.map +0 -1
  178. package/src/lib/config-storage.d.ts +0 -30
  179. package/src/lib/config-storage.d.ts.map +0 -1
  180. package/src/lib/layouts/blocks/ColumnsBlock.d.ts +0 -25
  181. package/src/lib/layouts/blocks/ColumnsBlock.d.ts.map +0 -1
  182. package/src/lib/layouts/blocks/SectionBlock.d.ts +0 -25
  183. package/src/lib/layouts/blocks/SectionBlock.d.ts.map +0 -1
  184. package/src/lib/layouts/index.d.ts +0 -23
  185. package/src/lib/layouts/index.d.ts.map +0 -1
  186. package/src/lib/layouts/registerLayoutBlocks.d.ts +0 -9
  187. package/src/lib/layouts/registerLayoutBlocks.d.ts.map +0 -1
  188. package/src/lib/mappers/apiMapper.d.ts +0 -66
  189. package/src/lib/mappers/apiMapper.d.ts.map +0 -1
  190. package/src/lib/rich-text/RichTextEditor.d.ts +0 -45
  191. package/src/lib/rich-text/RichTextEditor.d.ts.map +0 -1
  192. package/src/lib/rich-text/RichTextPreview.d.ts +0 -16
  193. package/src/lib/rich-text/RichTextPreview.d.ts.map +0 -1
  194. package/src/lib/rich-text/index.d.ts +0 -9
  195. package/src/lib/rich-text/index.d.ts.map +0 -1
  196. package/src/lib/utils/blockHelpers.d.ts +0 -23
  197. package/src/lib/utils/blockHelpers.d.ts.map +0 -1
  198. package/src/lib/utils/configValidation.d.ts +0 -23
  199. package/src/lib/utils/configValidation.d.ts.map +0 -1
  200. package/src/registry/BlockRegistry.d.ts +0 -62
  201. package/src/registry/BlockRegistry.d.ts.map +0 -1
  202. package/src/registry/index.d.ts +0 -6
  203. package/src/registry/index.d.ts.map +0 -1
  204. package/src/state/EditorContext.d.ts +0 -45
  205. package/src/state/EditorContext.d.ts.map +0 -1
  206. package/src/state/index.d.ts +0 -7
  207. package/src/state/index.d.ts.map +0 -1
  208. package/src/state/reducer.d.ts +0 -11
  209. package/src/state/reducer.d.ts.map +0 -1
  210. package/src/state/types.d.ts +0 -162
  211. package/src/state/types.d.ts.map +0 -1
  212. package/src/types/block.d.ts +0 -221
  213. package/src/types/block.d.ts.map +0 -1
  214. package/src/types/index.d.ts +0 -8
  215. package/src/types/index.d.ts.map +0 -1
  216. package/src/types/post.d.ts +0 -136
  217. package/src/types/post.d.ts.map +0 -1
  218. package/src/utils/client.d.ts +0 -48
  219. package/src/utils/client.d.ts.map +0 -1
  220. package/src/views/CanvasEditor/BlockWrapper.d.ts +0 -16
  221. package/src/views/CanvasEditor/BlockWrapper.d.ts.map +0 -1
  222. package/src/views/CanvasEditor/CanvasEditorView.d.ts +0 -14
  223. package/src/views/CanvasEditor/CanvasEditorView.d.ts.map +0 -1
  224. package/src/views/CanvasEditor/EditorBody.d.ts +0 -22
  225. package/src/views/CanvasEditor/EditorBody.d.ts.map +0 -1
  226. package/src/views/CanvasEditor/EditorHeader.d.ts +0 -18
  227. package/src/views/CanvasEditor/EditorHeader.d.ts.map +0 -1
  228. package/src/views/CanvasEditor/LayoutContainer.d.ts +0 -17
  229. package/src/views/CanvasEditor/LayoutContainer.d.ts.map +0 -1
  230. package/src/views/CanvasEditor/SaveConfirmationModal.d.ts +0 -13
  231. package/src/views/CanvasEditor/SaveConfirmationModal.d.ts.map +0 -1
  232. package/src/views/CanvasEditor/components/CustomBlockItem.d.ts +0 -14
  233. package/src/views/CanvasEditor/components/CustomBlockItem.d.ts.map +0 -1
  234. package/src/views/CanvasEditor/components/EditorCanvas.d.ts +0 -29
  235. package/src/views/CanvasEditor/components/EditorCanvas.d.ts.map +0 -1
  236. package/src/views/CanvasEditor/components/EditorLibrary.d.ts +0 -7
  237. package/src/views/CanvasEditor/components/EditorLibrary.d.ts.map +0 -1
  238. package/src/views/CanvasEditor/components/EditorSidebar.d.ts +0 -13
  239. package/src/views/CanvasEditor/components/EditorSidebar.d.ts.map +0 -1
  240. package/src/views/CanvasEditor/components/ErrorBanner.d.ts +0 -6
  241. package/src/views/CanvasEditor/components/ErrorBanner.d.ts.map +0 -1
  242. package/src/views/CanvasEditor/components/FeaturedMediaSection.d.ts +0 -25
  243. package/src/views/CanvasEditor/components/FeaturedMediaSection.d.ts.map +0 -1
  244. package/src/views/CanvasEditor/components/LibraryItem.d.ts +0 -14
  245. package/src/views/CanvasEditor/components/LibraryItem.d.ts.map +0 -1
  246. package/src/views/CanvasEditor/components/PrivacySettingsSection.d.ts +0 -15
  247. package/src/views/CanvasEditor/components/PrivacySettingsSection.d.ts.map +0 -1
  248. package/src/views/CanvasEditor/components/index.d.ts +0 -21
  249. package/src/views/CanvasEditor/components/index.d.ts.map +0 -1
  250. package/src/views/CanvasEditor/hooks/index.d.ts +0 -10
  251. package/src/views/CanvasEditor/hooks/index.d.ts.map +0 -1
  252. package/src/views/CanvasEditor/hooks/useHeroBlock.d.ts +0 -8
  253. package/src/views/CanvasEditor/hooks/useHeroBlock.d.ts.map +0 -1
  254. package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts +0 -3
  255. package/src/views/CanvasEditor/hooks/useKeyboardShortcuts.d.ts.map +0 -1
  256. package/src/views/CanvasEditor/hooks/usePostLoader.d.ts +0 -5
  257. package/src/views/CanvasEditor/hooks/usePostLoader.d.ts.map +0 -1
  258. package/src/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts +0 -2
  259. package/src/views/CanvasEditor/hooks/useRegisteredBlocks.d.ts.map +0 -1
  260. package/src/views/CanvasEditor/hooks/useUnsavedChanges.d.ts +0 -25
  261. package/src/views/CanvasEditor/hooks/useUnsavedChanges.d.ts.map +0 -1
  262. package/src/views/CanvasEditor/index.d.ts +0 -16
  263. package/src/views/CanvasEditor/index.d.ts.map +0 -1
  264. package/src/views/PostManager/EmptyState.d.ts +0 -10
  265. package/src/views/PostManager/EmptyState.d.ts.map +0 -1
  266. package/src/views/PostManager/PostActionsMenu.d.ts +0 -12
  267. package/src/views/PostManager/PostActionsMenu.d.ts.map +0 -1
  268. package/src/views/PostManager/PostCards.d.ts +0 -15
  269. package/src/views/PostManager/PostCards.d.ts.map +0 -1
  270. package/src/views/PostManager/PostFilters.d.ts +0 -16
  271. package/src/views/PostManager/PostFilters.d.ts.map +0 -1
  272. package/src/views/PostManager/PostManagerView.d.ts +0 -11
  273. package/src/views/PostManager/PostManagerView.d.ts.map +0 -1
  274. package/src/views/PostManager/PostStats.d.ts +0 -11
  275. package/src/views/PostManager/PostStats.d.ts.map +0 -1
  276. package/src/views/PostManager/PostTable.d.ts +0 -15
  277. package/src/views/PostManager/PostTable.d.ts.map +0 -1
  278. package/src/views/PostManager/index.d.ts +0 -12
  279. package/src/views/PostManager/index.d.ts.map +0 -1
  280. package/src/views/Preview/PreviewBridgeView.d.ts +0 -12
  281. package/src/views/Preview/PreviewBridgeView.d.ts.map +0 -1
  282. package/src/views/Preview/index.d.ts +0 -6
  283. package/src/views/Preview/index.d.ts.map +0 -1
  284. package/src/views/Settings/SettingsView.d.ts +0 -10
  285. package/src/views/Settings/SettingsView.d.ts.map +0 -1
  286. package/src/views/Settings/index.d.ts +0 -6
  287. package/src/views/Settings/index.d.ts.map +0 -1
  288. package/src/views/SlugSEO/SlugSEOManagerView.d.ts +0 -12
  289. package/src/views/SlugSEO/SlugSEOManagerView.d.ts.map +0 -1
  290. package/src/views/SlugSEO/index.d.ts +0 -6
  291. package/src/views/SlugSEO/index.d.ts.map +0 -1
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useState } from 'react';
4
- import { ArrowLeft, Library, Settings2, Clock, Edit, Eye, Globe, ChevronDown } from 'lucide-react';
4
+ import { ArrowLeft, Library, Settings2, Save, Clock, Edit, Eye, Plus, ChevronDown, CheckCircle2 } from 'lucide-react';
5
5
  import { useEditor } from '../../state/EditorContext';
6
6
  import { SaveConfirmationModal } from './SaveConfirmationModal';
7
7
  export function EditorHeader({ isLibraryOpen, onLibraryToggle, isPreviewMode, onPreviewToggle, isSidebarOpen, onSidebarToggle, isSaving, onSave, onSaveError, autoSaveEnabled = false, onAutoSaveToggle, isDirty = false, autoSaveCountdown = null, autoSaveStatus = 'idle', languages = [], currentLanguage = 'en', onLanguageChange, onAddLanguage, }) {
@@ -18,100 +18,64 @@ export function EditorHeader({ isLibraryOpen, onLibraryToggle, isPreviewMode, on
18
18
  fr: 'Français',
19
19
  es: 'Español',
20
20
  };
21
- const availableToAdd = ['en', 'nl', 'sv', 'de', 'fr', 'es'].filter(lang => !languages.includes(lang));
21
+ const getFlagUrl = (lang) => {
22
+ const mapping = {
23
+ en: 'gb', nl: 'nl', sv: 'se', de: 'de', fr: 'fr', es: 'es'
24
+ };
25
+ return `https://flagcdn.com/w40/${(mapping[lang] || lang).toLowerCase()}.png`;
26
+ };
27
+ const allCreatedLanguages = Array.from(new Set([...languages, currentLanguage]));
28
+ const availableToAdd = ['en', 'nl', 'sv', 'de', 'fr', 'es'].filter(lang => !allCreatedLanguages.includes(lang));
22
29
  const handleSaveDraftClick = () => {
23
30
  setSaveAsDraft(true);
24
- setSaveError(null); // Clear any previous errors
31
+ setSaveError(null);
25
32
  setShowConfirmModal(true);
26
33
  };
27
34
  const handlePublishClick = () => {
28
35
  setSaveAsDraft(false);
29
- setSaveError(null); // Clear any previous errors
36
+ setSaveError(null);
30
37
  setShowConfirmModal(true);
31
38
  };
32
39
  const handleConfirmSave = async () => {
33
40
  try {
34
- const targetStatus = saveAsDraft ? 'draft' : 'published';
35
- console.log('[EditorHeader] Starting save process...', { saveAsDraft, targetStatus, currentStatus: state.status });
36
- // Set status before saving - ensure state is updated
37
41
  if (saveAsDraft) {
38
42
  dispatch({ type: 'SET_STATUS', payload: 'draft' });
39
43
  }
40
44
  else {
41
45
  dispatch({ type: 'SET_STATUS', payload: 'published' });
42
46
  }
43
- // Wait longer to ensure state update propagates through the reducer and context
44
- // React state updates are asynchronous, so we need to wait for the state to actually update
45
47
  await new Promise(resolve => setTimeout(resolve, 150));
46
- // Verify status was updated
47
- console.log('[EditorHeader] Status after update:', state.status, 'Expected:', targetStatus);
48
48
  await onSave(!saveAsDraft);
49
- console.log('[EditorHeader] Post saved successfully');
50
- // Clear any previous errors
51
49
  setSaveError(null);
52
- // Modal will show success message and close automatically
53
50
  }
54
51
  catch (error) {
55
- console.error('[EditorHeader] Failed to save post:', error);
56
- // Extract user-friendly error message
57
52
  let errorMessage = error.message || 'Failed to save post';
58
- // Make error messages more user-friendly
59
- if (errorMessage.includes('Missing required fields')) {
60
- // Keep the detailed message about missing fields
61
- errorMessage = errorMessage.replace('Missing required fields for publishing:', 'To publish, please fill in:');
62
- }
63
- else if (errorMessage.includes('All required fields')) {
64
- errorMessage = 'To publish, please fill in all required fields: summary, featured image, category, and content.';
65
- }
66
- else if (errorMessage.includes('Unauthorized')) {
67
- errorMessage = 'You are not authorized to save this post. Please log in again.';
68
- }
69
- else if (errorMessage.includes('Failed to save')) {
70
- errorMessage = 'Unable to save the post. Please check your connection and try again.';
71
- }
72
53
  setSaveError(errorMessage);
73
54
  onSaveError(errorMessage);
74
- // Re-throw the error so the modal knows it failed and doesn't show success
75
55
  throw error;
76
56
  }
77
57
  };
78
- return (_jsxs("div", { className: "flex items-center justify-between px-6 py-3 bg-dashboard-sidebar backdrop-blur-md border-b border-dashboard-border flex-none shrink-0", children: [_jsxs("div", { className: "flex items-center gap-6", children: [_jsx("button", { onClick: () => {
58
+ return (_jsxs("div", { className: "flex items-center justify-between px-4 lg:px-8 py-3 lg:py-4 bg-dashboard-bg/80 backdrop-blur-xl border-b border-dashboard-border/50 flex-none shrink-0 z-50", children: [_jsxs("div", { className: "flex items-center gap-3 lg:gap-6", children: [_jsx("button", { onClick: () => {
79
59
  if (isDirty) {
80
- const confirmed = window.confirm('You have unsaved changes. Are you sure you want to leave? Your changes will be lost.');
81
- if (!confirmed) {
60
+ if (!window.confirm('You have unsaved changes. Leave anyway?'))
82
61
  return;
83
- }
84
62
  }
85
63
  window.location.href = '/dashboard/blog';
86
- }, className: "text-neutral-500 dark:text-neutral-400 hover:text-neutral-950 dark:hover:text-white transition-colors", children: _jsx(ArrowLeft, { size: 20, strokeWidth: 1.5 }) }), _jsx("div", { className: "h-4 w-[1px] bg-neutral-300 dark:border-neutral-700" }), _jsxs("button", { onClick: onLibraryToggle, className: `flex items-center gap-2 text-[10px] uppercase tracking-widest font-black transition-all ${isLibraryOpen ? 'text-dashboard-text' : 'text-neutral-500 dark:text-neutral-400'}`, children: [_jsx(Library, { size: 16, strokeWidth: 1.5 }), "Library"] }), languages.length > 0 && onLanguageChange && (_jsxs(_Fragment, { children: [_jsx("div", { className: "h-4 w-[1px] bg-neutral-300 dark:border-neutral-700" }), _jsxs("div", { className: "relative", children: [_jsxs("button", { onClick: () => setShowLanguageDropdown(!showLanguageDropdown), className: "flex items-center gap-2 px-3 py-2 text-[10px] uppercase tracking-widest font-bold bg-dashboard-card border border-dashboard-border rounded-lg text-neutral-600 dark:text-neutral-400 hover:text-dashboard-text hover:border-primary/50 transition-all shadow-sm", children: [_jsx(Globe, { size: 14, strokeWidth: 1.5 }), _jsx("span", { children: languageLabels[currentLanguage] || currentLanguage.toUpperCase() }), _jsx(ChevronDown, { size: 12, className: `transition-transform ${showLanguageDropdown ? 'rotate-180' : ''}` })] }), showLanguageDropdown && (_jsxs("div", { className: "absolute top-full left-0 mt-2 py-1 bg-dashboard-card border border-dashboard-border rounded-lg shadow-xl z-[9999] min-w-[160px] overflow-hidden", children: [_jsx("div", { className: "px-3 py-2 text-[9px] text-neutral-500 uppercase tracking-wider border-b border-dashboard-border", children: "Beschikbare Talen" }), languages.map(lang => (_jsx("button", { onClick: () => {
87
- onLanguageChange(lang);
64
+ }, className: "size-9 lg:size-10 flex items-center justify-center bg-dashboard-card border border-dashboard-border rounded-xl text-dashboard-text-secondary hover:text-primary hover:border-primary/30 transition-all active:scale-95 shadow-sm", children: _jsx(ArrowLeft, { className: "size-[18px] lg:size-[20px]" }) }), _jsx("div", { className: "h-6 lg:h-8 w-px bg-dashboard-border/30" }), _jsxs("button", { onClick: onLibraryToggle, className: `flex items-center gap-2 lg:gap-3 px-3 lg:px-5 py-2 lg:py-2.5 rounded-xl text-[10px] font-black uppercase tracking-[0.2em] transition-all border ${isLibraryOpen
65
+ ? 'bg-primary text-white border-primary/20 shadow-lg shadow-primary/20'
66
+ : 'bg-dashboard-card text-dashboard-text-secondary border-dashboard-border hover:border-primary/30'}`, children: [_jsx(Library, { size: 16 }), _jsx("span", { className: "hidden xl:inline", children: "Blocks Library" }), _jsx("span", { className: "xl:hidden hidden lg:inline text-[8px]", children: "Blocks" })] }), languages.length > 0 && onLanguageChange && (_jsxs("div", { className: "relative group", children: [_jsxs("button", { onClick: () => setShowLanguageDropdown(!showLanguageDropdown), className: "flex items-center gap-2 lg:gap-3 px-3 lg:px-4 py-2 lg:py-2.5 bg-dashboard-card border border-dashboard-border rounded-xl hover:border-primary/30 transition-all shadow-sm", children: [_jsx("img", { src: getFlagUrl(currentLanguage), className: "w-4 h-2.5 lg:w-5 lg:h-3.5 object-cover rounded-sm border border-white/20", alt: "" }), _jsx("span", { className: "text-[10px] font-black uppercase tracking-widest text-dashboard-text-secondary", children: currentLanguage.toUpperCase() }), _jsx(ChevronDown, { className: `size-[12px] lg:size-[14px] text-dashboard-text-secondary transition-transform ${showLanguageDropdown ? 'rotate-180' : ''}` })] }), showLanguageDropdown && (_jsxs("div", { className: "absolute top-full left-0 mt-3 p-2 bg-dashboard-bg/95 backdrop-blur-2xl border border-dashboard-border rounded-2xl shadow-2xl z-[100] min-w-[180px] animate-in fade-in zoom-in-95 duration-200", children: [_jsx("label", { className: "px-3 py-2 text-[8px] font-black text-dashboard-text-secondary uppercase tracking-[0.3em] block border-b border-dashboard-border/30 mb-1", children: "Switch Edition" }), allCreatedLanguages.map(lang => (_jsxs("button", { onClick: () => {
67
+ onLanguageChange(lang);
68
+ setShowLanguageDropdown(false);
69
+ }, className: `w-full flex items-center gap-3 px-3 py-2.5 rounded-xl transition-all ${lang === currentLanguage
70
+ ? 'bg-primary/10 text-primary font-bold'
71
+ : 'text-dashboard-text-secondary hover:bg-white/5 hover:text-dashboard-text'}`, children: [_jsx("img", { src: getFlagUrl(lang), className: "w-4 h-3 object-cover rounded-sm", alt: "" }), _jsx("span", { className: "text-[10px] font-black uppercase tracking-widest", children: languageLabels[lang] || lang.toUpperCase() })] }, lang))), availableToAdd.length > 0 && onAddLanguage && (_jsxs(_Fragment, { children: [_jsx("div", { className: "my-2 border-t border-dashboard-border/30 mx-2" }), _jsx("label", { className: "px-3 py-2 text-[8px] font-black text-dashboard-text-secondary uppercase tracking-[0.3em] block mb-1", children: "Add Edition" }), availableToAdd.map(lang => (_jsxs("button", { onClick: () => {
72
+ onAddLanguage(lang);
88
73
  setShowLanguageDropdown(false);
89
- }, className: `w-full text-left px-3 py-2 text-[10px] uppercase tracking-wider transition-colors ${lang === currentLanguage
90
- ? 'bg-primary/10 text-primary font-bold'
91
- : 'text-neutral-600 dark:text-neutral-400 hover:bg-dashboard-bg hover:text-dashboard-text'}`, children: languageLabels[lang] || lang.toUpperCase() }, lang))), availableToAdd.length > 0 && onAddLanguage && (_jsxs(_Fragment, { children: [_jsx("div", { className: "my-1 border-t border-dashboard-border" }), _jsx("div", { className: "px-3 py-1 text-[9px] text-neutral-500 uppercase tracking-wider", children: "Add Language" }), availableToAdd.slice(0, 3).map(lang => (_jsxs("button", { onClick: () => {
92
- onAddLanguage(lang);
93
- setShowLanguageDropdown(false);
94
- }, className: "w-full text-left px-3 py-2 text-[10px] uppercase tracking-wider text-neutral-600 dark:text-neutral-400 hover:bg-dashboard-bg hover:text-dashboard-text transition-colors", children: ["+ ", languageLabels[lang] || lang.toUpperCase()] }, lang)))] }))] }))] })] }))] }), _jsxs("div", { className: "flex items-center gap-4", children: [onAutoSaveToggle && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("button", { onClick: () => onAutoSaveToggle(!autoSaveEnabled), className: `relative flex items-center gap-2 px-3 py-1.5 rounded-full text-[10px] uppercase tracking-widest font-bold transition-all ${autoSaveEnabled
95
- ? 'bg-primary/20 text-primary border border-primary/30'
96
- : 'bg-dashboard-bg text-neutral-600 dark:text-neutral-400 border border-dashboard-border hover:text-neutral-950 dark:hover:text-white'}`, title: autoSaveEnabled ? 'Auto-save enabled (saves after 10s of inactivity)' : 'Click to enable auto-save', children: [_jsx(Clock, { size: 12, className: autoSaveEnabled && autoSaveStatus !== 'saving' ? 'animate-pulse' : '' }), _jsx("span", { children: "Auto-save" }), _jsx("span", { className: `ml-1 text-[9px] ${autoSaveEnabled ? 'text-primary' : 'text-neutral-500 dark:text-neutral-400'}`, children: autoSaveEnabled ? 'ON' : 'OFF' }), autoSaveEnabled && isDirty && (_jsxs("span", { className: "ml-1.5 text-[9px] font-bold tabular-nums", children: [autoSaveStatus === 'saving' && (_jsx("span", { className: "text-primary animate-pulse", children: "Saving..." })), autoSaveStatus === 'saved' && (_jsx("span", { className: "text-green-500 dark:text-green-400", children: "Saved!" })), autoSaveStatus === 'error' && (_jsx("span", { className: "text-red-500 dark:text-red-400", children: "Error" })), autoSaveStatus === 'idle' && autoSaveCountdown !== null && (_jsxs("span", { className: "text-primary/70", children: [autoSaveCountdown, "s"] }))] }))] }), isDirty && !autoSaveEnabled && (_jsx("span", { className: "text-[10px] text-amber-500 dark:text-amber-400 font-bold uppercase tracking-widest animate-pulse", children: "Unsaved" }))] })), _jsxs("div", { className: "flex items-center bg-dashboard-bg border border-dashboard-border rounded-full p-1 gap-1", children: [_jsxs("button", { onClick: () => {
97
- if (isPreviewMode) {
98
- onPreviewToggle();
99
- }
100
- }, className: `flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[10px] uppercase tracking-widest font-bold transition-all ${!isPreviewMode
101
- ? 'bg-primary text-white shadow-sm'
102
- : 'text-neutral-600 dark:text-neutral-400 hover:text-neutral-950 dark:hover:text-white'}`, title: "Edit mode - Make changes to your post", children: [_jsx(Edit, { size: 12, strokeWidth: 2.5 }), _jsx("span", { children: "Edit" })] }), _jsxs("button", { onClick: () => {
103
- if (!isPreviewMode) {
104
- onPreviewToggle();
105
- }
106
- }, className: `flex items-center gap-1.5 px-3 py-1.5 rounded-full text-[10px] uppercase tracking-widest font-bold transition-all ${isPreviewMode
107
- ? 'bg-primary text-white shadow-sm'
108
- : 'text-neutral-600 dark:text-neutral-400 hover:text-neutral-950 dark:hover:text-white'}`, title: "Preview mode - See how your post will look", children: [_jsx(Eye, { size: 12, strokeWidth: 2.5 }), _jsx("span", { children: "Preview" })] })] }), (state.status === 'draft' || !state.postId) && (_jsx("button", { onClick: handleSaveDraftClick, disabled: isSaving, className: `px-4 py-2 border-2 border-dashboard-border text-dashboard-text rounded-full text-[10px] font-bold uppercase tracking-widest transition-all ${isSaving
109
- ? 'opacity-50 cursor-not-allowed'
110
- : 'hover:bg-dashboard-bg'}`, children: isSaving ? 'Saving...' : 'Save Draft' })), _jsx("button", { onClick: handlePublishClick, disabled: isSaving, className: `px-6 py-2 bg-primary text-white rounded-full text-[10px] font-bold uppercase tracking-widest transition-all shadow-lg shadow-primary/20 ${isSaving
111
- ? 'opacity-50 cursor-not-allowed'
112
- : 'hover:bg-primary/90'}`, children: isSaving ? 'Saving...' : state.status === 'published' ? 'Update Post' : 'Publish Post' }), _jsx("button", { onClick: onSidebarToggle, className: `p-2 rounded-full transition-colors ${isSidebarOpen
113
- ? 'bg-dashboard-bg text-dashboard-text'
114
- : 'text-neutral-500 dark:text-neutral-400 hover:bg-dashboard-bg'}`, children: _jsx(Settings2, { size: 18 }) })] }), _jsx(SaveConfirmationModal, { isOpen: showConfirmModal, onClose: () => {
74
+ }, className: "w-full flex items-center gap-3 px-3 py-2.5 rounded-xl text-dashboard-text-secondary hover:bg-primary/10 hover:text-primary transition-all group/add", children: [_jsxs("div", { className: "relative", children: [_jsx("img", { src: getFlagUrl(lang), className: "w-4 h-3 object-cover rounded-sm opacity-60 group-hover/add:opacity-100 transition-opacity", alt: "" }), _jsx("div", { className: "absolute -top-1 -right-1 size-2 bg-primary rounded-full border border-dashboard-bg flex items-center justify-center text-[6px] text-white font-bold", children: "+" })] }), _jsx("span", { className: "text-[10px] font-black uppercase tracking-widest", children: languageLabels[lang] || lang.toUpperCase() })] }, lang)))] }))] }))] }))] }), _jsxs("div", { className: "hidden md:flex items-center gap-2 lg:gap-4", children: [state.status === 'published' && (_jsxs("div", { className: "flex items-center gap-2 px-3 lg:px-4 py-1.5 bg-emerald-500/10 border border-emerald-500/20 rounded-full text-emerald-500", children: [_jsx(CheckCircle2, { size: 12, className: "animate-pulse" }), _jsx("span", { className: "text-[9px] font-black uppercase tracking-[0.2em] hidden lg:inline", children: "Live Edition" }), _jsx("span", { className: "text-[9px] font-black uppercase tracking-[0.2em] lg:hidden", children: "Live" })] })), state.status === 'not-translated' && (_jsxs("div", { className: "flex items-center gap-2 px-3 lg:px-4 py-1.5 bg-blue-500/10 border border-blue-500/20 rounded-full text-blue-500", children: [_jsx(Plus, { size: 12 }), _jsx("span", { className: "text-[9px] font-black uppercase tracking-[0.2em] hidden lg:inline", children: "New Edition" }), _jsx("span", { className: "text-[9px] font-black uppercase tracking-[0.2em] lg:hidden", children: "New" })] })), isDirty && !autoSaveEnabled && (_jsxs("div", { className: "flex items-center gap-2 px-3 lg:px-4 py-1.5 bg-amber-500/10 border border-amber-500/20 rounded-full text-amber-500 animate-pulse", children: [_jsx(Clock, { size: 12 }), _jsx("span", { className: "text-[9px] font-black uppercase tracking-[0.2em] hidden lg:inline", children: "Unsaved Edits" }), _jsx("span", { className: "text-[9px] font-black uppercase tracking-[0.2em] lg:hidden", children: "Dirty" })] }))] }), _jsxs("div", { className: "flex items-center gap-2 lg:gap-4", children: [onAutoSaveToggle && (_jsxs("button", { onClick: () => onAutoSaveToggle(!autoSaveEnabled), className: `group flex items-center gap-2 lg:gap-3 px-3 lg:px-4 py-2 lg:py-2.5 rounded-xl border transition-all ${autoSaveEnabled
75
+ ? 'bg-primary/10 border-primary/30 text-primary'
76
+ : 'bg-dashboard-card border border-dashboard-border text-dashboard-text-secondary'}`, children: [_jsx(Clock, { size: 14, className: autoSaveEnabled && autoSaveStatus === 'saving' ? 'animate-spin' : '' }), _jsx("span", { className: "text-[9px] font-black uppercase tracking-widest hidden lg:inline", children: autoSaveStatus === 'saving' ? 'Syncing...' : 'Auto-Sync' }), _jsx("div", { className: `size-1.5 rounded-full ${autoSaveEnabled ? 'bg-primary animate-pulse' : 'bg-dashboard-text-secondary/30'}` })] })), _jsxs("div", { className: "flex items-center bg-dashboard-card border border-dashboard-border rounded-xl p-1 shadow-inner", children: [_jsxs("button", { onClick: () => isPreviewMode && onPreviewToggle(), className: `flex items-center gap-2 px-3 lg:px-4 py-1.5 lg:py-2 rounded-lg text-[10px] font-black uppercase tracking-widest transition-all ${!isPreviewMode ? 'bg-primary text-white shadow-md' : 'text-dashboard-text-secondary hover:text-dashboard-text'}`, children: [_jsx(Edit, { size: 12 }), _jsx("span", { className: "hidden sm:inline", children: "Edit" })] }), _jsxs("button", { onClick: () => !isPreviewMode && onPreviewToggle(), className: `flex items-center gap-2 px-3 lg:px-4 py-1.5 lg:py-2 rounded-lg text-[10px] font-black uppercase tracking-widest transition-all ${isPreviewMode ? 'bg-primary text-white shadow-md' : 'text-dashboard-text-secondary hover:text-dashboard-text'}`, children: [_jsx(Eye, { size: 12 }), _jsx("span", { className: "hidden sm:inline", children: "View" })] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [state.status !== 'published' && (_jsxs("button", { onClick: handleSaveDraftClick, disabled: isSaving, className: "px-4 lg:px-6 py-2 lg:py-2.5 bg-dashboard-card border border-dashboard-border text-dashboard-text-secondary rounded-xl text-[10px] font-black uppercase tracking-[0.2em] hover:border-primary/30 transition-all active:scale-95", children: [_jsx("span", { className: "hidden lg:inline", children: isSaving ? '...' : 'Save Draft' }), _jsx("span", { className: "lg:hidden", children: isSaving ? '...' : 'Draft' })] })), _jsxs("button", { onClick: handlePublishClick, disabled: isSaving, className: "px-5 lg:px-8 py-2 lg:py-2.5 bg-primary text-white rounded-xl text-[10px] font-black uppercase tracking-[0.3em] shadow-xl shadow-primary/20 hover:scale-[1.02] active:scale-95 transition-all", children: [_jsx("span", { className: "hidden lg:inline", children: isSaving ? 'Publishing...' : state.status === 'published' ? 'Update Live' : 'Go Live' }), _jsx(Save, { size: 14, className: "lg:hidden" })] })] }), _jsx("button", { onClick: onSidebarToggle, className: `size-9 lg:size-10 flex items-center justify-center rounded-xl transition-all border ${isSidebarOpen
77
+ ? 'bg-primary/10 border-primary/30 text-primary shadow-lg shadow-primary/10'
78
+ : 'bg-dashboard-card border border-dashboard-border text-dashboard-text-secondary hover:border-primary/30'}`, children: _jsx(Settings2, { className: "size-[18px] lg:size-[20px]" }) })] }), _jsx(SaveConfirmationModal, { isOpen: showConfirmModal, onClose: () => {
115
79
  setShowConfirmModal(false);
116
80
  setSaveAsDraft(false);
117
81
  setSaveError(null);
@@ -1 +1 @@
1
- {"version":3,"file":"LayoutContainer.d.ts","sourceRoot":"","sources":["../../../src/views/CanvasEditor/LayoutContainer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI1C,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACvE,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACvF,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,eAAe,CAAC,EAC5B,MAAM,EACN,WAAW,EACX,UAAU,EACV,aAAa,EACb,aAAa,EACb,WAAW,EACX,SAAc,EACd,UAA+B,GAClC,EAAE,oBAAoB,2CA6OtB"}
1
+ {"version":3,"file":"LayoutContainer.d.ts","sourceRoot":"","sources":["../../../src/views/CanvasEditor/LayoutContainer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAI1C,MAAM,WAAW,oBAAoB;IACjC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACvE,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACvF,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,eAAe,CAAC,EAC5B,MAAM,EACN,WAAW,EACX,UAAU,EACV,aAAa,EACb,aAAa,EACb,WAAW,EACX,SAAc,EACd,UAA+B,GAClC,EAAE,oBAAoB,2CAwOtB"}
@@ -9,7 +9,7 @@ import { Plus } from 'lucide-react';
9
9
  import { BlockWrapper } from './BlockWrapper';
10
10
  import { useEditor } from '../../state/EditorContext';
11
11
  export function LayoutContainer({ blocks, containerId, onBlockAdd, onBlockUpdate, onBlockDelete, onBlockMove, className = '', emptyLabel = 'Drop blocks here', }) {
12
- const { darkMode } = useEditor();
12
+ const { darkMode, helpers } = useEditor();
13
13
  // --- State ---
14
14
  const [dragOverIndex, setDragOverIndex] = useState(null);
15
15
  const [dropAtEnd, setDropAtEnd] = useState(false);
@@ -21,27 +21,34 @@ export function LayoutContainer({ blocks, containerId, onBlockAdd, onBlockUpdate
21
21
  const dropAtEndRef = useRef(false);
22
22
  // --- Cleanup & Event Listeners ---
23
23
  useEffect(() => {
24
- const resetState = () => {
24
+ const resetState = (e) => {
25
+ // Only reset if this is the container that was actually being dragged over
26
+ // or if it's a global dragend event
25
27
  setDropIndicatorPosition(null);
26
28
  setDragOverIndex(null);
27
29
  setDropAtEnd(false);
28
- dropAtEndRef.current = false; // Reset ref too
30
+ dropAtEndRef.current = false;
29
31
  setIsDragging(false);
30
- // Clear global dragged block ID on dragend (in case drag was cancelled)
31
- if (typeof window !== 'undefined') {
32
- window.__DRAGGED_BLOCK_ID__ = null;
33
- }
34
32
  };
35
33
  const container = containerRef.current;
36
34
  if (container) {
37
35
  container.addEventListener('clear-drop-indicator', resetState);
38
- document.addEventListener('dragend', resetState);
36
+ // Listen for dragend on the document but ONLY if we are currently dragging
37
+ const handleGlobalDragEnd = () => {
38
+ if (isDragging) {
39
+ resetState(new Event('dragend'));
40
+ if (typeof window !== 'undefined') {
41
+ window.__DRAGGED_BLOCK_ID__ = null;
42
+ }
43
+ }
44
+ };
45
+ document.addEventListener('dragend', handleGlobalDragEnd);
39
46
  return () => {
40
47
  container.removeEventListener('clear-drop-indicator', resetState);
41
- document.removeEventListener('dragend', resetState);
48
+ document.removeEventListener('dragend', handleGlobalDragEnd);
42
49
  };
43
50
  }
44
- }, []);
51
+ }, [isDragging]);
45
52
  // --- Drag & Drop Logic ---
46
53
  const handleDragOverBlock = (e, index, element) => {
47
54
  e.preventDefault();
@@ -119,65 +126,32 @@ export function LayoutContainer({ blocks, containerId, onBlockAdd, onBlockUpdate
119
126
  const handleDrop = (e, index) => {
120
127
  e.preventDefault();
121
128
  e.stopPropagation();
122
- const blockId = e.dataTransfer.getData('block-id') || window.__DRAGGED_BLOCK_ID__;
123
- const blockType = e.dataTransfer.getData('block-type');
124
- // Clear the global dragged block ID immediately to prevent it from being used for new blocks
129
+ // MATCHING KEYS: use blockId and blockType (not hyphenated)
130
+ const blockId = e.dataTransfer.getData('blockId') || window.__DRAGGED_BLOCK_ID__ || e.dataTransfer.getData('text/plain');
131
+ const blockType = e.dataTransfer.getData('blockType');
132
+ // Clear the global dragged block ID immediately
125
133
  if (typeof window !== 'undefined') {
126
134
  window.__DRAGGED_BLOCK_ID__ = null;
127
135
  }
128
- // Logic: index is null when dropping on the container background (appends to end)
129
- // When dropAtEnd is true, we want to place it AFTER the block at index, so targetIndex = index + 1
130
- // When dropAtEnd is false, we want to place it BEFORE the block at index, so targetIndex = index
131
- // Use ref to get the latest value (React state updates are async)
132
136
  const isDropAtEnd = dropAtEndRef.current;
133
137
  let targetIndex = index === null ? blocks.length : (isDropAtEnd ? index + 1 : index);
134
138
  if (blockId) {
135
139
  const currentIndex = blocks.findIndex(b => b.id === blockId);
136
140
  if (currentIndex !== -1) {
137
- // Moving within the same array - need to adjust for removal
141
+ // Moving within same container
138
142
  let finalMoveIndex = targetIndex;
139
143
  if (currentIndex < targetIndex) {
140
- // Moving forward: when we remove the item from currentIndex, everything after it shifts down by 1.
141
- if (isDropAtEnd) {
142
- // Dropping below: we want it at index + 1 in the original array
143
- // If currentIndex <= index: after removal, block at index stays at index, so we want index + 1 = targetIndex
144
- // If index < currentIndex < targetIndex: after removal, we still want index + 1, but since we removed
145
- // an item before targetIndex, the position targetIndex in original = targetIndex - 1 in new array
146
- if (index !== null && currentIndex <= index) {
147
- // Item is at or before target block - no adjustment needed
148
- finalMoveIndex = targetIndex;
149
- }
150
- else {
151
- // Item is after target block but before targetIndex - need to adjust
152
- finalMoveIndex = targetIndex - 1;
153
- }
154
- }
155
- else {
156
- // Dropping above: targetIndex = index means "before the block at index"
157
- // After removal, if currentIndex < index, the block at index shifts to index - 1,
158
- // so we want it at index - 1 in the new array.
159
- finalMoveIndex = targetIndex - 1;
160
- }
144
+ finalMoveIndex = targetIndex - 1;
161
145
  }
162
- // If currentIndex >= targetIndex, no adjustment needed (moving backward or same position)
163
- console.log('[LayoutContainer] Drop calculation:', {
164
- blockId,
165
- index,
166
- dropAtEnd: isDropAtEnd,
167
- currentIndex,
168
- targetIndex,
169
- finalMoveIndex,
170
- blocksCount: blocks.length
171
- });
172
146
  onBlockMove(blockId, Math.max(0, finalMoveIndex), containerId);
173
147
  }
174
148
  else {
175
- // Moving from another container - no adjustment needed
149
+ // Moving from different container
176
150
  onBlockMove(blockId, targetIndex, containerId);
177
151
  }
178
152
  }
179
153
  else if (blockType) {
180
- // Adding new block - use targetIndex as-is
154
+ // Adding new block
181
155
  onBlockAdd(blockType, targetIndex, containerId);
182
156
  }
183
157
  // Clean up
@@ -191,32 +165,37 @@ export function LayoutContainer({ blocks, containerId, onBlockAdd, onBlockUpdate
191
165
  else
192
166
  blockRefs.current.delete(id);
193
167
  };
194
- return (_jsxs("div", { ref: containerRef, "data-layout-container": containerId, className: `relative flex flex-col min-h-[40px] transition-colors ${className}`, onDragOver: (e) => { e.preventDefault(); setIsDragging(true); }, onDrop: (e) => handleDrop(e, null), onDragLeave: (e) => {
168
+ return (_jsxs("div", { ref: containerRef, "data-layout-container": containerId, className: `relative flex flex-col min-h-[40px] transition-colors pb-2 ${className}`, onDragEnter: (e) => {
169
+ e.preventDefault();
170
+ e.stopPropagation();
171
+ setIsDragging(true);
172
+ }, onDragOver: (e) => {
173
+ e.preventDefault();
174
+ e.stopPropagation();
175
+ setIsDragging(true);
176
+ }, onDrop: (e) => handleDrop(e, null), onDragLeave: (e) => {
195
177
  if (!e.currentTarget.contains(e.relatedTarget)) {
178
+ setIsDragging(false);
196
179
  setDropIndicatorPosition(null);
197
180
  }
198
- }, children: [dropIndicatorPosition && isDragging && (_jsx(DropIndicator, { position: dropIndicatorPosition, darkMode: darkMode })), blocks.length === 0 ? (_jsx(EmptyState, { isDragging: isDragging, darkMode: darkMode, label: emptyLabel })) : (blocks.map((block, index) => (_jsx("div", { ref: setBlockRef(block.id), onDragOver: (e) => handleDragOverBlock(e, index, blockRefs.current.get(block.id)), onDrop: (e) => handleDrop(e, index), className: "relative mb-4 last:mb-0", children: _jsx(BlockWrapper, { block: block, onUpdate: (data) => onBlockUpdate(block.id, data, containerId), onDelete: () => onBlockDelete(block.id, containerId), onMoveUp: index > 0 ? () => onBlockMove(block.id, index - 1, containerId) : undefined, onMoveDown: index < blocks.length - 1 ? () => onBlockMove(block.id, index + 1, containerId) : undefined }) }, block.id))))] }));
181
+ }, children: [dropIndicatorPosition && isDragging && (_jsx(DropIndicator, { position: dropIndicatorPosition, darkMode: darkMode })), blocks.length === 0 ? (_jsx(EmptyState, { isDragging: isDragging, darkMode: darkMode, label: emptyLabel })) : (blocks.map((block, index) => (_jsx("div", { ref: setBlockRef(block.id), onDragOver: (e) => handleDragOverBlock(e, index, blockRefs.current.get(block.id)), onDrop: (e) => handleDrop(e, index), className: "relative mb-4 last:mb-0", children: _jsx(BlockWrapper, { block: block, onUpdate: (data) => onBlockUpdate(block.id, data, containerId), onDelete: () => onBlockDelete(block.id, containerId), onDuplicate: () => helpers.duplicateBlock(block.id), onMoveUp: index > 0 ? () => onBlockMove(block.id, index - 1, containerId) : undefined, onMoveDown: index < blocks.length - 1 ? () => onBlockMove(block.id, index + 1, containerId) : undefined,
182
+ // Essential for nested rendering: pass children and handlers to the Edit component
183
+ childBlocks: Array.isArray(block.children) && typeof block.children[0] === 'object' ? block.children : [], onChildBlockAdd: (type, idx, cid) => onBlockAdd(type, idx ?? 0, cid || containerId), onChildBlockUpdate: (bid, data, cid) => onBlockUpdate(bid, data, cid || containerId), onChildBlockDelete: (bid, cid) => onBlockDelete(bid, cid || containerId), onChildBlockMove: (bid, idx, cid) => onBlockMove(bid, idx, cid || containerId) }) }, block.id))))] }));
199
184
  }
200
185
  /**
201
- * Visual Line that shows where the block will land
186
+ * Visual Components
202
187
  */
203
188
  function DropIndicator({ position, darkMode }) {
204
- return (_jsxs("div", { className: "absolute z-50 pointer-events-none", style: {
205
- top: `${position.top - 12}px`,
206
- left: `${position.left}px`,
207
- width: `${position.width}px`,
208
- height: '24px',
209
- }, children: [_jsx("div", { className: `absolute inset-0 rounded-lg border border-dashed backdrop-blur-sm
210
- ${darkMode ? 'bg-primary/20 border-primary/40' : 'bg-primary/10 border-primary/30'}` }), _jsx("div", { className: `absolute top-1/2 left-0 right-0 h-0.5 transform -translate-y-1/2
211
- ${darkMode ? 'bg-primary' : 'bg-primary'}` }), _jsx("div", { className: "absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2", children: _jsx("div", { className: "w-6 h-6 rounded-full flex items-center justify-center bg-primary shadow-lg", children: _jsx("div", { className: "w-2 h-2 rounded-full bg-white" }) }) })] }));
189
+ return (_jsxs("div", { className: "absolute z-50 pointer-events-none transition-all duration-150 ease-out", style: {
190
+ top: position.top,
191
+ left: position.left,
192
+ width: position.width,
193
+ height: '4px',
194
+ marginTop: '-2px', // Center on the line
195
+ }, children: [_jsx("div", { className: "w-full h-full bg-primary rounded-full shadow-[0_0_8px_rgba(var(--primary-rgb),0.5)] animate-pulse" }), _jsx("div", { className: "absolute left-0 top-1/2 -translate-y-1/2 -translate-x-1 w-2 h-2 rounded-full bg-primary" }), _jsx("div", { className: "absolute right-0 top-1/2 -translate-y-1/2 translate-x-1 w-2 h-2 rounded-full bg-primary" })] }));
212
196
  }
213
- /**
214
- * Placeholder when the container is empty
215
- */
216
197
  function EmptyState({ isDragging, darkMode, label }) {
217
- return (_jsxs("div", { className: `flex flex-col items-center justify-center py-12 px-6 rounded-2xl border border-dashed transition-all
218
- ${darkMode
219
- ? isDragging ? 'border-primary/50 bg-primary/10' : 'border-neutral-700 bg-neutral-800/20'
220
- : isDragging ? 'border-primary/50 bg-primary/5' : 'border-neutral-200 bg-neutral-50/30'}`, children: [_jsx("div", { className: `p-3 rounded-full mb-3 ${darkMode ? 'bg-neutral-800' : 'bg-neutral-100'}`, children: _jsx(Plus, { size: 20, className: isDragging ? 'text-primary' : 'text-neutral-400' }) }), _jsx("p", { className: `text-xs font-black uppercase tracking-wider
221
- ${isDragging ? 'text-primary' : 'text-neutral-500'}`, children: isDragging ? 'Drop Block Here' : label })] }));
198
+ return (_jsxs("div", { className: `flex flex-col items-center justify-center py-10 rounded-2xl border-2 border-dashed transition-all duration-300 ${isDragging
199
+ ? 'border-primary bg-primary/5 scale-[0.98]'
200
+ : 'border-neutral-200 dark:border-neutral-800 bg-neutral-50/50 dark:bg-neutral-900/20'}`, children: [_jsx(Plus, { size: 24, className: `mb-2 transition-colors ${isDragging ? 'text-primary' : 'text-neutral-300 dark:text-neutral-700'}` }), _jsx("span", { className: `text-[10px] font-bold uppercase tracking-widest ${isDragging ? 'text-primary' : 'text-neutral-400 dark:text-neutral-600'}`, children: label })] }));
222
201
  }
@@ -40,5 +40,5 @@ export function CustomBlockItem({ blockType, name, description, icon, onAddBlock
40
40
  mouseDownRef.current = null;
41
41
  setTimeout(() => setHasDragged(false), 100);
42
42
  };
43
- return (_jsxs("div", { draggable: true, onDragStart: handleDragStart, onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onClick: handleClick, className: "p-4 rounded-xl border border-dashboard-border bg-dashboard-bg hover:border-primary cursor-pointer transition-all group", title: description, children: [_jsxs("div", { className: "flex items-center justify-between mb-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "text-neutral-500 dark:text-neutral-400 group-hover:text-primary dark:group-hover:text-primary transition-colors", children: icon }), _jsx("span", { className: "text-[10px] font-bold uppercase tracking-wider text-neutral-700 dark:text-neutral-300 group-hover:text-neutral-950 dark:group-hover:text-white transition-colors", children: name })] }), _jsx(GripVertical, { size: 12, className: "text-neutral-400 dark:text-neutral-500 group-hover:text-neutral-600 dark:group-hover:text-neutral-400" })] }), description && (_jsx("p", { className: "text-[9px] text-neutral-500 dark:text-neutral-400 leading-relaxed line-clamp-2", children: description }))] }));
43
+ return (_jsxs("div", { draggable: true, onDragStart: handleDragStart, onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onClick: handleClick, className: "p-5 rounded-[1.5rem] border border-dashboard-border/50 bg-dashboard-card/30 backdrop-blur-sm hover:border-primary/40 hover:bg-primary/[0.02] hover:shadow-2xl hover:shadow-primary/10 transition-all duration-500 cursor-grab active:cursor-grabbing group", title: description, children: [_jsxs("div", { className: "flex items-center justify-between mb-3", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("div", { className: "text-dashboard-text-secondary group-hover:text-primary transition-all duration-500 group-hover:scale-110", children: icon }), _jsx("span", { className: "text-[10px] font-black uppercase tracking-[0.2em] text-dashboard-text-secondary group-hover:text-dashboard-text transition-colors", children: name })] }), _jsx(GripVertical, { size: 14, className: "text-dashboard-text-secondary/30 group-hover:text-primary transition-colors" })] }), description && (_jsx("p", { className: "text-[9px] text-dashboard-text-secondary/60 leading-relaxed line-clamp-2 italic font-medium", children: description }))] }));
44
44
  }
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  import type { Block } from '../../../types/block';
2
3
  import type { BlockTypeDefinition } from '../../../types/block';
3
4
  export interface EditorCanvasProps {
@@ -9,21 +10,32 @@ export interface EditorCanvasProps {
9
10
  siteId: string;
10
11
  locale: string;
11
12
  darkMode: boolean;
13
+ tags?: string[];
12
14
  backgroundColors?: {
13
15
  light: string;
14
16
  dark?: string;
15
17
  };
16
18
  featuredImage?: {
17
19
  id?: string;
20
+ src?: string;
18
21
  alt?: string;
19
22
  };
23
+ LayoutWrapper?: React.ComponentType<{
24
+ children: React.ReactNode;
25
+ header?: React.ReactNode;
26
+ footer?: React.ReactNode;
27
+ heroImage?: React.ReactNode;
28
+ isPreview?: boolean;
29
+ isWrapper?: boolean;
30
+ tags?: string[];
31
+ }>;
20
32
  onTitleChange: (title: string) => void;
21
33
  onHeroBlockUpdate: (data: Partial<Block['data']>) => void;
22
34
  onHeroBlockDelete: () => void;
23
35
  onBlockAdd: (type: string, index: number, containerId?: string) => void;
24
- onBlockUpdate: (id: string, data: Partial<Block['data']>) => void;
25
- onBlockDelete: (id: string) => void;
36
+ onBlockUpdate: (id: string, data: Partial<Block['data']>, containerId?: string) => void;
37
+ onBlockDelete: (id: string, containerId?: string) => void;
26
38
  onBlockMove: (id: string, newIndex: number, containerId?: string) => void;
27
39
  }
28
- export declare function EditorCanvas({ isPreviewMode, heroBlock, heroBlockDefinition, contentBlocks, title, siteId, locale, darkMode, backgroundColors, featuredImage, onTitleChange, onHeroBlockUpdate, onHeroBlockDelete, onBlockAdd, onBlockUpdate, onBlockDelete, onBlockMove, }: EditorCanvasProps): import("react/jsx-runtime").JSX.Element;
40
+ export declare function EditorCanvas({ isPreviewMode, heroBlock, heroBlockDefinition, contentBlocks, title, siteId, locale, darkMode, tags, backgroundColors, featuredImage, LayoutWrapper, onTitleChange, onHeroBlockUpdate, onHeroBlockDelete, onBlockAdd, onBlockUpdate, onBlockDelete, onBlockMove, }: EditorCanvasProps): import("react/jsx-runtime").JSX.Element;
29
41
  //# sourceMappingURL=EditorCanvas.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditorCanvas.d.ts","sourceRoot":"","sources":["../../../../src/views/CanvasEditor/components/EditorCanvas.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAC9B,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;IACxB,mBAAmB,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACrD,aAAa,EAAE,KAAK,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE;QACf,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,aAAa,CAAC,EAAE;QACZ,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,iBAAiB,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,CAAC;IAC1D,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,CAAC;IAClE,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7E;AAED,wBAAgB,YAAY,CAAC,EACzB,aAAa,EACb,SAAS,EACT,mBAAmB,EACnB,aAAa,EACb,KAAK,EACL,MAAM,EACN,MAAM,EACN,QAAQ,EACR,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,aAAa,EACb,WAAW,GACd,EAAE,iBAAiB,2CA0GnB"}
1
+ {"version":3,"file":"EditorCanvas.d.ts","sourceRoot":"","sources":["../../../../src/views/CanvasEditor/components/EditorCanvas.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAIjD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAC9B,aAAa,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;IACxB,mBAAmB,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACrD,aAAa,EAAE,KAAK,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,gBAAgB,CAAC,EAAE;QACf,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,aAAa,CAAC,EAAE;QACZ,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAChC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;QAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;QACzB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;QACzB,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;QAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC,CAAC;IACH,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,iBAAiB,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,CAAC;IAC1D,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACxE,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACxF,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7E;AAED,wBAAgB,YAAY,CAAC,EACzB,aAAa,EACb,SAAS,EACT,mBAAmB,EACnB,aAAa,EACb,KAAK,EACL,MAAM,EACN,MAAM,EACN,QAAQ,EACR,IAAS,EACT,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,aAAa,EACb,WAAW,GACd,EAAE,iBAAiB,2CAoJnB"}
@@ -1,10 +1,10 @@
1
1
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useRef, useEffect } from 'react';
4
4
  import { BlockWrapper } from '../BlockWrapper';
5
5
  import { EditorBody } from '../EditorBody';
6
6
  import { BlockRenderer } from '../../../lib/blocks/BlockRenderer';
7
- export function EditorCanvas({ isPreviewMode, heroBlock, heroBlockDefinition, contentBlocks, title, siteId, locale, darkMode, backgroundColors, featuredImage, onTitleChange, onHeroBlockUpdate, onHeroBlockDelete, onBlockAdd, onBlockUpdate, onBlockDelete, onBlockMove, }) {
7
+ export function EditorCanvas({ isPreviewMode, heroBlock, heroBlockDefinition, contentBlocks, title, siteId, locale, darkMode, tags = [], backgroundColors, featuredImage, LayoutWrapper, onTitleChange, onHeroBlockUpdate, onHeroBlockDelete, onBlockAdd, onBlockUpdate, onBlockDelete, onBlockMove, }) {
8
8
  const titleRef = useRef(null);
9
9
  // Handle Title Auto-resize
10
10
  useEffect(() => {
@@ -13,20 +13,42 @@ export function EditorCanvas({ isPreviewMode, heroBlock, heroBlockDefinition, co
13
13
  titleRef.current.style.height = `${titleRef.current.scrollHeight}px`;
14
14
  }
15
15
  }, [title]);
16
- return (_jsx("div", { className: "flex-1 overflow-y-auto overflow-x-hidden pb-40 px-6 custom-scrollbar selection:bg-primary/20 dark:selection:bg-primary/30 min-h-0", style: {
17
- backgroundColor: backgroundColors
18
- ? (darkMode && backgroundColors.dark
19
- ? backgroundColors.dark
20
- : backgroundColors.light)
21
- : undefined,
22
- }, children: _jsxs("div", { className: `mx-auto transition-all duration-500 max-w-7xl w-full`, children: [!isPreviewMode && heroBlockDefinition && heroBlock && (_jsx("div", { className: "mb-12", children: _jsx(BlockWrapper, { block: heroBlock, onUpdate: onHeroBlockUpdate, onDelete: onHeroBlockDelete, onMoveUp: () => { }, onMoveDown: () => { }, allBlocks: [heroBlock] }) })), isPreviewMode ? (_jsxs("div", { className: "space-y-8", children: [heroBlockDefinition && heroBlock && (_jsx(BlockRenderer, { block: heroBlock, context: {
23
- siteId,
24
- locale,
25
- // Pass featured image as fallback for hero block
26
- // Only pass id and alt - plugin-images handles transforms
27
- fallbackImage: featuredImage ? {
28
- id: featuredImage.id,
29
- alt: featuredImage.alt,
30
- } : undefined,
31
- } })), !heroBlockDefinition && title && (_jsx("h1", { className: "text-5xl font-serif font-medium text-neutral-950 dark:text-white leading-tight mb-12", children: title })), contentBlocks.length > 0 ? (_jsx("div", { className: "space-y-8", children: contentBlocks.map((block) => (_jsx(BlockRenderer, { block: block, context: { siteId, locale } }, block.id))) })) : (_jsx("div", { className: "text-center py-20 text-neutral-400 dark:text-neutral-500", children: _jsx("p", { className: "text-sm", children: "No content blocks yet. Switch to Edit mode to add blocks." }) }))] })) : (_jsxs(_Fragment, { children: [!heroBlockDefinition && (_jsx("div", { className: "mb-12", children: _jsx("textarea", { ref: titleRef, rows: 1, value: title, onChange: (e) => onTitleChange(e.target.value), placeholder: "The title of your story...", className: "w-full bg-transparent border-none outline-none text-5xl font-serif font-medium placeholder:text-neutral-500 dark:placeholder:text-neutral-500 resize-none leading-tight transition-colors duration-300 text-neutral-950 dark:text-white" }) })), _jsx(EditorBody, { blocks: contentBlocks, darkMode: darkMode, backgroundColors: backgroundColors, onBlockAdd: onBlockAdd, onBlockUpdate: onBlockUpdate, onBlockDelete: onBlockDelete, onBlockMove: onBlockMove })] }))] }) }));
16
+ const renderPreviewContent = () => {
17
+ // Filter out hero block from content if it's already rendered in header
18
+ const mainContent = heroBlockDefinition && heroBlock
19
+ ? contentBlocks.filter(b => b.type !== 'hero')
20
+ : contentBlocks;
21
+ const commonContext = {
22
+ siteId,
23
+ locale,
24
+ fallbackImage: featuredImage ? {
25
+ id: featuredImage.id,
26
+ src: featuredImage.src,
27
+ alt: featuredImage.alt,
28
+ } : undefined,
29
+ };
30
+ return (_jsxs("div", { className: "space-y-8", children: [!heroBlockDefinition && title && (_jsx("h1", { className: "text-5xl font-serif font-medium leading-tight mb-12", style: { color: 'var(--color-forest, var(--color-neutral-950))' }, children: title })), mainContent.length > 0 ? (_jsx("div", { className: "space-y-8", children: mainContent.map((block) => (_jsx(BlockRenderer, { block: block, context: commonContext }, block.id))) })) : (_jsx("div", { className: "text-center py-20 text-neutral-400 dark:text-neutral-500", children: _jsx("p", { className: "text-sm", children: "No content blocks yet. Switch to Edit mode to add blocks." }) }))] }));
31
+ };
32
+ const renderEditorContent = () => {
33
+ // Filter out hero block from content if it's already rendered in header
34
+ const mainBlocks = heroBlockDefinition && heroBlock
35
+ ? contentBlocks.filter(b => b.type !== 'hero')
36
+ : contentBlocks;
37
+ return (_jsxs("div", { className: "space-y-12", children: [!heroBlockDefinition && (_jsx("div", { className: "mb-12", children: _jsx("textarea", { ref: titleRef, rows: 1, value: title, onChange: (e) => onTitleChange(e.target.value), placeholder: "The title of your story...", className: "w-full bg-transparent border-none outline-none text-5xl md:text-7xl lg:text-9xl font-serif font-medium placeholder:text-neutral-500 dark:placeholder:text-neutral-500 resize-none leading-tight transition-colors duration-300 italic", style: { color: 'var(--color-forest, var(--color-neutral-950))' } }) })), _jsx(EditorBody, { blocks: mainBlocks, darkMode: darkMode, backgroundColors: backgroundColors, onBlockAdd: onBlockAdd, onBlockUpdate: onBlockUpdate, onBlockDelete: onBlockDelete, onBlockMove: onBlockMove })] }));
38
+ };
39
+ // Render Hero Block for Slot Injection
40
+ const heroElement = heroBlockDefinition && heroBlock ? (isPreviewMode ? (_jsx(BlockRenderer, { block: heroBlock, context: {
41
+ siteId,
42
+ locale,
43
+ fallbackImage: featuredImage ? {
44
+ id: featuredImage.id,
45
+ src: featuredImage.src,
46
+ alt: featuredImage.alt,
47
+ } : undefined,
48
+ } })) : (_jsx(BlockWrapper, { block: heroBlock, onUpdate: onHeroBlockUpdate, onDelete: onHeroBlockDelete, onMoveUp: () => { }, onMoveDown: () => { } }))) : null;
49
+ return (_jsx("div", { "data-theme": darkMode ? 'dark' : 'light', className: "flex-1 overflow-y-auto overflow-x-hidden pb-40 px-4 lg:px-10 custom-scrollbar selection:bg-primary/20 dark:selection:bg-primary/30 min-h-0 transition-colors duration-300", style: {
50
+ backgroundColor: darkMode
51
+ ? (backgroundColors?.dark || '#0c0c0c')
52
+ : (backgroundColors?.light || '#ffffff')
53
+ }, children: _jsx("div", { className: `${!LayoutWrapper ? 'mx-auto transition-all duration-500 max-w-[1600px] w-full px-2 pt-8' : ''}`, children: LayoutWrapper ? (_jsx("div", { "data-theme": darkMode ? 'dark' : 'light', "data-dashboard": "false", className: "theme-reset contents", children: _jsx(LayoutWrapper, { header: heroElement, isPreview: true, isWrapper: true, tags: tags, children: isPreviewMode ? renderPreviewContent() : renderEditorContent() }) })) : (_jsxs("div", { "data-theme": darkMode ? 'dark' : 'light', "data-dashboard": "false", className: "theme-reset", children: [heroElement, _jsx("div", { className: "max-w-[1600px] mx-auto px-4 sm:px-6 lg:px-8 py-6 prose prose-lg max-w-none prose-headings:font-serif", children: isPreviewMode ? renderPreviewContent() : renderEditorContent() })] })) }) }));
32
54
  }
@@ -1,7 +1,11 @@
1
1
  import type { BlockTypeDefinition } from '../../../types/block';
2
2
  export interface EditorLibraryProps {
3
3
  registeredBlocks: BlockTypeDefinition[];
4
- onAddBlock: (type: string) => void;
4
+ onAddBlock: (blockType: string) => void;
5
5
  }
6
+ /**
7
+ * Editor Library Component
8
+ * Displays available blocks that can be added to the canvas
9
+ */
6
10
  export declare function EditorLibrary({ registeredBlocks, onAddBlock }: EditorLibraryProps): import("react/jsx-runtime").JSX.Element;
7
11
  //# sourceMappingURL=EditorLibrary.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EditorLibrary.d.ts","sourceRoot":"","sources":["../../../../src/views/CanvasEditor/components/EditorLibrary.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,MAAM,WAAW,kBAAkB;IAC/B,gBAAgB,EAAE,mBAAmB,EAAE,CAAC;IACxC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,wBAAgB,aAAa,CAAC,EAAE,gBAAgB,EAAE,UAAU,EAAE,EAAE,kBAAkB,2CA6GjF"}
1
+ {"version":3,"file":"EditorLibrary.d.ts","sourceRoot":"","sources":["../../../../src/views/CanvasEditor/components/EditorLibrary.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,MAAM,WAAW,kBAAkB;IAC/B,gBAAgB,EAAE,mBAAmB,EAAE,CAAC;IACxC,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,gBAAgB,EAAE,UAAU,EAAE,EAAE,kBAAkB,2CAwHjF"}
@@ -2,13 +2,17 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Library, Image as ImageIcon, LayoutTemplate, Type, Box } from 'lucide-react';
4
4
  import { LibraryItem, CustomBlockItem } from './index';
5
+ /**
6
+ * Editor Library Component
7
+ * Displays available blocks that can be added to the canvas
8
+ */
5
9
  export function EditorLibrary({ registeredBlocks, onAddBlock }) {
6
- // Get all registered blocks from state (excluding Hero block from sidebar)
7
- const allBlocks = registeredBlocks.filter(block => block.type !== 'hero');
8
- const textBlocks = allBlocks.filter(block => block.category === 'text');
9
- const customBlocks = allBlocks.filter(block => block.category === 'custom');
10
- const mediaBlocks = allBlocks.filter(block => block.category === 'media');
11
- const layoutBlocks = allBlocks.filter(block => block.category === 'layout');
10
+ // Categorize blocks
11
+ const allBlocks = registeredBlocks || [];
12
+ const textBlocks = allBlocks.filter(bl => bl.category === 'text' || bl.type === 'heading' || bl.type === 'paragraph' || bl.type === 'list');
13
+ const mediaBlocks = allBlocks.filter(bl => bl.category === 'media' || bl.type === 'image' || bl.type === 'gallery' || bl.type === 'video');
14
+ const layoutBlocks = allBlocks.filter(bl => bl.category === 'layout' || bl.type === 'section' || bl.type === 'columns' || bl.type === 'spacer');
15
+ const customBlocks = allBlocks.filter(bl => !textBlocks.includes(bl) && !mediaBlocks.includes(bl) && !layoutBlocks.includes(bl));
12
16
  return (_jsxs("div", { className: "p-6 w-72 min-w-0 max-w-full", children: [textBlocks.length > 0 && (_jsxs("div", { className: "mb-10", children: [_jsx("h3", { className: "text-[10px] uppercase tracking-[0.2em] text-neutral-500 dark:text-neutral-400 font-black mb-6", children: "Text" }), _jsx("div", { className: "grid grid-cols-2 gap-3", children: textBlocks.map((block) => {
13
17
  const IconComponent = block.icon || block.components.Icon || Type;
14
18
  return (_jsx(LibraryItem, { icon: _jsx(IconComponent, { size: 16 }), label: block.name, blockType: block.type, description: block.description, onAddBlock: onAddBlock }, block.type));
@@ -21,5 +25,5 @@ export function EditorLibrary({ registeredBlocks, onAddBlock }) {
21
25
  }) })] })), customBlocks.length > 0 && (_jsxs("div", { children: [_jsx("h3", { className: "text-[10px] uppercase tracking-[0.2em] text-neutral-500 dark:text-neutral-400 font-black mb-6", children: "Custom Blocks" }), _jsx("div", { className: "space-y-3", children: customBlocks.map((block) => {
22
26
  const IconComponent = block.icon || block.components.Icon || Box;
23
27
  return (_jsx(CustomBlockItem, { blockType: block.type, name: block.name, description: block.description, icon: _jsx(IconComponent, { size: 14 }), onAddBlock: onAddBlock }, block.type));
24
- }) })] })), allBlocks.length === 0 && (_jsxs("div", { className: "text-center py-12", children: [_jsx(Library, { size: 32, className: "mx-auto text-neutral-300 dark:text-neutral-700 mb-4" }), _jsx("p", { className: "text-xs text-neutral-500 dark:text-neutral-400", children: "No blocks registered yet." })] }))] }));
28
+ }) })] })), allBlocks.length === 0 && (_jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [_jsx(Library, { className: "size-12 text-neutral-300 dark:text-neutral-700 mb-4" }), _jsx("p", { className: "text-xs text-neutral-500 dark:text-neutral-400", children: "No blocks registered yet." })] }))] }));
25
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EditorSidebar.d.ts","sourceRoot":"","sources":["../../../../src/views/CanvasEditor/components/EditorSidebar.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,WAAW,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACjD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;CAC/D;AAED,wBAAgB,aAAa,CAAC,EAC1B,IAAI,EACJ,GAAG,EACH,QAAQ,EACR,SAAS,EACT,MAAM,EACN,WAAW,EACX,gBAAgB,GACnB,EAAE,kBAAkB,2CA0JpB"}
1
+ {"version":3,"file":"EditorSidebar.d.ts","sourceRoot":"","sources":["../../../../src/views/CanvasEditor/components/EditorSidebar.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,WAAW,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACjD,gBAAgB,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;CAC/D;AAED,wBAAgB,aAAa,CAAC,EAC1B,IAAI,EACJ,GAAG,EACH,QAAQ,EACR,SAAS,EACT,MAAM,EACN,WAAW,EACX,gBAAgB,GACnB,EAAE,kBAAkB,2CA6NpB"}