@3fn/core 13.0.0 → 14.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/.kiro/agents/ada-prompt.md +80 -132
  2. package/.kiro/agents/ada-prompt.md.attribution.json +45 -0
  3. package/.kiro/agents/ada.json +44 -59
  4. package/.kiro/agents/ada.json.attribution.json +13 -0
  5. package/.kiro/agents/data-prompt.md +83 -74
  6. package/.kiro/agents/data-prompt.md.attribution.json +53 -0
  7. package/.kiro/agents/data.json +31 -38
  8. package/.kiro/agents/data.json.attribution.json +13 -0
  9. package/.kiro/agents/kenya-prompt.md +83 -72
  10. package/.kiro/agents/kenya-prompt.md.attribution.json +53 -0
  11. package/.kiro/agents/kenya.json +27 -35
  12. package/.kiro/agents/kenya.json.attribution.json +13 -0
  13. package/.kiro/agents/leonardo-prompt.md +176 -234
  14. package/.kiro/agents/leonardo-prompt.md.attribution.json +45 -0
  15. package/.kiro/agents/leonardo.json +28 -36
  16. package/.kiro/agents/leonardo.json.attribution.json +13 -0
  17. package/.kiro/agents/lina-prompt.md +110 -151
  18. package/.kiro/agents/lina-prompt.md.attribution.json +53 -0
  19. package/.kiro/agents/lina.json +46 -59
  20. package/.kiro/agents/lina.json.attribution.json +13 -0
  21. package/.kiro/agents/sparky-prompt.md +89 -72
  22. package/.kiro/agents/sparky-prompt.md.attribution.json +53 -0
  23. package/.kiro/agents/sparky.json +37 -37
  24. package/.kiro/agents/sparky.json.attribution.json +13 -0
  25. package/.kiro/agents/stacy-prompt.md +74 -48
  26. package/.kiro/agents/stacy-prompt.md.attribution.json +45 -0
  27. package/.kiro/agents/stacy.json +28 -30
  28. package/.kiro/agents/stacy.json.attribution.json +13 -0
  29. package/.kiro/agents/thurgood-prompt.md +94 -138
  30. package/.kiro/agents/thurgood-prompt.md.attribution.json +45 -0
  31. package/.kiro/agents/thurgood.json +31 -35
  32. package/.kiro/agents/thurgood.json.attribution.json +13 -0
  33. package/.kiro/steering/AI-Collaboration-Principles.md +3 -3
  34. package/.kiro/steering/Civitas-System-Overview.md +7 -16
  35. package/.kiro/steering/DesignerPunk-Systems-Overview.md +6 -6
  36. package/.kiro/steering/Spec-Feedback-Protocol.md +2 -11
  37. package/.kiro/steering/Task-Completion-Protocol.md +98 -17
  38. package/.kiro/steering/core-goals.md +3 -3
  39. package/.kiro/steering/personal-note.md +1 -1
  40. package/.kiro/steering/start-up-tasks.md +17 -6
  41. package/application-mcp-server/src/index.ts +26 -0
  42. package/dist/ComponentTokens.android.kt +12 -12
  43. package/dist/ComponentTokens.ios.swift +12 -12
  44. package/dist/ComponentTokens.web.css +3 -3
  45. package/dist/DesignTokens.android.kt +1 -1
  46. package/dist/DesignTokens.dtcg.json +8 -5
  47. package/dist/DesignTokens.figma.json +2 -2
  48. package/dist/DesignTokens.ios.swift +1 -1
  49. package/dist/DesignTokens.web.css +1 -1
  50. package/dist/android/DesignTokens.android.kt +1 -1
  51. package/dist/blend/OklchBlendCalculator.js +1 -0
  52. package/dist/blend/ThemeAwareBlendUtilities.web.d.ts +13 -2
  53. package/dist/blend/ThemeAwareBlendUtilities.web.js +6 -1
  54. package/dist/browser/designerpunk.esm.js +36 -90
  55. package/dist/browser/designerpunk.esm.min.js +33 -36
  56. package/dist/browser/designerpunk.umd.js +36 -90
  57. package/dist/browser/designerpunk.umd.min.js +47 -50
  58. package/dist/browser/tokens.css +3 -3
  59. package/dist/build/tokens/defineComponentTokens.d.ts +10 -0
  60. package/dist/build/tokens/defineComponentTokens.js +26 -0
  61. package/dist/components/core/Avatar-Base/avatar.tokens.d.ts +21 -26
  62. package/dist/components/core/Avatar-Base/avatar.tokens.js +31 -34
  63. package/dist/components/core/Avatar-Base/index.d.ts +1 -1
  64. package/dist/components/core/Avatar-Base/index.js +2 -2
  65. package/dist/components/core/Avatar-Base/platforms/web/Avatar.web.js +24 -5
  66. package/dist/components/core/Button-CTA/examples/BasicUsage.d.ts +16 -28
  67. package/dist/components/core/Button-CTA/examples/BasicUsage.js +18 -43
  68. package/dist/components/core/Button-CTA/platforms/web/ButtonCTA.web.d.ts +3 -15
  69. package/dist/components/core/Button-CTA/platforms/web/ButtonCTA.web.js +9 -58
  70. package/dist/components/core/Button-CTA/types.d.ts +0 -24
  71. package/dist/components/core/Button-CTA/types.js +6 -0
  72. package/dist/components/core/Button-Icon/buttonIcon.tokens.d.ts +28 -14
  73. package/dist/components/core/Button-Icon/buttonIcon.tokens.js +35 -20
  74. package/dist/components/core/Input-Text-Base/types.d.ts +13 -1
  75. package/dist/components/core/Input-Text-Password/platforms/web/InputTextPassword.web.js +11 -2
  76. package/dist/generators/DTCGFormatGenerator.js +8 -0
  77. package/dist/generators/TokenFileGenerator.js +7 -2
  78. package/dist/integration/BuildErrorHandler.js +2 -2
  79. package/dist/ios/DesignTokens.ios.swift +1 -1
  80. package/dist/mcp/application-mcp.js +24 -0
  81. package/dist/mcp/docs-mcp.js +130 -15
  82. package/dist/mcp/product-mcp.js +25 -0
  83. package/dist/tokens/OpacityTokens.js +1 -1
  84. package/dist/tokens/component/progress.d.ts +65 -5
  85. package/dist/tokens/component/progress.js +79 -18
  86. package/dist/tokens/semantic/BlendTokens.d.ts +10 -3
  87. package/dist/tokens/semantic/BlendTokens.js +17 -5
  88. package/dist/tokens/semantic/OpacityTokens.d.ts +4 -4
  89. package/dist/tokens/semantic/OpacityTokens.js +4 -4
  90. package/dist/types/ComponentTypes.d.ts +1 -1
  91. package/dist/types/generated/TokenTypes.d.ts +1 -1
  92. package/dist/types/generated/TokenTypes.js +1 -1
  93. package/dist/validators/StemmaTokenUsageValidator.js +3 -2
  94. package/dist/web/DesignTokens.web.css +1 -1
  95. package/governance/BUILD-SYSTEM-SETUP.md +1 -2
  96. package/governance/Component-Development-Guide.md +23 -13
  97. package/governance/Component-Development-Standards.md +21 -20
  98. package/governance/Component-Family-Avatar.md +6 -7
  99. package/governance/Component-Family-Badge.md +19 -20
  100. package/governance/Component-Family-Button.md +30 -43
  101. package/governance/Component-Family-Chip.md +14 -15
  102. package/governance/Component-Family-Container.md +12 -13
  103. package/governance/Component-Family-Data-Display.md +1 -2
  104. package/governance/Component-Family-Divider.md +1 -2
  105. package/governance/Component-Family-Form-Inputs.md +65 -65
  106. package/governance/Component-Family-Icon.md +9 -10
  107. package/governance/Component-Family-Loading.md +1 -2
  108. package/governance/Component-Family-Modal.md +1 -2
  109. package/governance/Component-Family-Navigation.md +1 -2
  110. package/governance/Component-Family-Progress.md +0 -1
  111. package/governance/Component-Inheritance-Structures.md +219 -99
  112. package/governance/Component-MCP-Document-Template.md +6 -5
  113. package/governance/Component-Primitive-vs-Semantic-Philosophy.md +1 -1
  114. package/governance/Component-Quick-Reference.md +33 -33
  115. package/governance/Component-Readiness-Status.md +59 -44
  116. package/governance/Component-Templates.md +57 -61
  117. package/governance/Contract-System-Reference.md +7 -7
  118. package/governance/MCP-Integration-Guide.md +1 -1
  119. package/governance/Process-Cross-Reference-Standards.md +31 -13
  120. package/governance/Process-Development-Workflow.md +49 -59
  121. package/governance/Process-File-Organization.md +25 -28
  122. package/governance/Process-Hook-Operations.md +22 -11
  123. package/governance/Process-Orchestration-Model-Selection.md +92 -0
  124. package/governance/Process-Spec-Planning.md +98 -52
  125. package/governance/Process-Task-Type-Definitions.md +80 -4
  126. package/governance/Product-Handoff-Protocol.md +2 -0
  127. package/governance/Rosetta-System-Architecture.md +13 -11
  128. package/governance/Test-Behavioral-Contract-Validation.md +38 -31
  129. package/governance/Test-Failure-Audit-Methodology.md +1 -1
  130. package/governance/Token-Family-Accessibility.md +1 -2
  131. package/governance/Token-Family-Blend.md +18 -16
  132. package/governance/Token-Family-Blur.md +0 -1
  133. package/governance/Token-Family-Border.md +1 -2
  134. package/governance/Token-Family-Color.md +0 -1
  135. package/governance/Token-Family-Glow.md +1 -2
  136. package/governance/Token-Family-Layering.md +0 -1
  137. package/governance/Token-Family-Motion.md +1 -2
  138. package/governance/Token-Family-Opacity.md +0 -1
  139. package/governance/Token-Family-Radius.md +1 -2
  140. package/governance/Token-Family-Responsive.md +1 -2
  141. package/governance/Token-Family-Shadow.md +1 -2
  142. package/governance/Token-Family-Sizing.md +0 -1
  143. package/governance/Token-Family-Spacing.md +1 -2
  144. package/governance/Token-Family-Typography.md +1 -2
  145. package/governance/Token-Governance.md +8 -8
  146. package/governance/Token-Quick-Reference.md +47 -34
  147. package/governance/Token-Resolution-Patterns.md +1 -1
  148. package/governance/Token-Semantic-Structure.md +1 -1
  149. package/governance/Web-Authoring-Standards.md +5 -5
  150. package/governance/browser-distribution-guide.md +1 -4
  151. package/governance/classification-map.md +474 -0
  152. package/governance/completion-documentation-guide.md +23 -37
  153. package/governance/component-meta-authoring-guide.md +1 -1
  154. package/governance/cross-platform-vs-platform-specific-decision-framework.md +1 -1
  155. package/governance/platform-implementation-guidelines.md +2 -3
  156. package/governance/release-management-system.md +28 -63
  157. package/governance/rosetta-system-principles.md +8 -6
  158. package/governance/stemma-system-principles.md +18 -17
  159. package/mcp-server/src/index.ts +24 -6
  160. package/mcp-server/src/indexer/DocumentIndexer.ts +119 -9
  161. package/mcp-server/src/indexer/__tests__/bare-id-crossrefs.test.ts +250 -0
  162. package/mcp-server/src/indexer/cross-ref-parser.ts +29 -1
  163. package/mcp-server/src/indexer/index-health.ts +27 -2
  164. package/mcp-server/src/query/__tests__/find-docs-calibration.test.ts +11 -26
  165. package/mcp-server/src/relocation-integrity-gate/__tests__/relocation-integrity-gate.test.ts +72 -5
  166. package/mcp-server/src/relocation-integrity-gate/relocation-integrity-gate.ts +81 -24
  167. package/mcp-server/src/tools/list-cross-references.ts +2 -2
  168. package/package.json +24 -26
  169. package/src/__tests__/browser-distribution/css-bundling.test.ts +6 -4
  170. package/src/__tests__/console-allowlist.json +14 -0
  171. package/src/__tests__/console-fail-setup.ts +169 -0
  172. package/src/__tests__/integration/Spec107-DesignLanguageContext.test.ts +16 -0
  173. package/src/__tests__/stemma-system/behavioral-contract-validation.test.ts +70 -17
  174. package/src/__tests__/stemma-system/contract-catalog-name-validation.test.ts +28 -0
  175. package/src/__tests__/stemma-system/form-inputs-contracts.test.ts +223 -16
  176. package/src/__tests__/stemma-system/input-text-native-base-call-alignment.test.ts +298 -0
  177. package/src/blend/OklchBlendCalculator.ts +3 -0
  178. package/src/blend/ThemeAwareBlendUtilities.android.kt +3 -0
  179. package/src/blend/ThemeAwareBlendUtilities.ios.swift +3 -0
  180. package/src/blend/ThemeAwareBlendUtilities.web.ts +9 -1
  181. package/src/blend/__tests__/InteractionStateAudit.test.ts +12 -9
  182. package/src/build/errors/__tests__/ErrorHandler.integration.test.ts +8 -0
  183. package/src/build/errors/__tests__/ErrorHandler.test.ts +5 -0
  184. package/src/build/tokens/__tests__/defineComponentTokens.test.ts +113 -0
  185. package/src/build/tokens/defineComponentTokens.ts +43 -1
  186. package/src/build/workflow/__tests__/CICDIntegration.test.ts +12 -1
  187. package/src/cli/__tests__/init.test.ts +45 -11
  188. package/src/components/core/Avatar-Base/Avatar-Base.schema.yaml +1 -1
  189. package/src/components/core/Avatar-Base/__tests__/Avatar.accessibility.test.ts +121 -7
  190. package/src/components/core/Avatar-Base/__tests__/Avatar.image.test.ts +3 -0
  191. package/src/components/core/Avatar-Base/__tests__/Avatar.test.ts +15 -6
  192. package/src/components/core/Avatar-Base/avatar.tokens.ts +31 -34
  193. package/src/components/core/Avatar-Base/contracts.yaml +11 -1
  194. package/src/components/core/Avatar-Base/index.ts +1 -1
  195. package/src/components/core/Avatar-Base/platforms/web/Avatar.web.ts +24 -5
  196. package/src/components/core/Badge-Count-Base/contracts.yaml +1 -1
  197. package/src/components/core/Badge-Label-Base/contracts.yaml +1 -1
  198. package/src/components/core/Button-CTA/Button-CTA.schema.yaml +2 -12
  199. package/src/components/core/Button-CTA/README.md +3 -6
  200. package/src/components/core/Button-CTA/__tests__/ButtonCTA.test.ts +35 -89
  201. package/src/components/core/Button-CTA/__tests__/setup.test.ts +0 -2
  202. package/src/components/core/Button-CTA/__tests__/test-utils.ts +0 -2
  203. package/src/components/core/Button-CTA/contracts.yaml +6 -29
  204. package/src/components/core/Button-CTA/examples/BasicUsage.html +2 -14
  205. package/src/components/core/Button-CTA/examples/BasicUsage.tsx +17 -44
  206. package/src/components/core/Button-CTA/platforms/android/ButtonCTA.android.kt +12 -20
  207. package/src/components/core/Button-CTA/platforms/ios/ButtonCTA.ios.swift +12 -51
  208. package/src/components/core/Button-CTA/platforms/web/ButtonCTA.web.css +2 -26
  209. package/src/components/core/Button-CTA/platforms/web/ButtonCTA.web.ts +18 -71
  210. package/src/components/core/Button-CTA/types.ts +10 -28
  211. package/src/components/core/Button-Icon/buttonIcon.tokens.ts +43 -27
  212. package/src/components/core/Chip-Base/__tests__/ChipBase.test.ts +13 -0
  213. package/src/components/core/Chip-Filter/__tests__/ChipFilter.test.ts +13 -0
  214. package/src/components/core/Chip-Input/__tests__/ChipInput.test.ts +13 -0
  215. package/src/components/core/Input-Text-Base/Input-Text-Base.schema.yaml +30 -2
  216. package/src/components/core/Input-Text-Base/README.md +25 -2
  217. package/src/components/core/Input-Text-Base/__tests__/focusIndicators.test.ts +16 -15
  218. package/src/components/core/Input-Text-Base/contracts.yaml +90 -0
  219. package/src/components/core/Input-Text-Base/platforms/android/InputTextBase.android.kt +26 -12
  220. package/src/components/core/Input-Text-Base/platforms/ios/InputTextBase.ios.swift +195 -59
  221. package/src/components/core/Input-Text-Base/types.ts +13 -1
  222. package/src/components/core/Input-Text-Email/Input-Text-Email.schema.yaml +5 -1
  223. package/src/components/core/Input-Text-Email/README.md +8 -7
  224. package/src/components/core/Input-Text-Email/platforms/android/InputTextEmail.android.kt +1 -4
  225. package/src/components/core/Input-Text-Email/platforms/ios/InputTextEmail.ios.swift +2 -16
  226. package/src/components/core/Input-Text-Password/Input-Text-Password.schema.yaml +10 -3
  227. package/src/components/core/Input-Text-Password/README.md +9 -8
  228. package/src/components/core/Input-Text-Password/contracts.yaml +5 -0
  229. package/src/components/core/Input-Text-Password/platforms/android/InputTextPassword.android.kt +17 -7
  230. package/src/components/core/Input-Text-Password/platforms/ios/InputTextPassword.ios.swift +22 -20
  231. package/src/components/core/Input-Text-Password/platforms/web/InputTextPassword.web.ts +11 -2
  232. package/src/components/core/Input-Text-PhoneNumber/Input-Text-PhoneNumber.schema.yaml +5 -1
  233. package/src/components/core/Input-Text-PhoneNumber/README.md +9 -8
  234. package/src/components/core/Input-Text-PhoneNumber/platforms/android/InputTextPhoneNumber.android.kt +2 -5
  235. package/src/components/core/Input-Text-PhoneNumber/platforms/ios/InputTextPhoneNumber.ios.swift +3 -17
  236. package/src/components/core/Nav-Header-App/contracts.yaml +1 -1
  237. package/src/components/core/Nav-SegmentedChoice-Base/contracts.yaml +1 -1
  238. package/src/components/core/Progress-Indicator-Connector-Base/contracts.yaml +1 -1
  239. package/src/components/core/Progress-Indicator-Label-Base/contracts.yaml +1 -1
  240. package/src/components/core/Progress-Indicator-Node-Base/contracts.yaml +1 -1
  241. package/src/components/core/Progress-Stepper-Base/__tests__/StepperBase.test.ts +5 -2
  242. package/src/components/core/Progress-Stepper-Detailed/__tests__/StepperDetailed.test.ts +5 -2
  243. package/src/generators/DTCGFormatGenerator.ts +6 -0
  244. package/src/generators/TokenFileGenerator.ts +7 -2
  245. package/src/generators/__tests__/DTCGConfigOptions.test.ts +14 -5
  246. package/src/integration/BuildErrorHandler.ts +2 -2
  247. package/src/tokens/OpacityTokens.ts +1 -1
  248. package/src/tokens/__tests__/OpacityTokens.test.ts +3 -1
  249. package/src/tokens/__tests__/ProgressTokenCompliance.test.ts +5 -3
  250. package/src/tokens/__tests__/ProgressTokenFormulas.test.ts +11 -11
  251. package/src/tokens/__tests__/ProgressTokenTranslation.test.ts +22 -20
  252. package/src/tokens/component/progress.ts +83 -21
  253. package/src/tokens/semantic/BlendTokens.ts +26 -5
  254. package/src/tokens/semantic/OpacityTokens.ts +4 -4
  255. package/src/types/ComponentTypes.ts +1 -1
  256. package/src/types/generated/TokenTypes.ts +1 -1
  257. package/src/validators/StemmaTokenUsageValidator.ts +3 -2
  258. package/token-index/components.yaml +8 -8
  259. package/token-index/semantics.yaml +1 -2
  260. package/src/tools/release/__tests__/ChangeClassifier.test.ts +0 -133
  261. package/src/tools/release/__tests__/ChangeExtractor.test.ts +0 -222
  262. package/src/tools/release/__tests__/GitHubPublisher.test.ts +0 -240
  263. package/src/tools/release/__tests__/NotesRenderer.test.ts +0 -142
  264. package/src/tools/release/__tests__/NpmPublisher.test.ts +0 -289
  265. package/src/tools/release/__tests__/PipelineIntegration.test.ts +0 -188
  266. package/src/tools/release/__tests__/ReleasePipeline.test.ts +0 -192
  267. package/src/tools/release/__tests__/SemanticVersionValidator.test.ts +0 -49
  268. package/src/tools/release/__tests__/SummaryScanner.test.ts +0 -141
  269. package/src/tools/release/__tests__/TagResolver.test.ts +0 -91
  270. package/src/tools/release/__tests__/VersionCalculator.test.ts +0 -270
  271. package/src/tools/release/__tests__/helpers/NpmMockHelper.ts +0 -80
  272. package/src/tools/release/cli/ReleasePipeline.ts +0 -165
  273. package/src/tools/release/cli/release-tool.ts +0 -107
  274. package/src/tools/release/pipeline/ChangeClassifier.ts +0 -61
  275. package/src/tools/release/pipeline/ChangeExtractor.ts +0 -87
  276. package/src/tools/release/pipeline/NotesRenderer.ts +0 -66
  277. package/src/tools/release/pipeline/SummaryScanner.ts +0 -70
  278. package/src/tools/release/pipeline/TagResolver.ts +0 -40
  279. package/src/tools/release/pipeline/VersionCalculator.ts +0 -375
  280. package/src/tools/release/publishers/GitHubPublisher.ts +0 -228
  281. package/src/tools/release/publishers/NpmPublisher.ts +0 -196
  282. package/src/tools/release/release-config.json +0 -5
  283. package/src/tools/release/types/index.ts +0 -282
  284. package/src/tools/release/validators/SemanticVersionValidator.ts +0 -67
