@carlonicora/nextjs-jsonapi 5.2.0 → 5.4.0

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 (237) hide show
  1. package/dist/{BlockNoteEditor-EGY4ZAAM.js → BlockNoteEditor-4YCAIEPT.js} +23 -22
  2. package/dist/BlockNoteEditor-4YCAIEPT.js.map +1 -0
  3. package/dist/{BlockNoteEditor-2QJVK2HH.mjs → BlockNoteEditor-YQL2SGFR.mjs} +8 -7
  4. package/dist/BlockNoteEditor-YQL2SGFR.mjs.map +1 -0
  5. package/dist/{BlockNoteViewer-6BQXJ4TB.mjs → BlockNoteViewer-AEJKJ27Q.mjs} +2 -2
  6. package/dist/{BlockNoteViewer-I2MMFH3S.js → BlockNoteViewer-YL3J7J2Y.js} +3 -3
  7. package/dist/{BlockNoteViewer-I2MMFH3S.js.map → BlockNoteViewer-YL3J7J2Y.js.map} +1 -1
  8. package/dist/BlogCategoryFields-DO48vOTE.d.mts +14 -0
  9. package/dist/BlogCategoryFields-DO48vOTE.d.ts +14 -0
  10. package/dist/BlogPostInterface-BB_4wcDR.d.mts +124 -0
  11. package/dist/BlogPostInterface-bWAT1rfR.d.ts +124 -0
  12. package/dist/billing/index.js +441 -441
  13. package/dist/billing/index.mjs +3 -3
  14. package/dist/blog-public.types-BbrzsC1c.d.mts +30 -0
  15. package/dist/blog-public.types-BbrzsC1c.d.ts +30 -0
  16. package/dist/{chunk-3VEQ5JZJ.js → chunk-3NLAXVIN.js} +860 -849
  17. package/dist/{chunk-3VEQ5JZJ.js.map → chunk-3NLAXVIN.js.map} +1 -1
  18. package/dist/{chunk-YMUPTXOT.mjs → chunk-3YW35YHQ.mjs} +1 -101
  19. package/dist/chunk-3YW35YHQ.mjs.map +1 -0
  20. package/dist/{chunk-EXICQC4A.js → chunk-5PPG6PL7.js} +3 -3
  21. package/dist/{chunk-EXICQC4A.js.map → chunk-5PPG6PL7.js.map} +1 -1
  22. package/dist/{chunk-NPKFMRH5.mjs → chunk-6DC2WVVB.mjs} +2 -2
  23. package/dist/{chunk-2Z3ZCYXX.mjs → chunk-EUKTBOI2.mjs} +19 -8
  24. package/dist/chunk-EUKTBOI2.mjs.map +1 -0
  25. package/dist/{chunk-THKYH65N.js → chunk-KSYQEKJX.js} +11 -111
  26. package/dist/chunk-KSYQEKJX.js.map +1 -0
  27. package/dist/{chunk-S5MQDWWC.js → chunk-NFBOSPNJ.js} +1451 -176
  28. package/dist/chunk-NFBOSPNJ.js.map +1 -0
  29. package/dist/{chunk-JEZQTZQ4.mjs → chunk-QMYQRPQC.mjs} +2 -2
  30. package/dist/{chunk-HNOWSFM5.mjs → chunk-WC63PJSC.mjs} +1278 -3
  31. package/dist/chunk-WC63PJSC.mjs.map +1 -0
  32. package/dist/chunk-XCHSX3VC.mjs +107 -0
  33. package/dist/chunk-XCHSX3VC.mjs.map +1 -0
  34. package/dist/{chunk-75MLT74B.js → chunk-YNCQSWQW.js} +8 -8
  35. package/dist/{chunk-75MLT74B.js.map → chunk-YNCQSWQW.js.map} +1 -1
  36. package/dist/chunk-YW4ZCEWB.js +107 -0
  37. package/dist/chunk-YW4ZCEWB.js.map +1 -0
  38. package/dist/client/index.d.mts +6 -39
  39. package/dist/client/index.d.ts +6 -39
  40. package/dist/client/index.js +4 -4
  41. package/dist/client/index.mjs +3 -3
  42. package/dist/components/index.d.mts +15 -4
  43. package/dist/components/index.d.ts +15 -4
  44. package/dist/components/index.js +4 -4
  45. package/dist/components/index.mjs +3 -3
  46. package/dist/contexts/index.js +4 -4
  47. package/dist/contexts/index.mjs +3 -3
  48. package/dist/core/index.d.mts +400 -3
  49. package/dist/core/index.d.ts +400 -3
  50. package/dist/core/index.js +64 -2
  51. package/dist/core/index.js.map +1 -1
  52. package/dist/core/index.mjs +63 -1
  53. package/dist/email-automation-enrollment.fields-BZvF14qx.d.mts +82 -0
  54. package/dist/email-automation-enrollment.fields-Cp3VMzFq.d.ts +82 -0
  55. package/dist/email-automations/index.css +30 -0
  56. package/dist/email-automations/index.css.map +1 -0
  57. package/dist/email-automations/index.d.mts +303 -0
  58. package/dist/email-automations/index.d.ts +303 -0
  59. package/dist/email-automations/index.js +1705 -0
  60. package/dist/email-automations/index.js.map +1 -0
  61. package/dist/email-automations/index.mjs +1705 -0
  62. package/dist/email-automations/index.mjs.map +1 -0
  63. package/dist/features/analytics/index.js +122 -122
  64. package/dist/features/analytics/index.mjs +4 -4
  65. package/dist/features/analytics/server.js +6 -5
  66. package/dist/features/analytics/server.js.map +1 -1
  67. package/dist/features/analytics/server.mjs +4 -3
  68. package/dist/features/analytics/server.mjs.map +1 -1
  69. package/dist/features/blog/index.css +30 -0
  70. package/dist/features/blog/index.css.map +1 -0
  71. package/dist/features/blog/index.d.mts +266 -0
  72. package/dist/features/blog/index.d.ts +266 -0
  73. package/dist/features/blog/index.js +1799 -0
  74. package/dist/features/blog/index.js.map +1 -0
  75. package/dist/features/blog/index.mjs +1799 -0
  76. package/dist/features/blog/index.mjs.map +1 -0
  77. package/dist/features/blog/server.d.mts +33 -0
  78. package/dist/features/blog/server.d.ts +33 -0
  79. package/dist/features/blog/server.js +139 -0
  80. package/dist/features/blog/server.js.map +1 -0
  81. package/dist/features/blog/server.mjs +139 -0
  82. package/dist/features/blog/server.mjs.map +1 -0
  83. package/dist/features/help/index.js +37 -37
  84. package/dist/features/help/index.mjs +3 -3
  85. package/dist/features/tokenusage/index.js +125 -125
  86. package/dist/features/tokenusage/index.mjs +4 -4
  87. package/dist/index.d.mts +5 -2
  88. package/dist/index.d.ts +5 -2
  89. package/dist/index.js +65 -3
  90. package/dist/index.js.map +1 -1
  91. package/dist/index.mjs +64 -2
  92. package/dist/{s3.service-CY-jgOAM.d.ts → s3.service-Bz_K-tjz.d.ts} +11 -0
  93. package/dist/{s3.service-Sri0QP7Z.d.mts → s3.service-D5zNCEW3.d.mts} +11 -0
  94. package/dist/server/index.d.mts +1 -1
  95. package/dist/server/index.d.ts +1 -1
  96. package/dist/server/index.js +8 -6
  97. package/dist/server/index.js.map +1 -1
  98. package/dist/server/index.mjs +12 -10
  99. package/dist/types-70acd-8C.d.mts +39 -0
  100. package/dist/types-l8SFleXi.d.ts +39 -0
  101. package/messages/en.json +210 -0
  102. package/messages/it.json +210 -0
  103. package/package.json +21 -1
  104. package/src/components/editors/BlockNoteEditor.tsx +13 -3
  105. package/src/components/forms/FormBlockNote.tsx +4 -0
  106. package/src/components/forms/FormFieldWrapper.tsx +1 -1
  107. package/src/components/forms/FormTextarea.tsx +2 -1
  108. package/src/components/navigations/ContentTitle.tsx +14 -3
  109. package/src/core/index.ts +12 -0
  110. package/src/core/registry/ModuleRegistry.ts +11 -0
  111. package/src/email-automations/index.ts +5 -0
  112. package/src/features/blog/BlogModules.ts +49 -0
  113. package/src/features/blog/components/admin/BlogAdminContainer.tsx +32 -0
  114. package/src/features/blog/components/admin/BlogCategoriesList.tsx +56 -0
  115. package/src/features/blog/components/admin/BlogCategoryEditor.tsx +230 -0
  116. package/src/features/blog/components/admin/BlogCoverImageField.tsx +123 -0
  117. package/src/features/blog/components/admin/BlogLayoutSetting.tsx +86 -0
  118. package/src/features/blog/components/admin/BlogPostComparison.tsx +54 -0
  119. package/src/features/blog/components/admin/BlogPostContainer.tsx +102 -0
  120. package/src/features/blog/components/admin/BlogPostDeleter.tsx +35 -0
  121. package/src/features/blog/components/admin/BlogPostEditor.tsx +207 -0
  122. package/src/features/blog/components/admin/BlogPostPublishButton.tsx +50 -0
  123. package/src/features/blog/components/admin/BlogPostTranslationEditor.tsx +110 -0
  124. package/src/features/blog/components/admin/BlogPostTranslationPanel.tsx +136 -0
  125. package/src/features/blog/components/admin/BlogPostsList.tsx +58 -0
  126. package/src/features/blog/components/admin/BlogTranslationStatus.tsx +104 -0
  127. package/src/features/blog/components/admin/__tests__/BlogPostTranslationPanel.spec.tsx +100 -0
  128. package/src/features/blog/components/admin/__tests__/BlogPostsList.spec.tsx +30 -0
  129. package/src/features/blog/components/admin/index.ts +14 -0
  130. package/src/features/blog/components/public/BlogCategoryChips.tsx +59 -0
  131. package/src/features/blog/components/public/BlogList.tsx +21 -0
  132. package/src/features/blog/components/public/BlogListColumn.tsx +53 -0
  133. package/src/features/blog/components/public/BlogListFeatured.tsx +57 -0
  134. package/src/features/blog/components/public/BlogListParts.tsx +74 -0
  135. package/src/features/blog/components/public/BlogListRail.tsx +62 -0
  136. package/src/features/blog/components/public/BlogPostCard.tsx +132 -0
  137. package/src/features/blog/components/public/BlogPostMeta.tsx +49 -0
  138. package/src/features/blog/components/public/BlogPostView.tsx +74 -0
  139. package/src/features/blog/components/public/BlogSearchBox.tsx +52 -0
  140. package/src/features/blog/components/public/__tests__/BlogList.spec.tsx +173 -0
  141. package/src/features/blog/components/public/__tests__/BlogPostView.spec.tsx +128 -0
  142. package/src/features/blog/components/public/blogPublicHelpers.ts +30 -0
  143. package/src/features/blog/components/public/index.ts +3 -0
  144. package/src/features/blog/contexts/BlogPostContext.tsx +66 -0
  145. package/src/features/blog/contexts/index.ts +1 -0
  146. package/src/features/blog/data/BlogCategory.ts +93 -0
  147. package/src/features/blog/data/BlogCategoryFields.ts +4 -0
  148. package/src/features/blog/data/BlogCategoryInterface.ts +24 -0
  149. package/src/features/blog/data/BlogCategoryService.ts +54 -0
  150. package/src/features/blog/data/BlogCategoryTranslation.ts +90 -0
  151. package/src/features/blog/data/BlogCategoryTranslationInterface.ts +22 -0
  152. package/src/features/blog/data/BlogCategoryTranslationService.ts +30 -0
  153. package/src/features/blog/data/BlogPost.spec.ts +123 -0
  154. package/src/features/blog/data/BlogPost.ts +159 -0
  155. package/src/features/blog/data/BlogPostFields.ts +7 -0
  156. package/src/features/blog/data/BlogPostInterface.ts +39 -0
  157. package/src/features/blog/data/BlogPostService.ts +82 -0
  158. package/src/features/blog/data/BlogPostTranslation.spec.ts +73 -0
  159. package/src/features/blog/data/BlogPostTranslation.ts +110 -0
  160. package/src/features/blog/data/BlogPostTranslationInterface.ts +27 -0
  161. package/src/features/blog/data/BlogPostTranslationService.ts +30 -0
  162. package/src/features/blog/data/BlogSettings.ts +37 -0
  163. package/src/features/blog/data/BlogSettingsInterface.ts +11 -0
  164. package/src/features/blog/data/BlogSettingsService.ts +24 -0
  165. package/src/features/blog/data/index.ts +17 -0
  166. package/src/features/blog/hooks/index.ts +3 -0
  167. package/src/features/blog/hooks/useBlogCategoryNames.ts +34 -0
  168. package/src/features/blog/hooks/useBlogCategoryTableStructure.tsx +84 -0
  169. package/src/features/blog/hooks/useBlogPostTableStructure.tsx +126 -0
  170. package/src/features/blog/index.ts +15 -0
  171. package/src/features/blog/server/fetchers.ts +120 -0
  172. package/src/features/blog/server/toPublic.spec.ts +91 -0
  173. package/src/features/blog/server/toPublic.ts +36 -0
  174. package/src/features/blog/server-entry.ts +17 -0
  175. package/src/features/blog/types/blog-public.types.ts +34 -0
  176. package/src/features/blog/types/blog.constants.ts +40 -0
  177. package/src/features/email-automation/EmailAutomationEnrollmentModule.ts +11 -0
  178. package/src/features/email-automation/EmailAutomationModule.ts +30 -0
  179. package/src/features/email-automation/EmailAutomationStepModule.ts +11 -0
  180. package/src/features/email-automation/EmailAutomationTriggerModule.ts +11 -0
  181. package/src/features/email-automation/components/__tests__/EmailAutomationEditor.spec.tsx +104 -0
  182. package/src/features/email-automation/components/canvas/EmailAutomationActiveSwitch.tsx +49 -0
  183. package/src/features/email-automation/components/canvas/EmailAutomationCanvas.tsx +474 -0
  184. package/src/features/email-automation/components/canvas/EmailAutomationCanvasInspector.tsx +89 -0
  185. package/src/features/email-automation/components/canvas/EmailAutomationCanvasTab.tsx +32 -0
  186. package/src/features/email-automation/components/canvas/__tests__/buildCanvasGraph.spec.ts +67 -0
  187. package/src/features/email-automation/components/canvas/buildCanvasGraph.ts +141 -0
  188. package/src/features/email-automation/components/canvas/edges/DelayEdge.tsx +68 -0
  189. package/src/features/email-automation/components/canvas/nodes/EmailStepNode.tsx +43 -0
  190. package/src/features/email-automation/components/canvas/nodes/TriggerNode.tsx +23 -0
  191. package/src/features/email-automation/components/canvas/shared/CanvasToolbar.tsx +53 -0
  192. package/src/features/email-automation/components/canvas/shared/EmptyCanvas.tsx +11 -0
  193. package/src/features/email-automation/components/canvas/shared/__tests__/autoLayout.spec.ts +42 -0
  194. package/src/features/email-automation/components/canvas/shared/__tests__/longPress.spec.ts +51 -0
  195. package/src/features/email-automation/components/canvas/shared/autoLayout.ts +55 -0
  196. package/src/features/email-automation/components/canvas/shared/index.ts +4 -0
  197. package/src/features/email-automation/components/canvas/shared/longPress.ts +57 -0
  198. package/src/features/email-automation/components/containers/EmailAutomationContainer.tsx +80 -0
  199. package/src/features/email-automation/components/containers/EmailAutomationsListContainer.tsx +27 -0
  200. package/src/features/email-automation/components/forms/EmailAutomationEditor.tsx +153 -0
  201. package/src/features/email-automation/components/forms/EmailStepEditor.tsx +151 -0
  202. package/src/features/email-automation/components/index.ts +15 -0
  203. package/src/features/email-automation/components/lists/EmailAutomationRecipientsList.tsx +90 -0
  204. package/src/features/email-automation/components/lists/EmailAutomationsList.tsx +76 -0
  205. package/src/features/email-automation/components/unsubscribe/EmailUnsubscribe.tsx +99 -0
  206. package/src/features/email-automation/components/unsubscribe/__tests__/EmailUnsubscribe.spec.tsx +55 -0
  207. package/src/features/email-automation/contexts/EmailAutomationContext.tsx +175 -0
  208. package/src/features/email-automation/data/EmailAutomation.ts +87 -0
  209. package/src/features/email-automation/data/EmailAutomationEnrollment.ts +105 -0
  210. package/src/features/email-automation/data/EmailAutomationEnrollmentInterface.ts +18 -0
  211. package/src/features/email-automation/data/EmailAutomationEnrollmentService.ts +31 -0
  212. package/src/features/email-automation/data/EmailAutomationInterface.ts +22 -0
  213. package/src/features/email-automation/data/EmailAutomationService.ts +106 -0
  214. package/src/features/email-automation/data/EmailAutomationStep.ts +104 -0
  215. package/src/features/email-automation/data/EmailAutomationStepInterface.ts +23 -0
  216. package/src/features/email-automation/data/EmailAutomationStepService.ts +80 -0
  217. package/src/features/email-automation/data/EmailAutomationTrigger.ts +28 -0
  218. package/src/features/email-automation/data/EmailAutomationTriggerInterface.ts +6 -0
  219. package/src/features/email-automation/data/__tests__/email-automation-models.spec.ts +103 -0
  220. package/src/features/email-automation/data/email-automation-enrollment.fields.ts +8 -0
  221. package/src/features/email-automation/data/email-automation.fields.ts +9 -0
  222. package/src/features/email-automation/data/index.ts +13 -0
  223. package/src/features/email-automation/hooks/index.ts +2 -0
  224. package/src/features/email-automation/hooks/useEmailAutomationEnrollmentTableStructure.tsx +126 -0
  225. package/src/features/email-automation/hooks/useEmailAutomationTableStructure.tsx +119 -0
  226. package/src/features/email-automation/index.ts +5 -0
  227. package/src/features/s3/data/s3.service.ts +17 -0
  228. package/dist/BlockNoteEditor-2QJVK2HH.mjs.map +0 -1
  229. package/dist/BlockNoteEditor-EGY4ZAAM.js.map +0 -1
  230. package/dist/chunk-2Z3ZCYXX.mjs.map +0 -1
  231. package/dist/chunk-HNOWSFM5.mjs.map +0 -1
  232. package/dist/chunk-S5MQDWWC.js.map +0 -1
  233. package/dist/chunk-THKYH65N.js.map +0 -1
  234. package/dist/chunk-YMUPTXOT.mjs.map +0 -1
  235. /package/dist/{BlockNoteViewer-6BQXJ4TB.mjs.map → BlockNoteViewer-AEJKJ27Q.mjs.map} +0 -0
  236. /package/dist/{chunk-NPKFMRH5.mjs.map → chunk-6DC2WVVB.mjs.map} +0 -0
  237. /package/dist/{chunk-JEZQTZQ4.mjs.map → chunk-QMYQRPQC.mjs.map} +0 -0
