rn-inputforge 0.4.0 → 0.5.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/README.md +723 -39
- package/lib/commonjs/adapters/index.js +25 -0
- package/lib/commonjs/adapters/index.js.map +1 -0
- package/lib/commonjs/adapters/reactHookForm.js +107 -0
- package/lib/commonjs/adapters/reactHookForm.js.map +1 -0
- package/lib/commonjs/components/FieldFlowAffordance/FieldFlowAffordance.js +104 -0
- package/lib/commonjs/components/FieldFlowAffordance/FieldFlowAffordance.js.map +1 -0
- package/lib/commonjs/components/FieldFlowAffordance/index.js +13 -0
- package/lib/commonjs/components/FieldFlowAffordance/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowCreditCard/FieldFlowCreditCard.js +146 -0
- package/lib/commonjs/components/FieldFlowCreditCard/FieldFlowCreditCard.js.map +1 -0
- package/lib/commonjs/components/FieldFlowCreditCard/index.js +13 -0
- package/lib/commonjs/components/FieldFlowCreditCard/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowDraftBanner/FieldFlowDraftBanner.js +156 -0
- package/lib/commonjs/components/FieldFlowDraftBanner/FieldFlowDraftBanner.js.map +1 -0
- package/lib/commonjs/components/FieldFlowDraftBanner/index.js +13 -0
- package/lib/commonjs/components/FieldFlowDraftBanner/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowInput/FieldFlowInput.js +143 -43
- package/lib/commonjs/components/FieldFlowInput/FieldFlowInput.js.map +1 -1
- package/lib/commonjs/components/FieldFlowInput/styles.js +16 -0
- package/lib/commonjs/components/FieldFlowInput/styles.js.map +1 -1
- package/lib/commonjs/components/FieldFlowNumberStepper/FieldFlowNumberStepper.js +136 -0
- package/lib/commonjs/components/FieldFlowNumberStepper/FieldFlowNumberStepper.js.map +1 -0
- package/lib/commonjs/components/FieldFlowNumberStepper/index.js +13 -0
- package/lib/commonjs/components/FieldFlowNumberStepper/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowPasswordStrength/FieldFlowPasswordStrength.js +122 -0
- package/lib/commonjs/components/FieldFlowPasswordStrength/FieldFlowPasswordStrength.js.map +1 -0
- package/lib/commonjs/components/FieldFlowPasswordStrength/index.js +13 -0
- package/lib/commonjs/components/FieldFlowPasswordStrength/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowPhone/FieldFlowPhone.js +263 -0
- package/lib/commonjs/components/FieldFlowPhone/FieldFlowPhone.js.map +1 -0
- package/lib/commonjs/components/FieldFlowPhone/index.js +13 -0
- package/lib/commonjs/components/FieldFlowPhone/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowRating/FieldFlowRating.js +106 -0
- package/lib/commonjs/components/FieldFlowRating/FieldFlowRating.js.map +1 -0
- package/lib/commonjs/components/FieldFlowRating/index.js +13 -0
- package/lib/commonjs/components/FieldFlowRating/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowSection/FieldFlowSection.js +141 -0
- package/lib/commonjs/components/FieldFlowSection/FieldFlowSection.js.map +1 -0
- package/lib/commonjs/components/FieldFlowSection/index.js +13 -0
- package/lib/commonjs/components/FieldFlowSection/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowSegmented/FieldFlowSegmented.js +195 -0
- package/lib/commonjs/components/FieldFlowSegmented/FieldFlowSegmented.js.map +1 -0
- package/lib/commonjs/components/FieldFlowSegmented/index.js +13 -0
- package/lib/commonjs/components/FieldFlowSegmented/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowSignature/FieldFlowSignature.js +200 -0
- package/lib/commonjs/components/FieldFlowSignature/FieldFlowSignature.js.map +1 -0
- package/lib/commonjs/components/FieldFlowSignature/index.js +13 -0
- package/lib/commonjs/components/FieldFlowSignature/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowSlider/FieldFlowSlider.js +178 -0
- package/lib/commonjs/components/FieldFlowSlider/FieldFlowSlider.js.map +1 -0
- package/lib/commonjs/components/FieldFlowSlider/index.js +13 -0
- package/lib/commonjs/components/FieldFlowSlider/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowStepper/FieldFlowStepper.js +166 -0
- package/lib/commonjs/components/FieldFlowStepper/FieldFlowStepper.js.map +1 -0
- package/lib/commonjs/components/FieldFlowStepper/index.js +13 -0
- package/lib/commonjs/components/FieldFlowStepper/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowTags/FieldFlowTags.js +240 -0
- package/lib/commonjs/components/FieldFlowTags/FieldFlowTags.js.map +1 -0
- package/lib/commonjs/components/FieldFlowTags/index.js +13 -0
- package/lib/commonjs/components/FieldFlowTags/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowTypeahead/FieldFlowTypeahead.js +227 -0
- package/lib/commonjs/components/FieldFlowTypeahead/FieldFlowTypeahead.js.map +1 -0
- package/lib/commonjs/components/FieldFlowTypeahead/index.js +13 -0
- package/lib/commonjs/components/FieldFlowTypeahead/index.js.map +1 -0
- package/lib/commonjs/components/FieldFlowUpload/FieldFlowUpload.js +191 -0
- package/lib/commonjs/components/FieldFlowUpload/FieldFlowUpload.js.map +1 -0
- package/lib/commonjs/components/FieldFlowUpload/index.js +13 -0
- package/lib/commonjs/components/FieldFlowUpload/index.js.map +1 -0
- package/lib/commonjs/hooks/index.js +35 -0
- package/lib/commonjs/hooks/index.js.map +1 -1
- package/lib/commonjs/hooks/useFieldFlowArray.js +110 -0
- package/lib/commonjs/hooks/useFieldFlowArray.js.map +1 -0
- package/lib/commonjs/hooks/useFieldFlowDirtyGuard.js +53 -0
- package/lib/commonjs/hooks/useFieldFlowDirtyGuard.js.map +1 -0
- package/lib/commonjs/hooks/useFieldFlowDraft.js +168 -0
- package/lib/commonjs/hooks/useFieldFlowDraft.js.map +1 -0
- package/lib/commonjs/hooks/useFieldFlowForm.js +224 -30
- package/lib/commonjs/hooks/useFieldFlowForm.js.map +1 -1
- package/lib/commonjs/hooks/useFieldFlowSteps.js +77 -0
- package/lib/commonjs/hooks/useFieldFlowSteps.js.map +1 -0
- package/lib/commonjs/hooks/useFormIntelligence.js +130 -0
- package/lib/commonjs/hooks/useFormIntelligence.js.map +1 -0
- package/lib/commonjs/i18n/index.js +25 -0
- package/lib/commonjs/i18n/index.js.map +1 -0
- package/lib/commonjs/i18n/messages.js +88 -0
- package/lib/commonjs/i18n/messages.js.map +1 -0
- package/lib/commonjs/index.js +322 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/intelligence/formAccessibility.js +79 -0
- package/lib/commonjs/intelligence/formAccessibility.js.map +1 -0
- package/lib/commonjs/intelligence/index.js +31 -0
- package/lib/commonjs/intelligence/index.js.map +1 -0
- package/lib/commonjs/intelligence/types.js +2 -0
- package/lib/commonjs/intelligence/types.js.map +1 -0
- package/lib/commonjs/motion/index.js +20 -0
- package/lib/commonjs/motion/index.js.map +1 -0
- package/lib/commonjs/motion/useFieldMotion.js +111 -0
- package/lib/commonjs/motion/useFieldMotion.js.map +1 -0
- package/lib/commonjs/motion/useReducedMotion.js +32 -0
- package/lib/commonjs/motion/useReducedMotion.js.map +1 -0
- package/lib/commonjs/theme/index.js +13 -0
- package/lib/commonjs/theme/index.js.map +1 -1
- package/lib/commonjs/theme/presets.js +142 -0
- package/lib/commonjs/theme/presets.js.map +1 -0
- package/lib/commonjs/utils/affordance.js +151 -0
- package/lib/commonjs/utils/affordance.js.map +1 -0
- package/lib/commonjs/utils/passwordStrength.js +79 -0
- package/lib/commonjs/utils/passwordStrength.js.map +1 -0
- package/lib/commonjs/utils/phoneCountries.js +119 -0
- package/lib/commonjs/utils/phoneCountries.js.map +1 -0
- package/lib/commonjs/validation/validators.js +10 -7
- package/lib/commonjs/validation/validators.js.map +1 -1
- package/lib/module/adapters/index.js +4 -0
- package/lib/module/adapters/index.js.map +1 -0
- package/lib/module/adapters/reactHookForm.js +100 -0
- package/lib/module/adapters/reactHookForm.js.map +1 -0
- package/lib/module/components/FieldFlowAffordance/FieldFlowAffordance.js +99 -0
- package/lib/module/components/FieldFlowAffordance/FieldFlowAffordance.js.map +1 -0
- package/lib/module/components/FieldFlowAffordance/index.js +4 -0
- package/lib/module/components/FieldFlowAffordance/index.js.map +1 -0
- package/lib/module/components/FieldFlowCreditCard/FieldFlowCreditCard.js +141 -0
- package/lib/module/components/FieldFlowCreditCard/FieldFlowCreditCard.js.map +1 -0
- package/lib/module/components/FieldFlowCreditCard/index.js +4 -0
- package/lib/module/components/FieldFlowCreditCard/index.js.map +1 -0
- package/lib/module/components/FieldFlowDraftBanner/FieldFlowDraftBanner.js +151 -0
- package/lib/module/components/FieldFlowDraftBanner/FieldFlowDraftBanner.js.map +1 -0
- package/lib/module/components/FieldFlowDraftBanner/index.js +4 -0
- package/lib/module/components/FieldFlowDraftBanner/index.js.map +1 -0
- package/lib/module/components/FieldFlowInput/FieldFlowInput.js +144 -44
- package/lib/module/components/FieldFlowInput/FieldFlowInput.js.map +1 -1
- package/lib/module/components/FieldFlowInput/styles.js +16 -0
- package/lib/module/components/FieldFlowInput/styles.js.map +1 -1
- package/lib/module/components/FieldFlowNumberStepper/FieldFlowNumberStepper.js +131 -0
- package/lib/module/components/FieldFlowNumberStepper/FieldFlowNumberStepper.js.map +1 -0
- package/lib/module/components/FieldFlowNumberStepper/index.js +4 -0
- package/lib/module/components/FieldFlowNumberStepper/index.js.map +1 -0
- package/lib/module/components/FieldFlowPasswordStrength/FieldFlowPasswordStrength.js +117 -0
- package/lib/module/components/FieldFlowPasswordStrength/FieldFlowPasswordStrength.js.map +1 -0
- package/lib/module/components/FieldFlowPasswordStrength/index.js +4 -0
- package/lib/module/components/FieldFlowPasswordStrength/index.js.map +1 -0
- package/lib/module/components/FieldFlowPhone/FieldFlowPhone.js +258 -0
- package/lib/module/components/FieldFlowPhone/FieldFlowPhone.js.map +1 -0
- package/lib/module/components/FieldFlowPhone/index.js +4 -0
- package/lib/module/components/FieldFlowPhone/index.js.map +1 -0
- package/lib/module/components/FieldFlowRating/FieldFlowRating.js +101 -0
- package/lib/module/components/FieldFlowRating/FieldFlowRating.js.map +1 -0
- package/lib/module/components/FieldFlowRating/index.js +4 -0
- package/lib/module/components/FieldFlowRating/index.js.map +1 -0
- package/lib/module/components/FieldFlowSection/FieldFlowSection.js +136 -0
- package/lib/module/components/FieldFlowSection/FieldFlowSection.js.map +1 -0
- package/lib/module/components/FieldFlowSection/index.js +4 -0
- package/lib/module/components/FieldFlowSection/index.js.map +1 -0
- package/lib/module/components/FieldFlowSegmented/FieldFlowSegmented.js +190 -0
- package/lib/module/components/FieldFlowSegmented/FieldFlowSegmented.js.map +1 -0
- package/lib/module/components/FieldFlowSegmented/index.js +4 -0
- package/lib/module/components/FieldFlowSegmented/index.js.map +1 -0
- package/lib/module/components/FieldFlowSignature/FieldFlowSignature.js +195 -0
- package/lib/module/components/FieldFlowSignature/FieldFlowSignature.js.map +1 -0
- package/lib/module/components/FieldFlowSignature/index.js +4 -0
- package/lib/module/components/FieldFlowSignature/index.js.map +1 -0
- package/lib/module/components/FieldFlowSlider/FieldFlowSlider.js +173 -0
- package/lib/module/components/FieldFlowSlider/FieldFlowSlider.js.map +1 -0
- package/lib/module/components/FieldFlowSlider/index.js +4 -0
- package/lib/module/components/FieldFlowSlider/index.js.map +1 -0
- package/lib/module/components/FieldFlowStepper/FieldFlowStepper.js +161 -0
- package/lib/module/components/FieldFlowStepper/FieldFlowStepper.js.map +1 -0
- package/lib/module/components/FieldFlowStepper/index.js +4 -0
- package/lib/module/components/FieldFlowStepper/index.js.map +1 -0
- package/lib/module/components/FieldFlowTags/FieldFlowTags.js +235 -0
- package/lib/module/components/FieldFlowTags/FieldFlowTags.js.map +1 -0
- package/lib/module/components/FieldFlowTags/index.js +4 -0
- package/lib/module/components/FieldFlowTags/index.js.map +1 -0
- package/lib/module/components/FieldFlowTypeahead/FieldFlowTypeahead.js +222 -0
- package/lib/module/components/FieldFlowTypeahead/FieldFlowTypeahead.js.map +1 -0
- package/lib/module/components/FieldFlowTypeahead/index.js +4 -0
- package/lib/module/components/FieldFlowTypeahead/index.js.map +1 -0
- package/lib/module/components/FieldFlowUpload/FieldFlowUpload.js +186 -0
- package/lib/module/components/FieldFlowUpload/FieldFlowUpload.js.map +1 -0
- package/lib/module/components/FieldFlowUpload/index.js +4 -0
- package/lib/module/components/FieldFlowUpload/index.js.map +1 -0
- package/lib/module/hooks/index.js +5 -0
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/useFieldFlowArray.js +106 -0
- package/lib/module/hooks/useFieldFlowArray.js.map +1 -0
- package/lib/module/hooks/useFieldFlowDirtyGuard.js +49 -0
- package/lib/module/hooks/useFieldFlowDirtyGuard.js.map +1 -0
- package/lib/module/hooks/useFieldFlowDraft.js +165 -0
- package/lib/module/hooks/useFieldFlowDraft.js.map +1 -0
- package/lib/module/hooks/useFieldFlowForm.js +224 -30
- package/lib/module/hooks/useFieldFlowForm.js.map +1 -1
- package/lib/module/hooks/useFieldFlowSteps.js +73 -0
- package/lib/module/hooks/useFieldFlowSteps.js.map +1 -0
- package/lib/module/hooks/useFormIntelligence.js +126 -0
- package/lib/module/hooks/useFormIntelligence.js.map +1 -0
- package/lib/module/i18n/index.js +4 -0
- package/lib/module/i18n/index.js.map +1 -0
- package/lib/module/i18n/messages.js +82 -0
- package/lib/module/i18n/messages.js.map +1 -0
- package/lib/module/index.js +31 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/intelligence/formAccessibility.js +72 -0
- package/lib/module/intelligence/formAccessibility.js.map +1 -0
- package/lib/module/intelligence/index.js +4 -0
- package/lib/module/intelligence/index.js.map +1 -0
- package/lib/module/intelligence/types.js +2 -0
- package/lib/module/intelligence/types.js.map +1 -0
- package/lib/module/motion/index.js +5 -0
- package/lib/module/motion/index.js.map +1 -0
- package/lib/module/motion/useFieldMotion.js +107 -0
- package/lib/module/motion/useFieldMotion.js.map +1 -0
- package/lib/module/motion/useReducedMotion.js +29 -0
- package/lib/module/motion/useReducedMotion.js.map +1 -0
- package/lib/module/theme/index.js +1 -0
- package/lib/module/theme/index.js.map +1 -1
- package/lib/module/theme/presets.js +138 -0
- package/lib/module/theme/presets.js.map +1 -0
- package/lib/module/utils/affordance.js +140 -0
- package/lib/module/utils/affordance.js.map +1 -0
- package/lib/module/utils/passwordStrength.js +74 -0
- package/lib/module/utils/passwordStrength.js.map +1 -0
- package/lib/module/utils/phoneCountries.js +113 -0
- package/lib/module/utils/phoneCountries.js.map +1 -0
- package/lib/module/validation/validators.js +10 -7
- package/lib/module/validation/validators.js.map +1 -1
- package/lib/typescript/adapters/index.d.ts +3 -0
- package/lib/typescript/adapters/index.d.ts.map +1 -0
- package/lib/typescript/adapters/reactHookForm.d.ts +56 -0
- package/lib/typescript/adapters/reactHookForm.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowAffordance/FieldFlowAffordance.d.ts +29 -0
- package/lib/typescript/components/FieldFlowAffordance/FieldFlowAffordance.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowAffordance/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowAffordance/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowCreditCard/FieldFlowCreditCard.d.ts +27 -0
- package/lib/typescript/components/FieldFlowCreditCard/FieldFlowCreditCard.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowCreditCard/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowCreditCard/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowDraftBanner/FieldFlowDraftBanner.d.ts +24 -0
- package/lib/typescript/components/FieldFlowDraftBanner/FieldFlowDraftBanner.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowDraftBanner/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowDraftBanner/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowInput/FieldFlowInput.d.ts.map +1 -1
- package/lib/typescript/components/FieldFlowInput/styles.d.ts +16 -0
- package/lib/typescript/components/FieldFlowInput/styles.d.ts.map +1 -1
- package/lib/typescript/components/FieldFlowInput/types.d.ts +32 -0
- package/lib/typescript/components/FieldFlowInput/types.d.ts.map +1 -1
- package/lib/typescript/components/FieldFlowNumberStepper/FieldFlowNumberStepper.d.ts +34 -0
- package/lib/typescript/components/FieldFlowNumberStepper/FieldFlowNumberStepper.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowNumberStepper/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowNumberStepper/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowPasswordStrength/FieldFlowPasswordStrength.d.ts +26 -0
- package/lib/typescript/components/FieldFlowPasswordStrength/FieldFlowPasswordStrength.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowPasswordStrength/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowPasswordStrength/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowPhone/FieldFlowPhone.d.ts +40 -0
- package/lib/typescript/components/FieldFlowPhone/FieldFlowPhone.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowPhone/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowPhone/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowRating/FieldFlowRating.d.ts +30 -0
- package/lib/typescript/components/FieldFlowRating/FieldFlowRating.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowRating/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowRating/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowSection/FieldFlowSection.d.ts +35 -0
- package/lib/typescript/components/FieldFlowSection/FieldFlowSection.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowSection/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowSection/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowSegmented/FieldFlowSegmented.d.ts +28 -0
- package/lib/typescript/components/FieldFlowSegmented/FieldFlowSegmented.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowSegmented/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowSegmented/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowSignature/FieldFlowSignature.d.ts +41 -0
- package/lib/typescript/components/FieldFlowSignature/FieldFlowSignature.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowSignature/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowSignature/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowSlider/FieldFlowSlider.d.ts +30 -0
- package/lib/typescript/components/FieldFlowSlider/FieldFlowSlider.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowSlider/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowSlider/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowStepper/FieldFlowStepper.d.ts +31 -0
- package/lib/typescript/components/FieldFlowStepper/FieldFlowStepper.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowStepper/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowStepper/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowTags/FieldFlowTags.d.ts +41 -0
- package/lib/typescript/components/FieldFlowTags/FieldFlowTags.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowTags/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowTags/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowTypeahead/FieldFlowTypeahead.d.ts +43 -0
- package/lib/typescript/components/FieldFlowTypeahead/FieldFlowTypeahead.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowTypeahead/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowTypeahead/index.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowUpload/FieldFlowUpload.d.ts +52 -0
- package/lib/typescript/components/FieldFlowUpload/FieldFlowUpload.d.ts.map +1 -0
- package/lib/typescript/components/FieldFlowUpload/index.d.ts +3 -0
- package/lib/typescript/components/FieldFlowUpload/index.d.ts.map +1 -0
- package/lib/typescript/hooks/index.d.ts +11 -1
- package/lib/typescript/hooks/index.d.ts.map +1 -1
- package/lib/typescript/hooks/useFieldFlowArray.d.ts +54 -0
- package/lib/typescript/hooks/useFieldFlowArray.d.ts.map +1 -0
- package/lib/typescript/hooks/useFieldFlowDirtyGuard.d.ts +26 -0
- package/lib/typescript/hooks/useFieldFlowDirtyGuard.d.ts.map +1 -0
- package/lib/typescript/hooks/useFieldFlowDraft.d.ts +64 -0
- package/lib/typescript/hooks/useFieldFlowDraft.d.ts.map +1 -0
- package/lib/typescript/hooks/useFieldFlowForm.d.ts +80 -2
- package/lib/typescript/hooks/useFieldFlowForm.d.ts.map +1 -1
- package/lib/typescript/hooks/useFieldFlowSteps.d.ts +42 -0
- package/lib/typescript/hooks/useFieldFlowSteps.d.ts.map +1 -0
- package/lib/typescript/hooks/useFormIntelligence.d.ts +23 -0
- package/lib/typescript/hooks/useFormIntelligence.d.ts.map +1 -0
- package/lib/typescript/i18n/index.d.ts +3 -0
- package/lib/typescript/i18n/index.d.ts.map +1 -0
- package/lib/typescript/i18n/messages.d.ts +16 -0
- package/lib/typescript/i18n/messages.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +48 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/intelligence/formAccessibility.d.ts +21 -0
- package/lib/typescript/intelligence/formAccessibility.d.ts.map +1 -0
- package/lib/typescript/intelligence/index.d.ts +4 -0
- package/lib/typescript/intelligence/index.d.ts.map +1 -0
- package/lib/typescript/intelligence/types.d.ts +36 -0
- package/lib/typescript/intelligence/types.d.ts.map +1 -0
- package/lib/typescript/motion/index.d.ts +4 -0
- package/lib/typescript/motion/index.d.ts.map +1 -0
- package/lib/typescript/motion/useFieldMotion.d.ts +31 -0
- package/lib/typescript/motion/useFieldMotion.d.ts.map +1 -0
- package/lib/typescript/motion/useReducedMotion.d.ts +5 -0
- package/lib/typescript/motion/useReducedMotion.d.ts.map +1 -0
- package/lib/typescript/theme/index.d.ts +2 -0
- package/lib/typescript/theme/index.d.ts.map +1 -1
- package/lib/typescript/theme/presets.d.ts +134 -0
- package/lib/typescript/theme/presets.d.ts.map +1 -0
- package/lib/typescript/utils/affordance.d.ts +36 -0
- package/lib/typescript/utils/affordance.d.ts.map +1 -0
- package/lib/typescript/utils/passwordStrength.d.ts +26 -0
- package/lib/typescript/utils/passwordStrength.d.ts.map +1 -0
- package/lib/typescript/utils/phoneCountries.d.ts +12 -0
- package/lib/typescript/utils/phoneCountries.d.ts.map +1 -0
- package/lib/typescript/validation/validators.d.ts +3 -1
- package/lib/typescript/validation/validators.d.ts.map +1 -1
- package/package.json +19 -2
- package/src/adapters/index.ts +9 -0
- package/src/adapters/reactHookForm.tsx +152 -0
- package/src/components/FieldFlowAffordance/FieldFlowAffordance.tsx +143 -0
- package/src/components/FieldFlowAffordance/index.ts +2 -0
- package/src/components/FieldFlowCreditCard/FieldFlowCreditCard.tsx +152 -0
- package/src/components/FieldFlowCreditCard/index.ts +2 -0
- package/src/components/FieldFlowDraftBanner/FieldFlowDraftBanner.tsx +169 -0
- package/src/components/FieldFlowDraftBanner/index.ts +2 -0
- package/src/components/FieldFlowInput/FieldFlowInput.tsx +174 -53
- package/src/components/FieldFlowInput/styles.ts +16 -0
- package/src/components/FieldFlowInput/types.ts +33 -0
- package/src/components/FieldFlowNumberStepper/FieldFlowNumberStepper.tsx +156 -0
- package/src/components/FieldFlowNumberStepper/index.ts +2 -0
- package/src/components/FieldFlowPasswordStrength/FieldFlowPasswordStrength.tsx +148 -0
- package/src/components/FieldFlowPasswordStrength/index.ts +2 -0
- package/src/components/FieldFlowPhone/FieldFlowPhone.tsx +298 -0
- package/src/components/FieldFlowPhone/index.ts +2 -0
- package/src/components/FieldFlowRating/FieldFlowRating.tsx +121 -0
- package/src/components/FieldFlowRating/index.ts +2 -0
- package/src/components/FieldFlowSection/FieldFlowSection.tsx +176 -0
- package/src/components/FieldFlowSection/index.ts +2 -0
- package/src/components/FieldFlowSegmented/FieldFlowSegmented.tsx +248 -0
- package/src/components/FieldFlowSegmented/index.ts +2 -0
- package/src/components/FieldFlowSignature/FieldFlowSignature.tsx +241 -0
- package/src/components/FieldFlowSignature/index.ts +7 -0
- package/src/components/FieldFlowSlider/FieldFlowSlider.tsx +190 -0
- package/src/components/FieldFlowSlider/index.ts +2 -0
- package/src/components/FieldFlowStepper/FieldFlowStepper.tsx +190 -0
- package/src/components/FieldFlowStepper/index.ts +2 -0
- package/src/components/FieldFlowTags/FieldFlowTags.tsx +319 -0
- package/src/components/FieldFlowTags/index.ts +2 -0
- package/src/components/FieldFlowTypeahead/FieldFlowTypeahead.tsx +261 -0
- package/src/components/FieldFlowTypeahead/index.ts +2 -0
- package/src/components/FieldFlowUpload/FieldFlowUpload.tsx +226 -0
- package/src/components/FieldFlowUpload/index.ts +6 -0
- package/src/hooks/index.ts +31 -0
- package/src/hooks/useFieldFlowArray.ts +153 -0
- package/src/hooks/useFieldFlowDirtyGuard.ts +70 -0
- package/src/hooks/useFieldFlowDraft.ts +221 -0
- package/src/hooks/useFieldFlowForm.ts +357 -28
- package/src/hooks/useFieldFlowSteps.ts +130 -0
- package/src/hooks/useFormIntelligence.ts +207 -0
- package/src/i18n/index.ts +6 -0
- package/src/i18n/messages.ts +101 -0
- package/src/index.ts +161 -3
- package/src/intelligence/formAccessibility.ts +87 -0
- package/src/intelligence/index.ts +12 -0
- package/src/intelligence/types.ts +34 -0
- package/src/motion/index.ts +3 -0
- package/src/motion/useFieldMotion.ts +120 -0
- package/src/motion/useReducedMotion.ts +31 -0
- package/src/theme/index.ts +2 -0
- package/src/theme/presets.ts +120 -0
- package/src/utils/affordance.ts +138 -0
- package/src/utils/passwordStrength.ts +109 -0
- package/src/utils/phoneCountries.ts +44 -0
- package/src/validation/validators.ts +17 -7
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import type { TextInput } from 'react-native';
|
|
2
3
|
import type { FieldFlowRules, ValidationResult } from '../types';
|
|
3
4
|
import { runRules } from '../validation/validators';
|
|
5
|
+
import {
|
|
6
|
+
getValidationMessages,
|
|
7
|
+
type FieldFlowLocale,
|
|
8
|
+
type FieldFlowValidationMessages,
|
|
9
|
+
} from '../i18n/messages';
|
|
10
|
+
import {
|
|
11
|
+
useFormIntelligence,
|
|
12
|
+
type UseFormIntelligenceResult,
|
|
13
|
+
} from './useFormIntelligence';
|
|
14
|
+
import type { FormIntelligenceOptions } from '../intelligence/types';
|
|
4
15
|
|
|
5
16
|
export type FieldFlowFormRules<T extends Record<string, string>> = {
|
|
6
17
|
[K in keyof T]?: FieldFlowRules;
|
|
@@ -23,6 +34,27 @@ export interface CrossFieldRule<T extends Record<string, string>> {
|
|
|
23
34
|
validate: (values: T) => ValidationResult;
|
|
24
35
|
}
|
|
25
36
|
|
|
37
|
+
export type FieldConditionFn<T extends Record<string, string>> = (values: T) => boolean;
|
|
38
|
+
|
|
39
|
+
export interface FieldConditionConfig<T extends Record<string, string>> {
|
|
40
|
+
/** Hide the field when false. Hidden fields are skipped during validation. */
|
|
41
|
+
showWhen?: FieldConditionFn<T>;
|
|
42
|
+
/** Dynamically require the field. */
|
|
43
|
+
requiredWhen?: FieldConditionFn<T>;
|
|
44
|
+
/** Dynamically disable the field (caller should pass `disabled` to the input). */
|
|
45
|
+
disabledWhen?: FieldConditionFn<T>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type FieldConditions<T extends Record<string, string>> = {
|
|
49
|
+
[K in keyof T]?: FieldConditionConfig<T>;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export interface FieldVisibilityState {
|
|
53
|
+
visible: boolean;
|
|
54
|
+
required: boolean;
|
|
55
|
+
disabled: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
26
58
|
export interface UseFieldFlowFormOptions<T extends Record<string, string>> {
|
|
27
59
|
initialValues: T;
|
|
28
60
|
rules?: FieldFlowFormRules<T>;
|
|
@@ -39,6 +71,10 @@ export interface UseFieldFlowFormOptions<T extends Record<string, string>> {
|
|
|
39
71
|
* }]
|
|
40
72
|
*/
|
|
41
73
|
crossFieldRules?: CrossFieldRule<T>[];
|
|
74
|
+
/**
|
|
75
|
+
* Conditional visibility / required / disabled rules evaluated against live values.
|
|
76
|
+
*/
|
|
77
|
+
conditions?: FieldConditions<T>;
|
|
42
78
|
/**
|
|
43
79
|
* Whole-form validator (e.g. from `zodFormValidate(schema)`).
|
|
44
80
|
* Merged after sync + cross-field rules; field keys map to error messages.
|
|
@@ -53,6 +89,20 @@ export interface UseFieldFlowFormOptions<T extends Record<string, string>> {
|
|
|
53
89
|
asyncValidators?: AsyncFieldValidators<T>;
|
|
54
90
|
/** Debounce for async field validators on change. Default: 400ms. */
|
|
55
91
|
asyncDebounceMs?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Enable form intelligence (friction analytics + a11y autofocus/announce on failed submit).
|
|
94
|
+
* Pass `true` for defaults, or an options object.
|
|
95
|
+
*/
|
|
96
|
+
intelligence?: boolean | FormIntelligenceOptions;
|
|
97
|
+
/** Preferred field order for focus-first-error / announcements. */
|
|
98
|
+
fieldOrder?: (keyof T)[];
|
|
99
|
+
/**
|
|
100
|
+
* Locale for default validation messages (`en` | `es` | `fr` | `de` | `pt` | `ar`).
|
|
101
|
+
* Ignored for rule keys that already pass a custom string message.
|
|
102
|
+
*/
|
|
103
|
+
locale?: FieldFlowLocale;
|
|
104
|
+
/** Full message catalog override (wins over `locale`). */
|
|
105
|
+
messages?: FieldFlowValidationMessages;
|
|
56
106
|
/** Called only when every field passes sync + cross-field + form + async validation. */
|
|
57
107
|
onSubmit?: (values: T) => void | Promise<void>;
|
|
58
108
|
}
|
|
@@ -67,30 +117,77 @@ export interface UseFieldFlowFormResult<T extends Record<string, string>> {
|
|
|
67
117
|
isValid: boolean;
|
|
68
118
|
/** True while any async field validator is in flight. */
|
|
69
119
|
isValidating: boolean;
|
|
120
|
+
/** True when current values differ from `initialValues`. */
|
|
121
|
+
isDirty: boolean;
|
|
122
|
+
/** Per-field dirty flags. */
|
|
123
|
+
dirtyFields: Partial<Record<keyof T, boolean>>;
|
|
70
124
|
setValue: (field: keyof T, value: string) => void;
|
|
125
|
+
setValues: (values: T | ((prev: T) => T)) => void;
|
|
126
|
+
/** Merge server / API errors (e.g. 422 field map). Touches those fields. */
|
|
127
|
+
setErrors: (errors: Partial<Record<keyof T, string | undefined>>) => void;
|
|
128
|
+
/** Set a single field error from the server. */
|
|
129
|
+
setFieldError: (field: keyof T, message: string | undefined) => void;
|
|
130
|
+
/** Clear one field or all errors. */
|
|
131
|
+
clearErrors: (field?: keyof T) => void;
|
|
71
132
|
handleChange: (field: keyof T) => (value: string) => void;
|
|
72
133
|
handleBlur: (field: keyof T) => () => void;
|
|
134
|
+
handleFocus: (field: keyof T) => () => void;
|
|
73
135
|
validateField: (field: keyof T) => Promise<boolean>;
|
|
136
|
+
/** Validate a subset of fields (wizard steps). */
|
|
137
|
+
validateFields: (fields: (keyof T)[]) => Promise<boolean>;
|
|
74
138
|
validateAll: () => Promise<boolean>;
|
|
75
139
|
submit: () => Promise<void>;
|
|
76
140
|
reset: () => void;
|
|
141
|
+
/** Evaluate conditional rules for a field against current values. */
|
|
142
|
+
getFieldState: (field: keyof T) => FieldVisibilityState;
|
|
143
|
+
isVisible: (field: keyof T) => boolean;
|
|
144
|
+
isRequired: (field: keyof T) => boolean;
|
|
145
|
+
isDisabled: (field: keyof T) => boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Convenience props to spread onto a FieldFlow input for a given field.
|
|
148
|
+
* Respects visibility (returns `null` when hidden so you can short-circuit render).
|
|
149
|
+
*/
|
|
150
|
+
getInputProps: (
|
|
151
|
+
field: keyof T,
|
|
152
|
+
) => null | {
|
|
153
|
+
value: string;
|
|
154
|
+
onChangeText: (value: string) => void;
|
|
155
|
+
onBlur: () => void;
|
|
156
|
+
onFocus: () => void;
|
|
157
|
+
errorText: string | undefined;
|
|
158
|
+
required: boolean;
|
|
159
|
+
disabled: boolean;
|
|
160
|
+
};
|
|
161
|
+
/** Present when `intelligence` is enabled. */
|
|
162
|
+
intelligence: UseFormIntelligenceResult<Extract<keyof T, string>> | null;
|
|
163
|
+
/** Register a TextInput ref for a11y autofocus (intelligence). */
|
|
164
|
+
registerFieldRef: (
|
|
165
|
+
field: keyof T,
|
|
166
|
+
ref: { current: TextInput | null } | TextInput | null,
|
|
167
|
+
) => void;
|
|
77
168
|
}
|
|
78
169
|
|
|
79
170
|
/**
|
|
80
171
|
* Drop-in form state manager for a set of FieldFlow inputs. Handles values,
|
|
81
|
-
* per-field + cross-field + async validation, touched-state,
|
|
172
|
+
* per-field + cross-field + conditional + async validation, touched-state,
|
|
173
|
+
* optional form intelligence, and submission.
|
|
82
174
|
*/
|
|
83
175
|
export function useFieldFlowForm<T extends Record<string, string>>({
|
|
84
176
|
initialValues,
|
|
85
177
|
rules,
|
|
86
178
|
crossFieldRules,
|
|
179
|
+
conditions,
|
|
87
180
|
formValidate,
|
|
88
181
|
asyncValidators,
|
|
89
182
|
asyncDebounceMs = 400,
|
|
183
|
+
intelligence: intelligenceOpt,
|
|
184
|
+
fieldOrder,
|
|
185
|
+
locale = 'en',
|
|
186
|
+
messages: messagesOverride,
|
|
90
187
|
onSubmit,
|
|
91
188
|
}: UseFieldFlowFormOptions<T>): UseFieldFlowFormResult<T> {
|
|
92
|
-
const [values,
|
|
93
|
-
const [errors,
|
|
189
|
+
const [values, setValuesState] = useState<T>(initialValues);
|
|
190
|
+
const [errors, setErrorsState] = useState<Partial<Record<keyof T, string>>>({});
|
|
94
191
|
const [touched, setTouched] = useState<Partial<Record<keyof T, boolean>>>({});
|
|
95
192
|
const [validating, setValidating] = useState<Partial<Record<keyof T, boolean>>>({});
|
|
96
193
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
@@ -99,26 +196,76 @@ export function useFieldFlowForm<T extends Record<string, string>>({
|
|
|
99
196
|
valuesRef.current = values;
|
|
100
197
|
const debounceTimers = useRef<Partial<Record<keyof T, ReturnType<typeof setTimeout>>>>({});
|
|
101
198
|
const asyncGen = useRef(0);
|
|
199
|
+
const messages = messagesOverride ?? getValidationMessages(locale);
|
|
200
|
+
|
|
201
|
+
const intelligenceEnabled = Boolean(intelligenceOpt);
|
|
202
|
+
const intelligenceOptions: FormIntelligenceOptions =
|
|
203
|
+
typeof intelligenceOpt === 'object' && intelligenceOpt ? intelligenceOpt : {};
|
|
204
|
+
const intelligence = useFormIntelligence<Extract<keyof T, string>>(
|
|
205
|
+
intelligenceEnabled ? intelligenceOptions : { focusFirstError: false, announceErrors: false },
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
const evalFieldState = useCallback(
|
|
209
|
+
(field: keyof T, allValues: T): FieldVisibilityState => {
|
|
210
|
+
const cfg = conditions?.[field];
|
|
211
|
+
const visible = cfg?.showWhen ? cfg.showWhen(allValues) : true;
|
|
212
|
+
const required = cfg?.requiredWhen ? cfg.requiredWhen(allValues) : Boolean(rules?.[field]?.required);
|
|
213
|
+
const disabled = cfg?.disabledWhen ? cfg.disabledWhen(allValues) : false;
|
|
214
|
+
return { visible, required, disabled };
|
|
215
|
+
},
|
|
216
|
+
[conditions, rules],
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
const getFieldState = useCallback(
|
|
220
|
+
(field: keyof T) => evalFieldState(field, valuesRef.current),
|
|
221
|
+
[evalFieldState],
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
const isVisible = useCallback((field: keyof T) => getFieldState(field).visible, [getFieldState]);
|
|
225
|
+
const isRequired = useCallback((field: keyof T) => getFieldState(field).required, [getFieldState]);
|
|
226
|
+
const isDisabled = useCallback((field: keyof T) => getFieldState(field).disabled, [getFieldState]);
|
|
227
|
+
|
|
228
|
+
const effectiveRulesFor = useCallback(
|
|
229
|
+
(field: keyof T, allValues: T): FieldFlowRules | undefined => {
|
|
230
|
+
const base = { ...(rules?.[field] ?? {}) };
|
|
231
|
+
const state = evalFieldState(field, allValues);
|
|
232
|
+
if (state.required && !base.required) {
|
|
233
|
+
base.required = true;
|
|
234
|
+
}
|
|
235
|
+
if (!state.required && base.required && conditions?.[field]?.requiredWhen) {
|
|
236
|
+
// Dynamically optional — strip required when condition is false
|
|
237
|
+
delete base.required;
|
|
238
|
+
}
|
|
239
|
+
return Object.keys(base).length ? base : undefined;
|
|
240
|
+
},
|
|
241
|
+
[rules, evalFieldState, conditions],
|
|
242
|
+
);
|
|
102
243
|
|
|
103
244
|
const syncErrorFor = useCallback(
|
|
104
245
|
(field: keyof T, fieldValue: string, allValues: T): string | undefined => {
|
|
105
|
-
const
|
|
246
|
+
const state = evalFieldState(field, allValues);
|
|
247
|
+
if (!state.visible) return undefined;
|
|
248
|
+
|
|
249
|
+
const result = runRules(fieldValue, effectiveRulesFor(field, allValues), messages);
|
|
106
250
|
if (!result.valid) return result.message;
|
|
107
251
|
|
|
108
252
|
if (crossFieldRules) {
|
|
109
253
|
for (const rule of crossFieldRules) {
|
|
110
254
|
if (rule.target !== field) continue;
|
|
255
|
+
const targetVisible = evalFieldState(rule.target, allValues).visible;
|
|
256
|
+
if (!targetVisible) continue;
|
|
111
257
|
const cross = rule.validate(allValues);
|
|
112
|
-
if (!cross.valid) return cross.message ??
|
|
258
|
+
if (!cross.valid) return cross.message ?? messages.invalid;
|
|
113
259
|
}
|
|
114
260
|
}
|
|
115
261
|
return undefined;
|
|
116
262
|
},
|
|
117
|
-
[
|
|
263
|
+
[crossFieldRules, effectiveRulesFor, evalFieldState, messages],
|
|
118
264
|
);
|
|
119
265
|
|
|
120
266
|
const runAsyncForField = useCallback(
|
|
121
267
|
async (field: keyof T, fieldValue: string, allValues: T): Promise<string | undefined> => {
|
|
268
|
+
if (!evalFieldState(field, allValues).visible) return undefined;
|
|
122
269
|
const validator = asyncValidators?.[field];
|
|
123
270
|
if (!validator) return undefined;
|
|
124
271
|
setValidating(prev => ({ ...prev, [field]: true }));
|
|
@@ -129,7 +276,7 @@ export function useFieldFlowForm<T extends Record<string, string>>({
|
|
|
129
276
|
setValidating(prev => ({ ...prev, [field]: false }));
|
|
130
277
|
}
|
|
131
278
|
},
|
|
132
|
-
[asyncValidators],
|
|
279
|
+
[asyncValidators, evalFieldState],
|
|
133
280
|
);
|
|
134
281
|
|
|
135
282
|
const scheduleAsync = useCallback(
|
|
@@ -142,7 +289,7 @@ export function useFieldFlowForm<T extends Record<string, string>>({
|
|
|
142
289
|
const gen = ++asyncGen.current;
|
|
143
290
|
const message = await runAsyncForField(field, fieldValue, allValues);
|
|
144
291
|
if (gen !== asyncGen.current) return;
|
|
145
|
-
|
|
292
|
+
setErrorsState(prev => {
|
|
146
293
|
const syncMsg = syncErrorFor(field, fieldValue, allValues);
|
|
147
294
|
if (syncMsg) return { ...prev, [field]: syncMsg };
|
|
148
295
|
return { ...prev, [field]: message };
|
|
@@ -155,17 +302,34 @@ export function useFieldFlowForm<T extends Record<string, string>>({
|
|
|
155
302
|
const validateField = useCallback(
|
|
156
303
|
async (field: keyof T): Promise<boolean> => {
|
|
157
304
|
const allValues = valuesRef.current;
|
|
305
|
+
if (!evalFieldState(field, allValues).visible) {
|
|
306
|
+
setErrorsState(prev => ({ ...prev, [field]: undefined }));
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
158
309
|
const fieldValue = allValues[field] ?? '';
|
|
159
310
|
const syncError = syncErrorFor(field, fieldValue, allValues);
|
|
160
311
|
if (syncError) {
|
|
161
|
-
|
|
312
|
+
setErrorsState(prev => ({ ...prev, [field]: syncError }));
|
|
162
313
|
return false;
|
|
163
314
|
}
|
|
164
315
|
const asyncError = await runAsyncForField(field, fieldValue, allValues);
|
|
165
|
-
|
|
316
|
+
setErrorsState(prev => ({ ...prev, [field]: asyncError }));
|
|
166
317
|
return !asyncError;
|
|
167
318
|
},
|
|
168
|
-
[runAsyncForField, syncErrorFor],
|
|
319
|
+
[evalFieldState, runAsyncForField, syncErrorFor],
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
const validateFields = useCallback(
|
|
323
|
+
async (fields: (keyof T)[]): Promise<boolean> => {
|
|
324
|
+
const results = await Promise.all(fields.map(f => validateField(f)));
|
|
325
|
+
setTouched(prev => {
|
|
326
|
+
const next = { ...prev };
|
|
327
|
+
for (const f of fields) next[f] = true;
|
|
328
|
+
return next;
|
|
329
|
+
});
|
|
330
|
+
return results.every(Boolean);
|
|
331
|
+
},
|
|
332
|
+
[validateField],
|
|
169
333
|
);
|
|
170
334
|
|
|
171
335
|
const validateAll = useCallback(async (): Promise<boolean> => {
|
|
@@ -176,32 +340,37 @@ export function useFieldFlowForm<T extends Record<string, string>>({
|
|
|
176
340
|
...(rules ? (Object.keys(rules) as (keyof T)[]) : []),
|
|
177
341
|
...(crossFieldRules?.map(r => r.target) ?? []),
|
|
178
342
|
...(asyncValidators ? (Object.keys(asyncValidators) as (keyof T)[]) : []),
|
|
343
|
+
...(conditions ? (Object.keys(conditions) as (keyof T)[]) : []),
|
|
179
344
|
]);
|
|
180
345
|
|
|
181
346
|
for (const key of keys) {
|
|
347
|
+
if (!evalFieldState(key, allValues).visible) continue;
|
|
182
348
|
const syncError = syncErrorFor(key, allValues[key] ?? '', allValues);
|
|
183
349
|
if (syncError) nextErrors[key] = syncError;
|
|
184
350
|
}
|
|
185
351
|
|
|
186
352
|
if (crossFieldRules) {
|
|
187
353
|
for (const rule of crossFieldRules) {
|
|
354
|
+
if (!evalFieldState(rule.target, allValues).visible) continue;
|
|
188
355
|
if (nextErrors[rule.target]) continue;
|
|
189
356
|
const result = rule.validate(allValues);
|
|
190
|
-
if (!result.valid) nextErrors[rule.target] = result.message ??
|
|
357
|
+
if (!result.valid) nextErrors[rule.target] = result.message ?? messages.invalid;
|
|
191
358
|
}
|
|
192
359
|
}
|
|
193
360
|
|
|
194
361
|
if (formValidate) {
|
|
195
362
|
const formErrors = await formValidate(allValues);
|
|
196
363
|
for (const key of Object.keys(formErrors) as (keyof T)[]) {
|
|
197
|
-
|
|
198
|
-
|
|
364
|
+
if (!evalFieldState(key, allValues).visible) continue;
|
|
365
|
+
const formMsg = formErrors[key];
|
|
366
|
+
if (formMsg && !nextErrors[key]) nextErrors[key] = formMsg;
|
|
199
367
|
}
|
|
200
368
|
}
|
|
201
369
|
|
|
202
370
|
if (asyncValidators) {
|
|
203
371
|
await Promise.all(
|
|
204
372
|
(Object.keys(asyncValidators) as (keyof T)[]).map(async key => {
|
|
373
|
+
if (!evalFieldState(key, allValues).visible) return;
|
|
205
374
|
if (nextErrors[key]) return;
|
|
206
375
|
const asyncError = await runAsyncForField(key, allValues[key] ?? '', allValues);
|
|
207
376
|
if (asyncError) nextErrors[key] = asyncError;
|
|
@@ -209,58 +378,162 @@ export function useFieldFlowForm<T extends Record<string, string>>({
|
|
|
209
378
|
);
|
|
210
379
|
}
|
|
211
380
|
|
|
212
|
-
|
|
381
|
+
setErrorsState(nextErrors);
|
|
382
|
+
setTouched(prev => {
|
|
383
|
+
const next = { ...prev };
|
|
384
|
+
for (const key of keys) {
|
|
385
|
+
if (evalFieldState(key, allValues).visible) next[key] = true;
|
|
386
|
+
}
|
|
387
|
+
return next;
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
const valid = Object.values(nextErrors).every(e => !e);
|
|
391
|
+
if (intelligenceEnabled) {
|
|
392
|
+
intelligence.onValidationResult(
|
|
393
|
+
valid,
|
|
394
|
+
nextErrors as Partial<Record<Extract<keyof T, string>, string | undefined>>,
|
|
395
|
+
fieldOrder as Extract<keyof T, string>[] | undefined,
|
|
396
|
+
);
|
|
397
|
+
}
|
|
398
|
+
return valid;
|
|
399
|
+
}, [
|
|
400
|
+
rules,
|
|
401
|
+
crossFieldRules,
|
|
402
|
+
formValidate,
|
|
403
|
+
asyncValidators,
|
|
404
|
+
conditions,
|
|
405
|
+
evalFieldState,
|
|
406
|
+
syncErrorFor,
|
|
407
|
+
runAsyncForField,
|
|
408
|
+
intelligenceEnabled,
|
|
409
|
+
intelligence,
|
|
410
|
+
fieldOrder,
|
|
411
|
+
messages,
|
|
412
|
+
]);
|
|
413
|
+
|
|
414
|
+
const setErrors = useCallback((next: Partial<Record<keyof T, string | undefined>>) => {
|
|
415
|
+
setErrorsState(prev => {
|
|
416
|
+
const merged = { ...prev };
|
|
417
|
+
for (const key of Object.keys(next) as (keyof T)[]) {
|
|
418
|
+
const msg = next[key];
|
|
419
|
+
if (msg == null || msg === '') delete merged[key];
|
|
420
|
+
else merged[key] = msg;
|
|
421
|
+
}
|
|
422
|
+
return merged;
|
|
423
|
+
});
|
|
213
424
|
setTouched(prev => {
|
|
425
|
+
const merged = { ...prev };
|
|
426
|
+
for (const key of Object.keys(next) as (keyof T)[]) {
|
|
427
|
+
if (next[key]) merged[key] = true;
|
|
428
|
+
}
|
|
429
|
+
return merged;
|
|
430
|
+
});
|
|
431
|
+
}, []);
|
|
432
|
+
|
|
433
|
+
const setFieldError = useCallback((field: keyof T, message: string | undefined) => {
|
|
434
|
+
setErrors({ [field]: message } as Partial<Record<keyof T, string | undefined>>);
|
|
435
|
+
}, [setErrors]);
|
|
436
|
+
|
|
437
|
+
const clearErrors = useCallback((field?: keyof T) => {
|
|
438
|
+
if (field == null) {
|
|
439
|
+
setErrorsState({});
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
setErrorsState(prev => {
|
|
443
|
+
if (!prev[field]) return prev;
|
|
214
444
|
const next = { ...prev };
|
|
215
|
-
|
|
445
|
+
delete next[field];
|
|
216
446
|
return next;
|
|
217
447
|
});
|
|
218
|
-
|
|
219
|
-
}, [rules, crossFieldRules, formValidate, asyncValidators, syncErrorFor, runAsyncForField]);
|
|
448
|
+
}, []);
|
|
220
449
|
|
|
221
450
|
const setValue = useCallback((field: keyof T, value: string) => {
|
|
222
|
-
|
|
451
|
+
setValuesState(prev => {
|
|
223
452
|
const next = { ...prev, [field]: value };
|
|
224
453
|
valuesRef.current = next;
|
|
225
454
|
return next;
|
|
226
455
|
});
|
|
227
456
|
}, []);
|
|
228
457
|
|
|
458
|
+
const setValues = useCallback((next: T | ((prev: T) => T)) => {
|
|
459
|
+
setValuesState(prev => {
|
|
460
|
+
const resolved = typeof next === 'function' ? (next as (p: T) => T)(prev) : next;
|
|
461
|
+
valuesRef.current = resolved;
|
|
462
|
+
return resolved;
|
|
463
|
+
});
|
|
464
|
+
}, []);
|
|
465
|
+
|
|
229
466
|
const handleChange = useCallback(
|
|
230
467
|
(field: keyof T) => (value: string) => {
|
|
231
468
|
setValue(field, value);
|
|
469
|
+
if (intelligenceEnabled) {
|
|
470
|
+
intelligence.trackChange(field as Extract<keyof T, string>);
|
|
471
|
+
}
|
|
232
472
|
const allValues = { ...valuesRef.current, [field]: value };
|
|
233
473
|
|
|
234
474
|
if (touched[field]) {
|
|
235
475
|
const syncError = syncErrorFor(field, value, allValues);
|
|
236
|
-
|
|
476
|
+
setErrorsState(prev => ({ ...prev, [field]: syncError }));
|
|
237
477
|
if (!syncError) scheduleAsync(field, value, allValues);
|
|
238
478
|
}
|
|
239
479
|
|
|
480
|
+
// Clear errors for fields that just became hidden
|
|
481
|
+
if (conditions) {
|
|
482
|
+
for (const key of Object.keys(conditions) as (keyof T)[]) {
|
|
483
|
+
if (!evalFieldState(key, allValues).visible) {
|
|
484
|
+
setErrorsState(prev => (prev[key] ? { ...prev, [key]: undefined } : prev));
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
240
489
|
if (crossFieldRules) {
|
|
241
490
|
for (const rule of crossFieldRules) {
|
|
242
491
|
if (rule.target === field) continue;
|
|
243
492
|
if (rule.deps && !rule.deps.includes(field)) continue;
|
|
244
493
|
if (!touched[rule.target] && !touched[field]) continue;
|
|
494
|
+
if (!evalFieldState(rule.target, allValues).visible) continue;
|
|
245
495
|
const result = rule.validate(allValues);
|
|
246
|
-
|
|
496
|
+
setErrorsState(prev => ({
|
|
247
497
|
...prev,
|
|
248
498
|
[rule.target]: result.valid
|
|
249
499
|
? syncErrorFor(rule.target, allValues[rule.target] ?? '', allValues)
|
|
250
|
-
: result.message ??
|
|
500
|
+
: result.message ?? messages.invalid,
|
|
251
501
|
}));
|
|
252
502
|
}
|
|
253
503
|
}
|
|
254
504
|
},
|
|
255
|
-
[
|
|
505
|
+
[
|
|
506
|
+
setValue,
|
|
507
|
+
touched,
|
|
508
|
+
syncErrorFor,
|
|
509
|
+
scheduleAsync,
|
|
510
|
+
crossFieldRules,
|
|
511
|
+
conditions,
|
|
512
|
+
evalFieldState,
|
|
513
|
+
intelligenceEnabled,
|
|
514
|
+
intelligence,
|
|
515
|
+
messages,
|
|
516
|
+
],
|
|
256
517
|
);
|
|
257
518
|
|
|
258
519
|
const handleBlur = useCallback(
|
|
259
520
|
(field: keyof T) => () => {
|
|
521
|
+
if (intelligenceEnabled) {
|
|
522
|
+
intelligence.trackBlur(field as Extract<keyof T, string>);
|
|
523
|
+
}
|
|
260
524
|
setTouched(prev => ({ ...prev, [field]: true }));
|
|
261
525
|
void validateField(field);
|
|
262
526
|
},
|
|
263
|
-
[validateField],
|
|
527
|
+
[validateField, intelligenceEnabled, intelligence],
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
const handleFocus = useCallback(
|
|
531
|
+
(field: keyof T) => () => {
|
|
532
|
+
if (intelligenceEnabled) {
|
|
533
|
+
intelligence.trackFocus(field as Extract<keyof T, string>);
|
|
534
|
+
}
|
|
535
|
+
},
|
|
536
|
+
[intelligenceEnabled, intelligence],
|
|
264
537
|
);
|
|
265
538
|
|
|
266
539
|
const submit = useCallback(async () => {
|
|
@@ -269,10 +542,11 @@ export function useFieldFlowForm<T extends Record<string, string>>({
|
|
|
269
542
|
setIsSubmitting(true);
|
|
270
543
|
try {
|
|
271
544
|
await onSubmit?.(valuesRef.current);
|
|
545
|
+
if (intelligenceEnabled) intelligence.trackSubmitSuccess();
|
|
272
546
|
} finally {
|
|
273
547
|
setIsSubmitting(false);
|
|
274
548
|
}
|
|
275
|
-
}, [onSubmit, validateAll]);
|
|
549
|
+
}, [onSubmit, validateAll, intelligenceEnabled, intelligence]);
|
|
276
550
|
|
|
277
551
|
const reset = useCallback(() => {
|
|
278
552
|
asyncGen.current += 1;
|
|
@@ -280,16 +554,56 @@ export function useFieldFlowForm<T extends Record<string, string>>({
|
|
|
280
554
|
const t = debounceTimers.current[key];
|
|
281
555
|
if (t) clearTimeout(t);
|
|
282
556
|
}
|
|
283
|
-
|
|
557
|
+
setValuesState(initialValues);
|
|
284
558
|
valuesRef.current = initialValues;
|
|
285
|
-
|
|
559
|
+
setErrorsState({});
|
|
286
560
|
setTouched({});
|
|
287
561
|
setValidating({});
|
|
288
|
-
|
|
562
|
+
if (intelligenceEnabled) intelligence.reset();
|
|
563
|
+
}, [initialValues, intelligenceEnabled, intelligence]);
|
|
564
|
+
|
|
565
|
+
const getInputProps = useCallback(
|
|
566
|
+
(field: keyof T) => {
|
|
567
|
+
const state = getFieldState(field);
|
|
568
|
+
if (!state.visible) return null;
|
|
569
|
+
return {
|
|
570
|
+
value: values[field] ?? '',
|
|
571
|
+
onChangeText: handleChange(field),
|
|
572
|
+
onBlur: handleBlur(field),
|
|
573
|
+
onFocus: handleFocus(field),
|
|
574
|
+
errorText: touched[field] ? errors[field] : undefined,
|
|
575
|
+
required: state.required,
|
|
576
|
+
disabled: state.disabled,
|
|
577
|
+
};
|
|
578
|
+
},
|
|
579
|
+
[getFieldState, values, handleChange, handleBlur, handleFocus, touched, errors],
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
const registerFieldRef = useCallback(
|
|
583
|
+
(field: keyof T, ref: { current: TextInput | null } | TextInput | null) => {
|
|
584
|
+
if (intelligenceEnabled) {
|
|
585
|
+
intelligence.registerFieldRef(field as Extract<keyof T, string>, ref);
|
|
586
|
+
}
|
|
587
|
+
},
|
|
588
|
+
[intelligenceEnabled, intelligence],
|
|
589
|
+
);
|
|
289
590
|
|
|
290
591
|
const isValid = useMemo(() => Object.values(errors).every(e => !e), [errors]);
|
|
291
592
|
const isValidating = useMemo(() => Object.values(validating).some(Boolean), [validating]);
|
|
292
593
|
|
|
594
|
+
const dirtyFields = useMemo(() => {
|
|
595
|
+
const next: Partial<Record<keyof T, boolean>> = {};
|
|
596
|
+
for (const key of Object.keys(initialValues) as (keyof T)[]) {
|
|
597
|
+
if ((values[key] ?? '') !== (initialValues[key] ?? '')) next[key] = true;
|
|
598
|
+
}
|
|
599
|
+
for (const key of Object.keys(values) as (keyof T)[]) {
|
|
600
|
+
if ((values[key] ?? '') !== (initialValues[key] ?? '')) next[key] = true;
|
|
601
|
+
}
|
|
602
|
+
return next;
|
|
603
|
+
}, [values, initialValues]);
|
|
604
|
+
|
|
605
|
+
const isDirty = useMemo(() => Object.values(dirtyFields).some(Boolean), [dirtyFields]);
|
|
606
|
+
|
|
293
607
|
return {
|
|
294
608
|
values,
|
|
295
609
|
errors,
|
|
@@ -298,12 +612,27 @@ export function useFieldFlowForm<T extends Record<string, string>>({
|
|
|
298
612
|
isSubmitting,
|
|
299
613
|
isValid,
|
|
300
614
|
isValidating,
|
|
615
|
+
isDirty,
|
|
616
|
+
dirtyFields,
|
|
301
617
|
setValue,
|
|
618
|
+
setValues,
|
|
619
|
+
setErrors,
|
|
620
|
+
setFieldError,
|
|
621
|
+
clearErrors,
|
|
302
622
|
handleChange,
|
|
303
623
|
handleBlur,
|
|
624
|
+
handleFocus,
|
|
304
625
|
validateField,
|
|
626
|
+
validateFields,
|
|
305
627
|
validateAll,
|
|
306
628
|
submit,
|
|
307
629
|
reset,
|
|
630
|
+
getFieldState,
|
|
631
|
+
isVisible,
|
|
632
|
+
isRequired,
|
|
633
|
+
isDisabled,
|
|
634
|
+
getInputProps,
|
|
635
|
+
intelligence: intelligenceEnabled ? intelligence : null,
|
|
636
|
+
registerFieldRef,
|
|
308
637
|
};
|
|
309
638
|
}
|