@xiwebdesign/xicms-core 4.17.1

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 (436) hide show
  1. package/dist/XiCMSProvider.d.ts +58 -0
  2. package/dist/XiCMSProvider.js +165 -0
  3. package/dist/XiCMSProvider.js.map +1 -0
  4. package/dist/admin/AdminApp.d.ts +4 -0
  5. package/dist/admin/AdminApp.js +62 -0
  6. package/dist/admin/AdminApp.js.map +1 -0
  7. package/dist/admin/AdminHelp.d.ts +2 -0
  8. package/dist/admin/AdminHelp.js +65 -0
  9. package/dist/admin/AdminHelp.js.map +1 -0
  10. package/dist/admin/NewsEditor.d.ts +2 -0
  11. package/dist/admin/NewsEditor.js +171 -0
  12. package/dist/admin/NewsEditor.js.map +1 -0
  13. package/dist/admin/SuperadminPanel.d.ts +4 -0
  14. package/dist/admin/SuperadminPanel.js +101 -0
  15. package/dist/admin/SuperadminPanel.js.map +1 -0
  16. package/dist/admin/blockEditors/StyleEditor.d.ts +10 -0
  17. package/dist/admin/blockEditors/StyleEditor.js +78 -0
  18. package/dist/admin/blockEditors/StyleEditor.js.map +1 -0
  19. package/dist/admin/blockEditors/index.d.ts +16 -0
  20. package/dist/admin/blockEditors/index.js +1602 -0
  21. package/dist/admin/blockEditors/index.js.map +1 -0
  22. package/dist/admin/editors/RichTextEditor.d.ts +10 -0
  23. package/dist/admin/editors/RichTextEditor.js +86 -0
  24. package/dist/admin/editors/RichTextEditor.js.map +1 -0
  25. package/dist/admin/forms/FormsPanel.d.ts +3 -0
  26. package/dist/admin/forms/FormsPanel.js +203 -0
  27. package/dist/admin/forms/FormsPanel.js.map +1 -0
  28. package/dist/admin/index.d.ts +21 -0
  29. package/dist/admin/index.js +38 -0
  30. package/dist/admin/index.js.map +1 -0
  31. package/dist/admin/lib/compressImage.d.ts +12 -0
  32. package/dist/admin/lib/compressImage.js +53 -0
  33. package/dist/admin/lib/compressImage.js.map +1 -0
  34. package/dist/admin/lib/mediaUsage.d.ts +9 -0
  35. package/dist/admin/lib/mediaUsage.js +25 -0
  36. package/dist/admin/lib/mediaUsage.js.map +1 -0
  37. package/dist/admin/lib/pagesClient.d.ts +38 -0
  38. package/dist/admin/lib/pagesClient.js +143 -0
  39. package/dist/admin/lib/pagesClient.js.map +1 -0
  40. package/dist/admin/lib/slugify.d.ts +2 -0
  41. package/dist/admin/lib/slugify.js +7 -0
  42. package/dist/admin/lib/slugify.js.map +1 -0
  43. package/dist/admin/lib/upload.d.ts +13 -0
  44. package/dist/admin/lib/upload.js +40 -0
  45. package/dist/admin/lib/upload.js.map +1 -0
  46. package/dist/admin/lib/zodFields.d.ts +27 -0
  47. package/dist/admin/lib/zodFields.js +48 -0
  48. package/dist/admin/lib/zodFields.js.map +1 -0
  49. package/dist/admin/media/MediaManager.d.ts +3 -0
  50. package/dist/admin/media/MediaManager.js +132 -0
  51. package/dist/admin/media/MediaManager.js.map +1 -0
  52. package/dist/admin/media/MediaPicker.d.ts +24 -0
  53. package/dist/admin/media/MediaPicker.js +93 -0
  54. package/dist/admin/media/MediaPicker.js.map +1 -0
  55. package/dist/admin/pages/PageEditor.d.ts +5 -0
  56. package/dist/admin/pages/PageEditor.js +239 -0
  57. package/dist/admin/pages/PageEditor.js.map +1 -0
  58. package/dist/admin/pages/PagesPanel.d.ts +3 -0
  59. package/dist/admin/pages/PagesPanel.js +92 -0
  60. package/dist/admin/pages/PagesPanel.js.map +1 -0
  61. package/dist/admin/panelRegistry.d.ts +20 -0
  62. package/dist/admin/panelRegistry.js +23 -0
  63. package/dist/admin/panelRegistry.js.map +1 -0
  64. package/dist/admin/patterns/PatternInserter.d.ts +10 -0
  65. package/dist/admin/patterns/PatternInserter.js +58 -0
  66. package/dist/admin/patterns/PatternInserter.js.map +1 -0
  67. package/dist/admin/settings/SettingsPanel.d.ts +3 -0
  68. package/dist/admin/settings/SettingsPanel.js +304 -0
  69. package/dist/admin/settings/SettingsPanel.js.map +1 -0
  70. package/dist/admin/settings/moduleSettingsForm.d.ts +12 -0
  71. package/dist/admin/settings/moduleSettingsForm.js +45 -0
  72. package/dist/admin/settings/moduleSettingsForm.js.map +1 -0
  73. package/dist/admin/stats/StatsPanel.d.ts +4 -0
  74. package/dist/admin/stats/StatsPanel.js +80 -0
  75. package/dist/admin/stats/StatsPanel.js.map +1 -0
  76. package/dist/admin/ui/ArrayEditor.d.ts +16 -0
  77. package/dist/admin/ui/ArrayEditor.js +38 -0
  78. package/dist/admin/ui/ArrayEditor.js.map +1 -0
  79. package/dist/admin/ui/ConfirmDialog.d.ts +22 -0
  80. package/dist/admin/ui/ConfirmDialog.js +47 -0
  81. package/dist/admin/ui/ConfirmDialog.js.map +1 -0
  82. package/dist/admin/ui/cn.d.ts +3 -0
  83. package/dist/admin/ui/cn.js +9 -0
  84. package/dist/admin/ui/cn.js.map +1 -0
  85. package/dist/admin/ui/dialog.d.ts +9 -0
  86. package/dist/admin/ui/dialog.js +47 -0
  87. package/dist/admin/ui/dialog.js.map +1 -0
  88. package/dist/admin/ui/index.d.ts +7 -0
  89. package/dist/admin/ui/index.js +29 -0
  90. package/dist/admin/ui/index.js.map +1 -0
  91. package/dist/admin/ui/primitives.d.ts +37 -0
  92. package/dist/admin/ui/primitives.js +137 -0
  93. package/dist/admin/ui/primitives.js.map +1 -0
  94. package/dist/admin/ui/select.d.ts +11 -0
  95. package/dist/admin/ui/select.js +27 -0
  96. package/dist/admin/ui/select.js.map +1 -0
  97. package/dist/admin/ui/switch.d.ts +6 -0
  98. package/dist/admin/ui/switch.js +22 -0
  99. package/dist/admin/ui/switch.js.map +1 -0
  100. package/dist/admin/ui/tabs.d.ts +5 -0
  101. package/dist/admin/ui/tabs.js +36 -0
  102. package/dist/admin/ui/tabs.js.map +1 -0
  103. package/dist/admin/ui/toast.d.ts +19 -0
  104. package/dist/admin/ui/toast.js +24 -0
  105. package/dist/admin/ui/toast.js.map +1 -0
  106. package/dist/admin/visual/VisualEditor.d.ts +10 -0
  107. package/dist/admin/visual/VisualEditor.js +597 -0
  108. package/dist/admin/visual/VisualEditor.js.map +1 -0
  109. package/dist/admin/visual/reorder.d.ts +6 -0
  110. package/dist/admin/visual/reorder.js +12 -0
  111. package/dist/admin/visual/reorder.js.map +1 -0
  112. package/dist/admin.css +1 -0
  113. package/dist/auth/AuthProvider.d.ts +30 -0
  114. package/dist/auth/AuthProvider.js +110 -0
  115. package/dist/auth/AuthProvider.js.map +1 -0
  116. package/dist/auth/LoginForm.d.ts +4 -0
  117. package/dist/auth/LoginForm.js +122 -0
  118. package/dist/auth/LoginForm.js.map +1 -0
  119. package/dist/auth/roles.d.ts +15 -0
  120. package/dist/auth/roles.js +21 -0
  121. package/dist/auth/roles.js.map +1 -0
  122. package/dist/blocks/BlockErrorBoundary.d.ts +32 -0
  123. package/dist/blocks/BlockErrorBoundary.js +39 -0
  124. package/dist/blocks/BlockErrorBoundary.js.map +1 -0
  125. package/dist/blocks/BlockRenderer.d.ts +15 -0
  126. package/dist/blocks/BlockRenderer.js +24 -0
  127. package/dist/blocks/BlockRenderer.js.map +1 -0
  128. package/dist/blocks/blockStyle.d.ts +14 -0
  129. package/dist/blocks/blockStyle.js +14 -0
  130. package/dist/blocks/blockStyle.js.map +1 -0
  131. package/dist/blocks/builtins/Accordion.d.ts +2 -0
  132. package/dist/blocks/builtins/Accordion.js +45 -0
  133. package/dist/blocks/builtins/Accordion.js.map +1 -0
  134. package/dist/blocks/builtins/Agenda.d.ts +23 -0
  135. package/dist/blocks/builtins/Agenda.js +102 -0
  136. package/dist/blocks/builtins/Agenda.js.map +1 -0
  137. package/dist/blocks/builtins/Banner.d.ts +2 -0
  138. package/dist/blocks/builtins/Banner.js +45 -0
  139. package/dist/blocks/builtins/Banner.js.map +1 -0
  140. package/dist/blocks/builtins/BeforeAfter.d.ts +2 -0
  141. package/dist/blocks/builtins/BeforeAfter.js +44 -0
  142. package/dist/blocks/builtins/BeforeAfter.js.map +1 -0
  143. package/dist/blocks/builtins/Booking.d.ts +2 -0
  144. package/dist/blocks/builtins/Booking.js +27 -0
  145. package/dist/blocks/builtins/Booking.js.map +1 -0
  146. package/dist/blocks/builtins/Breadcrumbs.d.ts +10 -0
  147. package/dist/blocks/builtins/Breadcrumbs.js +73 -0
  148. package/dist/blocks/builtins/Breadcrumbs.js.map +1 -0
  149. package/dist/blocks/builtins/Cards.d.ts +2 -0
  150. package/dist/blocks/builtins/Cards.js +94 -0
  151. package/dist/blocks/builtins/Cards.js.map +1 -0
  152. package/dist/blocks/builtins/Columns.d.ts +2 -0
  153. package/dist/blocks/builtins/Columns.js +22 -0
  154. package/dist/blocks/builtins/Columns.js.map +1 -0
  155. package/dist/blocks/builtins/Contact.d.ts +7 -0
  156. package/dist/blocks/builtins/Contact.js +121 -0
  157. package/dist/blocks/builtins/Contact.js.map +1 -0
  158. package/dist/blocks/builtins/Countdown.d.ts +18 -0
  159. package/dist/blocks/builtins/Countdown.js +65 -0
  160. package/dist/blocks/builtins/Countdown.js.map +1 -0
  161. package/dist/blocks/builtins/Cta.d.ts +2 -0
  162. package/dist/blocks/builtins/Cta.js +52 -0
  163. package/dist/blocks/builtins/Cta.js.map +1 -0
  164. package/dist/blocks/builtins/Downloads.d.ts +2 -0
  165. package/dist/blocks/builtins/Downloads.js +32 -0
  166. package/dist/blocks/builtins/Downloads.js.map +1 -0
  167. package/dist/blocks/builtins/Elements.d.ts +4 -0
  168. package/dist/blocks/builtins/Elements.js +64 -0
  169. package/dist/blocks/builtins/Elements.js.map +1 -0
  170. package/dist/blocks/builtins/Embed.d.ts +2 -0
  171. package/dist/blocks/builtins/Embed.js +30 -0
  172. package/dist/blocks/builtins/Embed.js.map +1 -0
  173. package/dist/blocks/builtins/Faq.d.ts +6 -0
  174. package/dist/blocks/builtins/Faq.js +110 -0
  175. package/dist/blocks/builtins/Faq.js.map +1 -0
  176. package/dist/blocks/builtins/FormBlock.d.ts +2 -0
  177. package/dist/blocks/builtins/FormBlock.js +221 -0
  178. package/dist/blocks/builtins/FormBlock.js.map +1 -0
  179. package/dist/blocks/builtins/Gallery.d.ts +23 -0
  180. package/dist/blocks/builtins/Gallery.js +177 -0
  181. package/dist/blocks/builtins/Gallery.js.map +1 -0
  182. package/dist/blocks/builtins/Hero.d.ts +2 -0
  183. package/dist/blocks/builtins/Hero.js +47 -0
  184. package/dist/blocks/builtins/Hero.js.map +1 -0
  185. package/dist/blocks/builtins/ImageBlock.d.ts +2 -0
  186. package/dist/blocks/builtins/ImageBlock.js +24 -0
  187. package/dist/blocks/builtins/ImageBlock.js.map +1 -0
  188. package/dist/blocks/builtins/Jobs.d.ts +8 -0
  189. package/dist/blocks/builtins/Jobs.js +65 -0
  190. package/dist/blocks/builtins/Jobs.js.map +1 -0
  191. package/dist/blocks/builtins/Layout.d.ts +3 -0
  192. package/dist/blocks/builtins/Layout.js +67 -0
  193. package/dist/blocks/builtins/Layout.js.map +1 -0
  194. package/dist/blocks/builtins/MapBlock.d.ts +2 -0
  195. package/dist/blocks/builtins/MapBlock.js +31 -0
  196. package/dist/blocks/builtins/MapBlock.js.map +1 -0
  197. package/dist/blocks/builtins/NewsListBlock.d.ts +2 -0
  198. package/dist/blocks/builtins/NewsListBlock.js +24 -0
  199. package/dist/blocks/builtins/NewsListBlock.js.map +1 -0
  200. package/dist/blocks/builtins/Newsletter.d.ts +2 -0
  201. package/dist/blocks/builtins/Newsletter.js +84 -0
  202. package/dist/blocks/builtins/Newsletter.js.map +1 -0
  203. package/dist/blocks/builtins/OpenNowBadge.d.ts +9 -0
  204. package/dist/blocks/builtins/OpenNowBadge.js +20 -0
  205. package/dist/blocks/builtins/OpenNowBadge.js.map +1 -0
  206. package/dist/blocks/builtins/OpeningHours.d.ts +2 -0
  207. package/dist/blocks/builtins/OpeningHours.js +47 -0
  208. package/dist/blocks/builtins/OpeningHours.js.map +1 -0
  209. package/dist/blocks/builtins/PdfBlock.d.ts +2 -0
  210. package/dist/blocks/builtins/PdfBlock.js +97 -0
  211. package/dist/blocks/builtins/PdfBlock.js.map +1 -0
  212. package/dist/blocks/builtins/Portfolio.d.ts +2 -0
  213. package/dist/blocks/builtins/Portfolio.js +94 -0
  214. package/dist/blocks/builtins/Portfolio.js.map +1 -0
  215. package/dist/blocks/builtins/Pricing.d.ts +6 -0
  216. package/dist/blocks/builtins/Pricing.js +77 -0
  217. package/dist/blocks/builtins/Pricing.js.map +1 -0
  218. package/dist/blocks/builtins/RichTextBlock.d.ts +2 -0
  219. package/dist/blocks/builtins/RichTextBlock.js +18 -0
  220. package/dist/blocks/builtins/RichTextBlock.js.map +1 -0
  221. package/dist/blocks/builtins/Search.d.ts +2 -0
  222. package/dist/blocks/builtins/Search.js +99 -0
  223. package/dist/blocks/builtins/Search.js.map +1 -0
  224. package/dist/blocks/builtins/Sections.d.ts +5 -0
  225. package/dist/blocks/builtins/Sections.js +183 -0
  226. package/dist/blocks/builtins/Sections.js.map +1 -0
  227. package/dist/blocks/builtins/Slider.d.ts +2 -0
  228. package/dist/blocks/builtins/Slider.js +131 -0
  229. package/dist/blocks/builtins/Slider.js.map +1 -0
  230. package/dist/blocks/builtins/Spacer.d.ts +2 -0
  231. package/dist/blocks/builtins/Spacer.js +19 -0
  232. package/dist/blocks/builtins/Spacer.js.map +1 -0
  233. package/dist/blocks/builtins/Team.d.ts +2 -0
  234. package/dist/blocks/builtins/Team.js +70 -0
  235. package/dist/blocks/builtins/Team.js.map +1 -0
  236. package/dist/blocks/builtins/Testimonials.d.ts +8 -0
  237. package/dist/blocks/builtins/Testimonials.js +82 -0
  238. package/dist/blocks/builtins/Testimonials.js.map +1 -0
  239. package/dist/blocks/builtins/Video.d.ts +9 -0
  240. package/dist/blocks/builtins/Video.js +77 -0
  241. package/dist/blocks/builtins/Video.js.map +1 -0
  242. package/dist/blocks/builtins/WhatsappChat.d.ts +8 -0
  243. package/dist/blocks/builtins/WhatsappChat.js +51 -0
  244. package/dist/blocks/builtins/WhatsappChat.js.map +1 -0
  245. package/dist/blocks/builtins/Widgets.d.ts +13 -0
  246. package/dist/blocks/builtins/Widgets.js +308 -0
  247. package/dist/blocks/builtins/Widgets.js.map +1 -0
  248. package/dist/blocks/builtins/consentEmbed.d.ts +17 -0
  249. package/dist/blocks/builtins/consentEmbed.js +31 -0
  250. package/dist/blocks/builtins/consentEmbed.js.map +1 -0
  251. package/dist/blocks/builtins/index.d.ts +46 -0
  252. package/dist/blocks/builtins/index.js +121 -0
  253. package/dist/blocks/builtins/index.js.map +1 -0
  254. package/dist/blocks/builtins/lib/bookingUrl.d.ts +8 -0
  255. package/dist/blocks/builtins/lib/bookingUrl.js +50 -0
  256. package/dist/blocks/builtins/lib/bookingUrl.js.map +1 -0
  257. package/dist/blocks/builtins/lib/fileIcon.d.ts +2 -0
  258. package/dist/blocks/builtins/lib/fileIcon.js +45 -0
  259. package/dist/blocks/builtins/lib/fileIcon.js.map +1 -0
  260. package/dist/blocks/builtins/lib/ics.d.ts +17 -0
  261. package/dist/blocks/builtins/lib/ics.js +50 -0
  262. package/dist/blocks/builtins/lib/ics.js.map +1 -0
  263. package/dist/blocks/builtins/lib/openingHours.d.ts +20 -0
  264. package/dist/blocks/builtins/lib/openingHours.js +79 -0
  265. package/dist/blocks/builtins/lib/openingHours.js.map +1 -0
  266. package/dist/blocks/builtins/lib/searchRank.d.ts +22 -0
  267. package/dist/blocks/builtins/lib/searchRank.js +45 -0
  268. package/dist/blocks/builtins/lib/searchRank.js.map +1 -0
  269. package/dist/blocks/builtins/lib/submitForm.d.ts +6 -0
  270. package/dist/blocks/builtins/lib/submitForm.js +14 -0
  271. package/dist/blocks/builtins/lib/submitForm.js.map +1 -0
  272. package/dist/blocks/context.d.ts +8 -0
  273. package/dist/blocks/context.js +20 -0
  274. package/dist/blocks/context.js.map +1 -0
  275. package/dist/blocks/index.d.ts +9 -0
  276. package/dist/blocks/index.js +21 -0
  277. package/dist/blocks/index.js.map +1 -0
  278. package/dist/blocks/registry.d.ts +75 -0
  279. package/dist/blocks/registry.js +71 -0
  280. package/dist/blocks/registry.js.map +1 -0
  281. package/dist/blocks/ui/index.d.ts +35 -0
  282. package/dist/blocks/ui/index.js +48 -0
  283. package/dist/blocks/ui/index.js.map +1 -0
  284. package/dist/components/EditBar.d.ts +2 -0
  285. package/dist/components/EditBar.js +20 -0
  286. package/dist/components/EditBar.js.map +1 -0
  287. package/dist/components/EditableImage.d.ts +18 -0
  288. package/dist/components/EditableImage.js +62 -0
  289. package/dist/components/EditableImage.js.map +1 -0
  290. package/dist/components/EditableRichText.d.ts +14 -0
  291. package/dist/components/EditableRichText.js +26 -0
  292. package/dist/components/EditableRichText.js.map +1 -0
  293. package/dist/components/EditableText.d.ts +21 -0
  294. package/dist/components/EditableText.js +25 -0
  295. package/dist/components/EditableText.js.map +1 -0
  296. package/dist/components/News.d.ts +38 -0
  297. package/dist/components/News.js +128 -0
  298. package/dist/components/News.js.map +1 -0
  299. package/dist/components/PageView.d.ts +8 -0
  300. package/dist/components/PageView.js +28 -0
  301. package/dist/components/PageView.js.map +1 -0
  302. package/dist/components/ResponsiveImage.d.ts +16 -0
  303. package/dist/components/ResponsiveImage.js +39 -0
  304. package/dist/components/ResponsiveImage.js.map +1 -0
  305. package/dist/components/site/SiteFooter.d.ts +12 -0
  306. package/dist/components/site/SiteFooter.js +34 -0
  307. package/dist/components/site/SiteFooter.js.map +1 -0
  308. package/dist/config.d.ts +8 -0
  309. package/dist/config.js +17 -0
  310. package/dist/config.js.map +1 -0
  311. package/dist/content/ContentProvider.d.ts +23 -0
  312. package/dist/content/ContentProvider.js +86 -0
  313. package/dist/content/ContentProvider.js.map +1 -0
  314. package/dist/content/types.d.ts +41 -0
  315. package/dist/content/types.js +1 -0
  316. package/dist/content/types.js.map +1 -0
  317. package/dist/demo/DemoStudio.d.ts +7 -0
  318. package/dist/demo/DemoStudio.js +54 -0
  319. package/dist/demo/DemoStudio.js.map +1 -0
  320. package/dist/demo/demoStore.d.ts +26 -0
  321. package/dist/demo/demoStore.js +115 -0
  322. package/dist/demo/demoStore.js.map +1 -0
  323. package/dist/editor/EditorProvider.d.ts +12 -0
  324. package/dist/editor/EditorProvider.js +22 -0
  325. package/dist/editor/EditorProvider.js.map +1 -0
  326. package/dist/firebase/admin.d.ts +7 -0
  327. package/dist/firebase/admin.js +31 -0
  328. package/dist/firebase/admin.js.map +1 -0
  329. package/dist/firebase/appcheck.d.ts +6 -0
  330. package/dist/firebase/appcheck.js +23 -0
  331. package/dist/firebase/appcheck.js.map +1 -0
  332. package/dist/firebase/client.d.ts +9 -0
  333. package/dist/firebase/client.js +44 -0
  334. package/dist/firebase/client.js.map +1 -0
  335. package/dist/firebase/region.d.ts +5 -0
  336. package/dist/firebase/region.js +7 -0
  337. package/dist/firebase/region.js.map +1 -0
  338. package/dist/index.d.ts +54 -0
  339. package/dist/index.js +172 -0
  340. package/dist/index.js.map +1 -0
  341. package/dist/layers.css +13 -0
  342. package/dist/lock/DemoLock.d.ts +5 -0
  343. package/dist/lock/DemoLock.js +35 -0
  344. package/dist/lock/DemoLock.js.map +1 -0
  345. package/dist/media/ImageContext.d.ts +41 -0
  346. package/dist/media/ImageContext.js +74 -0
  347. package/dist/media/ImageContext.js.map +1 -0
  348. package/dist/modules/builtins.d.ts +46 -0
  349. package/dist/modules/builtins.js +462 -0
  350. package/dist/modules/builtins.js.map +1 -0
  351. package/dist/modules/consent/ConsentBanner.d.ts +42 -0
  352. package/dist/modules/consent/ConsentBanner.js +119 -0
  353. package/dist/modules/consent/ConsentBanner.js.map +1 -0
  354. package/dist/modules/consent/useConsent.d.ts +28 -0
  355. package/dist/modules/consent/useConsent.js +52 -0
  356. package/dist/modules/consent/useConsent.js.map +1 -0
  357. package/dist/modules/context.d.ts +20 -0
  358. package/dist/modules/context.js +31 -0
  359. package/dist/modules/context.js.map +1 -0
  360. package/dist/modules/contract.d.ts +9 -0
  361. package/dist/modules/contract.js +38 -0
  362. package/dist/modules/contract.js.map +1 -0
  363. package/dist/modules/defineModule.d.ts +11 -0
  364. package/dist/modules/defineModule.js +7 -0
  365. package/dist/modules/defineModule.js.map +1 -0
  366. package/dist/modules/index.d.ts +13 -0
  367. package/dist/modules/index.js +44 -0
  368. package/dist/modules/index.js.map +1 -0
  369. package/dist/modules/overrides.d.ts +17 -0
  370. package/dist/modules/overrides.js +25 -0
  371. package/dist/modules/overrides.js.map +1 -0
  372. package/dist/modules/registry.d.ts +40 -0
  373. package/dist/modules/registry.js +79 -0
  374. package/dist/modules/registry.js.map +1 -0
  375. package/dist/modules/types.d.ts +66 -0
  376. package/dist/modules/types.js +1 -0
  377. package/dist/modules/types.js.map +1 -0
  378. package/dist/patterns/builtins.d.ts +31 -0
  379. package/dist/patterns/builtins.js +415 -0
  380. package/dist/patterns/builtins.js.map +1 -0
  381. package/dist/patterns/index.d.ts +6 -0
  382. package/dist/patterns/index.js +9 -0
  383. package/dist/patterns/index.js.map +1 -0
  384. package/dist/patterns/patterns.d.ts +28 -0
  385. package/dist/patterns/patterns.js +53 -0
  386. package/dist/patterns/patterns.js.map +1 -0
  387. package/dist/render/PageRenderer.d.ts +13 -0
  388. package/dist/render/PageRenderer.js +14 -0
  389. package/dist/render/PageRenderer.js.map +1 -0
  390. package/dist/render/PublishedPage.d.ts +13 -0
  391. package/dist/render/PublishedPage.js +16 -0
  392. package/dist/render/PublishedPage.js.map +1 -0
  393. package/dist/schema/blocks.d.ts +15052 -0
  394. package/dist/schema/blocks.js +794 -0
  395. package/dist/schema/blocks.js.map +1 -0
  396. package/dist/schema/forms.d.ts +111 -0
  397. package/dist/schema/forms.js +47 -0
  398. package/dist/schema/forms.js.map +1 -0
  399. package/dist/schema/index.d.ts +11 -0
  400. package/dist/schema/index.js +16 -0
  401. package/dist/schema/index.js.map +1 -0
  402. package/dist/schema/pages.d.ts +674 -0
  403. package/dist/schema/pages.js +37 -0
  404. package/dist/schema/pages.js.map +1 -0
  405. package/dist/schema/seo.d.ts +29 -0
  406. package/dist/schema/seo.js +17 -0
  407. package/dist/schema/seo.js.map +1 -0
  408. package/dist/schema/settings.d.ts +1126 -0
  409. package/dist/schema/settings.js +128 -0
  410. package/dist/schema/settings.js.map +1 -0
  411. package/dist/schema/siteConfig.d.ts +722 -0
  412. package/dist/schema/siteConfig.js +39 -0
  413. package/dist/schema/siteConfig.js.map +1 -0
  414. package/dist/server/env.d.ts +10 -0
  415. package/dist/server/env.js +36 -0
  416. package/dist/server/env.js.map +1 -0
  417. package/dist/server/index.d.ts +10 -0
  418. package/dist/server/index.js +51 -0
  419. package/dist/server/index.js.map +1 -0
  420. package/dist/server/pages.d.ts +15 -0
  421. package/dist/server/pages.js +99 -0
  422. package/dist/server/pages.js.map +1 -0
  423. package/dist/server/sanitize.d.ts +2 -0
  424. package/dist/server/sanitize.js +55 -0
  425. package/dist/server/sanitize.js.map +1 -0
  426. package/dist/server/seo.d.ts +116 -0
  427. package/dist/server/seo.js +179 -0
  428. package/dist/server/seo.js.map +1 -0
  429. package/dist/settings/useSiteSettings.d.ts +25 -0
  430. package/dist/settings/useSiteSettings.js +68 -0
  431. package/dist/settings/useSiteSettings.js.map +1 -0
  432. package/dist/styles.css +2495 -0
  433. package/dist/theme/presets.d.ts +12 -0
  434. package/dist/theme/presets.js +147 -0
  435. package/dist/theme/presets.js.map +1 -0
  436. package/package.json +112 -0