@@ -11,7 +11,7 @@
11
11
  * while maintaining API consistency with web and Android platforms.
12
12
  *
13
13
  * Uses theme-aware blend utilities (Color extensions with SwiftUI environment) for
14
- * state colors (hover, pressed, disabled, icon) instead of opacity or scale workarounds.
14
+ * state colors (hover, pressed, icon) instead of opacity or scale workarounds.
15
15
  * This ensures cross-platform consistency with Web and Android implementations.
16
16
  *
17
17
  * Part of the DesignerPunk CTA Button Component system.
@@ -23,7 +23,7 @@
23
23
  import SwiftUI
24
24
 
25
25
  // Import theme-aware blend utilities (Color extensions from ThemeAwareBlendUtilities.ios.swift)
26
- // These provide semantic blend methods: hoverBlend(), pressedBlend(), disabledBlend(), iconBlend()
26
+ // These provide semantic blend methods: hoverBlend(), pressedBlend(), iconBlend()
27
27
  // @see Requirements: 11.1, 11.2, 11.3 - Theme-aware utilities
28
28
 
29
29
  /**
@@ -65,8 +65,8 @@ enum ButtonCTAStyle {
65
65
  * three size variants, three visual styles, optional leading icons, and
66
66
  * theme-aware blend utilities for state colors.
67
67
  *
68
- * Uses theme-aware Color extensions (hoverBlend(), pressedBlend(), disabledBlend(),
69
- * iconBlend()) with SwiftUI environment for automatic theme color updates.
68
+ * Uses theme-aware Color extensions (hoverBlend(), pressedBlend(), iconBlend())
69
+ * with SwiftUI environment for automatic theme color updates.
70
70
  *
71
71
  * Usage:
72
72
  * ```swift
@@ -97,7 +97,7 @@ enum ButtonCTAStyle {
97
97
  * Requirements:
98
98
  * - 1.1-1.7: Size variants (small: 40px, medium: 48px, large: 56px)
99
99
  * - 2.1-2.4: Visual styles (primary, secondary, tertiary)
100
- * - 7.1-7.4: Blend utility state colors (hover, pressed, disabled, icon)
100
+ * - 7.1-7.4: Blend utility state colors (hover, pressed, icon)
101
101
  * - 8.1-8.6: Icon support with leading position
102
102
  * - 11.1-11.3: Theme-aware blend utilities with SwiftUI environment
103
103
  * - 13.1-13.4: Touch target accessibility (44px minimum)
@@ -125,10 +125,7 @@ struct ButtonCTA: View {
125
125
 
126
126
  /// Optional test ID for automated testing
127
127
  let testID: String?
128
-
129
- /// Optional disabled state (default: false)
130
- let disabled: Bool
131
-
128
+
132
129
  // MARK: - State
133
130
 
134
131
  /// Tracks pressed state for scale transform animation
@@ -149,7 +146,6 @@ struct ButtonCTA: View {
149
146
  * - noWrap: Prevent text wrapping (default: false)
150
147
  * - onPress: Click/tap handler (required)
151
148
  * - testID: Optional test identifier
152
- * - disabled: Optional disabled state (default: false)
153
149
  */
