@riverbankcms/sdk 0.109.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 (186) hide show
  1. package/dist/{PreviewEditorSidebar-DWqwfy3_.mjs → PreviewEditorSidebar-CTR6LUhN.mjs} +178 -117
  2. package/dist/{PreviewEditorUI-B7OL4sfR.mjs → PreviewEditorUI-DZg15Zip.mjs} +3 -4
  3. package/dist/{PreviewQueryProvider-D0y2l8JN.mjs → PreviewQueryProvider-kkmjklLG.mjs} +1 -1
  4. package/dist/{SdkPreviewModeRuntime-D8Gt9Gbe.mjs → SdkPreviewModeRuntime-DeOTAFvR.mjs} +229 -219
  5. package/dist/{SiteChromeCustomizeContext-DUpalEdL.mjs → SiteChromeCustomizeContext-DOSDLCiJ.mjs} +1695 -2169
  6. package/dist/_dts/ai/src/contracts/proposals.d.ts +1716 -76
  7. package/dist/_dts/api/src/commercePortalEndpoints.d.ts +5 -5
  8. package/dist/_dts/api/src/contentRuntime.d.ts +4 -1
  9. package/dist/_dts/api/src/courses.d.ts +30 -15
  10. package/dist/_dts/api/src/endpoints.d.ts +14 -4
  11. package/dist/_dts/api/src/index.d.ts +2 -2
  12. package/dist/_dts/api/src/sdkContracts.d.ts +23 -11
  13. package/dist/_dts/api/src/siteManagementEndpoints.d.ts +5 -1
  14. package/dist/_dts/api/src/siteOperations.d.ts +11 -19
  15. package/dist/_dts/api/src/siteRuntimeEndpoints.d.ts +6 -6
  16. package/dist/_dts/api/src/webhooks.d.ts +98 -1
  17. package/dist/_dts/billing/src/site-arrangements.d.ts +3 -0
  18. package/dist/_dts/blocks/src/client/course-registration.d.ts +4 -1
  19. package/dist/_dts/blocks/src/client.d.ts +4 -1
  20. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -4
  21. package/dist/_dts/blocks/src/index.d.ts +3 -1
  22. package/dist/_dts/blocks/src/system/blocks/course-registration.d.ts +2 -1
  23. package/dist/_dts/blocks/src/system/blocks/courses/shared/types.d.ts +2 -1
  24. package/dist/_dts/blocks/src/system/blocks/cta-full.d.ts +2 -4
  25. package/dist/_dts/blocks/src/system/blocks/event-registration.d.ts +2 -1
  26. package/dist/_dts/blocks/src/system/blocks/events/event-listing.d.ts +2 -1
  27. package/dist/_dts/blocks/src/system/blocks/events/event-spotlight.d.ts +2 -1
  28. package/dist/_dts/blocks/src/system/blocks/events/recurring-schedule.d.ts +3 -2
  29. package/dist/_dts/blocks/src/system/blocks/events/shared/types.d.ts +2 -1
  30. package/dist/_dts/blocks/src/system/blocks/file-download.d.ts +2 -1
  31. package/dist/_dts/blocks/src/system/blocks/newsletter-signup.d.ts +2 -1
  32. package/dist/_dts/blocks/src/system/blocks/shop.d.ts +2 -1
  33. package/dist/_dts/blocks/src/system/blocks/single-button.d.ts +2 -1
  34. package/dist/_dts/blocks/src/system/constants/buttonRoles.d.ts +35 -0
  35. package/dist/_dts/blocks/src/system/fields/button.d.ts +10 -21
  36. package/dist/_dts/blocks/src/system/fields/ctas.d.ts +2 -1
  37. package/dist/_dts/blocks/src/system/fragments/library/heroCtaRow.d.ts +9 -5
  38. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +18 -18
  39. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +9 -9
  40. package/dist/_dts/blocks/src/system/runtime/hooks/useHeadlessWholeSeriesRegistrationFlow.d.ts +29 -0
  41. package/dist/_dts/blocks/src/system/runtime/nodes/buttonAffordance.d.ts +1 -1
  42. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/ErrorStep.d.ts +2 -1
  43. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/PaymentFailedStep.d.ts +2 -1
  44. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/VerifyingTimeoutStep.d.ts +2 -1
  45. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/types.d.ts +21 -0
  46. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/useCourseRegistrationWizard.d.ts +4 -4
  47. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/whole-series-registration.headless.contract.d.ts +326 -0
  48. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration/whole-series-registration.headless.planning.d.ts +27 -0
  49. package/dist/_dts/blocks/src/system/runtime/nodes/course-registration.interactive.d.ts +5 -4
  50. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/event-registration.headless.contract.d.ts +3 -2
  51. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration/types.d.ts +2 -1
  52. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +5 -4
  53. package/dist/_dts/blocks/src/system/runtime/nodes/file-download.d.ts +2 -3
  54. package/dist/_dts/blocks/src/system/runtime/nodes/newsletter-form.types.d.ts +2 -1
  55. package/dist/_dts/blocks/src/system/runtime/nodes/shared/contract-schemas.d.ts +6 -3
  56. package/dist/_dts/blocks/src/system/runtime/nodes/shop.interactive.d.ts +7 -6
  57. package/dist/_dts/blocks/src/system/runtime/nodes/shop.types.d.ts +2 -1
  58. package/dist/_dts/blocks/src/system/runtime/shared/types.d.ts +2 -1
  59. package/dist/_dts/content-editor/src/FooterComposerPanel.d.ts +4 -2
  60. package/dist/_dts/content-editor/src/index.d.ts +12 -12
  61. package/dist/_dts/content-editor/src/ui/editorUiStore.d.ts +17 -2
  62. package/dist/_dts/db/src/generated/supabase/database.types.d.ts +221 -53
  63. package/dist/_dts/editor-blocks/src/widgets/button/context.d.ts +3 -2
  64. package/dist/_dts/preview-next/src/client/index.d.ts +3 -2
  65. package/dist/_dts/preview-next/src/client/preview/ButtonStylePicker.d.ts +16 -0
  66. package/dist/_dts/preview-next/src/client/preview/PageBlockEditorPanel.d.ts +2 -3
  67. package/dist/_dts/preview-next/src/client/preview/PreviewDesignOpenRequestContext.d.ts +7 -0
  68. package/dist/_dts/preview-next/src/client/preview/PreviewEditorSidebar.d.ts +5 -11
  69. package/dist/_dts/preview-next/src/client/preview/PreviewShell.d.ts +5 -6
  70. package/dist/_dts/preview-next/src/client/preview/PreviewShellLayout.d.ts +6 -7
  71. package/dist/_dts/preview-next/src/client/preview/SiteChromeCustomizeContext.d.ts +7 -9
  72. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.d.ts +4 -11
  73. package/dist/_dts/preview-next/src/client/preview/StyleConfigurator.state.d.ts +7 -7
  74. package/dist/_dts/preview-next/src/client/preview/sidebarTabPreference.d.ts +0 -8
  75. package/dist/_dts/preview-next/src/client/preview/siteChromeLookRows.d.ts +1 -11
  76. package/dist/_dts/preview-next/src/client/preview/siteChromeQuickControlHistoryState.d.ts +1 -5
  77. package/dist/_dts/preview-next/src/client/preview/siteChromeSavePlan.d.ts +2 -3
  78. package/dist/_dts/preview-next/src/client/preview/siteStylePreviewPlanner.d.ts +3 -4
  79. package/dist/_dts/preview-next/src/client/preview/styleConfiguratorSnapshot.d.ts +3 -5
  80. package/dist/_dts/sdk/src/bookings/index.d.ts +5 -4
  81. package/dist/_dts/sdk/src/bookings/types.d.ts +3 -3
  82. package/dist/_dts/sdk/src/cli/commands/style.d.ts +3 -2
  83. package/dist/_dts/sdk/src/client/management/types.d.ts +2 -1
  84. package/dist/_dts/sdk/src/contracts/system-block-content.d.ts +12 -15
  85. package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -1
  86. package/dist/_dts/sdk/src/version.d.ts +1 -1
  87. package/dist/_dts/sdk/src/webhooks/index.d.ts +1 -1
  88. package/dist/_dts/sdk/src/webhooks/verify.d.ts +3 -3
  89. package/dist/_dts/site-commands/src/commands.d.ts +129 -6
  90. package/dist/_dts/theme-core/src/buttons/index.d.ts +1 -1
  91. package/dist/_dts/theme-core/src/buttons/styles/domain.d.ts +80 -0
  92. package/dist/_dts/theme-core/src/buttons/styles/index.d.ts +3 -0
  93. package/dist/_dts/theme-core/src/buttons/styles/recipes/defineStaticButtonStyleRecipe.d.ts +49 -0
  94. package/dist/_dts/theme-core/src/buttons/styles/recipes/quietArrow.d.ts +67 -0
  95. package/dist/_dts/theme-core/src/buttons/styles/recipes/staticRecipes.d.ts +649 -0
  96. package/dist/_dts/theme-core/src/buttons/styles/registry.d.ts +753 -0
  97. package/dist/_dts/theme-core/src/buttons/styles/selection.d.ts +69 -0
  98. package/dist/_dts/theme-core/src/site-styles/curatedSiteStyles.d.ts +26 -24
  99. package/dist/_dts/theme-core/src/site-styles/footerLooks.d.ts +19 -153
  100. package/dist/_dts/theme-core/src/site-styles/headerCtaVariants.d.ts +3 -1
  101. package/dist/_dts/theme-core/src/site-styles/previewCompiler.d.ts +8 -9
  102. package/dist/_dts/theme-core/src/site-styles/runtimeCompiler.d.ts +4 -4
  103. package/dist/_dts/ui/src/palette/hex.d.ts +3 -3
  104. package/dist/cli/index.mjs +1760 -1914
  105. package/dist/cli/init-docs/content/workflow-isr-revalidation.md +1 -1
  106. package/dist/client/{DiscountCodeDisclosure-DU1ygxU2.mjs → DiscountCodeDisclosure-C4xvTBux.mjs} +1 -1
  107. package/dist/client/{EventCombined.client-DB5zagCo.mjs → EventCombined.client-Cr7G131j.mjs} +2 -3
  108. package/dist/client/{EventListing.client-CTX9JHBL.mjs → EventListing.client-CAjbseNy.mjs} +2 -2
  109. package/dist/client/{LeafletStaticMap-BYImhgiB.mjs → LeafletStaticMap-BMlWfwz3.mjs} +1 -1
  110. package/dist/client/{MagicLinkForm-CRkw_M3l.mjs → MagicLinkForm-ChdFz96y.mjs} +1 -2
  111. package/dist/client/{StepIndicator-BnmVBJJh.mjs → StepIndicator-7D3GaBeM.mjs} +2 -2
  112. package/dist/client/{accordion-CeGreumd.mjs → accordion-D8JTs2Si.mjs} +1 -1
  113. package/dist/client/{bookingForm-CSzFNrpN.mjs → bookingForm-H3DCRBHs.mjs} +6 -7
  114. package/dist/client/bookings.mjs +3069 -1447
  115. package/dist/client/{carousel-B2jDtogf.mjs → carousel-DMr_QWlz.mjs} +1 -1
  116. package/dist/client/{cart-D-jZ-vaY.mjs → cart-DWMbfBdR.mjs} +3 -3
  117. package/dist/client/{checkout-Dza-LA7N.mjs → checkout-zmfdkXLx.mjs} +3 -3
  118. package/dist/client/client.mjs +1732 -1913
  119. package/dist/client/{colorStyles-CrgzoXsm.mjs → colorStyles-gcTh5yZT.mjs} +2 -12
  120. package/dist/client/{colorTokenParts-CMugwvX_.mjs → colorTokenParts-FSS3al6l.mjs} +31 -1
  121. package/dist/client/{courseRegistration-TYkNychb.mjs → courseRegistration-Z_mn18jy.mjs} +100 -37
  122. package/dist/client/{eventCalendar-BI_90SsT.mjs → eventCalendar-CYp0YJGF.mjs} +4 -5
  123. package/dist/client/{eventCombined-mNrpryE9.mjs → eventCombined-rKyYZUa9.mjs} +2 -2
  124. package/dist/client/{eventDetails-D4GVlCIY.mjs → eventDetails-X0ZaUuMj.mjs} +3 -3
  125. package/dist/client/{eventListing-YhKN018y.mjs → eventListing-W1SuL7EP.mjs} +2 -2
  126. package/dist/client/{eventRegistration-CdHGtilr.mjs → eventRegistration-ClWricui.mjs} +6 -7
  127. package/dist/client/{form-AcAL45rA.mjs → form--eKPwAAD.mjs} +1 -2
  128. package/dist/client/{headerSection-uEC52ueD.mjs → headerSection-BSeGr-FS.mjs} +2 -3
  129. package/dist/client/hooks.mjs +1554 -1871
  130. package/dist/client/{locationMap-_wJDSUYe.mjs → locationMap-BpOrtNYn.mjs} +8 -5
  131. package/dist/client/{media-BK0O3b-U.mjs → media-DoF0dcVx.mjs} +2 -2
  132. package/dist/client/{newsletterForm-DrArsb2B.mjs → newsletterForm-Bt7it7Dy.mjs} +1 -2
  133. package/dist/client/{pricing-BSYVghwo.mjs → pricing-BTjSDDr4.mjs} +1 -1
  134. package/dist/client/{productDetail-Dyk90sMs.mjs → productDetail-ICnVTcCg.mjs} +3 -3
  135. package/dist/client/{productList-BCKThwAI.mjs → productList-ZHr6D604.mjs} +3 -3
  136. package/dist/client/{propsDecoder-CkXxkdSR.mjs → propsDecoder-wWN0tBDF.mjs} +2351 -129
  137. package/dist/client/rendering/client.mjs +1664 -1824
  138. package/dist/client/rendering/islands.mjs +20 -20
  139. package/dist/client/rendering.mjs +1697 -1909
  140. package/dist/client/{shop-DeltVH10.mjs → shop-C1u_BUn0.mjs} +5 -6
  141. package/dist/client/{shop-commerce-BD9Jsm2Z.mjs → shop-commerce-CleZdRha.mjs} +5 -6
  142. package/dist/client/{shop-commerce-store-CmXD6FDS.mjs → shop-commerce-store-ycnoB2Ce.mjs} +1 -1
  143. package/dist/client/{shopShared-B8v-lH_F.mjs → shopShared-CPhByt2a.mjs} +3 -3
  144. package/dist/client/{useDiscountCodeUi-DbWJN8ld.mjs → useDiscountCodeUi-cStSQI6C.mjs} +1 -1
  145. package/dist/client/{useEventFilters-EJIMUnqT.mjs → useEventFilters-DKPN7hSY.mjs} +26 -27
  146. package/dist/client/{usePolling-Cmh14fc7.mjs → usePolling-BKAd6pkZ.mjs} +2 -2
  147. package/dist/preview-next/before-render.mjs +37 -6
  148. package/dist/preview-next/client/runtime.mjs +4 -4
  149. package/dist/preview-next/middleware.mjs +37 -6
  150. package/dist/{previewAuthStore-CTO7CRPk.mjs → previewAuthStore-BkT1D06A.mjs} +37 -6
  151. package/dist/{sdk-runtime-Dou0GAav.mjs → sdk-runtime-hu3wr3ng.mjs} +2 -2
  152. package/dist/{separator-CI5wZNXT.mjs → separator-Bln8izQ9.mjs} +1 -1
  153. package/dist/server/components.mjs +1472 -1788
  154. package/dist/server/config-validation.mjs +1559 -1876
  155. package/dist/server/config.mjs +1559 -1876
  156. package/dist/server/data.mjs +1554 -1871
  157. package/dist/server/index.mjs +38 -7
  158. package/dist/server/next/revalidate.mjs +53 -1
  159. package/dist/server/next.mjs +1584 -1869
  160. package/dist/server/page-converter.mjs +1543 -1860
  161. package/dist/server/prebuild.mjs +1 -1
  162. package/dist/server/rendering/server.mjs +1472 -1788
  163. package/dist/server/rendering.mjs +1472 -1788
  164. package/dist/server/routing.mjs +1600 -1891
  165. package/dist/server/server.mjs +1574 -1860
  166. package/dist/server/theme-bridge.mjs +1436 -1619
  167. package/dist/server/theme.mjs +1345 -1241
  168. package/dist/server/webhooks.mjs +54 -2
  169. package/package.json +1 -1
  170. package/dist/_dts/theme-core/src/buttons/personalities/brushed-wash.d.ts +0 -16
  171. package/dist/_dts/theme-core/src/buttons/personalities/confident-chip.d.ts +0 -16
  172. package/dist/_dts/theme-core/src/buttons/personalities/earth-pill.d.ts +0 -16
  173. package/dist/_dts/theme-core/src/buttons/personalities/editorial-link.d.ts +0 -16
  174. package/dist/_dts/theme-core/src/buttons/personalities/flat-ink.d.ts +0 -20
  175. package/dist/_dts/theme-core/src/buttons/personalities/index.d.ts +0 -172
  176. package/dist/_dts/theme-core/src/buttons/personalities/ink-stamp.d.ts +0 -16
  177. package/dist/_dts/theme-core/src/buttons/personalities/joy-stamp.d.ts +0 -22
  178. package/dist/_dts/theme-core/src/buttons/personalities/ornate-ritual.d.ts +0 -16
  179. package/dist/_dts/theme-core/src/buttons/personalities/pebble.d.ts +0 -16
  180. package/dist/_dts/theme-core/src/buttons/personalities/quiet-arrow.d.ts +0 -17
  181. package/dist/_dts/theme-core/src/buttons/personalities/showtime-pill.d.ts +0 -17
  182. package/dist/_dts/theme-core/src/buttons/personalities/soft-pill.d.ts +0 -16
  183. package/dist/_dts/theme-core/src/buttons/personalities/two-tone-pill.d.ts +0 -17
  184. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +0 -285
  185. package/dist/client/buttons-DoFV7KDL.mjs +0 -2115
  186. package/dist/client/foregroundContract-xICPq59x.mjs +0 -31
