@goldencomm/create-baseline 0.0.1 → 0.1.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 (756) hide show
  1. package/README.md +18 -79
  2. package/index.mjs +175 -283
  3. package/package.json +13 -30
  4. package/templates/ci/bitbucket-pipelines.yml +29 -0
  5. package/templates/code-connect/accordion-item.figma.ts +45 -0
  6. package/templates/code-connect/accordion.figma.ts +40 -0
  7. package/templates/code-connect/alert.figma.ts +378 -0
  8. package/templates/code-connect/avatar-badge.figma.ts +14 -0
  9. package/templates/code-connect/avatar-group-count.figma.ts +16 -0
  10. package/templates/code-connect/avatar-group.figma.ts +30 -0
  11. package/templates/code-connect/avatar.figma.ts +34 -0
  12. package/templates/code-connect/badge.figma.ts +383 -0
  13. package/templates/code-connect/breadcrumb-item.figma.ts +23 -0
  14. package/templates/code-connect/breadcrumb-separator.figma.ts +12 -0
  15. package/templates/code-connect/breadcrumb.figma.ts +32 -0
  16. package/templates/code-connect/button-group.figma.ts +28 -0
  17. package/templates/code-connect/button.figma.ts +408 -0
  18. package/templates/code-connect/card.figma.ts +74 -0
  19. package/templates/code-connect/carousel.figma.ts +27 -0
  20. package/templates/code-connect/checkbox.figma.ts +34 -0
  21. package/templates/code-connect/columns-1.figma.ts +43 -0
  22. package/templates/code-connect/columns-2.figma.ts +49 -0
  23. package/templates/code-connect/columns-3.figma.ts +45 -0
  24. package/templates/code-connect/columns-4.figma.ts +46 -0
  25. package/templates/code-connect/container.figma.ts +42 -0
  26. package/templates/code-connect/dialog.figma.ts +72 -0
  27. package/templates/code-connect/drawer.figma.ts +69 -0
  28. package/templates/code-connect/dropdown-menu-checkbox-item.figma.ts +19 -0
  29. package/templates/code-connect/dropdown-menu-item.figma.ts +25 -0
  30. package/templates/code-connect/dropdown-menu-label.figma.ts +16 -0
  31. package/templates/code-connect/dropdown-menu-radio-item.figma.ts +19 -0
  32. package/templates/code-connect/dropdown-menu-separator.figma.ts +12 -0
  33. package/templates/code-connect/dropdown-menu-sub-trigger.figma.ts +22 -0
  34. package/templates/code-connect/dropdown-menu.figma.ts +44 -0
  35. package/templates/code-connect/field-horizontal.figma.ts +73 -0
  36. package/templates/code-connect/field.figma.ts +68 -0
  37. package/templates/code-connect/hover-card.figma.ts +41 -0
  38. package/templates/code-connect/icon-button.figma.ts +382 -0
  39. package/templates/code-connect/input-group.figma.ts +51 -0
  40. package/templates/code-connect/input-otp.figma.ts +40 -0
  41. package/templates/code-connect/input.figma.ts +42 -0
  42. package/templates/code-connect/item-group.figma.ts +30 -0
  43. package/templates/code-connect/item.figma.ts +50 -0
  44. package/templates/code-connect/kbd.figma.ts +16 -0
  45. package/templates/code-connect/media.figma.ts +35 -0
  46. package/templates/code-connect/meter.figma.ts +31 -0
  47. package/templates/code-connect/native-select.figma.ts +36 -0
  48. package/templates/code-connect/navigation-menu-link.figma.ts +33 -0
  49. package/templates/code-connect/navigation-menu-trigger.figma.ts +28 -0
  50. package/templates/code-connect/navigation-menu.figma.ts +30 -0
  51. package/templates/code-connect/pagination-ellipsis.figma.ts +11 -0
  52. package/templates/code-connect/pagination-link.figma.ts +24 -0
  53. package/templates/code-connect/pagination-next.figma.ts +17 -0
  54. package/templates/code-connect/pagination-previous.figma.ts +17 -0
  55. package/templates/code-connect/pagination.figma.ts +33 -0
  56. package/templates/code-connect/panel.figma.ts +40 -0
  57. package/templates/code-connect/popover.figma.ts +58 -0
  58. package/templates/code-connect/progress.figma.ts +34 -0
  59. package/templates/code-connect/radio.figma.ts +29 -0
  60. package/templates/code-connect/section.figma.ts +42 -0
  61. package/templates/code-connect/select.figma.ts +30 -0
  62. package/templates/code-connect/sheet.figma.ts +70 -0
  63. package/templates/code-connect/sidebar-menu-button.figma.ts +36 -0
  64. package/templates/code-connect/sidebar.figma.ts +44 -0
  65. package/templates/code-connect/spinner.figma.ts +13 -0
  66. package/templates/code-connect/switch.figma.ts +32 -0
  67. package/templates/code-connect/table-cell.figma.ts +21 -0
  68. package/templates/code-connect/table.figma.ts +62 -0
  69. package/templates/code-connect/tabs-trigger.figma.ts +369 -0
  70. package/templates/code-connect/tabs.figma.ts +28 -0
  71. package/templates/code-connect/textarea.figma.ts +32 -0
  72. package/templates/code-connect/toggle-group.figma.ts +24 -0
  73. package/templates/code-connect/toggle.figma.ts +385 -0
  74. package/templates/code-connect/tooltip.figma.ts +29 -0
  75. package/templates/next/app/globals.css +13 -12
  76. package/templates/next/app/page.tsx +38 -26
  77. package/templates/next/public/placeholder.svg +1 -0
  78. package/templates/shopify/.gitattributes +1 -0
  79. package/templates/shopify/.shopifyignore +23 -0
  80. package/templates/shopify/.theme-check.yml +1 -0
  81. package/templates/shopify/CODE_OF_CONDUCT.md +132 -0
  82. package/templates/shopify/CONTRIBUTING.md +24 -0
  83. package/templates/shopify/LICENSE.md +9 -0
  84. package/templates/shopify/README.md +160 -0
  85. package/templates/shopify/assets/carousel.js +2 -0
  86. package/templates/shopify/assets/critical.css +117 -0
  87. package/templates/shopify/assets/icon-account.svg +6 -0
  88. package/templates/shopify/assets/icon-cart.svg +5 -0
  89. package/templates/shopify/assets/predictive-search.js +65 -0
  90. package/templates/shopify/assets/shoppy-x-ray.svg +1 -0
  91. package/templates/shopify/blocks/_accordion-item.liquid +44 -0
  92. package/templates/shopify/blocks/_card-footer.liquid +26 -0
  93. package/templates/shopify/blocks/_carousel-slide.liquid +21 -0
  94. package/templates/shopify/blocks/_column.liquid +30 -0
  95. package/templates/shopify/blocks/_dialog-footer.liquid +28 -0
  96. package/templates/shopify/blocks/_sheet-footer.liquid +28 -0
  97. package/templates/shopify/blocks/_tab.liquid +21 -0
  98. package/templates/shopify/blocks/accordion.liquid +40 -0
  99. package/templates/shopify/blocks/blog-posts.liquid +70 -0
  100. package/templates/shopify/blocks/button.figma.ts +359 -0
  101. package/templates/shopify/blocks/button.liquid +477 -0
  102. package/templates/shopify/blocks/card.liquid +73 -0
  103. package/templates/shopify/blocks/carousel.liquid +47 -0
  104. package/templates/shopify/blocks/columns.liquid +73 -0
  105. package/templates/shopify/blocks/contact-form.liquid +69 -0
  106. package/templates/shopify/blocks/container.liquid +29 -0
  107. package/templates/shopify/blocks/dialog.liquid +77 -0
  108. package/templates/shopify/blocks/group.liquid +105 -0
  109. package/templates/shopify/blocks/heading.liquid +57 -0
  110. package/templates/shopify/blocks/icon-button.figma.ts +358 -0
  111. package/templates/shopify/blocks/media.liquid +80 -0
  112. package/templates/shopify/blocks/navigation-menu.liquid +23 -0
  113. package/templates/shopify/blocks/panel.liquid +64 -0
  114. package/templates/shopify/blocks/popover.liquid +88 -0
  115. package/templates/shopify/blocks/section-heading.liquid +68 -0
  116. package/templates/shopify/blocks/sheet.liquid +90 -0
  117. package/templates/shopify/blocks/tabs.liquid +58 -0
  118. package/templates/shopify/blocks/text.liquid +59 -0
  119. package/templates/shopify/build-js.mjs +22 -0
  120. package/templates/shopify/config/settings_data.json +182 -0
  121. package/templates/shopify/config/settings_schema.json +365 -0
  122. package/templates/shopify/layout/password.liquid +19 -0
  123. package/templates/shopify/layout/theme.liquid +57 -0
  124. package/templates/shopify/locales/en.default.json +58 -0
  125. package/templates/shopify/locales/en.default.schema.json +303 -0
  126. package/templates/shopify/package-lock.json +521 -0
  127. package/templates/shopify/package.json +17 -0
  128. package/templates/shopify/sections/404.liquid +23 -0
  129. package/templates/shopify/sections/article.liquid +81 -0
  130. package/templates/shopify/sections/baseline-header.liquid +236 -0
  131. package/templates/shopify/sections/baseline-kitchen-sink.liquid +988 -0
  132. package/templates/shopify/sections/baseline-section.liquid +661 -0
  133. package/templates/shopify/sections/blog.liquid +36 -0
  134. package/templates/shopify/sections/cart.liquid +65 -0
  135. package/templates/shopify/sections/collection.liquid +54 -0
  136. package/templates/shopify/sections/collections.liquid +83 -0
  137. package/templates/shopify/sections/custom-section.liquid +60 -0
  138. package/templates/shopify/sections/footer-group.json +25 -0
  139. package/templates/shopify/sections/footer.liquid +57 -0
  140. package/templates/shopify/sections/header-group.json +22 -0
  141. package/templates/shopify/sections/page.liquid +18 -0
  142. package/templates/shopify/sections/password.liquid +36 -0
  143. package/templates/shopify/sections/product.liquid +60 -0
  144. package/templates/shopify/sections/search.liquid +73 -0
  145. package/templates/shopify/snippets/accordion-item.figma.ts +34 -0
  146. package/templates/shopify/snippets/accordion-item.liquid +36 -0
  147. package/templates/shopify/snippets/accordion.figma.ts +37 -0
  148. package/templates/shopify/snippets/accordion.liquid +169 -0
  149. package/templates/shopify/snippets/alert.figma.ts +31 -0
  150. package/templates/shopify/snippets/alert.liquid +104 -0
  151. package/templates/shopify/snippets/avatar-group.figma.ts +17 -0
  152. package/templates/shopify/snippets/avatar-group.liquid +66 -0
  153. package/templates/shopify/snippets/avatar.figma.ts +24 -0
  154. package/templates/shopify/snippets/avatar.liquid +143 -0
  155. package/templates/shopify/snippets/badge.figma.ts +355 -0
  156. package/templates/shopify/snippets/badge.liquid +111 -0
  157. package/templates/shopify/snippets/baseline-schemes.liquid +44 -0
  158. package/templates/shopify/snippets/baseline-tokens.liquid +712 -0
  159. package/templates/shopify/snippets/breadcrumb.figma.ts +12 -0
  160. package/templates/shopify/snippets/breadcrumb.liquid +124 -0
  161. package/templates/shopify/snippets/button-group.liquid +148 -0
  162. package/templates/shopify/snippets/button.liquid +144 -0
  163. package/templates/shopify/snippets/card.figma.ts +43 -0
  164. package/templates/shopify/snippets/card.liquid +196 -0
  165. package/templates/shopify/snippets/carousel-item.liquid +18 -0
  166. package/templates/shopify/snippets/carousel.figma.ts +28 -0
  167. package/templates/shopify/snippets/carousel.liquid +121 -0
  168. package/templates/shopify/snippets/checkbox.liquid +147 -0
  169. package/templates/shopify/snippets/container.liquid +52 -0
  170. package/templates/shopify/snippets/css-variables.liquid +18 -0
  171. package/templates/shopify/snippets/dialog.figma.ts +36 -0
  172. package/templates/shopify/snippets/dialog.liquid +217 -0
  173. package/templates/shopify/snippets/field-separator.liquid +68 -0
  174. package/templates/shopify/snippets/field.liquid +187 -0
  175. package/templates/shopify/snippets/icon.liquid +101 -0
  176. package/templates/shopify/snippets/image.liquid +64 -0
  177. package/templates/shopify/snippets/input-group.liquid +196 -0
  178. package/templates/shopify/snippets/input.liquid +126 -0
  179. package/templates/shopify/snippets/item-group.liquid +31 -0
  180. package/templates/shopify/snippets/item.figma.ts +40 -0
  181. package/templates/shopify/snippets/item.liquid +162 -0
  182. package/templates/shopify/snippets/media.figma.ts +33 -0
  183. package/templates/shopify/snippets/media.liquid +273 -0
  184. package/templates/shopify/snippets/meta-tags.liquid +105 -0
  185. package/templates/shopify/snippets/meter.figma.ts +24 -0
  186. package/templates/shopify/snippets/meter.liquid +118 -0
  187. package/templates/shopify/snippets/native-select.liquid +141 -0
  188. package/templates/shopify/snippets/navigation-menu-item.figma.ts +23 -0
  189. package/templates/shopify/snippets/navigation-menu-item.liquid +40 -0
  190. package/templates/shopify/snippets/navigation-menu-link.figma.ts +27 -0
  191. package/templates/shopify/snippets/navigation-menu-link.liquid +31 -0
  192. package/templates/shopify/snippets/navigation-menu.figma.ts +12 -0
  193. package/templates/shopify/snippets/navigation-menu.liquid +300 -0
  194. package/templates/shopify/snippets/pagination.figma.ts +13 -0
  195. package/templates/shopify/snippets/pagination.liquid +208 -0
  196. package/templates/shopify/snippets/popover.figma.ts +41 -0
  197. package/templates/shopify/snippets/popover.liquid +203 -0
  198. package/templates/shopify/snippets/progress.figma.ts +26 -0
  199. package/templates/shopify/snippets/progress.liquid +114 -0
  200. package/templates/shopify/snippets/radio.liquid +145 -0
  201. package/templates/shopify/snippets/sheet.figma.ts +37 -0
  202. package/templates/shopify/snippets/sheet.liquid +197 -0
  203. package/templates/shopify/snippets/sidebar-menu-item.liquid +34 -0
  204. package/templates/shopify/snippets/sidebar-menu-sub-link.liquid +17 -0
  205. package/templates/shopify/snippets/sidebar-menu.liquid +139 -0
  206. package/templates/shopify/snippets/spinner.liquid +42 -0
  207. package/templates/shopify/snippets/switch.liquid +180 -0
  208. package/templates/shopify/snippets/tab.figma.ts +353 -0
  209. package/templates/shopify/snippets/tab.liquid +33 -0
  210. package/templates/shopify/snippets/tabs.figma.ts +21 -0
  211. package/templates/shopify/snippets/tabs.liquid +260 -0
  212. package/templates/shopify/snippets/text-styles.liquid +45 -0
  213. package/templates/shopify/snippets/textarea.liquid +103 -0
  214. package/templates/shopify/snippets/toggle-group.figma.ts +30 -0
  215. package/templates/shopify/snippets/toggle-group.liquid +46 -0
  216. package/templates/shopify/snippets/toggle.figma.ts +357 -0
  217. package/templates/shopify/snippets/toggle.liquid +104 -0
  218. package/templates/shopify/snippets/typeset.liquid +498 -0
  219. package/templates/shopify/src/carousel.js +94 -0
  220. package/templates/shopify/templates/404.json +20 -0
  221. package/templates/shopify/templates/article.json +20 -0
  222. package/templates/shopify/templates/blog.json +20 -0
  223. package/templates/shopify/templates/cart.json +20 -0
  224. package/templates/shopify/templates/collection.json +20 -0
  225. package/templates/shopify/templates/gift_card.liquid +73 -0
  226. package/templates/shopify/templates/index.json +18 -0
  227. package/templates/shopify/templates/list-collections.json +20 -0
  228. package/templates/shopify/templates/page.json +20 -0
  229. package/templates/shopify/templates/password.json +21 -0
  230. package/templates/shopify/templates/product.json +20 -0
  231. package/templates/shopify/templates/search.json +20 -0
  232. package/templates/skills/baseline-client-tokens/SKILL.md +74 -0
  233. package/templates/wordpress/.ddev/commands/web/seed +258 -3
  234. package/templates/wordpress/.ddev/config.yaml +10 -7
  235. package/templates/wordpress/.ddev/seed/gravityforms-contact.json +1 -0
  236. package/templates/wordpress/README.md +37 -39
  237. package/templates/wordpress/auth.json.example +1 -1
  238. package/templates/wordpress/composer.json +88 -84
  239. package/templates/wordpress/theme/README.md +3 -0
  240. package/templates/wordpress/theme/acf-json/.gitkeep +0 -0
  241. package/templates/wordpress/theme/acf-json/group_baseline_alert.json +83 -0
  242. package/templates/wordpress/theme/acf-json/group_baseline_avatar.json +82 -0
  243. package/templates/wordpress/theme/acf-json/group_baseline_avatar_group.json +35 -0
  244. package/templates/wordpress/theme/acf-json/group_baseline_badge.json +93 -0
  245. package/templates/wordpress/theme/acf-json/group_baseline_carousel.json +21 -0
  246. package/templates/wordpress/theme/acf-json/group_baseline_carousel_slide.json +16 -0
  247. package/templates/wordpress/theme/acf-json/group_baseline_dialog.json +68 -0
  248. package/templates/wordpress/theme/acf-json/group_baseline_dialog_footer.json +23 -0
  249. package/templates/wordpress/theme/acf-json/group_baseline_item.json +101 -0
  250. package/templates/wordpress/theme/acf-json/group_baseline_item_group.json +26 -0
  251. package/templates/wordpress/theme/acf-json/group_baseline_sheet.json +104 -0
  252. package/templates/wordpress/theme/acf-json/group_baseline_sheet_footer.json +31 -0
  253. package/templates/wordpress/theme/assets/app.css +2 -0
  254. package/templates/wordpress/theme/assets/editor.css +2 -0
  255. package/templates/wordpress/theme/assets/images/placeholder.svg +1 -0
  256. package/templates/wordpress/theme/assets/js/carousel-editor.js +85 -0
  257. package/templates/wordpress/theme/assets/js/carousel.js +2 -0
  258. package/templates/wordpress/theme/assets/js/core-button-editor.js +243 -0
  259. package/templates/wordpress/theme/assets/js/core-layout-editor.js +144 -0
  260. package/templates/wordpress/theme/assets/js/core-navigation.js +11 -0
  261. package/templates/wordpress/theme/assets/js/media-editor.js +52 -0
  262. package/templates/wordpress/theme/assets/js/media.js +38 -0
  263. package/templates/wordpress/theme/assets/tokens.css +1030 -0
  264. package/templates/wordpress/theme/blocks/alert/alert.figma.ts +32 -0
  265. package/templates/wordpress/theme/blocks/alert/block.json +24 -0
  266. package/templates/wordpress/theme/blocks/alert/render.php +30 -0
  267. package/templates/wordpress/theme/blocks/avatar/block.json +24 -0
  268. package/templates/wordpress/theme/blocks/avatar/render.php +35 -0
  269. package/templates/wordpress/theme/blocks/avatar-group/avatar-group.figma.ts +16 -0
  270. package/templates/wordpress/theme/blocks/avatar-group/block.json +25 -0
  271. package/templates/wordpress/theme/blocks/avatar-group/render.php +27 -0
  272. package/templates/wordpress/theme/blocks/badge/badge.figma.ts +349 -0
  273. package/templates/wordpress/theme/blocks/badge/block.json +23 -0
  274. package/templates/wordpress/theme/blocks/badge/render.php +28 -0
  275. package/templates/wordpress/theme/blocks/carousel/block.json +25 -0
  276. package/templates/wordpress/theme/blocks/carousel/carousel.figma.ts +22 -0
  277. package/templates/wordpress/theme/blocks/carousel/render.php +54 -0
  278. package/templates/wordpress/theme/blocks/carousel-slide/block.json +24 -0
  279. package/templates/wordpress/theme/blocks/carousel-slide/render.php +13 -0
  280. package/templates/wordpress/theme/blocks/dialog/block.json +24 -0
  281. package/templates/wordpress/theme/blocks/dialog/dialog.figma.ts +36 -0
  282. package/templates/wordpress/theme/blocks/dialog/render.php +41 -0
  283. package/templates/wordpress/theme/blocks/dialog-footer/block.json +25 -0
  284. package/templates/wordpress/theme/blocks/dialog-footer/render.php +18 -0
  285. package/templates/wordpress/theme/blocks/item/block.json +25 -0
  286. package/templates/wordpress/theme/blocks/item/item.figma.ts +43 -0
  287. package/templates/wordpress/theme/blocks/item/render.php +38 -0
  288. package/templates/wordpress/theme/blocks/item-group/block.json +25 -0
  289. package/templates/wordpress/theme/blocks/item-group/item-group.figma.ts +28 -0
  290. package/templates/wordpress/theme/blocks/item-group/render.php +22 -0
  291. package/templates/wordpress/theme/blocks/sheet/block.json +24 -0
  292. package/templates/wordpress/theme/blocks/sheet/render.php +39 -0
  293. package/templates/wordpress/theme/blocks/sheet/sheet.figma.ts +38 -0
  294. package/templates/wordpress/theme/blocks/sheet-footer/block.json +25 -0
  295. package/templates/wordpress/theme/blocks/sheet-footer/render.php +18 -0
  296. package/templates/wordpress/theme/build-js.mjs +22 -0
  297. package/templates/wordpress/theme/code-connect/accordion-item.figma.ts +47 -0
  298. package/templates/wordpress/theme/code-connect/accordion.figma.ts +37 -0
  299. package/templates/wordpress/theme/code-connect/avatar.figma.ts +25 -0
  300. package/templates/wordpress/theme/code-connect/breadcrumb.figma.ts +12 -0
  301. package/templates/wordpress/theme/code-connect/button.figma.ts +360 -0
  302. package/templates/wordpress/theme/code-connect/card.figma.ts +45 -0
  303. package/templates/wordpress/theme/code-connect/icon-button.figma.ts +359 -0
  304. package/templates/wordpress/theme/code-connect/navigation-menu.figma.ts +20 -0
  305. package/templates/wordpress/theme/code-connect/pagination.figma.ts +17 -0
  306. package/templates/wordpress/theme/code-connect/popover.figma.ts +42 -0
  307. package/templates/wordpress/theme/code-connect/tabs.figma.ts +32 -0
  308. package/templates/wordpress/theme/code-connect/toggle-group.figma.ts +34 -0
  309. package/templates/wordpress/theme/code-connect/toggle.figma.ts +356 -0
  310. package/templates/wordpress/theme/composer.json +7 -0
  311. package/templates/wordpress/theme/footer.php +4 -0
  312. package/templates/wordpress/theme/functions.php +86 -0
  313. package/templates/wordpress/theme/header.php +17 -0
  314. package/templates/wordpress/theme/inc/acf.php +13 -0
  315. package/templates/wordpress/theme/inc/blocks.php +41 -0
  316. package/templates/wordpress/theme/inc/carousel.php +36 -0
  317. package/templates/wordpress/theme/inc/components/alert.php +83 -0
  318. package/templates/wordpress/theme/inc/components/avatar.php +111 -0
  319. package/templates/wordpress/theme/inc/components/badge.php +96 -0
  320. package/templates/wordpress/theme/inc/components/button.php +77 -0
  321. package/templates/wordpress/theme/inc/components/dialog.php +98 -0
  322. package/templates/wordpress/theme/inc/components/item.php +111 -0
  323. package/templates/wordpress/theme/inc/components/popover.php +125 -0
  324. package/templates/wordpress/theme/inc/components/sheet.php +88 -0
  325. package/templates/wordpress/theme/inc/components/toggle.php +127 -0
  326. package/templates/wordpress/theme/inc/core-button.php +96 -0
  327. package/templates/wordpress/theme/inc/core-card.php +30 -0
  328. package/templates/wordpress/theme/inc/core-layout.php +76 -0
  329. package/templates/wordpress/theme/inc/core-navigation.php +31 -0
  330. package/templates/wordpress/theme/inc/core-pagination.php +87 -0
  331. package/templates/wordpress/theme/inc/header.php +39 -0
  332. package/templates/wordpress/theme/inc/icons.generated.php +94 -0
  333. package/templates/wordpress/theme/inc/icons.php +70 -0
  334. package/templates/wordpress/theme/inc/looks.generated.php +18 -0
  335. package/templates/wordpress/theme/inc/media.php +183 -0
  336. package/templates/wordpress/theme/inc/sections.php +16 -0
  337. package/templates/wordpress/theme/index.php +24 -0
  338. package/templates/wordpress/theme/package-lock.json +1637 -0
  339. package/templates/wordpress/theme/package.json +23 -0
  340. package/templates/wordpress/theme/parts/header.html +23 -0
  341. package/templates/wordpress/theme/patterns/blog-card-grid.php +41 -0
  342. package/templates/wordpress/theme/patterns/card.php +46 -0
  343. package/templates/wordpress/theme/patterns/contact-centered.php +22 -0
  344. package/templates/wordpress/theme/patterns/cta-left.php +25 -0
  345. package/templates/wordpress/theme/patterns/faq-centered.php +36 -0
  346. package/templates/wordpress/theme/patterns/header-inline.php +33 -0
  347. package/templates/wordpress/theme/patterns/header-stacked.php +25 -0
  348. package/templates/wordpress/theme/patterns/hero-centered.php +28 -0
  349. package/templates/wordpress/theme/patterns/hero-split.php +41 -0
  350. package/templates/wordpress/theme/patterns/section.php +28 -0
  351. package/templates/wordpress/theme/src/app.css +45 -0
  352. package/templates/wordpress/theme/src/carousel.css +93 -0
  353. package/templates/wordpress/theme/src/carousel.js +94 -0
  354. package/templates/wordpress/theme/src/checkbox.css +102 -0
  355. package/templates/wordpress/theme/src/core-accordion.css +158 -0
  356. package/templates/wordpress/theme/src/core-avatar.css +68 -0
  357. package/templates/wordpress/theme/src/core-breadcrumbs.css +124 -0
  358. package/templates/wordpress/theme/src/core-button-editor.css +45 -0
  359. package/templates/wordpress/theme/src/core-button.css +155 -0
  360. package/templates/wordpress/theme/src/core-card.css +157 -0
  361. package/templates/wordpress/theme/src/core-layout.css +73 -0
  362. package/templates/wordpress/theme/src/core-navigation.css +290 -0
  363. package/templates/wordpress/theme/src/core-pagination.css +112 -0
  364. package/templates/wordpress/theme/src/core-table.css +88 -0
  365. package/templates/wordpress/theme/src/core-tabs.css +86 -0
  366. package/templates/wordpress/theme/src/dialog.css +29 -0
  367. package/templates/wordpress/theme/src/editor.css +65 -0
  368. package/templates/wordpress/theme/src/field.css +95 -0
  369. package/templates/wordpress/theme/src/fonts.css +3 -0
  370. package/templates/wordpress/theme/src/gravityforms.css +919 -0
  371. package/templates/wordpress/theme/src/header.css +80 -0
  372. package/templates/wordpress/theme/src/icons.generated.css +16 -0
  373. package/templates/wordpress/theme/src/input-group.css +105 -0
  374. package/templates/wordpress/theme/src/input.css +116 -0
  375. package/templates/wordpress/theme/src/item.css +7 -0
  376. package/templates/wordpress/theme/src/looks.generated.css +358 -0
  377. package/templates/wordpress/theme/src/media.css +160 -0
  378. package/templates/wordpress/theme/src/radio.css +88 -0
  379. package/templates/wordpress/theme/src/sections.css +80 -0
  380. package/templates/wordpress/theme/src/sheet.css +24 -0
  381. package/templates/wordpress/theme/src/switch.css +120 -0
  382. package/templates/wordpress/theme/src/text-styles.css +44 -0
  383. package/templates/wordpress/theme/src/textarea.css +61 -0
  384. package/templates/wordpress/theme/src/toggle-group.css +28 -0
  385. package/templates/wordpress/theme/src/typeset.css +510 -0
  386. package/templates/wordpress/theme/style.css +13 -0
  387. package/templates/wordpress/theme/theme.json +362 -0
  388. package/templates/wordpress/web/wp-config.php +38 -0
  389. package/templates/wordpress/wp-cli.yml +1 -0
  390. package/templates/next/.claude/skills/ai-elements/SKILL.md +0 -160
  391. package/templates/next/.claude/skills/ai-elements/references/agent.md +0 -134
  392. package/templates/next/.claude/skills/ai-elements/references/artifact.md +0 -84
  393. package/templates/next/.claude/skills/ai-elements/references/attachments.md +0 -190
  394. package/templates/next/.claude/skills/ai-elements/references/audio-player.md +0 -134
  395. package/templates/next/.claude/skills/ai-elements/references/canvas.md +0 -34
  396. package/templates/next/.claude/skills/ai-elements/references/chain-of-thought.md +0 -81
  397. package/templates/next/.claude/skills/ai-elements/references/checkpoint.md +0 -183
  398. package/templates/next/.claude/skills/ai-elements/references/code-block.md +0 -170
  399. package/templates/next/.claude/skills/ai-elements/references/commit.md +0 -177
  400. package/templates/next/.claude/skills/ai-elements/references/confirmation.md +0 -262
  401. package/templates/next/.claude/skills/ai-elements/references/connection.md +0 -34
  402. package/templates/next/.claude/skills/ai-elements/references/context.md +0 -126
  403. package/templates/next/.claude/skills/ai-elements/references/controls.md +0 -32
  404. package/templates/next/.claude/skills/ai-elements/references/conversation.md +0 -224
  405. package/templates/next/.claude/skills/ai-elements/references/edge.md +0 -52
  406. package/templates/next/.claude/skills/ai-elements/references/environment-variables.md +0 -102
  407. package/templates/next/.claude/skills/ai-elements/references/file-tree.md +0 -72
  408. package/templates/next/.claude/skills/ai-elements/references/image.md +0 -146
  409. package/templates/next/.claude/skills/ai-elements/references/inline-citation.md +0 -299
  410. package/templates/next/.claude/skills/ai-elements/references/jsx-preview.md +0 -104
  411. package/templates/next/.claude/skills/ai-elements/references/message.md +0 -237
  412. package/templates/next/.claude/skills/ai-elements/references/mic-selector.md +0 -189
  413. package/templates/next/.claude/skills/ai-elements/references/model-selector.md +0 -112
  414. package/templates/next/.claude/skills/ai-elements/references/node.md +0 -73
  415. package/templates/next/.claude/skills/ai-elements/references/open-in-chat.md +0 -67
  416. package/templates/next/.claude/skills/ai-elements/references/package-info.md +0 -95
  417. package/templates/next/.claude/skills/ai-elements/references/panel.md +0 -33
  418. package/templates/next/.claude/skills/ai-elements/references/persona.md +0 -166
  419. package/templates/next/.claude/skills/ai-elements/references/plan.md +0 -79
  420. package/templates/next/.claude/skills/ai-elements/references/prompt-input.md +0 -579
  421. package/templates/next/.claude/skills/ai-elements/references/queue.md +0 -172
  422. package/templates/next/.claude/skills/ai-elements/references/reasoning.md +0 -238
  423. package/templates/next/.claude/skills/ai-elements/references/sandbox.md +0 -129
  424. package/templates/next/.claude/skills/ai-elements/references/schema-display.md +0 -102
  425. package/templates/next/.claude/skills/ai-elements/references/shimmer.md +0 -48
  426. package/templates/next/.claude/skills/ai-elements/references/snippet.md +0 -64
  427. package/templates/next/.claude/skills/ai-elements/references/sources.md +0 -209
  428. package/templates/next/.claude/skills/ai-elements/references/speech-input.md +0 -163
  429. package/templates/next/.claude/skills/ai-elements/references/stack-trace.md +0 -224
  430. package/templates/next/.claude/skills/ai-elements/references/suggestion.md +0 -124
  431. package/templates/next/.claude/skills/ai-elements/references/task.md +0 -222
  432. package/templates/next/.claude/skills/ai-elements/references/terminal.md +0 -103
  433. package/templates/next/.claude/skills/ai-elements/references/test-results.md +0 -157
  434. package/templates/next/.claude/skills/ai-elements/references/tool.md +0 -285
  435. package/templates/next/.claude/skills/ai-elements/references/toolbar.md +0 -32
  436. package/templates/next/.claude/skills/ai-elements/references/transcription.md +0 -120
  437. package/templates/next/.claude/skills/ai-elements/references/voice-selector.md +0 -241
  438. package/templates/next/.claude/skills/ai-elements/references/web-preview.md +0 -200
  439. package/templates/next/.claude/skills/ai-elements/scripts/agent.tsx +0 -61
  440. package/templates/next/.claude/skills/ai-elements/scripts/artifact.tsx +0 -127
  441. package/templates/next/.claude/skills/ai-elements/scripts/attachments-inline.tsx +0 -128
  442. package/templates/next/.claude/skills/ai-elements/scripts/attachments-list.tsx +0 -95
  443. package/templates/next/.claude/skills/ai-elements/scripts/attachments.tsx +0 -85
  444. package/templates/next/.claude/skills/ai-elements/scripts/audio-player-remote.tsx +0 -35
  445. package/templates/next/.claude/skills/ai-elements/scripts/audio-player.tsx +0 -68
  446. package/templates/next/.claude/skills/ai-elements/scripts/chain-of-thought.tsx +0 -82
  447. package/templates/next/.claude/skills/ai-elements/scripts/checkpoint.tsx +0 -110
  448. package/templates/next/.claude/skills/ai-elements/scripts/code-block-dark.tsx +0 -46
  449. package/templates/next/.claude/skills/ai-elements/scripts/code-block.tsx +0 -120
  450. package/templates/next/.claude/skills/ai-elements/scripts/commit.tsx +0 -94
  451. package/templates/next/.claude/skills/ai-elements/scripts/confirmation-accepted.tsx +0 -40
  452. package/templates/next/.claude/skills/ai-elements/scripts/confirmation-rejected.tsx +0 -40
  453. package/templates/next/.claude/skills/ai-elements/scripts/confirmation-request.tsx +0 -54
  454. package/templates/next/.claude/skills/ai-elements/scripts/confirmation.tsx +0 -55
  455. package/templates/next/.claude/skills/ai-elements/scripts/context.tsx +0 -45
  456. package/templates/next/.claude/skills/ai-elements/scripts/conversation.tsx +0 -177
  457. package/templates/next/.claude/skills/ai-elements/scripts/environment-variables.tsx +0 -62
  458. package/templates/next/.claude/skills/ai-elements/scripts/file-tree-basic.tsx +0 -18
  459. package/templates/next/.claude/skills/ai-elements/scripts/file-tree-expanded.tsx +0 -21
  460. package/templates/next/.claude/skills/ai-elements/scripts/file-tree-selection.tsx +0 -24
  461. package/templates/next/.claude/skills/ai-elements/scripts/file-tree.tsx +0 -42
  462. package/templates/next/.claude/skills/ai-elements/scripts/image.tsx +0 -20
  463. package/templates/next/.claude/skills/ai-elements/scripts/inline-citation.tsx +0 -97
  464. package/templates/next/.claude/skills/ai-elements/scripts/jsx-preview.tsx +0 -104
  465. package/templates/next/.claude/skills/ai-elements/scripts/message.tsx +0 -365
  466. package/templates/next/.claude/skills/ai-elements/scripts/mic-selector.tsx +0 -49
  467. package/templates/next/.claude/skills/ai-elements/scripts/model-selector.tsx +0 -365
  468. package/templates/next/.claude/skills/ai-elements/scripts/open-in-chat.tsx +0 -33
  469. package/templates/next/.claude/skills/ai-elements/scripts/package-info.tsx +0 -51
  470. package/templates/next/.claude/skills/ai-elements/scripts/persona-command.tsx +0 -110
  471. package/templates/next/.claude/skills/ai-elements/scripts/persona-glint.tsx +0 -110
  472. package/templates/next/.claude/skills/ai-elements/scripts/persona-halo.tsx +0 -110
  473. package/templates/next/.claude/skills/ai-elements/scripts/persona-mana.tsx +0 -110
  474. package/templates/next/.claude/skills/ai-elements/scripts/persona-obsidian.tsx +0 -110
  475. package/templates/next/.claude/skills/ai-elements/scripts/persona-opal.tsx +0 -110
  476. package/templates/next/.claude/skills/ai-elements/scripts/plan.tsx +0 -65
  477. package/templates/next/.claude/skills/ai-elements/scripts/prompt-input-cursor.tsx +0 -502
  478. package/templates/next/.claude/skills/ai-elements/scripts/prompt-input-tooltip.tsx +0 -44
  479. package/templates/next/.claude/skills/ai-elements/scripts/prompt-input.tsx +0 -267
  480. package/templates/next/.claude/skills/ai-elements/scripts/queue-prompt-input.tsx +0 -394
  481. package/templates/next/.claude/skills/ai-elements/scripts/queue.tsx +0 -295
  482. package/templates/next/.claude/skills/ai-elements/scripts/reasoning.tsx +0 -71
  483. package/templates/next/.claude/skills/ai-elements/scripts/sandbox.tsx +0 -178
  484. package/templates/next/.claude/skills/ai-elements/scripts/schema-display-basic.tsx +0 -9
  485. package/templates/next/.claude/skills/ai-elements/scripts/schema-display-body.tsx +0 -20
  486. package/templates/next/.claude/skills/ai-elements/scripts/schema-display-nested.tsx +0 -23
  487. package/templates/next/.claude/skills/ai-elements/scripts/schema-display-params.tsx +0 -16
  488. package/templates/next/.claude/skills/ai-elements/scripts/schema-display.tsx +0 -110
  489. package/templates/next/.claude/skills/ai-elements/scripts/shimmer-duration.tsx +0 -31
  490. package/templates/next/.claude/skills/ai-elements/scripts/shimmer-elements.tsx +0 -43
  491. package/templates/next/.claude/skills/ai-elements/scripts/shimmer.tsx +0 -17
  492. package/templates/next/.claude/skills/ai-elements/scripts/snippet-plain.tsx +0 -19
  493. package/templates/next/.claude/skills/ai-elements/scripts/snippet.tsx +0 -25
  494. package/templates/next/.claude/skills/ai-elements/scripts/sources-custom.tsx +0 -39
  495. package/templates/next/.claude/skills/ai-elements/scripts/sources.tsx +0 -32
  496. package/templates/next/.claude/skills/ai-elements/scripts/speech-input.tsx +0 -84
  497. package/templates/next/.claude/skills/ai-elements/scripts/stack-trace-collapsed.tsx +0 -39
  498. package/templates/next/.claude/skills/ai-elements/scripts/stack-trace-no-internal.tsx +0 -41
  499. package/templates/next/.claude/skills/ai-elements/scripts/stack-trace.tsx +0 -58
  500. package/templates/next/.claude/skills/ai-elements/scripts/suggestion-input.tsx +0 -144
  501. package/templates/next/.claude/skills/ai-elements/scripts/suggestion.tsx +0 -32
  502. package/templates/next/.claude/skills/ai-elements/scripts/task.tsx +0 -59
  503. package/templates/next/.claude/skills/ai-elements/scripts/terminal-basic.tsx +0 -7
  504. package/templates/next/.claude/skills/ai-elements/scripts/terminal-clear.tsx +0 -19
  505. package/templates/next/.claude/skills/ai-elements/scripts/terminal-streaming.tsx +0 -38
  506. package/templates/next/.claude/skills/ai-elements/scripts/terminal.tsx +0 -82
  507. package/templates/next/.claude/skills/ai-elements/scripts/test-results-basic.tsx +0 -27
  508. package/templates/next/.claude/skills/ai-elements/scripts/test-results-errors.tsx +0 -51
  509. package/templates/next/.claude/skills/ai-elements/scripts/test-results-suites.tsx +0 -40
  510. package/templates/next/.claude/skills/ai-elements/scripts/test-results.tsx +0 -102
  511. package/templates/next/.claude/skills/ai-elements/scripts/tool-input-available.tsx +0 -31
  512. package/templates/next/.claude/skills/ai-elements/scripts/tool-input-streaming.tsx +0 -30
  513. package/templates/next/.claude/skills/ai-elements/scripts/tool-output-available.tsx +0 -80
  514. package/templates/next/.claude/skills/ai-elements/scripts/tool-output-error.tsx +0 -44
  515. package/templates/next/.claude/skills/ai-elements/scripts/tool.tsx +0 -222
  516. package/templates/next/.claude/skills/ai-elements/scripts/transcription.tsx +0 -290
  517. package/templates/next/.claude/skills/ai-elements/scripts/voice-selector.tsx +0 -245
  518. package/templates/next/.claude/skills/ai-elements/scripts/web-preview.tsx +0 -115
  519. package/templates/next/.claude/skills/ai-sdk/SKILL.md +0 -78
  520. package/templates/next/.claude/skills/frontend-design/LICENSE.txt +0 -177
  521. package/templates/next/.claude/skills/frontend-design/SKILL.md +0 -55
  522. package/templates/next/.claude/skills/gc-implement-figma-page/SKILL.md +0 -93
  523. package/templates/next/.claude/skills/migrate-ai-sdk-v6-to-v7/SKILL.md +0 -108
  524. package/templates/next/.claude/skills/vercel-composition-patterns/AGENTS.md +0 -946
  525. package/templates/next/.claude/skills/vercel-composition-patterns/README.md +0 -60
  526. package/templates/next/.claude/skills/vercel-composition-patterns/SKILL.md +0 -89
  527. package/templates/next/.claude/skills/vercel-composition-patterns/metadata.json +0 -11
  528. package/templates/next/.claude/skills/vercel-composition-patterns/rules/_sections.md +0 -29
  529. package/templates/next/.claude/skills/vercel-composition-patterns/rules/_template.md +0 -24
  530. package/templates/next/.claude/skills/vercel-composition-patterns/rules/architecture-avoid-boolean-props.md +0 -100
  531. package/templates/next/.claude/skills/vercel-composition-patterns/rules/architecture-compound-components.md +0 -112
  532. package/templates/next/.claude/skills/vercel-composition-patterns/rules/patterns-children-over-render-props.md +0 -87
  533. package/templates/next/.claude/skills/vercel-composition-patterns/rules/patterns-explicit-variants.md +0 -100
  534. package/templates/next/.claude/skills/vercel-composition-patterns/rules/react19-no-forwardref.md +0 -42
  535. package/templates/next/.claude/skills/vercel-composition-patterns/rules/state-context-interface.md +0 -191
  536. package/templates/next/.claude/skills/vercel-composition-patterns/rules/state-decouple-implementation.md +0 -113
  537. package/templates/next/.claude/skills/vercel-composition-patterns/rules/state-lift-state.md +0 -125
  538. package/templates/next/.claude/skills/vercel-react-best-practices/AGENTS.md +0 -3810
  539. package/templates/next/.claude/skills/vercel-react-best-practices/README.md +0 -123
  540. package/templates/next/.claude/skills/vercel-react-best-practices/SKILL.md +0 -149
  541. package/templates/next/.claude/skills/vercel-react-best-practices/metadata.json +0 -15
  542. package/templates/next/.claude/skills/vercel-react-best-practices/rules/_sections.md +0 -46
  543. package/templates/next/.claude/skills/vercel-react-best-practices/rules/_template.md +0 -28
  544. package/templates/next/.claude/skills/vercel-react-best-practices/rules/advanced-effect-event-deps.md +0 -56
  545. package/templates/next/.claude/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -55
  546. package/templates/next/.claude/skills/vercel-react-best-practices/rules/advanced-init-once.md +0 -42
  547. package/templates/next/.claude/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -39
  548. package/templates/next/.claude/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -38
  549. package/templates/next/.claude/skills/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +0 -37
  550. package/templates/next/.claude/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -82
  551. package/templates/next/.claude/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -51
  552. package/templates/next/.claude/skills/vercel-react-best-practices/rules/async-parallel.md +0 -28
  553. package/templates/next/.claude/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -99
  554. package/templates/next/.claude/skills/vercel-react-best-practices/rules/bundle-analyzable-paths.md +0 -63
  555. package/templates/next/.claude/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -60
  556. package/templates/next/.claude/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -31
  557. package/templates/next/.claude/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -49
  558. package/templates/next/.claude/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -35
  559. package/templates/next/.claude/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -50
  560. package/templates/next/.claude/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -74
  561. package/templates/next/.claude/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -71
  562. package/templates/next/.claude/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -48
  563. package/templates/next/.claude/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -56
  564. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -107
  565. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -80
  566. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -28
  567. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -70
  568. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -32
  569. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -50
  570. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-flatmap-filter.md +0 -60
  571. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -45
  572. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -37
  573. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -49
  574. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -82
  575. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-request-idle-callback.md +0 -105
  576. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -24
  577. package/templates/next/.claude/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -57
  578. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -26
  579. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -47
  580. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -40
  581. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -38
  582. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -46
  583. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -82
  584. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +0 -30
  585. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rendering-resource-hints.md +0 -85
  586. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rendering-script-defer-async.md +0 -68
  587. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -28
  588. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +0 -75
  589. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -39
  590. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -45
  591. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +0 -40
  592. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -29
  593. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -74
  594. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -58
  595. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +0 -38
  596. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -44
  597. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +0 -45
  598. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-no-inline-components.md +0 -82
  599. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -35
  600. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +0 -64
  601. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -40
  602. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-use-deferred-value.md +0 -59
  603. package/templates/next/.claude/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +0 -73
  604. package/templates/next/.claude/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -73
  605. package/templates/next/.claude/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -96
  606. package/templates/next/.claude/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -41
  607. package/templates/next/.claude/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -76
  608. package/templates/next/.claude/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -65
  609. package/templates/next/.claude/skills/vercel-react-best-practices/rules/server-hoist-static-io.md +0 -149
  610. package/templates/next/.claude/skills/vercel-react-best-practices/rules/server-no-shared-module-state.md +0 -50
  611. package/templates/next/.claude/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -83
  612. package/templates/next/.claude/skills/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +0 -34
  613. package/templates/next/.claude/skills/vercel-react-best-practices/rules/server-serialization.md +0 -38
  614. package/templates/next/.claude/skills/web-design-guidelines/SKILL.md +0 -39
  615. package/templates/next/CLAUDE.md +0 -42
  616. package/templates/next/README.md +0 -30
  617. package/templates/next/_gitignore +0 -4
  618. package/templates/next/app/layout.tsx +0 -44
  619. package/templates/next/globals.d.ts +0 -8
  620. package/templates/next/next.config.mjs +0 -6
  621. package/templates/next/package.json +0 -38
  622. package/templates/next/postcss.config.mjs +0 -5
  623. package/templates/next/skills-lock.json +0 -47
  624. package/templates/next/tsconfig.json +0 -36
  625. package/templates/shopify-theme/.claude/skills/gc-shopify-block/SKILL.md +0 -44
  626. package/templates/shopify-theme/.claude/skills/shopify-dev/SKILL.md +0 -51
  627. package/templates/shopify-theme/.claude/skills/shopify-dev/scripts/log_skill_use.mjs +0 -205
  628. package/templates/shopify-theme/.claude/skills/shopify-dev/scripts/search_docs.mjs +0 -272
  629. package/templates/shopify-theme/.claude/skills/shopify-dev/scripts/track-telemetry.ps1 +0 -361
  630. package/templates/shopify-theme/.claude/skills/shopify-dev/scripts/track-telemetry.sh +0 -527
  631. package/templates/shopify-theme/.claude/skills/shopify-liquid/SKILL.md +0 -343
  632. package/templates/shopify-theme/.claude/skills/shopify-liquid/blocks/hero-slide.liquid +0 -342
  633. package/templates/shopify-theme/.claude/skills/shopify-liquid/config/settings_schema.json +0 -1
  634. package/templates/shopify-theme/.claude/skills/shopify-liquid/featured-collection.liquid +0 -457
  635. package/templates/shopify-theme/.claude/skills/shopify-liquid/locales/en.default.json +0 -10
  636. package/templates/shopify-theme/.claude/skills/shopify-liquid/locales/en.default.schema.json +0 -103
  637. package/templates/shopify-theme/.claude/skills/shopify-liquid/package.json +0 -10
  638. package/templates/shopify-theme/.claude/skills/shopify-liquid/scripts/search_docs.mjs +0 -759
  639. package/templates/shopify-theme/.claude/skills/shopify-liquid/scripts/track-telemetry.ps1 +0 -361
  640. package/templates/shopify-theme/.claude/skills/shopify-liquid/scripts/track-telemetry.sh +0 -527
  641. package/templates/shopify-theme/.claude/skills/shopify-liquid/scripts/validate.mjs +0 -654
  642. package/templates/shopify-theme/.claude/skills/shopify-liquid/sections/hero-banner.liquid +0 -329
  643. package/templates/shopify-theme/.claude/skills/shopify-use-shopify-cli/SKILL.md +0 -165
  644. package/templates/shopify-theme/.claude/skills/shopify-use-shopify-cli/scripts/log_skill_use.mjs +0 -205
  645. package/templates/shopify-theme/.claude/skills/shopify-use-shopify-cli/scripts/track-telemetry.ps1 +0 -361
  646. package/templates/shopify-theme/.claude/skills/shopify-use-shopify-cli/scripts/track-telemetry.sh +0 -527
  647. package/templates/shopify-theme/.shopifyignore +0 -9
  648. package/templates/shopify-theme/CLAUDE.md +0 -51
  649. package/templates/shopify-theme/README.md +0 -92
  650. package/templates/shopify-theme/assets/baseline.css +0 -8390
  651. package/templates/shopify-theme/assets/swiper-element-bundle.min.js +0 -14
  652. package/templates/shopify-theme/blocks/_accordion.liquid +0 -59
  653. package/templates/shopify-theme/blocks/_carousel-slide.liquid +0 -24
  654. package/templates/shopify-theme/blocks/_modal-body.liquid +0 -18
  655. package/templates/shopify-theme/blocks/_modal-footer.liquid +0 -36
  656. package/templates/shopify-theme/blocks/_modal-header.liquid +0 -19
  657. package/templates/shopify-theme/blocks/_modal-media.liquid +0 -37
  658. package/templates/shopify-theme/blocks/accordion-group.liquid +0 -53
  659. package/templates/shopify-theme/blocks/alert.liquid +0 -92
  660. package/templates/shopify-theme/blocks/avatar-group.liquid +0 -51
  661. package/templates/shopify-theme/blocks/avatar.liquid +0 -56
  662. package/templates/shopify-theme/blocks/badge.liquid +0 -33
  663. package/templates/shopify-theme/blocks/breadcrumb.liquid +0 -45
  664. package/templates/shopify-theme/blocks/button.liquid +0 -51
  665. package/templates/shopify-theme/blocks/buttons.liquid +0 -41
  666. package/templates/shopify-theme/blocks/card.liquid +0 -67
  667. package/templates/shopify-theme/blocks/carousel.liquid +0 -55
  668. package/templates/shopify-theme/blocks/column.liquid +0 -33
  669. package/templates/shopify-theme/blocks/image.liquid +0 -37
  670. package/templates/shopify-theme/blocks/modal.liquid +0 -52
  671. package/templates/shopify-theme/blocks/popover.liquid +0 -24
  672. package/templates/shopify-theme/blocks/skeleton.liquid +0 -22
  673. package/templates/shopify-theme/blocks/spinner.liquid +0 -22
  674. package/templates/shopify-theme/blocks/split.liquid +0 -39
  675. package/templates/shopify-theme/blocks/tab.liquid +0 -19
  676. package/templates/shopify-theme/blocks/tabs.liquid +0 -78
  677. package/templates/shopify-theme/blocks/tags.liquid +0 -55
  678. package/templates/shopify-theme/blocks/text.liquid +0 -55
  679. package/templates/shopify-theme/blocks/tooltip.liquid +0 -50
  680. package/templates/shopify-theme/blocks/typography.liquid +0 -90
  681. package/templates/shopify-theme/config/settings_data.json +0 -4
  682. package/templates/shopify-theme/config/settings_schema.json +0 -10
  683. package/templates/shopify-theme/layout/theme.liquid +0 -21
  684. package/templates/shopify-theme/locales/en.default.json +0 -5
  685. package/templates/shopify-theme/locales/en.default.schema.json +0 -131
  686. package/templates/shopify-theme/package.json +0 -21
  687. package/templates/shopify-theme/scripts/sync-tokens.mjs +0 -32
  688. package/templates/shopify-theme/sections/baseline-components.liquid +0 -81
  689. package/templates/shopify-theme/skills-lock.json +0 -23
  690. package/templates/shopify-theme/snippets/lucide.liquid +0 -34
  691. package/templates/shopify-theme/snippets/pagination.liquid +0 -44
  692. package/templates/shopify-theme/templates/collection.json +0 -13
  693. package/templates/shopify-theme/templates/gift_card.liquid +0 -5
  694. package/templates/shopify-theme/templates/index.json +0 -135
  695. package/templates/shopify-theme/templates/list-collections.json +0 -13
  696. package/templates/shopify-theme/templates/product.json +0 -13
  697. package/templates/wordpress/.claude/CLAUDE.md +0 -37
  698. package/templates/wordpress/.claude/skills/wp-block-development/SKILL.md +0 -174
  699. package/templates/wordpress/.claude/skills/wp-block-development/references/attributes-and-serialization.md +0 -22
  700. package/templates/wordpress/.claude/skills/wp-block-development/references/block-json.md +0 -49
  701. package/templates/wordpress/.claude/skills/wp-block-development/references/creating-new-blocks.md +0 -46
  702. package/templates/wordpress/.claude/skills/wp-block-development/references/debugging.md +0 -36
  703. package/templates/wordpress/.claude/skills/wp-block-development/references/deprecations.md +0 -24
  704. package/templates/wordpress/.claude/skills/wp-block-development/references/dynamic-rendering.md +0 -23
  705. package/templates/wordpress/.claude/skills/wp-block-development/references/inner-blocks.md +0 -25
  706. package/templates/wordpress/.claude/skills/wp-block-development/references/registration.md +0 -30
  707. package/templates/wordpress/.claude/skills/wp-block-development/references/supports-and-wrappers.md +0 -18
  708. package/templates/wordpress/.claude/skills/wp-block-development/references/tooling-and-testing.md +0 -21
  709. package/templates/wordpress/.claude/skills/wp-block-development/scripts/list_blocks.mjs +0 -121
  710. package/templates/wordpress/.claude/skills/wp-block-themes/SKILL.md +0 -116
  711. package/templates/wordpress/.claude/skills/wp-block-themes/references/creating-new-block-theme.md +0 -37
  712. package/templates/wordpress/.claude/skills/wp-block-themes/references/debugging.md +0 -24
  713. package/templates/wordpress/.claude/skills/wp-block-themes/references/patterns.md +0 -18
  714. package/templates/wordpress/.claude/skills/wp-block-themes/references/style-variations.md +0 -14
  715. package/templates/wordpress/.claude/skills/wp-block-themes/references/templates-and-parts.md +0 -16
  716. package/templates/wordpress/.claude/skills/wp-block-themes/references/theme-json.md +0 -59
  717. package/templates/wordpress/.claude/skills/wp-block-themes/scripts/detect_block_themes.mjs +0 -117
  718. package/templates/wordpress/.claude/skills/wp-performance/SKILL.md +0 -146
  719. package/templates/wordpress/.claude/skills/wp-performance/references/autoload-options.md +0 -24
  720. package/templates/wordpress/.claude/skills/wp-performance/references/cron.md +0 -20
  721. package/templates/wordpress/.claude/skills/wp-performance/references/database.md +0 -20
  722. package/templates/wordpress/.claude/skills/wp-performance/references/http-api.md +0 -15
  723. package/templates/wordpress/.claude/skills/wp-performance/references/measurement.md +0 -21
  724. package/templates/wordpress/.claude/skills/wp-performance/references/object-cache.md +0 -24
  725. package/templates/wordpress/.claude/skills/wp-performance/references/query-monitor-headless.md +0 -38
  726. package/templates/wordpress/.claude/skills/wp-performance/references/server-timing.md +0 -22
  727. package/templates/wordpress/.claude/skills/wp-performance/references/wp-cli-doctor.md +0 -24
  728. package/templates/wordpress/.claude/skills/wp-performance/references/wp-cli-profile.md +0 -32
  729. package/templates/wordpress/.claude/skills/wp-performance/scripts/perf_inspect.mjs +0 -128
  730. package/templates/wordpress/.claude/skills/wp-plugin-development/SKILL.md +0 -112
  731. package/templates/wordpress/.claude/skills/wp-plugin-development/references/data-and-cron.md +0 -19
  732. package/templates/wordpress/.claude/skills/wp-plugin-development/references/debugging.md +0 -19
  733. package/templates/wordpress/.claude/skills/wp-plugin-development/references/lifecycle.md +0 -33
  734. package/templates/wordpress/.claude/skills/wp-plugin-development/references/security.md +0 -29
  735. package/templates/wordpress/.claude/skills/wp-plugin-development/references/settings-api.md +0 -22
  736. package/templates/wordpress/.claude/skills/wp-plugin-development/references/structure.md +0 -16
  737. package/templates/wordpress/.claude/skills/wp-plugin-development/scripts/detect_plugins.mjs +0 -122
  738. package/templates/wordpress/.claude/skills/wp-rest-api/SKILL.md +0 -114
  739. package/templates/wordpress/.claude/skills/wp-rest-api/references/authentication.md +0 -18
  740. package/templates/wordpress/.claude/skills/wp-rest-api/references/custom-content-types.md +0 -20
  741. package/templates/wordpress/.claude/skills/wp-rest-api/references/discovery-and-params.md +0 -20
  742. package/templates/wordpress/.claude/skills/wp-rest-api/references/responses-and-fields.md +0 -30
  743. package/templates/wordpress/.claude/skills/wp-rest-api/references/routes-and-endpoints.md +0 -36
  744. package/templates/wordpress/.claude/skills/wp-rest-api/references/schema.md +0 -22
  745. package/templates/wordpress/.ddev/docker-compose.packages.yaml +0 -14
  746. package/templates/wordpress/.ddev/docker-compose.redis.yaml +0 -11
  747. package/templates/wordpress/.env.example +0 -33
  748. package/templates/wordpress/CLAUDE.md +0 -34
  749. package/templates/wordpress/_gitignore +0 -33
  750. package/templates/wordpress/composer.lock +0 -1594
  751. package/templates/wordpress/package.json +0 -13
  752. package/templates/wordpress/scripts/seed.sh +0 -64
  753. package/templates/wordpress/skills-lock.json +0 -35
  754. package/templates/wordpress/wp-config.php +0 -89
  755. package/templates/wordpress/wp-content/index.php +0 -2
  756. package/templates/wordpress/wp-content/mu-plugins/baseline-bootstrap.php +0 -26