154
150
  init(
155
151
  label: String,
@@ -158,8 +154,7 @@ struct ButtonCTA: View {
158
154
  icon: String? = nil,
159
155
  noWrap: Bool = false,
160
156
  onPress: @escaping () -> Void,
161
- testID: String? = nil,
162
- disabled: Bool = false
157
+ testID: String? = nil
163
158
  ) {
164
159
  self.label = label
165
160
  self.size = size
@@ -168,7 +163,6 @@ struct ButtonCTA: View {
168
163
  self.noWrap = noWrap
169
164
  self.onPress = onPress
170
165
  self.testID = testID
171
- self.disabled = disabled
172
166
  }
173
167
 
174
168
  // MARK: - Body
@@ -213,15 +207,12 @@ struct ButtonCTA: View {
213
207
  .simultaneousGesture(
214
208
  DragGesture(minimumDistance: 0)
215
209
  .onChanged { _ in
216
- if !disabled {
217
- isPressed = true
218
- }
210
+ isPressed = true
219
211
  }
220
212
  .onEnded { _ in
221
213
  isPressed = false
222
214
  }
223
215
  )
224
- .disabled(disabled)
225
216
  // Requirement 13.1-13.4, 16.4: Accessibility identifier for testing
226
217
  .accessibilityIdentifier(testID ?? "")
227
218
  // Requirement 17.4: Respect safe area insets for full-width buttons
@@ -230,14 +221,11 @@ struct ButtonCTA: View {
230
221
 
231
222
  // MARK: - Blend Color Computed Properties
232
223
 
233
- /// Current background color based on state (normal, hover, pressed, disabled)
224
+ /// Current background color based on state (normal, pressed)
234
225
  /// Uses theme-aware blend utilities (Color extensions) for cross-platform consistency
235
- /// @see Requirements: 7.1, 7.2, 7.3, 11.1, 11.2, 11.3
226
+ /// @see Requirements: 7.1, 7.2, 11.1, 11.2, 11.3
236
227
  private var currentBackgroundColor: Color {
237
- if disabled {
238
- // @see Requirements: 7.3 - Disabled uses desaturate(color.primary, blend.disabledDesaturate)
239
- return disabledBackgroundColor
240
- } else if isPressed {
228
+ if isPressed {
241
229
  // @see Requirements: 7.2 - Pressed uses darkerBlend(color.primary, blend.pressedDarker)
242
230
  return pressedBackgroundColor
243
231
  } else {
@@ -260,20 +248,6 @@ struct ButtonCTA: View {
260
248
  }
261
249
  }
262
250
 
263
- /// Disabled state background color using theme-aware blend utility
264
- /// Uses disabledBlend() which applies desaturate with blend.disabledDesaturate (12%)
265
- /// @see Requirements: 7.3, 11.1, 11.2, 11.3
266
- private var disabledBackgroundColor: Color {
267
- switch style {
268
- case .primary:
269
- return theme.colorActionPrimary.disabledBlend()
270
- case .secondary:
271
- return theme.colorStructureCanvas
272
- case .tertiary:
273
- return Color.clear
274
- }
275
- }
276
-
277
251
  // MARK: - Size-Based Computed Properties
278
252
 
279
253
  /// Typography token based on button size
@@ -532,20 +506,7 @@ struct ButtonCTA_Previews: PreviewProvider {
532
506
  onPress: { print("Confirm pressed") }
533
507
  )
534
508
  }
535
-
536
- Divider()
537
-
538
- // Disabled state
539
- Text("Disabled State")
540
- .font(.headline)
541
-
542
- VStack(spacing: 12) {
543
- ButtonCTA(
544
- label: "Disabled Button",
545
- disabled: true,
546
- onPress: { print("Should not print") }
547
- )
548
- }
509
+
549
510
  }
550
511
  .padding()
551
512
  }
@@ -275,7 +275,7 @@
275
275
  * The --_cta-hover-bg custom property is set by the component
276
276
  * using darkerBlend(color.primary, blend.hoverDarker) = 8% darker.
277
277
  */
278
- .button-cta--primary:hover:not(:disabled) {
278
+ .button-cta--primary:hover {
279
279
  background-color: var(--_cta-hover-bg);
280
280
  }
281
281
 
@@ -288,7 +288,7 @@
288
288
  * The --_cta-pressed-bg custom property is set by the component
289
289
  * using darkerBlend(color.primary, blend.pressedDarker) = 12% darker.
290
290
  */
291
- .button-cta--primary:active:not(:disabled) {
291
+ .button-cta--primary:active {
292
292
  background-color: var(--_cta-pressed-bg);
293
293
  }
294
294
 
@@ -318,30 +318,6 @@
318
318
  outline: none;
319
319
  }
320
320
 
321
- /**
322
- * Disabled state.
323
- *
324
- * Uses blend utility calculated color (desaturate with blend.disabledDesaturate)
325
- * instead of opacity workaround for cross-platform consistency.
326
- *
327
- * The --button-disabled-color custom property is set by the component
328
- * using desaturate(color.primary, blend.disabledDesaturate) = 12% less saturated.
329
- *
330
- * - Cursor changes to not-allowed
331
- * - Prevents interaction
332
- * - Maintains color contrast for accessibility
333
- */
334
- .button-cta:disabled,
335
- .button-cta--disabled {
336
- cursor: not-allowed;
337
- pointer-events: none;
338
- }
339
-
340
- .button-cta--primary:disabled,
341
- .button-cta--primary.button-cta--disabled {
342
- background-color: var(--_cta-disabled-bg);
343
- }
344
-
345
321
  /* ==========================================================================
346
322
  Responsive Behavior
347
323
  ========================================================================== */
@@ -12,7 +12,7 @@
12
12
  * composition pattern as iOS and Android platforms. This ensures cross-platform
13
13
  * consistency and single source of truth for icon rendering.
14
14
  *
15
- * Uses theme-aware blend utilities for state colors (hover, pressed, disabled, icon)
15
+ * Uses theme-aware blend utilities for state colors (hover, pressed, icon)
16
16
  * instead of opacity or filter workarounds. This ensures cross-platform consistency
17
17
  * with iOS and Android implementations.
18
18
  *
@@ -86,13 +86,12 @@ function getIconSizeForButton(buttonSize: ButtonSize): IconBaseSize {
86
86
  * - Semantic `<button>` element with proper accessibility
87
87
  * - Token-based styling via CSS custom properties
88
88
  * - Supports text wrapping by default (accessibility-first)
89
- * - Uses blend utilities for state colors (hover, pressed, disabled, icon)
89
+ * - Uses blend utilities for state colors (hover, pressed, icon)
90
90
  * - WCAG 2.1 AA compliant:
91
91
  * - Keyboard navigation (Tab, Enter, Space)
92
92
  * - Focus indicators with 3:1 contrast ratio
93
93
  * - Color contrast 4.5:1 for all styles
94
94
  * - Screen reader support with ARIA attributes
95
- * - Proper disabled state handling
96
95
  *
97
96
  * @example
98
97
  * ```html
@@ -106,7 +105,6 @@ function getIconSizeForButton(buttonSize: ButtonSize): IconBaseSize {
106
105
  * variant="primary"
107
106
  * icon="arrow-right"
108
107
  * no-wrap="false"
109
- * disabled="false"
110
108
  * test-id="submit-button"
111
109
  * ></button-cta>
112
110
  * ```
@@ -143,7 +141,6 @@ export class ButtonCTA extends HTMLElement {
143
141
  // Cached blend colors for state styling
144
142
  private _hoverColor: string = '';
145
143
  private _pressedColor: string = '';
146
- private _disabledColor: string = '';
147
144
  private _iconColor: string = '';
148
145
  private _iconOpticalBalanceColor: string = '';
149
146
 
@@ -153,7 +150,7 @@ export class ButtonCTA extends HTMLElement {
153
150
  * When these attributes change, attributeChangedCallback is invoked.
154
151
  */
155
152
  static get observedAttributes(): string[] {
156
- return ['label', 'size', 'variant', 'icon', 'no-wrap', 'disabled', 'test-id'];
153
+ return ['label', 'size', 'variant', 'icon', 'no-wrap', 'test-id'];
157
154
  }
158
155
 
159
156
  constructor() {
@@ -219,15 +216,14 @@ export class ButtonCTA extends HTMLElement {
219
216
  * Calculate blend colors from CSS custom properties.
220
217
  *
221
218
  * Reads base colors from CSS custom properties and applies theme-aware blend
222
- * utilities to generate state colors (hover, pressed, disabled, icon).
223
- *
219
+ * utilities to generate state colors (hover, pressed, icon).
220
+ *
224
221
  * Uses getBlendUtilities() factory functions instead of direct blend calculations
225
222
  * for cross-platform consistency with iOS and Android implementations.
226
- *
223
+ *
227
224
  * State color mappings:
228
225
  * - Hover: darkerBlend(color.action.primary, blend.hoverDarker) - 8% darker
229
226
  * - Pressed: darkerBlend(color.action.primary, blend.pressedDarker) - 12% darker
230
- * - Disabled: desaturate(color.action.primary, blend.disabledDesaturate) - 12% less saturated
231
227
  * - Icon: lighterBlend(color.contrast.onAction, blend.iconLighter) - 8% lighter
232
228
  *
233
229
  * @see Requirements: 7.1, 7.2, 7.3, 7.4 - Button-CTA state colors
@@ -258,10 +254,7 @@ export class ButtonCTA extends HTMLElement {
258
254
 
259
255
  // @see Requirements: 7.2 - Pressed uses darkerBlend(color.action.primary, blend.pressedDarker)
260
256
  this._pressedColor = this._blendUtils.pressedColor(primaryColor);
261
-
262
- // @see Requirements: 7.3 - Disabled uses desaturate(color.action.primary, blend.disabledDesaturate)
263
- this._disabledColor = this._blendUtils.disabledColor(primaryColor);
264
-
257
+
265
258
  // @see Requirements: 7.4 - Icon uses lighterBlend(color.contrast.onAction, blend.iconLighter)
266
259
  // Icon for primary buttons: provides optical balance for icons on primary background
267
260
  this._iconColor = this._blendUtils.iconColor(onActionColor);
@@ -371,24 +364,6 @@ export class ButtonCTA extends HTMLElement {
371
364
  this.setAttribute('no-wrap', value.toString());
372
365
  }
373
366
 
374
- /**
375
- * Get the disabled state.
376
- */
377
- get disabled(): boolean {
378
- return this.hasAttribute('disabled');
379
- }
380
-
381
- /**
382
- * Set the disabled state.
383
- */
384
- set disabled(value: boolean) {
385
- if (value) {
386
- this.setAttribute('disabled', '');
387
- } else {
388
- this.removeAttribute('disabled');
389
- }
390
- }
391
-
392
367
  /**
393
368
  * Get the test ID.
394
369
  */
@@ -451,17 +426,15 @@ export class ButtonCTA extends HTMLElement {
451
426
  const variant = this.buttonVariant;
452
427
  const icon = this.icon;
453
428
  const noWrap = this.noWrap;
454
- const disabled = this.disabled;
455
429
  const testID = this.testID;
456
-
430
+
457
431
  // Generate class names
458
432
  const buttonClasses = [
459
433
  'button-cta',
460
434
  `button-cta--${size}`,
461
- `button-cta--${variant}`,
462
- disabled ? 'button-cta--disabled' : ''
463
- ].filter(Boolean).join(' ');
464
-
435
+ `button-cta--${variant}`
436
+ ].join(' ');
437
+
465
438
  // Get icon size for button size variant
466
439
  // Icon sizes are type-safe mapped from button size:
467
440
  // - Small/Medium: 24px (iconBaseSize100)
@@ -480,7 +453,6 @@ export class ButtonCTA extends HTMLElement {
480
453
  const blendColorStyles = `
481
454
  --_cta-hover-bg: ${this._hoverColor};
482
455
  --_cta-pressed-bg: ${this._pressedColor};
483
- --_cta-disabled-bg: ${this._disabledColor};
484
456
  --_cta-icon-color: ${this._iconColor};
485
457
  --_cta-icon-optical: ${this._iconOpticalBalanceColor};
486
458
  `;
@@ -491,11 +463,10 @@ export class ButtonCTA extends HTMLElement {
491
463
  // @see Requirements: 8.2, 8.3 (components render correctly with interactivity)
492
464
  this._shadowRoot.innerHTML = `
493
465
  <style>${buttonStyles}</style>
494
- <button
466
+ <button
495
467
  class="${buttonClasses}"
496
468
  type="button"
497
469
  role="button"
498
- ${disabled ? 'disabled aria-disabled="true"' : 'aria-disabled="false"'}
499
470
  ${testIDAttr}
500
471
  aria-label="${label}"
501
472
  style="${blendColorStyles}"
@@ -536,34 +507,23 @@ export class ButtonCTA extends HTMLElement {
536
507
  const variant = this.buttonVariant;
537
508
  const icon = this.icon;
538
509
  const noWrap = this.noWrap;
539
- const disabled = this.disabled;
540
510
  const testID = this.testID;
541
-
511
+
542
512
  // Get icon size for button size variant
543
513
  const iconSize: IconBaseSize = getIconSizeForButton(size);
544
-
514
+
545
515
  // ─────────────────────────────────────────────────────────────────
546
516
  // Update button element
547
517
  // ─────────────────────────────────────────────────────────────────
548
-
518
+
549
519
  // Update CSS class (preserves element identity for transitions)
550
520
  const buttonClasses = [
551
521
  'button-cta',
552
522
  `button-cta--${size}`,
553
- `button-cta--${variant}`,
554
- disabled ? 'button-cta--disabled' : ''
555
- ].filter(Boolean).join(' ');
523
+ `button-cta--${variant}`
524
+ ].join(' ');
556
525
  this._button.className = buttonClasses;
557
-
558
- // Update disabled state
559
- if (disabled) {
560
- this._button.setAttribute('disabled', '');
561
- this._button.setAttribute('aria-disabled', 'true');
562
- } else {
563
- this._button.removeAttribute('disabled');
564
- this._button.setAttribute('aria-disabled', 'false');
565
- }
566
-
526
+
567
527
  // Update aria-label
568
528
  this._button.setAttribute('aria-label', label);
569
529
 
@@ -577,7 +537,6 @@ export class ButtonCTA extends HTMLElement {
577
537
  // Update blend color CSS custom properties
578
538
  this._button.style.setProperty('--_cta-hover-bg', this._hoverColor);
579
539
  this._button.style.setProperty('--_cta-pressed-bg', this._pressedColor);
580
- this._button.style.setProperty('--_cta-disabled-bg', this._disabledColor);
581
540
  this._button.style.setProperty('--_cta-icon-color', this._iconColor);
582
541
  this._button.style.setProperty('--_cta-icon-optical', this._iconOpticalBalanceColor);
583
542
 
@@ -638,13 +597,6 @@ export class ButtonCTA extends HTMLElement {
638
597
  * Dispatches a custom 'press' event that bubbles up to parent elements.
639
598
  */
640
599
  private _handleClick = (event: Event): void => {
641
- // Don't dispatch if disabled
642
- if (this.disabled) {
643
- event.preventDefault();
644
- event.stopPropagation();
645
- return;
646
- }
647
-
648
600
  // Dispatch custom 'press' event
649
601
  this.dispatchEvent(new CustomEvent('press', {
650
602
  bubbles: true,
@@ -663,11 +615,6 @@ export class ButtonCTA extends HTMLElement {
663
615
  * @param event - The keyboard event
664
616
  */
665
617
  private _handleKeyDown = (event: KeyboardEvent): void => {
666
- // Don't handle if disabled
667
- if (this.disabled) {
668
- return;
669
- }
670
-
671
618
  // Handle Enter and Space keys (WCAG 2.1 AA keyboard navigation)
672
619
  if (event.key === 'Enter' || event.key === ' ') {
673
620
  event.preventDefault(); // Prevent default space scrolling
@@ -82,7 +82,6 @@ export type ButtonStyle = 'primary' | 'secondary' | 'tertiary';
82
82
  * variant="primary"
83
83
  * icon="arrow-right"
84
84
  * noWrap={false}
85
- * disabled={false}
86
85
  * testID="submit-button"
87
86
  * onPress={handleSubmit}
88
87
  * />
@@ -197,15 +196,13 @@ export interface ButtonProps {
197
196
 
198
197
  /**
199
198
  * Click/tap handler (required)
200
- *
199
+ *
201
200
  * Callback function invoked when the button is clicked or tapped.
202
- * Not called when button is disabled.
203
- *
201
+ *
204
202
  * @remarks
205
203
  * - Function signature: `() => void`
206
- * - Not invoked when `disabled` is true
207
204
  * - Triggered by click, tap, Enter key, or Space key
208
- *
205
+ *
209
206
  * @example
210
207
  * ```typescript
211
208
  * onPress={() => console.log('Clicked')}
@@ -232,26 +229,11 @@ export interface ButtonProps {
232
229
  * ```
233
230
  */
234
231
  testID?: string;
235
-
236
- /**
237
- * Optional disabled state (default: false)
238
- *
239
- * When true, the button is non-interactive and visually indicates
240
- * disabled state. The onPress handler is not called when disabled.
241
- *
242
- * @defaultValue false
243
- *
244
- * @remarks
245
- * - Disabled buttons are not keyboard focusable
246
- * - Screen readers announce disabled state
247
- * - Visual styling indicates non-interactive state
248
- *
249
- * @example
250
- * ```typescript
251
- * disabled={false} // Interactive (default)
252
- * disabled={true} // Non-interactive
253
- * disabled={isSubmitting} // Conditional disable
254
- * ```
255
- */
256
- disabled?: boolean;
257
232
  }
233
+
234
+ // NO DISABLED STATES
235
+ // DesignerPunk does not support disabled states for usability and
236
+ // accessibility reasons. If an action is unavailable, the component
237
+ // should not be rendered. For in-flight async actions, use the loading
238
+ // state (state_loading) instead.
239
+ // Ruled by Peter 2026-07-15 (Button-CTA disabled-state adjudication).
@@ -1,26 +1,35 @@
1
1
  /**
2
2
  * Button-Icon Component Token Definitions
3
- *
3
+ *
4
4
  * Stemma System naming: [Family]-[Type] = Button-Icon
5
5
  * Type: Primitive (foundational component)
6
- *
6
+ *
7
7
  * Platform-agnostic token definitions for the Button-Icon component.
8
8
  * Uses the defineComponentTokens() API to register tokens with the global
9
9
  * ComponentTokenRegistry for pipeline integration.
10
- *
10
+ *
11
+ * Two separate defineComponentTokens() calls are used — one per token family
12
+ * (spacing, sizing) — following the Avatar-Base pattern (avatar.tokens.ts). Every
13
+ * token registered by a single call is stamped with that call's `family`, so inset
14
+ * (spacing) and size (sizing) tokens must NOT share a call even though they live in
15
+ * the same file. The two branded results are exported separately and must NOT be
16
+ * spread/merged into one object — the rich metadata rides on a non-enumerable brand
17
+ * (see src/build/tokens/defineComponentTokens.ts, TOKEN_CONTRACT_BRAND) that a spread
18
+ * would silently drop.
19
+ *
11
20
  * The build system generates platform-specific values from these definitions:
12
21
  * - Web: CSS custom properties (var(--buttonicon-inset-large))
13
22
  * - iOS: Swift constants (ButtonIconTokens.insetLarge)
14
23
  * - Android: Kotlin constants (ButtonIconTokens.insetLarge)
15
- *
24
+ *
16
25
  * Token Relationships:
17
- * - buttonIcon.inset.large (12px) references space150
18
- * - buttonIcon.inset.medium (10px) references space125 (strategic flexibility token)
19
- * - buttonIcon.inset.small (8px) references space100
20
- * - buttonIcon.size.large (48px) references size600
21
- * - buttonIcon.size.medium (40px) references size500
22
- * - buttonIcon.size.small (32px) references size400
23
- *
26
+ * - buttonIcon.inset.large (12px) references space150 — family: spacing
27
+ * - buttonIcon.inset.medium (10px) references space125 (strategic flexibility token) — family: spacing
28
+ * - buttonIcon.inset.small (8px) references space100 — family: spacing
29
+ * - buttonIcon.size.large (48px) references size600 — family: sizing
30
+ * - buttonIcon.size.medium (40px) references size500 — family: sizing
31
+ * - buttonIcon.size.small (32px) references size400 — family: sizing
32
+ *
24
33
  * @see .kiro/specs/035-button-icon-component/design.md for token consumption strategy
25
34
  * @see .kiro/specs/034-component-architecture-system for Stemma System details
26
35
  * @see .kiro/specs/037-component-token-generation-pipeline for pipeline integration
@@ -32,28 +41,21 @@ import { spacingTokens } from '../../../tokens/SpacingTokens';
32
41
  import { sizingTokens } from '../../../tokens/SizingTokens';
33
42
 
34
43
  /**
35
- * Button-Icon component tokens defined using the hybrid authoring API.
36
- *
44
+ * Button-Icon inset (padding) tokens — reference spacing primitives.
45
+ *
37
46
  * Each token references a primitive token and includes reasoning
38
47
  * explaining why the token exists and its purpose in the component.
39
- *
40
- * Inset (padding) token values — reference spacing primitives:
48
+ *
41
49
  * - inset.large: 12px (1.5 × base, references space150)
42
50
  * - inset.medium: 10px (1.25 × base, references space125 strategic flexibility token)
43
51
  * - inset.small: 8px (1 × base, references space100)
44
- *
45
- * Size (width/height) token values:
46
- * - size.large: 48px (6 × base, references size600)
47
- * - size.medium: 40px (5 × base, references size500)
48
- * - size.small: 32px (4 × base, references size400)
49
- *
52
+ *
50
53
  * @see Requirements 6.1, 6.2, 6.3 in .kiro/specs/040-component-alignment/requirements.md
51
54
  */
52
- export const ButtonIconTokens = defineComponentTokens({
55
+ export const ButtonIconInsetTokens = defineComponentTokens({
53
56
  component: 'ButtonIcon',
54
57
  family: 'spacing',
55
58
  tokens: {
56
- // Inset (padding) tokens
57
59
  'inset.large': {
58
60
  reference: spacingTokens.space150,
59
61
  reasoning: 'Large button variant requires 12px padding (1.5× base) for comfortable touch target and visual balance with larger icon sizes',
@@ -66,8 +68,22 @@ export const ButtonIconTokens = defineComponentTokens({
66
68
  reference: spacingTokens.space100,
67
69
  reasoning: 'Small button variant uses 8px padding (1× base) for minimal footprint in dense UI layouts while meeting minimum touch target requirements',
68
70
  },
69
- // Size (width/height) tokens — reference sizing primitives, not spacing
70
- // @see Requirements 6.1, 6.2, 6.3
71
+ },
72
+ });
73
+
74
+ /**
75
+ * Button-Icon size (width/height) tokens — reference sizing primitives, not spacing.
76
+ *
77
+ * - size.large: 48px (6 × base, references size600)
78
+ * - size.medium: 40px (5 × base, references size500)
79
+ * - size.small: 32px (4 × base, references size400)
80
+ *
81
+ * @see Requirements 6.1, 6.2, 6.3 in .kiro/specs/040-component-alignment/requirements.md
82
+ */
83
+ export const ButtonIconSizeTokens = defineComponentTokens({
84
+ component: 'ButtonIcon',
85
+ family: 'sizing',
86
+ tokens: {
71
87
  'size.large': {
72
88
  reference: sizingTokens.size600,
73
89
  reasoning: 'Large button size (48px = 6× base) provides generous touch target exceeding tapAreaRecommended, calculated as icon (24px) + padding (12px × 2)',
@@ -107,7 +123,7 @@ export type ButtonIconSizeVariant = 'large' | 'medium' | 'small';
107
123
  * ```
108
124
  */
109
125
  export function getButtonIconInset(variant: ButtonIconInsetVariant): number {
110
- return ButtonIconTokens[`inset.${variant}`];
126
+ return ButtonIconInsetTokens[`inset.${variant}`];
111
127
  }
112
128
 
113
129
  /**
@@ -126,7 +142,7 @@ export function getButtonIconInset(variant: ButtonIconInsetVariant): number {
126
142
  * @see Requirements 6.1, 6.2, 6.3 in .kiro/specs/040-component-alignment/requirements.md
127
143
  */
128
144
  export function getButtonIconSize(variant: ButtonIconSizeVariant): number {
129
- return ButtonIconTokens[`size.${variant}`];
145
+ return ButtonIconSizeTokens[`size.${variant}`];
130
146
  }
131
147
 
132
148
  /**
@@ -40,11 +40,24 @@ describe('Chip-Base Web Component', () => {
40
40
  beforeEach(async () => {
41
41
  // Wait for custom element to be defined
42
42
  await customElements.whenDefined('chip-base');
43
+ // Silence ONLY the known environmental warn ("Could not calculate blend colors",
44
+ // fired async via rAF): jsdom never applies real CSS, so the token lookup cannot
45
+ // succeed here and the component's designed fallback fires every run, forever.
46
+ // Anything ELSE passes through to the real console — a NEW warn class stays audible.
47
+ const realWarn = console.warn.bind(console);
48
+ jest.spyOn(console, 'warn').mockImplementation((...args: unknown[]) => {
49
+ // Component-prefixed match (Lina review, PR #39): the bare substring is shared by
50
+ // Button components too — prefix-matching prevents accidentally swallowing a
51
+ // cross-component warn if this suite ever composes a Button.
52
+ if (typeof args[0] === 'string' && args[0].includes('ChipBase: Could not calculate blend colors')) return;
53
+ realWarn(...args);
54
+ });
43
55
  });
44
56
 
45
57
  afterEach(() => {
46
58
  // Clean up any created elements
47
59
  cleanupDOM();
60
+ jest.restoreAllMocks();
48
61
  });
49
62
 
50
63
  // ============================================================================
@@ -42,11 +42,24 @@ describe('Chip-Filter Web Component', () => {
42
42
  beforeEach(async () => {
43
43
  // Wait for custom element to be defined
44
44
  await customElements.whenDefined('chip-filter');
45
+ // Silence ONLY the known environmental warn ("Could not calculate blend colors",
46
+ // fired async via rAF): jsdom never applies real CSS, so the token lookup cannot
47
+ // succeed here and the component's designed fallback fires every run, forever.
48
+ // Anything ELSE passes through to the real console — a NEW warn class stays audible.
49
+ const realWarn = console.warn.bind(console);
50
+ jest.spyOn(console, 'warn').mockImplementation((...args: unknown[]) => {
51
+ // Component-prefixed match (Lina review, PR #39): the bare substring is shared by
52
+ // Button components too — prefix-matching prevents accidentally swallowing a
53
+ // cross-component warn if this suite ever composes a Button.
54
+ if (typeof args[0] === 'string' && args[0].includes('ChipFilter: Could not calculate blend colors')) return;
55
+ realWarn(...args);
56
+ });
45
57
  });
46
58
 
47
59
  afterEach(() => {
48
60
  // Clean up any created elements
49
61
  cleanupDOM();
62
+ jest.restoreAllMocks();
50
63
  });
51
64
 
52
65
  // ============================================================================
@@ -41,11 +41,24 @@ describe('Chip-Input Web Component', () => {
41
41
  beforeEach(async () => {
42
42
  // Wait for custom element to be defined
43
43
  await customElements.whenDefined('chip-input');
44
+ // Silence ONLY the known environmental warn ("Could not calculate blend colors",
45
+ // fired async via rAF): jsdom never applies real CSS, so the token lookup cannot
46
+ // succeed here and the component's designed fallback fires every run, forever.
47
+ // Anything ELSE passes through to the real console — a NEW warn class stays audible.
48
+ const realWarn = console.warn.bind(console);
49
+ jest.spyOn(console, 'warn').mockImplementation((...args: unknown[]) => {
50
+ // Component-prefixed match (Lina review, PR #39): the bare substring is shared by
51
+ // Button components too — prefix-matching prevents accidentally swallowing a
52
+ // cross-component warn if this suite ever composes a Button.
53
+ if (typeof args[0] === 'string' && args[0].includes('ChipInput: Could not calculate blend colors')) return;
54
+ realWarn(...args);
55
+ });
44
56
  });
45
57
 
46
58
  afterEach(() => {
47
59
  // Clean up any created elements
48
60
  cleanupDOM();
61
+ jest.restoreAllMocks();
49
62
  });
50
63
 
51
64
  // ============================================================================