@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,1602 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { collection, getDocs } from "firebase/firestore";
5
+ import { getDb } from "../../firebase/client";
6
+ import { Button, Field, Input, Textarea } from "../ui/primitives";
7
+ import { Select } from "../ui/select";
8
+ import { Switch } from "../ui/switch";
9
+ import { ArrayEditor } from "../ui/ArrayEditor";
10
+ import { RichTextEditor } from "../editors/RichTextEditor";
11
+ import { MediaPickerButton } from "../media/MediaPicker";
12
+ import { useRegistry } from "../../blocks/context";
13
+ import { introspectObjectSchema } from "../lib/zodFields";
14
+ const VARIANT_OPTIONS = [
15
+ { value: "primary", label: "Primair" },
16
+ { value: "secondary", label: "Secundair" },
17
+ { value: "outline", label: "Outline" }
18
+ ];
19
+ function patch(block, onChange, part) {
20
+ onChange({ ...block, ...part });
21
+ }
22
+ function ImageUploadButton({ siteId, onUploaded }) {
23
+ return /* @__PURE__ */ jsx(MediaPickerButton, { siteId, onSelect: (m) => onUploaded(m.url, m.mediaId, m.alt) });
24
+ }
25
+ function HeroEditor({ block, siteId, onChange }) {
26
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
27
+ /* @__PURE__ */ jsx(Field, { label: "Regeltje boven de titel (optioneel)", hint: "bv. 'Hoveniers sinds 2001'", children: /* @__PURE__ */ jsx(Input, { value: block.eyebrow ?? "", onChange: (e) => patch(block, onChange, { eyebrow: e.target.value || void 0 }) }) }),
28
+ /* @__PURE__ */ jsx(Field, { label: "Titel", children: /* @__PURE__ */ jsx(Input, { value: block.title ?? "", onChange: (e) => patch(block, onChange, { title: e.target.value }) }) }),
29
+ /* @__PURE__ */ jsx(Field, { label: "Ondertitel", children: /* @__PURE__ */ jsx(Input, { value: block.subtitle ?? "", onChange: (e) => patch(block, onChange, { subtitle: e.target.value }) }) }),
30
+ /* @__PURE__ */ jsx(Field, { label: "Uitlijning", children: /* @__PURE__ */ jsx(
31
+ Select,
32
+ {
33
+ value: block.align ?? "left",
34
+ onValueChange: (v) => patch(block, onChange, { align: v }),
35
+ options: [
36
+ { value: "left", label: "Links" },
37
+ { value: "center", label: "Gecentreerd" }
38
+ ]
39
+ }
40
+ ) }),
41
+ /* @__PURE__ */ jsx(Field, { label: "Achtergrondafbeelding", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
42
+ /* @__PURE__ */ jsx(Input, { value: block.imageUrl ?? "", onChange: (e) => patch(block, onChange, { imageUrl: e.target.value }), placeholder: "URL of upload \u2192" }),
43
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url, mediaId) => patch(block, onChange, { imageUrl: url, imageId: mediaId }) })
44
+ ] }) }),
45
+ /* @__PURE__ */ jsx(Field, { label: "Video-achtergrond (mp4/webm, optioneel)", hint: "Overschrijft de afbeelding.", children: /* @__PURE__ */ jsx(Input, { value: block.videoUrl ?? "", onChange: (e) => patch(block, onChange, { videoUrl: e.target.value }) }) }),
46
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
47
+ /* @__PURE__ */ jsx(Field, { label: "Verticale uitlijning", children: /* @__PURE__ */ jsx(
48
+ Select,
49
+ {
50
+ value: block.vAlign ?? "center",
51
+ onValueChange: (v) => patch(block, onChange, { vAlign: v }),
52
+ options: [
53
+ { value: "top", label: "Boven" },
54
+ { value: "center", label: "Midden" },
55
+ { value: "bottom", label: "Onder" }
56
+ ]
57
+ }
58
+ ) }),
59
+ /* @__PURE__ */ jsx(Field, { label: "Hoogte", children: /* @__PURE__ */ jsx(
60
+ Select,
61
+ {
62
+ value: block.minHeight ?? "auto",
63
+ onValueChange: (v) => patch(block, onChange, { minHeight: v }),
64
+ options: [
65
+ { value: "auto", label: "Automatisch" },
66
+ { value: "sm", label: "Klein" },
67
+ { value: "md", label: "Normaal" },
68
+ { value: "lg", label: "Groot" },
69
+ { value: "full", label: "Volledig scherm" }
70
+ ]
71
+ }
72
+ ) }),
73
+ /* @__PURE__ */ jsx(Field, { label: "Overlay-kleur (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: block.overlayColor ?? "", onChange: (e) => patch(block, onChange, { overlayColor: e.target.value }), placeholder: "#000000" }) }),
74
+ /* @__PURE__ */ jsx(Field, { label: "Overlay-dekking (%)", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.overlayOpacity ?? 0), onChange: (e) => patch(block, onChange, { overlayOpacity: Math.max(0, Math.min(100, Number(e.target.value) || 0)) }) }) }),
75
+ /* @__PURE__ */ jsx(ToggleField, { label: "Gradient-overlay (donker onderaan \u2014 leesbare tekst op foto's)", checked: Boolean(block.overlayGradient), onChange: (v) => patch(block, onChange, { overlayGradient: v }) })
76
+ ] }),
77
+ /* @__PURE__ */ jsxs("div", { children: [
78
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Knoppen" }),
79
+ /* @__PURE__ */ jsx(
80
+ ArrayEditor,
81
+ {
82
+ items: block.buttons ?? [],
83
+ onChange: (buttons) => patch(block, onChange, { buttons }),
84
+ newItem: () => ({ label: "", href: "#", variant: "primary" }),
85
+ addLabel: "+ Knop",
86
+ renderRow: (b, update) => /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
87
+ /* @__PURE__ */ jsx(Input, { value: b.label, placeholder: "Label", onChange: (e) => update({ label: e.target.value }) }),
88
+ /* @__PURE__ */ jsx(Input, { value: b.href, placeholder: "/pad of https://\u2026", onChange: (e) => update({ href: e.target.value }) }),
89
+ /* @__PURE__ */ jsx(Select, { value: b.variant, onValueChange: (v) => update({ variant: v }), options: VARIANT_OPTIONS })
90
+ ] })
91
+ }
92
+ )
93
+ ] })
94
+ ] });
95
+ }
96
+ function RichTextBlockEditor({ block, siteId, onChange }) {
97
+ return /* @__PURE__ */ jsx(Field, { label: "Tekst", children: /* @__PURE__ */ jsx(RichTextEditor, { siteId, value: block.html ?? "", onChange: (html) => patch(block, onChange, { html }) }) });
98
+ }
99
+ function ImageEditor({ block, siteId, onChange }) {
100
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
101
+ /* @__PURE__ */ jsx(Field, { label: "Afbeelding", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
102
+ /* @__PURE__ */ jsx(Input, { value: block.url ?? "", onChange: (e) => patch(block, onChange, { url: e.target.value }), placeholder: "URL of upload \u2192" }),
103
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url, mediaId) => patch(block, onChange, { url, mediaId }) })
104
+ ] }) }),
105
+ /* @__PURE__ */ jsx(Field, { label: "Alt-tekst (toegankelijkheid)", hint: "Beschrijf de afbeelding kort.", children: /* @__PURE__ */ jsx(Input, { value: block.alt ?? "", onChange: (e) => patch(block, onChange, { alt: e.target.value }) }) }),
106
+ /* @__PURE__ */ jsx(Field, { label: "Bijschrift", children: /* @__PURE__ */ jsx(Input, { value: block.caption ?? "", onChange: (e) => patch(block, onChange, { caption: e.target.value }) }) }),
107
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
108
+ /* @__PURE__ */ jsx(Field, { label: "Link (klikbaar)", children: /* @__PURE__ */ jsx(Input, { value: block.href ?? "", onChange: (e) => patch(block, onChange, { href: e.target.value }) }) }),
109
+ /* @__PURE__ */ jsx(Field, { label: "Uitlijning", children: /* @__PURE__ */ jsx(
110
+ Select,
111
+ {
112
+ value: block.align ?? "center",
113
+ onValueChange: (v) => patch(block, onChange, { align: v }),
114
+ options: [
115
+ { value: "left", label: "Links" },
116
+ { value: "center", label: "Midden" },
117
+ { value: "right", label: "Rechts" }
118
+ ]
119
+ }
120
+ ) }),
121
+ /* @__PURE__ */ jsx(Field, { label: "Beeldverhouding", children: /* @__PURE__ */ jsx(
122
+ Select,
123
+ {
124
+ value: block.aspectRatio ?? "auto",
125
+ onValueChange: (v) => patch(block, onChange, { aspectRatio: v }),
126
+ options: [
127
+ { value: "auto", label: "Automatisch" },
128
+ { value: "16/9", label: "16:9" },
129
+ { value: "4/3", label: "4:3" },
130
+ { value: "1/1", label: "1:1" },
131
+ { value: "3/2", label: "3:2" }
132
+ ]
133
+ }
134
+ ) })
135
+ ] })
136
+ ] });
137
+ }
138
+ function CtaEditor({ block, onChange }) {
139
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
140
+ /* @__PURE__ */ jsx(Field, { label: "Titel", children: /* @__PURE__ */ jsx(Input, { value: block.title ?? "", onChange: (e) => patch(block, onChange, { title: e.target.value }) }) }),
141
+ /* @__PURE__ */ jsx(Field, { label: "Tekst", children: /* @__PURE__ */ jsx(Textarea, { rows: 2, value: block.text ?? "", onChange: (e) => patch(block, onChange, { text: e.target.value }) }) }),
142
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
143
+ /* @__PURE__ */ jsx(Field, { label: "Knoptekst", children: /* @__PURE__ */ jsx(Input, { value: block.buttonLabel ?? "", onChange: (e) => patch(block, onChange, { buttonLabel: e.target.value }) }) }),
144
+ /* @__PURE__ */ jsx(Field, { label: "Knoplink", children: /* @__PURE__ */ jsx(Input, { value: block.buttonHref ?? "", onChange: (e) => patch(block, onChange, { buttonHref: e.target.value }) }) }),
145
+ /* @__PURE__ */ jsx(Field, { label: "Knopstijl", children: /* @__PURE__ */ jsx(Select, { value: block.buttonVariant ?? "primary", onValueChange: (v) => patch(block, onChange, { buttonVariant: v }), options: VARIANT_OPTIONS }) }),
146
+ /* @__PURE__ */ jsx(Field, { label: "Achtergrondkleur (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: block.backgroundColor ?? "", onChange: (e) => patch(block, onChange, { backgroundColor: e.target.value }), placeholder: "#f8fafc" }) }),
147
+ /* @__PURE__ */ jsx(Field, { label: "Tweede knop \u2014 tekst (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: block.button2Label ?? "", onChange: (e) => patch(block, onChange, { button2Label: e.target.value }) }) }),
148
+ /* @__PURE__ */ jsx(Field, { label: "Tweede knop \u2014 link", children: /* @__PURE__ */ jsx(Input, { value: block.button2Href ?? "", onChange: (e) => patch(block, onChange, { button2Href: e.target.value }) }) })
149
+ ] }),
150
+ /* @__PURE__ */ jsx(Field, { label: "Weergave", children: /* @__PURE__ */ jsx(
151
+ Select,
152
+ {
153
+ value: block.sticky ? "sticky" : "section",
154
+ onValueChange: (v) => patch(block, onChange, { sticky: v === "sticky" }),
155
+ options: [
156
+ { value: "section", label: "Sectie in de pagina" },
157
+ { value: "sticky", label: "Vaste balk onderaan (sticky)" }
158
+ ]
159
+ }
160
+ ) })
161
+ ] });
162
+ }
163
+ function FaqEditor({ block, siteId, onChange }) {
164
+ const items = block.items ?? [];
165
+ const set = (next) => patch(block, onChange, { items: next });
166
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
167
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
168
+ /* @__PURE__ */ jsx(ToggleField, { label: "Items standaard open tonen", checked: block.defaultOpen === true, onChange: (v) => patch(block, onChange, { defaultOpen: v }) }),
169
+ items.map((it, i) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2 rounded-lg border border-slate-200 p-3", children: [
170
+ /* @__PURE__ */ jsx(Field, { label: `Vraag ${i + 1}`, children: /* @__PURE__ */ jsx(Input, { value: it.q ?? "", onChange: (e) => set(items.map((x, j) => j === i ? { ...x, q: e.target.value } : x)) }) }),
171
+ it.aHtml !== void 0 ? /* @__PURE__ */ jsx(Field, { label: "Antwoord (met opmaak)", children: /* @__PURE__ */ jsx(RichTextEditor, { siteId, value: it.aHtml, onChange: (html) => set(items.map((x, j) => j === i ? { ...x, aHtml: html } : x)) }) }) : /* @__PURE__ */ jsx(Field, { label: "Antwoord", children: /* @__PURE__ */ jsx(Textarea, { rows: 2, value: it.a ?? "", onChange: (e) => set(items.map((x, j) => j === i ? { ...x, a: e.target.value } : x)) }) }),
172
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
173
+ it.aHtml === void 0 ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => set(items.map((x, j) => j === i ? { ...x, aHtml: x.a ? `<p>${x.a}</p>` : "<p></p>" } : x)), children: "Opmaak gebruiken" }) : /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => set(items.map((x, j) => j === i ? { q: x.q, a: x.a } : x)), children: "Terug naar platte tekst" }),
174
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => set(items.filter((_, j) => j !== i)), children: "Verwijderen" })
175
+ ] })
176
+ ] }, i)),
177
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => set([...items, { q: "", a: "" }]), children: "+ Vraag toevoegen" }) })
178
+ ] });
179
+ }
180
+ function OpeningHoursEditor({ block, onChange }) {
181
+ const rows = block.rows ?? [];
182
+ const set = (next) => patch(block, onChange, { rows: next });
183
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
184
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
185
+ rows.map((r, i) => /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[1fr_1fr_auto] items-end gap-2", children: [
186
+ /* @__PURE__ */ jsx(Field, { label: "Dag(en)", children: /* @__PURE__ */ jsx(Input, { value: r.day ?? "", onChange: (e) => set(rows.map((x, j) => j === i ? { ...x, day: e.target.value } : x)) }) }),
187
+ /* @__PURE__ */ jsx(Field, { label: "Tijden", children: /* @__PURE__ */ jsx(Input, { value: r.hours ?? "", onChange: (e) => set(rows.map((x, j) => j === i ? { ...x, hours: e.target.value } : x)) }) }),
188
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => set(rows.filter((_, j) => j !== i)), children: "\u2715" })
189
+ ] }, i)),
190
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => set([...rows, { day: "", hours: "" }]), children: "+ Rij toevoegen" }) }),
191
+ /* @__PURE__ */ jsx(ToggleField, { label: "'Nu geopend'-badge", checked: Boolean(block.showStatus), onChange: (v) => patch(block, onChange, { showStatus: v }) }),
192
+ /* @__PURE__ */ jsx(ToggleField, { label: "JSON-LD (openingstijden voor Google)", checked: Boolean(block.jsonLd), onChange: (v) => patch(block, onChange, { jsonLd: v }) })
193
+ ] });
194
+ }
195
+ function PricingEditor({ block, onChange }) {
196
+ const items = block.items ?? [];
197
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
198
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
199
+ /* @__PURE__ */ jsx(
200
+ ArrayEditor,
201
+ {
202
+ items,
203
+ onChange: (next) => patch(block, onChange, { items: next }),
204
+ newItem: () => ({ label: "", price: "", features: [], highlighted: false }),
205
+ addLabel: "+ Pakket",
206
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
207
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
208
+ /* @__PURE__ */ jsx(Input, { value: it.label, placeholder: "Naam", onChange: (e) => update({ label: e.target.value }) }),
209
+ /* @__PURE__ */ jsx(Input, { value: it.price, placeholder: "\u20AC 00", onChange: (e) => update({ price: e.target.value }) }),
210
+ /* @__PURE__ */ jsx(Input, { value: it.billingPeriod ?? "", placeholder: "/maand", onChange: (e) => update({ billingPeriod: e.target.value }) })
211
+ ] }),
212
+ /* @__PURE__ */ jsx(Input, { value: it.detail ?? "", placeholder: "Korte omschrijving", onChange: (e) => update({ detail: e.target.value }) }),
213
+ /* @__PURE__ */ jsx(Field, { label: "Features (\xE9\xE9n per regel)", children: /* @__PURE__ */ jsx(
214
+ Textarea,
215
+ {
216
+ rows: 3,
217
+ value: (it.features ?? []).join("\n"),
218
+ onChange: (e) => update({ features: e.target.value.split("\n").map((s) => s.trim()).filter(Boolean) })
219
+ }
220
+ ) }),
221
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
222
+ /* @__PURE__ */ jsx(Input, { value: it.ctaLabel ?? "", placeholder: "Knoptekst", onChange: (e) => update({ ctaLabel: e.target.value }) }),
223
+ /* @__PURE__ */ jsx(Input, { value: it.ctaHref ?? "", placeholder: "Knoplink", onChange: (e) => update({ ctaHref: e.target.value }) })
224
+ ] }),
225
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm", children: [
226
+ /* @__PURE__ */ jsx("input", { type: "checkbox", checked: Boolean(it.highlighted), onChange: (e) => update({ highlighted: e.target.checked }) }),
227
+ "Uitgelicht pakket"
228
+ ] })
229
+ ] })
230
+ }
231
+ ),
232
+ /* @__PURE__ */ jsx(Field, { label: "Voetnoot (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: block.note ?? "", onChange: (e) => patch(block, onChange, { note: e.target.value }) }) }),
233
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 items-end gap-2", children: [
234
+ /* @__PURE__ */ jsx(Field, { label: "Valuta", hint: "ISO-code voor zoekmachines, bv. EUR", children: /* @__PURE__ */ jsx(Input, { value: block.currency ?? "EUR", onChange: (e) => patch(block, onChange, { currency: e.target.value || "EUR" }) }) }),
235
+ /* @__PURE__ */ jsx(ToggleField, { label: "JSON-LD (Product/Offer)", checked: Boolean(block.jsonLd), onChange: (v) => patch(block, onChange, { jsonLd: v }) })
236
+ ] })
237
+ ] });
238
+ }
239
+ function NewsListEditor({ block, onChange }) {
240
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
241
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
242
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-3", children: [
243
+ /* @__PURE__ */ jsx(Field, { label: "Per pagina", hint: "0 = alles ineens; anders 'Meer laden'-knop", children: /* @__PURE__ */ jsx(
244
+ Input,
245
+ {
246
+ type: "number",
247
+ value: String(block.pageSize ?? 0),
248
+ onChange: (e) => patch(block, onChange, { pageSize: Math.max(0, Math.min(24, Number(e.target.value) || 0)) })
249
+ }
250
+ ) }),
251
+ /* @__PURE__ */ jsx(Field, { label: "Aantal", children: /* @__PURE__ */ jsx(
252
+ Input,
253
+ {
254
+ type: "number",
255
+ value: String(block.limit ?? 6),
256
+ onChange: (e) => patch(block, onChange, { limit: Math.max(1, Math.min(50, Number(e.target.value) || 6)) })
257
+ }
258
+ ) }),
259
+ /* @__PURE__ */ jsx(Field, { label: "Basispad", children: /* @__PURE__ */ jsx(Input, { value: block.basePath ?? "/nieuws", onChange: (e) => patch(block, onChange, { basePath: e.target.value }) }) })
260
+ ] })
261
+ ] });
262
+ }
263
+ function FormEditor({ block, siteId, onChange }) {
264
+ const [forms, setForms] = useState([]);
265
+ useEffect(() => {
266
+ const db = getDb();
267
+ if (!db) return;
268
+ let cancelled = false;
269
+ void getDocs(collection(db, "sites", siteId, "forms")).then((snap) => {
270
+ if (!cancelled) setForms(snap.docs.map((d) => ({ id: d.id, name: String(d.data().name ?? d.id) })));
271
+ });
272
+ return () => {
273
+ cancelled = true;
274
+ };
275
+ }, [siteId]);
276
+ const current = block.formId ?? "";
277
+ const missing = current && forms.length > 0 && !forms.some((f) => f.id === current);
278
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
279
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
280
+ /* @__PURE__ */ jsx(Field, { label: "Formulier", hint: "Maak een formulier aan onder het tabblad Formulieren.", children: forms.length > 0 ? /* @__PURE__ */ jsx(
281
+ Select,
282
+ {
283
+ value: current,
284
+ placeholder: "Kies een formulier\u2026",
285
+ onValueChange: (v) => patch(block, onChange, { formId: v }),
286
+ options: forms.map((f) => ({ value: f.id, label: f.name }))
287
+ }
288
+ ) : /* @__PURE__ */ jsx(Input, { value: current, onChange: (e) => patch(block, onChange, { formId: e.target.value }), placeholder: "Formulier-id" }) }),
289
+ missing && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-600", children: "Dit formulier-id bestaat niet (meer). Kies een bestaand formulier." })
290
+ ] });
291
+ }
292
+ function SpacerEditor({ block, onChange }) {
293
+ return /* @__PURE__ */ jsx(Field, { label: "Hoogte", children: /* @__PURE__ */ jsx(
294
+ Select,
295
+ {
296
+ value: block.size ?? "md",
297
+ onValueChange: (v) => patch(block, onChange, { size: v }),
298
+ options: [
299
+ { value: "sm", label: "Klein" },
300
+ { value: "md", label: "Normaal" },
301
+ { value: "lg", label: "Groot" },
302
+ { value: "xl", label: "Extra groot" }
303
+ ]
304
+ }
305
+ ) });
306
+ }
307
+ function GalleryEditor({ block, siteId, onChange }) {
308
+ const items = block.items ?? [];
309
+ const set = (next) => patch(block, onChange, { items: next });
310
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
311
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
312
+ /* @__PURE__ */ jsx(Field, { label: "Kolommen", hint: "0 = volg module-instelling", children: /* @__PURE__ */ jsx(
313
+ Input,
314
+ {
315
+ type: "number",
316
+ value: String(block.columns ?? 0),
317
+ onChange: (e) => patch(block, onChange, { columns: Math.max(0, Math.min(6, Number(e.target.value) || 0)) })
318
+ }
319
+ ) }),
320
+ /* @__PURE__ */ jsx(Field, { label: "Lightbox", children: /* @__PURE__ */ jsx(
321
+ Select,
322
+ {
323
+ value: block.lightbox ?? "inherit",
324
+ onValueChange: (v) => patch(block, onChange, { lightbox: v }),
325
+ options: [
326
+ { value: "inherit", label: "Volg module-instelling" },
327
+ { value: "on", label: "Aan" },
328
+ { value: "off", label: "Uit" }
329
+ ]
330
+ }
331
+ ) }),
332
+ /* @__PURE__ */ jsx(Field, { label: "Beeldverhouding", children: /* @__PURE__ */ jsx(
333
+ Select,
334
+ {
335
+ value: block.aspectRatio ?? "1/1",
336
+ onValueChange: (v) => patch(block, onChange, { aspectRatio: v }),
337
+ options: [
338
+ { value: "1/1", label: "Vierkant (1:1)" },
339
+ { value: "4/3", label: "4:3" },
340
+ { value: "3/2", label: "3:2" },
341
+ { value: "16/9", label: "16:9" },
342
+ { value: "auto", label: "Eigen verhouding" }
343
+ ]
344
+ }
345
+ ) })
346
+ ] }),
347
+ items.map((it, i) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2 rounded-lg border border-slate-200 p-3", children: [
348
+ /* @__PURE__ */ jsx(Field, { label: `Foto ${i + 1}`, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
349
+ /* @__PURE__ */ jsx(Input, { value: it.url ?? "", onChange: (e) => set(items.map((x, j) => j === i ? { ...x, url: e.target.value } : x)), placeholder: "URL of upload \u2192" }),
350
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => set(items.map((x, j) => j === i ? { ...x, url } : x)) })
351
+ ] }) }),
352
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
353
+ /* @__PURE__ */ jsx(Field, { label: "Alt-tekst", children: /* @__PURE__ */ jsx(Input, { value: it.alt ?? "", onChange: (e) => set(items.map((x, j) => j === i ? { ...x, alt: e.target.value } : x)) }) }),
354
+ /* @__PURE__ */ jsx(Field, { label: "Bijschrift", children: /* @__PURE__ */ jsx(Input, { value: it.caption ?? "", onChange: (e) => set(items.map((x, j) => j === i ? { ...x, caption: e.target.value } : x)) }) }),
355
+ /* @__PURE__ */ jsx(Field, { label: "Tag", hint: "Voor de filterbalk", children: /* @__PURE__ */ jsx(Input, { value: it.tag ?? "", onChange: (e) => set(items.map((x, j) => j === i ? { ...x, tag: e.target.value || void 0 } : x)) }) })
356
+ ] }),
357
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => set(items.filter((_, j) => j !== i)), children: "Verwijderen" }) })
358
+ ] }, i)),
359
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => set([...items, { url: "", alt: "" }]), children: "+ Foto toevoegen" }) }),
360
+ /* @__PURE__ */ jsx(ToggleField, { label: "Filterbalk op tags", checked: Boolean(block.showFilter), onChange: (v) => patch(block, onChange, { showFilter: v }) })
361
+ ] });
362
+ }
363
+ function TestimonialsEditor({ block, siteId, onChange }) {
364
+ const items = block.items ?? [];
365
+ const set = (next) => patch(block, onChange, { items: next });
366
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
367
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
368
+ items.map((it, i) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2 rounded-lg border border-slate-200 p-3", children: [
369
+ /* @__PURE__ */ jsx(Field, { label: "Quote", children: /* @__PURE__ */ jsx(Textarea, { rows: 2, value: it.quote ?? "", onChange: (e) => set(items.map((x, j) => j === i ? { ...x, quote: e.target.value } : x)) }) }),
370
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
371
+ /* @__PURE__ */ jsx(Field, { label: "Naam", children: /* @__PURE__ */ jsx(Input, { value: it.author ?? "", onChange: (e) => set(items.map((x, j) => j === i ? { ...x, author: e.target.value } : x)) }) }),
372
+ /* @__PURE__ */ jsx(Field, { label: "Functie", children: /* @__PURE__ */ jsx(Input, { value: it.role ?? "", onChange: (e) => set(items.map((x, j) => j === i ? { ...x, role: e.target.value } : x)) }) }),
373
+ /* @__PURE__ */ jsx(Field, { label: "Sterren (1-5)", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(it.rating ?? ""), onChange: (e) => set(items.map((x, j) => j === i ? { ...x, rating: e.target.value ? Math.max(1, Math.min(5, Number(e.target.value))) : void 0 } : x)) }) })
374
+ ] }),
375
+ /* @__PURE__ */ jsx(Field, { label: "Avatar", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
376
+ /* @__PURE__ */ jsx(Input, { value: it.avatarUrl ?? "", onChange: (e) => set(items.map((x, j) => j === i ? { ...x, avatarUrl: e.target.value } : x)), placeholder: "URL of upload \u2192" }),
377
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => set(items.map((x, j) => j === i ? { ...x, avatarUrl: url } : x)) })
378
+ ] }) }),
379
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => set(items.filter((_, j) => j !== i)), children: "Verwijderen" }) })
380
+ ] }, i)),
381
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => set([...items, { quote: "", author: "", rating: 5 }]), children: "+ Review toevoegen" }) })
382
+ ] });
383
+ }
384
+ function TeamEditor({ block, siteId, onChange }) {
385
+ const members = block.members ?? [];
386
+ const set = (next) => patch(block, onChange, { members: next });
387
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
388
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
389
+ members.map((m, i) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2 rounded-lg border border-slate-200 p-3", children: [
390
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
391
+ /* @__PURE__ */ jsx(Field, { label: "Naam", children: /* @__PURE__ */ jsx(Input, { value: m.name ?? "", onChange: (e) => set(members.map((x, j) => j === i ? { ...x, name: e.target.value } : x)) }) }),
392
+ /* @__PURE__ */ jsx(Field, { label: "Functie", children: /* @__PURE__ */ jsx(Input, { value: m.role ?? "", onChange: (e) => set(members.map((x, j) => j === i ? { ...x, role: e.target.value } : x)) }) })
393
+ ] }),
394
+ /* @__PURE__ */ jsx(Field, { label: "Foto", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
395
+ /* @__PURE__ */ jsx(Input, { value: m.photoUrl ?? "", onChange: (e) => set(members.map((x, j) => j === i ? { ...x, photoUrl: e.target.value } : x)), placeholder: "URL of upload \u2192" }),
396
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => set(members.map((x, j) => j === i ? { ...x, photoUrl: url } : x)) })
397
+ ] }) }),
398
+ /* @__PURE__ */ jsx(Field, { label: "Bio", children: /* @__PURE__ */ jsx(Textarea, { rows: 2, value: m.bio ?? "", onChange: (e) => set(members.map((x, j) => j === i ? { ...x, bio: e.target.value } : x)) }) }),
399
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
400
+ /* @__PURE__ */ jsx(Field, { label: "E-mail (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: m.email ?? "", onChange: (e) => set(members.map((x, j) => j === i ? { ...x, email: e.target.value } : x)) }) }),
401
+ /* @__PURE__ */ jsx(Field, { label: "Telefoon (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: m.phone ?? "", onChange: (e) => set(members.map((x, j) => j === i ? { ...x, phone: e.target.value } : x)) }) })
402
+ ] }),
403
+ /* @__PURE__ */ jsx(Field, { label: "Social (platform|url, \xE9\xE9n per regel)", children: /* @__PURE__ */ jsx(
404
+ Textarea,
405
+ {
406
+ rows: 2,
407
+ value: (m.social ?? []).map((s) => `${s.platform}|${s.href}`).join("\n"),
408
+ onChange: (e) => set(
409
+ members.map(
410
+ (x, j) => j === i ? {
411
+ ...x,
412
+ social: e.target.value.split("\n").map((line) => line.split("|")).filter((p) => p[0] && p[1]).map(([platform, href]) => ({ platform: platform.trim(), href: href.trim() }))
413
+ } : x
414
+ )
415
+ )
416
+ }
417
+ ) }),
418
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => set(members.filter((_, j) => j !== i)), children: "Verwijderen" }) })
419
+ ] }, i)),
420
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => set([...members, { name: "" }]), children: "+ Lid toevoegen" }) }),
421
+ /* @__PURE__ */ jsx(ToggleField, { label: "Groeperen per afdeling", checked: Boolean(block.groupByDepartment), onChange: (v) => patch(block, onChange, { groupByDepartment: v }) })
422
+ ] });
423
+ }
424
+ function AgendaEditor({ block, onChange }) {
425
+ const events = block.events ?? [];
426
+ const set = (next) => patch(block, onChange, { events: next });
427
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
428
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
429
+ events.map((ev, i) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2 rounded-lg border border-slate-200 p-3", children: [
430
+ /* @__PURE__ */ jsx(Field, { label: "Titel", children: /* @__PURE__ */ jsx(Input, { value: ev.title ?? "", onChange: (e) => set(events.map((x, j) => j === i ? { ...x, title: e.target.value } : x)) }) }),
431
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
432
+ /* @__PURE__ */ jsx(Field, { label: "Start", hint: "bv. 2026-07-01 of 2026-07-01T19:30", children: /* @__PURE__ */ jsx(Input, { value: ev.start ?? "", onChange: (e) => set(events.map((x, j) => j === i ? { ...x, start: e.target.value } : x)) }) }),
433
+ /* @__PURE__ */ jsx(Field, { label: "Einde (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: ev.end ?? "", onChange: (e) => set(events.map((x, j) => j === i ? { ...x, end: e.target.value } : x)) }) })
434
+ ] }),
435
+ /* @__PURE__ */ jsx(Field, { label: "Locatie (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: ev.location ?? "", onChange: (e) => set(events.map((x, j) => j === i ? { ...x, location: e.target.value } : x)) }) }),
436
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => set(events.filter((_, j) => j !== i)), children: "Verwijderen" }) })
437
+ ] }, i)),
438
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => set([...events, { title: "", start: "" }]), children: "+ Evenement toevoegen" }) })
439
+ ] });
440
+ }
441
+ function SearchEditor({ block, onChange }) {
442
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
443
+ /* @__PURE__ */ jsx(Field, { label: "Placeholder", children: /* @__PURE__ */ jsx(Input, { value: block.placeholder ?? "Zoeken\u2026", onChange: (e) => patch(block, onChange, { placeholder: e.target.value }) }) }),
444
+ /* @__PURE__ */ jsx(Field, { label: "Nieuws meenemen", children: /* @__PURE__ */ jsx(
445
+ Select,
446
+ {
447
+ value: block.includeNews === false ? "no" : "yes",
448
+ onValueChange: (v) => patch(block, onChange, { includeNews: v === "yes" }),
449
+ options: [
450
+ { value: "yes", label: "Ja, ook nieuwsartikelen" },
451
+ { value: "no", label: "Nee, alleen pagina's" }
452
+ ]
453
+ }
454
+ ) })
455
+ ] });
456
+ }
457
+ function HeadingField({ block, onChange }) {
458
+ return /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) });
459
+ }
460
+ function ToggleField({ label, checked, onChange }) {
461
+ return /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm", children: [
462
+ /* @__PURE__ */ jsx(Switch, { checked, onCheckedChange: onChange }),
463
+ label
464
+ ] });
465
+ }
466
+ function FeatureEditor({ block, siteId, onChange }) {
467
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
468
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
469
+ /* @__PURE__ */ jsx(Field, { label: "Tekst", children: /* @__PURE__ */ jsx(RichTextEditor, { siteId, value: block.html ?? "", onChange: (html) => patch(block, onChange, { html }) }) }),
470
+ /* @__PURE__ */ jsx(Field, { label: "Afbeelding", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
471
+ /* @__PURE__ */ jsx(Input, { value: block.imageUrl ?? "", onChange: (e) => patch(block, onChange, { imageUrl: e.target.value }), placeholder: "URL of upload \u2192" }),
472
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => patch(block, onChange, { imageUrl: url }) })
473
+ ] }) }),
474
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
475
+ /* @__PURE__ */ jsx(Field, { label: "Beeldpositie", children: /* @__PURE__ */ jsx(Select, { value: block.imagePosition ?? "left", onValueChange: (v) => patch(block, onChange, { imagePosition: v }), options: [{ value: "left", label: "Links" }, { value: "right", label: "Rechts" }] }) }),
476
+ /* @__PURE__ */ jsx(Field, { label: "Knoptekst", children: /* @__PURE__ */ jsx(Input, { value: block.buttonLabel ?? "", onChange: (e) => patch(block, onChange, { buttonLabel: e.target.value }) }) }),
477
+ /* @__PURE__ */ jsx(Field, { label: "Knoplink", children: /* @__PURE__ */ jsx(Input, { value: block.buttonHref ?? "", onChange: (e) => patch(block, onChange, { buttonHref: e.target.value }) }) })
478
+ ] })
479
+ ] });
480
+ }
481
+ function CountersEditor({ block, siteId, onChange }) {
482
+ const items = block.items ?? [];
483
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
484
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
485
+ /* @__PURE__ */ jsx(
486
+ ArrayEditor,
487
+ {
488
+ items,
489
+ onChange: (next) => patch(block, onChange, { items: next }),
490
+ newItem: () => ({ value: "", label: "" }),
491
+ addLabel: "+ Teller",
492
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-4 gap-2", children: [
493
+ /* @__PURE__ */ jsx(Input, { value: it.prefix ?? "", placeholder: "\xB1", onChange: (e) => update({ prefix: e.target.value }) }),
494
+ /* @__PURE__ */ jsx(Input, { value: it.value, placeholder: "100", onChange: (e) => update({ value: e.target.value }) }),
495
+ /* @__PURE__ */ jsx(Input, { value: it.suffix ?? "", placeholder: "+", onChange: (e) => update({ suffix: e.target.value }) }),
496
+ /* @__PURE__ */ jsx(Input, { value: it.label, placeholder: "Label", onChange: (e) => update({ label: e.target.value }) })
497
+ ] })
498
+ }
499
+ ),
500
+ /* @__PURE__ */ jsx(ToggleField, { label: "Tel-animatie bij scrollen", checked: block.animate !== false, onChange: (v) => patch(block, onChange, { animate: v }) })
501
+ ] });
502
+ }
503
+ function LogosEditor({ block, siteId, onChange }) {
504
+ const items = block.items ?? [];
505
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
506
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
507
+ /* @__PURE__ */ jsx(
508
+ ArrayEditor,
509
+ {
510
+ items,
511
+ onChange: (next) => patch(block, onChange, { items: next }),
512
+ newItem: () => ({ src: "", alt: "" }),
513
+ addLabel: "+ Logo",
514
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
515
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
516
+ /* @__PURE__ */ jsx(Input, { value: it.src, placeholder: "URL of upload \u2192", onChange: (e) => update({ src: e.target.value }) }),
517
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => update({ src: url }) })
518
+ ] }),
519
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
520
+ /* @__PURE__ */ jsx(Input, { value: it.alt, placeholder: "Alt-tekst", onChange: (e) => update({ alt: e.target.value }) }),
521
+ /* @__PURE__ */ jsx(Input, { value: it.href ?? "", placeholder: "Link (optioneel)", onChange: (e) => update({ href: e.target.value }) })
522
+ ] })
523
+ ] })
524
+ }
525
+ ),
526
+ /* @__PURE__ */ jsx(ToggleField, { label: "Logo's in grijstinten", checked: block.grayscale !== false, onChange: (v) => patch(block, onChange, { grayscale: v }) }),
527
+ /* @__PURE__ */ jsx(ToggleField, { label: "Doorlopende band (marquee)", checked: Boolean(block.marquee), onChange: (v) => patch(block, onChange, { marquee: v }) })
528
+ ] });
529
+ }
530
+ function TimelineEditor({ block, siteId, onChange }) {
531
+ const items = block.items ?? [];
532
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
533
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
534
+ /* @__PURE__ */ jsx(
535
+ ArrayEditor,
536
+ {
537
+ items,
538
+ onChange: (next) => patch(block, onChange, { items: next }),
539
+ newItem: () => ({ title: "" }),
540
+ addLabel: "+ Stap",
541
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
542
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[3rem_1fr_1fr] gap-2", children: [
543
+ /* @__PURE__ */ jsx(Input, { value: it.icon ?? "", placeholder: "\u{1F528}", title: "Icoon (emoji)", onChange: (e) => update({ icon: e.target.value || void 0 }) }),
544
+ /* @__PURE__ */ jsx(Input, { value: it.title, placeholder: "Titel", onChange: (e) => update({ title: e.target.value }) }),
545
+ /* @__PURE__ */ jsx(Input, { value: it.date ?? "", placeholder: "Datum/label", onChange: (e) => update({ date: e.target.value }) })
546
+ ] }),
547
+ /* @__PURE__ */ jsx(Textarea, { rows: 2, value: it.text ?? "", placeholder: "Toelichting", onChange: (e) => update({ text: e.target.value }) })
548
+ ] })
549
+ }
550
+ ),
551
+ /* @__PURE__ */ jsx(ToggleField, { label: "Alternerende layout (links/rechts)", checked: Boolean(block.alternate), onChange: (v) => patch(block, onChange, { alternate: v }) })
552
+ ] });
553
+ }
554
+ function VideoEditor({ block, siteId, onChange }) {
555
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
556
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
557
+ /* @__PURE__ */ jsx(Field, { label: "Bron", children: /* @__PURE__ */ jsx(Select, { value: block.provider ?? "youtube", onValueChange: (v) => patch(block, onChange, { provider: v }), options: [{ value: "youtube", label: "YouTube" }, { value: "vimeo", label: "Vimeo" }, { value: "file", label: "MP4/WebM-URL" }] }) }),
558
+ /* @__PURE__ */ jsx(Field, { label: "Id of URL", children: /* @__PURE__ */ jsx(Input, { value: block.src ?? "", onChange: (e) => patch(block, onChange, { src: e.target.value }) }) })
559
+ ] }),
560
+ /* @__PURE__ */ jsx(Field, { label: "Bijschrift (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: block.caption ?? "", onChange: (e) => patch(block, onChange, { caption: e.target.value }) }) }),
561
+ /* @__PURE__ */ jsx(Field, { label: "Voorvertoningsbeeld (optioneel)", children: /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
562
+ /* @__PURE__ */ jsx(Input, { value: block.posterUrl ?? "", onChange: (e) => patch(block, onChange, { posterUrl: e.target.value || void 0 }), placeholder: "URL of upload \u2192" }),
563
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => patch(block, onChange, { posterUrl: url }) })
564
+ ] }) }),
565
+ /* @__PURE__ */ jsx(ToggleField, { label: "Pas tonen na cookie-toestemming", checked: block.consentGated !== false, onChange: (v) => patch(block, onChange, { consentGated: v }) }),
566
+ /* @__PURE__ */ jsx(ToggleField, { label: "Click-to-play (speler laadt pas na klik \u2014 sneller & privacyvriendelijker)", checked: Boolean(block.facade), onChange: (v) => patch(block, onChange, { facade: v }) })
567
+ ] });
568
+ }
569
+ function BannerEditor({ block, onChange }) {
570
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
571
+ /* @__PURE__ */ jsx(Field, { label: "Tekst", children: /* @__PURE__ */ jsx(Input, { value: block.text ?? "", onChange: (e) => patch(block, onChange, { text: e.target.value }) }) }),
572
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
573
+ /* @__PURE__ */ jsx(Field, { label: "Link", children: /* @__PURE__ */ jsx(Input, { value: block.href ?? "", onChange: (e) => patch(block, onChange, { href: e.target.value }) }) }),
574
+ /* @__PURE__ */ jsx(Field, { label: "Linktekst", children: /* @__PURE__ */ jsx(Input, { value: block.linkLabel ?? "", onChange: (e) => patch(block, onChange, { linkLabel: e.target.value }) }) }),
575
+ /* @__PURE__ */ jsx(Field, { label: "Stijl", children: /* @__PURE__ */ jsx(Select, { value: block.tone ?? "info", onValueChange: (v) => patch(block, onChange, { tone: v }), options: [{ value: "info", label: "Info" }, { value: "success", label: "Succes" }, { value: "warning", label: "Waarschuwing" }] }) })
576
+ ] }),
577
+ /* @__PURE__ */ jsx(ToggleField, { label: "Sluitbaar", checked: block.dismissible !== false, onChange: (v) => patch(block, onChange, { dismissible: v }) }),
578
+ block.dismissible !== false && /* @__PURE__ */ jsx(Field, { label: "Versie", hint: "Wijzig (bv. '2') als de tekst verandert \u2014 wie de oude balk wegklikte ziet de nieuwe weer", children: /* @__PURE__ */ jsx(Input, { value: block.dismissVersion ?? "", onChange: (e) => patch(block, onChange, { dismissVersion: e.target.value || void 0 }) }) })
579
+ ] });
580
+ }
581
+ function GeoField({ value, onChange }) {
582
+ const [text, setText] = useState(value ? `${value.lat}, ${value.lng}` : "");
583
+ return /* @__PURE__ */ jsx(Field, { label: "Co\xF6rdinaten (lat, lng)", hint: "bv. 52.0907, 5.1214 \u2014 toont het bedrijf op de juiste plek in Google", children: /* @__PURE__ */ jsx(
584
+ Input,
585
+ {
586
+ value: text,
587
+ placeholder: "52.0907, 5.1214",
588
+ onChange: (e) => {
589
+ setText(e.target.value);
590
+ const m = e.target.value.trim().match(/^(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)$/);
591
+ if (!m) {
592
+ if (e.target.value.trim() === "") onChange(void 0);
593
+ return;
594
+ }
595
+ const lat = Number(m[1]);
596
+ const lng = Number(m[2]);
597
+ if (Math.abs(lat) <= 90 && Math.abs(lng) <= 180) onChange({ lat, lng });
598
+ }
599
+ }
600
+ ) });
601
+ }
602
+ function ContactEditor({ block, siteId, onChange }) {
603
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
604
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
605
+ /* @__PURE__ */ jsx(Field, { label: "Adres", children: /* @__PURE__ */ jsx(Input, { value: block.address ?? "", onChange: (e) => patch(block, onChange, { address: e.target.value }) }) }),
606
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
607
+ /* @__PURE__ */ jsx(Field, { label: "Telefoon", children: /* @__PURE__ */ jsx(Input, { value: block.phone ?? "", onChange: (e) => patch(block, onChange, { phone: e.target.value }) }) }),
608
+ /* @__PURE__ */ jsx(Field, { label: "E-mail", children: /* @__PURE__ */ jsx(Input, { value: block.email ?? "", onChange: (e) => patch(block, onChange, { email: e.target.value }) }) })
609
+ ] }),
610
+ /* @__PURE__ */ jsx(Field, { label: "Openingstijden", children: /* @__PURE__ */ jsx(Input, { value: block.hours ?? "", onChange: (e) => patch(block, onChange, { hours: e.target.value }) }) }),
611
+ /* @__PURE__ */ jsx(
612
+ GeoField,
613
+ {
614
+ value: block.geo,
615
+ onChange: (geo) => patch(block, onChange, { geo })
616
+ }
617
+ ),
618
+ /* @__PURE__ */ jsx(ToggleField, { label: "JSON-LD (LocalBusiness)", checked: Boolean(block.jsonLd), onChange: (v) => patch(block, onChange, { jsonLd: v }) })
619
+ ] });
620
+ }
621
+ function SocialEditor({ block, siteId, onChange }) {
622
+ const items = block.items ?? [];
623
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
624
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
625
+ /* @__PURE__ */ jsx(
626
+ ArrayEditor,
627
+ {
628
+ items,
629
+ onChange: (next) => patch(block, onChange, { items: next }),
630
+ newItem: () => ({ platform: "", href: "" }),
631
+ addLabel: "+ Social-link",
632
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
633
+ /* @__PURE__ */ jsx(Input, { value: it.platform, placeholder: "bv. Instagram", onChange: (e) => update({ platform: e.target.value }) }),
634
+ /* @__PURE__ */ jsx(Input, { value: it.href, placeholder: "https://\u2026", onChange: (e) => update({ href: e.target.value }) })
635
+ ] })
636
+ }
637
+ )
638
+ ] });
639
+ }
640
+ function MapEditor({ block, onChange }) {
641
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
642
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
643
+ /* @__PURE__ */ jsx(Field, { label: "Aanbieder", children: /* @__PURE__ */ jsx(Select, { value: block.provider ?? "osm", onValueChange: (v) => patch(block, onChange, { provider: v }), options: [{ value: "osm", label: "OpenStreetMap (adres)" }, { value: "google", label: "Google (embed-URL)" }] }) }),
644
+ /* @__PURE__ */ jsx(Field, { label: "Hoogte (px)", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.height ?? 360), onChange: (e) => patch(block, onChange, { height: Math.max(150, Math.min(800, Number(e.target.value) || 360)) }) }) })
645
+ ] }),
646
+ /* @__PURE__ */ jsx(Field, { label: block.provider === "google" ? "Embed-URL" : "Adres / zoekterm", children: /* @__PURE__ */ jsx(Input, { value: block.query ?? "", onChange: (e) => patch(block, onChange, { query: e.target.value }) }) }),
647
+ /* @__PURE__ */ jsx(ToggleField, { label: "Pas tonen na cookie-toestemming", checked: block.consentGated !== false, onChange: (v) => patch(block, onChange, { consentGated: v }) })
648
+ ] });
649
+ }
650
+ function NewsletterEditor({ block, siteId, onChange }) {
651
+ const [forms, setForms] = useState([]);
652
+ useEffect(() => {
653
+ const db = getDb();
654
+ if (!db) return;
655
+ let cancelled = false;
656
+ void getDocs(collection(db, "sites", siteId, "forms")).then((snap) => {
657
+ if (!cancelled) setForms(snap.docs.map((d) => ({ id: d.id, name: String(d.data().name ?? d.id) })));
658
+ });
659
+ return () => {
660
+ cancelled = true;
661
+ };
662
+ }, [siteId]);
663
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
664
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
665
+ /* @__PURE__ */ jsx(Field, { label: "Tekst", children: /* @__PURE__ */ jsx(Input, { value: block.text ?? "", onChange: (e) => patch(block, onChange, { text: e.target.value }) }) }),
666
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
667
+ /* @__PURE__ */ jsx(Field, { label: "Knoptekst", children: /* @__PURE__ */ jsx(Input, { value: block.buttonLabel ?? "", onChange: (e) => patch(block, onChange, { buttonLabel: e.target.value }) }) }),
668
+ /* @__PURE__ */ jsx(Field, { label: "Aanmeld-URL (provider)", hint: "bv. Mailchimp form-action", children: /* @__PURE__ */ jsx(Input, { value: block.actionUrl ?? "", onChange: (e) => patch(block, onChange, { actionUrl: e.target.value }) }) })
669
+ ] }),
670
+ !block.actionUrl && /* @__PURE__ */ jsx(Field, { label: "Of: opslaan in XiCMS-formulier", hint: "Maak onder Formulieren een formulier met een 'email'-veld; aanmeldingen verschijnen daar.", children: forms.length > 0 ? /* @__PURE__ */ jsx(
671
+ Select,
672
+ {
673
+ value: block.formId ?? "",
674
+ placeholder: "Kies een formulier\u2026",
675
+ onValueChange: (v) => patch(block, onChange, { formId: v || void 0 }),
676
+ options: forms.map((f) => ({ value: f.id, label: f.name }))
677
+ }
678
+ ) : /* @__PURE__ */ jsx(Input, { value: block.formId ?? "", onChange: (e) => patch(block, onChange, { formId: e.target.value || void 0 }), placeholder: "formulier-id" }) }),
679
+ /* @__PURE__ */ jsx(Field, { label: "AVG-akkoordtekst", hint: "Leeg = geen checkbox; bv. 'Ik ga akkoord met de privacyverklaring'", children: /* @__PURE__ */ jsx(Input, { value: block.consentText ?? "", onChange: (e) => patch(block, onChange, { consentText: e.target.value || void 0 }) }) })
680
+ ] });
681
+ }
682
+ function BookingEditor({ block, siteId, onChange }) {
683
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
684
+ /* @__PURE__ */ jsxs("p", { className: "rounded-md bg-slate-50 p-2 text-xs text-slate-600", children: [
685
+ "Dit blok ",
686
+ /* @__PURE__ */ jsx("strong", { children: "toont een bestaand afsprakensysteem" }),
687
+ " in je pagina (een embed). XiCMS heeft geen eigen agenda. Maak een account bij een boekingsdienst \u2014 bv.",
688
+ " ",
689
+ /* @__PURE__ */ jsx("strong", { children: "Calendly" }),
690
+ ", ",
691
+ /* @__PURE__ */ jsx("strong", { children: "Salonized" }),
692
+ ", ",
693
+ /* @__PURE__ */ jsx("strong", { children: "Treatwell" }),
694
+ ",",
695
+ " ",
696
+ /* @__PURE__ */ jsx("strong", { children: "Acuity" }),
697
+ " of ",
698
+ /* @__PURE__ */ jsx("strong", { children: "SimplyBook" }),
699
+ " \u2014 kopieer daar de \u201Cembed/insluiten\u201D-link en plak die hieronder."
700
+ ] }),
701
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
702
+ /* @__PURE__ */ jsx(Field, { label: "Reserveersysteem", hint: "Kies je aanbieder of 'Eigen embed' voor een vrije link.", children: /* @__PURE__ */ jsx(
703
+ Select,
704
+ {
705
+ value: block.provider ?? "custom",
706
+ onValueChange: (v) => patch(block, onChange, { provider: v }),
707
+ options: [
708
+ { value: "custom", label: "Eigen embed (vrije URL)" },
709
+ { value: "calendly", label: "Calendly" },
710
+ { value: "cal", label: "Cal.com" },
711
+ { value: "formitable", label: "Formitable" },
712
+ { value: "resengo", label: "Resengo" },
713
+ { value: "thefork", label: "TheFork" },
714
+ { value: "treatwell", label: "Treatwell" },
715
+ { value: "salonized", label: "Salonized" },
716
+ { value: "tablebooker", label: "Tablebooker" },
717
+ { value: "bookingkit", label: "bookingkit" }
718
+ ]
719
+ }
720
+ ) }),
721
+ /* @__PURE__ */ jsx(Field, { label: "Embed-URL of account-naam", hint: "Volledige link \xF3f alleen je slug/id \u2014 de provider-keuze bouwt er de juiste embed van.", children: /* @__PURE__ */ jsx(Input, { value: block.embedUrl ?? "", onChange: (e) => patch(block, onChange, { embedUrl: e.target.value }), placeholder: "https://calendly.com/jouw-naam/intake \u2014 of: jouw-naam/intake" }) }),
722
+ /* @__PURE__ */ jsx(Field, { label: "Hoogte (px)", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.height ?? 630), onChange: (e) => patch(block, onChange, { height: Math.max(300, Math.min(1200, Number(e.target.value) || 630)) }) }) }),
723
+ /* @__PURE__ */ jsx(ToggleField, { label: "Pas tonen na cookie-toestemming", checked: block.consentGated !== false, onChange: (v) => patch(block, onChange, { consentGated: v }) })
724
+ ] });
725
+ }
726
+ function ButtonsEditor({ block, onChange }) {
727
+ const items = block.items ?? [];
728
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
729
+ /* @__PURE__ */ jsx(Field, { label: "Uitlijning", children: /* @__PURE__ */ jsx(
730
+ Select,
731
+ {
732
+ value: block.align ?? "left",
733
+ onValueChange: (v) => patch(block, onChange, { align: v }),
734
+ options: [{ value: "left", label: "Links" }, { value: "center", label: "Midden" }, { value: "right", label: "Rechts" }]
735
+ }
736
+ ) }),
737
+ /* @__PURE__ */ jsx(
738
+ ArrayEditor,
739
+ {
740
+ items,
741
+ onChange: (next) => patch(block, onChange, { items: next }),
742
+ newItem: () => ({ label: "", href: "#", variant: "primary" }),
743
+ addLabel: "+ Knop",
744
+ renderRow: (b, update) => /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
745
+ /* @__PURE__ */ jsx(Input, { value: b.label, placeholder: "Label", onChange: (e) => update({ label: e.target.value }) }),
746
+ /* @__PURE__ */ jsx(Input, { value: b.href, placeholder: "/pad of https://\u2026", onChange: (e) => update({ href: e.target.value }) }),
747
+ /* @__PURE__ */ jsx(Select, { value: b.variant, onValueChange: (v) => update({ variant: v }), options: VARIANT_OPTIONS })
748
+ ] })
749
+ }
750
+ )
751
+ ] });
752
+ }
753
+ function QuoteEditor({ block, onChange }) {
754
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
755
+ /* @__PURE__ */ jsx(Field, { label: "Uitspraak", children: /* @__PURE__ */ jsx(Textarea, { rows: 3, value: block.text ?? "", onChange: (e) => patch(block, onChange, { text: e.target.value }) }) }),
756
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
757
+ /* @__PURE__ */ jsx(Field, { label: "Auteur", children: /* @__PURE__ */ jsx(Input, { value: block.author ?? "", onChange: (e) => patch(block, onChange, { author: e.target.value }) }) }),
758
+ /* @__PURE__ */ jsx(Field, { label: "Functie", children: /* @__PURE__ */ jsx(Input, { value: block.role ?? "", onChange: (e) => patch(block, onChange, { role: e.target.value }) }) })
759
+ ] })
760
+ ] });
761
+ }
762
+ function DividerEditor({ block, onChange }) {
763
+ return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
764
+ /* @__PURE__ */ jsx(Field, { label: "Stijl", children: /* @__PURE__ */ jsx(Select, { value: block.variant ?? "line", onValueChange: (v) => patch(block, onChange, { variant: v }), options: [{ value: "line", label: "Lijn" }, { value: "dots", label: "Stippen" }, { value: "space", label: "Alleen ruimte" }] }) }),
765
+ /* @__PURE__ */ jsx(Field, { label: "Ruimte", children: /* @__PURE__ */ jsx(Select, { value: block.spacing ?? "md", onValueChange: (v) => patch(block, onChange, { spacing: v }), options: [{ value: "sm", label: "Klein" }, { value: "md", label: "Normaal" }, { value: "lg", label: "Groot" }] }) })
766
+ ] });
767
+ }
768
+ function AccordionEditor({ block, siteId, onChange }) {
769
+ const items = block.items ?? [];
770
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
771
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
772
+ /* @__PURE__ */ jsx(
773
+ ArrayEditor,
774
+ {
775
+ items,
776
+ onChange: (next) => patch(block, onChange, { items: next }),
777
+ newItem: () => ({ title: "", body: "" }),
778
+ addLabel: "+ Paneel",
779
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
780
+ /* @__PURE__ */ jsx(Input, { value: it.title, placeholder: "Titel", onChange: (e) => update({ title: e.target.value }) }),
781
+ it.bodyHtml !== void 0 ? /* @__PURE__ */ jsx(RichTextEditor, { siteId, value: it.bodyHtml, onChange: (html) => update({ bodyHtml: html }) }) : /* @__PURE__ */ jsx(Textarea, { rows: 2, value: it.body, placeholder: "Inhoud", onChange: (e) => update({ body: e.target.value }) }),
782
+ /* @__PURE__ */ jsx("div", { children: it.bodyHtml === void 0 ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => update({ bodyHtml: it.body ? `<p>${it.body}</p>` : "<p></p>" }), children: "Opmaak gebruiken" }) : /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => update({ bodyHtml: void 0 }), children: "Terug naar platte tekst" }) })
783
+ ] })
784
+ }
785
+ ),
786
+ /* @__PURE__ */ jsx(ToggleField, { label: "Meerdere tegelijk open", checked: Boolean(block.multiple), onChange: (v) => patch(block, onChange, { multiple: v }) })
787
+ ] });
788
+ }
789
+ function EmbedEditor({ block, onChange }) {
790
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
791
+ /* @__PURE__ */ jsx(Field, { label: "URL (iframe)", children: /* @__PURE__ */ jsx(Input, { value: block.url ?? "", onChange: (e) => patch(block, onChange, { url: e.target.value }) }) }),
792
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
793
+ /* @__PURE__ */ jsx(Field, { label: "Titel (toegankelijkheid)", children: /* @__PURE__ */ jsx(Input, { value: block.title ?? "", onChange: (e) => patch(block, onChange, { title: e.target.value }) }) }),
794
+ /* @__PURE__ */ jsx(Field, { label: "Hoogte (px)", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.height ?? 420), onChange: (e) => patch(block, onChange, { height: Math.max(150, Math.min(1200, Number(e.target.value) || 420)) }) }) })
795
+ ] }),
796
+ /* @__PURE__ */ jsx(Field, { label: "Beeldverhouding", hint: "'Vaste hoogte' gebruikt het hoogte-veld", children: /* @__PURE__ */ jsx(
797
+ Select,
798
+ {
799
+ value: block.aspectRatio ?? "fixed",
800
+ onValueChange: (v) => patch(block, onChange, { aspectRatio: v }),
801
+ options: [
802
+ { value: "fixed", label: "Vaste hoogte" },
803
+ { value: "16/9", label: "16:9" },
804
+ { value: "4/3", label: "4:3" },
805
+ { value: "1/1", label: "Vierkant" }
806
+ ]
807
+ }
808
+ ) }),
809
+ /* @__PURE__ */ jsx(ToggleField, { label: "Pas tonen na cookie-toestemming", checked: block.consentGated !== false, onChange: (v) => patch(block, onChange, { consentGated: v }) })
810
+ ] });
811
+ }
812
+ function nestKey() {
813
+ return (globalThis.crypto?.randomUUID?.() ?? `b${Date.now()}${Math.random()}`).slice(0, 12);
814
+ }
815
+ function NestedBlocksEditor({
816
+ blocks,
817
+ siteId,
818
+ onChange,
819
+ addLabel = "+ Blok toevoegen\u2026"
820
+ }) {
821
+ const registry = useRegistry();
822
+ const [openKey, setOpenKey] = useState(null);
823
+ const list = blocks ?? [];
824
+ const addOptions = [...registry.values()].map((d) => ({ value: d.type, label: `${d.icon ?? "\u25AB"} ${d.label}` }));
825
+ function add(type) {
826
+ const def = registry.get(type);
827
+ const base = def?.defaults?.() ?? {};
828
+ const b = { _key: nestKey(), _type: type, ...base };
829
+ onChange([...list, b]);
830
+ setOpenKey(b._key);
831
+ }
832
+ function move(i, dir) {
833
+ const j = i + dir;
834
+ if (j < 0 || j >= list.length) return;
835
+ const copy = [...list];
836
+ [copy[i], copy[j]] = [copy[j], copy[i]];
837
+ onChange(copy);
838
+ }
839
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
840
+ list.map((b, i) => {
841
+ const type = b._type;
842
+ const def = registry.get(type);
843
+ const Editor = def?.Editor ?? builtinBlockEditors[type] ?? GenericEditor;
844
+ const open = openKey === b._key;
845
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-slate-200 bg-white", children: [
846
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5", children: [
847
+ /* @__PURE__ */ jsxs(
848
+ "button",
849
+ {
850
+ type: "button",
851
+ className: "flex-1 truncate text-left text-sm",
852
+ onClick: () => setOpenKey(open ? null : b._key),
853
+ children: [
854
+ /* @__PURE__ */ jsx("span", { className: "mr-1", children: def?.icon ?? "\u25AB" }),
855
+ def?.label ?? type
856
+ ]
857
+ }
858
+ ),
859
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => move(i, -1), "aria-label": "Omhoog", children: "\u2191" }),
860
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => move(i, 1), "aria-label": "Omlaag", children: "\u2193" }),
861
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onChange(list.filter((_, j) => j !== i)), "aria-label": "Verwijderen", children: "\u{1F5D1}" })
862
+ ] }),
863
+ open && /* @__PURE__ */ jsx("div", { className: "border-t border-slate-100 p-2", children: /* @__PURE__ */ jsx(Editor, { block: b, siteId, onChange: (next) => onChange(list.map((x, j) => j === i ? next : x)) }) })
864
+ ] }, b._key ?? i);
865
+ }),
866
+ list.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-slate-400", children: "Nog geen blokken." }),
867
+ /* @__PURE__ */ jsx(Select, { value: "", placeholder: addLabel, onValueChange: (v) => v && add(v), options: addOptions })
868
+ ] });
869
+ }
870
+ function ColumnsEditor({ block, siteId, onChange }) {
871
+ const cols = block.columns ?? [];
872
+ const set = (next) => patch(block, onChange, { columns: next });
873
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
874
+ cols.map((c, i) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2 rounded-lg border border-slate-200 p-2", children: [
875
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
876
+ /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-slate-500", children: [
877
+ "Kolom ",
878
+ i + 1
879
+ ] }),
880
+ cols.length > 1 && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => set(cols.filter((_, j) => j !== i)), children: "Kolom weg" })
881
+ ] }),
882
+ /* @__PURE__ */ jsx(
883
+ NestedBlocksEditor,
884
+ {
885
+ blocks: c.blocks ?? [],
886
+ siteId,
887
+ onChange: (next) => set(cols.map((x, j) => j === i ? { ...x, blocks: next } : x))
888
+ }
889
+ )
890
+ ] }, i)),
891
+ cols.length < 4 && /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => set([...cols, { blocks: [] }]), children: "+ Kolom toevoegen" })
892
+ ] });
893
+ }
894
+ function WithSidebarEditor({ block, siteId, onChange }) {
895
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
896
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
897
+ /* @__PURE__ */ jsx(Field, { label: "Zijbalk", children: /* @__PURE__ */ jsx(
898
+ Select,
899
+ {
900
+ value: block.side ?? "right",
901
+ onValueChange: (v) => patch(block, onChange, { side: v }),
902
+ options: [{ value: "right", label: "Rechts" }, { value: "left", label: "Links" }]
903
+ }
904
+ ) }),
905
+ /* @__PURE__ */ jsx(Field, { label: "Breedte", children: /* @__PURE__ */ jsx(
906
+ Select,
907
+ {
908
+ value: block.sidebarWidth ?? "md",
909
+ onValueChange: (v) => patch(block, onChange, { sidebarWidth: v }),
910
+ options: [{ value: "sm", label: "Smal" }, { value: "md", label: "Normaal" }, { value: "lg", label: "Breed" }]
911
+ }
912
+ ) }),
913
+ /* @__PURE__ */ jsx(Field, { label: "Meescrollen", children: /* @__PURE__ */ jsx(
914
+ Select,
915
+ {
916
+ value: block.sticky === false ? "no" : "yes",
917
+ onValueChange: (v) => patch(block, onChange, { sticky: v === "yes" }),
918
+ options: [{ value: "yes", label: "Sticky" }, { value: "no", label: "Nee" }]
919
+ }
920
+ ) })
921
+ ] }),
922
+ /* @__PURE__ */ jsx(Field, { label: "Hoofdinhoud", children: /* @__PURE__ */ jsx(
923
+ NestedBlocksEditor,
924
+ {
925
+ blocks: block.main ?? [],
926
+ siteId,
927
+ onChange: (next) => patch(block, onChange, { main: next })
928
+ }
929
+ ) }),
930
+ /* @__PURE__ */ jsx(Field, { label: "Zijbalk (widgets)", hint: "Plaats hier compacte widgets: laatste nieuws, agenda, contact\u2026", children: /* @__PURE__ */ jsx(
931
+ NestedBlocksEditor,
932
+ {
933
+ blocks: block.aside ?? [],
934
+ siteId,
935
+ onChange: (next) => patch(block, onChange, { aside: next }),
936
+ addLabel: "+ Widget/blok toevoegen\u2026"
937
+ }
938
+ ) })
939
+ ] });
940
+ }
941
+ function TabsEditor({ block, siteId, onChange }) {
942
+ const tabs = block.tabs ?? [];
943
+ const set = (next) => patch(block, onChange, { tabs: next });
944
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
945
+ tabs.map((t, i) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2 rounded-lg border border-slate-200 p-2", children: [
946
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
947
+ /* @__PURE__ */ jsx(Input, { value: t.label, placeholder: `Tab ${i + 1}`, onChange: (e) => set(tabs.map((x, j) => j === i ? { ...x, label: e.target.value } : x)) }),
948
+ tabs.length > 1 && /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => set(tabs.filter((_, j) => j !== i)), children: "\u{1F5D1}" })
949
+ ] }),
950
+ /* @__PURE__ */ jsx(
951
+ NestedBlocksEditor,
952
+ {
953
+ blocks: t.blocks ?? [],
954
+ siteId,
955
+ onChange: (next) => set(tabs.map((x, j) => j === i ? { ...x, blocks: next } : x))
956
+ }
957
+ )
958
+ ] }, i)),
959
+ tabs.length < 10 && /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", size: "sm", onClick: () => set([...tabs, { label: `Tab ${tabs.length + 1}`, blocks: [] }]), children: "+ Tab toevoegen" })
960
+ ] });
961
+ }
962
+ function CardsEditor({ block, siteId, onChange }) {
963
+ const items = block.items ?? [];
964
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
965
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
966
+ /* @__PURE__ */ jsx(Field, { label: "Intro (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: block.intro ?? "", onChange: (e) => patch(block, onChange, { intro: e.target.value }) }) }),
967
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
968
+ /* @__PURE__ */ jsx(Field, { label: "Kolommen", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.columns ?? 3), onChange: (e) => patch(block, onChange, { columns: Math.max(1, Math.min(4, Number(e.target.value) || 3)) }) }) }),
969
+ /* @__PURE__ */ jsx(Field, { label: "Beeldstijl", hint: "cover = beeld tot de kaartranden", children: /* @__PURE__ */ jsx(
970
+ Select,
971
+ {
972
+ value: block.imageStyle ?? "inset",
973
+ onValueChange: (v) => patch(block, onChange, { imageStyle: v }),
974
+ options: [
975
+ { value: "inset", label: "Ingekaderd" },
976
+ { value: "cover", label: "Edge-to-edge (postkaart)" }
977
+ ]
978
+ }
979
+ ) })
980
+ ] }),
981
+ /* @__PURE__ */ jsx(
982
+ ArrayEditor,
983
+ {
984
+ items,
985
+ onChange: (next) => patch(block, onChange, { items: next }),
986
+ newItem: () => ({ icon: "", title: "", text: "" }),
987
+ addLabel: "+ Kaart",
988
+ renderRow: (it, update, i) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
989
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
990
+ /* @__PURE__ */ jsx(Field, { label: "Icoon (emoji)", children: /* @__PURE__ */ jsx(Input, { value: it.icon ?? "", onChange: (e) => update({ icon: e.target.value }) }) }),
991
+ /* @__PURE__ */ jsx(Field, { label: "Titel", children: /* @__PURE__ */ jsx(Input, { value: it.title, onChange: (e) => update({ title: e.target.value }) }) })
992
+ ] }),
993
+ /* @__PURE__ */ jsx(Field, { label: "Tekst", children: /* @__PURE__ */ jsx(Textarea, { rows: 2, value: it.text ?? "", onChange: (e) => update({ text: e.target.value }) }) }),
994
+ /* @__PURE__ */ jsx(Field, { label: "Afbeelding (optioneel)", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
995
+ /* @__PURE__ */ jsx(Input, { value: it.imageUrl ?? "", onChange: (e) => update({ imageUrl: e.target.value }), placeholder: "URL of upload \u2192" }),
996
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => update({ imageUrl: url }) }, i)
997
+ ] }) }),
998
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
999
+ /* @__PURE__ */ jsx(Field, { label: "Link (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: it.href ?? "", onChange: (e) => update({ href: e.target.value }) }) }),
1000
+ /* @__PURE__ */ jsx(Field, { label: "Linktekst", children: /* @__PURE__ */ jsx(Input, { value: it.linkLabel ?? "", onChange: (e) => update({ linkLabel: e.target.value }) }) })
1001
+ ] }),
1002
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1.5 text-xs text-slate-600", children: [
1003
+ /* @__PURE__ */ jsx("input", { type: "checkbox", checked: Boolean(it.featured), onChange: (e) => update({ featured: e.target.checked }) }),
1004
+ "Uitgelicht (accentrand)"
1005
+ ] })
1006
+ ] })
1007
+ }
1008
+ )
1009
+ ] });
1010
+ }
1011
+ function DownloadsEditor({ block, siteId, onChange }) {
1012
+ const items = block.items ?? [];
1013
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1014
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
1015
+ /* @__PURE__ */ jsx(
1016
+ ArrayEditor,
1017
+ {
1018
+ items,
1019
+ onChange: (next) => patch(block, onChange, { items: next }),
1020
+ newItem: () => ({ label: "", href: "", meta: "" }),
1021
+ addLabel: "+ Document",
1022
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
1023
+ /* @__PURE__ */ jsx(Input, { value: it.label, placeholder: "Naam (bv. Brochure 2026)", onChange: (e) => update({ label: e.target.value }) }),
1024
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1025
+ /* @__PURE__ */ jsx(Input, { value: it.href, placeholder: "URL naar bestand", onChange: (e) => update({ href: e.target.value }) }),
1026
+ /* @__PURE__ */ jsx(Input, { value: it.meta ?? "", placeholder: "PDF \xB7 1,2 MB", onChange: (e) => update({ meta: e.target.value }) })
1027
+ ] })
1028
+ ] })
1029
+ }
1030
+ )
1031
+ ] });
1032
+ }
1033
+ function PdfEditor({ block, siteId, onChange }) {
1034
+ const docs = block.documents ?? [];
1035
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1036
+ /* @__PURE__ */ jsxs("p", { className: "rounded-md bg-slate-50 p-2 text-xs text-slate-600", children: [
1037
+ "Toon \xE9\xE9n of meer ",
1038
+ /* @__PURE__ */ jsx("strong", { children: "PDF's" }),
1039
+ " (bv. lunch-, diner- en wijnkaart). Bij meerdere verschijnen tabs. Vervang een kaart door simpelweg de URL te wijzigen."
1040
+ ] }),
1041
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
1042
+ /* @__PURE__ */ jsx(
1043
+ ArrayEditor,
1044
+ {
1045
+ items: docs,
1046
+ onChange: (next) => patch(block, onChange, { documents: next }),
1047
+ newItem: () => ({ label: "", url: "" }),
1048
+ addLabel: "+ PDF",
1049
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
1050
+ /* @__PURE__ */ jsx(Input, { value: it.label, placeholder: "Naam (bv. Lunchkaart)", onChange: (e) => update({ label: e.target.value }) }),
1051
+ /* @__PURE__ */ jsx(Input, { value: it.url, placeholder: "URL naar de PDF", onChange: (e) => update({ url: e.target.value }) })
1052
+ ] })
1053
+ }
1054
+ ),
1055
+ /* @__PURE__ */ jsx(Field, { label: "Hoogte (px)", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.height ?? 820), onChange: (e) => patch(block, onChange, { height: Math.max(300, Math.min(1600, Number(e.target.value) || 820)) }) }) }),
1056
+ /* @__PURE__ */ jsx(ToggleField, { label: "Open/Download-link tonen", checked: block.showDownload !== false, onChange: (v) => patch(block, onChange, { showDownload: v }) })
1057
+ ] });
1058
+ }
1059
+ function CountdownEditor({ block, onChange }) {
1060
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1061
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1062
+ /* @__PURE__ */ jsx(Field, { label: "Streefdatum/-tijd", hint: "bv. 2026-12-31T23:59", children: /* @__PURE__ */ jsx(Input, { type: "datetime-local", value: block.target ?? "", onChange: (e) => patch(block, onChange, { target: e.target.value }) }) }),
1063
+ /* @__PURE__ */ jsx(Field, { label: "Tekst als de tijd om is", children: /* @__PURE__ */ jsx(Input, { value: block.expiredText ?? "", onChange: (e) => patch(block, onChange, { expiredText: e.target.value }) }) }),
1064
+ /* @__PURE__ */ jsx(ToggleField, { label: "Labels tonen (dagen/uur/min/sec)", checked: block.showLabels !== false, onChange: (v) => patch(block, onChange, { showLabels: v }) }),
1065
+ /* @__PURE__ */ jsx(Field, { label: "Na afloop", children: /* @__PURE__ */ jsx(
1066
+ Select,
1067
+ {
1068
+ value: block.onExpire ?? "message",
1069
+ onValueChange: (v) => patch(block, onChange, { onExpire: v }),
1070
+ options: [
1071
+ { value: "message", label: "Melding tonen" },
1072
+ { value: "hide", label: "Blok verbergen" }
1073
+ ]
1074
+ }
1075
+ ) })
1076
+ ] });
1077
+ }
1078
+ function SliderEditor({ block, siteId, onChange }) {
1079
+ const slides = block.slides ?? [];
1080
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1081
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1082
+ /* @__PURE__ */ jsx(Field, { label: "Beeldverhouding", children: /* @__PURE__ */ jsx(
1083
+ Select,
1084
+ {
1085
+ value: block.aspectRatio ?? "16/9",
1086
+ onValueChange: (v) => patch(block, onChange, { aspectRatio: v }),
1087
+ options: [
1088
+ { value: "16/9", label: "16:9" },
1089
+ { value: "4/3", label: "4:3" },
1090
+ { value: "3/2", label: "3:2" },
1091
+ { value: "1/1", label: "Vierkant" },
1092
+ { value: "21/9", label: "Breedbeeld" }
1093
+ ]
1094
+ }
1095
+ ) }),
1096
+ /* @__PURE__ */ jsx(Field, { label: "Interval (sec)", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.interval ?? 5), onChange: (e) => patch(block, onChange, { interval: Math.max(2, Math.min(20, Number(e.target.value) || 5)) }) }) })
1097
+ ] }),
1098
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-4", children: [
1099
+ /* @__PURE__ */ jsx(ToggleField, { label: "Automatisch afspelen", checked: Boolean(block.autoplay), onChange: (v) => patch(block, onChange, { autoplay: v }) }),
1100
+ /* @__PURE__ */ jsx(ToggleField, { label: "Stippen", checked: block.showDots !== false, onChange: (v) => patch(block, onChange, { showDots: v }) }),
1101
+ /* @__PURE__ */ jsx(ToggleField, { label: "Pijlen", checked: block.showArrows !== false, onChange: (v) => patch(block, onChange, { showArrows: v }) })
1102
+ ] }),
1103
+ /* @__PURE__ */ jsx(
1104
+ ArrayEditor,
1105
+ {
1106
+ items: slides,
1107
+ onChange: (next) => patch(block, onChange, { slides: next }),
1108
+ newItem: () => ({ imageUrl: "", alt: "", caption: "" }),
1109
+ addLabel: "+ Slide",
1110
+ renderRow: (it, update, i) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
1111
+ /* @__PURE__ */ jsx(Field, { label: `Afbeelding ${i + 1}`, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1112
+ /* @__PURE__ */ jsx(Input, { value: it.imageUrl ?? "", onChange: (e) => update({ imageUrl: e.target.value }), placeholder: "URL of upload \u2192" }),
1113
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => update({ imageUrl: url }) }, i)
1114
+ ] }) }),
1115
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1116
+ /* @__PURE__ */ jsx(Input, { value: it.alt ?? "", placeholder: "Alt-tekst", onChange: (e) => update({ alt: e.target.value }) }),
1117
+ /* @__PURE__ */ jsx(Input, { value: it.href ?? "", placeholder: "Link (optioneel)", onChange: (e) => update({ href: e.target.value }) })
1118
+ ] }),
1119
+ /* @__PURE__ */ jsx(Input, { value: it.caption ?? "", placeholder: "Bijschrift (optioneel)", onChange: (e) => update({ caption: e.target.value }) })
1120
+ ] })
1121
+ }
1122
+ )
1123
+ ] });
1124
+ }
1125
+ function NewsWidgetEditor({ block, onChange }) {
1126
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1127
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1128
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1129
+ /* @__PURE__ */ jsx(Field, { label: "Aantal", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.limit ?? 5), onChange: (e) => patch(block, onChange, { limit: Math.max(1, Math.min(12, Number(e.target.value) || 5)) }) }) }),
1130
+ /* @__PURE__ */ jsx(Field, { label: "Basispad", children: /* @__PURE__ */ jsx(Input, { value: block.basePath ?? "/nieuws", onChange: (e) => patch(block, onChange, { basePath: e.target.value }) }) })
1131
+ ] }),
1132
+ /* @__PURE__ */ jsx(ToggleField, { label: "Miniaturen tonen", checked: Boolean(block.showImages), onChange: (v) => patch(block, onChange, { showImages: v }) })
1133
+ ] });
1134
+ }
1135
+ function AgendaWidgetEditor({ block, onChange }) {
1136
+ const events = block.events ?? [];
1137
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1138
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1139
+ /* @__PURE__ */ jsx(Field, { label: "Aantal", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.limit ?? 5), onChange: (e) => patch(block, onChange, { limit: Math.max(1, Math.min(12, Number(e.target.value) || 5)) }) }) }),
1140
+ /* @__PURE__ */ jsx(
1141
+ ArrayEditor,
1142
+ {
1143
+ items: events,
1144
+ onChange: (next) => patch(block, onChange, { events: next }),
1145
+ newItem: () => ({ title: "", start: "" }),
1146
+ addLabel: "+ Evenement",
1147
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
1148
+ /* @__PURE__ */ jsx(Input, { value: it.title, placeholder: "Titel", onChange: (e) => update({ title: e.target.value }) }),
1149
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1150
+ /* @__PURE__ */ jsx(Input, { value: it.start, placeholder: "2026-07-01T19:30", onChange: (e) => update({ start: e.target.value }) }),
1151
+ /* @__PURE__ */ jsx(Input, { value: it.location ?? "", placeholder: "Locatie", onChange: (e) => update({ location: e.target.value }) })
1152
+ ] })
1153
+ ] })
1154
+ }
1155
+ ),
1156
+ /* @__PURE__ */ jsx(ToggleField, { label: "Verlopen evenementen verbergen", checked: block.hidePast !== false, onChange: (v) => patch(block, onChange, { hidePast: v }) })
1157
+ ] });
1158
+ }
1159
+ function OpeningHoursWidgetEditor({ block, onChange }) {
1160
+ const rows = block.rows ?? [];
1161
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1162
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1163
+ /* @__PURE__ */ jsx(
1164
+ ArrayEditor,
1165
+ {
1166
+ items: rows,
1167
+ onChange: (next) => patch(block, onChange, { rows: next }),
1168
+ newItem: () => ({ day: "", hours: "" }),
1169
+ addLabel: "+ Regel",
1170
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1171
+ /* @__PURE__ */ jsx(Input, { value: it.day, placeholder: "Maandag", onChange: (e) => update({ day: e.target.value }) }),
1172
+ /* @__PURE__ */ jsx(Input, { value: it.hours, placeholder: "09:00 \u2013 17:00", onChange: (e) => update({ hours: e.target.value }) })
1173
+ ] })
1174
+ }
1175
+ ),
1176
+ /* @__PURE__ */ jsx(ToggleField, { label: "Vandaag markeren", checked: block.highlightToday !== false, onChange: (v) => patch(block, onChange, { highlightToday: v }) })
1177
+ ] });
1178
+ }
1179
+ function ContactWidgetEditor({ block, onChange }) {
1180
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1181
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1182
+ /* @__PURE__ */ jsx(Field, { label: "Adres", children: /* @__PURE__ */ jsx(Input, { value: block.address ?? "", onChange: (e) => patch(block, onChange, { address: e.target.value }) }) }),
1183
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1184
+ /* @__PURE__ */ jsx(Field, { label: "Telefoon", children: /* @__PURE__ */ jsx(Input, { value: block.phone ?? "", onChange: (e) => patch(block, onChange, { phone: e.target.value }) }) }),
1185
+ /* @__PURE__ */ jsx(Field, { label: "E-mail", children: /* @__PURE__ */ jsx(Input, { value: block.email ?? "", onChange: (e) => patch(block, onChange, { email: e.target.value }) }) })
1186
+ ] })
1187
+ ] });
1188
+ }
1189
+ function SocialWidgetEditor({ block, onChange }) {
1190
+ const items = block.items ?? [];
1191
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1192
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1193
+ /* @__PURE__ */ jsx(
1194
+ ArrayEditor,
1195
+ {
1196
+ items,
1197
+ onChange: (next) => patch(block, onChange, { items: next }),
1198
+ newItem: () => ({ platform: "", href: "" }),
1199
+ addLabel: "+ Link",
1200
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1201
+ /* @__PURE__ */ jsx(Input, { value: it.platform, placeholder: "Instagram", onChange: (e) => update({ platform: e.target.value }) }),
1202
+ /* @__PURE__ */ jsx(Input, { value: it.href, placeholder: "https://\u2026", onChange: (e) => update({ href: e.target.value }) })
1203
+ ] })
1204
+ }
1205
+ )
1206
+ ] });
1207
+ }
1208
+ function NewsletterWidgetEditor({ block, onChange }) {
1209
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1210
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1211
+ /* @__PURE__ */ jsx(Field, { label: "Tekst", children: /* @__PURE__ */ jsx(Input, { value: block.text ?? "", onChange: (e) => patch(block, onChange, { text: e.target.value }) }) }),
1212
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1213
+ /* @__PURE__ */ jsx(Field, { label: "Knoptekst", children: /* @__PURE__ */ jsx(Input, { value: block.buttonLabel ?? "Aanmelden", onChange: (e) => patch(block, onChange, { buttonLabel: e.target.value }) }) }),
1214
+ /* @__PURE__ */ jsx(Field, { label: "Aanmeld-URL", children: /* @__PURE__ */ jsx(Input, { value: block.actionUrl ?? "", onChange: (e) => patch(block, onChange, { actionUrl: e.target.value }) }) })
1215
+ ] })
1216
+ ] });
1217
+ }
1218
+ function CtaWidgetEditor({ block, onChange }) {
1219
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1220
+ /* @__PURE__ */ jsx(Field, { label: "Titel", children: /* @__PURE__ */ jsx(Input, { value: block.title ?? "", onChange: (e) => patch(block, onChange, { title: e.target.value }) }) }),
1221
+ /* @__PURE__ */ jsx(Field, { label: "Tekst", children: /* @__PURE__ */ jsx(Input, { value: block.text ?? "", onChange: (e) => patch(block, onChange, { text: e.target.value }) }) }),
1222
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1223
+ /* @__PURE__ */ jsx(Field, { label: "Knoptekst", children: /* @__PURE__ */ jsx(Input, { value: block.buttonLabel ?? "", onChange: (e) => patch(block, onChange, { buttonLabel: e.target.value }) }) }),
1224
+ /* @__PURE__ */ jsx(Field, { label: "Knoplink", children: /* @__PURE__ */ jsx(Input, { value: block.buttonHref ?? "", onChange: (e) => patch(block, onChange, { buttonHref: e.target.value }) }) })
1225
+ ] }),
1226
+ /* @__PURE__ */ jsx(Field, { label: "Achtergrondkleur (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: block.backgroundColor ?? "", onChange: (e) => patch(block, onChange, { backgroundColor: e.target.value }), placeholder: "#f5f5f5" }) })
1227
+ ] });
1228
+ }
1229
+ function GalleryWidgetEditor({ block, siteId, onChange }) {
1230
+ const items = block.items ?? [];
1231
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1232
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1233
+ /* @__PURE__ */ jsx(Field, { label: "Kolommen", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.columns ?? 3), onChange: (e) => patch(block, onChange, { columns: Math.max(2, Math.min(4, Number(e.target.value) || 3)) }) }) }),
1234
+ /* @__PURE__ */ jsx(
1235
+ ArrayEditor,
1236
+ {
1237
+ items,
1238
+ onChange: (next) => patch(block, onChange, { items: next }),
1239
+ newItem: () => ({ url: "", alt: "" }),
1240
+ addLabel: "+ Foto",
1241
+ renderRow: (it, update, i) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
1242
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1243
+ /* @__PURE__ */ jsx(Input, { value: it.url ?? "", onChange: (e) => update({ url: e.target.value }), placeholder: "URL of upload \u2192" }),
1244
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => update({ url }) }, i)
1245
+ ] }),
1246
+ /* @__PURE__ */ jsx(Input, { value: it.alt ?? "", placeholder: "Alt-tekst", onChange: (e) => update({ alt: e.target.value }) })
1247
+ ] })
1248
+ }
1249
+ )
1250
+ ] });
1251
+ }
1252
+ function TestimonialsWidgetEditor({ block, onChange }) {
1253
+ const items = block.items ?? [];
1254
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1255
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1256
+ /* @__PURE__ */ jsx(
1257
+ ArrayEditor,
1258
+ {
1259
+ items,
1260
+ onChange: (next) => patch(block, onChange, { items: next }),
1261
+ newItem: () => ({ quote: "", author: "" }),
1262
+ addLabel: "+ Review",
1263
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
1264
+ /* @__PURE__ */ jsx(Textarea, { rows: 2, value: it.quote, placeholder: "Citaat", onChange: (e) => update({ quote: e.target.value }) }),
1265
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1266
+ /* @__PURE__ */ jsx(Input, { value: it.author, placeholder: "Naam", onChange: (e) => update({ author: e.target.value }) }),
1267
+ /* @__PURE__ */ jsx(Input, { type: "number", value: String(it.rating ?? ""), placeholder: "Sterren 1-5", onChange: (e) => update({ rating: e.target.value ? Math.max(1, Math.min(5, Number(e.target.value))) : void 0 }) })
1268
+ ] })
1269
+ ] })
1270
+ }
1271
+ )
1272
+ ] });
1273
+ }
1274
+ function CardsWidgetEditor({ block, onChange }) {
1275
+ const items = block.items ?? [];
1276
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1277
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1278
+ /* @__PURE__ */ jsx(
1279
+ ArrayEditor,
1280
+ {
1281
+ items,
1282
+ onChange: (next) => patch(block, onChange, { items: next }),
1283
+ newItem: () => ({ icon: "", title: "", text: "" }),
1284
+ addLabel: "+ Item",
1285
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
1286
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1287
+ /* @__PURE__ */ jsx(Input, { value: it.icon ?? "", placeholder: "Icoon (emoji)", onChange: (e) => update({ icon: e.target.value }) }),
1288
+ /* @__PURE__ */ jsx(Input, { value: it.title, placeholder: "Titel", onChange: (e) => update({ title: e.target.value }) })
1289
+ ] }),
1290
+ /* @__PURE__ */ jsx(Input, { value: it.text ?? "", placeholder: "Korte tekst", onChange: (e) => update({ text: e.target.value }) }),
1291
+ /* @__PURE__ */ jsx(Input, { value: it.href ?? "", placeholder: "Link (optioneel)", onChange: (e) => update({ href: e.target.value }) })
1292
+ ] })
1293
+ }
1294
+ )
1295
+ ] });
1296
+ }
1297
+ function DownloadsWidgetEditor({ block, onChange }) {
1298
+ const items = block.items ?? [];
1299
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1300
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1301
+ /* @__PURE__ */ jsx(Field, { label: "Aantal", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.limit ?? 5), onChange: (e) => patch(block, onChange, { limit: Math.max(1, Math.min(12, Number(e.target.value) || 5)) }) }) }),
1302
+ /* @__PURE__ */ jsx(
1303
+ ArrayEditor,
1304
+ {
1305
+ items,
1306
+ onChange: (next) => patch(block, onChange, { items: next }),
1307
+ newItem: () => ({ label: "", href: "", meta: "" }),
1308
+ addLabel: "+ Document",
1309
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
1310
+ /* @__PURE__ */ jsx(Input, { value: it.label, placeholder: "Naam", onChange: (e) => update({ label: e.target.value }) }),
1311
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1312
+ /* @__PURE__ */ jsx(Input, { value: it.href, placeholder: "URL", onChange: (e) => update({ href: e.target.value }) }),
1313
+ /* @__PURE__ */ jsx(Input, { value: it.meta ?? "", placeholder: "PDF \xB7 1,2 MB", onChange: (e) => update({ meta: e.target.value }) })
1314
+ ] })
1315
+ ] })
1316
+ }
1317
+ )
1318
+ ] });
1319
+ }
1320
+ function CountdownWidgetEditor({ block, onChange }) {
1321
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1322
+ /* @__PURE__ */ jsx(Field, { label: "Kop", children: /* @__PURE__ */ jsx(Input, { value: block.heading ?? "", onChange: (e) => patch(block, onChange, { heading: e.target.value }) }) }),
1323
+ /* @__PURE__ */ jsx(Field, { label: "Streefdatum/-tijd", hint: "bv. 2026-12-31T23:59", children: /* @__PURE__ */ jsx(Input, { type: "datetime-local", value: block.target ?? "", onChange: (e) => patch(block, onChange, { target: e.target.value }) }) }),
1324
+ /* @__PURE__ */ jsx(Field, { label: "Tekst als de tijd om is", children: /* @__PURE__ */ jsx(Input, { value: block.expiredText ?? "", onChange: (e) => patch(block, onChange, { expiredText: e.target.value }) }) })
1325
+ ] });
1326
+ }
1327
+ function GenericEditor({ block, siteId, onChange }) {
1328
+ const registry = useRegistry();
1329
+ const def = registry.get(String(block._type ?? ""));
1330
+ const fields = def ? introspectObjectSchema(def.schema) : [];
1331
+ if (fields.length === 0) {
1332
+ return /* @__PURE__ */ jsx("p", { className: "text-sm text-slate-500", children: "Voor dit bloktype is geen editor beschikbaar." });
1333
+ }
1334
+ return /* @__PURE__ */ jsx("div", { className: "grid gap-3", children: fields.map((f) => {
1335
+ if (f.kind === "boolean") {
1336
+ return /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm", children: [
1337
+ /* @__PURE__ */ jsx(Switch, { checked: Boolean(block[f.key]), onCheckedChange: (v) => patch(block, onChange, { [f.key]: v }) }),
1338
+ f.label
1339
+ ] }, f.key);
1340
+ }
1341
+ if (f.kind === "enum") {
1342
+ return /* @__PURE__ */ jsx(Field, { label: f.label, children: /* @__PURE__ */ jsx(
1343
+ Select,
1344
+ {
1345
+ value: String(block[f.key] ?? f.options?.[0] ?? ""),
1346
+ onValueChange: (v) => patch(block, onChange, { [f.key]: v }),
1347
+ options: (f.options ?? []).map((o) => ({ value: o, label: o }))
1348
+ }
1349
+ ) }, f.key);
1350
+ }
1351
+ if (f.kind === "number") {
1352
+ return /* @__PURE__ */ jsx(Field, { label: f.label, children: /* @__PURE__ */ jsx(
1353
+ Input,
1354
+ {
1355
+ type: "number",
1356
+ value: String(block[f.key] ?? ""),
1357
+ onChange: (e) => patch(block, onChange, { [f.key]: e.target.value === "" ? void 0 : Number(e.target.value) })
1358
+ }
1359
+ ) }, f.key);
1360
+ }
1361
+ if (f.kind === "json") {
1362
+ return /* @__PURE__ */ jsx(GenericJsonField, { field: f, block, onChange }, f.key);
1363
+ }
1364
+ if (f.key === "html") {
1365
+ return /* @__PURE__ */ jsx(Field, { label: "Tekst", children: /* @__PURE__ */ jsx(RichTextEditor, { siteId, value: block.html ?? "", onChange: (html) => patch(block, onChange, { html }) }) }, f.key);
1366
+ }
1367
+ const isImage = /image|photo|foto|logo|cover|avatar/i.test(f.key);
1368
+ if (isImage) {
1369
+ return /* @__PURE__ */ jsx(Field, { label: f.label, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1370
+ /* @__PURE__ */ jsx(Input, { value: String(block[f.key] ?? ""), onChange: (e) => patch(block, onChange, { [f.key]: e.target.value }), placeholder: "URL of kies \u2192" }),
1371
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => patch(block, onChange, { [f.key]: url }) })
1372
+ ] }) }, f.key);
1373
+ }
1374
+ const long = (f.maxLength ?? 0) > 500;
1375
+ return /* @__PURE__ */ jsx(Field, { label: f.label, children: long ? /* @__PURE__ */ jsx(Textarea, { rows: 4, value: String(block[f.key] ?? ""), onChange: (e) => patch(block, onChange, { [f.key]: e.target.value }) }) : /* @__PURE__ */ jsx(Input, { value: String(block[f.key] ?? ""), onChange: (e) => patch(block, onChange, { [f.key]: e.target.value }) }) }, f.key);
1376
+ }) });
1377
+ }
1378
+ function GenericJsonField({
1379
+ field,
1380
+ block,
1381
+ onChange
1382
+ }) {
1383
+ const [text, setText] = useState(() => JSON.stringify(block[field.key] ?? null, null, 2));
1384
+ const [error, setError] = useState(null);
1385
+ const commit = () => {
1386
+ try {
1387
+ const parsed = JSON.parse(text);
1388
+ const res = field.schema.safeParse(parsed);
1389
+ if (!res.success) {
1390
+ setError("Voldoet niet aan het verwachte formaat van dit veld.");
1391
+ return;
1392
+ }
1393
+ setError(null);
1394
+ patch(block, onChange, { [field.key]: res.data });
1395
+ } catch {
1396
+ setError("Geen geldige JSON.");
1397
+ }
1398
+ };
1399
+ return /* @__PURE__ */ jsxs(Field, { label: `${field.label} (JSON)`, hint: "Geavanceerd veld \u2014 wordt gecontroleerd v\xF3\xF3r opslaan.", children: [
1400
+ /* @__PURE__ */ jsx(
1401
+ Textarea,
1402
+ {
1403
+ rows: 6,
1404
+ value: text,
1405
+ onChange: (e) => setText(e.target.value),
1406
+ onBlur: commit,
1407
+ spellCheck: false,
1408
+ className: "font-mono text-xs"
1409
+ }
1410
+ ),
1411
+ error && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-600", children: error })
1412
+ ] });
1413
+ }
1414
+ function WhatsappChatEditor({ block, onChange }) {
1415
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1416
+ /* @__PURE__ */ jsx(Field, { label: "Telefoonnummer (internationaal)", hint: "bv. 31612345678 \u2014 zonder + of spaties mag ook", children: /* @__PURE__ */ jsx(Input, { value: block.phone ?? "", onChange: (e) => patch(block, onChange, { phone: e.target.value }) }) }),
1417
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1418
+ /* @__PURE__ */ jsx(Field, { label: "Label (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: block.label ?? "", onChange: (e) => patch(block, onChange, { label: e.target.value || void 0 }) }) }),
1419
+ /* @__PURE__ */ jsx(Field, { label: "Positie", children: /* @__PURE__ */ jsx(
1420
+ Select,
1421
+ {
1422
+ value: block.position ?? "br",
1423
+ onValueChange: (v) => patch(block, onChange, { position: v }),
1424
+ options: [
1425
+ { value: "br", label: "Rechtsonder" },
1426
+ { value: "bl", label: "Linksonder" }
1427
+ ]
1428
+ }
1429
+ ) })
1430
+ ] }),
1431
+ /* @__PURE__ */ jsx(Field, { label: "Vooringevuld bericht (optioneel)", hint: "Staat alvast in het WhatsApp-venster van de bezoeker", children: /* @__PURE__ */ jsx(Input, { value: block.prefilledText ?? "", onChange: (e) => patch(block, onChange, { prefilledText: e.target.value || void 0 }) }) })
1432
+ ] });
1433
+ }
1434
+ function BeforeAfterEditor({ block, siteId, onChange }) {
1435
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1436
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
1437
+ /* @__PURE__ */ jsx(Field, { label: "Foto v\xF3\xF3r", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1438
+ /* @__PURE__ */ jsx(Input, { value: block.beforeUrl ?? "", onChange: (e) => patch(block, onChange, { beforeUrl: e.target.value }), placeholder: "URL of upload \u2192" }),
1439
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => patch(block, onChange, { beforeUrl: url }) })
1440
+ ] }) }),
1441
+ /* @__PURE__ */ jsx(Field, { label: "Foto n\xE1", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1442
+ /* @__PURE__ */ jsx(Input, { value: block.afterUrl ?? "", onChange: (e) => patch(block, onChange, { afterUrl: e.target.value }), placeholder: "URL of upload \u2192" }),
1443
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => patch(block, onChange, { afterUrl: url }) })
1444
+ ] }) }),
1445
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
1446
+ /* @__PURE__ */ jsx(Field, { label: "Label v\xF3\xF3r", children: /* @__PURE__ */ jsx(Input, { value: block.beforeLabel ?? "Voor", onChange: (e) => patch(block, onChange, { beforeLabel: e.target.value }) }) }),
1447
+ /* @__PURE__ */ jsx(Field, { label: "Label n\xE1", children: /* @__PURE__ */ jsx(Input, { value: block.afterLabel ?? "Na", onChange: (e) => patch(block, onChange, { afterLabel: e.target.value }) }) }),
1448
+ /* @__PURE__ */ jsx(Field, { label: "Beeldverhouding", children: /* @__PURE__ */ jsx(
1449
+ Select,
1450
+ {
1451
+ value: block.aspectRatio ?? "4/3",
1452
+ onValueChange: (v) => patch(block, onChange, { aspectRatio: v }),
1453
+ options: [
1454
+ { value: "16/9", label: "16:9" },
1455
+ { value: "4/3", label: "4:3" },
1456
+ { value: "3/2", label: "3:2" },
1457
+ { value: "1/1", label: "Vierkant" }
1458
+ ]
1459
+ }
1460
+ ) })
1461
+ ] }),
1462
+ /* @__PURE__ */ jsx(Field, { label: "Alt-tekst", children: /* @__PURE__ */ jsx(Input, { value: block.alt ?? "", onChange: (e) => patch(block, onChange, { alt: e.target.value }) }) })
1463
+ ] });
1464
+ }
1465
+ function PortfolioEditor({ block, siteId, onChange }) {
1466
+ const items = block.items ?? [];
1467
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1468
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
1469
+ /* @__PURE__ */ jsx(Field, { label: "Intro (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: block.intro ?? "", onChange: (e) => patch(block, onChange, { intro: e.target.value || void 0 }) }) }),
1470
+ /* @__PURE__ */ jsx(
1471
+ ArrayEditor,
1472
+ {
1473
+ items,
1474
+ onChange: (next) => patch(block, onChange, { items: next }),
1475
+ newItem: () => ({ imageUrl: "", title: "" }),
1476
+ addLabel: "+ Project",
1477
+ renderRow: (it, update, i) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
1478
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1479
+ /* @__PURE__ */ jsx(Input, { value: it.imageUrl, placeholder: "URL of upload \u2192", onChange: (e) => update({ imageUrl: e.target.value }) }),
1480
+ /* @__PURE__ */ jsx(ImageUploadButton, { siteId, onUploaded: (url) => update({ imageUrl: url }) }, i)
1481
+ ] }),
1482
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1483
+ /* @__PURE__ */ jsx(Input, { value: it.title, placeholder: "Titel", onChange: (e) => update({ title: e.target.value }) }),
1484
+ /* @__PURE__ */ jsx(Input, { value: it.category ?? "", placeholder: "Categorie (voor filter)", onChange: (e) => update({ category: e.target.value || void 0 }) })
1485
+ ] }),
1486
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1487
+ /* @__PURE__ */ jsx(Input, { value: it.description ?? "", placeholder: "Korte omschrijving", onChange: (e) => update({ description: e.target.value || void 0 }) }),
1488
+ /* @__PURE__ */ jsx(Input, { value: it.href ?? "", placeholder: "Link (optioneel, i.p.v. lightbox)", onChange: (e) => update({ href: e.target.value || void 0 }) })
1489
+ ] })
1490
+ ] })
1491
+ }
1492
+ ),
1493
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 items-end gap-2", children: [
1494
+ /* @__PURE__ */ jsx(Field, { label: "Kolommen", children: /* @__PURE__ */ jsx(Input, { type: "number", value: String(block.columns ?? 3), onChange: (e) => patch(block, onChange, { columns: Math.max(1, Math.min(4, Number(e.target.value) || 3)) }) }) }),
1495
+ /* @__PURE__ */ jsx(ToggleField, { label: "Filterbalk", checked: block.showFilter !== false, onChange: (v) => patch(block, onChange, { showFilter: v }) }),
1496
+ /* @__PURE__ */ jsx(ToggleField, { label: "Lightbox", checked: block.lightbox !== false, onChange: (v) => patch(block, onChange, { lightbox: v }) })
1497
+ ] })
1498
+ ] });
1499
+ }
1500
+ function JobsEditor({ block, siteId, onChange }) {
1501
+ const items = block.items ?? [];
1502
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1503
+ /* @__PURE__ */ jsx(HeadingField, { block, siteId, onChange }),
1504
+ /* @__PURE__ */ jsx(Field, { label: "Intro (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: block.intro ?? "", onChange: (e) => patch(block, onChange, { intro: e.target.value || void 0 }) }) }),
1505
+ /* @__PURE__ */ jsx(
1506
+ ArrayEditor,
1507
+ {
1508
+ items,
1509
+ onChange: (next) => patch(block, onChange, { items: next }),
1510
+ newItem: () => ({ title: "" }),
1511
+ addLabel: "+ Vacature",
1512
+ renderRow: (it, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
1513
+ /* @__PURE__ */ jsx(Input, { value: it.title, placeholder: "Functietitel", onChange: (e) => update({ title: e.target.value }) }),
1514
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
1515
+ /* @__PURE__ */ jsx(Input, { value: it.employmentType ?? "", placeholder: "Fulltime/Parttime", onChange: (e) => update({ employmentType: e.target.value || void 0 }) }),
1516
+ /* @__PURE__ */ jsx(Input, { value: it.location ?? "", placeholder: "Plaats", onChange: (e) => update({ location: e.target.value || void 0 }) }),
1517
+ /* @__PURE__ */ jsx(Input, { value: it.salary ?? "", placeholder: "Salaris (optioneel)", onChange: (e) => update({ salary: e.target.value || void 0 }) })
1518
+ ] }),
1519
+ /* @__PURE__ */ jsx(Textarea, { rows: 2, value: it.description ?? "", placeholder: "Korte omschrijving", onChange: (e) => update({ description: e.target.value || void 0 }) }),
1520
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
1521
+ /* @__PURE__ */ jsx(Input, { value: it.applyUrl ?? "", placeholder: "Sollicitatielink (optioneel)", onChange: (e) => update({ applyUrl: e.target.value || void 0 }) }),
1522
+ /* @__PURE__ */ jsx(Input, { type: "date", value: it.datePosted ?? "", title: "Plaatsingsdatum (voor Google Jobs)", onChange: (e) => update({ datePosted: e.target.value || void 0 }) })
1523
+ ] })
1524
+ ] })
1525
+ }
1526
+ ),
1527
+ /* @__PURE__ */ jsx(ToggleField, { label: "JSON-LD (Google Jobs)", checked: block.jsonLd !== false, onChange: (v) => patch(block, onChange, { jsonLd: v }) })
1528
+ ] });
1529
+ }
1530
+ function BreadcrumbsEditor({ block, onChange }) {
1531
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
1532
+ /* @__PURE__ */ jsx(Field, { label: "Home-label", children: /* @__PURE__ */ jsx(Input, { value: block.homeLabel ?? "Home", onChange: (e) => patch(block, onChange, { homeLabel: e.target.value }) }) }),
1533
+ /* @__PURE__ */ jsx(ToggleField, { label: "JSON-LD (BreadcrumbList)", checked: block.jsonLd !== false, onChange: (v) => patch(block, onChange, { jsonLd: v }) }),
1534
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-slate-500", children: "Labels worden automatisch afgeleid van de URL (bv. /diensten/tuinaanleg \u2192 Diensten / Tuinaanleg)." })
1535
+ ] });
1536
+ }
1537
+ const builtinBlockEditors = {
1538
+ hero: HeroEditor,
1539
+ richText: RichTextBlockEditor,
1540
+ image: ImageEditor,
1541
+ cta: CtaEditor,
1542
+ faq: FaqEditor,
1543
+ openingHours: OpeningHoursEditor,
1544
+ pricing: PricingEditor,
1545
+ newsList: NewsListEditor,
1546
+ form: FormEditor,
1547
+ spacer: SpacerEditor,
1548
+ gallery: GalleryEditor,
1549
+ testimonials: TestimonialsEditor,
1550
+ team: TeamEditor,
1551
+ agenda: AgendaEditor,
1552
+ search: SearchEditor,
1553
+ feature: FeatureEditor,
1554
+ counters: CountersEditor,
1555
+ logos: LogosEditor,
1556
+ timeline: TimelineEditor,
1557
+ video: VideoEditor,
1558
+ banner: BannerEditor,
1559
+ contact: ContactEditor,
1560
+ social: SocialEditor,
1561
+ map: MapEditor,
1562
+ newsletter: NewsletterEditor,
1563
+ booking: BookingEditor,
1564
+ buttons: ButtonsEditor,
1565
+ quote: QuoteEditor,
1566
+ divider: DividerEditor,
1567
+ accordion: AccordionEditor,
1568
+ embed: EmbedEditor,
1569
+ // Indeling
1570
+ columns: ColumnsEditor,
1571
+ withSidebar: WithSidebarEditor,
1572
+ tabs: TabsEditor,
1573
+ // Nieuwe modules
1574
+ cards: CardsEditor,
1575
+ downloads: DownloadsEditor,
1576
+ pdf: PdfEditor,
1577
+ countdown: CountdownEditor,
1578
+ slider: SliderEditor,
1579
+ whatsappChat: WhatsappChatEditor,
1580
+ beforeAfter: BeforeAfterEditor,
1581
+ portfolio: PortfolioEditor,
1582
+ jobs: JobsEditor,
1583
+ breadcrumbs: BreadcrumbsEditor,
1584
+ // Widgets
1585
+ newsWidget: NewsWidgetEditor,
1586
+ agendaWidget: AgendaWidgetEditor,
1587
+ openingHoursWidget: OpeningHoursWidgetEditor,
1588
+ contactWidget: ContactWidgetEditor,
1589
+ socialWidget: SocialWidgetEditor,
1590
+ newsletterWidget: NewsletterWidgetEditor,
1591
+ ctaWidget: CtaWidgetEditor,
1592
+ galleryWidget: GalleryWidgetEditor,
1593
+ testimonialsWidget: TestimonialsWidgetEditor,
1594
+ cardsWidget: CardsWidgetEditor,
1595
+ downloadsWidget: DownloadsWidgetEditor,
1596
+ countdownWidget: CountdownWidgetEditor
1597
+ };
1598
+ export {
1599
+ GenericEditor,
1600
+ builtinBlockEditors
1601
+ };
1602
+ //# sourceMappingURL=index.js.map