@@ -0,0 +1,111 @@
1
+ <?php
2
+ /**
3
+ * Baseline Avatar for template code (spec: components/avatar/spec.md): a person or entity that is not a WordPress user
4
+ * (a team member, a testimonial author, a company). Post and comment authors use core/avatar, styled in
5
+ * src/core-avatar.css. Emits the same markup and classes as the React Avatar (registry/src/ui/avatar/avatar.tsx):
6
+ *
7
+ * echo baseline_avatar(['src' => $photo_url, 'alt' => 'Jordan Diaz', 'fallback' => 'JD']);
8
+ * echo baseline_avatar(['fallback' => 'JD', 'size' => 'lg', 'badge' => 'success', 'badge_label' => 'online']);
9
+ * echo baseline_avatar(['icon' => 'user', 'size' => 'sm']);
10
+ *
11
+ * Without JavaScript there is no load state: the <img> renders when there is a URL and the fallback otherwise.
12
+ * Class strings are static maps (ADR-0008): Tailwind scans this file, so every class must appear here literally.
13
+ */
14
+
15
+ declare(strict_types=1);
16
+
17
+ const BASELINE_AVATAR_ROOT = 'group/avatar relative flex shrink-0 rounded-full select-none after:pointer-events-none after:absolute after:inset-0 after:rounded-full after:border-(length:--bl-avatar-border-width) after:border-border after:mix-blend-darken';
18
+
19
+ const BASELINE_AVATAR_SIZES = [
20
+ 'xs' => 'size-(--bl-avatar-xs-size)',
21
+ 'sm' => 'size-(--bl-avatar-sm-size)',
22
+ 'md' => 'size-(--bl-avatar-md-size)',
23
+ 'lg' => 'size-(--bl-avatar-lg-size)',
24
+ 'xl' => 'size-(--bl-avatar-xl-size)',
25
+ ];
26
+
27
+ const BASELINE_AVATAR_IMAGE = 'aspect-square size-full rounded-full object-cover';
28
+
29
+ const BASELINE_AVATAR_FALLBACK = 'flex size-full items-center justify-center rounded-full bg-muted text-muted-foreground font-(family-name:--bl-avatar-font-family) font-(--bl-avatar-font-weight) group-data-[size=xs]/avatar:text-(length:--bl-avatar-xs-font-size) group-data-[size=xs]/avatar:leading-(--bl-avatar-xs-line-height) group-data-[size=sm]/avatar:text-(length:--bl-avatar-sm-font-size) group-data-[size=sm]/avatar:leading-(--bl-avatar-sm-line-height) group-data-[size=md]/avatar:text-(length:--bl-avatar-md-font-size) group-data-[size=md]/avatar:leading-(--bl-avatar-md-line-height) group-data-[size=lg]/avatar:text-(length:--bl-avatar-lg-font-size) group-data-[size=lg]/avatar:leading-(--bl-avatar-lg-line-height) group-data-[size=xl]/avatar:text-(length:--bl-avatar-xl-font-size) group-data-[size=xl]/avatar:leading-(--bl-avatar-xl-line-height)';
30
+
31
+ // the fallback icon's size per avatar size (an svg here, where React sizes its <Icon> span)
32
+ const BASELINE_AVATAR_ICON = [
33
+ 'xs' => 'size-(--bl-avatar-xs-icon-size)',
34
+ 'sm' => 'size-(--bl-avatar-sm-icon-size)',
35
+ 'md' => 'size-(--bl-avatar-md-icon-size)',
36
+ 'lg' => 'size-(--bl-avatar-lg-icon-size)',
37
+ 'xl' => 'size-(--bl-avatar-xl-icon-size)',
38
+ ];
39
+
40
+ const BASELINE_AVATAR_BADGE = 'absolute end-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground select-none ring-(length:--bl-overlap-ring-width) ring-background group-data-[size=xs]/avatar:size-(--bl-avatar-xs-badge-size) group-data-[size=sm]/avatar:size-(--bl-avatar-sm-badge-size) group-data-[size=md]/avatar:size-(--bl-avatar-md-badge-size) group-data-[size=lg]/avatar:size-(--bl-avatar-lg-badge-size) group-data-[size=xl]/avatar:size-(--bl-avatar-xl-badge-size)';
41
+
42
+ /**
43
+ * @param array{
44
+ * src?: string, alt?: string, fallback?: string, icon?: string, size?: string,
45
+ * badge?: bool|string, badge_label?: string, class?: string, root_attrs?: string
46
+ * } $args `badge` is true for a plain dot or a status scheme ('success' | 'warning' | 'error'); `root_attrs` replaces
47
+ * the root's class attribute (the acf/avatar block passes get_block_wrapper_attributes() built on
48
+ * baseline_avatar_classes(), so the avatar itself is the block's root and no wrapper div breaks a group)
49
+ */
50
+ function baseline_avatar(array $args): string
51
+ {
52
+ $size = baseline_avatar_size((string) ($args['size'] ?? 'md'));
53
+ $src = (string) ($args['src'] ?? '');
54
+ $alt = (string) ($args['alt'] ?? '');
55
+
56
+ if ($src !== '') {
57
+ $inner = '<img data-slot="avatar-image" class="' . BASELINE_AVATAR_IMAGE . '" src="' . esc_url($src) . '" alt="' . esc_attr($alt) . '" loading="lazy" decoding="async">';
58
+ } else {
59
+ $content = !empty($args['icon'])
60
+ ? baseline_icon((string) $args['icon'], BASELINE_AVATAR_ICON[$size] . ' shrink-0', $alt)
61
+ : esc_html((string) ($args['fallback'] ?? ''));
62
+ $label = ($alt !== '' && empty($args['icon'])) ? ' role="img" aria-label="' . esc_attr($alt) . '"' : '';
63
+ $inner = '<span data-slot="avatar-fallback" class="' . BASELINE_AVATAR_FALLBACK . '"' . $label . '>' . $content . '</span>';
64
+ }
65
+
66
+ $badge = '';
67
+ if (!empty($args['badge'])) {
68
+ $scheme = in_array($args['badge'], ['success', 'warning', 'error'], true) ? ' data-scheme="' . $args['badge'] . '"' : '';
69
+ $hidden = !empty($args['badge_label']) ? '<span class="sr-only">' . esc_html((string) $args['badge_label']) . '</span>' : '';
70
+ $badge = '<span data-slot="avatar-badge" class="' . BASELINE_AVATAR_BADGE . '"' . $scheme . '>' . $hidden . '</span>';
71
+ }
72
+
73
+ $root = isset($args['root_attrs'])
74
+ ? (string) $args['root_attrs']
75
+ : 'class="' . esc_attr(baseline_avatar_classes($size, (string) ($args['class'] ?? ''))) . '"';
76
+ return '<span data-slot="avatar" data-size="' . $size . '" ' . $root . '>' . $inner . $badge . '</span>';
77
+ }
78
+
79
+ /** A size from the five, md otherwise. */
80
+ function baseline_avatar_size(string $size): string
81
+ {
82
+ return isset(BASELINE_AVATAR_SIZES[$size]) ? $size : 'md';
83
+ }
84
+
85
+ /** The avatar root's classes for a size (shared by baseline_avatar() and the acf/avatar block's wrapper attributes). */
86
+ function baseline_avatar_classes(string $size, string $extra = ''): string
87
+ {
88
+ // not-typeset: typeset's media rule gives an <img> a top margin and radius, which pushed the photo out of the circle
89
+ return trim(BASELINE_AVATAR_ROOT . ' not-typeset ' . BASELINE_AVATAR_SIZES[baseline_avatar_size($size)] . ' ' . $extra);
90
+ }
91
+
92
+ // Avatar Group and its "+N" count: the React AvatarGroup / AvatarGroupCount classes (each avatar after the first moves
93
+ // in by avatar/group/gap and gets the shared overlap ring; the count takes the size of the group's avatars).
94
+ const BASELINE_AVATAR_GROUP = 'group/avatar-group not-typeset flex space-x-(--bl-avatar-group-gap) *:data-[slot=avatar]:ring-(length:--bl-overlap-ring-width) *:data-[slot=avatar]:ring-background';
95
+
96
+ const BASELINE_AVATAR_GROUP_COUNT = 'after:pointer-events-none after:absolute after:inset-0 after:rounded-full after:border-(length:--bl-avatar-border-width) after:border-border after:mix-blend-darken relative flex shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground ring-(length:--bl-overlap-ring-width) ring-background font-(family-name:--bl-avatar-font-family) font-(--bl-avatar-font-weight) size-(--bl-avatar-md-size) text-(length:--bl-avatar-md-font-size) leading-(--bl-avatar-md-line-height) group-has-data-[size=xs]/avatar-group:size-(--bl-avatar-xs-size) group-has-data-[size=xs]/avatar-group:text-(length:--bl-avatar-xs-font-size) group-has-data-[size=xs]/avatar-group:leading-(--bl-avatar-xs-line-height) group-has-data-[size=sm]/avatar-group:size-(--bl-avatar-sm-size) group-has-data-[size=sm]/avatar-group:text-(length:--bl-avatar-sm-font-size) group-has-data-[size=sm]/avatar-group:leading-(--bl-avatar-sm-line-height) group-has-data-[size=lg]/avatar-group:size-(--bl-avatar-lg-size) group-has-data-[size=lg]/avatar-group:text-(length:--bl-avatar-lg-font-size) group-has-data-[size=lg]/avatar-group:leading-(--bl-avatar-lg-line-height) group-has-data-[size=xl]/avatar-group:size-(--bl-avatar-xl-size) group-has-data-[size=xl]/avatar-group:text-(length:--bl-avatar-xl-font-size) group-has-data-[size=xl]/avatar-group:leading-(--bl-avatar-xl-line-height)';
97
+
98
+ /** The "+N" that ends a group. */
99
+ function baseline_avatar_group_count(int $count): string
100
+ {
101
+ return '<div data-slot="avatar-group-count" class="' . BASELINE_AVATAR_GROUP_COUNT . '">+' . $count . '</div>';
102
+ }
103
+
104
+ /** The acf/avatar block's Icon select lists the active icon set's vocabulary, as acf/badge's does. */
105
+ add_filter('acf/load_field/key=field_baseline_avatar_icon', static function (array $field): array {
106
+ $field['choices'] = ['' => __('None (initials)', 'baseline')];
107
+ foreach (baseline_icons() as $name => $icon) {
108
+ $field['choices'][$name] = (string) ($icon['label'] ?? $name);
109
+ }
110
+ return $field;
111
+ });
@@ -0,0 +1,96 @@
1
+ <?php
2
+ /**
3
+ * Baseline Badge for template code and the acf/badge block (spec: components/badge/spec.md). Emits the same markup
4
+ * and classes as the React Badge (registry/src/ui/badge/badge.tsx), so the HTML target and this theme agree:
5
+ *
6
+ * echo baseline_badge(['label' => 'New']);
7
+ * echo baseline_badge(['label' => 'Sale', 'variant' => 'destructive', 'size' => 'sm']);
8
+ * echo baseline_badge(['label' => 'Paid', 'scheme' => 'success', 'icon' => 'check']);
9
+ * echo baseline_badge(['label' => 'Docs', 'variant' => 'outline', 'href' => '/docs']);
10
+ *
11
+ * Status is the scheme, never a variant (PLAN §5.2): `scheme` renders as data-scheme on the badge.
12
+ * Class strings are static maps (ADR-0008): Tailwind scans this file, so every class must appear here literally.
13
+ */
14
+
15
+ declare(strict_types=1);
16
+
17
+ const BASELINE_BADGE_BASE = 'group/badge inline-flex w-fit shrink-0 items-center justify-center overflow-hidden whitespace-nowrap border-(length:--bl-badge-border-width) border-transparent font-(--bl-badge-font-weight) transition-all focus-visible:border-ring focus-visible:ring-(length:--bl-control-ring-width) focus-visible:ring-ring/50 [&>svg]:pointer-events-none';
18
+
19
+ const BASELINE_BADGE_VARIANTS = [
20
+ 'default' => 'bg-primary text-primary-foreground [a]:hover:bg-primary/80',
21
+ 'secondary' => 'bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80',
22
+ 'destructive' => 'bg-destructive/10 text-destructive focus-visible:ring-destructive/20 [a]:hover:bg-destructive/20',
23
+ 'outline' => 'border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground',
24
+ 'ghost' => 'text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground',
25
+ 'link' => 'text-primary underline-offset-4 [a]:hover:underline',
26
+ ];
27
+
28
+ const BASELINE_BADGE_SIZES = [
29
+ 'sm' => 'h-(--bl-badge-sm-height) gap-(--bl-badge-sm-gap) px-(--bl-badge-sm-padding-x) rounded-(--bl-badge-sm-radius) text-(length:--bl-badge-sm-font-size) leading-(--bl-badge-sm-line-height) [&>svg]:size-(--bl-badge-sm-icon-size) has-data-[icon=inline-start]:ps-(--bl-badge-sm-padding-x-icon) has-data-[icon=inline-end]:pe-(--bl-badge-sm-padding-x-icon)',
30
+ 'md' => 'h-(--bl-badge-md-height) gap-(--bl-badge-md-gap) px-(--bl-badge-md-padding-x) rounded-(--bl-badge-md-radius) text-(length:--bl-badge-md-font-size) leading-(--bl-badge-md-line-height) [&>svg]:size-(--bl-badge-md-icon-size) has-data-[icon=inline-start]:ps-(--bl-badge-md-padding-x-icon) has-data-[icon=inline-end]:pe-(--bl-badge-md-padding-x-icon)',
31
+ ];
32
+
33
+ const BASELINE_BADGE_SCHEMES = ['success', 'warning', 'error'];
34
+
35
+ /**
36
+ * @param array{
37
+ * label?: string, variant?: string, size?: string, scheme?: string, icon?: string, icon_position?: string,
38
+ * href?: string, target?: string, class?: string
39
+ * } $args
40
+ */
41
+ function baseline_badge(array $args): string
42
+ {
43
+ $variant = (string) ($args['variant'] ?? 'default');
44
+ $size = (string) ($args['size'] ?? 'md');
45
+ $scheme = (string) ($args['scheme'] ?? '');
46
+ $icon = (string) ($args['icon'] ?? '');
47
+ $end = ($args['icon_position'] ?? 'start') === 'end';
48
+ $href = (string) ($args['href'] ?? '');
49
+ if (!isset(BASELINE_BADGE_VARIANTS[$variant])) {
50
+ $variant = 'default';
51
+ }
52
+ if (!isset(BASELINE_BADGE_SIZES[$size])) {
53
+ $size = 'md';
54
+ }
55
+
56
+ // not-typeset: a link badge in post content must not take typeset's link styling (ADR-0028)
57
+ $classes = trim(BASELINE_BADGE_BASE . ' not-typeset ' . BASELINE_BADGE_VARIANTS[$variant] . ' ' . BASELINE_BADGE_SIZES[$size] . ' ' . (string) ($args['class'] ?? ''));
58
+ $attrs = [
59
+ 'class' => $classes,
60
+ 'data-slot' => 'badge',
61
+ 'data-variant' => $variant,
62
+ 'data-size' => $size,
63
+ 'data-scheme' => in_array($scheme, BASELINE_BADGE_SCHEMES, true) ? $scheme : null,
64
+ ];
65
+
66
+ $glyph = '';
67
+ if ($icon !== '') {
68
+ // shrink-0 only: the badge's [&>svg]:size-* rule sizes the glyph from the tokens
69
+ $svg = baseline_icon($icon, 'shrink-0');
70
+ $glyph = (string) preg_replace('/^<svg\b/', '<svg data-icon="' . ($end ? 'inline-end' : 'inline-start') . '"', $svg, 1);
71
+ }
72
+ $label = esc_html((string) ($args['label'] ?? __('Badge', 'baseline')));
73
+ $inner = $end ? $label . $glyph : $glyph . $label;
74
+
75
+ if ($href !== '') {
76
+ $attrs['href'] = $href;
77
+ if (!empty($args['target'])) {
78
+ $attrs['target'] = (string) $args['target'];
79
+ $attrs['rel'] = 'noopener';
80
+ }
81
+ return '<a' . baseline_attrs($attrs) . '>' . $inner . '</a>';
82
+ }
83
+ return '<span' . baseline_attrs($attrs) . '>' . $inner . '</span>';
84
+ }
85
+
86
+ /**
87
+ * The block's Icon select lists the active icon set's vocabulary (inc/icons.generated.php), so it follows the set
88
+ * the designer picked in Figma with nothing hand-kept.
89
+ */
90
+ add_filter('acf/load_field/key=field_baseline_badge_icon', static function (array $field): array {
91
+ $field['choices'] = ['' => __('None', 'baseline')];
92
+ foreach (baseline_icons() as $name => $icon) {
93
+ $field['choices'][$name] = (string) ($icon['label'] ?? $name);
94
+ }
95
+ return $field;
96
+ });
@@ -0,0 +1,77 @@
1
+ <?php
2
+ /**
3
+ * Baseline Button for template code (header phone link, templates, other blocks). Emits the SAME markup and classes
4
+ * as core/button (ADR-0018), so one stylesheet serves editors and templates:
5
+ *
6
+ * echo baseline_button(['label' => 'Call us', 'href' => 'tel:+15555555555', 'variant' => 'outline', 'size' => 'sm']);
7
+ * echo baseline_button(['label' => 'Add to cart', 'type' => 'submit', 'disabled' => !$in_stock]);
8
+ *
9
+ * Spec: components/button/spec.md. Icon-only sizes arrive with the icon vocabulary (M5).
10
+ */
11
+
12
+ declare(strict_types=1);
13
+
14
+ /**
15
+ * @param array{
16
+ * label?: string, href?: string, target?: string, type?: string, variant?: string, size?: string,
17
+ * disabled?: bool, id?: string, class?: string, attrs?: array<string, string|bool|null>, children?: string
18
+ * } $args
19
+ */
20
+ function baseline_button(array $args): string
21
+ {
22
+ $label = (string) ($args['label'] ?? 'Button');
23
+ $href = (string) ($args['href'] ?? '');
24
+ $variant = (string) ($args['variant'] ?? 'default');
25
+ $size = (string) ($args['size'] ?? 'md');
26
+ $disabled = (bool) ($args['disabled'] ?? false);
27
+ if (!isset(BASELINE_BUTTON_STYLES[$variant])) {
28
+ $variant = 'default';
29
+ }
30
+ if (!in_array($size, BASELINE_BUTTON_SIZES, true)) {
31
+ $size = 'md';
32
+ }
33
+
34
+ $wrapper = trim('wp-block-button is-style-' . BASELINE_BUTTON_STYLES[$variant] . ' is-size-' . $size . ' ' . (string) ($args['class'] ?? ''));
35
+ $attrs = [
36
+ 'class' => 'wp-block-button__link wp-element-button',
37
+ 'data-variant' => $variant,
38
+ 'data-size' => $size,
39
+ 'id' => $args['id'] ?? null,
40
+ ];
41
+ foreach ((array) ($args['attrs'] ?? []) as $k => $v) {
42
+ $attrs[$k] = $v;
43
+ }
44
+ $inner = isset($args['children']) ? (string) $args['children'] : esc_html($label);
45
+
46
+ if ($href !== '' && !$disabled) {
47
+ $attrs['href'] = $href;
48
+ if (!empty($args['target'])) {
49
+ $attrs['target'] = (string) $args['target'];
50
+ $attrs['rel'] = 'noopener';
51
+ }
52
+ $el = '<a' . baseline_attrs($attrs) . '>' . $inner . '</a>';
53
+ } else {
54
+ $attrs['type'] = (string) ($args['type'] ?? 'button');
55
+ if ($disabled) {
56
+ $attrs['disabled'] = true;
57
+ $attrs['aria-disabled'] = 'true';
58
+ }
59
+ $el = '<button' . baseline_attrs($attrs) . '>' . $inner . '</button>';
60
+ }
61
+ return '<div class="' . esc_attr($wrapper) . '">' . $el . '</div>';
62
+ }
63
+
64
+ /** Escapes and joins an attribute map; true renders a bare attribute, null/false/'' omit it. */
65
+ function baseline_attrs(array $attrs): string
66
+ {
67
+ $out = '';
68
+ foreach ($attrs as $k => $v) {
69
+ if ($v === null || $v === false || $v === '') {
70
+ continue;
71
+ }
72
+ $out .= $v === true
73
+ ? ' ' . esc_attr((string) $k)
74
+ : ' ' . esc_attr((string) $k) . '="' . ($k === 'href' ? esc_url((string) $v) : esc_attr((string) $v)) . '"';
75
+ }
76
+ return $out;
77
+ }
@@ -0,0 +1,98 @@
1
+ <?php
2
+ /**
3
+ * Baseline Dialog for template code and the acf/dialog block (spec: components/dialog/spec.md). Emits the same markup
4
+ * and classes as the React Dialog (registry/src/ui/dialog/dialog.tsx): a native <dialog closedby="any"> opened by a
5
+ * Button carrying command="show-modal" commandfor, so it works with no JavaScript (ladder 1):
6
+ *
7
+ * echo baseline_dialog([
8
+ * 'id' => 'newsletter', 'trigger' => 'Subscribe', 'title' => 'Join the newsletter',
9
+ * 'description' => 'One email a month.', 'body' => $form_html, 'footer' => baseline_dialog_footer('', true),
10
+ * ]);
11
+ *
12
+ * Safari has no `closedby` yet (2026-10), so there an outside click does not close it; Escape and the buttons do.
13
+ * Class strings are static (ADR-0008) and kept identical to React's, so one look serves both.
14
+ */
15
+
16
+ declare(strict_types=1);
17
+
18
+ // The <dialog> (React's contentClasses, minus the full-bleed media rule, which has no WordPress counterpart yet).
19
+ const BASELINE_DIALOG_CONTENT = 'group/dialog-content fixed inset-0 m-auto h-fit max-h-[calc(100%-2rem)] w-full max-w-[calc(100%-2rem)] sm:max-w-(--bl-dialog-max-width) hidden open:grid gap-(--bl-dialog-gap) overflow-y-auto overscroll-contain rounded-(--bl-dialog-radius) border-0 bg-popover p-(--bl-dialog-padding) text-sm text-popover-foreground outline-none ring-(length:--bl-dialog-border-width) ring-(--bl-dialog-border) scale-95 opacity-0 open:scale-100 open:opacity-100 starting:open:scale-95 starting:open:opacity-0 transition-[opacity,scale,display,overlay] transition-discrete duration-100 motion-reduce:transition-none backdrop:bg-(--overlay) supports-backdrop-filter:backdrop:backdrop-blur-xs backdrop:opacity-0 open:backdrop:opacity-100 starting:open:backdrop:opacity-0 backdrop:transition-[opacity,display,overlay] backdrop:transition-discrete backdrop:duration-100 motion-reduce:backdrop:transition-none';
20
+
21
+ // The block editor shows the panel in place (a closed <dialog> would hide the content editors need to reach).
22
+ const BASELINE_DIALOG_PREVIEW = 'relative grid w-full max-w-(--bl-dialog-max-width) gap-(--bl-dialog-gap) rounded-(--bl-dialog-radius) bg-popover p-(--bl-dialog-padding) text-sm text-popover-foreground ring-(length:--bl-dialog-border-width) ring-(--bl-dialog-border)';
23
+
24
+ const BASELINE_DIALOG_HEADER = 'flex flex-col gap-(--bl-dialog-header-gap)';
25
+ const BASELINE_DIALOG_TITLE = 'm-0 font-heading text-(length:--bl-dialog-title-font-size) leading-(--bl-dialog-title-line-height) font-(--bl-dialog-title-font-weight)';
26
+ const BASELINE_DIALOG_DESCRIPTION = 'm-0 text-(length:--bl-dialog-description-font-size) leading-(--bl-dialog-description-line-height) text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground';
27
+ const BASELINE_DIALOG_FOOTER = '-mx-(--bl-dialog-padding) -mb-(--bl-dialog-padding) flex flex-col-reverse gap-(--bl-dialog-footer-gap) sm:flex-row sm:justify-end rounded-b-(--bl-dialog-radius) border-t-(length:--bl-dialog-border-width) border-border bg-(--bl-dialog-footer-background) p-(--bl-dialog-padding)';
28
+ const BASELINE_DIALOG_CLOSE = 'absolute top-(--bl-dialog-close-inset) end-(--bl-dialog-close-inset)';
29
+
30
+ /**
31
+ * The footer: bordered and muted, bleeding to the dialog's edges, stacked below sm. `$close_label` adds an outline
32
+ * button that closes the dialog through <form method="dialog">, which needs no id and no script.
33
+ */
34
+ function baseline_dialog_footer(string $actions, string $close_label = '', string $root_attrs = ''): string
35
+ {
36
+ $close = '';
37
+ if ($close_label !== '') {
38
+ $close = '<form method="dialog" class="contents">'
39
+ . baseline_button(['label' => $close_label, 'variant' => 'outline', 'type' => 'submit'])
40
+ . '</form>';
41
+ }
42
+ $root = $root_attrs !== '' ? $root_attrs : 'class="' . esc_attr(BASELINE_DIALOG_FOOTER) . '"';
43
+ // Close first: it is the Cancel beside the primary action, so the row reads Cancel, Continue (upstream's demo order)
44
+ // and the stacked footer (flex-col-reverse) puts the primary action on top.
45
+ return '<div data-slot="dialog-footer" ' . $root . '>' . $close . $actions . '</div>';
46
+ }
47
+
48
+ /**
49
+ * @param array{
50
+ * id?: string, trigger?: string|false, trigger_variant?: string, class?: string, trigger_size?: string, title?: string,
51
+ * description?: string, body?: string, footer?: string, show_close?: bool, preview?: bool
52
+ * } $args `body` and `footer` are ready markup (InnerBlocks, a form, baseline_dialog_footer()); `preview` renders the
53
+ * panel in place, for the block editor. `trigger` false leaves the trigger out, for a dialog opened another way (Media's
54
+ * play button); `class` adds classes to the <dialog>.
55
+ */
56
+ function baseline_dialog(array $args): string
57
+ {
58
+ $id = sanitize_html_class((string) ($args['id'] ?? '')) ?: wp_unique_id('dialog-');
59
+ $title = (string) ($args['title'] ?? '');
60
+ $desc = (string) ($args['description'] ?? '');
61
+ $preview = !empty($args['preview']);
62
+
63
+ $header = '';
64
+ if ($title !== '' || $desc !== '') {
65
+ $header = '<div data-slot="dialog-header" class="' . BASELINE_DIALOG_HEADER . '">'
66
+ . ($title !== '' ? '<h2 id="' . esc_attr($id . '-title') . '" data-slot="dialog-title" class="' . BASELINE_DIALOG_TITLE . '">' . esc_html($title) . '</h2>' : '')
67
+ . ($desc !== '' ? '<p id="' . esc_attr($id . '-description') . '" data-slot="dialog-description" class="' . BASELINE_DIALOG_DESCRIPTION . '">' . esc_html($desc) . '</p>' : '')
68
+ . '</div>';
69
+ }
70
+
71
+ $close = '';
72
+ if ($args['show_close'] ?? true) {
73
+ $close = baseline_button([
74
+ 'variant' => 'ghost',
75
+ 'size' => 'sm', // icon-only: core/button's square at the sm size (src/core-button.css)
76
+ 'class' => 'is-icon-only has-icon ' . BASELINE_DIALOG_CLOSE,
77
+ 'children' => baseline_icon('close') . '<span class="sr-only">' . esc_html__('Close', 'baseline') . '</span>',
78
+ 'attrs' => ['command' => 'close', 'commandfor' => $id, 'data-slot' => 'dialog-close'],
79
+ ]);
80
+ }
81
+
82
+ $inner = $header . (string) ($args['body'] ?? '') . (string) ($args['footer'] ?? '') . $close;
83
+
84
+ $trigger = ($args['trigger'] ?? null) === false ? '' : baseline_button([
85
+ 'label' => (string) ($args['trigger'] ?? __('Open', 'baseline')),
86
+ 'variant' => (string) ($args['trigger_variant'] ?? 'outline'),
87
+ 'size' => (string) ($args['trigger_size'] ?? 'md'),
88
+ 'attrs' => ['command' => 'show-modal', 'commandfor' => $id, 'data-slot' => 'dialog-trigger'],
89
+ ]);
90
+
91
+ if ($preview) {
92
+ return $trigger . '<div data-slot="dialog-content" class="' . BASELINE_DIALOG_PREVIEW . '">' . $inner . '</div>';
93
+ }
94
+ $labelled = $title !== '' ? ' aria-labelledby="' . esc_attr($id . '-title') . '"' : '';
95
+ $described = $desc !== '' ? ' aria-describedby="' . esc_attr($id . '-description') . '"' : '';
96
+ return $trigger . '<dialog id="' . esc_attr($id) . '" data-slot="dialog-content" closedby="any"' . $labelled . $described
97
+ . ' class="' . esc_attr(trim(BASELINE_DIALOG_CONTENT . ' ' . (string) ($args['class'] ?? ''))) . '">' . $inner . '</dialog>';
98
+ }
@@ -0,0 +1,111 @@
1
+ <?php
2
+ /**
3
+ * Baseline Item for template code and the acf/item block (spec: components/item/spec.md). Emits the same markup and
4
+ * classes as the React Item (registry/src/ui/item/item.tsx):
5
+ *
6
+ * echo baseline_item(['title' => 'Jordan Diaz', 'description' => 'jordan@example.com', 'image' => $url, 'size' => 'sm']);
7
+ * echo baseline_item(['title' => 'Docs', 'description' => 'Read the guide', 'href' => '/docs', 'variant' => 'outline']);
8
+ *
9
+ * A link item is one <a> (keeps the link role, no listitem role) and renders no actions: nothing interactive may sit
10
+ * inside a link. Class strings are static maps (ADR-0008): Tailwind scans this file, so every class appears literally.
11
+ */
12
+
13
+ declare(strict_types=1);
14
+
15
+ const BASELINE_ITEM_ROOT = 'group/item flex w-full flex-wrap items-center rounded-(--bl-item-radius) border-(length:--bl-item-border-width) text-(length:--bl-item-title-font-size) leading-(--bl-item-title-line-height) transition-colors duration-100 outline-none focus-visible:border-ring focus-visible:ring-(length:--bl-control-ring-width) focus-visible:ring-ring [a]:transition-colors [a]:hover:bg-muted';
16
+
17
+ const BASELINE_ITEM_VARIANTS = [
18
+ 'default' => 'border-transparent',
19
+ 'outline' => 'border-border',
20
+ 'muted' => 'border-transparent bg-(--bl-item-muted-background)',
21
+ ];
22
+
23
+ const BASELINE_ITEM_SIZES = [
24
+ 'md' => 'gap-(--bl-item-md-gap) px-(--bl-item-md-padding-x) py-(--bl-item-md-padding-y)',
25
+ 'sm' => 'gap-(--bl-item-sm-gap) px-(--bl-item-sm-padding-x) py-(--bl-item-sm-padding-y)',
26
+ 'xs' => 'gap-(--bl-item-xs-gap) px-(--bl-item-xs-padding-x) py-(--bl-item-xs-padding-y)',
27
+ ];
28
+
29
+ const BASELINE_ITEM_MEDIA = 'flex shrink-0 items-center justify-center gap-(--bl-item-actions-gap) group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start [&_svg]:pointer-events-none';
30
+ const BASELINE_ITEM_MEDIA_ICON = '[&_svg]:size-(--bl-item-media-icon-size)';
31
+ const BASELINE_ITEM_MEDIA_IMAGE = 'size-(--bl-item-media-md-size) overflow-hidden rounded-(--bl-item-media-radius) group-data-[size=sm]/item:size-(--bl-item-media-sm-size) group-data-[size=xs]/item:size-(--bl-item-media-xs-size) [&_img]:size-full [&_img]:object-cover [&_img]:m-0 [&_img]:rounded-none';
32
+
33
+ const BASELINE_ITEM_CONTENT = 'flex flex-1 flex-col gap-(--bl-item-md-content-gap) group-data-[size=sm]/item:gap-(--bl-item-sm-content-gap) group-data-[size=xs]/item:gap-(--bl-item-xs-content-gap)';
34
+ const BASELINE_ITEM_TITLE = 'line-clamp-1 flex w-fit items-center gap-(--bl-item-actions-gap) underline-offset-4 text-(length:--bl-item-title-font-size) leading-(--bl-item-title-line-height) font-(--bl-item-title-font-weight)';
35
+ const BASELINE_ITEM_DESCRIPTION = 'm-0 line-clamp-2 text-start font-normal text-muted-foreground text-(length:--bl-item-description-md-font-size) leading-(--bl-item-description-md-line-height) group-data-[size=sm]/item:text-(length:--bl-item-description-sm-font-size) group-data-[size=sm]/item:leading-(--bl-item-description-sm-line-height) group-data-[size=xs]/item:text-(length:--bl-item-description-xs-font-size) group-data-[size=xs]/item:leading-(--bl-item-description-xs-line-height) [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary';
36
+ const BASELINE_ITEM_ACTIONS = 'flex items-center gap-(--bl-item-actions-gap)';
37
+
38
+ /** The group: role=list, its gap following the items' size (src/item.css carries it through ACF's wrappers). */
39
+ const BASELINE_ITEM_GROUP = 'group/item-group not-typeset flex w-full flex-col gap-(--bl-item-group-md-gap) has-data-[size=sm]:gap-(--bl-item-group-sm-gap) has-data-[size=xs]:gap-(--bl-item-group-xs-gap)';
40
+
41
+ /**
42
+ * @param array{
43
+ * title?: string, description?: string, variant?: string, size?: string, icon?: string, image?: string,
44
+ * image_alt?: string, href?: string, actions?: string, class?: string, root_attrs?: string
45
+ * } $args `description` may hold inline HTML (links); `actions` is ready markup (core/buttons InnerBlocks in the block);
46
+ * `root_attrs` replaces the root's class attribute (the block passes get_block_wrapper_attributes()).
47
+ */
48
+ function baseline_item(array $args): string
49
+ {
50
+ $size = baseline_item_size((string) ($args['size'] ?? 'md'));
51
+ $href = (string) ($args['href'] ?? '');
52
+
53
+ $media = '';
54
+ if (!empty($args['image'])) {
55
+ $media = '<div data-slot="item-media" data-variant="image" class="' . BASELINE_ITEM_MEDIA . ' ' . BASELINE_ITEM_MEDIA_IMAGE . '">'
56
+ . '<img src="' . esc_url((string) $args['image']) . '" alt="' . esc_attr((string) ($args['image_alt'] ?? '')) . '" loading="lazy" decoding="async"></div>';
57
+ } elseif (!empty($args['icon'])) {
58
+ $media = '<div data-slot="item-media" data-variant="icon" class="' . BASELINE_ITEM_MEDIA . ' ' . BASELINE_ITEM_MEDIA_ICON . '">'
59
+ . baseline_icon((string) $args['icon'], 'shrink-0') . '</div>';
60
+ }
61
+
62
+ $content = '<div data-slot="item-content" class="' . BASELINE_ITEM_CONTENT . '">';
63
+ if (!empty($args['title'])) {
64
+ $content .= '<div data-slot="item-title" class="' . BASELINE_ITEM_TITLE . '">' . esc_html((string) $args['title']) . '</div>';
65
+ }
66
+ if (!empty($args['description'])) {
67
+ // a link item may not contain links: a nested <a> makes the browser split the row
68
+ $allowed = ['strong' => [], 'em' => [], 'br' => []];
69
+ if ($href === '') {
70
+ $allowed['a'] = ['href' => true, 'target' => true, 'rel' => true];
71
+ }
72
+ $content .= '<p data-slot="item-description" class="' . BASELINE_ITEM_DESCRIPTION . '">' . wp_kses((string) $args['description'], $allowed) . '</p>';
73
+ }
74
+ $content .= '</div>';
75
+
76
+ // nothing interactive inside a link item
77
+ $actions = ($href === '' && !empty($args['actions']))
78
+ ? '<div data-slot="item-actions" class="' . BASELINE_ITEM_ACTIONS . '">' . $args['actions'] . '</div>'
79
+ : '';
80
+
81
+ $root = isset($args['root_attrs'])
82
+ ? (string) $args['root_attrs']
83
+ : 'class="' . esc_attr(baseline_item_classes((string) ($args['variant'] ?? 'default'), $size, (string) ($args['class'] ?? ''))) . '"';
84
+ $inner = $media . $content . $actions;
85
+ return $href !== ''
86
+ ? '<a href="' . esc_url($href) . '" data-slot="item" data-size="' . $size . '" ' . $root . '>' . $inner . '</a>'
87
+ : '<div role="listitem" data-slot="item" data-size="' . $size . '" ' . $root . '>' . $inner . '</div>';
88
+ }
89
+
90
+ /** A size from the three, md otherwise. */
91
+ function baseline_item_size(string $size): string
92
+ {
93
+ return isset(BASELINE_ITEM_SIZES[$size]) ? $size : 'md';
94
+ }
95
+
96
+ /** The item root's classes (shared by baseline_item() and the acf/item block's wrapper attributes). */
97
+ function baseline_item_classes(string $variant, string $size, string $extra = ''): string
98
+ {
99
+ $variant = isset(BASELINE_ITEM_VARIANTS[$variant]) ? $variant : 'default';
100
+ // not-typeset: an item in post content must not take typeset's paragraph and link rules (ADR-0028)
101
+ return trim(BASELINE_ITEM_ROOT . ' not-typeset ' . BASELINE_ITEM_VARIANTS[$variant] . ' ' . BASELINE_ITEM_SIZES[baseline_item_size($size)] . ' ' . $extra);
102
+ }
103
+
104
+ /** The acf/item block's Icon select lists the active icon set's vocabulary, as acf/badge's does. */
105
+ add_filter('acf/load_field/key=field_baseline_item_icon', static function (array $field): array {
106
+ $field['choices'] = ['' => __('None', 'baseline')];
107
+ foreach (baseline_icons() as $name => $icon) {
108
+ $field['choices'][$name] = (string) ($icon['label'] ?? $name);
109
+ }
110
+ return $field;
111
+ });
@@ -0,0 +1,125 @@
1
+ <?php
2
+ /**
3
+ * Baseline Popover for template code (spec: components/popover/spec.md). Emits the same markup and classes as the React
4
+ * Popover (registry/src/ui/popover/popover.tsx): a <div popover="auto"> toggled by a Button carrying
5
+ * command="toggle-popover" commandfor, placed by CSS anchor positioning, so it works with no JavaScript (ladder 1):
6
+ *
7
+ * echo baseline_popover([
8
+ * 'id' => 'pricing-seats', 'trigger' => 'What counts as a seat?', 'trigger_variant' => 'link',
9
+ * 'title' => 'Seats', 'description' => 'Everyone who signs in during the month.', 'align' => 'start',
10
+ * ]);
11
+ *
12
+ * A helper only, no editor block (user, 2026-10-05): popovers on marketing sites belong in templates and patterns, such
13
+ * as a pricing table's explainers. Class strings are static (ADR-0008) and kept identical to React's.
14
+ */
15
+
16
+ declare(strict_types=1);
17
+
18
+ const BASELINE_POPOVER_CONTENT = 'group/popover-content inset-auto m-0 flex not-open:hidden w-(--bl-popover-width) max-w-[calc(100vw-1rem)] flex-col gap-(--bl-popover-gap) overflow-visible rounded-(--bl-popover-radius) border-0 bg-popover p-(--bl-popover-padding) text-sm text-popover-foreground shadow-md outline-none ring-(length:--bl-popover-border-width) ring-(--bl-popover-border) scale-95 opacity-0 open:translate-0 open:scale-100 open:opacity-100 starting:open:scale-95 starting:open:opacity-0 transition-[opacity,scale,translate,display,overlay] transition-discrete duration-100 motion-reduce:transition-none';
19
+
20
+ // React's contentVariants side classes: the transform origin and the slide in from the trigger's side.
21
+ const BASELINE_POPOVER_SIDE = [
22
+ 'bottom' => 'origin-top -translate-y-2 starting:open:-translate-y-2',
23
+ 'top' => 'origin-bottom translate-y-2 starting:open:translate-y-2',
24
+ 'right' => 'origin-left -translate-x-2 starting:open:-translate-x-2',
25
+ 'left' => 'origin-right translate-x-2 starting:open:translate-x-2',
26
+ 'inline-end' => 'origin-left -translate-x-2 starting:open:-translate-x-2 rtl:origin-right rtl:translate-x-2 rtl:starting:open:translate-x-2',
27
+ 'inline-start' => 'origin-right translate-x-2 starting:open:translate-x-2 rtl:origin-left rtl:-translate-x-2 rtl:starting:open:-translate-x-2',
28
+ ];
29
+
30
+ // position-area per side and alignment, the margin facing the trigger, the flip, the edge alignOffset pushes from
31
+ const BASELINE_POPOVER_AREA = [
32
+ 'bottom' => ['start' => 'block-end span-inline-end', 'center' => 'block-end', 'end' => 'block-end span-inline-start'],
33
+ 'top' => ['start' => 'block-start span-inline-end', 'center' => 'block-start', 'end' => 'block-start span-inline-start'],
34
+ 'inline-end' => ['start' => 'inline-end span-block-end', 'center' => 'inline-end', 'end' => 'inline-end span-block-start'],
35
+ 'inline-start' => ['start' => 'inline-start span-block-end', 'center' => 'inline-start', 'end' => 'inline-start span-block-start'],
36
+ 'right' => ['start' => 'right span-bottom', 'center' => 'right', 'end' => 'right span-top'],
37
+ 'left' => ['start' => 'left span-bottom', 'center' => 'left', 'end' => 'left span-top'],
38
+ ];
39
+ const BASELINE_POPOVER_SIDE_MARGIN = [
40
+ 'bottom' => 'margin-block-start', 'top' => 'margin-block-end', 'inline-end' => 'margin-inline-start',
41
+ 'inline-start' => 'margin-inline-end', 'right' => 'margin-left', 'left' => 'margin-right',
42
+ ];
43
+ const BASELINE_POPOVER_ALIGN_MARGIN = [
44
+ 'bottom' => ['margin-inline-start', 'margin-inline-end'], 'top' => ['margin-inline-start', 'margin-inline-end'],
45
+ 'inline-end' => ['margin-block-start', 'margin-block-end'], 'inline-start' => ['margin-block-start', 'margin-block-end'],
46
+ 'right' => ['margin-top', 'margin-bottom'], 'left' => ['margin-top', 'margin-bottom'],
47
+ ];
48
+
49
+ const BASELINE_POPOVER_HEADER = 'flex flex-col gap-(--bl-popover-header-gap) text-sm';
50
+ const BASELINE_POPOVER_TITLE = 'm-0 text-(length:--bl-popover-title-font-size) leading-(--bl-popover-title-line-height) font-(--bl-popover-title-font-weight)';
51
+ const BASELINE_POPOVER_DESCRIPTION = 'm-0 text-(length:--bl-popover-description-font-size) leading-(--bl-popover-description-line-height) text-muted-foreground';
52
+
53
+ /** An id as a dashed ident for anchor-name / position-anchor (React's anchorName()). */
54
+ function baseline_popover_anchor(string $id): string
55
+ {
56
+ return '--' . preg_replace('/[^\w-]/', '_', $id);
57
+ }
58
+
59
+ /**
60
+ * @param array{
61
+ * id?: string, trigger?: string|false, trigger_variant?: string, trigger_size?: string, title?: string,
62
+ * description?: string, body?: string, side?: string, align?: string, side_offset?: int, align_offset?: int,
63
+ * label?: string, class?: string
64
+ * } $args `body` is ready markup. `trigger` false leaves the trigger out: then give your own trigger
65
+ * baseline_popover_trigger_attrs($id). Without a title, pass `label` for the panel's accessible name.
66
+ */
67
+ function baseline_popover(array $args): string
68
+ {
69
+ $id = sanitize_html_class((string) ($args['id'] ?? '')) ?: wp_unique_id('popover-');
70
+ $side = array_key_exists((string) ($args['side'] ?? ''), BASELINE_POPOVER_AREA) ? (string) $args['side'] : 'bottom';
71
+ $align = in_array($args['align'] ?? '', ['start', 'center', 'end'], true) ? (string) $args['align'] : 'center';
72
+ $title = (string) ($args['title'] ?? '');
73
+ $desc = (string) ($args['description'] ?? '');
74
+ $offset = (int) ($args['side_offset'] ?? 4);
75
+ $along = (int) ($args['align_offset'] ?? 0);
76
+
77
+ $header = '';
78
+ if ($title !== '' || $desc !== '') {
79
+ $header = '<div data-slot="popover-header" class="' . BASELINE_POPOVER_HEADER . '">'
80
+ . ($title !== '' ? '<h2 id="' . esc_attr($id . '-title') . '" data-slot="popover-title" class="' . BASELINE_POPOVER_TITLE . '">' . esc_html($title) . '</h2>' : '')
81
+ . ($desc !== '' ? '<p id="' . esc_attr($id . '-description') . '" data-slot="popover-description" class="' . BASELINE_POPOVER_DESCRIPTION . '">' . esc_html($desc) . '</p>' : '')
82
+ . '</div>';
83
+ }
84
+
85
+ $style = 'position-anchor:' . baseline_popover_anchor($id) . ';position-area:' . BASELINE_POPOVER_AREA[$side][$align]
86
+ . ';position-try-fallbacks:' . (in_array($side, ['top', 'bottom'], true) ? 'flip-block' : 'flip-inline')
87
+ . ';' . BASELINE_POPOVER_SIDE_MARGIN[$side] . ':' . $offset . 'px';
88
+ if ($align !== 'center' && $along !== 0) {
89
+ $style .= ';' . BASELINE_POPOVER_ALIGN_MARGIN[$side][$align === 'start' ? 0 : 1] . ':' . $along . 'px';
90
+ }
91
+
92
+ $name = $title !== ''
93
+ ? ' aria-labelledby="' . esc_attr($id . '-title') . '"'
94
+ : (isset($args['label']) ? ' aria-label="' . esc_attr((string) $args['label']) . '"' : '');
95
+ $described = $desc !== '' ? ' aria-describedby="' . esc_attr($id . '-description') . '"' : '';
96
+
97
+ $trigger = ($args['trigger'] ?? null) === false ? '' : baseline_button([
98
+ 'label' => (string) ($args['trigger'] ?? __('Open', 'baseline')),
99
+ 'variant' => (string) ($args['trigger_variant'] ?? 'outline'),
100
+ 'size' => (string) ($args['trigger_size'] ?? 'md'),
101
+ 'attrs' => baseline_popover_trigger_attrs($id),
102
+ ]);
103
+
104
+ return $trigger . '<div id="' . esc_attr($id) . '" popover="auto" role="dialog" data-slot="popover-content"'
105
+ . ' data-side="' . esc_attr($side) . '" data-align="' . esc_attr($align) . '"' . $name . $described
106
+ // not-typeset: in post content typeset's heading and paragraph rules would restyle the title and description (ADR-0028)
107
+ . ' class="' . esc_attr(trim(BASELINE_POPOVER_CONTENT . ' not-typeset ' . BASELINE_POPOVER_SIDE[$side] . ' ' . (string) ($args['class'] ?? ''))) . '"'
108
+ . ' style="' . esc_attr($style) . '">' . $header . (string) ($args['body'] ?? '') . '</div>';
109
+ }
110
+
111
+ /**
112
+ * The attributes that make any button the popover's trigger and anchor: for a trigger you render yourself.
113
+ *
114
+ * @return array<string, string>
115
+ */
116
+ function baseline_popover_trigger_attrs(string $id): array
117
+ {
118
+ return [
119
+ 'type' => 'button',
120
+ 'command' => 'toggle-popover',
121
+ 'commandfor' => $id,
122
+ 'style' => 'anchor-name:' . baseline_popover_anchor($id),
123
+ 'data-slot' => 'popover-trigger',
124
+ ];
125
+ }