@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
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
name: Input-Text-Base
|
|
12
12
|
type: primitive
|
|
13
13
|
family: FormInput
|
|
14
|
-
version: "1.
|
|
14
|
+
version: "1.1.0"
|
|
15
15
|
readiness:
|
|
16
16
|
web:
|
|
17
17
|
reviewed: true
|
|
@@ -25,6 +25,16 @@ composition:
|
|
|
25
25
|
- component: Icon-Base
|
|
26
26
|
role: Trailing contextual icon (error, success, info)
|
|
27
27
|
required: false
|
|
28
|
+
slots:
|
|
29
|
+
- name: trailingContent
|
|
30
|
+
description: >-
|
|
31
|
+
Trailing content slot rendered after the status icons. Semantic
|
|
32
|
+
variants use it to inject interactive trailing controls (e.g.,
|
|
33
|
+
Input-Text-Password's visibility toggle). Native platforms only
|
|
34
|
+
(iOS: AnyView?, Android: @Composable lambda) — the web base has no
|
|
35
|
+
equivalent slot; web variants render trailing controls in their
|
|
36
|
+
own Shadow DOM.
|
|
37
|
+
required: false
|
|
28
38
|
|
|
29
39
|
# Component description
|
|
30
40
|
description: |
|
|
@@ -113,7 +123,11 @@ properties:
|
|
|
113
123
|
type: boolean
|
|
114
124
|
required: false
|
|
115
125
|
default: false
|
|
116
|
-
description:
|
|
126
|
+
description: >-
|
|
127
|
+
Read-only display state (state_readonly contract) — the value is
|
|
128
|
+
non-editable but stays perceivable, selectable, and copyable; no
|
|
129
|
+
keyboard/IME is raised and disabled semantics are never applied. iOS
|
|
130
|
+
renders it as selectable static text inside the field chrome.
|
|
117
131
|
|
|
118
132
|
required:
|
|
119
133
|
type: boolean
|
|
@@ -188,9 +202,23 @@ platform_notes:
|
|
|
188
202
|
ios:
|
|
189
203
|
implementation: SwiftUI View
|
|
190
204
|
file: platforms/ios/InputTextBase.ios.swift
|
|
205
|
+
notes: |
|
|
206
|
+
Platform composition parameters (not part of the cross-platform props):
|
|
207
|
+
- trailingContent: AnyView? = nil — trailing content slot (see composition.slots)
|
|
208
|
+
Masking: type .password renders SecureField; other types render TextField.
|
|
209
|
+
Variants toggle visibility by switching type between .password and .text.
|
|
191
210
|
android:
|
|
192
211
|
implementation: Jetpack Compose Composable
|
|
193
212
|
file: platforms/android/InputTextBase.android.kt
|
|
213
|
+
notes: |
|
|
214
|
+
Platform composition parameters (not part of the cross-platform props):
|
|
215
|
+
- modifier, imeAction, keyboardActions — standard Compose passthroughs
|
|
216
|
+
- visualTransformation: VisualTransformation? = null — masking override;
|
|
217
|
+
null derives from type (PasswordVisualTransformation for PASSWORD)
|
|
218
|
+
- trailingContent: (@Composable () -> Unit)? = null — trailing content
|
|
219
|
+
slot (see composition.slots)
|
|
220
|
+
Variants toggle password visibility via visualTransformation while
|
|
221
|
+
keeping type = PASSWORD (preserves the password keyboard type).
|
|
194
222
|
|
|
195
223
|
# Semantic components that inherit from this primitive
|
|
196
224
|
semantic_variants:
|
|
@@ -36,11 +36,12 @@ This component guarantees the following behaviors across all platforms:
|
|
|
36
36
|
| `validates_on_blur` | Validation triggers on blur | 3.3.1 |
|
|
37
37
|
| `error_state_display` | Shows error message and styling | 3.3.1, 1.4.1 |
|
|
38
38
|
| `success_state_display` | Shows success styling | 1.4.1 |
|
|
39
|
-
| `disabled_state` | Prevents interaction when disabled | 4.1.2 |
|
|
40
39
|
| `trailing_icon_display` | Shows contextual trailing icons | 1.4.1 |
|
|
41
40
|
| `focus_ring` | WCAG 2.4.7 focus visible indicator | 2.4.7 |
|
|
42
41
|
| `reduced_motion_support` | Respects prefers-reduced-motion | 2.3.3 |
|
|
43
42
|
|
|
43
|
+
**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).
|
|
44
|
+
|
|
44
45
|
---
|
|
45
46
|
|
|
46
47
|
## Related Documentation
|
|
@@ -145,12 +146,27 @@ InputTextBase(
|
|
|
145
146
|
| `type` | `'text' \| 'email' \| 'password' \| 'tel' \| 'url'` | No | `'text'` | Input type |
|
|
146
147
|
| `autocomplete` | `string` | No | - | Autocomplete attribute for browser autofill |
|
|
147
148
|
| `placeholder` | `string` | No | - | Placeholder text (only shown when label is floated and input is empty) |
|
|
148
|
-
| `readOnly` | `boolean` | No | `false` | Read-only state (
|
|
149
|
+
| `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. Ignored for secure types; not supported by Input-Text-Password |
|
|
149
150
|
| `required` | `boolean` | No | `false` | Required field indicator |
|
|
150
151
|
| `maxLength` | `number` | No | - | Maximum length for input value |
|
|
151
152
|
| `testID` | `string` | No | - | Test ID for automated testing |
|
|
152
153
|
| `className` | `string` | No | - | Additional CSS class names (web only) |
|
|
153
154
|
|
|
155
|
+
### Platform Composition Parameters (native only)
|
|
156
|
+
|
|
157
|
+
These parameters exist on the native implementations for platform composition —
|
|
158
|
+
they are not part of the cross-platform props contract above:
|
|
159
|
+
|
|
160
|
+
| Parameter | Platform | Type | Default | Description |
|
|
161
|
+
|-----------|----------|------|---------|-------------|
|
|
162
|
+
| `trailingContent` | iOS | `AnyView?` | `nil` | Trailing content slot rendered after the status icons (e.g., Input-Text-Password's visibility toggle) |
|
|
163
|
+
| `trailingContent` | Android | `(@Composable () -> Unit)?` | `null` | Same slot, Compose form |
|
|
164
|
+
| `visualTransformation` | Android | `VisualTransformation?` | `null` | Masking override; `null` derives from `type` (`PasswordVisualTransformation` for `PASSWORD`). Lets variants toggle password visibility while keeping the password keyboard type |
|
|
165
|
+
| `modifier`, `imeAction`, `keyboardActions` | Android | — | — | Standard Compose passthroughs |
|
|
166
|
+
|
|
167
|
+
The web base has no trailing slot equivalent — web semantic variants render
|
|
168
|
+
trailing controls inside their own Shadow DOM.
|
|
169
|
+
|
|
154
170
|
---
|
|
155
171
|
|
|
156
172
|
## Token Consumption
|
|
@@ -221,6 +237,13 @@ Legacy type aliases are provided for backward compatibility during migration.
|
|
|
221
237
|
|
|
222
238
|
## Changelog
|
|
223
239
|
|
|
240
|
+
### v1.1.0 (July 2026)
|
|
241
|
+
|
|
242
|
+
- Native bases gain a `trailingContent` composition slot (iOS `AnyView?`, Android `@Composable` lambda) so semantic variants can inject trailing controls — required by Input-Text-Password's visibility toggle
|
|
243
|
+
- Android base gains a `visualTransformation` override (null = derived from `type`) so variants can toggle masking without changing the input type
|
|
244
|
+
- Fixed Input-Text-PhoneNumber native callers referencing nonexistent enum members (`.phone`/`PHONE` → `.tel`/`TEL`)
|
|
245
|
+
- Added static base-call alignment test (`src/__tests__/stemma-system/input-text-native-base-call-alignment.test.ts`) guarding native call sites against parameter/enum drift
|
|
246
|
+
|
|
224
247
|
### v1.0.0 (January 2026)
|
|
225
248
|
|
|
226
249
|
- Initial release as Input-Text-Base (renamed from TextInputField)
|
|
@@ -165,8 +165,8 @@ describe('Input-Text-Base Focus Indicators', () => {
|
|
|
165
165
|
expect(iosComponentContent).toContain('accessibilityFocusWidth');
|
|
166
166
|
expect(iosComponentContent).toContain('accessibilityFocusOffset');
|
|
167
167
|
|
|
168
|
-
// Verify focus ring is visible when focused
|
|
169
|
-
expect(iosComponentContent).toContain('.opacity(isFocused
|
|
168
|
+
// Verify focus ring is visible when focused
|
|
169
|
+
expect(iosComponentContent).toContain('.opacity(isFocused ? 1 : 0)');
|
|
170
170
|
});
|
|
171
171
|
|
|
172
172
|
it('should have focus ring animation that respects reduce motion', () => {
|
|
@@ -194,8 +194,8 @@ describe('Input-Text-Base Focus Indicators', () => {
|
|
|
194
194
|
expect(androidComponentContent).toContain('accessibilityFocusColor');
|
|
195
195
|
expect(androidComponentContent).toContain('accessibilityFocusOffset');
|
|
196
196
|
|
|
197
|
-
// Verify focus ring is conditional on focus state
|
|
198
|
-
expect(androidComponentContent).toContain('if (isFocused
|
|
197
|
+
// Verify focus ring is conditional on focus state
|
|
198
|
+
expect(androidComponentContent).toContain('if (isFocused)');
|
|
199
199
|
});
|
|
200
200
|
});
|
|
201
201
|
|
|
@@ -219,16 +219,17 @@ describe('Input-Text-Base Focus Indicators', () => {
|
|
|
219
219
|
|
|
220
220
|
// iOS: Verify focus ring is not conditional on error/success state
|
|
221
221
|
// (it should always show when focused, regardless of validation state)
|
|
222
|
-
//
|
|
223
|
-
//
|
|
222
|
+
// Find the focus ring section in InputTextBaseFieldChrome (the shared
|
|
223
|
+
// field chrome, extracted from InputTextBaseFieldStyle per the B-prime
|
|
224
|
+
// readOnly ruling, 2026-07-15)
|
|
224
225
|
const iosFocusRingSection = iosContent.substring(
|
|
225
|
-
iosContent.indexOf('.opacity(isFocused
|
|
226
|
-
iosContent.indexOf('.opacity(isFocused
|
|
226
|
+
iosContent.indexOf('.opacity(isFocused ? 1 : 0)'),
|
|
227
|
+
iosContent.indexOf('.opacity(isFocused ? 1 : 0)') + 200
|
|
227
228
|
);
|
|
228
|
-
expect(iosFocusRingSection).toContain('.opacity(isFocused
|
|
229
|
-
|
|
230
|
-
// Android: Verify focus ring is conditional on focus state
|
|
231
|
-
expect(androidContent).toContain('if (isFocused
|
|
229
|
+
expect(iosFocusRingSection).toContain('.opacity(isFocused ? 1 : 0)');
|
|
230
|
+
|
|
231
|
+
// Android: Verify focus ring is conditional on focus state
|
|
232
|
+
expect(androidContent).toContain('if (isFocused)');
|
|
232
233
|
});
|
|
233
234
|
});
|
|
234
235
|
|
|
@@ -249,10 +250,10 @@ describe('Input-Text-Base Focus Indicators', () => {
|
|
|
249
250
|
expect(cssContent).toContain(':focus-visible');
|
|
250
251
|
|
|
251
252
|
// iOS: Uses overlay with opacity based on focus state
|
|
252
|
-
expect(iosContent).toContain('.opacity(isFocused
|
|
253
|
-
|
|
253
|
+
expect(iosContent).toContain('.opacity(isFocused ? 1 : 0)');
|
|
254
|
+
|
|
254
255
|
// Android: Uses conditional border based on focus state
|
|
255
|
-
expect(androidContent).toContain('if (isFocused
|
|
256
|
+
expect(androidContent).toContain('if (isFocused)');
|
|
256
257
|
});
|
|
257
258
|
|
|
258
259
|
it('should document WCAG 2.4.7 compliance in behavioral contracts', () => {
|
|
@@ -9,12 +9,29 @@ contracts:
|
|
|
9
9
|
behavior: |
|
|
10
10
|
Component can receive focus via Tab key navigation.
|
|
11
11
|
Focus state is visually indicated and triggers label animation.
|
|
12
|
+
|
|
13
|
+
Platform note — iOS readOnly carve-out (declared, adjudicated): when
|
|
14
|
+
readOnly is true, iOS renders the value as selectable static text
|
|
15
|
+
(see state_readonly) and does NOT participate in keyboard/Full
|
|
16
|
+
Keyboard Access focus order; onFocus/onBlur are declared not-fired on
|
|
17
|
+
that path. Web and Android readOnly fields affirmatively REMAIN in
|
|
18
|
+
focus order and fire focus events (removing an Android readOnly field
|
|
19
|
+
from focus order would require enabled=false — banned disabled
|
|
20
|
+
semantics — so normalizing web/Android down to iOS is not an
|
|
21
|
+
available move). The carve-out is a mitigable declared exception, not
|
|
22
|
+
a settled permanent difference: an on-device .focusable(interactions:)
|
|
23
|
+
prototype is tracked, and if it verifies (FKA reachability + keyboard
|
|
24
|
+
copy), iOS re-enters focus order and this note tightens to full
|
|
25
|
+
three-platform participation.
|
|
26
|
+
Ruling: .kiro/issues/input-text-base-ios-readonly-adjudication.md
|
|
27
|
+
(RULED B-prime, Peter 2026-07-15).
|
|
12
28
|
wcag: "2.1.1 Keyboard"
|
|
13
29
|
platforms: [web, ios, android]
|
|
14
30
|
validation:
|
|
15
31
|
- Tab key moves focus to input
|
|
16
32
|
- Focus state is visually distinct
|
|
17
33
|
- Focus triggers label float animation
|
|
34
|
+
- readOnly fields remain in keyboard focus order on web and Android
|
|
18
35
|
test_approach: |
|
|
19
36
|
- Press Tab, verify input receives focus
|
|
20
37
|
- Verify label animates on focus
|
|
@@ -74,6 +91,79 @@ contracts:
|
|
|
74
91
|
- Set error state, verify border/label/icon/message
|
|
75
92
|
required: true
|
|
76
93
|
|
|
94
|
+
# state_readonly concept ratified into the Concept Catalog via ballot
|
|
95
|
+
# (.kiro/docs/ballots/2026-07-15-state-readonly-concept.md, RATIFIED Peter
|
|
96
|
+
# 2026-07-15). Authored under the B-prime ruling:
|
|
97
|
+
# .kiro/issues/input-text-base-ios-readonly-adjudication.md (RULED by Peter,
|
|
98
|
+
# 2026-07-15).
|
|
99
|
+
state_readonly:
|
|
100
|
+
category: state
|
|
101
|
+
description: Displays a non-editable value that stays perceivable, selectable, and copyable — never disabled semantics
|
|
102
|
+
behavior: |
|
|
103
|
+
When readOnly is true, the component displays its value without
|
|
104
|
+
allowing edits. Invariants on all platforms:
|
|
105
|
+
- Content is selectable and copyable (whole-string copy is the
|
|
106
|
+
accepted iOS behavior — long-press select/copy on static text).
|
|
107
|
+
- Content is not editable; no software keyboard/IME is raised.
|
|
108
|
+
- Assistive technology announces the label, the value, and a
|
|
109
|
+
read-only indication — NEVER a disabled/dimmed trait or state.
|
|
110
|
+
- No disabled semantics of any kind (no SwiftUI .disabled(), no
|
|
111
|
+
Compose enabled=false, no aria-disabled/disabled attribute).
|
|
112
|
+
|
|
113
|
+
Announcement per platform:
|
|
114
|
+
- Web: native readonly attribute semantics (implicit aria-readonly).
|
|
115
|
+
- Android: explicit stateDescription("read only") in semantics.
|
|
116
|
+
- iOS: composed accessibility — label + value + read-only hint.
|
|
117
|
+
|
|
118
|
+
Focus order per platform:
|
|
119
|
+
- Web and Android: readOnly fields affirmatively PARTICIPATE in
|
|
120
|
+
keyboard focus order and fire onFocus/onBlur.
|
|
121
|
+
- iOS: readOnly content is rendered as selectable static text inside
|
|
122
|
+
the shared field chrome (B-prime); it is NOT in keyboard/FKA focus
|
|
123
|
+
order and onFocus/onBlur are DECLARED not-fired — a mitigable
|
|
124
|
+
declared exception. A .focusable(interactions:) on-device prototype
|
|
125
|
+
is tracked; if it verifies, this contract auto-tightens and iOS
|
|
126
|
+
re-enters focus order.
|
|
127
|
+
|
|
128
|
+
Tap-acknowledgment delta (platform note): tapping an Android readOnly
|
|
129
|
+
field focuses it (focus ring engages; empty-field label floats);
|
|
130
|
+
tapping the iOS readOnly text gives no acknowledgment until
|
|
131
|
+
long-press (select/copy). Declared, cosmetic.
|
|
132
|
+
|
|
133
|
+
Empty-value behavior: the label rests in placeholder position on all
|
|
134
|
+
platforms (no platform force-floats it), and the field chrome
|
|
135
|
+
reserves its full height unconditionally.
|
|
136
|
+
|
|
137
|
+
Secure-type carve-out (declared): when Input-Text-Base is used
|
|
138
|
+
directly with a secure/password type, readOnly is IGNORED — the field
|
|
139
|
+
remains an editable secure field. The read-only display path renders
|
|
140
|
+
the value as selectable plaintext and must be unreachable for
|
|
141
|
+
secrets; read-only passwords are excluded at the variant level
|
|
142
|
+
(Input-Text-Password excludes state_readonly and never forwards
|
|
143
|
+
readOnly).
|
|
144
|
+
wcag: "4.1.2 Name, Role, Value"
|
|
145
|
+
platforms: [web, ios, android]
|
|
146
|
+
validation:
|
|
147
|
+
- Value is not editable when readOnly is true
|
|
148
|
+
- Content is selectable and copyable on all platforms
|
|
149
|
+
- No software keyboard/IME is raised
|
|
150
|
+
- Web renders the native readonly attribute
|
|
151
|
+
- Android passes readOnly to the text field with enabled=true and sets
|
|
152
|
+
stateDescription("read only")
|
|
153
|
+
- iOS renders selectable Text (textSelection enabled) inside the
|
|
154
|
+
shared field chrome and composes a read-only accessibility hint
|
|
155
|
+
- No platform applies disabled semantics (.disabled(), enabled=false,
|
|
156
|
+
aria-disabled, dimmed trait)
|
|
157
|
+
- readOnly fields remain in keyboard focus order on web and Android
|
|
158
|
+
test_approach: |
|
|
159
|
+
- Static (Jest): web readonly attribute wiring; Android
|
|
160
|
+
readOnly = readOnly pass-through; iOS textSelection path present and
|
|
161
|
+
no .disabled( anywhere in Form Inputs iOS sources
|
|
162
|
+
- Device: attempt edit (rejected), copy value, verify announcement
|
|
163
|
+
(VoiceOver: label + value + read-only hint, never "dimmed";
|
|
164
|
+
TalkBack: "read only")
|
|
165
|
+
required: true
|
|
166
|
+
|
|
77
167
|
state_success:
|
|
78
168
|
category: state
|
|
79
169
|
description: Shows success styling
|
|
@@ -13,17 +13,17 @@
|
|
|
13
13
|
* - Color animation (text.subtle → primary with blend.focusSaturate)
|
|
14
14
|
* - Offset animation (translateY)
|
|
15
15
|
* - Trailing icon support (error, success, info)
|
|
16
|
+
* - Trailing content slot for semantic variants (e.g., password toggle)
|
|
16
17
|
* - Respects reduce motion settings
|
|
17
18
|
* - WCAG 2.1 AA compliant
|
|
18
|
-
* - Uses theme-aware blend utilities for state colors (focus
|
|
19
|
-
*
|
|
19
|
+
* - Uses theme-aware blend utilities for state colors (focus)
|
|
20
|
+
*
|
|
20
21
|
* Behavioral Contracts:
|
|
21
22
|
* - focusable: Can receive keyboard focus
|
|
22
23
|
* - float_label_animation: Label animates on focus
|
|
23
24
|
* - validates_on_blur: Validation triggers on blur
|
|
24
25
|
* - error_state_display: Shows error message and styling
|
|
25
26
|
* - success_state_display: Shows success styling
|
|
26
|
-
* - disabled_state: Prevents interaction when disabled
|
|
27
27
|
* - trailing_icon_display: Shows contextual trailing icons
|
|
28
28
|
* - focus_ring: WCAG 2.4.7 focus visible indicator
|
|
29
29
|
* - reduced_motion_support: Respects prefers-reduced-motion
|
|
@@ -57,6 +57,7 @@ import androidx.compose.ui.platform.LocalDensity
|
|
|
57
57
|
import androidx.compose.ui.semantics.contentDescription
|
|
58
58
|
import androidx.compose.ui.semantics.error
|
|
59
59
|
import androidx.compose.ui.semantics.semantics
|
|
60
|
+
import androidx.compose.ui.semantics.stateDescription
|
|
60
61
|
import androidx.compose.ui.text.TextStyle
|
|
61
62
|
import androidx.compose.ui.text.font.FontWeight
|
|
62
63
|
import androidx.compose.ui.text.input.ImeAction
|
|
@@ -68,7 +69,6 @@ import androidx.compose.ui.unit.dp
|
|
|
68
69
|
import androidx.compose.ui.unit.sp
|
|
69
70
|
import android.provider.Settings
|
|
70
71
|
import com.designerpunk.tokens.focusBlend
|
|
71
|
-
import com.designerpunk.tokens.disabledBlend
|
|
72
72
|
|
|
73
73
|
/**
|
|
74
74
|
* Input type enumeration
|
|
@@ -99,13 +99,17 @@ enum class InputType {
|
|
|
99
99
|
* @param isSuccess Success state indicator
|
|
100
100
|
* @param showInfoIcon Info icon support
|
|
101
101
|
* @param type Input type
|
|
102
|
+
* @param visualTransformation Override for the input's visual transformation.
|
|
103
|
+
* When null, derived from type (PasswordVisualTransformation for PASSWORD).
|
|
104
|
+
* Semantic variants use this to control masking (e.g., password visibility toggle).
|
|
102
105
|
* @param placeholder Placeholder text (only shown when label is floated and input is empty)
|
|
103
106
|
* @param readOnly Read-only state
|
|
104
107
|
* @param required Required field indicator
|
|
105
108
|
* @param maxLength Maximum length for input value
|
|
106
109
|
* @param imeAction IME action for keyboard
|
|
107
110
|
* @param keyboardActions Keyboard actions
|
|
108
|
-
* @param
|
|
111
|
+
* @param trailingContent Trailing content slot rendered after the status icons
|
|
112
|
+
* (e.g., password visibility toggle)
|
|
109
113
|
*/
|
|
110
114
|
@Composable
|
|
111
115
|
fun InputTextBase(
|
|
@@ -121,13 +125,14 @@ fun InputTextBase(
|
|
|
121
125
|
isSuccess: Boolean = false,
|
|
122
126
|
showInfoIcon: Boolean = false,
|
|
123
127
|
type: InputType = InputType.TEXT,
|
|
128
|
+
visualTransformation: VisualTransformation? = null,
|
|
124
129
|
placeholder: String? = null,
|
|
125
130
|
readOnly: Boolean = false,
|
|
126
131
|
required: Boolean = false,
|
|
127
132
|
maxLength: Int? = null,
|
|
128
133
|
imeAction: ImeAction = ImeAction.Done,
|
|
129
134
|
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
|
130
|
-
|
|
135
|
+
trailingContent: (@Composable () -> Unit)? = null
|
|
131
136
|
) {
|
|
132
137
|
// State
|
|
133
138
|
var isFocused by remember { mutableStateOf(false) }
|
|
@@ -192,7 +197,6 @@ fun InputTextBase(
|
|
|
192
197
|
targetValue = when {
|
|
193
198
|
hasError -> colorFeedbackErrorText
|
|
194
199
|
isSuccess -> colorFeedbackSuccessText
|
|
195
|
-
isDisabled -> colorActionPrimary.disabledBlend()
|
|
196
200
|
isFocused -> colorActionPrimary.focusBlend()
|
|
197
201
|
else -> colorTextMuted
|
|
198
202
|
},
|
|
@@ -204,7 +208,6 @@ fun InputTextBase(
|
|
|
204
208
|
targetValue = when {
|
|
205
209
|
hasError -> colorFeedbackErrorText
|
|
206
210
|
isSuccess -> colorFeedbackSuccessText
|
|
207
|
-
isDisabled -> colorActionPrimary.disabledBlend()
|
|
208
211
|
isFocused -> colorActionPrimary.focusBlend()
|
|
209
212
|
else -> colorBorder
|
|
210
213
|
},
|
|
@@ -230,6 +233,14 @@ fun InputTextBase(
|
|
|
230
233
|
if (errorMessage != null) {
|
|
231
234
|
error(errorMessage)
|
|
232
235
|
}
|
|
236
|
+
if (readOnly) {
|
|
237
|
+
// Explicit TalkBack read-only announcement — label, value,
|
|
238
|
+
// and "read only", never a disabled/dimmed state
|
|
239
|
+
// (state_readonly contract, announcement-parity condition 3:
|
|
240
|
+
// .kiro/issues/input-text-base-ios-readonly-adjudication.md,
|
|
241
|
+
// RULED B-prime, Peter 2026-07-15).
|
|
242
|
+
stateDescription = "read only"
|
|
243
|
+
}
|
|
233
244
|
}
|
|
234
245
|
) {
|
|
235
246
|
// Input wrapper with label and trailing icon
|
|
@@ -278,7 +289,7 @@ fun InputTextBase(
|
|
|
278
289
|
shape = RoundedCornerShape(radius150)
|
|
279
290
|
)
|
|
280
291
|
.then(
|
|
281
|
-
if (isFocused
|
|
292
|
+
if (isFocused) {
|
|
282
293
|
Modifier.border(
|
|
283
294
|
width = accessibilityFocusWidth,
|
|
284
295
|
color = accessibilityFocusColor,
|
|
@@ -295,7 +306,7 @@ fun InputTextBase(
|
|
|
295
306
|
lineHeight = typographyInputLineHeight.sp,
|
|
296
307
|
fontWeight = FontWeight(typographyInputFontWeight),
|
|
297
308
|
letterSpacing = typographyInputLetterSpacing.sp,
|
|
298
|
-
color =
|
|
309
|
+
color = colorTextDefault
|
|
299
310
|
),
|
|
300
311
|
keyboardOptions = KeyboardOptions(
|
|
301
312
|
keyboardType = getKeyboardType(type),
|
|
@@ -303,8 +314,8 @@ fun InputTextBase(
|
|
|
303
314
|
),
|
|
304
315
|
keyboardActions = keyboardActions,
|
|
305
316
|
singleLine = true,
|
|
306
|
-
readOnly = readOnly
|
|
307
|
-
visualTransformation = if (type == InputType.PASSWORD) {
|
|
317
|
+
readOnly = readOnly,
|
|
318
|
+
visualTransformation = visualTransformation ?: if (type == InputType.PASSWORD) {
|
|
308
319
|
PasswordVisualTransformation()
|
|
309
320
|
} else {
|
|
310
321
|
VisualTransformation.None
|
|
@@ -373,6 +384,9 @@ fun InputTextBase(
|
|
|
373
384
|
)
|
|
374
385
|
}
|
|
375
386
|
}
|
|
387
|
+
|
|
388
|
+
// Trailing content slot (e.g., password visibility toggle)
|
|
389
|
+
trailingContent?.invoke()
|
|
376
390
|
}
|
|
377
391
|
|
|
378
392
|
// Helper text (persistent)
|