@riverbankcms/sdk 0.108.0 → 0.111.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 (278) hide show
  1. package/README.md +21 -1
  2. package/dist/{PreviewEditorSidebar-BBT-kZAM.mjs → PreviewEditorSidebar-CTR6LUhN.mjs} +181 -135
  3. package/dist/{PreviewEditorUI-D69xNKT2.mjs → PreviewEditorUI-DZg15Zip.mjs} +3 -4
  4. package/dist/{PreviewQueryProvider-RRu7wyQ5.mjs → PreviewQueryProvider-kkmjklLG.mjs} +1 -1
  5. package/dist/{SdkPreviewModeRuntime-CuDjXH6o.mjs → SdkPreviewModeRuntime-DeOTAFvR.mjs} +436 -367
  6. package/dist/{SiteChromeCustomizeContext-BQUY2dEk.mjs → SiteChromeCustomizeContext-DOSDLCiJ.mjs} +3442 -3029
  7. package/dist/_dts/ai/src/contracts/proposals.d.ts +12633 -10490
  8. package/dist/_dts/api/src/bookingAdjustments.d.ts +5 -0
  9. package/dist/_dts/api/src/bookingOperations.d.ts +4 -0
  10. package/dist/_dts/api/src/bookingRecords.d.ts +2 -17
  11. package/dist/_dts/api/src/bookingRefundOutcomes.d.ts +6 -6
  12. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +5 -5
  13. package/dist/_dts/api/src/common/envelope.d.ts +7 -0
  14. package/dist/_dts/api/src/contentRuntime.d.ts +4 -1
  15. package/dist/_dts/api/src/courses.d.ts +31 -15
  16. package/dist/_dts/api/src/customerMembershipOutcomes.d.ts +5 -5
  17. package/dist/_dts/api/src/endpoints.d.ts +49 -4
  18. package/dist/_dts/api/src/index.d.ts +3 -3
  19. package/dist/_dts/api/src/participantMessaging.d.ts +18 -12
  20. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +1 -0
  21. package/dist/_dts/api/src/sdkContracts.d.ts +259 -1
  22. package/dist/_dts/api/src/siteInfrastructure.d.ts +13 -0
  23. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +6 -6
  24. package/dist/_dts/api/src/siteOperations.d.ts +11 -19
  25. package/dist/_dts/api/src/sitePlatformEndpoints.d.ts +29 -1
  26. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +37 -31
  27. package/dist/_dts/api/src/webhooks.d.ts +98 -1
  28. package/dist/_dts/billing/src/site-arrangements.d.ts +3 -0
  29. package/dist/_dts/block-form/src/widgets/BackgroundGradientWidget/BackgroundGradientField.d.ts +9 -0
  30. package/dist/_dts/block-form/src/widgets/BackgroundGradientWidget/BackgroundGradientWidget.d.ts +3 -4
  31. package/dist/_dts/blocks/src/client/course-registration.d.ts +4 -1
  32. package/dist/_dts/blocks/src/client.d.ts +4 -1
  33. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +8 -8
  34. package/dist/_dts/blocks/src/index.d.ts +4 -2
  35. package/dist/_dts/blocks/src/system/blocks/audio-player.d.ts +3 -0
  36. package/dist/_dts/blocks/src/system/blocks/body-text.d.ts +3 -0
  37. package/dist/_dts/blocks/src/system/blocks/contact-newsletter.d.ts +3 -0
  38. package/dist/_dts/blocks/src/system/blocks/course-registration.d.ts +3 -23
  39. package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +2 -1
  40. package/dist/_dts/blocks/src/system/blocks/cta-full.d.ts +5 -4
  41. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +3 -23
  42. package/dist/_dts/blocks/src/system/blocks/events/event-listing.d.ts +2 -1
  43. package/dist/_dts/blocks/src/system/blocks/events/event-spotlight.d.ts +2 -1
  44. package/dist/_dts/blocks/src/system/blocks/events/recurring-schedule.d.ts +3 -2
  45. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +2 -1
  46. package/dist/_dts/blocks/src/system/blocks/file-download.d.ts +5 -1
  47. package/dist/_dts/blocks/src/system/blocks/form.d.ts +3 -0
  48. package/dist/_dts/blocks/src/system/blocks/image-gallery.d.ts +3 -0
  49. package/dist/_dts/blocks/src/system/blocks/media-text.d.ts +3 -0
  50. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +5 -1
  51. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +2 -1
  52. package/dist/_dts/blocks/src/system/blocks/single-button.d.ts +2 -1
  53. package/dist/_dts/blocks/src/system/blocks/site-header.d.ts +3 -0
  54. package/dist/_dts/blocks/src/system/blocks/team-members.d.ts +3 -0
  55. package/dist/_dts/blocks/src/system/blocks/testimonials.d.ts +3 -0
  56. package/dist/_dts/blocks/src/system/blocks/video-grid.d.ts +3 -0
  57. package/dist/_dts/blocks/src/system/constants/background.d.ts +1 -1
  58. package/dist/_dts/blocks/src/system/constants/buttonRoles.d.ts +35 -0
  59. package/dist/_dts/blocks/src/system/customize/backgrounds.d.ts +16 -6
  60. package/dist/_dts/blocks/src/system/defineBlock.d.ts +9 -1
  61. package/dist/_dts/blocks/src/system/fields/button.d.ts +10 -21
  62. package/dist/_dts/blocks/src/system/fields/ctas.d.ts +10 -1
  63. package/dist/_dts/blocks/src/system/fragments/library/heroCtaRow.d.ts +9 -5
  64. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +31 -0
  65. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +24 -24
  66. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +12 -12
  67. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessWholeSeriesRegistrationFlow.d.ts +29 -0
  68. package/dist/_dts/blocks/src/system/runtime/nodes/buttonAffordance.d.ts +1 -1
  69. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/ErrorStep.d.ts +2 -1
  70. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/PaymentFailedStep.d.ts +2 -1
  71. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/VerifyingTimeoutStep.d.ts +2 -1
  72. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/types.d.ts +21 -0
  73. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.d.ts +4 -4
  74. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/whole-series-registration.headless.contract.d.ts +326 -0
  75. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/whole-series-registration.headless.planning.d.ts +27 -0
  76. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.interactive.d.ts +5 -4
  77. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +3 -2
  78. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +2 -1
  79. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +5 -4
  80. package/dist/_dts/blocks/src/system/runtime/nodes/file-download.d.ts +2 -3
  81. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +2 -1
  82. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +7 -4
  83. package/dist/_dts/blocks/src/system/runtime/nodes/shop.interactive.d.ts +7 -6
  84. package/dist/_dts/blocks/src/system/runtime/nodes/shop.types.d.ts +2 -1
  85. package/dist/_dts/blocks/src/system/runtime/shared/types.d.ts +2 -1
  86. package/dist/_dts/content-editor/src/FooterComposerPanel.d.ts +4 -2
  87. package/dist/_dts/content-editor/src/index.d.ts +12 -12
  88. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +17 -2
  89. package/dist/_dts/content-model/src/content-types/entryValidation.d.ts +31 -0
  90. package/dist/_dts/content-model/src/content-types/scaffold.d.ts +58 -0
  91. package/dist/_dts/content-model/src/content-types/sentinels.d.ts +36 -0
  92. package/dist/_dts/content-model/src/index.d.ts +3 -0
  93. package/dist/_dts/core/src/booking-date-time.d.ts +8 -0
  94. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +3278 -3196
  95. package/dist/_dts/editor-blocks/src/widgets/button/context.d.ts +3 -2
  96. package/dist/_dts/media-core/src/fileMimeDetection.d.ts +16 -0
  97. package/dist/_dts/media-core/src/fileStorage.d.ts +8 -0
  98. package/dist/_dts/media-core/src/storagePathDomain.d.ts +2 -0
  99. package/dist/_dts/media-core/src/uploadVerificationContract.d.ts +3 -0
  100. package/dist/_dts/preview-next/src/client/blocks/BlockToolbar.d.ts +2 -0
  101. package/dist/_dts/preview-next/src/client/index.d.ts +3 -2
  102. package/dist/_dts/preview-next/src/client/preview/ButtonStylePicker.d.ts +16 -0
  103. package/dist/_dts/preview-next/src/client/preview/PageBlockEditorPanel.d.ts +2 -3
  104. package/dist/_dts/preview-next/src/client/preview/PreviewDesignOpenRequestContext.d.ts +7 -0
  105. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +5 -11
  106. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +5 -6
  107. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +6 -7
  108. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +7 -9
  109. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.d.ts +4 -11
  110. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +8 -7
  111. package/dist/_dts/preview-next/src/client/preview/sidebarTabPreference.d.ts +0 -8
  112. package/dist/_dts/preview-next/src/client/preview/siteChromeLookRows.d.ts +1 -11
  113. package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlHistoryState.d.ts +1 -5
  114. package/dist/_dts/preview-next/src/client/preview/siteChromeSavePlan.d.ts +2 -3
  115. package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +3 -4
  116. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorApplyPayload.d.ts +1 -1
  117. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorSnapshot.d.ts +3 -5
  118. package/dist/_dts/sdk/src/bookings/index.d.ts +5 -4
  119. package/dist/_dts/sdk/src/bookings/types.d.ts +3 -3
  120. package/dist/_dts/sdk/src/cli/commands/audit.d.ts +1 -1
  121. package/dist/_dts/sdk/src/cli/commands/compare.d.ts +1 -1
  122. package/dist/_dts/sdk/src/cli/commands/deploy.d.ts +1 -1
  123. package/dist/_dts/sdk/src/cli/commands/drafts.d.ts +18 -0
  124. package/dist/_dts/sdk/src/cli/commands/entry.d.ts +15 -0
  125. package/dist/_dts/sdk/src/cli/commands/init-docs.d.ts +2 -2
  126. package/dist/_dts/sdk/src/cli/commands/publish-all.d.ts +1 -1
  127. package/dist/_dts/sdk/src/cli/commands/pull.d.ts +1 -0
  128. package/dist/_dts/sdk/src/cli/commands/push/execute/diff.d.ts +1 -1
  129. package/dist/_dts/sdk/src/cli/commands/push/options.d.ts +3 -0
  130. package/dist/_dts/sdk/src/cli/commands/push-execute.d.ts +12 -1
  131. package/dist/_dts/sdk/src/cli/commands/setup.d.ts +1 -0
  132. package/dist/_dts/sdk/src/cli/commands/style.d.ts +3 -2
  133. package/dist/_dts/sdk/src/cli/commands/verify.d.ts +1 -0
  134. package/dist/_dts/sdk/src/cli/helpers.d.ts +22 -1
  135. package/dist/_dts/sdk/src/cli/index.d.ts +4 -0
  136. package/dist/_dts/sdk/src/cli/output.d.ts +88 -0
  137. package/dist/_dts/sdk/src/cli/program.d.ts +29 -0
  138. package/dist/_dts/sdk/src/cli/push-config.d.ts +1 -1
  139. package/dist/_dts/sdk/src/client/management/catalog.d.ts +10 -0
  140. package/dist/_dts/sdk/src/client/management/http.d.ts +7 -1
  141. package/dist/_dts/sdk/src/client/management/index.d.ts +1 -1
  142. package/dist/_dts/sdk/src/client/management/types.d.ts +45 -20
  143. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +12 -15
  144. package/dist/_dts/sdk/src/date-time/index.d.ts +68 -0
  145. package/dist/_dts/sdk/src/public-api/contracts.d.ts +3 -1
  146. package/dist/_dts/sdk/src/version.d.ts +1 -1
  147. package/dist/_dts/sdk/src/webhooks/index.d.ts +1 -1
  148. package/dist/_dts/sdk/src/webhooks/verify.d.ts +3 -3
  149. package/dist/_dts/site-commands/src/commands.d.ts +1010 -817
  150. package/dist/_dts/theme-core/src/accordions/types.d.ts +1 -1
  151. package/dist/_dts/theme-core/src/buttons/core.d.ts +15 -46
  152. package/dist/_dts/theme-core/src/buttons/effectClassification.d.ts +147 -0
  153. package/dist/_dts/theme-core/src/buttons/effects/types.d.ts +2 -3
  154. package/dist/_dts/theme-core/src/buttons/generateDefaultButtonSystem.d.ts +1 -1
  155. package/dist/_dts/theme-core/src/buttons/index.d.ts +2 -1
  156. package/dist/_dts/theme-core/src/buttons/presets.d.ts +4 -25
  157. package/dist/_dts/theme-core/src/buttons/resolveButtonColourStates.d.ts +100 -0
  158. package/dist/_dts/theme-core/src/buttons/resolvedButtonCss.d.ts +16 -0
  159. package/dist/_dts/theme-core/src/buttons/styles/domain.d.ts +80 -0
  160. package/dist/_dts/theme-core/src/buttons/styles/index.d.ts +3 -0
  161. package/dist/_dts/theme-core/src/buttons/styles/recipes/defineStaticButtonStyleRecipe.d.ts +49 -0
  162. package/dist/_dts/theme-core/src/buttons/styles/recipes/quietArrow.d.ts +67 -0
  163. package/dist/_dts/theme-core/src/buttons/styles/recipes/staticRecipes.d.ts +649 -0
  164. package/dist/_dts/theme-core/src/buttons/styles/registry.d.ts +753 -0
  165. package/dist/_dts/theme-core/src/buttons/styles/selection.d.ts +69 -0
  166. package/dist/_dts/theme-core/src/buttons/types.d.ts +101 -83
  167. package/dist/_dts/theme-core/src/cards/types.d.ts +16 -16
  168. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  169. package/dist/_dts/theme-core/src/gradients/presets.d.ts +200 -8
  170. package/dist/_dts/theme-core/src/gradients/utils.d.ts +6 -2
  171. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +87 -126
  172. package/dist/_dts/theme-core/src/mock-themes/modern-minimal.d.ts +1 -1
  173. package/dist/_dts/theme-core/src/navigation/types.d.ts +2 -2
  174. package/dist/_dts/theme-core/src/palette/curated/index.d.ts +2 -2
  175. package/dist/_dts/theme-core/src/palette/curated/types.d.ts +5 -8
  176. package/dist/_dts/theme-core/src/palette/index.d.ts +0 -1
  177. package/dist/_dts/theme-core/src/schema.d.ts +112 -138
  178. package/dist/_dts/theme-core/src/site-styles/backgroundAppearance.d.ts +2 -2
  179. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +26 -24
  180. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +10 -10
  181. package/dist/_dts/theme-core/src/site-styles/footerLooks.d.ts +19 -153
  182. package/dist/_dts/theme-core/src/site-styles/headerCtaVariants.d.ts +3 -1
  183. package/dist/_dts/theme-core/src/site-styles/pageDesignEditorModel.d.ts +3 -2
  184. package/dist/_dts/theme-core/src/site-styles/pageDesignIntent.d.ts +13 -6
  185. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +8 -9
  186. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +33 -12
  187. package/dist/_dts/theme-core/src/site-styles/styleTags.d.ts +2 -2
  188. package/dist/_dts/ui/src/palette/hex.d.ts +3 -3
  189. package/dist/cli/index.mjs +68396 -67339
  190. package/dist/cli/init-docs/content/cli-reference.md +50 -7
  191. package/dist/cli/init-docs/content/content-management.md +7 -4
  192. package/dist/cli/init-docs/content/workflow-isr-revalidation.md +1 -1
  193. package/dist/cli/init-docs/content/workflow-publish.md +5 -1
  194. package/dist/client/{DiscountCodeDisclosure-D6TOf6Hi.mjs → DiscountCodeDisclosure-C4xvTBux.mjs} +1 -1
  195. package/dist/client/{EventCombined.client-Dao3zxRk.mjs → EventCombined.client-Cr7G131j.mjs} +2 -3
  196. package/dist/client/{EventListing.client-B2NNt4y1.mjs → EventListing.client-CAjbseNy.mjs} +2 -2
  197. package/dist/client/{LeafletStaticMap-BhwFo16w.mjs → LeafletStaticMap-BMlWfwz3.mjs} +1 -1
  198. package/dist/client/{MagicLinkForm-BWnB7cMR.mjs → MagicLinkForm-ChdFz96y.mjs} +1 -2
  199. package/dist/client/{StepIndicator-TzRiQ0BY.mjs → StepIndicator-7D3GaBeM.mjs} +2 -2
  200. package/dist/client/{accordion-BPy-AJ4_.mjs → accordion-D8JTs2Si.mjs} +1 -1
  201. package/dist/client/{bookingForm-BL4PGZds.mjs → bookingForm-H3DCRBHs.mjs} +6 -7
  202. package/dist/client/bookings.mjs +4649 -2767
  203. package/dist/client/{carousel-C2b7Cn9-.mjs → carousel-DMr_QWlz.mjs} +1 -1
  204. package/dist/client/{cart-BQcbXIVD.mjs → cart-DWMbfBdR.mjs} +3 -3
  205. package/dist/client/{checkout-DEmpGRJu.mjs → checkout-zmfdkXLx.mjs} +3 -3
  206. package/dist/client/client.mjs +3195 -2488
  207. package/dist/client/{colorStyles-jZS6KfkP.mjs → colorStyles-gcTh5yZT.mjs} +2 -41
  208. package/dist/client/{colorTokenParts-CMugwvX_.mjs → colorTokenParts-FSS3al6l.mjs} +31 -1
  209. package/dist/client/{courseRegistration-BqRZPmsq.mjs → courseRegistration-Z_mn18jy.mjs} +100 -37
  210. package/dist/client/{eventCalendar-B8N_tSl5.mjs → eventCalendar-CYp0YJGF.mjs} +4 -5
  211. package/dist/client/{eventCombined-Gjn6gtq7.mjs → eventCombined-rKyYZUa9.mjs} +2 -2
  212. package/dist/client/{eventDetails-M-VCxA-r.mjs → eventDetails-X0ZaUuMj.mjs} +3 -3
  213. package/dist/client/{eventListing-DR19hqYi.mjs → eventListing-W1SuL7EP.mjs} +2 -2
  214. package/dist/client/{eventRegistration-BR02a0k3.mjs → eventRegistration-ClWricui.mjs} +6 -7
  215. package/dist/client/{form-LY2xIbwg.mjs → form--eKPwAAD.mjs} +1 -2
  216. package/dist/client/{headerSection-CYwwXJfh.mjs → headerSection-BSeGr-FS.mjs} +2 -3
  217. package/dist/client/hooks.mjs +2169 -2093
  218. package/dist/client/{locationMap-DWnBXrFq.mjs → locationMap-BpOrtNYn.mjs} +8 -5
  219. package/dist/client/{media-DHtSxS5V.mjs → media-DoF0dcVx.mjs} +4 -3
  220. package/dist/client/{newsletterForm-D9s-fQ2P.mjs → newsletterForm-Bt7it7Dy.mjs} +1 -2
  221. package/dist/client/{pricing-DDq80oYc.mjs → pricing-BTjSDDr4.mjs} +1 -1
  222. package/dist/client/{productDetail-B0SbWd45.mjs → productDetail-ICnVTcCg.mjs} +3 -3
  223. package/dist/client/{productList-PwYlZn0y.mjs → productList-ZHr6D604.mjs} +3 -3
  224. package/dist/client/{propsDecoder-BRWBiH7i.mjs → propsDecoder-wWN0tBDF.mjs} +2484 -223
  225. package/dist/client/rendering/client.mjs +2532 -2144
  226. package/dist/client/rendering/islands.mjs +20 -20
  227. package/dist/client/rendering.mjs +3322 -2462
  228. package/dist/client/{shop-CMwZPYME.mjs → shop-C1u_BUn0.mjs} +5 -6
  229. package/dist/client/{shop-commerce-BuxsFate.mjs → shop-commerce-CleZdRha.mjs} +5 -6
  230. package/dist/client/{shop-commerce-store-boYlEJ91.mjs → shop-commerce-store-ycnoB2Ce.mjs} +1 -1
  231. package/dist/client/{shopShared-D2naaOes.mjs → shopShared-CPhByt2a.mjs} +3 -3
  232. package/dist/client/{useDiscountCodeUi-D9RHpVoj.mjs → useDiscountCodeUi-cStSQI6C.mjs} +1 -1
  233. package/dist/client/{useEventFilters-igGiK1re.mjs → useEventFilters-DKPN7hSY.mjs} +46 -70
  234. package/dist/client/{usePolling-CI7MbsFB.mjs → usePolling-BKAd6pkZ.mjs} +2 -2
  235. package/dist/preview-next/before-render.mjs +72 -6
  236. package/dist/preview-next/client/runtime.mjs +4 -4
  237. package/dist/preview-next/middleware.mjs +72 -6
  238. package/dist/{previewAuthStore-a_cBD28m.mjs → previewAuthStore-BkT1D06A.mjs} +72 -6
  239. package/dist/{sdk-runtime-MBzD-GmP.mjs → sdk-runtime-hu3wr3ng.mjs} +2 -2
  240. package/dist/{separator-5ahRBC85.mjs → separator-Bln8izQ9.mjs} +1 -1
  241. package/dist/server/components.mjs +3123 -2391
  242. package/dist/server/config-validation.mjs +2169 -2093
  243. package/dist/server/config.mjs +2169 -2093
  244. package/dist/server/data.mjs +2169 -2093
  245. package/dist/server/date-time.mjs +386 -0
  246. package/dist/server/index.mjs +73 -7
  247. package/dist/server/next/revalidate.mjs +53 -1
  248. package/dist/server/next.mjs +3195 -2397
  249. package/dist/server/page-converter.mjs +2192 -1945
  250. package/dist/server/prebuild.mjs +1 -1
  251. package/dist/server/rendering/server.mjs +2844 -2325
  252. package/dist/server/rendering.mjs +3123 -2391
  253. package/dist/server/routing.mjs +2269 -2149
  254. package/dist/server/server.mjs +2244 -2102
  255. package/dist/server/theme-bridge.mjs +2720 -1887
  256. package/dist/server/theme.mjs +1669 -1322
  257. package/dist/server/webhooks.mjs +54 -2
  258. package/dist/styles/index.css +5 -0
  259. package/package.json +7 -1
  260. package/dist/_dts/theme-core/src/buttons/personalities/brushed-wash.d.ts +0 -16
  261. package/dist/_dts/theme-core/src/buttons/personalities/confident-chip.d.ts +0 -16
  262. package/dist/_dts/theme-core/src/buttons/personalities/earth-pill.d.ts +0 -16
  263. package/dist/_dts/theme-core/src/buttons/personalities/editorial-link.d.ts +0 -16
  264. package/dist/_dts/theme-core/src/buttons/personalities/flat-ink.d.ts +0 -20
  265. package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +0 -172
  266. package/dist/_dts/theme-core/src/buttons/personalities/ink-stamp.d.ts +0 -16
  267. package/dist/_dts/theme-core/src/buttons/personalities/joy-stamp.d.ts +0 -22
  268. package/dist/_dts/theme-core/src/buttons/personalities/ornate-ritual.d.ts +0 -16
  269. package/dist/_dts/theme-core/src/buttons/personalities/pebble.d.ts +0 -16
  270. package/dist/_dts/theme-core/src/buttons/personalities/quiet-arrow.d.ts +0 -17
  271. package/dist/_dts/theme-core/src/buttons/personalities/showtime-pill.d.ts +0 -17
  272. package/dist/_dts/theme-core/src/buttons/personalities/soft-pill.d.ts +0 -16
  273. package/dist/_dts/theme-core/src/buttons/personalities/two-tone-pill.d.ts +0 -17
  274. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +0 -273
  275. package/dist/_dts/theme-core/src/buttons/presets/types.d.ts +0 -88
  276. package/dist/_dts/theme-core/src/buttons/utils/contrast.d.ts +0 -38
  277. package/dist/_dts/theme-core/src/palette/themePaletteCompatibility.d.ts +0 -57
  278. package/dist/client/buttons-EBjyslaX.mjs +0 -1852