@@ -0,0 +1,1799 @@
1
+ "use client";
2
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+ var _chunk3NLAXVINjs = require('../../chunk-3NLAXVIN.js');
42
+ require('../../chunk-YNCQSWQW.js');
43
+ require('../../chunk-G4JR3SFV.js');
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+ var _chunkNFBOSPNJjs = require('../../chunk-NFBOSPNJ.js');
69
+ require('../../chunk-LXKSUWAV.js');
70
+ require('../../chunk-JTPRJNT2.js');
71
+ require('../../chunk-GHE4VT2R.js');
72
+ require('../../chunk-3EPNHTMH.js');
73
+
74
+
75
+ var _chunk7QVYU63Ejs = require('../../chunk-7QVYU63E.js');
76
+
77
+ // src/features/blog/components/admin/BlogAdminContainer.tsx
78
+ var _nextintl = require('next-intl');
79
+
80
+ // src/features/blog/components/admin/BlogCategoriesList.tsx
81
+ var _lucidereact = require('lucide-react');
82
+
83
+
84
+ // src/features/blog/hooks/useBlogCategoryTableStructure.tsx
85
+
86
+ var _react = require('react');
87
+
88
+ // src/features/blog/components/admin/BlogCategoryEditor.tsx
89
+ var _zod = require('@hookform/resolvers/zod');
90
+
91
+
92
+
93
+ var _reacthookform = require('react-hook-form');
94
+ var _uuid = require('uuid');
95
+ var _zod3 = require('zod');
96
+
97
+ // src/features/blog/components/admin/BlogCoverImageField.tsx
98
+
99
+ var _image = require('next/image'); var _image2 = _interopRequireDefault(_image);
100
+
101
+ var _jsxruntime = require('react/jsx-runtime');
102
+ var dropzone = {
103
+ multiple: false,
104
+ maxSize: 100 * 1024 * 1024,
105
+ preventDropOnDocument: false,
106
+ accept: {
107
+ "application/images": [".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg"]
108
+ }
109
+ };
110
+ async function uploadBlogImage(params) {
111
+ if (!params.selection || !params.key) return;
112
+ await _chunkNFBOSPNJjs.S3Service.upload({
113
+ key: params.key,
114
+ contentType: params.selection.contentType,
115
+ file: params.selection.file,
116
+ isPublic: true
117
+ });
118
+ }
119
+ _chunk7QVYU63Ejs.__name.call(void 0, uploadBlogImage, "uploadBlogImage");
120
+ function BlogCoverImageField({
121
+ form,
122
+ id,
123
+ label,
124
+ keyPrefix,
125
+ entityId,
126
+ currentUrl,
127
+ alt,
128
+ selection,
129
+ onSelectionChange
130
+ }) {
131
+ const [files, setFiles] = _react.useState.call(void 0, null);
132
+ _react.useEffect.call(void 0, () => {
133
+ if (selection === null) setFiles(null);
134
+ }, [selection]);
135
+ const previewUrl = _react.useMemo.call(void 0, () => selection ? URL.createObjectURL(selection.file) : void 0, [selection]);
136
+ _react.useEffect.call(void 0, () => {
137
+ return () => {
138
+ if (previewUrl) URL.revokeObjectURL(previewUrl);
139
+ };
140
+ }, [previewUrl]);
141
+ const src = _nullishCoalesce(previewUrl, () => ( currentUrl));
142
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormFieldWrapper, { form, name: id, label, children: (field) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
143
+ _chunk3NLAXVINjs.FileUploader,
144
+ {
145
+ value: files,
146
+ onValueChange: (value) => {
147
+ setFiles(value);
148
+ const file = _optionalChain([value, 'optionalAccess', _ => _[0]]);
149
+ if (!file) return;
150
+ const extension = _nullishCoalesce(file.type.split("/").pop(), () => ( ""));
151
+ field.onChange(`${keyPrefix}/${entityId}/${entityId}.${Date.now()}.${extension}`);
152
+ onSelectionChange({ file, contentType: file.type });
153
+ },
154
+ dropzoneOptions: dropzone,
155
+ className: "w-full",
156
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FileInput, { className: "text-muted-foreground/50 rounded-lg outline-1 outline-dashed", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex w-full flex-col items-center justify-center p-4", children: src ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
157
+ _image2.default,
158
+ {
159
+ src,
160
+ alt: _nullishCoalesce(alt, () => ( label)),
161
+ width: 320,
162
+ height: 180,
163
+ className: "h-auto max-h-48 w-auto rounded-md object-cover",
164
+ unoptimized: _chunkNFBOSPNJjs.isRemoteImageSrc.call(void 0, previewUrl ? void 0 : currentUrl)
165
+ }
166
+ ) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
167
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.UploadIcon, { className: "my-4 h-8 w-8" }),
168
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground text-xs", children: label })
169
+ ] }) }) })
170
+ }
171
+ ) });
172
+ }
173
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogCoverImageField, "BlogCoverImageField");
174
+
175
+ // src/features/blog/components/admin/BlogTranslationStatus.tsx
176
+
177
+
178
+
179
+
180
+ var BLOG_STATUS_BADGE = {
181
+ draft: "softGray",
182
+ published: "softGreen",
183
+ unpublished: "softAmber"
184
+ };
185
+ function blogCategoryAdminName(category) {
186
+ return _nullishCoalesce(_nullishCoalesce(_optionalChain([category, 'access', _2 => _2.original, 'optionalAccess', _3 => _3.name]), () => ( category.name)), () => ( ""));
187
+ }
188
+ _chunk7QVYU63Ejs.__name.call(void 0, blogCategoryAdminName, "blogCategoryAdminName");
189
+ function useBlogLanguageName() {
190
+ const locale = _chunkNFBOSPNJjs.useI18nLocale.call(void 0, );
191
+ const names = _react.useMemo.call(void 0, () => {
192
+ try {
193
+ return new Intl.DisplayNames([locale], { type: "language" });
194
+ } catch (e) {
195
+ return void 0;
196
+ }
197
+ }, [locale]);
198
+ return _react.useCallback.call(void 0,
199
+ (language) => {
200
+ const name = _optionalChain([names, 'optionalAccess', _4 => _4.of, 'call', _5 => _5(language)]);
201
+ if (!name) return language;
202
+ return name.charAt(0).toLocaleUpperCase(locale) + name.slice(1);
203
+ },
204
+ [names, locale]
205
+ );
206
+ }
207
+ _chunk7QVYU63Ejs.__name.call(void 0, useBlogLanguageName, "useBlogLanguageName");
208
+ function useBlogDateFormatter() {
209
+ const locale = _chunkNFBOSPNJjs.useI18nLocale.call(void 0, );
210
+ return _react.useCallback.call(void 0, (date) => date ? date.toLocaleDateString(locale, { dateStyle: "medium" }) : "", [locale]);
211
+ }
212
+ _chunk7QVYU63Ejs.__name.call(void 0, useBlogDateFormatter, "useBlogDateFormatter");
213
+ function BlogTranslationStatus({ aiStatus, onRetranslate }) {
214
+ const t = _nextintl.useTranslations.call(void 0, );
215
+ const [isRetrying, setIsRetrying] = _react.useState.call(void 0, false);
216
+ if (aiStatus === "completed") return null;
217
+ if (aiStatus === "pending" || aiStatus === "in_progress") {
218
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center gap-x-2", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.Badge, { variant: "softBlue", children: [
219
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.LoaderCircleIcon, { className: "animate-spin" }),
220
+ aiStatus === "pending" ? t("blog.translation.pending") : t("blog.translation.translating")
221
+ ] }) });
222
+ }
223
+ const retranslate = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, async () => {
224
+ if (!onRetranslate) return;
225
+ setIsRetrying(true);
226
+ try {
227
+ await onRetranslate();
228
+ } catch (error) {
229
+ _chunk3NLAXVINjs.errorToast.call(void 0, { title: t("common.errors.error"), error });
230
+ } finally {
231
+ setIsRetrying(false);
232
+ }
233
+ }, "retranslate");
234
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-x-2", children: [
235
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Badge, { variant: "softRed", children: t("blog.translation.failed") }),
236
+ onRetranslate && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.Button, { type: "button", size: "sm", variant: "outline", onClick: () => void retranslate(), disabled: isRetrying, children: [
237
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.RotateCcwIcon, {}),
238
+ t("blog.actions.translateAgain")
239
+ ] })
240
+ ] });
241
+ }
242
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogTranslationStatus, "BlogTranslationStatus");
243
+
244
+ // src/features/blog/components/admin/BlogCategoryEditor.tsx
245
+
246
+ var buildTranslationSchema = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (t) => _zod3.z.object({
247
+ id: _zod3.z.string(),
248
+ name: _zod3.z.string().min(1, { message: t("blog.errors.name") }),
249
+ slug: _zod3.z.string().optional(),
250
+ description: _zod3.z.string().optional()
251
+ }), "buildTranslationSchema");
252
+ var buildFormSchema = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (t) => _zod3.z.object({
253
+ id: _zod3.z.string().uuid(),
254
+ originalLanguage: _zod3.z.string().min(1, { message: t("blog.errors.language") }),
255
+ name: _zod3.z.string().min(1, { message: t("blog.errors.name") }),
256
+ slug: _zod3.z.string().optional(),
257
+ description: _zod3.z.string().optional(),
258
+ image: _zod3.z.string().optional(),
259
+ translations: _zod3.z.array(buildTranslationSchema(t))
260
+ }), "buildFormSchema");
261
+ var sameTranslation = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (a, b) => !!b && a.name === b.name && (_nullishCoalesce(a.slug, () => ( ""))) === (_nullishCoalesce(b.slug, () => ( ""))) && (_nullishCoalesce(a.description, () => ( ""))) === (_nullishCoalesce(b.description, () => ( ""))), "sameTranslation");
262
+ function BlogCategoryEditor({ category, trigger, onSuccess }) {
263
+ const t = _nextintl.useTranslations.call(void 0, );
264
+ const formSchema = _react.useMemo.call(void 0, () => buildFormSchema(t), [t]);
265
+ const locale = _chunkNFBOSPNJjs.useI18nLocale.call(void 0, );
266
+ const languageName = useBlogLanguageName();
267
+ const [image, setImage] = _react.useState.call(void 0, null);
268
+ const languages = _react.useMemo.call(void 0, () => _chunkNFBOSPNJjs.getI18nSupportedLocales.call(void 0, ), []);
269
+ const original = _optionalChain([category, 'optionalAccess', _6 => _6.original]);
270
+ const translations = _react.useMemo.call(void 0,
271
+ () => (_nullishCoalesce(_optionalChain([category, 'optionalAccess', _7 => _7.translations]), () => ( []))).filter((translation) => !translation.isOriginal),
272
+ [category]
273
+ );
274
+ const getDefaultValues = _react.useCallback.call(void 0,
275
+ () => ({
276
+ id: _optionalChain([category, 'optionalAccess', _8 => _8.id]) || _uuid.v4.call(void 0, ),
277
+ originalLanguage: _nullishCoalesce(_optionalChain([category, 'optionalAccess', _9 => _9.originalLanguage]), () => ( (languages.includes(locale) ? locale : languages[0]))),
278
+ name: _nullishCoalesce(_nullishCoalesce(_optionalChain([original, 'optionalAccess', _10 => _10.name]), () => ( _optionalChain([category, 'optionalAccess', _11 => _11.name]))), () => ( "")),
279
+ slug: _nullishCoalesce(_optionalChain([original, 'optionalAccess', _12 => _12.slug]), () => ( "")),
280
+ description: _nullishCoalesce(_optionalChain([original, 'optionalAccess', _13 => _13.description]), () => ( "")),
281
+ // The stored value is a signed URL, not a key: only a newly picked file writes a key.
282
+ image: "",
283
+ translations: translations.map((translation) => ({
284
+ id: translation.id,
285
+ name: _nullishCoalesce(translation.name, () => ( "")),
286
+ slug: _nullishCoalesce(translation.slug, () => ( "")),
287
+ description: _nullishCoalesce(translation.description, () => ( ""))
288
+ }))
289
+ }),
290
+ [category, original, translations, languages, locale]
291
+ );
292
+ const form = _reacthookform.useForm.call(void 0, {
293
+ resolver: _zod.zodResolver.call(void 0, formSchema),
294
+ defaultValues: getDefaultValues()
295
+ });
296
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
297
+ _chunk3NLAXVINjs.EditorSheet,
298
+ {
299
+ form,
300
+ entityType: t("blog.entities.category"),
301
+ entityName: _nullishCoalesce(_optionalChain([original, 'optionalAccess', _14 => _14.name]), () => ( _optionalChain([category, 'optionalAccess', _15 => _15.name]))),
302
+ title: category ? t("blog.admin.editCategory") : t("blog.admin.newCategory"),
303
+ isEdit: !!category,
304
+ module: _chunkNFBOSPNJjs.Modules.BlogCategory,
305
+ size: "md",
306
+ onSubmit: async (values) => {
307
+ if (values.image && image) await uploadBlogImage({ key: values.image, selection: image });
308
+ const imageKey = values.image && image ? values.image : void 0;
309
+ if (!category) {
310
+ return _chunkNFBOSPNJjs.BlogCategoryService.create({
311
+ id: values.id,
312
+ originalLanguage: values.originalLanguage,
313
+ name: values.name,
314
+ description: values.description,
315
+ image: imageKey
316
+ });
317
+ }
318
+ const defaults = getDefaultValues();
319
+ const originalChanged = !!imageKey || !sameTranslation(
320
+ { id: values.id, name: values.name, slug: values.slug, description: values.description },
321
+ { id: defaults.id, name: defaults.name, slug: defaults.slug, description: defaults.description }
322
+ );
323
+ if (originalChanged) {
324
+ await _chunkNFBOSPNJjs.BlogCategoryService.update({
325
+ id: values.id,
326
+ originalLanguage: _optionalChain([category, 'optionalAccess', _16 => _16.originalLanguage]),
327
+ name: values.name,
328
+ slug: values.slug || void 0,
329
+ description: values.description,
330
+ image: imageKey
331
+ });
332
+ }
333
+ for (const translation of values.translations) {
334
+ const before = defaults.translations.find((candidate) => candidate.id === translation.id);
335
+ if (sameTranslation(translation, before)) continue;
336
+ await _chunkNFBOSPNJjs.BlogCategoryTranslationService.update({
337
+ id: translation.id,
338
+ name: translation.name,
339
+ slug: translation.slug || void 0,
340
+ description: translation.description
341
+ });
342
+ }
343
+ return { id: values.id };
344
+ },
345
+ onReset: () => {
346
+ setImage(null);
347
+ return getDefaultValues();
348
+ },
349
+ onSuccess: _nullishCoalesce(onSuccess, () => ( (() => {
350
+ }))),
351
+ trigger,
352
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-full flex-col gap-y-4", children: [
353
+ !category && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
354
+ _chunk3NLAXVINjs.FormSelect,
355
+ {
356
+ form,
357
+ id: "originalLanguage",
358
+ name: t("blog.fields.originalLanguage"),
359
+ values: languages.map((language) => ({ id: language, text: languageName(language) })),
360
+ isRequired: true
361
+ }
362
+ ),
363
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormInput, { form, id: "name", name: t("blog.fields.name"), isRequired: true }),
364
+ category && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormInput, { form, id: "slug", name: t("blog.fields.slug"), description: t("blog.fields.slugHelp") }),
365
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormTextarea, { form, id: "description", name: t("blog.fields.description") }),
366
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
367
+ BlogCoverImageField,
368
+ {
369
+ form,
370
+ id: "image",
371
+ label: t("blog.fields.image"),
372
+ keyPrefix: _chunkNFBOSPNJjs.BLOG_CATEGORY_UPLOAD_PREFIX,
373
+ entityId: form.getValues("id"),
374
+ currentUrl: _optionalChain([category, 'optionalAccess', _17 => _17.image]),
375
+ selection: image,
376
+ onSelectionChange: setImage
377
+ }
378
+ ),
379
+ translations.length > 0 && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-y-2", children: [
380
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.SectionHeader, { className: "mt-2", children: t("blog.fields.languages") }),
381
+ translations.map((translation, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.Collapsible, { className: "rounded-md border", children: [
382
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.CollapsibleTrigger, { className: "flex w-full items-center justify-between gap-x-2 px-3 py-2 text-start", children: [
383
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "flex items-center gap-x-2 text-sm font-medium", children: [
384
+ languageName(translation.language),
385
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogTranslationStatus, { aiStatus: translation.aiStatus })
386
+ ] }),
387
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ChevronDownIcon, { className: "text-muted-foreground size-4" })
388
+ ] }),
389
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.CollapsibleContent, { className: "flex flex-col gap-y-4 border-t p-3", children: [
390
+ translation.aiStatus === "failed" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
391
+ BlogTranslationStatus,
392
+ {
393
+ aiStatus: translation.aiStatus,
394
+ onRetranslate: async () => {
395
+ await _chunkNFBOSPNJjs.BlogCategoryTranslationService.retranslate({ id: translation.id });
396
+ await _optionalChain([onSuccess, 'optionalCall', _18 => _18()]);
397
+ }
398
+ }
399
+ ),
400
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormInput, { form, id: `translations.${index}.name`, name: t("blog.fields.name"), isRequired: true }),
401
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
402
+ _chunk3NLAXVINjs.FormInput,
403
+ {
404
+ form,
405
+ id: `translations.${index}.slug`,
406
+ name: t("blog.fields.slug"),
407
+ description: t("blog.fields.slugHelp")
408
+ }
409
+ ),
410
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
411
+ _chunk3NLAXVINjs.FormTextarea,
412
+ {
413
+ form,
414
+ id: `translations.${index}.description`,
415
+ name: t("blog.fields.description")
416
+ }
417
+ )
418
+ ] })
419
+ ] }, translation.id))
420
+ ] })
421
+ ] })
422
+ }
423
+ );
424
+ }
425
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogCategoryEditor, "BlogCategoryEditor");
426
+
427
+ // src/features/blog/hooks/useBlogCategoryTableStructure.tsx
428
+
429
+ var useBlogCategoryTableStructure = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (params) => {
430
+ const t = _nextintl.useTranslations.call(void 0, );
431
+ const refresh = _optionalChain([params, 'access', _19 => _19.dataRetriever, 'optionalAccess', _20 => _20.refresh]);
432
+ const tableData = _react.useMemo.call(void 0, () => {
433
+ return params.data.map((category) => {
434
+ const entry = { jsonApiData: category };
435
+ params.fields.forEach((field) => {
436
+ entry[field] = category[field];
437
+ });
438
+ return entry;
439
+ });
440
+ }, [params.data, params.fields]);
441
+ const fieldColumnMap = {
442
+ ["name" /* name */]: () => ({
443
+ id: "name" /* name */,
444
+ accessorKey: "name" /* name */,
445
+ header: t("blog.fields.name"),
446
+ cell: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, ({ row }) => {
447
+ const category = row.original.jsonApiData;
448
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
449
+ BlogCategoryEditor,
450
+ {
451
+ category,
452
+ onSuccess: refresh,
453
+ trigger: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", className: "text-primary text-start font-medium", children: blogCategoryAdminName(category) || category.id })
454
+ }
455
+ );
456
+ }, "cell"),
457
+ enableSorting: false,
458
+ enableHiding: false
459
+ }),
460
+ ["languages" /* languages */]: () => ({
461
+ id: "languages" /* languages */,
462
+ accessorKey: "languages" /* languages */,
463
+ header: t("blog.fields.languages"),
464
+ cell: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, ({ row }) => {
465
+ const category = row.original.jsonApiData;
466
+ const total = category.translations.length;
467
+ if (total === 0) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground text-xs", children: "\u2014" });
468
+ const ready = category.translations.filter((translation) => translation.aiStatus === "completed").length;
469
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "block text-xs tabular-nums text-end", children: [
470
+ ready,
471
+ "/",
472
+ total
473
+ ] });
474
+ }, "cell"),
475
+ enableSorting: false,
476
+ enableHiding: false
477
+ })
478
+ };
479
+ const columns = _react.useMemo.call(void 0, () => {
480
+ return params.fields.map((field) => _optionalChain([fieldColumnMap, 'access', _21 => _21[field], 'optionalCall', _22 => _22()])).filter((col) => col !== void 0);
481
+ }, [params.fields, fieldColumnMap, t, refresh]);
482
+ return _react.useMemo.call(void 0, () => ({ data: tableData, columns }), [tableData, columns]);
483
+ }, "useBlogCategoryTableStructure");
484
+ _chunk3NLAXVINjs.registerTableGenerator.call(void 0, "blog-categories", useBlogCategoryTableStructure);
485
+
486
+ // src/features/blog/components/admin/BlogCategoriesList.tsx
487
+
488
+ function BlogCategoriesList({ fullWidth } = {}) {
489
+ const t = _nextintl.useTranslations.call(void 0, );
490
+ const data = _chunk3NLAXVINjs.useDataListRetriever.call(void 0, {
491
+ retriever: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (params) => _chunkNFBOSPNJjs.BlogCategoryService.findMany(params), "retriever"),
492
+ retrieverParams: {},
493
+ module: _chunkNFBOSPNJjs.Modules.BlogCategory
494
+ });
495
+ const functions = [
496
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
497
+ BlogCategoryEditor,
498
+ {
499
+ onSuccess: data.refresh,
500
+ trigger: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Button, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}), nativeButton: false, size: "sm", variant: "outline", children: t("blog.admin.newCategory") })
501
+ },
502
+ "create-blog-category"
503
+ )
504
+ ];
505
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
506
+ _chunk3NLAXVINjs.ContentListTable,
507
+ {
508
+ data,
509
+ fields: ["name" /* name */, "languages" /* languages */],
510
+ tableGeneratorType: _chunkNFBOSPNJjs.Modules.BlogCategory,
511
+ functions,
512
+ fullWidth,
513
+ title: t("blog.entities.categories"),
514
+ emptyState: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.EmptyState, { icon: _lucidereact.TagIcon, title: t("blog.admin.emptyCategories") })
515
+ }
516
+ );
517
+ }
518
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogCategoriesList, "BlogCategoriesList");
519
+
520
+ // src/features/blog/components/admin/BlogLayoutSetting.tsx
521
+
522
+
523
+
524
+ function BlogLayoutSetting() {
525
+ const t = _nextintl.useTranslations.call(void 0, );
526
+ const [layout, setLayout] = _react.useState.call(void 0, void 0);
527
+ const [saving, setSaving] = _react.useState.call(void 0, false);
528
+ _react.useEffect.call(void 0, () => {
529
+ let active = true;
530
+ _chunkNFBOSPNJjs.BlogSettingsService.get().then((settings) => {
531
+ if (active) setLayout(_nullishCoalesce(_optionalChain([settings, 'optionalAccess', _23 => _23.listLayout]), () => ( "featured")));
532
+ }).catch(() => {
533
+ if (active) setLayout("featured");
534
+ });
535
+ return () => {
536
+ active = false;
537
+ };
538
+ }, []);
539
+ const options = {
540
+ featured: { label: t("blog.layout.featured"), description: t("blog.layout.featuredDescription") },
541
+ column: { label: t("blog.layout.column"), description: t("blog.layout.columnDescription") },
542
+ rail: { label: t("blog.layout.rail"), description: t("blog.layout.railDescription") }
543
+ };
544
+ const save = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, async (next) => {
545
+ const previous = layout;
546
+ setLayout(next);
547
+ setSaving(true);
548
+ try {
549
+ await _chunkNFBOSPNJjs.BlogSettingsService.save({ id: _chunkNFBOSPNJjs.BLOG_SETTINGS_ID, listLayout: next });
550
+ _chunkNFBOSPNJjs.showToast.call(void 0, t("blog.layout.saved"));
551
+ } catch (error) {
552
+ setLayout(previous);
553
+ _chunk3NLAXVINjs.errorToast.call(void 0, { title: t("common.errors.error"), error });
554
+ } finally {
555
+ setSaving(false);
556
+ }
557
+ }, "save");
558
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-full max-w-3xl flex-col gap-y-4 p-4", children: [
559
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.SectionHeader, { children: t("blog.layout.title") }),
560
+ layout && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
561
+ _chunk3NLAXVINjs.RadioGroup,
562
+ {
563
+ value: layout,
564
+ onValueChange: (value) => {
565
+ if (!value || value === layout) return;
566
+ void save(value);
567
+ },
568
+ disabled: saving,
569
+ className: "grid grid-cols-1 gap-3 md:grid-cols-3",
570
+ children: _chunkNFBOSPNJjs.BLOG_LIST_LAYOUTS.map((option) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
571
+ "label",
572
+ {
573
+ htmlFor: `blog-layout-${option}`,
574
+ className: "has-data-checked:border-primary flex cursor-pointer items-start gap-x-3 rounded-lg border p-4",
575
+ children: [
576
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.RadioGroupItem, { value: option, id: `blog-layout-${option}`, className: "mt-0.5" }),
577
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "flex flex-col gap-y-1", children: [
578
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-sm font-medium", children: options[option].label }),
579
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground text-xs/relaxed", children: options[option].description })
580
+ ] })
581
+ ]
582
+ },
583
+ option
584
+ ))
585
+ }
586
+ )
587
+ ] });
588
+ }
589
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogLayoutSetting, "BlogLayoutSetting");
590
+
591
+ // src/features/blog/components/admin/BlogPostsList.tsx
592
+
593
+
594
+
595
+ // src/features/blog/hooks/useBlogPostTableStructure.tsx
596
+
597
+
598
+
599
+ // src/features/blog/hooks/useBlogCategoryNames.ts
600
+
601
+ function useBlogCategoryNames() {
602
+ const [names, setNames] = _react.useState.call(void 0, {});
603
+ _react.useEffect.call(void 0, () => {
604
+ let cancelled = false;
605
+ _chunkNFBOSPNJjs.BlogCategoryService.findMany({ fetchAll: true }).then((categories) => {
606
+ if (cancelled) return;
607
+ setNames(Object.fromEntries(categories.map((category) => [category.id, blogCategoryAdminName(category)])));
608
+ }).catch(() => {
609
+ });
610
+ return () => {
611
+ cancelled = true;
612
+ };
613
+ }, []);
614
+ return _react.useCallback.call(void 0, (categoryId) => _nullishCoalesce(names[categoryId], () => ( "")), [names]);
615
+ }
616
+ _chunk7QVYU63Ejs.__name.call(void 0, useBlogCategoryNames, "useBlogCategoryNames");
617
+
618
+ // src/features/blog/hooks/useBlogPostTableStructure.tsx
619
+
620
+ var useBlogPostTableStructure = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (params) => {
621
+ const t = _nextintl.useTranslations.call(void 0, );
622
+ const locale = _chunkNFBOSPNJjs.useI18nLocale.call(void 0, );
623
+ const generateUrl = _chunk3NLAXVINjs.usePageUrlGenerator.call(void 0, );
624
+ const categoryName = useBlogCategoryNames();
625
+ const tableData = _react.useMemo.call(void 0, () => {
626
+ return params.data.map((post) => {
627
+ const entry = { jsonApiData: post };
628
+ params.fields.forEach((field) => {
629
+ entry[field] = post[field];
630
+ });
631
+ return entry;
632
+ });
633
+ }, [params.data, params.fields]);
634
+ const fieldColumnMap = {
635
+ ["title" /* title */]: () => ({
636
+ id: "title" /* title */,
637
+ accessorKey: "title" /* title */,
638
+ header: t("blog.fields.title"),
639
+ cell: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, ({ row }) => {
640
+ const post = row.original.jsonApiData;
641
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Link, { href: generateUrl({ page: _chunkNFBOSPNJjs.Modules.BlogPost, id: post.id }), children: _nullishCoalesce(_nullishCoalesce(_optionalChain([post, 'access', _24 => _24.original, 'optionalAccess', _25 => _25.title]), () => ( post.title)), () => ( post.id)) });
642
+ }, "cell"),
643
+ enableSorting: false,
644
+ enableHiding: false
645
+ }),
646
+ ["status" /* status */]: () => ({
647
+ id: "status" /* status */,
648
+ accessorKey: "status" /* status */,
649
+ header: t("blog.fields.status"),
650
+ cell: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, ({ row }) => {
651
+ const post = row.original.jsonApiData;
652
+ const label = {
653
+ draft: t("blog.status.draft"),
654
+ published: t("blog.status.published"),
655
+ unpublished: t("blog.status.unpublished")
656
+ }[post.status];
657
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Badge, { variant: _nullishCoalesce(BLOG_STATUS_BADGE[post.status], () => ( "softGray")), children: _nullishCoalesce(label, () => ( post.status)) });
658
+ }, "cell"),
659
+ enableSorting: false,
660
+ enableHiding: false
661
+ }),
662
+ ["categories" /* categories */]: () => ({
663
+ id: "categories" /* categories */,
664
+ accessorKey: "categories" /* categories */,
665
+ header: t("blog.fields.categories"),
666
+ cell: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, ({ row }) => {
667
+ const post = row.original.jsonApiData;
668
+ const names = post.categories.map((category) => categoryName(category.id)).filter(Boolean);
669
+ if (names.length === 0) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground text-xs", children: "\u2014" });
670
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs", children: names.join(", ") });
671
+ }, "cell"),
672
+ enableSorting: false,
673
+ enableHiding: false
674
+ }),
675
+ ["publishedAt" /* publishedAt */]: () => ({
676
+ id: "publishedAt" /* publishedAt */,
677
+ accessorKey: "publishedAt" /* publishedAt */,
678
+ header: t("blog.fields.publishedAt"),
679
+ cell: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, ({ row }) => {
680
+ const post = row.original.jsonApiData;
681
+ if (!post.publishedAt) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground text-xs", children: "\u2014" });
682
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs tabular-nums", children: post.publishedAt.toLocaleDateString(locale, { dateStyle: "medium" }) });
683
+ }, "cell"),
684
+ enableSorting: false,
685
+ enableHiding: false
686
+ }),
687
+ ["languages" /* languages */]: () => ({
688
+ id: "languages" /* languages */,
689
+ accessorKey: "languages" /* languages */,
690
+ header: t("blog.fields.languages"),
691
+ cell: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, ({ row }) => {
692
+ const post = row.original.jsonApiData;
693
+ const total = post.translations.length;
694
+ if (total === 0) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground text-xs", children: "\u2014" });
695
+ const ready = post.translations.filter((translation) => translation.aiStatus === "completed").length;
696
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "block text-xs tabular-nums text-end", children: [
697
+ ready,
698
+ "/",
699
+ total
700
+ ] });
701
+ }, "cell"),
702
+ enableSorting: false,
703
+ enableHiding: false
704
+ })
705
+ };
706
+ const columns = _react.useMemo.call(void 0, () => {
707
+ return params.fields.map((field) => _optionalChain([fieldColumnMap, 'access', _26 => _26[field], 'optionalCall', _27 => _27()])).filter((col) => col !== void 0);
708
+ }, [params.fields, fieldColumnMap, t, generateUrl, locale, categoryName]);
709
+ return _react.useMemo.call(void 0, () => ({ data: tableData, columns }), [tableData, columns]);
710
+ }, "useBlogPostTableStructure");
711
+ _chunk3NLAXVINjs.registerTableGenerator.call(void 0, "blog-posts", useBlogPostTableStructure);
712
+
713
+ // src/features/blog/components/admin/BlogPostEditor.tsx
714
+
715
+
716
+
717
+
718
+
719
+
720
+
721
+ var isBodyEmpty = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (body) => !body || Array.isArray(body) && body.length === 0, "isBodyEmpty");
722
+ function BlogPostEditor({ post, trigger, onSuccess }) {
723
+ const t = _nextintl.useTranslations.call(void 0, );
724
+ const categoryName = useBlogCategoryNames();
725
+ const router = _chunkNFBOSPNJjs.useI18nRouter.call(void 0, );
726
+ const locale = _chunkNFBOSPNJjs.useI18nLocale.call(void 0, );
727
+ const languageName = useBlogLanguageName();
728
+ const original = _optionalChain([post, 'optionalAccess', _28 => _28.original]);
729
+ const [cover, setCover] = _react.useState.call(void 0, null);
730
+ const [isBodyEmptyState, setIsBodyEmptyState] = _react.useState.call(void 0, isBodyEmpty(_optionalChain([original, 'optionalAccess', _29 => _29.body])));
731
+ const languages = _react.useMemo.call(void 0, () => _chunkNFBOSPNJjs.getI18nSupportedLocales.call(void 0, ), []);
732
+ const formSchema = _react.useMemo.call(void 0,
733
+ () => _zod3.z.object({
734
+ id: _zod3.z.string().uuid(),
735
+ originalLanguage: _zod3.z.string().min(1, { message: t("blog.errors.language") }),
736
+ title: _zod3.z.string().min(1, { message: t("blog.errors.title") }),
737
+ slug: _zod3.z.string().optional(),
738
+ summary: _zod3.z.string().optional(),
739
+ body: _zod3.z.any(),
740
+ coverImage: _zod3.z.string().optional(),
741
+ coverImageAlt: _zod3.z.string().optional(),
742
+ categories: _zod3.z.array(_zod3.z.object({ id: _zod3.z.string(), name: _zod3.z.string() }))
743
+ }),
744
+ []
745
+ );
746
+ const getDefaultValues = _react.useCallback.call(void 0,
747
+ () => ({
748
+ id: _optionalChain([post, 'optionalAccess', _30 => _30.id]) || _uuid.v4.call(void 0, ),
749
+ originalLanguage: _nullishCoalesce(_optionalChain([post, 'optionalAccess', _31 => _31.originalLanguage]), () => ( (languages.includes(locale) ? locale : languages[0]))),
750
+ title: _nullishCoalesce(_optionalChain([original, 'optionalAccess', _32 => _32.title]), () => ( "")),
751
+ slug: _nullishCoalesce(_optionalChain([original, 'optionalAccess', _33 => _33.slug]), () => ( "")),
752
+ summary: _nullishCoalesce(_optionalChain([original, 'optionalAccess', _34 => _34.summary]), () => ( "")),
753
+ body: _optionalChain([original, 'optionalAccess', _35 => _35.body]) || [],
754
+ // The stored value is a signed URL, not a key: only a newly picked file
755
+ // writes a key here, and only then is the field sent.
756
+ coverImage: "",
757
+ coverImageAlt: _nullishCoalesce(_optionalChain([original, 'optionalAccess', _36 => _36.coverImageAlt]), () => ( "")),
758
+ categories: (_nullishCoalesce(_optionalChain([post, 'optionalAccess', _37 => _37.categories]), () => ( []))).map((category) => ({
759
+ id: category.id,
760
+ name: blogCategoryAdminName(category)
761
+ }))
762
+ }),
763
+ [post, original, languages, locale]
764
+ );
765
+ const form = _reacthookform.useForm.call(void 0, {
766
+ resolver: _zod.zodResolver.call(void 0, formSchema),
767
+ defaultValues: getDefaultValues()
768
+ });
769
+ const { dirtyFields } = form.formState;
770
+ const isFormDirty = _react.useCallback.call(void 0, () => {
771
+ const dirty = { ...dirtyFields };
772
+ if (dirty.body && isBodyEmptyState) delete dirty.body;
773
+ return Object.keys(dirty).length > 0;
774
+ }, [dirtyFields, isBodyEmptyState]);
775
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
776
+ _chunk3NLAXVINjs.EditorSheet,
777
+ {
778
+ form,
779
+ entityType: t("blog.entities.post"),
780
+ entityName: _optionalChain([original, 'optionalAccess', _38 => _38.title]),
781
+ title: post ? t("blog.admin.editPost") : t("blog.admin.newPost"),
782
+ isEdit: !!post,
783
+ module: _chunkNFBOSPNJjs.Modules.BlogPost,
784
+ size: "lg",
785
+ isFormDirty,
786
+ onSubmit: async (values) => {
787
+ if (values.coverImage && cover) await uploadBlogImage({ key: values.coverImage, selection: cover });
788
+ const payload = {
789
+ id: values.id,
790
+ title: values.title,
791
+ // An empty summary lets the worker write one; on edit the summary is
792
+ // sent only when changed here, so an untouched AI summary is regenerated.
793
+ summary: post ? form.getFieldState("summary").isDirty ? values.summary : void 0 : values.summary || void 0,
794
+ body: values.body,
795
+ coverImage: values.coverImage && cover ? values.coverImage : void 0,
796
+ coverImageAlt: values.coverImageAlt,
797
+ categoryIds: values.categories.map((category) => category.id)
798
+ };
799
+ if (post) {
800
+ return _chunkNFBOSPNJjs.BlogPostService.update({
801
+ ...payload,
802
+ originalLanguage: post.originalLanguage,
803
+ slug: values.slug || void 0
804
+ });
805
+ }
806
+ return _chunkNFBOSPNJjs.BlogPostService.create({ ...payload, originalLanguage: values.originalLanguage });
807
+ },
808
+ onReset: () => {
809
+ setCover(null);
810
+ setIsBodyEmptyState(isBodyEmpty(_optionalChain([original, 'optionalAccess', _39 => _39.body])));
811
+ return getDefaultValues();
812
+ },
813
+ onSuccess,
814
+ onNavigate: (url) => router.push(url),
815
+ trigger,
816
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-full flex-col gap-y-4", children: [
817
+ !post && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
818
+ _chunk3NLAXVINjs.FormSelect,
819
+ {
820
+ form,
821
+ id: "originalLanguage",
822
+ name: t("blog.fields.originalLanguage"),
823
+ values: languages.map((language) => ({ id: language, text: languageName(language) })),
824
+ isRequired: true
825
+ }
826
+ ),
827
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormInput, { form, id: "title", name: t("blog.fields.title"), isRequired: true }),
828
+ post && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormInput, { form, id: "slug", name: t("blog.fields.slug"), description: t("blog.fields.slugHelp") }),
829
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
830
+ _chunk3NLAXVINjs.FormTextarea,
831
+ {
832
+ form,
833
+ id: "summary",
834
+ name: t("blog.fields.summary"),
835
+ description: t("blog.fields.summaryHelp")
836
+ }
837
+ ),
838
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
839
+ BlogCoverImageField,
840
+ {
841
+ form,
842
+ id: "coverImage",
843
+ label: t("blog.fields.coverImage"),
844
+ keyPrefix: _chunkNFBOSPNJjs.BLOG_POST_UPLOAD_PREFIX,
845
+ entityId: form.getValues("id"),
846
+ currentUrl: _optionalChain([post, 'optionalAccess', _40 => _40.coverImage]),
847
+ alt: _optionalChain([original, 'optionalAccess', _41 => _41.coverImageAlt]),
848
+ selection: cover,
849
+ onSelectionChange: setCover
850
+ }
851
+ ),
852
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormInput, { form, id: "coverImageAlt", name: t("blog.fields.coverImageAlt") }),
853
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
854
+ _chunk3NLAXVINjs.EntityMultiSelector,
855
+ {
856
+ id: "categories",
857
+ form,
858
+ label: t("blog.fields.categories"),
859
+ retriever: (params) => _chunkNFBOSPNJjs.BlogCategoryService.findMany(params),
860
+ module: _chunkNFBOSPNJjs.Modules.BlogCategory,
861
+ getLabel: blogCategoryAdminName,
862
+ getFormValueLabel: (value) => value.name || categoryName(value.id)
863
+ }
864
+ ),
865
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
866
+ _chunk3NLAXVINjs.FormBlockNote,
867
+ {
868
+ uploadKeyPrefix: _chunkNFBOSPNJjs.BLOG_POST_UPLOAD_PREFIX,
869
+ form,
870
+ id: "body",
871
+ name: t("blog.fields.body"),
872
+ type: "blog-post",
873
+ isRequired: true,
874
+ onEmptyChange: setIsBodyEmptyState
875
+ }
876
+ )
877
+ ] })
878
+ }
879
+ );
880
+ }
881
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostEditor, "BlogPostEditor");
882
+
883
+ // src/features/blog/components/admin/BlogPostsList.tsx
884
+
885
+ function BlogPostsList({ fullWidth } = {}) {
886
+ const t = _nextintl.useTranslations.call(void 0, );
887
+ const data = _chunk3NLAXVINjs.useDataListRetriever.call(void 0, {
888
+ retriever: /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (params) => _chunkNFBOSPNJjs.BlogPostService.findMany(params), "retriever"),
889
+ retrieverParams: {},
890
+ module: _chunkNFBOSPNJjs.Modules.BlogPost
891
+ });
892
+ const functions = [
893
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
894
+ BlogPostEditor,
895
+ {
896
+ trigger: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Button, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}), nativeButton: false, size: "sm", variant: "outline", children: t("blog.admin.newPost") })
897
+ },
898
+ "create-blog-post"
899
+ )
900
+ ];
901
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
902
+ _chunk3NLAXVINjs.ContentListTable,
903
+ {
904
+ data,
905
+ fields: [
906
+ "title" /* title */,
907
+ "status" /* status */,
908
+ "categories" /* categories */,
909
+ "publishedAt" /* publishedAt */,
910
+ "languages" /* languages */
911
+ ],
912
+ tableGeneratorType: _chunkNFBOSPNJjs.Modules.BlogPost,
913
+ functions,
914
+ fullWidth,
915
+ title: t("blog.entities.posts"),
916
+ emptyState: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.EmptyState, { icon: _lucidereact.NewspaperIcon, title: t("blog.admin.empty") })
917
+ }
918
+ );
919
+ }
920
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostsList, "BlogPostsList");
921
+
922
+ // src/features/blog/components/admin/BlogAdminContainer.tsx
923
+
924
+ function BlogAdminContainer() {
925
+ const t = _nextintl.useTranslations.call(void 0, );
926
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.AdministrationProvider, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
927
+ _chunk3NLAXVINjs.RoundPageContainer,
928
+ {
929
+ module: _chunkNFBOSPNJjs.Modules.BlogPost,
930
+ fullWidth: true,
931
+ tabs: [
932
+ { sectionKey: "posts", label: t("blog.tabs.posts"), content: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostsList, { fullWidth: true }) },
933
+ { sectionKey: "categories", label: t("blog.tabs.categories"), content: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogCategoriesList, { fullWidth: true }) },
934
+ { sectionKey: "layout", label: t("blog.tabs.layout"), content: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogLayoutSetting, {}) }
935
+ ]
936
+ }
937
+ ) });
938
+ }
939
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogAdminContainer, "BlogAdminContainer");
940
+
941
+ // src/features/blog/components/admin/BlogPostContainer.tsx
942
+
943
+
944
+
945
+ // src/features/blog/contexts/BlogPostContext.tsx
946
+
947
+
948
+ var TRANSLATION_POLL_MS = 5e3;
949
+ var BlogPostContext = _react.createContext.call(void 0, void 0);
950
+ var BlogPostProvider = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, ({ postId, children }) => {
951
+ const [post, setPost] = _react.useState.call(void 0, void 0);
952
+ const reload = _react.useCallback.call(void 0, async () => {
953
+ const loaded = await _chunkNFBOSPNJjs.BlogPostService.findOne({ id: postId });
954
+ setPost(loaded);
955
+ }, [postId]);
956
+ _react.useEffect.call(void 0, () => {
957
+ void reload();
958
+ }, [reload]);
959
+ const isTranslating = _react.useMemo.call(void 0,
960
+ () => (_nullishCoalesce(_optionalChain([post, 'optionalAccess', _42 => _42.translations]), () => ( []))).some(
961
+ (translation) => translation.aiStatus === "pending" || translation.aiStatus === "in_progress"
962
+ ),
963
+ [post]
964
+ );
965
+ _react.useEffect.call(void 0, () => {
966
+ if (!isTranslating) return;
967
+ const handle = setInterval(() => {
968
+ reload().catch(() => {
969
+ });
970
+ }, TRANSLATION_POLL_MS);
971
+ return () => clearInterval(handle);
972
+ }, [isTranslating, reload]);
973
+ const value = _react.useMemo.call(void 0, () => ({ post, reload }), [post, reload]);
974
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostContext.Provider, { value, children });
975
+ }, "BlogPostProvider");
976
+ var useBlogPost = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, () => {
977
+ const context = _react.useContext.call(void 0, BlogPostContext);
978
+ if (context === void 0) {
979
+ throw new Error("useBlogPost must be used within a BlogPostProvider");
980
+ }
981
+ return context;
982
+ }, "useBlogPost");
983
+
984
+ // src/features/blog/components/admin/BlogPostDeleter.tsx
985
+
986
+
987
+ function BlogPostDeleter() {
988
+ const t = _nextintl.useTranslations.call(void 0, );
989
+ const generateUrl = _chunk3NLAXVINjs.usePageUrlGenerator.call(void 0, );
990
+ const { post } = useBlogPost();
991
+ if (!post) return null;
992
+ const type = t("blog.entities.post");
993
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
994
+ _chunk3NLAXVINjs.CommonDeleter,
995
+ {
996
+ title: t("common.delete.title", { type }),
997
+ subtitle: t("common.delete.subtitle", { type }),
998
+ description: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "text-destructive p-4 text-sm", children: t("common.delete.description", { type }) }),
999
+ showLabel: true,
1000
+ deleteFunction: () => _chunkNFBOSPNJjs.BlogPostService.delete({ id: post.id }),
1001
+ redirectTo: generateUrl({ page: _chunkNFBOSPNJjs.Modules.BlogPost })
1002
+ }
1003
+ );
1004
+ }
1005
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostDeleter, "BlogPostDeleter");
1006
+
1007
+ // src/features/blog/components/admin/BlogPostPublishButton.tsx
1008
+
1009
+
1010
+
1011
+
1012
+ function BlogPostPublishButton() {
1013
+ const t = _nextintl.useTranslations.call(void 0, );
1014
+ const { post, reload } = useBlogPost();
1015
+ const [saving, setSaving] = _react.useState.call(void 0, false);
1016
+ if (!post) return null;
1017
+ const isPublished = post.status === "published";
1018
+ const toggle = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, async () => {
1019
+ setSaving(true);
1020
+ try {
1021
+ if (isPublished) await _chunkNFBOSPNJjs.BlogPostService.unpublish({ id: post.id });
1022
+ else await _chunkNFBOSPNJjs.BlogPostService.publish({ id: post.id });
1023
+ await reload();
1024
+ } catch (error) {
1025
+ _chunk3NLAXVINjs.errorToast.call(void 0, { title: t("common.errors.error"), error });
1026
+ } finally {
1027
+ setSaving(false);
1028
+ }
1029
+ }, "toggle");
1030
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1031
+ _chunk3NLAXVINjs.Button,
1032
+ {
1033
+ type: "button",
1034
+ size: "sm",
1035
+ variant: isPublished ? "outline" : "default",
1036
+ onClick: () => void toggle(),
1037
+ disabled: saving,
1038
+ children: [
1039
+ isPublished ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.EyeOffIcon, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.EyeIcon, {}),
1040
+ isPublished ? t("blog.actions.unpublish") : t("blog.actions.publish")
1041
+ ]
1042
+ }
1043
+ );
1044
+ }
1045
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostPublishButton, "BlogPostPublishButton");
1046
+
1047
+ // src/features/blog/components/admin/BlogPostTranslationPanel.tsx
1048
+
1049
+
1050
+
1051
+
1052
+
1053
+ // src/features/blog/components/admin/BlogPostComparison.tsx
1054
+
1055
+
1056
+ function BlogPostTranslationFields({ translation }) {
1057
+ const t = _nextintl.useTranslations.call(void 0, );
1058
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-y-4", children: [
1059
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.DetailField, { label: t("blog.fields.title"), value: translation.title }),
1060
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.DetailField, { label: t("blog.fields.slug"), value: translation.slug }),
1061
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.DetailField, { label: t("blog.fields.summary"), value: translation.summary }),
1062
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.DetailField, { label: t("blog.fields.coverImageAlt"), value: translation.coverImageAlt }),
1063
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.DetailField, { label: t("blog.fields.body"), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.BlockNoteEditorContainer, { id: translation.id, type: "blog-post", initialContent: translation.body }) })
1064
+ ] });
1065
+ }
1066
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostTranslationFields, "BlogPostTranslationFields");
1067
+ function BlogPostComparison({ original, translation }) {
1068
+ const t = _nextintl.useTranslations.call(void 0, );
1069
+ const languageName = useBlogLanguageName();
1070
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [
1071
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "bg-muted/40 flex flex-col gap-y-4 rounded-lg border p-4", children: [
1072
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-x-2", children: [
1073
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.MicroLabel, { as: "h3", children: languageName(original.language) }),
1074
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Badge, { variant: "softGray", children: t("blog.translation.original") })
1075
+ ] }),
1076
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostTranslationFields, { translation: original })
1077
+ ] }),
1078
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-y-4 rounded-lg border p-4", children: [
1079
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-x-2", children: [
1080
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.MicroLabel, { as: "h3", children: languageName(translation.language) }),
1081
+ translation.source === "manual" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Badge, { variant: "softAmber", children: t("blog.translation.editedByHand") })
1082
+ ] }),
1083
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostTranslationFields, { translation })
1084
+ ] })
1085
+ ] });
1086
+ }
1087
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostComparison, "BlogPostComparison");
1088
+
1089
+ // src/features/blog/components/admin/BlogPostTranslationEditor.tsx
1090
+
1091
+
1092
+
1093
+
1094
+
1095
+
1096
+ var isBodyEmpty2 = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (body) => !body || Array.isArray(body) && body.length === 0, "isBodyEmpty");
1097
+ var buildFormSchema2 = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (t) => _zod3.z.object({
1098
+ id: _zod3.z.string().uuid(),
1099
+ title: _zod3.z.string().min(1, { message: t("blog.errors.title") }),
1100
+ slug: _zod3.z.string().optional(),
1101
+ summary: _zod3.z.string().optional(),
1102
+ body: _zod3.z.any(),
1103
+ coverImageAlt: _zod3.z.string().optional()
1104
+ }), "buildFormSchema");
1105
+ function BlogPostTranslationEditor({ translation, trigger, onSuccess }) {
1106
+ const t = _nextintl.useTranslations.call(void 0, );
1107
+ const formSchema = _react.useMemo.call(void 0, () => buildFormSchema2(t), [t]);
1108
+ const languageName = useBlogLanguageName();
1109
+ const [isBodyEmptyState, setIsBodyEmptyState] = _react.useState.call(void 0, isBodyEmpty2(translation.body));
1110
+ const getDefaultValues = _react.useCallback.call(void 0,
1111
+ () => ({
1112
+ id: translation.id,
1113
+ title: _nullishCoalesce(translation.title, () => ( "")),
1114
+ slug: _nullishCoalesce(translation.slug, () => ( "")),
1115
+ summary: _nullishCoalesce(translation.summary, () => ( "")),
1116
+ body: translation.body || [],
1117
+ coverImageAlt: _nullishCoalesce(translation.coverImageAlt, () => ( ""))
1118
+ }),
1119
+ [translation]
1120
+ );
1121
+ const form = _reacthookform.useForm.call(void 0, {
1122
+ resolver: _zod.zodResolver.call(void 0, formSchema),
1123
+ defaultValues: getDefaultValues()
1124
+ });
1125
+ const { dirtyFields } = form.formState;
1126
+ const isFormDirty = _react.useCallback.call(void 0, () => {
1127
+ const dirty = { ...dirtyFields };
1128
+ if (dirty.body && isBodyEmptyState) delete dirty.body;
1129
+ return Object.keys(dirty).length > 0;
1130
+ }, [dirtyFields, isBodyEmptyState]);
1131
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1132
+ _chunk3NLAXVINjs.EditorSheet,
1133
+ {
1134
+ form,
1135
+ entityType: t("blog.entities.post"),
1136
+ entityName: translation.title,
1137
+ title: `${t("blog.admin.editPost")} \xB7 ${languageName(translation.language)}`,
1138
+ isEdit: true,
1139
+ module: _chunkNFBOSPNJjs.Modules.BlogPostTranslation,
1140
+ size: "lg",
1141
+ isFormDirty,
1142
+ onSubmit: async (values) => _chunkNFBOSPNJjs.BlogPostTranslationService.update({
1143
+ id: values.id,
1144
+ title: values.title,
1145
+ slug: values.slug || void 0,
1146
+ summary: values.summary,
1147
+ body: values.body,
1148
+ coverImageAlt: values.coverImageAlt
1149
+ }),
1150
+ onReset: () => {
1151
+ setIsBodyEmptyState(isBodyEmpty2(translation.body));
1152
+ return getDefaultValues();
1153
+ },
1154
+ onSuccess: _nullishCoalesce(onSuccess, () => ( (() => {
1155
+ }))),
1156
+ trigger,
1157
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-full flex-col gap-y-4", children: [
1158
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormInput, { form, id: "title", name: t("blog.fields.title"), isRequired: true }),
1159
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormInput, { form, id: "slug", name: t("blog.fields.slug"), description: t("blog.fields.slugHelp") }),
1160
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormTextarea, { form, id: "summary", name: t("blog.fields.summary") }),
1161
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.FormInput, { form, id: "coverImageAlt", name: t("blog.fields.coverImageAlt") }),
1162
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1163
+ _chunk3NLAXVINjs.FormBlockNote,
1164
+ {
1165
+ uploadKeyPrefix: _chunkNFBOSPNJjs.BLOG_POST_UPLOAD_PREFIX,
1166
+ form,
1167
+ id: "body",
1168
+ name: t("blog.fields.body"),
1169
+ type: "blog-post",
1170
+ isRequired: true,
1171
+ onEmptyChange: setIsBodyEmptyState
1172
+ }
1173
+ )
1174
+ ] })
1175
+ }
1176
+ );
1177
+ }
1178
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostTranslationEditor, "BlogPostTranslationEditor");
1179
+
1180
+ // src/features/blog/components/admin/BlogPostTranslationPanel.tsx
1181
+
1182
+ function BlogPostTranslationPanel({ post, translation, onChanged }) {
1183
+ const t = _nextintl.useTranslations.call(void 0, );
1184
+ const categoryName = useBlogCategoryNames();
1185
+ const languageName = useBlogLanguageName();
1186
+ const formatDate = useBlogDateFormatter();
1187
+ const [isComparing, setIsComparing] = _react.useState.call(void 0, false);
1188
+ const original = post.original;
1189
+ const reload = _nullishCoalesce(onChanged, () => ( (async () => {
1190
+ })));
1191
+ const editTrigger = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.Button, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}), nativeButton: false, size: "sm", variant: "outline", children: [
1192
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.PencilIcon, {}),
1193
+ t("blog.actions.edit")
1194
+ ] });
1195
+ if (translation.isOriginal) {
1196
+ const statusLabel = {
1197
+ draft: t("blog.status.draft"),
1198
+ published: t("blog.status.published"),
1199
+ unpublished: t("blog.status.unpublished")
1200
+ }[post.status];
1201
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-full flex-col gap-y-6 p-4", children: [
1202
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between gap-x-4", children: [
1203
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Badge, { variant: "softGray", children: t("blog.translation.original") }),
1204
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostEditor, { post, trigger: editTrigger, onSuccess: reload })
1205
+ ] }),
1206
+ post.coverImage && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1207
+ _image2.default,
1208
+ {
1209
+ src: post.coverImage,
1210
+ alt: _nullishCoalesce(translation.coverImageAlt, () => ( translation.title)),
1211
+ width: 640,
1212
+ height: 360,
1213
+ className: "h-auto max-h-72 w-auto rounded-lg object-cover",
1214
+ unoptimized: _chunkNFBOSPNJjs.isRemoteImageSrc.call(void 0, post.coverImage)
1215
+ }
1216
+ ),
1217
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "grid grid-cols-1 gap-4 md:grid-cols-3", children: [
1218
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.DetailField, { label: t("blog.fields.status"), value: statusLabel }),
1219
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.DetailField, { label: t("blog.fields.publishedAt"), value: formatDate(post.publishedAt) || "\u2014" }),
1220
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1221
+ _chunk3NLAXVINjs.DetailField,
1222
+ {
1223
+ label: t("blog.fields.categories"),
1224
+ value: post.categories.map((category) => categoryName(category.id)).filter(Boolean).join(", ") || "\u2014"
1225
+ }
1226
+ )
1227
+ ] }),
1228
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostTranslationFields, { translation })
1229
+ ] });
1230
+ }
1231
+ const isWorking = translation.aiStatus === "pending" || translation.aiStatus === "in_progress";
1232
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-full flex-col gap-y-6 p-4", children: [
1233
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Alert, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.AlertDescription, { className: "flex flex-col gap-y-2", children: [
1234
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-wrap items-center gap-2", children: [
1235
+ translation.source === "manual" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Badge, { variant: "softAmber", children: t("blog.translation.editedByHand") }),
1236
+ original && translation.translatedAt && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: t("blog.translation.translatedFrom", {
1237
+ language: languageName(original.language),
1238
+ date: formatDate(translation.translatedAt)
1239
+ }) })
1240
+ ] }),
1241
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: t("blog.translation.overwriteWarning") }),
1242
+ original && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Button, { type: "button", size: "sm", variant: "ghost", onClick: () => setIsComparing((value) => !value), children: isComparing ? t("blog.actions.hideComparison") : t("blog.actions.compareWithOriginal") }) })
1243
+ ] }) }),
1244
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between gap-x-4", children: [
1245
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1246
+ BlogTranslationStatus,
1247
+ {
1248
+ aiStatus: translation.aiStatus,
1249
+ onRetranslate: async () => {
1250
+ await _chunkNFBOSPNJjs.BlogPostTranslationService.retranslate({ id: translation.id });
1251
+ await reload();
1252
+ }
1253
+ }
1254
+ ),
1255
+ !isWorking && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostTranslationEditor, { translation, trigger: editTrigger, onSuccess: reload })
1256
+ ] }),
1257
+ isComparing && original ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostComparison, { original, translation }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostTranslationFields, { translation })
1258
+ ] });
1259
+ }
1260
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostTranslationPanel, "BlogPostTranslationPanel");
1261
+
1262
+ // src/features/blog/components/admin/BlogPostContainer.tsx
1263
+
1264
+ function BlogPostContainer({ postId }) {
1265
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostProvider, { postId, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostShell, {}) });
1266
+ }
1267
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostContainer, "BlogPostContainer");
1268
+ function BlogPostShell() {
1269
+ const t = _nextintl.useTranslations.call(void 0, );
1270
+ const generateUrl = _chunk3NLAXVINjs.usePageUrlGenerator.call(void 0, );
1271
+ const languageName = useBlogLanguageName();
1272
+ const { post, reload } = useBlogPost();
1273
+ const translations = _react.useMemo.call(void 0, () => {
1274
+ const all = _nullishCoalesce(_optionalChain([post, 'optionalAccess', _43 => _43.translations]), () => ( []));
1275
+ return [
1276
+ ...all.filter((translation) => translation.isOriginal),
1277
+ ...all.filter((translation) => !translation.isOriginal)
1278
+ ];
1279
+ }, [post]);
1280
+ if (!post) return null;
1281
+ const title = _nullishCoalesce(_nullishCoalesce(_optionalChain([post, 'access', _44 => _44.original, 'optionalAccess', _45 => _45.title]), () => ( post.title)), () => ( ""));
1282
+ const breadcrumbs = [
1283
+ { name: t("blog.admin.title"), href: generateUrl({ page: _chunkNFBOSPNJjs.Modules.BlogPost }) },
1284
+ { name: title }
1285
+ ];
1286
+ const statusLabel = {
1287
+ draft: t("blog.status.draft"),
1288
+ published: t("blog.status.published"),
1289
+ unpublished: t("blog.status.unpublished")
1290
+ }[post.status];
1291
+ const tabLabel = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (translation) => {
1292
+ const parts = [languageName(translation.language)];
1293
+ if (translation.isOriginal) parts.push(t("blog.translation.original"));
1294
+ if (translation.aiStatus === "pending" || translation.aiStatus === "in_progress")
1295
+ parts.push(t("blog.translation.translating"));
1296
+ if (translation.aiStatus === "failed") parts.push(t("blog.translation.failed"));
1297
+ return parts.join(" \xB7 ");
1298
+ }, "tabLabel");
1299
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1300
+ _chunk3NLAXVINjs.SharedProvider,
1301
+ {
1302
+ value: {
1303
+ breadcrumbs,
1304
+ title: {
1305
+ type: t("blog.admin.title"),
1306
+ element: title,
1307
+ functions: [
1308
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Badge, { variant: BLOG_STATUS_BADGE[post.status], children: statusLabel }, "blogPostStatus"),
1309
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostPublishButton, {}, "blogPostPublish"),
1310
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostDeleter, {}, "blogPostDeleter")
1311
+ ]
1312
+ }
1313
+ },
1314
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1315
+ _chunk3NLAXVINjs.RoundPageContainer,
1316
+ {
1317
+ module: _chunkNFBOSPNJjs.Modules.BlogPost,
1318
+ id: post.id,
1319
+ fullWidth: true,
1320
+ forceHeader: true,
1321
+ tabs: translations.map((translation) => ({
1322
+ sectionKey: translation.language,
1323
+ label: tabLabel(translation),
1324
+ content: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostTranslationPanel, { post, translation, onChanged: reload })
1325
+ }))
1326
+ }
1327
+ )
1328
+ }
1329
+ );
1330
+ }
1331
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostShell, "BlogPostShell");
1332
+
1333
+ // src/features/blog/components/public/BlogCategoryChips.tsx
1334
+
1335
+
1336
+ // src/features/blog/components/public/blogPublicHelpers.ts
1337
+ function blogListHref(basePath, params) {
1338
+ const search = new URLSearchParams();
1339
+ if (params.category) search.set("category", params.category);
1340
+ if (params.q) search.set("q", params.q);
1341
+ if (params.page && params.page > 1) search.set("page", String(params.page));
1342
+ const query = search.toString();
1343
+ return query ? `${basePath}?${query}` : basePath;
1344
+ }
1345
+ _chunk7QVYU63Ejs.__name.call(void 0, blogListHref, "blogListHref");
1346
+ function blogPostHref(basePath, slug) {
1347
+ return `${basePath}/${encodeURIComponent(slug)}`;
1348
+ }
1349
+ _chunk7QVYU63Ejs.__name.call(void 0, blogPostHref, "blogPostHref");
1350
+ function resolvePostCategory(post, categories) {
1351
+ for (const id of post.categoryIds) {
1352
+ const category = categories.find((c) => c.id === id);
1353
+ if (category) return category;
1354
+ }
1355
+ return void 0;
1356
+ }
1357
+ _chunk7QVYU63Ejs.__name.call(void 0, resolvePostCategory, "resolvePostCategory");
1358
+
1359
+ // src/features/blog/components/public/BlogCategoryChips.tsx
1360
+
1361
+ function BlogCategoryChips(props) {
1362
+ const { categories, basePath, activeCategorySlug, query, variant = "chips", className } = props;
1363
+ const t = _nextintl.useTranslations.call(void 0, );
1364
+ const items = [
1365
+ {
1366
+ key: "all",
1367
+ label: t("blog.public.all"),
1368
+ href: blogListHref(basePath, { q: query }),
1369
+ active: !activeCategorySlug
1370
+ },
1371
+ ...categories.map((category) => ({
1372
+ key: category.id,
1373
+ label: category.name,
1374
+ href: blogListHref(basePath, { category: category.slug, q: query }),
1375
+ active: category.slug === activeCategorySlug
1376
+ }))
1377
+ ];
1378
+ const inactiveVariant = variant === "chips" ? "outline" : "ghost";
1379
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "nav", { "aria-label": t("blog.entities.categories"), className, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "ul", { className: variant === "chips" ? "flex flex-wrap items-center gap-2" : "flex flex-col items-start gap-2", children: items.map((item) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "li", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1380
+ _chunk3NLAXVINjs.Badge,
1381
+ {
1382
+ variant: item.active ? "default" : inactiveVariant,
1383
+ render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Link, { href: item.href, "aria-current": item.active ? "page" : void 0 }),
1384
+ children: item.label
1385
+ }
1386
+ ) }, item.key)) }) });
1387
+ }
1388
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogCategoryChips, "BlogCategoryChips");
1389
+
1390
+ // src/features/blog/components/public/BlogListParts.tsx
1391
+
1392
+
1393
+ function BlogListHeader(props) {
1394
+ const { align = "start", showSubtitle = true } = props;
1395
+ const t = _nextintl.useTranslations.call(void 0, );
1396
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "header", { className: align === "center" ? "text-center" : void 0, children: [
1397
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1398
+ _chunk3NLAXVINjs.ContentTitle,
1399
+ {
1400
+ type: t("blog.public.eyebrow"),
1401
+ element: t("blog.public.title"),
1402
+ headingLevel: 1,
1403
+ className: _chunkNFBOSPNJjs.cn.call(void 0, "mb-0", align === "center" && "[&_div]:justify-center")
1404
+ }
1405
+ ),
1406
+ showSubtitle ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-muted-foreground mt-3 text-sm leading-relaxed", children: t("blog.public.subtitle") }) : null
1407
+ ] });
1408
+ }
1409
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogListHeader, "BlogListHeader");
1410
+ function BlogListEmpty(props) {
1411
+ const t = _nextintl.useTranslations.call(void 0, );
1412
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: _chunkNFBOSPNJjs.cn.call(void 0, "text-muted-foreground py-12 text-center text-sm", props.className), children: props.query ? t("blog.public.noResults") : t("blog.public.empty") });
1413
+ }
1414
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogListEmpty, "BlogListEmpty");
1415
+ function BlogLoadMore(props) {
1416
+ const { basePath, page, activeCategorySlug, query, className } = props;
1417
+ const t = _nextintl.useTranslations.call(void 0, );
1418
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkNFBOSPNJjs.cn.call(void 0, "flex justify-center", className), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1419
+ _chunk3NLAXVINjs.Link,
1420
+ {
1421
+ href: blogListHref(basePath, { category: activeCategorySlug, q: query, page: page + 1 }),
1422
+ scroll: false,
1423
+ className: _chunk3NLAXVINjs.buttonVariants.call(void 0, { variant: "outline" }),
1424
+ children: t("blog.public.loadMore")
1425
+ }
1426
+ ) });
1427
+ }
1428
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogLoadMore, "BlogLoadMore");
1429
+
1430
+ // src/features/blog/components/public/BlogPostCard.tsx
1431
+
1432
+
1433
+
1434
+ // src/features/blog/components/public/BlogPostMeta.tsx
1435
+
1436
+
1437
+ var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
1438
+ function BlogPostMeta(props) {
1439
+ const { post, showAuthor, showDate, showUpdated, className } = props;
1440
+ const t = _nextintl.useTranslations.call(void 0, );
1441
+ const format = _nextintl.useFormatter.call(void 0, );
1442
+ const parts = [];
1443
+ if (showAuthor && post.authorName) parts.push(t("blog.public.by", { author: post.authorName }));
1444
+ if (showDate && post.publishedAt) {
1445
+ parts.push(format.dateTime(new Date(post.publishedAt), { dateStyle: "medium" }));
1446
+ }
1447
+ if (showUpdated && post.publishedAt && post.updatedAt && new Date(post.updatedAt).getTime() - new Date(post.publishedAt).getTime() > ONE_DAY_MS) {
1448
+ parts.push(t("blog.public.updated", { date: format.dateTime(new Date(post.updatedAt), { dateStyle: "medium" }) }));
1449
+ }
1450
+ parts.push(t("blog.public.readingTime", { minutes: post.readingMinutes }));
1451
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: _chunkNFBOSPNJjs.cn.call(void 0, "text-muted-foreground text-xs", className), children: parts.map((part, index) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { children: [
1452
+ index > 0 ? " \xB7 " : null,
1453
+ part
1454
+ ] }, index)) });
1455
+ }
1456
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostMeta, "BlogPostMeta");
1457
+
1458
+ // src/features/blog/components/public/BlogPostCard.tsx
1459
+
1460
+ function BlogPostCover(props) {
1461
+ const { src, alt, sizes, priority, className } = props;
1462
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkNFBOSPNJjs.cn.call(void 0, "border-border bg-primary/10 relative overflow-hidden rounded-lg border", className), children: src ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1463
+ _image2.default,
1464
+ {
1465
+ src,
1466
+ alt: _nullishCoalesce(alt, () => ( "")),
1467
+ fill: true,
1468
+ sizes,
1469
+ priority,
1470
+ className: "object-cover",
1471
+ unoptimized: _chunkNFBOSPNJjs.isRemoteImageSrc.call(void 0, src)
1472
+ }
1473
+ ) : null });
1474
+ }
1475
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostCover, "BlogPostCover");
1476
+ function BlogPostCard(props) {
1477
+ const { post, categories, basePath, variant = "card", priority, headingLevel = "h2" } = props;
1478
+ const format = _nextintl.useFormatter.call(void 0, );
1479
+ const category = resolvePostCategory(post, categories);
1480
+ const isProminent = variant === "hero" || variant === "large";
1481
+ const eyebrow = variant === "row" && post.publishedAt ? [_optionalChain([category, 'optionalAccess', _46 => _46.name]), format.dateTime(new Date(post.publishedAt), { day: "numeric", month: "short" })].filter(Boolean).join(" \xB7 ") : _optionalChain([category, 'optionalAccess', _47 => _47.name]);
1482
+ const text = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-w-0 flex-col", children: [
1483
+ eyebrow ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.MicroLabel, { as: "span", children: eyebrow }) : null,
1484
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.SectionHeader, { level: headingLevel === "h3" ? 3 : 2, className: "mt-1.5", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.Link, { href: blogPostHref(basePath, post.slug), className: "after:absolute after:inset-0", children: post.title }) }),
1485
+ post.summary ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-muted-foreground mt-2 text-sm leading-relaxed", children: post.summary }) : null,
1486
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostMeta, { post, showAuthor: isProminent, showDate: isProminent, className: "mt-3" })
1487
+ ] });
1488
+ if (variant === "hero") {
1489
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "article", { className: "group relative grid items-center gap-6 md:grid-cols-[1.4fr_1fr] md:gap-10", children: [
1490
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1491
+ BlogPostCover,
1492
+ {
1493
+ src: post.coverImage,
1494
+ alt: post.coverImageAlt,
1495
+ sizes: "(min-width: 1024px) 560px, (min-width: 768px) 58vw, 100vw",
1496
+ priority,
1497
+ className: "aspect-[16/10]"
1498
+ }
1499
+ ),
1500
+ text
1501
+ ] });
1502
+ }
1503
+ if (variant === "row") {
1504
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "article", { className: "group relative grid items-center gap-4 sm:grid-cols-[10rem_1fr] sm:gap-6", children: [
1505
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1506
+ BlogPostCover,
1507
+ {
1508
+ src: post.coverImage,
1509
+ alt: post.coverImageAlt,
1510
+ sizes: "(min-width: 640px) 160px, 100vw",
1511
+ priority,
1512
+ className: "aspect-[16/10]"
1513
+ }
1514
+ ),
1515
+ text
1516
+ ] });
1517
+ }
1518
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "article", { className: "group relative flex flex-col gap-4", children: [
1519
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1520
+ BlogPostCover,
1521
+ {
1522
+ src: post.coverImage,
1523
+ alt: post.coverImageAlt,
1524
+ sizes: variant === "large" ? "(min-width: 1024px) 760px, 100vw" : "(min-width: 1024px) 320px, (min-width: 640px) 50vw, 100vw",
1525
+ priority,
1526
+ className: variant === "large" ? "aspect-[16/8]" : "aspect-[16/10]"
1527
+ }
1528
+ ),
1529
+ text
1530
+ ] });
1531
+ }
1532
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostCard, "BlogPostCard");
1533
+
1534
+ // src/features/blog/components/public/BlogSearchBox.tsx
1535
+
1536
+
1537
+
1538
+
1539
+ function BlogSearchBox(props) {
1540
+ const { basePath, query, activeCategorySlug, className } = props;
1541
+ const t = _nextintl.useTranslations.call(void 0, );
1542
+ const router = _chunkNFBOSPNJjs.useI18nRouter.call(void 0, );
1543
+ const [value, setValue] = _react.useState.call(void 0, _nullishCoalesce(query, () => ( "")));
1544
+ _react.useEffect.call(void 0, () => setValue(_nullishCoalesce(query, () => ( ""))), [query]);
1545
+ const onSubmit = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (event) => {
1546
+ event.preventDefault();
1547
+ const q = value.trim();
1548
+ router.push(blogListHref(basePath, { category: activeCategorySlug, q: q || void 0 }));
1549
+ }, "onSubmit");
1550
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "form", { role: "search", onSubmit, className, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.InputGroup, { children: [
1551
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.InputGroupAddon, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.SearchIcon, {}) }),
1552
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1553
+ _chunk3NLAXVINjs.InputGroupInput,
1554
+ {
1555
+ type: "search",
1556
+ name: "q",
1557
+ value,
1558
+ onChange: (event) => setValue(event.target.value),
1559
+ placeholder: t("blog.public.searchPlaceholder"),
1560
+ "aria-label": t("blog.public.search")
1561
+ }
1562
+ )
1563
+ ] }) });
1564
+ }
1565
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogSearchBox, "BlogSearchBox");
1566
+
1567
+ // src/features/blog/components/public/BlogListColumn.tsx
1568
+
1569
+ function BlogListColumn(props) {
1570
+ const { list, categories, activeCategorySlug, query, page, basePath } = props;
1571
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "section", { className: "px-4 pt-16 pb-20 md:pt-20", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mx-auto max-w-2xl", children: [
1572
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogListHeader, { align: "center" }),
1573
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1574
+ BlogCategoryChips,
1575
+ {
1576
+ categories,
1577
+ basePath,
1578
+ activeCategorySlug,
1579
+ query,
1580
+ className: "mt-8 [&>ul]:justify-center"
1581
+ }
1582
+ ),
1583
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogSearchBox, { basePath, query, activeCategorySlug, className: "mt-4" }),
1584
+ list.posts.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogListEmpty, { query }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "divide-border mt-10 flex flex-col divide-y", children: list.posts.map((post, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "py-6 first:pt-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1585
+ BlogPostCard,
1586
+ {
1587
+ post,
1588
+ categories,
1589
+ basePath,
1590
+ variant: "row",
1591
+ priority: index === 0
1592
+ }
1593
+ ) }, post.id)) }),
1594
+ list.hasMore ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1595
+ BlogLoadMore,
1596
+ {
1597
+ basePath,
1598
+ page,
1599
+ activeCategorySlug,
1600
+ query,
1601
+ className: "mt-10"
1602
+ }
1603
+ ) : null
1604
+ ] }) });
1605
+ }
1606
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogListColumn, "BlogListColumn");
1607
+
1608
+ // src/features/blog/components/public/BlogListFeatured.tsx
1609
+
1610
+ function BlogListFeatured(props) {
1611
+ const { list, categories, activeCategorySlug, query, page, basePath } = props;
1612
+ const [hero, ...rest] = list.posts;
1613
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "section", { className: "px-4 pt-16 pb-20 md:pt-20", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mx-auto max-w-5xl", children: [
1614
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogListHeader, {}),
1615
+ hero ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mt-10", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostCard, { post: hero, categories, basePath, variant: "hero", priority: true }) }) : null,
1616
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-12 flex flex-col gap-3 md:flex-row md:items-center", children: [
1617
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1618
+ BlogCategoryChips,
1619
+ {
1620
+ categories,
1621
+ basePath,
1622
+ activeCategorySlug,
1623
+ query,
1624
+ className: "flex-1"
1625
+ }
1626
+ ),
1627
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1628
+ BlogSearchBox,
1629
+ {
1630
+ basePath,
1631
+ query,
1632
+ activeCategorySlug,
1633
+ className: "md:w-64"
1634
+ }
1635
+ )
1636
+ ] }),
1637
+ list.posts.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogListEmpty, { query }) : null,
1638
+ rest.length > 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mt-8 grid gap-x-6 gap-y-10 sm:grid-cols-2 lg:grid-cols-3", children: rest.map((post) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostCard, { post, categories, basePath }, post.id)) }) : null,
1639
+ list.hasMore ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1640
+ BlogLoadMore,
1641
+ {
1642
+ basePath,
1643
+ page,
1644
+ activeCategorySlug,
1645
+ query,
1646
+ className: "mt-12"
1647
+ }
1648
+ ) : null
1649
+ ] }) });
1650
+ }
1651
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogListFeatured, "BlogListFeatured");
1652
+
1653
+ // src/features/blog/components/public/BlogListRail.tsx
1654
+
1655
+
1656
+ function BlogListRail(props) {
1657
+ const { list, categories, activeCategorySlug, query, page, basePath } = props;
1658
+ const t = _nextintl.useTranslations.call(void 0, );
1659
+ const [first, ...rest] = list.posts;
1660
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "section", { className: "px-4 pt-16 pb-20 md:pt-20", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mx-auto grid max-w-5xl gap-10 md:grid-cols-[13rem_1fr] md:gap-12", children: [
1661
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "aside", { className: "flex flex-col gap-6", children: [
1662
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogListHeader, { showSubtitle: false }),
1663
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogSearchBox, { basePath, query, activeCategorySlug }),
1664
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
1665
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.MicroLabel, { as: "span", className: "block", children: t("blog.entities.categories") }),
1666
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1667
+ BlogCategoryChips,
1668
+ {
1669
+ categories,
1670
+ basePath,
1671
+ activeCategorySlug,
1672
+ query,
1673
+ variant: "list",
1674
+ className: "mt-3"
1675
+ }
1676
+ )
1677
+ ] })
1678
+ ] }),
1679
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "min-w-0", children: [
1680
+ first ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostCard, { post: first, categories, basePath, variant: "large", priority: true }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogListEmpty, { query }),
1681
+ rest.length > 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "border-border mt-10 grid gap-x-6 gap-y-10 border-t pt-10 sm:grid-cols-2", children: rest.map((post) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostCard, { post, categories, basePath }, post.id)) }) : null,
1682
+ list.hasMore ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1683
+ BlogLoadMore,
1684
+ {
1685
+ basePath,
1686
+ page,
1687
+ activeCategorySlug,
1688
+ query,
1689
+ className: "mt-12"
1690
+ }
1691
+ ) : null
1692
+ ] })
1693
+ ] }) });
1694
+ }
1695
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogListRail, "BlogListRail");
1696
+
1697
+ // src/features/blog/components/public/BlogList.tsx
1698
+
1699
+ function BlogList(props) {
1700
+ switch (props.layout) {
1701
+ case "column":
1702
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogListColumn, { ...props });
1703
+ case "rail":
1704
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogListRail, { ...props });
1705
+ case "featured":
1706
+ default:
1707
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogListFeatured, { ...props });
1708
+ }
1709
+ }
1710
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogList, "BlogList");
1711
+
1712
+ // src/features/blog/components/public/BlogPostView.tsx
1713
+
1714
+
1715
+
1716
+ function BlogPostView(props) {
1717
+ const { post, categories, related, basePath } = props;
1718
+ const t = _nextintl.useTranslations.call(void 0, );
1719
+ const category = resolvePostCategory(post, categories);
1720
+ const more = related.slice(0, 3);
1721
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "article", { className: "px-4 pt-12 pb-20 md:pt-16", children: [
1722
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mx-auto max-w-3xl", children: [
1723
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk3NLAXVINjs.Link, { href: basePath, className: "inline-flex items-center gap-1.5", children: [
1724
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ArrowLeftIcon, { className: "size-4 rtl:rotate-180" }),
1725
+ t("blog.public.back")
1726
+ ] }),
1727
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "header", { className: "mt-8", children: [
1728
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.ContentTitle, { type: _optionalChain([category, 'optionalAccess', _48 => _48.name]), element: post.title, headingLevel: 1, className: "mb-0" }),
1729
+ post.summary ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-muted-foreground mt-3 text-sm leading-relaxed", children: post.summary }) : null,
1730
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BlogPostMeta, { post, showAuthor: true, showDate: true, showUpdated: true, className: "mt-4" })
1731
+ ] }),
1732
+ post.coverImage ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1733
+ BlogPostCover,
1734
+ {
1735
+ src: post.coverImage,
1736
+ alt: post.coverImageAlt,
1737
+ sizes: "(min-width: 768px) 768px, 100vw",
1738
+ priority: true,
1739
+ className: "mt-8 aspect-[16/9]"
1740
+ }
1741
+ ) : null,
1742
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mt-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.BlockNoteEditorContainer, { id: post.id, type: "blog-post", initialContent: post.body }) })
1743
+ ] }),
1744
+ more.length > 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "section", { className: "mx-auto mt-16 max-w-5xl", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "border-border border-t pt-10", children: [
1745
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk3NLAXVINjs.SectionHeader, { level: 2, children: t("blog.public.moreIn", { category: _nullishCoalesce(_optionalChain([category, 'optionalAccess', _49 => _49.name]), () => ( "")) }) }),
1746
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mt-6 grid gap-x-6 gap-y-10 sm:grid-cols-2 lg:grid-cols-3", children: more.map((relatedPost) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1747
+ BlogPostCard,
1748
+ {
1749
+ post: relatedPost,
1750
+ categories,
1751
+ basePath,
1752
+ headingLevel: "h3"
1753
+ },
1754
+ relatedPost.id
1755
+ )) })
1756
+ ] }) }) : null
1757
+ ] });
1758
+ }
1759
+ _chunk7QVYU63Ejs.__name.call(void 0, BlogPostView, "BlogPostView");
1760
+
1761
+
1762
+
1763
+
1764
+
1765
+
1766
+
1767
+
1768
+
1769
+
1770
+
1771
+
1772
+
1773
+
1774
+
1775
+
1776
+
1777
+
1778
+
1779
+
1780
+
1781
+
1782
+
1783
+
1784
+
1785
+
1786
+
1787
+
1788
+
1789
+
1790
+
1791
+
1792
+
1793
+
1794
+
1795
+
1796
+
1797
+
1798
+ exports.BLOG_ACTION = _chunkNFBOSPNJjs.BLOG_ACTION; exports.BLOG_CATEGORY_UPLOAD_PREFIX = _chunkNFBOSPNJjs.BLOG_CATEGORY_UPLOAD_PREFIX; exports.BLOG_LIST_LAYOUTS = _chunkNFBOSPNJjs.BLOG_LIST_LAYOUTS; exports.BLOG_MODULE_ID = _chunkNFBOSPNJjs.BLOG_MODULE_ID; exports.BLOG_POST_STATUSES = _chunkNFBOSPNJjs.BLOG_POST_STATUSES; exports.BLOG_POST_UPLOAD_PREFIX = _chunkNFBOSPNJjs.BLOG_POST_UPLOAD_PREFIX; exports.BLOG_PUBLIC_PREFIX = _chunkNFBOSPNJjs.BLOG_PUBLIC_PREFIX; exports.BLOG_SETTINGS_ID = _chunkNFBOSPNJjs.BLOG_SETTINGS_ID; exports.BLOG_STATUS_BADGE = BLOG_STATUS_BADGE; exports.BLOG_TRANSLATION_SOURCES = _chunkNFBOSPNJjs.BLOG_TRANSLATION_SOURCES; exports.BLOG_UPLOAD_ROOT = _chunkNFBOSPNJjs.BLOG_UPLOAD_ROOT; exports.BlogAdminContainer = BlogAdminContainer; exports.BlogCategoriesList = BlogCategoriesList; exports.BlogCategoryEditor = BlogCategoryEditor; exports.BlogCoverImageField = BlogCoverImageField; exports.BlogLayoutSetting = BlogLayoutSetting; exports.BlogList = BlogList; exports.BlogPostComparison = BlogPostComparison; exports.BlogPostContainer = BlogPostContainer; exports.BlogPostDeleter = BlogPostDeleter; exports.BlogPostEditor = BlogPostEditor; exports.BlogPostProvider = BlogPostProvider; exports.BlogPostPublishButton = BlogPostPublishButton; exports.BlogPostTranslationEditor = BlogPostTranslationEditor; exports.BlogPostTranslationFields = BlogPostTranslationFields; exports.BlogPostTranslationPanel = BlogPostTranslationPanel; exports.BlogPostView = BlogPostView; exports.BlogPostsList = BlogPostsList; exports.BlogTranslationStatus = BlogTranslationStatus; exports.blogCategoryAdminName = blogCategoryAdminName; exports.uploadBlogImage = uploadBlogImage; exports.useBlogCategoryNames = useBlogCategoryNames; exports.useBlogCategoryTableStructure = useBlogCategoryTableStructure; exports.useBlogDateFormatter = useBlogDateFormatter; exports.useBlogLanguageName = useBlogLanguageName; exports.useBlogPost = useBlogPost; exports.useBlogPostTableStructure = useBlogPostTableStructure;
1799
+ //# sourceMappingURL=index.js.map