@@ -1,2115 +0,0 @@
1
- import { t as parseColorTokenParts } from "./colorTokenParts-CMugwvX_.mjs";
2
- import { $ as themeColorTokenSchema, Q as parseThemeColorToken } from "./propsDecoder-CkXxkdSR.mjs";
3
- import { z as z$1 } from "zod";
4
- //#region ../theme-core/src/buttons/effectClassification.ts
5
- /**
6
- * Exhaustive live policy for every registered effect id.
7
- *
8
- * The resolver consumes the transition payload directly, so adding an effect
9
- * cannot update classification without also defining its runtime behavior.
10
- */
11
- const BUTTON_EFFECT_POLICIES = {
12
- "darken-background": {
13
- classification: "colour-transition",
14
- transition: {
15
- kind: "adjust-shade",
16
- direction: "darker"
17
- }
18
- },
19
- "lighten-background": {
20
- classification: "colour-transition",
21
- transition: {
22
- kind: "adjust-shade",
23
- direction: "lighter"
24
- }
25
- },
26
- "background-on-hover": {
27
- classification: "colour-transition",
28
- transition: { kind: "replace-background" }
29
- },
30
- "background-on-hover-alpha": {
31
- classification: "unsupported-colour",
32
- reason: "alpha_requires_surface"
33
- },
34
- "fade-background": {
35
- classification: "unsupported-colour",
36
- reason: "changes_element_opacity"
37
- },
38
- "opacity-reduce": {
39
- classification: "unsupported-colour",
40
- reason: "changes_element_opacity"
41
- },
42
- "gradient-text": {
43
- classification: "unsupported-colour",
44
- reason: "changes_foreground"
45
- },
46
- "text-color-change": {
47
- classification: "unsupported-colour",
48
- reason: "changes_foreground"
49
- },
50
- "border-color-change": {
51
- classification: "unsupported-colour",
52
- reason: "changes_border"
53
- },
54
- "aurora-glow": {
55
- classification: "unsupported-background-overlay",
56
- reason: "unresolved_background_overlay"
57
- },
58
- "cosmic-stardust": {
59
- classification: "unsupported-background-overlay",
60
- reason: "unresolved_background_overlay"
61
- },
62
- "gradient-border-fill": {
63
- classification: "unsupported-background-overlay",
64
- reason: "unresolved_background_overlay"
65
- },
66
- "animated-gradient-border-fill": {
67
- classification: "unsupported-background-overlay",
68
- reason: "unresolved_background_overlay"
69
- },
70
- "nav-underline": {
71
- classification: "not-button",
72
- reason: "not_button_effect"
73
- },
74
- "nav-frosted-base": {
75
- classification: "not-button",
76
- reason: "not_button_effect"
77
- },
78
- "nav-frosted-hover": {
79
- classification: "not-button",
80
- reason: "not_button_effect"
81
- },
82
- "nav-frosted-active": {
83
- classification: "not-button",
84
- reason: "not_button_effect"
85
- },
86
- "animated-gradient": { classification: "non-colour" },
87
- "border-glow": { classification: "non-colour" },
88
- "drop-shadow": { classification: "non-colour" },
89
- "inner-shadow": { classification: "non-colour" },
90
- "neumorphic-shadow": { classification: "non-colour" },
91
- "outer-glow": { classification: "non-colour" },
92
- "retro-3d-shadow": { classification: "non-colour" },
93
- "scale-up": { classification: "non-colour" },
94
- "scale-down": { classification: "non-colour" },
95
- lift: { classification: "non-colour" },
96
- "press-down": { classification: "non-colour" },
97
- pop: { classification: "non-colour" },
98
- "border-bottom-grow": { classification: "non-colour" },
99
- "sketchy-border": { classification: "non-colour" },
100
- "pulse-animation": { classification: "non-colour" }
101
- };
102
- function getButtonEffectPolicy(effectId) {
103
- return Object.prototype.hasOwnProperty.call(BUTTON_EFFECT_POLICIES, effectId) ? BUTTON_EFFECT_POLICIES[effectId] : null;
104
- }
105
- function classifyButtonEffectId(effectId) {
106
- return getButtonEffectPolicy(effectId)?.classification ?? "unknown";
107
- }
108
- //#endregion
109
- //#region ../theme-core/src/buttons/types.ts
110
- /**
111
- * Standard semantic variant roles a theme exposes.
112
- *
113
- * Block content references variants by role; the active theme determines
114
- * what each role looks like.
115
- */
116
- const VARIANT_ROLES = [
117
- "primary",
118
- "secondary",
119
- "outline",
120
- "ghost",
121
- "link",
122
- "tertiary",
123
- "accent"
124
- ];
125
- function parseOpaqueButtonColourToken(value) {
126
- const token = parseThemeColorToken(value);
127
- if (token === null) return null;
128
- const parts = parseColorTokenParts(token);
129
- return parts.kind === "token" && parts.opacityPercent === null ? token : null;
130
- }
131
- function unsafeAsOpaqueButtonColourToken(value) {
132
- return value;
133
- }
134
- const opaqueButtonColourTokenSchema = themeColorTokenSchema.refine((value) => parseOpaqueButtonColourToken(value) !== null, "Button colour tokens must be opaque").transform((value) => {
135
- const token = parseOpaqueButtonColourToken(value);
136
- if (token === null) throw new Error("Invariant: opaque button token passed its schema");
137
- return token;
138
- });
139
- const cornerStyleSchema = z$1.enum([
140
- "square",
141
- "rounded",
142
- "pill"
143
- ]);
144
- const shadowSizeSchema = z$1.enum([
145
- "none",
146
- "low",
147
- "medium",
148
- "high"
149
- ]);
150
- const textTransformSchema = z$1.enum([
151
- "none",
152
- "uppercase",
153
- "lowercase",
154
- "capitalize"
155
- ]);
156
- const fontWeightSchema = z$1.union([
157
- z$1.literal(500),
158
- z$1.literal(600),
159
- z$1.literal(700)
160
- ]);
161
- const buttonTypographySchema = z$1.enum(["body", "heading"]);
162
- const letterSpacingSchema = z$1.enum([
163
- "tight",
164
- "normal",
165
- "loose"
166
- ]);
167
- const hoverTransformSchema = z$1.enum([
168
- "none",
169
- "lift",
170
- "scale",
171
- "press"
172
- ]);
173
- const hoverColorSchema = z$1.enum([
174
- "none",
175
- "brighten",
176
- "darken",
177
- "saturate",
178
- "token"
179
- ]);
180
- const buttonPaddingPresetSchema = z$1.enum([
181
- "compact",
182
- "default",
183
- "spacious"
184
- ]);
185
- const gradientStyleSchema = z$1.enum([
186
- "linear",
187
- "radial",
188
- "conic"
189
- ]);
190
- const gradientSharpnessSchema = z$1.enum([
191
- "smooth",
192
- "medium",
193
- "hard"
194
- ]);
195
- const prioritySchema = z$1.union([
196
- z$1.literal(1),
197
- z$1.literal(2),
198
- z$1.literal(3)
199
- ]);
200
- z$1.enum(VARIANT_ROLES);
201
- const buttonSizeNameSchema = z$1.enum([
202
- "sm",
203
- "md",
204
- "lg",
205
- "xl"
206
- ]);
207
- /**
208
- * CSS padding string in `"<vertical> <horizontal>"` shorthand form.
209
- *
210
- * Exactly two space-separated CSS length tokens. Each token is either the
211
- * literal `0` or a number followed by `rem`/`em`/`px`/`%`. This lets the
212
- * generator trust the shape rather than defensively defaulting downstream.
213
- */
214
- const PADDING_TOKEN_PATTERN = /^(?:0|\d+(?:\.\d+)?(?:rem|em|px|%))$/;
215
- const paddingShorthandSchema = z$1.string().refine((value) => {
216
- const parts = value.split(/\s+/).filter(Boolean);
217
- return parts.length === 2 && parts.every((token) => PADDING_TOKEN_PATTERN.test(token));
218
- }, { message: "Padding must be two space-separated CSS length tokens (e.g. \"0.5rem 1rem\"). Use `0` for zero." });
219
- const buttonSizeConfigSchema = z$1.object({
220
- padding: paddingShorthandSchema,
221
- fontSize: z$1.string().optional()
222
- });
223
- /**
224
- * `xl` is optional on the wire so themes persisted before the `xl` size was
225
- * added (e.g. SWTS) continue to parse. When `xl` is missing the schema
226
- * backfills it from `lg`, keeping `ButtonSizes` a complete `sm/md/lg/xl` map
227
- * downstream — generators never need to deal with an undefined `xl`.
228
- */
229
- const buttonSizesSchema = z$1.object({
230
- sm: buttonSizeConfigSchema,
231
- md: buttonSizeConfigSchema,
232
- lg: buttonSizeConfigSchema,
233
- xl: buttonSizeConfigSchema.optional()
234
- }).transform(({ sm, md, lg, xl }) => ({
235
- sm,
236
- md,
237
- lg,
238
- xl: xl ?? lg
239
- }));
240
- const canonicalButtonGlobalSettingsSchema = z$1.object({
241
- cornerStyle: cornerStyleSchema,
242
- cornerRadius: z$1.number().min(0).max(24).optional(),
243
- /**
244
- * Family-level shadow inherited by variants that don't set their own.
245
- * Optional and flat-by-default: when omitted, buttons carry no drop shadow
246
- * (`elevation: 'none'`). A personality opts the whole family into a shadow by
247
- * setting this; individual variants still override. There is no system-level
248
- * shadow-by-default — shadows only appear when explicitly declared.
249
- */
250
- shadow: shadowSizeSchema.optional(),
251
- textTransform: textTransformSchema,
252
- fontWeight: fontWeightSchema,
253
- /**
254
- * @deprecated Set per-variant via `variant.border.widthClass` instead.
255
- * Schema field is preserved so existing presets parse; the value is unread
256
- * by the current generator and will be removed once the legacy
257
- * `primitives/content/components/Button.tsx` slot exports are deleted.
258
- */
259
- borderWidth: z$1.union([
260
- z$1.literal(1),
261
- z$1.literal(2),
262
- z$1.literal(3)
263
- ]),
264
- typography: buttonTypographySchema.optional(),
265
- fontSize: z$1.string().optional(),
266
- letterSpacing: letterSpacingSchema.optional(),
267
- italic: z$1.boolean().optional(),
268
- paddingPreset: buttonPaddingPresetSchema.optional(),
269
- hoverTransform: hoverTransformSchema,
270
- hoverColor: hoverColorSchema,
271
- hoverColorToken: opaqueButtonColourTokenSchema.optional(),
272
- gradientStyle: gradientStyleSchema.optional(),
273
- gradientAngle: z$1.number().min(0).max(360).optional(),
274
- gradientSharpness: gradientSharpnessSchema.optional()
275
- });
276
- const buttonGlobalSettingsSchema = z$1.preprocess(normalizeLegacyButtonGlobalInput, canonicalButtonGlobalSettingsSchema);
277
- const gradientDirectionSchema = z$1.enum([
278
- "to-r",
279
- "to-l",
280
- "to-t",
281
- "to-b",
282
- "to-tr",
283
- "to-tl",
284
- "to-br",
285
- "to-bl"
286
- ]);
287
- const buttonBackgroundSchema = z$1.discriminatedUnion("type", [
288
- z$1.object({
289
- type: z$1.literal("solid"),
290
- colorToken: opaqueButtonColourTokenSchema
291
- }),
292
- z$1.object({
293
- type: z$1.literal("gradient"),
294
- stops: z$1.array(opaqueButtonColourTokenSchema).min(2).transform((stops) => {
295
- const [first, second, ...rest] = stops;
296
- if (first === void 0 || second === void 0) throw new Error("Invariant: gradient stops passed the minimum length schema");
297
- return [
298
- first,
299
- second,
300
- ...rest
301
- ];
302
- }),
303
- direction: gradientDirectionSchema,
304
- foregroundToken: opaqueButtonColourTokenSchema
305
- }),
306
- z$1.object({
307
- type: z$1.literal("surface"),
308
- role: z$1.literal("link")
309
- })
310
- ]);
311
- const effectApplicationSchema = z$1.object({
312
- effectId: z$1.string(),
313
- options: z$1.record(z$1.string(), z$1.json()).optional()
314
- });
315
- const buttonBorderSchema = z$1.object({ widthClass: z$1.string() });
316
- const buttonVariantAffordanceSchema = z$1.object({ iconId: z$1.string().min(1) });
317
- const variantShadowSchema = z$1.object({
318
- elevation: z$1.enum([
319
- "none",
320
- "low",
321
- "medium",
322
- "high"
323
- ]),
324
- softness: z$1.enum([
325
- "crisp",
326
- "soft",
327
- "hard"
328
- ]).nullable(),
329
- position: z$1.enum(["bottom", "bottom-right"]).default("bottom"),
330
- colorToken: themeColorTokenSchema.optional()
331
- });
332
- const variantEffectsSchema = z$1.object({
333
- base: z$1.array(effectApplicationSchema).optional(),
334
- hover: z$1.array(effectApplicationSchema).optional(),
335
- active: z$1.array(effectApplicationSchema).optional(),
336
- focus: z$1.array(effectApplicationSchema).optional()
337
- });
338
- /**
339
- * Per-variant size overrides schema — every entry is optional.
340
- *
341
- * For each size key present, the values override the theme's `sizes` config
342
- * for that size on this variant. Missing sizes fall through to theme.sizes,
343
- * then system defaults.
344
- */
345
- const variantSizeOverridesSchema = z$1.object({
346
- sm: buttonSizeConfigSchema.optional(),
347
- md: buttonSizeConfigSchema.optional(),
348
- lg: buttonSizeConfigSchema.optional(),
349
- xl: buttonSizeConfigSchema.optional()
350
- });
351
- /**
352
- * Unified variant schema. Every variant participates in the size system; the
353
- * optional `sizes` field lets a variant scale differently than the theme
354
- * default (e.g. link-style variants declaring zero horizontal padding at
355
- * every size).
356
- */
357
- const canonicalButtonVariantSchema = z$1.object({
358
- id: z$1.string(),
359
- name: z$1.string().min(1).max(20),
360
- enabled: z$1.boolean(),
361
- priority: prioritySchema,
362
- background: buttonBackgroundSchema,
363
- /** Tailwind radius token (e.g. `'rounded-md'`). Omit to inherit from `global.cornerStyle`. */
364
- borderRadius: z$1.string().optional(),
365
- shadow: variantShadowSchema.optional(),
366
- border: buttonBorderSchema.optional(),
367
- hoverBackgroundToken: opaqueButtonColourTokenSchema.optional(),
368
- effects: variantEffectsSchema.optional(),
369
- sizes: variantSizeOverridesSchema.optional(),
370
- affordance: buttonVariantAffordanceSchema.optional()
371
- });
372
- /**
373
- * Temporary persisted-theme admission boundary for issue #1206.
374
- *
375
- * Production inventory on 2026-07-22 found 22 rows using the old independent
376
- * `textColorToken`/border colour shape. New source and all downstream code use
377
- * only the canonical relationship. Delete this preprocessor after the reviewed
378
- * production rewrite reports zero legacy rows.
379
- */
380
- const buttonVariantSchema = z$1.preprocess(normalizeLegacyButtonVariantInput, canonicalButtonVariantSchema);
381
- const buttonSystemSchema = z$1.object({
382
- global: buttonGlobalSettingsSchema,
383
- variants: z$1.array(buttonVariantSchema).min(1).max(6),
384
- sizes: buttonSizesSchema.optional()
385
- });
386
- function normalizeLegacyButtonVariantInput(input) {
387
- if (!isUnknownRecord(input)) return input;
388
- const background = input.background;
389
- if (!isUnknownRecord(background)) return input;
390
- 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;
391
- const { textColorToken, ...withoutLegacyText } = input;
392
- const normalizedBorder = isUnknownRecord(input.border) && typeof input.border.widthClass === "string" ? { widthClass: input.border.widthClass } : input.border;
393
- const normalizedAffordance = isUnknownRecord(input.affordance) && typeof input.affordance.iconId === "string" ? { iconId: input.affordance.iconId } : input.affordance;
394
- const normalizedEffects = normalizeLegacyButtonEffects(input.effects, background.type);
395
- const hoverBackgroundToken = stripLegacyTokenAlpha(input.hoverBackgroundToken);
396
- if (background.type === "transparent") return {
397
- ...withoutLegacyText,
398
- background: {
399
- type: "surface",
400
- role: "link"
401
- },
402
- border: normalizedBorder,
403
- affordance: normalizedAffordance,
404
- effects: normalizedEffects,
405
- hoverBackgroundToken
406
- };
407
- if (background.type === "gradient") {
408
- const stops = Array.isArray(background.stops) ? background.stops.map(stripLegacyTokenAlpha) : background.stops;
409
- return {
410
- ...withoutLegacyText,
411
- background: {
412
- ...background,
413
- stops,
414
- foregroundToken: stripLegacyTokenAlpha(background.foregroundToken ?? textColorToken)
415
- },
416
- border: normalizedBorder,
417
- affordance: normalizedAffordance,
418
- effects: normalizedEffects,
419
- hoverBackgroundToken
420
- };
421
- }
422
- return {
423
- ...withoutLegacyText,
424
- background: background.type === "solid" ? {
425
- ...background,
426
- colorToken: stripLegacyTokenAlpha(background.colorToken)
427
- } : background,
428
- border: normalizedBorder,
429
- affordance: normalizedAffordance,
430
- effects: normalizedEffects,
431
- hoverBackgroundToken
432
- };
433
- }
434
- function normalizeLegacyButtonGlobalInput(input) {
435
- if (!isUnknownRecord(input)) return input;
436
- const hoverColorToken = stripLegacyTokenAlpha(input.hoverColorToken);
437
- return hoverColorToken === input.hoverColorToken ? input : {
438
- ...input,
439
- hoverColorToken
440
- };
441
- }
442
- function hasLegacyAlphaToken(input, background) {
443
- const stops = isUnknownArray(background.stops) ? background.stops : [];
444
- return [
445
- input.hoverBackgroundToken,
446
- background.colorToken,
447
- background.foregroundToken,
448
- ...stops
449
- ].some((token) => stripLegacyTokenAlpha(token) !== token);
450
- }
451
- function stripLegacyTokenAlpha(value) {
452
- if (typeof value !== "string") return value;
453
- const slashIndex = value.indexOf("/");
454
- return slashIndex < 0 ? value : value.slice(0, slashIndex);
455
- }
456
- function hasLegacyButtonEffects(input) {
457
- if (!isUnknownRecord(input)) return false;
458
- return [
459
- "base",
460
- "hover",
461
- "active",
462
- "focus"
463
- ].some((state) => {
464
- const effects = input[state];
465
- return Array.isArray(effects) && effects.some((effect) => {
466
- if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return true;
467
- const classification = classifyButtonEffectId(effect.effectId);
468
- if (classification !== "colour-transition" && classification !== "non-colour") return true;
469
- return effect.effectId === "background-on-hover" && isUnknownRecord(effect.options) && stripLegacyTokenAlpha(effect.options.colorToken) !== effect.options.colorToken;
470
- });
471
- });
472
- }
473
- function normalizeLegacyButtonEffects(input, backgroundType) {
474
- if (!isUnknownRecord(input)) return input;
475
- const normalized = {};
476
- for (const state of [
477
- "base",
478
- "hover",
479
- "active",
480
- "focus"
481
- ]) {
482
- const effects = input[state];
483
- if (!Array.isArray(effects)) continue;
484
- const safeEffects = effects.flatMap((effect) => {
485
- if (!isUnknownRecord(effect) || typeof effect.effectId !== "string") return [];
486
- const classification = classifyButtonEffectId(effect.effectId);
487
- if (classification === "non-colour") return [effect];
488
- if (classification !== "colour-transition") return [];
489
- if (effect.effectId === "background-on-hover") {
490
- const options = isUnknownRecord(effect.options) ? effect.options : null;
491
- const colorToken = options === null ? null : parseOpaqueButtonColourToken(stripLegacyTokenAlpha(options.colorToken));
492
- return colorToken === null ? [] : [{
493
- ...effect,
494
- options: {
495
- ...options,
496
- colorToken
497
- }
498
- }];
499
- }
500
- if (backgroundType !== "solid") return [];
501
- const rawAmount = isUnknownRecord(effect.options) ? effect.options.amount : void 0;
502
- const amount = typeof rawAmount === "number" && rawAmount > 0 ? Math.max(100, Math.round(rawAmount / 100) * 100) : 100;
503
- return [{
504
- ...effect,
505
- options: {
506
- ...isUnknownRecord(effect.options) ? effect.options : {},
507
- amount
508
- }
509
- }];
510
- });
511
- if (safeEffects.length > 0) normalized[state] = safeEffects;
512
- }
513
- return Object.keys(normalized).length === 0 ? void 0 : normalized;
514
- }
515
- function isUnknownRecord(value) {
516
- return typeof value === "object" && value !== null && !Array.isArray(value);
517
- }
518
- function isUnknownArray(value) {
519
- return Array.isArray(value);
520
- }
521
- //#endregion
522
- //#region ../theme-core/src/buttons/classNames.ts
523
- function themeButtonVariantClassNames(variant) {
524
- if (variant === "default") return [variant];
525
- return [variant, `button-${variant}`];
526
- }
527
- function themeButtonSizeClassName(size) {
528
- return `btn-${size}`;
529
- }
530
- function themeButtonClassName(spec) {
531
- return [
532
- ...themeButtonVariantClassNames(spec.variant),
533
- themeButtonSizeClassName(spec.size),
534
- spec.extraClassName
535
- ].filter(Boolean).join(" ");
536
- }
537
- //#endregion
538
- //#region ../theme-core/src/palette/utils/colorConversion.ts
539
- function hexToRgb(hex) {
540
- const h = hex.replace(/^#/, "");
541
- const m = h.length === 3 ? h.split("").map((c) => c + c).join("") : h;
542
- if (m.length !== 6) throw new Error("Bad hex");
543
- const int = parseInt(m, 16);
544
- return {
545
- r: int >> 16 & 255,
546
- g: int >> 8 & 255,
547
- b: int & 255
548
- };
549
- }
550
- function srgbToLinear(u) {
551
- const x = u / 255;
552
- return x <= .04045 ? x / 12.92 : Math.pow((x + .055) / 1.055, 2.4);
553
- }
554
- //#endregion
555
- //#region ../theme-core/src/palette/utils/contrast.ts
556
- function relativeLuminance(r, g, b) {
557
- const R = srgbToLinear(r), G = srgbToLinear(g), B = srgbToLinear(b);
558
- return .2126 * R + .7152 * G + .0722 * B;
559
- }
560
- buttonSizeNameSchema.options;
561
- //#endregion
562
- //#region ../theme-core/src/site-styles/styleTags.ts
563
- /**
564
- * Descriptive style-axis metadata for button personalities and palette
565
- * variants. Site Style picker shape is curated explicitly; these tags remain
566
- * for catalog audit, docs, and future discovery tooling.
567
- */
568
- const STYLE_AXIS_VALUES = {
569
- tone: [
570
- "minimal",
571
- "classic",
572
- "bold"
573
- ],
574
- energy: ["calm", "vibrant"],
575
- motion: [
576
- "subtle",
577
- "standard",
578
- "expressive"
579
- ],
580
- era: [
581
- "editorial",
582
- "modern",
583
- "organic",
584
- "technical",
585
- "retro"
586
- ]
587
- };
588
- const styleTagsSchema = z$1.object({
589
- tone: z$1.enum(STYLE_AXIS_VALUES.tone).optional(),
590
- energy: z$1.enum(STYLE_AXIS_VALUES.energy).optional(),
591
- motion: z$1.enum(STYLE_AXIS_VALUES.motion).optional(),
592
- era: z$1.enum(STYLE_AXIS_VALUES.era).optional()
593
- });
594
- //#endregion
595
- //#region ../theme-core/src/buttons/personalities/types.ts
596
- function asButtonPersonalityId(value) {
597
- if (value.length === 0) throw new Error("ButtonPersonalityId must be a non-empty string");
598
- return value;
599
- }
600
- const buttonPersonalityIdSchema = z$1.string().min(1).transform((value) => asButtonPersonalityId(value));
601
- z$1.object({
602
- id: buttonPersonalityIdSchema,
603
- name: z$1.string().min(1),
604
- description: z$1.string().min(1),
605
- tags: styleTagsSchema,
606
- buttonSystem: buttonSystemSchema
607
- });
608
- /**
609
- * Helper for personality file modules to keep the call site short and
610
- * type-safe. `as const satisfies ...` would also work but produces wider
611
- * types at use sites.
612
- */
613
- function defineButtonPersonality(input) {
614
- return {
615
- id: asButtonPersonalityId(input.id),
616
- name: input.name,
617
- description: input.description,
618
- tags: input.tags,
619
- buttonSystem: buttonSystemSchema.parse(input.buttonSystem)
620
- };
621
- }
622
- //#endregion
623
- //#region ../theme-core/src/buttons/personalities/brushed-wash.ts
624
- /**
625
- * Brushed Wash — gradient backgrounds that read as watercolour washes.
626
- * Generous padding, soft shadows; pairs with vibrant organic brands.
627
- */
628
- const brushedWash = defineButtonPersonality({
629
- id: "brushed-wash",
630
- name: "Brushed Wash",
631
- description: "Watercolour-gradient buttons with soft shadows and generous padding.",
632
- tags: {
633
- tone: "classic",
634
- energy: "vibrant",
635
- motion: "standard",
636
- era: "organic"
637
- },
638
- buttonSystem: {
639
- global: {
640
- cornerStyle: "rounded",
641
- shadow: "low",
642
- textTransform: "none",
643
- fontWeight: 500,
644
- borderWidth: 1,
645
- hoverTransform: "none",
646
- hoverColor: "none"
647
- },
648
- sizes: {
649
- sm: {
650
- padding: "0.75rem 2rem",
651
- fontSize: "text-sm"
652
- },
653
- md: { padding: "1rem 2.5rem" },
654
- lg: {
655
- padding: "1.25rem 3rem",
656
- fontSize: "text-lg"
657
- },
658
- xl: {
659
- padding: "1.625rem 3.75rem",
660
- fontSize: "text-xl"
661
- }
662
- },
663
- variants: [
664
- {
665
- id: "primary",
666
- name: "Primary",
667
- enabled: true,
668
- priority: 1,
669
- background: {
670
- type: "gradient",
671
- stops: ["primary", "accent"],
672
- direction: "to-r",
673
- foregroundToken: "primaryForeground"
674
- },
675
- borderRadius: "rounded-lg",
676
- shadow: {
677
- elevation: "low",
678
- softness: "soft",
679
- position: "bottom"
680
- }
681
- },
682
- {
683
- id: "secondary",
684
- name: "Secondary",
685
- enabled: true,
686
- priority: 2,
687
- background: {
688
- type: "gradient",
689
- stops: ["secondary", "accent"],
690
- direction: "to-br",
691
- foregroundToken: "primaryForeground"
692
- },
693
- borderRadius: "rounded-lg",
694
- shadow: {
695
- elevation: "low",
696
- softness: "soft",
697
- position: "bottom"
698
- }
699
- },
700
- {
701
- id: "outline",
702
- name: "Outline",
703
- enabled: true,
704
- priority: 3,
705
- background: {
706
- type: "surface",
707
- role: "link"
708
- },
709
- borderRadius: "rounded-lg",
710
- border: { widthClass: "border" },
711
- effects: { hover: [{
712
- effectId: "background-on-hover",
713
- options: { colorToken: "surface" }
714
- }] }
715
- },
716
- {
717
- id: "ghost",
718
- name: "Ghost",
719
- enabled: true,
720
- priority: 3,
721
- background: {
722
- type: "surface",
723
- role: "link"
724
- },
725
- borderRadius: "rounded-lg",
726
- effects: { hover: [{
727
- effectId: "background-on-hover",
728
- options: { colorToken: "surface" }
729
- }] }
730
- }
731
- ]
732
- }
733
- });
734
- //#endregion
735
- //#region ../theme-core/src/buttons/personalities/confident-chip.ts
736
- /**
737
- * Confident Chip — moderate-radius solid buttons that read as competent and
738
- * direct. Default for Clear Professional; works for any modern brand voice.
739
- */
740
- const confidentChip = defineButtonPersonality({
741
- id: "confident-chip",
742
- name: "Confident Chip",
743
- description: "Mid-radius solid buttons with a crisp hover.",
744
- tags: {
745
- tone: "classic",
746
- energy: "calm",
747
- motion: "standard",
748
- era: "modern"
749
- },
750
- buttonSystem: {
751
- global: {
752
- cornerStyle: "rounded",
753
- shadow: "medium",
754
- textTransform: "none",
755
- fontWeight: 600,
756
- borderWidth: 1,
757
- hoverTransform: "none",
758
- hoverColor: "none"
759
- },
760
- variants: [
761
- {
762
- id: "primary",
763
- name: "Primary",
764
- enabled: true,
765
- priority: 1,
766
- background: {
767
- type: "solid",
768
- colorToken: "primary"
769
- },
770
- borderRadius: "rounded-md",
771
- shadow: {
772
- elevation: "medium",
773
- softness: "soft",
774
- position: "bottom"
775
- },
776
- effects: {
777
- hover: [{
778
- effectId: "darken-background",
779
- options: { amount: 100 }
780
- }],
781
- active: [{
782
- effectId: "scale-down",
783
- options: { scale: "0.97" }
784
- }]
785
- }
786
- },
787
- {
788
- id: "secondary",
789
- name: "Secondary",
790
- enabled: true,
791
- priority: 2,
792
- background: {
793
- type: "solid",
794
- colorToken: "surface"
795
- },
796
- borderRadius: "rounded-md",
797
- border: { widthClass: "border" },
798
- effects: { hover: [{
799
- effectId: "background-on-hover",
800
- options: { colorToken: "background" }
801
- }] }
802
- },
803
- {
804
- id: "outline",
805
- name: "Outline",
806
- enabled: true,
807
- priority: 3,
808
- background: {
809
- type: "surface",
810
- role: "link"
811
- },
812
- borderRadius: "rounded-md",
813
- border: { widthClass: "border" },
814
- effects: { hover: [{
815
- effectId: "background-on-hover",
816
- options: { colorToken: "surface" }
817
- }] }
818
- },
819
- {
820
- id: "ghost",
821
- name: "Ghost",
822
- enabled: true,
823
- priority: 3,
824
- background: {
825
- type: "surface",
826
- role: "link"
827
- },
828
- borderRadius: "rounded-md",
829
- effects: { hover: [{
830
- effectId: "background-on-hover",
831
- options: { colorToken: "surface" }
832
- }] }
833
- }
834
- ]
835
- }
836
- });
837
- //#endregion
838
- //#region ../theme-core/src/buttons/personalities/earth-pill.ts
839
- /**
840
- * Earth Pill - warm studio pills with compact, primary-coloured ghost CTAs.
841
- * Built for grounded editorial wellness styles such as Soft Earth.
842
- */
843
- const earthPill = defineButtonPersonality({
844
- id: "earth-pill",
845
- name: "Earth Pill",
846
- description: "Compact terracotta pills with quiet primary-coloured ghost CTAs.",
847
- tags: {
848
- tone: "classic",
849
- energy: "calm",
850
- motion: "subtle",
851
- era: "organic"
852
- },
853
- buttonSystem: {
854
- global: {
855
- cornerStyle: "pill",
856
- shadow: "low",
857
- textTransform: "none",
858
- fontWeight: 500,
859
- borderWidth: 1,
860
- hoverTransform: "lift",
861
- hoverColor: "none",
862
- typography: "body",
863
- paddingPreset: "default"
864
- },
865
- sizes: {
866
- sm: {
867
- padding: "0.5rem 1rem",
868
- fontSize: "text-sm"
869
- },
870
- md: { padding: "0.625rem 1.35rem" },
871
- lg: {
872
- padding: "0.75rem 1.65rem",
873
- fontSize: "text-lg"
874
- },
875
- xl: {
876
- padding: "0.875rem 2rem",
877
- fontSize: "text-xl"
878
- }
879
- },
880
- variants: [
881
- {
882
- id: "primary",
883
- name: "Primary",
884
- enabled: true,
885
- priority: 1,
886
- background: {
887
- type: "solid",
888
- colorToken: "primary"
889
- },
890
- borderRadius: "rounded-full",
891
- shadow: {
892
- elevation: "low",
893
- softness: "soft",
894
- position: "bottom"
895
- },
896
- effects: {
897
- hover: [{
898
- effectId: "lift",
899
- options: { translateY: "-1px" }
900
- }, {
901
- effectId: "background-on-hover",
902
- options: { colorToken: "accent" }
903
- }],
904
- active: [{
905
- effectId: "scale-down",
906
- options: { scale: "0.98" }
907
- }]
908
- }
909
- },
910
- {
911
- id: "secondary",
912
- name: "Secondary",
913
- enabled: true,
914
- priority: 2,
915
- background: {
916
- type: "surface",
917
- role: "link"
918
- },
919
- borderRadius: "rounded-full",
920
- border: { widthClass: "border" },
921
- effects: { hover: [{
922
- effectId: "background-on-hover",
923
- options: { colorToken: "muted" }
924
- }] }
925
- },
926
- {
927
- id: "outline",
928
- name: "Outline",
929
- enabled: true,
930
- priority: 3,
931
- background: {
932
- type: "surface",
933
- role: "link"
934
- },
935
- borderRadius: "rounded-full",
936
- border: { widthClass: "border" },
937
- effects: { hover: [{
938
- effectId: "background-on-hover",
939
- options: { colorToken: "surfaceAlt" }
940
- }] }
941
- },
942
- {
943
- id: "ghost",
944
- name: "Ghost",
945
- enabled: true,
946
- priority: 3,
947
- background: {
948
- type: "surface",
949
- role: "link"
950
- },
951
- borderRadius: "rounded-full",
952
- shadow: {
953
- elevation: "none",
954
- softness: null,
955
- position: "bottom"
956
- },
957
- sizes: {
958
- sm: {
959
- padding: "0.25rem 0",
960
- fontSize: "text-sm"
961
- },
962
- md: { padding: "0.375rem 0" },
963
- lg: {
964
- padding: "0.5rem 0",
965
- fontSize: "text-lg"
966
- },
967
- xl: {
968
- padding: "0.625rem 0",
969
- fontSize: "text-xl"
970
- }
971
- }
972
- }
973
- ]
974
- }
975
- });
976
- //#endregion
977
- //#region ../theme-core/src/buttons/personalities/editorial-link.ts
978
- /**
979
- * Editorial Link — all variants are link-style with a growing underline.
980
- * Default for Warm Editorial and Quiet Luxury; reads as refined and quiet.
981
- */
982
- const editorialLink = defineButtonPersonality({
983
- id: "editorial-link",
984
- name: "Editorial Link",
985
- description: "Link-style with a growing underline. Refined, typographic.",
986
- tags: {
987
- tone: "minimal",
988
- energy: "calm",
989
- motion: "subtle",
990
- era: "editorial"
991
- },
992
- buttonSystem: {
993
- global: {
994
- cornerStyle: "square",
995
- textTransform: "none",
996
- fontWeight: 500,
997
- borderWidth: 1,
998
- hoverTransform: "none",
999
- hoverColor: "none"
1000
- },
1001
- variants: [
1002
- {
1003
- id: "primary",
1004
- name: "Primary",
1005
- enabled: true,
1006
- priority: 1,
1007
- background: {
1008
- type: "surface",
1009
- role: "link"
1010
- },
1011
- borderRadius: "rounded-none",
1012
- sizes: {
1013
- sm: { padding: "0.25rem 0" },
1014
- md: { padding: "0.5rem 0" },
1015
- lg: { padding: "0.625rem 0" },
1016
- xl: { padding: "0.75rem 0" }
1017
- },
1018
- effects: { base: [{
1019
- effectId: "border-bottom-grow",
1020
- options: {
1021
- height: 2,
1022
- colorToken: "text",
1023
- origin: "left"
1024
- }
1025
- }] }
1026
- },
1027
- {
1028
- id: "secondary",
1029
- name: "Secondary",
1030
- enabled: true,
1031
- priority: 2,
1032
- background: {
1033
- type: "surface",
1034
- role: "link"
1035
- },
1036
- borderRadius: "rounded-none",
1037
- sizes: {
1038
- sm: { padding: "0.25rem 0" },
1039
- md: { padding: "0.5rem 0" },
1040
- lg: { padding: "0.625rem 0" },
1041
- xl: { padding: "0.75rem 0" }
1042
- },
1043
- effects: { base: [{
1044
- effectId: "border-bottom-grow",
1045
- options: {
1046
- height: 1,
1047
- colorToken: "mutedText",
1048
- origin: "left"
1049
- }
1050
- }] }
1051
- },
1052
- {
1053
- id: "outline",
1054
- name: "Outline",
1055
- enabled: true,
1056
- priority: 3,
1057
- background: {
1058
- type: "surface",
1059
- role: "link"
1060
- },
1061
- borderRadius: "rounded-none",
1062
- sizes: {
1063
- sm: { padding: "0.25rem 0" },
1064
- md: { padding: "0.5rem 0" },
1065
- lg: { padding: "0.625rem 0" },
1066
- xl: { padding: "0.75rem 0" }
1067
- },
1068
- effects: { base: [{
1069
- effectId: "border-bottom-grow",
1070
- options: {
1071
- height: 1,
1072
- colorToken: "accent",
1073
- origin: "left"
1074
- }
1075
- }] }
1076
- },
1077
- {
1078
- id: "ghost",
1079
- name: "Ghost",
1080
- enabled: true,
1081
- priority: 3,
1082
- background: {
1083
- type: "surface",
1084
- role: "link"
1085
- },
1086
- borderRadius: "rounded-none",
1087
- sizes: {
1088
- sm: { padding: "0.25rem 0" },
1089
- md: { padding: "0.5rem 0" },
1090
- lg: { padding: "0.625rem 0" },
1091
- xl: { padding: "0.75rem 0" }
1092
- }
1093
- }
1094
- ]
1095
- }
1096
- });
1097
- //#endregion
1098
- //#region ../theme-core/src/buttons/personalities/flat-ink.ts
1099
- /**
1100
- * Flat Ink — a solid ink primary, a hairline ghost secondary, and a single
1101
- * amber accent climax, all completely flat (no drop shadow) with a modest
1102
- * radius. Reads as grounded, editorial and clinician-precise: the Fulcrum
1103
- * physiotherapy voice. The primary shifts to the secondary (moss) on hover and
1104
- * every variant lifts 2px; the amber accent is meant to be used sparingly as
1105
- * the page's one conversion climax.
1106
- */
1107
- const flatInk = defineButtonPersonality({
1108
- id: "flat-ink",
1109
- name: "Flat Ink",
1110
- description: "Flat solid-ink primary, hairline ghost secondary, and a single amber accent climax — modest radius, no shadow.",
1111
- tags: {
1112
- tone: "classic",
1113
- energy: "calm",
1114
- motion: "subtle",
1115
- era: "editorial"
1116
- },
1117
- buttonSystem: {
1118
- global: {
1119
- cornerStyle: "rounded",
1120
- textTransform: "none",
1121
- fontWeight: 600,
1122
- borderWidth: 1,
1123
- typography: "body",
1124
- letterSpacing: "tight",
1125
- paddingPreset: "default",
1126
- hoverTransform: "lift",
1127
- hoverColor: "none"
1128
- },
1129
- sizes: {
1130
- sm: {
1131
- padding: "0.625rem 1.125rem",
1132
- fontSize: "text-sm"
1133
- },
1134
- md: { padding: "0.8125rem 1.375rem" },
1135
- lg: {
1136
- padding: "0.9375rem 1.625rem",
1137
- fontSize: "text-lg"
1138
- },
1139
- xl: {
1140
- padding: "1.0625rem 2rem",
1141
- fontSize: "text-xl"
1142
- }
1143
- },
1144
- variants: [
1145
- {
1146
- id: "primary",
1147
- name: "Primary",
1148
- enabled: true,
1149
- priority: 1,
1150
- background: {
1151
- type: "solid",
1152
- colorToken: "primary"
1153
- },
1154
- borderRadius: "rounded-lg",
1155
- affordance: { iconId: "ArrowRight" },
1156
- effects: { hover: [{
1157
- effectId: "lift",
1158
- options: { translateY: "-2px" }
1159
- }, {
1160
- effectId: "background-on-hover",
1161
- options: { colorToken: "secondary" }
1162
- }] }
1163
- },
1164
- {
1165
- id: "secondary",
1166
- name: "Secondary",
1167
- enabled: true,
1168
- priority: 2,
1169
- background: {
1170
- type: "surface",
1171
- role: "link"
1172
- },
1173
- borderRadius: "rounded-lg",
1174
- border: { widthClass: "border" },
1175
- effects: { hover: [{
1176
- effectId: "lift",
1177
- options: { translateY: "-2px" }
1178
- }, {
1179
- effectId: "background-on-hover",
1180
- options: { colorToken: "surfaceAlt" }
1181
- }] }
1182
- },
1183
- {
1184
- id: "accent",
1185
- name: "Accent",
1186
- enabled: true,
1187
- priority: 3,
1188
- background: {
1189
- type: "solid",
1190
- colorToken: "accent"
1191
- },
1192
- borderRadius: "rounded-lg",
1193
- affordance: { iconId: "ArrowRight" },
1194
- effects: { hover: [{
1195
- effectId: "lift",
1196
- options: { translateY: "-2px" }
1197
- }] }
1198
- }
1199
- ]
1200
- }
1201
- });
1202
- //#endregion
1203
- //#region ../theme-core/src/buttons/personalities/ink-stamp.ts
1204
- /**
1205
- * Ink Stamp — solid earthy fills with a bordered, hand-stamped block-print
1206
- * feel. Reads as bold and handmade; suits expressive craft brands.
1207
- */
1208
- const inkStamp = defineButtonPersonality({
1209
- id: "ink-stamp",
1210
- name: "Ink Stamp",
1211
- description: "Hand-stamped block-print buttons with a slight lift on hover.",
1212
- tags: {
1213
- tone: "bold",
1214
- energy: "vibrant",
1215
- motion: "standard",
1216
- era: "organic"
1217
- },
1218
- buttonSystem: {
1219
- global: {
1220
- cornerStyle: "rounded",
1221
- textTransform: "uppercase",
1222
- fontWeight: 600,
1223
- borderWidth: 1,
1224
- hoverTransform: "none",
1225
- hoverColor: "none",
1226
- letterSpacing: "loose"
1227
- },
1228
- sizes: {
1229
- sm: {
1230
- padding: "0.5rem 1.25rem",
1231
- fontSize: "text-xs"
1232
- },
1233
- md: {
1234
- padding: "0.75rem 1.75rem",
1235
- fontSize: "text-sm"
1236
- },
1237
- lg: {
1238
- padding: "0.875rem 2.25rem",
1239
- fontSize: "text-base"
1240
- },
1241
- xl: {
1242
- padding: "1.125rem 2.75rem",
1243
- fontSize: "text-lg"
1244
- }
1245
- },
1246
- variants: [
1247
- {
1248
- id: "primary",
1249
- name: "Primary",
1250
- enabled: true,
1251
- priority: 1,
1252
- background: {
1253
- type: "solid",
1254
- colorToken: "primary"
1255
- },
1256
- borderRadius: "rounded-md",
1257
- effects: {
1258
- hover: [{
1259
- effectId: "drop-shadow",
1260
- options: { intensity: "medium" }
1261
- }, {
1262
- effectId: "scale-up",
1263
- options: { scale: "1.02" }
1264
- }],
1265
- active: [{
1266
- effectId: "scale-down",
1267
- options: { scale: "0.98" }
1268
- }]
1269
- }
1270
- },
1271
- {
1272
- id: "secondary",
1273
- name: "Secondary",
1274
- enabled: true,
1275
- priority: 2,
1276
- background: {
1277
- type: "surface",
1278
- role: "link"
1279
- },
1280
- borderRadius: "rounded-md",
1281
- border: { widthClass: "border-2" },
1282
- effects: { hover: [{
1283
- effectId: "background-on-hover",
1284
- options: { colorToken: "surface" }
1285
- }] }
1286
- },
1287
- {
1288
- id: "outline",
1289
- name: "Outline",
1290
- enabled: true,
1291
- priority: 3,
1292
- background: {
1293
- type: "surface",
1294
- role: "link"
1295
- },
1296
- borderRadius: "rounded-md",
1297
- border: { widthClass: "border-2" },
1298
- effects: { hover: [{
1299
- effectId: "background-on-hover",
1300
- options: { colorToken: "surface" }
1301
- }] }
1302
- },
1303
- {
1304
- id: "ghost",
1305
- name: "Ghost",
1306
- enabled: true,
1307
- priority: 3,
1308
- background: {
1309
- type: "surface",
1310
- role: "link"
1311
- },
1312
- borderRadius: "rounded-none",
1313
- sizes: {
1314
- sm: {
1315
- padding: "0.375rem 0",
1316
- fontSize: "text-xs"
1317
- },
1318
- md: {
1319
- padding: "0.5rem 0",
1320
- fontSize: "text-sm"
1321
- },
1322
- lg: {
1323
- padding: "0.625rem 0",
1324
- fontSize: "text-base"
1325
- },
1326
- xl: {
1327
- padding: "0.75rem 0",
1328
- fontSize: "text-lg"
1329
- }
1330
- },
1331
- effects: { base: [{
1332
- effectId: "border-bottom-grow",
1333
- options: {
1334
- height: 1,
1335
- colorToken: "accent",
1336
- origin: "left"
1337
- }
1338
- }] }
1339
- }
1340
- ]
1341
- }
1342
- });
1343
- //#endregion
1344
- //#region ../theme-core/src/buttons/personalities/joy-stamp.ts
1345
- /**
1346
- * Joy Stamp — neo-brutalist pills with a hard, brand-coloured offset shadow
1347
- * that collapses as the button presses into it on hover. Authored for the
1348
- * Original Joy site style: a cream "stamp" shadow under the solid primary, and
1349
- * a brown shadow under the cream outline. Reads as bold, warm, and handmade.
1350
- *
1351
- * The coloured offset shadow relies on the per-variant `shadow.colorToken`
1352
- * extension; the press is the shared `press-down` effect, which matches its
1353
- * translate to each variant's own shadow offset.
1354
- */
1355
- const joyStamp = defineButtonPersonality({
1356
- id: "joy-stamp",
1357
- name: "Joy Stamp",
1358
- description: "Pill buttons with a hard, brand-coloured offset shadow that presses in on hover.",
1359
- tags: {
1360
- tone: "bold",
1361
- energy: "vibrant",
1362
- motion: "expressive",
1363
- era: "organic"
1364
- },
1365
- buttonSystem: {
1366
- global: {
1367
- cornerStyle: "pill",
1368
- shadow: "high",
1369
- textTransform: "none",
1370
- typography: "heading",
1371
- fontWeight: 700,
1372
- fontSize: "text-lg",
1373
- borderWidth: 2,
1374
- hoverTransform: "none",
1375
- hoverColor: "none"
1376
- },
1377
- sizes: {
1378
- sm: {
1379
- padding: "0.625rem 1.25rem",
1380
- fontSize: "text-base"
1381
- },
1382
- md: {
1383
- padding: "0.875rem 1.75rem",
1384
- fontSize: "text-lg"
1385
- },
1386
- lg: {
1387
- padding: "1.125rem 2.25rem",
1388
- fontSize: "text-xl"
1389
- },
1390
- xl: {
1391
- padding: "1.25rem 2.75rem",
1392
- fontSize: "text-2xl"
1393
- }
1394
- },
1395
- variants: [{
1396
- id: "primary",
1397
- name: "Primary",
1398
- enabled: true,
1399
- priority: 1,
1400
- background: {
1401
- type: "solid",
1402
- colorToken: "primary"
1403
- },
1404
- borderRadius: "rounded-full",
1405
- shadow: {
1406
- elevation: "high",
1407
- softness: "hard",
1408
- position: "bottom-right",
1409
- colorToken: "text"
1410
- },
1411
- effects: { hover: [{ effectId: "press-down" }] }
1412
- }, {
1413
- id: "secondary",
1414
- name: "Secondary",
1415
- enabled: true,
1416
- priority: 2,
1417
- background: {
1418
- type: "surface",
1419
- role: "link"
1420
- },
1421
- borderRadius: "rounded-full",
1422
- border: { widthClass: "border-2" },
1423
- shadow: {
1424
- elevation: "high",
1425
- softness: "hard",
1426
- position: "bottom-right",
1427
- colorToken: "secondary"
1428
- },
1429
- effects: { hover: [{ effectId: "press-down" }] }
1430
- }]
1431
- }
1432
- });
1433
- //#endregion
1434
- //#region ../theme-core/src/buttons/personalities/ornate-ritual.ts
1435
- /**
1436
- * Ornate Ritual — framed, ceremonial buttons with jewel-toned fills and
1437
- * deliberate spacing. Designed for music, ceremony, and soulful event sites.
1438
- */
1439
- const ornateRitual = defineButtonPersonality({
1440
- id: "ornate-ritual",
1441
- name: "Ornate Ritual",
1442
- description: "Ceremonial framed buttons with jewel-toned fills and quiet color-change hover states.",
1443
- tags: {
1444
- tone: "classic",
1445
- energy: "vibrant",
1446
- motion: "subtle",
1447
- era: "organic"
1448
- },
1449
- buttonSystem: {
1450
- global: {
1451
- cornerStyle: "rounded",
1452
- textTransform: "uppercase",
1453
- fontWeight: 600,
1454
- borderWidth: 1,
1455
- hoverTransform: "none",
1456
- hoverColor: "none",
1457
- letterSpacing: "loose"
1458
- },
1459
- sizes: {
1460
- sm: {
1461
- padding: "0.5625rem 1.25rem",
1462
- fontSize: "text-xs"
1463
- },
1464
- md: {
1465
- padding: "0.75rem 1.75rem",
1466
- fontSize: "text-xs"
1467
- },
1468
- lg: {
1469
- padding: "0.875rem 2.25rem",
1470
- fontSize: "text-sm"
1471
- },
1472
- xl: {
1473
- padding: "1rem 2.75rem",
1474
- fontSize: "text-base"
1475
- }
1476
- },
1477
- variants: [
1478
- {
1479
- id: "primary",
1480
- name: "Primary",
1481
- enabled: true,
1482
- priority: 1,
1483
- background: {
1484
- type: "solid",
1485
- colorToken: "primary"
1486
- },
1487
- borderRadius: "rounded-md",
1488
- border: { widthClass: "border" },
1489
- effects: {
1490
- hover: [{
1491
- effectId: "background-on-hover",
1492
- options: { colorToken: "primary-100" }
1493
- }],
1494
- active: [{
1495
- effectId: "scale-down",
1496
- options: { scale: "0.98" }
1497
- }]
1498
- }
1499
- },
1500
- {
1501
- id: "secondary",
1502
- name: "Secondary",
1503
- enabled: true,
1504
- priority: 2,
1505
- background: {
1506
- type: "solid",
1507
- colorToken: "secondary"
1508
- },
1509
- borderRadius: "rounded-md",
1510
- border: { widthClass: "border" },
1511
- effects: { hover: [{
1512
- effectId: "background-on-hover",
1513
- options: { colorToken: "surface" }
1514
- }] }
1515
- },
1516
- {
1517
- id: "outline",
1518
- name: "Outline",
1519
- enabled: true,
1520
- priority: 3,
1521
- background: {
1522
- type: "surface",
1523
- role: "link"
1524
- },
1525
- borderRadius: "rounded-md",
1526
- border: { widthClass: "border" },
1527
- effects: { hover: [{
1528
- effectId: "background-on-hover",
1529
- options: { colorToken: "muted" }
1530
- }] }
1531
- },
1532
- {
1533
- id: "ghost",
1534
- name: "Ghost",
1535
- enabled: true,
1536
- priority: 3,
1537
- background: {
1538
- type: "surface",
1539
- role: "link"
1540
- },
1541
- borderRadius: "rounded-none",
1542
- sizes: {
1543
- sm: {
1544
- padding: "0.375rem 0",
1545
- fontSize: "text-xs"
1546
- },
1547
- md: {
1548
- padding: "0.5rem 0",
1549
- fontSize: "text-sm"
1550
- },
1551
- lg: {
1552
- padding: "0.625rem 0",
1553
- fontSize: "text-base"
1554
- },
1555
- xl: {
1556
- padding: "0.75rem 0",
1557
- fontSize: "text-lg"
1558
- }
1559
- },
1560
- effects: { base: [{
1561
- effectId: "border-bottom-grow",
1562
- options: {
1563
- height: 1,
1564
- colorToken: "accent",
1565
- origin: "left"
1566
- }
1567
- }] }
1568
- }
1569
- ]
1570
- }
1571
- });
1572
- //#endregion
1573
- //#region ../theme-core/src/buttons/personalities/pebble.ts
1574
- /**
1575
- * Pebble — large pill primaries with generous padding. Reads as spa-luxurious
1576
- * and natural; pairs well with wellness/yoga/dance brands.
1577
- */
1578
- const pebble = defineButtonPersonality({
1579
- id: "pebble",
1580
- name: "Pebble",
1581
- description: "Generous pill buttons with a quiet colour-softening hover.",
1582
- tags: {
1583
- tone: "classic",
1584
- energy: "calm",
1585
- motion: "standard",
1586
- era: "organic"
1587
- },
1588
- buttonSystem: {
1589
- global: {
1590
- cornerStyle: "pill",
1591
- textTransform: "none",
1592
- fontWeight: 500,
1593
- borderWidth: 2,
1594
- hoverTransform: "none",
1595
- hoverColor: "none"
1596
- },
1597
- sizes: {
1598
- sm: {
1599
- padding: "0.625rem 1.75rem",
1600
- fontSize: "text-sm"
1601
- },
1602
- md: { padding: "0.875rem 2.25rem" },
1603
- lg: {
1604
- padding: "1.125rem 2.75rem",
1605
- fontSize: "text-lg"
1606
- },
1607
- xl: {
1608
- padding: "1.5rem 3.5rem",
1609
- fontSize: "text-xl"
1610
- }
1611
- },
1612
- variants: [
1613
- {
1614
- id: "primary",
1615
- name: "Primary",
1616
- enabled: true,
1617
- priority: 1,
1618
- background: {
1619
- type: "solid",
1620
- colorToken: "primary"
1621
- },
1622
- borderRadius: "rounded-full",
1623
- effects: { hover: [{
1624
- effectId: "darken-background",
1625
- options: { amount: 100 }
1626
- }] }
1627
- },
1628
- {
1629
- id: "secondary",
1630
- name: "Secondary",
1631
- enabled: true,
1632
- priority: 2,
1633
- background: {
1634
- type: "surface",
1635
- role: "link"
1636
- },
1637
- borderRadius: "rounded-full",
1638
- border: { widthClass: "border-2" },
1639
- effects: { hover: [{
1640
- effectId: "background-on-hover",
1641
- options: { colorToken: "accent" }
1642
- }] }
1643
- },
1644
- {
1645
- id: "outline",
1646
- name: "Outline",
1647
- enabled: true,
1648
- priority: 3,
1649
- background: {
1650
- type: "surface",
1651
- role: "link"
1652
- },
1653
- borderRadius: "rounded-full",
1654
- border: { widthClass: "border" },
1655
- effects: { hover: [{
1656
- effectId: "background-on-hover",
1657
- options: { colorToken: "surface" }
1658
- }] }
1659
- },
1660
- {
1661
- id: "ghost",
1662
- name: "Ghost",
1663
- enabled: true,
1664
- priority: 3,
1665
- background: {
1666
- type: "surface",
1667
- role: "link"
1668
- },
1669
- borderRadius: "rounded-full",
1670
- sizes: {
1671
- sm: {
1672
- padding: "0.375rem 0.875rem",
1673
- fontSize: "text-sm"
1674
- },
1675
- md: { padding: "0.5rem 1rem" },
1676
- lg: {
1677
- padding: "0.625rem 1.25rem",
1678
- fontSize: "text-lg"
1679
- },
1680
- xl: {
1681
- padding: "0.75rem 1.5rem",
1682
- fontSize: "text-xl"
1683
- }
1684
- }
1685
- }
1686
- ]
1687
- }
1688
- });
1689
- //#endregion
1690
- //#region ../theme-core/src/buttons/personalities/quiet-arrow.ts
1691
- /**
1692
- * Quiet Arrow — wide, flat editorial buttons for grounded service businesses.
1693
- * Primary and secondary keep stable semantic colours; surrounding surfaces are
1694
- * responsible for contrast rather than reversing the button roles.
1695
- */
1696
- const quietArrow = defineButtonPersonality({
1697
- id: "quiet-arrow",
1698
- name: "Quiet Arrow",
1699
- description: "Wide, flat arrow buttons with a solid primary and a primary-colour outlined secondary.",
1700
- tags: {
1701
- tone: "classic",
1702
- energy: "calm",
1703
- motion: "subtle",
1704
- era: "editorial"
1705
- },
1706
- buttonSystem: {
1707
- global: {
1708
- cornerStyle: "rounded",
1709
- textTransform: "uppercase",
1710
- fontWeight: 500,
1711
- borderWidth: 1,
1712
- typography: "body",
1713
- fontSize: "text-sm",
1714
- letterSpacing: "loose",
1715
- hoverTransform: "none",
1716
- hoverColor: "none"
1717
- },
1718
- sizes: {
1719
- sm: {
1720
- padding: "0.625rem 1.25rem",
1721
- fontSize: "text-xs"
1722
- },
1723
- md: {
1724
- padding: "0.8125rem 1.75rem",
1725
- fontSize: "text-sm"
1726
- },
1727
- lg: {
1728
- padding: "0.9375rem 2.125rem",
1729
- fontSize: "text-sm"
1730
- },
1731
- xl: {
1732
- padding: "1.0625rem 2.5rem",
1733
- fontSize: "text-base"
1734
- }
1735
- },
1736
- variants: [
1737
- {
1738
- id: "primary",
1739
- name: "Primary",
1740
- enabled: true,
1741
- priority: 1,
1742
- background: {
1743
- type: "solid",
1744
- colorToken: "primary"
1745
- },
1746
- borderRadius: "rounded-xl",
1747
- affordance: { iconId: "ArrowRight" },
1748
- effects: { hover: [{
1749
- effectId: "darken-background",
1750
- options: { amount: 100 }
1751
- }] }
1752
- },
1753
- {
1754
- id: "secondary",
1755
- name: "Secondary",
1756
- enabled: true,
1757
- priority: 2,
1758
- background: {
1759
- type: "surface",
1760
- role: "link"
1761
- },
1762
- borderRadius: "rounded-xl",
1763
- border: { widthClass: "border" },
1764
- affordance: { iconId: "ArrowRight" },
1765
- effects: { hover: [{
1766
- effectId: "background-on-hover",
1767
- options: { colorToken: "surfaceAlt" }
1768
- }] }
1769
- },
1770
- {
1771
- id: "outline",
1772
- name: "Outline",
1773
- enabled: true,
1774
- priority: 3,
1775
- background: {
1776
- type: "surface",
1777
- role: "link"
1778
- },
1779
- borderRadius: "rounded-xl",
1780
- border: { widthClass: "border" }
1781
- },
1782
- {
1783
- id: "ghost",
1784
- name: "Ghost",
1785
- enabled: true,
1786
- priority: 3,
1787
- background: {
1788
- type: "surface",
1789
- role: "link"
1790
- },
1791
- borderRadius: "rounded-xl"
1792
- }
1793
- ]
1794
- }
1795
- });
1796
- //#endregion
1797
- //#region ../theme-core/src/buttons/personalities/showtime-pill.ts
1798
- /**
1799
- * Showtime Pill — bold, spacious, fully rounded buttons with playful pop
1800
- * motion. Suits energetic schools, performers, festivals, and community brands
1801
- * that need calls to action to feel loud without becoming visually chaotic.
1802
- */
1803
- const showtimePill = defineButtonPersonality({
1804
- id: "showtime-pill",
1805
- name: "Showtime Pill",
1806
- description: "Bold pill buttons with uppercase labels, generous padding, and a playful pop.",
1807
- tags: {
1808
- tone: "bold",
1809
- energy: "vibrant",
1810
- motion: "expressive",
1811
- era: "modern"
1812
- },
1813
- buttonSystem: {
1814
- global: {
1815
- cornerStyle: "pill",
1816
- shadow: "low",
1817
- textTransform: "uppercase",
1818
- fontWeight: 700,
1819
- borderWidth: 2,
1820
- hoverTransform: "lift",
1821
- hoverColor: "darken",
1822
- typography: "body",
1823
- paddingPreset: "spacious",
1824
- italic: false
1825
- },
1826
- sizes: {
1827
- sm: {
1828
- padding: "0.625rem 1.25rem",
1829
- fontSize: "0.875rem"
1830
- },
1831
- md: {
1832
- padding: "0.875rem 1.75rem",
1833
- fontSize: "1rem"
1834
- },
1835
- lg: {
1836
- padding: "1.125rem 2.25rem",
1837
- fontSize: "1.125rem"
1838
- },
1839
- xl: {
1840
- padding: "1.125rem 2.25rem",
1841
- fontSize: "1.125rem"
1842
- }
1843
- },
1844
- variants: [
1845
- {
1846
- id: "primary",
1847
- name: "Primary",
1848
- enabled: true,
1849
- priority: 1,
1850
- background: {
1851
- type: "solid",
1852
- colorToken: "primary"
1853
- },
1854
- borderRadius: "rounded-full",
1855
- effects: { hover: [{ effectId: "pop" }] }
1856
- },
1857
- {
1858
- id: "secondary",
1859
- name: "Secondary",
1860
- enabled: true,
1861
- priority: 2,
1862
- background: {
1863
- type: "surface",
1864
- role: "link"
1865
- },
1866
- borderRadius: "rounded-full",
1867
- border: { widthClass: "border-2" },
1868
- effects: { hover: [{ effectId: "pop" }] }
1869
- },
1870
- {
1871
- id: "hero",
1872
- name: "Hero",
1873
- enabled: true,
1874
- priority: 1,
1875
- background: {
1876
- type: "solid",
1877
- colorToken: "secondary"
1878
- },
1879
- borderRadius: "rounded-full",
1880
- effects: { hover: [{ effectId: "pop" }] }
1881
- },
1882
- {
1883
- id: "header",
1884
- name: "Header",
1885
- enabled: true,
1886
- priority: 2,
1887
- background: {
1888
- type: "solid",
1889
- colorToken: "background"
1890
- },
1891
- borderRadius: "rounded-full",
1892
- border: { widthClass: "border-2" },
1893
- effects: { hover: [{
1894
- effectId: "background-on-hover",
1895
- options: { colorToken: "surface" }
1896
- }] }
1897
- },
1898
- {
1899
- id: "outline",
1900
- name: "Outline",
1901
- enabled: true,
1902
- priority: 3,
1903
- background: {
1904
- type: "surface",
1905
- role: "link"
1906
- },
1907
- borderRadius: "rounded-full",
1908
- border: { widthClass: "border-2" },
1909
- effects: { hover: [{
1910
- effectId: "background-on-hover",
1911
- options: { colorToken: "background" }
1912
- }] }
1913
- },
1914
- {
1915
- id: "ghost",
1916
- name: "Ghost",
1917
- enabled: true,
1918
- priority: 3,
1919
- background: {
1920
- type: "surface",
1921
- role: "link"
1922
- },
1923
- borderRadius: "rounded-full",
1924
- effects: { hover: [{
1925
- effectId: "background-on-hover",
1926
- options: { colorToken: "surface" }
1927
- }] }
1928
- }
1929
- ]
1930
- }
1931
- });
1932
- //#endregion
1933
- //#region ../theme-core/src/buttons/personalities/soft-pill.ts
1934
- /**
1935
- * Soft Pill — rounded-full pill buttons with a hover lift. The default for
1936
- * Calm Studio and Modern Wellness; reads as quietly modern and welcoming.
1937
- */
1938
- const softPill = defineButtonPersonality({
1939
- id: "soft-pill",
1940
- name: "Soft Pill",
1941
- description: "Rounded pills with a gentle lift on hover. Quietly modern.",
1942
- tags: {
1943
- tone: "classic",
1944
- energy: "calm",
1945
- motion: "subtle",
1946
- era: "organic"
1947
- },
1948
- buttonSystem: {
1949
- global: {
1950
- cornerStyle: "pill",
1951
- shadow: "low",
1952
- textTransform: "none",
1953
- fontWeight: 500,
1954
- borderWidth: 2,
1955
- hoverTransform: "lift",
1956
- hoverColor: "none"
1957
- },
1958
- variants: [
1959
- {
1960
- id: "primary",
1961
- name: "Primary",
1962
- enabled: true,
1963
- priority: 1,
1964
- background: {
1965
- type: "solid",
1966
- colorToken: "primary"
1967
- },
1968
- borderRadius: "rounded-full",
1969
- shadow: {
1970
- elevation: "low",
1971
- softness: "soft",
1972
- position: "bottom"
1973
- },
1974
- effects: {
1975
- hover: [{
1976
- effectId: "lift",
1977
- options: { translateY: "-1px" }
1978
- }],
1979
- active: [{
1980
- effectId: "scale-down",
1981
- options: { scale: "0.98" }
1982
- }]
1983
- }
1984
- },
1985
- {
1986
- id: "secondary",
1987
- name: "Secondary",
1988
- enabled: true,
1989
- priority: 2,
1990
- background: {
1991
- type: "surface",
1992
- role: "link"
1993
- },
1994
- borderRadius: "rounded-full",
1995
- border: { widthClass: "border-2" },
1996
- effects: { hover: [{
1997
- effectId: "background-on-hover",
1998
- options: { colorToken: "surface" }
1999
- }] }
2000
- },
2001
- {
2002
- id: "outline",
2003
- name: "Outline",
2004
- enabled: true,
2005
- priority: 3,
2006
- background: {
2007
- type: "surface",
2008
- role: "link"
2009
- },
2010
- borderRadius: "rounded-full",
2011
- border: { widthClass: "border" },
2012
- effects: { hover: [{
2013
- effectId: "background-on-hover",
2014
- options: { colorToken: "surface" }
2015
- }] }
2016
- },
2017
- {
2018
- id: "ghost",
2019
- name: "Ghost",
2020
- enabled: true,
2021
- priority: 3,
2022
- background: {
2023
- type: "surface",
2024
- role: "link"
2025
- },
2026
- borderRadius: "rounded-full",
2027
- effects: { hover: [{
2028
- effectId: "background-on-hover",
2029
- options: { colorToken: "surface" }
2030
- }] }
2031
- }
2032
- ]
2033
- }
2034
- });
2035
- //#endregion
2036
- //#region ../theme-core/src/buttons/personalities/two-tone-pill.ts
2037
- const solidSecondary = {
2038
- id: "secondary",
2039
- name: "Secondary",
2040
- enabled: true,
2041
- priority: 2,
2042
- background: {
2043
- type: "solid",
2044
- colorToken: unsafeAsOpaqueButtonColourToken("secondary")
2045
- },
2046
- borderRadius: "rounded-full",
2047
- shadow: {
2048
- elevation: "none",
2049
- softness: null,
2050
- position: "bottom"
2051
- },
2052
- effects: {
2053
- hover: [{
2054
- effectId: "background-on-hover-alpha",
2055
- options: {
2056
- colorToken: "secondary",
2057
- opacity: 88
2058
- }
2059
- }],
2060
- active: [{
2061
- effectId: "scale-down",
2062
- options: { scale: "0.98" }
2063
- }]
2064
- }
2065
- };
2066
- //#endregion
2067
- //#region ../theme-core/src/buttons/personalities/index.ts
2068
- const buttonPersonalities = [
2069
- softPill,
2070
- defineButtonPersonality({
2071
- id: "two-tone-pill",
2072
- name: "Two-tone Pill",
2073
- description: "Rounded pills with distinct solid primary and secondary brand colours.",
2074
- tags: softPill.tags,
2075
- buttonSystem: {
2076
- ...softPill.buttonSystem,
2077
- variants: softPill.buttonSystem.variants.map((variant) => variant.id === "secondary" ? solidSecondary : variant)
2078
- }
2079
- }),
2080
- earthPill,
2081
- confidentChip,
2082
- editorialLink,
2083
- pebble,
2084
- inkStamp,
2085
- flatInk,
2086
- brushedWash,
2087
- showtimePill,
2088
- joyStamp,
2089
- ornateRitual,
2090
- quietArrow
2091
- ];
2092
- new Map(buttonPersonalities.map((p) => [p.id, p]));
2093
- buttonPersonalities.map((personality) => ({
2094
- id: personality.id,
2095
- name: personality.name,
2096
- description: personality.description,
2097
- category: presetCategory(personality),
2098
- buttonSystem: personality.buttonSystem,
2099
- compatibility: {
2100
- ...personality.tags.tone ? { tones: [personality.tags.tone] } : {},
2101
- ...personality.tags.energy ? { energies: [personality.tags.energy] } : {}
2102
- }
2103
- }));
2104
- function presetCategory(personality) {
2105
- switch (personality.tags.era) {
2106
- case "retro": return "retro";
2107
- case "editorial": return "minimal";
2108
- case "organic": return "artistic";
2109
- case "modern": return personality.tags.tone === "bold" ? "modern" : "technical";
2110
- case "technical": return "technical";
2111
- case void 0: return "modern";
2112
- }
2113
- }
2114
- //#endregion
2115
- export { hexToRgb as n, themeButtonClassName as r, relativeLuminance as t };