@@ -132,41 +132,12 @@ function isThemeColorToken(value) {
132
132
  const parts = parseColorTokenParts(value);
133
133
  return parts.kind === "token" && isThemeColorTokenBase(parts.token);
134
134
  }
135
+ function parseThemeColorToken(value) {
136
+ if (!isThemeColorToken(value)) return null;
137
+ return value.trim();
138
+ }
135
139
  const themeColorTokenSchema = z$1.string().min(1).refine((value) => Boolean(isThemeColorToken(value)), "Expected a known Theme V2 color token");
136
140
  //#endregion
137
- //#region ../theme-core/src/site-styles/styleTags.ts
138
- /**
139
- * Descriptive style-axis metadata for button personalities and palette
140
- * variants. Site Style picker shape is curated explicitly; these tags remain
141
- * for catalog audit, docs, and future discovery tooling.
142
- */
143
- const STYLE_AXIS_VALUES = {
144
- tone: [
145
- "minimal",
146
- "classic",
147
- "bold"
148
- ],
149
- energy: ["calm", "vibrant"],
150
- motion: [
151
- "subtle",
152
- "standard",
153
- "expressive"
154
- ],
155
- era: [
156
- "editorial",
157
- "modern",
158
- "organic",
159
- "technical",
160
- "retro"
161
- ]
162
- };
163
- const styleTagsSchema = z$1.object({
164
- tone: z$1.enum(STYLE_AXIS_VALUES.tone).optional(),
165
- energy: z$1.enum(STYLE_AXIS_VALUES.energy).optional(),
166
- motion: z$1.enum(STYLE_AXIS_VALUES.motion).optional(),
167
- era: z$1.enum(STYLE_AXIS_VALUES.era).optional()
168
- });
169
- //#endregion
170
141
  //#region ../theme-core/src/lib/media.ts
