@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.
- package/.kiro/agents/ada-prompt.md +80 -132
- package/.kiro/agents/ada-prompt.md.attribution.json +45 -0
- package/.kiro/agents/ada.json +44 -59
- package/.kiro/agents/ada.json.attribution.json +13 -0
- package/.kiro/agents/data-prompt.md +83 -74
- package/.kiro/agents/data-prompt.md.attribution.json +53 -0
- package/.kiro/agents/data.json +31 -38
- package/.kiro/agents/data.json.attribution.json +13 -0
- package/.kiro/agents/kenya-prompt.md +83 -72
- package/.kiro/agents/kenya-prompt.md.attribution.json +53 -0
- package/.kiro/agents/kenya.json +27 -35
- package/.kiro/agents/kenya.json.attribution.json +13 -0
- package/.kiro/agents/leonardo-prompt.md +176 -234
- package/.kiro/agents/leonardo-prompt.md.attribution.json +45 -0
- package/.kiro/agents/leonardo.json +28 -36
- package/.kiro/agents/leonardo.json.attribution.json +13 -0
- package/.kiro/agents/lina-prompt.md +110 -151
- package/.kiro/agents/lina-prompt.md.attribution.json +53 -0
- package/.kiro/agents/lina.json +46 -59
- package/.kiro/agents/lina.json.attribution.json +13 -0
- package/.kiro/agents/sparky-prompt.md +89 -72
- package/.kiro/agents/sparky-prompt.md.attribution.json +53 -0
- package/.kiro/agents/sparky.json +37 -37
- package/.kiro/agents/sparky.json.attribution.json +13 -0
- package/.kiro/agents/stacy-prompt.md +74 -48
- package/.kiro/agents/stacy-prompt.md.attribution.json +45 -0
- package/.kiro/agents/stacy.json +28 -30
- package/.kiro/agents/stacy.json.attribution.json +13 -0
- package/.kiro/agents/thurgood-prompt.md +94 -138
- package/.kiro/agents/thurgood-prompt.md.attribution.json +45 -0
- package/.kiro/agents/thurgood.json +31 -35
- package/.kiro/agents/thurgood.json.attribution.json +13 -0
- package/.kiro/steering/AI-Collaboration-Principles.md +3 -3
- package/.kiro/steering/Civitas-System-Overview.md +7 -16
- package/.kiro/steering/DesignerPunk-Systems-Overview.md +6 -6
- package/.kiro/steering/Spec-Feedback-Protocol.md +2 -11
- package/.kiro/steering/Task-Completion-Protocol.md +98 -17
- package/.kiro/steering/core-goals.md +3 -3
- package/.kiro/steering/personal-note.md +1 -1
- package/.kiro/steering/start-up-tasks.md +17 -6
- package/application-mcp-server/src/index.ts +26 -0
- package/dist/ComponentTokens.android.kt +12 -12
- package/dist/ComponentTokens.ios.swift +12 -12
- package/dist/ComponentTokens.web.css +3 -3
- package/dist/DesignTokens.android.kt +1 -1
- package/dist/DesignTokens.dtcg.json +8 -5
- package/dist/DesignTokens.figma.json +2 -2
- package/dist/DesignTokens.ios.swift +1 -1
- package/dist/DesignTokens.web.css +1 -1
- package/dist/android/DesignTokens.android.kt +1 -1
- package/dist/blend/OklchBlendCalculator.js +1 -0
- package/dist/blend/ThemeAwareBlendUtilities.web.d.ts +13 -2
- package/dist/blend/ThemeAwareBlendUtilities.web.js +6 -1
- package/dist/browser/designerpunk.esm.js +36 -90
- package/dist/browser/designerpunk.esm.min.js +33 -36
- package/dist/browser/designerpunk.umd.js +36 -90
- package/dist/browser/designerpunk.umd.min.js +47 -50
- package/dist/browser/tokens.css +3 -3
- package/dist/build/tokens/defineComponentTokens.d.ts +10 -0
- package/dist/build/tokens/defineComponentTokens.js +26 -0
- package/dist/components/core/Avatar-Base/avatar.tokens.d.ts +21 -26
- package/dist/components/core/Avatar-Base/avatar.tokens.js +31 -34
- package/dist/components/core/Avatar-Base/index.d.ts +1 -1
- package/dist/components/core/Avatar-Base/index.js +2 -2
- package/dist/components/core/Avatar-Base/platforms/web/Avatar.web.js +24 -5
- package/dist/components/core/Button-CTA/examples/BasicUsage.d.ts +16 -28
- package/dist/components/core/Button-CTA/examples/BasicUsage.js +18 -43
- package/dist/components/core/Button-CTA/platforms/web/ButtonCTA.web.d.ts +3 -15
- package/dist/components/core/Button-CTA/platforms/web/ButtonCTA.web.js +9 -58
- package/dist/components/core/Button-CTA/types.d.ts +0 -24
- package/dist/components/core/Button-CTA/types.js +6 -0
- package/dist/components/core/Button-Icon/buttonIcon.tokens.d.ts +28 -14
- package/dist/components/core/Button-Icon/buttonIcon.tokens.js +35 -20
- package/dist/components/core/Input-Text-Base/types.d.ts +13 -1
- package/dist/components/core/Input-Text-Password/platforms/web/InputTextPassword.web.js +11 -2
- package/dist/generators/DTCGFormatGenerator.js +8 -0
- package/dist/generators/TokenFileGenerator.js +7 -2
- package/dist/integration/BuildErrorHandler.js +2 -2
- package/dist/ios/DesignTokens.ios.swift +1 -1
- package/dist/mcp/application-mcp.js +24 -0
- package/dist/mcp/docs-mcp.js +130 -15
- package/dist/mcp/product-mcp.js +25 -0
- package/dist/tokens/OpacityTokens.js +1 -1
- package/dist/tokens/component/progress.d.ts +65 -5
- package/dist/tokens/component/progress.js +79 -18
- package/dist/tokens/semantic/BlendTokens.d.ts +10 -3
- package/dist/tokens/semantic/BlendTokens.js +17 -5
- package/dist/tokens/semantic/OpacityTokens.d.ts +4 -4
- package/dist/tokens/semantic/OpacityTokens.js +4 -4
- package/dist/types/ComponentTypes.d.ts +1 -1
- package/dist/types/generated/TokenTypes.d.ts +1 -1
- package/dist/types/generated/TokenTypes.js +1 -1
- package/dist/validators/StemmaTokenUsageValidator.js +3 -2
- package/dist/web/DesignTokens.web.css +1 -1
- package/governance/BUILD-SYSTEM-SETUP.md +1 -2
- package/governance/Component-Development-Guide.md +23 -13
- package/governance/Component-Development-Standards.md +21 -20
- package/governance/Component-Family-Avatar.md +6 -7
- package/governance/Component-Family-Badge.md +19 -20
- package/governance/Component-Family-Button.md +30 -43
- package/governance/Component-Family-Chip.md +14 -15
- package/governance/Component-Family-Container.md +12 -13
- package/governance/Component-Family-Data-Display.md +1 -2
- package/governance/Component-Family-Divider.md +1 -2
- package/governance/Component-Family-Form-Inputs.md +65 -65
- package/governance/Component-Family-Icon.md +9 -10
- package/governance/Component-Family-Loading.md +1 -2
- package/governance/Component-Family-Modal.md +1 -2
- package/governance/Component-Family-Navigation.md +1 -2
- package/governance/Component-Family-Progress.md +0 -1
- package/governance/Component-Inheritance-Structures.md +219 -99
- package/governance/Component-MCP-Document-Template.md +6 -5
- package/governance/Component-Primitive-vs-Semantic-Philosophy.md +1 -1
- package/governance/Component-Quick-Reference.md +33 -33
- package/governance/Component-Readiness-Status.md +59 -44
- package/governance/Component-Templates.md +57 -61
- package/governance/Contract-System-Reference.md +7 -7
- package/governance/MCP-Integration-Guide.md +1 -1
- package/governance/Process-Cross-Reference-Standards.md +31 -13
- package/governance/Process-Development-Workflow.md +49 -59
- package/governance/Process-File-Organization.md +25 -28
- package/governance/Process-Hook-Operations.md +22 -11
- package/governance/Process-Orchestration-Model-Selection.md +92 -0
- package/governance/Process-Spec-Planning.md +98 -52
- package/governance/Process-Task-Type-Definitions.md +80 -4
- package/governance/Product-Handoff-Protocol.md +2 -0
- package/governance/Rosetta-System-Architecture.md +13 -11
- package/governance/Test-Behavioral-Contract-Validation.md +38 -31
- package/governance/Test-Failure-Audit-Methodology.md +1 -1
- package/governance/Token-Family-Accessibility.md +1 -2
- package/governance/Token-Family-Blend.md +18 -16
- package/governance/Token-Family-Blur.md +0 -1
- package/governance/Token-Family-Border.md +1 -2
- package/governance/Token-Family-Color.md +0 -1
- package/governance/Token-Family-Glow.md +1 -2
- package/governance/Token-Family-Layering.md +0 -1
- package/governance/Token-Family-Motion.md +1 -2
- package/governance/Token-Family-Opacity.md +0 -1
- package/governance/Token-Family-Radius.md +1 -2
- package/governance/Token-Family-Responsive.md +1 -2
- package/governance/Token-Family-Shadow.md +1 -2
- package/governance/Token-Family-Sizing.md +0 -1
- package/governance/Token-Family-Spacing.md +1 -2
- package/governance/Token-Family-Typography.md +1 -2
- package/governance/Token-Governance.md +8 -8
- package/governance/Token-Quick-Reference.md +47 -34
- package/governance/Token-Resolution-Patterns.md +1 -1
- package/governance/Token-Semantic-Structure.md +1 -1
- package/governance/Web-Authoring-Standards.md +5 -5
- package/governance/browser-distribution-guide.md +1 -4
- package/governance/classification-map.md +474 -0
- package/governance/completion-documentation-guide.md +23 -37
- package/governance/component-meta-authoring-guide.md +1 -1
- package/governance/cross-platform-vs-platform-specific-decision-framework.md +1 -1
- package/governance/platform-implementation-guidelines.md +2 -3
- package/governance/release-management-system.md +28 -63
- package/governance/rosetta-system-principles.md +8 -6
- package/governance/stemma-system-principles.md +18 -17
- package/mcp-server/src/index.ts +24 -6
- package/mcp-server/src/indexer/DocumentIndexer.ts +119 -9
- package/mcp-server/src/indexer/__tests__/bare-id-crossrefs.test.ts +250 -0
- package/mcp-server/src/indexer/cross-ref-parser.ts +29 -1
- package/mcp-server/src/indexer/index-health.ts +27 -2
- package/mcp-server/src/query/__tests__/find-docs-calibration.test.ts +11 -26
- package/mcp-server/src/relocation-integrity-gate/__tests__/relocation-integrity-gate.test.ts +72 -5
- package/mcp-server/src/relocation-integrity-gate/relocation-integrity-gate.ts +81 -24
- package/mcp-server/src/tools/list-cross-references.ts +2 -2
- package/package.json +24 -26
- package/src/__tests__/browser-distribution/css-bundling.test.ts +6 -4
- package/src/__tests__/console-allowlist.json +14 -0
- package/src/__tests__/console-fail-setup.ts +169 -0
- package/src/__tests__/integration/Spec107-DesignLanguageContext.test.ts +16 -0
- package/src/__tests__/stemma-system/behavioral-contract-validation.test.ts +70 -17
- package/src/__tests__/stemma-system/contract-catalog-name-validation.test.ts +28 -0
- package/src/__tests__/stemma-system/form-inputs-contracts.test.ts +223 -16
- package/src/__tests__/stemma-system/input-text-native-base-call-alignment.test.ts +298 -0
- package/src/blend/OklchBlendCalculator.ts +3 -0
- package/src/blend/ThemeAwareBlendUtilities.android.kt +3 -0
- package/src/blend/ThemeAwareBlendUtilities.ios.swift +3 -0
- package/src/blend/ThemeAwareBlendUtilities.web.ts +9 -1
- package/src/blend/__tests__/InteractionStateAudit.test.ts +12 -9
- package/src/build/errors/__tests__/ErrorHandler.integration.test.ts +8 -0
- package/src/build/errors/__tests__/ErrorHandler.test.ts +5 -0
- package/src/build/tokens/__tests__/defineComponentTokens.test.ts +113 -0
- package/src/build/tokens/defineComponentTokens.ts +43 -1
- package/src/build/workflow/__tests__/CICDIntegration.test.ts +12 -1
- package/src/cli/__tests__/init.test.ts +45 -11
- package/src/components/core/Avatar-Base/Avatar-Base.schema.yaml +1 -1
- package/src/components/core/Avatar-Base/__tests__/Avatar.accessibility.test.ts +121 -7
- package/src/components/core/Avatar-Base/__tests__/Avatar.image.test.ts +3 -0
- package/src/components/core/Avatar-Base/__tests__/Avatar.test.ts +15 -6
- package/src/components/core/Avatar-Base/avatar.tokens.ts +31 -34
- package/src/components/core/Avatar-Base/contracts.yaml +11 -1
- package/src/components/core/Avatar-Base/index.ts +1 -1
- package/src/components/core/Avatar-Base/platforms/web/Avatar.web.ts +24 -5
- package/src/components/core/Badge-Count-Base/contracts.yaml +1 -1
- package/src/components/core/Badge-Label-Base/contracts.yaml +1 -1
- package/src/components/core/Button-CTA/Button-CTA.schema.yaml +2 -12
- package/src/components/core/Button-CTA/README.md +3 -6
- package/src/components/core/Button-CTA/__tests__/ButtonCTA.test.ts +35 -89
- package/src/components/core/Button-CTA/__tests__/setup.test.ts +0 -2
- package/src/components/core/Button-CTA/__tests__/test-utils.ts +0 -2
- package/src/components/core/Button-CTA/contracts.yaml +6 -29
- package/src/components/core/Button-CTA/examples/BasicUsage.html +2 -14
- package/src/components/core/Button-CTA/examples/BasicUsage.tsx +17 -44
- package/src/components/core/Button-CTA/platforms/android/ButtonCTA.android.kt +12 -20
- package/src/components/core/Button-CTA/platforms/ios/ButtonCTA.ios.swift +12 -51
- package/src/components/core/Button-CTA/platforms/web/ButtonCTA.web.css +2 -26
- package/src/components/core/Button-CTA/platforms/web/ButtonCTA.web.ts +18 -71
- package/src/components/core/Button-CTA/types.ts +10 -28
- package/src/components/core/Button-Icon/buttonIcon.tokens.ts +43 -27
- package/src/components/core/Chip-Base/__tests__/ChipBase.test.ts +13 -0
- package/src/components/core/Chip-Filter/__tests__/ChipFilter.test.ts +13 -0
- package/src/components/core/Chip-Input/__tests__/ChipInput.test.ts +13 -0
- package/src/components/core/Input-Text-Base/Input-Text-Base.schema.yaml +30 -2
- package/src/components/core/Input-Text-Base/README.md +25 -2
- package/src/components/core/Input-Text-Base/__tests__/focusIndicators.test.ts +16 -15
- package/src/components/core/Input-Text-Base/contracts.yaml +90 -0
- package/src/components/core/Input-Text-Base/platforms/android/InputTextBase.android.kt +26 -12
- package/src/components/core/Input-Text-Base/platforms/ios/InputTextBase.ios.swift +195 -59
- package/src/components/core/Input-Text-Base/types.ts +13 -1
- package/src/components/core/Input-Text-Email/Input-Text-Email.schema.yaml +5 -1
- package/src/components/core/Input-Text-Email/README.md +8 -7
- package/src/components/core/Input-Text-Email/platforms/android/InputTextEmail.android.kt +1 -4
- package/src/components/core/Input-Text-Email/platforms/ios/InputTextEmail.ios.swift +2 -16
- package/src/components/core/Input-Text-Password/Input-Text-Password.schema.yaml +10 -3
- package/src/components/core/Input-Text-Password/README.md +9 -8
- package/src/components/core/Input-Text-Password/contracts.yaml +5 -0
- package/src/components/core/Input-Text-Password/platforms/android/InputTextPassword.android.kt +17 -7
- package/src/components/core/Input-Text-Password/platforms/ios/InputTextPassword.ios.swift +22 -20
- package/src/components/core/Input-Text-Password/platforms/web/InputTextPassword.web.ts +11 -2
- package/src/components/core/Input-Text-PhoneNumber/Input-Text-PhoneNumber.schema.yaml +5 -1
- package/src/components/core/Input-Text-PhoneNumber/README.md +9 -8
- package/src/components/core/Input-Text-PhoneNumber/platforms/android/InputTextPhoneNumber.android.kt +2 -5
- package/src/components/core/Input-Text-PhoneNumber/platforms/ios/InputTextPhoneNumber.ios.swift +3 -17
- package/src/components/core/Nav-Header-App/contracts.yaml +1 -1
- package/src/components/core/Nav-SegmentedChoice-Base/contracts.yaml +1 -1
- package/src/components/core/Progress-Indicator-Connector-Base/contracts.yaml +1 -1
- package/src/components/core/Progress-Indicator-Label-Base/contracts.yaml +1 -1
- package/src/components/core/Progress-Indicator-Node-Base/contracts.yaml +1 -1
- package/src/components/core/Progress-Stepper-Base/__tests__/StepperBase.test.ts +5 -2
- package/src/components/core/Progress-Stepper-Detailed/__tests__/StepperDetailed.test.ts +5 -2
- package/src/generators/DTCGFormatGenerator.ts +6 -0
- package/src/generators/TokenFileGenerator.ts +7 -2
- package/src/generators/__tests__/DTCGConfigOptions.test.ts +14 -5
- package/src/integration/BuildErrorHandler.ts +2 -2
- package/src/tokens/OpacityTokens.ts +1 -1
- package/src/tokens/__tests__/OpacityTokens.test.ts +3 -1
- package/src/tokens/__tests__/ProgressTokenCompliance.test.ts +5 -3
- package/src/tokens/__tests__/ProgressTokenFormulas.test.ts +11 -11
- package/src/tokens/__tests__/ProgressTokenTranslation.test.ts +22 -20
- package/src/tokens/component/progress.ts +83 -21
- package/src/tokens/semantic/BlendTokens.ts +26 -5
- package/src/tokens/semantic/OpacityTokens.ts +4 -4
- package/src/types/ComponentTypes.ts +1 -1
- package/src/types/generated/TokenTypes.ts +1 -1
- package/src/validators/StemmaTokenUsageValidator.ts +3 -2
- package/token-index/components.yaml +8 -8
- package/token-index/semantics.yaml +1 -2
- package/src/tools/release/__tests__/ChangeClassifier.test.ts +0 -133
- package/src/tools/release/__tests__/ChangeExtractor.test.ts +0 -222
- package/src/tools/release/__tests__/GitHubPublisher.test.ts +0 -240
- package/src/tools/release/__tests__/NotesRenderer.test.ts +0 -142
- package/src/tools/release/__tests__/NpmPublisher.test.ts +0 -289
- package/src/tools/release/__tests__/PipelineIntegration.test.ts +0 -188
- package/src/tools/release/__tests__/ReleasePipeline.test.ts +0 -192
- package/src/tools/release/__tests__/SemanticVersionValidator.test.ts +0 -49
- package/src/tools/release/__tests__/SummaryScanner.test.ts +0 -141
- package/src/tools/release/__tests__/TagResolver.test.ts +0 -91
- package/src/tools/release/__tests__/VersionCalculator.test.ts +0 -270
- package/src/tools/release/__tests__/helpers/NpmMockHelper.ts +0 -80
- package/src/tools/release/cli/ReleasePipeline.ts +0 -165
- package/src/tools/release/cli/release-tool.ts +0 -107
- package/src/tools/release/pipeline/ChangeClassifier.ts +0 -61
- package/src/tools/release/pipeline/ChangeExtractor.ts +0 -87
- package/src/tools/release/pipeline/NotesRenderer.ts +0 -66
- package/src/tools/release/pipeline/SummaryScanner.ts +0 -70
- package/src/tools/release/pipeline/TagResolver.ts +0 -40
- package/src/tools/release/pipeline/VersionCalculator.ts +0 -375
- package/src/tools/release/publishers/GitHubPublisher.ts +0 -228
- package/src/tools/release/publishers/NpmPublisher.ts +0 -196
- package/src/tools/release/release-config.json +0 -5
- package/src/tools/release/types/index.ts +0 -282
- package/src/tools/release/validators/SemanticVersionValidator.ts +0 -67
package/src/components/core/Input-Text-Password/platforms/android/InputTextPassword.android.kt
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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. **
|
|
153
|
-
7. **
|
|
154
|
-
8. **
|
|
155
|
-
|
|
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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
|
package/src/components/core/Input-Text-PhoneNumber/platforms/android/InputTextPhoneNumber.android.kt
CHANGED
|
@@ -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.
|
|
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
|
|
package/src/components/core/Input-Text-PhoneNumber/platforms/ios/InputTextPhoneNumber.ios.swift
CHANGED
|
@@ -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: .
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
204
|
-
//
|
|
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
|
-
//
|
|
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/
|
|
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/
|
|
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: '
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
|
56
|
-
expect(
|
|
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
|
|
70
|
-
const currentKey = `node.size.${size}.current` as keyof typeof
|
|
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(
|
|
73
|
-
expect(
|
|
74
|
-
expect(
|
|
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
|
|
88
|
-
expect(
|
|
89
|
-
expect(
|
|
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
|
});
|