@upstart.gg/sdk 0.0.130 → 0.0.132

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 (533) hide show
  1. package/dist/shared/ai/schemas.d.ts +13 -0
  2. package/dist/shared/ai/schemas.d.ts.map +1 -0
  3. package/dist/shared/ai/schemas.js +3 -0
  4. package/dist/shared/ai/types.d.ts +170 -0
  5. package/dist/shared/ai/types.d.ts.map +1 -0
  6. package/dist/shared/{chunk-EJGNYD4V.js → ai/types.js} +0 -1
  7. package/dist/shared/ajv.d.ts +2 -1
  8. package/dist/shared/ajv.d.ts.map +1 -1
  9. package/dist/shared/ajv.js +1 -1
  10. package/dist/shared/attributes.d.ts +300 -12
  11. package/dist/shared/attributes.d.ts.map +1 -1
  12. package/dist/shared/attributes.js +1 -1
  13. package/dist/shared/brick-manifest.d.ts +3 -1
  14. package/dist/shared/brick-manifest.d.ts.map +1 -1
  15. package/dist/shared/brick-manifest.js +1 -1
  16. package/dist/shared/bricks/manifests/accordion.manifest.d.ts +4 -3
  17. package/dist/shared/bricks/manifests/accordion.manifest.d.ts.map +1 -1
  18. package/dist/shared/bricks/manifests/accordion.manifest.js +1 -1
  19. package/dist/shared/bricks/manifests/all-manifests.d.ts +4 -1
  20. package/dist/shared/bricks/manifests/all-manifests.d.ts.map +1 -1
  21. package/dist/shared/bricks/manifests/all-manifests.js +1 -1
  22. package/dist/shared/bricks/manifests/box.manifest.d.ts +6 -4
  23. package/dist/shared/bricks/manifests/box.manifest.d.ts.map +1 -1
  24. package/dist/shared/bricks/manifests/box.manifest.js +1 -1
  25. package/dist/shared/bricks/manifests/button.manifest.d.ts +4 -3
  26. package/dist/shared/bricks/manifests/button.manifest.d.ts.map +1 -1
  27. package/dist/shared/bricks/manifests/button.manifest.js +1 -1
  28. package/dist/shared/bricks/manifests/card.manifest.d.ts +6 -5
  29. package/dist/shared/bricks/manifests/card.manifest.d.ts.map +1 -1
  30. package/dist/shared/bricks/manifests/card.manifest.js +1 -1
  31. package/dist/shared/bricks/manifests/carousel.manifest.d.ts +6 -5
  32. package/dist/shared/bricks/manifests/carousel.manifest.d.ts.map +1 -1
  33. package/dist/shared/bricks/manifests/carousel.manifest.js +1 -1
  34. package/dist/shared/bricks/manifests/footer.manifest.d.ts +40 -5
  35. package/dist/shared/bricks/manifests/footer.manifest.d.ts.map +1 -1
  36. package/dist/shared/bricks/manifests/footer.manifest.js +1 -1
  37. package/dist/shared/bricks/manifests/form.manifest.d.ts +6 -5
  38. package/dist/shared/bricks/manifests/form.manifest.d.ts.map +1 -1
  39. package/dist/shared/bricks/manifests/form.manifest.js +1 -1
  40. package/dist/shared/bricks/manifests/hero.manifest.d.ts +4 -3
  41. package/dist/shared/bricks/manifests/hero.manifest.d.ts.map +1 -1
  42. package/dist/shared/bricks/manifests/hero.manifest.js +1 -1
  43. package/dist/shared/bricks/manifests/html.manifest.d.ts +3 -2
  44. package/dist/shared/bricks/manifests/html.manifest.d.ts.map +1 -1
  45. package/dist/shared/bricks/manifests/html.manifest.js +1 -1
  46. package/dist/shared/bricks/manifests/icon.manifest.d.ts +3 -2
  47. package/dist/shared/bricks/manifests/icon.manifest.d.ts.map +1 -1
  48. package/dist/shared/bricks/manifests/icon.manifest.js +1 -1
  49. package/dist/shared/bricks/manifests/image.manifest.d.ts +10 -6
  50. package/dist/shared/bricks/manifests/image.manifest.d.ts.map +1 -1
  51. package/dist/shared/bricks/manifests/image.manifest.js +1 -1
  52. package/dist/shared/bricks/manifests/images-gallery.manifest.d.ts +7 -6
  53. package/dist/shared/bricks/manifests/images-gallery.manifest.d.ts.map +1 -1
  54. package/dist/shared/bricks/manifests/images-gallery.manifest.js +1 -1
  55. package/dist/shared/bricks/manifests/map.manifest.d.ts +5 -4
  56. package/dist/shared/bricks/manifests/map.manifest.d.ts.map +1 -1
  57. package/dist/shared/bricks/manifests/map.manifest.js +1 -1
  58. package/dist/shared/bricks/manifests/navbar.manifest.d.ts +42 -8
  59. package/dist/shared/bricks/manifests/navbar.manifest.d.ts.map +1 -1
  60. package/dist/shared/bricks/manifests/navbar.manifest.js +1 -1
  61. package/dist/shared/bricks/manifests/sidebar.manifest.d.ts +4 -3
  62. package/dist/shared/bricks/manifests/sidebar.manifest.d.ts.map +1 -1
  63. package/dist/shared/bricks/manifests/sidebar.manifest.js +1 -1
  64. package/dist/shared/bricks/manifests/social-links.manifest.d.ts +5 -4
  65. package/dist/shared/bricks/manifests/social-links.manifest.d.ts.map +1 -1
  66. package/dist/shared/bricks/manifests/social-links.manifest.js +1 -1
  67. package/dist/shared/bricks/manifests/spacer.manifest.d.ts +3 -2
  68. package/dist/shared/bricks/manifests/spacer.manifest.d.ts.map +1 -1
  69. package/dist/shared/bricks/manifests/spacer.manifest.js +1 -1
  70. package/dist/shared/bricks/manifests/testimonials.manifest.d.ts +6 -5
  71. package/dist/shared/bricks/manifests/testimonials.manifest.d.ts.map +1 -1
  72. package/dist/shared/bricks/manifests/testimonials.manifest.js +1 -1
  73. package/dist/shared/bricks/manifests/text.manifest.d.ts +4 -3
  74. package/dist/shared/bricks/manifests/text.manifest.d.ts.map +1 -1
  75. package/dist/shared/bricks/manifests/text.manifest.js +1 -1
  76. package/dist/shared/bricks/manifests/video.manifest.d.ts +4 -3
  77. package/dist/shared/bricks/manifests/video.manifest.d.ts.map +1 -1
  78. package/dist/shared/bricks/manifests/video.manifest.js +1 -1
  79. package/dist/shared/bricks/props/align.d.ts.map +1 -1
  80. package/dist/shared/bricks/props/align.js +1 -1
  81. package/dist/shared/bricks/props/background.d.ts +6 -9
  82. package/dist/shared/bricks/props/background.d.ts.map +1 -1
  83. package/dist/shared/bricks/props/background.js +1 -1
  84. package/dist/shared/bricks/props/border.d.ts.map +1 -1
  85. package/dist/shared/bricks/props/border.js +1 -1
  86. package/dist/shared/bricks/props/color-preset.d.ts +3 -4
  87. package/dist/shared/bricks/props/color-preset.d.ts.map +1 -1
  88. package/dist/shared/bricks/props/color-preset.js +1 -1
  89. package/dist/shared/bricks/props/color.js +1 -1
  90. package/dist/shared/bricks/props/common.d.ts +6 -6
  91. package/dist/shared/bricks/props/common.d.ts.map +1 -1
  92. package/dist/shared/bricks/props/common.js +1 -1
  93. package/dist/shared/bricks/props/css-length.d.ts.map +1 -1
  94. package/dist/shared/bricks/props/css-length.js +1 -1
  95. package/dist/shared/bricks/props/datasource.d.ts +1 -1
  96. package/dist/shared/bricks/props/datasource.js +1 -1
  97. package/dist/shared/bricks/props/date.d.ts.map +1 -1
  98. package/dist/shared/bricks/props/date.js +1 -1
  99. package/dist/shared/bricks/props/direction.d.ts.map +1 -1
  100. package/dist/shared/bricks/props/direction.js +1 -1
  101. package/dist/shared/bricks/props/dynamic.d.ts.map +1 -1
  102. package/dist/shared/bricks/props/dynamic.js +1 -1
  103. package/dist/shared/bricks/props/effects.d.ts +0 -1
  104. package/dist/shared/bricks/props/effects.d.ts.map +1 -1
  105. package/dist/shared/bricks/props/effects.js +1 -1
  106. package/dist/shared/bricks/props/file.d.ts.map +1 -1
  107. package/dist/shared/bricks/props/file.js +1 -1
  108. package/dist/shared/bricks/props/geolocation.js +1 -1
  109. package/dist/shared/bricks/props/helpers.d.ts +2 -2
  110. package/dist/shared/bricks/props/helpers.js +1 -1
  111. package/dist/shared/bricks/props/image.d.ts +4 -4
  112. package/dist/shared/bricks/props/image.d.ts.map +1 -1
  113. package/dist/shared/bricks/props/image.js +1 -1
  114. package/dist/shared/bricks/props/position.d.ts +0 -2
  115. package/dist/shared/bricks/props/position.d.ts.map +1 -1
  116. package/dist/shared/bricks/props/position.js +1 -1
  117. package/dist/shared/bricks/props/string.js +1 -1
  118. package/dist/shared/bricks/props/tags.d.ts.map +1 -1
  119. package/dist/shared/bricks/props/tags.js +1 -1
  120. package/dist/shared/bricks/props/text.js +1 -1
  121. package/dist/shared/bricks/props/types.d.ts +1 -2
  122. package/dist/shared/bricks/props/types.d.ts.map +1 -1
  123. package/dist/shared/bricks.d.ts +189 -18
  124. package/dist/shared/bricks.d.ts.map +1 -1
  125. package/dist/shared/bricks.js +1 -1
  126. package/dist/shared/chunk-2CYAFF56.js +3 -0
  127. package/dist/shared/chunk-2NLDX5FG.js +3 -0
  128. package/dist/shared/chunk-3FPFR5RA.js +3 -0
  129. package/dist/shared/chunk-3P36LG6T.js +3 -0
  130. package/dist/shared/chunk-3QOAHMV4.js +5 -0
  131. package/dist/shared/chunk-46YDGGFF.js +3 -0
  132. package/dist/shared/chunk-4GIZ6WSG.js +3 -0
  133. package/dist/shared/chunk-5DZIQGY2.js +3 -0
  134. package/dist/shared/chunk-5WY7LYXK.js +3 -0
  135. package/dist/shared/chunk-5X5SX5N7.js +4 -0
  136. package/dist/shared/chunk-6L3Z5SZQ.js +3 -0
  137. package/dist/shared/{chunk-UU2MSQXY.js → chunk-6PGAWO4H.js} +1 -1
  138. package/dist/shared/chunk-6R76KIHZ.js +3 -0
  139. package/dist/shared/chunk-7UBMXMNJ.js +3 -0
  140. package/dist/shared/chunk-AB3IMRXZ.js +3 -0
  141. package/dist/shared/chunk-AMQAGDFH.js +3 -0
  142. package/dist/shared/chunk-ARMM6B47.js +3 -0
  143. package/dist/shared/chunk-ARYG4XMX.js +3 -0
  144. package/dist/shared/chunk-AZHH3XJJ.js +3 -0
  145. package/dist/shared/chunk-DHSWVVMI.js +3 -0
  146. package/dist/shared/chunk-DKNOZLA6.js +3 -0
  147. package/dist/shared/chunk-EVDZ2KND.js +6 -0
  148. package/dist/shared/chunk-F4JNKU7J.js +3 -0
  149. package/dist/shared/chunk-GC5OWY2Z.js +3 -0
  150. package/dist/shared/chunk-HP7CZB2F.js +3 -0
  151. package/dist/shared/chunk-HSRXUIVM.js +3 -0
  152. package/dist/shared/chunk-ILIWVWHC.js +8 -0
  153. package/dist/shared/chunk-JRCVYDCD.js +3 -0
  154. package/dist/shared/chunk-K5ADUHF4.js +3 -0
  155. package/dist/shared/chunk-L2HOZVBC.js +3 -0
  156. package/dist/shared/chunk-LEWKHCRI.js +3 -0
  157. package/dist/shared/chunk-LT4CW2F7.js +3 -0
  158. package/dist/shared/chunk-ML4JSDQM.js +34 -0
  159. package/dist/shared/chunk-MVCVVKBY.js +3 -0
  160. package/dist/shared/chunk-NKIEDT7V.js +3 -0
  161. package/dist/shared/chunk-NQKXDMQ5.js +3 -0
  162. package/dist/shared/chunk-PO6UODZ5.js +8 -0
  163. package/dist/shared/chunk-PW5HRVMD.js +3 -0
  164. package/dist/shared/chunk-PZYX3ACO.js +3 -0
  165. package/dist/shared/chunk-QGFQA7OZ.js +4 -0
  166. package/dist/shared/chunk-RJZZWCBD.js +3 -0
  167. package/dist/shared/chunk-SAJY7H6N.js +3 -0
  168. package/dist/shared/chunk-SFDRAHYP.js +3 -0
  169. package/dist/shared/chunk-STDCM2KD.js +3 -0
  170. package/dist/shared/chunk-TH5SONR6.js +3 -0
  171. package/dist/shared/chunk-UCR2UZOY.js +3 -0
  172. package/dist/shared/chunk-UDQWYGSO.js +3 -0
  173. package/dist/shared/{chunk-LSPN22SI.js → chunk-URRCKLAS.js} +3 -3
  174. package/dist/shared/{chunk-OIOYMECS.js → chunk-US53TNMK.js} +1 -1
  175. package/dist/shared/chunk-VDX2J22H.js +3 -0
  176. package/dist/shared/chunk-VK26ZZFR.js +3 -0
  177. package/dist/shared/chunk-VLXZMESE.js +3 -0
  178. package/dist/shared/chunk-WAML3IGZ.js +3 -0
  179. package/dist/shared/chunk-WXKRIUTA.js +3 -0
  180. package/dist/shared/chunk-X62OEAE6.js +3 -0
  181. package/dist/shared/chunk-XED6ARVN.js +3 -0
  182. package/dist/shared/chunk-XZLBM4AX.js +3 -0
  183. package/dist/shared/chunk-Y3X4F4YJ.js +3 -0
  184. package/dist/shared/chunk-Z4YKRLOX.js +3 -0
  185. package/dist/shared/context.d.ts +4 -12
  186. package/dist/shared/context.d.ts.map +1 -1
  187. package/dist/shared/datarecords/external/airtable/handler.d.ts +22 -5
  188. package/dist/shared/datarecords/external/airtable/handler.d.ts.map +1 -1
  189. package/dist/shared/datarecords/external/airtable/handler.js +1 -1
  190. package/dist/shared/datarecords/external/airtable/oauth/config.js +3 -0
  191. package/dist/shared/datarecords/external/airtable/types.d.ts +25 -0
  192. package/dist/shared/datarecords/external/airtable/types.d.ts.map +1 -1
  193. package/dist/shared/datarecords/external/airtable/types.js +3 -0
  194. package/dist/shared/datarecords/external/generic-webhook/handler.js +3 -0
  195. package/dist/shared/datarecords/external/generic-webhook/options.js +3 -0
  196. package/dist/shared/datarecords/external/google/sheets/client.js +3 -0
  197. package/dist/shared/datarecords/external/google/sheets/handler.d.ts +29 -5
  198. package/dist/shared/datarecords/external/google/sheets/handler.d.ts.map +1 -1
  199. package/dist/shared/datarecords/external/google/sheets/handler.js +5 -4
  200. package/dist/shared/datarecords/external/google/sheets/{options.d.ts → types.d.ts} +1 -1
  201. package/dist/shared/datarecords/external/google/sheets/types.d.ts.map +1 -0
  202. package/dist/shared/datarecords/external/google/sheets/types.js +3 -0
  203. package/dist/shared/datarecords/external/notion/handler.d.ts +29 -7
  204. package/dist/shared/datarecords/external/notion/handler.d.ts.map +1 -1
  205. package/dist/shared/datarecords/external/notion/handler.js +1 -1
  206. package/dist/shared/datarecords/external/notion/oauth/config.js +3 -0
  207. package/dist/shared/datarecords/external/notion/{options.d.ts → types.d.ts} +11 -1
  208. package/dist/shared/datarecords/external/notion/types.d.ts.map +1 -0
  209. package/dist/shared/datarecords/external/notion/types.js +3 -0
  210. package/dist/shared/datarecords/types.d.ts +17 -165
  211. package/dist/shared/datarecords/types.d.ts.map +1 -1
  212. package/dist/shared/datarecords/types.js +1 -1
  213. package/dist/shared/datarecords.d.ts +2 -2
  214. package/dist/shared/datarecords.d.ts.map +1 -1
  215. package/dist/shared/datarecords.js +1 -1
  216. package/dist/shared/datasources/external/facebook/posts/fetcher.js +3 -0
  217. package/dist/shared/datasources/external/facebook/posts/schema.js +3 -0
  218. package/dist/shared/datasources/external/http-json/fetcher.js +3 -0
  219. package/dist/shared/datasources/external/http-json/options.js +3 -0
  220. package/dist/shared/datasources/external/http-json/schema.js +3 -0
  221. package/dist/shared/datasources/external/instagram/feed/fetcher.js +3 -0
  222. package/dist/shared/datasources/external/instagram/feed/schema.js +3 -0
  223. package/dist/shared/datasources/external/mastodon/account/fetcher.js +3 -0
  224. package/dist/shared/datasources/external/mastodon/account/schema.js +3 -0
  225. package/dist/shared/datasources/external/mastodon/options.js +3 -0
  226. package/dist/shared/datasources/external/mastodon/status/fetcher.js +3 -0
  227. package/dist/shared/datasources/external/mastodon/status/sample.array.js +3 -0
  228. package/dist/shared/datasources/external/mastodon/status/sample.single.js +3 -0
  229. package/dist/shared/datasources/external/mastodon/status/schema.d.ts.map +1 -1
  230. package/dist/shared/datasources/external/mastodon/status/schema.js +3 -0
  231. package/dist/shared/datasources/external/meta/options.js +3 -0
  232. package/dist/shared/datasources/external/rss/fetcher.js +3 -0
  233. package/dist/shared/datasources/external/rss/options.js +3 -0
  234. package/dist/shared/datasources/external/rss/schema.js +3 -0
  235. package/dist/shared/datasources/external/threads/media/fetcher.js +3 -0
  236. package/dist/shared/datasources/external/threads/media/schema.js +3 -0
  237. package/dist/shared/datasources/external/tiktok/video/fetcher.js +3 -0
  238. package/dist/shared/datasources/external/tiktok/video/options.js +3 -0
  239. package/dist/shared/datasources/external/tiktok/video/schema.js +3 -0
  240. package/dist/shared/datasources/external/youtube/list/fetcher.js +3 -0
  241. package/dist/shared/datasources/external/youtube/list/options.js +3 -0
  242. package/dist/shared/datasources/external/youtube/list/schema.js +3 -0
  243. package/dist/shared/datasources/fetcher.js +2 -0
  244. package/dist/shared/datasources/internal/blog/schema.js +3 -0
  245. package/dist/shared/datasources/internal/changelog/schema.js +3 -0
  246. package/dist/shared/datasources/internal/contact-info/schema.js +3 -0
  247. package/dist/shared/datasources/internal/cv/schema.js +3 -0
  248. package/dist/shared/datasources/internal/faq/schema.js +3 -0
  249. package/dist/shared/datasources/internal/job-board/schema.js +3 -0
  250. package/dist/shared/datasources/internal/links/schema.js +3 -0
  251. package/dist/shared/datasources/internal/recipes/schema.js +3 -0
  252. package/dist/shared/datasources/internal/restaurant/schema.js +3 -0
  253. package/dist/shared/datasources/samples.js +3 -0
  254. package/dist/shared/datasources/schemas.d.ts +0 -49
  255. package/dist/shared/datasources/schemas.d.ts.map +1 -1
  256. package/dist/shared/datasources/schemas.js +1 -1
  257. package/dist/shared/datasources/types.d.ts +53 -130
  258. package/dist/shared/datasources/types.d.ts.map +1 -1
  259. package/dist/shared/datasources/types.js +1 -1
  260. package/dist/shared/datasources/utils.js +3 -0
  261. package/dist/shared/datasources.d.ts +7 -4
  262. package/dist/shared/datasources.d.ts.map +1 -1
  263. package/dist/shared/datasources.js +1 -1
  264. package/dist/shared/errors.js +1 -1
  265. package/dist/shared/images.d.ts +1 -12
  266. package/dist/shared/images.d.ts.map +1 -1
  267. package/dist/shared/images.js +1 -1
  268. package/dist/shared/index.js +3 -0
  269. package/dist/shared/manifest.js +3 -0
  270. package/dist/shared/page.d.ts +143 -12
  271. package/dist/shared/page.d.ts.map +1 -1
  272. package/dist/shared/page.js +1 -1
  273. package/dist/shared/site.d.ts +224 -114
  274. package/dist/shared/site.d.ts.map +1 -1
  275. package/dist/shared/site.js +1 -1
  276. package/dist/shared/sitemap.d.ts +167 -23
  277. package/dist/shared/sitemap.d.ts.map +1 -1
  278. package/dist/shared/sitemap.js +1 -1
  279. package/dist/shared/social-icons.js +3 -0
  280. package/dist/shared/theme.d.ts +41 -4
  281. package/dist/shared/theme.d.ts.map +1 -1
  282. package/dist/shared/theme.js +1 -1
  283. package/dist/shared/utils/invariant.js +1 -1
  284. package/dist/shared/utils/llm.d.ts +19 -0
  285. package/dist/shared/utils/llm.d.ts.map +1 -0
  286. package/dist/shared/utils/llm.js +3 -0
  287. package/dist/shared/utils/schema.d.ts +6 -1
  288. package/dist/shared/utils/schema.d.ts.map +1 -1
  289. package/dist/shared/utils/schema.js +1 -1
  290. package/dist/shared/utils/tests/schema.test.d.ts +2 -0
  291. package/dist/shared/utils/tests/schema.test.d.ts.map +1 -0
  292. package/dist/shared/utils/typed-ref.d.ts +1 -6
  293. package/dist/shared/utils/typed-ref.d.ts.map +1 -1
  294. package/dist/shared/utils/typed-ref.js +1 -1
  295. package/package.json +18 -19
  296. package/src/shared/ai/schemas.ts +33 -0
  297. package/src/shared/ai/types.ts +155 -0
  298. package/src/shared/ajv.ts +123 -0
  299. package/src/shared/analytics/init.ts +14 -0
  300. package/src/shared/analytics/track.ts +21 -0
  301. package/src/shared/analytics/types.ts +13 -0
  302. package/src/shared/attributes.ts +396 -0
  303. package/src/shared/brick-manifest.ts +119 -0
  304. package/src/shared/bricks/manifests/accordion.manifest.ts +482 -0
  305. package/src/shared/bricks/manifests/all-manifests.ts +121 -0
  306. package/src/shared/bricks/manifests/box.manifest.ts +551 -0
  307. package/src/shared/bricks/manifests/button.manifest.ts +208 -0
  308. package/src/shared/bricks/manifests/card.manifest.ts +320 -0
  309. package/src/shared/bricks/manifests/carousel.manifest.ts +708 -0
  310. package/src/shared/bricks/manifests/footer.manifest.ts +509 -0
  311. package/src/shared/bricks/manifests/form.manifest.ts +226 -0
  312. package/src/shared/bricks/manifests/hero.manifest.ts +365 -0
  313. package/src/shared/bricks/manifests/html.manifest.ts +127 -0
  314. package/src/shared/bricks/manifests/icon.manifest.ts +164 -0
  315. package/src/shared/bricks/manifests/image.manifest.ts +378 -0
  316. package/src/shared/bricks/manifests/images-gallery.manifest.ts +822 -0
  317. package/src/shared/bricks/manifests/map.manifest.ts +215 -0
  318. package/src/shared/bricks/manifests/navbar.manifest.ts +361 -0
  319. package/src/shared/bricks/manifests/sidebar.manifest.ts +88 -0
  320. package/src/shared/bricks/manifests/social-links.manifest.ts +497 -0
  321. package/src/shared/bricks/manifests/spacer.manifest.ts +54 -0
  322. package/src/shared/bricks/manifests/testimonials.manifest.ts +480 -0
  323. package/src/shared/bricks/manifests/tests/header.manifest.test.ts +10 -0
  324. package/src/shared/bricks/manifests/text.manifest.ts +245 -0
  325. package/src/shared/bricks/manifests/video.manifest.ts +115 -0
  326. package/src/shared/bricks/props/align.ts +63 -0
  327. package/src/shared/bricks/props/background.ts +79 -0
  328. package/src/shared/bricks/props/boolean.ts +7 -0
  329. package/src/shared/bricks/props/border.ts +86 -0
  330. package/src/shared/bricks/props/color-preset.ts +390 -0
  331. package/src/shared/bricks/props/color.ts +40 -0
  332. package/src/shared/bricks/props/common.ts +64 -0
  333. package/src/shared/bricks/props/css-length.ts +32 -0
  334. package/src/shared/bricks/props/datarecord.ts +11 -0
  335. package/src/shared/bricks/props/datasource.ts +82 -0
  336. package/src/shared/bricks/props/date.ts +21 -0
  337. package/src/shared/bricks/props/direction.ts +21 -0
  338. package/src/shared/bricks/props/dynamic.ts +112 -0
  339. package/src/shared/bricks/props/effects.ts +71 -0
  340. package/src/shared/bricks/props/enum.ts +38 -0
  341. package/src/shared/bricks/props/file.ts +10 -0
  342. package/src/shared/bricks/props/geolocation.ts +36 -0
  343. package/src/shared/bricks/props/helpers.ts +73 -0
  344. package/src/shared/bricks/props/image.ts +96 -0
  345. package/src/shared/bricks/props/number.ts +8 -0
  346. package/src/shared/bricks/props/position.ts +11 -0
  347. package/src/shared/bricks/props/string.ts +72 -0
  348. package/src/shared/bricks/props/tags.ts +26 -0
  349. package/src/shared/bricks/props/tests/background.test.ts +90 -0
  350. package/src/shared/bricks/props/tests/border.test.ts +12 -0
  351. package/src/shared/bricks/props/tests/effects.test.ts +37 -0
  352. package/src/shared/bricks/props/tests/helpers.test.ts +98 -0
  353. package/src/shared/bricks/props/tests/image.test.ts +71 -0
  354. package/src/shared/bricks/props/tests/string.test.ts +80 -0
  355. package/src/shared/bricks/props/text.ts +107 -0
  356. package/src/shared/bricks/props/types.ts +72 -0
  357. package/src/shared/bricks.ts +1237 -0
  358. package/src/shared/context.ts +32 -0
  359. package/src/shared/datarecords/external/airtable/handler.ts +501 -0
  360. package/src/shared/datarecords/external/airtable/oauth/config.ts +11 -0
  361. package/src/shared/datarecords/external/airtable/types.ts +63 -0
  362. package/src/shared/datarecords/external/generic-webhook/handler.ts +10 -0
  363. package/src/shared/datarecords/external/generic-webhook/options.ts +13 -0
  364. package/src/shared/datarecords/external/google/oauth/config.ts +30 -0
  365. package/src/shared/datarecords/external/google/sheets/client.ts +112 -0
  366. package/src/shared/datarecords/external/google/sheets/handler.ts +253 -0
  367. package/src/shared/datarecords/external/google/sheets/types.ts +10 -0
  368. package/src/shared/datarecords/external/notion/handler.ts +469 -0
  369. package/src/shared/datarecords/external/notion/oauth/config.ts +7 -0
  370. package/src/shared/datarecords/external/notion/types.ts +28 -0
  371. package/src/shared/datarecords/types.ts +165 -0
  372. package/src/shared/datarecords.ts +5 -0
  373. package/src/shared/datasources/README.md +3 -0
  374. package/src/shared/datasources/external/facebook/posts/fetcher.ts +52 -0
  375. package/src/shared/datasources/external/facebook/posts/sample.ts +35 -0
  376. package/src/shared/datasources/external/facebook/posts/schema.ts +33 -0
  377. package/src/shared/datasources/external/facebook/posts/tests/fetcher.test.ts +73 -0
  378. package/src/shared/datasources/external/http-json/fetcher.ts +31 -0
  379. package/src/shared/datasources/external/http-json/options.ts +8 -0
  380. package/src/shared/datasources/external/http-json/schema.ts +6 -0
  381. package/src/shared/datasources/external/http-json/tests/fetcher.test.ts +70 -0
  382. package/src/shared/datasources/external/instagram/feed/fetcher.ts +33 -0
  383. package/src/shared/datasources/external/instagram/feed/sample.ts +22 -0
  384. package/src/shared/datasources/external/instagram/feed/schema.ts +23 -0
  385. package/src/shared/datasources/external/instagram/feed/tests/fetcher.test.ts +64 -0
  386. package/src/shared/datasources/external/mastodon/account/fetcher.ts +24 -0
  387. package/src/shared/datasources/external/mastodon/account/sample.ts +33 -0
  388. package/src/shared/datasources/external/mastodon/account/schema.ts +45 -0
  389. package/src/shared/datasources/external/mastodon/account/tests/fetcher.test.ts +47 -0
  390. package/src/shared/datasources/external/mastodon/options.ts +6 -0
  391. package/src/shared/datasources/external/mastodon/status/fetcher.ts +35 -0
  392. package/src/shared/datasources/external/mastodon/status/sample.array.ts +59 -0
  393. package/src/shared/datasources/external/mastodon/status/sample.single.ts +55 -0
  394. package/src/shared/datasources/external/mastodon/status/schema.ts +125 -0
  395. package/src/shared/datasources/external/mastodon/status/tests/fetcher.test.ts +74 -0
  396. package/src/shared/datasources/external/meta/oauth/config.ts +16 -0
  397. package/src/shared/datasources/external/meta/options.ts +7 -0
  398. package/src/shared/datasources/external/rss/fetcher.ts +31 -0
  399. package/src/shared/datasources/external/rss/options.ts +7 -0
  400. package/src/shared/datasources/external/rss/sample.ts +22 -0
  401. package/src/shared/datasources/external/rss/schema.ts +42 -0
  402. package/src/shared/datasources/external/threads/media/fetcher.ts +53 -0
  403. package/src/shared/datasources/external/threads/media/sample.ts +44 -0
  404. package/src/shared/datasources/external/threads/media/schema.ts +37 -0
  405. package/src/shared/datasources/external/tiktok/oauth/config.ts +17 -0
  406. package/src/shared/datasources/external/tiktok/video/fetcher.ts +39 -0
  407. package/src/shared/datasources/external/tiktok/video/options.ts +8 -0
  408. package/src/shared/datasources/external/tiktok/video/sample.ts +26 -0
  409. package/src/shared/datasources/external/tiktok/video/schema.ts +27 -0
  410. package/src/shared/datasources/external/youtube/list/fetcher.ts +37 -0
  411. package/src/shared/datasources/external/youtube/list/options.ts +11 -0
  412. package/src/shared/datasources/external/youtube/list/sample.ts +33 -0
  413. package/src/shared/datasources/external/youtube/list/schema.ts +38 -0
  414. package/src/shared/datasources/external/youtube/oauth/config.ts +15 -0
  415. package/src/shared/datasources/fetcher.ts +16 -0
  416. package/src/shared/datasources/internal/blog/schema.ts +69 -0
  417. package/src/shared/datasources/internal/changelog/schema.ts +48 -0
  418. package/src/shared/datasources/internal/contact-info/schema.ts +20 -0
  419. package/src/shared/datasources/internal/cv/schema.ts +217 -0
  420. package/src/shared/datasources/internal/faq/schema.ts +27 -0
  421. package/src/shared/datasources/internal/job-board/schema.ts +228 -0
  422. package/src/shared/datasources/internal/links/schema.ts +15 -0
  423. package/src/shared/datasources/internal/recipes/schema.ts +42 -0
  424. package/src/shared/datasources/internal/restaurant/schema.ts +225 -0
  425. package/src/shared/datasources/samples.ts +26 -0
  426. package/src/shared/datasources/schemas.ts +48 -0
  427. package/src/shared/datasources/types.ts +490 -0
  428. package/src/shared/datasources/utils.ts +17 -0
  429. package/src/shared/datasources.ts +57 -0
  430. package/src/shared/env.ts +23 -0
  431. package/src/shared/errors.ts +1 -0
  432. package/src/shared/images.ts +44 -0
  433. package/src/shared/index.ts +3 -0
  434. package/src/shared/layout-constants.ts +19 -0
  435. package/src/shared/manifest.ts +50 -0
  436. package/src/shared/oauth.ts +16 -0
  437. package/src/shared/page.ts +36 -0
  438. package/src/shared/prompt.ts +9 -0
  439. package/src/shared/responsive.ts +5 -0
  440. package/src/shared/site.ts +59 -0
  441. package/src/shared/sitemap.ts +98 -0
  442. package/src/shared/social-icons.ts +307 -0
  443. package/src/shared/tests/attributes.test.ts +31 -0
  444. package/src/shared/theme.ts +244 -0
  445. package/src/shared/themes/README.md +34 -0
  446. package/src/shared/themes/color-system.ts +146 -0
  447. package/src/shared/themes/tests/color-system.test.ts +170 -0
  448. package/src/shared/utils/canvas-data-uri.ts +2 -0
  449. package/src/shared/utils/invariant.ts +25 -0
  450. package/src/shared/utils/json-date.ts +8 -0
  451. package/src/shared/utils/llm.ts +282 -0
  452. package/src/shared/utils/merge.ts +12 -0
  453. package/src/shared/utils/object-hash.ts +7 -0
  454. package/src/shared/utils/schema.ts +359 -0
  455. package/src/shared/utils/string-enum.ts +12 -0
  456. package/src/shared/utils/tests/schema.test.ts +724 -0
  457. package/src/shared/utils/try-catch.ts +12 -0
  458. package/src/shared/utils/typed-ref.ts +53 -0
  459. package/dist/shared/bricks/props/container.d.ts +0 -11
  460. package/dist/shared/bricks/props/container.d.ts.map +0 -1
  461. package/dist/shared/bricks/props/container.js +0 -3
  462. package/dist/shared/bricks/props/gap.d.ts +0 -9
  463. package/dist/shared/bricks/props/gap.d.ts.map +0 -1
  464. package/dist/shared/bricks/props/gap.js +0 -3
  465. package/dist/shared/bricks/props/padding.d.ts +0 -5
  466. package/dist/shared/bricks/props/padding.d.ts.map +0 -1
  467. package/dist/shared/bricks/props/padding.js +0 -3
  468. package/dist/shared/bricks/props/tests/padding.d.ts +0 -2
  469. package/dist/shared/bricks/props/tests/padding.d.ts.map +0 -1
  470. package/dist/shared/chunk-2IYSJYNE.js +0 -3
  471. package/dist/shared/chunk-3EM3B4DX.js +0 -3
  472. package/dist/shared/chunk-4TH3C76A.js +0 -3
  473. package/dist/shared/chunk-5N6MBJJ4.js +0 -3
  474. package/dist/shared/chunk-6FITVVZX.js +0 -3
  475. package/dist/shared/chunk-6WCGUAQN.js +0 -3
  476. package/dist/shared/chunk-7DMUDZ4H.js +0 -3
  477. package/dist/shared/chunk-ACVLF55Q.js +0 -3
  478. package/dist/shared/chunk-AQPN5SE2.js +0 -3
  479. package/dist/shared/chunk-BZGNY7LB.js +0 -3
  480. package/dist/shared/chunk-C3VGP4CA.js +0 -3
  481. package/dist/shared/chunk-CT3EI7YN.js +0 -3
  482. package/dist/shared/chunk-DQXDGV67.js +0 -3
  483. package/dist/shared/chunk-E22E4XWE.js +0 -3
  484. package/dist/shared/chunk-ETYYRWLK.js +0 -3
  485. package/dist/shared/chunk-EYPREFMH.js +0 -3
  486. package/dist/shared/chunk-FKNNTHWX.js +0 -5
  487. package/dist/shared/chunk-HHO3ONTQ.js +0 -3
  488. package/dist/shared/chunk-I46VBMLF.js +0 -3
  489. package/dist/shared/chunk-IIFTGWFZ.js +0 -3
  490. package/dist/shared/chunk-JS4K5JRM.js +0 -5
  491. package/dist/shared/chunk-KHFNN4P3.js +0 -3
  492. package/dist/shared/chunk-L6WHBSRZ.js +0 -8
  493. package/dist/shared/chunk-LFQZRGHS.js +0 -3
  494. package/dist/shared/chunk-LGP6GWIY.js +0 -3
  495. package/dist/shared/chunk-NLEWXPVM.js +0 -3
  496. package/dist/shared/chunk-NNI225RG.js +0 -3
  497. package/dist/shared/chunk-QISTDGPP.js +0 -3
  498. package/dist/shared/chunk-QSZWDE3D.js +0 -3
  499. package/dist/shared/chunk-RGLVKILY.js +0 -3
  500. package/dist/shared/chunk-SLRU4CT6.js +0 -4
  501. package/dist/shared/chunk-T3LIA4YB.js +0 -3
  502. package/dist/shared/chunk-T4LMBG2G.js +0 -3
  503. package/dist/shared/chunk-TATG6SFZ.js +0 -3
  504. package/dist/shared/chunk-TF3JVVRU.js +0 -3
  505. package/dist/shared/chunk-TTTXV7TJ.js +0 -6
  506. package/dist/shared/chunk-TWBY2GOR.js +0 -3
  507. package/dist/shared/chunk-UAQHU6L6.js +0 -3
  508. package/dist/shared/chunk-UHF6IEKV.js +0 -3
  509. package/dist/shared/chunk-UMHXXXVP.js +0 -3
  510. package/dist/shared/chunk-VGRYSAXA.js +0 -3
  511. package/dist/shared/chunk-VPFCY4DH.js +0 -3
  512. package/dist/shared/chunk-VZPXXFVX.js +0 -3
  513. package/dist/shared/chunk-WU6Q4WYD.js +0 -3
  514. package/dist/shared/chunk-X43MB5WD.js +0 -3
  515. package/dist/shared/chunk-YBGPPF7T.js +0 -3
  516. package/dist/shared/chunk-YFFTZ5T6.js +0 -3
  517. package/dist/shared/chunk-ZQGNYK5I.js +0 -8
  518. package/dist/shared/chunk-ZTDUXSWH.js +0 -3
  519. package/dist/shared/datarecords/external/airtable/client.d.ts +0 -8
  520. package/dist/shared/datarecords/external/airtable/client.d.ts.map +0 -1
  521. package/dist/shared/datarecords/external/airtable/elements.d.ts +0 -21
  522. package/dist/shared/datarecords/external/airtable/elements.d.ts.map +0 -1
  523. package/dist/shared/datarecords/external/airtable/options.d.ts +0 -10
  524. package/dist/shared/datarecords/external/airtable/options.d.ts.map +0 -1
  525. package/dist/shared/datarecords/external/google/sheets/options.d.ts.map +0 -1
  526. package/dist/shared/datarecords/external/notion/client.d.ts +0 -8
  527. package/dist/shared/datarecords/external/notion/client.d.ts.map +0 -1
  528. package/dist/shared/datarecords/external/notion/options.d.ts.map +0 -1
  529. package/dist/shared/datarecords/external/notion/utils.d.ts +0 -5
  530. package/dist/shared/datarecords/external/notion/utils.d.ts.map +0 -1
  531. package/dist/shared/utils/schema-resolver.d.ts +0 -3
  532. package/dist/shared/utils/schema-resolver.d.ts.map +0 -1
  533. package/dist/shared/utils/schema-resolver.js +0 -3