171
142
  const hotspotSchema = z.object({
172
143
  x: z.number().min(0).max(1),
@@ -224,6 +195,111 @@ const mediaSchema = z.object({
224
195
  transform: transformSchema.optional()
225
196
  });
226
197
  //#endregion
198
+ //#region ../theme-core/src/buttons/effectClassification.ts
199
+ /**
200
+ * Exhaustive live policy for every registered effect id.
201
+ *
202
+ * The resolver consumes the transition payload directly, so adding an effect
203
+ * cannot update classification without also defining its runtime behavior.
204
+ */
205
+ const BUTTON_EFFECT_POLICIES = {
206
+ "darken-background": {
207
+ classification: "colour-transition",
208
+ transition: {
209
+ kind: "adjust-shade",
210
+ direction: "darker"
211
+ }
212
+ },
213
+ "lighten-background": {
214
+ classification: "colour-transition",
215
+ transition: {
216
+ kind: "adjust-shade",
217
+ direction: "lighter"
218
+ }
219
+ },
220
+ "background-on-hover": {
221
+ classification: "colour-transition",
222
+ transition: { kind: "replace-background" }
223
+ },
224
+ "background-on-hover-alpha": {
225
+ classification: "unsupported-colour",
226
+ reason: "alpha_requires_surface"
227
+ },
228
+ "fade-background": {
229
+ classification: "unsupported-colour",
230
+ reason: "changes_element_opacity"
231
+ },
232
+ "opacity-reduce": {
233
+ classification: "unsupported-colour",
234
+ reason: "changes_element_opacity"
235
+ },
236
+ "gradient-text": {
237
+ classification: "unsupported-colour",
238
+ reason: "changes_foreground"
239
+ },
240
+ "text-color-change": {
241
+ classification: "unsupported-colour",
242
+ reason: "changes_foreground"
243
+ },
244
+ "border-color-change": {
245
+ classification: "unsupported-colour",
246
+ reason: "changes_border"
247
+ },
248
+ "aurora-glow": {
249
+ classification: "unsupported-background-overlay",
250
+ reason: "unresolved_background_overlay"
251
+ },
252
+ "cosmic-stardust": {
253
+ classification: "unsupported-background-overlay",
254
+ reason: "unresolved_background_overlay"
255
+ },
256
+ "gradient-border-fill": {
257
+ classification: "unsupported-background-overlay",
258
+ reason: "unresolved_background_overlay"
259
+ },
260
+ "animated-gradient-border-fill": {
261
+ classification: "unsupported-background-overlay",
262
+ reason: "unresolved_background_overlay"
263
+ },
264
+ "nav-underline": {
265
+ classification: "not-button",
266
+ reason: "not_button_effect"
267
+ },
268
+ "nav-frosted-base": {
269
+ classification: "not-button",
270
+ reason: "not_button_effect"
271
+ },
272
+ "nav-frosted-hover": {
273
+ classification: "not-button",
274
+ reason: "not_button_effect"
275
+ },
276
+ "nav-frosted-active": {
277
+ classification: "not-button",
278
+ reason: "not_button_effect"
279
+ },
280
+ "animated-gradient": { classification: "non-colour" },
281
+ "border-glow": { classification: "non-colour" },
282
+ "drop-shadow": { classification: "non-colour" },
283
+ "inner-shadow": { classification: "non-colour" },
284
+ "neumorphic-shadow": { classification: "non-colour" },
285
+ "outer-glow": { classification: "non-colour" },
286
+ "retro-3d-shadow": { classification: "non-colour" },
287
+ "scale-up": { classification: "non-colour" },
288
+ "scale-down": { classification: "non-colour" },
289
+ lift: { classification: "non-colour" },
290
+ "press-down": { classification: "non-colour" },
291
+ pop: { classification: "non-colour" },
292
+ "border-bottom-grow": { classification: "non-colour" },
293
+ "sketchy-border": { classification: "non-colour" },
294
+ "pulse-animation": { classification: "non-colour" }
295
+ };
296
+ function getButtonEffectPolicy(effectId) {
297
+ return Object.prototype.hasOwnProperty.call(BUTTON_EFFECT_POLICIES, effectId) ? BUTTON_EFFECT_POLICIES[effectId] : null;
298
+ }
299
+ function classifyButtonEffectId(effectId) {
300
+ return getButtonEffectPolicy(effectId)?.classification ?? "unknown";
301
+ }
302
+ //#endregion
227
303
  //#region ../theme-core/src/buttons/types.ts
228
304
  /**
229
305
  * Standard semantic variant roles a theme exposes.
@@ -240,6 +316,20 @@ const VARIANT_ROLES = [
240
316
  "tertiary",
241
317
  "accent"
242
318
  ];
319
+ function parseOpaqueButtonColourToken(value) {
320
+ const token = parseThemeColorToken(value);
321
+ if (token === null) return null;
322
+ const parts = parseColorTokenParts(token);
323
+ return parts.kind === "token" && parts.opacityPercent === null ? token : null;
324
+ }
325
+ function unsafeAsOpaqueButtonColourToken(value) {
326
+ return value;
327
+ }
328
+ const opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => parseOpaqueButtonColourToken(value) !== null, "Button colour tokens must be opaque").transform((value) => {
329
+ const token = parseOpaqueButtonColourToken(value);
330
+ if (token === null) throw new Error("Invariant: opaque button token passed its schema");
331
+ return token;
332
+ });
243
333
  const cornerStyleSchema = z$1.enum([
244
334
  "square",
245
335
  "rounded",
@@ -341,7 +431,7 @@ const buttonSizesSchema = z$1.object({
341
431
  lg,
342
432
  xl: xl ?? lg
343
433
  }));
344
- const buttonGlobalSettingsSchema = z$1.object({
434
+ const canonicalButtonGlobalSettingsSchema = z$1.object({
345
435
  cornerStyle: cornerStyleSchema,
346
436
  cornerRadius: z$1.number().min(0).max(24).optional(),
347
437
  /**
@@ -372,11 +462,12 @@ const buttonGlobalSettingsSchema = z$1.object({
372
462
  paddingPreset: buttonPaddingPresetSchema.optional(),
373
463
  hoverTransform: hoverTransformSchema,
374
464
  hoverColor: hoverColorSchema,
375
- hoverColorToken: themeColorTokenSchema.optional(),
465
+ hoverColorToken: opaqueButtonColourTokenSchema.optional(),
376
466
  gradientStyle: gradientStyleSchema.optional(),
377
467
  gradientAngle: z$1.number().min(0).max(360).optional(),
378
468
  gradientSharpness: gradientSharpnessSchema.optional()
379
469
  });
470
+ const buttonGlobalSettingsSchema = z$1.preprocess(normalizeLegacyButtonGlobalInput, canonicalButtonGlobalSettingsSchema);
380
471
  const gradientDirectionSchema$1 = z$1.enum([
381
472
  "to-r",
382
473
  "to-l",
@@ -387,30 +478,37 @@ const gradientDirectionSchema$1 = z$1.enum([
387
478
  "to-br",
388
479
  "to-bl"
389
480
  ]);
390
- const buttonBackgroundSchema = z$1.discriminatedUnion("type", [
481
+ const buttonColourTreatmentSchema = z$1.discriminatedUnion("type", [
391
482
  z$1.object({
392
483
  type: z$1.literal("solid"),
393
- colorToken: themeColorTokenSchema
484
+ colorToken: opaqueButtonColourTokenSchema
394
485
  }),
395
486
  z$1.object({
396
487
  type: z$1.literal("gradient"),
397
- stops: z$1.array(themeColorTokenSchema).min(2),
398
- direction: gradientDirectionSchema$1
488
+ stops: z$1.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
489
+ const [first, second, ...rest] = stops;
490
+ if (first === void 0 || second === void 0) throw new Error("Invariant: gradient stops passed the minimum length schema");
491
+ return [
492
+ first,
493
+ second,
494
+ ...rest
495
+ ];
496
+ }),
497
+ direction: gradientDirectionSchema$1,
498
+ foregroundToken: opaqueButtonColourTokenSchema
399
499
  }),
400
- z$1.object({ type: z$1.literal("transparent") })
500
+ z$1.object({
501
+ type: z$1.literal("surface"),
502
+ role: z$1.literal("link")
503
+ })
401
504
  ]);
505
+ const buttonBackgroundSchema = buttonColourTreatmentSchema;
402
506
  const effectApplicationSchema$1 = z$1.object({
403
507
  effectId: z$1.string(),
404
- options: z$1.record(z$1.string(), z$1.any()).optional()
405
- });
406
- const buttonBorderSchema = z$1.object({
407
- widthClass: z$1.string(),
408
- colorToken: themeColorTokenSchema
409
- });
410
- const buttonVariantAffordanceSchema = z$1.object({
411
- iconId: z$1.string().min(1),
412
- colorToken: themeColorTokenSchema.optional()
508
+ options: z$1.record(z$1.string(), z$1.json()).optional()
413
509
  });
510
+ const buttonBorderSchema = z$1.object({ widthClass: z$1.string() });
511
+ const buttonVariantAffordanceSchema = z$1.object({ iconId: z$1.string().min(1) });
414
512
  const variantShadowSchema = z$1.object({
415
513
  elevation: z$1.enum([
416
514
  "none",
@@ -451,299 +549,595 @@ const variantSizeOverridesSchema = z$1.object({
451
549
  * default (e.g. link-style variants declaring zero horizontal padding at
452
550
  * every size).
453
551
  */
454
- const buttonVariantSchema = z$1.object({
552
+ const canonicalButtonVariantSchema = z$1.object({
455
553
  id: z$1.string(),
456
554
  name: z$1.string().min(1).max(20),
457
555
  enabled: z$1.boolean(),
458
556
  priority: prioritySchema,
459
557
  background: buttonBackgroundSchema,
460
- textColorToken: themeColorTokenSchema,
461
558
  /** Tailwind radius token (e.g. `'rounded-md'`). Omit to inherit from `global.cornerStyle`. */
462
559
  borderRadius: z$1.string().optional(),
463
560
  shadow: variantShadowSchema.optional(),
464
561
  border: buttonBorderSchema.optional(),
465
- hoverBackgroundToken: z$1.string().optional(),
562
+ hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
466
563
  effects: variantEffectsSchema.optional(),
467
564
  sizes: variantSizeOverridesSchema.optional(),
468
565
  affordance: buttonVariantAffordanceSchema.optional()
469
566
  });
567
+ /**
568
+ * Temporary persisted-theme admission boundary for issue #1206.
569
+ *
570
+ * Production inventory on 2026-07-22 found 22 rows using the old independent
571
+ * `textColorToken`/border colour shape. New source and all downstream code use
572
+ * only the canonical relationship. Delete this preprocessor after the reviewed
573
+ * production rewrite reports zero legacy rows.
574
+ */
575
+ const buttonVariantSchema = z$1.preprocess(normalizeLegacyButtonVariantInput, canonicalButtonVariantSchema);
470
576
  const buttonSystemSchema = z$1.object({
471
577
  global: buttonGlobalSettingsSchema,
472
578
  variants: z$1.array(buttonVariantSchema).min(1).max(6),
473
579
  sizes: buttonSizesSchema.optional()
474
580
  });
581
+ function normalizeLegacyButtonVariantInput(input) {
582
+ if (!isUnknownRecord(input)) return input;
583
+ const background = input.background;
584
+ if (!isUnknownRecord(background)) return input;
585
+ if (!(background.type === "transparent" || Object.prototype.hasOwnProperty.call(input, "textColorToken") || isUnknownRecord(input.border) && Object.prototype.hasOwnProperty.call(input.border, "colorToken") || hasLegacyButtonEffects(input.effects) || hasLegacyAlphaToken(input, background))) return input;
586
+ const { textColorToken, ...withoutLegacyText } = input;
587
+ const normalizedBorder = isUnknownRecord(input.border) && typeof input.border.widthClass === "string" ? { widthClass: input.border.widthClass } : input.border;
588
+ const normalizedAffordance = isUnknownRecord(input.affordance) && typeof input.affordance.iconId === "string" ? { iconId: input.affordance.iconId } : input.affordance;
589
+ const normalizedEffects = normalizeLegacyButtonEffects(input.effects, background.type);
590
+ const hoverBackgroundToken = stripLegacyTokenAlpha(input.hoverBackgroundToken);
591
+ if (background.type === "transparent") return {
592
+ ...withoutLegacyText,
593
+ background: {
594
+ type: "surface",
595
+ role: "link"
596
+ },
597
+ border: normalizedBorder,
598
+ affordance: normalizedAffordance,
599
+ effects: normalizedEffects,
600
+ hoverBackgroundToken
601
+ };
602
+ if (background.type === "gradient") {
603
+ const stops = Array.isArray(background.stops) ? background.stops.map(stripLegacyTokenAlpha) : background.stops;
604
+ return {
605
+ ...withoutLegacyText,
606
+ background: {
607
+ ...background,
608
+ stops,
609
+ foregroundToken: stripLegacyTokenAlpha(background.foregroundToken ?? textColorToken)
610
+ },
611
+ border: normalizedBorder,
612
+ affordance: normalizedAffordance,
613
+ effects: normalizedEffects,
614
+ hoverBackgroundToken
615
+ };
616
+ }
617
+ return {
618
+ ...withoutLegacyText,
619
+ background: background.type === "solid" ? {
620
+ ...background,
621
+ colorToken: stripLegacyTokenAlpha(background.colorToken)
622
+ } : background,
623
+ border: normalizedBorder,
624
+ affordance: normalizedAffordance,
625
+ effects: normalizedEffects,
626
+ hoverBackgroundToken
627
+ };
628
+ }
629
+ function normalizeLegacyButtonGlobalInput(input) {
630
+ if (!isUnknownRecord(input)) return input;
631
+ const hoverColorToken = stripLegacyTokenAlpha(input.hoverColorToken);
632
+ return hoverColorToken === input.hoverColorToken ? input : {
633
+ ...input,
634
+ hoverColorToken
635
+ };
636
+ }
637
+ function hasLegacyAlphaToken(input, background) {
638
+ const stops = isUnknownArray(background.stops) ? background.stops : [];
639
+ return [
640
+ input.hoverBackgroundToken,
641
+ background.colorToken,
642
+ background.foregroundToken,
643
+ ...stops
644
+ ].some((token) => stripLegacyTokenAlpha(token) !== token);
645
+ }
646
+ function stripLegacyTokenAlpha(value) {
647
+ if (typeof value !== "string") return value;
648
+ const slashIndex = value.indexOf("/");
649
+ return slashIndex < 0 ? value : value.slice(0, slashIndex);
650
+ }
651
+ function hasLegacyButtonEffects(input) {
652
+ if (!isUnknownRecord(input)) return false;
653
+ return [
654
+ "base",
655
+ "hover",
656
+ "active",
657
+ "focus"
658
+ ].some((state) => {
659
+ const effects = input[state];
660
+ return Array.isArray(effects) && effects.some((effect) => {
661
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return true;
662
+ const classification = classifyButtonEffectId(effect.effectId);
663
+ if (classification !== "colour-transition" && classification !== "non-colour") return true;
664
+ return effect.effectId === "background-on-hover" && isUnknownRecord(effect.options) && stripLegacyTokenAlpha(effect.options.colorToken) !== effect.options.colorToken;
665
+ });
666
+ });
667
+ }
668
+ function normalizeLegacyButtonEffects(input, backgroundType) {
669
+ if (!isUnknownRecord(input)) return input;
670
+ const normalized = {};
671
+ for (const state of [
672
+ "base",
673
+ "hover",
674
+ "active",
675
+ "focus"
676
+ ]) {
677
+ const effects = input[state];
678
+ if (!Array.isArray(effects)) continue;
679
+ const safeEffects = effects.flatMap((effect) => {
680
+ if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return [];
681
+ const classification = classifyButtonEffectId(effect.effectId);
682
+ if (classification === "non-colour") return [effect];
683
+ if (classification !== "colour-transition") return [];
684
+ if (effect.effectId === "background-on-hover") {
685
+ const options = isUnknownRecord(effect.options) ? effect.options : null;
686
+ const colorToken = options === null ? null : parseOpaqueButtonColourToken(stripLegacyTokenAlpha(options.colorToken));
687
+ return colorToken === null ? [] : [{
688
+ ...effect,
689
+ options: {
690
+ ...options,
691
+ colorToken
692
+ }
693
+ }];
694
+ }
695
+ if (backgroundType !== "solid") return [];
696
+ const rawAmount = isUnknownRecord(effect.options) ? effect.options.amount : void 0;
697
+ const amount = typeof rawAmount === "number" && rawAmount > 0 ? Math.max(100, Math.round(rawAmount / 100) * 100) : 100;
698
+ return [{
699
+ ...effect,
700
+ options: {
701
+ ...isUnknownRecord(effect.options) ? effect.options : {},
702
+ amount
703
+ }
704
+ }];
705
+ });
706
+ if (safeEffects.length > 0) normalized[state] = safeEffects;
707
+ }
708
+ return Object.keys(normalized).length === 0 ? void 0 : normalized;
709
+ }
710
+ function isUnknownRecord(value) {
711
+ return typeof value === "object" && value !== null && !Array.isArray(value);
712
+ }
713
+ function isUnknownArray(value) {
714
+ return Array.isArray(value);
715
+ }
475
716
  buttonSizeNameSchema.options;
476
717
  //#endregion
477
- //#region ../theme-core/src/buttons/personalities/types.ts
478
- function asButtonPersonalityId(value) {
479
- if (value.length === 0) throw new Error("ButtonPersonalityId must be a non-empty string");
480
- return value;
718
+ //#region ../theme-core/src/buttons/styles/domain.ts
719
+ const PUBLIC_BUTTON_ROLES = [
720
+ "primary",
721
+ "secondary",
722
+ "outline",
723
+ "ghost",
724
+ "accent"
725
+ ];
726
+ function defineButtonStyleRecipe(recipe) {
727
+ return recipe;
481
728
  }
482
- const buttonPersonalityIdSchema = z$1.string().min(1).transform((value) => asButtonPersonalityId(value));
483
- z$1.object({
484
- id: buttonPersonalityIdSchema,
485
- name: z$1.string().min(1),
486
- description: z$1.string().min(1),
487
- tags: styleTagsSchema,
488
- buttonSystem: buttonSystemSchema
489
- });
490
- /**
491
- * Helper for personality file modules to keep the call site short and
492
- * type-safe. `as const satisfies ...` would also work but produces wider
493
- * types at use sites.
494
- */
495
- function defineButtonPersonality(input) {
729
+ function materializeButtonRoles(definitions) {
730
+ const primary = materializeCompleteRole("primary", definitions.primary.appearance);
731
+ const secondary = materializeCompleteRole("secondary", definitions.secondary.appearance);
732
+ const completeRoles = {
733
+ primary,
734
+ secondary
735
+ };
496
736
  return {
497
- id: asButtonPersonalityId(input.id),
498
- name: input.name,
499
- description: input.description,
500
- tags: input.tags,
501
- buttonSystem: input.buttonSystem
737
+ primary,
738
+ secondary,
739
+ outline: materializeSupportingRole("outline", definitions.outline, completeRoles),
740
+ ghost: materializeSupportingRole("ghost", definitions.ghost, completeRoles),
741
+ accent: materializeSupportingRole("accent", definitions.accent, completeRoles)
742
+ };
743
+ }
744
+ function resolveButtonStyleRecipe(recipe, parameters) {
745
+ const parsedParameters = recipe.parameterSchema.safeParse(parameters);
746
+ if (!parsedParameters.success) return {
747
+ kind: "error",
748
+ error: {
749
+ kind: "invalid-parameters",
750
+ styleId: recipe.id,
751
+ issues: parsedParameters.error.issues.map((issue) => issue.message)
752
+ }
753
+ };
754
+ const definition = recipe.defineSystem(parsedParameters.data);
755
+ const roles = materializeButtonRoles(definition.roles);
756
+ const buttonSystem = {
757
+ global: definition.global,
758
+ variants: PUBLIC_BUTTON_ROLES.map((role) => roles[role]),
759
+ ...definition.sizes ? { sizes: definition.sizes } : {}
760
+ };
761
+ const parsedButtonSystem = buttonSystemSchema.safeParse(buttonSystem);
762
+ if (!parsedButtonSystem.success) return {
763
+ kind: "error",
764
+ error: {
765
+ kind: "invalid-button-system",
766
+ styleId: recipe.id,
767
+ issues: parsedButtonSystem.error.issues.map((issue) => issue.message)
768
+ }
769
+ };
770
+ return {
771
+ kind: "resolved",
772
+ buttonSystem: parsedButtonSystem.data
773
+ };
774
+ }
775
+ function materializeSupportingRole(role, definition, completeRoles) {
776
+ if (definition.kind === "complete") return materializeCompleteRole(role, definition.appearance);
777
+ return {
778
+ ...completeRoles[definition.from],
779
+ ...definition.overrides,
780
+ id: role,
781
+ name: roleName(role),
782
+ enabled: true,
783
+ priority: 3
784
+ };
785
+ }
786
+ function materializeCompleteRole(role, appearance) {
787
+ return {
788
+ ...appearance,
789
+ id: role,
790
+ name: roleName(role),
791
+ enabled: true,
792
+ priority: rolePriority(role)
502
793
  };
503
794
  }
795
+ function roleName(role) {
796
+ return role.charAt(0).toUpperCase() + role.slice(1);
797
+ }
798
+ function rolePriority(role) {
799
+ if (role === "primary") return 1;
800
+ if (role === "secondary") return 2;
801
+ return 3;
802
+ }
504
803
  //#endregion
505
- //#region ../theme-core/src/buttons/personalities/brushed-wash.ts
506
- /**
507
- * Brushed Wash — gradient backgrounds that read as watercolour washes.
508
- * Generous padding, soft shadows; pairs with vibrant organic brands.
509
- */
510
- const brushedWash = defineButtonPersonality({
511
- id: "brushed-wash",
512
- name: "Brushed Wash",
513
- description: "Watercolour-gradient buttons with soft shadows and generous padding.",
804
+ //#region ../theme-core/src/buttons/styles/selection.ts
805
+ const BUTTON_STYLE_IDS = [
806
+ "soft-pill",
807
+ "earth-pill",
808
+ "confident-chip",
809
+ "editorial-link",
810
+ "pebble",
811
+ "ink-stamp",
812
+ "flat-ink",
813
+ "brushed-wash",
814
+ "showtime-pill",
815
+ "joy-stamp",
816
+ "ornate-ritual",
817
+ "quiet-arrow"
818
+ ];
819
+ const quietArrowParametersSchema = z$1.object({ secondaryTreatment: z$1.enum(["outlined", "solid-accent"]) }).strict();
820
+ const emptyParametersSchema$1 = z$1.object({}).strict();
821
+ function selectionBranch(styleId, parameters) {
822
+ return z$1.object({
823
+ styleId: z$1.literal(styleId),
824
+ parameters
825
+ }).strict();
826
+ }
827
+ z$1.discriminatedUnion("styleId", [
828
+ selectionBranch("soft-pill", emptyParametersSchema$1),
829
+ selectionBranch("earth-pill", emptyParametersSchema$1),
830
+ selectionBranch("confident-chip", emptyParametersSchema$1),
831
+ selectionBranch("editorial-link", emptyParametersSchema$1),
832
+ selectionBranch("pebble", emptyParametersSchema$1),
833
+ selectionBranch("ink-stamp", emptyParametersSchema$1),
834
+ selectionBranch("flat-ink", emptyParametersSchema$1),
835
+ selectionBranch("brushed-wash", emptyParametersSchema$1),
836
+ selectionBranch("showtime-pill", emptyParametersSchema$1),
837
+ selectionBranch("joy-stamp", emptyParametersSchema$1),
838
+ selectionBranch("ornate-ritual", emptyParametersSchema$1),
839
+ selectionBranch("quiet-arrow", quietArrowParametersSchema)
840
+ ]);
841
+ //#endregion
842
+ //#region ../theme-core/src/buttons/styles/recipes/quietArrow.ts
843
+ const quietArrowRecipe = defineButtonStyleRecipe({
844
+ id: "quiet-arrow",
845
+ accessibilityLabel: "Wide uppercase buttons with trailing arrows",
514
846
  tags: {
515
847
  tone: "classic",
516
- energy: "vibrant",
517
- motion: "standard",
518
- era: "organic"
848
+ energy: "calm",
849
+ motion: "subtle",
850
+ era: "editorial"
519
851
  },
520
- buttonSystem: {
852
+ parameterSchema: quietArrowParametersSchema,
853
+ defaultParameters: { secondaryTreatment: "outlined" },
854
+ controls: [{
855
+ kind: "choice",
856
+ parameter: "secondaryTreatment",
857
+ label: "Secondary button treatment",
858
+ options: [{
859
+ value: "outlined",
860
+ label: "Outlined"
861
+ }, {
862
+ value: "solid-accent",
863
+ label: "Solid accent"
864
+ }]
865
+ }],
866
+ defineSystem: (parameters) => ({
521
867
  global: {
522
868
  cornerStyle: "rounded",
523
- shadow: "low",
524
- textTransform: "none",
869
+ textTransform: "uppercase",
525
870
  fontWeight: 500,
526
871
  borderWidth: 1,
872
+ typography: "body",
873
+ fontSize: "text-sm",
874
+ letterSpacing: "loose",
527
875
  hoverTransform: "none",
528
876
  hoverColor: "none"
529
877
  },
530
878
  sizes: {
531
879
  sm: {
532
- padding: "0.75rem 2rem",
880
+ padding: "0.625rem 1.25rem",
881
+ fontSize: "text-xs"
882
+ },
883
+ md: {
884
+ padding: "0.8125rem 1.75rem",
533
885
  fontSize: "text-sm"
534
886
  },
535
- md: { padding: "1rem 2.5rem" },
536
887
  lg: {
537
- padding: "1.25rem 3rem",
538
- fontSize: "text-lg"
888
+ padding: "0.9375rem 2.125rem",
889
+ fontSize: "text-sm"
539
890
  },
540
891
  xl: {
541
- padding: "1.625rem 3.75rem",
542
- fontSize: "text-xl"
892
+ padding: "1.0625rem 2.5rem",
893
+ fontSize: "text-base"
543
894
  }
544
895
  },
545
- variants: [
546
- {
547
- id: "primary",
548
- name: "Primary",
549
- enabled: true,
550
- priority: 1,
551
- background: {
552
- type: "gradient",
553
- stops: ["primary", "accent"],
554
- direction: "to-r"
555
- },
556
- textColorToken: "primaryForeground",
557
- borderRadius: "rounded-lg",
558
- shadow: {
559
- elevation: "low",
560
- softness: "soft",
561
- position: "bottom"
562
- },
563
- effects: { hover: [{
564
- effectId: "opacity-reduce",
565
- options: { reduction: -15 }
566
- }] }
567
- },
568
- {
569
- id: "secondary",
570
- name: "Secondary",
571
- enabled: true,
572
- priority: 2,
573
- background: {
574
- type: "gradient",
575
- stops: ["secondary", "accent"],
576
- direction: "to-br"
577
- },
578
- textColorToken: "primaryForeground",
579
- borderRadius: "rounded-lg",
580
- shadow: {
581
- elevation: "low",
582
- softness: "soft",
583
- position: "bottom"
584
- },
585
- effects: { hover: [{
586
- effectId: "opacity-reduce",
587
- options: { reduction: -15 }
588
- }] }
589
- },
590
- {
591
- id: "outline",
592
- name: "Outline",
593
- enabled: true,
594
- priority: 3,
595
- background: { type: "transparent" },
596
- textColorToken: "primary",
597
- borderRadius: "rounded-lg",
598
- border: {
599
- widthClass: "border",
600
- colorToken: "primary"
601
- },
602
- effects: { hover: [{
603
- effectId: "background-on-hover",
604
- options: { colorToken: "surface" }
605
- }] }
606
- },
607
- {
608
- id: "ghost",
609
- name: "Ghost",
610
- enabled: true,
611
- priority: 3,
612
- background: { type: "transparent" },
613
- textColorToken: "text",
614
- borderRadius: "rounded-lg",
615
- effects: { hover: [{
616
- effectId: "background-on-hover",
617
- options: { colorToken: "surface" }
618
- }] }
896
+ roles: {
897
+ primary: {
898
+ kind: "complete",
899
+ appearance: {
900
+ background: {
901
+ type: "solid",
902
+ colorToken: unsafeAsOpaqueButtonColourToken("primary")
903
+ },
904
+ borderRadius: "rounded-xl",
905
+ affordance: { iconId: "ArrowRight" },
906
+ effects: { hover: [{
907
+ effectId: "darken-background",
908
+ options: { amount: 100 }
909
+ }] }
910
+ }
911
+ },
912
+ secondary: {
913
+ kind: "complete",
914
+ appearance: parameters.secondaryTreatment === "solid-accent" ? {
915
+ background: {
916
+ type: "solid",
917
+ colorToken: unsafeAsOpaqueButtonColourToken("accent")
918
+ },
919
+ borderRadius: "rounded-xl",
920
+ affordance: { iconId: "ArrowRight" },
921
+ effects: { hover: [{
922
+ effectId: "darken-background",
923
+ options: { amount: 100 }
924
+ }] }
925
+ } : {
926
+ background: {
927
+ type: "surface",
928
+ role: "link"
929
+ },
930
+ borderRadius: "rounded-xl",
931
+ border: { widthClass: "border" },
932
+ affordance: { iconId: "ArrowRight" },
933
+ effects: { hover: [{
934
+ effectId: "background-on-hover",
935
+ options: { colorToken: "surfaceAlt" }
936
+ }] }
937
+ }
938
+ },
939
+ outline: {
940
+ kind: "complete",
941
+ appearance: {
942
+ background: {
943
+ type: "surface",
944
+ role: "link"
945
+ },
946
+ borderRadius: "rounded-xl",
947
+ border: { widthClass: "border" }
948
+ }
949
+ },
950
+ ghost: {
951
+ kind: "complete",
952
+ appearance: {
953
+ background: {
954
+ type: "surface",
955
+ role: "link"
956
+ },
957
+ borderRadius: "rounded-xl"
958
+ }
959
+ },
960
+ accent: {
961
+ kind: "derive",
962
+ from: "primary",
963
+ overrides: { background: {
964
+ type: "solid",
965
+ colorToken: unsafeAsOpaqueButtonColourToken("accent")
966
+ } }
619
967
  }
620
- ]
621
- }
968
+ }
969
+ })
622
970
  });
623
971
  //#endregion
624
- //#region ../theme-core/src/buttons/personalities/confident-chip.ts
625
- /**
626
- * Confident Chip — moderate-radius solid buttons that read as competent and
627
- * direct. Default for Clear Professional; works for any modern brand voice.
628
- */
629
- const confidentChip = defineButtonPersonality({
630
- id: "confident-chip",
631
- name: "Confident Chip",
632
- description: "Mid-radius solid buttons with a crisp hover.",
972
+ //#region ../theme-core/src/buttons/styles/recipes/defineStaticButtonStyleRecipe.ts
973
+ const emptyParametersSchema = z$1.object({}).strict();
974
+ function defineStaticButtonStyleRecipe(input) {
975
+ const system = normalizeSystem(input.system);
976
+ return defineButtonStyleRecipe({
977
+ id: input.id,
978
+ accessibilityLabel: input.accessibilityLabel,
979
+ tags: input.tags,
980
+ parameterSchema: emptyParametersSchema,
981
+ defaultParameters: {},
982
+ controls: [],
983
+ defineSystem: () => system
984
+ });
985
+ }
986
+ function normalizeSystem(input) {
987
+ return {
988
+ global: buttonGlobalSettingsSchema.parse(input.global),
989
+ ...input.sizes ? { sizes: input.sizes } : {},
990
+ roles: {
991
+ primary: normalizeCompleteRole(input.roles.primary),
992
+ secondary: normalizeCompleteRole(input.roles.secondary),
993
+ outline: normalizeSupportingRole(input.roles.outline),
994
+ ghost: normalizeSupportingRole(input.roles.ghost),
995
+ accent: normalizeSupportingRole(input.roles.accent)
996
+ }
997
+ };
998
+ }
999
+ function normalizeCompleteRole(role) {
1000
+ return {
1001
+ kind: "complete",
1002
+ appearance: normalizeAppearance(role.appearance)
1003
+ };
1004
+ }
1005
+ function normalizeSupportingRole(role) {
1006
+ if (role.kind === "complete") return normalizeCompleteRole(role);
1007
+ return {
1008
+ kind: "derive",
1009
+ from: role.from,
1010
+ ...role.overrides ? { overrides: normalizeAppearanceOverrides(role.overrides) } : {}
1011
+ };
1012
+ }
1013
+ function normalizeAppearance(appearance) {
1014
+ const { background, hoverBackgroundToken, ...rest } = appearance;
1015
+ return {
1016
+ ...rest,
1017
+ background: buttonColourTreatmentSchema.parse(background),
1018
+ ...hoverBackgroundToken ? { hoverBackgroundToken: opaqueButtonColourTokenSchema.parse(hoverBackgroundToken) } : {}
1019
+ };
1020
+ }
1021
+ function normalizeAppearanceOverrides(overrides) {
1022
+ const { background, hoverBackgroundToken, ...rest } = overrides;
1023
+ return {
1024
+ ...rest,
1025
+ ...background ? { background: buttonColourTreatmentSchema.parse(background) } : {},
1026
+ ...hoverBackgroundToken ? { hoverBackgroundToken: opaqueButtonColourTokenSchema.parse(hoverBackgroundToken) } : {}
1027
+ };
1028
+ }
1029
+ //#endregion
1030
+ //#region ../theme-core/src/buttons/styles/recipes/staticRecipes.ts
1031
+ const softPillRecipe = defineStaticButtonStyleRecipe({
1032
+ id: "soft-pill",
1033
+ accessibilityLabel: "Rounded pill buttons with a gentle hover lift",
633
1034
  tags: {
634
1035
  tone: "classic",
635
1036
  energy: "calm",
636
- motion: "standard",
637
- era: "modern"
1037
+ motion: "subtle",
1038
+ era: "organic"
638
1039
  },
639
- buttonSystem: {
1040
+ system: {
640
1041
  global: {
641
- cornerStyle: "rounded",
642
- shadow: "medium",
1042
+ cornerStyle: "pill",
1043
+ shadow: "low",
643
1044
  textTransform: "none",
644
- fontWeight: 600,
645
- borderWidth: 1,
646
- hoverTransform: "none",
1045
+ fontWeight: 500,
1046
+ borderWidth: 2,
1047
+ hoverTransform: "lift",
647
1048
  hoverColor: "none"
648
1049
  },
649
- variants: [
650
- {
651
- id: "primary",
652
- name: "Primary",
653
- enabled: true,
654
- priority: 1,
655
- background: {
656
- type: "solid",
657
- colorToken: "primary"
658
- },
659
- textColorToken: "primaryForeground",
660
- borderRadius: "rounded-md",
661
- shadow: {
662
- elevation: "medium",
663
- softness: "soft",
664
- position: "bottom"
665
- },
666
- effects: {
667
- hover: [{
668
- effectId: "darken-background",
669
- options: { amount: 60 }
670
- }],
671
- active: [{
672
- effectId: "scale-down",
673
- options: { scale: "0.97" }
674
- }]
1050
+ roles: {
1051
+ primary: {
1052
+ kind: "complete",
1053
+ appearance: {
1054
+ background: {
1055
+ type: "solid",
1056
+ colorToken: "primary"
1057
+ },
1058
+ borderRadius: "rounded-full",
1059
+ shadow: {
1060
+ elevation: "low",
1061
+ softness: "soft",
1062
+ position: "bottom"
1063
+ },
1064
+ effects: {
1065
+ hover: [{
1066
+ effectId: "lift",
1067
+ options: { translateY: "-1px" }
1068
+ }],
1069
+ active: [{
1070
+ effectId: "scale-down",
1071
+ options: { scale: "0.98" }
1072
+ }]
1073
+ }
1074
+ }
1075
+ },
1076
+ secondary: {
1077
+ kind: "complete",
1078
+ appearance: {
1079
+ background: {
1080
+ type: "surface",
1081
+ role: "link"
1082
+ },
1083
+ borderRadius: "rounded-full",
1084
+ border: { widthClass: "border-2" },
1085
+ effects: { hover: [{
1086
+ effectId: "background-on-hover",
1087
+ options: { colorToken: "surface" }
1088
+ }] }
1089
+ }
1090
+ },
1091
+ outline: {
1092
+ kind: "complete",
1093
+ appearance: {
1094
+ background: {
1095
+ type: "surface",
1096
+ role: "link"
1097
+ },
1098
+ borderRadius: "rounded-full",
1099
+ border: { widthClass: "border" },
1100
+ effects: { hover: [{
1101
+ effectId: "background-on-hover",
1102
+ options: { colorToken: "surface" }
1103
+ }] }
1104
+ }
1105
+ },
1106
+ ghost: {
1107
+ kind: "complete",
1108
+ appearance: {
1109
+ background: {
1110
+ type: "surface",
1111
+ role: "link"
1112
+ },
1113
+ borderRadius: "rounded-full",
1114
+ effects: { hover: [{
1115
+ effectId: "background-on-hover",
1116
+ options: { colorToken: "surface" }
1117
+ }] }
675
1118
  }
676
1119
  },
677
- {
678
- id: "secondary",
679
- name: "Secondary",
680
- enabled: true,
681
- priority: 2,
682
- background: {
1120
+ accent: {
1121
+ kind: "derive",
1122
+ from: "primary",
1123
+ overrides: { background: {
683
1124
  type: "solid",
684
- colorToken: "surface"
685
- },
686
- textColorToken: "text",
687
- borderRadius: "rounded-md",
688
- border: {
689
- widthClass: "border",
690
- colorToken: "border"
691
- },
692
- effects: { hover: [{
693
- effectId: "background-on-hover",
694
- options: { colorToken: "background" }
695
- }] }
696
- },
697
- {
698
- id: "outline",
699
- name: "Outline",
700
- enabled: true,
701
- priority: 3,
702
- background: { type: "transparent" },
703
- textColorToken: "primary",
704
- borderRadius: "rounded-md",
705
- border: {
706
- widthClass: "border",
707
- colorToken: "primary"
708
- },
709
- effects: { hover: [{
710
- effectId: "background-on-hover",
711
- options: { colorToken: "surface" }
712
- }] }
713
- },
714
- {
715
- id: "ghost",
716
- name: "Ghost",
717
- enabled: true,
718
- priority: 3,
719
- background: { type: "transparent" },
720
- textColorToken: "primary",
721
- borderRadius: "rounded-md",
722
- effects: { hover: [{
723
- effectId: "background-on-hover",
724
- options: { colorToken: "surface" }
725
- }] }
1125
+ colorToken: "accent"
1126
+ } }
726
1127
  }
727
- ]
1128
+ }
728
1129
  }
729
1130
  });
730
- //#endregion
731
- //#region ../theme-core/src/buttons/personalities/earth-pill.ts
732
- /**
733
- * Earth Pill - warm studio pills with compact, primary-coloured ghost CTAs.
734
- * Built for grounded editorial wellness styles such as Soft Earth.
735
- */
736
- const earthPill = defineButtonPersonality({
1131
+ const earthPillRecipe = defineStaticButtonStyleRecipe({
737
1132
  id: "earth-pill",
738
- name: "Earth Pill",
739
- description: "Compact terracotta pills with quiet primary-coloured ghost CTAs.",
1133
+ accessibilityLabel: "Compact rounded buttons with a quiet hover lift",
740
1134
  tags: {
741
1135
  tone: "classic",
742
1136
  energy: "calm",
743
1137
  motion: "subtle",
744
1138
  era: "organic"
745
1139
  },
746
- buttonSystem: {
1140
+ system: {
747
1141
  global: {
748
1142
  cornerStyle: "pill",
749
1143
  shadow: "low",
@@ -770,124 +1164,222 @@ const earthPill = defineButtonPersonality({
770
1164
  fontSize: "text-xl"
771
1165
  }
772
1166
  },
773
- variants: [
774
- {
775
- id: "primary",
776
- name: "Primary",
777
- enabled: true,
778
- priority: 1,
779
- background: {
780
- type: "solid",
781
- colorToken: "primary"
782
- },
783
- textColorToken: "primaryForeground",
784
- borderRadius: "rounded-full",
785
- shadow: {
786
- elevation: "low",
787
- softness: "soft",
788
- position: "bottom"
789
- },
790
- effects: {
791
- hover: [{
792
- effectId: "lift",
793
- options: { translateY: "-1px" }
794
- }, {
1167
+ roles: {
1168
+ primary: {
1169
+ kind: "complete",
1170
+ appearance: {
1171
+ background: {
1172
+ type: "solid",
1173
+ colorToken: "primary"
1174
+ },
1175
+ borderRadius: "rounded-full",
1176
+ shadow: {
1177
+ elevation: "low",
1178
+ softness: "soft",
1179
+ position: "bottom"
1180
+ },
1181
+ effects: {
1182
+ hover: [{
1183
+ effectId: "lift",
1184
+ options: { translateY: "-1px" }
1185
+ }, {
1186
+ effectId: "background-on-hover",
1187
+ options: { colorToken: "accent" }
1188
+ }],
1189
+ active: [{
1190
+ effectId: "scale-down",
1191
+ options: { scale: "0.98" }
1192
+ }]
1193
+ }
1194
+ }
1195
+ },
1196
+ secondary: {
1197
+ kind: "complete",
1198
+ appearance: {
1199
+ background: {
1200
+ type: "surface",
1201
+ role: "link"
1202
+ },
1203
+ borderRadius: "rounded-full",
1204
+ border: { widthClass: "border" },
1205
+ effects: { hover: [{
795
1206
  effectId: "background-on-hover",
796
- options: { colorToken: "accent" }
797
- }],
798
- active: [{
799
- effectId: "scale-down",
800
- options: { scale: "0.98" }
801
- }]
1207
+ options: { colorToken: "muted" }
1208
+ }] }
1209
+ }
1210
+ },
1211
+ outline: {
1212
+ kind: "complete",
1213
+ appearance: {
1214
+ background: {
1215
+ type: "surface",
1216
+ role: "link"
1217
+ },
1218
+ borderRadius: "rounded-full",
1219
+ border: { widthClass: "border" },
1220
+ effects: { hover: [{
1221
+ effectId: "background-on-hover",
1222
+ options: { colorToken: "surfaceAlt" }
1223
+ }] }
802
1224
  }
803
1225
  },
804
- {
805
- id: "secondary",
806
- name: "Secondary",
807
- enabled: true,
808
- priority: 2,
809
- background: { type: "transparent" },
810
- textColorToken: "primary",
811
- borderRadius: "rounded-full",
812
- border: {
813
- widthClass: "border",
814
- colorToken: "primary"
815
- },
816
- effects: { hover: [{
817
- effectId: "background-on-hover",
818
- options: { colorToken: "muted" }
819
- }] }
820
- },
821
- {
822
- id: "outline",
823
- name: "Outline",
824
- enabled: true,
825
- priority: 3,
826
- background: { type: "transparent" },
827
- textColorToken: "text",
828
- borderRadius: "rounded-full",
829
- border: {
830
- widthClass: "border",
831
- colorToken: "border"
832
- },
833
- effects: { hover: [{
834
- effectId: "background-on-hover",
835
- options: { colorToken: "surfaceAlt" }
836
- }] }
837
- },
838
- {
839
- id: "ghost",
840
- name: "Ghost",
841
- enabled: true,
842
- priority: 3,
843
- background: { type: "transparent" },
844
- textColorToken: "primary",
845
- borderRadius: "rounded-full",
846
- shadow: {
847
- elevation: "none",
848
- softness: null,
849
- position: "bottom"
850
- },
851
- sizes: {
852
- sm: {
853
- padding: "0.25rem 0",
854
- fontSize: "text-sm"
1226
+ ghost: {
1227
+ kind: "complete",
1228
+ appearance: {
1229
+ background: {
1230
+ type: "surface",
1231
+ role: "link"
855
1232
  },
856
- md: { padding: "0.375rem 0" },
857
- lg: {
858
- padding: "0.5rem 0",
859
- fontSize: "text-lg"
1233
+ borderRadius: "rounded-full",
1234
+ shadow: {
1235
+ elevation: "none",
1236
+ softness: null,
1237
+ position: "bottom"
860
1238
  },
861
- xl: {
862
- padding: "0.625rem 0",
863
- fontSize: "text-xl"
1239
+ sizes: {
1240
+ sm: {
1241
+ padding: "0.25rem 0",
1242
+ fontSize: "text-sm"
1243
+ },
1244
+ md: { padding: "0.375rem 0" },
1245
+ lg: {
1246
+ padding: "0.5rem 0",
1247
+ fontSize: "text-lg"
1248
+ },
1249
+ xl: {
1250
+ padding: "0.625rem 0",
1251
+ fontSize: "text-xl"
1252
+ }
864
1253
  }
865
- },
866
- effects: { hover: [{
867
- effectId: "opacity-reduce",
868
- options: { reduction: 25 }
869
- }] }
1254
+ }
1255
+ },
1256
+ accent: {
1257
+ kind: "derive",
1258
+ from: "primary",
1259
+ overrides: { background: {
1260
+ type: "solid",
1261
+ colorToken: "accent"
1262
+ } }
870
1263
  }
871
- ]
1264
+ }
872
1265
  }
873
1266
  });
874
- //#endregion
875
- //#region ../theme-core/src/buttons/personalities/editorial-link.ts
876
- /**
877
- * Editorial Link — all variants are link-style with a growing underline.
878
- * Default for Warm Editorial and Quiet Luxury; reads as refined and quiet.
879
- */
880
- const editorialLink = defineButtonPersonality({
881
- id: "editorial-link",
882
- name: "Editorial Link",
883
- description: "Link-style with a growing underline. Refined, typographic.",
1267
+ const confidentChipRecipe = defineStaticButtonStyleRecipe({
1268
+ id: "confident-chip",
1269
+ accessibilityLabel: "Moderately rounded solid buttons with a crisp hover",
884
1270
  tags: {
885
- tone: "minimal",
1271
+ tone: "classic",
886
1272
  energy: "calm",
887
- motion: "subtle",
888
- era: "editorial"
1273
+ motion: "standard",
1274
+ era: "modern"
889
1275
  },
890
- buttonSystem: {
1276
+ system: {
1277
+ global: {
1278
+ cornerStyle: "rounded",
1279
+ shadow: "medium",
1280
+ textTransform: "none",
1281
+ fontWeight: 600,
1282
+ borderWidth: 1,
1283
+ hoverTransform: "none",
1284
+ hoverColor: "none"
1285
+ },
1286
+ roles: {
1287
+ primary: {
1288
+ kind: "complete",
1289
+ appearance: {
1290
+ background: {
1291
+ type: "solid",
1292
+ colorToken: "primary"
1293
+ },
1294
+ borderRadius: "rounded-md",
1295
+ shadow: {
1296
+ elevation: "medium",
1297
+ softness: "soft",
1298
+ position: "bottom"
1299
+ },
1300
+ effects: {
1301
+ hover: [{
1302
+ effectId: "darken-background",
1303
+ options: { amount: 100 }
1304
+ }],
1305
+ active: [{
1306
+ effectId: "scale-down",
1307
+ options: { scale: "0.97" }
1308
+ }]
1309
+ }
1310
+ }
1311
+ },
1312
+ secondary: {
1313
+ kind: "complete",
1314
+ appearance: {
1315
+ background: {
1316
+ type: "solid",
1317
+ colorToken: "surface"
1318
+ },
1319
+ borderRadius: "rounded-md",
1320
+ border: { widthClass: "border" },
1321
+ effects: { hover: [{
1322
+ effectId: "background-on-hover",
1323
+ options: { colorToken: "background" }
1324
+ }] }
1325
+ }
1326
+ },
1327
+ outline: {
1328
+ kind: "complete",
1329
+ appearance: {
1330
+ background: {
1331
+ type: "surface",
1332
+ role: "link"
1333
+ },
1334
+ borderRadius: "rounded-md",
1335
+ border: { widthClass: "border" },
1336
+ effects: { hover: [{
1337
+ effectId: "background-on-hover",
1338
+ options: { colorToken: "surface" }
1339
+ }] }
1340
+ }
1341
+ },
1342
+ ghost: {
1343
+ kind: "complete",
1344
+ appearance: {
1345
+ background: {
1346
+ type: "surface",
1347
+ role: "link"
1348
+ },
1349
+ borderRadius: "rounded-md",
1350
+ effects: { hover: [{
1351
+ effectId: "background-on-hover",
1352
+ options: { colorToken: "surface" }
1353
+ }] }
1354
+ }
1355
+ },
1356
+ accent: {
1357
+ kind: "derive",
1358
+ from: "primary",
1359
+ overrides: { background: {
1360
+ type: "solid",
1361
+ colorToken: "accent"
1362
+ } }
1363
+ }
1364
+ }
1365
+ }
1366
+ });
1367
+ const editorialSizes = {
1368
+ sm: { padding: "0.25rem 0" },
1369
+ md: { padding: "0.5rem 0" },
1370
+ lg: { padding: "0.625rem 0" },
1371
+ xl: { padding: "0.75rem 0" }
1372
+ };
1373
+ const editorialLinkRecipe = defineStaticButtonStyleRecipe({
1374
+ id: "editorial-link",
1375
+ accessibilityLabel: "Flat typographic buttons with an underline treatment",
1376
+ tags: {
1377
+ tone: "minimal",
1378
+ energy: "calm",
1379
+ motion: "subtle",
1380
+ era: "editorial"
1381
+ },
1382
+ system: {
891
1383
  global: {
892
1384
  cornerStyle: "square",
893
1385
  textTransform: "none",
@@ -896,463 +1388,323 @@ const editorialLink = defineButtonPersonality({
896
1388
  hoverTransform: "none",
897
1389
  hoverColor: "none"
898
1390
  },
899
- variants: [
900
- {
901
- id: "primary",
902
- name: "Primary",
903
- enabled: true,
904
- priority: 1,
905
- background: { type: "transparent" },
906
- textColorToken: "text",
907
- borderRadius: "rounded-none",
908
- sizes: {
909
- sm: { padding: "0.25rem 0" },
910
- md: { padding: "0.5rem 0" },
911
- lg: { padding: "0.625rem 0" },
912
- xl: { padding: "0.75rem 0" }
913
- },
914
- effects: { base: [{
1391
+ roles: {
1392
+ primary: {
1393
+ kind: "complete",
1394
+ appearance: {
1395
+ background: {
1396
+ type: "surface",
1397
+ role: "link"
1398
+ },
1399
+ borderRadius: "rounded-none",
1400
+ sizes: editorialSizes,
1401
+ effects: { base: [{
1402
+ effectId: "border-bottom-grow",
1403
+ options: {
1404
+ height: 2,
1405
+ colorToken: "text",
1406
+ origin: "left"
1407
+ }
1408
+ }] }
1409
+ }
1410
+ },
1411
+ secondary: {
1412
+ kind: "complete",
1413
+ appearance: {
1414
+ background: {
1415
+ type: "surface",
1416
+ role: "link"
1417
+ },
1418
+ borderRadius: "rounded-none",
1419
+ sizes: editorialSizes,
1420
+ effects: { base: [{
1421
+ effectId: "border-bottom-grow",
1422
+ options: {
1423
+ height: 1,
1424
+ colorToken: "mutedText",
1425
+ origin: "left"
1426
+ }
1427
+ }] }
1428
+ }
1429
+ },
1430
+ outline: {
1431
+ kind: "complete",
1432
+ appearance: {
1433
+ background: {
1434
+ type: "surface",
1435
+ role: "link"
1436
+ },
1437
+ borderRadius: "rounded-none",
1438
+ sizes: editorialSizes,
1439
+ effects: { base: [{
1440
+ effectId: "border-bottom-grow",
1441
+ options: {
1442
+ height: 1,
1443
+ colorToken: "accent",
1444
+ origin: "left"
1445
+ }
1446
+ }] }
1447
+ }
1448
+ },
1449
+ ghost: {
1450
+ kind: "complete",
1451
+ appearance: {
1452
+ background: {
1453
+ type: "surface",
1454
+ role: "link"
1455
+ },
1456
+ borderRadius: "rounded-none",
1457
+ sizes: editorialSizes
1458
+ }
1459
+ },
1460
+ accent: {
1461
+ kind: "derive",
1462
+ from: "primary",
1463
+ overrides: { effects: { base: [{
915
1464
  effectId: "border-bottom-grow",
916
1465
  options: {
917
1466
  height: 2,
918
- colorToken: "text",
919
- origin: "left"
920
- }
921
- }] }
922
- },
923
- {
924
- id: "secondary",
925
- name: "Secondary",
926
- enabled: true,
927
- priority: 2,
928
- background: { type: "transparent" },
929
- textColorToken: "mutedText",
930
- borderRadius: "rounded-none",
931
- sizes: {
932
- sm: { padding: "0.25rem 0" },
933
- md: { padding: "0.5rem 0" },
934
- lg: { padding: "0.625rem 0" },
935
- xl: { padding: "0.75rem 0" }
936
- },
937
- effects: { base: [{
938
- effectId: "border-bottom-grow",
939
- options: {
940
- height: 1,
941
- colorToken: "mutedText",
942
- origin: "left"
943
- }
944
- }] }
945
- },
946
- {
947
- id: "outline",
948
- name: "Outline",
949
- enabled: true,
950
- priority: 3,
951
- background: { type: "transparent" },
952
- textColorToken: "accent",
953
- borderRadius: "rounded-none",
954
- sizes: {
955
- sm: { padding: "0.25rem 0" },
956
- md: { padding: "0.5rem 0" },
957
- lg: { padding: "0.625rem 0" },
958
- xl: { padding: "0.75rem 0" }
959
- },
960
- effects: { base: [{
961
- effectId: "border-bottom-grow",
962
- options: {
963
- height: 1,
964
1467
  colorToken: "accent",
965
1468
  origin: "left"
966
1469
  }
967
- }] }
968
- },
969
- {
970
- id: "ghost",
971
- name: "Ghost",
972
- enabled: true,
973
- priority: 3,
974
- background: { type: "transparent" },
975
- textColorToken: "mutedText",
976
- borderRadius: "rounded-none",
977
- sizes: {
978
- sm: { padding: "0.25rem 0" },
979
- md: { padding: "0.5rem 0" },
980
- lg: { padding: "0.625rem 0" },
981
- xl: { padding: "0.75rem 0" }
982
- },
983
- effects: { hover: [{
984
- effectId: "opacity-reduce",
985
- options: { reduction: -20 }
986
- }] }
1470
+ }] } }
987
1471
  }
988
- ]
1472
+ }
989
1473
  }
990
1474
  });
991
- //#endregion
992
- //#region ../theme-core/src/buttons/personalities/flat-ink.ts
993
- /**
994
- * Flat Ink — a solid ink primary, a hairline ghost secondary, and a single
995
- * amber accent climax, all completely flat (no drop shadow) with a modest
996
- * radius. Reads as grounded, editorial and clinician-precise: the Fulcrum
997
- * physiotherapy voice. The primary shifts to the secondary (moss) on hover and
998
- * every variant lifts 2px; the amber accent is meant to be used sparingly as
999
- * the page's one conversion climax.
1000
- */
1001
- const flatInk = defineButtonPersonality({
1002
- id: "flat-ink",
1003
- name: "Flat Ink",
1004
- description: "Flat solid-ink primary, hairline ghost secondary, and a single amber accent climax — modest radius, no shadow.",
1475
+ const pebbleRecipe = defineStaticButtonStyleRecipe({
1476
+ id: "pebble",
1477
+ accessibilityLabel: "Generously padded pill buttons",
1005
1478
  tags: {
1006
1479
  tone: "classic",
1007
1480
  energy: "calm",
1008
- motion: "subtle",
1009
- era: "editorial"
1481
+ motion: "standard",
1482
+ era: "organic"
1010
1483
  },
1011
- buttonSystem: {
1484
+ system: {
1012
1485
  global: {
1013
- cornerStyle: "rounded",
1486
+ cornerStyle: "pill",
1014
1487
  textTransform: "none",
1015
- fontWeight: 600,
1016
- borderWidth: 1,
1017
- typography: "body",
1018
- letterSpacing: "tight",
1019
- paddingPreset: "default",
1020
- hoverTransform: "lift",
1488
+ fontWeight: 500,
1489
+ borderWidth: 2,
1490
+ hoverTransform: "none",
1021
1491
  hoverColor: "none"
1022
1492
  },
1023
1493
  sizes: {
1024
1494
  sm: {
1025
- padding: "0.625rem 1.125rem",
1495
+ padding: "0.625rem 1.75rem",
1026
1496
  fontSize: "text-sm"
1027
1497
  },
1028
- md: { padding: "0.8125rem 1.375rem" },
1498
+ md: { padding: "0.875rem 2.25rem" },
1029
1499
  lg: {
1030
- padding: "0.9375rem 1.625rem",
1500
+ padding: "1.125rem 2.75rem",
1031
1501
  fontSize: "text-lg"
1032
1502
  },
1033
1503
  xl: {
1034
- padding: "1.0625rem 2rem",
1504
+ padding: "1.5rem 3.5rem",
1035
1505
  fontSize: "text-xl"
1036
1506
  }
1037
1507
  },
1038
- variants: [
1039
- {
1040
- id: "primary",
1041
- name: "Primary",
1042
- enabled: true,
1043
- priority: 1,
1044
- background: {
1045
- type: "solid",
1046
- colorToken: "primary"
1047
- },
1048
- textColorToken: "primaryForeground",
1049
- borderRadius: "rounded-lg",
1050
- affordance: {
1051
- iconId: "ArrowRight",
1052
- colorToken: "accent"
1053
- },
1054
- effects: { hover: [{
1055
- effectId: "lift",
1056
- options: { translateY: "-2px" }
1057
- }, {
1058
- effectId: "background-on-hover",
1059
- options: { colorToken: "secondary" }
1060
- }] }
1061
- },
1062
- {
1063
- id: "secondary",
1064
- name: "Secondary",
1065
- enabled: true,
1066
- priority: 2,
1067
- background: { type: "transparent" },
1068
- textColorToken: "primary",
1069
- borderRadius: "rounded-lg",
1070
- border: {
1071
- widthClass: "border",
1072
- colorToken: "border"
1073
- },
1074
- effects: { hover: [{
1075
- effectId: "lift",
1076
- options: { translateY: "-2px" }
1077
- }, {
1078
- effectId: "background-on-hover",
1079
- options: { colorToken: "surfaceAlt" }
1080
- }] }
1081
- },
1082
- {
1083
- id: "accent",
1084
- name: "Accent",
1085
- enabled: true,
1086
- priority: 3,
1087
- background: {
1508
+ roles: {
1509
+ primary: {
1510
+ kind: "complete",
1511
+ appearance: {
1512
+ background: {
1513
+ type: "solid",
1514
+ colorToken: "primary"
1515
+ },
1516
+ borderRadius: "rounded-full",
1517
+ effects: { hover: [{
1518
+ effectId: "darken-background",
1519
+ options: { amount: 100 }
1520
+ }] }
1521
+ }
1522
+ },
1523
+ secondary: {
1524
+ kind: "complete",
1525
+ appearance: {
1526
+ background: {
1527
+ type: "surface",
1528
+ role: "link"
1529
+ },
1530
+ borderRadius: "rounded-full",
1531
+ border: { widthClass: "border-2" },
1532
+ effects: { hover: [{
1533
+ effectId: "background-on-hover",
1534
+ options: { colorToken: "accent" }
1535
+ }] }
1536
+ }
1537
+ },
1538
+ outline: {
1539
+ kind: "complete",
1540
+ appearance: {
1541
+ background: {
1542
+ type: "surface",
1543
+ role: "link"
1544
+ },
1545
+ borderRadius: "rounded-full",
1546
+ border: { widthClass: "border" },
1547
+ effects: { hover: [{
1548
+ effectId: "background-on-hover",
1549
+ options: { colorToken: "surface" }
1550
+ }] }
1551
+ }
1552
+ },
1553
+ ghost: {
1554
+ kind: "complete",
1555
+ appearance: {
1556
+ background: {
1557
+ type: "surface",
1558
+ role: "link"
1559
+ },
1560
+ borderRadius: "rounded-full",
1561
+ sizes: {
1562
+ sm: {
1563
+ padding: "0.375rem 0.875rem",
1564
+ fontSize: "text-sm"
1565
+ },
1566
+ md: { padding: "0.5rem 1rem" },
1567
+ lg: {
1568
+ padding: "0.625rem 1.25rem",
1569
+ fontSize: "text-lg"
1570
+ },
1571
+ xl: {
1572
+ padding: "0.75rem 1.5rem",
1573
+ fontSize: "text-xl"
1574
+ }
1575
+ }
1576
+ }
1577
+ },
1578
+ accent: {
1579
+ kind: "derive",
1580
+ from: "primary",
1581
+ overrides: { background: {
1088
1582
  type: "solid",
1089
1583
  colorToken: "accent"
1090
- },
1091
- textColorToken: "accentForeground",
1092
- borderRadius: "rounded-lg",
1093
- affordance: {
1094
- iconId: "ArrowRight",
1095
- colorToken: "accentForeground"
1096
- },
1097
- effects: { hover: [{
1098
- effectId: "lift",
1099
- options: { translateY: "-2px" }
1100
- }] }
1584
+ } }
1101
1585
  }
1102
- ]
1586
+ }
1103
1587
  }
1104
1588
  });
1105
- //#endregion
1106
- //#region ../theme-core/src/buttons/personalities/ink-stamp.ts
1107
- /**
1108
- * Ink Stamp — solid earthy fills with a bordered, hand-stamped block-print
1109
- * feel. Reads as bold and handmade; suits expressive craft brands.
1110
- */
1111
- const inkStamp = defineButtonPersonality({
1112
- id: "ink-stamp",
1113
- name: "Ink Stamp",
1114
- description: "Hand-stamped block-print buttons with a slight lift on hover.",
1589
+ const brushedWashRecipe = defineStaticButtonStyleRecipe({
1590
+ id: "brushed-wash",
1591
+ accessibilityLabel: "Generously padded gradient buttons with soft shadows",
1115
1592
  tags: {
1116
- tone: "bold",
1593
+ tone: "classic",
1117
1594
  energy: "vibrant",
1118
1595
  motion: "standard",
1119
1596
  era: "organic"
1120
1597
  },
1121
- buttonSystem: {
1598
+ system: {
1122
1599
  global: {
1123
1600
  cornerStyle: "rounded",
1124
- textTransform: "uppercase",
1125
- fontWeight: 600,
1601
+ shadow: "low",
1602
+ textTransform: "none",
1603
+ fontWeight: 500,
1126
1604
  borderWidth: 1,
1127
1605
  hoverTransform: "none",
1128
- hoverColor: "none",
1129
- letterSpacing: "loose"
1606
+ hoverColor: "none"
1130
1607
  },
1131
1608
  sizes: {
1132
1609
  sm: {
1133
- padding: "0.5rem 1.25rem",
1134
- fontSize: "text-xs"
1135
- },
1136
- md: {
1137
- padding: "0.75rem 1.75rem",
1610
+ padding: "0.75rem 2rem",
1138
1611
  fontSize: "text-sm"
1139
1612
  },
1613
+ md: { padding: "1rem 2.5rem" },
1140
1614
  lg: {
1141
- padding: "0.875rem 2.25rem",
1142
- fontSize: "text-base"
1615
+ padding: "1.25rem 3rem",
1616
+ fontSize: "text-lg"
1143
1617
  },
1144
1618
  xl: {
1145
- padding: "1.125rem 2.75rem",
1146
- fontSize: "text-lg"
1619
+ padding: "1.625rem 3.75rem",
1620
+ fontSize: "text-xl"
1147
1621
  }
1148
1622
  },
1149
- variants: [
1150
- {
1151
- id: "primary",
1152
- name: "Primary",
1153
- enabled: true,
1154
- priority: 1,
1155
- background: {
1156
- type: "solid",
1157
- colorToken: "primary"
1158
- },
1159
- textColorToken: "primaryForeground",
1160
- borderRadius: "rounded-md",
1161
- effects: {
1162
- hover: [{
1163
- effectId: "drop-shadow",
1164
- options: { intensity: "medium" }
1165
- }, {
1166
- effectId: "scale-up",
1167
- options: { scale: "1.02" }
1168
- }],
1169
- active: [{
1170
- effectId: "scale-down",
1171
- options: { scale: "0.98" }
1172
- }]
1623
+ roles: {
1624
+ primary: {
1625
+ kind: "complete",
1626
+ appearance: {
1627
+ background: {
1628
+ type: "gradient",
1629
+ stops: ["primary", "accent"],
1630
+ direction: "to-r",
1631
+ foregroundToken: "primaryForeground"
1632
+ },
1633
+ borderRadius: "rounded-lg",
1634
+ shadow: {
1635
+ elevation: "low",
1636
+ softness: "soft",
1637
+ position: "bottom"
1638
+ }
1173
1639
  }
1174
1640
  },
1175
- {
1176
- id: "secondary",
1177
- name: "Secondary",
1178
- enabled: true,
1179
- priority: 2,
1180
- background: { type: "transparent" },
1181
- textColorToken: "primary",
1182
- borderRadius: "rounded-md",
1183
- border: {
1184
- widthClass: "border-2",
1185
- colorToken: "primary"
1186
- },
1187
- effects: { hover: [{
1188
- effectId: "background-on-hover",
1189
- options: { colorToken: "surface" }
1190
- }] }
1191
- },
1192
- {
1193
- id: "outline",
1194
- name: "Outline",
1195
- enabled: true,
1196
- priority: 3,
1197
- background: { type: "transparent" },
1198
- textColorToken: "text",
1199
- borderRadius: "rounded-md",
1200
- border: {
1201
- widthClass: "border-2",
1202
- colorToken: "border"
1203
- },
1204
- effects: { hover: [{
1205
- effectId: "background-on-hover",
1206
- options: { colorToken: "surface" }
1207
- }] }
1208
- },
1209
- {
1210
- id: "ghost",
1211
- name: "Ghost",
1212
- enabled: true,
1213
- priority: 3,
1214
- background: { type: "transparent" },
1215
- textColorToken: "accent",
1216
- borderRadius: "rounded-none",
1217
- sizes: {
1218
- sm: {
1219
- padding: "0.375rem 0",
1220
- fontSize: "text-xs"
1641
+ secondary: {
1642
+ kind: "complete",
1643
+ appearance: {
1644
+ background: {
1645
+ type: "gradient",
1646
+ stops: ["secondary", "accent"],
1647
+ direction: "to-br",
1648
+ foregroundToken: "primaryForeground"
1221
1649
  },
1222
- md: {
1223
- padding: "0.5rem 0",
1224
- fontSize: "text-sm"
1225
- },
1226
- lg: {
1227
- padding: "0.625rem 0",
1228
- fontSize: "text-base"
1229
- },
1230
- xl: {
1231
- padding: "0.75rem 0",
1232
- fontSize: "text-lg"
1233
- }
1234
- },
1235
- effects: { base: [{
1236
- effectId: "border-bottom-grow",
1237
- options: {
1238
- height: 1,
1239
- colorToken: "accent",
1240
- origin: "left"
1650
+ borderRadius: "rounded-lg",
1651
+ shadow: {
1652
+ elevation: "low",
1653
+ softness: "soft",
1654
+ position: "bottom"
1241
1655
  }
1242
- }] }
1243
- }
1244
- ]
1245
- }
1246
- });
1247
- //#endregion
1248
- //#region ../theme-core/src/buttons/personalities/joy-stamp.ts
1249
- /**
1250
- * Joy Stamp — neo-brutalist pills with a hard, brand-coloured offset shadow
1251
- * that collapses as the button presses into it on hover. Authored for the
1252
- * Original Joy site style: a cream "stamp" shadow under the solid primary, and
1253
- * a brown shadow under the cream outline. Reads as bold, warm, and handmade.
1254
- *
1255
- * The coloured offset shadow relies on the per-variant `shadow.colorToken`
1256
- * extension; the press is the shared `press-down` effect, which matches its
1257
- * translate to each variant's own shadow offset.
1258
- */
1259
- const joyStamp = defineButtonPersonality({
1260
- id: "joy-stamp",
1261
- name: "Joy Stamp",
1262
- description: "Pill buttons with a hard, brand-coloured offset shadow that presses in on hover.",
1263
- tags: {
1264
- tone: "bold",
1265
- energy: "vibrant",
1266
- motion: "expressive",
1267
- era: "organic"
1268
- },
1269
- buttonSystem: {
1270
- global: {
1271
- cornerStyle: "pill",
1272
- shadow: "high",
1273
- textTransform: "none",
1274
- typography: "heading",
1275
- fontWeight: 700,
1276
- fontSize: "text-lg",
1277
- borderWidth: 2,
1278
- hoverTransform: "none",
1279
- hoverColor: "none"
1280
- },
1281
- sizes: {
1282
- sm: {
1283
- padding: "0.625rem 1.25rem",
1284
- fontSize: "text-base"
1656
+ }
1285
1657
  },
1286
- md: {
1287
- padding: "0.875rem 1.75rem",
1288
- fontSize: "text-lg"
1658
+ outline: {
1659
+ kind: "complete",
1660
+ appearance: {
1661
+ background: {
1662
+ type: "surface",
1663
+ role: "link"
1664
+ },
1665
+ borderRadius: "rounded-lg",
1666
+ border: { widthClass: "border" },
1667
+ effects: { hover: [{
1668
+ effectId: "background-on-hover",
1669
+ options: { colorToken: "surface" }
1670
+ }] }
1671
+ }
1289
1672
  },
1290
- lg: {
1291
- padding: "1.125rem 2.25rem",
1292
- fontSize: "text-xl"
1673
+ ghost: {
1674
+ kind: "complete",
1675
+ appearance: {
1676
+ background: {
1677
+ type: "surface",
1678
+ role: "link"
1679
+ },
1680
+ borderRadius: "rounded-lg",
1681
+ effects: { hover: [{
1682
+ effectId: "background-on-hover",
1683
+ options: { colorToken: "surface" }
1684
+ }] }
1685
+ }
1293
1686
  },
1294
- xl: {
1295
- padding: "1.25rem 2.75rem",
1296
- fontSize: "text-2xl"
1687
+ accent: {
1688
+ kind: "derive",
1689
+ from: "primary",
1690
+ overrides: { background: {
1691
+ type: "solid",
1692
+ colorToken: "accent"
1693
+ } }
1297
1694
  }
1298
- },
1299
- variants: [{
1300
- id: "primary",
1301
- name: "Primary",
1302
- enabled: true,
1303
- priority: 1,
1304
- background: {
1305
- type: "solid",
1306
- colorToken: "primary"
1307
- },
1308
- textColorToken: "primaryForeground",
1309
- borderRadius: "rounded-full",
1310
- shadow: {
1311
- elevation: "high",
1312
- softness: "hard",
1313
- position: "bottom-right",
1314
- colorToken: "text"
1315
- },
1316
- effects: { hover: [{ effectId: "press-down" }] }
1317
- }, {
1318
- id: "secondary",
1319
- name: "Secondary",
1320
- enabled: true,
1321
- priority: 2,
1322
- background: { type: "transparent" },
1323
- textColorToken: "text",
1324
- borderRadius: "rounded-full",
1325
- border: {
1326
- widthClass: "border-2",
1327
- colorToken: "text"
1328
- },
1329
- shadow: {
1330
- elevation: "high",
1331
- softness: "hard",
1332
- position: "bottom-right",
1333
- colorToken: "secondary"
1334
- },
1335
- effects: { hover: [{ effectId: "press-down" }] }
1336
- }]
1695
+ }
1337
1696
  }
1338
1697
  });
1339
- //#endregion
1340
- //#region ../theme-core/src/buttons/personalities/ornate-ritual.ts
1341
- /**
1342
- * Ornate Ritual — framed, ceremonial buttons with jewel-toned fills and
1343
- * deliberate spacing. Designed for music, ceremony, and soulful event sites.
1344
- */
1345
- const ornateRitual = defineButtonPersonality({
1346
- id: "ornate-ritual",
1347
- name: "Ornate Ritual",
1348
- description: "Ceremonial framed buttons with jewel-toned fills and quiet color-change hover states.",
1698
+ const inkStampRecipe = defineStaticButtonStyleRecipe({
1699
+ id: "ink-stamp",
1700
+ accessibilityLabel: "Uppercase block-print buttons with a playful hover",
1349
1701
  tags: {
1350
- tone: "classic",
1702
+ tone: "bold",
1351
1703
  energy: "vibrant",
1352
- motion: "subtle",
1704
+ motion: "standard",
1353
1705
  era: "organic"
1354
1706
  },
1355
- buttonSystem: {
1707
+ system: {
1356
1708
  global: {
1357
1709
  cornerStyle: "rounded",
1358
1710
  textTransform: "uppercase",
@@ -1364,378 +1716,256 @@ const ornateRitual = defineButtonPersonality({
1364
1716
  },
1365
1717
  sizes: {
1366
1718
  sm: {
1367
- padding: "0.5625rem 1.25rem",
1719
+ padding: "0.5rem 1.25rem",
1368
1720
  fontSize: "text-xs"
1369
1721
  },
1370
1722
  md: {
1371
1723
  padding: "0.75rem 1.75rem",
1372
- fontSize: "text-xs"
1724
+ fontSize: "text-sm"
1373
1725
  },
1374
1726
  lg: {
1375
1727
  padding: "0.875rem 2.25rem",
1376
- fontSize: "text-sm"
1728
+ fontSize: "text-base"
1377
1729
  },
1378
1730
  xl: {
1379
- padding: "1rem 2.75rem",
1380
- fontSize: "text-base"
1731
+ padding: "1.125rem 2.75rem",
1732
+ fontSize: "text-lg"
1381
1733
  }
1382
1734
  },
1383
- variants: [
1384
- {
1385
- id: "primary",
1386
- name: "Primary",
1387
- enabled: true,
1388
- priority: 1,
1389
- background: {
1390
- type: "solid",
1391
- colorToken: "primary"
1392
- },
1393
- textColorToken: "primaryForeground",
1394
- borderRadius: "rounded-md",
1395
- border: {
1396
- widthClass: "border",
1397
- colorToken: "primary"
1398
- },
1399
- effects: {
1400
- hover: [{
1735
+ roles: {
1736
+ primary: {
1737
+ kind: "complete",
1738
+ appearance: {
1739
+ background: {
1740
+ type: "solid",
1741
+ colorToken: "primary"
1742
+ },
1743
+ borderRadius: "rounded-md",
1744
+ effects: {
1745
+ hover: [{
1746
+ effectId: "drop-shadow",
1747
+ options: { intensity: "medium" }
1748
+ }, {
1749
+ effectId: "scale-up",
1750
+ options: { scale: "1.02" }
1751
+ }],
1752
+ active: [{
1753
+ effectId: "scale-down",
1754
+ options: { scale: "0.98" }
1755
+ }]
1756
+ }
1757
+ }
1758
+ },
1759
+ secondary: {
1760
+ kind: "complete",
1761
+ appearance: {
1762
+ background: {
1763
+ type: "surface",
1764
+ role: "link"
1765
+ },
1766
+ borderRadius: "rounded-md",
1767
+ border: { widthClass: "border-2" },
1768
+ effects: { hover: [{
1401
1769
  effectId: "background-on-hover",
1402
- options: { colorToken: "primary-100" }
1403
- }],
1404
- active: [{
1405
- effectId: "scale-down",
1406
- options: { scale: "0.98" }
1407
- }]
1770
+ options: { colorToken: "surface" }
1771
+ }] }
1408
1772
  }
1409
1773
  },
1410
- {
1411
- id: "secondary",
1412
- name: "Secondary",
1413
- enabled: true,
1414
- priority: 2,
1415
- background: {
1416
- type: "solid",
1417
- colorToken: "secondary"
1418
- },
1419
- textColorToken: "primaryForeground",
1420
- borderRadius: "rounded-md",
1421
- border: {
1422
- widthClass: "border",
1423
- colorToken: "primary"
1424
- },
1425
- effects: { hover: [{
1426
- effectId: "background-on-hover",
1427
- options: { colorToken: "surface" }
1428
- }] }
1429
- },
1430
- {
1431
- id: "outline",
1432
- name: "Outline",
1433
- enabled: true,
1434
- priority: 3,
1435
- background: { type: "transparent" },
1436
- textColorToken: "primary",
1437
- borderRadius: "rounded-md",
1438
- border: {
1439
- widthClass: "border",
1440
- colorToken: "primary"
1441
- },
1442
- effects: { hover: [{
1443
- effectId: "background-on-hover",
1444
- options: { colorToken: "muted" }
1445
- }] }
1446
- },
1447
- {
1448
- id: "ghost",
1449
- name: "Ghost",
1450
- enabled: true,
1451
- priority: 3,
1452
- background: { type: "transparent" },
1453
- textColorToken: "accent",
1454
- borderRadius: "rounded-none",
1455
- sizes: {
1456
- sm: {
1457
- padding: "0.375rem 0",
1458
- fontSize: "text-xs"
1774
+ outline: {
1775
+ kind: "complete",
1776
+ appearance: {
1777
+ background: {
1778
+ type: "surface",
1779
+ role: "link"
1459
1780
  },
1460
- md: {
1461
- padding: "0.5rem 0",
1462
- fontSize: "text-sm"
1781
+ borderRadius: "rounded-md",
1782
+ border: { widthClass: "border-2" },
1783
+ effects: { hover: [{
1784
+ effectId: "background-on-hover",
1785
+ options: { colorToken: "surface" }
1786
+ }] }
1787
+ }
1788
+ },
1789
+ ghost: {
1790
+ kind: "complete",
1791
+ appearance: {
1792
+ background: {
1793
+ type: "surface",
1794
+ role: "link"
1463
1795
  },
1464
- lg: {
1465
- padding: "0.625rem 0",
1466
- fontSize: "text-base"
1796
+ borderRadius: "rounded-none",
1797
+ sizes: {
1798
+ sm: {
1799
+ padding: "0.375rem 0",
1800
+ fontSize: "text-xs"
1801
+ },
1802
+ md: {
1803
+ padding: "0.5rem 0",
1804
+ fontSize: "text-sm"
1805
+ },
1806
+ lg: {
1807
+ padding: "0.625rem 0",
1808
+ fontSize: "text-base"
1809
+ },
1810
+ xl: {
1811
+ padding: "0.75rem 0",
1812
+ fontSize: "text-lg"
1813
+ }
1467
1814
  },
1468
- xl: {
1469
- padding: "0.75rem 0",
1470
- fontSize: "text-lg"
1471
- }
1472
- },
1473
- effects: { base: [{
1474
- effectId: "border-bottom-grow",
1475
- options: {
1476
- height: 1,
1477
- colorToken: "accent",
1478
- origin: "left"
1479
- }
1480
- }] }
1481
- }
1482
- ]
1483
- }
1484
- });
1485
- //#endregion
1486
- //#region ../theme-core/src/buttons/personalities/pebble.ts
1487
- /**
1488
- * Pebble — large pill primaries with generous padding. Reads as spa-luxurious
1489
- * and natural; pairs well with wellness/yoga/dance brands.
1490
- */
1491
- const pebble = defineButtonPersonality({
1492
- id: "pebble",
1493
- name: "Pebble",
1494
- description: "Generous pill buttons with a quiet colour-softening hover.",
1495
- tags: {
1496
- tone: "classic",
1497
- energy: "calm",
1498
- motion: "standard",
1499
- era: "organic"
1500
- },
1501
- buttonSystem: {
1502
- global: {
1503
- cornerStyle: "pill",
1504
- textTransform: "none",
1505
- fontWeight: 500,
1506
- borderWidth: 2,
1507
- hoverTransform: "none",
1508
- hoverColor: "none"
1509
- },
1510
- sizes: {
1511
- sm: {
1512
- padding: "0.625rem 1.75rem",
1513
- fontSize: "text-sm"
1514
- },
1515
- md: { padding: "0.875rem 2.25rem" },
1516
- lg: {
1517
- padding: "1.125rem 2.75rem",
1518
- fontSize: "text-lg"
1815
+ effects: { base: [{
1816
+ effectId: "border-bottom-grow",
1817
+ options: {
1818
+ height: 1,
1819
+ colorToken: "accent",
1820
+ origin: "left"
1821
+ }
1822
+ }] }
1823
+ }
1519
1824
  },
1520
- xl: {
1521
- padding: "1.5rem 3.5rem",
1522
- fontSize: "text-xl"
1523
- }
1524
- },
1525
- variants: [
1526
- {
1527
- id: "primary",
1528
- name: "Primary",
1529
- enabled: true,
1530
- priority: 1,
1531
- background: {
1825
+ accent: {
1826
+ kind: "derive",
1827
+ from: "primary",
1828
+ overrides: { background: {
1532
1829
  type: "solid",
1533
- colorToken: "primary"
1534
- },
1535
- textColorToken: "primaryForeground",
1536
- borderRadius: "rounded-full",
1537
- effects: { hover: [{
1538
- effectId: "background-on-hover-alpha",
1539
- options: {
1540
- colorToken: "primary",
1541
- opacity: 88
1542
- }
1543
- }] }
1544
- },
1545
- {
1546
- id: "secondary",
1547
- name: "Secondary",
1548
- enabled: true,
1549
- priority: 2,
1550
- background: { type: "transparent" },
1551
- textColorToken: "primary",
1552
- borderRadius: "rounded-full",
1553
- border: {
1554
- widthClass: "border-2",
1555
1830
  colorToken: "accent"
1556
- },
1557
- effects: { hover: [{
1558
- effectId: "background-on-hover",
1559
- options: { colorToken: "accent" }
1560
- }] }
1561
- },
1562
- {
1563
- id: "outline",
1564
- name: "Outline",
1565
- enabled: true,
1566
- priority: 3,
1567
- background: { type: "transparent" },
1568
- textColorToken: "text",
1569
- borderRadius: "rounded-full",
1570
- border: {
1571
- widthClass: "border",
1572
- colorToken: "border"
1573
- },
1574
- effects: { hover: [{
1575
- effectId: "background-on-hover",
1576
- options: { colorToken: "surface" }
1577
- }] }
1578
- },
1579
- {
1580
- id: "ghost",
1581
- name: "Ghost",
1582
- enabled: true,
1583
- priority: 3,
1584
- background: { type: "transparent" },
1585
- textColorToken: "primary",
1586
- borderRadius: "rounded-full",
1587
- sizes: {
1588
- sm: {
1589
- padding: "0.375rem 0.875rem",
1590
- fontSize: "text-sm"
1591
- },
1592
- md: { padding: "0.5rem 1rem" },
1593
- lg: {
1594
- padding: "0.625rem 1.25rem",
1595
- fontSize: "text-lg"
1596
- },
1597
- xl: {
1598
- padding: "0.75rem 1.5rem",
1599
- fontSize: "text-xl"
1600
- }
1601
- },
1602
- effects: { hover: [{
1603
- effectId: "opacity-reduce",
1604
- options: { reduction: 30 }
1605
- }] }
1831
+ } }
1606
1832
  }
1607
- ]
1833
+ }
1608
1834
  }
1609
1835
  });
1610
- //#endregion
1611
- //#region ../theme-core/src/buttons/personalities/quiet-arrow.ts
1612
- /**
1613
- * Quiet Arrow — wide, flat editorial buttons for grounded service businesses.
1614
- * Primary and secondary keep stable semantic colours; surrounding surfaces are
1615
- * responsible for contrast rather than reversing the button roles.
1616
- */
1617
- const quietArrow = defineButtonPersonality({
1618
- id: "quiet-arrow",
1619
- name: "Quiet Arrow",
1620
- description: "Wide, flat arrow buttons with a solid primary and a primary-colour outlined secondary.",
1836
+ const flatInkRecipe = defineStaticButtonStyleRecipe({
1837
+ id: "flat-ink",
1838
+ accessibilityLabel: "Flat rounded buttons with arrow affordances",
1621
1839
  tags: {
1622
1840
  tone: "classic",
1623
1841
  energy: "calm",
1624
1842
  motion: "subtle",
1625
1843
  era: "editorial"
1626
1844
  },
1627
- buttonSystem: {
1845
+ system: {
1628
1846
  global: {
1629
1847
  cornerStyle: "rounded",
1630
- textTransform: "uppercase",
1631
- fontWeight: 500,
1848
+ textTransform: "none",
1849
+ fontWeight: 600,
1632
1850
  borderWidth: 1,
1633
1851
  typography: "body",
1634
- fontSize: "text-sm",
1635
- letterSpacing: "loose",
1636
- hoverTransform: "none",
1852
+ letterSpacing: "tight",
1853
+ paddingPreset: "default",
1854
+ hoverTransform: "lift",
1637
1855
  hoverColor: "none"
1638
1856
  },
1639
1857
  sizes: {
1640
1858
  sm: {
1641
- padding: "0.625rem 1.25rem",
1642
- fontSize: "text-xs"
1643
- },
1644
- md: {
1645
- padding: "0.8125rem 1.75rem",
1859
+ padding: "0.625rem 1.125rem",
1646
1860
  fontSize: "text-sm"
1647
1861
  },
1862
+ md: { padding: "0.8125rem 1.375rem" },
1648
1863
  lg: {
1649
- padding: "0.9375rem 2.125rem",
1650
- fontSize: "text-sm"
1864
+ padding: "0.9375rem 1.625rem",
1865
+ fontSize: "text-lg"
1651
1866
  },
1652
1867
  xl: {
1653
- padding: "1.0625rem 2.5rem",
1654
- fontSize: "text-base"
1868
+ padding: "1.0625rem 2rem",
1869
+ fontSize: "text-xl"
1655
1870
  }
1656
1871
  },
1657
- variants: [
1658
- {
1659
- id: "primary",
1660
- name: "Primary",
1661
- enabled: true,
1662
- priority: 1,
1663
- background: {
1664
- type: "solid",
1665
- colorToken: "primary"
1666
- },
1667
- textColorToken: "primaryForeground",
1668
- borderRadius: "rounded-xl",
1669
- affordance: { iconId: "ArrowRight" },
1670
- effects: { hover: [{
1671
- effectId: "background-on-hover-alpha",
1672
- options: {
1673
- colorToken: "primary",
1674
- opacity: 90
1675
- }
1676
- }] }
1677
- },
1678
- {
1679
- id: "secondary",
1680
- name: "Secondary",
1681
- enabled: true,
1682
- priority: 2,
1683
- background: { type: "transparent" },
1684
- textColorToken: "primary",
1685
- borderRadius: "rounded-xl",
1686
- border: {
1687
- widthClass: "border",
1688
- colorToken: "primary"
1689
- },
1690
- affordance: { iconId: "ArrowRight" },
1691
- effects: { hover: [{
1692
- effectId: "background-on-hover",
1693
- options: { colorToken: "surfaceAlt" }
1694
- }] }
1695
- },
1696
- {
1697
- id: "outline",
1698
- name: "Outline",
1699
- enabled: true,
1700
- priority: 3,
1701
- background: { type: "transparent" },
1702
- textColorToken: "primary",
1703
- borderRadius: "rounded-xl",
1704
- border: {
1705
- widthClass: "border",
1706
- colorToken: "primary"
1872
+ roles: {
1873
+ primary: {
1874
+ kind: "complete",
1875
+ appearance: {
1876
+ background: {
1877
+ type: "solid",
1878
+ colorToken: "primary"
1879
+ },
1880
+ borderRadius: "rounded-lg",
1881
+ affordance: { iconId: "ArrowRight" },
1882
+ effects: { hover: [{
1883
+ effectId: "lift",
1884
+ options: { translateY: "-2px" }
1885
+ }, {
1886
+ effectId: "background-on-hover",
1887
+ options: { colorToken: "secondary" }
1888
+ }] }
1889
+ }
1890
+ },
1891
+ secondary: {
1892
+ kind: "complete",
1893
+ appearance: {
1894
+ background: {
1895
+ type: "surface",
1896
+ role: "link"
1897
+ },
1898
+ borderRadius: "rounded-lg",
1899
+ border: { widthClass: "border" },
1900
+ effects: { hover: [{
1901
+ effectId: "lift",
1902
+ options: { translateY: "-2px" }
1903
+ }, {
1904
+ effectId: "background-on-hover",
1905
+ options: { colorToken: "surfaceAlt" }
1906
+ }] }
1907
+ }
1908
+ },
1909
+ outline: {
1910
+ kind: "complete",
1911
+ appearance: {
1912
+ background: {
1913
+ type: "surface",
1914
+ role: "link"
1915
+ },
1916
+ borderRadius: "rounded-lg",
1917
+ border: { widthClass: "border" },
1918
+ effects: { hover: [{
1919
+ effectId: "lift",
1920
+ options: { translateY: "-2px" }
1921
+ }, {
1922
+ effectId: "background-on-hover",
1923
+ options: { colorToken: "surfaceAlt" }
1924
+ }] }
1925
+ }
1926
+ },
1927
+ ghost: {
1928
+ kind: "complete",
1929
+ appearance: {
1930
+ background: {
1931
+ type: "surface",
1932
+ role: "link"
1933
+ },
1934
+ borderRadius: "rounded-lg",
1935
+ effects: { hover: [{
1936
+ effectId: "lift",
1937
+ options: { translateY: "-2px" }
1938
+ }] }
1707
1939
  }
1708
1940
  },
1709
- {
1710
- id: "ghost",
1711
- name: "Ghost",
1712
- enabled: true,
1713
- priority: 3,
1714
- background: { type: "transparent" },
1715
- textColorToken: "primary",
1716
- borderRadius: "rounded-xl"
1941
+ accent: {
1942
+ kind: "complete",
1943
+ appearance: {
1944
+ background: {
1945
+ type: "solid",
1946
+ colorToken: "accent"
1947
+ },
1948
+ borderRadius: "rounded-lg",
1949
+ affordance: { iconId: "ArrowRight" },
1950
+ effects: { hover: [{
1951
+ effectId: "lift",
1952
+ options: { translateY: "-2px" }
1953
+ }] }
1954
+ }
1717
1955
  }
1718
- ]
1956
+ }
1719
1957
  }
1720
1958
  });
1721
- //#endregion
1722
- //#region ../theme-core/src/buttons/personalities/showtime-pill.ts
1723
- /**
1724
- * Showtime Pill — bold, spacious, fully rounded buttons with playful pop
1725
- * motion. Suits energetic schools, performers, festivals, and community brands
1726
- * that need calls to action to feel loud without becoming visually chaotic.
1727
- */
1728
- const showtimePill = defineButtonPersonality({
1959
+ const showtimePillRecipe = defineStaticButtonStyleRecipe({
1729
1960
  id: "showtime-pill",
1730
- name: "Showtime Pill",
1731
- description: "Bold pill buttons with uppercase labels, generous padding, and a playful pop.",
1961
+ accessibilityLabel: "Bold uppercase pill buttons with playful movement",
1732
1962
  tags: {
1733
1963
  tone: "bold",
1734
1964
  energy: "vibrant",
1735
1965
  motion: "expressive",
1736
1966
  era: "modern"
1737
1967
  },
1738
- buttonSystem: {
1968
+ system: {
1739
1969
  global: {
1740
1970
  cornerStyle: "pill",
1741
1971
  shadow: "low",
@@ -1766,263 +1996,380 @@ const showtimePill = defineButtonPersonality({
1766
1996
  fontSize: "1.125rem"
1767
1997
  }
1768
1998
  },
1769
- variants: [
1770
- {
1771
- id: "primary",
1772
- name: "Primary",
1773
- enabled: true,
1774
- priority: 1,
1775
- background: {
1776
- type: "solid",
1777
- colorToken: "primary"
1778
- },
1779
- textColorToken: "background",
1780
- borderRadius: "rounded-full",
1781
- effects: { hover: [{ effectId: "pop" }] }
1782
- },
1783
- {
1784
- id: "secondary",
1785
- name: "Secondary",
1786
- enabled: true,
1787
- priority: 2,
1788
- background: { type: "transparent" },
1789
- textColorToken: "primary",
1790
- borderRadius: "rounded-full",
1791
- border: {
1792
- widthClass: "border-2",
1793
- colorToken: "primary"
1794
- },
1795
- effects: { hover: [{ effectId: "pop" }] }
1796
- },
1797
- {
1798
- id: "hero",
1799
- name: "Hero",
1800
- enabled: true,
1801
- priority: 1,
1802
- background: {
1803
- type: "solid",
1804
- colorToken: "secondary"
1805
- },
1806
- textColorToken: "primary",
1807
- borderRadius: "rounded-full",
1808
- effects: { hover: [{ effectId: "pop" }] }
1809
- },
1810
- {
1811
- id: "header",
1812
- name: "Header",
1813
- enabled: true,
1814
- priority: 2,
1815
- background: {
1816
- type: "solid",
1817
- colorToken: "background"
1818
- },
1819
- textColorToken: "primary",
1820
- borderRadius: "rounded-full",
1821
- border: {
1822
- widthClass: "border-2",
1823
- colorToken: "primary"
1824
- },
1825
- effects: { hover: [{
1826
- effectId: "background-on-hover",
1827
- options: { colorToken: "surface" }
1828
- }] }
1829
- },
1830
- {
1831
- id: "outline",
1832
- name: "Outline",
1833
- enabled: true,
1834
- priority: 3,
1835
- background: { type: "transparent" },
1836
- textColorToken: "primary",
1837
- borderRadius: "rounded-full",
1838
- border: {
1839
- widthClass: "border-2",
1840
- colorToken: "primary"
1841
- },
1842
- effects: { hover: [{
1843
- effectId: "background-on-hover",
1844
- options: { colorToken: "background" }
1845
- }] }
1846
- },
1847
- {
1848
- id: "ghost",
1849
- name: "Ghost",
1850
- enabled: true,
1851
- priority: 3,
1852
- background: { type: "transparent" },
1853
- textColorToken: "primary",
1854
- borderRadius: "rounded-full",
1855
- effects: { hover: [{
1856
- effectId: "background-on-hover",
1857
- options: { colorToken: "surface" }
1858
- }] }
1999
+ roles: {
2000
+ primary: {
2001
+ kind: "complete",
2002
+ appearance: {
2003
+ background: {
2004
+ type: "solid",
2005
+ colorToken: "primary"
2006
+ },
2007
+ borderRadius: "rounded-full",
2008
+ effects: { hover: [{ effectId: "pop" }] }
2009
+ }
2010
+ },
2011
+ secondary: {
2012
+ kind: "complete",
2013
+ appearance: {
2014
+ background: {
2015
+ type: "surface",
2016
+ role: "link"
2017
+ },
2018
+ borderRadius: "rounded-full",
2019
+ border: { widthClass: "border-2" },
2020
+ effects: { hover: [{ effectId: "pop" }] }
2021
+ }
2022
+ },
2023
+ outline: {
2024
+ kind: "complete",
2025
+ appearance: {
2026
+ background: {
2027
+ type: "surface",
2028
+ role: "link"
2029
+ },
2030
+ borderRadius: "rounded-full",
2031
+ border: { widthClass: "border-2" },
2032
+ effects: { hover: [{
2033
+ effectId: "background-on-hover",
2034
+ options: { colorToken: "background" }
2035
+ }] }
2036
+ }
2037
+ },
2038
+ ghost: {
2039
+ kind: "complete",
2040
+ appearance: {
2041
+ background: {
2042
+ type: "surface",
2043
+ role: "link"
2044
+ },
2045
+ borderRadius: "rounded-full",
2046
+ effects: { hover: [{
2047
+ effectId: "background-on-hover",
2048
+ options: { colorToken: "surface" }
2049
+ }] }
2050
+ }
2051
+ },
2052
+ accent: {
2053
+ kind: "complete",
2054
+ appearance: {
2055
+ background: {
2056
+ type: "solid",
2057
+ colorToken: "secondary"
2058
+ },
2059
+ borderRadius: "rounded-full",
2060
+ effects: { hover: [{ effectId: "pop" }] }
2061
+ }
1859
2062
  }
1860
- ]
2063
+ }
1861
2064
  }
1862
2065
  });
1863
- //#endregion
1864
- //#region ../theme-core/src/buttons/personalities/soft-pill.ts
1865
- /**
1866
- * Soft Pill — rounded-full pill buttons with a hover lift. The default for
1867
- * Calm Studio and Modern Wellness; reads as quietly modern and welcoming.
1868
- */
1869
- const softPill = defineButtonPersonality({
1870
- id: "soft-pill",
1871
- name: "Soft Pill",
1872
- description: "Rounded pills with a gentle lift on hover. Quietly modern.",
2066
+ const joyStampRecipe = defineStaticButtonStyleRecipe({
2067
+ id: "joy-stamp",
2068
+ accessibilityLabel: "Bold pill buttons with a hard offset shadow",
1873
2069
  tags: {
1874
- tone: "classic",
1875
- energy: "calm",
1876
- motion: "subtle",
2070
+ tone: "bold",
2071
+ energy: "vibrant",
2072
+ motion: "expressive",
1877
2073
  era: "organic"
1878
2074
  },
1879
- buttonSystem: {
2075
+ system: {
1880
2076
  global: {
1881
2077
  cornerStyle: "pill",
1882
- shadow: "low",
2078
+ shadow: "high",
1883
2079
  textTransform: "none",
1884
- fontWeight: 500,
2080
+ typography: "heading",
2081
+ fontWeight: 700,
2082
+ fontSize: "text-lg",
1885
2083
  borderWidth: 2,
1886
- hoverTransform: "lift",
2084
+ hoverTransform: "none",
1887
2085
  hoverColor: "none"
1888
2086
  },
1889
- variants: [
1890
- {
1891
- id: "primary",
1892
- name: "Primary",
1893
- enabled: true,
1894
- priority: 1,
1895
- background: {
1896
- type: "solid",
1897
- colorToken: "primary"
1898
- },
1899
- textColorToken: "primaryForeground",
1900
- borderRadius: "rounded-full",
1901
- shadow: {
1902
- elevation: "low",
1903
- softness: "soft",
1904
- position: "bottom"
1905
- },
1906
- effects: {
1907
- hover: [{
1908
- effectId: "lift",
1909
- options: { translateY: "-1px" }
1910
- }],
1911
- active: [{
1912
- effectId: "scale-down",
1913
- options: { scale: "0.98" }
1914
- }]
2087
+ sizes: {
2088
+ sm: {
2089
+ padding: "0.625rem 1.25rem",
2090
+ fontSize: "text-base"
2091
+ },
2092
+ md: {
2093
+ padding: "0.875rem 1.75rem",
2094
+ fontSize: "text-lg"
2095
+ },
2096
+ lg: {
2097
+ padding: "1.125rem 2.25rem",
2098
+ fontSize: "text-xl"
2099
+ },
2100
+ xl: {
2101
+ padding: "1.25rem 2.75rem",
2102
+ fontSize: "text-2xl"
2103
+ }
2104
+ },
2105
+ roles: {
2106
+ primary: {
2107
+ kind: "complete",
2108
+ appearance: {
2109
+ background: {
2110
+ type: "solid",
2111
+ colorToken: "primary"
2112
+ },
2113
+ borderRadius: "rounded-full",
2114
+ shadow: {
2115
+ elevation: "high",
2116
+ softness: "hard",
2117
+ position: "bottom-right",
2118
+ colorToken: "text"
2119
+ },
2120
+ effects: { hover: [{ effectId: "press-down" }] }
2121
+ }
2122
+ },
2123
+ secondary: {
2124
+ kind: "complete",
2125
+ appearance: {
2126
+ background: {
2127
+ type: "surface",
2128
+ role: "link"
2129
+ },
2130
+ borderRadius: "rounded-full",
2131
+ border: { widthClass: "border-2" },
2132
+ shadow: {
2133
+ elevation: "high",
2134
+ softness: "hard",
2135
+ position: "bottom-right",
2136
+ colorToken: "secondary"
2137
+ },
2138
+ effects: { hover: [{ effectId: "press-down" }] }
2139
+ }
2140
+ },
2141
+ outline: {
2142
+ kind: "derive",
2143
+ from: "secondary"
2144
+ },
2145
+ ghost: {
2146
+ kind: "complete",
2147
+ appearance: {
2148
+ background: {
2149
+ type: "surface",
2150
+ role: "link"
2151
+ },
2152
+ borderRadius: "rounded-full",
2153
+ effects: { hover: [{ effectId: "press-down" }] }
1915
2154
  }
1916
2155
  },
1917
- {
1918
- id: "secondary",
1919
- name: "Secondary",
1920
- enabled: true,
1921
- priority: 2,
1922
- background: { type: "transparent" },
1923
- textColorToken: "primary",
1924
- borderRadius: "rounded-full",
1925
- border: {
1926
- widthClass: "border-2",
1927
- colorToken: "primary"
1928
- },
1929
- effects: { hover: [{
1930
- effectId: "background-on-hover",
1931
- options: { colorToken: "surface" }
1932
- }] }
1933
- },
1934
- {
1935
- id: "outline",
1936
- name: "Outline",
1937
- enabled: true,
1938
- priority: 3,
1939
- background: { type: "transparent" },
1940
- textColorToken: "text",
1941
- borderRadius: "rounded-full",
1942
- border: {
1943
- widthClass: "border",
1944
- colorToken: "border"
1945
- },
1946
- effects: { hover: [{
1947
- effectId: "background-on-hover",
1948
- options: { colorToken: "surface" }
1949
- }] }
1950
- },
1951
- {
1952
- id: "ghost",
1953
- name: "Ghost",
1954
- enabled: true,
1955
- priority: 3,
1956
- background: { type: "transparent" },
1957
- textColorToken: "text",
1958
- borderRadius: "rounded-full",
1959
- effects: { hover: [{
1960
- effectId: "background-on-hover",
1961
- options: { colorToken: "surface" }
1962
- }] }
2156
+ accent: {
2157
+ kind: "derive",
2158
+ from: "primary",
2159
+ overrides: { background: {
2160
+ type: "solid",
2161
+ colorToken: "accent"
2162
+ } }
1963
2163
  }
1964
- ]
2164
+ }
1965
2165
  }
1966
2166
  });
1967
- //#endregion
1968
- //#region ../theme-core/src/buttons/personalities/two-tone-pill.ts
1969
- const solidSecondary = {
1970
- id: "secondary",
1971
- name: "Secondary",
1972
- enabled: true,
1973
- priority: 2,
1974
- background: {
1975
- type: "solid",
1976
- colorToken: "secondary"
1977
- },
1978
- textColorToken: "onSecondary",
1979
- borderRadius: "rounded-full",
1980
- shadow: {
1981
- elevation: "none",
1982
- softness: null,
1983
- position: "bottom"
2167
+ const ornateRitualRecipe = defineStaticButtonStyleRecipe({
2168
+ id: "ornate-ritual",
2169
+ accessibilityLabel: "Uppercase framed buttons with restrained movement",
2170
+ tags: {
2171
+ tone: "classic",
2172
+ energy: "vibrant",
2173
+ motion: "subtle",
2174
+ era: "organic"
1984
2175
  },
1985
- effects: {
1986
- hover: [{
1987
- effectId: "background-on-hover-alpha",
1988
- options: {
1989
- colorToken: "secondary",
1990
- opacity: 88
2176
+ system: {
2177
+ global: {
2178
+ cornerStyle: "rounded",
2179
+ textTransform: "uppercase",
2180
+ fontWeight: 600,
2181
+ borderWidth: 1,
2182
+ hoverTransform: "none",
2183
+ hoverColor: "none",
2184
+ letterSpacing: "loose"
2185
+ },
2186
+ sizes: {
2187
+ sm: {
2188
+ padding: "0.5625rem 1.25rem",
2189
+ fontSize: "text-xs"
2190
+ },
2191
+ md: {
2192
+ padding: "0.75rem 1.75rem",
2193
+ fontSize: "text-xs"
2194
+ },
2195
+ lg: {
2196
+ padding: "0.875rem 2.25rem",
2197
+ fontSize: "text-sm"
2198
+ },
2199
+ xl: {
2200
+ padding: "1rem 2.75rem",
2201
+ fontSize: "text-base"
1991
2202
  }
1992
- }],
1993
- active: [{
1994
- effectId: "scale-down",
1995
- options: { scale: "0.98" }
1996
- }]
2203
+ },
2204
+ roles: {
2205
+ primary: {
2206
+ kind: "complete",
2207
+ appearance: {
2208
+ background: {
2209
+ type: "solid",
2210
+ colorToken: "primary"
2211
+ },
2212
+ borderRadius: "rounded-md",
2213
+ border: { widthClass: "border" },
2214
+ effects: {
2215
+ hover: [{
2216
+ effectId: "background-on-hover",
2217
+ options: { colorToken: "primary-100" }
2218
+ }],
2219
+ active: [{
2220
+ effectId: "scale-down",
2221
+ options: { scale: "0.98" }
2222
+ }]
2223
+ }
2224
+ }
2225
+ },
2226
+ secondary: {
2227
+ kind: "complete",
2228
+ appearance: {
2229
+ background: {
2230
+ type: "solid",
2231
+ colorToken: "secondary"
2232
+ },
2233
+ borderRadius: "rounded-md",
2234
+ border: { widthClass: "border" },
2235
+ effects: { hover: [{
2236
+ effectId: "background-on-hover",
2237
+ options: { colorToken: "surface" }
2238
+ }] }
2239
+ }
2240
+ },
2241
+ outline: {
2242
+ kind: "complete",
2243
+ appearance: {
2244
+ background: {
2245
+ type: "surface",
2246
+ role: "link"
2247
+ },
2248
+ borderRadius: "rounded-md",
2249
+ border: { widthClass: "border" },
2250
+ effects: { hover: [{
2251
+ effectId: "background-on-hover",
2252
+ options: { colorToken: "muted" }
2253
+ }] }
2254
+ }
2255
+ },
2256
+ ghost: {
2257
+ kind: "complete",
2258
+ appearance: {
2259
+ background: {
2260
+ type: "surface",
2261
+ role: "link"
2262
+ },
2263
+ borderRadius: "rounded-none",
2264
+ sizes: {
2265
+ sm: {
2266
+ padding: "0.375rem 0",
2267
+ fontSize: "text-xs"
2268
+ },
2269
+ md: {
2270
+ padding: "0.5rem 0",
2271
+ fontSize: "text-sm"
2272
+ },
2273
+ lg: {
2274
+ padding: "0.625rem 0",
2275
+ fontSize: "text-base"
2276
+ },
2277
+ xl: {
2278
+ padding: "0.75rem 0",
2279
+ fontSize: "text-lg"
2280
+ }
2281
+ },
2282
+ effects: { base: [{
2283
+ effectId: "border-bottom-grow",
2284
+ options: {
2285
+ height: 1,
2286
+ colorToken: "accent",
2287
+ origin: "left"
2288
+ }
2289
+ }] }
2290
+ }
2291
+ },
2292
+ accent: {
2293
+ kind: "derive",
2294
+ from: "primary",
2295
+ overrides: { background: {
2296
+ type: "solid",
2297
+ colorToken: "accent"
2298
+ } }
2299
+ }
2300
+ }
1997
2301
  }
1998
- };
2302
+ });
1999
2303
  //#endregion
2000
- //#region ../theme-core/src/buttons/personalities/index.ts
2001
- const buttonPersonalities = [
2002
- softPill,
2003
- defineButtonPersonality({
2004
- id: "two-tone-pill",
2005
- name: "Two-tone Pill",
2006
- description: "Rounded pills with distinct solid primary and secondary brand colours.",
2007
- tags: softPill.tags,
2008
- buttonSystem: {
2009
- ...softPill.buttonSystem,
2010
- variants: softPill.buttonSystem.variants.map((variant) => variant.id === "secondary" ? solidSecondary : variant)
2011
- }
2012
- }),
2013
- earthPill,
2014
- confidentChip,
2015
- editorialLink,
2016
- pebble,
2017
- inkStamp,
2018
- flatInk,
2019
- brushedWash,
2020
- showtimePill,
2021
- joyStamp,
2022
- ornateRitual,
2023
- quietArrow
2304
+ //#region ../theme-core/src/buttons/styles/registry.ts
2305
+ const buttonStyleRecipes = [
2306
+ softPillRecipe,
2307
+ earthPillRecipe,
2308
+ confidentChipRecipe,
2309
+ editorialLinkRecipe,
2310
+ pebbleRecipe,
2311
+ inkStampRecipe,
2312
+ flatInkRecipe,
2313
+ brushedWashRecipe,
2314
+ showtimePillRecipe,
2315
+ joyStampRecipe,
2316
+ ornateRitualRecipe,
2317
+ quietArrowRecipe
2024
2318
  ];
2025
- new Map(buttonPersonalities.map((p) => [p.id, p]));
2319
+ const recipesById = new Map(buttonStyleRecipes.map((recipe) => [recipe.id, recipe]));
2320
+ function findButtonStyleRecipe(id) {
2321
+ const recipe = recipesById.get(id);
2322
+ if (recipe === void 0) throw new Error(`Button style registry is missing known style ${id}`);
2323
+ return recipe;
2324
+ }
2325
+ function resolveButtonStyleSelection(selection) {
2326
+ switch (selection.styleId) {
2327
+ case "soft-pill": return resolveButtonStyleRecipe(softPillRecipe, selection.parameters);
2328
+ case "earth-pill": return resolveButtonStyleRecipe(earthPillRecipe, selection.parameters);
2329
+ case "confident-chip": return resolveButtonStyleRecipe(confidentChipRecipe, selection.parameters);
2330
+ case "editorial-link": return resolveButtonStyleRecipe(editorialLinkRecipe, selection.parameters);
2331
+ case "pebble": return resolveButtonStyleRecipe(pebbleRecipe, selection.parameters);
2332
+ case "ink-stamp": return resolveButtonStyleRecipe(inkStampRecipe, selection.parameters);
2333
+ case "flat-ink": return resolveButtonStyleRecipe(flatInkRecipe, selection.parameters);
2334
+ case "brushed-wash": return resolveButtonStyleRecipe(brushedWashRecipe, selection.parameters);
2335
+ case "showtime-pill": return resolveButtonStyleRecipe(showtimePillRecipe, selection.parameters);
2336
+ case "joy-stamp": return resolveButtonStyleRecipe(joyStampRecipe, selection.parameters);
2337
+ case "ornate-ritual": return resolveButtonStyleRecipe(ornateRitualRecipe, selection.parameters);
2338
+ case "quiet-arrow": return resolveButtonStyleRecipe(quietArrowRecipe, selection.parameters);
2339
+ }
2340
+ }
2341
+ function defaultButtonStyleSelectionFor(styleId) {
2342
+ return {
2343
+ styleId,
2344
+ parameters: findButtonStyleRecipe(styleId).defaultParameters
2345
+ };
2346
+ }
2347
+ if (buttonStyleRecipes.map((recipe) => recipe.id).length !== BUTTON_STYLE_IDS.length || BUTTON_STYLE_IDS.some((id) => !recipesById.has(id))) throw new Error("Button style registry and ButtonStyleId catalog are out of sync");
2348
+ buttonStyleRecipes.map((recipe) => {
2349
+ const resolved = resolveButtonStyleSelection(defaultButtonStyleSelectionFor(recipe.id));
2350
+ if (resolved.kind === "error") throw new Error(`Invalid registered button style ${recipe.id}: ${resolved.error.issues.join(", ")}`);
2351
+ return {
2352
+ id: recipe.id,
2353
+ name: recipe.accessibilityLabel,
2354
+ description: recipe.accessibilityLabel,
2355
+ category: presetCategory(recipe),
2356
+ buttonSystem: resolved.buttonSystem,
2357
+ compatibility: {
2358
+ ...recipe.tags.tone ? { tones: [recipe.tags.tone] } : {},
2359
+ ...recipe.tags.energy ? { energies: [recipe.tags.energy] } : {}
2360
+ }
2361
+ };
2362
+ });
2363
+ function presetCategory(recipe) {
2364
+ switch (recipe.tags.era) {
2365
+ case "retro": return "retro";
2366
+ case "editorial": return "minimal";
2367
+ case "organic": return "artistic";
2368
+ case "modern": return recipe.tags.tone === "bold" ? "modern" : "technical";
2369
+ case "technical": return "technical";
2370
+ case void 0: return "modern";
2371
+ }
2372
+ }
2026
2373
  //#endregion
2027
2374
  //#region ../theme-core/src/cards/types.ts
2028
2375
  const cardVariantRoleValues = ["default", "alternative"];