@@ -0,0 +1,128 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { collection, getDocs, limit as fbLimit, onSnapshot, orderBy, query, where } from "firebase/firestore";
5
+ import { getDb } from "../firebase/client";
6
+ import { useSiteConfig } from "../config";
7
+ import DOMPurify from "dompurify";
8
+ import { useAuth } from "../auth/AuthProvider";
9
+ import { canEdit } from "../auth/roles";
10
+ import { isDemoActive, getDemoNews } from "../demo/demoStore";
11
+ import { Img } from "../media/ImageContext";
12
+ function useNews(opts = {}) {
13
+ const { siteId } = useSiteConfig();
14
+ const { role } = useAuth();
15
+ const editor = canEdit(role);
16
+ const [articles, setArticles] = useState([]);
17
+ const [loading, setLoading] = useState(true);
18
+ const onlyPublished = opts.onlyPublished ?? !editor;
19
+ const live = opts.live ?? editor;
20
+ const cap = Math.min(opts.max ?? 50, 50);
21
+ useEffect(() => {
22
+ if (isDemoActive()) {
23
+ const all = getDemoNews(siteId);
24
+ setArticles((onlyPublished ? all.filter((a) => a.published) : all).slice(0, cap));
25
+ setLoading(false);
26
+ return;
27
+ }
28
+ const db = getDb();
29
+ if (!db) {
30
+ setLoading(false);
31
+ return;
32
+ }
33
+ const base = collection(db, "sites", siteId, "news");
34
+ const q = onlyPublished ? query(base, where("published", "==", true), orderBy("date", "desc"), fbLimit(cap)) : query(base, orderBy("date", "desc"), fbLimit(cap));
35
+ const map = (snap) => setArticles(snap.docs.map((d) => ({ id: d.id, ...d.data() })));
36
+ if (!live) {
37
+ let active = true;
38
+ getDocs(q).then((snap) => {
39
+ if (active) {
40
+ map(snap);
41
+ setLoading(false);
42
+ }
43
+ }).catch(() => active && setLoading(false));
44
+ return () => {
45
+ active = false;
46
+ };
47
+ }
48
+ const unsub = onSnapshot(
49
+ q,
50
+ (snap) => {
51
+ map(snap);
52
+ setLoading(false);
53
+ },
54
+ () => setLoading(false)
55
+ );
56
+ return () => unsub();
57
+ }, [siteId, onlyPublished, live, cap]);
58
+ return { articles, loading };
59
+ }
60
+ function NewsList({ basePath = "/nieuws", className, emptyLabel = "Nog geen nieuws.", limit, pageSize }) {
61
+ const { articles, loading } = useNews({ max: limit });
62
+ const paged = typeof pageSize === "number" && pageSize > 0;
63
+ const [visible, setVisible] = useState(paged ? pageSize : Infinity);
64
+ if (loading) return /* @__PURE__ */ jsx("p", { children: "Nieuws laden\u2026" });
65
+ if (articles.length === 0) return /* @__PURE__ */ jsx("p", { children: emptyLabel });
66
+ const all = typeof limit === "number" ? articles.slice(0, limit) : articles;
67
+ const shown = paged ? all.slice(0, visible) : all;
68
+ return /* @__PURE__ */ jsxs("div", { className, style: { display: "grid", gap: "1rem" }, children: [
69
+ shown.map((a, i) => /* @__PURE__ */ jsxs("article", { className: "xicms-card", style: { padding: "1.25rem" }, children: [
70
+ a.coverUrl && // Eerste cover boven de vouw = vaak de LCP → priority (geen lazy-load-vertraging).
71
+ /* @__PURE__ */ jsx(Img, { src: a.coverUrl, alt: "", width: 1200, height: 700, sizes: "(max-width: 720px) 100vw, 33vw", priority: i === 0, style: { width: "100%", height: "auto", borderRadius: 8, marginBottom: "0.75rem" } }),
72
+ /* @__PURE__ */ jsx("p", { style: { fontSize: 12, opacity: 0.7, margin: 0 }, children: a.date }),
73
+ /* @__PURE__ */ jsxs("h2", { style: { margin: "0.25rem 0", fontSize: "1.35rem" }, children: [
74
+ /* @__PURE__ */ jsx("a", { href: `${basePath}/${a.slug ?? a.id}`, children: a.title }),
75
+ !a.published && /* @__PURE__ */ jsx("span", { style: { marginLeft: 8, fontSize: 12, color: "#b45309" }, children: "(concept)" })
76
+ ] }),
77
+ a.excerpt && /* @__PURE__ */ jsx("p", { style: { margin: 0, opacity: 0.85 }, children: a.excerpt })
78
+ ] }, a.id)),
79
+ paged && shown.length < all.length && /* @__PURE__ */ jsx("div", { style: { textAlign: "center" }, children: /* @__PURE__ */ jsxs("button", { type: "button", className: "xicms-btn", onClick: () => setVisible((v) => v + pageSize), children: [
80
+ "Meer laden (",
81
+ all.length - shown.length,
82
+ ")"
83
+ ] }) })
84
+ ] });
85
+ }
86
+ function articleBlogPostingJsonLd(article, opts = {}) {
87
+ return {
88
+ "@context": "https://schema.org",
89
+ "@type": "BlogPosting",
90
+ headline: article.title,
91
+ datePublished: article.date,
92
+ ...article.excerpt ? { description: article.excerpt } : {},
93
+ ...article.coverUrl ? { image: article.coverUrl } : {},
94
+ ...opts.url ? { url: opts.url, mainEntityOfPage: opts.url } : {},
95
+ ...opts.siteName ? { publisher: { "@type": "Organization", name: opts.siteName } } : {}
96
+ };
97
+ }
98
+ function NewsArticleView({ article, jsonLd = true }) {
99
+ const { name } = useSiteConfig();
100
+ const [html, setHtml] = useState(null);
101
+ useEffect(() => {
102
+ setHtml(article.bodyHtml ? DOMPurify.sanitize(article.bodyHtml) : null);
103
+ }, [article.bodyHtml]);
104
+ const fallbackText = article.body ?? (article.bodyHtml ? article.bodyHtml.replace(/<[^>]*>/g, " ") : "");
105
+ return /* @__PURE__ */ jsxs("article", { children: [
106
+ /* @__PURE__ */ jsx("p", { style: { fontSize: 12, opacity: 0.6 }, children: article.date }),
107
+ /* @__PURE__ */ jsx("h1", { children: article.title }),
108
+ article.coverUrl && /* @__PURE__ */ jsx(Img, { src: article.coverUrl, alt: "", width: 1200, height: 700, sizes: "(max-width: 900px) 100vw, 800px", priority: true, style: { width: "100%", height: "auto", borderRadius: 12, margin: "1rem 0" } }),
109
+ html ? (
110
+ // eslint-disable-next-line react/no-danger
111
+ /* @__PURE__ */ jsx("div", { className: "xicms-richtext", dangerouslySetInnerHTML: { __html: html } })
112
+ ) : fallbackText.split(/\n{2,}/).map((p, i) => /* @__PURE__ */ jsx("p", { style: { whiteSpace: "pre-wrap" }, children: p }, i)),
113
+ jsonLd && /* @__PURE__ */ jsx(
114
+ "script",
115
+ {
116
+ type: "application/ld+json",
117
+ dangerouslySetInnerHTML: { __html: JSON.stringify(articleBlogPostingJsonLd(article, { siteName: name })) }
118
+ }
119
+ )
120
+ ] });
121
+ }
122
+ export {
123
+ NewsArticleView,
124
+ NewsList,
125
+ articleBlogPostingJsonLd,
126
+ useNews
127
+ };
128
+ //# sourceMappingURL=News.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/News.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { collection, getDocs, limit as fbLimit, onSnapshot, orderBy, query, where } from \"firebase/firestore\";\nimport { getDb } from \"../firebase/client\";\nimport { useSiteConfig } from \"../config\";\nimport DOMPurify from \"dompurify\";\nimport { useAuth } from \"../auth/AuthProvider\";\nimport { canEdit } from \"../auth/roles\";\nimport { isDemoActive, getDemoNews } from \"../demo/demoStore\";\nimport { Img } from \"../media/ImageContext\";\nimport type { NewsArticle } from \"../content/types\";\n\n/**\n * Lijst van nieuwsartikelen voor de huidige site.\n * - `live: false` (standaard publiek): één keer ophalen met getDocs → geen per-bezoeker listener\n * (scheelt Firestore-kosten op druk bezochte sites).\n * - `live: true` (admin): realtime via onSnapshot, zodat wijzigingen meteen zichtbaar zijn.\n */\nexport function useNews(opts: { onlyPublished?: boolean; live?: boolean; max?: number } = {}): {\n articles: NewsArticle[];\n loading: boolean;\n} {\n const { siteId } = useSiteConfig();\n // Via useAuth (niet via het deprecated ContentProvider-pad — News hoort niet aan legacy te hangen).\n const { role } = useAuth();\n const editor = canEdit(role);\n const [articles, setArticles] = useState<NewsArticle[]>([]);\n const [loading, setLoading] = useState(true);\n const onlyPublished = opts.onlyPublished ?? !editor;\n const live = opts.live ?? editor; // editors zien live; publiek één keer\n // Begrens de query: zonder cap zou een nieuws-rijke site ALLE artikelen downloaden bij elk bezoek.\n const cap = Math.min(opts.max ?? 50, 50);\n\n useEffect(() => {\n // Demo-modus: nieuws komt uit de lokale seed (geen Firebase), zodat nieuws-blokken/widgets\n // in de demo ook gevuld zijn.\n if (isDemoActive()) {\n const all = getDemoNews(siteId);\n setArticles((onlyPublished ? all.filter((a) => a.published) : all).slice(0, cap));\n setLoading(false);\n return;\n }\n const db = getDb();\n if (!db) {\n setLoading(false);\n return;\n }\n const base = collection(db, \"sites\", siteId, \"news\");\n const q = onlyPublished\n ? query(base, where(\"published\", \"==\", true), orderBy(\"date\", \"desc\"), fbLimit(cap))\n : query(base, orderBy(\"date\", \"desc\"), fbLimit(cap));\n const map = (snap: { docs: { id: string; data: () => unknown }[] }) =>\n setArticles(snap.docs.map((d) => ({ id: d.id, ...(d.data() as Omit<NewsArticle, \"id\">) })));\n\n if (!live) {\n let active = true;\n getDocs(q)\n .then((snap) => {\n if (active) {\n map(snap);\n setLoading(false);\n }\n })\n .catch(() => active && setLoading(false));\n return () => {\n active = false;\n };\n }\n\n const unsub = onSnapshot(\n q,\n (snap) => {\n map(snap);\n setLoading(false);\n },\n () => setLoading(false),\n );\n return () => unsub();\n }, [siteId, onlyPublished, live, cap]);\n\n return { articles, loading };\n}\n\ninterface NewsListProps {\n /** Basispad voor links naar een artikel, bv. \"/nieuws\". */\n basePath?: string;\n className?: string;\n emptyLabel?: string;\n /** Maximaal aantal artikelen om te tonen. */\n limit?: number;\n /** Toon eerst dit aantal en laad de rest met een \"Meer laden\"-knop (0/leeg = alles ineens). */\n pageSize?: number;\n}\n\n/** Standaardweergave van nieuwsartikelen als kaartenlijst, optioneel gepagineerd. */\nexport function NewsList({ basePath = \"/nieuws\", className, emptyLabel = \"Nog geen nieuws.\", limit, pageSize }: NewsListProps) {\n const { articles, loading } = useNews({ max: limit });\n const paged = typeof pageSize === \"number\" && pageSize > 0;\n const [visible, setVisible] = useState(paged ? pageSize : Infinity);\n\n if (loading) return <p>Nieuws laden…</p>;\n if (articles.length === 0) return <p>{emptyLabel}</p>;\n\n const all = typeof limit === \"number\" ? articles.slice(0, limit) : articles;\n const shown = paged ? all.slice(0, visible) : all;\n\n return (\n <div className={className} style={{ display: \"grid\", gap: \"1rem\" }}>\n {shown.map((a, i) => (\n <article key={a.id} className=\"xicms-card\" style={{ padding: \"1.25rem\" }}>\n {a.coverUrl && (\n // Eerste cover boven de vouw = vaak de LCP → priority (geen lazy-load-vertraging).\n <Img src={a.coverUrl} alt=\"\" width={1200} height={700} sizes=\"(max-width: 720px) 100vw, 33vw\" priority={i === 0} style={{ width: \"100%\", height: \"auto\", borderRadius: 8, marginBottom: \"0.75rem\" }} />\n )}\n <p style={{ fontSize: 12, opacity: 0.7, margin: 0 }}>{a.date}</p>\n {/* h2: de lijst staat direct onder de pagina-h1 — h3 zou een kopniveau overslaan. */}\n <h2 style={{ margin: \"0.25rem 0\", fontSize: \"1.35rem\" }}>\n <a href={`${basePath}/${a.slug ?? a.id}`}>{a.title}</a>\n {!a.published && <span style={{ marginLeft: 8, fontSize: 12, color: \"#b45309\" }}>(concept)</span>}\n </h2>\n {a.excerpt && <p style={{ margin: 0, opacity: 0.85 }}>{a.excerpt}</p>}\n </article>\n ))}\n {paged && shown.length < all.length && (\n <div style={{ textAlign: \"center\" }}>\n <button type=\"button\" className=\"xicms-btn\" onClick={() => setVisible((v) => v + (pageSize as number))}>\n Meer laden ({all.length - shown.length})\n </button>\n </div>\n )}\n </div>\n );\n}\n\n/** BlogPosting-JSON-LD voor een artikel — puur, zodat het testbaar is. */\nexport function articleBlogPostingJsonLd(article: NewsArticle, opts: { siteName?: string; url?: string } = {}): Record<string, unknown> {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BlogPosting\",\n headline: article.title,\n datePublished: article.date,\n ...(article.excerpt ? { description: article.excerpt } : {}),\n ...(article.coverUrl ? { image: article.coverUrl } : {}),\n ...(opts.url ? { url: opts.url, mainEntityOfPage: opts.url } : {}),\n ...(opts.siteName ? { publisher: { \"@type\": \"Organization\", name: opts.siteName } } : {}),\n };\n}\n\n/** Detailweergave van één artikel, met BlogPosting-JSON-LD voor zoekmachines. */\nexport function NewsArticleView({ article, jsonLd = true }: { article: NewsArticle; jsonLd?: boolean }) {\n const { name } = useSiteConfig();\n // Rich-text wordt bij het RENDEREN gesanitized (DOMPurify) — de render is de veiligheidsgrens,\n // ook als er ooit ongesaneerde HTML in Firestore zou belanden. DOMPurify heeft echter een echte\n // DOM nodig: op de server (SSR/prerender) is sanitize geen functie. Daarom rendert de eerste\n // render (server én client-hydration, identiek) de platte-tekst-fallback en wisselt het effect\n // — client-only — naar de gesanitizede rich-text.\n const [html, setHtml] = useState<string | null>(null);\n useEffect(() => {\n setHtml(article.bodyHtml ? DOMPurify.sanitize(article.bodyHtml) : null);\n }, [article.bodyHtml]);\n // Fallback tot de sanitizer klaar is: kale tekst (tags gestript, gerenderd als tekstnodes — veilig).\n const fallbackText = article.body ?? (article.bodyHtml ? article.bodyHtml.replace(/<[^>]*>/g, \" \") : \"\");\n return (\n <article>\n <p style={{ fontSize: 12, opacity: 0.6 }}>{article.date}</p>\n <h1>{article.title}</h1>\n {article.coverUrl && (\n <Img src={article.coverUrl} alt=\"\" width={1200} height={700} sizes=\"(max-width: 900px) 100vw, 800px\" priority style={{ width: \"100%\", height: \"auto\", borderRadius: 12, margin: \"1rem 0\" }} />\n )}\n {html ? (\n // eslint-disable-next-line react/no-danger\n <div className=\"xicms-richtext\" dangerouslySetInnerHTML={{ __html: html }} />\n ) : (\n fallbackText.split(/\\n{2,}/).map((p, i) => (\n <p key={i} style={{ whiteSpace: \"pre-wrap\" }}>\n {p}\n </p>\n ))\n )}\n {jsonLd && (\n <script\n type=\"application/ld+json\"\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: JSON.stringify(articleBlogPostingJsonLd(article, { siteName: name })) }}\n />\n )}\n </article>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Registreert één pageview voor de huidige site/pad — max. één keer per browsersessie per pad
3
+ * (sessionStorage). Privacy-vriendelijk en goedkoop. No-op zonder Firebase. Plaats dit in de
4
+ * publieke layout van een klantsite (binnen <XiCMSProvider>).
5
+ */
6
+ export declare function PageView({ path }: {
7
+ path: string;
8
+ }): null;
@@ -0,0 +1,28 @@
1
+ "use client";
2
+ import { useEffect } from "react";
3
+ import { getFunctions, httpsCallable } from "firebase/functions";
4
+ import { getFirebaseApp } from "../firebase/client";
5
+ import { functionsRegion } from "../firebase/region";
6
+ import { useSiteConfig } from "../config";
7
+ function PageView({ path }) {
8
+ const { siteId } = useSiteConfig();
9
+ useEffect(() => {
10
+ if (typeof window === "undefined") return;
11
+ const key = `xicms_view:${siteId}:${path}`;
12
+ try {
13
+ if (sessionStorage.getItem(key)) return;
14
+ sessionStorage.setItem(key, "1");
15
+ } catch {
16
+ }
17
+ const app = getFirebaseApp();
18
+ if (!app) return;
19
+ const fn = httpsCallable(getFunctions(app, functionsRegion()), "trackView");
20
+ void fn({ siteId, path }).catch(() => {
21
+ });
22
+ }, [siteId, path]);
23
+ return null;
24
+ }
25
+ export {
26
+ PageView
27
+ };
28
+ //# sourceMappingURL=PageView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/PageView.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect } from \"react\";\nimport { getFunctions, httpsCallable } from \"firebase/functions\";\nimport { getFirebaseApp } from \"../firebase/client\";\nimport { functionsRegion } from \"../firebase/region\";\nimport { useSiteConfig } from \"../config\";\n\n/**\n * Registreert één pageview voor de huidige site/pad — max. één keer per browsersessie per pad\n * (sessionStorage). Privacy-vriendelijk en goedkoop. No-op zonder Firebase. Plaats dit in de\n * publieke layout van een klantsite (binnen <XiCMSProvider>).\n */\nexport function PageView({ path }: { path: string }) {\n const { siteId } = useSiteConfig();\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const key = `xicms_view:${siteId}:${path}`;\n try {\n if (sessionStorage.getItem(key)) return;\n sessionStorage.setItem(key, \"1\");\n } catch {\n /* private mode e.d. — ga gewoon door */\n }\n const app = getFirebaseApp();\n if (!app) return;\n const fn = httpsCallable(getFunctions(app, functionsRegion()), \"trackView\");\n void fn({ siteId, path }).catch(() => {\n /* stats mogen nooit de site breken */\n });\n }, [siteId, path]);\n\n return null;\n}\n"],"mappings":";AAEA,SAAS,iBAAiB;AAC1B,SAAS,cAAc,qBAAqB;AAC5C,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAOvB,SAAS,SAAS,EAAE,KAAK,GAAqB;AACnD,QAAM,EAAE,OAAO,IAAI,cAAc;AAEjC,YAAU,MAAM;AACd,QAAI,OAAO,WAAW,YAAa;AACnC,UAAM,MAAM,cAAc,MAAM,IAAI,IAAI;AACxC,QAAI;AACF,UAAI,eAAe,QAAQ,GAAG,EAAG;AACjC,qBAAe,QAAQ,KAAK,GAAG;AAAA,IACjC,QAAQ;AAAA,IAER;AACA,UAAM,MAAM,eAAe;AAC3B,QAAI,CAAC,IAAK;AACV,UAAM,KAAK,cAAc,aAAa,KAAK,gBAAgB,CAAC,GAAG,WAAW;AAC1E,SAAK,GAAG,EAAE,QAAQ,KAAK,CAAC,EAAE,MAAM,MAAM;AAAA,IAEtC,CAAC;AAAA,EACH,GAAG,CAAC,QAAQ,IAAI,CAAC;AAEjB,SAAO;AACT;","names":[]}
@@ -0,0 +1,16 @@
1
+ import type { CSSProperties } from "react";
2
+ import type { MediaItem } from "../content/types";
3
+ /**
4
+ * Rendert een afbeelding met srcset/webp uit de door de pipeline gegenereerde varianten.
5
+ * Server-safe. Valt terug op de originele `url` als er nog geen varianten zijn.
6
+ */
7
+ export declare function ResponsiveImage({ media, url, alt, className, style, sizes, priority, }: {
8
+ media?: Pick<MediaItem, "url" | "alt" | "width" | "height" | "variants">;
9
+ url?: string;
10
+ alt?: string;
11
+ className?: string;
12
+ style?: CSSProperties;
13
+ sizes?: string;
14
+ /** Zet dit op een above-the-fold beeld (bv. hero): eager laden + hoge fetch-prioriteit voor LCP. */
15
+ priority?: boolean;
16
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,39 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ function ResponsiveImage({
3
+ media,
4
+ url,
5
+ alt,
6
+ className,
7
+ style,
8
+ sizes = "100vw",
9
+ priority = false
10
+ }) {
11
+ const src = media?.url ?? url;
12
+ if (!src) return null;
13
+ const altText = alt ?? media?.alt ?? "";
14
+ const ladder = media?.variants?.sizes ?? [];
15
+ const webp = media?.variants?.webp;
16
+ const srcSet = ladder.length ? ladder.map((v) => `${v.url} ${v.width}w`).join(", ") : void 0;
17
+ return /* @__PURE__ */ jsxs("picture", { children: [
18
+ webp && /* @__PURE__ */ jsx("source", { type: "image/webp", srcSet: `${webp.url} ${webp.width}w`, sizes }),
19
+ /* @__PURE__ */ jsx(
20
+ "img",
21
+ {
22
+ src,
23
+ srcSet,
24
+ sizes: srcSet ? sizes : void 0,
25
+ alt: altText,
26
+ width: media?.width,
27
+ height: media?.height,
28
+ loading: priority ? "eager" : "lazy",
29
+ fetchPriority: priority ? "high" : void 0,
30
+ className,
31
+ style
32
+ }
33
+ )
34
+ ] });
35
+ }
36
+ export {
37
+ ResponsiveImage
38
+ };
39
+ //# sourceMappingURL=ResponsiveImage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/ResponsiveImage.tsx"],"sourcesContent":["import type { CSSProperties } from \"react\";\nimport type { MediaItem } from \"../content/types\";\n\n/**\n * Rendert een afbeelding met srcset/webp uit de door de pipeline gegenereerde varianten.\n * Server-safe. Valt terug op de originele `url` als er nog geen varianten zijn.\n */\nexport function ResponsiveImage({\n media,\n url,\n alt,\n className,\n style,\n sizes = \"100vw\",\n priority = false,\n}: {\n media?: Pick<MediaItem, \"url\" | \"alt\" | \"width\" | \"height\" | \"variants\">;\n url?: string;\n alt?: string;\n className?: string;\n style?: CSSProperties;\n sizes?: string;\n /** Zet dit op een above-the-fold beeld (bv. hero): eager laden + hoge fetch-prioriteit voor LCP. */\n priority?: boolean;\n}) {\n const src = media?.url ?? url;\n if (!src) return null;\n const altText = alt ?? media?.alt ?? \"\";\n const ladder = media?.variants?.sizes ?? [];\n const webp = media?.variants?.webp;\n\n const srcSet = ladder.length\n ? ladder.map((v) => `${v.url} ${v.width}w`).join(\", \")\n : undefined;\n\n return (\n <picture>\n {webp && <source type=\"image/webp\" srcSet={`${webp.url} ${webp.width}w`} sizes={sizes} />}\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img\n src={src}\n srcSet={srcSet}\n sizes={srcSet ? sizes : undefined}\n alt={altText}\n width={media?.width}\n height={media?.height}\n loading={priority ? \"eager\" : \"lazy\"}\n fetchPriority={priority ? \"high\" : undefined}\n className={className}\n style={style}\n />\n </picture>\n );\n}\n"],"mappings":"AAoCI,SACW,KADX;AA7BG,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR,WAAW;AACb,GASG;AACD,QAAM,MAAM,OAAO,OAAO;AAC1B,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,UAAU,OAAO,OAAO,OAAO;AACrC,QAAM,SAAS,OAAO,UAAU,SAAS,CAAC;AAC1C,QAAM,OAAO,OAAO,UAAU;AAE9B,QAAM,SAAS,OAAO,SAClB,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,KAAK,IAAI,IACnD;AAEJ,SACE,qBAAC,aACE;AAAA,YAAQ,oBAAC,YAAO,MAAK,cAAa,QAAQ,GAAG,KAAK,GAAG,IAAI,KAAK,KAAK,KAAK,OAAc;AAAA,IAEvF;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,OAAO,SAAS,QAAQ;AAAA,QACxB,KAAK;AAAA,QACL,OAAO,OAAO;AAAA,QACd,QAAQ,OAAO;AAAA,QACf,SAAS,WAAW,UAAU;AAAA,QAC9B,eAAe,WAAW,SAAS;AAAA,QACnC;AAAA,QACA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;","names":[]}
@@ -0,0 +1,12 @@
1
+ import type { ReactNode } from "react";
2
+ import type { FooterSettings } from "../../schema/settings";
3
+ /**
4
+ * Door de klant in /beheer bewerkbare footer. Unstyled-by-default: alle opmaak hangt aan
5
+ * `xicms-footer*`-classNames + thema-CSS-variabelen, zodat een site hem volledig kan herstijlen
6
+ * (of vervangen door een eigen footer). De inhoud komt live uit `settings/public.footer`.
7
+ */
8
+ export declare function SiteFooter({ className, renderColumn, }: {
9
+ className?: string;
10
+ /** Override de opmaak van één kolom zonder de logica te forken. */
11
+ renderColumn?: (column: NonNullable<FooterSettings["columns"]>[number], index: number) => ReactNode;
12
+ }): import("react").JSX.Element;
@@ -0,0 +1,34 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useSiteSettings } from "../../settings/useSiteSettings";
4
+ import { useSiteConfig } from "../../config";
5
+ function SiteFooter({
6
+ className,
7
+ renderColumn
8
+ }) {
9
+ const { settings } = useSiteSettings();
10
+ const config = useSiteConfig();
11
+ const footer = settings.footer ?? {};
12
+ const name = settings.name ?? config.name;
13
+ const columns = footer.columns ?? [];
14
+ const social = footer.social ?? [];
15
+ const showAdminLink = footer.showAdminLink !== false;
16
+ const year = (/* @__PURE__ */ new Date()).getFullYear();
17
+ return /* @__PURE__ */ jsxs("footer", { className: className ?? "xicms-footer", children: [
18
+ columns.length > 0 && /* @__PURE__ */ jsx("div", { className: "xicms-footer__columns", children: columns.map(
19
+ (col, i) => renderColumn ? /* @__PURE__ */ jsx("div", { children: renderColumn(col, i) }, i) : /* @__PURE__ */ jsxs("div", { className: "xicms-footer__column", children: [
20
+ col.heading && /* @__PURE__ */ jsx("h3", { className: "xicms-footer__heading", children: col.heading }),
21
+ /* @__PURE__ */ jsx("ul", { className: "xicms-footer__links", children: (col.links ?? []).map((l, j) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { href: l.href, children: l.label }) }, j)) })
22
+ ] }, i)
23
+ ) }),
24
+ social.length > 0 && /* @__PURE__ */ jsx("ul", { className: "xicms-footer__social", children: social.map((s, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", { href: s.href, "aria-label": s.platform, rel: "noopener noreferrer", target: "_blank", children: s.platform }) }, i)) }),
25
+ /* @__PURE__ */ jsxs("div", { className: "xicms-footer__bottom", children: [
26
+ /* @__PURE__ */ jsx("span", { children: footer.copyright ?? `\xA9 ${year} ${name}` }),
27
+ showAdminLink && /* @__PURE__ */ jsx("a", { href: "/beheer", children: "Beheer" })
28
+ ] })
29
+ ] });
30
+ }
31
+ export {
32
+ SiteFooter
33
+ };
34
+ //# sourceMappingURL=SiteFooter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/site/SiteFooter.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ReactNode } from \"react\";\nimport { useSiteSettings } from \"../../settings/useSiteSettings\";\nimport { useSiteConfig } from \"../../config\";\nimport type { FooterSettings } from \"../../schema/settings\";\n\n/**\n * Door de klant in /beheer bewerkbare footer. Unstyled-by-default: alle opmaak hangt aan\n * `xicms-footer*`-classNames + thema-CSS-variabelen, zodat een site hem volledig kan herstijlen\n * (of vervangen door een eigen footer). De inhoud komt live uit `settings/public.footer`.\n */\nexport function SiteFooter({\n className,\n renderColumn,\n}: {\n className?: string;\n /** Override de opmaak van één kolom zonder de logica te forken. */\n renderColumn?: (column: NonNullable<FooterSettings[\"columns\"]>[number], index: number) => ReactNode;\n}) {\n const { settings } = useSiteSettings();\n const config = useSiteConfig();\n const footer = settings.footer ?? {};\n const name = settings.name ?? config.name;\n const columns = footer.columns ?? [];\n const social = footer.social ?? [];\n const showAdminLink = footer.showAdminLink !== false;\n const year = new Date().getFullYear();\n\n return (\n <footer className={className ?? \"xicms-footer\"}>\n {columns.length > 0 && (\n <div className=\"xicms-footer__columns\">\n {columns.map((col, i) =>\n renderColumn ? (\n <div key={i}>{renderColumn(col, i)}</div>\n ) : (\n <div key={i} className=\"xicms-footer__column\">\n {col.heading && <h3 className=\"xicms-footer__heading\">{col.heading}</h3>}\n <ul className=\"xicms-footer__links\">\n {(col.links ?? []).map((l, j) => (\n <li key={j}>\n <a href={l.href}>{l.label}</a>\n </li>\n ))}\n </ul>\n </div>\n ),\n )}\n </div>\n )}\n\n {social.length > 0 && (\n <ul className=\"xicms-footer__social\">\n {social.map((s, i) => (\n <li key={i}>\n <a href={s.href} aria-label={s.platform} rel=\"noopener noreferrer\" target=\"_blank\">\n {s.platform}\n </a>\n </li>\n ))}\n </ul>\n )}\n\n <div className=\"xicms-footer__bottom\">\n <span>{footer.copyright ?? `© ${year} ${name}`}</span>\n {showAdminLink && <a href=\"/beheer\">Beheer</a>}\n </div>\n </footer>\n );\n}\n"],"mappings":";AAmCc,cAEA,YAFA;AAhCd,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAQvB,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AACF,GAIG;AACD,QAAM,EAAE,SAAS,IAAI,gBAAgB;AACrC,QAAM,SAAS,cAAc;AAC7B,QAAM,SAAS,SAAS,UAAU,CAAC;AACnC,QAAM,OAAO,SAAS,QAAQ,OAAO;AACrC,QAAM,UAAU,OAAO,WAAW,CAAC;AACnC,QAAM,SAAS,OAAO,UAAU,CAAC;AACjC,QAAM,gBAAgB,OAAO,kBAAkB;AAC/C,QAAM,QAAO,oBAAI,KAAK,GAAE,YAAY;AAEpC,SACE,qBAAC,YAAO,WAAW,aAAa,gBAC7B;AAAA,YAAQ,SAAS,KAChB,oBAAC,SAAI,WAAU,yBACZ,kBAAQ;AAAA,MAAI,CAAC,KAAK,MACjB,eACE,oBAAC,SAAa,uBAAa,KAAK,CAAC,KAAvB,CAAyB,IAEnC,qBAAC,SAAY,WAAU,wBACpB;AAAA,YAAI,WAAW,oBAAC,QAAG,WAAU,yBAAyB,cAAI,SAAQ;AAAA,QACnE,oBAAC,QAAG,WAAU,uBACV,eAAI,SAAS,CAAC,GAAG,IAAI,CAAC,GAAG,MACzB,oBAAC,QACC,8BAAC,OAAE,MAAM,EAAE,MAAO,YAAE,OAAM,KADnB,CAET,CACD,GACH;AAAA,WARQ,CASV;AAAA,IAEJ,GACF;AAAA,IAGD,OAAO,SAAS,KACf,oBAAC,QAAG,WAAU,wBACX,iBAAO,IAAI,CAAC,GAAG,MACd,oBAAC,QACC,8BAAC,OAAE,MAAM,EAAE,MAAM,cAAY,EAAE,UAAU,KAAI,uBAAsB,QAAO,UACvE,YAAE,UACL,KAHO,CAIT,CACD,GACH;AAAA,IAGF,qBAAC,SAAI,WAAU,wBACb;AAAA,0BAAC,UAAM,iBAAO,aAAa,QAAK,IAAI,IAAI,IAAI,IAAG;AAAA,MAC9C,iBAAiB,oBAAC,OAAE,MAAK,WAAU,oBAAM;AAAA,OAC5C;AAAA,KACF;AAEJ;","names":[]}
@@ -0,0 +1,8 @@
1
+ import { type ReactNode } from "react";
2
+ import type { SiteConfig } from "./schema/siteConfig";
3
+ export declare function ConfigProvider({ config, children }: {
4
+ config: SiteConfig;
5
+ children: ReactNode;
6
+ }): import("react").JSX.Element;
7
+ /** Lees de actieve SiteConfig (siteId, theme, mode, …). */
8
+ export declare function useSiteConfig(): SiteConfig;
package/dist/config.js ADDED
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { createContext, useContext } from "react";
4
+ const ConfigContext = createContext(null);
5
+ function ConfigProvider({ config, children }) {
6
+ return /* @__PURE__ */ jsx(ConfigContext.Provider, { value: config, children });
7
+ }
8
+ function useSiteConfig() {
9
+ const ctx = useContext(ConfigContext);
10
+ if (!ctx) throw new Error("useSiteConfig moet binnen <XiCMSProvider> worden gebruikt.");
11
+ return ctx;
12
+ }
13
+ export {
14
+ ConfigProvider,
15
+ useSiteConfig
16
+ };
17
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.tsx"],"sourcesContent":["\"use client\";\n\nimport { createContext, useContext, type ReactNode } from \"react\";\nimport type { SiteConfig } from \"./schema/siteConfig\";\n\nconst ConfigContext = createContext<SiteConfig | null>(null);\n\nexport function ConfigProvider({ config, children }: { config: SiteConfig; children: ReactNode }) {\n return <ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>;\n}\n\n/** Lees de actieve SiteConfig (siteId, theme, mode, …). */\nexport function useSiteConfig(): SiteConfig {\n const ctx = useContext(ConfigContext);\n if (!ctx) throw new Error(\"useSiteConfig moet binnen <XiCMSProvider> worden gebruikt.\");\n return ctx;\n}\n"],"mappings":";AAQS;AANT,SAAS,eAAe,kBAAkC;AAG1D,MAAM,gBAAgB,cAAiC,IAAI;AAEpD,SAAS,eAAe,EAAE,QAAQ,SAAS,GAAgD;AAChG,SAAO,oBAAC,cAAc,UAAd,EAAuB,OAAO,QAAS,UAAS;AAC1D;AAGO,SAAS,gBAA4B;AAC1C,QAAM,MAAM,WAAW,aAAa;AACpC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,4DAA4D;AACtF,SAAO;AACT;","names":[]}
@@ -0,0 +1,23 @@
1
+ import { type ReactNode } from "react";
2
+ interface ContentState {
3
+ /** Haal een waarde op; valt terug op defaults en daarna op `fallback`. */
4
+ get: (key: string, fallback?: string) => string;
5
+ /** Sla een waarde op (alleen als de gebruiker mag bewerken). */
6
+ set: (key: string, value: string) => Promise<void>;
7
+ /** Of de bewerk-modus aanstaat. */
8
+ editMode: boolean;
9
+ setEditMode: (on: boolean) => void;
10
+ /** Of de huidige gebruiker content mag bewerken. */
11
+ canEdit: boolean;
12
+ loading: boolean;
13
+ }
14
+ /** @deprecated LEGACY v1 (plat `cms/content`-model). Vervangen door het block-model (pagina's/
15
+ * drafts) + de visuele editor. Blijft werken voor bestaande sites; verwijdering volgt in een major. */
16
+ export declare function ContentProvider({ siteId, defaults, children, }: {
17
+ siteId: string;
18
+ defaults?: Record<string, string>;
19
+ children: ReactNode;
20
+ }): import("react").JSX.Element;
21
+ /** @deprecated Hoort bij het legacy `cms/content`-model. Voor rechten: `useAuth()` + `canEdit(role)`. */
22
+ export declare function useContent(): ContentState;
23
+ export {};
@@ -0,0 +1,86 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import {
4
+ createContext,
5
+ useContext,
6
+ useEffect,
7
+ useMemo,
8
+ useState
9
+ } from "react";
10
+ import { doc, getDoc, onSnapshot, setDoc, serverTimestamp } from "firebase/firestore";
11
+ import { getDb } from "../firebase/client";
12
+ import { useAuth } from "../auth/AuthProvider";
13
+ import { canEdit } from "../auth/roles";
14
+ const ContentContext = createContext(null);
15
+ function ContentProvider({
16
+ siteId,
17
+ defaults = {},
18
+ children
19
+ }) {
20
+ const { role } = useAuth();
21
+ const editable = canEdit(role);
22
+ const [values, setValues] = useState({});
23
+ const [editMode, setEditMode] = useState(false);
24
+ const [loading, setLoading] = useState(true);
25
+ useEffect(() => {
26
+ const db = getDb();
27
+ if (!db) {
28
+ setLoading(false);
29
+ return;
30
+ }
31
+ const ref = doc(db, "sites", siteId, "cms", "content");
32
+ const apply = (snap) => {
33
+ const data = snap.data();
34
+ setValues(data?.values ?? {});
35
+ setLoading(false);
36
+ };
37
+ if (editable) {
38
+ const unsub = onSnapshot(ref, apply, () => setLoading(false));
39
+ return () => unsub();
40
+ }
41
+ let active = true;
42
+ getDoc(ref).then((snap) => {
43
+ if (active) apply(snap);
44
+ }).catch(() => {
45
+ if (active) setLoading(false);
46
+ });
47
+ return () => {
48
+ active = false;
49
+ };
50
+ }, [siteId, editable]);
51
+ useEffect(() => {
52
+ if (!editable && editMode) setEditMode(false);
53
+ }, [editable, editMode]);
54
+ const value = useMemo(
55
+ () => ({
56
+ get: (key, fallback = "") => values[key] ?? defaults[key] ?? fallback,
57
+ set: async (key, val) => {
58
+ if (!editable) return;
59
+ const db = getDb();
60
+ if (!db) return;
61
+ const ref = doc(db, "sites", siteId, "cms", "content");
62
+ await setDoc(
63
+ ref,
64
+ { values: { [key]: val }, updatedAt: serverTimestamp() },
65
+ { merge: true }
66
+ );
67
+ },
68
+ editMode,
69
+ setEditMode,
70
+ canEdit: editable,
71
+ loading
72
+ }),
73
+ [values, defaults, editMode, editable, loading, siteId]
74
+ );
75
+ return /* @__PURE__ */ jsx(ContentContext.Provider, { value, children });
76
+ }
77
+ function useContent() {
78
+ const ctx = useContext(ContentContext);
79
+ if (!ctx) throw new Error("useContent moet binnen <XiCMSProvider> worden gebruikt.");
80
+ return ctx;
81
+ }
82
+ export {
83
+ ContentProvider,
84
+ useContent
85
+ };
86
+ //# sourceMappingURL=ContentProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/content/ContentProvider.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from \"react\";\nimport { doc, getDoc, onSnapshot, setDoc, serverTimestamp } from \"firebase/firestore\";\nimport { getDb } from \"../firebase/client\";\nimport { useAuth } from \"../auth/AuthProvider\";\nimport { canEdit } from \"../auth/roles\";\n\ninterface ContentState {\n /** Haal een waarde op; valt terug op defaults en daarna op `fallback`. */\n get: (key: string, fallback?: string) => string;\n /** Sla een waarde op (alleen als de gebruiker mag bewerken). */\n set: (key: string, value: string) => Promise<void>;\n /** Of de bewerk-modus aanstaat. */\n editMode: boolean;\n setEditMode: (on: boolean) => void;\n /** Of de huidige gebruiker content mag bewerken. */\n canEdit: boolean;\n loading: boolean;\n}\n\nconst ContentContext = createContext<ContentState | null>(null);\n\n/** @deprecated LEGACY v1 (plat `cms/content`-model). Vervangen door het block-model (pagina's/\n * drafts) + de visuele editor. Blijft werken voor bestaande sites; verwijdering volgt in een major. */\nexport function ContentProvider({\n siteId,\n defaults = {},\n children,\n}: {\n siteId: string;\n defaults?: Record<string, string>;\n children: ReactNode;\n}) {\n const { role } = useAuth();\n const editable = canEdit(role);\n const [values, setValues] = useState<Record<string, string>>({});\n const [editMode, setEditMode] = useState(false);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n const db = getDb();\n if (!db) {\n setLoading(false);\n return;\n }\n const ref = doc(db, \"sites\", siteId, \"cms\", \"content\");\n const apply = (snap: { data: () => unknown }) => {\n const data = snap.data() as { values?: Record<string, string> } | undefined;\n setValues(data?.values ?? {});\n setLoading(false);\n };\n\n // Kostenbesparing: publieke bezoekers (geen bewerkrechten) lezen de content één keer\n // (getDoc) i.p.v. een realtime listener per bezoeker. Editors houden onSnapshot zodat ze\n // hun eigen wijzigingen meteen terugzien.\n if (editable) {\n const unsub = onSnapshot(ref, apply, () => setLoading(false));\n return () => unsub();\n }\n let active = true;\n getDoc(ref)\n .then((snap) => {\n if (active) apply(snap);\n })\n .catch(() => {\n if (active) setLoading(false);\n });\n return () => {\n active = false;\n };\n }, [siteId, editable]);\n\n // Geen bewerk-rechten? Forceer edit-modus uit.\n useEffect(() => {\n if (!editable && editMode) setEditMode(false);\n }, [editable, editMode]);\n\n const value = useMemo<ContentState>(\n () => ({\n get: (key, fallback = \"\") => values[key] ?? defaults[key] ?? fallback,\n set: async (key, val) => {\n if (!editable) return;\n const db = getDb();\n if (!db) return;\n const ref = doc(db, \"sites\", siteId, \"cms\", \"content\");\n await setDoc(\n ref,\n { values: { [key]: val }, updatedAt: serverTimestamp() },\n { merge: true },\n );\n },\n editMode,\n setEditMode,\n canEdit: editable,\n loading,\n }),\n [values, defaults, editMode, editable, loading, siteId],\n );\n\n return <ContentContext.Provider value={value}>{children}</ContentContext.Provider>;\n}\n\n/** @deprecated Hoort bij het legacy `cms/content`-model. Voor rechten: `useAuth()` + `canEdit(role)`. */\nexport function useContent(): ContentState {\n const ctx = useContext(ContentContext);\n if (!ctx) throw new Error(\"useContent moet binnen <XiCMSProvider> worden gebruikt.\");\n return ctx;\n}\n"],"mappings":";AA2GS;AAzGT;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,KAAK,QAAQ,YAAY,QAAQ,uBAAuB;AACjE,SAAS,aAAa;AACtB,SAAS,eAAe;AACxB,SAAS,eAAe;AAexB,MAAM,iBAAiB,cAAmC,IAAI;AAIvD,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA,WAAW,CAAC;AAAA,EACZ;AACF,GAIG;AACD,QAAM,EAAE,KAAK,IAAI,QAAQ;AACzB,QAAM,WAAW,QAAQ,IAAI;AAC7B,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAiC,CAAC,CAAC;AAC/D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAE3C,YAAU,MAAM;AACd,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,IAAI;AACP,iBAAW,KAAK;AAChB;AAAA,IACF;AACA,UAAM,MAAM,IAAI,IAAI,SAAS,QAAQ,OAAO,SAAS;AACrD,UAAM,QAAQ,CAAC,SAAkC;AAC/C,YAAM,OAAO,KAAK,KAAK;AACvB,gBAAU,MAAM,UAAU,CAAC,CAAC;AAC5B,iBAAW,KAAK;AAAA,IAClB;AAKA,QAAI,UAAU;AACZ,YAAM,QAAQ,WAAW,KAAK,OAAO,MAAM,WAAW,KAAK,CAAC;AAC5D,aAAO,MAAM,MAAM;AAAA,IACrB;AACA,QAAI,SAAS;AACb,WAAO,GAAG,EACP,KAAK,CAAC,SAAS;AACd,UAAI,OAAQ,OAAM,IAAI;AAAA,IACxB,CAAC,EACA,MAAM,MAAM;AACX,UAAI,OAAQ,YAAW,KAAK;AAAA,IAC9B,CAAC;AACH,WAAO,MAAM;AACX,eAAS;AAAA,IACX;AAAA,EACF,GAAG,CAAC,QAAQ,QAAQ,CAAC;AAGrB,YAAU,MAAM;AACd,QAAI,CAAC,YAAY,SAAU,aAAY,KAAK;AAAA,EAC9C,GAAG,CAAC,UAAU,QAAQ,CAAC;AAEvB,QAAM,QAAQ;AAAA,IACZ,OAAO;AAAA,MACL,KAAK,CAAC,KAAK,WAAW,OAAO,OAAO,GAAG,KAAK,SAAS,GAAG,KAAK;AAAA,MAC7D,KAAK,OAAO,KAAK,QAAQ;AACvB,YAAI,CAAC,SAAU;AACf,cAAM,KAAK,MAAM;AACjB,YAAI,CAAC,GAAI;AACT,cAAM,MAAM,IAAI,IAAI,SAAS,QAAQ,OAAO,SAAS;AACrD,cAAM;AAAA,UACJ;AAAA,UACA,EAAE,QAAQ,EAAE,CAAC,GAAG,GAAG,IAAI,GAAG,WAAW,gBAAgB,EAAE;AAAA,UACvD,EAAE,OAAO,KAAK;AAAA,QAChB;AAAA,MACF;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,UAAU,UAAU,UAAU,SAAS,MAAM;AAAA,EACxD;AAEA,SAAO,oBAAC,eAAe,UAAf,EAAwB,OAAe,UAAS;AAC1D;AAGO,SAAS,aAA2B;AACzC,QAAM,MAAM,WAAW,cAAc;AACrC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,yDAAyD;AACnF,SAAO;AACT;","names":[]}
@@ -0,0 +1,41 @@
1
+ /** Een nieuwsartikel zoals opgeslagen in `sites/{siteId}/news/{id}`. */
2
+ export interface NewsArticle {
3
+ id: string;
4
+ title: string;
5
+ slug: string;
6
+ excerpt?: string;
7
+ body: string;
8
+ /** Optionele rich-text-versie van de inhoud (HTML). Wordt bij renderen altijd gesanitized;
9
+ * ontbreekt dit veld, dan rendert `body` als platte tekst (bestaand gedrag). */
10
+ bodyHtml?: string;
11
+ coverUrl?: string;
12
+ /** ISO-datum (yyyy-mm-dd). */
13
+ date: string;
14
+ published: boolean;
15
+ }
16
+ /** Een geoptimaliseerde variant van een afbeelding (door de media-pipeline gegenereerd). */
17
+ export interface MediaVariant {
18
+ url: string;
19
+ path: string;
20
+ width: number;
21
+ }
22
+ /** Een media-item zoals opgeslagen in `sites/{siteId}/media/{id}`. */
23
+ export interface MediaItem {
24
+ id: string;
25
+ url: string;
26
+ path: string;
27
+ name: string;
28
+ contentType?: string;
29
+ size?: number;
30
+ /** Toegankelijkheids-tekst. */
31
+ alt?: string;
32
+ width?: number;
33
+ height?: number;
34
+ /** Door de sharp-Cloud-Function gevulde varianten. */
35
+ variants?: {
36
+ webp?: MediaVariant;
37
+ sizes?: MediaVariant[];
38
+ };
39
+ /** "processing" tot de pipeline klaar is, daarna "ready". */
40
+ status?: "processing" | "ready";
41
+ }
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Bovenbalk voor de DEMO-bewerkmodus (`config.demoEditing`). Biedt een pseudo-login waarmee
3
+ * bezoekers het beheer (teksten + blokken) kunnen uitproberen, en maakt heel duidelijk dat
4
+ * wijzigingen NIET worden opgeslagen — ze blijven alleen lokaal in de browser en zijn met één
5
+ * klik te resetten. De echte bewerkacties ("Pagina bewerken", "Uitloggen") staan in de EditBar.
6
+ */
7
+ export declare function DemoStudio(): import("react").JSX.Element | null;
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { useAuth } from "../auth/AuthProvider";
5
+ import { useSiteConfig } from "../config";
6
+ import { DEMO_EVENT, isDemoLoggedIn, resetDemo } from "./demoStore";
7
+ function DemoStudio() {
8
+ const { demo, demoSignIn } = useAuth();
9
+ const { siteId } = useSiteConfig();
10
+ const [loggedIn, setLoggedIn] = useState(false);
11
+ useEffect(() => {
12
+ if (!demo) return;
13
+ const sync = () => setLoggedIn(isDemoLoggedIn());
14
+ sync();
15
+ window.addEventListener(DEMO_EVENT, sync);
16
+ return () => window.removeEventListener(DEMO_EVENT, sync);
17
+ }, [demo]);
18
+ if (!demo) return null;
19
+ return /* @__PURE__ */ jsx("div", { className: "xicms-demostudio", role: "region", "aria-label": "Demo-bewerkmodus", children: !loggedIn ? /* @__PURE__ */ jsxs(Fragment, { children: [
20
+ /* @__PURE__ */ jsxs("span", { className: "xicms-demostudio__msg", children: [
21
+ /* @__PURE__ */ jsx("strong", { children: "Probeer het zelf:" }),
22
+ " log in als demo-beheerder en bewerk teksten, foto's en blokken \u2014 ",
23
+ /* @__PURE__ */ jsx("strong", { children: "niets wordt opgeslagen" }),
24
+ ", je wijzigingen blijven alleen in jouw browser."
25
+ ] }),
26
+ /* @__PURE__ */ jsx("button", { type: "button", className: "xicms-btn", onClick: demoSignIn, children: "Probeer het beheer (demo-login)" })
27
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
28
+ /* @__PURE__ */ jsxs("span", { className: "xicms-demostudio__msg", children: [
29
+ "\u270F\uFE0F ",
30
+ /* @__PURE__ */ jsx("strong", { children: "Demo-bewerkmodus." }),
31
+ " Klik onderaan op ",
32
+ /* @__PURE__ */ jsx("strong", { children: "\u201CPagina bewerken\u201D" }),
33
+ " om blokken aan te passen. Let op: ",
34
+ /* @__PURE__ */ jsx("strong", { children: "wijzigingen worden niet opgeslagen" }),
35
+ " \u2014 ze staan alleen lokaal in jouw browser."
36
+ ] }),
37
+ /* @__PURE__ */ jsx(
38
+ "button",
39
+ {
40
+ type: "button",
41
+ className: "xicms-btn xicms-btn--ghost",
42
+ onClick: () => {
43
+ resetDemo(siteId);
44
+ if (typeof window !== "undefined") window.location.reload();
45
+ },
46
+ children: "Reset demo"
47
+ }
48
+ )
49
+ ] }) });
50
+ }
51
+ export {
52
+ DemoStudio
53
+ };
54
+ //# sourceMappingURL=DemoStudio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/demo/DemoStudio.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { useAuth } from \"../auth/AuthProvider\";\nimport { useSiteConfig } from \"../config\";\nimport { DEMO_EVENT, isDemoLoggedIn, resetDemo } from \"./demoStore\";\n\n/**\n * Bovenbalk voor de DEMO-bewerkmodus (`config.demoEditing`). Biedt een pseudo-login waarmee\n * bezoekers het beheer (teksten + blokken) kunnen uitproberen, en maakt heel duidelijk dat\n * wijzigingen NIET worden opgeslagen — ze blijven alleen lokaal in de browser en zijn met één\n * klik te resetten. De echte bewerkacties (\"Pagina bewerken\", \"Uitloggen\") staan in de EditBar.\n */\nexport function DemoStudio() {\n const { demo, demoSignIn } = useAuth();\n const { siteId } = useSiteConfig();\n const [loggedIn, setLoggedIn] = useState(false);\n\n useEffect(() => {\n if (!demo) return;\n const sync = () => setLoggedIn(isDemoLoggedIn());\n sync();\n window.addEventListener(DEMO_EVENT, sync);\n return () => window.removeEventListener(DEMO_EVENT, sync);\n }, [demo]);\n\n if (!demo) return null;\n\n return (\n <div className=\"xicms-demostudio\" role=\"region\" aria-label=\"Demo-bewerkmodus\">\n {!loggedIn ? (\n <>\n <span className=\"xicms-demostudio__msg\">\n <strong>Probeer het zelf:</strong> log in als demo-beheerder en bewerk teksten, foto&apos;s en\n blokken — <strong>niets wordt opgeslagen</strong>, je wijzigingen blijven alleen in jouw browser.\n </span>\n <button type=\"button\" className=\"xicms-btn\" onClick={demoSignIn}>\n Probeer het beheer (demo-login)\n </button>\n </>\n ) : (\n <>\n <span className=\"xicms-demostudio__msg\">\n ✏️ <strong>Demo-bewerkmodus.</strong> Klik onderaan op <strong>“Pagina bewerken”</strong> om\n blokken aan te passen. Let op: <strong>wijzigingen worden niet opgeslagen</strong> — ze staan\n alleen lokaal in jouw browser.\n </span>\n <button\n type=\"button\"\n className=\"xicms-btn xicms-btn--ghost\"\n onClick={() => {\n resetDemo(siteId);\n // Herlaad zodat de pagina terugvalt op de oorspronkelijke (seed-)inhoud.\n if (typeof window !== \"undefined\") window.location.reload();\n }}\n >\n Reset demo\n </button>\n </>\n )}\n </div>\n );\n}\n"],"mappings":";AA+BQ,mBAEI,KADF,YADF;AA7BR,SAAS,WAAW,gBAAgB;AACpC,SAAS,eAAe;AACxB,SAAS,qBAAqB;AAC9B,SAAS,YAAY,gBAAgB,iBAAiB;AAQ/C,SAAS,aAAa;AAC3B,QAAM,EAAE,MAAM,WAAW,IAAI,QAAQ;AACrC,QAAM,EAAE,OAAO,IAAI,cAAc;AACjC,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAE9C,YAAU,MAAM;AACd,QAAI,CAAC,KAAM;AACX,UAAM,OAAO,MAAM,YAAY,eAAe,CAAC;AAC/C,SAAK;AACL,WAAO,iBAAiB,YAAY,IAAI;AACxC,WAAO,MAAM,OAAO,oBAAoB,YAAY,IAAI;AAAA,EAC1D,GAAG,CAAC,IAAI,CAAC;AAET,MAAI,CAAC,KAAM,QAAO;AAElB,SACE,oBAAC,SAAI,WAAU,oBAAmB,MAAK,UAAS,cAAW,oBACxD,WAAC,WACA,iCACE;AAAA,yBAAC,UAAK,WAAU,yBACd;AAAA,0BAAC,YAAO,+BAAiB;AAAA,MAAS;AAAA,MACxB,oBAAC,YAAO,oCAAsB;AAAA,MAAS;AAAA,OACnD;AAAA,IACA,oBAAC,YAAO,MAAK,UAAS,WAAU,aAAY,SAAS,YAAY,6CAEjE;AAAA,KACF,IAEA,iCACE;AAAA,yBAAC,UAAK,WAAU,yBAAwB;AAAA;AAAA,MACnC,oBAAC,YAAO,+BAAiB;AAAA,MAAS;AAAA,MAAkB,oBAAC,YAAO,yCAAiB;AAAA,MAAS;AAAA,MAC1D,oBAAC,YAAO,gDAAkC;AAAA,MAAS;AAAA,OAEpF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,SAAS,MAAM;AACb,oBAAU,MAAM;AAEhB,cAAI,OAAO,WAAW,YAAa,QAAO,SAAS,OAAO;AAAA,QAC5D;AAAA,QACD;AAAA;AAAA,IAED;AAAA,KACF,GAEJ;AAEJ;","names":[]}