@@ -0,0 +1,31 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import {
3
+ type PageAttributes,
4
+ resolvePageAttributes,
5
+ resolveSiteAttributes,
6
+ type SiteAttributes,
7
+ } from "../attributes";
8
+
9
+ describe("Attributes test suite", () => {
10
+ describe("resolvePageAttributes", () => {
11
+ it("should resolve attributes with default values", () => {
12
+ const attributes = {};
13
+ expect(resolvePageAttributes(attributes)).toMatchObject<PageAttributes>({
14
+ robotsIndexing: true,
15
+ path: "/",
16
+ title: "Untitled",
17
+ description: "",
18
+ keywords: "",
19
+ });
20
+ });
21
+ });
22
+ describe("resolveSiteAttributes", () => {
23
+ it("should resolve site attributes with default values", () => {
24
+ const attributes = {};
25
+ expect(resolveSiteAttributes(attributes)).toMatchObject<SiteAttributes>({
26
+ language: "en",
27
+ navbar: {},
28
+ });
29
+ });
30
+ });
31
+ });
@@ -0,0 +1,244 @@
1
+ import { Type, type Static } from "@sinclair/typebox";
2
+ import chroma from "chroma-js";
3
+ import { colorPalette } from "@upstart.gg/style-system/colors";
4
+ import { StringEnum } from "./utils/string-enum";
5
+ import { toLLMSchema } from "./utils/llm";
6
+
7
+ export const fontStacks = [
8
+ { value: "system-ui", label: "System UI" },
9
+ { value: "transitional", label: "Transitional" },
10
+ { value: "old-style", label: "Old style" },
11
+ { value: "humanist", label: "Humanist" },
12
+ { value: "geometric-humanist", label: "Geometric humanist" },
13
+ { value: "classical-humanist", label: "Classical humanist" },
14
+ { value: "neo-grotesque", label: "Neo-grotesque" },
15
+ { value: "monospace-slab-serif", label: "Monospace slab serif" },
16
+ { value: "monospace-code", label: "Monospace code" },
17
+ { value: "industrial", label: "Industrial" },
18
+ { value: "rounded-sans", label: "Rounded sans" },
19
+ { value: "slab-serif", label: "Slab serif" },
20
+ { value: "antique", label: "Antique" },
21
+ { value: "didone", label: "Didone" },
22
+ { value: "handwritten", label: "Handwritten" },
23
+ ];
24
+
25
+ const headingFont = Type.Object(
26
+ {
27
+ type: StringEnum(["stack", "theme", "google"], {
28
+ title: "Type of font",
29
+ description: "The type of font. Can be a font stack, a theme font or a Google font",
30
+ }),
31
+ family: Type.String({
32
+ title: "Family",
33
+ description: "The font family (eg. the name of the font)",
34
+ }),
35
+ },
36
+ {
37
+ title: "Headings font",
38
+ description: "Used for titles and headings",
39
+ additionalProperties: false,
40
+ },
41
+ );
42
+
43
+ const bodyFont = Type.Object(
44
+ {
45
+ type: StringEnum(["stack", "theme", "google"], {
46
+ title: "Type of font",
47
+ description: "The type of font. Can be a font stack, a theme font or a Google font",
48
+ }),
49
+ family: Type.String({
50
+ title: "Family",
51
+ description: "The font family (eg. the name of the font)",
52
+ }),
53
+ },
54
+ {
55
+ title: "Body font",
56
+ description: "Used for paragraphs and body text",
57
+ additionalProperties: false,
58
+ },
59
+ );
60
+
61
+ export const themeSchema = Type.Object(
62
+ {
63
+ id: Type.String({ title: "ID", description: "The unique identifier of the theme" }),
64
+ name: Type.String({ title: "Name", description: "The name of the theme" }),
65
+ description: Type.String({ title: "Description", description: "The description of the theme" }),
66
+ tags: Type.Array(Type.String({ title: "Tag" }), { title: "Tags", description: "The tags of the theme" }),
67
+ browserColorScheme: StringEnum(["light", "dark"], {
68
+ title: "Browser scheme",
69
+ description: "Color of browser-provided UI. Either 'light' or 'dark'",
70
+ }),
71
+ // Define the theme colors
72
+ colors: Type.Object(
73
+ {
74
+ primary: Type.String({
75
+ title: "Primary",
76
+ description: "The brand's primary color.",
77
+ "ai:instructions": "Use oklch() css notation.",
78
+ examples: ["oklch(0.62 0.241 354.308)"],
79
+ }),
80
+ secondary: Type.String({
81
+ title: "Secondary",
82
+ description: "The brand's second most used color",
83
+ "ai:instructions": "Use oklch() css notation.",
84
+ examples: ["oklch(0.65 0.22 185)"],
85
+ }),
86
+ accent: Type.String({
87
+ title: "Accent",
88
+ description: "The brand's least used color",
89
+ "ai:instructions": "Use oklch() css notation.",
90
+ examples: ["oklch(0.82 0.18 85)"],
91
+ }),
92
+ neutral: Type.String({
93
+ title: "Neutral",
94
+ description: "The base neutral color",
95
+ "ai:instructions": "Use oklch() css notation.",
96
+ examples: ["oklch(0.38 0.08 280)"],
97
+ }),
98
+ base100: Type.String({
99
+ title: "Base",
100
+ description:
101
+ "Base surface color of page, used for blank backgrounds. Should be white or near-white for light color-schemes, and black or near-black for dark color-schemes.",
102
+ "ai:instructions": "Use oklab() css notation.",
103
+ examples: ["oklch(0.99 0.008 92)"],
104
+ }),
105
+ base200: Type.String({
106
+ title: "Base 2",
107
+ description:
108
+ "Should be darker than base 100 but still light for light color-schemes, and lighter but still dark for dark color-schemes.",
109
+ "ai:instructions": "Use oklab() css notation.",
110
+ examples: ["oklch(0.97 0.01 85)"],
111
+ }),
112
+ base300: Type.String({
113
+ title: "Base 3",
114
+ description:
115
+ "3rd base color, should be darker than base 200 for light color-schemes, and lighter than base 200 for dark color-schemes.",
116
+ "ai:instructions": "Use oklab() css notation.",
117
+ examples: ["oklch(0.95 0.02 80)"],
118
+ }),
119
+ },
120
+ {
121
+ title: "Theme base colors",
122
+ description: "The base colors of the theme. Each theme must declare all these colors",
123
+ additionalProperties: false,
124
+ },
125
+ ),
126
+
127
+ // Define the theme typography
128
+ typography: Type.Object(
129
+ {
130
+ base: Type.Number({
131
+ title: "Base font size",
132
+ description: "The base font size in pixels. It is safe to keep it as is.",
133
+ "ai:instructions": "A safe value is 16.",
134
+ }),
135
+ heading: headingFont,
136
+ body: bodyFont,
137
+ alternatives: Type.Array(
138
+ Type.Object(
139
+ {
140
+ body: bodyFont,
141
+ heading: headingFont,
142
+ },
143
+ { additionalProperties: false },
144
+ ),
145
+ {
146
+ title: "Alternative fonts",
147
+ description: "Alternative fonts that can be suggested to the user. Takes the same shape",
148
+ },
149
+ ),
150
+ },
151
+ { additionalProperties: false },
152
+ ),
153
+ },
154
+ {
155
+ additionalProperties: false,
156
+ },
157
+ );
158
+
159
+ export type Theme = Static<typeof themeSchema>;
160
+ export const themesArray = Type.Array(themeSchema);
161
+
162
+ export function getThemesArrayForLLM() {
163
+ return toLLMSchema(themesArray);
164
+ }
165
+
166
+ export type ThemesArray = Static<typeof themesArray>;
167
+ export type FontType = Theme["typography"]["body"];
168
+
169
+ export const defaultTheme: Theme = {
170
+ id: "_default_",
171
+ name: "default",
172
+ description: "Default Upstart theme",
173
+ tags: ["gradient", "vibrant", "modern", "creative", "dynamic", "artistic", "bold"],
174
+ browserColorScheme: "light",
175
+ colors: {
176
+ base100: "#FFF", // Warm white background
177
+ base200: "oklch(0.99 0.008 92)", // Soft cream
178
+ base300: "oklch(0.97 0.01 85)", // Light warm gray
179
+ primary: "oklch(0.55 0.241 354.308)",
180
+ secondary: "oklch(0.65 0.22 185)",
181
+ accent: "oklch(0.82 0.18 85)",
182
+ neutral: "oklch(0.38 0.08 280)",
183
+ },
184
+ typography: {
185
+ base: 16,
186
+ heading: { type: "stack", family: "system-ui" },
187
+ body: { type: "stack", family: "system-ui" },
188
+ alternatives: [],
189
+ },
190
+ };
191
+
192
+ export function isDefaultTheme(theme: Theme): boolean {
193
+ return theme.id === defaultTheme.id;
194
+ }
195
+
196
+ /**
197
+ * Process a theme, eventually fixing colors and translating them to oklch notations
198
+ * @param theme
199
+ */
200
+ export function processTheme(theme: Theme): Theme {
201
+ return {
202
+ ...theme,
203
+ typography: {
204
+ ...theme.typography,
205
+ base: 16, // override any base size
206
+ },
207
+ colors: Object.entries(theme.colors).reduce(
208
+ (acc, [key, value]) => {
209
+ const fixedColor = fixOklchColor(value);
210
+ return {
211
+ // biome-ignore lint/performance/noAccumulatingSpread: <explanation>
212
+ ...acc,
213
+ [key]: fixedColor,
214
+ };
215
+ },
216
+ {} as typeof theme.colors,
217
+ ),
218
+ };
219
+ }
220
+
221
+ function fixOklchColor(color: string) {
222
+ const valid = chroma.valid(color);
223
+ if (valid) {
224
+ return color;
225
+ }
226
+ // Try to fix the color if it looks like oklch
227
+ const oklchRegex = /ok(lch|lab)\(([^)]+)\)/;
228
+ if (oklchRegex.test(color)) {
229
+ const withoutComma = color.replace(/,/g, " ");
230
+ if (chroma.valid(withoutComma)) {
231
+ return withoutComma;
232
+ }
233
+ }
234
+ // tailwind colors
235
+ if (/^([a-z]+)-([0-9]+)$/.test(color)) {
236
+ const [name, shade] = color.split("-");
237
+ // @ts-ignore
238
+ const twColor = colorPalette[name]?.[shade] as string | undefined;
239
+ if (twColor) {
240
+ return twColor;
241
+ }
242
+ }
243
+ return color;
244
+ }
@@ -0,0 +1,34 @@
1
+ # Theme guidelines
2
+
3
+ ## Primary color
4
+
5
+ Main brand color, used for key actions and important UI elements.
6
+
7
+ ### Uses
8
+ - Primary buttons (600bg)
9
+ - Selected state (100bg, 700 text)
10
+
11
+ ### Shades
12
+
13
+ - 50-100: Selected states, hover backgrounds
14
+ - 200-300: Subtle highlights
15
+ - 500-600: Buttons, key actions
16
+ - 700: Text links, icons
17
+ - 800-900: Heavy emphasis
18
+
19
+ ## Secondary color
20
+
21
+ Supporting colors, used for secondary actions and UI elements.
22
+
23
+ ### Shades
24
+
25
+ - 50-100: Backgrounds, containers
26
+ - 200-300: Borders, dividers
27
+ - 500-600: Secondary buttons
28
+ - 700: Secondary text
29
+ - 800: Headers in secondary contexts
30
+
31
+ ## Accent Color
32
+
33
+ Used sparingly for attention-grabbing elements and highlights
34
+
@@ -0,0 +1,146 @@
1
+ import chroma from "chroma-js";
2
+ import type { Theme } from "../theme";
3
+ export { default as chroma } from "chroma-js";
4
+ import { kebabCase } from "lodash-es";
5
+ import { css } from "@upstart.gg/style-system/twind";
6
+
7
+ export type ColorType = keyof Theme["colors"];
8
+ export type ElementColorType = "page-background" | "background" | "text" | "border" | "shadow";
9
+
10
+ export const baseColors: Record<ColorType, string> = {
11
+ primary: "Primary color",
12
+ secondary: "Secondary color",
13
+ accent: "Accent color",
14
+ neutral: "Neutral color",
15
+ base100: "Base color",
16
+ base200: "Base (level 2)",
17
+ base300: "Base (level 3)",
18
+ };
19
+
20
+ export const shadeNumbers = [900, 800, 700, 600, 500, 400, 300, 200, 100, 50] as const;
21
+ type ShadeNumber = (typeof shadeNumbers)[number];
22
+
23
+ const semanticAliases: Partial<Record<ShadeNumber, string>> = {
24
+ 100: "subtle",
25
+ 300: "light",
26
+ 700: "dark",
27
+ };
28
+
29
+ export type ElementColor = string;
30
+
31
+ export function getColorsSuggestions(baseHueOrColor: number | string, theme: Theme) {
32
+ return [];
33
+ }
34
+
35
+ export function isStandardColor(color: unknown): boolean {
36
+ if (typeof color !== "string") {
37
+ return false;
38
+ }
39
+ return (
40
+ color.startsWith("oklch") ||
41
+ color.startsWith("oklab") ||
42
+ color.startsWith("rgb") ||
43
+ color.startsWith("hsl") ||
44
+ color.startsWith("#") ||
45
+ color.startsWith("var(--")
46
+ );
47
+ }
48
+
49
+ export function propToStyle(prop: string | number | undefined, cssAttr: string) {
50
+ if (typeof prop === "undefined") {
51
+ return undefined;
52
+ }
53
+ // @ts-ignore
54
+ return isStandardColor(prop) || typeof prop === "number" ? css({ [cssAttr as string]: prop }) : prop;
55
+ }
56
+
57
+ export function getContrastingTextColor(
58
+ backgroundColor: string | chroma.Color,
59
+ contrastThreshold = 3.5,
60
+ ): string {
61
+ // Convert the background color to a chroma color object
62
+ const bgColor = chroma(backgroundColor);
63
+
64
+ // Get potential text colors
65
+ const white = "#ffffff";
66
+ const black = "#000000";
67
+
68
+ // Calculate contrast ratios
69
+ const contrastWithWhite = chroma.contrast(bgColor, white);
70
+ const contrastWithBlack = chroma.contrast(bgColor, black);
71
+
72
+ // If both options meet the contrast threshold, return the one with better contrast
73
+ if (contrastWithWhite >= contrastThreshold && contrastWithBlack >= contrastThreshold) {
74
+ return white;
75
+ // return contrastWithWhite >= contrastWithBlack ? white : black;
76
+ }
77
+
78
+ // If only one meets the threshold, use that one
79
+ if (contrastWithWhite >= contrastThreshold) {
80
+ return white;
81
+ }
82
+
83
+ if (contrastWithBlack >= contrastThreshold) {
84
+ return black;
85
+ }
86
+
87
+ // If neither meets the threshold, return the one with better contrast
88
+ // (though it may not meet accessibility standards)
89
+ return contrastWithWhite >= contrastWithBlack ? white : black;
90
+ }
91
+ export function propToClass(value: string | number | undefined, classPrefix: string) {
92
+ if (typeof value === "undefined") {
93
+ return undefined;
94
+ }
95
+ return isStandardColor(value) || typeof value === "number" ? `${classPrefix}-[${value}]` : value;
96
+ }
97
+
98
+ export function generateColorsVars(theme: Theme) {
99
+ const shades: Record<string, string> = {};
100
+ const colorNames = Object.keys(baseColors) as ColorType[];
101
+
102
+ colorNames.forEach((_colorName) => {
103
+ const color = theme.colors[_colorName];
104
+ const colorName = kebabCase(_colorName);
105
+ // Add the original color as the default (without number suffix)
106
+ shades[`color-${colorName}`] = color;
107
+ // Alias it to 500
108
+ shades[`color-${colorName}-500`] = color;
109
+
110
+ // Generate base color content
111
+ const contentColor = getContrastingTextColor(color);
112
+ shades[`color-${colorName}-content`] = contentColor;
113
+ shades[`color-${colorName}-500-content`] = contentColor;
114
+
115
+ const baseColor = chroma(color);
116
+ const darkest = baseColor.darken(2.5);
117
+ const lightest = baseColor.brighten(3.5);
118
+
119
+ const colorScale = chroma.scale([lightest, baseColor, darkest]).domain([50, 500, 900]).mode("oklch");
120
+
121
+ // Generate shades for other colors than base colors
122
+ if (!colorName.startsWith("base")) {
123
+ shadeNumbers.forEach((shade) => {
124
+ if (shade === 500) {
125
+ return;
126
+ }
127
+ const varName = `color-${colorName}-${shade}`;
128
+
129
+ // Gen color for the specific shade
130
+ const shadedColor = colorScale(shade);
131
+ shades[varName] = shadedColor.css("oklch");
132
+
133
+ // Gen content color for this same shade
134
+ const contentColor = getContrastingTextColor(shadedColor);
135
+ shades[`color-${colorName}-${shade}-content`] = contentColor;
136
+
137
+ if (semanticAliases[shade]) {
138
+ shades[`color-${colorName}-${semanticAliases[shade]}`] = shades[varName];
139
+ shades[`color-${colorName}-${semanticAliases[shade]}-content`] = contentColor;
140
+ }
141
+ });
142
+ }
143
+ });
144
+
145
+ return shades;
146
+ }
@@ -0,0 +1,170 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { generateColorsVars } from "../color-system";
3
+ import type { Theme } from "~/shared/theme";
4
+
5
+ const lightTheme: Theme = {
6
+ id: "light",
7
+ name: "Light Theme",
8
+ tags: ["light"],
9
+ typography: {
10
+ base: 16,
11
+ heading: { type: "stack", family: "system-ui" },
12
+ body: { type: "stack", family: "system-ui" },
13
+ alternatives: [],
14
+ },
15
+ description: "A light theme with oklch colors for better contrast and accessibility.",
16
+ browserColorScheme: "light",
17
+ // oklch colors for better contrast and accessibility
18
+ colors: {
19
+ primary: "oklch(0.5 0.1 240 / 1)",
20
+ secondary: "oklch(0.4 0.1 120 / 1)",
21
+ accent: "oklch(0.3 0.1 60 / 1)",
22
+ neutral: "oklch(0.6 0.1 0 / 1)",
23
+ base100: "oklch(0.95 0.1 0 / 1)",
24
+ base200: "oklch(0.85 0.1 0 / 1)",
25
+ base300: "oklch(0.75 0.1 0 / 1)",
26
+ },
27
+ };
28
+
29
+ const darkTheme: Theme = {
30
+ id: "dark",
31
+ name: "Dark Theme",
32
+ tags: ["dark"],
33
+ typography: {
34
+ base: 16,
35
+ heading: { type: "stack", family: "system-ui" },
36
+ body: { type: "stack", family: "system-ui" },
37
+ alternatives: [],
38
+ },
39
+ description: "A dark theme with oklch colors for better contrast and accessibility.",
40
+ browserColorScheme: "dark",
41
+ // oklch colors for better contrast and accessibility
42
+ colors: {
43
+ primary: "oklch(0.2 0.1 240 / 1)",
44
+ secondary: "oklch(0.3 0.1 120 / 1)",
45
+ accent: "oklch(0.4 0.1 60 / 1)",
46
+ neutral: "oklch(0.5 0.1 0 / 1)",
47
+ base100: "oklch(0.15 0.1 0 / 1)",
48
+ base200: "oklch(0.25 0.1 0 / 1)",
49
+ base300: "oklch(0.35 0.1 0 / 1)",
50
+ },
51
+ };
52
+
53
+ const redTheme: Theme = {
54
+ id: "sunset-coral-glow",
55
+ name: "Sunset Coral Glow",
56
+ tags: ["warm", "coral", "sunset"],
57
+ colors: {
58
+ accent: "oklch(60 0.5 30)",
59
+ base100: "oklch(99 0.05 0)",
60
+ base200: "oklch(97 0.1 0)",
61
+ base300: "oklch(95 0.15 0)",
62
+ neutral: "oklch(95 0.2 5)",
63
+ primary: "oklch(85 0.7 20)",
64
+ secondary: "oklch(75 0.6 25)",
65
+ },
66
+ typography: {
67
+ base: 16,
68
+ body: {
69
+ type: "google",
70
+ family: "Raleway",
71
+ },
72
+ heading: {
73
+ type: "google",
74
+ family: "Pacifico",
75
+ },
76
+ alternatives: [],
77
+ },
78
+ browserColorScheme: "light",
79
+ description: "",
80
+ };
81
+
82
+ describe("Color system test suite", () => {
83
+ describe("generateColorsVars", () => {
84
+ it("Should generate the correct colors for a light theme", () => {
85
+ const colors = generateColorsVars(lightTheme);
86
+ expect(colors["color-primary"]).toBe("oklch(0.5 0.1 240 / 1)");
87
+ expect(colors["color-primary-content"]).toBe("#ffffff"); // White text on primary
88
+ // Aliases
89
+ expect(colors["color-primary-subtle"]).toBe(colors["color-primary-100"]);
90
+ expect(colors["color-primary-light"]).toBe(colors["color-primary-300"]);
91
+ expect(colors["color-primary-dark"]).toBe(colors["color-primary-700"]);
92
+
93
+ // Various colors
94
+ expect(colors["color-secondary"]).toBe("oklch(0.4 0.1 120 / 1)");
95
+ expect(colors["color-secondary-content"]).toBe("#ffffff"); // White text on secondary
96
+ expect(colors["color-accent"]).toBe("oklch(0.3 0.1 60 / 1)");
97
+ expect(colors["color-accent-content"]).toBe("#ffffff"); // White text on accent
98
+ expect(colors["color-neutral"]).toBe("oklch(0.6 0.1 0 / 1)");
99
+ expect(colors["color-neutral-content"]).toBe("#ffffff"); // White text on neutral
100
+ expect(colors["color-base-100"]).toBe("oklch(0.95 0.1 0 / 1)");
101
+ expect(colors["color-base-200"]).toBe("oklch(0.85 0.1 0 / 1)");
102
+ expect(colors["color-base-300"]).toBe("oklch(0.75 0.1 0 / 1)");
103
+
104
+ // All shades should be present
105
+ expect(Object.keys(colors)).toContain("color-primary-50");
106
+ expect(Object.keys(colors)).toContain("color-primary-100");
107
+ expect(Object.keys(colors)).toContain("color-primary-200");
108
+ expect(Object.keys(colors)).toContain("color-primary-300");
109
+ expect(Object.keys(colors)).toContain("color-primary-400");
110
+ expect(Object.keys(colors)).toContain("color-primary-500");
111
+ expect(Object.keys(colors)).toContain("color-primary-600");
112
+ expect(Object.keys(colors)).toContain("color-primary-700");
113
+ expect(Object.keys(colors)).toContain("color-primary-800");
114
+ expect(Object.keys(colors)).toContain("color-primary-900");
115
+ });
116
+ it("Should generate the correct colors for a dark theme", () => {
117
+ const colors = generateColorsVars(darkTheme);
118
+ expect(colors["color-primary"]).toBe("oklch(0.2 0.1 240 / 1)");
119
+ expect(colors["color-primary-content"]).toBe("#ffffff"); // White text on primary
120
+ // Aliases
121
+ expect(colors["color-primary-subtle"]).toBe(colors["color-primary-100"]);
122
+ expect(colors["color-primary-light"]).toBe(colors["color-primary-300"]);
123
+ expect(colors["color-primary-dark"]).toBe(colors["color-primary-700"]);
124
+
125
+ // Various colors
126
+ expect(colors["color-secondary"]).toBe("oklch(0.3 0.1 120 / 1)");
127
+ expect(colors["color-secondary-content"]).toBe("#ffffff"); // White text on secondary
128
+ expect(colors["color-accent"]).toBe("oklch(0.4 0.1 60 / 1)");
129
+ expect(colors["color-accent-content"]).toBe("#ffffff"); // White text on accent
130
+ expect(colors["color-neutral"]).toBe("oklch(0.5 0.1 0 / 1)");
131
+ expect(colors["color-neutral-content"]).toBe("#ffffff"); // White text on neutral
132
+ expect(colors["color-base-100"]).toBe("oklch(0.15 0.1 0 / 1)");
133
+ expect(colors["color-base-200"]).toBe("oklch(0.25 0.1 0 / 1)");
134
+ expect(colors["color-base-300"]).toBe("oklch(0.35 0.1 0 / 1)");
135
+
136
+ // All shades should be present
137
+ expect(Object.keys(colors)).toContain("color-primary-50");
138
+ expect(Object.keys(colors)).toContain("color-primary-100");
139
+ expect(Object.keys(colors)).toContain("color-primary-200");
140
+ expect(Object.keys(colors)).toContain("color-primary-300");
141
+ expect(Object.keys(colors)).toContain("color-primary-400");
142
+ expect(Object.keys(colors)).toContain("color-primary-500");
143
+ expect(Object.keys(colors)).toContain("color-primary-600");
144
+ expect(Object.keys(colors)).toContain("color-primary-700");
145
+ expect(Object.keys(colors)).toContain("color-primary-800");
146
+ expect(Object.keys(colors)).toContain("color-primary-900");
147
+ });
148
+ it('should not generate "none" oklch values for the dark theme', () => {
149
+ const colors = generateColorsVars(darkTheme);
150
+
151
+ expect(colors["color-primary"], "color primary contains none").not.toContain("none");
152
+ expect(colors["color-primary-500"], "color-primary-500 contains none").not.toContain("none");
153
+ expect(colors["color-primary-200"], "color-primary-200 contains none").not.toContain("none");
154
+ expect(colors["color-primary-content"], "color-primary-content contains none").not.toContain("none");
155
+ expect(colors["color-secondary"], "color-secondary contains none").not.toContain("none");
156
+ expect(colors["color-secondary-500"], "color-secondary-500 contains none").not.toContain("none");
157
+ expect(colors["color-secondary-200"], "color-secondary-200 contains none").not.toContain("none");
158
+ expect(colors["color-secondary-content"], "color-secondary-content contains none").not.toContain(
159
+ "none",
160
+ );
161
+ expect(colors["color-accent"], "color-accent contains none").not.toContain("none");
162
+ expect(colors["color-accent-content"], "color-accent-content contains none").not.toContain("none");
163
+ expect(colors["color-neutral"], "color-neutral contains none").not.toContain("none");
164
+ expect(colors["color-neutral-content"], "color-neutral-content contains none").not.toContain("none");
165
+ expect(colors["color-base-100"], "color-base-100 contains none").not.toContain("none");
166
+ expect(colors["color-base-200"], "color-base-200 contains none").not.toContain("none");
167
+ expect(colors["color-base-300"], "color-base-300 contains none").not.toContain("none");
168
+ });
169
+ });
170
+ });