@vamos-ui/react 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (704) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +27 -2
  3. package/dist/blocks/block-heading.d.ts +29 -0
  4. package/dist/blocks/block-heading.js +39 -0
  5. package/dist/blocks/block-image.d.ts +52 -0
  6. package/dist/blocks/block-image.js +48 -0
  7. package/dist/blocks/block-link.d.ts +30 -0
  8. package/dist/blocks/block-link.js +36 -0
  9. package/dist/blocks/create-blocks.d.ts +54 -0
  10. package/dist/blocks/create-blocks.js +52 -0
  11. package/dist/blocks/index.d.ts +55 -0
  12. package/dist/blocks/index.js +59 -0
  13. package/dist/blocks/json-ld.d.ts +18 -0
  14. package/dist/blocks/json-ld.js +44 -0
  15. package/dist/blocks/labels.d.ts +20 -0
  16. package/dist/blocks/labels.js +43 -0
  17. package/dist/blocks/rich-text.d.ts +36 -0
  18. package/dist/blocks/rich-text.js +106 -0
  19. package/dist/blocks/schema/define-block.d.ts +151 -0
  20. package/dist/blocks/schema/define-block.js +120 -0
  21. package/dist/blocks/schema/emphasis.d.ts +17 -0
  22. package/dist/blocks/schema/emphasis.js +69 -0
  23. package/dist/blocks/schema/fields.d.ts +497 -0
  24. package/dist/blocks/schema/fields.js +240 -0
  25. package/dist/blocks/schema/icons.d.ts +2 -0
  26. package/dist/blocks/schema/icons.js +26 -0
  27. package/dist/blocks/schema/index.d.ts +18 -0
  28. package/dist/blocks/schema/index.js +21 -0
  29. package/dist/blocks/schema/lint-types.d.ts +16 -0
  30. package/dist/blocks/schema/lint-types.js +2 -0
  31. package/dist/blocks/schema/lint.d.ts +32 -0
  32. package/dist/blocks/schema/lint.js +164 -0
  33. package/dist/blocks/schema/localize.d.ts +20 -0
  34. package/dist/blocks/schema/localize.js +29 -0
  35. package/dist/blocks/schema/localized.d.ts +25 -0
  36. package/dist/blocks/schema/localized.js +53 -0
  37. package/dist/blocks/schema/migrate.d.ts +24 -0
  38. package/dist/blocks/schema/migrate.js +75 -0
  39. package/dist/blocks/schema/nodes.d.ts +196 -0
  40. package/dist/blocks/schema/nodes.js +78 -0
  41. package/dist/blocks/schema/rich-doc-schema.d.ts +32 -0
  42. package/dist/blocks/schema/rich-doc-schema.js +66 -0
  43. package/dist/blocks/schema/rich-doc.d.ts +90 -0
  44. package/dist/blocks/schema/rich-doc.js +62 -0
  45. package/dist/blocks/schema/safety.d.ts +20 -0
  46. package/dist/blocks/schema/safety.js +49 -0
  47. package/dist/blocks/schema/types.d.ts +172 -0
  48. package/dist/blocks/schema/types.js +3 -0
  49. package/dist/blocks/schema/validate.d.ts +17 -0
  50. package/dist/blocks/schema/validate.js +32 -0
  51. package/dist/blocks/schema/walk.d.ts +22 -0
  52. package/dist/blocks/schema/walk.js +60 -0
  53. package/dist/blocks/section-header.d.ts +38 -0
  54. package/dist/blocks/section-header.js +22 -0
  55. package/dist/blocks/section.d.ts +59 -0
  56. package/dist/blocks/section.js +66 -0
  57. package/dist/blocks/site/_kit-1.d.ts +101 -0
  58. package/dist/blocks/site/_kit-1.js +137 -0
  59. package/dist/blocks/site/_site-icon-1.d.ts +6 -0
  60. package/dist/blocks/site/_site-icon-1.js +15 -0
  61. package/dist/blocks/site/announcement-bar.d.ts +42 -0
  62. package/dist/blocks/site/announcement-bar.js +38 -0
  63. package/dist/blocks/site/announcement-dismiss.d.ts +18 -0
  64. package/dist/blocks/site/announcement-dismiss.js +28 -0
  65. package/dist/blocks/site/article-layout.d.ts +65 -0
  66. package/dist/blocks/site/article-layout.js +88 -0
  67. package/dist/blocks/site/blog-list.d.ts +79 -0
  68. package/dist/blocks/site/blog-list.js +78 -0
  69. package/dist/blocks/site/comparison-table.d.ts +54 -0
  70. package/dist/blocks/site/comparison-table.js +38 -0
  71. package/dist/blocks/site/consent-banner.d.ts +52 -0
  72. package/dist/blocks/site/consent-banner.js +33 -0
  73. package/dist/blocks/site/contact-dock.d.ts +52 -0
  74. package/dist/blocks/site/contact-dock.js +55 -0
  75. package/dist/blocks/site/contact-form.d.ts +60 -0
  76. package/dist/blocks/site/contact-form.js +45 -0
  77. package/dist/blocks/site/cta-booking.d.ts +43 -0
  78. package/dist/blocks/site/cta-booking.js +69 -0
  79. package/dist/blocks/site/cta.d.ts +74 -0
  80. package/dist/blocks/site/cta.js +113 -0
  81. package/dist/blocks/site/embed-facade.d.ts +20 -0
  82. package/dist/blocks/site/embed-facade.js +21 -0
  83. package/dist/blocks/site/faq.d.ts +48 -0
  84. package/dist/blocks/site/faq.js +52 -0
  85. package/dist/blocks/site/feature-grid.d.ts +46 -0
  86. package/dist/blocks/site/feature-grid.js +50 -0
  87. package/dist/blocks/site/feature-tabs.d.ts +22 -0
  88. package/dist/blocks/site/feature-tabs.js +11 -0
  89. package/dist/blocks/site/footer.d.ts +68 -0
  90. package/dist/blocks/site/footer.js +61 -0
  91. package/dist/blocks/site/gallery-section.d.ts +42 -0
  92. package/dist/blocks/site/gallery-section.js +48 -0
  93. package/dist/blocks/site/hero-video.d.ts +15 -0
  94. package/dist/blocks/site/hero-video.js +31 -0
  95. package/dist/blocks/site/hero.d.ts +64 -0
  96. package/dist/blocks/site/hero.js +73 -0
  97. package/dist/blocks/site/logo-strip.d.ts +44 -0
  98. package/dist/blocks/site/logo-strip.js +27 -0
  99. package/dist/blocks/site/map-hours.d.ts +83 -0
  100. package/dist/blocks/site/map-hours.js +125 -0
  101. package/dist/blocks/site/media-text.d.ts +45 -0
  102. package/dist/blocks/site/media-text.js +56 -0
  103. package/dist/blocks/site/menu-list.d.ts +74 -0
  104. package/dist/blocks/site/menu-list.js +84 -0
  105. package/dist/blocks/site/navbar-submenu.d.ts +18 -0
  106. package/dist/blocks/site/navbar-submenu.js +51 -0
  107. package/dist/blocks/site/navbar.d.ts +67 -0
  108. package/dist/blocks/site/navbar.js +64 -0
  109. package/dist/blocks/site/not-found.d.ts +40 -0
  110. package/dist/blocks/site/not-found.js +38 -0
  111. package/dist/blocks/site/page-intro.d.ts +46 -0
  112. package/dist/blocks/site/page-intro.js +44 -0
  113. package/dist/blocks/site/pricing-table.d.ts +67 -0
  114. package/dist/blocks/site/pricing-table.js +83 -0
  115. package/dist/blocks/site/process.d.ts +36 -0
  116. package/dist/blocks/site/process.js +42 -0
  117. package/dist/blocks/site/registry-1.d.ts +720 -0
  118. package/dist/blocks/site/registry-1.js +783 -0
  119. package/dist/blocks/site/registry-2.d.ts +914 -0
  120. package/dist/blocks/site/registry-2.js +563 -0
  121. package/dist/blocks/site/rich-text-section.d.ts +34 -0
  122. package/dist/blocks/site/rich-text-section.js +32 -0
  123. package/dist/blocks/site/shared/brand-icons.d.ts +21 -0
  124. package/dist/blocks/site/shared/brand-icons.js +56 -0
  125. package/dist/blocks/site/shared/consent-gate.d.ts +41 -0
  126. package/dist/blocks/site/shared/consent-gate.js +43 -0
  127. package/dist/blocks/site/shared/consent-island.d.ts +38 -0
  128. package/dist/blocks/site/shared/consent-island.js +63 -0
  129. package/dist/blocks/site/shared/consent.d.ts +49 -0
  130. package/dist/blocks/site/shared/consent.js +130 -0
  131. package/dist/blocks/site/shared/contact-form-island.d.ts +41 -0
  132. package/dist/blocks/site/shared/contact-form-island.js +100 -0
  133. package/dist/blocks/site/shared/copy-link.d.ts +10 -0
  134. package/dist/blocks/site/shared/copy-link.js +25 -0
  135. package/dist/blocks/site/shared/dock-avoid.d.ts +15 -0
  136. package/dist/blocks/site/shared/dock-avoid.js +107 -0
  137. package/dist/blocks/site/shared/dock-hours.d.ts +13 -0
  138. package/dist/blocks/site/shared/dock-hours.js +25 -0
  139. package/dist/blocks/site/shared/gallery-lightbox.d.ts +12 -0
  140. package/dist/blocks/site/shared/gallery-lightbox.js +10 -0
  141. package/dist/blocks/site/shared/island-keys.d.ts +10 -0
  142. package/dist/blocks/site/shared/island-keys.js +44 -0
  143. package/dist/blocks/site/shared/kit-2.d.ts +55 -0
  144. package/dist/blocks/site/shared/kit-2.js +84 -0
  145. package/dist/blocks/site/shared/labels-2.d.ts +209 -0
  146. package/dist/blocks/site/shared/labels-2.js +427 -0
  147. package/dist/blocks/site/shared/open-now.d.ts +22 -0
  148. package/dist/blocks/site/shared/open-now.js +27 -0
  149. package/dist/blocks/site/shared/opening-hours.d.ts +117 -0
  150. package/dist/blocks/site/shared/opening-hours.js +245 -0
  151. package/dist/blocks/site/shared/site-accent.d.ts +48 -0
  152. package/dist/blocks/site/shared/site-accent.js +249 -0
  153. package/dist/blocks/site/shared/site-form.d.ts +79 -0
  154. package/dist/blocks/site/shared/site-form.js +111 -0
  155. package/dist/blocks/site/shared/site-routing.d.ts +54 -0
  156. package/dist/blocks/site/shared/site-routing.js +86 -0
  157. package/dist/blocks/site/shared/testimonials-carousel.d.ts +17 -0
  158. package/dist/blocks/site/shared/testimonials-carousel.js +64 -0
  159. package/dist/blocks/site/site-shell.d.ts +108 -0
  160. package/dist/blocks/site/site-shell.js +254 -0
  161. package/dist/blocks/site/stats-band.d.ts +42 -0
  162. package/dist/blocks/site/stats-band.js +45 -0
  163. package/dist/blocks/site/team.d.ts +44 -0
  164. package/dist/blocks/site/team.js +48 -0
  165. package/dist/blocks/site/testimonials.d.ts +68 -0
  166. package/dist/blocks/site/testimonials.js +66 -0
  167. package/dist/blocks/types.d.ts +63 -0
  168. package/dist/blocks/types.js +2 -0
  169. package/dist/business/approval-flow.d.ts +152 -0
  170. package/dist/business/approval-flow.js +221 -0
  171. package/dist/business/export-core.d.ts +55 -0
  172. package/dist/business/export-core.js +101 -0
  173. package/dist/business/export.d.ts +148 -0
  174. package/dist/business/export.js +264 -0
  175. package/dist/business/import-core.d.ts +104 -0
  176. package/dist/business/import-core.js +281 -0
  177. package/dist/business/import-wizard.d.ts +186 -0
  178. package/dist/business/import-wizard.js +401 -0
  179. package/dist/business/index.d.ts +12 -0
  180. package/dist/business/index.js +22 -0
  181. package/dist/business/line-items-core.d.ts +129 -0
  182. package/dist/business/line-items-core.js +183 -0
  183. package/dist/business/line-items.d.ts +119 -0
  184. package/dist/business/line-items.js +299 -0
  185. package/dist/business/multi-step-form.d.ts +131 -0
  186. package/dist/business/multi-step-form.js +337 -0
  187. package/dist/business/permission-core.d.ts +59 -0
  188. package/dist/business/permission-core.js +99 -0
  189. package/dist/business/permission-matrix.d.ts +158 -0
  190. package/dist/business/permission-matrix.js +341 -0
  191. package/dist/business/setup-checklist.d.ts +80 -0
  192. package/dist/business/setup-checklist.js +92 -0
  193. package/dist/business/signer-status.d.ts +53 -0
  194. package/dist/business/signer-status.js +76 -0
  195. package/dist/charts/area-chart.d.ts +35 -0
  196. package/dist/charts/area-chart.js +33 -0
  197. package/dist/charts/bar-chart.d.ts +27 -0
  198. package/dist/charts/bar-chart.js +46 -0
  199. package/dist/charts/bar-list.d.ts +47 -0
  200. package/dist/charts/bar-list.js +60 -0
  201. package/dist/charts/chart-shell.d.ts +173 -0
  202. package/dist/charts/chart-shell.js +205 -0
  203. package/dist/charts/chart.d.ts +73 -0
  204. package/dist/charts/chart.js +106 -0
  205. package/dist/charts/combo-chart.d.ts +29 -0
  206. package/dist/charts/combo-chart.js +47 -0
  207. package/dist/charts/donut-chart.d.ts +33 -0
  208. package/dist/charts/donut-chart.js +113 -0
  209. package/dist/charts/funnel.d.ts +51 -0
  210. package/dist/charts/funnel.js +69 -0
  211. package/dist/charts/gauge.d.ts +62 -0
  212. package/dist/charts/gauge.js +104 -0
  213. package/dist/charts/heatmap.d.ts +81 -0
  214. package/dist/charts/heatmap.js +338 -0
  215. package/dist/charts/index.d.ts +12 -0
  216. package/dist/charts/index.js +14 -0
  217. package/dist/charts/line-chart.d.ts +21 -0
  218. package/dist/charts/line-chart.js +36 -0
  219. package/dist/charts/test-utils.d.ts +2 -0
  220. package/dist/charts/test-utils.js +38 -0
  221. package/dist/charts/utils.d.ts +130 -0
  222. package/dist/charts/utils.js +262 -0
  223. package/dist/components/_qr-core.d.ts +26 -0
  224. package/dist/components/_qr-core.js +376 -0
  225. package/dist/components/accordion.d.ts +47 -0
  226. package/dist/components/accordion.js +70 -0
  227. package/dist/components/activity-timeline.d.ts +149 -0
  228. package/dist/components/activity-timeline.js +122 -0
  229. package/dist/components/address-field.d.ts +116 -0
  230. package/dist/components/address-field.js +219 -0
  231. package/dist/components/alert-dialog.d.ts +99 -0
  232. package/dist/components/alert-dialog.js +192 -0
  233. package/dist/components/alert.d.ts +42 -0
  234. package/dist/components/alert.js +82 -0
  235. package/dist/components/app-shell.d.ts +159 -0
  236. package/dist/components/app-shell.js +289 -0
  237. package/dist/components/attachment-list.d.ts +96 -0
  238. package/dist/components/attachment-list.js +196 -0
  239. package/dist/components/audit-log.d.ts +150 -0
  240. package/dist/components/audit-log.js +205 -0
  241. package/dist/components/avatar.d.ts +87 -0
  242. package/dist/components/avatar.js +126 -0
  243. package/dist/components/backup-codes.d.ts +42 -0
  244. package/dist/components/backup-codes.js +67 -0
  245. package/dist/components/badge.d.ts +41 -0
  246. package/dist/components/badge.js +68 -0
  247. package/dist/components/breadcrumb.d.ts +78 -0
  248. package/dist/components/breadcrumb.js +106 -0
  249. package/dist/components/button-group.d.ts +52 -0
  250. package/dist/components/button-group.js +77 -0
  251. package/dist/components/button.d.ts +58 -0
  252. package/dist/components/button.js +107 -0
  253. package/dist/components/calendar.d.ts +240 -0
  254. package/dist/components/calendar.js +483 -0
  255. package/dist/components/card.d.ts +66 -0
  256. package/dist/components/card.js +76 -0
  257. package/dist/components/carousel.d.ts +170 -0
  258. package/dist/components/carousel.js +348 -0
  259. package/dist/components/checkbox.d.ts +78 -0
  260. package/dist/components/checkbox.js +138 -0
  261. package/dist/components/color-picker.d.ts +112 -0
  262. package/dist/components/color-picker.js +235 -0
  263. package/dist/components/combobox.d.ts +136 -0
  264. package/dist/components/combobox.js +294 -0
  265. package/dist/components/command.d.ts +281 -0
  266. package/dist/components/command.js +498 -0
  267. package/dist/components/comment-thread.d.ts +252 -0
  268. package/dist/components/comment-thread.js +449 -0
  269. package/dist/components/context-menu.d.ts +77 -0
  270. package/dist/components/context-menu.js +82 -0
  271. package/dist/components/currency-input.d.ts +43 -0
  272. package/dist/components/currency-input.js +85 -0
  273. package/dist/components/date-picker.d.ts +141 -0
  274. package/dist/components/date-picker.js +241 -0
  275. package/dist/components/date-range-picker.d.ts +91 -0
  276. package/dist/components/date-range-picker.js +251 -0
  277. package/dist/components/description-list.d.ts +92 -0
  278. package/dist/components/description-list.js +42 -0
  279. package/dist/components/dialog.d.ts +139 -0
  280. package/dist/components/dialog.js +185 -0
  281. package/dist/components/dropdown-menu.d.ts +100 -0
  282. package/dist/components/dropdown-menu.js +102 -0
  283. package/dist/components/editor-layout.d.ts +166 -0
  284. package/dist/components/editor-layout.js +237 -0
  285. package/dist/components/empty-state.d.ts +49 -0
  286. package/dist/components/empty-state.js +68 -0
  287. package/dist/components/entity-card.d.ts +83 -0
  288. package/dist/components/entity-card.js +92 -0
  289. package/dist/components/file-upload.d.ts +256 -0
  290. package/dist/components/file-upload.js +490 -0
  291. package/dist/components/formatted-input.d.ts +177 -0
  292. package/dist/components/formatted-input.js +399 -0
  293. package/dist/components/hierarchy-chart.d.ts +190 -0
  294. package/dist/components/hierarchy-chart.js +890 -0
  295. package/dist/components/hover-card.d.ts +21 -0
  296. package/dist/components/hover-card.js +32 -0
  297. package/dist/components/iban-input.d.ts +38 -0
  298. package/dist/components/iban-input.js +112 -0
  299. package/dist/components/id-input.d.ts +65 -0
  300. package/dist/components/id-input.js +130 -0
  301. package/dist/components/image.d.ts +130 -0
  302. package/dist/components/image.js +168 -0
  303. package/dist/components/input-otp.d.ts +62 -0
  304. package/dist/components/input-otp.js +73 -0
  305. package/dist/components/input.d.ts +141 -0
  306. package/dist/components/input.js +187 -0
  307. package/dist/components/item.d.ts +96 -0
  308. package/dist/components/item.js +113 -0
  309. package/dist/components/kbd.d.ts +64 -0
  310. package/dist/components/kbd.js +119 -0
  311. package/dist/components/list-layout.d.ts +144 -0
  312. package/dist/components/list-layout.js +210 -0
  313. package/dist/components/native-select.d.ts +33 -0
  314. package/dist/components/native-select.js +48 -0
  315. package/dist/components/navigation-menu.d.ts +127 -0
  316. package/dist/components/navigation-menu.js +129 -0
  317. package/dist/components/notification-center.d.ts +164 -0
  318. package/dist/components/notification-center.js +399 -0
  319. package/dist/components/page-header.d.ts +60 -0
  320. package/dist/components/page-header.js +60 -0
  321. package/dist/components/pagination.d.ts +121 -0
  322. package/dist/components/pagination.js +174 -0
  323. package/dist/components/phone-input.d.ts +49 -0
  324. package/dist/components/phone-input.js +266 -0
  325. package/dist/components/pin-map.d.ts +58 -0
  326. package/dist/components/pin-map.js +167 -0
  327. package/dist/components/popover.d.ts +38 -0
  328. package/dist/components/popover.js +69 -0
  329. package/dist/components/progress.d.ts +79 -0
  330. package/dist/components/progress.js +97 -0
  331. package/dist/components/qr-code.d.ts +36 -0
  332. package/dist/components/qr-code.js +27 -0
  333. package/dist/components/radio-group.d.ts +43 -0
  334. package/dist/components/radio-group.js +81 -0
  335. package/dist/components/record-detail-layout.d.ts +167 -0
  336. package/dist/components/record-detail-layout.js +233 -0
  337. package/dist/components/record-picker.d.ts +199 -0
  338. package/dist/components/record-picker.js +650 -0
  339. package/dist/components/resizable.d.ts +50 -0
  340. package/dist/components/resizable.js +88 -0
  341. package/dist/components/scroll-area.d.ts +40 -0
  342. package/dist/components/scroll-area.js +56 -0
  343. package/dist/components/select.d.ts +126 -0
  344. package/dist/components/select.js +137 -0
  345. package/dist/components/separator.d.ts +31 -0
  346. package/dist/components/separator.js +41 -0
  347. package/dist/components/settings-layout.d.ts +134 -0
  348. package/dist/components/settings-layout.js +180 -0
  349. package/dist/components/sheet.d.ts +103 -0
  350. package/dist/components/sheet.js +165 -0
  351. package/dist/components/sidebar.d.ts +171 -0
  352. package/dist/components/sidebar.js +421 -0
  353. package/dist/components/signature-pad.d.ts +85 -0
  354. package/dist/components/signature-pad.js +283 -0
  355. package/dist/components/skeleton.d.ts +64 -0
  356. package/dist/components/skeleton.js +53 -0
  357. package/dist/components/sla-timer.d.ts +75 -0
  358. package/dist/components/sla-timer.js +142 -0
  359. package/dist/components/slider.d.ts +57 -0
  360. package/dist/components/slider.js +133 -0
  361. package/dist/components/slug-input.d.ts +69 -0
  362. package/dist/components/slug-input.js +201 -0
  363. package/dist/components/sparkline.d.ts +54 -0
  364. package/dist/components/sparkline.js +122 -0
  365. package/dist/components/spinner.d.ts +34 -0
  366. package/dist/components/spinner.js +34 -0
  367. package/dist/components/stat.d.ts +135 -0
  368. package/dist/components/stat.js +130 -0
  369. package/dist/components/status-picker.d.ts +107 -0
  370. package/dist/components/status-picker.js +175 -0
  371. package/dist/components/stepper.d.ts +86 -0
  372. package/dist/components/stepper.js +103 -0
  373. package/dist/components/switch.d.ts +34 -0
  374. package/dist/components/switch.js +70 -0
  375. package/dist/components/table.d.ts +101 -0
  376. package/dist/components/table.js +72 -0
  377. package/dist/components/tabs.d.ts +103 -0
  378. package/dist/components/tabs.js +173 -0
  379. package/dist/components/tag-input.d.ts +77 -0
  380. package/dist/components/tag-input.js +305 -0
  381. package/dist/components/task-list.d.ts +89 -0
  382. package/dist/components/task-list.js +238 -0
  383. package/dist/components/time-picker.d.ts +119 -0
  384. package/dist/components/time-picker.js +399 -0
  385. package/dist/components/toast.d.ts +87 -0
  386. package/dist/components/toast.js +142 -0
  387. package/dist/components/toggle.d.ts +77 -0
  388. package/dist/components/toggle.js +109 -0
  389. package/dist/components/tooltip.d.ts +69 -0
  390. package/dist/components/tooltip.js +105 -0
  391. package/dist/components/top-bar.d.ts +87 -0
  392. package/dist/components/top-bar.js +99 -0
  393. package/dist/components/tour.d.ts +60 -0
  394. package/dist/components/tour.js +139 -0
  395. package/dist/components/tree-select.d.ts +89 -0
  396. package/dist/components/tree-select.js +243 -0
  397. package/dist/components/tree-view.d.ts +109 -0
  398. package/dist/components/tree-view.js +170 -0
  399. package/dist/components/typography.d.ts +107 -0
  400. package/dist/components/typography.js +128 -0
  401. package/dist/components/user-picker.d.ts +89 -0
  402. package/dist/components/user-picker.js +162 -0
  403. package/dist/components/version-history.d.ts +191 -0
  404. package/dist/components/version-history.js +431 -0
  405. package/dist/data-table/csv.d.ts +27 -0
  406. package/dist/data-table/csv.js +68 -0
  407. package/dist/data-table/data-table.d.ts +423 -0
  408. package/dist/data-table/data-table.js +1259 -0
  409. package/dist/data-table/filter-bar.d.ts +146 -0
  410. package/dist/data-table/filter-bar.js +569 -0
  411. package/dist/data-table/filter-fns.d.ts +65 -0
  412. package/dist/data-table/filter-fns.js +382 -0
  413. package/dist/data-table/index.d.ts +8 -0
  414. package/dist/data-table/index.js +9 -0
  415. package/dist/data-table/saved-views.d.ts +100 -0
  416. package/dist/data-table/saved-views.js +251 -0
  417. package/dist/data-table/types.d.ts +168 -0
  418. package/dist/data-table/types.js +87 -0
  419. package/dist/data-table/url-state.d.ts +94 -0
  420. package/dist/data-table/url-state.js +303 -0
  421. package/dist/data-table/view-state.d.ts +16 -0
  422. package/dist/data-table/view-state.js +81 -0
  423. package/dist/editor/_test-setup.d.ts +1 -0
  424. package/dist/editor/_test-setup.js +33 -0
  425. package/dist/editor/block-editor.d.ts +137 -0
  426. package/dist/editor/block-editor.js +280 -0
  427. package/dist/editor/commands.d.ts +31 -0
  428. package/dist/editor/commands.js +150 -0
  429. package/dist/editor/context.d.ts +108 -0
  430. package/dist/editor/context.js +30 -0
  431. package/dist/editor/convert.d.ts +66 -0
  432. package/dist/editor/convert.js +567 -0
  433. package/dist/editor/drag-handle.d.ts +10 -0
  434. package/dist/editor/drag-handle.js +69 -0
  435. package/dist/editor/extensions.d.ts +34 -0
  436. package/dist/editor/extensions.js +239 -0
  437. package/dist/editor/index.d.ts +14 -0
  438. package/dist/editor/index.js +17 -0
  439. package/dist/editor/inserter.d.ts +12 -0
  440. package/dist/editor/inserter.js +88 -0
  441. package/dist/editor/inspector.d.ts +17 -0
  442. package/dist/editor/inspector.js +65 -0
  443. package/dist/editor/items.d.ts +62 -0
  444. package/dist/editor/items.js +195 -0
  445. package/dist/editor/labels.d.ts +119 -0
  446. package/dist/editor/labels.js +130 -0
  447. package/dist/editor/markdown.d.ts +14 -0
  448. package/dist/editor/markdown.js +209 -0
  449. package/dist/editor/menus.d.ts +20 -0
  450. package/dist/editor/menus.js +236 -0
  451. package/dist/editor/nodes.d.ts +14 -0
  452. package/dist/editor/nodes.js +201 -0
  453. package/dist/editor/outline.d.ts +11 -0
  454. package/dist/editor/outline.js +52 -0
  455. package/dist/editor/schema-form.d.ts +64 -0
  456. package/dist/editor/schema-form.js +290 -0
  457. package/dist/editor/slash-menu.d.ts +15 -0
  458. package/dist/editor/slash-menu.js +119 -0
  459. package/dist/fonts/catalog.d.ts +53 -0
  460. package/dist/fonts/catalog.js +121 -0
  461. package/dist/fonts/font-picker.d.ts +70 -0
  462. package/dist/fonts/font-picker.js +225 -0
  463. package/dist/fonts/index.d.ts +6 -0
  464. package/dist/fonts/index.js +7 -0
  465. package/dist/fonts/loader.d.ts +66 -0
  466. package/dist/fonts/loader.js +161 -0
  467. package/dist/fonts/pairing-picker.d.ts +31 -0
  468. package/dist/fonts/pairing-picker.js +81 -0
  469. package/dist/fonts/pairings.d.ts +84 -0
  470. package/dist/fonts/pairings.js +149 -0
  471. package/dist/fonts/provider.d.ts +34 -0
  472. package/dist/fonts/provider.js +51 -0
  473. package/dist/form/index.d.ts +1 -0
  474. package/dist/form/index.js +1 -0
  475. package/dist/format/core.d.ts +149 -0
  476. package/dist/format/core.js +357 -0
  477. package/dist/format/index.d.ts +4 -0
  478. package/dist/format/index.js +5 -0
  479. package/dist/format/use-format.d.ts +1 -0
  480. package/dist/format/use-format.js +3 -0
  481. package/dist/index.d.ts +91 -0
  482. package/dist/index.js +92 -0
  483. package/dist/lib/cn.d.ts +3 -0
  484. package/dist/lib/cn.js +16 -0
  485. package/dist/lib/color.d.ts +64 -0
  486. package/dist/lib/color.js +177 -0
  487. package/dist/lib/compose-refs.d.ts +24 -0
  488. package/dist/lib/compose-refs.js +45 -0
  489. package/dist/lib/data-islands.d.ts +194 -0
  490. package/dist/lib/data-islands.js +368 -0
  491. package/dist/lib/date.d.ts +129 -0
  492. package/dist/lib/date.js +386 -0
  493. package/dist/lib/field-context.d.ts +64 -0
  494. package/dist/lib/field-context.js +62 -0
  495. package/dist/lib/floating-arrow.d.ts +18 -0
  496. package/dist/lib/floating-arrow.js +15 -0
  497. package/dist/lib/islands.d.ts +38 -0
  498. package/dist/lib/islands.js +40 -0
  499. package/dist/lib/labels.d.ts +51 -0
  500. package/dist/lib/labels.js +56 -0
  501. package/dist/lib/layer.d.ts +36 -0
  502. package/dist/lib/layer.js +42 -0
  503. package/dist/lib/locale.d.ts +85 -0
  504. package/dist/lib/locale.js +105 -0
  505. package/dist/lib/menu.d.ts +58 -0
  506. package/dist/lib/menu.js +99 -0
  507. package/dist/lib/message-format.d.ts +20 -0
  508. package/dist/lib/message-format.js +116 -0
  509. package/dist/lib/nav.d.ts +132 -0
  510. package/dist/lib/nav.js +178 -0
  511. package/dist/lib/provider.d.ts +100 -0
  512. package/dist/lib/provider.js +105 -0
  513. package/dist/lib/public.d.ts +23 -0
  514. package/dist/lib/public.js +34 -0
  515. package/dist/lib/sr-name.d.ts +18 -0
  516. package/dist/lib/sr-name.js +17 -0
  517. package/dist/lib/text.d.ts +100 -0
  518. package/dist/lib/text.js +233 -0
  519. package/dist/lib/theme-scope.d.ts +58 -0
  520. package/dist/lib/theme-scope.js +59 -0
  521. package/dist/lib/use-async-list.d.ts +60 -0
  522. package/dist/lib/use-async-list.js +119 -0
  523. package/dist/lib/use-container-width.d.ts +19 -0
  524. package/dist/lib/use-container-width.js +39 -0
  525. package/dist/lib/use-controllable-state.d.ts +33 -0
  526. package/dist/lib/use-controllable-state.js +56 -0
  527. package/dist/lib/use-edge-fade.d.ts +13 -0
  528. package/dist/lib/use-edge-fade.js +43 -0
  529. package/dist/lib/use-formatted-input.d.ts +69 -0
  530. package/dist/lib/use-formatted-input.js +152 -0
  531. package/dist/lib/use-hotkeys.d.ts +80 -0
  532. package/dist/lib/use-hotkeys.js +221 -0
  533. package/dist/lib/use-hover-intent.d.ts +44 -0
  534. package/dist/lib/use-hover-intent.js +119 -0
  535. package/dist/lib/use-media-query.d.ts +21 -0
  536. package/dist/lib/use-media-query.js +28 -0
  537. package/dist/lib/use-reduced-motion.d.ts +8 -0
  538. package/dist/lib/use-reduced-motion.js +13 -0
  539. package/dist/lib/use-tree.d.ts +153 -0
  540. package/dist/lib/use-tree.js +534 -0
  541. package/dist/lib/value-format.d.ts +25 -0
  542. package/dist/lib/value-format.js +56 -0
  543. package/dist/lib/variants.d.ts +131 -0
  544. package/dist/lib/variants.js +109 -0
  545. package/dist/locale-data/core/date.d.ts +24 -0
  546. package/dist/locale-data/core/date.js +68 -0
  547. package/dist/locale-data/core/decimal.d.ts +19 -0
  548. package/dist/locale-data/core/decimal.js +79 -0
  549. package/dist/locale-data/core/holidays.d.ts +30 -0
  550. package/dist/locale-data/core/holidays.js +79 -0
  551. package/dist/locale-data/core/iban.d.ts +29 -0
  552. package/dist/locale-data/core/iban.js +74 -0
  553. package/dist/locale-data/core/index.d.ts +7 -0
  554. package/dist/locale-data/core/index.js +6 -0
  555. package/dist/locale-data/core/types.d.ts +173 -0
  556. package/dist/locale-data/core/types.js +6 -0
  557. package/dist/locale-data/core/week-info.d.ts +23 -0
  558. package/dist/locale-data/core/week-info.js +85 -0
  559. package/dist/locale-data/core/working-days.d.ts +27 -0
  560. package/dist/locale-data/core/working-days.js +133 -0
  561. package/dist/locale-data/index.d.ts +2 -0
  562. package/dist/locale-data/index.js +4 -0
  563. package/dist/locale-data/tr/address-tr.json +1 -0
  564. package/dist/locale-data/tr/address.d.ts +23 -0
  565. package/dist/locale-data/tr/address.js +52 -0
  566. package/dist/locale-data/tr/holidays.d.ts +31 -0
  567. package/dist/locale-data/tr/holidays.js +81 -0
  568. package/dist/locale-data/tr/iban.d.ts +21 -0
  569. package/dist/locale-data/tr/iban.js +45 -0
  570. package/dist/locale-data/tr/id.d.ts +36 -0
  571. package/dist/locale-data/tr/id.js +120 -0
  572. package/dist/locale-data/tr/index.d.ts +12 -0
  573. package/dist/locale-data/tr/index.js +33 -0
  574. package/dist/locale-data/tr/kdv.d.ts +91 -0
  575. package/dist/locale-data/tr/kdv.js +222 -0
  576. package/dist/locales/en.d.ts +2102 -0
  577. package/dist/locales/en.js +2088 -0
  578. package/dist/locales/tr.d.ts +2086 -0
  579. package/dist/locales/tr.js +2087 -0
  580. package/dist/media/focal-point.d.ts +42 -0
  581. package/dist/media/focal-point.js +96 -0
  582. package/dist/media/gallery-layout.d.ts +19 -0
  583. package/dist/media/gallery-layout.js +61 -0
  584. package/dist/media/gallery.d.ts +64 -0
  585. package/dist/media/gallery.js +140 -0
  586. package/dist/media/image-cropper.d.ts +86 -0
  587. package/dist/media/image-cropper.js +170 -0
  588. package/dist/media/image-field.d.ts +115 -0
  589. package/dist/media/image-field.js +212 -0
  590. package/dist/media/index.d.ts +19 -0
  591. package/dist/media/index.js +23 -0
  592. package/dist/media/lightbox.d.ts +82 -0
  593. package/dist/media/lightbox.js +171 -0
  594. package/dist/media/link-preview.d.ts +97 -0
  595. package/dist/media/link-preview.js +177 -0
  596. package/dist/media/media-library.d.ts +244 -0
  597. package/dist/media/media-library.js +776 -0
  598. package/dist/media/media-picker.d.ts +96 -0
  599. package/dist/media/media-picker.js +209 -0
  600. package/dist/media/media-provider.d.ts +23 -0
  601. package/dist/media/media-provider.js +44 -0
  602. package/dist/media/media-utils.d.ts +39 -0
  603. package/dist/media/media-utils.js +145 -0
  604. package/dist/media/memory-adapter.d.ts +22 -0
  605. package/dist/media/memory-adapter.js +162 -0
  606. package/dist/media/rest-adapter.d.ts +90 -0
  607. package/dist/media/rest-adapter.js +208 -0
  608. package/dist/media/serp.d.ts +62 -0
  609. package/dist/media/serp.js +108 -0
  610. package/dist/media/test-fixtures.d.ts +3 -0
  611. package/dist/media/test-fixtures.js +37 -0
  612. package/dist/media/types.d.ts +183 -0
  613. package/dist/media/types.js +3 -0
  614. package/dist/media/use-pan-zoom.d.ts +51 -0
  615. package/dist/media/use-pan-zoom.js +156 -0
  616. package/dist/media/use-upload-queue.d.ts +64 -0
  617. package/dist/media/use-upload-queue.js +115 -0
  618. package/dist/media/video-player.d.ts +135 -0
  619. package/dist/media/video-player.js +319 -0
  620. package/dist/motion/core.d.ts +32 -0
  621. package/dist/motion/core.js +77 -0
  622. package/dist/motion/count-up.d.ts +29 -0
  623. package/dist/motion/count-up.js +92 -0
  624. package/dist/motion/index.d.ts +11 -0
  625. package/dist/motion/index.js +13 -0
  626. package/dist/motion/motion-scope.d.ts +17 -0
  627. package/dist/motion/motion-scope.js +16 -0
  628. package/dist/motion/page-transition.d.ts +33 -0
  629. package/dist/motion/page-transition.js +61 -0
  630. package/dist/motion/parallax.d.ts +37 -0
  631. package/dist/motion/parallax.js +90 -0
  632. package/dist/motion/pointer.d.ts +38 -0
  633. package/dist/motion/pointer.js +117 -0
  634. package/dist/motion/reveal.d.ts +72 -0
  635. package/dist/motion/reveal.js +133 -0
  636. package/dist/motion/scroll-shrink.d.ts +18 -0
  637. package/dist/motion/scroll-shrink.js +47 -0
  638. package/dist/motion/skeleton-swap.d.ts +17 -0
  639. package/dist/motion/skeleton-swap.js +43 -0
  640. package/dist/motion/text-reveal.d.ts +30 -0
  641. package/dist/motion/text-reveal.js +29 -0
  642. package/dist/motion/ticker.d.ts +35 -0
  643. package/dist/motion/ticker.js +16 -0
  644. package/dist/next/index.d.ts +42 -0
  645. package/dist/next/index.js +36 -0
  646. package/dist/render/block-renderer.d.ts +56 -0
  647. package/dist/render/block-renderer.js +137 -0
  648. package/dist/render/index.d.ts +6 -0
  649. package/dist/render/index.js +7 -0
  650. package/dist/render/prepare.d.ts +61 -0
  651. package/dist/render/prepare.js +119 -0
  652. package/dist/scheduler/core/duration.d.ts +83 -0
  653. package/dist/scheduler/core/duration.js +174 -0
  654. package/dist/scheduler/core/gantt.d.ts +63 -0
  655. package/dist/scheduler/core/gantt.js +226 -0
  656. package/dist/scheduler/core/index.d.ts +6 -0
  657. package/dist/scheduler/core/index.js +7 -0
  658. package/dist/scheduler/core/layout.d.ts +97 -0
  659. package/dist/scheduler/core/layout.js +249 -0
  660. package/dist/scheduler/core/time-scale.d.ts +89 -0
  661. package/dist/scheduler/core/time-scale.js +173 -0
  662. package/dist/scheduler/gantt.d.ts +125 -0
  663. package/dist/scheduler/gantt.js +532 -0
  664. package/dist/scheduler/index.d.ts +6 -0
  665. package/dist/scheduler/index.js +7 -0
  666. package/dist/scheduler/resource-calendar.d.ts +218 -0
  667. package/dist/scheduler/resource-calendar.js +661 -0
  668. package/dist/scheduler/scheduler.d.ts +168 -0
  669. package/dist/scheduler/scheduler.js +768 -0
  670. package/dist/scheduler/shared.d.ts +63 -0
  671. package/dist/scheduler/shared.js +145 -0
  672. package/dist/scheduler/time-tracker.d.ts +138 -0
  673. package/dist/scheduler/time-tracker.js +403 -0
  674. package/dist/sortable/core.d.ts +67 -0
  675. package/dist/sortable/core.js +167 -0
  676. package/dist/sortable/index.d.ts +8 -0
  677. package/dist/sortable/index.js +10 -0
  678. package/dist/sortable/kanban-core.d.ts +70 -0
  679. package/dist/sortable/kanban-core.js +67 -0
  680. package/dist/sortable/kanban.d.ts +147 -0
  681. package/dist/sortable/kanban.js +472 -0
  682. package/dist/sortable/sortable-list.d.ts +71 -0
  683. package/dist/sortable/sortable-list.js +76 -0
  684. package/dist/sortable/sortable-tree.d.ts +105 -0
  685. package/dist/sortable/sortable-tree.js +462 -0
  686. package/dist/sortable/sortable.d.ts +188 -0
  687. package/dist/sortable/sortable.js +485 -0
  688. package/dist/sortable/use-pointer-drag.d.ts +75 -0
  689. package/dist/sortable/use-pointer-drag.js +173 -0
  690. package/dist/sortable/use-time-scale.d.ts +11 -0
  691. package/dist/sortable/use-time-scale.js +19 -0
  692. package/dist/styles/base.css +51 -0
  693. package/dist/styles/blocks.css +949 -0
  694. package/dist/styles/calendar.css +642 -0
  695. package/dist/styles/charts.css +264 -0
  696. package/dist/styles/data.css +474 -0
  697. package/dist/styles/editors.css +1022 -0
  698. package/dist/styles/forms.css +406 -0
  699. package/dist/styles/media.css +515 -0
  700. package/dist/styles/motion.css +389 -0
  701. package/dist/styles/navigation.css +293 -0
  702. package/dist/styles/overlays.css +244 -0
  703. package/dist/styles.css +743 -0
  704. package/package.json +160 -4
