@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,290 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ // SchemaForm: a form generated from a zod object schema + `f.*` metadata + field hints.
4
+ // The block inspector uses it; so can item settings, theme settings and form builders.
5
+ import * as React from "react";
6
+ import { ArrowDown, ArrowUp, ChevronRight, Plus, Trash2 } from "lucide-react";
7
+ import { cn } from "../lib/cn.js";
8
+ import { useLabels } from "../lib/labels.js";
9
+ import { getFieldMeta, isLocalizedSchema, schemaKind, unwrapSchema } from "../blocks/schema/fields.js";
10
+ import { BLOCK_ICONS } from "../blocks/schema/icons.js";
11
+ import { Field, Input, Textarea } from "../components/input.js";
12
+ import { Switch } from "../components/switch.js";
13
+ import { NativeSelect } from "../components/native-select.js";
14
+ import { ToggleGroup, ToggleGroupItem } from "../components/toggle.js";
15
+ import { Button, IconButton } from "../components/button.js";
16
+ import { blockEditorLabels } from "./labels.js";
17
+ import { RichTextEditor } from "./block-editor.js";
18
+ const humanize = (key) => key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/^\w/, (c) => c.toUpperCase());
19
+ const defOf = (s) => unwrapSchema(s)._zod.def;
20
+ const isOptional = (s) => {
21
+ const t = s._zod.def.type;
22
+ return t === "optional" || t === "default" || t === "prefault" || t === "nullable";
23
+ };
24
+ /** The inner schema of `Localized<T>` (`T | { [locale]: T }`). */
25
+ function localizedInner(s) {
26
+ const options = defOf(s).options;
27
+ return options?.[0] ?? s;
28
+ }
29
+ function readLocalized(v, locale) {
30
+ if (v && typeof v === "object" && !Array.isArray(v) && !("type" in v && v.type === "doc")) {
31
+ const map = v;
32
+ if (Object.keys(map).every((k) => /^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/.test(k)))
33
+ return map[locale] ?? map[Object.keys(map)[0]];
34
+ }
35
+ return v;
36
+ }
37
+ function writeLocalized(prev, next, locale) {
38
+ if (prev && typeof prev === "object" && !Array.isArray(prev) && !("type" in prev)) {
39
+ const map = prev;
40
+ if (Object.keys(map).length && Object.keys(map).every((k) => /^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/.test(k)))
41
+ return { ...map, [locale]: next };
42
+ }
43
+ return next;
44
+ }
45
+ function enumOptions(s) {
46
+ const d = defOf(s);
47
+ const entries = d.entries;
48
+ if (entries)
49
+ return Object.values(entries);
50
+ const values = d.values;
51
+ return (values ?? []).map(String);
52
+ }
53
+ function issuesOf(errors) {
54
+ if (!errors)
55
+ return [];
56
+ if (Array.isArray(errors))
57
+ return errors;
58
+ return errors.issues ?? [];
59
+ }
60
+ const pathKey = (p) => p.map(String).join(".");
61
+ function errorFor(ctx, path) {
62
+ const k = pathKey(path);
63
+ return ctx.issues.find((i) => pathKey(i.path) === k)?.message;
64
+ }
65
+ // ---------------------------------------------------------------- built-in widgets
66
+ function TextWidget({ id, value, onChange, meta, placeholder, invalid, disabled }) {
67
+ const v = typeof value === "string" ? value : "";
68
+ if (meta?.multiline || meta?.widget === "textarea")
69
+ return _jsx(Textarea, { id: id, value: v, rows: 3, maxLength: meta?.max, placeholder: placeholder, invalid: invalid, disabled: disabled, onChange: (e) => onChange(e.target.value || undefined) });
70
+ return _jsx(Input, { id: id, size: "sm", value: v, maxLength: meta?.max, showCount: !!meta?.max && meta.max <= 160, placeholder: placeholder, invalid: invalid, disabled: disabled, onChange: (e) => onChange(e.target.value || undefined) });
71
+ }
72
+ function UrlWidget({ id, value, onChange, placeholder, invalid, disabled }) {
73
+ return _jsx(Input, { id: id, size: "sm", type: "text", inputMode: "url", value: typeof value === "string" ? value : "", placeholder: placeholder ?? "/page or https://…", invalid: invalid, disabled: disabled, onChange: (e) => onChange(e.target.value || undefined) });
74
+ }
75
+ function NumberWidget({ id, value, onChange, meta, invalid, disabled }) {
76
+ return (_jsx(Input, { id: id, size: "sm", type: "number", inputMode: "decimal", min: meta?.min, max: meta?.max, value: typeof value === "number" ? String(value) : "", invalid: invalid, disabled: disabled, onChange: (e) => onChange(e.target.value === "" ? undefined : Number(e.target.value)), className: "tabular" }));
77
+ }
78
+ function SelectWidget({ id, value, onChange, schema, label, invalid, disabled, meta }) {
79
+ const options = meta?.field === "icon" ? [...BLOCK_ICONS] : enumOptions(schema);
80
+ const current = typeof value === "string" ? value : "";
81
+ if (options.length <= 4 && meta?.widget !== "select" && meta?.field !== "icon")
82
+ return (_jsx(ToggleGroup, { id: id, "aria-label": label, size: "sm", block: true, value: current, onValueChange: (v) => v && onChange(v), disabled: disabled, children: options.map((o) => (_jsx(ToggleGroupItem, { value: o, className: "capitalize", children: humanize(o) }, o))) }));
83
+ return _jsx(NativeSelect, { id: id, size: "sm", value: current, invalid: invalid, disabled: disabled, placeholder: current ? undefined : "—", items: options.map((o) => ({ value: o, label: humanize(o) })), onChange: (e) => onChange(e.target.value) });
84
+ }
85
+ function ToggleWidget({ id, value, onChange, disabled, label }) {
86
+ return _jsx(Switch, { id: id, size: "sm", "aria-label": label, checked: value === true, disabled: disabled, onCheckedChange: (c) => onChange(c) });
87
+ }
88
+ function RichWidget({ id, value, onChange, placeholder, invalid, disabled }) {
89
+ return _jsx(RichTextEditor, { id: id, size: "sm", minHeight: "5.5rem", maxHeight: "16rem", value: value, onChange: (d) => onChange(d), placeholder: placeholder, invalid: invalid, readOnly: disabled, toolbar: true });
90
+ }
91
+ function JsonWidget({ id, value, onChange, invalid, disabled }) {
92
+ const [text, setText] = React.useState(() => JSON.stringify(value ?? null, null, 2));
93
+ const [bad, setBad] = React.useState(false);
94
+ return (_jsx(Textarea, { id: id, rows: 4, value: text, invalid: invalid || bad, disabled: disabled, className: "font-mono text-xs", onChange: (e) => {
95
+ setText(e.target.value);
96
+ try {
97
+ onChange(JSON.parse(e.target.value));
98
+ setBad(false);
99
+ }
100
+ catch {
101
+ setBad(true);
102
+ }
103
+ } }));
104
+ }
105
+ const BUILTIN = {
106
+ text: TextWidget,
107
+ textarea: TextWidget,
108
+ "inline-text": TextWidget,
109
+ url: UrlWidget,
110
+ number: NumberWidget,
111
+ select: SelectWidget,
112
+ segmented: SelectWidget,
113
+ toggle: ToggleWidget,
114
+ switch: ToggleWidget,
115
+ rich: RichWidget,
116
+ richtext: RichWidget,
117
+ json: JsonWidget,
118
+ };
119
+ function widgetFor(schema, meta, hint) {
120
+ if (hint?.widget)
121
+ return hint.widget;
122
+ if (meta?.widget)
123
+ return meta.widget;
124
+ switch (meta?.field) {
125
+ case "heading":
126
+ case "text":
127
+ return "text";
128
+ case "rich":
129
+ return "rich";
130
+ case "select":
131
+ case "icon":
132
+ return "select";
133
+ case "toggle":
134
+ return "toggle";
135
+ case "number":
136
+ return "number";
137
+ case "list":
138
+ case "social":
139
+ return "list";
140
+ case "group":
141
+ case "image":
142
+ case "link":
143
+ case "cta":
144
+ case "money":
145
+ case "address":
146
+ return "group";
147
+ case "phone":
148
+ case "date":
149
+ return "text";
150
+ }
151
+ const kind = schemaKind(schema);
152
+ if (kind === "string")
153
+ return "text";
154
+ if (kind === "number")
155
+ return "number";
156
+ if (kind === "boolean")
157
+ return "toggle";
158
+ if (kind === "enum" || kind === "literal")
159
+ return "select";
160
+ if (kind === "array")
161
+ return "list";
162
+ if (kind === "object")
163
+ return "group";
164
+ return "json";
165
+ }
166
+ function FieldNode({ ctx, name, schema, value, onChange, path, hint, nested }) {
167
+ const id = React.useId();
168
+ const meta = getFieldMeta(schema);
169
+ const localized = isLocalizedSchema(schema);
170
+ const inner = localized ? localizedInner(unwrapSchema(schema)) : unwrapSchema(schema);
171
+ const label = hint?.label ?? meta?.label ?? humanize(name);
172
+ const help = hint?.help ?? meta?.help;
173
+ const placeholder = hint?.placeholder ?? meta?.placeholder;
174
+ const error = errorFor(ctx, path);
175
+ const required = !isOptional(schema);
176
+ if (meta?.variants && ctx.variant && !meta.variants.includes(ctx.variant))
177
+ return null;
178
+ const plain = localized ? readLocalized(value, ctx.locale) : value;
179
+ const write = (v) => onChange(localized ? writeLocalized(value, v, ctx.locale) : v);
180
+ const widget = widgetFor(inner, meta, hint);
181
+ if (widget === "group")
182
+ return _jsx(GroupNode, { ctx: ctx, label: label, help: help, schema: inner, value: plain, onChange: write, path: path, nested: nested });
183
+ if (widget === "list")
184
+ return _jsx(ListNode, { ctx: ctx, label: label, help: help, schema: inner, meta: meta, value: plain, onChange: write, path: path, error: error });
185
+ const Widget = ctx.widgets?.[widget] ?? BUILTIN[widget] ?? JsonWidget;
186
+ const horizontal = widget === "toggle" || widget === "switch";
187
+ return (_jsx(Field, { id: id, label: label, hint: help, error: error, required: required && widget !== "toggle", orientation: horizontal ? "horizontal" : "vertical", children: _jsx(Widget, { id: id, value: plain, onChange: write, schema: inner, meta: meta, label: label, placeholder: placeholder, invalid: !!error, disabled: ctx.disabled, locale: ctx.locale }) }));
188
+ }
189
+ function GroupNode({ ctx, label, help, schema, value, onChange, path, nested }) {
190
+ const shape = (unwrapSchema(schema).shape ?? {});
191
+ const obj = (value && typeof value === "object" ? value : {});
192
+ const legendId = React.useId();
193
+ return (_jsxs("fieldset", { className: cn("vui-sf-group", nested && "is-nested"), "aria-labelledby": legendId, children: [_jsx("legend", { id: legendId, className: "vui-sf-legend", children: label }), help ? _jsx("p", { className: "-mt-1 text-xs text-fg-muted", children: help }) : null, Object.entries(shape).map(([k, s]) => (_jsx(FieldNode, { ctx: ctx, name: k, schema: s, value: obj[k], path: [...path, k], onChange: (v) => onChange(compact({ ...obj, [k]: v })), nested: true }, k)))] }));
194
+ }
195
+ const compact = (o) => {
196
+ const r = {};
197
+ for (const [k, v] of Object.entries(o))
198
+ if (v !== undefined)
199
+ r[k] = v;
200
+ return r;
201
+ };
202
+ function itemSummary(item) {
203
+ if (typeof item === "string")
204
+ return item;
205
+ if (!item || typeof item !== "object")
206
+ return null;
207
+ for (const k of ["title", "q", "label", "name", "heading", "text"]) {
208
+ const v = item[k];
209
+ if (typeof v === "string" && v.trim())
210
+ return v;
211
+ if (v && typeof v === "object") {
212
+ const first = Object.values(v).find((x) => typeof x === "string");
213
+ if (typeof first === "string")
214
+ return first;
215
+ }
216
+ }
217
+ const link = item.link?.label;
218
+ if (typeof link === "string")
219
+ return link;
220
+ return null;
221
+ }
222
+ function ListNode({ ctx, label, help, schema, meta, value, onChange, path, error }) {
223
+ const { t } = ctx;
224
+ const element = defOf(schema).element;
225
+ const list = Array.isArray(value) ? value : [];
226
+ const [open, setOpen] = React.useState(list.length ? 0 : null);
227
+ const headingId = React.useId();
228
+ const max = meta?.max;
229
+ const itemName = (i) => (meta?.itemLabel ? meta.itemLabel.replace("{n}", String(i + 1)) : t("itemN", { n: i + 1 }));
230
+ const blank = () => {
231
+ if (!element)
232
+ return "";
233
+ const kind = schemaKind(element);
234
+ if (kind === "object")
235
+ return {};
236
+ if (kind === "string")
237
+ return "";
238
+ if (kind === "number")
239
+ return 0;
240
+ return null;
241
+ };
242
+ const move = (i, d) => {
243
+ const j = i + d;
244
+ if (j < 0 || j >= list.length)
245
+ return;
246
+ const next = [...list];
247
+ [next[i], next[j]] = [next[j], next[i]];
248
+ onChange(next);
249
+ setOpen(j);
250
+ };
251
+ return (_jsxs("section", { className: "vui-sf-list", "aria-labelledby": headingId, children: [_jsx("div", { className: "flex items-baseline justify-between gap-2", children: _jsxs("h4", { id: headingId, className: "vui-sf-legend", children: [label, " ", _jsx("span", { className: "font-normal tabular text-fg-subtle", children: list.length })] }) }), help ? _jsx("p", { className: "-mt-1 text-xs text-fg-muted", children: help }) : null, error ? (_jsx("p", { className: "text-xs text-danger", role: "alert", children: error })) : null, _jsx("ol", { className: "flex flex-col gap-1.5", children: list.map((item, i) => {
252
+ const name = itemSummary(item) ?? itemName(i);
253
+ const expanded = open === i;
254
+ const panelId = `${headingId}-${i}`;
255
+ const itemError = ctx.issues.some((iss) => pathKey(iss.path).startsWith(pathKey([...path, i])));
256
+ return (_jsxs("li", { className: "vui-sf-item", "data-open": expanded ? "" : undefined, "data-invalid": itemError ? "" : undefined, children: [_jsxs("div", { className: "flex items-center gap-1", children: [_jsxs("button", { type: "button", className: "vui-sf-item-head focus-ring", "aria-expanded": expanded, "aria-controls": panelId, onClick: () => setOpen(expanded ? null : i), children: [_jsx(ChevronRight, { "aria-hidden": true, className: "size-3.5 shrink-0 text-fg-subtle transition-transform rtl:-scale-x-100" }), _jsx("span", { className: "truncate", children: name })] }), _jsx(IconButton, { size: "xs", label: t("moveItemUp", { label: name }), disabled: i === 0 || ctx.disabled, onClick: () => move(i, -1), children: _jsx(ArrowUp, {}) }), _jsx(IconButton, { size: "xs", label: t("moveItemDown", { label: name }), disabled: i === list.length - 1 || ctx.disabled, onClick: () => move(i, 1), children: _jsx(ArrowDown, {}) }), _jsx(IconButton, { size: "xs", variant: "danger-ghost", label: t("removeItem", { label: name }), disabled: ctx.disabled || (meta?.min !== undefined && list.length <= meta.min), onClick: () => {
257
+ onChange(list.filter((_, j) => j !== i));
258
+ setOpen(null);
259
+ }, children: _jsx(Trash2, {}) })] }), expanded && element ? (_jsx("div", { id: panelId, className: "vui-sf-item-body", children: _jsx(FieldNode, { ctx: ctx, name: itemName(i), schema: element, value: item, path: [...path, i], onChange: (v) => onChange(list.map((x, j) => (j === i ? v : x))), nested: true }) })) : null] }, i));
260
+ }) }), _jsxs(Button, { size: "xs", variant: "ghost", className: "self-start", disabled: ctx.disabled || (max !== undefined && list.length >= max), onClick: () => {
261
+ onChange([...list, blank()]);
262
+ setOpen(list.length);
263
+ }, children: [_jsx(Plus, { "aria-hidden": true }), t("addItem", { label: (meta?.itemLabel ?? label).replace(/\s*\{n\}/, "").toLowerCase() })] })] }));
264
+ }
265
+ // ---------------------------------------------------------------- SchemaForm
266
+ const GROUP_ORDER = ["content", "style", "advanced"];
267
+ /**
268
+ * A form generated from a zod object schema. Widgets come from `f.*` metadata (heading, rich,
269
+ * image, list…), the zod type, or a hint (`fields.title.widget = "textarea"`). Localized fields
270
+ * edit the `locale` entry. Arrays are sortable lists with add / remove / move (keyboard only).
271
+ *
272
+ * ```tsx
273
+ * <SchemaForm schema={faqBlock.schema} value={props} onChange={setProps} errors={result.error} locale="en" />
274
+ * ```
275
+ */
276
+ export function SchemaForm({ schema, value, onChange, fields, widgets, errors, layout = "sidebar", variant, locale = "en", disabled, labels, className }) {
277
+ const t = useLabels("blockEditor", blockEditorLabels, labels);
278
+ const ctx = { t, widgets, issues: issuesOf(errors), locale, disabled, variant };
279
+ const shape = (schema.shape ?? {});
280
+ const entries = Object.entries(shape).filter(([k]) => {
281
+ const h = fields?.[k];
282
+ return !h?.hidden && (!h?.when || h.when(value));
283
+ });
284
+ const grouped = GROUP_ORDER.map((g) => ({ g, list: entries.filter(([k]) => (fields?.[k]?.group ?? "content") === g) })).filter((x) => x.list.length);
285
+ const other = entries.filter(([k]) => !GROUP_ORDER.includes(fields?.[k]?.group ?? "content"));
286
+ if (other.length)
287
+ grouped.push({ g: "advanced", list: other });
288
+ const titles = { content: t("content"), style: t("style"), advanced: t("advanced") };
289
+ return (_jsx("div", { "data-slot": "schema-form", "data-layout": layout, className: cn("vui-sf", className), children: grouped.map(({ g, list }) => (_jsxs("section", { className: "vui-sf-section", "aria-label": titles[g], children: [grouped.length > 1 ? _jsx("h3", { className: "vui-eyebrow", children: titles[g] }) : null, _jsx("div", { className: cn("flex flex-col gap-3.5", layout === "dialog" && "sm:grid sm:grid-cols-2 sm:gap-x-5"), children: list.map(([k, s]) => (_jsx(FieldNode, { ctx: ctx, name: k, schema: s, value: value[k], path: [k], hint: fields?.[k], onChange: (v) => onChange(compact({ ...value, [k]: v })) }, k))) })] }, g))) }));
290
+ }
@@ -0,0 +1,15 @@
1
+ import * as React from "react";
2
+ import { type InsertItem } from "./items.js";
3
+ /** Items for the current editor, filtered by `allowedBlocks`. */
4
+ export declare function useInsertItems(): InsertItem[];
5
+ /** Search over title + keywords, folded for the UI locale ("İ" matches "i" in Turkish). */
6
+ export declare function searchItems(items: InsertItem[], query: string, locale: string): InsertItem[];
7
+ export interface BlockEditorSlashMenuProps {
8
+ className?: string;
9
+ }
10
+ /**
11
+ * The "/" inserter: type `/` in an empty line (or after a space), then filter, arrow, Enter.
12
+ * A cmdk listbox driven from the editor (focus stays in the text; `aria-activedescendant`
13
+ * follows the highlighted option). Esc closes and leaves the typed text.
14
+ */
15
+ export declare function BlockEditorSlashMenu({ className }: BlockEditorSlashMenuProps): React.ReactPortal | null;
@@ -0,0 +1,119 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { createPortal } from "react-dom";
5
+ import { cn } from "../lib/cn.js";
6
+ import { useLocale } from "../lib/locale.js";
7
+ import { matchText } from "../lib/text.js";
8
+ import { Layer } from "../lib/layer.js";
9
+ import { usePortalContainer } from "../lib/theme-scope.js";
10
+ import { Command, CommandGroup, CommandItem, CommandList } from "../components/command.js";
11
+ import { Kbd } from "../components/kbd.js";
12
+ import { useBlockEditor, useSlashState } from "./context.js";
13
+ import { filterAllowed, registryItems, runInsert, textItems } from "./items.js";
14
+ const GROUP_ORDER = ["text", "media", "layout", "blocks"];
15
+ const GROUP_LABEL = { text: "groupText", media: "groupMedia", layout: "groupLayout", blocks: "groupBlocks", patterns: "groupPatterns" };
16
+ /** Items for the current editor, filtered by `allowedBlocks`. */
17
+ export function useInsertItems() {
18
+ const { t, registry, variant, allowedTypes } = useBlockEditor();
19
+ return React.useMemo(() => {
20
+ const richText = variant === "rich-text";
21
+ const all = [...textItems(t, { richText }), ...(richText ? [] : registryItems(registry))];
22
+ return filterAllowed(all, allowedTypes());
23
+ }, [t, registry, variant, allowedTypes]);
24
+ }
25
+ /** Search over title + keywords, folded for the UI locale ("İ" matches "i" in Turkish). */
26
+ export function searchItems(items, query, locale) {
27
+ const q = query.trim();
28
+ if (!q)
29
+ return items;
30
+ return items.filter((it) => matchText(it.title, q, locale) || it.keywords.some((k) => matchText(k, q, locale)));
31
+ }
32
+ /**
33
+ * The "/" inserter: type `/` in an empty line (or after a space), then filter, arrow, Enter.
34
+ * A cmdk listbox driven from the editor (focus stays in the text; `aria-activedescendant`
35
+ * follows the highlighted option). Esc closes and leaves the typed text.
36
+ */
37
+ export function BlockEditorSlashMenu({ className }) {
38
+ const { editor, slash, t, lang } = useBlockEditor();
39
+ const { locale } = useLocale();
40
+ const state = useSlashState(slash);
41
+ const items = useInsertItems();
42
+ const results = React.useMemo(() => (state ? searchItems(items, state.query, locale) : []), [items, state, locale]);
43
+ const grouped = React.useMemo(() => GROUP_ORDER.map((g) => ({ g, list: results.filter((r) => r.group === g) })).filter((x) => x.list.length), [results]);
44
+ const flat = React.useMemo(() => grouped.flatMap((x) => x.list), [grouped]);
45
+ const [active, setActive] = React.useState(0);
46
+ const listRef = React.useRef(null);
47
+ const container = usePortalContainer();
48
+ const listId = React.useId();
49
+ React.useEffect(() => setActive(0), [state?.query]);
50
+ const choose = React.useCallback((item) => {
51
+ if (!editor || !state || !item)
52
+ return;
53
+ runInsert(editor, item, { lang, range: state.range });
54
+ slash.set(null);
55
+ }, [editor, state, lang, slash]);
56
+ // Keys arrive from the editor while the menu is open.
57
+ React.useEffect(() => {
58
+ slash.keydown.current = (e) => {
59
+ if (!flat.length)
60
+ return false;
61
+ if (e.key === "ArrowDown") {
62
+ setActive((a) => (a + 1) % flat.length);
63
+ return true;
64
+ }
65
+ if (e.key === "ArrowUp") {
66
+ setActive((a) => (a - 1 + flat.length) % flat.length);
67
+ return true;
68
+ }
69
+ if (e.key === "Enter" || e.key === "Tab") {
70
+ choose(flat[active]);
71
+ return true;
72
+ }
73
+ return false;
74
+ };
75
+ return () => {
76
+ slash.keydown.current = null;
77
+ };
78
+ }, [slash, flat, active, choose]);
79
+ // Combobox wiring on the contenteditable while open.
80
+ React.useEffect(() => {
81
+ const dom = editor?.view.dom;
82
+ if (!dom)
83
+ return;
84
+ if (!state) {
85
+ ["aria-controls", "aria-expanded", "aria-activedescendant", "aria-autocomplete", "aria-haspopup"].forEach((a) => dom.removeAttribute(a));
86
+ return;
87
+ }
88
+ dom.setAttribute("aria-haspopup", "listbox");
89
+ dom.setAttribute("aria-expanded", "true");
90
+ dom.setAttribute("aria-autocomplete", "list");
91
+ const list = listRef.current?.querySelector("[cmdk-list]") ?? listRef.current;
92
+ if (list?.id)
93
+ dom.setAttribute("aria-controls", list.id);
94
+ // cmdk marks the highlighted item after its own render: read it on the next tick.
95
+ const id = setTimeout(() => {
96
+ const sel = listRef.current?.querySelector('[cmdk-item][aria-selected="true"]');
97
+ if (sel?.id)
98
+ dom.setAttribute("aria-activedescendant", sel.id);
99
+ else
100
+ dom.removeAttribute("aria-activedescendant");
101
+ }, 0);
102
+ return () => clearTimeout(id);
103
+ });
104
+ React.useEffect(() => {
105
+ listRef.current?.querySelector('[cmdk-item][aria-selected="true"]')?.scrollIntoView({ block: "nearest" });
106
+ }, [active]);
107
+ if (!state || !editor || typeof document === "undefined")
108
+ return null;
109
+ const rect = state.rect;
110
+ const vh = typeof window !== "undefined" ? window.innerHeight : 800;
111
+ const below = !rect || rect.bottom + 340 < vh || rect.top < 340;
112
+ const style = rect
113
+ ? below
114
+ ? { position: "fixed", top: rect.bottom + 6, left: Math.max(8, rect.left - 8) }
115
+ : { position: "fixed", bottom: vh - rect.top + 6, left: Math.max(8, rect.left - 8) }
116
+ : { position: "fixed", top: 80, left: 24 };
117
+ const menu = (_jsx(Layer, { ref: listRef, "data-slot": "block-editor-slash", className: cn("vui-slash surface-popover ui-pop z-(--z-popover) rounded-ui-lg", className), style: style, onMouseDown: (e) => e.preventDefault(), children: _jsx(Command, { shouldFilter: false, value: flat[active]?.id ?? "", onValueChange: (v) => setActive(Math.max(0, flat.findIndex((f) => f.id === v))), label: t("insert"), loop: true, children: _jsx(CommandList, { id: listId, label: t("insert"), className: "max-h-[min(20rem,50dvh)]", children: flat.length ? (grouped.map(({ g, list }) => (_jsx(CommandGroup, { heading: t(GROUP_LABEL[g]), children: list.map((it) => (_jsx(CommandItem, { value: it.id, icon: _jsx("span", { className: "vui-slash-icon", children: _jsx(it.icon, { className: "size-4" }) }), description: it.hint, onSelect: () => choose(it), badge: it.shortcut ? _jsx(Kbd, { size: "sm", variant: "ghost", children: it.shortcut }) : undefined, children: it.title }, it.id))) }, g)))) : (_jsx("p", { className: "px-3 py-6 text-center text-sm text-fg-muted", role: "status", children: t("noBlocks", { query: state.query }) })) }) }) }));
118
+ return createPortal(menu, container ?? document.body);
119
+ }
@@ -0,0 +1,53 @@
1
+ export type FontCategory = "sans" | "serif" | "display" | "rounded" | "condensed" | "mono" | "handwriting";
2
+ /** Sub-classification inside `sans` (geometric · humanist · grotesk) and `serif` (text · display). */
3
+ export type FontStyle = "geometric" | "humanist" | "grotesk" | "text" | "display";
4
+ export interface FontAxis {
5
+ /** OpenType axis tag: `wght`, `opsz`, `wdth`, `ital`, `slnt` or a custom one (`SOFT`, `WONK`…). */
6
+ tag: string;
7
+ min: number;
8
+ max: number;
9
+ }
10
+ export interface GoogleFont {
11
+ /** Exact Google Fonts family name, e.g. `"Bricolage Grotesque"`. */
12
+ family: string;
13
+ /** URL-safe id, e.g. `"bricolage-grotesque"`. */
14
+ id: string;
15
+ category: FontCategory;
16
+ style?: FontStyle;
17
+ /** Available weights (static instances, or named stops of the variable range). */
18
+ weights: number[];
19
+ /** Has true italics. */
20
+ italics: boolean;
21
+ /** Variable axes; empty for static families. */
22
+ axes: FontAxis[];
23
+ /** Character subsets offered by Google Fonts. */
24
+ subsets: string[];
25
+ /** One line: what it is good for. */
26
+ use: string;
27
+ }
28
+ export interface FontGroup {
29
+ id: string;
30
+ label: string;
31
+ category: FontCategory;
32
+ style?: FontStyle;
33
+ }
34
+ /** The catalog, grouped in display order. */
35
+ export declare const fontGroups: FontGroup[];
36
+ /** Top-level categories with labels, in display order. */
37
+ export declare const fontCategories: {
38
+ id: FontCategory;
39
+ label: string;
40
+ }[];
41
+ /** 59 Google Fonts families, all with latin-ext. */
42
+ export declare const googleFonts: GoogleFont[];
43
+ /** Look a family up by name (case-insensitive) or id. */
44
+ export declare function getFont(familyOrId: string): GoogleFont | undefined;
45
+ /** The group a font belongs to. */
46
+ export declare function fontGroupOf(font: GoogleFont): FontGroup;
47
+ /** Is the family variable (has a `wght` axis)? */
48
+ export declare function isVariableFont(font: GoogleFont): boolean;
49
+ /**
50
+ * CSS `font-family` value for a family: the quoted name plus a category fallback.
51
+ * A name that is not in the catalog is treated as a ready CSS stack and returned as is.
52
+ */
53
+ export declare function fontStack(family: string): string;
@@ -0,0 +1,121 @@
1
+ // Google Fonts catalog for Vamos UI. Generated from https://fonts.google.com/metadata/fonts
2
+ // (2026-11-10) and curated by hand. Every family covers latin-ext (Turkish ğ ş ı İ ç ö ü).
3
+ /** The catalog, grouped in display order. */
4
+ export const fontGroups = [
5
+ { id: "sans-geometric", label: "Sans · Geometric", category: "sans", style: "geometric" },
6
+ { id: "sans-humanist", label: "Sans · Humanist", category: "sans", style: "humanist" },
7
+ { id: "sans-grotesk", label: "Sans · Grotesk", category: "sans", style: "grotesk" },
8
+ { id: "serif-text", label: "Serif · Text", category: "serif", style: "text" },
9
+ { id: "serif-display", label: "Serif · Display", category: "serif", style: "display" },
10
+ { id: "display", label: "Display", category: "display" },
11
+ { id: "rounded", label: "Rounded", category: "rounded" },
12
+ { id: "condensed", label: "Condensed", category: "condensed" },
13
+ { id: "mono", label: "Mono", category: "mono" },
14
+ { id: "handwriting", label: "Handwriting", category: "handwriting" },
15
+ ];
16
+ /** Top-level categories with labels, in display order. */
17
+ export const fontCategories = [
18
+ { id: "sans", label: "Sans" },
19
+ { id: "serif", label: "Serif" },
20
+ { id: "display", label: "Display" },
21
+ { id: "rounded", label: "Rounded" },
22
+ { id: "condensed", label: "Condensed" },
23
+ { id: "mono", label: "Mono" },
24
+ { id: "handwriting", label: "Handwriting" },
25
+ ];
26
+ /** 59 Google Fonts families, all with latin-ext. */
27
+ export const googleFonts = [
28
+ { family: "Outfit", id: "outfit", category: "sans", style: "geometric", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: false, axes: [{ tag: "wght", min: 100, max: 900 }], subsets: ["latin", "latin-ext"], use: "Product UI and SaaS sites; clean circles, friendly at every weight." },
29
+ { family: "Sora", id: "sora", category: "sans", style: "geometric", weights: [100, 200, 300, 400, 500, 600, 700, 800], italics: false, axes: [{ tag: "wght", min: 100, max: 800 }], subsets: ["latin", "latin-ext"], use: "Tech and fintech headlines; wide, confident and slightly futuristic." },
30
+ { family: "Plus Jakarta Sans", id: "plus-jakarta-sans", category: "sans", style: "geometric", weights: [200, 300, 400, 500, 600, 700, 800], italics: true, axes: [{ tag: "wght", min: 200, max: 800 }], subsets: ["cyrillic-ext", "latin", "latin-ext", "vietnamese"], use: "Modern dashboards and marketing; open counters, crisp at 13px." },
31
+ { family: "Manrope", id: "manrope", category: "sans", style: "geometric", weights: [200, 300, 400, 500, 600, 700, 800], italics: false, axes: [{ tag: "wght", min: 200, max: 800 }], subsets: ["cyrillic", "cyrillic-ext", "greek", "latin", "latin-ext", "vietnamese"], use: "Dense admin tables; semi-condensed geometry with clear numerals." },
32
+ { family: "Urbanist", id: "urbanist", category: "sans", style: "geometric", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 100, max: 900 }], subsets: ["latin", "latin-ext"], use: "Fashion, hospitality and lifestyle brands; airy and elegant." },
33
+ { family: "Lexend", id: "lexend", category: "sans", style: "geometric", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: false, axes: [{ tag: "wght", min: 100, max: 900 }], subsets: ["latin", "latin-ext", "vietnamese"], use: "Long reading and accessibility-first UIs; tuned for reading speed." },
34
+ { family: "Red Hat Display", id: "red-hat-display", category: "sans", style: "geometric", weights: [300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 300, max: 900 }], subsets: ["latin", "latin-ext"], use: "Bold product headlines; pairs with Red Hat Mono." },
35
+ { family: "Onest", id: "onest", category: "sans", style: "humanist", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: false, axes: [{ tag: "wght", min: 100, max: 900 }], subsets: ["cyrillic", "cyrillic-ext", "latin", "latin-ext", "math", "symbols", "vietnamese"], use: "Default UI face; warm, compact and very legible in Turkish." },
36
+ { family: "Figtree", id: "figtree", category: "sans", style: "humanist", weights: [300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 300, max: 900 }], subsets: ["latin", "latin-ext"], use: "Friendly product UI and onboarding; soft geometric-humanist hybrid." },
37
+ { family: "DM Sans", id: "dm-sans", category: "sans", style: "humanist", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000], italics: true, axes: [{ tag: "opsz", min: 9, max: 40 }, { tag: "wght", min: 100, max: 1000 }], subsets: ["latin", "latin-ext"], use: "Low-contrast UI text; optical sizes keep small labels open." },
38
+ { family: "IBM Plex Sans", id: "ibm-plex-sans", category: "sans", style: "humanist", weights: [100, 200, 300, 400, 500, 600, 700], italics: true, axes: [{ tag: "wdth", min: 75, max: 100 }, { tag: "wght", min: 100, max: 700 }], subsets: ["cyrillic", "cyrillic-ext", "greek", "latin", "latin-ext", "vietnamese"], use: "Corporate, finance and B2B panels; engineered and neutral." },
39
+ { family: "Source Sans 3", id: "source-sans-3", category: "sans", style: "humanist", weights: [200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 200, max: 900 }], subsets: ["cyrillic", "cyrillic-ext", "greek", "greek-ext", "latin", "latin-ext", "vietnamese"], use: "Long forms and documentation; calm, proven workhorse." },
40
+ { family: "Instrument Sans", id: "instrument-sans", category: "sans", style: "humanist", weights: [400, 500, 600, 700], italics: true, axes: [{ tag: "wdth", min: 75, max: 100 }, { tag: "wght", min: 400, max: 700 }], subsets: ["latin", "latin-ext"], use: "Editorial sites and studios; precise with a width axis." },
41
+ { family: "Commissioner", id: "commissioner", category: "sans", style: "humanist", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: false, axes: [{ tag: "FLAR", min: 0, max: 100 }, { tag: "VOLM", min: 0, max: 100 }, { tag: "slnt", min: -12, max: 0 }, { tag: "wght", min: 100, max: 900 }], subsets: ["cyrillic", "cyrillic-ext", "greek", "latin", "latin-ext", "vietnamese"], use: "Civic and public-sector UIs; flared variant for headings." },
42
+ { family: "Hanken Grotesk", id: "hanken-grotesk", category: "sans", style: "grotesk", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 100, max: 900 }], subsets: ["cyrillic-ext", "latin", "latin-ext", "vietnamese"], use: "Neutral UI text with character; great for CRM and HR." },
43
+ { family: "Geist", id: "geist", category: "sans", style: "grotesk", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 100, max: 900 }], subsets: ["cyrillic", "cyrillic-ext", "latin", "latin-ext", "vietnamese"], use: "Developer tools and dashboards; tight, modern Swiss feel." },
44
+ { family: "Schibsted Grotesk", id: "schibsted-grotesk", category: "sans", style: "grotesk", weights: [400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 400, max: 900 }], subsets: ["latin", "latin-ext"], use: "News and content sites; sturdy headlines and body." },
45
+ { family: "Familjen Grotesk", id: "familjen-grotesk", category: "sans", style: "grotesk", weights: [400, 500, 600, 700], italics: true, axes: [{ tag: "wght", min: 400, max: 700 }], subsets: ["latin", "latin-ext", "vietnamese"], use: "Brand sites and portfolios; quirky details at large sizes." },
46
+ { family: "Bricolage Grotesque", id: "bricolage-grotesque", category: "sans", style: "grotesk", weights: [200, 300, 400, 500, 600, 700, 800], italics: false, axes: [{ tag: "opsz", min: 12, max: 96 }, { tag: "wdth", min: 75, max: 100 }, { tag: "wght", min: 200, max: 800 }], subsets: ["latin", "latin-ext", "vietnamese"], use: "Expressive headlines; optical size and width axes." },
47
+ { family: "Host Grotesk", id: "host-grotesk", category: "sans", style: "grotesk", weights: [300, 400, 500, 600, 700, 800], italics: true, axes: [{ tag: "wght", min: 300, max: 800 }], subsets: ["latin", "latin-ext"], use: "Hosting, SaaS and marketing pages; clear and contemporary." },
48
+ { family: "Archivo", id: "archivo", category: "sans", style: "grotesk", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wdth", min: 62, max: 125 }, { tag: "wght", min: 100, max: 900 }], subsets: ["latin", "latin-ext", "vietnamese"], use: "Data-heavy screens and posters; width axis from narrow to wide." },
49
+ { family: "Work Sans", id: "work-sans", category: "sans", style: "grotesk", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 100, max: 900 }], subsets: ["latin", "latin-ext", "vietnamese"], use: "Agency sites; slightly wide grotesque that reads well large." },
50
+ { family: "Inter Tight", id: "inter-tight", category: "sans", style: "grotesk", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 100, max: 900 }], subsets: ["cyrillic", "cyrillic-ext", "greek", "greek-ext", "latin", "latin-ext", "vietnamese"], use: "Compact headings in product UI; tighter spacing than its parent." },
51
+ { family: "Newsreader", id: "newsreader", category: "serif", style: "text", weights: [200, 300, 400, 500, 600, 700, 800], italics: true, axes: [{ tag: "opsz", min: 6, max: 72 }, { tag: "wght", min: 200, max: 800 }], subsets: ["latin", "latin-ext", "vietnamese"], use: "Blogs and long-form articles; optical sizes from captions to titles." },
52
+ { family: "Source Serif 4", id: "source-serif-4", category: "serif", style: "text", weights: [200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "opsz", min: 8, max: 60 }, { tag: "wght", min: 200, max: 900 }], subsets: ["cyrillic", "cyrillic-ext", "greek", "latin", "latin-ext", "vietnamese"], use: "Documentation and reports; sturdy text serif with optical sizes." },
53
+ { family: "Literata", id: "literata", category: "serif", style: "text", weights: [200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "opsz", min: 7, max: 72 }, { tag: "wght", min: 200, max: 900 }], subsets: ["cyrillic", "cyrillic-ext", "greek", "greek-ext", "latin", "latin-ext", "vietnamese"], use: "E-books and reading apps; designed for long screen reading." },
54
+ { family: "Lora", id: "lora", category: "serif", style: "text", weights: [400, 500, 600, 700], italics: true, axes: [{ tag: "wght", min: 400, max: 700 }], subsets: ["cyrillic", "cyrillic-ext", "latin", "latin-ext", "math", "symbols", "vietnamese"], use: "Lifestyle blogs and menus; calligraphic, warm body text." },
55
+ { family: "Crimson Pro", id: "crimson-pro", category: "serif", style: "text", weights: [200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 200, max: 900 }], subsets: ["latin", "latin-ext", "vietnamese"], use: "Literary sites and essays; classic old-style book face." },
56
+ { family: "Spectral", id: "spectral", category: "serif", style: "text", weights: [200, 300, 400, 500, 600, 700, 800], italics: true, axes: [], subsets: ["cyrillic", "cyrillic-ext", "latin", "latin-ext", "vietnamese"], use: "Premium editorial and legal copy; refined, screen-first serif." },
57
+ { family: "EB Garamond", id: "eb-garamond", category: "serif", style: "text", weights: [400, 500, 600, 700, 800], italics: true, axes: [{ tag: "wght", min: 400, max: 800 }], subsets: ["cyrillic", "cyrillic-ext", "greek", "greek-ext", "latin", "latin-ext", "vietnamese"], use: "Heritage brands, invitations and quotes; classic Garamond." },
58
+ { family: "Instrument Serif", id: "instrument-serif", category: "serif", style: "display", weights: [400], italics: true, axes: [], subsets: ["latin", "latin-ext"], use: "Editorial headlines; condensed, elegant, lovely in italic." },
59
+ { family: "Fraunces", id: "fraunces", category: "serif", style: "display", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "SOFT", min: 0, max: 100 }, { tag: "WONK", min: 0, max: 1 }, { tag: "opsz", min: 9, max: 144 }, { tag: "wght", min: 100, max: 900 }], subsets: ["latin", "latin-ext", "vietnamese"], use: "Soft, wonky display serif for food, spa and boutique brands." },
60
+ { family: "Playfair Display", id: "playfair-display", category: "serif", style: "display", weights: [400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 400, max: 900 }], subsets: ["cyrillic", "latin", "latin-ext", "vietnamese"], use: "Luxury and fashion headlines; high-contrast transitional." },
61
+ { family: "DM Serif Display", id: "dm-serif-display", category: "serif", style: "display", weights: [400], italics: true, axes: [], subsets: ["latin", "latin-ext"], use: "Magazine-style headlines with strong contrast." },
62
+ { family: "Young Serif", id: "young-serif", category: "serif", style: "display", weights: [400], italics: false, axes: [], subsets: ["latin", "latin-ext"], use: "Warm, chunky headings for cafes, bakeries and kids brands." },
63
+ { family: "Bodoni Moda", id: "bodoni-moda", category: "serif", style: "display", weights: [400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "opsz", min: 6, max: 96 }, { tag: "wght", min: 400, max: 900 }], subsets: ["latin", "latin-ext", "math", "symbols"], use: "Fashion and beauty; razor-thin Didone with optical sizes." },
64
+ { family: "Syne", id: "syne", category: "display", weights: [400, 500, 600, 700, 800], italics: false, axes: [{ tag: "wght", min: 400, max: 800 }], subsets: ["greek", "latin", "latin-ext"], use: "Art, culture and studio sites; extended and avant-garde at heavy weights." },
65
+ { family: "Unbounded", id: "unbounded", category: "display", weights: [200, 300, 400, 500, 600, 700, 800, 900], italics: false, axes: [{ tag: "wght", min: 200, max: 900 }], subsets: ["cyrillic", "cyrillic-ext", "latin", "latin-ext", "vietnamese"], use: "Web3, events and posters; wide rounded display." },
66
+ { family: "Dela Gothic One", id: "dela-gothic-one", category: "display", weights: [400], italics: false, axes: [], subsets: ["cyrillic", "greek", "japanese", "latin", "latin-ext", "vietnamese"], use: "Loud campaign headlines and banners; heavy and blocky." },
67
+ { family: "Funnel Display", id: "funnel-display", category: "display", weights: [300, 400, 500, 600, 700, 800], italics: false, axes: [{ tag: "wght", min: 300, max: 800 }], subsets: ["latin", "latin-ext"], use: "Bold marketing headlines; geometric with punchy joins." },
68
+ { family: "Nunito", id: "nunito", category: "rounded", weights: [200, 300, 400, 500, 600, 700, 800, 900, 1000], italics: true, axes: [{ tag: "wght", min: 200, max: 1000 }], subsets: ["cyrillic", "cyrillic-ext", "latin", "latin-ext", "vietnamese"], use: "Friendly apps, education and health; fully rounded terminals." },
69
+ { family: "Quicksand", id: "quicksand", category: "rounded", weights: [300, 400, 500, 600, 700], italics: false, axes: [{ tag: "wght", min: 300, max: 700 }], subsets: ["latin", "latin-ext", "vietnamese"], use: "Light, playful headings for kids, pets and wellness." },
70
+ { family: "Fredoka", id: "fredoka", category: "rounded", weights: [300, 400, 500, 600, 700], italics: false, axes: [{ tag: "wdth", min: 75, max: 125 }, { tag: "wght", min: 300, max: 700 }], subsets: ["hebrew", "latin", "latin-ext"], use: "Playful product UI and games; rounded with a width axis." },
71
+ { family: "Varela Round", id: "varela-round", category: "rounded", weights: [400], italics: false, axes: [], subsets: ["hebrew", "latin", "latin-ext", "vietnamese"], use: "Soft UI labels and onboarding; single regular weight." },
72
+ { family: "Barlow Condensed", id: "barlow-condensed", category: "condensed", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [], subsets: ["latin", "latin-ext", "vietnamese"], use: "Sports, transport and signage; slightly rounded condensed grotesk." },
73
+ { family: "Oswald", id: "oswald", category: "condensed", weights: [200, 300, 400, 500, 600, 700], italics: false, axes: [{ tag: "wght", min: 200, max: 700 }], subsets: ["cyrillic", "cyrillic-ext", "latin", "latin-ext", "vietnamese"], use: "Posters, menus and stat-heavy headers; classic condensed gothic." },
74
+ { family: "Antonio", id: "antonio", category: "condensed", weights: [100, 200, 300, 400, 500, 600, 700], italics: false, axes: [{ tag: "wght", min: 100, max: 700 }], subsets: ["latin", "latin-ext"], use: "Tall, refined headlines; elegant condensed sans." },
75
+ { family: "Archivo Narrow", id: "archivo-narrow", category: "condensed", weights: [400, 500, 600, 700], italics: true, axes: [{ tag: "wght", min: 400, max: 700 }], subsets: ["latin", "latin-ext", "vietnamese"], use: "Tables and dense lists where width is scarce." },
76
+ { family: "Saira Condensed", id: "saira-condensed", category: "condensed", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: false, axes: [], subsets: ["latin", "latin-ext", "vietnamese"], use: "Tech and automotive; squared condensed shapes." },
77
+ { family: "JetBrains Mono", id: "jetbrains-mono", category: "mono", weights: [100, 200, 300, 400, 500, 600, 700, 800], italics: true, axes: [{ tag: "wght", min: 100, max: 800 }], subsets: ["cyrillic", "cyrillic-ext", "greek", "latin", "latin-ext", "vietnamese"], use: "Code, IDs and numbers in admin UIs; tall x-height." },
78
+ { family: "Geist Mono", id: "geist-mono", category: "mono", weights: [100, 200, 300, 400, 500, 600, 700, 800, 900], italics: true, axes: [{ tag: "wght", min: 100, max: 900 }], subsets: ["cyrillic", "cyrillic-ext", "latin", "latin-ext", "symbols2", "vietnamese"], use: "Developer dashboards; pairs with Geist." },
79
+ { family: "IBM Plex Mono", id: "ibm-plex-mono", category: "mono", weights: [100, 200, 300, 400, 500, 600, 700], italics: true, axes: [], subsets: ["cyrillic", "cyrillic-ext", "latin", "latin-ext", "vietnamese"], use: "Corporate data and logs; pairs with IBM Plex Sans." },
80
+ { family: "Space Mono", id: "space-mono", category: "mono", weights: [400, 700], italics: true, axes: [], subsets: ["latin", "latin-ext", "vietnamese"], use: "Retro-tech display and labels; quirky fixed-width." },
81
+ { family: "DM Mono", id: "dm-mono", category: "mono", weights: [300, 400, 500], italics: true, axes: [], subsets: ["latin", "latin-ext"], use: "Calm code and tabular figures; pairs with DM Sans." },
82
+ { family: "Fira Code", id: "fira-code", category: "mono", weights: [300, 400, 500, 600, 700], italics: false, axes: [{ tag: "wght", min: 300, max: 700 }], subsets: ["cyrillic", "cyrillic-ext", "greek", "greek-ext", "latin", "latin-ext", "symbols2"], use: "Code blocks with programming ligatures." },
83
+ { family: "Martian Mono", id: "martian-mono", category: "mono", weights: [100, 200, 300, 400, 500, 600, 700, 800], italics: false, axes: [{ tag: "wdth", min: 75, max: 112.5 }, { tag: "wght", min: 100, max: 800 }], subsets: ["cyrillic", "cyrillic-ext", "latin", "latin-ext"], use: "Wide technical display and dashboards; width axis." },
84
+ { family: "Caveat", id: "caveat", category: "handwriting", weights: [400, 500, 600, 700], italics: false, axes: [{ tag: "wght", min: 400, max: 700 }], subsets: ["cyrillic", "cyrillic-ext", "latin", "latin-ext"], use: "Notes, annotations and friendly accents." },
85
+ { family: "Kalam", id: "kalam", category: "handwriting", weights: [300, 400, 700], italics: false, axes: [], subsets: ["devanagari", "latin", "latin-ext"], use: "Informal labels and sketches; felt-pen feel." },
86
+ { family: "Patrick Hand", id: "patrick-hand", category: "handwriting", weights: [400], italics: false, axes: [], subsets: ["latin", "latin-ext", "vietnamese"], use: "Kids, education and playful callouts; neat print handwriting." },
87
+ ];
88
+ const byFamily = new Map(googleFonts.map((f) => [f.family.toLowerCase(), f]));
89
+ const byId = new Map(googleFonts.map((f) => [f.id, f]));
90
+ /** Look a family up by name (case-insensitive) or id. */
91
+ export function getFont(familyOrId) {
92
+ return byFamily.get(familyOrId.toLowerCase()) ?? byId.get(familyOrId);
93
+ }
94
+ /** The group a font belongs to. */
95
+ export function fontGroupOf(font) {
96
+ return fontGroups.find((g) => g.category === font.category && (g.style == null || g.style === font.style)) ?? fontGroups[0];
97
+ }
98
+ /** Is the family variable (has a `wght` axis)? */
99
+ export function isVariableFont(font) {
100
+ return font.axes.some((a) => a.tag === "wght");
101
+ }
102
+ const fallbacks = {
103
+ sans: "ui-sans-serif, system-ui, sans-serif",
104
+ rounded: "ui-rounded, ui-sans-serif, system-ui, sans-serif",
105
+ display: "ui-sans-serif, system-ui, sans-serif",
106
+ condensed: "ui-sans-serif, system-ui, sans-serif",
107
+ serif: "ui-serif, Georgia, serif",
108
+ mono: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
109
+ handwriting: "cursive",
110
+ };
111
+ /**
112
+ * CSS `font-family` value for a family: the quoted name plus a category fallback.
113
+ * A name that is not in the catalog is treated as a ready CSS stack and returned as is.
114
+ */
115
+ export function fontStack(family) {
116
+ const f = getFont(family);
117
+ if (!f)
118
+ return family;
119
+ const serifDisplay = f.category === "serif";
120
+ return `"${f.family}", ${serifDisplay ? fallbacks.serif : fallbacks[f.category]}`;
121
+ }