@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
@@ -117,12 +117,20 @@ private fun validatePasswordRequirements(
117
117
  * @param isSuccess Success state indicator
118
118
  * @param showInfoIcon Info icon support
119
119
  * @param placeholder Placeholder text (only shown when label is floated and input is empty)
120
- * @param readOnly Read-only state
120
+ * @param readOnly Read-only state — NOT SUPPORTED on Input-Text-Password.
121
+ * readOnly is contracted OUT of the Password variant (see Input-Text-Password
122
+ * contracts.yaml excludes.state_readonly; adjudication condition 4:
123
+ * .kiro/issues/input-text-base-ios-readonly-adjudication.md — RULED B-prime,
124
+ * Peter 2026-07-15). Zero named consumers; contracting it out deletes the
125
+ * security fork rather than fencing it. Note this is contract conformance,
126
+ * not a security fix: on Android the masked PasswordVisualTransformation
127
+ * already suppresses copy/cut ([DATA R2] §3 verification). This param is
128
+ * accepted for API stability but IGNORED: it is never forwarded to
129
+ * InputTextBase.
121
130
  * @param required Required field indicator
122
131
  * @param maxLength Maximum length for input value
123
132
  * @param imeAction IME action for keyboard
124
133
  * @param keyboardActions Keyboard actions
125
- * @param isDisabled Disabled state
126
134
  * @param showToggle Whether to show the toggle button
127
135
  * @param isNewPassword Whether this is for a new password
128
136
  * @param invalidPasswordMessage Custom invalid password message
@@ -150,7 +158,6 @@ fun InputTextPassword(
150
158
  maxLength: Int? = null,
151
159
  imeAction: ImeAction = ImeAction.Done,
152
160
  keyboardActions: KeyboardActions = KeyboardActions.Default,
153
- isDisabled: Boolean = false,
154
161
  showToggle: Boolean = true,
155
162
  isNewPassword: Boolean = false,
156
163
  invalidPasswordMessage: String = DEFAULT_INVALID_PASSWORD_MESSAGE,
@@ -212,8 +219,7 @@ fun InputTextPassword(
212
219
  onClick = {
213
220
  isPasswordVisible = !isPasswordVisible
214
221
  onToggleVisibility?.invoke(isPasswordVisible)
215
- },
216
- enabled = !isDisabled
222
+ }
217
223
  ) {
218
224
  Icon(
219
225
  imageVector = if (isPasswordVisible) Icons.Filled.VisibilityOff else Icons.Filled.Visibility,
@@ -256,12 +262,16 @@ fun InputTextPassword(
256
262
  type = InputType.PASSWORD,
257
263
  visualTransformation = visualTransformation,
258
264
  placeholder = placeholder,
259
- readOnly = readOnly,
265
+ // readOnly is contracted out of Input-Text-Password (excludes.state_readonly;
266
+ // adjudication condition 4: .kiro/issues/input-text-base-ios-readonly-adjudication.md
267
+ // — RULED B-prime, Peter 2026-07-15). Always stripped. Contract conformance,
268
+ // not a security fix — Android's masked PasswordVisualTransformation already
269
+ // suppresses copy/cut, so Android was never the hazard here ([DATA R2] §3).
270
+ readOnly = false,
260
271
  required = required,
261
272
  maxLength = maxLength,
262
273
  imeAction = imeAction,
263
274
  keyboardActions = keyboardActions,
264
- isDisabled = isDisabled,
265
275
  trailingContent = toggleButton
266
276
  )
267
277
  }
@@ -132,7 +132,16 @@ struct InputTextPassword: View {
132
132
  /// Placeholder text (only shown when label is floated and input is empty)
133
133
  let placeholder: String?
134
134
 
135
- /// Read-only state
135
+ /// Read-only state — NOT SUPPORTED on Input-Text-Password.
136
+ ///
137
+ /// readOnly is contracted OUT of the Password variant (see
138
+ /// contracts.yaml excludes.state_readonly; adjudication condition 4:
139
+ /// .kiro/issues/input-text-base-ios-readonly-adjudication.md — RULED
140
+ /// B-prime, Peter 2026-07-15). Zero named consumers, and the Base's
141
+ /// read-only path renders selectable plaintext Text — a readOnly
142
+ /// Password must never reach it, masked or revealed. This prop is
143
+ /// accepted for API stability but IGNORED: it is never forwarded to
144
+ /// InputTextBase.
136
145
  let readOnly: Bool
137
146
 
138
147
  /// Required field indicator
@@ -140,10 +149,7 @@ struct InputTextPassword: View {
140
149
 
141
150
  /// Maximum length for input value
142
151
  let maxLength: Int?
143
-
144
- /// Disabled state
145
- let isDisabled: Bool
146
-
152
+
147
153
  /// Whether to show the toggle button
148
154
  let showToggle: Bool
149
155
 
@@ -212,7 +218,6 @@ struct InputTextPassword: View {
212
218
  readOnly: Bool = false,
213
219
  required: Bool = false,
214
220
  maxLength: Int? = nil,
215
- isDisabled: Bool = false,
216
221
  showToggle: Bool = true,
217
222
  isNewPassword: Bool = false,
218
223
  invalidPasswordMessage: String = defaultInvalidPasswordMessage,
@@ -235,7 +240,6 @@ struct InputTextPassword: View {
235
240
  self.readOnly = readOnly
236
241
  self.required = required
237
242
  self.maxLength = maxLength
238
- self.isDisabled = isDisabled
239
243
  self.showToggle = showToggle
240
244
  self.isNewPassword = isNewPassword
241
245
  self.invalidPasswordMessage = invalidPasswordMessage
@@ -273,10 +277,14 @@ struct InputTextPassword: View {
273
277
  type: .text,
274
278
  autocomplete: contentType,
275
279
  placeholder: placeholder,
276
- readOnly: readOnly,
280
+ // SECURITY: readOnly is contracted out of Input-Text-Password
281
+ // (adjudication, RULED B-prime, Peter 2026-07-15). The revealed
282
+ // branch uses type .text — forwarding readOnly here would route
283
+ // the secret to the Base's selectable plaintext Text path.
284
+ // Always stripped.
285
+ readOnly: false,
277
286
  required: required,
278
287
  maxLength: maxLength,
279
- isDisabled: isDisabled,
280
288
  trailingContent: showToggle ? AnyView(toggleButton) : nil
281
289
  )
282
290
  } else {
@@ -304,10 +312,13 @@ struct InputTextPassword: View {
304
312
  type: .password,
305
313
  autocomplete: contentType,
306
314
  placeholder: placeholder,
307
- readOnly: readOnly,
315
+ // SECURITY: readOnly is contracted out of Input-Text-Password
316
+ // (adjudication, RULED B-prime, Peter 2026-07-15). Stripped on
317
+ // the masked branch too — the Base additionally gates its
318
+ // read-only Text path away from secure fields (defense in depth).
319
+ readOnly: false,
308
320
  required: required,
309
321
  maxLength: maxLength,
310
- isDisabled: isDisabled,
311
322
  trailingContent: showToggle ? AnyView(toggleButton) : nil
312
323
  )
313
324
  }
@@ -327,7 +338,6 @@ struct InputTextPassword: View {
327
338
  .contentShape(Rectangle())
328
339
  }
329
340
  .buttonStyle(PlainButtonStyle())
330
- .disabled(isDisabled)
331
341
  .accessibilityLabel(isPasswordVisible ? "Hide password" : "Show password")
332
342
  .accessibilityAddTraits(.isButton)
333
343
  }
@@ -408,14 +418,6 @@ struct InputTextPassword_Previews: PreviewProvider {
408
418
  isSuccess: true
409
419
  )
410
420
 
411
- InputTextPassword(
412
- id: "preview-disabled",
413
- label: "Password",
414
- value: .constant("secretpassword"),
415
- helperText: "This field is disabled",
416
- isDisabled: true
417
- )
418
-
419
421
  InputTextPassword(
420
422
  id: "preview-new-password",
421
423
  label: "New Password",
@@ -74,6 +74,9 @@ export class InputTextPassword extends HTMLElement {
74
74
  'error-message',
75
75
  'is-success',
76
76
  'show-info-icon',
77
+ // read-only is accepted for API stability but IGNORED — readOnly is
78
+ // contracted out of Input-Text-Password (see render(), and
79
+ // contracts.yaml excludes.state_readonly).
77
80
  'read-only',
78
81
  'required',
79
82
  'max-length',
@@ -154,7 +157,14 @@ export class InputTextPassword extends HTMLElement {
154
157
  const propsErrorMessage = this.getAttribute('error-message') || '';
155
158
  const isSuccess = this.getAttribute('is-success') === 'true';
156
159
  const showInfoIcon = this.getAttribute('show-info-icon') === 'true';
157
- const readOnly = this.hasAttribute('read-only');
160
+ // read-only is NOT read or forwarded: readOnly is contracted out of
161
+ // Input-Text-Password (adjudication condition 4:
162
+ // .kiro/issues/input-text-base-ios-readonly-adjudication.md — RULED
163
+ // B-prime, Peter 2026-07-15). On web this is contract conformance, not a
164
+ // security fix — a readonly password input stays masked and browsers
165
+ // block copy from type=password — but the exclusion holds uniformly on
166
+ // all three platforms. The attribute is accepted (observedAttributes)
167
+ // for API stability and ignored.
158
168
  const required = this.hasAttribute('required');
159
169
  const maxLength = this.getAttribute('max-length');
160
170
  const showToggle = this.getAttribute('show-toggle') !== 'false'; // Default true
@@ -197,7 +207,6 @@ export class InputTextPassword extends HTMLElement {
197
207
  ${errorMessage ? `error-message="${errorMessage}"` : ''}
198
208
  ${isSuccess ? 'is-success="true"' : ''}
199
209
  ${showInfoIcon ? 'show-info-icon="true"' : ''}
200
- ${readOnly ? 'read-only' : ''}
201
210
  ${required ? 'required' : ''}
202
211
  ${maxLength ? `max-length="${maxLength}"` : ''}
203
212
  ></input-text-base>
@@ -103,7 +103,11 @@ properties:
103
103
  type: boolean
104
104
  required: false
105
105
  default: false
106
- description: Read-only state (alternative to disabled)
106
+ description: >-
107
+ Read-only display state (state_readonly contract) — the value is
108
+ non-editable but stays perceivable, selectable, and copyable; no
109
+ keyboard/IME is raised and disabled semantics are never applied. iOS
110
+ renders it as selectable static text inside the field chrome.
107
111
 
108
112
  required:
109
113
  type: boolean
@@ -101,7 +101,7 @@ InputTextPhoneNumber(
101
101
  | `isSuccess` | boolean | No | false | Success state indicator |
102
102
  | `showInfoIcon` | boolean | No | false | Show info icon |
103
103
  | `placeholder` | string | No | - | Placeholder text |
104
- | `readOnly` | boolean | No | false | Read-only state |
104
+ | `readOnly` | boolean | No | false | Read-only display state (`state_readonly` contract): value is non-editable but selectable and copyable; no keyboard raised; iOS renders selectable text in the field chrome |
105
105
  | `required` | boolean | No | false | Required field indicator |
106
106
  | `maxLength` | number | No | - | Maximum input length |
107
107
  | `testID` | string | No | - | Test ID for automation |
@@ -149,16 +149,17 @@ InputTextPhoneNumber(
149
149
  3. **validates_on_blur**: Validation triggers on blur
150
150
  4. **error_state_display**: Shows error message and styling
151
151
  5. **success_state_display**: Shows success styling
152
- 6. **disabled_state**: Prevents interaction when disabled
153
- 7. **trailing_icon_display**: Shows contextual trailing icons
154
- 8. **focus_ring**: WCAG 2.4.7 focus visible indicator
155
- 9. **reduced_motion_support**: Respects prefers-reduced-motion
152
+ 6. **trailing_icon_display**: Shows contextual trailing icons
153
+ 7. **focus_ring**: WCAG 2.4.7 focus visible indicator
154
+ 8. **reduced_motion_support**: Respects prefers-reduced-motion
155
+
156
+ **Excluded**: `state_disabled` — DesignerPunk does not support disabled states for usability and accessibility reasons. If an action is unavailable, the component should not be rendered (adjudicated 2026-07-15).
156
157
 
157
158
  ### Phone-Specific Contracts
158
159
 
159
- 10. **validates_phone_format**: Validates phone against country-specific patterns
160
- 11. **provides_phone_formatting**: Formats phone numbers as user types
161
- 12. **supports_international_formats**: Handles multiple country formats
160
+ 9. **validates_phone_format**: Validates phone against country-specific patterns
161
+ 10. **provides_phone_formatting**: Formats phone numbers as user types
162
+ 11. **supports_international_formats**: Handles multiple country formats
162
163
 
163
164
  ## Validation
164
165
 
@@ -151,7 +151,6 @@ private fun isValidPhoneNumber(phoneNumber: String, countryCode: String = DEFAUL
151
151
  * @param maxLength Maximum length for input value
152
152
  * @param imeAction IME action for keyboard
153
153
  * @param keyboardActions Keyboard actions
154
- * @param isDisabled Disabled state
155
154
  * @param countryCode Country code for formatting and validation
156
155
  * @param autoFormat Whether to auto-format as user types
157
156
  * @param invalidPhoneMessage Custom invalid phone message
@@ -177,7 +176,6 @@ fun InputTextPhoneNumber(
177
176
  maxLength: Int? = null,
178
177
  imeAction: ImeAction = ImeAction.Done,
179
178
  keyboardActions: KeyboardActions = KeyboardActions.Default,
180
- isDisabled: Boolean = false,
181
179
  countryCode: String = DEFAULT_COUNTRY_CODE,
182
180
  autoFormat: Boolean = true,
183
181
  invalidPhoneMessage: String = DEFAULT_INVALID_PHONE_MESSAGE,
@@ -252,14 +250,13 @@ fun InputTextPhoneNumber(
252
250
  errorMessage = effectiveErrorMessage,
253
251
  isSuccess = isSuccess,
254
252
  showInfoIcon = showInfoIcon,
255
- type = InputType.PHONE,
253
+ type = InputType.TEL,
256
254
  placeholder = placeholder,
257
255
  readOnly = readOnly,
258
256
  required = required,
259
257
  maxLength = maxLength,
260
258
  imeAction = imeAction,
261
- keyboardActions = keyboardActions,
262
- isDisabled = isDisabled
259
+ keyboardActions = keyboardActions
263
260
  )
264
261
  }
265
262
 
@@ -175,10 +175,7 @@ struct InputTextPhoneNumber: View {
175
175
 
176
176
  /// Maximum length for input value
177
177
  let maxLength: Int?
178
-
179
- /// Disabled state
180
- let isDisabled: Bool
181
-
178
+
182
179
  /// Country code for formatting and validation
183
180
  let countryCode: String
184
181
 
@@ -243,7 +240,6 @@ struct InputTextPhoneNumber: View {
243
240
  readOnly: Bool = false,
244
241
  required: Bool = false,
245
242
  maxLength: Int? = nil,
246
- isDisabled: Bool = false,
247
243
  countryCode: String = defaultCountryCode,
248
244
  autoFormat: Bool = true,
249
245
  invalidPhoneMessage: String = defaultInvalidPhoneMessage,
@@ -264,7 +260,6 @@ struct InputTextPhoneNumber: View {
264
260
  self.readOnly = readOnly
265
261
  self.required = required
266
262
  self.maxLength = maxLength
267
- self.isDisabled = isDisabled
268
263
  self.countryCode = countryCode
269
264
  self.autoFormat = autoFormat
270
265
  self.invalidPhoneMessage = invalidPhoneMessage
@@ -296,13 +291,12 @@ struct InputTextPhoneNumber: View {
296
291
  errorMessage: effectiveErrorMessage,
297
292
  isSuccess: isSuccess,
298
293
  showInfoIcon: showInfoIcon,
299
- type: .phone,
294
+ type: .tel,
300
295
  autocomplete: .telephoneNumber,
301
296
  placeholder: placeholder,
302
297
  readOnly: readOnly,
303
298
  required: required,
304
- maxLength: maxLength,
305
- isDisabled: isDisabled
299
+ maxLength: maxLength
306
300
  )
307
301
  .onAppear {
308
302
  // Initialize formatted value from initial value
@@ -396,14 +390,6 @@ struct InputTextPhoneNumber_Previews: PreviewProvider {
396
390
  countryCode: "GB"
397
391
  )
398
392
 
399
- InputTextPhoneNumber(
400
- id: "preview-disabled",
401
- label: "Phone Number",
402
- value: .constant("5551234567"),
403
- helperText: "This field is disabled",
404
- isDisabled: true
405
- )
406
-
407
393
  InputTextPhoneNumber(
408
394
  id: "preview-required",
409
395
  label: "Phone Number",
@@ -12,7 +12,7 @@ contracts:
12
12
  may contain logos, search inputs, or other non-heading content.
13
13
  Heading semantics are the responsibility of Nav-Header-Page (h1)
14
14
  and future variants (Nav-Header-Modal: h2).
15
- wcag: null
15
+ wcag: "N/A" # legitimate-null: renders-no-heading negative guarantee, no positive WCAG SC (125-B 4.2)
16
16
  platforms: [web, ios, android]
17
17
  validation:
18
18
  - No h1/h2/h3 element rendered
@@ -122,7 +122,7 @@ contracts:
122
122
  description: Renders text label for text segments
123
123
  behavior: |
124
124
  When a segment has a label property, renders the label as text content.
125
- wcag: null
125
+ wcag: "1.3.1 Info and Relationships"
126
126
  platforms: [web, ios, android]
127
127
  validation:
128
128
  - Text segment displays label string
@@ -59,7 +59,7 @@ contracts:
59
59
  Connector-Base is marked as decorative (aria-hidden on web,
60
60
  accessibilityHidden on iOS, clearAndSetSemantics on Android).
61
61
  Semantic variants provide ARIA roles and labels.
62
- wcag: null
62
+ wcag: "1.1.1 Non-text Content"
63
63
  platforms: [web, ios, android]
64
64
  validation:
65
65
  - Connector has aria-hidden="true" (web)
@@ -65,7 +65,7 @@ contracts:
65
65
  Label-Base is marked as decorative (aria-hidden on web,
66
66
  accessibilityHidden on iOS, clearAndSetSemantics on Android).
67
67
  Semantic variants provide ARIA roles and labels.
68
- wcag: null
68
+ wcag: "1.1.1 Non-text Content"
69
69
  platforms: [web, ios, android]
70
70
  validation:
71
71
  - Label has aria-hidden="true" (web)
@@ -85,7 +85,7 @@ contracts:
85
85
  Node-Base is marked as decorative (aria-hidden on web,
86
86
  accessibilityHidden on iOS, clearAndSetSemantics on Android).
87
87
  Semantic variants provide ARIA roles and labels.
88
- wcag: null
88
+ wcag: "1.1.1 Non-text Content"
89
89
  platforms: [web, ios, android]
90
90
  validation:
91
91
  - Node has aria-hidden="true" (web)
@@ -255,8 +255,11 @@ describe('Progress-Stepper-Base', () => {
255
255
  });
256
256
 
257
257
  it('throws error when size="sm" (Req 8.10)', () => {
258
- // jsdom's custom element lifecycle is async, so we need to catch the error differently
259
- const errorHandler = jest.fn();
258
+ // jsdom's custom element lifecycle is async, so we need to catch the error differently.
259
+ // preventDefault() marks the error HANDLED, which stops jsdom's default reporter from
260
+ // printing an "Uncaught [Error: ...]" console.error block for this expected throw
261
+ // (CI-log noise; the assertion below still receives the event first).
262
+ const errorHandler = jest.fn((event: ErrorEvent) => event.preventDefault());
260
263
  window.addEventListener('error', errorHandler);
261
264
 
262
265
  createStepper({ 'total-steps': '3', 'current-step': '1', size: 'sm' });
@@ -353,8 +353,11 @@ describe('Progress-Stepper-Detailed', () => {
353
353
  });
354
354
 
355
355
  it('throws error when size="sm" (Req 8.10)', () => {
356
- // jsdom's custom element lifecycle is async, so we need to catch the error differently
357
- const errorHandler = jest.fn();
356
+ // jsdom's custom element lifecycle is async, so we need to catch the error differently.
357
+ // preventDefault() marks the error HANDLED, which stops jsdom's default reporter from
358
+ // printing an "Uncaught [Error: ...]" console.error block for this expected throw
359
+ // (CI-log noise; the assertion below still receives the event first).
360
+ const errorHandler = jest.fn((event: ErrorEvent) => event.preventDefault());
358
361
  window.addEventListener('error', errorHandler);
359
362
 
360
363
  createStepperDetailed({
@@ -724,6 +724,12 @@ export class DTCGFormatGenerator {
724
724
  } else if (token.direction === 'lighter') {
725
725
  extensions.blendType = 'lighterBlend';
726
726
  }
727
+ // Deprecation metadata (e.g. blend.disabledDesaturate) — lets includeDeprecated: false strip it
728
+ if (token.deprecated) {
729
+ extensions.deprecated = true;
730
+ if (token.deprecatedSince) extensions.deprecatedSince = token.deprecatedSince;
731
+ if (token.deprecatedReason) extensions.deprecatedReason = token.deprecatedReason;
732
+ }
727
733
 
728
734
  group[key] = this.toDTCGToken(aliasValue, 'number', token.description, extensions);
729
735
  }
@@ -565,6 +565,7 @@ export class TokenFileGenerator {
565
565
  private getiOSComponentTokenType(token: RegisteredComponentToken): string {
566
566
  switch (token.family) {
567
567
  case 'spacing':
568
+ case 'sizing':
568
569
  case 'radius':
569
570
  case 'fontSize':
570
571
  case 'tapArea':
@@ -619,8 +620,12 @@ export class TokenFileGenerator {
619
620
  const familyClass = this.getFamilyClassName(token.family);
620
621
  return `${familyClass}.${token.primitiveReference}`;
621
622
  }
622
- // Dimensional families need .dp suffix to match primitive token output (Task 1.4)
623
- const dimensionalFamilies = ['spacing', 'radius', 'tapArea', 'fontSize', 'borderWidth'];
623
+ // Dimensional families need .dp suffix to match primitive token output (Task 1.4).
624
+ // 'sizing' is dimensional (component width/height) and belongs here: without it, a
625
+ // value-path sizing token emits a bare Int, which fails to compile against consumers
626
+ // that type the member as Dp (e.g. Avatar.android.kt's
627
+ // `val iconSizeXs: Dp = GeneratedAvatarTokens.iconSizeXs`).
628
+ const dimensionalFamilies = ['spacing', 'sizing', 'radius', 'tapArea', 'fontSize', 'borderWidth'];
624
629
  if (dimensionalFamilies.includes(token.family)) {
625
630
  return `${token.value}.dp`;
626
631
  }
@@ -200,9 +200,8 @@ describe('DTCGFormatGenerator Configuration Options', () => {
200
200
  // -------------------------------------------------------------------------
201
201
  describe('includeDeprecated: false', () => {
202
202
  it('should exclude tokens marked as deprecated', () => {
203
- // Since no tokens currently have deprecated: true in their data,
204
- // we verify the infrastructure works by generating with both configs
205
- // and confirming the output is identical (no deprecated tokens to strip)
203
+ // blend.disabledDesaturate is deprecated (2026-07-15, no-disabled-states ruling)
204
+ // and is currently the only deprecated token in the corpus
206
205
  const withDeprecated = new DTCGFormatGenerator({ includeDeprecated: true });
207
206
  const withoutDeprecated = new DTCGFormatGenerator({ includeDeprecated: false });
208
207
 
@@ -213,10 +212,20 @@ describe('DTCGFormatGenerator Configuration Options', () => {
213
212
  expect(outputWith.$schema).toBeDefined();
214
213
  expect(outputWithout.$schema).toBeDefined();
215
214
 
216
- // Since no tokens are currently deprecated, counts should match
215
+ // includeDeprecated: true keeps the token and carries deprecation metadata
216
+ const blendWith = outputWith.semanticBlend as Record<string, any>;
217
+ expect(blendWith['blend.disabledDesaturate']).toBeDefined();
218
+ expect(blendWith['blend.disabledDesaturate'].$extensions?.designerpunk?.deprecated).toBe(true);
219
+ expect(blendWith['blend.disabledDesaturate'].$extensions?.designerpunk?.deprecatedSince).toBe('2026-07-15');
220
+
221
+ // includeDeprecated: false strips it
222
+ const blendWithout = outputWithout.semanticBlend as Record<string, any>;
223
+ expect(blendWithout['blend.disabledDesaturate']).toBeUndefined();
224
+
225
+ // Exactly the deprecated token is stripped — nothing else
217
226
  const countWith = countAllTokens(outputWith);
218
227
  const countWithout = countAllTokens(outputWithout);
219
- expect(countWith).toBe(countWithout);
228
+ expect(countWith).toBe(countWithout + 1);
220
229
  });
221
230
  });
222
231
  });
@@ -268,7 +268,7 @@ export class BuildErrorHandler {
268
268
  'Validate configuration against schema'
269
269
  ],
270
270
  documentation: [
271
- 'https://github.com/3fn/DesignerPunkv2/docs/build-integration.md'
271
+ 'https://github.com/3fn/DesignerPunk/docs/build-integration.md'
272
272
  ]
273
273
  };
274
274
  }
@@ -293,7 +293,7 @@ export class BuildErrorHandler {
293
293
  'Ensure platform files are generated correctly'
294
294
  ],
295
295
  documentation: [
296
- `https://github.com/3fn/DesignerPunkv2/docs/platforms/${platform}.md`
296
+ `https://github.com/3fn/DesignerPunk/docs/platforms/${platform}.md`
297
297
  ]
298
298
  };
299
299
  }
@@ -113,7 +113,7 @@ export const opacityTokens: Record<string, PrimitiveToken> = {
113
113
  category: TokenCategory.OPACITY,
114
114
  baseValue: OPACITY_BASE_VALUE * 6,
115
115
  familyBaseValue: OPACITY_BASE_VALUE,
116
- description: 'Disabled state - faded, very strong overlay',
116
+ description: 'Very strong transparency - background scrims and modal overlays (referenced by opacity.heavy)',
117
117
  mathematicalRelationship: 'base × 6 = 0.08 × 6 = 0.48',
118
118
  baselineGridAlignment: false,
119
119
  isStrategicFlexibility: false,
@@ -280,7 +280,9 @@ describe('Opacity Tokens', () => {
280
280
 
281
281
  expect(opacity000?.description).toContain('Fully transparent');
282
282
  expect(opacity008?.description).toContain('Subtle transparency');
283
- expect(opacity048?.description).toContain('Disabled state');
283
+ // opacity048 description corrected 2026-07-15: disabled-state phrasing removed
284
+ // (no-disabled-states philosophy, Button-CTA adjudication)
285
+ expect(opacity048?.description).toContain('Very strong transparency');
284
286
  expect(opacity100?.description).toContain('Fully opaque');
285
287
  });
286
288
 
@@ -22,18 +22,20 @@ import {
22
22
  PROGRESS_COLOR_TOKEN_COUNT,
23
23
  } from '../semantic/ColorTokens';
24
24
  import {
25
- ProgressTokens,
25
+ getProgressRegisteredTokens,
26
26
  PROGRESS_COMPONENT_TOKEN_COUNT,
27
27
  progressComponentTokenNames,
28
28
  } from '../component/progress';
29
- import { getTokenContract } from '../../build/tokens';
30
29
  import type { RegisteredComponentToken } from '../../registries/ComponentTokenRegistry';
31
30
 
32
31
  // Spec 124: defineComponentTokens no longer self-registers into ComponentTokenRegistry;
33
32
  // the rich tokens ride back on the branded return and are recovered via getTokenContract.
34
33
  // (Was: reads of ComponentTokenRegistry.getByComponent('Progress') populated by the import
35
34
  // side effect — now empty/false-red.)
36
- const progressRegisteredTokens: RegisteredComponentToken[] = getTokenContract(ProgressTokens) ?? [];
35
+ //
36
+ // Progress registers through THREE family calls (sizing / spacing / borderWidth); the
37
+ // helper concatenates their branded contracts in declaration order.
38
+ const progressRegisteredTokens: RegisteredComponentToken[] = getProgressRegisteredTokens();
37
39
 
38
40
  describe('Progress Token Compliance', () => {
39
41
  // ==========================================================================
@@ -13,7 +13,7 @@
13
13
  * @see .kiro/specs/048-progress-family/design.md (Size Variant, Current Size Formula)
14
14
  */
15
15
 
16
- import { ProgressTokens } from '../component/progress';
16
+ import { progressTokenValues } from '../component/progress';
17
17
  import { SPACING_BASE_VALUE } from '../SpacingTokens';
18
18
 
19
19
  describe('Progress Token Formula Validation', () => {
@@ -52,8 +52,8 @@ describe('Progress Token Formula Validation', () => {
52
52
  const calculated = SPACING_BASE_VALUE * multiplier;
53
53
  expect(calculated).toBe(expected);
54
54
 
55
- const tokenKey = `node.size.${size}.current` as keyof typeof ProgressTokens;
56
- expect(ProgressTokens[tokenKey]).toBe(expected);
55
+ const tokenKey = `node.size.${size}.current` as keyof typeof progressTokenValues;
56
+ expect(progressTokenValues[tokenKey]).toBe(expected);
57
57
  }
58
58
  );
59
59
  });
@@ -66,12 +66,12 @@ describe('Progress Token Formula Validation', () => {
66
66
  ] as const)(
67
67
  'should maintain +4px offset for %s (base %dpx → current %dpx)',
68
68
  (size, base, current) => {
69
- const baseKey = `node.size.${size}` as keyof typeof ProgressTokens;
70
- const currentKey = `node.size.${size}.current` as keyof typeof ProgressTokens;
69
+ const baseKey = `node.size.${size}` as keyof typeof progressTokenValues;
70
+ const currentKey = `node.size.${size}.current` as keyof typeof progressTokenValues;
71
71
 
72
- expect(ProgressTokens[baseKey]).toBe(base);
73
- expect(ProgressTokens[currentKey]).toBe(current);
74
- expect(ProgressTokens[currentKey] - ProgressTokens[baseKey]).toBe(4);
72
+ expect(progressTokenValues[baseKey]).toBe(base);
73
+ expect(progressTokenValues[currentKey]).toBe(current);
74
+ expect(progressTokenValues[currentKey] - progressTokenValues[baseKey]).toBe(4);
75
75
  }
76
76
  );
77
77
  });
@@ -84,9 +84,9 @@ describe('Progress Token Formula Validation', () => {
84
84
  ] as const)(
85
85
  'should align %s (%dpx) to 4px baseline grid',
86
86
  (tokenName, expected) => {
87
- const tokenKey = tokenName as keyof typeof ProgressTokens;
88
- expect(ProgressTokens[tokenKey]).toBe(expected);
89
- expect(ProgressTokens[tokenKey] % 4).toBe(0);
87
+ const tokenKey = tokenName as keyof typeof progressTokenValues;
88
+ expect(progressTokenValues[tokenKey]).toBe(expected);
89
+ expect(progressTokenValues[tokenKey] % 4).toBe(0);
90
90
  }
91
91
  );
92
92
  });