@@ -0,0 +1,69 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../../lib/cn.js";
5
+ import { formatMessage } from "../../lib/message-format.js";
6
+ import { formatTime } from "./shared/opening-hours.js";
7
+ const DAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
8
+ const defaultTimes = () => Array.from({ length: 21 }, (_, i) => `${String(12 + Math.floor(i / 2)).padStart(2, "0")}:${i % 2 ? "30" : "00"}`);
9
+ /** Today as `YYYY-MM-DD` in the business's time zone (never toISOString). */
10
+ export function todayIn(timeZone, now = new Date()) {
11
+ const parts = new Intl.DateTimeFormat("en-CA", { timeZone, year: "numeric", month: "2-digit", day: "2-digit" }).formatToParts(now);
12
+ const get = (t) => parts.find((p) => p.type === t)?.value ?? "";
13
+ return `${get("year")}-${get("month")}-${get("day")}`;
14
+ }
15
+ const weekdayOf = (ymd) => {
16
+ const [y, m, d] = ymd.split("-").map(Number);
17
+ return DAYS[new Date(Date.UTC(y, m - 1, d)).getUTCDay()];
18
+ };
19
+ /**
20
+ * Booking bar island of the CTA `booking` variant (~2 KB). Native date/select fields; on submit
21
+ * it builds a prefilled WhatsApp message (Intl-formatted date and time) or sends the fields to a
22
+ * booking URL. Without JS the form still posts to the same target.
23
+ */
24
+ export function CtaBooking({ provider, target, fields, services, times, maxGuests = 8, closedDays, timeZone, locale, strings, fallbackMessage, className }) {
25
+ const uid = React.useId();
26
+ const [min, setMin] = React.useState(undefined);
27
+ const [error, setError] = React.useState(null);
28
+ React.useEffect(() => setMin(todayIn(timeZone)), [timeZone]);
29
+ const timeList = times ?? defaultTimes();
30
+ const waUrl = `https://wa.me/${target.replace(/\D/g, "")}`;
31
+ const dayName = (wd) => {
32
+ // 2026-11-01 is a Sunday: offset into the week for a localized plural weekday name.
33
+ const d = new Date(Date.UTC(2026, 10, 1 + DAYS.indexOf(wd)));
34
+ return new Intl.DateTimeFormat(locale, { weekday: "long", timeZone: "UTC" }).format(d);
35
+ };
36
+ const check = (ymd) => {
37
+ if (ymd && closedDays?.includes(weekdayOf(ymd))) {
38
+ setError(formatMessage(strings.closedOn, { day: dayName(weekdayOf(ymd)) }, locale));
39
+ return false;
40
+ }
41
+ setError(null);
42
+ return true;
43
+ };
44
+ const onSubmit = (e) => {
45
+ const data = new FormData(e.currentTarget);
46
+ const date = String(data.get("date") ?? "");
47
+ if (!check(date)) {
48
+ e.preventDefault();
49
+ return;
50
+ }
51
+ if (provider !== "whatsapp")
52
+ return; // native GET to the booking URL
53
+ e.preventDefault();
54
+ const [y, m, d] = date ? date.split("-").map(Number) : [];
55
+ const dateText = date ? new Intl.DateTimeFormat(locale, { weekday: "short", day: "numeric", month: "long", timeZone: "UTC" }).format(new Date(Date.UTC(y, m - 1, d))) : "—";
56
+ const time = String(data.get("time") ?? "");
57
+ // Same clock as the time list and the opening hours (12- or 24-hour by locale).
58
+ const timeText = time ? formatTime(time, locale) : "—";
59
+ const guests = Number(data.get("guests") ?? 2);
60
+ const service = String(data.get("service") ?? "");
61
+ const text = formatMessage(service ? strings.messageService : strings.message, { date: dateText, time: timeText, service, guests: formatMessage(strings.guestsCount, { count: guests }, locale) }, locale);
62
+ window.open(`${waUrl}?text=${encodeURIComponent(text)}`, "_blank", "noopener,noreferrer");
63
+ };
64
+ const cell = "vb-booking-cell flex min-w-0 flex-col gap-1 bg-scene px-4 py-2.5";
65
+ const label = "font-mono text-[0.6875rem] uppercase tracking-[0.08em] text-fg-subtle";
66
+ const control = "vb-booking-control w-full min-w-0 bg-transparent text-body text-fg outline-none";
67
+ const errId = `${uid}-err`;
68
+ return (_jsxs("form", { action: provider === "whatsapp" ? waUrl : target, method: "get", target: provider === "whatsapp" ? "_blank" : undefined, onSubmit: onSubmit, className: cn("vb-booking flex flex-col gap-2", className), children: [provider === "whatsapp" ? _jsx("input", { type: "hidden", name: "text", value: fallbackMessage }) : null, _jsxs("div", { className: "vb-booking-bar grid grid-cols-2 gap-px overflow-hidden rounded-ui border border-field-border bg-field-border @2xl:flex @2xl:items-stretch", children: [fields.includes("date") ? (_jsxs("div", { className: cn(cell, "@2xl:flex-1"), children: [_jsx("label", { htmlFor: `${uid}-date`, className: label, children: strings.date }), _jsx("input", { id: `${uid}-date`, name: "date", type: "date", required: true, min: min, "aria-invalid": error ? true : undefined, "aria-describedby": error ? errId : undefined, onChange: (e) => check(e.currentTarget.value), className: cn(control, "tabular") })] })) : null, fields.includes("time") ? (_jsxs("div", { className: cn(cell, "@2xl:w-36"), children: [_jsx("label", { htmlFor: `${uid}-time`, className: label, children: strings.time }), _jsx("select", { id: `${uid}-time`, name: "time", required: true, defaultValue: timeList.includes("19:30") ? "19:30" : timeList[0], className: cn(control, "tabular"), children: timeList.map((t) => (_jsx("option", { value: t, children: formatTime(t, locale) }, t))) })] })) : null, fields.includes("guests") ? (_jsxs("div", { className: cn(cell, "@2xl:w-36"), children: [_jsx("label", { htmlFor: `${uid}-guests`, className: label, children: strings.guests }), _jsx("select", { id: `${uid}-guests`, name: "guests", defaultValue: "2", className: cn(control, "tabular"), children: Array.from({ length: maxGuests }, (_, i) => i + 1).map((n) => (_jsx("option", { value: n, children: formatMessage(strings.guestsCount, { count: n }, locale) }, n))) })] })) : null, fields.includes("service") && services?.length ? (_jsxs("div", { className: cn(cell, "@2xl:flex-1"), children: [_jsx("label", { htmlFor: `${uid}-service`, className: label, children: strings.service }), _jsx("select", { id: `${uid}-service`, name: "service", className: control, children: services.map((s) => (_jsx("option", { value: s, children: s }, s))) })] })) : null, _jsx("div", { className: "col-span-2 flex bg-scene p-1.5 @2xl:col-span-1", children: _jsxs("button", { type: "submit", className: "vb-action-primary inline-flex h-full min-h-11 w-full items-center justify-center gap-2 rounded-[calc(var(--radius)-4px)] bg-accent px-5 text-[15px] font-semibold text-accent-fg transition-[filter] hover:brightness-[1.04] focus-ring", children: [strings.submit, provider === "whatsapp" ? _jsxs("span", { className: "sr-only", children: [" ", strings.opensWhatsApp] }) : null] }) })] }), _jsx("p", { id: errId, role: "alert", className: cn("text-small text-danger", !error && "sr-only"), children: error ?? "" })] }));
69
+ }
@@ -0,0 +1,74 @@
1
+ import * as React from "react";
2
+ import type { BlockBaseProps } from "../types.js";
3
+ import type { RichDoc } from "../schema/rich-doc.js";
4
+ import { type BookingField, type BookingWeekday } from "./cta-booking.js";
5
+ import { type SiteBlockLabels, type SiteCta, type SiteImage } from "./_kit-1.js";
6
+ export type CtaVariant = "band" | "split" | "minimal" | "newsletter" | "booking";
7
+ /** `https://wa.me/<digits>?text=<encoded>` from an E.164 number. */
8
+ export declare function waLink(e164: string, text?: string): string;
9
+ export interface CtaBookingConfig {
10
+ /** whatsapp: prefilled message · url: GET the fields to a booking page · phone: a call button · embed: calendar facade. */
11
+ provider: "whatsapp" | "url" | "phone" | "embed";
12
+ /** E.164 for whatsapp / phone. */
13
+ whatsapp?: string;
14
+ phone?: string;
15
+ /** url: booking page; embed: Calendly (or other allowed) URL. */
16
+ url?: string;
17
+ fields?: BookingField[];
18
+ services?: string[];
19
+ times?: string[];
20
+ maxGuests?: number;
21
+ closedDays?: BookingWeekday[];
22
+ timeZone?: string;
23
+ /** "Hi, I'd like a table for {guests} on {date} at {time}." */
24
+ messageTemplate?: string;
25
+ /** embed: preview image shown before the calendar loads. */
26
+ preview?: SiteImage;
27
+ }
28
+ export interface CtaProps extends Omit<BlockBaseProps, "variant" | "labels"> {
29
+ /**
30
+ * band: a full-width accent band; big title at the start, actions at the end, phone line below.
31
+ * split: title + action on the start side, a cropped photo on the end side.
32
+ * minimal: no background; a very large centred title and one huge underlined text link.
33
+ * newsletter: title + text at the start, email field + button at the end, consent below.
34
+ * booking: a thin bar — date · time · guests/service — ending with "Ask for availability".
35
+ */
36
+ variant?: CtaVariant;
37
+ eyebrow?: React.ReactNode;
38
+ title: React.ReactNode;
39
+ lead?: React.ReactNode;
40
+ /** ≤ 2; one primary. In `minimal` only the first is used, as a large text link. */
41
+ actions?: SiteCta[];
42
+ /** split: the photo. */
43
+ media?: SiteImage;
44
+ /** band/split: mono contact line ("0216 000 00 00 · WhatsApp"). */
45
+ contact?: {
46
+ phone?: string;
47
+ whatsapp?: string;
48
+ whatsappText?: string;
49
+ };
50
+ newsletter?: {
51
+ /** Form action: a URL or a server action. */
52
+ action?: string | ((formData: FormData) => void | Promise<void>);
53
+ placeholder?: string;
54
+ buttonLabel?: string;
55
+ /** Consent text under the field (the app's legal copy). */
56
+ consent?: RichDoc | string;
57
+ /** Rendered result after a submit (the app passes it back). */
58
+ status?: "idle" | "success" | "error";
59
+ message?: React.ReactNode;
60
+ };
61
+ booking?: CtaBookingConfig;
62
+ /** Small print under the block ("No card needed. Cancel any time."). */
63
+ fineprint?: React.ReactNode;
64
+ labels?: SiteBlockLabels;
65
+ }
66
+ /**
67
+ * End-of-page call to action, newsletter signup or booking entry point. Server component;
68
+ * newsletter is a plain form (works without JS), booking a small island, embeds a facade.
69
+ *
70
+ * ```tsx
71
+ * <Cta title="Book the *long table*" actions={[{ link: { href: "/book", label: "Book a table" }, style: "primary" }]} contact={{ phone: "+902160000000" }} />
72
+ * ```
73
+ */
74
+ export declare function Cta(props: CtaProps): React.JSX.Element;
@@ -0,0 +1,113 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { CalendarDays } from "lucide-react";
3
+ import { cn } from "../../lib/cn.js";
4
+ import { Container, Section } from "../section.js";
5
+ import { BlockHeading } from "../block-heading.js";
6
+ import { BlockImage } from "../block-image.js";
7
+ import { BlockLink } from "../block-link.js";
8
+ import { RichText } from "../rich-text.js";
9
+ import { CtaBooking } from "./cta-booking.js";
10
+ import { EmbedFacade } from "./embed-facade.js";
11
+ import { formatSitePhone } from "./navbar.js";
12
+ import { ArrowEnd, CtaList, field, siteTemplate, siteText, useBlockIds } from "./_kit-1.js";
13
+ import { Reveal } from "../../motion/reveal.js";
14
+ /** `https://wa.me/<digits>?text=<encoded>` from an E.164 number. */
15
+ export function waLink(e164, text) {
16
+ const base = `https://wa.me/${e164.replace(/\D/g, "")}`;
17
+ return text ? `${base}?text=${encodeURIComponent(text)}` : base;
18
+ }
19
+ /**
20
+ * End-of-page call to action, newsletter signup or booking entry point. Server component;
21
+ * newsletter is a plain form (works without JS), booking a small island, embeds a facade.
22
+ *
23
+ * ```tsx
24
+ * <Cta title="Book the *long table*" actions={[{ link: { href: "/book", label: "Book a table" }, style: "primary" }]} contact={{ phone: "+902160000000" }} />
25
+ * ```
26
+ */
27
+ export function Cta(props) {
28
+ const { variant = "band", id, theme, anchor, className, editMode, components, labels } = props;
29
+ const { base, headingId } = useBlockIds(id, "cta");
30
+ const sectionTheme = variant === "band" ? { surface: "accent", ...theme } : theme;
31
+ const inner = { ...props, headingId };
32
+ return (_jsx(Section, { theme: sectionTheme, anchor: anchor, headingId: headingId, blockId: base, blockType: "cta", editMode: editMode, components: components, labels: labels, "data-variant": variant, className: cn("vb-cta", className), children: _jsx(Reveal, { disabled: editMode, children: variant === "split" ? _jsx(Split, { ...inner }) : variant === "minimal" ? _jsx(Minimal, { ...inner }) : variant === "newsletter" ? _jsx(Newsletter, { ...inner }) : variant === "booking" ? _jsx(Booking, { ...inner }) : _jsx(Band, { ...inner }) }) }));
33
+ }
34
+ function Heading({ p, size = "display-l", className }) {
35
+ return _jsx(BlockHeading, { id: p.headingId, level: p.headingLevel ?? 2, size: size, text: p.title, editMode: p.editMode, field: "props.title", labels: p.labels, locale: p.locale, className: className });
36
+ }
37
+ function Eyebrow({ p, className }) {
38
+ if (!p.eyebrow)
39
+ return null;
40
+ return (_jsx("p", { className: cn("font-mono text-eyebrow uppercase tracking-[0.08em] text-fg-muted", className), ...field(p.editMode, "eyebrow"), children: p.eyebrow }));
41
+ }
42
+ function Lead({ p, className }) {
43
+ if (!p.lead)
44
+ return null;
45
+ return (_jsx("p", { className: cn("vb-lead max-w-[52ch] text-lead text-fg-muted", className), ...field(p.editMode, "lead"), children: p.lead }));
46
+ }
47
+ function Fineprint({ p, className }) {
48
+ if (!p.fineprint)
49
+ return null;
50
+ return (_jsx("p", { className: cn("text-small text-fg-subtle", className), ...field(p.editMode, "fineprint"), children: p.fineprint }));
51
+ }
52
+ function ContactLine({ p, className }) {
53
+ const c = p.contact;
54
+ if (!c?.phone && !c?.whatsapp)
55
+ return null;
56
+ const t = siteText(p.labels, p.locale);
57
+ const linkCls = "rounded-[2px] underline decoration-current/30 underline-offset-4 transition-[text-decoration-color] hover:decoration-current focus-ring";
58
+ return (_jsxs("p", { className: cn("flex flex-wrap items-center gap-x-3 gap-y-1 font-mono text-small tabular text-fg-muted", className), ...field(p.editMode, "contact"), children: [c.phone ? (_jsx("a", { href: `tel:${c.phone}`, "data-track": "call", className: linkCls, children: formatSitePhone(c.phone, p.locale) })) : null, c.phone && c.whatsapp ? _jsx("span", { "aria-hidden": true, children: "\u00B7" }) : null, c.whatsapp ? (_jsxs("a", { href: waLink(c.whatsapp, c.whatsappText), target: "_blank", rel: "noopener noreferrer", "data-track": "whatsapp", className: linkCls, children: ["WhatsApp", _jsxs("span", { className: "sr-only", children: [" ", t("opensWhatsApp")] })] })) : null] }));
59
+ }
60
+ const actionsOf = (p, extra) => _jsx(CtaList, { actions: p.actions, components: p.components, labels: p.labels, locale: p.locale, editMode: p.editMode, ...extra });
61
+ /* band ------------------------------------------------------------------ */
62
+ function Band(p) {
63
+ return (_jsxs(Container, { className: "grid gap-x-(--gutter) gap-y-10 @4xl:grid-cols-12 @4xl:items-end", children: [_jsxs("div", { className: "flex flex-col gap-6 @4xl:col-span-8", children: [_jsx(Eyebrow, { p: p }), _jsx(Heading, { p: p, className: "max-w-[16ch]" }), _jsx(Lead, { p: p })] }), _jsxs("div", { className: "flex flex-col gap-5 @4xl:col-span-4 @4xl:items-end", children: [actionsOf(p, { size: "xl", className: "@4xl:justify-end" }), _jsx(ContactLine, { p: p })] }), _jsx(Fineprint, { p: p, className: "@4xl:col-span-12" })] }));
64
+ }
65
+ /* split ----------------------------------------------------------------- */
66
+ function Split(p) {
67
+ return (_jsxs(Container, { className: "grid gap-x-(--gutter) gap-y-10 @4xl:grid-cols-12 @4xl:items-stretch", children: [_jsxs("div", { className: "flex flex-col justify-between gap-10 @4xl:col-span-6 @4xl:py-4", children: [_jsxs("div", { className: "flex flex-col gap-6", children: [_jsx(Eyebrow, { p: p }), _jsx(Heading, { p: p }), _jsx(Lead, { p: p })] }), _jsxs("div", { className: "flex flex-col gap-5", children: [actionsOf(p), _jsx(ContactLine, { p: p }), _jsx(Fineprint, { p: p })] })] }), p.media ? (_jsx("div", { className: "@4xl:col-span-5 @4xl:col-start-8", children: _jsx(BlockImage, { ...p.media, aspect: "4:5", sizes: "(min-width: 56rem) 40vw, 100vw", className: "h-full rounded-ui", components: p.components, labels: p.labels, editMode: p.editMode, field: "props.media" }) })) : null] }));
68
+ }
69
+ /* minimal --------------------------------------------------------------- */
70
+ function Minimal(p) {
71
+ const a = p.actions?.[0];
72
+ return (_jsxs(Container, { className: "flex flex-col items-center gap-10 text-center", children: [_jsx(Eyebrow, { p: p }), _jsx(Heading, { p: p, className: "max-w-[18ch]" }), _jsx(Lead, { p: p, className: "mx-auto" }), a ? (_jsxs(BlockLink, { href: a.link.href, newTab: a.link.newTab, components: p.components, labels: p.labels, locale: p.locale, editMode: p.editMode, field: "props.actions.0", className: "vb-cta-biglink group/big inline-flex items-center gap-[0.35em] rounded-[2px] font-display text-display-m text-fg underline decoration-1 decoration-accent underline-offset-[0.18em] transition-[text-decoration-thickness] hover:decoration-2 focus-ring", children: [a.link.label, _jsx(ArrowEnd, { className: "size-[0.8em] group-hover/big:translate-x-1 rtl:group-hover/big:-translate-x-1" })] })) : null, _jsx(ContactLine, { p: p, className: "justify-center" }), _jsx(Fineprint, { p: p })] }));
73
+ }
74
+ /* newsletter ------------------------------------------------------------ */
75
+ function Newsletter(p) {
76
+ const t = siteText(p.labels, p.locale);
77
+ const n = p.newsletter ?? {};
78
+ const { base } = useBlockIds(p.id, "newsletter");
79
+ const inputId = `${base}-email`;
80
+ const statusId = `${base}-status`;
81
+ const consentId = `${base}-consent`;
82
+ return (_jsxs(Container, { className: "grid gap-x-(--gutter) gap-y-8 @4xl:grid-cols-12 @4xl:items-end", children: [_jsxs("div", { className: "flex flex-col gap-5 @4xl:col-span-6", children: [_jsx(Eyebrow, { p: p }), _jsx(Heading, { p: p, size: "display-m" }), _jsx(Lead, { p: p })] }), _jsxs("div", { className: "flex flex-col gap-3 @4xl:col-span-5 @4xl:col-start-8", children: [n.status === "success" ? (_jsx("p", { id: statusId, role: "status", className: "border-s-2 border-accent ps-4 text-body text-fg", children: n.message ?? t("subscribed") })) : (_jsxs("form", { action: n.action, method: "post", className: "flex flex-col gap-3", ...field(p.editMode, "newsletter"), children: [_jsx("label", { htmlFor: inputId, className: "sr-only", children: t("emailLabel") }), _jsxs("div", { className: "flex flex-col gap-2 @2xl:flex-row", children: [_jsx("input", { id: inputId, name: "email", type: "email", required: true, autoComplete: "email", inputMode: "email", placeholder: n.placeholder ?? t("emailPlaceholder"), "aria-invalid": n.status === "error" ? true : undefined, "aria-describedby": [n.status === "error" ? statusId : null, n.consent ? consentId : null].filter(Boolean).join(" ") || undefined, className: "h-12 min-w-0 flex-1 rounded-ui border border-field-border bg-field px-4 text-body text-fg outline-none transition-colors placeholder:text-fg-subtle hover:border-field-border-hover focus-visible:border-ring focus-ring" }), _jsx("input", { type: "text", name: "company_website", tabIndex: -1, autoComplete: "off", "aria-hidden": true, className: "sr-only" }), _jsx("button", { type: "submit", className: "vb-action-primary inline-flex h-12 shrink-0 items-center justify-center rounded-ui bg-accent px-6 text-[15px] font-semibold text-accent-fg transition-[filter] hover:brightness-[1.04] focus-ring", children: n.buttonLabel ?? t("subscribe") })] }), n.status === "error" ? (_jsx("p", { id: statusId, role: "alert", className: "text-small text-danger", children: n.message ?? t("subscribeError") })) : null, n.consent ? (_jsx("div", { id: consentId, children: _jsx(RichText, { doc: n.consent, size: "sm", components: p.components, labels: p.labels, locale: p.locale, className: "text-fg-subtle [&_a]:text-fg-muted" }) })) : null] })), _jsx(Fineprint, { p: p })] })] }));
83
+ }
84
+ /* booking --------------------------------------------------------------- */
85
+ function Booking(p) {
86
+ const t = siteText(p.labels, p.locale);
87
+ const b = p.booking ?? { provider: "phone" };
88
+ const locale = p.locale ?? "en-US";
89
+ let control;
90
+ if (b.provider === "embed" && b.url) {
91
+ control = (_jsx("div", { className: "relative aspect-[16/10] overflow-hidden rounded-ui border border-line @4xl:aspect-[21/9]", children: _jsxs(EmbedFacade, { kind: "iframe", src: b.url, title: typeof p.title === "string" ? p.title.replace(/\*/g, "") : t("openCalendar"), buttonLabel: t("openCalendar"), children: [b.preview ? _jsx(BlockImage, { ...b.preview, decorative: true, aspect: "21:9", className: "absolute inset-0 h-full opacity-60", components: p.components }) : null, _jsxs("span", { className: "absolute inset-0 flex flex-col items-center justify-center gap-3 bg-[color-mix(in_oklch,var(--scene)_55%,transparent)] text-center", children: [_jsxs("span", { className: "inline-flex h-12 items-center gap-2.5 rounded-ui bg-fg px-6 text-[15px] font-semibold text-scene", children: [_jsx(CalendarDays, { "aria-hidden": true, strokeWidth: 1.5, className: "size-[18px]" }), t("openCalendar")] }), _jsx("span", { className: "text-small text-fg-muted", children: t("loadsCalendar", { provider: new URL(b.url).hostname.replace(/^www\./, "") }) })] })] }) }));
92
+ }
93
+ else if (b.provider === "phone") {
94
+ control = (_jsxs("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-3", children: [b.phone ? (_jsx(BlockLink, { href: `tel:${b.phone}`, appearance: "primary", components: p.components, labels: p.labels, "data-track": "call", children: formatSitePhone(b.phone, locale) })) : null, actionsOf(p, { forceStyle: "link" })] }));
95
+ }
96
+ else {
97
+ const fields = b.fields?.length ? b.fields : ["date", "time", "guests"];
98
+ const target = b.provider === "whatsapp" ? (b.whatsapp ?? "") : (b.url ?? "");
99
+ control = (_jsx(CtaBooking, { provider: b.provider === "whatsapp" ? "whatsapp" : "url", target: target, fields: fields, services: b.services, times: b.times, maxGuests: b.maxGuests, closedDays: b.closedDays, timeZone: b.timeZone, locale: locale, fallbackMessage: t("bookingFallback"), strings: {
100
+ date: t("date"),
101
+ time: t("time"),
102
+ guests: t("guests"),
103
+ service: t("service"),
104
+ guestsCount: siteTemplate(p.labels, "guestsCount"),
105
+ submit: t("askAvailability"),
106
+ opensWhatsApp: t("opensWhatsApp"),
107
+ closedOn: siteTemplate(p.labels, "closedOn"),
108
+ message: b.messageTemplate ?? siteTemplate(p.labels, "bookingMessage"),
109
+ messageService: b.messageTemplate ?? siteTemplate(p.labels, "bookingMessageService"),
110
+ } }));
111
+ }
112
+ return (_jsxs(Container, { className: "grid gap-x-(--gutter) gap-y-5 @4xl:grid-cols-12 @4xl:items-end", children: [_jsxs("div", { className: "flex flex-col gap-2 @4xl:col-span-4", children: [_jsx(Eyebrow, { p: p }), _jsx(Heading, { p: p, size: "h3" }), _jsx(Lead, { p: p, className: "text-body" })] }), _jsxs("div", { className: "flex flex-col gap-3 @4xl:col-span-8", children: [control, _jsx(Fineprint, { p: p })] })] }));
113
+ }
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ export interface EmbedFacadeProps {
3
+ /** `iframe`: YouTube/Vimeo/Calendly URL loaded on click. `video`: an MP4 played inline. */
4
+ kind: "iframe" | "video";
5
+ src: string;
6
+ /** Accessible title of the iframe / video. */
7
+ title: string;
8
+ /** The static preview (server-rendered poster image + play affordance). */
9
+ children: React.ReactNode;
10
+ /** Accessible name of the button ("Play video: Our kitchen"). */
11
+ buttonLabel: string;
12
+ /** `allow` attribute for the iframe. */
13
+ allow?: string;
14
+ className?: string;
15
+ }
16
+ /**
17
+ * Facade: a static preview that becomes the real embed only after a click (no third-party
18
+ * cookies or scripts before the visitor asks, ~0.5 KB). Focus moves into the embed.
19
+ */
20
+ export declare function EmbedFacade({ kind, src, title, children, buttonLabel, allow, className }: EmbedFacadeProps): React.JSX.Element;
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../../lib/cn.js";
5
+ import { SrName } from "../../lib/sr-name.js";
6
+ /**
7
+ * Facade: a static preview that becomes the real embed only after a click (no third-party
8
+ * cookies or scripts before the visitor asks, ~0.5 KB). Focus moves into the embed.
9
+ */
10
+ export function EmbedFacade({ kind, src, title, children, buttonLabel, allow = "autoplay; fullscreen; picture-in-picture; encrypted-media", className }) {
11
+ const [active, setActive] = React.useState(false);
12
+ const target = React.useRef(null);
13
+ React.useEffect(() => {
14
+ if (active)
15
+ target.current?.focus();
16
+ }, [active]);
17
+ if (active) {
18
+ return kind === "video" ? (_jsx("video", { ref: target, src: src, title: title, controls: true, autoPlay: true, playsInline: true, className: cn("size-full bg-scene object-cover", className) })) : (_jsx("iframe", { ref: target, src: src, title: title, allow: allow, allowFullScreen: true, loading: "lazy", className: cn("size-full border-0 bg-scene", className) }));
19
+ }
20
+ return (_jsx("button", { type: "button", onClick: () => setActive(true), className: cn("vb-facade group/facade relative block size-full text-start focus-ring", className), children: _jsx(SrName, { name: buttonLabel, children: children }) }));
21
+ }
@@ -0,0 +1,48 @@
1
+ import * as React from "react";
2
+ import type { BlockBaseProps } from "../types.js";
3
+ import { type RichDoc } from "../schema/rich-doc.js";
4
+ import { type SiteBlockLabels, type SiteCta } from "./_kit-1.js";
5
+ export type FaqVariant = "split" | "stacked" | "columns";
6
+ export interface FaqItem {
7
+ q: string;
8
+ /** RichDoc or plain text (blank line = paragraph). */
9
+ a: RichDoc | string;
10
+ /** Anchor id; default `faq-<slug of the question>` (locale-aware). */
11
+ id?: string;
12
+ }
13
+ export interface FaqProps extends Omit<BlockBaseProps, "variant" | "labels"> {
14
+ /**
15
+ * split: sticky title + "Can't find your question?" link on the start side, accordion on the end side.
16
+ * stacked: title above, accordion full width at a 42rem measure.
17
+ * columns: no accordion — every answer open in two columns (short answers, maximally indexable).
18
+ */
19
+ variant?: FaqVariant;
20
+ eyebrow?: React.ReactNode;
21
+ title?: React.ReactNode;
22
+ lead?: React.ReactNode;
23
+ items: FaqItem[];
24
+ /** Only one answer open at a time (native `<details name>`). Default true. */
25
+ exclusive?: boolean;
26
+ /** Open the first answer. Default false. */
27
+ openFirst?: boolean;
28
+ /** "Message us" link under the title. */
29
+ contact?: SiteCta;
30
+ /** Open the item matching `location.hash` (`#faq-parking`) — a 200-byte inline script. Default true. */
31
+ deepLink?: boolean;
32
+ labels?: SiteBlockLabels;
33
+ }
34
+ /** `FAQPage` JSON-LD for the items. */
35
+ export declare function faqJsonLd(items: {
36
+ q: string;
37
+ a: RichDoc | string;
38
+ }[]): Record<string, unknown>;
39
+ /**
40
+ * Questions and answers — 0 JS: native `<details name>` (exclusive accordion), animated with
41
+ * `::details-content` where supported; closed answers stay findable by in-page search.
42
+ * Server component.
43
+ *
44
+ * ```tsx
45
+ * <Faq title="Before you *book*" items={[{ q: "Is there parking?", a: "Yes — two hours free in the Piazza garage." }]} />
46
+ * ```
47
+ */
48
+ export declare function Faq({ variant, eyebrow, title, lead, items, exclusive, openFirst, contact, deepLink, id, theme, anchor, className, headingLevel, labels, locale, components, editMode, }: FaqProps): React.JSX.Element;
@@ -0,0 +1,52 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ import { slugify } from "../../lib/text.js";
4
+ import { Container, Section } from "../section.js";
5
+ import { SectionHeader } from "../section-header.js";
6
+ import { BlockLink } from "../block-link.js";
7
+ import { RichText } from "../rich-text.js";
8
+ import { richToText } from "../schema/rich-doc.js";
9
+ import { ArrowEnd, siteText, useBlockIds } from "./_kit-1.js";
10
+ import { Stagger } from "../../motion/reveal.js";
11
+ /** `FAQPage` JSON-LD for the items. */
12
+ export function faqJsonLd(items) {
13
+ return {
14
+ "@type": "FAQPage",
15
+ mainEntity: items.map((it) => ({
16
+ "@type": "Question",
17
+ name: it.q,
18
+ acceptedAnswer: { "@type": "Answer", text: typeof it.a === "string" ? it.a : richToText(it.a) },
19
+ })),
20
+ };
21
+ }
22
+ const DEEP_LINK = `(function(){var h=decodeURIComponent(location.hash.slice(1));if(!h)return;var d=document.getElementById(h);if(d&&d.tagName==="DETAILS")d.open=true;})();`;
23
+ /**
24
+ * Questions and answers — 0 JS: native `<details name>` (exclusive accordion), animated with
25
+ * `::details-content` where supported; closed answers stay findable by in-page search.
26
+ * Server component.
27
+ *
28
+ * ```tsx
29
+ * <Faq title="Before you *book*" items={[{ q: "Is there parking?", a: "Yes — two hours free in the Piazza garage." }]} />
30
+ * ```
31
+ */
32
+ export function Faq({ variant = "split", eyebrow, title, lead, items, exclusive = true, openFirst, contact, deepLink = true, id, theme, anchor, className, headingLevel = 2, labels, locale, components, editMode, }) {
33
+ const t = siteText(labels, locale);
34
+ const { base, headingId } = useBlockIds(id, "faq");
35
+ const QTag = `h${Math.min(headingLevel + 1, 6)}`;
36
+ const itemId = (it) => it.id ?? `faq-${slugify(it.q, { locale, maxLength: 48 })}`;
37
+ const answer = (it, i) => (_jsx(RichText, { doc: it.a, headingOffset: 2, components: components, labels: labels, locale: locale, editMode: editMode, field: `props.items.${i}.a`, className: "text-fg-muted" }));
38
+ const contactEl = contact ? (_jsxs("p", { className: "flex flex-col gap-1 text-small text-fg-muted", children: [_jsx("span", { children: t("faqMore") }), _jsxs(BlockLink, { href: contact.link.href, newTab: contact.link.newTab, appearance: "link", components: components, labels: labels, locale: locale, className: "w-fit text-body", children: [contact.link.label, _jsx(ArrowEnd, {})] })] })) : null;
39
+ const header = title || eyebrow || lead ? _jsx(SectionHeader, { eyebrow: eyebrow, title: title, lead: lead, headingLevel: headingLevel, headingId: headingId, editMode: editMode, labels: labels, locale: locale }) : null;
40
+ const list = variant === "columns" ? (_jsx(Stagger, { asChild: true, effect: "fade", disabled: editMode, children: _jsx("dl", { className: "grid gap-x-(--gutter) @4xl:grid-cols-2", children: items.map((it, i) => (_jsxs("div", { id: itemId(it), className: "flex flex-col gap-3 border-t border-line py-7", children: [_jsx("dt", { className: "text-h3 font-semibold tracking-[-0.012em] text-fg text-balance", "data-field": editMode ? `props.items.${i}.q` : undefined, children: it.q }), _jsx("dd", { className: "m-0", children: answer(it, i) })] }, i))) }) })) : (_jsx(Stagger, { asChild: true, effect: "fade", disabled: editMode, children: _jsx("div", { className: "vb-faq-list border-b border-line", children: items.map((it, i) => (_jsxs("details", { id: itemId(it), name: exclusive ? `${base}-faq` : undefined, open: openFirst && i === 0 ? true : undefined, className: "vb-faq-item group/faq border-t border-line", children: [_jsxs("summary", { className: "vb-faq-q flex cursor-pointer list-none items-start justify-between gap-6 py-6 text-start focus-ring rounded-[2px]", children: [_jsx(QTag, { className: "text-h3 font-semibold tracking-[-0.012em] text-fg text-balance", "data-field": editMode ? `props.items.${i}.q` : undefined, children: it.q }), _jsx("span", { "aria-hidden": true, className: "vb-faq-marker relative mt-[0.45em] size-3.5 shrink-0" })] }), _jsx("div", { className: "vb-faq-a max-w-[64ch] pb-7 pe-10", children: answer(it, i) })] }, i))) }) }));
41
+ let content;
42
+ if (variant === "split") {
43
+ content = (_jsxs(Container, { className: "grid gap-x-(--gutter) gap-y-10 @4xl:grid-cols-12", children: [_jsx("div", { className: "@4xl:col-span-4", children: _jsxs("div", { className: "flex flex-col gap-8 @4xl:sticky @4xl:top-[calc(var(--vb-nav-h,4.5rem)+2rem)]", children: [header, contactEl] }) }), _jsx("div", { className: "@4xl:col-span-7 @4xl:col-start-6", children: list })] }));
44
+ }
45
+ else if (variant === "stacked") {
46
+ content = (_jsxs(Container, { className: "flex flex-col gap-10", children: [header, _jsx("div", { className: "max-w-(--prose)", children: list }), contactEl] }));
47
+ }
48
+ else {
49
+ content = (_jsxs(Container, { className: "flex flex-col gap-10", children: [header ? _jsxs("div", { className: "flex flex-col gap-6 @4xl:flex-row @4xl:items-end @4xl:justify-between", children: [header, contactEl] }) : contactEl, list] }));
50
+ }
51
+ return (_jsxs(Section, { theme: theme, anchor: anchor, headingId: title ? headingId : undefined, blockId: base, blockType: "faq", editMode: editMode, className: cn("vb-faq", className), "data-variant": variant, children: [content, deepLink && variant !== "columns" ? _jsx("script", { dangerouslySetInnerHTML: { __html: DEEP_LINK } }) : null] }));
52
+ }
@@ -0,0 +1,46 @@
1
+ import * as React from "react";
2
+ import type { BlockBaseProps } from "../types.js";
3
+ import { type SiteBlockLabels, type SiteCta, type SiteImage } from "./_kit-1.js";
4
+ export type FeatureGridVariant = "list" | "grid" | "tabs" | "sticky-media";
5
+ export interface FeatureItem {
6
+ title: React.ReactNode;
7
+ text?: React.ReactNode;
8
+ /** Lucide name ("calendar-check") or a node. Small, before the title, never boxed. */
9
+ icon?: React.ReactNode;
10
+ media?: SiteImage;
11
+ /** Makes the whole row clickable (one link, stretched with `::after`). */
12
+ link?: {
13
+ href: string;
14
+ label?: React.ReactNode;
15
+ newTab?: boolean;
16
+ };
17
+ }
18
+ export interface FeatureGridProps extends Omit<BlockBaseProps, "variant" | "labels"> {
19
+ /**
20
+ * list (default): two columns of rows, hairline above each, mono 01 index, no cards.
21
+ * grid: 3–4 columns, a 1px top rule per item, optional small icon before the title.
22
+ * tabs: feature titles on the start side, the selected one's image on the end side.
23
+ * sticky-media: a sticky image on the start side swaps as the list scrolls (CSS view timelines).
24
+ */
25
+ variant?: FeatureGridVariant;
26
+ eyebrow?: React.ReactNode;
27
+ title?: React.ReactNode;
28
+ lead?: React.ReactNode;
29
+ /** Header actions (≤ 2). */
30
+ actions?: SiteCta[];
31
+ items: FeatureItem[];
32
+ /** Mono index numbers. Default: true for list, false otherwise. */
33
+ numbered?: boolean;
34
+ /** grid: column count on wide containers. Default 3. */
35
+ columns?: 2 | 3 | 4;
36
+ labels?: SiteBlockLabels;
37
+ }
38
+ /**
39
+ * Services, treatments or product modules — without the card wall. Server component; the `tabs`
40
+ * variant is a Radix Tabs island, `sticky-media` is CSS only.
41
+ *
42
+ * ```tsx
43
+ * <FeatureGrid title="What we *build*" items={[{ title: "Restaurant sites", text: "Menus your staff can edit…" }]} />
44
+ * ```
45
+ */
46
+ export declare function FeatureGrid({ variant, eyebrow, title, lead, actions, items, numbered, columns, id, theme, anchor, className, headingLevel, labels, locale, components, editMode, }: FeatureGridProps): React.JSX.Element;
@@ -0,0 +1,50 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ import { Container, Section } from "../section.js";
4
+ import { SectionHeader } from "../section-header.js";
5
+ import { BlockImage } from "../block-image.js";
6
+ import { BlockLink } from "../block-link.js";
7
+ import { FeatureTabs } from "./feature-tabs.js";
8
+ import { SiteIcon } from "./_site-icon-1.js";
9
+ import { ArrowEnd, indexLabel, useBlockIds } from "./_kit-1.js";
10
+ import { Stagger } from "../../motion/reveal.js";
11
+ const plain = (n) => (typeof n === "string" ? n : undefined);
12
+ /**
13
+ * Services, treatments or product modules — without the card wall. Server component; the `tabs`
14
+ * variant is a Radix Tabs island, `sticky-media` is CSS only.
15
+ *
16
+ * ```tsx
17
+ * <FeatureGrid title="What we *build*" items={[{ title: "Restaurant sites", text: "Menus your staff can edit…" }]} />
18
+ * ```
19
+ */
20
+ export function FeatureGrid({ variant = "list", eyebrow, title, lead, actions, items, numbered, columns = 3, id, theme, anchor, className, headingLevel = 2, labels, locale, components, editMode, }) {
21
+ const { base, headingId } = useBlockIds(id, "features");
22
+ // Two items never make a grid: fall back to the list.
23
+ const v = variant === "grid" && items.length <= 2 ? "list" : variant;
24
+ const showIndex = numbered ?? v === "list";
25
+ const ItemTag = `h${Math.min(headingLevel + 1, 6)}`;
26
+ const linkProps = { components, labels, locale };
27
+ const itemTitle = (it, i, cls) => (_jsx(ItemTag, { className: cn("text-h3 font-semibold tracking-[-0.012em] text-fg text-balance", cls), "data-field": editMode ? `props.items.${i}.title` : undefined, children: it.link ? (_jsx(BlockLink, { href: it.link.href, newTab: it.link.newTab, ...linkProps, className: "vb-stretched rounded-[2px] focus-ring", children: it.title })) : (it.title) }));
28
+ const itemText = (it, i, cls) => it.text ? (_jsx("p", { className: cn("text-body text-fg-muted text-pretty", cls), "data-field": editMode ? `props.items.${i}.text` : undefined, children: it.text })) : null;
29
+ const more = (it) => it.link?.label ? (_jsxs("span", { "aria-hidden": true, className: "mt-auto inline-flex items-center gap-1.5 pt-2 text-small font-medium text-fg", children: [it.link.label, _jsx(ArrowEnd, { className: "group-hover/fi:translate-x-0.5 rtl:group-hover/fi:-translate-x-0.5" })] })) : null;
30
+ let body;
31
+ if (v === "tabs") {
32
+ body = (_jsxs(_Fragment, { children: [_jsx(FeatureTabs, { className: "hidden @4xl:grid", label: plain(title), items: items.map((it, i) => ({
33
+ value: `f${i}`,
34
+ title: it.title,
35
+ text: it.text,
36
+ panel: (_jsxs("div", { className: "flex flex-col gap-4", children: [it.media ? _jsx(BlockImage, { ...it.media, aspect: "3:2", sizes: "(min-width: 56rem) 55vw, 100vw", className: "rounded-ui border border-line", components: components, labels: labels }) : null, it.link ? (_jsxs(BlockLink, { href: it.link.href, newTab: it.link.newTab, appearance: "link", ...linkProps, children: [it.link.label ?? it.title, _jsx(ArrowEnd, {})] })) : null] })),
37
+ })) }), _jsx("ol", { className: "flex flex-col @4xl:hidden", children: items.map((it, i) => (_jsxs("li", { className: "flex flex-col gap-3 border-t border-line py-6", children: [itemTitle(it, i), itemText(it, i), it.media ? _jsx(BlockImage, { ...it.media, aspect: "3:2", sizes: "100vw", className: "mt-2 rounded-ui border border-line", components: components, labels: labels }) : null] }, i))) })] }));
38
+ }
39
+ else if (v === "sticky-media") {
40
+ const names = items.map((_, i) => `--vbf-${base.replace(/[^a-zA-Z0-9_-]/g, "")}-${i}`);
41
+ body = (_jsxs("div", { className: "vb-sticky-features grid gap-x-(--gutter) @4xl:grid-cols-12", style: { timelineScope: names.join(", ") }, children: [_jsx("div", { className: "vb-sticky-media", "aria-hidden": true, children: _jsx("div", { className: "sticky top-[calc(var(--vb-nav-h,4.5rem)+2rem)]", children: _jsx("div", { className: "relative overflow-hidden rounded-ui", children: items.map((it, i) => it.media ? (_jsx(BlockImage, { ...it.media, decorative: true, aspect: "4:5", sizes: "(min-width: 56rem) 45vw, 100vw", className: cn("vb-sticky-frame", i > 0 && "absolute! inset-0"), "data-pos": i === 0 ? "first" : i === items.length - 1 ? "last" : undefined, style: { "--vbf-timeline": names[i], zIndex: i }, components: components }, i)) : null) }) }) }), _jsx("ol", { className: "vb-sticky-list flex flex-col", children: items.map((it, i) => (_jsxs("li", { className: "vb-sticky-item flex min-h-[min(70svh,34rem)] flex-col justify-center gap-4 border-t border-line py-10", style: { viewTimelineName: names[i] }, children: [it.media ? _jsx(BlockImage, { ...it.media, aspect: "3:2", sizes: "100vw", className: "vb-sticky-inline mb-2 rounded-ui", components: components, labels: labels }) : null, _jsx("span", { className: "font-mono text-eyebrow tabular text-fg-subtle", children: indexLabel(i) }), itemTitle(it, i, "text-display-m font-display font-normal"), itemText(it, i, "max-w-[46ch]"), it.link ? (_jsxs(BlockLink, { href: it.link.href, newTab: it.link.newTab, appearance: "link", ...linkProps, className: "mt-2", children: [it.link.label ?? it.title, _jsx(ArrowEnd, {})] })) : null] }, i))) })] }));
42
+ }
43
+ else if (v === "grid") {
44
+ body = (_jsx("ul", { className: cn("grid gap-x-(--gutter) gap-y-12 @2xl:grid-cols-2", columns >= 3 && "@4xl:grid-cols-3", columns === 4 && "@6xl:grid-cols-4", columns === 2 && "@4xl:grid-cols-2"), children: items.map((it, i) => (_jsxs("li", { className: cn("group/fi relative flex flex-col gap-3 border-t border-line pt-4", it.link && "vb-linked"), children: [it.media ? _jsx(BlockImage, { ...it.media, aspect: "3:2", sizes: "(min-width: 56rem) 30vw, 100vw", className: "mb-2 rounded-ui", components: components, labels: labels }) : null, _jsxs("div", { className: "flex items-start gap-3 pt-2", children: [showIndex ? _jsx("span", { className: "pt-1.5 font-mono text-eyebrow tabular text-fg-subtle", children: indexLabel(i) }) : null, it.icon ? _jsx(SiteIcon, { icon: it.icon, className: "mt-1" }) : null, itemTitle(it, i)] }), itemText(it, i), more(it)] }, i))) }));
45
+ }
46
+ else {
47
+ body = (_jsx("ol", { className: "grid gap-x-(--gutter) @4xl:grid-cols-2", children: items.map((it, i) => (_jsxs("li", { className: cn("group/fi relative grid grid-cols-[3rem_1fr] gap-x-4 gap-y-3 border-t border-line py-7 @2xl:grid-cols-[4.5rem_1fr]", it.link && "vb-linked", !showIndex && "grid-cols-1!"), children: [showIndex ? _jsx("span", { className: "row-span-3 pt-1.5 font-mono text-eyebrow tabular text-fg-subtle", children: indexLabel(i) }) : null, itemTitle(it, i), itemText(it, i, "max-w-[52ch]"), more(it)] }, i))) }));
48
+ }
49
+ return (_jsx(Section, { theme: theme, anchor: anchor, headingId: title ? headingId : undefined, blockId: base, blockType: "features", editMode: editMode, components: components, labels: labels, className: cn("vb-features", className), "data-variant": v, children: _jsxs(Container, { className: "flex flex-col gap-[calc(var(--section-y)*0.45)]", children: [title || eyebrow || lead ? (_jsx(SectionHeader, { eyebrow: eyebrow, title: title, lead: lead, align: lead ? "split" : "start", headingLevel: headingLevel, headingId: headingId, editMode: editMode, labels: labels, locale: locale, actions: actions?.length ? actions.map((a, i) => (_jsxs(BlockLink, { href: a.link.href, newTab: a.link.newTab, appearance: a.style ?? "link", ...linkProps, children: [a.link.label, (a.style ?? "link") === "link" ? _jsx(ArrowEnd, {}) : null] }, i))) : undefined })) : null, v === "list" || v === "grid" ? (_jsx(Stagger, { asChild: true, disabled: editMode, children: body })) : (_jsx("div", { children: body }))] }) }));
50
+ }
@@ -0,0 +1,22 @@
1
+ import * as React from "react";
2
+ export interface FeatureTabsItem {
3
+ value: string;
4
+ /** Tab label (feature title). */
5
+ title: React.ReactNode;
6
+ /** Short text under the active tab. */
7
+ text?: React.ReactNode;
8
+ /** Server-rendered panel (large image / screenshot + link). */
9
+ panel: React.ReactNode;
10
+ }
11
+ export interface FeatureTabsProps {
12
+ items: FeatureTabsItem[];
13
+ /** Accessible name of the tab list (the section title as text). */
14
+ label?: string;
15
+ defaultValue?: string;
16
+ className?: string;
17
+ }
18
+ /**
19
+ * Tabs island of the Feature grid `tabs` variant (WAI-ARIA Tabs via Radix, vertical arrow keys).
20
+ * Feature titles on the start side, the selected feature's media on the end side.
21
+ */
22
+ export declare function FeatureTabs({ items, label, defaultValue, className }: FeatureTabsProps): React.JSX.Element;
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Tabs } from "radix-ui";
4
+ import { cn } from "../../lib/cn.js";
5
+ /**
6
+ * Tabs island of the Feature grid `tabs` variant (WAI-ARIA Tabs via Radix, vertical arrow keys).
7
+ * Feature titles on the start side, the selected feature's media on the end side.
8
+ */
9
+ export function FeatureTabs({ items, label, defaultValue, className }) {
10
+ return (_jsxs(Tabs.Root, { orientation: "vertical", defaultValue: defaultValue ?? items[0]?.value, className: cn("grid gap-x-(--gutter) gap-y-8 @4xl:grid-cols-12", className), children: [_jsx(Tabs.List, { "aria-label": label, className: "flex flex-col border-s border-line @4xl:col-span-5", children: items.map((it) => (_jsxs(Tabs.Trigger, { value: it.value, className: "vb-feature-tab group/ft relative -ms-px flex flex-col items-start gap-2 border-s-2 border-transparent py-4 ps-6 pe-2 text-start outline-none transition-colors focus-ring data-[state=active]:border-accent", children: [_jsx("span", { className: "text-h3 font-semibold tracking-[-0.012em] text-fg-muted transition-colors group-hover/ft:text-fg group-data-[state=active]/ft:text-fg", children: it.title }), it.text ? _jsx("span", { className: "hidden max-w-[52ch] text-body text-fg-muted group-data-[state=active]/ft:block", children: it.text }) : null] }, it.value))) }), items.map((it) => (_jsx(Tabs.Content, { value: it.value, className: "outline-none focus-ring @4xl:col-span-7 vb-feature-panel", children: it.panel }, it.value)))] }));
11
+ }